Home | History | Annotate | Line # | Download | only in vi
      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
     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
     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
     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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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