Home | History | Annotate | Line # | Download | only in perl_api
perl.xs revision 1.1.1.1
      1  1.1  christos /*-
      2  1.1  christos  * Copyright (c) 1992, 1993, 1994
      3  1.1  christos  *	The Regents of the University of California.  All rights reserved.
      4  1.1  christos  * Copyright (c) 1992, 1993, 1994, 1995, 1996
      5  1.1  christos  *	Keith Bostic.  All rights reserved.
      6  1.1  christos  * Copyright (c) 1995
      7  1.1  christos  *	George V. Neville-Neil. All rights reserved.
      8  1.1  christos  * Copyright (c) 1996-2001
      9  1.1  christos  *	Sven Verdoolaege. All rights reserved.
     10  1.1  christos  *
     11  1.1  christos  * See the LICENSE file for redistribution information.
     12  1.1  christos  */
     13  1.1  christos 
     14  1.1  christos #undef VI
     15  1.1  christos 
     16  1.1  christos #ifndef lint
     17  1.1  christos 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 ";
     18  1.1  christos #endif /* not lint */
     19  1.1  christos 
     20  1.1  christos #include <sys/types.h>
     21  1.1  christos #include <sys/queue.h>
     22  1.1  christos #include <sys/time.h>
     23  1.1  christos 
     24  1.1  christos #include <bitstring.h>
     25  1.1  christos #include <ctype.h>
     26  1.1  christos #include <limits.h>
     27  1.1  christos #include <signal.h>
     28  1.1  christos #include <stdio.h>
     29  1.1  christos #include <stdlib.h>
     30  1.1  christos #include <string.h>
     31  1.1  christos #include <termios.h>
     32  1.1  christos #include <unistd.h>
     33  1.1  christos 
     34  1.1  christos #include <EXTERN.h>
     35  1.1  christos #include <perl.h>
     36  1.1  christos #include <XSUB.h>
     37  1.1  christos 
     38  1.1  christos /* perl redefines them
     39  1.1  christos  * avoid warnings
     40  1.1  christos  */
     41  1.1  christos #undef USE_DYNAMIC_LOADING
     42  1.1  christos #undef DEBUG
     43  1.1  christos #undef PACKAGE
     44  1.1  christos #undef ARGS
     45  1.1  christos #define ARGS ARGS
     46  1.1  christos 
     47  1.1  christos #include "config.h"
     48  1.1  christos 
     49  1.1  christos #include "../common/common.h"
     50  1.1  christos #include "../perl_api/extern.h"
     51  1.1  christos 
     52  1.1  christos #ifndef DEFSV
     53  1.1  christos #define DEFSV GvSV(defgv)
     54  1.1  christos #endif
     55  1.1  christos #ifndef ERRSV
     56  1.1  christos #define ERRSV GvSV(errgv)
     57  1.1  christos #endif
     58  1.1  christos #ifndef dTHX
     59  1.1  christos #define dTHXs
     60  1.1  christos #else
     61  1.1  christos #define dTHXs dTHX;
     62  1.1  christos #endif
     63  1.1  christos 
     64  1.1  christos static void msghandler __P((SCR *, mtype_t, char *, size_t));
     65  1.1  christos 
     66  1.1  christos typedef struct _perl_data {
     67  1.1  christos     	PerlInterpreter*	interp;
     68  1.1  christos 	SV 	*svcurscr, *svstart, *svstop, *svid;
     69  1.1  christos 	CONVWIN	 cw;
     70  1.1  christos 	char 	*errmsg;
     71  1.1  christos } perl_data_t;
     72  1.1  christos 
     73  1.1  christos #define PERLP(sp)   ((perl_data_t *)sp->wp->perl_private)
     74  1.1  christos 
     75  1.1  christos #define CHAR2INTP(sp,n,nlen,w,wlen)					    \
     76  1.1  christos     CHAR2INT5(sp,((perl_data_t *)sp->wp->perl_private)->cw,n,nlen,w,wlen)
     77  1.1  christos 
     78  1.1  christos /*
     79  1.1  christos  * INITMESSAGE --
     80  1.1  christos  *	Macros to point messages at the Perl message handler.
     81  1.1  christos  */
     82  1.1  christos #define	INITMESSAGE(sp)							\
     83  1.1  christos 	scr_msg = sp->wp->scr_msg;					\
     84  1.1  christos 	sp->wp->scr_msg = msghandler;
     85  1.1  christos #define	ENDMESSAGE(sp)							\
     86  1.1  christos 	sp->wp->scr_msg = scr_msg;					\
     87  1.1  christos 	if (rval) croak(PERLP(sp)->errmsg);
     88  1.1  christos 
     89  1.1  christos void xs_init __P((pTHXo));
     90  1.1  christos 
     91  1.1  christos /*
     92  1.1  christos  * perl_end --
     93  1.1  christos  *	Clean up perl interpreter
     94  1.1  christos  *
     95  1.1  christos  * PUBLIC: int perl_end __P((GS *));
     96  1.1  christos  */
     97  1.1  christos int
     98  1.1  christos perl_end(gp)
     99  1.1  christos 	GS *gp;
    100  1.1  christos {
    101  1.1  christos 	/*
    102  1.1  christos 	 * Call perl_run and perl_destuct to call END blocks and DESTROY
    103  1.1  christos 	 * methods.
    104  1.1  christos 	 */
    105  1.1  christos 	if (gp->perl_interp) {
    106  1.1  christos 		perl_run(gp->perl_interp);
    107  1.1  christos 		perl_destruct(gp->perl_interp);
    108  1.1  christos #if defined(DEBUG) || defined(PURIFY) || defined(LIBRARY)
    109  1.1  christos 		perl_free(gp->perl_interp);
    110  1.1  christos #endif
    111  1.1  christos 		/* XXX rather make sure only one thread calls perl_end */
    112  1.1  christos 		gp->perl_interp = 0;
    113  1.1  christos 	}
    114  1.1  christos }
    115  1.1  christos 
    116  1.1  christos /*
    117  1.1  christos  * perl_eval
    118  1.1  christos  *	Evaluate a string
    119  1.1  christos  * 	We don't use mortal SVs because no one will clean up after us
    120  1.1  christos  */
    121  1.1  christos static void
    122  1.1  christos perl_eval(string)
    123  1.1  christos 	char *string;
    124  1.1  christos {
    125  1.1  christos 	dTHXs
    126  1.1  christos 
    127  1.1  christos 	SV* sv = newSVpv(string, 0);
    128  1.1  christos 
    129  1.1  christos 	/* G_KEEPERR to catch syntax error; better way ? */
    130  1.1  christos 	sv_setpv(ERRSV,"");
    131  1.1  christos 	perl_eval_sv(sv, G_DISCARD | G_NOARGS | G_KEEPERR);
    132  1.1  christos 	SvREFCNT_dec(sv);
    133  1.1  christos }
    134  1.1  christos 
    135  1.1  christos /*
    136  1.1  christos  * perl_init --
    137  1.1  christos  *	Create the perl commands used by nvi.
    138  1.1  christos  *
    139  1.1  christos  * PUBLIC: int perl_init __P((SCR *));
    140  1.1  christos  */
    141  1.1  christos int
    142  1.1  christos perl_init(scrp)
    143  1.1  christos 	SCR *scrp;
    144  1.1  christos {
    145  1.1  christos 	AV * av;
    146  1.1  christos 	GS *gp;
    147  1.1  christos 	WIN *wp;
    148  1.1  christos 	char *bootargs[] = { "VI", NULL };
    149  1.1  christos #ifndef USE_SFIO
    150  1.1  christos 	SV *svcurscr;
    151  1.1  christos #endif
    152  1.1  christos 	perl_data_t *pp;
    153  1.1  christos 
    154  1.1  christos 	static char *args[] = { "", "-e", "" };
    155  1.1  christos 	size_t length;
    156  1.1  christos 	char *file = __FILE__;
    157  1.1  christos 
    158  1.1  christos 	gp = scrp->gp;
    159  1.1  christos 	wp = scrp->wp;
    160  1.1  christos 
    161  1.1  christos 	if (gp->perl_interp == NULL) {
    162  1.1  christos 	gp->perl_interp = perl_alloc();
    163  1.1  christos   	perl_construct(gp->perl_interp);
    164  1.1  christos 	if (perl_parse(gp->perl_interp, xs_init, 3, args, 0)) {
    165  1.1  christos 		perl_destruct(gp->perl_interp);
    166  1.1  christos 		perl_free(gp->perl_interp);
    167  1.1  christos 		gp->perl_interp = NULL;
    168  1.1  christos 		return 1;
    169  1.1  christos 	}
    170  1.1  christos 	{
    171  1.1  christos 	dTHXs
    172  1.1  christos 
    173  1.1  christos         perl_call_argv("VI::bootstrap", G_DISCARD, bootargs);
    174  1.1  christos 	perl_eval("$SIG{__WARN__}='VI::Warn'");
    175  1.1  christos 
    176  1.1  christos 	av_unshift(av = GvAVn(PL_incgv), 1);
    177  1.1  christos 	av_store(av, 0, newSVpv(_PATH_PERLSCRIPTS,
    178  1.1  christos 				sizeof(_PATH_PERLSCRIPTS)-1));
    179  1.1  christos 
    180  1.1  christos #ifdef USE_SFIO
    181  1.1  christos 	sfdisc(PerlIO_stdout(), sfdcnewnvi(scrp));
    182  1.1  christos 	sfdisc(PerlIO_stderr(), sfdcnewnvi(scrp));
    183  1.1  christos #else
    184  1.1  christos 	svcurscr = perl_get_sv("curscr", TRUE);
    185  1.1  christos 	sv_magic((SV *)gv_fetchpv("STDOUT",TRUE, SVt_PVIO), svcurscr,
    186  1.1  christos 		 	'q', Nullch, 0);
    187  1.1  christos 	sv_magic((SV *)gv_fetchpv("STDERR",TRUE, SVt_PVIO), svcurscr,
    188  1.1  christos 		 	'q', Nullch, 0);
    189  1.1  christos #endif /* USE_SFIO */
    190  1.1  christos 	}
    191  1.1  christos 	}
    192  1.1  christos 	MALLOC(scrp, pp, perl_data_t *, sizeof(perl_data_t));
    193  1.1  christos 	wp->perl_private = pp;
    194  1.1  christos 	memset(&pp->cw, 0, sizeof(pp->cw));
    195  1.1  christos #ifdef USE_ITHREADS
    196  1.1  christos 	pp->interp = perl_clone(gp->perl_interp, 0);
    197  1.1  christos         if (1) { /* hack for bug fixed in perl-current (5.6.1) */
    198  1.1  christos             dTHXa(pp->interp);
    199  1.1  christos             if (PL_scopestack_ix == 0) {
    200  1.1  christos                 ENTER;
    201  1.1  christos             }
    202  1.1  christos         }
    203  1.1  christos #else
    204  1.1  christos 	pp->interp = gp->perl_interp;
    205  1.1  christos #endif
    206  1.1  christos 	pp->errmsg = 0;
    207  1.1  christos 	{
    208  1.1  christos 		dTHXs
    209  1.1  christos 
    210  1.1  christos 		SvREADONLY_on(pp->svcurscr = perl_get_sv("curscr", TRUE));
    211  1.1  christos 		SvREADONLY_on(pp->svstart = perl_get_sv("VI::StartLine", TRUE));
    212  1.1  christos 		SvREADONLY_on(pp->svstop = perl_get_sv("VI::StopLine", TRUE));
    213  1.1  christos 		SvREADONLY_on(pp->svid = perl_get_sv("VI::ScreenId", TRUE));
    214  1.1  christos 	}
    215  1.1  christos 	return (0);
    216  1.1  christos }
    217  1.1  christos 
    218  1.1  christos /*
    219  1.1  christos  * perl_screen_end
    220  1.1  christos  *	Remove all refences to the screen to be destroyed
    221  1.1  christos  *
    222  1.1  christos  * PUBLIC: int perl_screen_end __P((SCR*));
    223  1.1  christos  */
    224  1.1  christos int
    225  1.1  christos perl_screen_end(scrp)
    226  1.1  christos 	SCR *scrp;
    227  1.1  christos {
    228  1.1  christos 	dTHXs
    229  1.1  christos 
    230  1.1  christos 	if (scrp->perl_private) {
    231  1.1  christos 		sv_setiv((SV*) scrp->perl_private, 0);
    232  1.1  christos 	}
    233  1.1  christos 	return 0;
    234  1.1  christos }
    235  1.1  christos 
    236  1.1  christos static void
    237  1.1  christos my_sighandler(i)
    238  1.1  christos 	int i;
    239  1.1  christos {
    240  1.1  christos 	croak("Perl command interrupted by SIGINT");
    241  1.1  christos }
    242  1.1  christos 
    243  1.1  christos /* Create a new reference to an SV pointing to the SCR structure
    244  1.1  christos  * The perl_private part of the SCR structure points to the SV,
    245  1.1  christos  * so there can only be one such SV for a particular SCR structure.
    246  1.1  christos  * When the last reference has gone (DESTROY is called),
    247  1.1  christos  * perl_private is reset; When the screen goes away before
    248  1.1  christos  * all references are gone, the value of the SV is reset;
    249  1.1  christos  * any subsequent use of any of those reference will produce
    250  1.1  christos  * a warning. (see typemap)
    251  1.1  christos  */
    252  1.1  christos static SV *
    253  1.1  christos newVIrv(rv, screen)
    254  1.1  christos 	SV *rv;
    255  1.1  christos 	SCR *screen;
    256  1.1  christos {
    257  1.1  christos 	dTHXs
    258  1.1  christos 
    259  1.1  christos 	if (!screen) return sv_setsv(rv, &PL_sv_undef), rv;
    260  1.1  christos 	sv_upgrade(rv, SVt_RV);
    261  1.1  christos 	if (!screen->perl_private) {
    262  1.1  christos 		screen->perl_private = newSV(0);
    263  1.1  christos 		sv_setiv(screen->perl_private, (IV) screen);
    264  1.1  christos 	}
    265  1.1  christos 	else SvREFCNT_inc(screen->perl_private);
    266  1.1  christos 	SvRV(rv) = screen->perl_private;
    267  1.1  christos 	SvROK_on(rv);
    268  1.1  christos 	return sv_bless(rv, gv_stashpv("VI", TRUE));
    269  1.1  christos }
    270  1.1  christos 
    271  1.1  christos /*
    272  1.1  christos  * perl_setenv
    273  1.1  christos  *	Use perl's setenv if perl interpreter has been started.
    274  1.1  christos  *	Perl uses its own setenv and gets confused if we change
    275  1.1  christos  *	the environment after it has started.
    276  1.1  christos  *
    277  1.1  christos  * PUBLIC: int perl_setenv __P((SCR* sp, const char *name, const char *value));
    278  1.1  christos  */
    279  1.1  christos int
    280  1.1  christos perl_setenv(SCR* scrp, const char *name, const char *value)
    281  1.1  christos {
    282  1.1  christos 	if (scrp->wp->perl_private == NULL) {
    283  1.1  christos 	    if (value == NULL)
    284  1.1  christos 		unsetenv(name);
    285  1.1  christos 	    else
    286  1.1  christos 		setenv(name, value, 1);
    287  1.1  christos 	} else
    288  1.1  christos 	    my_setenv(name, value);
    289  1.1  christos }
    290  1.1  christos 
    291  1.1  christos 
    292  1.1  christos /*
    293  1.1  christos  * perl_ex_perl -- :[line [,line]] perl [command]
    294  1.1  christos  *	Run a command through the perl interpreter.
    295  1.1  christos  *
    296  1.1  christos  * PUBLIC: int perl_ex_perl __P((SCR*, CHAR_T *, size_t, db_recno_t, db_recno_t));
    297  1.1  christos  */
    298  1.1  christos int
    299  1.1  christos perl_ex_perl(scrp, cmdp, cmdlen, f_lno, t_lno)
    300  1.1  christos 	SCR *scrp;
    301  1.1  christos 	CHAR_T *cmdp;
    302  1.1  christos 	size_t cmdlen;
    303  1.1  christos 	db_recno_t f_lno, t_lno;
    304  1.1  christos {
    305  1.1  christos 	WIN *wp;
    306  1.1  christos 	size_t length;
    307  1.1  christos 	size_t len;
    308  1.1  christos 	char *err;
    309  1.1  christos 	char *np;
    310  1.1  christos 	size_t nlen;
    311  1.1  christos 	Signal_t (*istat)();
    312  1.1  christos 	perl_data_t *pp;
    313  1.1  christos 
    314  1.1  christos 	/* Initialize the interpreter. */
    315  1.1  christos 	if (scrp->wp->perl_private == NULL && perl_init(scrp))
    316  1.1  christos 			return (1);
    317  1.1  christos 	pp = scrp->wp->perl_private;
    318  1.1  christos     {
    319  1.1  christos 	dTHXs
    320  1.1  christos 	dSP;
    321  1.1  christos 
    322  1.1  christos 	sv_setiv(pp->svstart, f_lno);
    323  1.1  christos 	sv_setiv(pp->svstop, t_lno);
    324  1.1  christos 	newVIrv(pp->svcurscr, scrp);
    325  1.1  christos 	/* Backwards compatibility. */
    326  1.1  christos 	newVIrv(pp->svid, scrp);
    327  1.1  christos 
    328  1.1  christos 	istat = signal(SIGINT, my_sighandler);
    329  1.1  christos 	INT2CHAR(scrp, cmdp, STRLEN(cmdp)+1, np, nlen);
    330  1.1  christos 	perl_eval(np);
    331  1.1  christos 	signal(SIGINT, istat);
    332  1.1  christos 
    333  1.1  christos 	SvREFCNT_dec(SvRV(pp->svcurscr));
    334  1.1  christos 	SvROK_off(pp->svcurscr);
    335  1.1  christos 	SvREFCNT_dec(SvRV(pp->svid));
    336  1.1  christos 	SvROK_off(pp->svid);
    337  1.1  christos 
    338  1.1  christos 	err = SvPV(ERRSV, length);
    339  1.1  christos 	if (!length)
    340  1.1  christos 		return (0);
    341  1.1  christos 
    342  1.1  christos 	err[length - 1] = '\0';
    343  1.1  christos 	msgq(scrp, M_ERR, "perl: %s", err);
    344  1.1  christos 	return (1);
    345  1.1  christos     }
    346  1.1  christos }
    347  1.1  christos 
    348  1.1  christos /*
    349  1.1  christos  * replace_line
    350  1.1  christos  *	replace a line with the contents of the perl variable $_
    351  1.1  christos  *	lines are split at '\n's
    352  1.1  christos  *	if $_ is undef, the line is deleted
    353  1.1  christos  *	returns possibly adjusted linenumber
    354  1.1  christos  */
    355  1.1  christos static int
    356  1.1  christos replace_line(scrp, line, t_lno, defsv)
    357  1.1  christos 	SCR *scrp;
    358  1.1  christos 	db_recno_t line, *t_lno;
    359  1.1  christos 	SV *defsv;
    360  1.1  christos {
    361  1.1  christos 	char *str, *next;
    362  1.1  christos 	CHAR_T *wp;
    363  1.1  christos 	size_t len, wlen;
    364  1.1  christos 	dTHXs
    365  1.1  christos 
    366  1.1  christos 	if (SvOK(defsv)) {
    367  1.1  christos 		str = SvPV(defsv,len);
    368  1.1  christos 		next = memchr(str, '\n', len);
    369  1.1  christos 		CHAR2INTP(scrp, str, next ? (next - str) : len, wp, wlen);
    370  1.1  christos 		api_sline(scrp, line, wp, wlen);
    371  1.1  christos 		while (next++) {
    372  1.1  christos 			len -= next - str;
    373  1.1  christos 			next = memchr(str = next, '\n', len);
    374  1.1  christos 			CHAR2INTP(scrp, str, next ? (next - str) : len,
    375  1.1  christos 				    wp, wlen);
    376  1.1  christos 			api_iline(scrp, ++line, wp, wlen);
    377  1.1  christos 			(*t_lno)++;
    378  1.1  christos 		}
    379  1.1  christos 	} else {
    380  1.1  christos 		api_dline(scrp, line--);
    381  1.1  christos 		(*t_lno)--;
    382  1.1  christos 	}
    383  1.1  christos 	return line;
    384  1.1  christos }
    385  1.1  christos 
    386  1.1  christos /*
    387  1.1  christos  * perl_ex_perldo -- :[line [,line]] perl [command]
    388  1.1  christos  *	Run a set of lines through the perl interpreter.
    389  1.1  christos  *
    390  1.1  christos  * PUBLIC: int perl_ex_perldo __P((SCR*, CHAR_T *, size_t, db_recno_t, db_recno_t));
    391  1.1  christos  */
    392  1.1  christos int
    393  1.1  christos perl_ex_perldo(scrp, cmdp, cmdlen, f_lno, t_lno)
    394  1.1  christos 	SCR *scrp;
    395  1.1  christos 	CHAR_T *cmdp;
    396  1.1  christos 	size_t cmdlen;
    397  1.1  christos 	db_recno_t f_lno, t_lno;
    398  1.1  christos {
    399  1.1  christos 	CHAR_T *p;
    400  1.1  christos 	WIN *wp;
    401  1.1  christos 	size_t length;
    402  1.1  christos 	size_t len;
    403  1.1  christos 	db_recno_t i;
    404  1.1  christos 	CHAR_T *str;
    405  1.1  christos 	char *estr;
    406  1.1  christos 	SV* cv;
    407  1.1  christos 	char *command;
    408  1.1  christos 	perl_data_t *pp;
    409  1.1  christos 	char *np;
    410  1.1  christos 	size_t nlen;
    411  1.1  christos 
    412  1.1  christos 	/* Initialize the interpreter. */
    413  1.1  christos 	if (scrp->wp->perl_private == NULL && perl_init(scrp))
    414  1.1  christos 			return (1);
    415  1.1  christos 	pp = scrp->wp->perl_private;
    416  1.1  christos     {
    417  1.1  christos 	dTHXs
    418  1.1  christos 	dSP;
    419  1.1  christos 
    420  1.1  christos 	newVIrv(pp->svcurscr, scrp);
    421  1.1  christos 	/* Backwards compatibility. */
    422  1.1  christos 	newVIrv(pp->svid, scrp);
    423  1.1  christos 
    424  1.1  christos 	INT2CHAR(scrp, cmdp, STRLEN(cmdp)+1, np, nlen);
    425  1.1  christos 	if (!(command = malloc(length = nlen - 1 + sizeof("sub {}"))))
    426  1.1  christos 		return 1;
    427  1.1  christos 	snprintf(command, length, "sub {%s}", np);
    428  1.1  christos 
    429  1.1  christos 	ENTER;
    430  1.1  christos 	SAVETMPS;
    431  1.1  christos 
    432  1.1  christos 	cv = perl_eval_pv(command, FALSE);
    433  1.1  christos 	free (command);
    434  1.1  christos 
    435  1.1  christos 	estr = SvPV(ERRSV,length);
    436  1.1  christos 	if (length)
    437  1.1  christos 		goto err;
    438  1.1  christos 
    439  1.1  christos 	for (i = f_lno; i <= t_lno && !api_gline(scrp, i, &str, &len); i++) {
    440  1.1  christos 		INT2CHAR(scrp, str, len, np, nlen);
    441  1.1  christos 		sv_setpvn(DEFSV,np,nlen);
    442  1.1  christos 		sv_setiv(pp->svstart, i);
    443  1.1  christos 		sv_setiv(pp->svstop, i);
    444  1.1  christos 		PUSHMARK(sp);
    445  1.1  christos                 perl_call_sv(cv, G_SCALAR | G_EVAL);
    446  1.1  christos 		estr = SvPV(ERRSV, length);
    447  1.1  christos 		if (length) break;
    448  1.1  christos 		SPAGAIN;
    449  1.1  christos 		if(SvTRUEx(POPs))
    450  1.1  christos 			i = replace_line(scrp, i, &t_lno, DEFSV);
    451  1.1  christos 		PUTBACK;
    452  1.1  christos 	}
    453  1.1  christos 	FREETMPS;
    454  1.1  christos 	LEAVE;
    455  1.1  christos 
    456  1.1  christos 	SvREFCNT_dec(SvRV(pp->svcurscr));
    457  1.1  christos 	SvROK_off(pp->svcurscr);
    458  1.1  christos 	SvREFCNT_dec(SvRV(pp->svid));
    459  1.1  christos 	SvROK_off(pp->svid);
    460  1.1  christos 
    461  1.1  christos 	if (!length)
    462  1.1  christos 		return (0);
    463  1.1  christos 
    464  1.1  christos err:	estr[length - 1] = '\0';
    465  1.1  christos 	msgq(scrp, M_ERR, "perl: %s", estr);
    466  1.1  christos 	return (1);
    467  1.1  christos     }
    468  1.1  christos }
    469  1.1  christos 
    470  1.1  christos /*
    471  1.1  christos  * msghandler --
    472  1.1  christos  *	Perl message routine so that error messages are processed in
    473  1.1  christos  *	Perl, not in nvi.
    474  1.1  christos  */
    475  1.1  christos static void
    476  1.1  christos msghandler(sp, mtype, msg, len)
    477  1.1  christos 	SCR *sp;
    478  1.1  christos 	mtype_t mtype;
    479  1.1  christos 	char *msg;
    480  1.1  christos 	size_t len;
    481  1.1  christos {
    482  1.1  christos 	char 	*errmsg;
    483  1.1  christos 
    484  1.1  christos 	errmsg = PERLP(sp)->errmsg;
    485  1.1  christos 
    486  1.1  christos 	/* Replace the trailing <newline> with an EOS. */
    487  1.1  christos 	/* Let's do that later instead */
    488  1.1  christos 	if (errmsg) free (errmsg);
    489  1.1  christos 	errmsg = malloc(len + 1);
    490  1.1  christos 	memcpy(errmsg, msg, len);
    491  1.1  christos 	errmsg[len] = '\0';
    492  1.1  christos 	PERLP(sp)->errmsg = errmsg;
    493  1.1  christos }
    494  1.1  christos 
    495  1.1  christos 
    496  1.1  christos typedef SCR *	VI;
    497  1.1  christos typedef SCR *	VI__OPT;
    498  1.1  christos typedef SCR *	VI__MAP;
    499  1.1  christos typedef SCR * 	VI__MARK;
    500  1.1  christos typedef SCR * 	VI__LINE;
    501  1.1  christos typedef AV *	AVREF;
    502  1.1  christos 
    503  1.1  christos typedef struct {
    504  1.1  christos     SV      *sprv;
    505  1.1  christos     TAGQ    *tqp;
    506  1.1  christos } perl_tagq;
    507  1.1  christos 
    508  1.1  christos typedef perl_tagq *  VI__TAGQ;
    509  1.1  christos typedef perl_tagq *  VI__TAGQ2;
    510  1.1  christos 
    511  1.1  christos MODULE = VI	PACKAGE = VI
    512  1.1  christos 
    513  1.1  christos # msg --
    514  1.1  christos #	Set the message line to text.
    515  1.1  christos #
    516  1.1  christos # Perl Command: VI::Msg
    517  1.1  christos # Usage: VI::Msg screenId text
    518  1.1  christos 
    519  1.1  christos void
    520  1.1  christos Msg(screen, text)
    521  1.1  christos 	VI          screen
    522  1.1  christos 	char *      text
    523  1.1  christos 
    524  1.1  christos 	ALIAS:
    525  1.1  christos 	PRINT = 1
    526  1.1  christos 
    527  1.1  christos 	CODE:
    528  1.1  christos 	api_imessage(screen, text);
    529  1.1  christos 
    530  1.1  christos # XS_VI_escreen --
    531  1.1  christos #	End a screen.
    532  1.1  christos #
    533  1.1  christos # Perl Command: VI::EndScreen
    534  1.1  christos # Usage: VI::EndScreen screenId
    535  1.1  christos 
    536  1.1  christos void
    537  1.1  christos EndScreen(screen)
    538  1.1  christos 	VI	screen
    539  1.1  christos 
    540  1.1  christos 	PREINIT:
    541  1.1  christos 	void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
    542  1.1  christos 	int rval;
    543  1.1  christos 
    544  1.1  christos 	CODE:
    545  1.1  christos 	INITMESSAGE(screen);
    546  1.1  christos 	rval = api_escreen(screen);
    547  1.1  christos 	ENDMESSAGE(screen);
    548  1.1  christos 
    549  1.1  christos # XS_VI_iscreen --
    550  1.1  christos #	Create a new screen.  If a filename is specified then the screen
    551  1.1  christos #	is opened with that file.
    552  1.1  christos #
    553  1.1  christos # Perl Command: VI::NewScreen
    554  1.1  christos # Usage: VI::NewScreen screenId [file]
    555  1.1  christos 
    556  1.1  christos VI
    557  1.1  christos Edit(screen, ...)
    558  1.1  christos 	VI screen
    559  1.1  christos 
    560  1.1  christos 	ALIAS:
    561  1.1  christos 	NewScreen = 1
    562  1.1  christos 
    563  1.1  christos 	PROTOTYPE: $;$
    564  1.1  christos 	PREINIT:
    565  1.1  christos 	void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
    566  1.1  christos 	int rval;
    567  1.1  christos 	char *file;
    568  1.1  christos 	SCR *nsp;
    569  1.1  christos 
    570  1.1  christos 	CODE:
    571  1.1  christos 	file = (items == 1) ? NULL : (char *)SvPV(ST(1),PL_na);
    572  1.1  christos 	INITMESSAGE(screen);
    573  1.1  christos 	rval = api_edit(screen, file, &nsp, ix);
    574  1.1  christos 	ENDMESSAGE(screen);
    575  1.1  christos 
    576  1.1  christos 	RETVAL = ix ? nsp : screen;
    577  1.1  christos 
    578  1.1  christos 	OUTPUT:
    579  1.1  christos 	RETVAL
    580  1.1  christos 
    581  1.1  christos # XS_VI_fscreen --
    582  1.1  christos #	Return the screen id associated with file name.
    583  1.1  christos #
    584  1.1  christos # Perl Command: VI::FindScreen
    585  1.1  christos # Usage: VI::FindScreen file
    586  1.1  christos 
    587  1.1  christos VI
    588  1.1  christos FindScreen(file)
    589  1.1  christos 	char *file
    590  1.1  christos 
    591  1.1  christos 	PREINIT:
    592  1.1  christos 	SCR *fsp;
    593  1.1  christos 	CODE:
    594  1.1  christos 	RETVAL = api_fscreen(0, file);
    595  1.1  christos 
    596  1.1  christos 	OUTPUT:
    597  1.1  christos 	RETVAL
    598  1.1  christos 
    599  1.1  christos # XS_VI_GetFileName --
    600  1.1  christos #	Return the file name of the screen
    601  1.1  christos #
    602  1.1  christos # Perl Command: VI::GetFileName
    603  1.1  christos # Usage: VI::GetFileName screenId
    604  1.1  christos 
    605  1.1  christos char *
    606  1.1  christos GetFileName(screen)
    607  1.1  christos 	VI screen;
    608  1.1  christos 
    609  1.1  christos 	PPCODE:
    610  1.1  christos 	EXTEND(sp,1);
    611  1.1  christos 	PUSHs(sv_2mortal(newSVpv(screen->frp->name, 0)));
    612  1.1  christos 
    613  1.1  christos # XS_VI_aline --
    614  1.1  christos #	-- Append the string text after the line in lineNumber.
    615  1.1  christos #
    616  1.1  christos # Perl Command: VI::AppendLine
    617  1.1  christos # Usage: VI::AppendLine screenId lineNumber text
    618  1.1  christos 
    619  1.1  christos void
    620  1.1  christos AppendLine(screen, linenumber, text)
    621  1.1  christos 	VI screen
    622  1.1  christos 	int linenumber
    623  1.1  christos 	char *text
    624  1.1  christos 
    625  1.1  christos 	PREINIT:
    626  1.1  christos 	void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
    627  1.1  christos 	int rval;
    628  1.1  christos 	size_t length;
    629  1.1  christos 
    630  1.1  christos 	CODE:
    631  1.1  christos 	SvPV(ST(2), length);
    632  1.1  christos 	INITMESSAGE(screen);
    633  1.1  christos 	rval = api_aline(screen, linenumber, text, length);
    634  1.1  christos 	ENDMESSAGE(screen);
    635  1.1  christos 
    636  1.1  christos # XS_VI_dline --
    637  1.1  christos #	Delete lineNum.
    638  1.1  christos #
    639  1.1  christos # Perl Command: VI::DelLine
    640  1.1  christos # Usage: VI::DelLine screenId lineNum
    641  1.1  christos 
    642  1.1  christos void
    643  1.1  christos DelLine(screen, linenumber)
    644  1.1  christos 	VI screen
    645  1.1  christos 	int linenumber
    646  1.1  christos 
    647  1.1  christos 	PREINIT:
    648  1.1  christos 	void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
    649  1.1  christos 	int rval;
    650  1.1  christos 
    651  1.1  christos 	CODE:
    652  1.1  christos 	INITMESSAGE(screen);
    653  1.1  christos 	rval = api_dline(screen, (db_recno_t)linenumber);
    654  1.1  christos 	ENDMESSAGE(screen);
    655  1.1  christos 
    656  1.1  christos # XS_VI_gline --
    657  1.1  christos #	Return lineNumber.
    658  1.1  christos #
    659  1.1  christos # Perl Command: VI::GetLine
    660  1.1  christos # Usage: VI::GetLine screenId lineNumber
    661  1.1  christos 
    662  1.1  christos char *
    663  1.1  christos GetLine(screen, linenumber)
    664  1.1  christos 	VI screen
    665  1.1  christos 	int linenumber
    666  1.1  christos 
    667  1.1  christos 	PREINIT:
    668  1.1  christos 	size_t len;
    669  1.1  christos 	void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
    670  1.1  christos 	int rval;
    671  1.1  christos 	char *line;
    672  1.1  christos 	CHAR_T *p;
    673  1.1  christos 
    674  1.1  christos 	PPCODE:
    675  1.1  christos 	INITMESSAGE(screen);
    676  1.1  christos 	rval = api_gline(screen, (db_recno_t)linenumber, &p, &len);
    677  1.1  christos 	ENDMESSAGE(screen);
    678  1.1  christos 
    679  1.1  christos 	EXTEND(sp,1);
    680  1.1  christos         PUSHs(sv_2mortal(newSVpv(len ? (char *)p : "", len)));
    681  1.1  christos 
    682  1.1  christos # XS_VI_sline --
    683  1.1  christos #	Set lineNumber to the text supplied.
    684  1.1  christos #
    685  1.1  christos # Perl Command: VI::SetLine
    686  1.1  christos # Usage: VI::SetLine screenId lineNumber text
    687  1.1  christos 
    688  1.1  christos void
    689  1.1  christos SetLine(screen, linenumber, text)
    690  1.1  christos 	VI screen
    691  1.1  christos 	int linenumber
    692  1.1  christos 	char *text
    693  1.1  christos 
    694  1.1  christos 	PREINIT:
    695  1.1  christos 	void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
    696  1.1  christos 	int rval;
    697  1.1  christos 	size_t length;
    698  1.1  christos 	size_t len;
    699  1.1  christos 	CHAR_T *line;
    700  1.1  christos 
    701  1.1  christos 	CODE:
    702  1.1  christos 	SvPV(ST(2), length);
    703  1.1  christos 	INITMESSAGE(screen);
    704  1.1  christos 	CHAR2INTP(screen, text, length, line, len);
    705  1.1  christos 	rval = api_sline(screen, linenumber, line, len);
    706  1.1  christos 	ENDMESSAGE(screen);
    707  1.1  christos 
    708  1.1  christos # XS_VI_iline --
    709  1.1  christos #	Insert the string text before the line in lineNumber.
    710  1.1  christos #
    711  1.1  christos # Perl Command: VI::InsertLine
    712  1.1  christos # Usage: VI::InsertLine screenId lineNumber text
    713  1.1  christos 
    714  1.1  christos void
    715  1.1  christos InsertLine(screen, linenumber, text)
    716  1.1  christos 	VI screen
    717  1.1  christos 	int linenumber
    718  1.1  christos 	char *text
    719  1.1  christos 
    720  1.1  christos 	PREINIT:
    721  1.1  christos 	void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
    722  1.1  christos 	int rval;
    723  1.1  christos 	size_t length;
    724  1.1  christos 	size_t len;
    725  1.1  christos 	CHAR_T *line;
    726  1.1  christos 
    727  1.1  christos 	CODE:
    728  1.1  christos 	SvPV(ST(2), length);
    729  1.1  christos 	INITMESSAGE(screen);
    730  1.1  christos 	CHAR2INTP(screen, text, length, line, len);
    731  1.1  christos 	rval = api_iline(screen, linenumber, line, len);
    732  1.1  christos 	ENDMESSAGE(screen);
    733  1.1  christos 
    734  1.1  christos # XS_VI_lline --
    735  1.1  christos #	Return the last line in the screen.
    736  1.1  christos #
    737  1.1  christos # Perl Command: VI::LastLine
    738  1.1  christos # Usage: VI::LastLine screenId
    739  1.1  christos 
    740  1.1  christos int
    741  1.1  christos LastLine(screen)
    742  1.1  christos 	VI screen
    743  1.1  christos 
    744  1.1  christos 	PREINIT:
    745  1.1  christos 	db_recno_t last;
    746  1.1  christos 	void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
    747  1.1  christos 	int rval;
    748  1.1  christos 
    749  1.1  christos 	CODE:
    750  1.1  christos 	INITMESSAGE(screen);
    751  1.1  christos 	rval = api_lline(screen, &last);
    752  1.1  christos 	ENDMESSAGE(screen);
    753  1.1  christos 	RETVAL=last;
    754  1.1  christos 
    755  1.1  christos 	OUTPUT:
    756  1.1  christos 	RETVAL
    757  1.1  christos 
    758  1.1  christos # XS_VI_getmark --
    759  1.1  christos #	Return the mark's cursor position as a list with two elements.
    760  1.1  christos #	{line, column}.
    761  1.1  christos #
    762  1.1  christos # Perl Command: VI::GetMark
    763  1.1  christos # Usage: VI::GetMark screenId mark
    764  1.1  christos 
    765  1.1  christos void
    766  1.1  christos GetMark(screen, mark)
    767  1.1  christos 	VI screen
    768  1.1  christos 	char mark
    769  1.1  christos 
    770  1.1  christos 	PREINIT:
    771  1.1  christos 	struct _mark cursor;
    772  1.1  christos 	void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
    773  1.1  christos 	int rval;
    774  1.1  christos 
    775  1.1  christos 	PPCODE:
    776  1.1  christos 	INITMESSAGE(screen);
    777  1.1  christos 	rval = api_getmark(screen, (int)mark, &cursor);
    778  1.1  christos 	ENDMESSAGE(screen);
    779  1.1  christos 
    780  1.1  christos 	EXTEND(sp,2);
    781  1.1  christos         PUSHs(sv_2mortal(newSViv(cursor.lno)));
    782  1.1  christos         PUSHs(sv_2mortal(newSViv(cursor.cno)));
    783  1.1  christos 
    784  1.1  christos # XS_VI_setmark --
    785  1.1  christos #	Set the mark to the line and column numbers supplied.
    786  1.1  christos #
    787  1.1  christos # Perl Command: VI::SetMark
    788  1.1  christos # Usage: VI::SetMark screenId mark line column
    789  1.1  christos 
    790  1.1  christos void
    791  1.1  christos SetMark(screen, mark, line, column)
    792  1.1  christos 	VI screen
    793  1.1  christos 	char mark
    794  1.1  christos 	int line
    795  1.1  christos 	int column
    796  1.1  christos 
    797  1.1  christos 	PREINIT:
    798  1.1  christos 	struct _mark cursor;
    799  1.1  christos 	void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
    800  1.1  christos 	int rval;
    801  1.1  christos 
    802  1.1  christos 	CODE:
    803  1.1  christos 	INITMESSAGE(screen);
    804  1.1  christos 	cursor.lno = line;
    805  1.1  christos 	cursor.cno = column;
    806  1.1  christos 	rval = api_setmark(screen, (int)mark, &cursor);
    807  1.1  christos 	ENDMESSAGE(screen);
    808  1.1  christos 
    809  1.1  christos # XS_VI_getcursor --
    810  1.1  christos #	Return the current cursor position as a list with two elements.
    811  1.1  christos #	{line, column}.
    812  1.1  christos #
    813  1.1  christos # Perl Command: VI::GetCursor
    814  1.1  christos # Usage: VI::GetCursor screenId
    815  1.1  christos 
    816  1.1  christos void
    817  1.1  christos GetCursor(screen)
    818  1.1  christos 	VI screen
    819  1.1  christos 
    820  1.1  christos 	PREINIT:
    821  1.1  christos 	struct _mark cursor;
    822  1.1  christos 	void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
    823  1.1  christos 	int rval;
    824  1.1  christos 
    825  1.1  christos 	PPCODE:
    826  1.1  christos 	INITMESSAGE(screen);
    827  1.1  christos 	rval = api_getcursor(screen, &cursor);
    828  1.1  christos 	ENDMESSAGE(screen);
    829  1.1  christos 
    830  1.1  christos 	EXTEND(sp,2);
    831  1.1  christos         PUSHs(sv_2mortal(newSViv(cursor.lno)));
    832  1.1  christos         PUSHs(sv_2mortal(newSViv(cursor.cno)));
    833  1.1  christos 
    834  1.1  christos # XS_VI_setcursor --
    835  1.1  christos #	Set the cursor to the line and column numbers supplied.
    836  1.1  christos #
    837  1.1  christos # Perl Command: VI::SetCursor
    838  1.1  christos # Usage: VI::SetCursor screenId line column
    839  1.1  christos 
    840  1.1  christos void
    841  1.1  christos SetCursor(screen, line, column)
    842  1.1  christos 	VI screen
    843  1.1  christos 	int line
    844  1.1  christos 	int column
    845  1.1  christos 
    846  1.1  christos 	PREINIT:
    847  1.1  christos 	struct _mark cursor;
    848  1.1  christos 	void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
    849  1.1  christos 	int rval;
    850  1.1  christos 
    851  1.1  christos 	CODE:
    852  1.1  christos 	INITMESSAGE(screen);
    853  1.1  christos 	cursor.lno = line;
    854  1.1  christos 	cursor.cno = column;
    855  1.1  christos 	rval = api_setcursor(screen, &cursor);
    856  1.1  christos 	ENDMESSAGE(screen);
    857  1.1  christos 
    858  1.1  christos # XS_VI_swscreen --
    859  1.1  christos #	Change the current focus to screen.
    860  1.1  christos #
    861  1.1  christos # Perl Command: VI::SwitchScreen
    862  1.1  christos # Usage: VI::SwitchScreen screenId screenId
    863  1.1  christos 
    864  1.1  christos void
    865  1.1  christos SwitchScreen(screenFrom, screenTo)
    866  1.1  christos 	VI screenFrom
    867  1.1  christos 	VI screenTo
    868  1.1  christos 
    869  1.1  christos 	PREINIT:
    870  1.1  christos 	void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
    871  1.1  christos 	int rval;
    872  1.1  christos 
    873  1.1  christos 	CODE:
    874  1.1  christos 	INITMESSAGE(screenFrom);
    875  1.1  christos 	rval = api_swscreen(screenFrom, screenTo);
    876  1.1  christos 	ENDMESSAGE(screenFrom);
    877  1.1  christos 
    878  1.1  christos # XS_VI_map --
    879  1.1  christos #	Associate a key with a perl procedure.
    880  1.1  christos #
    881  1.1  christos # Perl Command: VI::MapKey
    882  1.1  christos # Usage: VI::MapKey screenId key perlproc
    883  1.1  christos 
    884  1.1  christos void
    885  1.1  christos MapKey(screen, key, commandsv)
    886  1.1  christos 	VI screen
    887  1.1  christos 	char *key
    888  1.1  christos 	SV *commandsv
    889  1.1  christos 
    890  1.1  christos 	PREINIT:
    891  1.1  christos 	void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
    892  1.1  christos 	int rval;
    893  1.1  christos 	int length;
    894  1.1  christos 	char *command;
    895  1.1  christos 
    896  1.1  christos 	CODE:
    897  1.1  christos 	INITMESSAGE(screen);
    898  1.1  christos 	command = SvPV(commandsv, length);
    899  1.1  christos 	rval = api_map(screen, key, command, length);
    900  1.1  christos 	ENDMESSAGE(screen);
    901  1.1  christos 
    902  1.1  christos # XS_VI_unmap --
    903  1.1  christos #	Unmap a key.
    904  1.1  christos #
    905  1.1  christos # Perl Command: VI::UnmapKey
    906  1.1  christos # Usage: VI::UnmmapKey screenId key
    907  1.1  christos 
    908  1.1  christos void
    909  1.1  christos UnmapKey(screen, key)
    910  1.1  christos 	VI screen
    911  1.1  christos 	char *key
    912  1.1  christos 
    913  1.1  christos 	PREINIT:
    914  1.1  christos 	void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
    915  1.1  christos 	int rval;
    916  1.1  christos 
    917  1.1  christos 	CODE:
    918  1.1  christos 	INITMESSAGE(screen);
    919  1.1  christos 	rval = api_unmap(screen, key);
    920  1.1  christos 	ENDMESSAGE(screen);
    921  1.1  christos 
    922  1.1  christos # XS_VI_opts_set --
    923  1.1  christos #	Set an option.
    924  1.1  christos #
    925  1.1  christos # Perl Command: VI::SetOpt
    926  1.1  christos # Usage: VI::SetOpt screenId setting
    927  1.1  christos 
    928  1.1  christos void
    929  1.1  christos SetOpt(screen, setting)
    930  1.1  christos 	VI screen
    931  1.1  christos 	char *setting
    932  1.1  christos 
    933  1.1  christos 	PREINIT:
    934  1.1  christos 	void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
    935  1.1  christos 	int rval;
    936  1.1  christos 	SV *svc;
    937  1.1  christos 
    938  1.1  christos 	CODE:
    939  1.1  christos 	INITMESSAGE(screen);
    940  1.1  christos 	svc = sv_2mortal(newSVpv(":set ", 5));
    941  1.1  christos 	sv_catpv(svc, setting);
    942  1.1  christos 	rval = api_run_str(screen, SvPV(svc, PL_na));
    943  1.1  christos 	ENDMESSAGE(screen);
    944  1.1  christos 
    945  1.1  christos # XS_VI_opts_get --
    946  1.1  christos #	Return the value of an option.
    947  1.1  christos #
    948  1.1  christos # Perl Command: VI::GetOpt
    949  1.1  christos # Usage: VI::GetOpt screenId option
    950  1.1  christos 
    951  1.1  christos void
    952  1.1  christos GetOpt(screen, option)
    953  1.1  christos 	VI screen
    954  1.1  christos 	char *option
    955  1.1  christos 
    956  1.1  christos 	PREINIT:
    957  1.1  christos 	void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
    958  1.1  christos 	int rval;
    959  1.1  christos 	char *value;
    960  1.1  christos 	CHAR_T *wp;
    961  1.1  christos 	size_t wlen;
    962  1.1  christos 
    963  1.1  christos 	PPCODE:
    964  1.1  christos 	INITMESSAGE(screen);
    965  1.1  christos 	CHAR2INTP(screen, option, strlen(option)+1, wp, wlen);
    966  1.1  christos 	rval = api_opts_get(screen, wp, &value, NULL);
    967  1.1  christos 	ENDMESSAGE(screen);
    968  1.1  christos 
    969  1.1  christos 	EXTEND(SP,1);
    970  1.1  christos 	PUSHs(sv_2mortal(newSVpv(value, 0)));
    971  1.1  christos 	free(value);
    972  1.1  christos 
    973  1.1  christos # XS_VI_run --
    974  1.1  christos #	Run the ex command cmd.
    975  1.1  christos #
    976  1.1  christos # Perl Command: VI::Run
    977  1.1  christos # Usage: VI::Run screenId cmd
    978  1.1  christos 
    979  1.1  christos void
    980  1.1  christos Run(screen, command)
    981  1.1  christos 	VI screen
    982  1.1  christos 	char *command;
    983  1.1  christos 
    984  1.1  christos 	PREINIT:
    985  1.1  christos 	void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
    986  1.1  christos 	int rval;
    987  1.1  christos 
    988  1.1  christos 	CODE:
    989  1.1  christos 	INITMESSAGE(screen);
    990  1.1  christos 	rval = api_run_str(screen, command);
    991  1.1  christos 	ENDMESSAGE(screen);
    992  1.1  christos 
    993  1.1  christos void
    994  1.1  christos DESTROY(screensv)
    995  1.1  christos 	SV* screensv
    996  1.1  christos 
    997  1.1  christos 	PREINIT:
    998  1.1  christos 	VI  screen;
    999  1.1  christos 
   1000  1.1  christos 	CODE:
   1001  1.1  christos 	if (sv_isa(screensv, "VI")) {
   1002  1.1  christos 		IV tmp = SvIV((SV*)SvRV(screensv));
   1003  1.1  christos 		screen = (SCR *) tmp;
   1004  1.1  christos 	}
   1005  1.1  christos 	else
   1006  1.1  christos 		croak("screen is not of type VI");
   1007  1.1  christos 
   1008  1.1  christos 	if (screen)
   1009  1.1  christos 	screen->perl_private = 0;
   1010  1.1  christos 
   1011  1.1  christos void
   1012  1.1  christos Warn(warning)
   1013  1.1  christos 	char *warning;
   1014  1.1  christos 
   1015  1.1  christos 	CODE:
   1016  1.1  christos 	sv_catpv(ERRSV,warning);
   1017  1.1  christos 
   1018  1.1  christos #define TIED(kind,package) \
   1019  1.1  christos 	sv_magic((SV *) (var = \
   1020  1.1  christos 	    (kind##V *)sv_2mortal((SV *)new##kind##V())), \
   1021  1.1  christos 		sv_setref_pv(sv_newmortal(), package, \
   1022  1.1  christos 			newVIrv(newSV(0), screen)),\
   1023  1.1  christos 		'P', Nullch, 0);\
   1024  1.1  christos 	RETVAL = newRV((SV *)var)
   1025  1.1  christos 
   1026  1.1  christos SV *
   1027  1.1  christos Opt(screen)
   1028  1.1  christos 	VI screen;
   1029  1.1  christos 	PREINIT:
   1030  1.1  christos 	HV *var;
   1031  1.1  christos 	CODE:
   1032  1.1  christos 	TIED(H,"VI::OPT");
   1033  1.1  christos 	OUTPUT:
   1034  1.1  christos 	RETVAL
   1035  1.1  christos 
   1036  1.1  christos SV *
   1037  1.1  christos Map(screen)
   1038  1.1  christos 	VI screen;
   1039  1.1  christos 	PREINIT:
   1040  1.1  christos 	HV *var;
   1041  1.1  christos 	CODE:
   1042  1.1  christos 	TIED(H,"VI::MAP");
   1043  1.1  christos 	OUTPUT:
   1044  1.1  christos 	RETVAL
   1045  1.1  christos 
   1046  1.1  christos SV *
   1047  1.1  christos Mark(screen)
   1048  1.1  christos 	VI screen
   1049  1.1  christos 	PREINIT:
   1050  1.1  christos 	HV *var;
   1051  1.1  christos 	CODE:
   1052  1.1  christos 	TIED(H,"VI::MARK");
   1053  1.1  christos 	OUTPUT:
   1054  1.1  christos 	RETVAL
   1055  1.1  christos 
   1056  1.1  christos SV *
   1057  1.1  christos Line(screen)
   1058  1.1  christos 	VI screen
   1059  1.1  christos 	PREINIT:
   1060  1.1  christos 	AV *var;
   1061  1.1  christos 	CODE:
   1062  1.1  christos 	TIED(A,"VI::LINE");
   1063  1.1  christos 	OUTPUT:
   1064  1.1  christos 	RETVAL
   1065  1.1  christos 
   1066  1.1  christos SV *
   1067  1.1  christos TagQ(screen, tag)
   1068  1.1  christos 	VI screen
   1069  1.1  christos 	char *tag;
   1070  1.1  christos 
   1071  1.1  christos 	PREINIT:
   1072  1.1  christos 	perl_tagq *ptag;
   1073  1.1  christos 
   1074  1.1  christos 	PPCODE:
   1075  1.1  christos 	if ((ptag = malloc(sizeof(perl_tagq))) == NULL)
   1076  1.1  christos 		goto err;
   1077  1.1  christos 
   1078  1.1  christos 	ptag->sprv = newVIrv(newSV(0), screen);
   1079  1.1  christos 	ptag->tqp = api_tagq_new(screen, tag);
   1080  1.1  christos 	if (ptag->tqp != NULL) {
   1081  1.1  christos 		EXTEND(SP,1);
   1082  1.1  christos 		PUSHs(sv_2mortal(sv_setref_pv(newSV(0), "VI::TAGQ", ptag)));
   1083  1.1  christos 	} else {
   1084  1.1  christos err:
   1085  1.1  christos 		ST(0) = &PL_sv_undef;
   1086  1.1  christos 		return;
   1087  1.1  christos 	}
   1088  1.1  christos 
   1089  1.1  christos MODULE = VI	PACKAGE = VI::OPT
   1090  1.1  christos 
   1091  1.1  christos void
   1092  1.1  christos DESTROY(screen)
   1093  1.1  christos 	VI::OPT screen
   1094  1.1  christos 
   1095  1.1  christos 	CODE:
   1096  1.1  christos 	# typemap did all the checking
   1097  1.1  christos 	SvREFCNT_dec((SV*)SvIV((SV*)SvRV(ST(0))));
   1098  1.1  christos 
   1099  1.1  christos void
   1100  1.1  christos FETCH(screen, key)
   1101  1.1  christos 	VI::OPT screen
   1102  1.1  christos 	char *key
   1103  1.1  christos 
   1104  1.1  christos 	PREINIT:
   1105  1.1  christos 	void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
   1106  1.1  christos 	int rval;
   1107  1.1  christos 	char *value;
   1108  1.1  christos 	int boolvalue;
   1109  1.1  christos 	CHAR_T *wp;
   1110  1.1  christos 	size_t wlen;
   1111  1.1  christos 
   1112  1.1  christos 	PPCODE:
   1113  1.1  christos 	INITMESSAGE(screen);
   1114  1.1  christos 	CHAR2INTP(screen, key, strlen(key)+1, wp, wlen);
   1115  1.1  christos 	rval = api_opts_get(screen, wp, &value, &boolvalue);
   1116  1.1  christos 	if (!rval) {
   1117  1.1  christos 		EXTEND(SP,1);
   1118  1.1  christos 		PUSHs(sv_2mortal((boolvalue == -1) ? newSVpv(value, 0)
   1119  1.1  christos 						   : newSViv(boolvalue)));
   1120  1.1  christos 		free(value);
   1121  1.1  christos 	} else ST(0) = &PL_sv_undef;
   1122  1.1  christos 	rval = 0;
   1123  1.1  christos 	ENDMESSAGE(screen);
   1124  1.1  christos 
   1125  1.1  christos void
   1126  1.1  christos STORE(screen, key, value)
   1127  1.1  christos 	VI::OPT	screen
   1128  1.1  christos 	char	*key
   1129  1.1  christos 	SV	*value
   1130  1.1  christos 
   1131  1.1  christos 	PREINIT:
   1132  1.1  christos 	void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
   1133  1.1  christos 	int rval;
   1134  1.1  christos 	CHAR_T *wp;
   1135  1.1  christos 	size_t wlen;
   1136  1.1  christos 
   1137  1.1  christos 	CODE:
   1138  1.1  christos 	INITMESSAGE(screen);
   1139  1.1  christos 	CHAR2INTP(screen, key, strlen(key)+1, wp, wlen);
   1140  1.1  christos 	rval = api_opts_set(screen, wp, SvPV(value, PL_na), SvIV(value),
   1141  1.1  christos                                          SvTRUEx(value));
   1142  1.1  christos 	ENDMESSAGE(screen);
   1143  1.1  christos 
   1144  1.1  christos MODULE = VI	PACKAGE = VI::MAP
   1145  1.1  christos 
   1146  1.1  christos void
   1147  1.1  christos DESTROY(screen)
   1148  1.1  christos 	VI::MAP screen
   1149  1.1  christos 
   1150  1.1  christos 	CODE:
   1151  1.1  christos 	# typemap did all the checking
   1152  1.1  christos 	SvREFCNT_dec((SV*)SvIV((SV*)SvRV(ST(0))));
   1153  1.1  christos 
   1154  1.1  christos void
   1155  1.1  christos STORE(screen, key, commandsv)
   1156  1.1  christos 	VI::MAP screen
   1157  1.1  christos 	char *key
   1158  1.1  christos 	SV *commandsv
   1159  1.1  christos 
   1160  1.1  christos 	PREINIT:
   1161  1.1  christos 	void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
   1162  1.1  christos 	int rval;
   1163  1.1  christos 	int length;
   1164  1.1  christos 	char *command;
   1165  1.1  christos 
   1166  1.1  christos 	CODE:
   1167  1.1  christos 	INITMESSAGE(screen);
   1168  1.1  christos 	command = SvPV(commandsv, length);
   1169  1.1  christos 	rval = api_map(screen, key, command, length);
   1170  1.1  christos 	ENDMESSAGE(screen);
   1171  1.1  christos 
   1172  1.1  christos void
   1173  1.1  christos DELETE(screen, key)
   1174  1.1  christos 	VI::MAP screen
   1175  1.1  christos 	char *key
   1176  1.1  christos 
   1177  1.1  christos 	PREINIT:
   1178  1.1  christos 	void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
   1179  1.1  christos 	int rval;
   1180  1.1  christos 
   1181  1.1  christos 	CODE:
   1182  1.1  christos 	INITMESSAGE(screen);
   1183  1.1  christos 	rval = api_unmap(screen, key);
   1184  1.1  christos 	ENDMESSAGE(screen);
   1185  1.1  christos 
   1186  1.1  christos MODULE = VI	PACKAGE = VI::MARK
   1187  1.1  christos 
   1188  1.1  christos void
   1189  1.1  christos DESTROY(screen)
   1190  1.1  christos 	VI::MARK screen
   1191  1.1  christos 
   1192  1.1  christos 	CODE:
   1193  1.1  christos 	# typemap did all the checking
   1194  1.1  christos 	SvREFCNT_dec((SV*)SvIV((SV*)SvRV(ST(0))));
   1195  1.1  christos 
   1196  1.1  christos int
   1197  1.1  christos EXISTS(screen, mark)
   1198  1.1  christos 	VI::MARK screen
   1199  1.1  christos 	char mark
   1200  1.1  christos 
   1201  1.1  christos 	PREINIT:
   1202  1.1  christos 	struct _mark cursor;
   1203  1.1  christos 	void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
   1204  1.1  christos 	int rval = 0; /* never croak */
   1205  1.1  christos 	int missing;
   1206  1.1  christos 
   1207  1.1  christos 	CODE:
   1208  1.1  christos 	INITMESSAGE(screen);
   1209  1.1  christos 	missing = api_getmark(screen, (int)mark, &cursor);
   1210  1.1  christos 	ENDMESSAGE(screen);
   1211  1.1  christos 	RETVAL = !missing;
   1212  1.1  christos 
   1213  1.1  christos 	OUTPUT:
   1214  1.1  christos 	RETVAL
   1215  1.1  christos 
   1216  1.1  christos AV *
   1217  1.1  christos FETCH(screen, mark)
   1218  1.1  christos 	VI::MARK screen
   1219  1.1  christos 	char mark
   1220  1.1  christos 
   1221  1.1  christos 	PREINIT:
   1222  1.1  christos 	struct _mark cursor;
   1223  1.1  christos 	void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
   1224  1.1  christos 	int rval;
   1225  1.1  christos 
   1226  1.1  christos 	CODE:
   1227  1.1  christos 	INITMESSAGE(screen);
   1228  1.1  christos 	rval = api_getmark(screen, (int)mark, &cursor);
   1229  1.1  christos 	ENDMESSAGE(screen);
   1230  1.1  christos 	RETVAL = newAV();
   1231  1.1  christos 	av_push(RETVAL, newSViv(cursor.lno));
   1232  1.1  christos 	av_push(RETVAL, newSViv(cursor.cno));
   1233  1.1  christos 
   1234  1.1  christos 	OUTPUT:
   1235  1.1  christos 	RETVAL
   1236  1.1  christos 
   1237  1.1  christos void
   1238  1.1  christos STORE(screen, mark, pos)
   1239  1.1  christos 	VI::MARK screen
   1240  1.1  christos 	char mark
   1241  1.1  christos 	AVREF pos
   1242  1.1  christos 
   1243  1.1  christos 	PREINIT:
   1244  1.1  christos 	struct _mark cursor;
   1245  1.1  christos 	void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
   1246  1.1  christos 	int rval;
   1247  1.1  christos 
   1248  1.1  christos 	CODE:
   1249  1.1  christos 	if (av_len(pos) < 1)
   1250  1.1  christos 	    croak("cursor position needs 2 elements");
   1251  1.1  christos 	INITMESSAGE(screen);
   1252  1.1  christos 	cursor.lno = SvIV(*av_fetch(pos, 0, 0));
   1253  1.1  christos 	cursor.cno = SvIV(*av_fetch(pos, 1, 0));
   1254  1.1  christos 	rval = api_setmark(screen, (int)mark, &cursor);
   1255  1.1  christos 	ENDMESSAGE(screen);
   1256  1.1  christos 
   1257  1.1  christos void
   1258  1.1  christos FIRSTKEY(screen, ...)
   1259  1.1  christos 	VI::MARK screen
   1260  1.1  christos 
   1261  1.1  christos 	ALIAS:
   1262  1.1  christos 	NEXTKEY = 1
   1263  1.1  christos 
   1264  1.1  christos 	PROTOTYPE: $;$
   1265  1.1  christos 
   1266  1.1  christos 	PREINIT:
   1267  1.1  christos 	int next;
   1268  1.1  christos 	char key[] = {0, 0};
   1269  1.1  christos 
   1270  1.1  christos 	PPCODE:
   1271  1.1  christos 	if (items == 2) {
   1272  1.1  christos 		next = 1;
   1273  1.1  christos 		*key = *(char *)SvPV(ST(1),PL_na);
   1274  1.1  christos 	} else next = 0;
   1275  1.1  christos 	if (api_nextmark(screen, next, key) != 1) {
   1276  1.1  christos 		EXTEND(sp, 1);
   1277  1.1  christos         	PUSHs(sv_2mortal(newSVpv(key, 1)));
   1278  1.1  christos 	} else ST(0) = &PL_sv_undef;
   1279  1.1  christos 
   1280  1.1  christos MODULE = VI	PACKAGE = VI::LINE
   1281  1.1  christos 
   1282  1.1  christos void
   1283  1.1  christos DESTROY(screen)
   1284  1.1  christos 	VI::LINE screen
   1285  1.1  christos 
   1286  1.1  christos 	CODE:
   1287  1.1  christos 	# typemap did all the checking
   1288  1.1  christos 	SvREFCNT_dec((SV*)SvIV((SV*)SvRV(ST(0))));
   1289  1.1  christos 
   1290  1.1  christos # similar to SetLine
   1291  1.1  christos 
   1292  1.1  christos void
   1293  1.1  christos STORE(screen, linenumber, text)
   1294  1.1  christos 	VI::LINE screen
   1295  1.1  christos 	int linenumber
   1296  1.1  christos 	char *text
   1297  1.1  christos 
   1298  1.1  christos 	PREINIT:
   1299  1.1  christos 	void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
   1300  1.1  christos 	int rval;
   1301  1.1  christos 	size_t length;
   1302  1.1  christos 	db_recno_t last;
   1303  1.1  christos 	size_t len;
   1304  1.1  christos 	CHAR_T *line;
   1305  1.1  christos 
   1306  1.1  christos 	CODE:
   1307  1.1  christos 	++linenumber;	/* vi 1 based ; perl 0 based */
   1308  1.1  christos 	SvPV(ST(2), length);
   1309  1.1  christos 	INITMESSAGE(screen);
   1310  1.1  christos 	rval = api_lline(screen, &last);
   1311  1.1  christos 	if (!rval) {
   1312  1.1  christos 	    if (linenumber > last)
   1313  1.1  christos 		rval = api_extend(screen, linenumber);
   1314  1.1  christos 	    if (!rval)
   1315  1.1  christos 		CHAR2INTP(screen, text, length, line, len);
   1316  1.1  christos 		rval = api_sline(screen, linenumber, line, len);
   1317  1.1  christos 	}
   1318  1.1  christos 	ENDMESSAGE(screen);
   1319  1.1  christos 
   1320  1.1  christos # similar to GetLine
   1321  1.1  christos 
   1322  1.1  christos char *
   1323  1.1  christos FETCH(screen, linenumber)
   1324  1.1  christos 	VI::LINE screen
   1325  1.1  christos 	int linenumber
   1326  1.1  christos 
   1327  1.1  christos 	PREINIT:
   1328  1.1  christos 	size_t len;
   1329  1.1  christos 	void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
   1330  1.1  christos 	int rval;
   1331  1.1  christos 	char *line;
   1332  1.1  christos 	CHAR_T *p;
   1333  1.1  christos 
   1334  1.1  christos 	PPCODE:
   1335  1.1  christos 	++linenumber;	/* vi 1 based ; perl 0 based */
   1336  1.1  christos 	INITMESSAGE(screen);
   1337  1.1  christos 	rval = api_gline(screen, (db_recno_t)linenumber, &p, &len);
   1338  1.1  christos 	ENDMESSAGE(screen);
   1339  1.1  christos 
   1340  1.1  christos 	EXTEND(sp,1);
   1341  1.1  christos 	PUSHs(sv_2mortal(newSVpv(len ? (char*)p : "", len)));
   1342  1.1  christos 
   1343  1.1  christos # similar to LastLine
   1344  1.1  christos 
   1345  1.1  christos int
   1346  1.1  christos FETCHSIZE(screen)
   1347  1.1  christos 	VI::LINE screen
   1348  1.1  christos 
   1349  1.1  christos 	PREINIT:
   1350  1.1  christos 	db_recno_t last;
   1351  1.1  christos 	void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
   1352  1.1  christos 	int rval;
   1353  1.1  christos 
   1354  1.1  christos 	CODE:
   1355  1.1  christos 	INITMESSAGE(screen);
   1356  1.1  christos 	rval = api_lline(screen, &last);
   1357  1.1  christos 	ENDMESSAGE(screen);
   1358  1.1  christos 	RETVAL=last;
   1359  1.1  christos 
   1360  1.1  christos 	OUTPUT:
   1361  1.1  christos 	RETVAL
   1362  1.1  christos 
   1363  1.1  christos void
   1364  1.1  christos STORESIZE(screen, count)
   1365  1.1  christos 	VI::LINE screen
   1366  1.1  christos 	int count
   1367  1.1  christos 
   1368  1.1  christos 	PREINIT:
   1369  1.1  christos 	db_recno_t last;
   1370  1.1  christos 	void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
   1371  1.1  christos 	int rval;
   1372  1.1  christos 
   1373  1.1  christos 	CODE:
   1374  1.1  christos 	INITMESSAGE(screen);
   1375  1.1  christos 	rval = api_lline(screen, &last);
   1376  1.1  christos 	if (!rval) {
   1377  1.1  christos 	    if (count > last)
   1378  1.1  christos 		rval = api_extend(screen, count);
   1379  1.1  christos 	    else while(last && last > count) {
   1380  1.1  christos 		rval = api_dline(screen, last--);
   1381  1.1  christos 		if (rval) break;
   1382  1.1  christos 	    }
   1383  1.1  christos 	}
   1384  1.1  christos 	ENDMESSAGE(screen);
   1385  1.1  christos 
   1386  1.1  christos void
   1387  1.1  christos EXTEND(screen, count)
   1388  1.1  christos 	VI::LINE screen
   1389  1.1  christos 	int count
   1390  1.1  christos 
   1391  1.1  christos 	CODE:
   1392  1.1  christos 
   1393  1.1  christos void
   1394  1.1  christos CLEAR(screen)
   1395  1.1  christos 	VI::LINE screen
   1396  1.1  christos 
   1397  1.1  christos 	PREINIT:
   1398  1.1  christos 	db_recno_t last;
   1399  1.1  christos 	void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
   1400  1.1  christos 	int rval;
   1401  1.1  christos 
   1402  1.1  christos 	CODE:
   1403  1.1  christos 	INITMESSAGE(screen);
   1404  1.1  christos 	rval = api_lline(screen, &last);
   1405  1.1  christos 	if (!rval) {
   1406  1.1  christos 	    while(last) {
   1407  1.1  christos 		rval = api_dline(screen, last--);
   1408  1.1  christos 		if (rval) break;
   1409  1.1  christos 	    }
   1410  1.1  christos 	}
   1411  1.1  christos 	ENDMESSAGE(screen);
   1412  1.1  christos 
   1413  1.1  christos void
   1414  1.1  christos PUSH(screen, ...)
   1415  1.1  christos 	VI::LINE screen;
   1416  1.1  christos 
   1417  1.1  christos 	PREINIT:
   1418  1.1  christos 	db_recno_t last;
   1419  1.1  christos 	void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
   1420  1.1  christos 	int rval, i, len;
   1421  1.1  christos 	char *line;
   1422  1.1  christos 
   1423  1.1  christos 	CODE:
   1424  1.1  christos 	INITMESSAGE(screen);
   1425  1.1  christos 	rval = api_lline(screen, &last);
   1426  1.1  christos 
   1427  1.1  christos 	if (!rval)
   1428  1.1  christos 		for (i = 1; i < items; ++i) {
   1429  1.1  christos 			line = SvPV(ST(i), len);
   1430  1.1  christos 			if ((rval = api_aline(screen, last++, line, len)))
   1431  1.1  christos 				break;
   1432  1.1  christos 		}
   1433  1.1  christos 	ENDMESSAGE(screen);
   1434  1.1  christos 
   1435  1.1  christos SV *
   1436  1.1  christos POP(screen)
   1437  1.1  christos 	VI::LINE screen;
   1438  1.1  christos 
   1439  1.1  christos 	PREINIT:
   1440  1.1  christos 	db_recno_t last;
   1441  1.1  christos 	void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
   1442  1.1  christos 	int rval, i, len;
   1443  1.1  christos 	CHAR_T *line;
   1444  1.1  christos 
   1445  1.1  christos 	PPCODE:
   1446  1.1  christos 	INITMESSAGE(screen);
   1447  1.1  christos 	rval = api_lline(screen, &last);
   1448  1.1  christos 	if (rval || last < 1)
   1449  1.1  christos 		ST(0) = &PL_sv_undef;
   1450  1.1  christos 	else {
   1451  1.1  christos 		rval = api_gline(screen, last, &line, &len) ||
   1452  1.1  christos 	 	       api_dline(screen, last);
   1453  1.1  christos 		EXTEND(sp,1);
   1454  1.1  christos 		PUSHs(sv_2mortal(newSVpv(len ? (char *)line : "", len)));
   1455  1.1  christos 	}
   1456  1.1  christos 	ENDMESSAGE(screen);
   1457  1.1  christos 
   1458  1.1  christos SV *
   1459  1.1  christos SHIFT(screen)
   1460  1.1  christos 	VI::LINE screen;
   1461  1.1  christos 
   1462  1.1  christos 	PREINIT:
   1463  1.1  christos 	db_recno_t last;
   1464  1.1  christos 	void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
   1465  1.1  christos 	int rval, i, len;
   1466  1.1  christos 	CHAR_T *line;
   1467  1.1  christos 
   1468  1.1  christos 	PPCODE:
   1469  1.1  christos 	INITMESSAGE(screen);
   1470  1.1  christos 	rval = api_lline(screen, &last);
   1471  1.1  christos 	if (rval || last < 1)
   1472  1.1  christos 		ST(0) = &PL_sv_undef;
   1473  1.1  christos 	else {
   1474  1.1  christos 		rval = api_gline(screen, (db_recno_t)1, &line, &len) ||
   1475  1.1  christos 	 	       api_dline(screen, (db_recno_t)1);
   1476  1.1  christos 		EXTEND(sp,1);
   1477  1.1  christos 		PUSHs(sv_2mortal(newSVpv(len ? (char *)line : "", len)));
   1478  1.1  christos 	}
   1479  1.1  christos 	ENDMESSAGE(screen);
   1480  1.1  christos 
   1481  1.1  christos void
   1482  1.1  christos UNSHIFT(screen, ...)
   1483  1.1  christos 	VI::LINE screen;
   1484  1.1  christos 
   1485  1.1  christos 	PREINIT:
   1486  1.1  christos 	void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
   1487  1.1  christos 	int rval, i, len;
   1488  1.1  christos 	char *np;
   1489  1.1  christos 	size_t nlen;
   1490  1.1  christos 	CHAR_T *line;
   1491  1.1  christos 
   1492  1.1  christos 	CODE:
   1493  1.1  christos 	INITMESSAGE(screen);
   1494  1.1  christos 	while (--items != 0) {
   1495  1.1  christos 		np = SvPV(ST(items), nlen);
   1496  1.1  christos 		CHAR2INTP(screen, np, nlen, line, len);
   1497  1.1  christos 		if ((rval = api_iline(screen, (db_recno_t)1, line, len)))
   1498  1.1  christos 			break;
   1499  1.1  christos 	}
   1500  1.1  christos 	ENDMESSAGE(screen);
   1501  1.1  christos 
   1502  1.1  christos void
   1503  1.1  christos SPLICE(screen, ...)
   1504  1.1  christos 	VI::LINE screen;
   1505  1.1  christos 
   1506  1.1  christos 	PREINIT:
   1507  1.1  christos 	db_recno_t last, db_offset;
   1508  1.1  christos 	void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
   1509  1.1  christos 	int rval, length, common, len, i, offset;
   1510  1.1  christos 	CHAR_T *line;
   1511  1.1  christos 	char *np;
   1512  1.1  christos 	size_t nlen;
   1513  1.1  christos 
   1514  1.1  christos 	PPCODE:
   1515  1.1  christos 	INITMESSAGE(screen);
   1516  1.1  christos 	rval = api_lline(screen, &last);
   1517  1.1  christos 	offset = items > 1 ? (int)SvIV(ST(1)) : 0;
   1518  1.1  christos 	if (offset < 0) offset += last;
   1519  1.1  christos 	if (offset < 0) {
   1520  1.1  christos 	    ENDMESSAGE(screen);
   1521  1.1  christos 	    croak("Invalid offset");
   1522  1.1  christos 	}
   1523  1.1  christos 	length = items > 2 ? (int)SvIV(ST(2)) : last - offset;
   1524  1.1  christos 	if (length > last - offset)
   1525  1.1  christos 		length = last - offset;
   1526  1.1  christos 	db_offset = offset + 1; /* 1 based */
   1527  1.1  christos 	EXTEND(sp,length);
   1528  1.1  christos 	for (common = MIN(length, items - 3), i = 3; common > 0;
   1529  1.1  christos 	    --common, ++db_offset, --length, ++i) {
   1530  1.1  christos 		rval |= api_gline(screen, db_offset, &line, &len);
   1531  1.1  christos 		INT2CHAR(screen, line, len, np, nlen);
   1532  1.1  christos 		PUSHs(sv_2mortal(newSVpv(nlen ? np : "", nlen)));
   1533  1.1  christos 		np = SvPV(ST(i), nlen);
   1534  1.1  christos 		CHAR2INTP(screen, np, nlen, line, len);
   1535  1.1  christos 		rval |= api_sline(screen, db_offset, line, len);
   1536  1.1  christos 	}
   1537  1.1  christos 	for (; length; --length) {
   1538  1.1  christos 		rval |= api_gline(screen, db_offset, &line, &len);
   1539  1.1  christos 		INT2CHAR(screen, line, len, np, nlen);
   1540  1.1  christos 		PUSHs(sv_2mortal(newSVpv(len ? np : "", nlen)));
   1541  1.1  christos 		rval |= api_dline(screen, db_offset);
   1542  1.1  christos 	}
   1543  1.1  christos 	for (; i < items; ++i) {
   1544  1.1  christos 		np = SvPV(ST(i), len);
   1545  1.1  christos 		CHAR2INTP(screen, np, len, line, nlen);
   1546  1.1  christos 		rval |= api_iline(screen, db_offset, line, nlen);
   1547  1.1  christos 	}
   1548  1.1  christos 	ENDMESSAGE(screen);
   1549  1.1  christos 
   1550  1.1  christos MODULE = VI	PACKAGE = VI::TAGQ
   1551  1.1  christos 
   1552  1.1  christos void
   1553  1.1  christos Add(tagq, filename, search, msg)
   1554  1.1  christos 	VI::TAGQ    tagq;
   1555  1.1  christos 	char	   *filename;
   1556  1.1  christos 	char	   *search;
   1557  1.1  christos 	char	   *msg;
   1558  1.1  christos 
   1559  1.1  christos 	PREINIT:
   1560  1.1  christos 	SCR *sp;
   1561  1.1  christos 
   1562  1.1  christos 	CODE:
   1563  1.1  christos 	sp = (SCR *)SvIV((SV*)SvRV(tagq->sprv));
   1564  1.1  christos 	if (!sp)
   1565  1.1  christos 		croak("screen no longer exists");
   1566  1.1  christos 	api_tagq_add(sp, tagq->tqp, filename, search, msg);
   1567  1.1  christos 
   1568  1.1  christos void
   1569  1.1  christos Push(tagq)
   1570  1.1  christos 	VI::TAGQ    tagq;
   1571  1.1  christos 
   1572  1.1  christos 	PREINIT:
   1573  1.1  christos 	SCR *sp;
   1574  1.1  christos 
   1575  1.1  christos 	CODE:
   1576  1.1  christos 	sp = (SCR *)SvIV((SV*)SvRV(tagq->sprv));
   1577  1.1  christos 	if (!sp)
   1578  1.1  christos 		croak("screen no longer exists");
   1579  1.1  christos 	api_tagq_push(sp, &tagq->tqp);
   1580  1.1  christos 
   1581  1.1  christos void
   1582  1.1  christos DESTROY(tagq)
   1583  1.1  christos 	# Can already be invalidated by push
   1584  1.1  christos 	VI::TAGQ2    tagq;
   1585  1.1  christos 
   1586  1.1  christos 	PREINIT:
   1587  1.1  christos 	SCR *sp;
   1588  1.1  christos 
   1589  1.1  christos 	CODE:
   1590  1.1  christos 	sp = (SCR *)SvIV((SV*)SvRV(tagq->sprv));
   1591  1.1  christos 	if (sp)
   1592  1.1  christos 		api_tagq_free(sp, tagq->tqp);
   1593  1.1  christos 	SvREFCNT_dec(tagq->sprv);
   1594  1.1  christos 	free(tagq);
   1595