1 /* $NetBSD: v_event.c,v 1.3 2014/01/26 21:43:45 christos Exp $ */
2 /*-
3 * Copyright (c) 1996
4 * Keith Bostic. All rights reserved.
5 *
6 * See the LICENSE file for redistribution information.
7 */
8
9 #include "config.h"
10
11 #include <sys/cdefs.h>
12 #if 0
13 #ifndef lint
14 static const char sccsid[] = "Id: v_event.c,v 8.21 2001/06/25 15:19:31 skimo Exp (Berkeley) Date: 2001/06/25 15:19:31 ";
15 #endif /* not lint */
16 #else
17 __RCSID("$NetBSD: v_event.c,v 1.3 2014/01/26 21:43:45 christos Exp $");
18 #endif
19
20 #include <sys/types.h>
21 #include <sys/queue.h>
22 #include <sys/time.h>
23
24 #include <bitstring.h>
25 #include <ctype.h>
26 #include <errno.h>
27 #include <limits.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <unistd.h>
32
33 #include "../common/common.h"
34 #include "../ipc/ip.h"
35 #include "vi.h"
36
37 /*
38 * v_c_settop --
39 * Scrollbar position.
40 */
41 static int
v_c_settop(SCR * sp,VICMD * vp)42 v_c_settop(SCR *sp, VICMD *vp)
43 {
44 SMAP *smp;
45 size_t x = 0, y = LASTLINE(sp); /* Future: change to -1 to not
46 * display the cursor
47 */
48 size_t tx, ty = -1;
49
50 /*
51 * We want to scroll the screen, without changing the cursor position.
52 * So, we fill the screen map and then flush it to the screen. Then,
53 * set the VIP_S_REFRESH flag so the main vi loop doesn't update the
54 * screen. When the next real command happens, the refresh code will
55 * notice that the screen map is way wrong and fix it.
56 *
57 * XXX
58 * There may be a serious performance problem here -- we're doing no
59 * optimization whatsoever, which means that we're copying the entire
60 * screen out to the X11 screen code on each change.
61 */
62 if (vs_sm_fill(sp, vp->ev.e_lno, P_TOP))
63 return (1);
64 for (smp = HMAP; smp <= TMAP; ++smp) {
65 SMAP_FLUSH(smp);
66 if (vs_line(sp, smp, &ty, &tx))
67 return (1);
68 if (ty != (size_t)-1) {
69 y = ty;
70 x = tx;
71 }
72 }
73 (void)sp->gp->scr_move(sp, y, x);
74
75 F_SET(VIP(sp), VIP_S_REFRESH);
76
77 return (sp->gp->scr_refresh(sp, 0));
78 }
79
80 /*
81 * v_edit --
82 * Edit command.
83 */
84 static int
v_edit(SCR * sp,VICMD * vp)85 v_edit(SCR *sp, VICMD *vp)
86 {
87 EXCMD cmd;
88
89 ex_cinit(sp, &cmd, C_EDIT, 0, OOBLNO, OOBLNO, 0);
90 argv_exp0(sp, &cmd, vp->ev.e_csp, vp->ev.e_len);
91 return (v_exec_ex(sp, vp, &cmd));
92 }
93
94 /*
95 * v_editopt --
96 * Set an option value.
97 */
98 static int
v_editopt(SCR * sp,VICMD * vp)99 v_editopt(SCR *sp, VICMD *vp)
100 {
101 int rval;
102 const char *np;
103 size_t nlen;
104 char *p2;
105
106 INT2CHAR(sp, vp->ev.e_str2, STRLEN(vp->ev.e_str2)+1, np, nlen);
107 p2 = strdup(np);
108 rval = api_opts_set(sp, vp->ev.e_str1, p2,
109 vp->ev.e_val1, vp->ev.e_val1);
110 if (sp->gp->scr_reply != NULL)
111 (void)sp->gp->scr_reply(sp, rval, NULL);
112 free(p2);
113 return (rval);
114 }
115
116 /*
117 * v_editsplit --
118 * Edit in a split screen.
119 */
120 static int
v_editsplit(SCR * sp,VICMD * vp)121 v_editsplit(SCR *sp, VICMD *vp)
122 {
123 EXCMD cmd;
124
125 ex_cinit(sp, &cmd, C_EDIT, 0, OOBLNO, OOBLNO, 0);
126 F_SET(&cmd, E_NEWSCREEN);
127 argv_exp0(sp, &cmd, vp->ev.e_csp, vp->ev.e_len);
128 return (v_exec_ex(sp, vp, &cmd));
129 }
130
131 /*
132 * v_tag --
133 * Tag command.
134 */
135 static int
v_tag(SCR * sp,VICMD * vp)136 v_tag(SCR *sp, VICMD *vp)
137 {
138 EXCMD cmd;
139
140 if (v_curword(sp))
141 return (1);
142
143 ex_cinit(sp, &cmd, C_TAG, 0, OOBLNO, OOBLNO, 0);
144 argv_exp0(sp, &cmd, VIP(sp)->keyw, STRLEN(VIP(sp)->keyw));
145 return (v_exec_ex(sp, vp, &cmd));
146 }
147
148 /*
149 * v_tagas --
150 * Tag on the supplied string.
151 */
152 static int
v_tagas(SCR * sp,VICMD * vp)153 v_tagas(SCR *sp, VICMD *vp)
154 {
155 EXCMD cmd;
156
157 ex_cinit(sp, &cmd, C_TAG, 0, OOBLNO, OOBLNO, 0);
158 argv_exp0(sp, &cmd, vp->ev.e_csp, vp->ev.e_len);
159 return (v_exec_ex(sp, vp, &cmd));
160 }
161
162 /*
163 * v_tagsplit --
164 * Tag in a split screen.
165 */
166 static int
v_tagsplit(SCR * sp,VICMD * vp)167 v_tagsplit(SCR *sp, VICMD *vp)
168 {
169 EXCMD cmd;
170
171 if (v_curword(sp))
172 return (1);
173
174 ex_cinit(sp, &cmd, C_TAG, 0, OOBLNO, OOBLNO, 0);
175 F_SET(&cmd, E_NEWSCREEN);
176 argv_exp0(sp, &cmd, VIP(sp)->keyw, STRLEN(VIP(sp)->keyw));
177 return (v_exec_ex(sp, vp, &cmd));
178 }
179
180 /*
181 * v_quit --
182 * Quit command.
183 */
184 static int
v_quit(SCR * sp,VICMD * vp)185 v_quit(SCR *sp, VICMD *vp)
186 {
187 EXCMD cmd;
188
189 ex_cinit(sp, &cmd, C_QUIT, 0, OOBLNO, OOBLNO, 0);
190 return (v_exec_ex(sp, vp, &cmd));
191 }
192
193 /*
194 * v_erepaint --
195 * Repaint selected lines from the screen.
196 *
197 * PUBLIC: int v_erepaint __P((SCR *, EVENT *));
198 */
199 int
v_erepaint(SCR * sp,EVENT * evp)200 v_erepaint(SCR *sp, EVENT *evp)
201 {
202 SMAP *smp;
203
204 for (; evp->e_flno <= evp->e_tlno; ++evp->e_flno) {
205 smp = HMAP + evp->e_flno - 1;
206 SMAP_FLUSH(smp);
207 if (vs_line(sp, smp, NULL, NULL))
208 return (1);
209 }
210 return (0);
211 }
212
213 /*
214 * v_sel_end --
215 * End selection.
216 */
217 static int
v_sel_end(SCR * sp,EVENT * evp)218 v_sel_end(SCR *sp, EVENT *evp)
219 {
220 SMAP *smp;
221 VI_PRIVATE *vip;
222
223 smp = HMAP + evp->e_lno;
224 if (smp > TMAP) {
225 /* XXX */
226 return (1);
227 }
228
229 vip = VIP(sp);
230 vip->sel.lno = smp->lno;
231 vip->sel.cno =
232 vs_colpos(sp, smp->lno, evp->e_cno + (smp->soff - 1) * sp->cols);
233 return (0);
234 }
235
236 /*
237 * v_sel_start --
238 * Start selection.
239 */
240 static int
v_sel_start(SCR * sp,EVENT * evp)241 v_sel_start(SCR *sp, EVENT *evp)
242 {
243 SMAP *smp;
244 VI_PRIVATE *vip;
245
246 smp = HMAP + evp->e_lno;
247 if (smp > TMAP) {
248 /* XXX */
249 return (1);
250 }
251
252 vip = VIP(sp);
253 vip->sel.lno = smp->lno;
254 vip->sel.cno =
255 vs_colpos(sp, smp->lno, evp->e_cno + (smp->soff - 1) * sp->cols);
256 return (0);
257 }
258
259 /*
260 * v_wq --
261 * Write and quit command.
262 */
263 static int
v_wq(SCR * sp,VICMD * vp)264 v_wq(SCR *sp, VICMD *vp)
265 {
266 EXCMD cmd;
267
268 ex_cinit(sp, &cmd, C_WQ, 0, OOBLNO, OOBLNO, 0);
269
270 cmd.addr1.lno = 1;
271 if (db_last(sp, &cmd.addr2.lno))
272 return (1);
273 return (v_exec_ex(sp, vp, &cmd));
274 }
275
276 /*
277 * v_write --
278 * Write command.
279 */
280 static int
v_write(SCR * sp,VICMD * vp)281 v_write(SCR *sp, VICMD *vp)
282 {
283 EXCMD cmd;
284
285 ex_cinit(sp, &cmd, C_WRITE, 0, OOBLNO, OOBLNO, 0);
286
287 cmd.addr1.lno = 1;
288 if (db_last(sp, &cmd.addr2.lno))
289 return (1);
290 return (v_exec_ex(sp, vp, &cmd));
291 }
292
293 /*
294 * v_writeas --
295 * Write command.
296 */
297 static int
v_writeas(SCR * sp,VICMD * vp)298 v_writeas(SCR *sp, VICMD *vp)
299 {
300 EXCMD cmd;
301
302 ex_cinit(sp, &cmd, C_WRITE, 0, OOBLNO, OOBLNO, 0);
303 argv_exp0(sp, &cmd, vp->ev.e_csp, vp->ev.e_len);
304
305 cmd.addr1.lno = 1;
306 if (db_last(sp, &cmd.addr2.lno))
307 return (1);
308 return (v_exec_ex(sp, vp, &cmd));
309 }
310
311 /*
312 * v_event --
313 * Find the event associated with a function.
314 *
315 * PUBLIC: int v_event __P((SCR *, VICMD *));
316 */
317 int
v_event(SCR * sp,VICMD * vp)318 v_event(SCR *sp, VICMD *vp)
319 {
320 /* This array maps events to vi command functions. */
321 #define VIKEYDEF(a, b) { a, b, NULL, NULL }
322 static VIKEYS const vievents[] = {
323 #define V_C_SETTOP 0 /* VI_C_SETTOP */
324 VIKEYDEF(v_c_settop, 0),
325 #define V_EDIT 1 /* VI_EDIT */
326 VIKEYDEF(v_edit, 0),
327 #define V_EDITOPT 2 /* VI_EDITOPT */
328 VIKEYDEF(v_editopt, 0),
329 #define V_EDITSPLIT 3 /* VI_EDITSPLIT */
330 VIKEYDEF(v_editsplit, 0),
331 #define V_EMARK 4 /* VI_MOUSE_MOVE */
332 VIKEYDEF(v_emark, V_ABS_L|V_MOVE),
333 #define V_QUIT 5 /* VI_QUIT */
334 VIKEYDEF(v_quit, 0),
335 #define V_SEARCH 6 /* VI_SEARCH */
336 VIKEYDEF(v_esearch, V_ABS_L|V_MOVE),
337 #define V_TAG 7 /* VI_TAG */
338 VIKEYDEF(v_tag, 0),
339 #define V_TAGAS 8 /* VI_TAGAS */
340 VIKEYDEF(v_tagas, 0),
341 #define V_TAGSPLIT 9 /* VI_TAGSPLIT */
342 VIKEYDEF(v_tagsplit, 0),
343 #define V_WQ 10 /* VI_WQ */
344 VIKEYDEF(v_wq, 0),
345 #define V_WRITE 11 /* VI_WRITE */
346 VIKEYDEF(v_write, 0),
347 #define V_WRITEAS 12 /* VI_WRITEAS */
348 VIKEYDEF(v_writeas, 0),
349 };
350
351 switch (vp->ev.e_ipcom) {
352 case VI_C_BOL:
353 vp->kp = &vikeys['0'];
354 break;
355 case VI_C_BOTTOM:
356 vp->kp = &vikeys['G'];
357 break;
358 case VI_C_DEL:
359 vp->kp = &vikeys['x'];
360 break;
361 case VI_C_DOWN:
362 F_SET(vp, VC_C1SET);
363 vp->count = vp->ev.e_lno;
364 vp->kp = &vikeys['\012'];
365 break;
366 case VI_C_EOL:
367 vp->kp = &vikeys['$'];
368 break;
369 case VI_C_INSERT:
370 vp->kp = &vikeys['i'];
371 break;
372 case VI_C_LEFT:
373 vp->kp = &vikeys['\010'];
374 break;
375 case VI_C_PGDOWN:
376 F_SET(vp, VC_C1SET);
377 vp->count = vp->ev.e_lno;
378 vp->kp = &vikeys['\006'];
379 break;
380 case VI_C_PGUP:
381 F_SET(vp, VC_C1SET);
382 vp->count = vp->ev.e_lno;
383 vp->kp = &vikeys['\002'];
384 break;
385 case VI_C_RIGHT:
386 vp->kp = &vikeys['\040'];
387 break;
388 case VI_C_SEARCH:
389 vp->kp = &vievents[V_SEARCH];
390 break;
391 case VI_C_SETTOP:
392 vp->kp = &vievents[V_C_SETTOP];
393 break;
394 case VI_C_TOP:
395 F_SET(vp, VC_C1SET);
396 vp->count = 1;
397 vp->kp = &vikeys['G'];
398 break;
399 case VI_C_UP:
400 F_SET(vp, VC_C1SET);
401 vp->count = vp->ev.e_lno;
402 vp->kp = &vikeys['\020'];
403 break;
404 case VI_EDIT:
405 vp->kp = &vievents[V_EDIT];
406 break;
407 case VI_EDITOPT:
408 vp->kp = &vievents[V_EDITOPT];
409 break;
410 case VI_EDITSPLIT:
411 vp->kp = &vievents[V_EDITSPLIT];
412 break;
413 case VI_MOUSE_MOVE:
414 vp->kp = &vievents[V_EMARK];
415 break;
416 case VI_SEL_END:
417 v_sel_end(sp, &vp->ev);
418 /* XXX RETURN IGNORE */
419 break;
420 case VI_SEL_START:
421 v_sel_start(sp, &vp->ev);
422 /* XXX RETURN IGNORE */
423 break;
424 case VI_QUIT:
425 vp->kp = &vievents[V_QUIT];
426 break;
427 case VI_TAG:
428 vp->kp = &vievents[V_TAG];
429 break;
430 case VI_TAGAS:
431 vp->kp = &vievents[V_TAGAS];
432 break;
433 case VI_TAGSPLIT:
434 vp->kp = &vievents[V_TAGSPLIT];
435 break;
436 case VI_UNDO:
437 vp->kp = &vikeys['u'];
438 break;
439 case VI_WQ:
440 vp->kp = &vievents[V_WQ];
441 break;
442 case VI_WRITE:
443 vp->kp = &vievents[V_WRITE];
444 break;
445 case VI_WRITEAS:
446 vp->kp = &vievents[V_WRITEAS];
447 break;
448 default:
449 return (1);
450 }
451 return (0);
452 }
453