vi: explain when the screen is updated in vi()
[neatvi.git] / mot.c
blobed0586b4a402fcb8e001c57b03436af3b6a5208e
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 rset *re = rset_make(1, &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 (rset_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)
75 break;
78 rset_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, int *row, int *off)
95 *row += dir;
96 while (*row >= 0 && *row < lbuf_len(lb) && lbuf_get(lb, *row)[0] != '{')
97 *row += dir;
98 *row = MAX(0, MIN(*row, lbuf_len(lb) - 1));
99 *off = 0;
100 return 0;
103 static int lbuf_lnnext(struct lbuf *lb, int dir, int *r, int *o)
105 int off = *o + dir;
106 if (off < 0 || !lbuf_get(lb, *r) || off >= uc_slen(lbuf_get(lb, *r)))
107 return 1;
108 *o = off;
109 return 0;
112 int lbuf_eol(struct lbuf *lb, int row)
114 int len = lbuf_get(lb, row) ? uc_slen(lbuf_get(lb, row)) : 0;
115 return len ? len - 1 : 0;
118 static int lbuf_next(struct lbuf *lb, int dir, int *r, int *o)
120 if (dir < 0 && *r >= lbuf_len(lb))
121 *r = MAX(0, lbuf_len(lb) - 1);
122 if (lbuf_lnnext(lb, dir, r, o)) {
123 if (!lbuf_get(lb, *r + dir))
124 return -1;
125 *r += dir;
126 *o = dir > 0 ? 0 : lbuf_eol(lb, *r);
127 return 0;
129 return 0;
132 /* return a pointer to the character at visual position c of line r */
133 static char *lbuf_chr(struct lbuf *lb, int r, int c)
135 char *ln = lbuf_get(lb, r);
136 return ln ? uc_chr(ln, c) : "";
139 /* move to the last character of the word */
140 static int lbuf_wordlast(struct lbuf *lb, int kind, int dir, int *row, int *off)
142 if (!kind || !(uc_kind(lbuf_chr(lb, *row, *off)) & kind))
143 return 0;
144 while (uc_kind(lbuf_chr(lb, *row, *off)) & kind)
145 if (lbuf_next(lb, dir, row, off))
146 return 1;
147 if (!(uc_kind(lbuf_chr(lb, *row, *off)) & kind))
148 lbuf_next(lb, -dir, row, off);
149 return 0;
152 int lbuf_wordbeg(struct lbuf *lb, int big, int dir, int *row, int *off)
154 int nl;
155 lbuf_wordlast(lb, big ? 3 : uc_kind(lbuf_chr(lb, *row, *off)), dir, row, off);
156 nl = uc_code(lbuf_chr(lb, *row, *off)) == '\n';
157 if (lbuf_next(lb, dir, row, off))
158 return 1;
159 while (uc_isspace(lbuf_chr(lb, *row, *off))) {
160 nl += uc_code(lbuf_chr(lb, *row, *off)) == '\n';
161 if (nl == 2)
162 return 0;
163 if (lbuf_next(lb, dir, row, off))
164 return 1;
166 return 0;
169 int lbuf_wordend(struct lbuf *lb, int big, int dir, int *row, int *off)
171 int nl = 0;
172 if (!uc_isspace(lbuf_chr(lb, *row, *off))) {
173 if (lbuf_next(lb, dir, row, off))
174 return 1;
175 nl = dir < 0 && uc_code(lbuf_chr(lb, *row, *off)) == '\n';
177 nl += dir > 0 && uc_code(lbuf_chr(lb, *row, *off)) == '\n';
178 while (uc_isspace(lbuf_chr(lb, *row, *off))) {
179 if (lbuf_next(lb, dir, row, off))
180 return 1;
181 nl += uc_code(lbuf_chr(lb, *row, *off)) == '\n';
182 if (nl == 2) {
183 if (dir < 0)
184 lbuf_next(lb, -dir, row, off);
185 return 0;
188 if (lbuf_wordlast(lb, big ? 3 : uc_kind(lbuf_chr(lb, *row, *off)), dir, row, off))
189 return 1;
190 return 0;
193 /* move to the matching character */
194 int lbuf_pair(struct lbuf *lb, int *row, int *off)
196 int r = *row, o = *off;
197 char *ln = lbuf_get(lb, *row);
198 char *pairs = "()[]{}";
199 int p; /* index for pairs[] */
200 int dep = 1; /* parenthesis depth */
201 if (!ln || !ln[o])
202 return 1;
203 while (!strchr(pairs, ln[o]))
204 if (!ln[++o])
205 return 1;
206 p = strchr(pairs, ln[o]) - pairs;
207 while (!lbuf_next(lb, (p & 1) ? -1 : +1, &r, &o)) {
208 int c = (unsigned char) lbuf_chr(lb, r, o)[0];
209 if (c == pairs[p ^ 1])
210 dep--;
211 if (c == pairs[p])
212 dep++;
213 if (!dep) {
214 *row = r;
215 *off = o;
216 return 0;
219 return 1;