vi: update the dimensions of a single window when the terminal is resized
[neatvi.git] / mot.c
blob4b1c65672c0b54db5b981a8557240910cdec2078
1 #include <stdio.h>
2 #include <string.h>
3 #include "vi.h"
5 int lbuf_indents(struct lbuf *lb, int r)
7 char *ln = lbuf_get(lb, r);
8 int o;
9 if (!ln)
10 return 0;
11 for (o = 0; uc_isspace(ln); o++)
12 ln = uc_next(ln);
13 return o;
16 static int uc_nextdir(char **s, char *beg, int dir)
18 if (dir < 0) {
19 if (*s == beg)
20 return 1;
21 *s = uc_prev(beg, *s);
22 } else {
23 *s = uc_next(*s);
24 if (!(*s)[0])
25 return 1;
27 return 0;
30 int lbuf_findchar(struct lbuf *lb, char *cs, int cmd, int n, int *row, int *off)
32 char *ln = lbuf_get(lb, *row);
33 char *s;
34 int dir = (cmd == 'f' || cmd == 't') ? +1 : -1;
35 if (!ln)
36 return 1;
37 if (n < 0)
38 dir = -dir;
39 if (n < 0)
40 n = -n;
41 s = uc_chr(ln, *off);
42 while (n > 0 && !uc_nextdir(&s, ln, dir))
43 if (uc_code(s) == uc_code(cs))
44 n--;
45 if (!n && (cmd == 't' || cmd == 'T'))
46 uc_nextdir(&s, ln, -dir);
47 if (!n)
48 *off = uc_off(ln, s - ln);
49 return n != 0;
52 int lbuf_search(struct lbuf *lb, char *kw, int dir, int *r, int *o, int *len)
54 int offs[2];
55 int found = 0;
56 int r0 = *r, o0 = *o;
57 int i;
58 struct rstr *re = rstr_make(kw, xic ? RE_ICASE : 0);
59 if (!re)
60 return 1;
61 for (i = r0; !found && i >= 0 && i < lbuf_len(lb); i += dir) {
62 char *s = lbuf_get(lb, i);
63 int off = dir > 0 && r0 == i ? uc_chr(s, o0 + 1) - s : 0;
64 while (rstr_find(re, s + off, 1, offs,
65 off ? RE_NOTBOL : 0) >= 0) {
66 if (dir < 0 && r0 == i &&
67 uc_off(s, off + offs[0]) >= o0)
68 break;
69 found = 1;
70 *o = uc_off(s, off + offs[0]);
71 *r = i;
72 *len = uc_off(s + off + offs[0], offs[1] - offs[0]);
73 off += offs[1] > offs[0] ? offs[1] : offs[1] + 1;
74 if (dir > 0 || !s[off] || s[off] == '\n')
75 break;
78 rstr_free(re);
79 return !found;
82 int lbuf_paragraphbeg(struct lbuf *lb, int dir, int *row, int *off)
84 while (*row >= 0 && *row < lbuf_len(lb) && !strcmp("\n", lbuf_get(lb, *row)))
85 *row += dir;
86 while (*row >= 0 && *row < lbuf_len(lb) && strcmp("\n", lbuf_get(lb, *row)))
87 *row += dir;
88 *row = MAX(0, MIN(*row, lbuf_len(lb) - 1));
89 *off = 0;
90 return 0;
93 int lbuf_sectionbeg(struct lbuf *lb, int dir, char *sec, int *row, int *off)
95 struct rstr *re = rstr_make(sec, 0);
96 *row += dir;
97 while (*row >= 0 && *row < lbuf_len(lb)) {
98 if (rstr_find(re, lbuf_get(lb, *row), 0, NULL, 0) >= 0)
99 break;
100 *row += dir;
102 rstr_free(re);
103 *row = MAX(0, MIN(*row, lbuf_len(lb) - 1));
104 *off = 0;
105 return 0;
108 static int lbuf_lnnext(struct lbuf *lb, int dir, int *r, int *o)
110 int off = *o + dir;
111 if (off < 0 || !lbuf_get(lb, *r) || off >= uc_slen(lbuf_get(lb, *r)))
112 return 1;
113 *o = off;
114 return 0;
117 int lbuf_eol(struct lbuf *lb, int row)
119 int len = lbuf_get(lb, row) ? uc_slen(lbuf_get(lb, row)) : 0;
120 return len ? len - 1 : 0;
123 static int lbuf_next(struct lbuf *lb, int dir, int *r, int *o)
125 if (dir < 0 && *r >= lbuf_len(lb))
126 *r = MAX(0, lbuf_len(lb) - 1);
127 if (lbuf_lnnext(lb, dir, r, o)) {
128 if (!lbuf_get(lb, *r + dir))
129 return -1;
130 *r += dir;
131 *o = dir > 0 ? 0 : lbuf_eol(lb, *r);
132 return 0;
134 return 0;
137 /* return a pointer to the character at visual position c of line r */
138 static char *lbuf_chr(struct lbuf *lb, int r, int c)
140 char *ln = lbuf_get(lb, r);
141 return ln ? uc_chr(ln, c) : "";
144 /* move to the last character of the word */
145 static int lbuf_wordlast(struct lbuf *lb, int kind, int dir, int *row, int *off)
147 if (!kind || !(uc_kind(lbuf_chr(lb, *row, *off)) & kind))
148 return 0;
149 while (uc_kind(lbuf_chr(lb, *row, *off)) & kind)
150 if (lbuf_next(lb, dir, row, off))
151 return 1;
152 if (!(uc_kind(lbuf_chr(lb, *row, *off)) & kind))
153 lbuf_next(lb, -dir, row, off);
154 return 0;
157 int lbuf_wordbeg(struct lbuf *lb, int big, int dir, int *row, int *off)
159 int nl;
160 lbuf_wordlast(lb, big ? 3 : uc_kind(lbuf_chr(lb, *row, *off)), dir, row, off);
161 nl = uc_code(lbuf_chr(lb, *row, *off)) == '\n';
162 if (lbuf_next(lb, dir, row, off))
163 return 1;
164 while (uc_isspace(lbuf_chr(lb, *row, *off))) {
165 nl += uc_code(lbuf_chr(lb, *row, *off)) == '\n';
166 if (nl == 2)
167 return 0;
168 if (lbuf_next(lb, dir, row, off))
169 return 1;
171 return 0;
174 int lbuf_wordend(struct lbuf *lb, int big, int dir, int *row, int *off)
176 int nl = 0;
177 if (!uc_isspace(lbuf_chr(lb, *row, *off))) {
178 if (lbuf_next(lb, dir, row, off))
179 return 1;
180 nl = dir < 0 && uc_code(lbuf_chr(lb, *row, *off)) == '\n';
182 nl += dir > 0 && uc_code(lbuf_chr(lb, *row, *off)) == '\n';
183 while (uc_isspace(lbuf_chr(lb, *row, *off))) {
184 if (lbuf_next(lb, dir, row, off))
185 return 1;
186 nl += uc_code(lbuf_chr(lb, *row, *off)) == '\n';
187 if (nl == 2) {
188 if (dir < 0)
189 lbuf_next(lb, -dir, row, off);
190 return 0;
193 if (lbuf_wordlast(lb, big ? 3 : uc_kind(lbuf_chr(lb, *row, *off)), dir, row, off))
194 return 1;
195 return 0;
198 /* move to the matching character */
199 int lbuf_pair(struct lbuf *lb, int *row, int *off)
201 int r = *row, o = *off;
202 char *pairs = "()[]{}";
203 int pchr; /* parenthesis character */
204 int pidx; /* index into pairs[] */
205 int dep = 1; /* parenthesis depth */
206 while ((pchr = (unsigned char) lbuf_chr(lb, r, o)[0]) && !strchr(pairs, pchr))
207 o++;
208 if (!pchr)
209 return 1;
210 pidx = strchr(pairs, pchr) - pairs;
211 while (!lbuf_next(lb, (pidx & 1) ? -1 : +1, &r, &o)) {
212 int c = (unsigned char) lbuf_chr(lb, r, o)[0];
213 if (c == pairs[pidx ^ 1])
214 dep--;
215 if (c == pairs[pidx])
216 dep++;
217 if (!dep) {
218 *row = r;
219 *off = o;
220 return 0;
223 return 1;