stag: allow multiple tag patterns for each extension
[neatvi.git] / ren.c
blobc87ac4fef8ee468eb71bd2950c1900e7a224daf1
1 /* rendering strings */
2 #include <ctype.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include "vi.h"
8 /* specify the screen position of the characters in s; reordering version */
9 int *ren_position_reorder(char *s)
11 int i, n;
12 char **chrs = uc_chop(s, &n);
13 int *off, *pos;
14 int cpos = 0;
15 pos = malloc((n + 1) * sizeof(pos[0]));
16 for (i = 0; i < n; i++)
17 pos[i] = i;
18 if (xorder)
19 dir_reorder(s, pos);
20 off = malloc(n * sizeof(off[0]));
21 for (i = 0; i < n; i++)
22 off[pos[i]] = i;
23 for (i = 0; i < n; i++) {
24 pos[off[i]] = cpos;
25 cpos += ren_cwid(chrs[off[i]], cpos);
27 pos[n] = cpos;
28 free(chrs);
29 free(off);
30 return pos;
33 /* specify the screen position of the characters in s; fast version */
34 int *ren_position(char *s)
36 int cpos = 0;
37 int *pos;
38 int i;
39 int n = uc_slen(s);
40 if (n <= xlim && xorder)
41 return ren_position_reorder(s);
42 pos = malloc((n + 1) * sizeof(pos[0]));
43 for (i = 0; i < n; i++, s += uc_len(s)) {
44 pos[i] = cpos;
45 cpos += ren_cwid(s, cpos);
47 pos[i] = cpos;
48 return pos;
51 int ren_wid(char *s)
53 int *pos = ren_position(s);
54 int n = uc_slen(s);
55 int ret = pos[n];
56 free(pos);
57 return ret;
60 /* find the next character after visual position p; if cur, start from p itself */
61 static int pos_next(int *pos, int n, int p, int cur)
63 int i, ret = -1;
64 for (i = 0; i < n; i++)
65 if (pos[i] - !cur >= p && (ret < 0 || pos[i] < pos[ret]))
66 ret = i;
67 return ret >= 0 ? pos[ret] : -1;
70 /* find the previous character after visual position p; if cur, start from p itself */
71 static int pos_prev(int *pos, int n, int p, int cur)
73 int i, ret = -1;
74 for (i = 0; i < n; i++)
75 if (pos[i] + !cur <= p && (ret < 0 || pos[i] > pos[ret]))
76 ret = i;
77 return ret >= 0 ? pos[ret] : -1;
80 /* convert character offset to visual position */
81 int ren_pos(char *s, int off)
83 int n = uc_slen(s);
84 int *pos = ren_position(s);
85 int ret = off < n ? pos[off] : 0;
86 free(pos);
87 return ret;
90 /* convert visual position to character offset */
91 int ren_off(char *s, int p)
93 int off = -1;
94 int n = uc_slen(s);
95 int *pos = ren_position(s);
96 int i;
97 p = pos_prev(pos, n, p, 1);
98 for (i = 0; i < n; i++)
99 if (pos[i] == p)
100 off = i;
101 free(pos);
102 return off >= 0 ? off : 0;
105 /* adjust cursor position */
106 int ren_cursor(char *s, int p)
108 int n, next;
109 int *pos;
110 if (!s)
111 return 0;
112 n = uc_slen(s);
113 pos = ren_position(s);
114 p = pos_prev(pos, n, p, 1);
115 if (uc_code(uc_chr(s, ren_off(s, p))) == '\n')
116 p = pos_prev(pos, n, p, 0);
117 next = pos_next(pos, n, p, 0);
118 p = (next >= 0 ? next : pos[n]) - 1;
119 free(pos);
120 return p >= 0 ? p : 0;
123 /* return an offset before EOL */
124 int ren_noeol(char *s, int o)
126 int n = s ? uc_slen(s) : 0;
127 if (o >= n)
128 o = MAX(0, n - 1);
129 return o > 0 && uc_chr(s, o)[0] == '\n' ? o - 1 : o;
132 /* the position of the next character */
133 int ren_next(char *s, int p, int dir)
135 int n = uc_slen(s);
136 int *pos = ren_position(s);
137 p = pos_prev(pos, n, p, 1);
138 if (dir >= 0)
139 p = pos_next(pos, n, p, 0);
140 else
141 p = pos_prev(pos, n, p, 0);
142 free(pos);
143 return s && uc_chr(s, ren_off(s, p))[0] != '\n' ? p : -1;
146 static char *ren_placeholder(char *s, int *wid)
148 char *src, *dst;
149 int i;
150 for (i = 0; !conf_placeholder(i, &src, &dst, wid); i++)
151 if (src[0] == s[0] && uc_code(src) == uc_code(s))
152 return dst;
153 if (wid)
154 *wid = 1;
155 if (uc_isbell(s))
156 return "�";
157 return NULL;
160 int ren_cwid(char *s, int pos)
162 int wid;
163 if (s[0] == '\t')
164 return 8 - (pos & 7);
165 if (ren_placeholder(s, &wid))
166 return wid;
167 return uc_wid(s);
170 char *ren_translate(char *s, char *ln)
172 char *p = ren_placeholder(s, NULL);
173 return p || !xshape ? p : uc_shape(ln, s);