449 lines
8.4 KiB
C
449 lines
8.4 KiB
C
/* $NetBSD: v_event.c,v 1.3 2009/01/18 03:45:50 lukem Exp $ */
|
|
|
|
/*-
|
|
* Copyright (c) 1996
|
|
* Keith Bostic. All rights reserved.
|
|
*
|
|
* See the LICENSE file for redistribution information.
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#ifndef lint
|
|
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";
|
|
#endif /* not lint */
|
|
|
|
#include <sys/types.h>
|
|
#include <sys/queue.h>
|
|
#include <sys/time.h>
|
|
|
|
#include <bitstring.h>
|
|
#include <ctype.h>
|
|
#include <errno.h>
|
|
#include <limits.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
|
|
#include "../common/common.h"
|
|
#include "../ipc/ip.h"
|
|
#include "vi.h"
|
|
|
|
/*
|
|
* v_c_settop --
|
|
* Scrollbar position.
|
|
*/
|
|
static int
|
|
v_c_settop(SCR *sp, VICMD *vp)
|
|
{
|
|
SMAP *smp;
|
|
size_t x = 0, y = LASTLINE(sp); /* Future: change to -1 to not
|
|
* display the cursor
|
|
*/
|
|
size_t tx, ty = -1;
|
|
|
|
/*
|
|
* We want to scroll the screen, without changing the cursor position.
|
|
* So, we fill the screen map and then flush it to the screen. Then,
|
|
* set the VIP_S_REFRESH flag so the main vi loop doesn't update the
|
|
* screen. When the next real command happens, the refresh code will
|
|
* notice that the screen map is way wrong and fix it.
|
|
*
|
|
* XXX
|
|
* There may be a serious performance problem here -- we're doing no
|
|
* optimization whatsoever, which means that we're copying the entire
|
|
* screen out to the X11 screen code on each change.
|
|
*/
|
|
if (vs_sm_fill(sp, vp->ev.e_lno, P_TOP))
|
|
return (1);
|
|
for (smp = HMAP; smp <= TMAP; ++smp) {
|
|
SMAP_FLUSH(smp);
|
|
if (vs_line(sp, smp, &ty, &tx))
|
|
return (1);
|
|
if (ty != (size_t)-1) {
|
|
y = ty;
|
|
x = tx;
|
|
}
|
|
}
|
|
(void)sp->gp->scr_move(sp, y, x);
|
|
|
|
F_SET(VIP(sp), VIP_S_REFRESH);
|
|
|
|
return (sp->gp->scr_refresh(sp, 0));
|
|
}
|
|
|
|
/*
|
|
* v_edit --
|
|
* Edit command.
|
|
*/
|
|
static int
|
|
v_edit(SCR *sp, VICMD *vp)
|
|
{
|
|
EXCMD cmd;
|
|
|
|
ex_cinit(sp, &cmd, C_EDIT, 0, OOBLNO, OOBLNO, 0);
|
|
argv_exp0(sp, &cmd, vp->ev.e_csp, vp->ev.e_len);
|
|
return (v_exec_ex(sp, vp, &cmd));
|
|
}
|
|
|
|
/*
|
|
* v_editopt --
|
|
* Set an option value.
|
|
*/
|
|
static int
|
|
v_editopt(SCR *sp, VICMD *vp)
|
|
{
|
|
int rval;
|
|
const char *np;
|
|
size_t nlen;
|
|
char *p2;
|
|
|
|
INT2CHAR(sp, vp->ev.e_str2, STRLEN(vp->ev.e_str2)+1, np, nlen);
|
|
p2 = strdup(np);
|
|
rval = api_opts_set(sp, vp->ev.e_str1, p2,
|
|
vp->ev.e_val1, vp->ev.e_val1);
|
|
if (sp->gp->scr_reply != NULL)
|
|
(void)sp->gp->scr_reply(sp, rval, NULL);
|
|
free(p2);
|
|
return (rval);
|
|
}
|
|
|
|
/*
|
|
* v_editsplit --
|
|
* Edit in a split screen.
|
|
*/
|
|
static int
|
|
v_editsplit(SCR *sp, VICMD *vp)
|
|
{
|
|
EXCMD cmd;
|
|
|
|
ex_cinit(sp, &cmd, C_EDIT, 0, OOBLNO, OOBLNO, 0);
|
|
F_SET(&cmd, E_NEWSCREEN);
|
|
argv_exp0(sp, &cmd, vp->ev.e_csp, vp->ev.e_len);
|
|
return (v_exec_ex(sp, vp, &cmd));
|
|
}
|
|
|
|
/*
|
|
* v_tag --
|
|
* Tag command.
|
|
*/
|
|
static int
|
|
v_tag(SCR *sp, VICMD *vp)
|
|
{
|
|
EXCMD cmd;
|
|
|
|
if (v_curword(sp))
|
|
return (1);
|
|
|
|
ex_cinit(sp, &cmd, C_TAG, 0, OOBLNO, OOBLNO, 0);
|
|
argv_exp0(sp, &cmd, VIP(sp)->keyw, STRLEN(VIP(sp)->keyw));
|
|
return (v_exec_ex(sp, vp, &cmd));
|
|
}
|
|
|
|
/*
|
|
* v_tagas --
|
|
* Tag on the supplied string.
|
|
*/
|
|
static int
|
|
v_tagas(SCR *sp, VICMD *vp)
|
|
{
|
|
EXCMD cmd;
|
|
|
|
ex_cinit(sp, &cmd, C_TAG, 0, OOBLNO, OOBLNO, 0);
|
|
argv_exp0(sp, &cmd, vp->ev.e_csp, vp->ev.e_len);
|
|
return (v_exec_ex(sp, vp, &cmd));
|
|
}
|
|
|
|
/*
|
|
* v_tagsplit --
|
|
* Tag in a split screen.
|
|
*/
|
|
static int
|
|
v_tagsplit(SCR *sp, VICMD *vp)
|
|
{
|
|
EXCMD cmd;
|
|
|
|
if (v_curword(sp))
|
|
return (1);
|
|
|
|
ex_cinit(sp, &cmd, C_TAG, 0, OOBLNO, OOBLNO, 0);
|
|
F_SET(&cmd, E_NEWSCREEN);
|
|
argv_exp0(sp, &cmd, VIP(sp)->keyw, STRLEN(VIP(sp)->keyw));
|
|
return (v_exec_ex(sp, vp, &cmd));
|
|
}
|
|
|
|
/*
|
|
* v_quit --
|
|
* Quit command.
|
|
*/
|
|
static int
|
|
v_quit(SCR *sp, VICMD *vp)
|
|
{
|
|
EXCMD cmd;
|
|
|
|
ex_cinit(sp, &cmd, C_QUIT, 0, OOBLNO, OOBLNO, 0);
|
|
return (v_exec_ex(sp, vp, &cmd));
|
|
}
|
|
|
|
/*
|
|
* v_erepaint --
|
|
* Repaint selected lines from the screen.
|
|
*
|
|
* PUBLIC: int v_erepaint __P((SCR *, EVENT *));
|
|
*/
|
|
int
|
|
v_erepaint(SCR *sp, EVENT *evp)
|
|
{
|
|
SMAP *smp;
|
|
|
|
for (; evp->e_flno <= evp->e_tlno; ++evp->e_flno) {
|
|
smp = HMAP + evp->e_flno - 1;
|
|
SMAP_FLUSH(smp);
|
|
if (vs_line(sp, smp, NULL, NULL))
|
|
return (1);
|
|
}
|
|
return (0);
|
|
}
|
|
|
|
/*
|
|
* v_sel_end --
|
|
* End selection.
|
|
*/
|
|
static int
|
|
v_sel_end(SCR *sp, EVENT *evp)
|
|
{
|
|
SMAP *smp;
|
|
VI_PRIVATE *vip;
|
|
|
|
smp = HMAP + evp->e_lno;
|
|
if (smp > TMAP) {
|
|
/* XXX */
|
|
return (1);
|
|
}
|
|
|
|
vip = VIP(sp);
|
|
vip->sel.lno = smp->lno;
|
|
vip->sel.cno =
|
|
vs_colpos(sp, smp->lno, evp->e_cno + (smp->soff - 1) * sp->cols);
|
|
return (0);
|
|
}
|
|
|
|
/*
|
|
* v_sel_start --
|
|
* Start selection.
|
|
*/
|
|
static int
|
|
v_sel_start(SCR *sp, EVENT *evp)
|
|
{
|
|
SMAP *smp;
|
|
VI_PRIVATE *vip;
|
|
|
|
smp = HMAP + evp->e_lno;
|
|
if (smp > TMAP) {
|
|
/* XXX */
|
|
return (1);
|
|
}
|
|
|
|
vip = VIP(sp);
|
|
vip->sel.lno = smp->lno;
|
|
vip->sel.cno =
|
|
vs_colpos(sp, smp->lno, evp->e_cno + (smp->soff - 1) * sp->cols);
|
|
return (0);
|
|
}
|
|
|
|
/*
|
|
* v_wq --
|
|
* Write and quit command.
|
|
*/
|
|
static int
|
|
v_wq(SCR *sp, VICMD *vp)
|
|
{
|
|
EXCMD cmd;
|
|
|
|
ex_cinit(sp, &cmd, C_WQ, 0, OOBLNO, OOBLNO, 0);
|
|
|
|
cmd.addr1.lno = 1;
|
|
if (db_last(sp, &cmd.addr2.lno))
|
|
return (1);
|
|
return (v_exec_ex(sp, vp, &cmd));
|
|
}
|
|
|
|
/*
|
|
* v_write --
|
|
* Write command.
|
|
*/
|
|
static int
|
|
v_write(SCR *sp, VICMD *vp)
|
|
{
|
|
EXCMD cmd;
|
|
|
|
ex_cinit(sp, &cmd, C_WRITE, 0, OOBLNO, OOBLNO, 0);
|
|
|
|
cmd.addr1.lno = 1;
|
|
if (db_last(sp, &cmd.addr2.lno))
|
|
return (1);
|
|
return (v_exec_ex(sp, vp, &cmd));
|
|
}
|
|
|
|
/*
|
|
* v_writeas --
|
|
* Write command.
|
|
*/
|
|
static int
|
|
v_writeas(SCR *sp, VICMD *vp)
|
|
{
|
|
EXCMD cmd;
|
|
|
|
ex_cinit(sp, &cmd, C_WRITE, 0, OOBLNO, OOBLNO, 0);
|
|
argv_exp0(sp, &cmd, vp->ev.e_csp, vp->ev.e_len);
|
|
|
|
cmd.addr1.lno = 1;
|
|
if (db_last(sp, &cmd.addr2.lno))
|
|
return (1);
|
|
return (v_exec_ex(sp, vp, &cmd));
|
|
}
|
|
|
|
/*
|
|
* v_event --
|
|
* Find the event associated with a function.
|
|
*
|
|
* PUBLIC: int v_event __P((SCR *, VICMD *));
|
|
*/
|
|
int
|
|
v_event(SCR *sp, VICMD *vp)
|
|
{
|
|
/* This array maps events to vi command functions. */
|
|
#define VIKEYDEF(a, b) { a, b, NULL, NULL }
|
|
static VIKEYS const vievents[] = {
|
|
#define V_C_SETTOP 0 /* VI_C_SETTOP */
|
|
VIKEYDEF(v_c_settop, 0),
|
|
#define V_EDIT 1 /* VI_EDIT */
|
|
VIKEYDEF(v_edit, 0),
|
|
#define V_EDITOPT 2 /* VI_EDITOPT */
|
|
VIKEYDEF(v_editopt, 0),
|
|
#define V_EDITSPLIT 3 /* VI_EDITSPLIT */
|
|
VIKEYDEF(v_editsplit, 0),
|
|
#define V_EMARK 4 /* VI_MOUSE_MOVE */
|
|
VIKEYDEF(v_emark, V_ABS_L|V_MOVE),
|
|
#define V_QUIT 5 /* VI_QUIT */
|
|
VIKEYDEF(v_quit, 0),
|
|
#define V_SEARCH 6 /* VI_SEARCH */
|
|
VIKEYDEF(v_esearch, V_ABS_L|V_MOVE),
|
|
#define V_TAG 7 /* VI_TAG */
|
|
VIKEYDEF(v_tag, 0),
|
|
#define V_TAGAS 8 /* VI_TAGAS */
|
|
VIKEYDEF(v_tagas, 0),
|
|
#define V_TAGSPLIT 9 /* VI_TAGSPLIT */
|
|
VIKEYDEF(v_tagsplit, 0),
|
|
#define V_WQ 10 /* VI_WQ */
|
|
VIKEYDEF(v_wq, 0),
|
|
#define V_WRITE 11 /* VI_WRITE */
|
|
VIKEYDEF(v_write, 0),
|
|
#define V_WRITEAS 12 /* VI_WRITEAS */
|
|
VIKEYDEF(v_writeas, 0),
|
|
};
|
|
|
|
switch (vp->ev.e_ipcom) {
|
|
case VI_C_BOL:
|
|
vp->kp = &vikeys['0'];
|
|
break;
|
|
case VI_C_BOTTOM:
|
|
vp->kp = &vikeys['G'];
|
|
break;
|
|
case VI_C_DEL:
|
|
vp->kp = &vikeys['x'];
|
|
break;
|
|
case VI_C_DOWN:
|
|
F_SET(vp, VC_C1SET);
|
|
vp->count = vp->ev.e_lno;
|
|
vp->kp = &vikeys['\012'];
|
|
break;
|
|
case VI_C_EOL:
|
|
vp->kp = &vikeys['$'];
|
|
break;
|
|
case VI_C_INSERT:
|
|
vp->kp = &vikeys['i'];
|
|
break;
|
|
case VI_C_LEFT:
|
|
vp->kp = &vikeys['\010'];
|
|
break;
|
|
case VI_C_PGDOWN:
|
|
F_SET(vp, VC_C1SET);
|
|
vp->count = vp->ev.e_lno;
|
|
vp->kp = &vikeys['\006'];
|
|
break;
|
|
case VI_C_PGUP:
|
|
F_SET(vp, VC_C1SET);
|
|
vp->count = vp->ev.e_lno;
|
|
vp->kp = &vikeys['\002'];
|
|
break;
|
|
case VI_C_RIGHT:
|
|
vp->kp = &vikeys['\040'];
|
|
break;
|
|
case VI_C_SEARCH:
|
|
vp->kp = &vievents[V_SEARCH];
|
|
break;
|
|
case VI_C_SETTOP:
|
|
vp->kp = &vievents[V_C_SETTOP];
|
|
break;
|
|
case VI_C_TOP:
|
|
F_SET(vp, VC_C1SET);
|
|
vp->count = 1;
|
|
vp->kp = &vikeys['G'];
|
|
break;
|
|
case VI_C_UP:
|
|
F_SET(vp, VC_C1SET);
|
|
vp->count = vp->ev.e_lno;
|
|
vp->kp = &vikeys['\020'];
|
|
break;
|
|
case VI_EDIT:
|
|
vp->kp = &vievents[V_EDIT];
|
|
break;
|
|
case VI_EDITOPT:
|
|
vp->kp = &vievents[V_EDITOPT];
|
|
break;
|
|
case VI_EDITSPLIT:
|
|
vp->kp = &vievents[V_EDITSPLIT];
|
|
break;
|
|
case VI_MOUSE_MOVE:
|
|
vp->kp = &vievents[V_EMARK];
|
|
break;
|
|
case VI_SEL_END:
|
|
v_sel_end(sp, &vp->ev);
|
|
/* XXX RETURN IGNORE */
|
|
break;
|
|
case VI_SEL_START:
|
|
v_sel_start(sp, &vp->ev);
|
|
/* XXX RETURN IGNORE */
|
|
break;
|
|
case VI_QUIT:
|
|
vp->kp = &vievents[V_QUIT];
|
|
break;
|
|
case VI_TAG:
|
|
vp->kp = &vievents[V_TAG];
|
|
break;
|
|
case VI_TAGAS:
|
|
vp->kp = &vievents[V_TAGAS];
|
|
break;
|
|
case VI_TAGSPLIT:
|
|
vp->kp = &vievents[V_TAGSPLIT];
|
|
break;
|
|
case VI_UNDO:
|
|
vp->kp = &vikeys['u'];
|
|
break;
|
|
case VI_WQ:
|
|
vp->kp = &vievents[V_WQ];
|
|
break;
|
|
case VI_WRITE:
|
|
vp->kp = &vievents[V_WRITE];
|
|
break;
|
|
case VI_WRITEAS:
|
|
vp->kp = &vievents[V_WRITEAS];
|
|
break;
|
|
default:
|
|
return (1);
|
|
}
|
|
return (0);
|
|
}
|