2 * Copyright (c) 1992, 1993, 1994
3 * The Regents of the University of California. All rights reserved.
4 * Copyright (c) 1992, 1993, 1994, 1995, 1996
5 * Keith Bostic. All rights reserved.
7 * George V. Neville-Neil. All rights reserved.
8 * Copyright (c) 1996-2001
9 * Sven Verdoolaege. All rights reserved.
11 * See the LICENSE file for redistribution information.
17 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 $";
20 #include <sys/types.h>
21 #include <sys/queue.h>
24 #include <bitstring.h>
38 /* perl redefines them
42 #undef USE_DYNAMIC_LOADING
50 #include "../common/common.h"
51 #include "../perl_api/extern.h"
54 #define DEFSV GvSV(defgv)
57 #define ERRSV GvSV(errgv)
65 static void msghandler __P((SCR *, mtype_t, char *, size_t));
67 typedef struct _perl_data {
68 PerlInterpreter* interp;
69 SV *svcurscr, *svstart, *svstop, *svid;
74 #define PERLP(sp) ((perl_data_t *)sp->wp->perl_private)
76 #define CHAR2INTP(sp,n,nlen,w,wlen) \
77 CHAR2INT5(sp,((perl_data_t *)sp->wp->perl_private)->cw,n,nlen,w,wlen)
81 * Macros to point messages at the Perl message handler.
83 #define INITMESSAGE(sp) \
84 scr_msg = sp->wp->scr_msg; \
85 sp->wp->scr_msg = msghandler;
86 #define ENDMESSAGE(sp) \
87 sp->wp->scr_msg = scr_msg; \
88 if (rval) croak("%s", PERLP(sp)->errmsg);
90 void xs_init __P((pTHXo));
94 * Clean up perl interpreter
96 * PUBLIC: int perl_end __P((GS *));
103 * Call perl_run and perl_destuct to call END blocks and DESTROY
106 if (gp->perl_interp) {
107 perl_run(gp->perl_interp);
108 perl_destruct(gp->perl_interp);
109 #if defined(DEBUG) || defined(PURIFY) || defined(LIBRARY)
110 perl_free(gp->perl_interp);
112 /* XXX rather make sure only one thread calls perl_end */
120 * We don't use mortal SVs because no one will clean up after us
128 SV* sv = newSVpv(string, 0);
130 /* G_KEEPERR to catch syntax error; better way ? */
132 perl_eval_sv(sv, G_DISCARD | G_NOARGS | G_KEEPERR);
138 * Create the perl commands used by nvi.
140 * PUBLIC: int perl_init __P((SCR *));
149 char *bootargs[] = { "VI", NULL };
155 static char *args[] = { "", "-e", "" };
157 char *file = __FILE__;
162 if (gp->perl_interp == NULL) {
163 gp->perl_interp = perl_alloc();
164 perl_construct(gp->perl_interp);
165 if (perl_parse(gp->perl_interp, xs_init, 3, args, 0)) {
166 perl_destruct(gp->perl_interp);
167 perl_free(gp->perl_interp);
168 gp->perl_interp = NULL;
174 perl_call_argv("VI::bootstrap", G_DISCARD, bootargs);
175 perl_eval("$SIG{__WARN__}='VI::Warn'");
177 av_unshift(av = GvAVn(PL_incgv), 1);
178 av_store(av, 0, newSVpv(_PATH_PERLSCRIPTS,
179 sizeof(_PATH_PERLSCRIPTS)-1));
182 sfdisc(PerlIO_stdout(), sfdcnewnvi(scrp));
183 sfdisc(PerlIO_stderr(), sfdcnewnvi(scrp));
185 svcurscr = perl_get_sv("curscr", TRUE);
186 sv_magic((SV *)gv_fetchpv("STDOUT",TRUE, SVt_PVIO), svcurscr,
188 sv_magic((SV *)gv_fetchpv("STDERR",TRUE, SVt_PVIO), svcurscr,
190 #endif /* USE_SFIO */
193 MALLOC(scrp, pp, perl_data_t *, sizeof(perl_data_t));
194 wp->perl_private = pp;
195 memset(&pp->cw, 0, sizeof(pp->cw));
197 pp->interp = perl_clone(gp->perl_interp, 0);
198 if (1) { /* hack for bug fixed in perl-current (5.6.1) */
200 if (PL_scopestack_ix == 0) {
205 pp->interp = gp->perl_interp;
211 SvREADONLY_on(pp->svcurscr = perl_get_sv("curscr", TRUE));
212 SvREADONLY_on(pp->svstart = perl_get_sv("VI::StartLine", TRUE));
213 SvREADONLY_on(pp->svstop = perl_get_sv("VI::StopLine", TRUE));
214 SvREADONLY_on(pp->svid = perl_get_sv("VI::ScreenId", TRUE));
221 * Remove all refences to the screen to be destroyed
223 * PUBLIC: int perl_screen_end __P((SCR*));
226 perl_screen_end(scrp)
231 if (scrp->perl_private) {
232 sv_setiv((SV*) scrp->perl_private, 0);
241 croak("Perl command interrupted by SIGINT");
244 /* Create a new reference to an SV pointing to the SCR structure
245 * The perl_private part of the SCR structure points to the SV,
246 * so there can only be one such SV for a particular SCR structure.
247 * When the last reference has gone (DESTROY is called),
248 * perl_private is reset; When the screen goes away before
249 * all references are gone, the value of the SV is reset;
250 * any subsequent use of any of those reference will produce
251 * a warning. (see typemap)
260 if (!screen) return sv_setsv(rv, &PL_sv_undef), rv;
261 sv_upgrade(rv, SVt_RV);
262 if (!screen->perl_private) {
263 screen->perl_private = newSV(0);
264 sv_setiv(screen->perl_private, (IV) screen);
266 else SvREFCNT_inc(screen->perl_private);
267 SvRV(rv) = screen->perl_private;
269 return sv_bless(rv, gv_stashpv("VI", TRUE));
274 * Use perl's setenv if perl interpreter has been started.
275 * Perl uses its own setenv and gets confused if we change
276 * the environment after it has started.
278 * PUBLIC: int perl_setenv __P((SCR* sp, const char *name, const char *value));
281 perl_setenv(SCR* scrp, const char *name, const char *value)
283 if (scrp->wp->perl_private == NULL) {
287 setenv(name, value, 1);
289 my_setenv(name, value);
294 * perl_ex_perl -- :[line [,line]] perl [command]
295 * Run a command through the perl interpreter.
297 * PUBLIC: int perl_ex_perl __P((SCR*, CHAR_T *, size_t, db_recno_t, db_recno_t));
300 perl_ex_perl(scrp, cmdp, cmdlen, f_lno, t_lno)
304 db_recno_t f_lno, t_lno;
315 /* Initialize the interpreter. */
316 if (scrp->wp->perl_private == NULL && perl_init(scrp))
318 pp = scrp->wp->perl_private;
323 sv_setiv(pp->svstart, f_lno);
324 sv_setiv(pp->svstop, t_lno);
325 newVIrv(pp->svcurscr, scrp);
326 /* Backwards compatibility. */
327 newVIrv(pp->svid, scrp);
329 istat = signal(SIGINT, my_sighandler);
330 INT2CHAR(scrp, cmdp, STRLEN(cmdp)+1, np, nlen);
332 signal(SIGINT, istat);
334 SvREFCNT_dec(SvRV(pp->svcurscr));
335 SvROK_off(pp->svcurscr);
336 SvREFCNT_dec(SvRV(pp->svid));
339 err = SvPV(ERRSV, length);
343 err[length - 1] = '\0';
344 msgq(scrp, M_ERR, "perl: %s", err);
351 * replace a line with the contents of the perl variable $_
352 * lines are split at '\n's
353 * if $_ is undef, the line is deleted
354 * returns possibly adjusted linenumber
357 replace_line(scrp, line, t_lno, defsv)
359 db_recno_t line, *t_lno;
368 str = SvPV(defsv,len);
369 next = memchr(str, '\n', len);
370 CHAR2INTP(scrp, str, next ? (next - str) : len, wp, wlen);
371 api_sline(scrp, line, wp, wlen);
374 next = memchr(str = next, '\n', len);
375 CHAR2INTP(scrp, str, next ? (next - str) : len,
377 api_iline(scrp, ++line, wp, wlen);
381 api_dline(scrp, line--);
388 * perl_ex_perldo -- :[line [,line]] perl [command]
389 * Run a set of lines through the perl interpreter.
391 * PUBLIC: int perl_ex_perldo __P((SCR*, CHAR_T *, size_t, db_recno_t, db_recno_t));
394 perl_ex_perldo(scrp, cmdp, cmdlen, f_lno, t_lno)
398 db_recno_t f_lno, t_lno;
413 /* Initialize the interpreter. */
414 if (scrp->wp->perl_private == NULL && perl_init(scrp))
416 pp = scrp->wp->perl_private;
421 newVIrv(pp->svcurscr, scrp);
422 /* Backwards compatibility. */
423 newVIrv(pp->svid, scrp);
425 INT2CHAR(scrp, cmdp, STRLEN(cmdp)+1, np, nlen);
426 if (!(command = malloc(length = nlen - 1 + sizeof("sub {}"))))
428 snprintf(command, length, "sub {%s}", np);
433 cv = perl_eval_pv(command, FALSE);
436 estr = SvPV(ERRSV,length);
440 for (i = f_lno; i <= t_lno && !api_gline(scrp, i, &str, &len); i++) {
441 INT2CHAR(scrp, str, len, np, nlen);
442 sv_setpvn(DEFSV,np,nlen);
443 sv_setiv(pp->svstart, i);
444 sv_setiv(pp->svstop, i);
446 perl_call_sv(cv, G_SCALAR | G_EVAL);
447 estr = SvPV(ERRSV, length);
451 i = replace_line(scrp, i, &t_lno, DEFSV);
457 SvREFCNT_dec(SvRV(pp->svcurscr));
458 SvROK_off(pp->svcurscr);
459 SvREFCNT_dec(SvRV(pp->svid));
465 err: estr[length - 1] = '\0';
466 msgq(scrp, M_ERR, "perl: %s", estr);
473 * Perl message routine so that error messages are processed in
477 msghandler(sp, mtype, msg, len)
485 errmsg = PERLP(sp)->errmsg;
487 /* Replace the trailing <newline> with an EOS. */
488 /* Let's do that later instead */
489 if (errmsg) free (errmsg);
490 errmsg = malloc(len + 1);
491 memcpy(errmsg, msg, len);
493 PERLP(sp)->errmsg = errmsg;
498 typedef SCR * VI__OPT;
499 typedef SCR * VI__MAP;
500 typedef SCR * VI__MARK;
501 typedef SCR * VI__LINE;
509 typedef perl_tagq * VI__TAGQ;
510 typedef perl_tagq * VI__TAGQ2;
512 MODULE = VI PACKAGE = VI
515 # Set the message line to text.
517 # Perl Command: VI::Msg
518 # Usage: VI::Msg screenId text
529 api_imessage(screen, text);
534 # Perl Command: VI::EndScreen
535 # Usage: VI::EndScreen screenId
542 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
547 rval = api_escreen(screen);
551 # Create a new screen. If a filename is specified then the screen
552 # is opened with that file.
554 # Perl Command: VI::NewScreen
555 # Usage: VI::NewScreen screenId [file]
566 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
572 file = (items == 1) ? NULL : (char *)SvPV(ST(1),PL_na);
574 rval = api_edit(screen, file, &nsp, ix);
577 RETVAL = ix ? nsp : screen;
583 # Return the screen id associated with file name.
585 # Perl Command: VI::FindScreen
586 # Usage: VI::FindScreen file
595 RETVAL = api_fscreen(0, file);
600 # XS_VI_GetFileName --
601 # Return the file name of the screen
603 # Perl Command: VI::GetFileName
604 # Usage: VI::GetFileName screenId
612 PUSHs(sv_2mortal(newSVpv(screen->frp->name, 0)));
615 # -- Append the string text after the line in lineNumber.
617 # Perl Command: VI::AppendLine
618 # Usage: VI::AppendLine screenId lineNumber text
621 AppendLine(screen, linenumber, text)
627 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
634 rval = api_aline(screen, linenumber, text, length);
640 # Perl Command: VI::DelLine
641 # Usage: VI::DelLine screenId lineNum
644 DelLine(screen, linenumber)
649 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
654 rval = api_dline(screen, (db_recno_t)linenumber);
660 # Perl Command: VI::GetLine
661 # Usage: VI::GetLine screenId lineNumber
664 GetLine(screen, linenumber)
670 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
677 rval = api_gline(screen, (db_recno_t)linenumber, &p, &len);
681 PUSHs(sv_2mortal(newSVpv(len ? (char *)p : "", len)));
684 # Set lineNumber to the text supplied.
686 # Perl Command: VI::SetLine
687 # Usage: VI::SetLine screenId lineNumber text
690 SetLine(screen, linenumber, text)
696 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
705 CHAR2INTP(screen, text, length, line, len);
706 rval = api_sline(screen, linenumber, line, len);
710 # Insert the string text before the line in lineNumber.
712 # Perl Command: VI::InsertLine
713 # Usage: VI::InsertLine screenId lineNumber text
716 InsertLine(screen, linenumber, text)
722 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
731 CHAR2INTP(screen, text, length, line, len);
732 rval = api_iline(screen, linenumber, line, len);
736 # Return the last line in the screen.
738 # Perl Command: VI::LastLine
739 # Usage: VI::LastLine screenId
747 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
752 rval = api_lline(screen, &last);
760 # Return the mark's cursor position as a list with two elements.
763 # Perl Command: VI::GetMark
764 # Usage: VI::GetMark screenId mark
767 GetMark(screen, mark)
773 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
778 rval = api_getmark(screen, (int)mark, &cursor);
782 PUSHs(sv_2mortal(newSViv(cursor.lno)));
783 PUSHs(sv_2mortal(newSViv(cursor.cno)));
786 # Set the mark to the line and column numbers supplied.
788 # Perl Command: VI::SetMark
789 # Usage: VI::SetMark screenId mark line column
792 SetMark(screen, mark, line, column)
800 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
807 rval = api_setmark(screen, (int)mark, &cursor);
811 # Return the current cursor position as a list with two elements.
814 # Perl Command: VI::GetCursor
815 # Usage: VI::GetCursor screenId
823 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
828 rval = api_getcursor(screen, &cursor);
832 PUSHs(sv_2mortal(newSViv(cursor.lno)));
833 PUSHs(sv_2mortal(newSViv(cursor.cno)));
836 # Set the cursor to the line and column numbers supplied.
838 # Perl Command: VI::SetCursor
839 # Usage: VI::SetCursor screenId line column
842 SetCursor(screen, line, column)
849 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
856 rval = api_setcursor(screen, &cursor);
860 # Change the current focus to screen.
862 # Perl Command: VI::SwitchScreen
863 # Usage: VI::SwitchScreen screenId screenId
866 SwitchScreen(screenFrom, screenTo)
871 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
875 INITMESSAGE(screenFrom);
876 rval = api_swscreen(screenFrom, screenTo);
877 ENDMESSAGE(screenFrom);
880 # Associate a key with a perl procedure.
882 # Perl Command: VI::MapKey
883 # Usage: VI::MapKey screenId key perlproc
886 MapKey(screen, key, commandsv)
892 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
899 command = SvPV(commandsv, length);
900 rval = api_map(screen, key, command, length);
906 # Perl Command: VI::UnmapKey
907 # Usage: VI::UnmmapKey screenId key
910 UnmapKey(screen, key)
915 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
920 rval = api_unmap(screen, key);
926 # Perl Command: VI::SetOpt
927 # Usage: VI::SetOpt screenId setting
930 SetOpt(screen, setting)
935 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
941 svc = sv_2mortal(newSVpv(":set ", 5));
942 sv_catpv(svc, setting);
943 rval = api_run_str(screen, SvPV(svc, PL_na));
947 # Return the value of an option.
949 # Perl Command: VI::GetOpt
950 # Usage: VI::GetOpt screenId option
953 GetOpt(screen, option)
958 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
966 CHAR2INTP(screen, option, strlen(option)+1, wp, wlen);
967 rval = api_opts_get(screen, wp, &value, NULL);
971 PUSHs(sv_2mortal(newSVpv(value, 0)));
975 # Run the ex command cmd.
977 # Perl Command: VI::Run
978 # Usage: VI::Run screenId cmd
986 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
991 rval = api_run_str(screen, command);
1002 if (sv_isa(screensv, "VI")) {
1003 IV tmp = SvIV((SV*)SvRV(screensv));
1004 screen = (SCR *) tmp;
1007 croak("screen is not of type VI");
1010 screen->perl_private = 0;
1017 sv_catpv(ERRSV,warning);
1019 #define TIED(kind,package) \
1020 sv_magic((SV *) (var = \
1021 (kind##V *)sv_2mortal((SV *)new##kind##V())), \
1022 sv_setref_pv(sv_newmortal(), package, \
1023 newVIrv(newSV(0), screen)),\
1025 RETVAL = newRV((SV *)var)
1076 if ((ptag = malloc(sizeof(perl_tagq))) == NULL)
1079 ptag->sprv = newVIrv(newSV(0), screen);
1080 ptag->tqp = api_tagq_new(screen, tag);
1081 if (ptag->tqp != NULL) {
1083 PUSHs(sv_2mortal(sv_setref_pv(newSV(0), "VI::TAGQ", ptag)));
1086 ST(0) = &PL_sv_undef;
1090 MODULE = VI PACKAGE = VI::OPT
1097 # typemap did all the checking
1098 SvREFCNT_dec((SV*)SvIV((SV*)SvRV(ST(0))));
1106 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
1114 INITMESSAGE(screen);
1115 CHAR2INTP(screen, key, strlen(key)+1, wp, wlen);
1116 rval = api_opts_get(screen, wp, &value, &boolvalue);
1119 PUSHs(sv_2mortal((boolvalue == -1) ? newSVpv(value, 0)
1120 : newSViv(boolvalue)));
1122 } else ST(0) = &PL_sv_undef;
1127 STORE(screen, key, value)
1133 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
1139 INITMESSAGE(screen);
1140 CHAR2INTP(screen, key, strlen(key)+1, wp, wlen);
1141 rval = api_opts_set(screen, wp, SvPV(value, PL_na), SvIV(value),
1145 MODULE = VI PACKAGE = VI::MAP
1152 # typemap did all the checking
1153 SvREFCNT_dec((SV*)SvIV((SV*)SvRV(ST(0))));
1156 STORE(screen, key, commandsv)
1162 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
1168 INITMESSAGE(screen);
1169 command = SvPV(commandsv, length);
1170 rval = api_map(screen, key, command, length);
1179 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
1183 INITMESSAGE(screen);
1184 rval = api_unmap(screen, key);
1187 MODULE = VI PACKAGE = VI::MARK
1194 # typemap did all the checking
1195 SvREFCNT_dec((SV*)SvIV((SV*)SvRV(ST(0))));
1198 EXISTS(screen, mark)
1203 struct _mark cursor;
1204 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
1205 int rval = 0; /* never croak */
1209 INITMESSAGE(screen);
1210 missing = api_getmark(screen, (int)mark, &cursor);
1223 struct _mark cursor;
1224 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
1228 INITMESSAGE(screen);
1229 rval = api_getmark(screen, (int)mark, &cursor);
1232 av_push(RETVAL, newSViv(cursor.lno));
1233 av_push(RETVAL, newSViv(cursor.cno));
1239 STORE(screen, mark, pos)
1245 struct _mark cursor;
1246 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
1250 if (av_len(pos) < 1)
1251 croak("cursor position needs 2 elements");
1252 INITMESSAGE(screen);
1253 cursor.lno = SvIV(*av_fetch(pos, 0, 0));
1254 cursor.cno = SvIV(*av_fetch(pos, 1, 0));
1255 rval = api_setmark(screen, (int)mark, &cursor);
1259 FIRSTKEY(screen, ...)
1269 char key[] = {0, 0};
1274 *key = *(char *)SvPV(ST(1),PL_na);
1276 if (api_nextmark(screen, next, key) != 1) {
1278 PUSHs(sv_2mortal(newSVpv(key, 1)));
1279 } else ST(0) = &PL_sv_undef;
1281 MODULE = VI PACKAGE = VI::LINE
1288 # typemap did all the checking
1289 SvREFCNT_dec((SV*)SvIV((SV*)SvRV(ST(0))));
1291 # similar to SetLine
1294 STORE(screen, linenumber, text)
1300 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
1308 ++linenumber; /* vi 1 based ; perl 0 based */
1309 SvPV(ST(2), length);
1310 INITMESSAGE(screen);
1311 rval = api_lline(screen, &last);
1313 if (linenumber > last)
1314 rval = api_extend(screen, linenumber);
1316 CHAR2INTP(screen, text, length, line, len);
1317 rval = api_sline(screen, linenumber, line, len);
1321 # similar to GetLine
1324 FETCH(screen, linenumber)
1330 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
1336 ++linenumber; /* vi 1 based ; perl 0 based */
1337 INITMESSAGE(screen);
1338 rval = api_gline(screen, (db_recno_t)linenumber, &p, &len);
1342 PUSHs(sv_2mortal(newSVpv(len ? (char*)p : "", len)));
1344 # similar to LastLine
1352 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
1356 INITMESSAGE(screen);
1357 rval = api_lline(screen, &last);
1365 STORESIZE(screen, count)
1371 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
1375 INITMESSAGE(screen);
1376 rval = api_lline(screen, &last);
1379 rval = api_extend(screen, count);
1380 else while(last && last > count) {
1381 rval = api_dline(screen, last--);
1388 EXTEND(screen, count)
1400 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
1404 INITMESSAGE(screen);
1405 rval = api_lline(screen, &last);
1408 rval = api_dline(screen, last--);
1420 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
1425 INITMESSAGE(screen);
1426 rval = api_lline(screen, &last);
1429 for (i = 1; i < items; ++i) {
1430 line = SvPV(ST(i), len);
1431 if ((rval = api_aline(screen, last++, line, len)))
1442 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
1447 INITMESSAGE(screen);
1448 rval = api_lline(screen, &last);
1449 if (rval || last < 1)
1450 ST(0) = &PL_sv_undef;
1452 rval = api_gline(screen, last, &line, &len) ||
1453 api_dline(screen, last);
1455 PUSHs(sv_2mortal(newSVpv(len ? (char *)line : "", len)));
1465 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
1470 INITMESSAGE(screen);
1471 rval = api_lline(screen, &last);
1472 if (rval || last < 1)
1473 ST(0) = &PL_sv_undef;
1475 rval = api_gline(screen, (db_recno_t)1, &line, &len) ||
1476 api_dline(screen, (db_recno_t)1);
1478 PUSHs(sv_2mortal(newSVpv(len ? (char *)line : "", len)));
1483 UNSHIFT(screen, ...)
1487 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
1494 INITMESSAGE(screen);
1495 while (--items != 0) {
1496 np = SvPV(ST(items), nlen);
1497 CHAR2INTP(screen, np, nlen, line, len);
1498 if ((rval = api_iline(screen, (db_recno_t)1, line, len)))
1508 db_recno_t last, db_offset;
1509 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
1510 int rval, length, common, len, i, offset;
1516 INITMESSAGE(screen);
1517 rval = api_lline(screen, &last);
1518 offset = items > 1 ? (int)SvIV(ST(1)) : 0;
1519 if (offset < 0) offset += last;
1522 croak("Invalid offset");
1524 length = items > 2 ? (int)SvIV(ST(2)) : last - offset;
1525 if (length > last - offset)
1526 length = last - offset;
1527 db_offset = offset + 1; /* 1 based */
1529 for (common = MIN(length, items - 3), i = 3; common > 0;
1530 --common, ++db_offset, --length, ++i) {
1531 rval |= api_gline(screen, db_offset, &line, &len);
1532 INT2CHAR(screen, line, len, np, nlen);
1533 PUSHs(sv_2mortal(newSVpv(nlen ? np : "", nlen)));
1534 np = SvPV(ST(i), nlen);
1535 CHAR2INTP(screen, np, nlen, line, len);
1536 rval |= api_sline(screen, db_offset, line, len);
1538 for (; length; --length) {
1539 rval |= api_gline(screen, db_offset, &line, &len);
1540 INT2CHAR(screen, line, len, np, nlen);
1541 PUSHs(sv_2mortal(newSVpv(len ? np : "", nlen)));
1542 rval |= api_dline(screen, db_offset);
1544 for (; i < items; ++i) {
1545 np = SvPV(ST(i), len);
1546 CHAR2INTP(screen, np, len, line, nlen);
1547 rval |= api_iline(screen, db_offset, line, nlen);
1551 MODULE = VI PACKAGE = VI::TAGQ
1554 Add(tagq, filename, search, msg)
1564 sp = (SCR *)SvIV((SV*)SvRV(tagq->sprv));
1566 croak("screen no longer exists");
1567 api_tagq_add(sp, tagq->tqp, filename, search, msg);
1577 sp = (SCR *)SvIV((SV*)SvRV(tagq->sprv));
1579 croak("screen no longer exists");
1580 api_tagq_push(sp, &tagq->tqp);
1584 # Can already be invalidated by push
1591 sp = (SCR *)SvIV((SV*)SvRV(tagq->sprv));
1593 api_tagq_free(sp, tagq->tqp);
1594 SvREFCNT_dec(tagq->sprv);