lbuf: useq should always be nonzero
[neatvi.git] / mot.c
blob93133d30ceb4bbe50427521858af4a1394cf90cd
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 int flg = off ? RE_NOTBOL : 0;
65 while (rset_find(re, s + off, 1, offs, flg) >= 0) {
66 if (dir < 0 && r0 == i && off + offs[0] >= o0)
67 break;
68 found = 1;
69 *o = uc_off(s, off + offs[0]);
70 *r = i;
71 *len = offs[1] - offs[0];
72 off += offs[1];
73 if (dir > 0)
74 break;
77 rset_free(re);
78 return !found;
81 int lbuf_paragraphbeg(struct lbuf *lb, int dir, int *row, int *off)
83 while (*row >= 0 && *row < lbuf_len(lb) && !strcmp("\n", lbuf_get(lb, *row)))
84 *row += dir;
85 while (*row >= 0 && *row < lbuf_len(lb) && strcmp("\n", lbuf_get(lb, *row)))
86 *row += dir;
87 *row = MAX(0, MIN(*row, lbuf_len(lb) - 1));
88 *off = 0;
89 return 0;
92 int lbuf_sectionbeg(struct lbuf *lb, int dir, int *row, int *off)
94 *row += dir;
95 while (*row >= 0 && *row < lbuf_len(lb) && lbuf_get(lb, *row)[0] != '{')
96 *row += dir;
97 *row = MAX(0, MIN(*row, lbuf_len(lb) - 1));
98 *off = 0;
99 return 0;
102 static int lbuf_lnnext(struct lbuf *lb, int dir, int *r, int *o)
104 int off = *o + dir;
105 if (off < 0 || !lbuf_get(lb, *r) || off >= uc_slen(lbuf_get(lb, *r)))
106 return 1;
107 *o = off;
108 return 0;
111 int lbuf_eol(struct lbuf *lb, int row)
113 int len = lbuf_get(lb, row) ? uc_slen(lbuf_get(lb, row)) : 0;
114 return len ? len - 1 : 0;
117 static int lbuf_next(struct lbuf *lb, int dir, int *r, int *o)
119 if (dir < 0 && *r >= lbuf_len(lb))
120 *r = MAX(0, lbuf_len(lb) - 1);
121 if (lbuf_lnnext(lb, dir, r, o)) {
122 if (!lbuf_get(lb, *r + dir))
123 return -1;
124 *r += dir;
125 *o = dir > 0 ? 0 : lbuf_eol(lb, *r);
126 return 0;
128 return 0;
131 /* return a pointer to the character at visual position c of line r */
132 static char *lbuf_chr(struct lbuf *lb, int r, int c)
134 char *ln = lbuf_get(lb, r);
135 return ln ? uc_chr(ln, c) : "";
138 /* move to the last character of the word */
139 static int lbuf_wordlast(struct lbuf *lb, int kind, int dir, int *row, int *off)
141 if (!kind || !(uc_kind(lbuf_chr(lb, *row, *off)) & kind))
142 return 0;
143 while (uc_kind(lbuf_chr(lb, *row, *off)) & kind)
144 if (lbuf_next(lb, dir, row, off))
145 return 1;
146 if (!(uc_kind(lbuf_chr(lb, *row, *off)) & kind))
147 lbuf_next(lb, -dir, row, off);
148 return 0;
151 int lbuf_wordbeg(struct lbuf *lb, int big, int dir, int *row, int *off)
153 int nl = 0;
154 lbuf_wordlast(lb, big ? 3 : uc_kind(lbuf_chr(lb, *row, *off)), dir, row, off);
155 if (lbuf_next(lb, dir, row, off))
156 return 1;
157 while (uc_isspace(lbuf_chr(lb, *row, *off))) {
158 nl = uc_code(lbuf_chr(lb, *row, *off)) == '\n' ? nl + 1 : 0;
159 if (nl == 2)
160 return 0;
161 if (lbuf_next(lb, dir, row, off))
162 return 1;
164 return 0;
167 int lbuf_wordend(struct lbuf *lb, int big, int dir, int *row, int *off)
169 int nl = uc_code(lbuf_chr(lb, *row, *off)) == '\n' ? -1 : 0;
170 if (!uc_isspace(lbuf_chr(lb, *row, *off)))
171 if (lbuf_next(lb, dir, row, off))
172 return 1;
173 while (uc_isspace(lbuf_chr(lb, *row, *off))) {
174 nl = uc_code(lbuf_chr(lb, *row, *off)) == '\n' ? nl + 1 : 0;
175 if (nl == 2) {
176 if (dir < 0)
177 lbuf_next(lb, -dir, row, off);
178 return 0;
180 if (lbuf_next(lb, dir, row, off))
181 return 1;
183 if (lbuf_wordlast(lb, big ? 3 : uc_kind(lbuf_chr(lb, *row, *off)), dir, row, off))
184 return 1;
185 return 0;