xref: /netbsd-src/external/bsd/nvi/dist/vi/v_event.c (revision 2f698edb5c1cb2dcd9e762b0abb50c41dde8b6b7)
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