119304Speter/*-
219304Speter * Copyright (c) 1992, 1993, 1994
319304Speter *	The Regents of the University of California.  All rights reserved.
419304Speter * Copyright (c) 1992, 1993, 1994, 1995, 1996
519304Speter *	Keith Bostic.  All rights reserved.
619304Speter * Copyright (c) 1995
719304Speter *	George V. Neville-Neil. All rights reserved.
819304Speter * Copyright (c) 1996
919304Speter *	Sven Verdoolaege. All rights reserved.
1019304Speter *
1119304Speter * See the LICENSE file for redistribution information.
1269474Ssheldonh *
1369474Ssheldonh * $FreeBSD$
1419304Speter */
1519304Speter
1619304Speter#include "config.h"
1719304Speter
1819304Speter#ifndef lint
1919304Speterstatic const char sccsid[] = "@(#)perl.xs	8.27 (Berkeley) 10/16/96";
2019304Speter#endif /* not lint */
2119304Speter
2219304Speter#include <sys/types.h>
2341839Speter#include <sys/param.h>
2419304Speter#include <sys/queue.h>
2519304Speter#include <sys/time.h>
2619304Speter
2719304Speter#include <bitstring.h>
2819304Speter#include <ctype.h>
2919304Speter#include <limits.h>
3019304Speter#include <signal.h>
3119304Speter#include <stdio.h>
3219304Speter#include <stdlib.h>
3319304Speter#include <string.h>
3419304Speter#include <termios.h>
3519304Speter#include <unistd.h>
3641839Speter#include <errno.h>
3719304Speter
3819304Speter#include "../common/common.h"
3919304Speter
4019304Speter#include <EXTERN.h>
4119304Speter#include <perl.h>
4219304Speter#include <XSUB.h>
4319304Speter
4419304Speter#include "perl_extern.h"
4519304Speter
4619304Speterstatic void msghandler __P((SCR *, mtype_t, char *, size_t));
4719304Speter
4819304Speterextern GS *__global_list;			/* XXX */
4919304Speter
5019304Speterstatic char *errmsg = 0;
5119304Speter
5219304Speter/*
5319304Speter * INITMESSAGE --
5419304Speter *	Macros to point messages at the Perl message handler.
5519304Speter */
5619304Speter#define	INITMESSAGE							\
5719304Speter	scr_msg = __global_list->scr_msg;				\
5819304Speter	__global_list->scr_msg = msghandler;
5919304Speter#define	ENDMESSAGE							\
6019304Speter	__global_list->scr_msg = scr_msg;				\
6119304Speter	if (rval) croak(errmsg);
6219304Speter
6319304Speterstatic void xs_init __P((void));
6419304Speter
6519304Speter/*
6619304Speter * perl_end --
6719304Speter *	Clean up perl interpreter
6819304Speter *
6919304Speter * PUBLIC: int perl_end __P((GS *));
7019304Speter */
7119304Speterint
7219304Speterperl_end(gp)
7319304Speter	GS *gp;
7419304Speter{
7519304Speter	/*
7619304Speter	 * Call perl_run and perl_destuct to call END blocks and DESTROY
7719304Speter	 * methods.
7819304Speter	 */
7919304Speter	if (gp->perl_interp) {
8019304Speter		/*Irestartop = 0;            			/ * XXX */
8119304Speter		perl_run(gp->perl_interp);
8219304Speter		perl_destruct(gp->perl_interp);
8319304Speter#if defined(DEBUG) || defined(PURIFY) || defined(LIBRARY)
8419304Speter		perl_free(gp->perl_interp);
8519304Speter#endif
8619304Speter	}
8719304Speter}
8819304Speter
8919304Speter/*
9019304Speter * perl_eval
9119304Speter *	Evaluate a string
9219304Speter * 	We don't use mortal SVs because no one will clean up after us
9319304Speter */
9419304Speterstatic void
9519304Speterperl_eval(string)
9619304Speter	char *string;
9719304Speter{
9819304Speter#ifdef HAVE_PERL_5_003_01
9919304Speter	SV* sv = newSVpv(string, 0);
10019304Speter
10119304Speter	perl_eval_sv(sv, G_DISCARD | G_NOARGS);
10219304Speter	SvREFCNT_dec(sv);
10319304Speter#else
10419304Speter	char *argv[2];
10519304Speter
10619304Speter	argv[0] = string;
10719304Speter	argv[1] = NULL;
10819304Speter	perl_call_argv("_eval_", G_EVAL | G_DISCARD | G_KEEPERR, argv);
10919304Speter#endif
11019304Speter}
11119304Speter
11219304Speter/*
11319304Speter * perl_init --
11419304Speter *	Create the perl commands used by nvi.
11519304Speter *
11619304Speter * PUBLIC: int perl_init __P((SCR *));
11719304Speter */
11819304Speterint
11919304Speterperl_init(scrp)
12019304Speter	SCR *scrp;
12119304Speter{
12219304Speter	AV * av;
12319304Speter	GS *gp;
12419304Speter	char *bootargs[] = { "VI", NULL };
12519304Speter#ifndef USE_SFIO
12619304Speter	SV *svcurscr;
12719304Speter#endif
12819304Speter
12919304Speter#ifndef HAVE_PERL_5_003_01
13019304Speter	static char *args[] = { "", "-e", "sub _eval_ { eval $_[0] }" };
13119304Speter#else
13219304Speter	static char *args[] = { "", "-e", "" };
13319304Speter#endif
13419304Speter	STRLEN length;
13519304Speter	char *file = __FILE__;
13619304Speter
13719304Speter	gp = scrp->gp;
13819304Speter	gp->perl_interp = perl_alloc();
13919304Speter  	perl_construct(gp->perl_interp);
14019304Speter	if (perl_parse(gp->perl_interp, xs_init, 3, args, 0)) {
14119304Speter		perl_destruct(gp->perl_interp);
14219304Speter		perl_free(gp->perl_interp);
14319304Speter		gp->perl_interp = NULL;
14419304Speter		return 1;
14519304Speter	}
14619304Speter        perl_call_argv("VI::bootstrap", G_DISCARD, bootargs);
14719304Speter	perl_eval("$SIG{__WARN__}='VI::Warn'");
14819304Speter
14941839Speter	av_unshift(av = GvAVn(PL_incgv), 1);
15019304Speter	av_store(av, 0, newSVpv(_PATH_PERLSCRIPTS,
15119304Speter				sizeof(_PATH_PERLSCRIPTS)-1));
15219304Speter
15319304Speter#ifdef USE_SFIO
15419304Speter	sfdisc(PerlIO_stdout(), sfdcnewnvi(scrp));
15519304Speter	sfdisc(PerlIO_stderr(), sfdcnewnvi(scrp));
15619304Speter#else
15719304Speter	svcurscr = perl_get_sv("curscr", TRUE);
15819304Speter	sv_magic((SV *)gv_fetchpv("STDOUT",TRUE, SVt_PVIO), svcurscr,
15919304Speter		 	'q', Nullch, 0);
16019304Speter	sv_magic((SV *)gv_fetchpv("STDERR",TRUE, SVt_PVIO), svcurscr,
16119304Speter		 	'q', Nullch, 0);
16219304Speter#endif /* USE_SFIO */
16319304Speter	return (0);
16419304Speter}
16519304Speter
16619304Speter/*
16719304Speter * perl_screen_end
16819304Speter *	Remove all refences to the screen to be destroyed
16919304Speter *
17019304Speter * PUBLIC: int perl_screen_end __P((SCR*));
17119304Speter */
17219304Speterint
17319304Speterperl_screen_end(scrp)
17419304Speter	SCR *scrp;
17519304Speter{
17619304Speter	if (scrp->perl_private) {
17719304Speter		sv_setiv((SV*) scrp->perl_private, 0);
17819304Speter	}
17919304Speter	return 0;
18019304Speter}
18119304Speter
18219304Speterstatic void
18319304Spetermy_sighandler(i)
18419304Speter	int i;
18519304Speter{
18619304Speter	croak("Perl command interrupted by SIGINT");
18719304Speter}
18819304Speter
18919304Speter/* Create a new reference to an SV pointing to the SCR structure
19019304Speter * The perl_private part of the SCR structure points to the SV,
19119304Speter * so there can only be one such SV for a particular SCR structure.
19219304Speter * When the last reference has gone (DESTROY is called),
19319304Speter * perl_private is reset; When the screen goes away before
19419304Speter * all references are gone, the value of the SV is reset;
19519304Speter * any subsequent use of any of those reference will produce
19619304Speter * a warning. (see typemap)
19719304Speter */
19819304Speterstatic SV *
19919304SpeternewVIrv(rv, screen)
20019304Speter	SV *rv;
20119304Speter	SCR *screen;
20219304Speter{
20319304Speter	sv_upgrade(rv, SVt_RV);
20419304Speter	if (!screen->perl_private) {
20519304Speter		screen->perl_private = newSV(0);
20619304Speter		sv_setiv(screen->perl_private, (IV) screen);
20719304Speter	}
20819304Speter	else SvREFCNT_inc(screen->perl_private);
20919304Speter	SvRV(rv) = screen->perl_private;
21019304Speter	SvROK_on(rv);
21119304Speter	return sv_bless(rv, gv_stashpv("VI", TRUE));
21219304Speter}
21319304Speter
21419304Speter
21519304Speter/*
21619304Speter * perl_ex_perl -- :[line [,line]] perl [command]
21719304Speter *	Run a command through the perl interpreter.
21819304Speter *
21919304Speter * PUBLIC: int perl_ex_perl __P((SCR*, CHAR_T *, size_t, recno_t, recno_t));
22019304Speter */
22119304Speterint
22219304Speterperl_ex_perl(scrp, cmdp, cmdlen, f_lno, t_lno)
22319304Speter	SCR *scrp;
22419304Speter	CHAR_T *cmdp;
22519304Speter	size_t cmdlen;
22619304Speter	recno_t f_lno, t_lno;
22719304Speter{
22819304Speter	static SV *svcurscr = 0, *svstart, *svstop, *svid;
22919304Speter	GS *gp;
23019304Speter	STRLEN length;
23119304Speter	size_t len;
23219304Speter	char *err;
23319304Speter	Signal_t (*istat)();
23419304Speter
23519304Speter	/* Initialize the interpreter. */
23619304Speter	gp = scrp->gp;
23719304Speter	if (!svcurscr) {
23819304Speter		if (gp->perl_interp == NULL && perl_init(scrp))
23919304Speter			return (1);
24019304Speter		SvREADONLY_on(svcurscr = perl_get_sv("curscr", TRUE));
24119304Speter		SvREADONLY_on(svstart = perl_get_sv("VI::StartLine", TRUE));
24219304Speter		SvREADONLY_on(svstop = perl_get_sv("VI::StopLine", TRUE));
24319304Speter		SvREADONLY_on(svid = perl_get_sv("VI::ScreenId", TRUE));
24419304Speter	}
24519304Speter
24619304Speter	sv_setiv(svstart, f_lno);
24719304Speter	sv_setiv(svstop, t_lno);
24819304Speter	newVIrv(svcurscr, scrp);
24919304Speter	/* Backwards compatibility. */
25019304Speter	newVIrv(svid, scrp);
25119304Speter
25219304Speter	istat = signal(SIGINT, my_sighandler);
25319304Speter	perl_eval(cmdp);
25419304Speter	signal(SIGINT, istat);
25519304Speter
25619304Speter	SvREFCNT_dec(SvRV(svcurscr));
25719304Speter	SvROK_off(svcurscr);
25819304Speter	SvREFCNT_dec(SvRV(svid));
25919304Speter	SvROK_off(svid);
26019304Speter
26169474Ssheldonh	err = SvPV(GvSV(PL_errgv), length);
26219304Speter	if (!length)
26319304Speter		return (0);
26419304Speter
26519304Speter	err[length - 1] = '\0';
26619304Speter	msgq(scrp, M_ERR, "perl: %s", err);
26719304Speter	return (1);
26819304Speter}
26919304Speter
27019304Speter/*
27119304Speter * replace_line
27219304Speter *	replace a line with the contents of the perl variable $_
27319304Speter *	lines are split at '\n's
27419304Speter *	if $_ is undef, the line is deleted
27519304Speter *	returns possibly adjusted linenumber
27619304Speter */
27719304Speterstatic int
27819304Speterreplace_line(scrp, line, t_lno)
27919304Speter	SCR *scrp;
28019304Speter	recno_t line, *t_lno;
28119304Speter{
28219304Speter	char *str, *next;
28319304Speter	size_t len;
28419304Speter
28569474Ssheldonh	if (SvOK(GvSV(PL_defgv))) {
28669474Ssheldonh		str = SvPV(GvSV(PL_defgv),len);
28719304Speter		next = memchr(str, '\n', len);
28819304Speter		api_sline(scrp, line, str, next ? (next - str) : len);
28919304Speter		while (next++) {
29019304Speter			len -= next - str;
29119304Speter			next = memchr(str = next, '\n', len);
29219304Speter			api_iline(scrp, ++line, str, next ? (next - str) : len);
29319304Speter			(*t_lno)++;
29419304Speter		}
29519304Speter	} else {
29619304Speter		api_dline(scrp, line--);
29719304Speter		(*t_lno)--;
29819304Speter	}
29919304Speter	return line;
30019304Speter}
30119304Speter
30219304Speter/*
30319304Speter * perl_ex_perldo -- :[line [,line]] perl [command]
30419304Speter *	Run a set of lines through the perl interpreter.
30519304Speter *
30619304Speter * PUBLIC: int perl_ex_perldo __P((SCR*, CHAR_T *, size_t, recno_t, recno_t));
30719304Speter */
30819304Speterint
30919304Speterperl_ex_perldo(scrp, cmdp, cmdlen, f_lno, t_lno)
31019304Speter	SCR *scrp;
31119304Speter	CHAR_T *cmdp;
31219304Speter	size_t cmdlen;
31319304Speter	recno_t f_lno, t_lno;
31419304Speter{
31519304Speter	static SV *svcurscr = 0, *svstart, *svstop, *svid;
31619304Speter	CHAR_T *p;
31719304Speter	GS *gp;
31819304Speter	STRLEN length;
31919304Speter	size_t len;
32019304Speter	recno_t i;
32119304Speter	char *str;
32219304Speter#ifndef HAVE_PERL_5_003_01
32319304Speter	char *argv[2];
32419304Speter#else
32519304Speter	SV* sv;
32619304Speter#endif
32719304Speter	dSP;
32819304Speter
32919304Speter	/* Initialize the interpreter. */
33019304Speter	gp = scrp->gp;
33119304Speter	if (!svcurscr) {
33219304Speter		if (gp->perl_interp == NULL && perl_init(scrp))
33319304Speter			return (1);
33419304Speter		SPAGAIN;
33519304Speter		SvREADONLY_on(svcurscr = perl_get_sv("curscr", TRUE));
33619304Speter		SvREADONLY_on(svstart = perl_get_sv("VI::StartLine", TRUE));
33719304Speter		SvREADONLY_on(svstop = perl_get_sv("VI::StopLine", TRUE));
33819304Speter		SvREADONLY_on(svid = perl_get_sv("VI::ScreenId", TRUE));
33919304Speter	}
34019304Speter
34119304Speter#ifndef HAVE_PERL_5_003_01
34219304Speter	argv[0] = cmdp;
34319304Speter	argv[1] = NULL;
34419304Speter#else
34519304Speter	length = strlen(cmdp);
34619304Speter	sv = newSV(length + sizeof("sub VI::perldo {")-1 + 1 /* } */);
34719304Speter	sv_setpvn(sv, "sub VI::perldo {", sizeof("sub VI::perldo {")-1);
34819304Speter	sv_catpvn(sv, cmdp, length);
34919304Speter	sv_catpvn(sv, "}", 1);
35019304Speter	perl_eval_sv(sv, G_DISCARD | G_NOARGS);
35119304Speter	SvREFCNT_dec(sv);
35269474Ssheldonh	str = SvPV(GvSV(PL_errgv),length);
35319304Speter	if (length)
35419304Speter		goto err;
35519304Speter#endif
35619304Speter
35719304Speter	newVIrv(svcurscr, scrp);
35819304Speter	/* Backwards compatibility. */
35919304Speter	newVIrv(svid, scrp);
36019304Speter
36119304Speter	ENTER;
36219304Speter	SAVETMPS;
36319304Speter	for (i = f_lno; i <= t_lno && !api_gline(scrp, i, &str, &len); i++) {
36469474Ssheldonh		sv_setpvn(GvSV(PL_defgv),str,len);
36519304Speter		sv_setiv(svstart, i);
36619304Speter		sv_setiv(svstop, i);
36719304Speter#ifndef HAVE_PERL_5_003_01
36819304Speter		perl_call_argv("_eval_", G_SCALAR | G_EVAL | G_KEEPERR, argv);
36919304Speter#else
37019304Speter		PUSHMARK(sp);
37119304Speter                perl_call_pv("VI::perldo", G_SCALAR | G_EVAL);
37219304Speter#endif
37369474Ssheldonh		str = SvPV(GvSV(PL_errgv), length);
37419304Speter		if (length) break;
37519304Speter		SPAGAIN;
37619304Speter		if(SvTRUEx(POPs))
37719304Speter			i = replace_line(scrp, i, &t_lno);
37819304Speter		PUTBACK;
37919304Speter	}
38019304Speter	FREETMPS;
38119304Speter	LEAVE;
38219304Speter
38319304Speter	SvREFCNT_dec(SvRV(svcurscr));
38419304Speter	SvROK_off(svcurscr);
38519304Speter	SvREFCNT_dec(SvRV(svid));
38619304Speter	SvROK_off(svid);
38719304Speter
38819304Speter	if (!length)
38919304Speter		return (0);
39019304Speter
39119304Spetererr:	str[length - 1] = '\0';
39219304Speter	msgq(scrp, M_ERR, "perl: %s", str);
39319304Speter	return (1);
39419304Speter}
39519304Speter
39619304Speter/*
39719304Speter * msghandler --
39819304Speter *	Perl message routine so that error messages are processed in
39919304Speter *	Perl, not in nvi.
40019304Speter */
40119304Speterstatic void
40219304Spetermsghandler(sp, mtype, msg, len)
40319304Speter	SCR *sp;
40419304Speter	mtype_t mtype;
40519304Speter	char *msg;
40619304Speter	size_t len;
40719304Speter{
40819304Speter	/* Replace the trailing <newline> with an EOS. */
40919304Speter	/* Let's do that later instead */
41019304Speter	if (errmsg) free (errmsg);
41119304Speter	errmsg = malloc(len + 1);
41219304Speter	memcpy(errmsg, msg, len);
41319304Speter	errmsg[len] = '\0';
41419304Speter}
41519304Speter
41619304Speter/* Register any extra external extensions */
41719304Speter
41819304Speterextern void boot_DynaLoader _((CV* cv));
41919304Speterextern void boot_VI _((CV* cv));
42019304Speter
42119304Speterstatic void
42219304Speterxs_init()
42319304Speter{
42441839Speter	char *file = __FILE__;
42541839Speter
42619304Speter#ifdef HAVE_PERL_5_003_01
42769474Ssheldonh	dXSUB_SYS
42819304Speter#endif
42919304Speter	newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, file);
43019304Speter	newXS("VI::bootstrap", boot_VI, file);
43119304Speter}
43219304Speter
43319304Spetertypedef SCR *	VI;
43419304Spetertypedef SCR *	VI__OPT;
43519304Spetertypedef SCR *	VI__MAP;
43619304Spetertypedef SCR * 	VI__MARK;
43719304Spetertypedef AV *	AVREF;
43819304Speter
43919304SpeterMODULE = VI	PACKAGE = VI
44019304Speter
44119304Speter# msg --
44219304Speter#	Set the message line to text.
44319304Speter#
44419304Speter# Perl Command: VI::Msg
44519304Speter# Usage: VI::Msg screenId text
44619304Speter
44719304Spetervoid
44819304SpeterMsg(screen, text)
44919304Speter	VI          screen
45019304Speter	char *      text
45119304Speter
45219304Speter	ALIAS:
45319304Speter	PRINT = 1
45419304Speter
45519304Speter	CODE:
45619304Speter	api_imessage(screen, text);
45719304Speter
45819304Speter# XS_VI_escreen --
45919304Speter#	End a screen.
46019304Speter#
46119304Speter# Perl Command: VI::EndScreen
46219304Speter# Usage: VI::EndScreen screenId
46319304Speter
46419304Spetervoid
46519304SpeterEndScreen(screen)
46619304Speter	VI	screen
46719304Speter
46819304Speter	PREINIT:
46919304Speter	void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
47019304Speter	int rval;
47119304Speter
47219304Speter	CODE:
47319304Speter	INITMESSAGE;
47419304Speter	rval = api_escreen(screen);
47519304Speter	ENDMESSAGE;
47619304Speter
47719304Speter# XS_VI_iscreen --
47819304Speter#	Create a new screen.  If a filename is specified then the screen
47919304Speter#	is opened with that file.
48019304Speter#
48119304Speter# Perl Command: VI::NewScreen
48219304Speter# Usage: VI::NewScreen screenId [file]
48319304Speter
48419304SpeterVI
48519304SpeterEdit(screen, ...)
48619304Speter	VI screen
48719304Speter
48819304Speter	ALIAS:
48919304Speter	NewScreen = 1
49019304Speter
49119304Speter	PROTOTYPE: $;$
49219304Speter	PREINIT:
49319304Speter	void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
49419304Speter	int rval;
49519304Speter	char *file;
49619304Speter	SCR *nsp;
49719304Speter
49819304Speter	CODE:
49969474Ssheldonh	file = (items == 1) ? NULL : (char *)SvPV(ST(1),PL_na);
50019304Speter	INITMESSAGE;
50119304Speter	rval = api_edit(screen, file, &nsp, ix);
50219304Speter	ENDMESSAGE;
50319304Speter
50419304Speter	RETVAL = ix ? nsp : screen;
50519304Speter
50619304Speter	OUTPUT:
50719304Speter	RETVAL
50819304Speter
50919304Speter# XS_VI_fscreen --
51019304Speter#	Return the screen id associated with file name.
51119304Speter#
51219304Speter# Perl Command: VI::FindScreen
51319304Speter# Usage: VI::FindScreen file
51419304Speter
51519304SpeterVI
51619304SpeterFindScreen(file)
51719304Speter	char *file
51819304Speter
51919304Speter	PREINIT:
52019304Speter	SCR *fsp;
52119304Speter	CODE:
52219304Speter	RETVAL = api_fscreen(0, file);
52319304Speter
52419304Speter# XS_VI_aline --
52519304Speter#	-- Append the string text after the line in lineNumber.
52619304Speter#
52719304Speter# Perl Command: VI::AppendLine
52819304Speter# Usage: VI::AppendLine screenId lineNumber text
52919304Speter
53019304Spetervoid
53119304SpeterAppendLine(screen, linenumber, text)
53219304Speter	VI screen
53319304Speter	int linenumber
53419304Speter	char *text
53519304Speter
53619304Speter	PREINIT:
53719304Speter	void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
53819304Speter	int rval;
53919304Speter	STRLEN length;
54019304Speter
54119304Speter	CODE:
54219304Speter	SvPV(ST(2), length);
54319304Speter	INITMESSAGE;
54419304Speter	rval = api_aline(screen, linenumber, text, length);
54519304Speter	ENDMESSAGE;
54619304Speter
54719304Speter# XS_VI_dline --
54819304Speter#	Delete lineNum.
54919304Speter#
55019304Speter# Perl Command: VI::DelLine
55119304Speter# Usage: VI::DelLine screenId lineNum
55219304Speter
55319304Spetervoid
55419304SpeterDelLine(screen, linenumber)
55519304Speter	VI screen
55619304Speter	int linenumber
55719304Speter
55819304Speter	PREINIT:
55919304Speter	void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
56019304Speter	int rval;
56119304Speter
56219304Speter	CODE:
56319304Speter	INITMESSAGE;
56419304Speter	rval = api_dline(screen, (recno_t)linenumber);
56519304Speter	ENDMESSAGE;
56619304Speter
56719304Speter# XS_VI_gline --
56819304Speter#	Return lineNumber.
56919304Speter#
57019304Speter# Perl Command: VI::GetLine
57119304Speter# Usage: VI::GetLine screenId lineNumber
57219304Speter
57319304Speterchar *
57419304SpeterGetLine(screen, linenumber)
57519304Speter	VI screen
57619304Speter	int linenumber
57719304Speter
57819304Speter	PREINIT:
57919304Speter	size_t len;
58019304Speter	void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
58119304Speter	int rval;
58219304Speter	char *line, *p;
58319304Speter
58419304Speter	PPCODE:
58519304Speter	INITMESSAGE;
58619304Speter	rval = api_gline(screen, (recno_t)linenumber, &p, &len);
58719304Speter	ENDMESSAGE;
58819304Speter
58919304Speter	EXTEND(sp,1);
59019304Speter        PUSHs(sv_2mortal(newSVpv(p, len)));
59119304Speter
59219304Speter# XS_VI_sline --
59319304Speter#	Set lineNumber to the text supplied.
59419304Speter#
59519304Speter# Perl Command: VI::SetLine
59619304Speter# Usage: VI::SetLine screenId lineNumber text
59719304Speter
59819304Spetervoid
59919304SpeterSetLine(screen, linenumber, text)
60019304Speter	VI screen
60119304Speter	int linenumber
60219304Speter	char *text
60319304Speter
60419304Speter	PREINIT:
60519304Speter	void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
60619304Speter	int rval;
60719304Speter	STRLEN length;
60819304Speter
60919304Speter	CODE:
61019304Speter	SvPV(ST(2), length);
61119304Speter	INITMESSAGE;
61219304Speter	rval = api_sline(screen, linenumber, text, length);
61319304Speter	ENDMESSAGE;
61419304Speter
61519304Speter# XS_VI_iline --
61619304Speter#	Insert the string text before the line in lineNumber.
61719304Speter#
61819304Speter# Perl Command: VI::InsertLine
61919304Speter# Usage: VI::InsertLine screenId lineNumber text
62019304Speter
62119304Spetervoid
62219304SpeterInsertLine(screen, linenumber, text)
62319304Speter	VI screen
62419304Speter	int linenumber
62519304Speter	char *text
62619304Speter
62719304Speter	PREINIT:
62819304Speter	void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
62919304Speter	int rval;
63019304Speter	STRLEN length;
63119304Speter
63219304Speter	CODE:
63319304Speter	SvPV(ST(2), length);
63419304Speter	INITMESSAGE;
63519304Speter	rval = api_iline(screen, linenumber, text, length);
63619304Speter	ENDMESSAGE;
63719304Speter
63819304Speter# XS_VI_lline --
63919304Speter#	Return the last line in the screen.
64019304Speter#
64119304Speter# Perl Command: VI::LastLine
64219304Speter# Usage: VI::LastLine screenId
64319304Speter
64419304Speterint
64519304SpeterLastLine(screen)
64619304Speter	VI screen
64719304Speter
64819304Speter	PREINIT:
64919304Speter	recno_t last;
65019304Speter	void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
65119304Speter	int rval;
65219304Speter
65319304Speter	CODE:
65419304Speter	INITMESSAGE;
65519304Speter	rval = api_lline(screen, &last);
65619304Speter	ENDMESSAGE;
65719304Speter	RETVAL=last;
65819304Speter
65919304Speter	OUTPUT:
66019304Speter	RETVAL
66119304Speter
66219304Speter# XS_VI_getmark --
66319304Speter#	Return the mark's cursor position as a list with two elements.
66419304Speter#	{line, column}.
66519304Speter#
66619304Speter# Perl Command: VI::GetMark
66719304Speter# Usage: VI::GetMark screenId mark
66819304Speter
66919304Spetervoid
67019304SpeterGetMark(screen, mark)
67119304Speter	VI screen
67219304Speter	char mark
67319304Speter
67419304Speter	PREINIT:
67519304Speter	struct _mark cursor;
67619304Speter	void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
67719304Speter	int rval;
67819304Speter
67919304Speter	PPCODE:
68019304Speter	INITMESSAGE;
68119304Speter	rval = api_getmark(screen, (int)mark, &cursor);
68219304Speter	ENDMESSAGE;
68319304Speter
68419304Speter	EXTEND(sp,2);
68519304Speter        PUSHs(sv_2mortal(newSViv(cursor.lno)));
68619304Speter        PUSHs(sv_2mortal(newSViv(cursor.cno)));
68719304Speter
68819304Speter# XS_VI_setmark --
68919304Speter#	Set the mark to the line and column numbers supplied.
69019304Speter#
69119304Speter# Perl Command: VI::SetMark
69219304Speter# Usage: VI::SetMark screenId mark line column
69319304Speter
69419304Spetervoid
69519304SpeterSetMark(screen, mark, line, column)
69619304Speter	VI screen
69719304Speter	char mark
69819304Speter	int line
69919304Speter	int column
70019304Speter
70119304Speter	PREINIT:
70219304Speter	struct _mark cursor;
70319304Speter	void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
70419304Speter	int rval;
70519304Speter
70619304Speter	CODE:
70719304Speter	INITMESSAGE;
70819304Speter	cursor.lno = line;
70919304Speter	cursor.cno = column;
71019304Speter	rval = api_setmark(screen, (int)mark, &cursor);
71119304Speter	ENDMESSAGE;
71219304Speter
71319304Speter# XS_VI_getcursor --
71419304Speter#	Return the current cursor position as a list with two elements.
71519304Speter#	{line, column}.
71619304Speter#
71719304Speter# Perl Command: VI::GetCursor
71819304Speter# Usage: VI::GetCursor screenId
71919304Speter
72019304Spetervoid
72119304SpeterGetCursor(screen)
72219304Speter	VI screen
72319304Speter
72419304Speter	PREINIT:
72519304Speter	struct _mark cursor;
72619304Speter	void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
72719304Speter	int rval;
72819304Speter
72919304Speter	PPCODE:
73019304Speter	INITMESSAGE;
73119304Speter	rval = api_getcursor(screen, &cursor);
73219304Speter	ENDMESSAGE;
73319304Speter
73419304Speter	EXTEND(sp,2);
73519304Speter        PUSHs(sv_2mortal(newSViv(cursor.lno)));
73619304Speter        PUSHs(sv_2mortal(newSViv(cursor.cno)));
73719304Speter
73819304Speter# XS_VI_setcursor --
73919304Speter#	Set the cursor to the line and column numbers supplied.
74019304Speter#
74119304Speter# Perl Command: VI::SetCursor
74219304Speter# Usage: VI::SetCursor screenId line column
74319304Speter
74419304Spetervoid
74519304SpeterSetCursor(screen, line, column)
74619304Speter	VI screen
74719304Speter	int line
74819304Speter	int column
74919304Speter
75019304Speter	PREINIT:
75119304Speter	struct _mark cursor;
75219304Speter	void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
75319304Speter	int rval;
75419304Speter
75519304Speter	CODE:
75619304Speter	INITMESSAGE;
75719304Speter	cursor.lno = line;
75819304Speter	cursor.cno = column;
75919304Speter	rval = api_setcursor(screen, &cursor);
76019304Speter	ENDMESSAGE;
76119304Speter
76219304Speter# XS_VI_swscreen --
76319304Speter#	Change the current focus to screen.
76419304Speter#
76519304Speter# Perl Command: VI::SwitchScreen
76619304Speter# Usage: VI::SwitchScreen screenId screenId
76719304Speter
76819304Spetervoid
76919304SpeterSwitchScreen(screenFrom, screenTo)
77019304Speter	VI screenFrom
77119304Speter	VI screenTo
77219304Speter
77319304Speter	PREINIT:
77419304Speter	void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
77519304Speter	int rval;
77619304Speter
77719304Speter	CODE:
77819304Speter	INITMESSAGE;
77919304Speter	rval = api_swscreen(screenFrom, screenTo);
78019304Speter	ENDMESSAGE;
78119304Speter
78219304Speter# XS_VI_map --
78319304Speter#	Associate a key with a perl procedure.
78419304Speter#
78519304Speter# Perl Command: VI::MapKey
78619304Speter# Usage: VI::MapKey screenId key perlproc
78719304Speter
78819304Spetervoid
78919304SpeterMapKey(screen, key, perlproc)
79019304Speter	VI screen
79119304Speter	char *key
79219304Speter	SV *perlproc
79319304Speter
79419304Speter	PREINIT:
79519304Speter	void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
79619304Speter	int rval;
79719304Speter	int length;
79819304Speter	char *command;
79919304Speter	SV *svc;
80019304Speter
80119304Speter	CODE:
80219304Speter	INITMESSAGE;
80319304Speter	svc = sv_2mortal(newSVpv(":perl ", 6));
80419304Speter	sv_catsv(svc, perlproc);
80519304Speter	command = SvPV(svc, length);
80619304Speter	rval = api_map(screen, key, command, length);
80719304Speter	ENDMESSAGE;
80819304Speter
80919304Speter# XS_VI_unmap --
81019304Speter#	Unmap a key.
81119304Speter#
81219304Speter# Perl Command: VI::UnmapKey
81319304Speter# Usage: VI::UnmmapKey screenId key
81419304Speter
81519304Spetervoid
81619304SpeterUnmapKey(screen, key)
81719304Speter	VI screen
81819304Speter	char *key
81919304Speter
82019304Speter	PREINIT:
82119304Speter	void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
82219304Speter	int rval;
82319304Speter
82419304Speter	CODE:
82519304Speter	INITMESSAGE;
82619304Speter	rval = api_unmap(screen, key);
82719304Speter	ENDMESSAGE;
82819304Speter
82919304Speter# XS_VI_opts_set --
83019304Speter#	Set an option.
83119304Speter#
83219304Speter# Perl Command: VI::SetOpt
83319304Speter# Usage: VI::SetOpt screenId setting
83419304Speter
83519304Spetervoid
83619304SpeterSetOpt(screen, setting)
83719304Speter	VI screen
83819304Speter	char *setting
83919304Speter
84019304Speter	PREINIT:
84119304Speter	void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
84219304Speter	int rval;
84319304Speter	SV *svc;
84419304Speter
84519304Speter	CODE:
84619304Speter	INITMESSAGE;
84719304Speter	svc = sv_2mortal(newSVpv(":set ", 5));
84819304Speter	sv_catpv(svc, setting);
84969474Ssheldonh	rval = api_run_str(screen, SvPV(svc, PL_na));
85019304Speter	ENDMESSAGE;
85119304Speter
85219304Speter# XS_VI_opts_get --
85319304Speter#	Return the value of an option.
85419304Speter#
85519304Speter# Perl Command: VI::GetOpt
85619304Speter# Usage: VI::GetOpt screenId option
85719304Speter
85819304Spetervoid
85919304SpeterGetOpt(screen, option)
86019304Speter	VI screen
86119304Speter	char *option
86219304Speter
86319304Speter	PREINIT:
86419304Speter	void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
86519304Speter	int rval;
86619304Speter	char *value;
86719304Speter
86819304Speter	PPCODE:
86919304Speter	INITMESSAGE;
87019304Speter	rval = api_opts_get(screen, option, &value, NULL);
87119304Speter	ENDMESSAGE;
87219304Speter
87319304Speter	EXTEND(SP,1);
87419304Speter	PUSHs(sv_2mortal(newSVpv(value, 0)));
87519304Speter	free(value);
87619304Speter
87719304Speter# XS_VI_run --
87819304Speter#	Run the ex command cmd.
87919304Speter#
88019304Speter# Perl Command: VI::Run
88119304Speter# Usage: VI::Run screenId cmd
88219304Speter
88319304Spetervoid
88419304SpeterRun(screen, command)
88519304Speter	VI screen
88619304Speter	char *command;
88719304Speter
88819304Speter	PREINIT:
88919304Speter	void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
89019304Speter	int rval;
89119304Speter
89219304Speter	CODE:
89319304Speter	INITMESSAGE;
89419304Speter	rval = api_run_str(screen, command);
89519304Speter	ENDMESSAGE;
89619304Speter
89719304Spetervoid
89819304SpeterDESTROY(screen)
89919304Speter	VI screen
90019304Speter
90119304Speter	CODE:
90219304Speter	screen->perl_private = 0;
90319304Speter
90419304Spetervoid
90519304SpeterWarn(warning)
90619304Speter	char *warning;
90719304Speter
90819304Speter	PREINIT:
90919304Speter	int i;
91019304Speter	CODE:
91169474Ssheldonh	sv_catpv(GvSV(PL_errgv),warning);
91219304Speter
91319304Speter#define TIED(package) \
91419304Speter	sv_magic((SV *) (hv = \
91519304Speter	    (HV *)sv_2mortal((SV *)newHV())), \
91619304Speter		sv_setref_pv(sv_newmortal(), package, \
91719304Speter			newVIrv(newSV(0), screen)),\
91819304Speter		'P', Nullch, 0);\
91919304Speter	RETVAL = newRV((SV *)hv)
92019304Speter
92119304SpeterSV *
92219304SpeterOpt(screen)
92319304Speter	VI screen;
92419304Speter	PREINIT:
92519304Speter	HV *hv;
92619304Speter	CODE:
92719304Speter	TIED("VI::OPT");
92819304Speter	OUTPUT:
92919304Speter	RETVAL
93019304Speter
93119304SpeterSV *
93219304SpeterMap(screen)
93319304Speter	VI screen;
93419304Speter	PREINIT:
93519304Speter	HV *hv;
93619304Speter	CODE:
93719304Speter	TIED("VI::MAP");
93819304Speter	OUTPUT:
93919304Speter	RETVAL
94019304Speter
94119304SpeterSV *
94219304SpeterMark(screen)
94319304Speter	VI screen
94419304Speter	PREINIT:
94519304Speter	HV *hv;
94619304Speter	CODE:
94719304Speter	TIED("VI::MARK");
94819304Speter	OUTPUT:
94919304Speter	RETVAL
95019304Speter
95119304SpeterMODULE = VI	PACKAGE = VI::OPT
95219304Speter
95319304Spetervoid
95419304SpeterDESTROY(screen)
95519304Speter	VI::OPT screen
95619304Speter
95719304Speter	CODE:
95819304Speter	# typemap did all the checking
95919304Speter	SvREFCNT_dec((SV*)SvIV((SV*)SvRV(ST(0))));
96019304Speter
96119304Spetervoid
96219304SpeterFETCH(screen, key)
96319304Speter	VI::OPT screen
96419304Speter	char *key
96519304Speter
96619304Speter	PREINIT:
96719304Speter	void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
96819304Speter	int rval;
96919304Speter	char *value;
97019304Speter	int boolvalue;
97119304Speter
97219304Speter	PPCODE:
97319304Speter	INITMESSAGE;
97419304Speter	rval = api_opts_get(screen, key, &value, &boolvalue);
97519304Speter	if (!rval) {
97619304Speter		EXTEND(SP,1);
97719304Speter		PUSHs(sv_2mortal((boolvalue == -1) ? newSVpv(value, 0)
97819304Speter						   : newSViv(boolvalue)));
97919304Speter		free(value);
98069474Ssheldonh	} else ST(0) = &PL_sv_undef;
98119304Speter	rval = 0;
98219304Speter	ENDMESSAGE;
98319304Speter
98419304Spetervoid
98519304SpeterSTORE(screen, key, value)
98619304Speter	VI::OPT	screen
98719304Speter	char	*key
98819304Speter	SV	*value
98919304Speter
99019304Speter	PREINIT:
99119304Speter	void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
99219304Speter	int rval;
99319304Speter
99419304Speter	CODE:
99519304Speter	INITMESSAGE;
99669474Ssheldonh	rval = api_opts_set(screen, key, SvPV(value, PL_na), SvIV(value),
99719304Speter                                         SvTRUEx(value));
99819304Speter	ENDMESSAGE;
99919304Speter
100019304SpeterMODULE = VI	PACKAGE = VI::MAP
100119304Speter
100219304Spetervoid
100319304SpeterDESTROY(screen)
100419304Speter	VI::MAP screen
100519304Speter
100619304Speter	CODE:
100719304Speter	# typemap did all the checking
100819304Speter	SvREFCNT_dec((SV*)SvIV((SV*)SvRV(ST(0))));
100919304Speter
101019304Spetervoid
101119304SpeterSTORE(screen, key, perlproc)
101219304Speter	VI::MAP screen
101319304Speter	char *key
101419304Speter	SV *perlproc
101519304Speter
101619304Speter	PREINIT:
101719304Speter	void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
101819304Speter	int rval;
101919304Speter	int length;
102019304Speter	char *command;
102119304Speter	SV *svc;
102219304Speter
102319304Speter	CODE:
102419304Speter	INITMESSAGE;
102519304Speter	svc = sv_2mortal(newSVpv(":perl ", 6));
102619304Speter	sv_catsv(svc, perlproc);
102719304Speter	command = SvPV(svc, length);
102819304Speter	rval = api_map(screen, key, command, length);
102919304Speter	ENDMESSAGE;
103019304Speter
103119304Spetervoid
103219304SpeterDELETE(screen, key)
103319304Speter	VI::MAP screen
103419304Speter	char *key
103519304Speter
103619304Speter	PREINIT:
103719304Speter	void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
103819304Speter	int rval;
103919304Speter
104019304Speter	CODE:
104119304Speter	INITMESSAGE;
104219304Speter	rval = api_unmap(screen, key);
104319304Speter	ENDMESSAGE;
104419304Speter
104519304SpeterMODULE = VI	PACKAGE = VI::MARK
104619304Speter
104719304Spetervoid
104819304SpeterDESTROY(screen)
104919304Speter	VI::MARK screen
105019304Speter
105119304Speter	CODE:
105219304Speter	# typemap did all the checking
105319304Speter	SvREFCNT_dec((SV*)SvIV((SV*)SvRV(ST(0))));
105419304Speter
105519304SpeterAV *
105619304SpeterFETCH(screen, mark)
105719304Speter	VI::MARK screen
105819304Speter	char mark
105919304Speter
106019304Speter	PREINIT:
106119304Speter	struct _mark cursor;
106219304Speter	void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
106319304Speter	int rval;
106419304Speter
106519304Speter	CODE:
106619304Speter	INITMESSAGE;
106719304Speter	rval = api_getmark(screen, (int)mark, &cursor);
106819304Speter	ENDMESSAGE;
106919304Speter	RETVAL = newAV();
107019304Speter	av_push(RETVAL, newSViv(cursor.lno));
107119304Speter	av_push(RETVAL, newSViv(cursor.cno));
107219304Speter
107319304Speter	OUTPUT:
107419304Speter	RETVAL
107519304Speter
107619304Spetervoid
107719304SpeterSTORE(screen, mark, pos)
107819304Speter	VI::MARK screen
107919304Speter	char mark
108019304Speter	AVREF pos
108119304Speter
108219304Speter	PREINIT:
108319304Speter	struct _mark cursor;
108419304Speter	void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
108519304Speter	int rval;
108619304Speter
108719304Speter	CODE:
108819304Speter	if (av_len(pos) < 1)
108919304Speter	    croak("cursor position needs 2 elements");
109019304Speter	INITMESSAGE;
109119304Speter	cursor.lno = SvIV(*av_fetch(pos, 0, 0));
109219304Speter	cursor.cno = SvIV(*av_fetch(pos, 1, 0));
109319304Speter	rval = api_setmark(screen, (int)mark, &cursor);
109419304Speter	ENDMESSAGE;
109519304Speter
109619304Spetervoid
109719304SpeterFIRSTKEY(screen, ...)
109819304Speter	VI::MARK screen
109919304Speter
110019304Speter	ALIAS:
110119304Speter	NEXTKEY = 1
110219304Speter
110319304Speter	PROTOTYPE: $;$
110419304Speter
110519304Speter	PREINIT:
110619304Speter	struct _mark cursor;
110719304Speter	void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
110819304Speter	int next;
110919304Speter	char key[] = {0, 0};
111019304Speter
111119304Speter	PPCODE:
111219304Speter	if (items == 2) {
111319304Speter		next = 1;
111469474Ssheldonh		*key = *(char *)SvPV(ST(1),PL_na);
111519304Speter	} else next = 0;
111619304Speter	if (api_nextmark(screen, next, key) != 1) {
111719304Speter		EXTEND(sp, 1);
111819304Speter        	PUSHs(sv_2mortal(newSVpv(key, 1)));
111969474Ssheldonh	} else ST(0) = &PL_sv_undef;
1120