Introduction
Introduction Statistics Contact Development Disclaimer Help
tled.c - neatvi - [fork] simple vi-type editor with UTF-8 support
git clone git://src.adamsgaard.dk/neatvi
Log
Files
Refs
README
---
tled.c (9295B)
---
1 /* line editing and drawing */
2 #include <ctype.h>
3 #include <stdio.h>
4 #include <string.h>
5 #include <stdlib.h>
6 #include <unistd.h>
7 #include "vi.h"
8
9 static char *kmap_map(int kmap, int c)
10 {
11 static char cs[4];
12 char **keymap = conf_kmap(kmap);
13 cs[0] = c;
14 return keymap[c] ? keymap[c] : cs;
15 }
16
17 static int led_posctx(int dir, int pos, int beg, int end)
18 {
19 return dir >= 0 ? pos - beg : end - pos - 1;
20 }
21
22 /* map cursor horizontal position to terminal column number */
23 int led_pos(char *s, int pos)
24 {
25 return led_posctx(dir_context(s), pos, xleft, xleft + xcols);
26 }
27
28 static int led_offdir(char **chrs, int *pos, int i)
29 {
30 if (pos[i] + ren_cwid(chrs[i], pos[i]) == pos[i + 1])
31 return +1;
32 if (pos[i + 1] + ren_cwid(chrs[i + 1], pos[i + 1]) == pos[i])
33 return -1;
34 return 0;
35 }
36
37 /* highlight text in reverse direction */
38 static void led_markrev(int n, char **chrs, int *pos, int *att)
39 {
40 int i = 0, j;
41 int hl = conf_hlrev();
42 while (i + 1 < n) {
43 int dir = led_offdir(chrs, pos, i);
44 int beg = i;
45 while (i + 1 < n && led_offdir(chrs, pos, i) == dir)
46 i++;
47 if (dir < 0)
48 for (j = beg; j <= i; j++)
49 att[j] = syn_merge(hl, att[j]);
50 if (i == beg)
51 i++;
52 }
53 }
54
55 /* render and highlight a line */
56 static char *led_render(char *s0, int cbeg, int cend, char *syn)
57 {
58 int n;
59 int *pos; /* pos[i]: the screen position of the i-th char…
60 int *off; /* off[i]: the character at screen position i */
61 int *att; /* att[i]: the attributes of i-th character */
62 char **chrs; /* chrs[i]: the i-th character in s1 */
63 int att_old = 0;
64 struct sbuf *out;
65 int i, j;
66 int ctx = dir_context(s0);
67 int att_blank = 0; /* the attribute of blank spac…
68 chrs = uc_chop(s0, &n);
69 pos = ren_position(s0);
70 off = malloc((cend - cbeg) * sizeof(off[0]));
71 memset(off, 0xff, (cend - cbeg) * sizeof(off[0]));
72 /* initialise off[] using pos[] */
73 for (i = 0; i < n; i++) {
74 int curwid = ren_cwid(chrs[i], pos[i]);
75 int curbeg = led_posctx(ctx, pos[i], cbeg, cend);
76 int curend = led_posctx(ctx, pos[i] + curwid - 1, cbeg, …
77 if (curbeg >= 0 && curbeg < (cend - cbeg) &&
78 curend >= 0 && curend < (cend - cbeg))
79 for (j = 0; j < curwid; j++)
80 off[led_posctx(ctx, pos[i] + j, cbeg, ce…
81 }
82 att = syn_highlight((n <= xlim && xhl) ? syn : "", s0);
83 /* the attribute of \n character is used for blanks */
84 for (i = 0; i < n; i++)
85 if (chrs[i][0] == '\n')
86 att_blank = att[i];
87 led_markrev(n, chrs, pos, att);
88 /* generate term output */
89 out = sbuf_make();
90 sbuf_str(out, conf_lnpref());
91 i = cbeg;
92 while (i < cend) {
93 int o = off[i - cbeg];
94 int att_new = o >= 0 ? att[o] : att_blank;
95 sbuf_str(out, term_att(att_new, att_old));
96 att_old = att_new;
97 if (o >= 0) {
98 if (ren_translate(chrs[o], s0))
99 sbuf_str(out, ren_translate(chrs[o], s0)…
100 else if (uc_isprint(chrs[o]))
101 sbuf_mem(out, chrs[o], uc_len(chrs[o]));
102 else
103 for (j = i; j < cend && off[j - cbeg] ==…
104 sbuf_chr(out, ' ');
105 while (i < cend && off[i - cbeg] == o)
106 i++;
107 } else {
108 sbuf_chr(out, ' ');
109 i++;
110 }
111 }
112 sbuf_str(out, term_att(0, att_old));
113 free(att);
114 free(pos);
115 free(off);
116 free(chrs);
117 return sbuf_done(out);
118 }
119
120 /* print a line on the screen */
121 void led_print(char *s, int row, char *syn)
122 {
123 char *r = led_render(s, xleft, xleft + xcols, syn);
124 term_pos(row, 0);
125 term_kill();
126 term_str(r);
127 free(r);
128 }
129
130 /* set xtd and return its old value */
131 static int td_set(int td)
132 {
133 int old = xtd;
134 xtd = td;
135 return old;
136 }
137
138 /* print a line on the screen; for ex messages */
139 void led_printmsg(char *s, int row, char *syn)
140 {
141 int td = td_set(+2);
142 char *r = led_render(s, xleft, xleft + xcols, syn);
143 td_set(td);
144 term_pos(row, 0);
145 term_kill();
146 term_str(r);
147 free(r);
148 }
149
150 static int led_lastchar(char *s)
151 {
152 char *r = *s ? strchr(s, '\0') : s;
153 if (r != s)
154 r = uc_beg(s, r - 1);
155 return r - s;
156 }
157
158 static int led_lastword(char *s)
159 {
160 char *r = *s ? uc_beg(s, strchr(s, '\0') - 1) : s;
161 int kind;
162 while (r > s && uc_isspace(r))
163 r = uc_beg(s, r - 1);
164 kind = r > s ? uc_kind(r) : 0;
165 while (r > s && uc_kind(uc_beg(s, r - 1)) == kind)
166 r = uc_beg(s, r - 1);
167 return r - s;
168 }
169
170 static void led_printparts(char *ai, char *pref, char *main,
171 char *post, int kmap, char *syn)
172 {
173 struct sbuf *ln;
174 int off, pos;
175 int idir = 0;
176 ln = sbuf_make();
177 sbuf_str(ln, ai);
178 sbuf_str(ln, pref);
179 sbuf_str(ln, main);
180 off = uc_slen(sbuf_buf(ln));
181 /* cursor position for inserting the next character */
182 if (*pref || *main || *ai) {
183 int len = sbuf_len(ln);
184 sbuf_str(ln, kmap_map(kmap, 'a'));
185 sbuf_str(ln, post);
186 idir = ren_pos(sbuf_buf(ln), off) -
187 ren_pos(sbuf_buf(ln), off - 1) < 0 ? -1 : +1;
188 sbuf_cut(ln, len);
189 }
190 term_record();
191 sbuf_str(ln, post);
192 pos = ren_cursor(sbuf_buf(ln), ren_pos(sbuf_buf(ln), MAX(0, off …
193 if (pos >= xleft + xcols)
194 xleft = pos - xcols / 2;
195 if (pos < xleft)
196 xleft = pos < xcols ? 0 : pos - xcols / 2;
197 led_print(sbuf_buf(ln), -1, syn);
198 term_pos(-1, led_pos(sbuf_buf(ln), pos + idir));
199 sbuf_free(ln);
200 term_commit();
201 }
202
203 /* continue reading the character starting with c */
204 static char *led_readchar(int c, int kmap)
205 {
206 static char buf[8];
207 int c1, c2;
208 int i, n;
209 if (c == TK_CTL('v')) { /* literal character */
210 buf[0] = term_read();
211 buf[1] = '\0';
212 return buf;
213 }
214 if (c == TK_CTL('k')) { /* digraph */
215 c1 = term_read();
216 if (TK_INT(c1))
217 return NULL;
218 c2 = term_read();
219 if (TK_INT(c2))
220 return NULL;
221 return conf_digraph(c1, c2);
222 }
223 if ((c & 0xc0) == 0xc0) { /* utf-8 character */
224 buf[0] = c;
225 n = uc_len(buf);
226 for (i = 1; i < n; i++)
227 buf[i] = term_read();
228 buf[n] = '\0';
229 return buf;
230 }
231 return kmap_map(kmap, c);
232 }
233
234 /* read a character from the terminal */
235 char *led_read(int *kmap)
236 {
237 int c = term_read();
238 while (!TK_INT(c)) {
239 switch (c) {
240 case TK_CTL('f'):
241 *kmap = xkmap_alt;
242 break;
243 case TK_CTL('e'):
244 *kmap = 0;
245 break;
246 default:
247 return led_readchar(c, *kmap);
248 }
249 c = term_read();
250 }
251 return NULL;
252 }
253
254 /* read a line from the terminal */
255 static char *led_line(char *pref, char *post, char *ai,
256 int ai_max, int *key, int *kmap, char *syn)
257 {
258 struct sbuf *sb;
259 int ai_len = strlen(ai);
260 int c, lnmode;
261 char *cs;
262 sb = sbuf_make();
263 if (!pref)
264 pref = "";
265 if (!post)
266 post = "";
267 while (1) {
268 led_printparts(ai, pref, sbuf_buf(sb), post, *kmap, syn);
269 c = term_read();
270 switch (c) {
271 case TK_CTL('f'):
272 *kmap = xkmap_alt;
273 continue;
274 case TK_CTL('e'):
275 *kmap = 0;
276 continue;
277 case TK_CTL('h'):
278 case 127:
279 if (sbuf_len(sb))
280 sbuf_cut(sb, led_lastchar(sbuf_buf(sb)));
281 break;
282 case TK_CTL('u'):
283 sbuf_cut(sb, 0);
284 break;
285 case TK_CTL('w'):
286 if (sbuf_len(sb))
287 sbuf_cut(sb, led_lastword(sbuf_buf(sb)));
288 break;
289 case TK_CTL('t'):
290 if (ai_len < ai_max) {
291 ai[ai_len++] = '\t';
292 ai[ai_len] = '\0';
293 }
294 break;
295 case TK_CTL('d'):
296 /* when ai and pref are empty, remove the first …
297 if (ai_len == 0 && !pref[0]) {
298 char *buf = sbuf_buf(sb);
299 if (buf[0] == ' ' || buf[0] == '\t') {
300 char *dup = uc_dup(buf + 1);
301 sbuf_cut(sb, 0);
302 sbuf_str(sb, dup);
303 free(dup);
304 }
305 }
306 if (ai_len > 0)
307 ai[--ai_len] = '\0';
308 break;
309 case TK_CTL('p'):
310 if (reg_get(0, &lnmode))
311 sbuf_str(sb, reg_get(0, &lnmode));
312 break;
313 default:
314 if (c == '\n' || TK_INT(c))
315 break;
316 if ((cs = led_readchar(c, *kmap)))
317 sbuf_str(sb, cs);
318 }
319 if (c == '\n' || TK_INT(c))
320 break;
321 }
322 *key = c;
323 return sbuf_done(sb);
324 }
325
326 /* read an ex command */
327 char *led_prompt(char *pref, char *post, int *kmap, char *syn)
328 {
329 int key;
330 int td = td_set(+2);
331 char *s = led_line(pref, post, "", 0, &key, kmap, syn);
332 td_set(td);
333 if (key == '\n') {
334 struct sbuf *sb = sbuf_make();
335 if (pref)
336 sbuf_str(sb, pref);
337 sbuf_str(sb, s);
338 if (post)
339 sbuf_str(sb, post);
340 free(s);
341 return sbuf_done(sb);
342 }
343 free(s);
344 return NULL;
345 }
346
347 /* read visual command input */
348 char *led_input(char *pref, char *post, int *kmap, char *syn)
349 {
350 struct sbuf *sb = sbuf_make();
351 char ai[128];
352 int ai_max = sizeof(ai) - 1;
353 int n = 0;
354 int key;
355 while (n < ai_max && (*pref == ' ' || *pref == '\t'))
356 ai[n++] = *pref++;
357 ai[n] = '\0';
358 while (1) {
359 char *ln = led_line(pref, post, ai, ai_max, &key, kmap, …
360 int ln_sp = 0; /* number of initial spaces in ln …
361 while (ln[ln_sp] && (ln[ln_sp] == ' ' || ln[ln_sp] == '\…
362 ln_sp++;
363 /* append the auto-indent only if there are other charac…
364 if (ln[ln_sp] || (pref && pref[0]) ||
365 (key != '\n' && post[0] && post[0] != '\…
366 sbuf_str(sb, ai);
367 if (pref)
368 sbuf_str(sb, pref);
369 sbuf_str(sb, ln);
370 if (key == '\n')
371 sbuf_chr(sb, '\n');
372 led_printparts(ai, pref ? pref : "", uc_lastline(ln),
373 key == '\n' ? "" : post, *kmap, syn);
374 if (key == '\n')
375 term_chr('\n');
376 if (!pref || !pref[0]) { /* updating autoindent */
377 int ai_len = ai_max ? strlen(ai) : 0;
378 int ai_new = ln_sp;
379 if (ai_len + ai_new > ai_max)
380 ai_new = ai_max - ai_len;
381 memcpy(ai + ai_len, ln, ai_new);
382 ai[ai_len + ai_new] = '\0';
383 }
384 if (!xai)
385 ai[0] = '\0';
386 free(ln);
387 if (key != '\n')
388 break;
389 term_room(1);
390 pref = NULL;
391 n = 0;
392 while (xai && (post[n] == ' ' || post[n] == '\t'))
393 n++;
394 memmove(post, post + n, strlen(post) - n + 1);
395 }
396 sbuf_str(sb, post);
397 if (TK_INT(key))
398 return sbuf_done(sb);
399 sbuf_free(sb);
400 return NULL;
401 }
You are viewing proxied material from mx1.adamsgaard.dk. 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.