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