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.45 2001/07/29 19:51:21 skimo Exp $ (Berkeley) $Date: 2001/07/29 19:51:21 $";
20 #include <sys/types.h>
21 #include <sys/queue.h>
24 #include <bitstring.h>
38 /* perl redefines them
41 #undef USE_DYNAMIC_LOADING
49 #include "../common/common.h"
50 #include "../perl_api/extern.h"
53 #define DEFSV GvSV(defgv)
56 #define ERRSV GvSV(errgv)
64 static void msghandler __P((SCR *, mtype_t, char *, size_t));
66 typedef struct _perl_data {
67 PerlInterpreter* interp;
68 SV *svcurscr, *svstart, *svstop, *svid;
73 #define PERLP(sp) ((perl_data_t *)sp->wp->perl_private)
75 #define CHAR2INTP(sp,n,nlen,w,wlen) \
76 CHAR2INT5(sp,((perl_data_t *)sp->wp->perl_private)->cw,n,nlen,w,wlen)
80 * Macros to point messages at the Perl message handler.
82 #define INITMESSAGE(sp) \
83 scr_msg = sp->wp->scr_msg; \
84 sp->wp->scr_msg = msghandler;
85 #define ENDMESSAGE(sp) \
86 sp->wp->scr_msg = scr_msg; \
87 if (rval) croak(PERLP(sp)->errmsg);
89 void xs_init __P((pTHXo));
93 * Clean up perl interpreter
95 * PUBLIC: int perl_end __P((GS *));
102 * Call perl_run and perl_destuct to call END blocks and DESTROY
105 if (gp->perl_interp) {
106 perl_run(gp->perl_interp);
107 perl_destruct(gp->perl_interp);
108 #if defined(DEBUG) || defined(PURIFY) || defined(LIBRARY)
109 perl_free(gp->perl_interp);
111 /* XXX rather make sure only one thread calls perl_end */
119 * We don't use mortal SVs because no one will clean up after us
127 SV* sv = newSVpv(string, 0);
129 /* G_KEEPERR to catch syntax error; better way ? */
131 perl_eval_sv(sv, G_DISCARD | G_NOARGS | G_KEEPERR);
137 * Create the perl commands used by nvi.
139 * PUBLIC: int perl_init __P((SCR *));
148 char *bootargs[] = { "VI", NULL };
154 static char *args[] = { "", "-e", "" };
156 char *file = __FILE__;
161 if (gp->perl_interp == NULL) {
162 gp->perl_interp = perl_alloc();
163 perl_construct(gp->perl_interp);
164 if (perl_parse(gp->perl_interp, xs_init, 3, args, 0)) {
165 perl_destruct(gp->perl_interp);
166 perl_free(gp->perl_interp);
167 gp->perl_interp = NULL;
173 perl_call_argv("VI::bootstrap", G_DISCARD, bootargs);
174 perl_eval("$SIG{__WARN__}='VI::Warn'");
176 av_unshift(av = GvAVn(PL_incgv), 1);
177 av_store(av, 0, newSVpv(_PATH_PERLSCRIPTS,
178 sizeof(_PATH_PERLSCRIPTS)-1));
181 sfdisc(PerlIO_stdout(), sfdcnewnvi(scrp));
182 sfdisc(PerlIO_stderr(), sfdcnewnvi(scrp));
184 svcurscr = perl_get_sv("curscr", TRUE);
185 sv_magic((SV *)gv_fetchpv("STDOUT",TRUE, SVt_PVIO), svcurscr,
187 sv_magic((SV *)gv_fetchpv("STDERR",TRUE, SVt_PVIO), svcurscr,
189 #endif /* USE_SFIO */
192 MALLOC(scrp, pp, perl_data_t *, sizeof(perl_data_t));
193 wp->perl_private = pp;
194 memset(&pp->cw, 0, sizeof(pp->cw));
196 pp->interp = perl_clone(gp->perl_interp, 0);
197 if (1) { /* hack for bug fixed in perl-current (5.6.1) */
199 if (PL_scopestack_ix == 0) {
204 pp->interp = gp->perl_interp;
210 SvREADONLY_on(pp->svcurscr = perl_get_sv("curscr", TRUE));
211 SvREADONLY_on(pp->svstart = perl_get_sv("VI::StartLine", TRUE));
212 SvREADONLY_on(pp->svstop = perl_get_sv("VI::StopLine", TRUE));
213 SvREADONLY_on(pp->svid = perl_get_sv("VI::ScreenId", TRUE));
220 * Remove all refences to the screen to be destroyed
222 * PUBLIC: int perl_screen_end __P((SCR*));
225 perl_screen_end(scrp)
230 if (scrp->perl_private) {
231 sv_setiv((SV*) scrp->perl_private, 0);
240 croak("Perl command interrupted by SIGINT");
243 /* Create a new reference to an SV pointing to the SCR structure
244 * The perl_private part of the SCR structure points to the SV,
245 * so there can only be one such SV for a particular SCR structure.
246 * When the last reference has gone (DESTROY is called),
247 * perl_private is reset; When the screen goes away before
248 * all references are gone, the value of the SV is reset;
249 * any subsequent use of any of those reference will produce
250 * a warning. (see typemap)
259 if (!screen) return sv_setsv(rv, &PL_sv_undef), rv;
260 sv_upgrade(rv, SVt_RV);
261 if (!screen->perl_private) {
262 screen->perl_private = newSV(0);
263 sv_setiv(screen->perl_private, (IV) screen);
265 else SvREFCNT_inc(screen->perl_private);
266 SvRV(rv) = screen->perl_private;
268 return sv_bless(rv, gv_stashpv("VI", TRUE));
273 * perl_ex_perl -- :[line [,line]] perl [command]
274 * Run a command through the perl interpreter.
276 * PUBLIC: int perl_ex_perl __P((SCR*, CHAR_T *, size_t, db_recno_t, db_recno_t));
279 perl_ex_perl(scrp, cmdp, cmdlen, f_lno, t_lno)
283 db_recno_t f_lno, t_lno;
294 /* Initialize the interpreter. */
295 if (scrp->wp->perl_private == NULL && perl_init(scrp))
297 pp = scrp->wp->perl_private;
302 sv_setiv(pp->svstart, f_lno);
303 sv_setiv(pp->svstop, t_lno);
304 newVIrv(pp->svcurscr, scrp);
305 /* Backwards compatibility. */
306 newVIrv(pp->svid, scrp);
308 istat = signal(SIGINT, my_sighandler);
309 INT2CHAR(scrp, cmdp, STRLEN(cmdp)+1, np, nlen);
311 signal(SIGINT, istat);
313 SvREFCNT_dec(SvRV(pp->svcurscr));
314 SvROK_off(pp->svcurscr);
315 SvREFCNT_dec(SvRV(pp->svid));
318 err = SvPV(ERRSV, length);
322 err[length - 1] = '\0';
323 msgq(scrp, M_ERR, "perl: %s", err);
330 * replace a line with the contents of the perl variable $_
331 * lines are split at '\n's
332 * if $_ is undef, the line is deleted
333 * returns possibly adjusted linenumber
336 replace_line(scrp, line, t_lno, defsv)
338 db_recno_t line, *t_lno;
347 str = SvPV(defsv,len);
348 next = memchr(str, '\n', len);
349 CHAR2INTP(scrp, str, next ? (next - str) : len, wp, wlen);
350 api_sline(scrp, line, wp, wlen);
353 next = memchr(str = next, '\n', len);
354 CHAR2INTP(scrp, str, next ? (next - str) : len,
356 api_iline(scrp, ++line, wp, wlen);
360 api_dline(scrp, line--);
367 * perl_ex_perldo -- :[line [,line]] perl [command]
368 * Run a set of lines through the perl interpreter.
370 * PUBLIC: int perl_ex_perldo __P((SCR*, CHAR_T *, size_t, db_recno_t, db_recno_t));
373 perl_ex_perldo(scrp, cmdp, cmdlen, f_lno, t_lno)
377 db_recno_t f_lno, t_lno;
392 /* Initialize the interpreter. */
393 if (scrp->wp->perl_private == NULL && perl_init(scrp))
395 pp = scrp->wp->perl_private;
400 newVIrv(pp->svcurscr, scrp);
401 /* Backwards compatibility. */
402 newVIrv(pp->svid, scrp);
404 INT2CHAR(scrp, cmdp, STRLEN(cmdp)+1, np, nlen);
405 if (!(command = malloc(length = nlen - 1 + sizeof("sub {}"))))
407 snprintf(command, length, "sub {%s}", np);
412 cv = perl_eval_pv(command, FALSE);
415 estr = SvPV(ERRSV,length);
419 for (i = f_lno; i <= t_lno && !api_gline(scrp, i, &str, &len); i++) {
420 INT2CHAR(scrp, str, len, np, nlen);
421 sv_setpvn(DEFSV,np,nlen);
422 sv_setiv(pp->svstart, i);
423 sv_setiv(pp->svstop, i);
425 perl_call_sv(cv, G_SCALAR | G_EVAL);
426 estr = SvPV(ERRSV, length);
430 i = replace_line(scrp, i, &t_lno, DEFSV);
436 SvREFCNT_dec(SvRV(pp->svcurscr));
437 SvROK_off(pp->svcurscr);
438 SvREFCNT_dec(SvRV(pp->svid));
444 err: estr[length - 1] = '\0';
445 msgq(scrp, M_ERR, "perl: %s", estr);
452 * Perl message routine so that error messages are processed in
456 msghandler(sp, mtype, msg, len)
464 errmsg = PERLP(sp)->errmsg;
466 /* Replace the trailing <newline> with an EOS. */
467 /* Let's do that later instead */
468 if (errmsg) free (errmsg);
469 errmsg = malloc(len + 1);
470 memcpy(errmsg, msg, len);
472 PERLP(sp)->errmsg = errmsg;
477 typedef SCR * VI__OPT;
478 typedef SCR * VI__MAP;
479 typedef SCR * VI__MARK;
480 typedef SCR * VI__LINE;
488 typedef perl_tagq * VI__TAGQ;
489 typedef perl_tagq * VI__TAGQ2;
491 MODULE = VI PACKAGE = VI
494 # Set the message line to text.
496 # Perl Command: VI::Msg
497 # Usage: VI::Msg screenId text
508 api_imessage(screen, text);
513 # Perl Command: VI::EndScreen
514 # Usage: VI::EndScreen screenId
521 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
526 rval = api_escreen(screen);
530 # Create a new screen. If a filename is specified then the screen
531 # is opened with that file.
533 # Perl Command: VI::NewScreen
534 # Usage: VI::NewScreen screenId [file]
545 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
551 file = (items == 1) ? NULL : (char *)SvPV(ST(1),PL_na);
553 rval = api_edit(screen, file, &nsp, ix);
556 RETVAL = ix ? nsp : screen;
562 # Return the screen id associated with file name.
564 # Perl Command: VI::FindScreen
565 # Usage: VI::FindScreen file
574 RETVAL = api_fscreen(0, file);
579 # XS_VI_GetFileName --
580 # Return the file name of the screen
582 # Perl Command: VI::GetFileName
583 # Usage: VI::GetFileName screenId
591 PUSHs(sv_2mortal(newSVpv(screen->frp->name, 0)));
594 # -- Append the string text after the line in lineNumber.
596 # Perl Command: VI::AppendLine
597 # Usage: VI::AppendLine screenId lineNumber text
600 AppendLine(screen, linenumber, text)
606 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
613 rval = api_aline(screen, linenumber, text, length);
619 # Perl Command: VI::DelLine
620 # Usage: VI::DelLine screenId lineNum
623 DelLine(screen, linenumber)
628 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
633 rval = api_dline(screen, (db_recno_t)linenumber);
639 # Perl Command: VI::GetLine
640 # Usage: VI::GetLine screenId lineNumber
643 GetLine(screen, linenumber)
649 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
656 rval = api_gline(screen, (db_recno_t)linenumber, &p, &len);
660 PUSHs(sv_2mortal(newSVpv(len ? (char *)p : "", len)));
663 # Set lineNumber to the text supplied.
665 # Perl Command: VI::SetLine
666 # Usage: VI::SetLine screenId lineNumber text
669 SetLine(screen, linenumber, text)
675 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
684 CHAR2INTP(screen, text, length, line, len);
685 rval = api_sline(screen, linenumber, line, len);
689 # Insert the string text before the line in lineNumber.
691 # Perl Command: VI::InsertLine
692 # Usage: VI::InsertLine screenId lineNumber text
695 InsertLine(screen, linenumber, text)
701 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
710 CHAR2INTP(screen, text, length, line, len);
711 rval = api_iline(screen, linenumber, line, len);
715 # Return the last line in the screen.
717 # Perl Command: VI::LastLine
718 # Usage: VI::LastLine screenId
726 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
731 rval = api_lline(screen, &last);
739 # Return the mark's cursor position as a list with two elements.
742 # Perl Command: VI::GetMark
743 # Usage: VI::GetMark screenId mark
746 GetMark(screen, mark)
752 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
757 rval = api_getmark(screen, (int)mark, &cursor);
761 PUSHs(sv_2mortal(newSViv(cursor.lno)));
762 PUSHs(sv_2mortal(newSViv(cursor.cno)));
765 # Set the mark to the line and column numbers supplied.
767 # Perl Command: VI::SetMark
768 # Usage: VI::SetMark screenId mark line column
771 SetMark(screen, mark, line, column)
779 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
786 rval = api_setmark(screen, (int)mark, &cursor);
790 # Return the current cursor position as a list with two elements.
793 # Perl Command: VI::GetCursor
794 # Usage: VI::GetCursor screenId
802 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
807 rval = api_getcursor(screen, &cursor);
811 PUSHs(sv_2mortal(newSViv(cursor.lno)));
812 PUSHs(sv_2mortal(newSViv(cursor.cno)));
815 # Set the cursor to the line and column numbers supplied.
817 # Perl Command: VI::SetCursor
818 # Usage: VI::SetCursor screenId line column
821 SetCursor(screen, line, column)
828 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
835 rval = api_setcursor(screen, &cursor);
839 # Change the current focus to screen.
841 # Perl Command: VI::SwitchScreen
842 # Usage: VI::SwitchScreen screenId screenId
845 SwitchScreen(screenFrom, screenTo)
850 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
854 INITMESSAGE(screenFrom);
855 rval = api_swscreen(screenFrom, screenTo);
856 ENDMESSAGE(screenFrom);
859 # Associate a key with a perl procedure.
861 # Perl Command: VI::MapKey
862 # Usage: VI::MapKey screenId key perlproc
865 MapKey(screen, key, commandsv)
871 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
878 command = SvPV(commandsv, length);
879 rval = api_map(screen, key, command, length);
885 # Perl Command: VI::UnmapKey
886 # Usage: VI::UnmmapKey screenId key
889 UnmapKey(screen, key)
894 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
899 rval = api_unmap(screen, key);
905 # Perl Command: VI::SetOpt
906 # Usage: VI::SetOpt screenId setting
909 SetOpt(screen, setting)
914 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
920 svc = sv_2mortal(newSVpv(":set ", 5));
921 sv_catpv(svc, setting);
922 rval = api_run_str(screen, SvPV(svc, PL_na));
926 # Return the value of an option.
928 # Perl Command: VI::GetOpt
929 # Usage: VI::GetOpt screenId option
932 GetOpt(screen, option)
937 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
945 CHAR2INTP(screen, option, strlen(option)+1, wp, wlen);
946 rval = api_opts_get(screen, wp, &value, NULL);
950 PUSHs(sv_2mortal(newSVpv(value, 0)));
954 # Run the ex command cmd.
956 # Perl Command: VI::Run
957 # Usage: VI::Run screenId cmd
965 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
970 rval = api_run_str(screen, command);
981 if (sv_isa(screensv, "VI")) {
982 IV tmp = SvIV((SV*)SvRV(screensv));
983 screen = (SCR *) tmp;
986 croak("screen is not of type VI");
989 screen->perl_private = 0;
996 sv_catpv(ERRSV,warning);
998 #define TIED(kind,package) \
999 sv_magic((SV *) (var = \
1000 (kind##V *)sv_2mortal((SV *)new##kind##V())), \
1001 sv_setref_pv(sv_newmortal(), package, \
1002 newVIrv(newSV(0), screen)),\
1004 RETVAL = newRV((SV *)var)
1055 if ((ptag = malloc(sizeof(perl_tagq))) == NULL)
1058 ptag->sprv = newVIrv(newSV(0), screen);
1059 ptag->tqp = api_tagq_new(screen, tag);
1060 if (ptag->tqp != NULL) {
1062 PUSHs(sv_2mortal(sv_setref_pv(newSV(0), "VI::TAGQ", ptag)));
1065 ST(0) = &PL_sv_undef;
1069 MODULE = VI PACKAGE = VI::OPT
1076 # typemap did all the checking
1077 SvREFCNT_dec((SV*)SvIV((SV*)SvRV(ST(0))));
1085 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
1093 INITMESSAGE(screen);
1094 CHAR2INTP(screen, key, strlen(key)+1, wp, wlen);
1095 rval = api_opts_get(screen, wp, &value, &boolvalue);
1098 PUSHs(sv_2mortal((boolvalue == -1) ? newSVpv(value, 0)
1099 : newSViv(boolvalue)));
1101 } else ST(0) = &PL_sv_undef;
1106 STORE(screen, key, value)
1112 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
1118 INITMESSAGE(screen);
1119 CHAR2INTP(screen, key, strlen(key)+1, wp, wlen);
1120 rval = api_opts_set(screen, wp, SvPV(value, PL_na), SvIV(value),
1124 MODULE = VI PACKAGE = VI::MAP
1131 # typemap did all the checking
1132 SvREFCNT_dec((SV*)SvIV((SV*)SvRV(ST(0))));
1135 STORE(screen, key, commandsv)
1141 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
1147 INITMESSAGE(screen);
1148 command = SvPV(commandsv, length);
1149 rval = api_map(screen, key, command, length);
1158 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
1162 INITMESSAGE(screen);
1163 rval = api_unmap(screen, key);
1166 MODULE = VI PACKAGE = VI::MARK
1173 # typemap did all the checking
1174 SvREFCNT_dec((SV*)SvIV((SV*)SvRV(ST(0))));
1177 EXISTS(screen, mark)
1182 struct _mark cursor;
1183 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
1184 int rval = 0; /* never croak */
1188 INITMESSAGE(screen);
1189 missing = api_getmark(screen, (int)mark, &cursor);
1202 struct _mark cursor;
1203 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
1207 INITMESSAGE(screen);
1208 rval = api_getmark(screen, (int)mark, &cursor);
1211 av_push(RETVAL, newSViv(cursor.lno));
1212 av_push(RETVAL, newSViv(cursor.cno));
1218 STORE(screen, mark, pos)
1224 struct _mark cursor;
1225 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
1229 if (av_len(pos) < 1)
1230 croak("cursor position needs 2 elements");
1231 INITMESSAGE(screen);
1232 cursor.lno = SvIV(*av_fetch(pos, 0, 0));
1233 cursor.cno = SvIV(*av_fetch(pos, 1, 0));
1234 rval = api_setmark(screen, (int)mark, &cursor);
1238 FIRSTKEY(screen, ...)
1248 char key[] = {0, 0};
1253 *key = *(char *)SvPV(ST(1),PL_na);
1255 if (api_nextmark(screen, next, key) != 1) {
1257 PUSHs(sv_2mortal(newSVpv(key, 1)));
1258 } else ST(0) = &PL_sv_undef;
1260 MODULE = VI PACKAGE = VI::LINE
1267 # typemap did all the checking
1268 SvREFCNT_dec((SV*)SvIV((SV*)SvRV(ST(0))));
1270 # similar to SetLine
1273 STORE(screen, linenumber, text)
1279 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
1287 ++linenumber; /* vi 1 based ; perl 0 based */
1288 SvPV(ST(2), length);
1289 INITMESSAGE(screen);
1290 rval = api_lline(screen, &last);
1292 if (linenumber > last)
1293 rval = api_extend(screen, linenumber);
1295 CHAR2INTP(screen, text, length, line, len);
1296 rval = api_sline(screen, linenumber, line, len);
1300 # similar to GetLine
1303 FETCH(screen, linenumber)
1309 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
1315 ++linenumber; /* vi 1 based ; perl 0 based */
1316 INITMESSAGE(screen);
1317 rval = api_gline(screen, (db_recno_t)linenumber, &p, &len);
1321 PUSHs(sv_2mortal(newSVpv(len ? (char*)p : "", len)));
1323 # similar to LastLine
1331 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
1335 INITMESSAGE(screen);
1336 rval = api_lline(screen, &last);
1344 STORESIZE(screen, count)
1350 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
1354 INITMESSAGE(screen);
1355 rval = api_lline(screen, &last);
1358 rval = api_extend(screen, count);
1359 else while(last && last > count) {
1360 rval = api_dline(screen, last--);
1367 EXTEND(screen, count)
1379 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
1383 INITMESSAGE(screen);
1384 rval = api_lline(screen, &last);
1387 rval = api_dline(screen, last--);
1399 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
1404 INITMESSAGE(screen);
1405 rval = api_lline(screen, &last);
1408 for (i = 1; i < items; ++i) {
1409 line = SvPV(ST(i), len);
1410 if ((rval = api_aline(screen, last++, line, len)))
1421 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
1426 INITMESSAGE(screen);
1427 rval = api_lline(screen, &last);
1428 if (rval || last < 1)
1429 ST(0) = &PL_sv_undef;
1431 rval = api_gline(screen, last, &line, &len) ||
1432 api_dline(screen, last);
1434 PUSHs(sv_2mortal(newSVpv(len ? (char *)line : "", len)));
1444 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
1449 INITMESSAGE(screen);
1450 rval = api_lline(screen, &last);
1451 if (rval || last < 1)
1452 ST(0) = &PL_sv_undef;
1454 rval = api_gline(screen, (db_recno_t)1, &line, &len) ||
1455 api_dline(screen, (db_recno_t)1);
1457 PUSHs(sv_2mortal(newSVpv(len ? (char *)line : "", len)));
1462 UNSHIFT(screen, ...)
1466 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
1473 INITMESSAGE(screen);
1474 while (--items != 0) {
1475 np = SvPV(ST(items), nlen);
1476 CHAR2INTP(screen, np, nlen, line, len);
1477 if ((rval = api_iline(screen, (db_recno_t)1, line, len)))
1487 db_recno_t last, db_offset;
1488 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
1489 int rval, length, common, len, i, offset;
1495 INITMESSAGE(screen);
1496 rval = api_lline(screen, &last);
1497 offset = items > 1 ? (int)SvIV(ST(1)) : 0;
1498 if (offset < 0) offset += last;
1501 croak("Invalid offset");
1503 length = items > 2 ? (int)SvIV(ST(2)) : last - offset;
1504 if (length > last - offset)
1505 length = last - offset;
1506 db_offset = offset + 1; /* 1 based */
1508 for (common = MIN(length, items - 3), i = 3; common > 0;
1509 --common, ++db_offset, --length, ++i) {
1510 rval |= api_gline(screen, db_offset, &line, &len);
1511 INT2CHAR(screen, line, len, np, nlen);
1512 PUSHs(sv_2mortal(newSVpv(nlen ? np : "", nlen)));
1513 np = SvPV(ST(i), nlen);
1514 CHAR2INTP(screen, np, nlen, line, len);
1515 rval |= api_sline(screen, db_offset, line, len);
1517 for (; length; --length) {
1518 rval |= api_gline(screen, db_offset, &line, &len);
1519 INT2CHAR(screen, line, len, np, nlen);
1520 PUSHs(sv_2mortal(newSVpv(len ? np : "", nlen)));
1521 rval |= api_dline(screen, db_offset);
1523 for (; i < items; ++i) {
1524 np = SvPV(ST(i), len);
1525 CHAR2INTP(screen, np, len, line, nlen);
1526 rval |= api_iline(screen, db_offset, line, nlen);
1530 MODULE = VI PACKAGE = VI::TAGQ
1533 Add(tagq, filename, search, msg)
1543 sp = (SCR *)SvIV((SV*)SvRV(tagq->sprv));
1545 croak("screen no longer exists");
1546 api_tagq_add(sp, tagq->tqp, filename, search, msg);
1556 sp = (SCR *)SvIV((SV*)SvRV(tagq->sprv));
1558 croak("screen no longer exists");
1559 api_tagq_push(sp, &tagq->tqp);
1563 # Can already be invalidated by push
1570 sp = (SCR *)SvIV((SV*)SvRV(tagq->sprv));
1572 api_tagq_free(sp, tagq->tqp);
1573 SvREFCNT_dec(tagq->sprv);