#include "config.h"
#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 "../common/common.h"
#include "vi.h"
#define LOG_CORRECT { \
if (!MAPPED_KEYS_WAITING(sp)) \
(void)log_cursor(sp); \
}
static u_int32_t set_txt_std(SCR *, VICMD *, u_int32_t);
int
v_iA(SCR *sp, VICMD *vp)
{
size_t len;
if (!db_get(sp, vp->m_start.lno, 0, NULL, &len))
sp->cno = len == 0 ? 0 : len - 1;
LOG_CORRECT;
return (v_ia(sp, vp));
}
int
v_ia(SCR *sp, VICMD *vp)
{
size_t len;
u_int32_t flags;
int isempty;
char *p;
flags = set_txt_std(sp, vp, 0);
sp->showmode = SM_APPEND;
sp->lno = vp->m_start.lno;
if (db_eget(sp, sp->lno, &p, &len, &isempty)) {
if (!isempty)
return (1);
len = 0;
LF_SET(TXT_APPENDEOL);
} else if (len) {
if (len == sp->cno + 1) {
sp->cno = len;
LF_SET(TXT_APPENDEOL);
} else
++sp->cno;
} else
LF_SET(TXT_APPENDEOL);
return (v_txt(sp, vp, NULL, p, len,
0, OOBLNO, F_ISSET(vp, VC_C1SET) ? vp->count : 1, flags));
}
int
v_iI(SCR *sp, VICMD *vp)
{
sp->cno = 0;
if (nonblank(sp, vp->m_start.lno, &sp->cno))
return (1);
LOG_CORRECT;
return (v_ii(sp, vp));
}
int
v_ii(SCR *sp, VICMD *vp)
{
size_t len;
u_int32_t flags;
int isempty;
char *p;
flags = set_txt_std(sp, vp, 0);
sp->showmode = SM_INSERT;
sp->lno = vp->m_start.lno;
if (db_eget(sp, sp->lno, &p, &len, &isempty)) {
if (!isempty)
return (1);
len = 0;
}
if (len == 0)
LF_SET(TXT_APPENDEOL);
return (v_txt(sp, vp, NULL, p, len,
0, OOBLNO, F_ISSET(vp, VC_C1SET) ? vp->count : 1, flags));
}
enum which { o_cmd, O_cmd };
static int io(SCR *, VICMD *, enum which);
int
v_iO(SCR *sp, VICMD *vp)
{
return (io(sp, vp, O_cmd));
}
int
v_io(SCR *sp, VICMD *vp)
{
return (io(sp, vp, o_cmd));
}
static int
io(SCR *sp, VICMD *vp, enum which cmd)
{
recno_t ai_line, lno;
size_t len;
u_int32_t flags;
char *p;
flags = set_txt_std(sp, vp, TXT_ADDNEWLINE | TXT_APPENDEOL);
sp->showmode = SM_INSERT;
if (sp->lno == 1) {
if (db_last(sp, &lno))
return (1);
if (lno != 0)
goto insert;
p = NULL;
len = 0;
ai_line = OOBLNO;
} else {
insert: p = "";
sp->cno = 0;
LOG_CORRECT;
if (cmd == O_cmd) {
if (db_insert(sp, sp->lno, p, 0))
return (1);
if (db_get(sp, sp->lno, DBG_FATAL, &p, &len))
return (1);
ai_line = sp->lno + 1;
} else {
if (db_append(sp, 1, sp->lno, p, 0))
return (1);
if (db_get(sp, ++sp->lno, DBG_FATAL, &p, &len))
return (1);
ai_line = sp->lno - 1;
}
}
return (v_txt(sp, vp, NULL, p, len,
0, ai_line, F_ISSET(vp, VC_C1SET) ? vp->count : 1, flags));
}
int
v_change(SCR *sp, VICMD *vp)
{
size_t blen, len;
u_int32_t flags;
int isempty, lmode, rval;
char *bp, *p;
F_CLR(vp, VM_RCM_MASK);
F_SET(vp, VM_RCM_SET);
if (vp->m_start.lno == vp->m_stop.lno &&
db_eget(sp, vp->m_start.lno, &p, &len, &isempty)) {
if (!isempty)
return (1);
return (v_ia(sp, vp));
}
flags = set_txt_std(sp, vp, 0);
sp->showmode = SM_CHANGE;
lmode = F_ISSET(vp, VM_LMODE) ? CUT_LINEMODE : 0;
if (lmode) {
vp->m_start.cno = 0;
if (O_ISSET(sp, O_AUTOINDENT)) {
if (nonblank(sp, vp->m_start.lno, &vp->m_start.cno))
return (1);
LF_SET(TXT_AICHARS);
}
}
sp->lno = vp->m_start.lno;
sp->cno = vp->m_start.cno;
LOG_CORRECT;
if (!lmode && vp->m_start.lno == vp->m_stop.lno) {
if (cut(sp,
F_ISSET(vp, VC_BUFFER) ? &vp->buffer : NULL,
&vp->m_start, &vp->m_stop, lmode))
return (1);
if (len == 0)
LF_SET(TXT_APPENDEOL);
LF_SET(TXT_EMARK | TXT_OVERWRITE);
return (v_txt(sp, vp, &vp->m_stop, p, len,
0, OOBLNO, F_ISSET(vp, VC_C1SET) ? vp->count : 1, flags));
}
if (cut(sp,
F_ISSET(vp, VC_BUFFER) ? &vp->buffer : NULL,
&vp->m_start, &vp->m_stop, lmode))
return (1);
if (lmode && vp->m_start.cno) {
if (db_get(sp, vp->m_start.lno, DBG_FATAL, &p, &len))
return (1);
GET_SPACE_RET(sp, bp, blen, vp->m_start.cno);
memmove(bp, p, vp->m_start.cno);
} else
bp = NULL;
if (del(sp, &vp->m_start, &vp->m_stop, lmode))
return (1);
if (lmode) {
if (db_insert(sp, vp->m_start.lno, bp, vp->m_start.cno))
return (1);
sp->lno = vp->m_start.lno;
len = sp->cno = vp->m_start.cno;
}
if (db_eget(sp, vp->m_start.lno, &p, &len, &isempty)) {
if (!isempty)
return (1);
len = 0;
}
if (vp->m_start.cno >= len)
LF_SET(TXT_APPENDEOL);
rval = v_txt(sp, vp, NULL, p, len,
0, OOBLNO, F_ISSET(vp, VC_C1SET) ? vp->count : 1, flags);
if (bp != NULL)
FREE_SPACE(sp, bp, blen);
return (rval);
}
int
v_Replace(SCR *sp, VICMD *vp)
{
size_t len;
u_int32_t flags;
int isempty;
char *p;
flags = set_txt_std(sp, vp, 0);
sp->showmode = SM_REPLACE;
if (db_eget(sp, vp->m_start.lno, &p, &len, &isempty)) {
if (!isempty)
return (1);
len = 0;
LF_SET(TXT_APPENDEOL);
} else {
if (len == 0)
LF_SET(TXT_APPENDEOL);
LF_SET(TXT_OVERWRITE | TXT_REPLACE);
}
vp->m_stop.lno = vp->m_start.lno;
vp->m_stop.cno = len ? len - 1 : 0;
return (v_txt(sp, vp, &vp->m_stop, p, len,
0, OOBLNO, F_ISSET(vp, VC_C1SET) ? vp->count : 1, flags));
}
int
v_subst(SCR *sp, VICMD *vp)
{
size_t len;
u_int32_t flags;
int isempty;
char *p;
flags = set_txt_std(sp, vp, 0);
sp->showmode = SM_CHANGE;
if (db_eget(sp, vp->m_start.lno, &p, &len, &isempty)) {
if (!isempty)
return (1);
len = 0;
LF_SET(TXT_APPENDEOL);
} else {
if (len == 0)
LF_SET(TXT_APPENDEOL);
LF_SET(TXT_EMARK | TXT_OVERWRITE);
}
vp->m_stop.lno = vp->m_start.lno;
vp->m_stop.cno =
vp->m_start.cno + (F_ISSET(vp, VC_C1SET) ? vp->count - 1 : 0);
if (vp->m_stop.cno > len - 1)
vp->m_stop.cno = len - 1;
if (p != NULL && cut(sp,
F_ISSET(vp, VC_BUFFER) ? &vp->buffer : NULL,
&vp->m_start, &vp->m_stop, 0))
return (1);
return (v_txt(sp, vp, &vp->m_stop, p, len, 0, OOBLNO, 1, flags));
}
static u_int32_t
set_txt_std(SCR *sp, VICMD *vp, u_int32_t flags)
{
LF_SET(TXT_CNTRLT |
TXT_ESCAPE | TXT_MAPINPUT | TXT_RECORD | TXT_RESOLVE);
if (F_ISSET(vp, VC_ISDOT))
LF_SET(TXT_REPLAY);
if (O_ISSET(sp, O_ALTWERASE))
LF_SET(TXT_ALTWERASE);
if (O_ISSET(sp, O_AUTOINDENT))
LF_SET(TXT_AUTOINDENT);
if (O_ISSET(sp, O_BEAUTIFY))
LF_SET(TXT_BEAUTIFY);
if (O_ISSET(sp, O_SHOWMATCH))
LF_SET(TXT_SHOWMATCH);
if (F_ISSET(sp, SC_SCRIPT))
LF_SET(TXT_CR);
if (O_ISSET(sp, O_TTYWERASE))
LF_SET(TXT_TTYWERASE);
if ((O_ISSET(sp, O_WRAPLEN) || O_ISSET(sp, O_WRAPMARGIN)) &&
(!MAPPED_KEYS_WAITING(sp) || !F_ISSET(vp, VC_C1SET)))
LF_SET(TXT_WRAPMARGIN);
return (flags);
}