vi: specifying yank buffer for d, c, y, and p
[neatvi.git] / led.c
blob763e37403b518b97a1fe77dcadf3ef27f30f4b12
1 #include <stdio.h>
2 #include <string.h>
3 #include <stdlib.h>
4 #include <unistd.h>
5 #include "vi.h"
6 #include "kmap.h"
8 static char **led_kmap = kmap_def;
10 static char *keymap(char **kmap, int c)
12 static char cs[4];
13 cs[0] = c;
14 return kmap[c] ? kmap[c] : cs;
17 /* map cursor horizontal position to terminal column number */
18 int led_pos(char *s, int pos)
20 return dir_context(s) >= 0 ? pos : xcols - pos - 1;
23 char *led_keymap(int c)
25 return c >= 0 ? keymap(led_kmap, c) : NULL;
28 static char *led_render(char *s0)
30 int n, maxcol = 0;
31 int *pos; /* pos[i]: the screen position of the i-th character */
32 int *off; /* off[i]: the character at screen position i */
33 char **chrs; /* chrs[i]: the i-th character in s1 */
34 char *s1;
35 struct sbuf *out;
36 int i;
37 s1 = ren_translate(s0 ? s0 : "");
38 chrs = uc_chop(s1, &n);
39 pos = ren_position(s0);
40 off = malloc(xcols * sizeof(off[0]));
41 memset(off, 0xff, xcols * sizeof(off[0]));
42 for (i = 0; i < n; i++) {
43 int curpos = led_pos(s0, pos[i]);
44 if (curpos >= 0 && curpos < xcols) {
45 off[curpos] = i;
46 if (curpos > maxcol)
47 maxcol = curpos;
50 out = sbuf_make();
51 for (i = 0; i <= maxcol; i++) {
52 if (off[i] >= 0 && uc_isprint(chrs[off[i]]))
53 sbuf_mem(out, chrs[off[i]], uc_len(chrs[off[i]]));
54 else
55 sbuf_chr(out, ' ');
57 free(pos);
58 free(off);
59 free(chrs);
60 free(s1);
61 return sbuf_done(out);
64 void led_print(char *s, int row)
66 char *r = led_render(s);
67 term_pos(row, 0);
68 term_kill();
69 term_str(r);
70 free(r);
73 static int led_lastchar(char *s)
75 char *r = *s ? strchr(s, '\0') : s;
76 if (r != s)
77 r = uc_beg(s, r - 1);
78 return r - s;
81 static int led_lastword(char *s)
83 char *r = *s ? uc_beg(s, strchr(s, '\0') - 1) : s;
84 int kind;
85 while (r > s && uc_isspace(r))
86 r = uc_beg(s, r - 1);
87 kind = r > s ? uc_kind(r) : 0;
88 while (r > s && uc_kind(uc_beg(s, r - 1)) == kind)
89 r = uc_beg(s, r - 1);
90 return r - s;
93 static void led_printparts(char *ai, char *pref, char *main, char *post)
95 struct sbuf *ln;
96 int off, pos;
97 ln = sbuf_make();
98 sbuf_str(ln, ai);
99 sbuf_str(ln, pref);
100 sbuf_str(ln, main);
101 off = uc_slen(sbuf_buf(ln));
102 sbuf_str(ln, post);
103 /* cursor position for inserting the next character */
104 if (post[0]) {
105 pos = ren_cursor(sbuf_buf(ln), ren_pos(sbuf_buf(ln), off));
106 } else {
107 int len = sbuf_len(ln);
108 sbuf_str(ln, keymap(led_kmap, 'a'));
109 pos = ren_cursor(sbuf_buf(ln), ren_pos(sbuf_buf(ln), off));
110 sbuf_cut(ln, len);
112 led_print(sbuf_buf(ln), -1);
113 term_pos(-1, led_pos(sbuf_buf(ln), pos));
114 sbuf_free(ln);
117 static char *led_line(char *pref, char *post, char *ai, int ai_max, int *key, char ***kmap)
119 struct sbuf *sb;
120 int ai_len = strlen(ai);
121 int c;
122 sb = sbuf_make();
123 if (!pref)
124 pref = "";
125 if (!post)
126 post = "";
127 while (1) {
128 led_printparts(ai, pref, sbuf_buf(sb), post);
129 c = term_read(-1);
130 switch (c) {
131 case TK_CTL('f'):
132 *kmap = kmap_farsi;
133 continue;
134 case TK_CTL('e'):
135 *kmap = kmap_def;
136 continue;
137 case TK_CTL('h'):
138 case 127:
139 if (sbuf_len(sb))
140 sbuf_cut(sb, led_lastchar(sbuf_buf(sb)));
141 break;
142 case TK_CTL('u'):
143 sbuf_cut(sb, 0);
144 break;
145 case TK_CTL('v'):
146 sbuf_chr(sb, term_read(-1));
147 break;
148 case TK_CTL('w'):
149 if (sbuf_len(sb))
150 sbuf_cut(sb, led_lastword(sbuf_buf(sb)));
151 break;
152 case TK_CTL('t'):
153 if (ai_len < ai_max)
154 ai[ai_len++] = '\t';
155 break;
156 case TK_CTL('d'):
157 if (ai_len > 0)
158 ai[--ai_len] = '\0';
159 break;
160 default:
161 if (c == '\n' || TK_INT(c))
162 break;
163 sbuf_str(sb, keymap(*kmap, c));
165 if (c == '\n' || TK_INT(c))
166 break;
168 *key = c;
169 return sbuf_done(sb);
172 /* read an ex command */
173 char *led_prompt(char *pref, char *post)
175 char **kmap = kmap_def;
176 char *s;
177 int key;
178 s = led_line(pref, post, "", 0, &key, &kmap);
179 if (key == '\n')
180 return s;
181 free(s);
182 return NULL;
185 /* read visual command input */
186 char *led_input(char *pref, char *post, char *ai, int ai_max)
188 struct sbuf *sb = sbuf_make();
189 char *first_ai = NULL;
190 int key;
191 while (1) {
192 char *ln = led_line(pref, post, ai, ai_max, &key, &led_kmap);
193 if (pref)
194 first_ai = uc_dup(ai);
195 if (!pref)
196 sbuf_str(sb, ai);
197 sbuf_str(sb, ln);
198 if (key == '\n')
199 sbuf_chr(sb, '\n');
200 led_printparts(ai, pref ? pref : "", ln, key == '\n' ? "" : post);
201 if (key == '\n')
202 term_chr('\n');
203 pref = NULL;
204 term_kill();
205 free(ln);
206 if (key != '\n')
207 break;
208 while (ai_max && post[0] && (post[0] == ' ' || post[0] == '\t'))
209 post++;
211 strcpy(ai, first_ai);
212 free(first_ai);
213 if (TK_INT(key))
214 return sbuf_done(sb);
215 sbuf_free(sb);
216 return NULL;