3e1db26a5a
Removing elvis, importing nvi, ctags, updating libedit. Change-Id: I881eb04d2dc64cf112facd992de1114e1a59107f
1594 lines
30 KiB
Text
1594 lines
30 KiB
Text
/*-
|
|
* Copyright (c) 1992, 1993, 1994
|
|
* The Regents of the University of California. All rights reserved.
|
|
* Copyright (c) 1992, 1993, 1994, 1995, 1996
|
|
* Keith Bostic. All rights reserved.
|
|
* Copyright (c) 1995
|
|
* George V. Neville-Neil. All rights reserved.
|
|
* Copyright (c) 1996-2001
|
|
* Sven Verdoolaege. All rights reserved.
|
|
*
|
|
* See the LICENSE file for redistribution information.
|
|
*/
|
|
|
|
#undef VI
|
|
|
|
#ifndef lint
|
|
static const char sccsid[] = "Id: perl.xs,v 8.46 2001/08/28 11:33:42 skimo Exp (Berkeley) Date: 2001/08/28 11:33:42";
|
|
#endif /* not lint */
|
|
|
|
#include <sys/types.h>
|
|
#include <sys/queue.h>
|
|
#include <sys/time.h>
|
|
|
|
#include <bitstring.h>
|
|
#include <ctype.h>
|
|
#include <limits.h>
|
|
#include <signal.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <termios.h>
|
|
#include <unistd.h>
|
|
|
|
#include <EXTERN.h>
|
|
#include <perl.h>
|
|
#include <XSUB.h>
|
|
|
|
/* perl redefines them
|
|
* avoid warnings
|
|
*/
|
|
#undef USE_DYNAMIC_LOADING
|
|
#undef DEBUG
|
|
#undef PACKAGE
|
|
#undef ARGS
|
|
#define ARGS ARGS
|
|
|
|
#include "config.h"
|
|
|
|
#include "../common/common.h"
|
|
#include "../perl_api/extern.h"
|
|
|
|
#ifndef DEFSV
|
|
#define DEFSV GvSV(defgv)
|
|
#endif
|
|
#ifndef ERRSV
|
|
#define ERRSV GvSV(errgv)
|
|
#endif
|
|
#ifndef dTHX
|
|
#define dTHXs
|
|
#else
|
|
#define dTHXs dTHX;
|
|
#endif
|
|
|
|
static void msghandler __P((SCR *, mtype_t, char *, size_t));
|
|
|
|
typedef struct _perl_data {
|
|
PerlInterpreter* interp;
|
|
SV *svcurscr, *svstart, *svstop, *svid;
|
|
CONVWIN cw;
|
|
char *errmsg;
|
|
} perl_data_t;
|
|
|
|
#define PERLP(sp) ((perl_data_t *)sp->wp->perl_private)
|
|
|
|
#define CHAR2INTP(sp,n,nlen,w,wlen) \
|
|
CHAR2INT5(sp,((perl_data_t *)sp->wp->perl_private)->cw,n,nlen,w,wlen)
|
|
|
|
/*
|
|
* INITMESSAGE --
|
|
* Macros to point messages at the Perl message handler.
|
|
*/
|
|
#define INITMESSAGE(sp) \
|
|
scr_msg = sp->wp->scr_msg; \
|
|
sp->wp->scr_msg = msghandler;
|
|
#define ENDMESSAGE(sp) \
|
|
sp->wp->scr_msg = scr_msg; \
|
|
if (rval) croak(PERLP(sp)->errmsg);
|
|
|
|
void xs_init __P((pTHXo));
|
|
|
|
/*
|
|
* perl_end --
|
|
* Clean up perl interpreter
|
|
*
|
|
* PUBLIC: int perl_end __P((GS *));
|
|
*/
|
|
int
|
|
perl_end(gp)
|
|
GS *gp;
|
|
{
|
|
/*
|
|
* Call perl_run and perl_destuct to call END blocks and DESTROY
|
|
* methods.
|
|
*/
|
|
if (gp->perl_interp) {
|
|
perl_run(gp->perl_interp);
|
|
perl_destruct(gp->perl_interp);
|
|
#if defined(DEBUG) || defined(PURIFY) || defined(LIBRARY)
|
|
perl_free(gp->perl_interp);
|
|
#endif
|
|
/* XXX rather make sure only one thread calls perl_end */
|
|
gp->perl_interp = 0;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* perl_eval
|
|
* Evaluate a string
|
|
* We don't use mortal SVs because no one will clean up after us
|
|
*/
|
|
static void
|
|
perl_eval(string)
|
|
char *string;
|
|
{
|
|
dTHXs
|
|
|
|
SV* sv = newSVpv(string, 0);
|
|
|
|
/* G_KEEPERR to catch syntax error; better way ? */
|
|
sv_setpv(ERRSV,"");
|
|
perl_eval_sv(sv, G_DISCARD | G_NOARGS | G_KEEPERR);
|
|
SvREFCNT_dec(sv);
|
|
}
|
|
|
|
/*
|
|
* perl_init --
|
|
* Create the perl commands used by nvi.
|
|
*
|
|
* PUBLIC: int perl_init __P((SCR *));
|
|
*/
|
|
int
|
|
perl_init(scrp)
|
|
SCR *scrp;
|
|
{
|
|
AV * av;
|
|
GS *gp;
|
|
WIN *wp;
|
|
char *bootargs[] = { "VI", NULL };
|
|
#ifndef USE_SFIO
|
|
SV *svcurscr;
|
|
#endif
|
|
perl_data_t *pp;
|
|
|
|
static char *args[] = { "", "-e", "" };
|
|
size_t length;
|
|
char *file = __FILE__;
|
|
|
|
gp = scrp->gp;
|
|
wp = scrp->wp;
|
|
|
|
if (gp->perl_interp == NULL) {
|
|
gp->perl_interp = perl_alloc();
|
|
perl_construct(gp->perl_interp);
|
|
if (perl_parse(gp->perl_interp, xs_init, 3, args, 0)) {
|
|
perl_destruct(gp->perl_interp);
|
|
perl_free(gp->perl_interp);
|
|
gp->perl_interp = NULL;
|
|
return 1;
|
|
}
|
|
{
|
|
dTHXs
|
|
|
|
perl_call_argv("VI::bootstrap", G_DISCARD, bootargs);
|
|
perl_eval("$SIG{__WARN__}='VI::Warn'");
|
|
|
|
av_unshift(av = GvAVn(PL_incgv), 1);
|
|
av_store(av, 0, newSVpv(_PATH_PERLSCRIPTS,
|
|
sizeof(_PATH_PERLSCRIPTS)-1));
|
|
|
|
#ifdef USE_SFIO
|
|
sfdisc(PerlIO_stdout(), sfdcnewnvi(scrp));
|
|
sfdisc(PerlIO_stderr(), sfdcnewnvi(scrp));
|
|
#else
|
|
svcurscr = perl_get_sv("curscr", TRUE);
|
|
sv_magic((SV *)gv_fetchpv("STDOUT",TRUE, SVt_PVIO), svcurscr,
|
|
'q', Nullch, 0);
|
|
sv_magic((SV *)gv_fetchpv("STDERR",TRUE, SVt_PVIO), svcurscr,
|
|
'q', Nullch, 0);
|
|
#endif /* USE_SFIO */
|
|
}
|
|
}
|
|
MALLOC(scrp, pp, perl_data_t *, sizeof(perl_data_t));
|
|
wp->perl_private = pp;
|
|
memset(&pp->cw, 0, sizeof(pp->cw));
|
|
#ifdef USE_ITHREADS
|
|
pp->interp = perl_clone(gp->perl_interp, 0);
|
|
if (1) { /* hack for bug fixed in perl-current (5.6.1) */
|
|
dTHXa(pp->interp);
|
|
if (PL_scopestack_ix == 0) {
|
|
ENTER;
|
|
}
|
|
}
|
|
#else
|
|
pp->interp = gp->perl_interp;
|
|
#endif
|
|
pp->errmsg = 0;
|
|
{
|
|
dTHXs
|
|
|
|
SvREADONLY_on(pp->svcurscr = perl_get_sv("curscr", TRUE));
|
|
SvREADONLY_on(pp->svstart = perl_get_sv("VI::StartLine", TRUE));
|
|
SvREADONLY_on(pp->svstop = perl_get_sv("VI::StopLine", TRUE));
|
|
SvREADONLY_on(pp->svid = perl_get_sv("VI::ScreenId", TRUE));
|
|
}
|
|
return (0);
|
|
}
|
|
|
|
/*
|
|
* perl_screen_end
|
|
* Remove all refences to the screen to be destroyed
|
|
*
|
|
* PUBLIC: int perl_screen_end __P((SCR*));
|
|
*/
|
|
int
|
|
perl_screen_end(scrp)
|
|
SCR *scrp;
|
|
{
|
|
dTHXs
|
|
|
|
if (scrp->perl_private) {
|
|
sv_setiv((SV*) scrp->perl_private, 0);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static void
|
|
my_sighandler(i)
|
|
int i;
|
|
{
|
|
croak("Perl command interrupted by SIGINT");
|
|
}
|
|
|
|
/* Create a new reference to an SV pointing to the SCR structure
|
|
* The perl_private part of the SCR structure points to the SV,
|
|
* so there can only be one such SV for a particular SCR structure.
|
|
* When the last reference has gone (DESTROY is called),
|
|
* perl_private is reset; When the screen goes away before
|
|
* all references are gone, the value of the SV is reset;
|
|
* any subsequent use of any of those reference will produce
|
|
* a warning. (see typemap)
|
|
*/
|
|
static SV *
|
|
newVIrv(rv, screen)
|
|
SV *rv;
|
|
SCR *screen;
|
|
{
|
|
dTHXs
|
|
|
|
if (!screen) return sv_setsv(rv, &PL_sv_undef), rv;
|
|
sv_upgrade(rv, SVt_RV);
|
|
if (!screen->perl_private) {
|
|
screen->perl_private = newSV(0);
|
|
sv_setiv(screen->perl_private, (IV) screen);
|
|
}
|
|
else SvREFCNT_inc(screen->perl_private);
|
|
SvRV(rv) = screen->perl_private;
|
|
SvROK_on(rv);
|
|
return sv_bless(rv, gv_stashpv("VI", TRUE));
|
|
}
|
|
|
|
/*
|
|
* perl_setenv
|
|
* Use perl's setenv if perl interpreter has been started.
|
|
* Perl uses its own setenv and gets confused if we change
|
|
* the environment after it has started.
|
|
*
|
|
* PUBLIC: int perl_setenv __P((SCR* sp, const char *name, const char *value));
|
|
*/
|
|
int
|
|
perl_setenv(SCR* scrp, const char *name, const char *value)
|
|
{
|
|
if (scrp->wp->perl_private == NULL) {
|
|
if (value == NULL)
|
|
unsetenv(name);
|
|
else
|
|
setenv(name, value, 1);
|
|
} else
|
|
my_setenv(name, value);
|
|
}
|
|
|
|
|
|
/*
|
|
* perl_ex_perl -- :[line [,line]] perl [command]
|
|
* Run a command through the perl interpreter.
|
|
*
|
|
* PUBLIC: int perl_ex_perl __P((SCR*, CHAR_T *, size_t, db_recno_t, db_recno_t));
|
|
*/
|
|
int
|
|
perl_ex_perl(scrp, cmdp, cmdlen, f_lno, t_lno)
|
|
SCR *scrp;
|
|
CHAR_T *cmdp;
|
|
size_t cmdlen;
|
|
db_recno_t f_lno, t_lno;
|
|
{
|
|
WIN *wp;
|
|
size_t length;
|
|
size_t len;
|
|
char *err;
|
|
char *np;
|
|
size_t nlen;
|
|
Signal_t (*istat)();
|
|
perl_data_t *pp;
|
|
|
|
/* Initialize the interpreter. */
|
|
if (scrp->wp->perl_private == NULL && perl_init(scrp))
|
|
return (1);
|
|
pp = scrp->wp->perl_private;
|
|
{
|
|
dTHXs
|
|
dSP;
|
|
|
|
sv_setiv(pp->svstart, f_lno);
|
|
sv_setiv(pp->svstop, t_lno);
|
|
newVIrv(pp->svcurscr, scrp);
|
|
/* Backwards compatibility. */
|
|
newVIrv(pp->svid, scrp);
|
|
|
|
istat = signal(SIGINT, my_sighandler);
|
|
INT2CHAR(scrp, cmdp, STRLEN(cmdp)+1, np, nlen);
|
|
perl_eval(np);
|
|
signal(SIGINT, istat);
|
|
|
|
SvREFCNT_dec(SvRV(pp->svcurscr));
|
|
SvROK_off(pp->svcurscr);
|
|
SvREFCNT_dec(SvRV(pp->svid));
|
|
SvROK_off(pp->svid);
|
|
|
|
err = SvPV(ERRSV, length);
|
|
if (!length)
|
|
return (0);
|
|
|
|
err[length - 1] = '\0';
|
|
msgq(scrp, M_ERR, "perl: %s", err);
|
|
return (1);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* replace_line
|
|
* replace a line with the contents of the perl variable $_
|
|
* lines are split at '\n's
|
|
* if $_ is undef, the line is deleted
|
|
* returns possibly adjusted linenumber
|
|
*/
|
|
static int
|
|
replace_line(scrp, line, t_lno, defsv)
|
|
SCR *scrp;
|
|
db_recno_t line, *t_lno;
|
|
SV *defsv;
|
|
{
|
|
char *str, *next;
|
|
CHAR_T *wp;
|
|
size_t len, wlen;
|
|
dTHXs
|
|
|
|
if (SvOK(defsv)) {
|
|
str = SvPV(defsv,len);
|
|
next = memchr(str, '\n', len);
|
|
CHAR2INTP(scrp, str, next ? (next - str) : len, wp, wlen);
|
|
api_sline(scrp, line, wp, wlen);
|
|
while (next++) {
|
|
len -= next - str;
|
|
next = memchr(str = next, '\n', len);
|
|
CHAR2INTP(scrp, str, next ? (next - str) : len,
|
|
wp, wlen);
|
|
api_iline(scrp, ++line, wp, wlen);
|
|
(*t_lno)++;
|
|
}
|
|
} else {
|
|
api_dline(scrp, line--);
|
|
(*t_lno)--;
|
|
}
|
|
return line;
|
|
}
|
|
|
|
/*
|
|
* perl_ex_perldo -- :[line [,line]] perl [command]
|
|
* Run a set of lines through the perl interpreter.
|
|
*
|
|
* PUBLIC: int perl_ex_perldo __P((SCR*, CHAR_T *, size_t, db_recno_t, db_recno_t));
|
|
*/
|
|
int
|
|
perl_ex_perldo(scrp, cmdp, cmdlen, f_lno, t_lno)
|
|
SCR *scrp;
|
|
CHAR_T *cmdp;
|
|
size_t cmdlen;
|
|
db_recno_t f_lno, t_lno;
|
|
{
|
|
CHAR_T *p;
|
|
WIN *wp;
|
|
size_t length;
|
|
size_t len;
|
|
db_recno_t i;
|
|
CHAR_T *str;
|
|
char *estr;
|
|
SV* cv;
|
|
char *command;
|
|
perl_data_t *pp;
|
|
char *np;
|
|
size_t nlen;
|
|
|
|
/* Initialize the interpreter. */
|
|
if (scrp->wp->perl_private == NULL && perl_init(scrp))
|
|
return (1);
|
|
pp = scrp->wp->perl_private;
|
|
{
|
|
dTHXs
|
|
dSP;
|
|
|
|
newVIrv(pp->svcurscr, scrp);
|
|
/* Backwards compatibility. */
|
|
newVIrv(pp->svid, scrp);
|
|
|
|
INT2CHAR(scrp, cmdp, STRLEN(cmdp)+1, np, nlen);
|
|
if (!(command = malloc(length = nlen - 1 + sizeof("sub {}"))))
|
|
return 1;
|
|
snprintf(command, length, "sub {%s}", np);
|
|
|
|
ENTER;
|
|
SAVETMPS;
|
|
|
|
cv = perl_eval_pv(command, FALSE);
|
|
free (command);
|
|
|
|
estr = SvPV(ERRSV,length);
|
|
if (length)
|
|
goto err;
|
|
|
|
for (i = f_lno; i <= t_lno && !api_gline(scrp, i, &str, &len); i++) {
|
|
INT2CHAR(scrp, str, len, np, nlen);
|
|
sv_setpvn(DEFSV,np,nlen);
|
|
sv_setiv(pp->svstart, i);
|
|
sv_setiv(pp->svstop, i);
|
|
PUSHMARK(sp);
|
|
perl_call_sv(cv, G_SCALAR | G_EVAL);
|
|
estr = SvPV(ERRSV, length);
|
|
if (length) break;
|
|
SPAGAIN;
|
|
if(SvTRUEx(POPs))
|
|
i = replace_line(scrp, i, &t_lno, DEFSV);
|
|
PUTBACK;
|
|
}
|
|
FREETMPS;
|
|
LEAVE;
|
|
|
|
SvREFCNT_dec(SvRV(pp->svcurscr));
|
|
SvROK_off(pp->svcurscr);
|
|
SvREFCNT_dec(SvRV(pp->svid));
|
|
SvROK_off(pp->svid);
|
|
|
|
if (!length)
|
|
return (0);
|
|
|
|
err: estr[length - 1] = '\0';
|
|
msgq(scrp, M_ERR, "perl: %s", estr);
|
|
return (1);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* msghandler --
|
|
* Perl message routine so that error messages are processed in
|
|
* Perl, not in nvi.
|
|
*/
|
|
static void
|
|
msghandler(sp, mtype, msg, len)
|
|
SCR *sp;
|
|
mtype_t mtype;
|
|
char *msg;
|
|
size_t len;
|
|
{
|
|
char *errmsg;
|
|
|
|
errmsg = PERLP(sp)->errmsg;
|
|
|
|
/* Replace the trailing <newline> with an EOS. */
|
|
/* Let's do that later instead */
|
|
if (errmsg) free (errmsg);
|
|
errmsg = malloc(len + 1);
|
|
memcpy(errmsg, msg, len);
|
|
errmsg[len] = '\0';
|
|
PERLP(sp)->errmsg = errmsg;
|
|
}
|
|
|
|
|
|
typedef SCR * VI;
|
|
typedef SCR * VI__OPT;
|
|
typedef SCR * VI__MAP;
|
|
typedef SCR * VI__MARK;
|
|
typedef SCR * VI__LINE;
|
|
typedef AV * AVREF;
|
|
|
|
typedef struct {
|
|
SV *sprv;
|
|
TAGQ *tqp;
|
|
} perl_tagq;
|
|
|
|
typedef perl_tagq * VI__TAGQ;
|
|
typedef perl_tagq * VI__TAGQ2;
|
|
|
|
MODULE = VI PACKAGE = VI
|
|
|
|
# msg --
|
|
# Set the message line to text.
|
|
#
|
|
# Perl Command: VI::Msg
|
|
# Usage: VI::Msg screenId text
|
|
|
|
void
|
|
Msg(screen, text)
|
|
VI screen
|
|
char * text
|
|
|
|
ALIAS:
|
|
PRINT = 1
|
|
|
|
CODE:
|
|
api_imessage(screen, text);
|
|
|
|
# XS_VI_escreen --
|
|
# End a screen.
|
|
#
|
|
# Perl Command: VI::EndScreen
|
|
# Usage: VI::EndScreen screenId
|
|
|
|
void
|
|
EndScreen(screen)
|
|
VI screen
|
|
|
|
PREINIT:
|
|
void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
|
|
int rval;
|
|
|
|
CODE:
|
|
INITMESSAGE(screen);
|
|
rval = api_escreen(screen);
|
|
ENDMESSAGE(screen);
|
|
|
|
# XS_VI_iscreen --
|
|
# Create a new screen. If a filename is specified then the screen
|
|
# is opened with that file.
|
|
#
|
|
# Perl Command: VI::NewScreen
|
|
# Usage: VI::NewScreen screenId [file]
|
|
|
|
VI
|
|
Edit(screen, ...)
|
|
VI screen
|
|
|
|
ALIAS:
|
|
NewScreen = 1
|
|
|
|
PROTOTYPE: $;$
|
|
PREINIT:
|
|
void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
|
|
int rval;
|
|
char *file;
|
|
SCR *nsp;
|
|
|
|
CODE:
|
|
file = (items == 1) ? NULL : (char *)SvPV(ST(1),PL_na);
|
|
INITMESSAGE(screen);
|
|
rval = api_edit(screen, file, &nsp, ix);
|
|
ENDMESSAGE(screen);
|
|
|
|
RETVAL = ix ? nsp : screen;
|
|
|
|
OUTPUT:
|
|
RETVAL
|
|
|
|
# XS_VI_fscreen --
|
|
# Return the screen id associated with file name.
|
|
#
|
|
# Perl Command: VI::FindScreen
|
|
# Usage: VI::FindScreen file
|
|
|
|
VI
|
|
FindScreen(file)
|
|
char *file
|
|
|
|
PREINIT:
|
|
SCR *fsp;
|
|
CODE:
|
|
RETVAL = api_fscreen(0, file);
|
|
|
|
OUTPUT:
|
|
RETVAL
|
|
|
|
# XS_VI_GetFileName --
|
|
# Return the file name of the screen
|
|
#
|
|
# Perl Command: VI::GetFileName
|
|
# Usage: VI::GetFileName screenId
|
|
|
|
char *
|
|
GetFileName(screen)
|
|
VI screen;
|
|
|
|
PPCODE:
|
|
EXTEND(sp,1);
|
|
PUSHs(sv_2mortal(newSVpv(screen->frp->name, 0)));
|
|
|
|
# XS_VI_aline --
|
|
# -- Append the string text after the line in lineNumber.
|
|
#
|
|
# Perl Command: VI::AppendLine
|
|
# Usage: VI::AppendLine screenId lineNumber text
|
|
|
|
void
|
|
AppendLine(screen, linenumber, text)
|
|
VI screen
|
|
int linenumber
|
|
char *text
|
|
|
|
PREINIT:
|
|
void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
|
|
int rval;
|
|
size_t length;
|
|
|
|
CODE:
|
|
SvPV(ST(2), length);
|
|
INITMESSAGE(screen);
|
|
rval = api_aline(screen, linenumber, text, length);
|
|
ENDMESSAGE(screen);
|
|
|
|
# XS_VI_dline --
|
|
# Delete lineNum.
|
|
#
|
|
# Perl Command: VI::DelLine
|
|
# Usage: VI::DelLine screenId lineNum
|
|
|
|
void
|
|
DelLine(screen, linenumber)
|
|
VI screen
|
|
int linenumber
|
|
|
|
PREINIT:
|
|
void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
|
|
int rval;
|
|
|
|
CODE:
|
|
INITMESSAGE(screen);
|
|
rval = api_dline(screen, (db_recno_t)linenumber);
|
|
ENDMESSAGE(screen);
|
|
|
|
# XS_VI_gline --
|
|
# Return lineNumber.
|
|
#
|
|
# Perl Command: VI::GetLine
|
|
# Usage: VI::GetLine screenId lineNumber
|
|
|
|
char *
|
|
GetLine(screen, linenumber)
|
|
VI screen
|
|
int linenumber
|
|
|
|
PREINIT:
|
|
size_t len;
|
|
void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
|
|
int rval;
|
|
char *line;
|
|
CHAR_T *p;
|
|
|
|
PPCODE:
|
|
INITMESSAGE(screen);
|
|
rval = api_gline(screen, (db_recno_t)linenumber, &p, &len);
|
|
ENDMESSAGE(screen);
|
|
|
|
EXTEND(sp,1);
|
|
PUSHs(sv_2mortal(newSVpv(len ? (char *)p : "", len)));
|
|
|
|
# XS_VI_sline --
|
|
# Set lineNumber to the text supplied.
|
|
#
|
|
# Perl Command: VI::SetLine
|
|
# Usage: VI::SetLine screenId lineNumber text
|
|
|
|
void
|
|
SetLine(screen, linenumber, text)
|
|
VI screen
|
|
int linenumber
|
|
char *text
|
|
|
|
PREINIT:
|
|
void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
|
|
int rval;
|
|
size_t length;
|
|
size_t len;
|
|
CHAR_T *line;
|
|
|
|
CODE:
|
|
SvPV(ST(2), length);
|
|
INITMESSAGE(screen);
|
|
CHAR2INTP(screen, text, length, line, len);
|
|
rval = api_sline(screen, linenumber, line, len);
|
|
ENDMESSAGE(screen);
|
|
|
|
# XS_VI_iline --
|
|
# Insert the string text before the line in lineNumber.
|
|
#
|
|
# Perl Command: VI::InsertLine
|
|
# Usage: VI::InsertLine screenId lineNumber text
|
|
|
|
void
|
|
InsertLine(screen, linenumber, text)
|
|
VI screen
|
|
int linenumber
|
|
char *text
|
|
|
|
PREINIT:
|
|
void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
|
|
int rval;
|
|
size_t length;
|
|
size_t len;
|
|
CHAR_T *line;
|
|
|
|
CODE:
|
|
SvPV(ST(2), length);
|
|
INITMESSAGE(screen);
|
|
CHAR2INTP(screen, text, length, line, len);
|
|
rval = api_iline(screen, linenumber, line, len);
|
|
ENDMESSAGE(screen);
|
|
|
|
# XS_VI_lline --
|
|
# Return the last line in the screen.
|
|
#
|
|
# Perl Command: VI::LastLine
|
|
# Usage: VI::LastLine screenId
|
|
|
|
int
|
|
LastLine(screen)
|
|
VI screen
|
|
|
|
PREINIT:
|
|
db_recno_t last;
|
|
void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
|
|
int rval;
|
|
|
|
CODE:
|
|
INITMESSAGE(screen);
|
|
rval = api_lline(screen, &last);
|
|
ENDMESSAGE(screen);
|
|
RETVAL=last;
|
|
|
|
OUTPUT:
|
|
RETVAL
|
|
|
|
# XS_VI_getmark --
|
|
# Return the mark's cursor position as a list with two elements.
|
|
# {line, column}.
|
|
#
|
|
# Perl Command: VI::GetMark
|
|
# Usage: VI::GetMark screenId mark
|
|
|
|
void
|
|
GetMark(screen, mark)
|
|
VI screen
|
|
char mark
|
|
|
|
PREINIT:
|
|
struct _mark cursor;
|
|
void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
|
|
int rval;
|
|
|
|
PPCODE:
|
|
INITMESSAGE(screen);
|
|
rval = api_getmark(screen, (int)mark, &cursor);
|
|
ENDMESSAGE(screen);
|
|
|
|
EXTEND(sp,2);
|
|
PUSHs(sv_2mortal(newSViv(cursor.lno)));
|
|
PUSHs(sv_2mortal(newSViv(cursor.cno)));
|
|
|
|
# XS_VI_setmark --
|
|
# Set the mark to the line and column numbers supplied.
|
|
#
|
|
# Perl Command: VI::SetMark
|
|
# Usage: VI::SetMark screenId mark line column
|
|
|
|
void
|
|
SetMark(screen, mark, line, column)
|
|
VI screen
|
|
char mark
|
|
int line
|
|
int column
|
|
|
|
PREINIT:
|
|
struct _mark cursor;
|
|
void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
|
|
int rval;
|
|
|
|
CODE:
|
|
INITMESSAGE(screen);
|
|
cursor.lno = line;
|
|
cursor.cno = column;
|
|
rval = api_setmark(screen, (int)mark, &cursor);
|
|
ENDMESSAGE(screen);
|
|
|
|
# XS_VI_getcursor --
|
|
# Return the current cursor position as a list with two elements.
|
|
# {line, column}.
|
|
#
|
|
# Perl Command: VI::GetCursor
|
|
# Usage: VI::GetCursor screenId
|
|
|
|
void
|
|
GetCursor(screen)
|
|
VI screen
|
|
|
|
PREINIT:
|
|
struct _mark cursor;
|
|
void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
|
|
int rval;
|
|
|
|
PPCODE:
|
|
INITMESSAGE(screen);
|
|
rval = api_getcursor(screen, &cursor);
|
|
ENDMESSAGE(screen);
|
|
|
|
EXTEND(sp,2);
|
|
PUSHs(sv_2mortal(newSViv(cursor.lno)));
|
|
PUSHs(sv_2mortal(newSViv(cursor.cno)));
|
|
|
|
# XS_VI_setcursor --
|
|
# Set the cursor to the line and column numbers supplied.
|
|
#
|
|
# Perl Command: VI::SetCursor
|
|
# Usage: VI::SetCursor screenId line column
|
|
|
|
void
|
|
SetCursor(screen, line, column)
|
|
VI screen
|
|
int line
|
|
int column
|
|
|
|
PREINIT:
|
|
struct _mark cursor;
|
|
void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
|
|
int rval;
|
|
|
|
CODE:
|
|
INITMESSAGE(screen);
|
|
cursor.lno = line;
|
|
cursor.cno = column;
|
|
rval = api_setcursor(screen, &cursor);
|
|
ENDMESSAGE(screen);
|
|
|
|
# XS_VI_swscreen --
|
|
# Change the current focus to screen.
|
|
#
|
|
# Perl Command: VI::SwitchScreen
|
|
# Usage: VI::SwitchScreen screenId screenId
|
|
|
|
void
|
|
SwitchScreen(screenFrom, screenTo)
|
|
VI screenFrom
|
|
VI screenTo
|
|
|
|
PREINIT:
|
|
void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
|
|
int rval;
|
|
|
|
CODE:
|
|
INITMESSAGE(screenFrom);
|
|
rval = api_swscreen(screenFrom, screenTo);
|
|
ENDMESSAGE(screenFrom);
|
|
|
|
# XS_VI_map --
|
|
# Associate a key with a perl procedure.
|
|
#
|
|
# Perl Command: VI::MapKey
|
|
# Usage: VI::MapKey screenId key perlproc
|
|
|
|
void
|
|
MapKey(screen, key, commandsv)
|
|
VI screen
|
|
char *key
|
|
SV *commandsv
|
|
|
|
PREINIT:
|
|
void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
|
|
int rval;
|
|
int length;
|
|
char *command;
|
|
|
|
CODE:
|
|
INITMESSAGE(screen);
|
|
command = SvPV(commandsv, length);
|
|
rval = api_map(screen, key, command, length);
|
|
ENDMESSAGE(screen);
|
|
|
|
# XS_VI_unmap --
|
|
# Unmap a key.
|
|
#
|
|
# Perl Command: VI::UnmapKey
|
|
# Usage: VI::UnmmapKey screenId key
|
|
|
|
void
|
|
UnmapKey(screen, key)
|
|
VI screen
|
|
char *key
|
|
|
|
PREINIT:
|
|
void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
|
|
int rval;
|
|
|
|
CODE:
|
|
INITMESSAGE(screen);
|
|
rval = api_unmap(screen, key);
|
|
ENDMESSAGE(screen);
|
|
|
|
# XS_VI_opts_set --
|
|
# Set an option.
|
|
#
|
|
# Perl Command: VI::SetOpt
|
|
# Usage: VI::SetOpt screenId setting
|
|
|
|
void
|
|
SetOpt(screen, setting)
|
|
VI screen
|
|
char *setting
|
|
|
|
PREINIT:
|
|
void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
|
|
int rval;
|
|
SV *svc;
|
|
|
|
CODE:
|
|
INITMESSAGE(screen);
|
|
svc = sv_2mortal(newSVpv(":set ", 5));
|
|
sv_catpv(svc, setting);
|
|
rval = api_run_str(screen, SvPV(svc, PL_na));
|
|
ENDMESSAGE(screen);
|
|
|
|
# XS_VI_opts_get --
|
|
# Return the value of an option.
|
|
#
|
|
# Perl Command: VI::GetOpt
|
|
# Usage: VI::GetOpt screenId option
|
|
|
|
void
|
|
GetOpt(screen, option)
|
|
VI screen
|
|
char *option
|
|
|
|
PREINIT:
|
|
void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
|
|
int rval;
|
|
char *value;
|
|
CHAR_T *wp;
|
|
size_t wlen;
|
|
|
|
PPCODE:
|
|
INITMESSAGE(screen);
|
|
CHAR2INTP(screen, option, strlen(option)+1, wp, wlen);
|
|
rval = api_opts_get(screen, wp, &value, NULL);
|
|
ENDMESSAGE(screen);
|
|
|
|
EXTEND(SP,1);
|
|
PUSHs(sv_2mortal(newSVpv(value, 0)));
|
|
free(value);
|
|
|
|
# XS_VI_run --
|
|
# Run the ex command cmd.
|
|
#
|
|
# Perl Command: VI::Run
|
|
# Usage: VI::Run screenId cmd
|
|
|
|
void
|
|
Run(screen, command)
|
|
VI screen
|
|
char *command;
|
|
|
|
PREINIT:
|
|
void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
|
|
int rval;
|
|
|
|
CODE:
|
|
INITMESSAGE(screen);
|
|
rval = api_run_str(screen, command);
|
|
ENDMESSAGE(screen);
|
|
|
|
void
|
|
DESTROY(screensv)
|
|
SV* screensv
|
|
|
|
PREINIT:
|
|
VI screen;
|
|
|
|
CODE:
|
|
if (sv_isa(screensv, "VI")) {
|
|
IV tmp = SvIV((SV*)SvRV(screensv));
|
|
screen = (SCR *) tmp;
|
|
}
|
|
else
|
|
croak("screen is not of type VI");
|
|
|
|
if (screen)
|
|
screen->perl_private = 0;
|
|
|
|
void
|
|
Warn(warning)
|
|
char *warning;
|
|
|
|
CODE:
|
|
sv_catpv(ERRSV,warning);
|
|
|
|
#define TIED(kind,package) \
|
|
sv_magic((SV *) (var = \
|
|
(kind##V *)sv_2mortal((SV *)new##kind##V())), \
|
|
sv_setref_pv(sv_newmortal(), package, \
|
|
newVIrv(newSV(0), screen)),\
|
|
'P', Nullch, 0);\
|
|
RETVAL = newRV((SV *)var)
|
|
|
|
SV *
|
|
Opt(screen)
|
|
VI screen;
|
|
PREINIT:
|
|
HV *var;
|
|
CODE:
|
|
TIED(H,"VI::OPT");
|
|
OUTPUT:
|
|
RETVAL
|
|
|
|
SV *
|
|
Map(screen)
|
|
VI screen;
|
|
PREINIT:
|
|
HV *var;
|
|
CODE:
|
|
TIED(H,"VI::MAP");
|
|
OUTPUT:
|
|
RETVAL
|
|
|
|
SV *
|
|
Mark(screen)
|
|
VI screen
|
|
PREINIT:
|
|
HV *var;
|
|
CODE:
|
|
TIED(H,"VI::MARK");
|
|
OUTPUT:
|
|
RETVAL
|
|
|
|
SV *
|
|
Line(screen)
|
|
VI screen
|
|
PREINIT:
|
|
AV *var;
|
|
CODE:
|
|
TIED(A,"VI::LINE");
|
|
OUTPUT:
|
|
RETVAL
|
|
|
|
SV *
|
|
TagQ(screen, tag)
|
|
VI screen
|
|
char *tag;
|
|
|
|
PREINIT:
|
|
perl_tagq *ptag;
|
|
|
|
PPCODE:
|
|
if ((ptag = malloc(sizeof(perl_tagq))) == NULL)
|
|
goto err;
|
|
|
|
ptag->sprv = newVIrv(newSV(0), screen);
|
|
ptag->tqp = api_tagq_new(screen, tag);
|
|
if (ptag->tqp != NULL) {
|
|
EXTEND(SP,1);
|
|
PUSHs(sv_2mortal(sv_setref_pv(newSV(0), "VI::TAGQ", ptag)));
|
|
} else {
|
|
err:
|
|
ST(0) = &PL_sv_undef;
|
|
return;
|
|
}
|
|
|
|
MODULE = VI PACKAGE = VI::OPT
|
|
|
|
void
|
|
DESTROY(screen)
|
|
VI::OPT screen
|
|
|
|
CODE:
|
|
# typemap did all the checking
|
|
SvREFCNT_dec((SV*)SvIV((SV*)SvRV(ST(0))));
|
|
|
|
void
|
|
FETCH(screen, key)
|
|
VI::OPT screen
|
|
char *key
|
|
|
|
PREINIT:
|
|
void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
|
|
int rval;
|
|
char *value;
|
|
int boolvalue;
|
|
CHAR_T *wp;
|
|
size_t wlen;
|
|
|
|
PPCODE:
|
|
INITMESSAGE(screen);
|
|
CHAR2INTP(screen, key, strlen(key)+1, wp, wlen);
|
|
rval = api_opts_get(screen, wp, &value, &boolvalue);
|
|
if (!rval) {
|
|
EXTEND(SP,1);
|
|
PUSHs(sv_2mortal((boolvalue == -1) ? newSVpv(value, 0)
|
|
: newSViv(boolvalue)));
|
|
free(value);
|
|
} else ST(0) = &PL_sv_undef;
|
|
rval = 0;
|
|
ENDMESSAGE(screen);
|
|
|
|
void
|
|
STORE(screen, key, value)
|
|
VI::OPT screen
|
|
char *key
|
|
SV *value
|
|
|
|
PREINIT:
|
|
void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
|
|
int rval;
|
|
CHAR_T *wp;
|
|
size_t wlen;
|
|
|
|
CODE:
|
|
INITMESSAGE(screen);
|
|
CHAR2INTP(screen, key, strlen(key)+1, wp, wlen);
|
|
rval = api_opts_set(screen, wp, SvPV(value, PL_na), SvIV(value),
|
|
SvTRUEx(value));
|
|
ENDMESSAGE(screen);
|
|
|
|
MODULE = VI PACKAGE = VI::MAP
|
|
|
|
void
|
|
DESTROY(screen)
|
|
VI::MAP screen
|
|
|
|
CODE:
|
|
# typemap did all the checking
|
|
SvREFCNT_dec((SV*)SvIV((SV*)SvRV(ST(0))));
|
|
|
|
void
|
|
STORE(screen, key, commandsv)
|
|
VI::MAP screen
|
|
char *key
|
|
SV *commandsv
|
|
|
|
PREINIT:
|
|
void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
|
|
int rval;
|
|
int length;
|
|
char *command;
|
|
|
|
CODE:
|
|
INITMESSAGE(screen);
|
|
command = SvPV(commandsv, length);
|
|
rval = api_map(screen, key, command, length);
|
|
ENDMESSAGE(screen);
|
|
|
|
void
|
|
DELETE(screen, key)
|
|
VI::MAP screen
|
|
char *key
|
|
|
|
PREINIT:
|
|
void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
|
|
int rval;
|
|
|
|
CODE:
|
|
INITMESSAGE(screen);
|
|
rval = api_unmap(screen, key);
|
|
ENDMESSAGE(screen);
|
|
|
|
MODULE = VI PACKAGE = VI::MARK
|
|
|
|
void
|
|
DESTROY(screen)
|
|
VI::MARK screen
|
|
|
|
CODE:
|
|
# typemap did all the checking
|
|
SvREFCNT_dec((SV*)SvIV((SV*)SvRV(ST(0))));
|
|
|
|
int
|
|
EXISTS(screen, mark)
|
|
VI::MARK screen
|
|
char mark
|
|
|
|
PREINIT:
|
|
struct _mark cursor;
|
|
void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
|
|
int rval = 0; /* never croak */
|
|
int missing;
|
|
|
|
CODE:
|
|
INITMESSAGE(screen);
|
|
missing = api_getmark(screen, (int)mark, &cursor);
|
|
ENDMESSAGE(screen);
|
|
RETVAL = !missing;
|
|
|
|
OUTPUT:
|
|
RETVAL
|
|
|
|
AV *
|
|
FETCH(screen, mark)
|
|
VI::MARK screen
|
|
char mark
|
|
|
|
PREINIT:
|
|
struct _mark cursor;
|
|
void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
|
|
int rval;
|
|
|
|
CODE:
|
|
INITMESSAGE(screen);
|
|
rval = api_getmark(screen, (int)mark, &cursor);
|
|
ENDMESSAGE(screen);
|
|
RETVAL = newAV();
|
|
av_push(RETVAL, newSViv(cursor.lno));
|
|
av_push(RETVAL, newSViv(cursor.cno));
|
|
|
|
OUTPUT:
|
|
RETVAL
|
|
|
|
void
|
|
STORE(screen, mark, pos)
|
|
VI::MARK screen
|
|
char mark
|
|
AVREF pos
|
|
|
|
PREINIT:
|
|
struct _mark cursor;
|
|
void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
|
|
int rval;
|
|
|
|
CODE:
|
|
if (av_len(pos) < 1)
|
|
croak("cursor position needs 2 elements");
|
|
INITMESSAGE(screen);
|
|
cursor.lno = SvIV(*av_fetch(pos, 0, 0));
|
|
cursor.cno = SvIV(*av_fetch(pos, 1, 0));
|
|
rval = api_setmark(screen, (int)mark, &cursor);
|
|
ENDMESSAGE(screen);
|
|
|
|
void
|
|
FIRSTKEY(screen, ...)
|
|
VI::MARK screen
|
|
|
|
ALIAS:
|
|
NEXTKEY = 1
|
|
|
|
PROTOTYPE: $;$
|
|
|
|
PREINIT:
|
|
int next;
|
|
char key[] = {0, 0};
|
|
|
|
PPCODE:
|
|
if (items == 2) {
|
|
next = 1;
|
|
*key = *(char *)SvPV(ST(1),PL_na);
|
|
} else next = 0;
|
|
if (api_nextmark(screen, next, key) != 1) {
|
|
EXTEND(sp, 1);
|
|
PUSHs(sv_2mortal(newSVpv(key, 1)));
|
|
} else ST(0) = &PL_sv_undef;
|
|
|
|
MODULE = VI PACKAGE = VI::LINE
|
|
|
|
void
|
|
DESTROY(screen)
|
|
VI::LINE screen
|
|
|
|
CODE:
|
|
# typemap did all the checking
|
|
SvREFCNT_dec((SV*)SvIV((SV*)SvRV(ST(0))));
|
|
|
|
# similar to SetLine
|
|
|
|
void
|
|
STORE(screen, linenumber, text)
|
|
VI::LINE screen
|
|
int linenumber
|
|
char *text
|
|
|
|
PREINIT:
|
|
void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
|
|
int rval;
|
|
size_t length;
|
|
db_recno_t last;
|
|
size_t len;
|
|
CHAR_T *line;
|
|
|
|
CODE:
|
|
++linenumber; /* vi 1 based ; perl 0 based */
|
|
SvPV(ST(2), length);
|
|
INITMESSAGE(screen);
|
|
rval = api_lline(screen, &last);
|
|
if (!rval) {
|
|
if (linenumber > last)
|
|
rval = api_extend(screen, linenumber);
|
|
if (!rval)
|
|
CHAR2INTP(screen, text, length, line, len);
|
|
rval = api_sline(screen, linenumber, line, len);
|
|
}
|
|
ENDMESSAGE(screen);
|
|
|
|
# similar to GetLine
|
|
|
|
char *
|
|
FETCH(screen, linenumber)
|
|
VI::LINE screen
|
|
int linenumber
|
|
|
|
PREINIT:
|
|
size_t len;
|
|
void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
|
|
int rval;
|
|
char *line;
|
|
CHAR_T *p;
|
|
|
|
PPCODE:
|
|
++linenumber; /* vi 1 based ; perl 0 based */
|
|
INITMESSAGE(screen);
|
|
rval = api_gline(screen, (db_recno_t)linenumber, &p, &len);
|
|
ENDMESSAGE(screen);
|
|
|
|
EXTEND(sp,1);
|
|
PUSHs(sv_2mortal(newSVpv(len ? (char*)p : "", len)));
|
|
|
|
# similar to LastLine
|
|
|
|
int
|
|
FETCHSIZE(screen)
|
|
VI::LINE screen
|
|
|
|
PREINIT:
|
|
db_recno_t last;
|
|
void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
|
|
int rval;
|
|
|
|
CODE:
|
|
INITMESSAGE(screen);
|
|
rval = api_lline(screen, &last);
|
|
ENDMESSAGE(screen);
|
|
RETVAL=last;
|
|
|
|
OUTPUT:
|
|
RETVAL
|
|
|
|
void
|
|
STORESIZE(screen, count)
|
|
VI::LINE screen
|
|
int count
|
|
|
|
PREINIT:
|
|
db_recno_t last;
|
|
void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
|
|
int rval;
|
|
|
|
CODE:
|
|
INITMESSAGE(screen);
|
|
rval = api_lline(screen, &last);
|
|
if (!rval) {
|
|
if (count > last)
|
|
rval = api_extend(screen, count);
|
|
else while(last && last > count) {
|
|
rval = api_dline(screen, last--);
|
|
if (rval) break;
|
|
}
|
|
}
|
|
ENDMESSAGE(screen);
|
|
|
|
void
|
|
EXTEND(screen, count)
|
|
VI::LINE screen
|
|
int count
|
|
|
|
CODE:
|
|
|
|
void
|
|
CLEAR(screen)
|
|
VI::LINE screen
|
|
|
|
PREINIT:
|
|
db_recno_t last;
|
|
void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
|
|
int rval;
|
|
|
|
CODE:
|
|
INITMESSAGE(screen);
|
|
rval = api_lline(screen, &last);
|
|
if (!rval) {
|
|
while(last) {
|
|
rval = api_dline(screen, last--);
|
|
if (rval) break;
|
|
}
|
|
}
|
|
ENDMESSAGE(screen);
|
|
|
|
void
|
|
PUSH(screen, ...)
|
|
VI::LINE screen;
|
|
|
|
PREINIT:
|
|
db_recno_t last;
|
|
void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
|
|
int rval, i, len;
|
|
char *line;
|
|
|
|
CODE:
|
|
INITMESSAGE(screen);
|
|
rval = api_lline(screen, &last);
|
|
|
|
if (!rval)
|
|
for (i = 1; i < items; ++i) {
|
|
line = SvPV(ST(i), len);
|
|
if ((rval = api_aline(screen, last++, line, len)))
|
|
break;
|
|
}
|
|
ENDMESSAGE(screen);
|
|
|
|
SV *
|
|
POP(screen)
|
|
VI::LINE screen;
|
|
|
|
PREINIT:
|
|
db_recno_t last;
|
|
void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
|
|
int rval, i, len;
|
|
CHAR_T *line;
|
|
|
|
PPCODE:
|
|
INITMESSAGE(screen);
|
|
rval = api_lline(screen, &last);
|
|
if (rval || last < 1)
|
|
ST(0) = &PL_sv_undef;
|
|
else {
|
|
rval = api_gline(screen, last, &line, &len) ||
|
|
api_dline(screen, last);
|
|
EXTEND(sp,1);
|
|
PUSHs(sv_2mortal(newSVpv(len ? (char *)line : "", len)));
|
|
}
|
|
ENDMESSAGE(screen);
|
|
|
|
SV *
|
|
SHIFT(screen)
|
|
VI::LINE screen;
|
|
|
|
PREINIT:
|
|
db_recno_t last;
|
|
void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
|
|
int rval, i, len;
|
|
CHAR_T *line;
|
|
|
|
PPCODE:
|
|
INITMESSAGE(screen);
|
|
rval = api_lline(screen, &last);
|
|
if (rval || last < 1)
|
|
ST(0) = &PL_sv_undef;
|
|
else {
|
|
rval = api_gline(screen, (db_recno_t)1, &line, &len) ||
|
|
api_dline(screen, (db_recno_t)1);
|
|
EXTEND(sp,1);
|
|
PUSHs(sv_2mortal(newSVpv(len ? (char *)line : "", len)));
|
|
}
|
|
ENDMESSAGE(screen);
|
|
|
|
void
|
|
UNSHIFT(screen, ...)
|
|
VI::LINE screen;
|
|
|
|
PREINIT:
|
|
void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
|
|
int rval, i, len;
|
|
char *np;
|
|
size_t nlen;
|
|
CHAR_T *line;
|
|
|
|
CODE:
|
|
INITMESSAGE(screen);
|
|
while (--items != 0) {
|
|
np = SvPV(ST(items), nlen);
|
|
CHAR2INTP(screen, np, nlen, line, len);
|
|
if ((rval = api_iline(screen, (db_recno_t)1, line, len)))
|
|
break;
|
|
}
|
|
ENDMESSAGE(screen);
|
|
|
|
void
|
|
SPLICE(screen, ...)
|
|
VI::LINE screen;
|
|
|
|
PREINIT:
|
|
db_recno_t last, db_offset;
|
|
void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
|
|
int rval, length, common, len, i, offset;
|
|
CHAR_T *line;
|
|
char *np;
|
|
size_t nlen;
|
|
|
|
PPCODE:
|
|
INITMESSAGE(screen);
|
|
rval = api_lline(screen, &last);
|
|
offset = items > 1 ? (int)SvIV(ST(1)) : 0;
|
|
if (offset < 0) offset += last;
|
|
if (offset < 0) {
|
|
ENDMESSAGE(screen);
|
|
croak("Invalid offset");
|
|
}
|
|
length = items > 2 ? (int)SvIV(ST(2)) : last - offset;
|
|
if (length > last - offset)
|
|
length = last - offset;
|
|
db_offset = offset + 1; /* 1 based */
|
|
EXTEND(sp,length);
|
|
for (common = MIN(length, items - 3), i = 3; common > 0;
|
|
--common, ++db_offset, --length, ++i) {
|
|
rval |= api_gline(screen, db_offset, &line, &len);
|
|
INT2CHAR(screen, line, len, np, nlen);
|
|
PUSHs(sv_2mortal(newSVpv(nlen ? np : "", nlen)));
|
|
np = SvPV(ST(i), nlen);
|
|
CHAR2INTP(screen, np, nlen, line, len);
|
|
rval |= api_sline(screen, db_offset, line, len);
|
|
}
|
|
for (; length; --length) {
|
|
rval |= api_gline(screen, db_offset, &line, &len);
|
|
INT2CHAR(screen, line, len, np, nlen);
|
|
PUSHs(sv_2mortal(newSVpv(len ? np : "", nlen)));
|
|
rval |= api_dline(screen, db_offset);
|
|
}
|
|
for (; i < items; ++i) {
|
|
np = SvPV(ST(i), len);
|
|
CHAR2INTP(screen, np, len, line, nlen);
|
|
rval |= api_iline(screen, db_offset, line, nlen);
|
|
}
|
|
ENDMESSAGE(screen);
|
|
|
|
MODULE = VI PACKAGE = VI::TAGQ
|
|
|
|
void
|
|
Add(tagq, filename, search, msg)
|
|
VI::TAGQ tagq;
|
|
char *filename;
|
|
char *search;
|
|
char *msg;
|
|
|
|
PREINIT:
|
|
SCR *sp;
|
|
|
|
CODE:
|
|
sp = (SCR *)SvIV((SV*)SvRV(tagq->sprv));
|
|
if (!sp)
|
|
croak("screen no longer exists");
|
|
api_tagq_add(sp, tagq->tqp, filename, search, msg);
|
|
|
|
void
|
|
Push(tagq)
|
|
VI::TAGQ tagq;
|
|
|
|
PREINIT:
|
|
SCR *sp;
|
|
|
|
CODE:
|
|
sp = (SCR *)SvIV((SV*)SvRV(tagq->sprv));
|
|
if (!sp)
|
|
croak("screen no longer exists");
|
|
api_tagq_push(sp, &tagq->tqp);
|
|
|
|
void
|
|
DESTROY(tagq)
|
|
# Can already be invalidated by push
|
|
VI::TAGQ2 tagq;
|
|
|
|
PREINIT:
|
|
SCR *sp;
|
|
|
|
CODE:
|
|
sp = (SCR *)SvIV((SV*)SvRV(tagq->sprv));
|
|
if (sp)
|
|
api_tagq_free(sp, tagq->tqp);
|
|
SvREFCNT_dec(tagq->sprv);
|
|
free(tagq);
|