1 /*
2  * perl.xs		-- perl interface for vile.
3  *
4  * Author: Kevin Buettner, Brendan O'Dea
5  *
6  * (with acknowledgments to the authors of the nvi perl interface and
7  * to Sean Ahern who has contributed snippets of code here and there
8  * and many valuable suggestions.)
9  *
10  * Created: Fall, 1997
11  *
12  * Description: The following code provides an interface to Perl from
13  * vile.  The file api.c (sometimes) provides a middle layer between
14  * this interface and the rest of vile.
15  *
16  * $Id: perl.xs,v 1.143 2021/12/07 01:40:25 tom Exp $
17  */
18 
19 /*
20  * Perl's header (and macro expansions) produce too many warnings to be useful.
21  */
22 #ifdef __GNUC__
23 #pragma GCC diagnostic ignored "-Wcast-qual"
24 #pragma GCC diagnostic ignored "-Wcompound-token-split-by-macro"
25 #pragma GCC diagnostic ignored "-Wconversion"
26 #pragma GCC diagnostic ignored "-Wnested-externs"
27 #pragma GCC diagnostic ignored "-Wshadow"
28 #pragma GCC diagnostic ignored "-Wpedantic"
29 #pragma GCC diagnostic ignored "-Wsign-conversion"
30 #pragma GCC diagnostic ignored "-Wunused-variable"
31 #pragma GCC diagnostic push
32 #pragma GCC diagnostic ignored "-Wundef"
33 #endif
34 
35 /*#
36   #
37   # Note: This embedded documentation may be retrieved for formatting
38   # with one of the pod transformers as follows.  To make the
39   # pod file, do
40   #
41   #     perl -lne 'print if s/^\s{1,2}#\s{0,1}//' perl.xs
42   #
43   # To transform the pod file into something nicely formatted, do
44   # one or more of the following:
45   #
46   #     pod2text vile-perl-api.pod >vile-perl-api.doc
47   #
48   #     pod2html vile-perl-api.pod >vile-perl-api.html
49   #
50   #     pod2man  vile-perl-api.pod >vile-perl-api.man
51   #
52   #     pod2latex vile-perl-api.pod >vile-perl-api.latex
53   #
54   # I experimented with different formatting layouts.  I found that I
55   # was unable to dispense with the initial transformation because
56   # xsubpp doesn't like it when some of my pod documentation started
57   # in the left-most column.  I've also found that placing the # in
58   # the left-most column will sometimes screw up xsubpp wrt to
59   # preprocessor statements.  It does not get confused when when there
60   # are one or more spaces preceding the pound sign.  I usually like
61   # to indent things by four spaces, and yet I wanted to use ^A-f in
62   # vile to reformat things, so I settled on two spaces, followed by
63   # a pound sign, followed by a single space, followed by whatever
64   # as the most pleasing layout.
65   #
66   #
67   # =pod
68   #
69   # =head1 NAME
70   #
71   # vile-perl-api       -- Vile/Perl interface reference
72   #
73   # =head1 DESCRIPTION
74   #
75   # This document describes the interface by which by Perl scripts may
76   # access the I<vile> editor's internals when run from an editor in which
77   # Perl has been embedded.
78   #
79   # There are presently two packages which comprise this interface.  They
80   # are:
81   #
82   # =over 4
83   #
84   # =item Vile
85   #
86   # Subroutines for accessing and controlling vile in general.
87   #
88   # =for html <br><br>
89   #
90   # =item Vile::Buffer
91   #
92   # Subroutines and methods for accessing individual buffers.
93   #
94   # =for html <br><br>
95   #
96   # =item Vile::Window
97   #
98   # Subroutines and methods for manipulating Vile's windows.
99   #
100   # =back
101   #
102   # =head2 Calling Perl from Vile
103   #
104   # The perl interpreter may be invoked from I<vile> using either
105   # the I<perl> or I<perldo> commands.
106   #
107   # =over 4
108   #
109  */
110 
111 #ifdef WIN32
112 #include "w32vile.h"
113 #undef WIN32_LEAN_AND_MEAN
114 #endif
115 
116 #if !(defined(__GNUC__) || defined(__attribute__))
117 #define __attribute__(p) /*nothing*/
118 #endif
119 
120 /* for vile */
121 #define MARK vile_MARK
122 #include "estruct.h"
123 #include "edef.h"
124 #include "api.h"
125 #undef MARK
126 #undef ABORT
127 
128 /* for perl */
129 #define main perl_main
130 #define regexp perl_regexp
131 #include <EXTERN.h>
132 #include <perl.h>
133 #include <XSUB.h>
134 #undef main
135 #undef regexp
136 #undef dofile
137 
138 #ifdef __GNUC__
139 #pragma GCC diagnostic pop
140 #endif
141 
142 /* Some earlier versions of perl don't have GIMME_V or G_VOID. We must
143    be careful of the order in which we check things if these defines
144    are activated. */
145 #ifndef GIMME_V
146 #define GIMME_V GIMME
147 #endif
148 
149 #ifndef G_VOID
150 #define G_VOID G_SCALAR
151 #endif
152 
153 #ifndef INT2PTR
154 #define INT2PTR(n) (n)
155 #endif
156 
157 /* Prior to perl5.005, the PL_ prefix wasn't used for things such
158    as PL_rs.  Define the PL_ macros that we use if necessary. */
159 
160 #include <patchlevel.h>		/* This is perl's patchlevel.h */
161 
162 #ifndef pTHX
163 #define pTHX			/* nothing */
164 #endif
165 
166 #ifndef pTHX_
167 #define pTHX_			/* nothing */
168 #endif
169 
170 #ifndef PERL_MAGIC_tiedscalar
171 #define	PERL_MAGIC_tiedscalar	'q'
172 #endif
173 
174 #ifndef PERL_MAGIC_ext
175 #define	PERL_MAGIC_ext		'~'
176 #endif
177 
178 #if !defined(__PATCHLEVEL_H_INCLUDED__) && !defined(SUBVERSION)
179 #error The patchlevel.h file is probably not from Perl
180 #endif
181 
182 #ifndef PERL_VERSION
183 #ifdef  PATCHLEVEL
184 #define PERL_VERSION PATCHLEVEL
185 #else
186 #error The patchlevel.h file does not define PATCHLEVEL
187 #endif
188 #endif
189 
190 #if PERL_VERSION < 5		/* before perl 5.5 */
191 #define PL_incgv	incgv
192 #define PL_rs		rs
193 #define PL_errgv	errgv
194 #define PL_na		na
195 #define PL_sv_undef	sv_undef
196 #endif
197 
198 #define PDEBUG 0		/* For debugging reference counts */
199 
200 static PerlInterpreter *perl_interp;
201 static int use_ml_as_prompt;
202 static SV *svcurbuf;		/* $Vile::current_buffer in perl */
203 static int svcurbuf_set(pTHX_ SV *, MAGIC *);
204 static WINDOW * set_curwp0(WINDOW *wp);
205 static MGVTBL svcurbuf_accessors = {
206 	/* Virtual table for svcurbuf magic. */
207 	NULL, svcurbuf_set, NULL, NULL, NULL
208 #if PERL_VERSION >= 8
209 	, NULL, NULL
210 #endif
211 #if PERL_VERSION >= 10
212 	, NULL
213 #endif
214 };
215 
216 static SV *ofs_sv;
217 static SV *ors_sv;
218 
219 #ifdef PERL_SYS_INIT3
220 #define USE_SYS_INIT3 1
221 #endif
222 
223 static int real_perl_init(void);
224 static void xs_init(pTHX);
225 static int  perl_prompt(void);
226 static int  perldo_prompt(void);
227 
228 /* tie a filehandle */
229 static void
tie_handle(SV * sv,SV * obj)230 tie_handle(SV *sv, SV *obj)
231 {
232     SV *tie = sv;
233 #if PERL_VERSION >= 8
234     if (!GvIOp(sv))
235 	GvIOp(sv) = newIO();
236 
237     tie = (SV *) GvIOp(sv);
238 #endif
239 
240     sv_magic(tie, obj, PERL_MAGIC_tiedscalar, Nullch, 0);
241 }
242 
243 /* write each line to message line */
244 static int
write_message(const char * prefix,SV * sv)245 write_message(const char *prefix, SV *sv)
246 {
247     int count = 0;
248     char *text = SvPV(sv, PL_na);
249     char *nl;
250 
251     while (text)
252     {
253 	if ((nl = strchr(text, '\n')) != 0)
254 	{
255 	    *nl = 0;
256 	    mktrimmed(text);
257 	    while (*++nl == '\n')
258 		;
259 
260 	    if (!*nl)
261 		nl = 0;
262 	}
263 
264 	if (*text)
265 	    mlforce("%s%s", prefix, text);
266 	else
267 	    mlerase();
268 	text = nl;
269 	count++;
270     }
271 
272     return count;
273 }
274 
275 /* require a file, `optional' indicates that it is OK for the file not
276    to exist */
277 static int
require(const char * file,int optional)278 require(const char *file, int optional)
279 {
280     TRACE((T_CALLED "Vile::require(%s,%s)\n", file, optional ? "optional" : "required"));
281     /* require the file */
282     perl_require_pv(file);
283 
284     /* OK */
285     if (!SvTRUE(GvSV(PL_errgv)))
286 	returnCode(TRUE);
287 
288     if (optional)
289     {
290 	/* this error is OK for optional files */
291 	SV *tmp = newSVpv("Can't locate ", (size_t) 0);
292 	char const *my_check;
293 	STRLEN sz;
294 	int not_found;
295 
296 	sv_catpv(tmp, file);
297 	sv_catpv(tmp, " ");
298 	my_check = SvPV(tmp, sz);
299 	not_found = !strncmp(SvPV(GvSV(PL_errgv), PL_na), my_check, sz);
300 	SvREFCNT_dec(tmp);
301 
302 	if (not_found)
303 	    returnCode(SORTOFTRUE);
304     }
305 
306     write_message("perl require:", GvSV(PL_errgv));
307     returnCode(FALSE);
308 }
309 
310 /* When no region is specified, this will cause the entire buffer to
311    be selected without moving DOT. */
312 void
perl_default_region(void)313 perl_default_region(void)
314 {
315     static REGION region;
316     vile_MARK save_DOT = DOT;
317 
318     DOT.l = lforw(buf_head(curbp));
319     DOT.o = b_left_margin(curbp);
320 
321     MK.l  = lback(buf_head(curbp));
322     MK.o  = b_left_margin(curbp);
323 
324     regionshape = rgn_FULLLINE;
325     haveregion = NULL;
326     if (getregion(curbp, &region)) {
327 	haveregion = &region;
328 	/* This should really go in getregion(), but other parts of
329 	   vile break when we do this. */
330 	if (is_header_line(region.r_end, curbp) && !b_val(curbp, MDNEWLINE))
331 	    region.r_size -= (B_COUNT) len_record_sep(curbp);
332     }
333     DOT = save_DOT;
334 }
335 
336 /*
337  * Create a VB buffer handle object.  These objects are both
338  * blessed into the Vile::Buffer class as well as made magical
339  * so that they may also be used as filehandles.
340  */
341 static SV *
newVBrv(SV * rv,VileBuf * sp)342 newVBrv(SV *rv, VileBuf *sp)
343 {
344     if (sp->perl_handle == 0) {
345 	sp->perl_handle = newGVgen("Vile::Buffer");
346 	GvSV((GV*)sp->perl_handle) = newSV((size_t) 0);
347 	sv_setiv(GvSV((GV*)sp->perl_handle), PTR2IV(sp));
348 	tie_handle(sp->perl_handle, rv);
349 	gv_IOadd((GV*)sp->perl_handle);
350 	IoLINES(GvIO((GV*)sp->perl_handle)) = 0;	/* initialise $. */
351     }
352 
353     sv_upgrade(rv, SVt_RV);
354     SvRV(rv) = sp->perl_handle;
355     SvREFCNT_inc(SvRV(rv));
356     SvROK_on(rv);
357     rv = sv_bless(rv, gv_stashpv("Vile::Buffer", TRUE));
358 #if PDEBUG
359     fprintf(stderr, "newVBrv: ");
360     sv_dump(rv);
361 #endif
362     return rv;
363 }
364 
365 static VileBuf *
getVB(SV * sv,const char ** croakmessage_ptr)366 getVB(SV *sv, const char **croakmessage_ptr)
367 {
368     VileBuf *vbp = 0;
369     if (sv_isa(sv, "Vile::Buffer")) {
370 	vbp = INT2PTR(VileBuf *, SvIV((SV*)GvSV((GV*)SvRV(sv))));
371 	if (vbp == 0) {
372 	    *croakmessage_ptr = "buffer no longer exists";
373 	}
374     }
375     else {
376 	*croakmessage_ptr = "buffer of wrong type";
377     }
378     return vbp;
379 }
380 
381 void
perl_free_handle(void * handle)382 perl_free_handle(void *handle)
383 {
384     /* Remove the magic from the handle.  This should break the
385        circular structure which would otherwise prevent the handle
386        from getting freed. */
387     sv_unmagic(handle, PERL_MAGIC_tiedscalar);
388 #if PDEBUG
389     fprintf(stderr, "In perl_free_handle: ");
390     sv_dump((SV*)handle);
391 #endif
392     /*
393      * Zero out perl's handle to the VileBuf structure
394      */
395     sv_setiv(GvSV((GV*)handle), (size_t) 0);
396 
397     /*
398      * Decrement the reference count to indicate the fact that
399      * we are no longer referencing it from the api private structure.
400      * If there aren't any other references from within perl either,
401      * then this scalar will be collected.
402      */
403     SvREFCNT_dec(handle);
404 }
405 
406 /*
407  * Create a VileWin object.  This is a good deal simpler than a VileBuf
408  * since we are merely taking a reference to an integer (the windows
409  * id) and blessing it.
410  */
411 static SV *
newVWrv(SV * rv,VileWin vw)412 newVWrv(SV *rv, VileWin vw)
413 {
414     sv_upgrade(rv, SVt_RV);
415     SvRV(rv) = newSViv((IV)win2id(vw));
416     SvROK_on(rv);
417     rv = sv_bless(rv, gv_stashpv("Vile::Window", TRUE));
418 #if PDEBUG
419     fprintf(stderr, "newVWrv: ");
420     sv_dump(rv);
421 #endif
422     return rv;
423 }
424 
425 static VileWin
getVW(SV * sv,const char ** croakmessage_ptr)426 getVW(SV *sv, const char **croakmessage_ptr)
427 {
428     VileWin vw = 0;
429     if (sv_isa(sv, "Vile::Window")) {
430 	vw = id2win((WIN_ID)SvIV((SV*)SvRV(sv)));
431 	if (!vw) {
432 	    *croakmessage_ptr = "window no longer exists";
433 	}
434     }
435     else {
436 	*croakmessage_ptr = "window of wrong type";
437     }
438     return vw;
439 }
440 
441 static int recursecount = 0;
442 
443 static int
do_perl_cmd(SV * cmd,int inplace)444 do_perl_cmd(SV *cmd, int inplace)
445 {
446     int old_isnamedcmd;
447     REGION region;
448     VileBuf *curvbp;
449 
450     TRACE((T_CALLED "do_perl_cmd\n"));
451 
452     use_ml_as_prompt = 0;
453 
454     if (recursecount == 0) {
455 	curvbp = api_bp2vbp(curbp);
456 	if (curvbp == 0)
457 	    returnCode(FALSE);
458 
459 	if (DOT.l == 0 || MK.l == 0 || getregion(curbp, &region) != TRUE) {
460 	    /* shouldn't ever get here. But just in case... */
461 	    perl_default_region();
462 	    if (getregion(curbp, &region) != TRUE) {
463 		mlforce("BUG: getregion won't return TRUE in perl.xs.");
464 	    }
465 	}
466 	if (is_header_line(region.r_end, curbp) && !b_val(curbp, MDNEWLINE))
467 	    region.r_size -= (B_COUNT) len_record_sep(curbp);
468 
469 	/* Initialize some of the fields in curvbp */
470 	curvbp->region = region;
471 	curvbp->regionshape = regionshape;
472 	curvbp->inplace_edit = inplace;
473 
474 	{
475 	    SV *sv = newVBrv(newSV((size_t) 0), curvbp);
476 	    sv_setsv(svcurbuf, sv);
477 	    SvREFCNT_dec(sv);
478 	}
479 	IoLINES(GvIO((GV*)curvbp->perl_handle)) = 0;  /* initialise $. */
480     }
481 
482     /* Make sure that mlreply_dir and mlreply_file will actually prompt
483        the user.  It is necessary to do this because isnamedcmd was not
484        getting set when invoked through a binding. */
485     old_isnamedcmd = isnamedcmd;
486     isnamedcmd = TRUE;
487 
488     recursecount++;
489 
490 #if PDEBUG
491     fprintf(stderr, "do_perl_command: before eval:\n");
492     sv_dump(svcurbuf);
493 #endif
494     sv_setpv(GvSV(PL_errgv),"");
495     if (SvROK(cmd) && SvTYPE(SvRV(cmd)) == SVt_PVCV)
496     {
497 	dSP;
498 	PUSHMARK(sp);
499 	PUTBACK;
500 	perl_call_sv(cmd, G_EVAL|G_VOID|G_DISCARD);
501     }
502     else
503 	perl_eval_sv(cmd, G_DISCARD|G_NOARGS|G_KEEPERR);
504 #if PDEBUG
505     fprintf(stderr, "do_perl_command: after eval: \n");
506     sv_dump(svcurbuf);
507 #endif
508 
509     isnamedcmd = old_isnamedcmd;
510     recursecount--;
511     if (recursecount == 0) {
512 	sv_setsv(svcurbuf, &PL_sv_undef);
513 	api_command_cleanup();
514     }
515     else {
516 	/* We don't do the hardcore cleanup if we're recursing, but
517 	   we at least need to make sure that curwp points at a
518 	   visible window */
519 	if (curwp_visible)
520 	    set_curwp0(curwp_visible);
521     }
522     if (!is_visible_window(curwp))
523 	mlforce("BUG: curwp not set to a visible window");
524 
525     if (SvTRUE(GvSV(PL_errgv)) == 0)
526 	returnCode(TRUE);
527 
528     write_message("perl cmd:", GvSV(PL_errgv));
529     returnCode(FALSE);
530 }
531 
532 /*
533  * procedures for bindable callbacks: see Vile::register*
534  */
535 
536 static SV *opsv;
537 
538 static int
perl_oper(void)539 perl_oper(void)
540 {
541     TRACE((T_CALLED "perl_oper\n"));
542     returnCode(do_perl_cmd(opsv, FALSE));
543 }
544 
545 int
perl_call_sub(void * data,int oper,int f,int n)546 perl_call_sub(void *data, int oper, int f, int n)
547 {
548     AV *av = data;	/* callback is an array containing: */
549     SV **name = 0;	/* the registered name, */
550     SV **sub = 0;	/* a sub name or coderef to call, */
551     SV **req = 0;	/* and an [optional] file to require */
552 
553     TRACE((T_CALLED "perl_call_sub\n"));
554     switch (av_len(av))
555     {
556 	case 2: /* (name, sub, require) */
557 	    if ((req = av_fetch(av, 2, 0)) != 0 && SvTRUE(*req))
558 		if (!require(SvPV(*req, PL_na), FALSE))
559 		    returnCode(FALSE);
560 
561 	    /* FALLTHRU */
562 
563 	case 1: /* (name, sub) */
564 	    if ((name = av_fetch(av, 0, 0)) == 0 || !SvTRUE(*name))
565 		croak("BUG: can't fetch name SV");
566 
567 	    if ((sub = av_fetch(av, 1, 0)) == 0 || !SvTRUE(*sub))
568 		croak("BUG: can't fetch subroutine SV");
569 
570 	    break;
571 
572 	default:
573 	    croak("BUG: array contains %d elements", (int) av_len(av) + 1);
574     }
575 
576     /* call the subroutine */
577     if (oper)
578     {
579 	opcmd = OPOTHER;
580 	opsv = *sub;
581 	f = vile_op(f, n, perl_oper, SvPV(*name, PL_na));
582     }
583     else
584     {
585 	if (!f)
586 	    n = 1;
587 
588 	while (n-- && (f = do_perl_cmd(*sub, FALSE)) != 0)
589 	    ;
590     }
591 
592     returnCode(f);
593 }
594 
595 void
perl_free_sub(void * data)596 perl_free_sub(void *data)
597 {
598     AV *av = data;
599     av_undef(av);
600 }
601 
602 /*
603  * Prompt for and execute a perl command.
604  *
605  * This function is actually only a wrapper for perl_prompt below to make
606  * the history management easier.
607  *
608   #
609   # =item :perl STMTS
610   #
611   # The I<perl> command will cause perl to execute one or more
612   # perl statements.  The user is usually prompted for the statements
613   # to execute immediately after ":perl " is entered.  The user is
614   # expected to enter legal perl statements or expressions.  These
615   # statements must all fit on one line.  (Vile's :-line will scroll
616   # horizontally though, so don't worry about running out of space.)
617   #
618   # The perl command may also appear in macros in vile's internal
619   # macro language, in which case the perl statements to execute must
620   # appear as a double quoted string to the perl command.  The user
621   # is not prompted in this case.
622   #
623   # Regardless, prior to execution, the global variable,
624   # C<$Vile::>C<current_buffer> is set to an object of type C<Vile::Buffer>
625   # which represents the current buffer.  The statements to be executed
626   # may choose to act either directly or indirectly on the current
627   # buffer via this variable or a suitable alias.
628   #
629   # Normally, the cursor's current position, also referred to as I<dot>,
630   # is left unchanged upon return from perl.  It can be propagated
631   # back to a viewable window by explicitly setting via the
632   # C<Vile::Buffer::>C<dot> method.
633   #
634   # For purposes of reading from the buffer, there is always a region
635   # associated with the buffer object.  By default, this region is the
636   # entire buffer.  (Which means that potentially, the entire buffer
637   # may be acted upon.) This range may be restricted by the user in
638   # the normal way through the use of a range specification which
639   # precedes the perl command.   E.g,
640   #
641   #     30,40perl @l = <$Vile::current_buffer>
642   #
643   # will cause lines 30 thru 40 to be placed into the @l array.
644   #
645   # =for html <br><br>
646   #
647  */
648 
649 int
perl(int f GCC_UNUSED,int n GCC_UNUSED)650 perl(int f GCC_UNUSED, int n GCC_UNUSED)
651 {
652     int status = FALSE;
653 
654 #if OPT_HISTORY
655     if (recursecount == 0)
656 	hst_init(EOS);
657 #endif
658 
659     if (perl_interp || real_perl_init())
660 	status = perl_prompt();
661 
662 #if OPT_HISTORY
663     if (recursecount == 0)
664 	hst_flush();
665 #endif
666 
667     return status;
668 }
669 
670 static int
perl_prompt(void)671 perl_prompt(void)
672 {
673     register int status;
674     char buf[NLINE];	/* buffer to receive command into */
675     SV *cmd;
676 
677     TRACE((T_CALLED "perl_prompt\n"));
678 
679     buf[0] = EOS;
680     if ((status = mlreply_no_opts("Perl command: ", buf, (UINT) sizeof(buf))) != TRUE)
681 	returnCode(status);
682 
683     /* Hack to workaround problem with perl5.005 in which package Dynaloader
684        sometimes winds up being the current package */
685 #if 0
686     /* This is what the code ought to look like... */
687     cmd = newSVpv(buf, 0);
688 #else
689     /* This is the hack... */
690     cmd = newSVpv("package main; ", (size_t) 0);
691     sv_catpv(cmd, buf);
692 #endif
693     status = do_perl_cmd(cmd, FALSE);
694     SvREFCNT_dec(cmd);
695     returnCode(status);
696 }
697 
698 #define isoctal(c) ((c) >= '0' && (c) <= '7')
octal(char ** s)699 static int octal(char **s)
700 {
701     int oct = 0;
702     int i = (**s > '3') ? 2 : 3;
703 
704     while (i-- && isoctal(**s))
705     {
706 	oct *= 8;
707 	oct += *((*s)++) - '0';
708     }
709 
710     return oct;
711 }
712 
713 /*#
714   #
715   # =item :perldo STMTS <Enter> OPTIONS
716   #
717   # The I<perldo> command is like the perl command, but it takes
718   # various options making it possible to write "one liners" to
719   # operate on the current buffer in much the same way that you might
720   # write a one line perl command at the prompt of your favorite shell
721   # to operate on a file.  The options even mimic those provided by
722   # the perl interpreter, so if you are familiar with one, you'll be
723   # familiar with the other.
724   #
725   # After entering the perldo command (preceded by an optional range
726   # specification) on the :-line, the user will be prompted for some
727   # perl statements to execute.  These should usually be written to
728   # operate on the $_ variable and leave the result in $_.
729   #
730   # After pressing the B<Enter> key, you'll be prompted for a set
731   # of options.  The default options are -lpi and will even be displayed
732   # as such.  The B<-i> switch causes the buffer to be edited in place.
733   # The B<-p> switch causes the user supplied statements to be placed
734   # in a loop which fetches lines one by one place them in $_ for each
735   # iteration of the loop along with a trailing C<print> which'll cause
736   # whatever's left in $_ to be put back into the buffer.  The B<-l> switch
737   # causes an initial chomp to be done on each line after it is read.
738   # It will also cause the output record separator to be set so that
739   # when $_ is written back to the buffer, it will end up on a line of
740   # its own.
741   #
742   # For example, the command:
743   #
744   #     :25,30perldo $_ = sprintf("%4d",$lnum++) . $_
745   #                  -lpi
746   #
747   # will cause each line in between 20 and 30 inclusive to be prefixed
748   # with a the number given by $lnum, which is also incremented for
749   # each line processed.  You'll probably want to initialize $lnum to
750   # some appropriate value via the I<perl> command first, perhaps
751   # like this:
752   #
753   #     :perl $lnum = 142;
754   #
755   # [I include this example, because this is something that I've
756   # wanted to do from time to time, when citing snippets of code
757   # which I want to discuss in an email message.]
758   #
759   # =item perldo options
760   #
761   # =for html <br><br>
762   #
763   # =over 4
764   #
765   # =item -n
766   #
767   # Enclose the perl statement(s) in a loop which iterates of the records
768   # (usually lines) of the region.  Each record in the region will
769   # be placed in $_.
770   #
771   # =for html <br><br>
772   #
773   # =item -p
774   #
775   # Like B<-n>, but do a print (of $_) at the end of the loop.
776   #
777   # =for html <br><br>
778   #
779   # =item -i
780   #
781   # Enable the I<inplace_edit> flag for the buffer.  When used with
782   # either B<-n> or B<-p>, this will cause the lines to be deleted from the
783   # buffer as they are read.
784   #
785   # Unlike the corresponding perl command line switch, it is not possible
786   # to specify a backup file.  If you don't like what happens, just hit
787   # the 'B<u>' key to undo it.
788   #
789   # =for html <br><br>
790   #
791   # =item -l
792   #
793   # Only meaningful when used with either B<-n> or B<-p>.  This will
794   # perform an initial chomp on $_ after a record has been read.
795   #
796   # =for html <br><br>
797   #
798   # =item -0
799   #
800   # This must be followed by one or more digits which represent the
801   # value with which to set $/ (which is the input record separator).
802   # The special value B<00> indicates that $/ should be set to the
803   # empty string which will cause Perl to slurp input in paragraph
804   # mode.  The special value 0777 indicates that perl should slurp
805   # the entire region without paying attention to record separators.
806   # Normally, $/ is set to '\n' which corresponds to -012
807   #
808   # =for html <br><br>
809   #
810   # =item -a
811   #
812   # Turn on autosplit mode.  Upon being read, each record is split
813   # into the @F array.
814   #
815   # =for html <br><br>
816   #
817   # =item -F
818   #
819   # When used with B<-a>, specify an alternate pattern to split on.
820   #
821   # =for html <br><br>
822   #
823   # =back
824   #
825   # The default region for the perldo command is the line on which
826   # the cursor is currently on.  The reason for this is that it is
827   # often used like vile's builtin substitute operator is and this
828   # is the default region for the substitute command.  You can of
829   # course use any of the standard means to operate over larger
830   # regions, e.g,
831   #
832   #     :1,$perldo s/a/b/g
833   #
834   #
835  */
836 
837 int
perldo(int f GCC_UNUSED,int n GCC_UNUSED)838 perldo(int f GCC_UNUSED, int n GCC_UNUSED)
839 {
840     int status = FALSE;
841 
842 #if OPT_HISTORY
843     hst_init(EOS);
844 #endif
845 
846     if (perl_interp || real_perl_init())
847 	status = perldo_prompt();
848 
849 #if OPT_HISTORY
850     hst_flush();
851 #endif
852 
853     return status;
854 }
855 
856 static int
perldo_prompt(void)857 perldo_prompt(void)
858 {
859     register int status;
860     char buf[NLINE];	/* buffer to receive command into */
861     char obuf[NLINE];	/* buffer for options */
862     SV *cmd;		/* constructed command string */
863 
864 #define	OPT_i	001
865 #define	OPT_n	002
866 #define	OPT_p	004
867 #define	OPT_l	010
868 #define	OPT_a	020
869     int opts = 0;
870     char *o = obuf;
871     char *split = "' '";
872 
873 #define	RS_PARA	0776
874 #define	RS_NONE	0777
875     int i_rs = '\n';
876     int o_rs = RS_NONE;
877 
878     TRACE((T_CALLED "perldo_prompt\n"));
879 
880     buf[0] = EOS;
881     if ((status = mlreply_no_opts("Perl command: ", buf, (UINT) sizeof(buf))) != TRUE)
882 	returnCode(status);
883 
884 #if OPT_HISTORY
885     hst_glue('\r');
886 #endif
887 
888     strcpy(obuf, "-lpi");
889     if ((status = mlreply_no_opts("options: ", obuf, (UINT) sizeof(obuf))) != TRUE)
890 	returnCode(status);
891 
892     /* skip optional leading `-' */
893     if (*o == '-')
894 	o++;
895 
896     /* parse options */
897     while (*o)
898 	switch (*o)
899 	{
900 	case 'a': opts |= OPT_a; o++; break;
901 	case 'i': opts |= OPT_i; o++; break;
902 	case 'n': opts &= ~OPT_p; opts |= OPT_n; o++; break;
903 	case 'p': opts &= ~OPT_n; opts |= OPT_p; o++; break;
904 	case 'l':
905 	    opts |= OPT_l;
906 	    o++;
907 	    if (isoctal(*o))
908 		o_rs = octal(&o);
909 	    else
910 		o_rs = i_rs;
911 
912 	    break;
913 
914 	case '0':
915 	    /* special cases: 00, 0777 */
916 	    if (*++o == '0' && !isoctal(*(o+1)))
917 	    {
918 		i_rs = RS_PARA;
919 		o++;
920 	    }
921 	    else if (!strncmp(o, "777", (size_t) 3))
922 	    {
923 		i_rs = RS_NONE;
924 		o += 3;
925 	    }
926 	    else
927 		i_rs = octal(&o);
928 
929 	    break;
930 
931 	case 'F':
932 	    opts |= OPT_a; /* implied */
933 	    if (*++o == '/' || *o == '"' || *o == '\'')
934 	    {
935 		char sep = *o;
936 		char esc = 0;
937 
938 		split = o++;
939 		while (*o)
940 		{
941 		    if (*o == sep && !esc)
942 		    {
943 			o++;
944 			break;
945 		    }
946 
947 		    if (*o++ == '\\')
948 			esc ^= 1;
949 		    else
950 			esc = 0;
951 		}
952 
953 		if (*o && *o != ' ')
954 		{
955 		    mlforce("[no closing %c]", sep);
956 		    returnCode(FALSE);
957 		}
958 	    }
959 	    else if (*o)
960 	    {
961 		split = o++;
962 		while (*o && *o != ' ') o++;
963 	    }
964 	    else
965 	    {
966 		mlforce("[-F requires an argument]");
967 		returnCode(FALSE);
968 	    }
969 
970 	    if (*o)
971 		*o++ = 0; /* terminate */
972 		/* FALLTHRU */
973 	    else
974 		break;
975 
976 	case ' ':
977 	    while (*o == ' ') o++;
978 	    if (!*o)
979 		break; /* trailing spaces */
980 
981 	    if (*o == '-' && *(o+1))
982 	    {
983 		o++;
984 		break;
985 	    }
986 
987 	    /* FALLTHRU */
988 
989 	default:
990 	    mlforce("[invalid option -%s]", o);
991 	    returnCode(FALSE);
992 	}
993 
994     /* construct command: block with localised $/ and $\ */
995 #if 0	/* See comment in perl_prompt() regarding this hack... */
996     /* No hack */
997     cmd = newSVpv("{local $/=", 0); /*}*/
998 #else
999     /* Package name hack - works around a bug in perl5.00503 */
1000     cmd = newSVpv("package main; {local $/=", (size_t) 0); /*}*/
1001 #endif
1002     if (i_rs == RS_NONE)
1003 	sv_catpv(cmd, "undef");
1004     else if (i_rs == RS_PARA)
1005 	sv_catpv(cmd, "''");
1006     else
1007 	sv_catpvf(cmd, "\"\\x%02x\"", i_rs);
1008 
1009     sv_catpv(cmd, ";local $\\=");
1010     if (o_rs == RS_NONE)
1011 	sv_catpv(cmd, "undef");
1012     else if (o_rs == RS_PARA)
1013 	sv_catpv(cmd, "\"\\n\\n\"");
1014     else
1015 	sv_catpvf(cmd, "\"\\x%02x\"", o_rs);
1016 
1017     /* set default output handle */
1018     sv_catpv(cmd, ";my $_save_fh=select ");
1019     if (opts & OPT_i)
1020 	sv_catpv(cmd, "$Vile::current_buffer"); /* -i goes to buffer */
1021     else
1022 	sv_catpv(cmd, "STDOUT"); /* mini */
1023 
1024     /* implicit loop for -n/-p */
1025     if (opts & (OPT_n|OPT_p))
1026     {
1027 	sv_catpv(cmd, ";LINE:while(<$Vile::current_buffer>){"); /*}*/
1028 	if (opts & OPT_l)
1029 	    sv_catpv(cmd, "chomp;");
1030 
1031 	/* autosplit to @F */
1032 	if (opts & OPT_a)
1033 	{
1034 	    sv_catpv(cmd, "@F=split ");
1035 	    if (*split == '/' || *split == '"' || *split == '\'')
1036 		sv_catpv(cmd, split);
1037 	    else
1038 	    {
1039 		char delim;
1040 		const char *test = "'~#\200\1";
1041 		/* try to find a delimiter not in the string */
1042 		while (*test && vl_index(split, *test)) test++;
1043 		delim = *test;
1044 		sv_catpvf(cmd, "q%c%s%c", delim, split, delim);
1045 	    }
1046 
1047 	    sv_catpv(cmd, ";");
1048 	}
1049     }
1050     else
1051 	sv_catpv(cmd, ";");
1052 
1053     /* add the command */
1054     sv_catpv(cmd, buf);
1055 
1056     /* close the loop */
1057     if (opts & (OPT_n|OPT_p))
1058     {
1059 /*{*/	sv_catpv(cmd, "}");
1060 	if (opts & OPT_p)
1061 	    sv_catpv(cmd, "continue{print}");
1062     }
1063     else
1064 	sv_catpv(cmd, ";");
1065 
1066     /* reset handle and close block */
1067 /*{*/ sv_catpv(cmd, "select $_save_fh}");
1068 
1069     status = do_perl_cmd(cmd, opts & OPT_i);
1070     SvREFCNT_dec(cmd);
1071 
1072     returnCode(status);
1073 }
1074 
1075 static int
svcurbuf_set(pTHX_ SV * sv,MAGIC * mg GCC_UNUSED)1076 svcurbuf_set(pTHX_ SV *sv, MAGIC *mg GCC_UNUSED)
1077 {
1078     VileBuf *vbp;
1079     if (sv_isa(sv, "Vile::Buffer")
1080 	&& (vbp = INT2PTR(VileBuf *, SvIV((SV*)GvSV((GV*)SvRV(sv))))) != NULL)
1081     {
1082 	api_swscreen(NULL, vbp);
1083     }
1084     else {
1085 	VileBuf *curvbp = api_bp2vbp(curbp);
1086 	if (curvbp != 0) {
1087 	    SV *my_sv = newVBrv(newSV((size_t) 0), curvbp);
1088 	    sv_setsv(svcurbuf, my_sv);
1089 	    SvREFCNT_dec(my_sv);
1090 	}
1091     }
1092     return 1;
1093 }
1094 
1095 static void
prepend_include(char * path)1096 prepend_include(char *path)
1097 {
1098     AV   *av;
1099     SV   *sv;
1100 
1101     if (is_directory(path)) {
1102 	TRACE(("prepend_include(%s)\n", path));
1103 	av_unshift(av = GvAVn(PL_incgv), 1);
1104 	sv = newSVpv(path, (size_t) 0);
1105 	av_store(av, 0, sv);
1106     }
1107 }
1108 
1109 static int
real_perl_init(void)1110 real_perl_init(void)
1111 {
1112     static char empty[1];
1113     static char option_e[] = "-e";
1114     static char values_0[] = "0";
1115     static char my_class[] = "Vile";
1116     char *embedding[] = { empty, option_e, values_0 };
1117     char *bootargs[]  = { my_class, NULL };
1118     SV   *svminibuf;
1119     char  temp[NFILEN];
1120     char *vile_path;
1121     static char svcurbuf_name[] = "Vile::current_buffer";
1122 
1123     TRACE((T_CALLED "perl_init\n"));
1124 
1125     perl_interp = perl_alloc();
1126     perl_construct(perl_interp);
1127 
1128     if (perl_parse(perl_interp, xs_init, 3, embedding, NULL)) {
1129 	perl_destruct(perl_interp);
1130 	perl_free(perl_interp);
1131 	perl_interp = NULL;
1132 	returnCode(FALSE);
1133     }
1134     perl_call_argv("Vile::bootstrap", G_DISCARD, bootargs);
1135 
1136     /* Add our own paths to the front of @INC */
1137 #ifdef HELP_LOC
1138     prepend_include(lengthen_path(strcpy(temp, "~/.vile/perl")));
1139     prepend_include(lengthen_path(pathcat(temp, HELP_LOC, "perl")));
1140 #endif
1141     /* Always recognize environment variable */
1142     if ((vile_path = vile_getenv("VILE_LIBDIR_PATH")) != 0)
1143     {
1144 	const char *cp = vile_path;
1145 	char result[NFILEN];
1146 	int first = TRUE;
1147 	/*
1148 	 * "patch" @INC to look (first) for scripts in the directory
1149 	 * %VILE_LIBDIR_PATH%\\perl .
1150 	 */
1151 	TRACE(("perl_init VILE_LIBDIR_PATH=%s\n", vile_path));
1152 	while ((cp = parse_pathlist(cp, result, &first)) != 0) {
1153 	    TRACE(("parsed %s\n", cp));
1154 	    prepend_include(pathcat(temp, result, "perl"));
1155 	}
1156     }
1157 
1158     /* Obtain handles to specific perl variables, creating them
1159        if they do not exist. */
1160     svcurbuf  = perl_get_sv(svcurbuf_name,  TRUE);
1161 
1162     svminibuf   = newVBrv(newSV((size_t) 0), api_bp2vbp(bminip));
1163 
1164     /* Tie STDOUT and STDERR to miniscr->PRINT() function */
1165     tie_handle((SV *) gv_fetchpv("STDOUT", TRUE, SVt_PVIO), svminibuf);
1166     tie_handle((SV *) gv_fetchpv("STDERR", TRUE, SVt_PVIO), svminibuf);
1167     tie_handle((SV *) gv_fetchpv("STDIN", TRUE, SVt_PVIO), svminibuf);
1168 
1169     sv_magic(svcurbuf, NULL, PERL_MAGIC_ext, svcurbuf_name,
1170 	     (I32) strlen(svcurbuf_name));
1171 
1172     mg_find(svcurbuf, PERL_MAGIC_ext)->mg_virtual = &svcurbuf_accessors;
1173     SvMAGICAL_on(svcurbuf);
1174 
1175     /* Some things are better (or easier) to do in perl... */
1176     perl_eval_pv("$SIG{__WARN__}='Vile::Warn';"
1177 		 "sub Vile::Buffer::PRINTF {"
1178 		 "    my $fh=shift; my $fmt=shift;"
1179 		 "    print $fh sprintf($fmt,@_);"
1180 		 "}", G_DISCARD);
1181 
1182     /* Fetch $\ and $, */
1183     ors_sv = perl_get_sv("\\", TRUE);
1184     ofs_sv = perl_get_sv(",", TRUE);
1185 
1186     /* Load user or system wide initialization script */
1187     require("vileinit.pl", TRUE);
1188     returnCode(TRUE);
1189 }
1190 
1191 /*
1192  * This is called from main.c in a context that precludes including Perl's
1193  * header files.
1194  */
perl_init(int * argc,char *** argv,char *** envp)1195 void perl_init(int *argc, char ***argv, char ***envp)
1196 {
1197 #ifdef USE_SYS_INIT3
1198     PERL_SYS_INIT3(argc, argv, envp);
1199 #endif
1200 }
1201 
1202 /* make sure END blocks and destructors get called */
perl_exit()1203 void perl_exit()
1204 {
1205     TRACE((T_CALLED "perl_exit\n"));
1206     if (perl_interp) {
1207 	perl_run(perl_interp);		/* process END blocks */
1208 	perl_destruct(perl_interp);	/* global destructors */
1209 	perl_free(perl_interp);
1210 	perl_interp = 0;
1211 #ifdef USE_SYS_INIT3
1212 	PERL_SYS_TERM();
1213 #endif
1214     }
1215     returnVoid();
1216 }
1217 
1218 /* Register any extra external extensions */
1219 
1220 #ifdef __cplusplus
1221 extern "C" {
1222 #endif
1223 
1224 extern void boot_DynaLoader(pTHX_ CV* cv);
1225 
1226 #if (defined(__CYGWIN__) || defined(WIN32)) && defined(USE_DYNAMIC_LOADING)
1227 __declspec(dllexport)
1228 #else
1229 extern
1230 #endif
1231 
1232 void boot_Vile(pTHX_ CV* cv);
1233 
1234 #ifdef __cplusplus
1235 }
1236 #endif
1237 
1238 static void
xs_init(pTHX)1239 xs_init(pTHX)
1240 {
1241     const char *file = __FILE__;
1242     dXSUB_SYS;
1243     newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, file);
1244     newXS("Vile::bootstrap", boot_Vile, file);
1245 }
1246 
1247 /*
1248  * Stringify a code ref so it may be called from vile.
1249  */
1250 
1251 static const char *CRfmtstr = "perl \"&{$Vile::CRs[%d]}\"";
1252 static AV *CRarray   = 0;
1253 static int freeCRidx = 0;
1254 
1255 static char *
stringify_coderef(SV * coderef)1256 stringify_coderef(SV *coderef) {
1257     char buf[40];
1258     int idx = 0;
1259     int cantstore = 0;
1260 
1261     if (CRarray == 0) {
1262 	/* Short name to keep the size of strings short on the vile side */
1263 	CRarray = perl_get_av("Vile::CRs", TRUE);
1264 	freeCRidx = -1;
1265     }
1266 
1267     if (freeCRidx >= 0) {
1268 	SV **svp;
1269 	idx = freeCRidx;
1270 	svp = av_fetch(CRarray, (I32) idx, 0);
1271 	if (svp == 0) {
1272 	    /* Something's screwy... */
1273 	    freeCRidx = -1;
1274 	}
1275 	else {
1276 	    freeCRidx = (int) SvIV(*svp);
1277 	}
1278 	if (av_store(CRarray, (I32) idx, SvREFCNT_inc(coderef)) == 0) {
1279 	    cantstore = 1;
1280 	    SvREFCNT_dec(coderef);
1281 	}
1282     }
1283     else
1284 	cantstore = 1;
1285 
1286     if (cantstore) {
1287 	av_push(CRarray, SvREFCNT_inc(coderef));
1288 	idx = av_len(CRarray);
1289     }
1290 
1291     sprintf(buf, CRfmtstr, idx);
1292     return strdup(buf);
1293 }
1294 
1295 #define HAVE_BROKEN_PERL_ANON_SUB_DEALLOC 1
1296 
1297 #if HAVE_BROKEN_PERL_ANON_SUB_DEALLOC
1298 static unsigned CRs_tofree_maxsize = 0;
1299 static unsigned CRs_tofree_idx = 0;
1300 static SV **CRs_tofree = 0;
1301 #endif /* HAVE_BROKEN_PERL_ANON_SUB_DEALLOC */
1302 
1303 void
perl_free_deferred()1304 perl_free_deferred()
1305 {
1306 #if HAVE_BROKEN_PERL_ANON_SUB_DEALLOC
1307     while (CRs_tofree_idx > 0) {
1308 	CRs_tofree_idx--;
1309 	SvREFCNT_dec(CRs_tofree[CRs_tofree_idx]);
1310     }
1311 #endif /* HAVE_BROKEN_PERL_ANON_SUB_DEALLOC */
1312 }
1313 
1314 int
perl_free_callback(char * callback)1315 perl_free_callback(char *callback)
1316 {
1317     int idx;
1318     if (sscanf(callback, CRfmtstr, &idx) == 1) {
1319 	SV **svp;
1320 	SV *svfreeCRidx;
1321 	svp = av_fetch(CRarray, (I32) idx, 0);
1322 	if (svp == 0)
1323 	    return 0;	/* Something screwy, bail... */
1324 
1325 	if (!SvROK(*svp) || SvTYPE(SvRV(*svp)) != SVt_PVCV)
1326 	    return 0;	/* Most likely freed already (?) */
1327 
1328 
1329 	/* I used to have the following line in the code here:
1330 
1331 		SvREFCNT_dec(*svp);
1332 
1333 	   But I now think this is wrong.  The reason is that while
1334 	   the av_store does not increment the reference count of the
1335 	   thing you're storing into the array, it does appear to
1336 	   decrement the reference count (and potentially free) the
1337 	   thing being replaced.
1338 
1339 	   So we won't decrement the reference count here.  If
1340 	   we did it here, we'd be doing it twice which is wrong. */
1341 
1342 #if HAVE_BROKEN_PERL_ANON_SUB_DEALLOC
1343 	/* There's a bug in perl5.00503 (and probably other
1344 	   versions as well) in which perl tries to look
1345 	   at some memory associated with a coderef after
1346 	   it's been freed.  Perhaps it was freed too early;
1347 	   I don't know.  I have been able to reproduce this
1348 	   problem in an ordinary (extension free) perl program,
1349 	   so I do know that there's a bug in perl.
1350 
1351 	   So here's how we work around it... we'll increment
1352 	   the reference count and stash the coderef away
1353 	   so that we can decrement it at a later time when
1354 	   it'll (hopefully) be safer to do so. */
1355 
1356 	SvREFCNT_inc(*svp);
1357 	if (CRs_tofree_idx >= CRs_tofree_maxsize) {
1358 	    unsigned oldsize = CRs_tofree_maxsize;
1359 	    CRs_tofree_maxsize += 4;
1360 	    GROW(CRs_tofree, SV*, oldsize, CRs_tofree_maxsize);
1361 	}
1362 	CRs_tofree[CRs_tofree_idx++] = *svp;
1363 #endif /* HAVE_BROKEN_PERL_ANON_SUB_DEALLOC */
1364 
1365 	svfreeCRidx = newSViv((IV)freeCRidx);
1366 	if (av_store(CRarray, (I32) idx, svfreeCRidx) == 0) {
1367 	    /* Not successful (!) */
1368 	    SvREFCNT_dec(svfreeCRidx);
1369 	}
1370 	else {
1371 	    freeCRidx = idx;
1372 	}
1373     }
1374     return 1;
1375 }
1376 
1377 /*
1378  * Returns a line number given an SV.  '$' represents the last line
1379  * in the file. '$$' represents the line after the last line.  The
1380  * only time that '$' and '$$' represent the same line is when the
1381  * buffer is empty.
1382  */
1383 
1384 static I32
sv2linenum(SV * sv)1385 sv2linenum(SV *sv)
1386 {
1387     I32 linenum;
1388 
1389     if (!SvIOKp(sv) && strcmp(SvPV(sv,PL_na),"$") == 0) {
1390 	linenum = vl_line_count(curbp);
1391     }
1392     else if (!SvIOKp(sv) && strcmp(SvPV(sv,PL_na),"$$") == 0) {
1393 	linenum = vl_line_count(curbp) + 1;
1394     }
1395     else {
1396 	linenum = (I32) SvIV(sv);
1397 	if (linenum < 1) {
1398 	    linenum = 1;
1399 	}
1400 	else if (linenum > vl_line_count(curbp)) {
1401 	    linenum = vl_line_count(curbp);
1402 	}
1403     }
1404     return linenum;
1405 }
1406 
1407 
1408 /*
1409  * Returns an offset within the current line (where DOT is) given an
1410  * SV.  '$' represents the last non-newline character in the line.  '$$'
1411  * represents the newline character.  The only time '$' and '$$' represent
1412  * the same position is when the line is empty.
1413  */
1414 
1415 static I32
sv2offset(SV * sv)1416 sv2offset(SV *sv)
1417 {
1418     I32 offset;
1419     if (!SvIOKp(sv) && strcmp(SvPV(sv,PL_na),"$") == 0) {
1420 	offset = llength(DOT.l) - 1;
1421 	if (offset < 0)
1422 	    offset = 0;
1423     }
1424     else if (!SvIOKp(sv) && strcmp(SvPV(sv,PL_na),"$$") == 0) {
1425 	offset = llength(DOT.l);
1426     }
1427     else {
1428 	offset = (I32) SvIV(sv);
1429 	if (offset < 0) {
1430 	    offset = 0;
1431 	}
1432 	else if (offset > llength(DOT.l)) {
1433 	    offset = llength(DOT.l);
1434 	}
1435     }
1436     return offset;
1437 }
1438 
1439 /*
1440  * Fetch a line or portion thereof from the current buffer.  Like
1441  * api_dotgline(), except it's faster because it creates an SV of
1442  * the right size from the outset.  It's also faster because it
1443  * relies on the caller to set up the fake window properly.  (Not
1444  * a big deal if only getting a scalar, but it can be if fetching
1445  * an entire array.)
1446  *
1447  * Does not handle rectangular regions.
1448  *
1449  * Implementation notes:  In my first attempts at implementing these
1450  * functions, I used the region's end mark to determine when/where to
1451  * stop.  This usually worked, but there were times (particularly
1452  * when the inplace_edit flag was set to true) when the end marker
1453  * would either disappear entirely or would move to some undesirable
1454  * location.  I considered "fixing" the mark machinery so that it
1455  * would work as I desired.  The only problem with this is that my
1456  * attempts to do this could either destabilize the rest of the editor
1457  * or cause vile to be incompatible with real vi.
1458  *
1459  * So I decided that a lot of the code would be cleaner if I simply
1460  * gave up trying to use the end marker.  Instead I rely on the
1461  * length field, r_size, located in the region structure to determine
1462  * the right time to stop.  The only problem I see with this approach
1463  * is that motions could screw it up... but I suppose we can adjust
1464  * the r_size field in one way or another to account for this.
1465  *
1466  * In any event, I've decided that it is a bad idea to rely on
1467  * either of the marks once buffer modifications have started.
1468  */
1469 
1470 static int
svgetline(SV ** svp,VileBuf * vbp,char * rsstr GCC_UNUSED,STRLEN rslen GCC_UNUSED)1471 svgetline(SV **svp, VileBuf *vbp, char *rsstr GCC_UNUSED, STRLEN rslen GCC_UNUSED)
1472 {
1473     B_COUNT len;
1474     B_COUNT nllen;
1475     char *text;
1476     SV *sv;
1477     const char *ending = get_record_sep(curbp);
1478     B_COUNT len_rs = (B_COUNT) len_record_sep(curbp);
1479 
1480     if (is_header_line(DOT, curbp)
1481      || vbp->region.r_size <= 0
1482      || llength(DOT.l) < DOT.o) {
1483 	*svp = newSVsv(&PL_sv_undef);
1484 	return FALSE;
1485     }
1486 
1487     len = (B_COUNT) (llength(DOT.l) - DOT.o);
1488     text = lvalue(DOT.l) + DOT.o;
1489 
1490     if (len > vbp->region.r_size)
1491 	len = vbp->region.r_size;
1492 
1493     if (   vbp->region.r_size > 0
1494 	&& (   lforw(DOT.l) != buf_head(curbp)
1495 	    || b_val(curbp, MDNEWLINE)))
1496     {
1497 	nllen = len_rs;
1498 	DOT.o = b_left_margin(curbp);
1499 	DOT.l = lforw(DOT.l);
1500     }
1501     else {
1502 	nllen = 0;
1503 	DOT.o += (C_NUM) len;
1504     }
1505 
1506     vbp->region.r_size -= len + nllen;
1507 
1508     if (vbp->inplace_edit)
1509 	vbp->ndel += len + nllen;
1510 
1511     *svp = sv = newSV(len + nllen + 1);	/* +1 for \0 */
1512 
1513     if (len > 0) {
1514 	sv_setpvn(sv, text, len);
1515 	if (nllen > 0)
1516 	    sv_catpvn(sv, ending, len_rs);
1517     }
1518     else if (nllen > 0) {
1519 	sv_setpvn(sv, ending, len_rs);
1520     }
1521     else {
1522 	sv_setpvn(sv, "", (size_t) 0);
1523     }
1524 
1525     return TRUE;
1526 }
1527 
1528 /*
1529  * Fetch an entire region (or remainder thereof).
1530  */
1531 
1532 static int
svgetregion(SV ** svp,VileBuf * vbp,char * rsstr GCC_UNUSED,STRLEN rslen GCC_UNUSED)1533 svgetregion(SV **svp, VileBuf *vbp, char *rsstr GCC_UNUSED, STRLEN rslen GCC_UNUSED)
1534 {
1535     B_COUNT len;
1536     SV *sv;
1537     LINE *lp;
1538     C_NUM off;
1539     const char *ending = get_record_sep(curbp);
1540     STRLEN len_rs = (STRLEN) len_record_sep(curbp);
1541 
1542     if (is_header_line(DOT, curbp) || vbp->region.r_size <= 0) {
1543 	*svp = newSVsv(&PL_sv_undef);
1544 	return FALSE;
1545     }
1546 
1547     len = vbp->region.r_size;
1548     vbp->region.r_size = 0;
1549 
1550     *svp = sv = newSV(len + 1);	/* + 1 for \0 */
1551     sv_setpvn(sv, "", (size_t) 0);
1552 
1553     if (vbp->inplace_edit)
1554 	vbp->ndel += len;
1555 
1556     lp = DOT.l;
1557     off = DOT.o;
1558     while (len > 0) {
1559 	STRLEN clen = (STRLEN) (llength(lp) - off);
1560 
1561 	if (clen > len)
1562 	    clen = len;
1563 
1564 	if (clen > 0) {
1565 	    sv_catpvn(sv, lvalue(lp) + off, clen);
1566 	    len -= clen;
1567 	    off += (C_NUM) clen;
1568 	}
1569 
1570 	if (len > 0) {
1571 	    if (lforw(lp) != buf_head(curbp) || b_val(curbp, MDNEWLINE))
1572 		sv_catpvn(sv, ending, len_rs);
1573 	    len -= (B_COUNT) len_rs;
1574 	    off++;
1575 	}
1576 
1577 	if (off > llength(lp)) {
1578 	    lp = lforw(lp);
1579 	    off = 0;
1580 	}
1581     }
1582     DOT.l = lp;
1583     DOT.o = off;
1584 
1585     return TRUE;
1586 }
1587 
1588 /*
1589  * Gets the next portion of a region up to the next record separator
1590  * or the end of region, whichever comes first.
1591  */
1592 
1593 static int
svgettors(SV ** svp,VileBuf * vbp,char * rsstr,STRLEN rslen)1594 svgettors(SV **svp, VileBuf *vbp, char *rsstr, STRLEN rslen)
1595 {
1596     B_COUNT len, reglen;
1597     SV *sv;
1598     int rs1;
1599     STRLEN orig_rslen = rslen;
1600     LINE *lp;
1601     C_NUM off;
1602     const char *ending = get_record_sep(curbp);
1603     STRLEN len_rs = (STRLEN) len_record_sep(curbp);
1604     char temp[10];
1605 
1606     /* See if we're already at the end of the region and have nothing
1607        to do. */
1608     if (is_header_line(DOT, curbp) || vbp->region.r_size <= 0) {
1609 	*svp = newSVsv(&PL_sv_undef);
1610 	return FALSE;
1611     }
1612 
1613     /* Adjust rsstr if need be */
1614     if (rslen == 0) {
1615 	rslen = strlen(ending);
1616 	if (rslen < (sizeof(temp) / 2) - 1) {
1617 	    rsstr = strcat(strcpy(temp, ending), ending);
1618 	    rslen = strlen(rsstr);
1619 	} else {	/* should never happen, but analyzers do not know */
1620 	    rsstr = temp;
1621 	    *rsstr = '\0';
1622 	    rslen = 0;
1623 	}
1624     }
1625 
1626     /* Get first separator character */
1627     rs1 = *rsstr;
1628 
1629     /* Compute length of region up to record separator or til
1630        end of region, whichever comes first */
1631     lp  = DOT.l;
1632     off = DOT.o;
1633     len = 0;
1634     reglen = vbp->region.r_size;
1635     for (;;) {
1636 	C_NUM loff;
1637 	int cont_off;
1638 	LINE *cont_lp;
1639 	int fidx;
1640 	STRLEN rsidx;
1641 
1642 	if (off > llength(lp)) {
1643 	    off = 0;
1644 	    lp = lforw(lp);
1645 	}
1646 
1647 	if (lp == buf_head(curbp) || len >= reglen)
1648 	    goto have_length;
1649 
1650 	/* loff is the last offset that we'll do our initial search
1651 	   to on this line */
1652 	loff = llength(lp);
1653 	if ((B_COUNT) (loff - off) > (reglen - len)) {
1654 	    loff = off;
1655 	    if (reglen > len)
1656 		loff +=  (C_NUM) (reglen - len);
1657 	}
1658 
1659 	/* Try to find the first record separator character */
1660 	if (rs1 == '\n') {
1661 	    /* newline; no searching needed, must be at end of line */
1662 	    if (loff < llength(lp)) {
1663 		len += (B_COUNT) loff;
1664 		goto have_length;
1665 	    }
1666 	    else
1667 		fidx = loff;
1668 	}
1669 	else {
1670 	    /* Gotta search */
1671 	    for (fidx = off; fidx < loff && lvalue(lp)[fidx] != rs1; fidx++)
1672 		;
1673 	    if (fidx >= loff) {
1674 		if (loff < llength(lp)) {
1675 		    len += (B_COUNT) loff;
1676 		    goto have_length;
1677 		}
1678 		len += (B_COUNT) (loff - off + 1);
1679 		off = loff + 1;
1680 		continue;
1681 	    }
1682 	}
1683 
1684 	/* If we get to this point, fidx points at first character in
1685 	   the record separator. */
1686 	len += (B_COUNT) (fidx - off + 1);
1687 	cont_lp = lp;
1688 	cont_off = fidx + 1;
1689 
1690 	/* Attempt to match the rest of the record separator */
1691 	for (rsidx = 1; rsidx < rslen; rsidx++) {
1692 	    fidx++;
1693 	    if (fidx >= llength(lp)) {
1694 		lp = lforw(lp);
1695 		fidx = 0;
1696 	    }
1697 	    if (lp == buf_head(curbp) || len + (B_COUNT) (rsidx - 1) >= reglen) {
1698 		len += (B_COUNT) (rsidx - 1);
1699 		goto have_length;
1700 	    }
1701 	    if (isreturn(rsstr[rsidx])) {
1702 		if (fidx < llength(lp))
1703 		    break;
1704 	    }
1705 	    else if (rsstr[rsidx] != lvalue(lp)[fidx])
1706 		break;
1707 	}
1708 
1709 	if (rsidx >= rslen) {
1710 	    len += (B_COUNT) (rslen - 1);
1711 	    goto have_length;
1712 	}
1713 	lp = cont_lp;
1714 	off = cont_off;
1715     }
1716 have_length:
1717 
1718     /* See if we have the special paragraph separator and if so, consume
1719        as many additional newlines as we can */
1720     if (orig_rslen == 0) {
1721 	lp = lforw(lp);
1722 	while (   ! (lp == buf_head(curbp) || len >= reglen)
1723 	       && llength(lp) == 0)
1724 	{
1725 	    len += len_rs;
1726 	    lp = lforw(lp);
1727 	}
1728     }
1729 
1730     /* Make sure there's still something left to return */
1731     if (len <= 0) {
1732 	*svp = newSVsv(&PL_sv_undef);
1733 	return FALSE;
1734     }
1735 
1736     vbp->region.r_size -= len;
1737 
1738     /* Now copy the region over to the SV... */
1739     *svp = sv = newSV(len + 1);	/* + 1 for \0 */
1740     sv_setpvn(sv, "", (size_t) 0);
1741 
1742     if (vbp->inplace_edit)
1743 	vbp->ndel += len;
1744 
1745     lp = DOT.l;
1746     off = DOT.o;
1747     while (len > 0) {
1748 	if (llength(lp) > off) {
1749 	    B_COUNT clen = (B_COUNT) (llength(lp) - off);
1750 
1751 	    if (clen > len)
1752 		clen = len;
1753 
1754 	    if (clen > 0) {
1755 		sv_catpvn(sv, lvalue(lp) + off, clen);
1756 		len -= clen;
1757 		off += (C_NUM) clen;
1758 	    }
1759 	}
1760 
1761 	if (len > 0) {
1762 	    if (lforw(lp) != buf_head(curbp) || b_val(curbp, MDNEWLINE))
1763 		sv_catpvn(sv, ending, len_rs);
1764 	    len -= len_rs;
1765 	    off++;
1766 	}
1767 
1768 	if (off > llength(lp)) {
1769 	    lp = lforw(lp);
1770 	    off = 0;
1771 	}
1772     }
1773     DOT.l = lp;
1774     DOT.o = off;
1775 
1776     return TRUE;
1777 }
1778 
1779 static char *
FindMode(char * mode,int isglobal,VALARGS * args)1780 FindMode(char *mode, int isglobal, VALARGS *args)
1781 {
1782     int status = FALSE;
1783     int literal = (toktyp(mode) == TOK_LITSTR);
1784     const char *value;
1785     char *result = 0;
1786     TBUFF *temp = 0;
1787     char new_mode[NLINE];
1788 
1789     if (literal)
1790 	status = find_mode(curbp, mode, isglobal, args);
1791 
1792     if (status == TRUE) {
1793 	value = string_mode_val(args);
1794     } else {
1795 	if (literal) {
1796 	    new_mode[0] = '$';
1797 	    vl_strncpy(new_mode+1, mode, sizeof(new_mode)-1);
1798 	    value = tokval(new_mode);
1799 	} else {
1800 	    /*
1801 	     * A function should be legal anywhere a variable value is.
1802 	     */
1803 	    if (toktyp(mode) == TOK_FUNCTION) {
1804 		char *save_str = execstr;
1805 		int save_flag = clexec;
1806 
1807 		if ((temp = tb_scopy(&temp, mode)) != 0
1808 		    && tb_length(temp) != 0) {
1809 
1810 		    execstr = skip_text(tb_values(temp));
1811 		    clexec = FALSE;
1812 		    if (isSpace(*execstr)) {
1813 			*execstr++ = 0;
1814 		    }
1815 		    tb_scopy(&temp, tokval(tb_values(temp)));
1816 		    tb_dequote(&temp);
1817 		    value = tb_values(temp);
1818 
1819 		    execstr = save_str;
1820 		    clexec = save_flag;
1821 		} else {
1822 		    value = "";
1823 		}
1824 	    } else {
1825 		value = tokval(mode);
1826 	    }
1827 	}
1828     }
1829 
1830     if (isErrorVal(value)) {
1831 	result = error_val;
1832     } else if (value != 0) {
1833 	if ((result = strmalloc(value)) == 0)
1834 	    value = "";
1835     } else {
1836 	value = "";
1837     }
1838     TRACE(("value of %s(%s) = %s\n", status ? "mode" : "", mode, value));
1839     tb_free(&temp);
1840     return result;
1841 }
1842 
1843 static void
FreeMode(char * value)1844 FreeMode(char *value)
1845 {
1846     /* we made a copy to avoid possibly writing on const (perl 5.005_03) */
1847     if (isLegalVal(value))
1848 	free(value);
1849 }
1850 
1851 /* A version of set_curwp that does nothing but the bare essentials. We
1852    use it in this file when we want to temporarily change the current
1853    window/buffer being acted upon.  It's important to do it this way so
1854    that the buffer tracking list is not affected.  Also, we absolutely
1855    don't want to run any of the hooks. */
1856 static WINDOW *
set_curwp0(WINDOW * wp)1857 set_curwp0(WINDOW *wp)
1858 {
1859     WINDOW *oldwp = curwp;
1860 
1861     curwp = wp;
1862     curbp = wp->w_bufp;
1863     return oldwp;
1864 }
1865 
1866 
1867 MODULE = Vile	PACKAGE = Vile
1868 
1869 PROTOTYPES: DISABLE
1870 
1871   #
1872   # =back
1873   #
1874   # =head2 Loading Perl Modules from Vile
1875   #
1876   # A perl module that is usable by vile should probably be
1877   # located some place on the @INC path.  For vile, the @INC
1878   # array has been augmented to include $HOME/.vile/perl and
1879   # /usr/local/share/vile.  (This latter path may differ depending
1880   # upon your machine and configuration options.)  If you want to
1881   # see what exactly what these paths are, just issue the following
1882   # command from within vile:
1883   #
1884   #     :perl print join ':', @INC[0,1]
1885   #
1886   # Let us suppose that the following script is stored in
1887   # $HOME/.vile/perl/number_lines.pl.
1888   #
1889   #     sub number_lines {
1890   #         my ($lnum, $width) = @_;
1891   #
1892   #         $lnum = 1 unless defined($lnum);
1893   #         $width = 4 unless defined($width);
1894   #
1895   #         $Vile::current_buffer->inplace_edit(1);
1896   #
1897   #         while (<$Vile::current_buffer>) {
1898   #             print $Vile::current_buffer
1899   #                   ' ' x ($width - length($lnum) - 1),
1900   #                   $lnum, ' ', $_;
1901   #             $lnum++;
1902   #         }
1903   #     }
1904   #
1905   #     1;
1906   #
1907   # Note the trailing "1;" at the end.  The reason for this is so
1908   # that I<true> is returned as the result of the script.  If things
1909   # are not done this way, the loading mechanism might flag an
1910   # error.  (All it needs to do is return a true value somehow.)
1911   #
1912   # Assuming the above code has been placed in the file
1913   # 'number_lines.pl', the following vile command may be used
1914   # to load it:
1915   #
1916   #         :perl require 'number_lines.pl'
1917   #
1918   # When writing a new script, I will often test it in the same
1919   # editor session that I've created the script in.  My script
1920   # may have a bug in it and I'll fix it.  In order to reload
1921   # the script, you can do the following:
1922   #
1923   #         :perl do 'number_lines.pl'
1924   #
1925   # Perl's builtin 'require' function wouldn't have worked to
1926   # reload the file because it keeps track of files that have
1927   # been loaded via this facility and refuses to load a file
1928   # twice.  The 'do' function on the other hand is a more general
1929   # facility for executing the contents of a file and doesn't
1930   # care how often it's called.
1931   #
1932   # Caveat: Sometimes it's better to start with a clean slate,
1933   # particularly if you've renamed your subroutines or if there
1934   # are global variables involved.  Just start a fresh copy of
1935   # vile and start over.
1936   #
1937   # Now to invoke our number_lines program, we do it as follows:
1938   #
1939   #         :perl number_lines(1)
1940   #
1941   # It is also possible to use vile's builtin macro language to
1942   # load perl modules and call them.  The hgrep.pl module comes
1943   # with the I<vile> distribution.  You may want to put the following
1944   # line in your F<.vilerc> file:
1945   #
1946   #	perl "use hgrep"
1947   #
1948   # See also the Vile::C<register> functions.
1949   #
1950 
1951 
1952 MODULE = Vile	PACKAGE = Vile
1953 
1954   #
1955   # =head2 Package Vile
1956   #
1957   # The B<Vile> package contains subroutines and methods of a
1958   # general nature.  They range from providing an interface to
1959   # I<vile's> modes to providing facilities for obtaining user input.
1960   #
1961   # =head2 Package Vile Subroutines and Methods
1962   #
1963   # =over 4
1964   #
1965   #
1966   # =item Warn
1967   #
1968   # Print a warning message
1969   #
1970   # =for html <br><br>
1971   #
1972 
1973 void
1974 Warn(warning)
1975     char *warning
1976 
1977     CODE:
1978 	write_message("perl warn:", GvSV(PL_errgv));
1979 	sv_catpv(GvSV(PL_errgv),warning);
1980 
1981   #
1982   # =item beep
1983   #
1984   # Rings terminal bell (or equivalent).
1985   #
1986   # =for html <br><br>
1987   #
1988 
1989 void
1990 beep()
1991     CODE:
1992 	kbd_alarm();
1993 
1994   #
1995   # =item buffers
1996   #
1997   # Returns a list of the editor's buffers.
1998   #
1999   # =for html <br><br>
2000   #
2001 
2002 void
2003 buffers(...)
2004 
2005     PREINIT:
2006 	BUFFER *bp;
2007 
2008     PPCODE:
2009 
2010 	if (! (items == 0
2011 	       || (items == 1 && strcmp(SvPV(ST(0), PL_na), "Vile") == 0)) )
2012 	{
2013 	    /* Must be called as either Vile::buffers() or Vile->buffers() */
2014 	    croak("buffers: called with too many arguments");
2015 	}
2016 
for_each_buffer(bp)2017 	for_each_buffer(bp) {
2018 	    XPUSHs(sv_2mortal(newVBrv(newSV((size_t) 0), api_bp2vbp(bp))));
2019 	}
2020 
2021   #
2022   # =item command CMDLINE
2023   #
2024   # executes the given vile command line (as if it were typed on the :
2025   # line).
2026   #
2027   # This is not exactly safe in all contexts.  (It is easy to cause
2028   # seg faults.) If you need access to some portion of vile that would
2029   # lead you to want to use this subroutine, let me know and I will
2030   # work on suitable facilities.
2031   #
2032   # =for html <br><br>
2033   #
2034 
2035 int
2036 command(cline)
2037     char *cline
2038 
2039     PREINIT:
2040 	int save_vl_msgs;
2041 
2042     CODE:
2043 	save_vl_msgs = vl_msgs;
2044 	vl_msgs = FALSE;
2045 	RETVAL = docmd(cline, TRUE, FALSE, 1);
2046 	vl_msgs = save_vl_msgs;
2047 
2048     OUTPUT:
2049 	RETVAL
2050 
2051   #
2052   # =item keystroke
2053   #
2054   # =item keystroke WAITVAL
2055   #
2056   # Returns a single, fairly raw keystroke from the keyboard.
2057   #
2058   # The optional WAITVAL indicates if the editor should wait for the
2059   # next keystroke.  When WAITVAL is false, undef will
2060   # be returned if no input is ready.
2061   #
2062   # =for html <br><br>
2063   #
2064 
2065 void
2066 keystroke(...)
2067 
2068     PREINIT:
2069 	int noget;
2070     PPCODE:
2071 	if (items > 1)
2072 	    croak("Too many arguments to keystroke");
2073 
2074 	curwp = curwp_visible ? curwp_visible : curwp;
2075 	curbp = curwp->w_bufp;
2076 
2077 	noget = FALSE;
2078 
2079 	if (items == 1 && SvTRUE(ST(0)) == 0) {
2080 	    if (!sysmapped_c_avail()) {
2081 		XPUSHs(&PL_sv_undef);
2082 		noget = TRUE;
2083 	    }
2084 	}
2085 
2086 	if (!noget)
2087 	    XPUSHs(sv_2mortal(newSViv((IV)sysmapped_c())));
2088 
2089 	curwp_visible = curwp;
2090 
2091   #
2092   # =item mlreply PROMPT
2093   #
2094   # =item mlreply PROMPT, INITIALVALUE
2095   #
2096   # Prompts the user with the given prompt and (optional) supplied
2097   # initial value.  Certain characters that the user may input have
2098   # special meanings to mlreply and may have to be escaped by the
2099   # user to be input.  If this is unacceptable, use mlreply_no_opts
2100   # instead.
2101   #
2102   # Returns the user's response string.  If the user aborts
2103   # (via the use of the escape key) the query, an undef is
2104   # returned.
2105   #
2106   # =for html <br><br>
2107   #
2108   # =item mlreply_no_opts PROMPT
2109   #
2110   # =item mlreply_no_opts PROMPT, INITIALVALUE
2111   #
2112   # Prompts the user with the given prompt and (optional) supplied
2113   # initial value.  All printable characters may be entered by the
2114   # user without any special escapes.
2115   #
2116   # Returns the user's response string.  If the user aborts
2117   # (via the use of the escape key) the query, an undef is
2118   # returned.
2119   #
2120   # =for html <br><br>
2121   #
2122   # =item mlreply_shell PROMPT
2123   #
2124   # =item mlreply_shell PROMPT, INITIALVALUE
2125   #
2126   # Like mlreply, but provide completions suitable for fetching shell
2127   # commands.
2128   #
2129   # =for html <br><br>
2130   #
2131 
2132 void
2133 mlreply(prompt, ...)
2134     char *prompt
2135 
2136     ALIAS:
2137 	Vile::mlreply_no_opts = 1
2138 	Vile::mlreply_shell = 2
2139 
2140     PREINIT:
2141 	char buf[NLINE];
2142 	int status;
2143 
2144     PPCODE:
2145 	if (items == 2)
2146 	    vl_strncpy(buf, SvPV(ST(1),PL_na), sizeof(buf));
2147 	else if (items > 2)
2148 	    croak("Too many arguments to mlreply");
2149 	else
2150 	    buf[0] = EOS;
2151 
2152 	switch (ix) {
2153 	    case 1:
2154 		status = mlreply_no_opts(prompt, buf, (UINT) sizeof(buf));
2155 		break;
2156 	    case 2:
2157 		status = mlreply_no_bs(prompt, buf, (UINT) sizeof(buf));
2158 		break;
2159 	    default:
2160 		status = mlreply(prompt, buf, (UINT) sizeof(buf));
2161 		break;
2162 	}
2163 #if OPT_HISTORY
2164 	if (status == TRUE)
2165 	    hst_glue('\r');
2166 #endif
2167 	XPUSHs((status == TRUE || status == FALSE)
2168 		 ? sv_2mortal(newSVpv(buf, (size_t) 0))
2169 		 : &PL_sv_undef);
2170 
2171 
2172   #
2173   # =item mlreply_dir PROMPT
2174   #
2175   # =item mlreply_dir PROMPT, INITIALVALUE
2176   #
2177   # Prompts the user for a directory name with the given prompt
2178   # and (optional) initial value.  Filename completion (via the
2179   # TAB key, if enabled) may be used to assist in entering
2180   # the directory name.
2181   #
2182   # Returns the user's response string.  If the user aborts
2183   # (via the use of the escape key) the query, an undef is
2184   # returned.
2185   #
2186   # =for html <br><br>
2187   #
2188 
2189 void
2190 mlreply_dir(prompt, ...)
2191     char *prompt
2192 
2193     PREINIT:
2194 	char buf[NFILEN];
2195 	static TBUFF *last;
2196 	int status;
2197 
2198     PPCODE:
2199 	if (items == 2) {
2200 	    tb_scopy(&last, SvPV(ST(1),PL_na));
2201 	}
2202 	else if (items > 2) {
2203 	    croak("Too many arguments to mlreply_dir");
2204 	}
2205 
2206 	buf[0] = EOS;
2207 	status = mlreply_dir(prompt, &last, buf);
2208 #if OPT_HISTORY
2209 	if (status == TRUE)
2210 	    hst_glue('\r');
2211 #endif
2212 	XPUSHs((status == TRUE || status == FALSE)
2213 		 ? sv_2mortal(newSVpv(buf, (size_t) 0))
2214 		 : &PL_sv_undef);
2215 
2216 
2217   #
2218   # =item mlreply_file PROMPT
2219   #
2220   # =item mlreply_file PROMPT, INITIALVALUE
2221   #
2222   # Prompts the user for a filename with the given prompt and
2223   # (optional) initial value.  Filename completion (via the
2224   # TAB key, if enabled) may be used to assist in entering
2225   # the filename.
2226   #
2227   # Returns the user's response string.  If the user aborts
2228   # (via the use of the escape key) the query, an undef is
2229   # returned.
2230   #
2231   # =for html <br><br>
2232   #
2233 
2234 void
2235 mlreply_file(prompt, ...)
2236     char *prompt
2237 
2238     PREINIT:
2239 	char buf[NFILEN];
2240 	static TBUFF *last;
2241 	int status;
2242 
2243     PPCODE:
2244 	if (items == 2) {
2245 	    tb_scopy(&last, SvPV(ST(1),PL_na));
2246 	}
2247 	else if (items > 2) {
2248 	    croak("Too many arguments to mlreply_file");
2249 	}
2250 
2251 	buf[0] = EOS;
2252 	status = mlreply_file(prompt, &last, FILEC_UNKNOWN, buf);
2253 #if OPT_HISTORY
2254 	if (status == TRUE)
2255 	    hst_glue('\r');
2256 #endif
2257 	XPUSHs((status == TRUE || status == FALSE)
2258 		 ? sv_2mortal(newSVpv(buf, (size_t) 0))
2259 		 : &PL_sv_undef);
2260 
2261   #
2262   # =item selection_buffer
2263   #
2264   # =item selection_buffer BUFOBJ
2265   #
2266   # =item Vile::Buffer::set_selection BUFOBJ
2267   #
2268   # Gets or sets the buffer associated with the current selection.
2269   #
2270   # When getting the selection, the buffer object that has the current
2271   # selection is returned and its region is set to be the same region
2272   # as is occupied by the selection.  If there is no current selection, undef
2273   # is returned.
2274   #
2275   # When setting the selection, a buffer object must be passed in.  The
2276   # editor's selection is set to the region associated with the buffer object.
2277   # If successful, the buffer object is returned; otherwise undef will be
2278   # returned.
2279   #
2280   # Examples:
2281   #
2282   #	$sel = Vile->selection_buffer->fetch;
2283   #                                     # Put the current selection in $sel
2284   #
2285   #     Vile->selection_buffer($Vile::current_buffer);
2286   #                                     # Set the selection to the region
2287   #                                     # contained in the current buffer
2288   #
2289   # Vile::Buffer::set_selection is an alias for Vile::selection_buffer, but
2290   # can only function as a setter.  It may be used like this:
2291   #
2292   #     Vile->current_buffer->set_region('w')->set_selection;
2293   #                                     # set the selection to be the word
2294   #                                     # starting at the current position
2295   #                                     # in the current buffer
2296   #
2297   #     Vile->current_buffer->motion('?\/\*' . "\n")
2298   #                         ->set_region('%')
2299   #                         ->set_selection();
2300   #                                     # set the selection to be the nearest
2301   #                                     # C-style comment above or at the
2302   #                                     # current position.
2303   #
2304   # =for html <br><br>
2305   #
2306 
2307 void
2308 selection_buffer(...)
2309 
2310     ALIAS:
2311 	Vile::Buffer::set_selection = 1
2312 
2313     PREINIT:
2314 	int argno;
2315 
2316     PPCODE:
2317 #if OPT_SELECTIONS
2318 	argno = 0;
2319 
2320 	if (strcmp(SvPV(ST(argno), PL_na), "Vile") == 0)
2321 	    argno++;
2322 
2323 	if (items - argno == 0) { /* getter */
2324 	    BUFFER *bp;
2325 	    AREGION aregion;
2326 
2327 	    bp = get_selection_buffer_and_region(&aregion);
2328 	    if (bp != NULL) {
2329 		VileBuf *vbp = api_bp2vbp(bp);
2330 		if (vbp != 0) {
2331 		    vbp->region = aregion.ar_region;
2332 		    vbp->regionshape =  aregion.ar_shape;
2333 		    XPUSHs(sv_2mortal(newVBrv(newSV((size_t) 0), vbp)));
2334 		}
2335 	    }
2336 	    else {
2337 		XPUSHs(&PL_sv_undef);
2338 	    }
2339 	}
2340 	else if (items - argno == 1) { /* setter */
2341 	    VileBuf *vbp;
2342 	    const char *croakmess;
2343 	    /* Need a buffer object */
2344 	    vbp = getVB(ST(argno), &croakmess);
2345 
2346 	    if (vbp == 0)
2347 		croak("Vile::%s: %s",
2348 		      ix == 1 ? "Buffer::set_selection" : "selection_buffer",
2349 		      croakmess);
2350 	    api_setup_fake_win(vbp, TRUE);
2351 	    DOT = vbp->region.r_orig;
2352 	    sel_begin();
2353 	    DOT = vbp->region.r_end;
2354 	    if (sel_extend(FALSE, FALSE) == TRUE) {
2355 		XPUSHs(ST(argno));
2356 	    }
2357 	    else {
2358 		XPUSHs(&PL_sv_undef);
2359 	    }
2360 	}
2361 	else {
2362 	    croak("Vile::selection_buffer: Incorrect number of arguments");
2363 	}
2364 #else
2365 	croak("%s requires vile to be compiled with OPT_SELECTIONS",
2366 	      GvNAME(CvGV(cv)));
2367 #endif
2368 
2369   #
2370   # =item set PAIRLIST
2371   #
2372   # =item get LIST
2373   #
2374   # =item Vile::Buffer::set BUFOBJ PAIRLIST
2375   #
2376   # =item Vile::Buffer::get BUFOBJ LIST
2377   #
2378   # Provides access to Vile's various modes, buffer and otherwise.
2379   #
2380   # For the set methods, PAIRLIST should be a list of key => value
2381   # pairs, where key is a mode name and value is an appropriate value
2382   # for that mode.  When used in an array context, the resulting key =>
2383   # value pairs are returned.  (The value may be a different, but
2384   # equivalent string than originally specified.) When used in a scalar
2385   # context, either the package name or buffer object is returned
2386   # (depending on how it was invoked) in order that the result may be
2387   # used as the target of further method calls.
2388   #
2389   # When one of the get forms is used, a list of modes should be
2390   # supplied.  When used in an array context, a list of key => value
2391   # pairs is returned.  When used in a scalar context, only one mode
2392   # name may be supplied and the value associated with this mode is
2393   # returned.
2394   #
2395   # The methods in Vile::Buffer attempt to get the local modes
2396   # associated with the buffer (falling back to the global ones if no
2397   # specific local mode has been specified up to this point).
2398   #
2399   # Note:  Access to certain internal attributes such as the buffer
2400   # name and file name are not provided via this mechanism yet.  There
2401   # is no good reason for this other than that vile does not provide
2402   # access to these attributes via its set command.
2403   #
2404   # =for html <br><br>
2405   #
2406 
2407 void
2408 set(...)
2409 
2410     ALIAS:
2411 	Vile::get = 1
2412 	Vile::Buffer::set = 2
2413 	Vile::Buffer::get = 3
2414 
2415     PREINIT:
2416 	int argno;
2417 	int isglobal;
2418 	int issetter;
2419 	char *mode;
2420 	char *value;
2421 	int status;
2422 	VALARGS args;
2423 	I32 gimme;
2424 	char **modenames;
2425 	int nmodenames = 0;
2426 
2427     PPCODE:
2428 #if OPT_EVAL
2429 	argno    = 0;
2430 	isglobal = (ix == 0 || ix == 1);
2431 	issetter = (ix == 0 || ix == 2);
2432 	gimme    = GIMME_V;
2433 	mode     = NULL;		/* just in case it never gets set */
2434 
2435 	if (!isglobal /* one of the Vile::Buffer methods */) {
2436 	    const char *croakmess;
2437 	    VileBuf *vbp;
2438 
2439 	    /* Need a buffer object */
2440 	    vbp = getVB(ST(argno), &croakmess);
2441 	    argno++;
2442 
2443 	    if (vbp == 0)
2444 		croak("Vile::Buffer::set: %s", croakmess);
2445 
2446 	    isglobal = 0;
2447 	    api_setup_fake_win(vbp, TRUE);
2448 	}
2449 	else {
2450 	    /* We're in the Vile package.  See if we're called via
2451 	       Vile->set */
2452 	    if (strcmp(SvPV(ST(argno), PL_na), "Vile") == 0)
2453 		argno++;
2454 	}
2455 
2456 	nmodenames = 0;
2457 	modenames = NULL;
2458 	if (gimme == G_ARRAY) {
2459 	    int n = items - argno + 1;		/* +1 in case of odd set */
2460 	    if (!issetter)
2461 		n *= 2;
2462 	    if (n > 0) {
2463 		modenames = typeallocn(char *, (unsigned) n);
2464 		if (modenames == NULL)
2465 		    croak("Can't allocate space");
2466 	    }
2467 	}
2468 
2469 	while (argno < items) {
2470 	    mode = SvPV(ST(argno), PL_na);
2471 	    argno++;
2472 
2473 	    TRACE(("Vile::%s(%d:%s)\n", issetter ? "set" : "get", argno, mode));
2474 
2475 	    /* Look for a mode first */
2476 	    status = FALSE;
2477 	    memset(&args, 0, sizeof(args));
2478 	    if (toktyp(mode) == TOK_LITSTR)
2479 		status = find_mode(curbp, mode, isglobal, &args);
2480 
2481 	    if (status == TRUE) {
2482 		if (modenames)
2483 		    modenames[nmodenames++] = mode;
2484 
2485 		if (issetter) {
2486 		    const char *val;
2487 		    val = NULL;
2488 		    if (argno >= items) {
2489 			if (args.names->type == VALTYPE_BOOL) {
2490 			    val = "1";
2491 			}
2492 			else {
2493 			    if (modenames) free(modenames);
2494 			    croak("set: value required for %s", mode);
2495 			}
2496 		    }
2497 		    else {
2498 			val = SvPV(ST(argno), PL_na);
2499 			argno++;
2500 		    }
2501 
2502 		    if (set_mode_value(curbp, mode, FALSE, TRUE, isglobal, &args, val) != TRUE) {
2503 			if (modenames) free(modenames);
2504 			croak("set: Invalid value %s for mode %s", val, mode);
2505 		    }
2506 		}
2507 	    } else {
2508 		const char *val = 0;
2509 
2510 		if (modenames)
2511 		    modenames[nmodenames++] = mode;
2512 
2513 		if (issetter) {
2514 		    if (argno >= items) {
2515 			if (modenames) free(modenames);
2516 			croak("set: value required for %s", mode);
2517 		    }
2518 		    else {
2519 			val = SvPV(ST(argno), PL_na);
2520 			argno++;
2521 		    }
2522 		    status = set_state_variable(mode, val);
2523 
2524 		    if (status != TRUE) {
2525 			if (modenames) free(modenames);
2526 			croak("set: Unable to set variable %s to value %s",
2527 			      mode, val);
2528 		    }
2529 		}
2530 	    }
2531 	}
2532 
2533 	if (modenames == NULL) {
2534 	    if (issetter) {
2535 		if (isglobal)
2536 		    XPUSHs(sv_2mortal(newSVpv("Vile", (size_t) 0)));
2537 		else
2538 		    XPUSHs(ST(0));	/* Buffer object */
2539 	    }
2540 	    else {
2541 		if (mode != NULL) {
2542 		    value = FindMode(mode, isglobal, &args);
2543 		    XPUSHs(sv_2mortal(newSVpv(value, (size_t) 0)));
2544 		    FreeMode(value);
2545 		}
2546 	    }
2547 	}
2548 	else {
2549 	    int i;
2550 	    for (i = 0; i < nmodenames; i++) {
2551 		mode = modenames[i];
2552 		value = FindMode(mode, isglobal, &args);
2553 		XPUSHs(sv_2mortal(newSVpv(mode, (size_t) 0)));
2554 		XPUSHs(sv_2mortal(newSVpv(value, (size_t) 0)));
2555 		FreeMode(value);
2556 	    }
2557 	    free(modenames);
2558 	}
2559 #else
2560 	croak("%s requires vile to be compiled with OPT_EVAL",
2561 	      GvNAME(CvGV(cv)));
2562 #endif
2563 
2564   #
2565   # =item update
2566   #
2567   # Update the editor's display.  It is usually not necessary to
2568   # call this if you're returning to the editor in fairly short
2569   # order.  It will be necessary to call this, for example, if
2570   # you write an input loop in perl which writes things to some
2571   # on-screen buffers, but does not return to the editor immediately.
2572   #
2573   # =for html <br><br>
2574   #
2575 
2576 void
2577 update()
2578     PPCODE:
2579 	api_update();
2580 
2581   #
2582   # =item working
2583   #
2584   # =item working VAL
2585   #
2586   # Returns value 1 if working message will be printed during
2587   # substantial pauses, 0 if disabled.
2588   #
2589   # When passed an argument, modifies value of the working message.
2590   #
2591   # =for html <br><br>
2592   #
2593 
2594 int
2595 working(...)
2596 
2597     CODE:
2598 #if OPT_WORKING
2599 	RETVAL = !vile_is_busy;
2600 #else
2601 	RETVAL = 0;
2602 #endif
2603 	if (items > 1)
2604 	    croak("Too many arguments to working");
2605 	else if (items == 1) {
2606 #if OPT_WORKING
2607 	    vile_is_busy = !SvIV(ST(0));
2608 #endif
2609 	}
2610     OUTPUT:
2611 	RETVAL
2612 
2613   #
2614   # =item register NAME, [SUB, HELP, REQUIRE]
2615   #
2616   # Register a subroutine SUB as Vile function NAME.  Once registered,
2617   # the subroutine may then be invoked as a named command and bound to
2618   # keystrokes.
2619   #
2620   # SUB may be given either as a string to eval, or a reference to a
2621   # subroutine.  If omitted, SUB defaults to NAME.
2622   #
2623   # HELP provides a description of the subroutine for the [Binding
2624   # List] functions.
2625   #
2626   # An optional file to require may be given.
2627   #
2628   # Example:
2629   #
2630   #     Vile::register grep => 'hgrep', 'recursive grep', 'hgrep.pl';
2631   #
2632   # or
2633   #
2634   #     require 'hgrep.pl';
2635   #     Vile::register grep => \&hgrep, 'recursive grep';
2636   #
2637   # also
2638   #
2639   #     sub foo { print "foo" }
2640   #     Vile::register 'foo';
2641   #     Vile::register bar => 'print "bar"';
2642   #     Vile::register quux => sub { print "quux" };
2643   #
2644   # =item register_motion NAME, [SUB, HELP, REQUIRE]
2645   #
2646   # =item register_oper NAME, [SUB, HELP, REQUIRE]
2647   #
2648   # These synonyms for Vile::C<register> allow perl subroutines to
2649   # behave as motions and operators.  For example, these subroutines
2650   # behave like their builtin counterparts:
2651   #
2652   #     *cb = \$Vile::current_buffer;
2653   #     Vile::register_motion 'my-forward-line-at-bol' => sub {
2654   #         $cb->dot((scalar $cb->dot) + 1, 0);
2655   #     };
2656   #
2657   #     Vile::register_oper 'my-delete-til' => sub { $cb->delete };
2658   #
2659   # =for html <br><br>
2660   #
2661 
2662 void
2663 register(name, ...)
2664     char *name
2665 
2666     ALIAS:
2667 	register_motion = MOTION
2668 	register_oper = OPER
2669 
2670     PREINIT:
2671 	CMDFUNC *cmd;
2672 	AV *av;
2673 	char *p;
2674 
2675     PPCODE:
2676 	TRACE(("Vile::register %s\n", name));
2677 #if OPT_NAMEBST
2678 	if (items > 4)
2679 	    croak("Too many arguments to %s", GvNAME(CvGV(cv)));
2680 
2681 	for (p = name; *p; p++)
2682 	    if (!isAlnum(*p) && *p != '-' && *p != '_')
2683 		croak("invalid subroutine name");
2684 
2685 	if ((cmd = typecalloc(CMDFUNC)) == 0)
2686 	    croak("Can't allocate space");
2687 
2688 	ix |= (I32) ((ix == OPER) ? RANGE : VIEWOK);
2689 	cmd->cu.c_perl = av = newAV();
2690 	cmd->c_flags = (REDO | UNDO | CMD_PERL | (CMDFLAGS) ix);
2691 #if OPT_ONLINEHELP
2692 	cmd->c_help = strmalloc((items > 2 && SvTRUE(ST(2)))
2693 				? SvPV(ST(2), PL_na)
2694 				: "Perl subroutine");
2695 #endif
2696 
2697 	if (insert_namebst(name, cmd, FALSE, 0) != TRUE)
2698 	{
2699 #if OPT_ONLINEHELP
2700 	    free((char *) cmd->c_help);
2701 #endif
2702 	    free(cmd);
2703 	    av_undef(av);
2704 	}
2705 	else
2706 	{
2707 	    /* push the name */
2708 	    av_push(av, newSVpv(name, (size_t) 0));
2709 
2710 	    /* push the subroutine */
2711 	    if (items > 1 && SvTRUE(ST(1)))
2712 	    {
2713 		SvREFCNT_inc(ST(1));
2714 		av_push(av, ST(1));
2715 
2716 		/* push the require */
2717 		if (items > 3 && SvTRUE(ST(3)))
2718 		{
2719 		    SvREFCNT_inc(ST(3));
2720 		    av_push(av, ST(3));
2721 		}
2722 	    }
2723 	    else /* sub = name */
2724 		av_push(av, newSVpv(name, (size_t) 0));
2725 	}
2726 #else
2727 	croak("%s requires vile to be compiled with OPT_NAMBST",
2728 	      GvNAME(CvGV(cv)));
2729 #endif
2730 
2731   #
2732   # =item watchfd FD, WATCHTYPE, CALLBACK
2733   #
2734   # Adds a callback so that when the file descriptor FD is available
2735   # for a particular type of I/O activity (specified by WATCHTYPE),
2736   # the callback associated with CALLBACK is called.
2737   #
2738   # WATCHTYPE must be one of 'read', 'write', or 'except' and have
2739   # the obvious meanings.
2740   #
2741   # The callback should either be a string representing a vile
2742   # command to execute (good luck) or (more usefully) a Perl subroutine
2743   # reference.
2744   #
2745   # =for html <br><br>
2746   #
2747 
2748 void
2749 watchfd(fd, watchtypestr, ...)
2750     int fd
2751     char *watchtypestr
2752 
2753     PREINIT:
2754 	char *cmd;
2755 	WATCHTYPE watchtype = 0;
2756 
2757 
2758     PPCODE:
2759 	if (items != 3)
2760 	    croak("Wrong number of arguments to watchfd");
2761 
2762 	if (strcmp(watchtypestr, "read") == 0)
2763 	    watchtype = WATCHREAD;
2764 	else if (strcmp(watchtypestr, "write") == 0)
2765 	    watchtype = WATCHWRITE;
2766 	else if (strcmp(watchtypestr, "except") == 0)
2767 	    watchtype = WATCHEXCEPT;
2768 	else
2769 	    croak("Second argument to watchfd must be one of \"read\", \"write\", or \"except\".");
2770 
2771 	if (SvROK(ST(2))
2772 	    && SvTYPE(SvRV(ST(2))) == SVt_PVCV)
2773 	{
2774 	    /* We have a code ref (cool) */
2775 	    cmd = stringify_coderef(ST(2));
2776 	}
2777 	else {
2778 	    /* It's just a string (how boring) */
2779 	    cmd = strdup(SvPV(ST(2),PL_na));
2780 	}
2781 	TRACE(("Vile::watchfd(fd=%d, watchtype=%d, cmd=%s)\n", fd, watchtype, cmd));
2782 	watchfd(fd, watchtype, cmd);
2783 
2784   #
2785   # =item unwatchfd FD
2786   #
2787   # Removes the callback associated with FD and frees up the
2788   # associated data structures.
2789   #
2790   # =for html <br><br>
2791   #
2792 
2793 void
2794 unwatchfd(fd)
2795     int fd
2796 
2797     PPCODE:
2798 	TRACE(("Vile::unwatchfd(fd=%d)\n", fd));
2799 	unwatchfd(fd);
2800 
2801 
2802 MODULE = Vile	PACKAGE = Vile::Buffer
2803 
2804   #
2805   # =back
2806   #
2807   # =head2 Package Vile::Buffer
2808   #
2809   # The Vile::Buffer package contains methods for creating new buffers
2810   # and for accessing already existing buffers in various ways.
2811   #
2812   # A Vile::Buffer object may be viewed as a filehandle.  Therefore,
2813   # the usual sorts of methods for reading from and writing to
2814   # filehandles will work as expected.
2815   #
2816   # Example:
2817   #
2818   # A word count program that you might invoke from your favorite
2819   # shell could be written as follows:
2820   #
2821   #     #!/usr/local/bin/perl -w
2822   #
2823   #     my $words;
2824   #     while (<>) {
2825   #         $words += split;
2826   #     }
2827   #     print "$words words\n";
2828   #
2829   # A programmer accustomed to the above, will find Vile's perl
2830   # interface to be a comfortable one.  Here is the above script
2831   # modified slightly to count the words in the current buffer:
2832   #
2833   #     sub wc {
2834   #         my $words;
2835   #         while (<$Vile::current_buffer>) {
2836   #             $words+=split;
2837   #         }
2838   #         print "$words words";
2839   #     }
2840   #
2841   # =head2 Package Vile::Buffer Methods
2842   #
2843   # =over 4
2844   #
2845 
2846   #
2847   # =item <BUFOBJ>
2848   #
2849   # When used in a scalar context, returns the next line or portion of
2850   # thereof in the current region.
2851   #
2852   # When used in an array context, returns the rest of the lines (or
2853   # portions thereof) in the current region.
2854   #
2855   # The current region is either set with set_region or set by default
2856   # for you when perl is invoked from vile.  This region will either
2857   # be the region that the user specified or the whole buffer if not
2858   # user specified.  Unless you know for sure that the region is set
2859   # properly, it is probably best to set it explicitly.
2860   #
2861   # After a line is read, DOT is left at the next location in the
2862   # buffer at which to start reading.  Note, however, that the value
2863   # of DOT (which a convenient name for the current position in the
2864   # buffer) is not propagated back to any of the user's windows unless
2865   # it has been explicitly set by calling dot (the method).
2866   #
2867   # When the I<inplace_edit> flag has been set via the C<inplace_edit>
2868   # method, text that is retrieved from the buffer is deleted
2869   # immediately after retrieval.
2870   #
2871   # Examples:
2872   #
2873   #     # Example 1: Put all lines of the current buffer into
2874   #     #            an array
2875   #
2876   #     $Vile::current_buffer->set_region(1,'$$');
2877   #                                     # Set the region to be the
2878   #                                     # entire buffer.
2879   #     my @lines = <$Vile::current_buffer>;
2880   #                                     # Fetch all lines and put them
2881   #                                     # in the @lines array.
2882   #     print $lines[$#lines/2] if @lines;
2883   #                                     # Print the middle line to
2884   #                                     # the status line
2885   #
2886   #
2887   #     # Example 2: Selectively delete lines from a buffer
2888   #
2889   #     my $curbuf = $Vile::current_buffer;
2890   #                                     # get an easier to type handle
2891   #                                     # for the current buffer
2892   #     $curbuf->inplace_edit(1);       # set the inplace_edit flag
2893   #                                     # so that lines will be deleted
2894   #                                     # as they are read
2895   #
2896   #     while (<$curbuf>) {             # fetch line into $_
2897   #         unless (/MUST\s+DELETE/) {  # see if we should keep the line
2898   #             print $curbuf $_;       # put it back if we should keep it
2899   #         }
2900   #     }
2901   #
2902   # =for html <br><br>
2903   #
2904 
2905 void
2906 READLINE(vbp)
2907     VileBuf * vbp
2908 
2909     PPCODE:
2910 	if (is_delinked_bp(vbp2bp(vbp))) {
2911 	    int status;
2912 	    char buf[NLINE];
2913 	    char prompt[NLINE];
2914 	    buf[0] = EOS;
2915 	    strcpy(prompt, "(perl input) ");
2916 	    if (use_ml_as_prompt && !is_empty_buf(bminip)) {
2917 		LINE *lp = lback(buf_head(bminip));
2918 		if (lisreal(lp)) {
2919 		    size_t len = (size_t) llength(lp);
2920 		    if (len > sizeof(prompt)-1)
2921 			len = sizeof(prompt)-1;
2922 		    (void) memcpy(prompt, lvalue(lp), len);
2923 		    prompt[len] = EOS;
2924 		}
2925 	    }
2926 	    status = mlreply_no_opts(prompt, buf, (UINT) sizeof(buf));
2927 #if OPT_HISTORY
2928 	    if (status == TRUE)
2929 		hst_glue('\r');
2930 #endif
2931 	    EXTEND(sp,1);
2932 	    if (status != TRUE && status != FALSE) {
2933 		PUSHs(&PL_sv_undef);
2934 	    }
2935 	    else {
2936 		use_ml_as_prompt = 0;
2937 		PUSHs(sv_2mortal(newSVpv(buf,(size_t) 0)));
2938 	    }
2939 	}
2940 	else {
2941 	    I32 gimme = GIMME_V;
2942 	    struct vile_MARK old_DOT;
2943 	    int (*fnc)(SV**, VileBuf*, char*, STRLEN);
2944 	    char *rsstr;
2945 	    STRLEN rslen;
2946 #ifdef HAVE_BROKEN_PERL_RS
2947 	    /* The input record separator, or $/ Normally, this is
2948 	     * available via the PL_rs macro, but apparently perl5.00402
2949 	     * on win32 systems don't export the necessary symbol from
2950 	     * the DLL.  So we have our own...  */
2951 	    SV *svrs = perl_get_sv("main::/", FALSE);
2952 #else
2953 #           define svrs PL_rs
2954 #endif
2955 
2956 	    if (RsSNARF(svrs)) {
2957 		fnc = svgetregion;
2958 		rsstr = 0;
2959 		rslen = 0;
2960 	    }
2961 	    else {
2962 		rsstr = SvPV(svrs, rslen);
2963 		if (rslen == 1 && isreturn(*rsstr))
2964 		    fnc = svgetline;
2965 		else
2966 		    fnc = svgettors;
2967 	    }
2968 
2969 	    /* Set up the fake window */
2970 	    api_setup_fake_win(vbp, TRUE);
2971 	    if (!vbp->dot_inited) {
2972 		DOT = vbp->region.r_orig;	/* set DOT to beginning of region */
2973 		vbp->dot_inited = 1;
2974 	    }
2975 
2976 	    old_DOT = DOT;
2977 
2978 	    if (gimme == G_VOID || gimme == G_SCALAR) {
2979 		SV *sv;
2980 		if (fnc(&sv, vbp, rsstr, rslen))
2981 		    IoLINES(GvIO((GV*)vbp->perl_handle))++; /* increment $. */
2982 
2983 		if (gimme == G_SCALAR) {
2984 		    XPUSHs(sv_2mortal(sv));
2985 		}
2986 	    }
2987 	    else { /* wants an array */
2988 		SV *sv;
2989 		int lines = 0;
2990 
2991 		while (fnc(&sv, vbp, rsstr, rslen)) {
2992 		    XPUSHs(sv_2mortal(sv));
2993 		    lines++;
2994 		}
2995 		IoLINES(GvIO((GV*)vbp->perl_handle)) = lines; /* set $. */
2996 	    }
2997 	    if (vbp->inplace_edit) {
2998 		DOT = old_DOT;
2999 	    }
3000 	}
3001 
3002   #
3003   # =item attribute BUFOBJ LIST
3004   #
3005   # Attach an attributed region to the region associated with BUFOBJ
3006   # with the attributes found in LIST.
3007   #
3008   # These attributes may be any of the following:
3009   #
3010   #     'color' => NUM          (where NUM is the color number
3011   #                              from 0 to 15)
3012   #     'underline'
3013   #     'bold'
3014   #     'reverse'
3015   #     'italic'
3016   #     'hyper' => HYPERCMD     (where HYPERCMD is a string
3017   #                             representing a vile command to
3018   #                             execute.  It may also be a
3019   #                             (perl) subroutine reference.
3020   #     'normal'
3021   #
3022   # Normal is a special case.  It will override any other arguments
3023   # passed in and remove all attributes associated with the region.
3024   #
3025   # =for html <br><br>
3026   #
3027 
3028 void
3029 attribute(vbp, ...)
3030     VileBuf *vbp
3031 
3032     PPCODE:
3033 #if OPT_SELECTIONS
3034 	if (items <= 1) {
3035 	    /* Hmm.  What does this mean?  Should we attempt to fetch
3036 	       the attributes for this region?  Should we turn off all
3037 	       the attributes?
3038 
3039 	       Personally, I think it'd be cool to return a list of
3040 	       all the regions and their attributes.  But I'll save
3041 	       that exercise for another night...
3042 	    */
3043 	}
3044 	else {
3045 	    int i;
3046 	    char *atname;
3047 	    VIDEO_ATTR vattr = 0;
3048 	    int normal = 0;
3049 	    char *hypercmd = 0;
3050 	    int status;
3051 
3052 	    for (i = 1; i < items; i++) {
3053 		atname = SvPV(ST(i), PL_na);
3054 		if (       strcmp(atname, "underline") == 0) {
3055 		    vattr |= VAUL;
3056 		} else if (strcmp(atname, "bold"     ) == 0) {
3057 		    vattr |= VABOLD;
3058 		} else if (strcmp(atname, "reverse"  ) == 0) {
3059 		    vattr |= VAREV;
3060 		} else if (strcmp(atname, "italic"   ) == 0) {
3061 		    vattr |= VAITAL;
3062 		} else if (strcmp(atname, "normal"   ) == 0) {
3063 		    normal = 1;
3064 		} else if (strcmp(atname, "color"    ) == 0) {
3065 		    i++;
3066 		    if (i < items) {
3067 			vattr |= VCOLORATTR(SvIV(ST(i)) & 0xf);
3068 		    }
3069 		    else {
3070 			croak("Color attribute not supplied");
3071 		    }
3072 		} else if (strcmp(atname, "hyper"    ) == 0
3073 			|| strcmp(atname, "hypertext") == 0) {
3074 		    i++;
3075 		    if (i < items) {
3076 			if (SvROK(ST(i))
3077 			    && SvTYPE(SvRV(ST(i))) == SVt_PVCV)
3078 			{
3079 			    /* We have a code ref */
3080 			    hypercmd = stringify_coderef(ST(i));
3081 			}
3082 			else {
3083 			    /* It's just a string */
3084 			    hypercmd = strdup(SvPV(ST(i),PL_na));
3085 			}
3086 		    }
3087 		    else {
3088 			croak("Hypertext command not supplied");
3089 		    }
3090 		} else {
3091 		    croak("Invalid attribute");
3092 		}
3093 	    }
3094 
3095 	    if (normal) {
3096 		vattr = 0;
3097 		FreeAndNull(hypercmd);
3098 	    }
3099 
3100 	    status = attributeregion_in_region(
3101 			&vbp->region, vbp->regionshape, vattr, hypercmd);
3102 
3103 	    if (status == TRUE)		/* not the same as "if (status)" */
3104 		XPUSHs(ST(0));		/* return buffer object */
3105 	    else
3106 		XPUSHs(&PL_sv_undef);	/* else return undef */
3107 	}
3108 #else
3109 	croak("%s requires vile to be compiled with OPT_SELECTIONS",
3110 	      GvNAME(CvGV(cv)));
3111 #endif
3112 
3113   #
3114   # =item attribute_cntl_a_sequences BUFOBJ
3115   #
3116   # Causes the editor to attach attributes to the <Ctrl>A
3117   # sequences found in the buffer for the current region (which
3118   # may be set via set_region).
3119   #
3120   # Returns the buffer object.
3121   #
3122   # =for html <br><br>
3123   #
3124 
3125 VileBuf *
3126 attribute_cntl_a_sequences(vbp)
3127     VileBuf *vbp
3128 
3129     CODE:
3130 #if OPT_SELECTIONS
3131 	api_setup_fake_win(vbp, TRUE);
3132 	attribute_cntl_a_seqs_in_region(&vbp->region, vbp->regionshape);
3133 	RETVAL = vbp;
3134 #else
3135 	croak("%s requires vile to be compiled with OPT_SELECTIONS",
3136 	      GvNAME(CvGV(cv)));
3137 #endif
3138 
3139     OUTPUT:
3140 	RETVAL
3141 
3142   #
3143   # =item buffername BUFOBJ
3144   #
3145   # Returns the buffer name associated with BUFOBJ.
3146   #
3147   # =for html <br><br>
3148   #
3149   # =item buffername BUFOBJ BUFNAME
3150   #
3151   # Sets the buffer name associated with BUFOBJ to the string
3152   # given by BUFNAME.  This string must be unique.  If the name
3153   # given is already being used by another buffer, or if it's
3154   # malformed in some way, undef will be returned.  Otherwise
3155   # the name of the buffer will be returned.
3156   #
3157   # Note: The name of the buffer returned may be different than
3158   # that passed in due some adjustments that may be done on the
3159   # buffer name.  (It will be trimmed of spaces and a length limit
3160   # is imposed.)
3161   #
3162   # =for html <br><br>
3163   #
3164   # =item filename BUFOBJ
3165   #
3166   # Returns the file name associated with BUFOBJ.
3167   #
3168   # =for html <br><br>
3169   #
3170   # =item filename BUFOBJ FILENAME
3171   #
3172   # Sets the name of the file associated with BUFOBJ to the string
3173   # given by FILENAME.
3174   #
3175   # =for html <br><br>
3176   #
3177 
3178 void
3179 buffername(vbp,...)
3180     VileBuf *vbp
3181 
3182     ALIAS:
3183 	filename = 1
3184 
3185     PREINIT:
3186 	int status;
3187 
3188     PPCODE:
3189 
3190 	status = TRUE;
3191 	api_setup_fake_win(vbp, TRUE);
3192 
3193 	if (items > 2)
3194 	    croak("Too many arguments to %s",
3195 		  ix == 0 ? "buffername" : "filename");
3196 	else if (items == 2) {
3197 	    if (ix == 0)
3198 		status = renamebuffer(curbp, SvPV(ST(1),PL_na));
3199 	    else
3200 		ch_fname(curbp, SvPV(ST(1),PL_na));
3201 	}
3202 
3203 	if (status == TRUE) {
3204 	    XPUSHs(sv_2mortal(newSVpv((ix == 0
3205 				       ? curbp->b_bname
3206 				       : curbp->b_fname),
3207 				      (size_t) 0)));
3208 	}
3209 	else {
3210 	    XPUSHs(&PL_sv_undef);		/* return undef */
3211 	}
3212 
3213   #
3214   # =item command BUFOBJ CMDLINE
3215   #
3216   # Executes the given vile command line (as if it were typed
3217   # on the : line) with BUFOBJ as the current buffer.
3218   #
3219   # Returns BUFOBJ if successful, otherwise returns undef.
3220   #
3221   # =for html <br><br>
3222   #
3223 
3224 void
3225 command(vbp,cline)
3226     VileBuf *vbp
3227     char *cline
3228 
3229     PREINIT:
3230 	int status;
3231 	int save_vl_msgs;
3232     PPCODE:
3233 	save_vl_msgs = vl_msgs;
3234 	vl_msgs = FALSE;
3235 	api_setup_fake_win(vbp, TRUE);
3236 	status = docmd(cline, TRUE, FALSE, 1);
3237 	vl_msgs = save_vl_msgs;
3238 	if (status) {
3239 	    XPUSHs(ST(0));		/* return buffer object */
3240 	}
3241 	else {
3242 	    XPUSHs(&PL_sv_undef);		/* return undef */
3243 	}
3244 
3245   #
3246   # =item current_buffer
3247   #
3248   # =item current_buffer BUFOBJ
3249   #
3250   # =item current_buffer PKGNAME
3251   #
3252   # =item current_buffer BUFOBJ   NEWBUFOBJ
3253   #
3254   # =item current_buffer PKGNAME  NEWBUFOBJ
3255   #
3256   # Returns the current buffer.  When first entering perl from a vile
3257   # session, the current buffer is the one that the user is actively
3258   # editing.  Several buffers may be on the screen at once, but only one
3259   # of them is current.  The current one will be the one in which the
3260   # cursor appears.
3261   #
3262   # This method may also be used to set the current buffer.  When used in
3263   # the form
3264   #
3265   #     $oldbuf->current_buffer($newbuf)
3266   #
3267   # then $newbuf will replace $oldbuf in one of the visible windows.
3268   # (This only makes sense when $oldbuf was visible in some window on the
3269   # screen.  If it wasn't visible, it'll just replace whatever buffer was
3270   # last both current and visible.)
3271   #
3272   # When used as a setter, the current buffer is still returned.  In this
3273   # case it will be the new buffer object which becomes the current
3274   # buffer.
3275   #
3276   # Note also that the current_buffer method is in both the Vile package
3277   # and the Vile::Buffer package.  I couldn't decide which package it should
3278   # be in so I put it into both.  It seemed like a real hassle to have to
3279   # say
3280   #
3281   #     my $curbuf = Vile::Buffer->current_buffer
3282   #
3283   # So instead, you can just say
3284   #
3285   #     my $curbuf = Vile->current_buffer;
3286   #
3287   # current_buffer is also a variable, so you can also do it this way:
3288   #
3289   #     my $curbuf = $Vile::current_buffer;
3290   #
3291   # If you want $main::curbuf (or some other variable) to be an alias to
3292   # the current buffer, you can do it like this:
3293   #
3294   #     *main::curbuf = \$Vile::current_buffer;
3295   #
3296   # Put this in some bit of initialization code and then you'll never have
3297   # to call the current_buffer method at all.
3298   #
3299   # One more point, since $Vile::current_buffer is magical, the alias
3300   # above will be magical too, so you'll be able to do
3301   #
3302   #     $curbuf = $newbuf;
3303   #
3304   # in order to set the buffer.  (Yeah, this looks obvious, but realize
3305   # that doing the assignment actually causes some vile specific code to
3306   # run which will cause $newbuf to become the new current buffer upon
3307   # return.)
3308   #
3309   # =for html <br><br>
3310   #
3311 
3312 VileBuf *
3313 current_buffer(...)
3314 
3315     ALIAS:
3316 	Vile::current_buffer = 1
3317 
3318     PREINIT:
3319 	VileBuf *callbuf = 0;
3320 	VileBuf *newbuf = 0;
3321 
3322     PPCODE:
3323 	TRACE(("Vile::current_buffer\n"));
3324 	if (items > 2)
3325 	    croak("Too many arguments to current_buffer");
3326 	else if (items == 2) {
3327 	    if (sv_isa(ST(0), "Vile::Buffer")) {
3328 		callbuf = INT2PTR(VileBuf *, SvIV((SV*)GvSV((GV*)SvRV(ST(0)))));
3329 		if (callbuf == 0) {
3330 		    croak("buffer no longer exists");
3331 		}
3332 	    }
3333 	    else
3334 		callbuf = 0;
3335 
3336 	    if (sv_isa(ST(1), "Vile::Buffer")) {
3337 		newbuf = INT2PTR(VileBuf *, SvIV((SV*)GvSV((GV*)SvRV(ST(1)))));
3338 		if (newbuf == 0) {
3339 		    croak("switched to buffer no longer exists");
3340 		}
3341 	    }
3342 	    else {
3343 		croak("switched to buffer of wrong type");
3344 	    }
3345 
3346 	    if (api_swscreen(callbuf, newbuf))
3347 		sv_setsv(svcurbuf, ST(1));
3348 	}
3349 
3350 	XPUSHs(svcurbuf);
3351 
3352   #
3353   # =item delete BUFOBJ
3354   #
3355   # Deletes the currently set region.
3356   #
3357   # Returns the buffer object if all went well, undef otherwise.
3358   #
3359   # =for html <br><br>
3360   #
3361 
3362 VileBuf *
3363 delete(vbp)
3364     VileBuf *vbp
3365 
3366     CODE:
3367 	if (api_delregion(vbp))
3368 	    RETVAL = vbp;
3369 	else
3370 	    RETVAL = 0;		/* which gets turned into undef */
3371     OUTPUT:
3372 	RETVAL
3373 
3374   #
3375   # =item dot BUFOBJ
3376   #
3377   # =item dot BUFOBJ LINENUM
3378   #
3379   # =item dot BUFOBJ LINENUM, OFFSET
3380   #
3381   # Returns the current value of dot (which represents the the current
3382   # position in the buffer).  When used in a scalar context, returns
3383   # the line number of dot.  When used in an array context, returns
3384   # the line number and position within the line.
3385   #
3386   # When supplied with one argument, the line number, dot is set to
3387   # the beginning of that line.  When supplied with two arguments,
3388   # both the line number and offset components are set.
3389   #
3390   # Either the line number or offset (or both) may be the special
3391   # string '$' which represents the last line in the buffer and the
3392   # last character on a line.
3393   #
3394   # Often times, however, the special string '$$' will be more useful.
3395   # It truly represents the farthest that it possible to go in both
3396   # the vertical and horizontal directions.  As a line number, this
3397   # represents the line beyond the last line of the buffer.
3398   # Characters inserted at this point will form a new line.  As an
3399   # offset, '$$' refers to the newline character at the end of a line.
3400   # Characters inserted at this point will be inserted before the
3401   # newline character.
3402   #
3403   #
3404   # Examples:
3405   #
3406   #     my $cb = $Vile::current_buffer; # Provide a convenient handle
3407   #                                     # for the current buffer.
3408   #
3409   #     $linenum = $cb->dot;            # Fetch the line number at which dot
3410   #                                     # is located.
3411   #
3412   #     $cb->dot($cb->dot+1);           # Advance dot by one line
3413   #     $cb->dot($cb->dot('$') - 1);
3414   #                                     # Set dot to the penultimate line of
3415   #                                     # the buffer.
3416   #
3417   #     $cb->dot(25, 6);                # Set dot to line 25, character 6
3418   #
3419   #     ($ln,$off) = $cb->dot;          # Fetch the current position
3420   #     $cb->dot($ln+1,$off-1);         # and advance one line, but
3421   #                                     # back one character.
3422   #
3423   #     $cb->inplace_edit(1);
3424   #     $cb->set_region(scalar($cb->dot), $cb->dot+5);
3425   #     @lines = <$cb>;
3426   #     $cb->dot($cb->dot - 1);
3427   #     print $cb @lines;
3428   #                                     # The above block takes (at
3429   #                                     # most) six lines starting at
3430   #                                     # the line DOT is on and moves
3431   #                                     # them before the previous
3432   #                                     # line.
3433   #
3434   # Note: current_position is an alias for dot.
3435   #
3436   # =for html <br><br>
3437   #
3438   # =item dotq BUFOBJ
3439   #
3440   # =item dotq BUFOBJ LINENUM
3441   #
3442   # =item dotq BUFOBJ LINENUM, OFFSET
3443   #
3444   # Like B<dot> except that it's "quiet" in its operation in the sense
3445   # that it doesn't attempt to propagate the API's concept of where the
3446   # current position is back to the editor when control is returned.
3447   #
3448   # This could be useful in situations where you want your Perl script
3449   # to quietly add some text to a buffer without disturbing any of the
3450   # user's windows into that buffer.
3451   #
3452   # =for html <br><br>
3453   #
3454 
3455 void
3456 dot(vbp, ...)
3457     VileBuf *vbp
3458 
3459     ALIAS:
3460 	current_position = 1
3461 	dotq = 2
3462 
3463     PREINIT:
3464 	I32 gimme;
3465 
3466     PPCODE:
3467 	api_setup_fake_win(vbp, TRUE);
3468 	if (items > 3) {
3469 	    croak("Vile::Buffer::%s Too many arguments",
3470 		  ix == 1 ? "current_position" : "dot");
3471 	}
3472 	else if (items > 1) {
3473 	    /* Expect a line number or '$' */
3474 
3475 	    api_gotoline(vbp, sv2linenum(ST(1)));
3476 
3477 	    if (items == 3)
3478 		DOT.o = sv2offset(ST(2));
3479 
3480 	    /* Don't allow api_dotgline to change dot if dot is explicitly
3481 	       set.  OTOH, simply querying dot doesn't count. */
3482 	    vbp->dot_inited = TRUE;
3483 	    if (ix != 2) {
3484 		/* Indicate that DOT has been explicitly changed which means
3485 		   that changes to DOT will be propagated upon return to vile */
3486 		vbp->dot_changed = TRUE;
3487 	    }
3488 	}
3489 	gimme = GIMME_V;
3490 	if (gimme == G_SCALAR) {
3491 	    XPUSHs(sv_2mortal(newSViv((IV)line_no(curbp, DOT.l))));
3492 	}
3493 	else if (gimme == G_ARRAY) {
3494 	    XPUSHs(sv_2mortal(newSViv((IV)line_no(curbp, DOT.l))));
3495 	    XPUSHs(sv_2mortal(newSViv((IV)DOT.o)));
3496 	}
3497 
3498   #
3499   # =item fetch BUFOBJ
3500   #
3501   # Returns the current region or remainder thereof.  The same effect
3502   # could be achieved by setting $/ to undef and then evaluating the
3503   # buffer object between angle brackets.
3504   #
3505   # Example:
3506   #
3507   #     $word = $Vile::current_buffer->set_region('w')->fetch;
3508   #                             # Fetch the next word and put it in $word
3509   #
3510   # =for html <br><br>
3511   #
3512 
3513 void
3514 fetch(vbp)
3515     VileBuf * vbp
3516 
3517     PREINIT:
3518 	SV *sv;
3519 	struct vile_MARK old_DOT;
3520 
3521     PPCODE:
3522 	/* Set up the fake window */
3523 	api_setup_fake_win(vbp, TRUE);
3524 	if (!vbp->dot_inited) {
3525 	    DOT = vbp->region.r_orig;	/* set DOT to beginning of region */
3526 	    vbp->dot_inited = 1;
3527 	}
3528 
3529 	old_DOT = DOT;
3530 
3531 	svgetregion(&sv, vbp, 0, (STRLEN) 0);
3532 
3533 	XPUSHs(sv_2mortal(sv));
3534 
3535 	if (vbp->inplace_edit)
3536 	    DOT = old_DOT;
3537 
3538 
3539   #
3540   # =item inplace_edit BUFOBJ
3541   #
3542   # =item inplace_edit BUFOBJ VALUE
3543   #
3544   # Sets the value of the "inplace edit" flag (either true of false).
3545   # Returns the old value.  When used without an argument, merely
3546   # returns current value without modifying the current value.
3547   #
3548   # This flag determines whether a line is deleted after being read.
3549   # E.g,
3550   #
3551   #     my $curbuf = $Vile::current_buffer;
3552   #     $curbuf->inplace_edit(1);
3553   #     while (<$curbuf>) {
3554   #         s/foo/bar/g;
3555   #         print;
3556   #     }
3557   #
3558   # The <$curbuf> operation will cause one line to be read and
3559   # deleted.  DOT will be left at the beginning of the next line.  The
3560   # print statement will cause $_ to get inserted prior the the next
3561   # line.
3562   #
3563   # Setting this flag to true is very similar to setting the
3564   # $INPLACE_EDIT flag (or $^I) for normal filehandles or using the B<-i>
3565   # switch from the command line.
3566   #
3567   # Setting it to false (which is its default value) will cause the
3568   # lines that are read to be left alone.
3569   #
3570   # =for html <br><br>
3571   #
3572 
3573 int
3574 inplace_edit(vbp, ...)
3575     VileBuf *vbp
3576 
3577     CODE:
3578 	RETVAL = vbp->inplace_edit;
3579 	if (items > 1)
3580 	    vbp->inplace_edit = SvIV(ST(1));
3581 
3582     OUTPUT:
3583 	RETVAL
3584 
3585   #
3586   # =item motion BUFOBJ MOTIONSTR
3587   #
3588   # Moves dot (the current position) by the given MOTIONSTR in
3589   # BUFOBJ.
3590   #
3591   # When used in an array context, returns a 4-tuple containing
3592   # the beginning and ending positions.  This 4-tuple is suitable
3593   # for passing to C<set_region>.
3594   #
3595   # When used in a scalar context, returns the buffer object that
3596   # it was called with.
3597   #
3598   # In either an array or scalar context, if the motion string was
3599   # bad, and undef is returned.  Motions that don't work are okay,
3600   # such as 'h' when you're already at the left edge of a line.  But
3601   # attempted "motions" like 'inewstring' will result in an error.
3602   #
3603   # Example:
3604   #
3605   #     # The following code deletes the previous 2 words and then
3606   #     # positions the cursor at the next occurrence of the word
3607   #     # "foo".
3608   #
3609   #     my $cb = $Vile::current_buffer;
3610   #     $cb->set_region($cb->motion("2b"))->delete;
3611   #                     # delete the previous two words
3612   #
3613   #     $cb->set_region("2b")->delete;
3614   #                     # another way to delete the previous
3615   #                     # two words
3616   #
3617   #     $cb->motion("/foo/");
3618   #                     # position DOT at the beginning of
3619   #                     # "foo".
3620   #
3621   #     $cb->dot($cb->dot);
3622   #                     # Make sure DOT gets propagated back.
3623   #                     # (It won't get propagated unless
3624   #                     # explicitly set.)
3625   #
3626   # =for html <br><br>
3627   #
3628 
3629 void
3630 motion(vbp,mstr)
3631     VileBuf *vbp
3632     char *mstr
3633 
3634     PREINIT:
3635 	I32 gimme;
3636 	struct vile_MARK old_DOT;
3637 	int status;
3638 
3639     PPCODE:
3640 	old_DOT = DOT;
3641 	status = api_motion(vbp, mstr);
3642 
3643 	gimme = GIMME_V;
3644 	if (!status) {
3645 	    XPUSHs(&PL_sv_undef);		/* return undef */
3646 	}
3647 	else if (gimme == G_SCALAR) {
3648 	    XPUSHs(ST(0));		/* return the buffer object */
3649 	}
3650 	else if (gimme == G_ARRAY) {
3651 	    I32 sl, el, so, eo;
3652 	    sl = line_no(curbp, old_DOT.l);
3653 	    so = old_DOT.o;
3654 	    el = line_no(curbp, DOT.l);
3655 	    eo = DOT.o;
3656 	    if (sl > el) {
3657 		I32 tl = sl;
3658 		sl = el;
3659 		el = tl;
3660 	    }
3661 	    if (sl == el && so > eo) {
3662 		I32 to = so;
3663 		so = eo;
3664 		eo = to;
3665 	    }
3666 	    XPUSHs(sv_2mortal(newSViv((IV)sl)));
3667 	    XPUSHs(sv_2mortal(newSViv((IV)so)));
3668 	    XPUSHs(sv_2mortal(newSViv((IV)el)));
3669 	    XPUSHs(sv_2mortal(newSViv((IV)eo)));
3670 	}
3671 
3672   #
3673   # =item new BUFOBJ
3674   #
3675   # =item new PKGNAME
3676   #
3677   # =item new BUFOBJ  FILENAME
3678   #
3679   # =item new PKGNAME FILENAME
3680   #
3681   # =item edit BUFOBJ
3682   #
3683   # =item edit PKGNAME
3684   #
3685   # =item edit BUFOBJ  FILENAME
3686   #
3687   # =item edit PKGNAME FILENAME
3688   #
3689   # These methods create a new buffer and return it.
3690   #
3691   # When no filename is supplied, an anonymous buffer is created.
3692   # These buffer's will be named [unnamed-1], [unnamed-2], etc.  and
3693   # will not have a file name associated with them.
3694   #
3695   # When a name is supplied as an argument to new or edit, a check is
3696   # made to see if the name is the same as an already existing buffer.
3697   # If so, that buffer is returned.  Otherwise, the name is taken to
3698   # be a file name.  If the file exists, it is opened and read into
3699   # the newly created buffer.  If the file does not exist, a new
3700   # buffer will be created with the associated file name.  The name of
3701   # the buffer will be based on the file name.  The file will be
3702   # created when the buffer is first written out to disk.
3703   #
3704   # new and edit are synonyms.  In each case, PKGNAME is Vile::Buffer.
3705   # There is no difference between Vile::Buffer->new($fname) and
3706   # $buf->new($fname).  These two different forms are merely provided
3707   # for convenience.
3708   #
3709   # Example:
3710   #
3711   #     $Vile::current_buffer = new Vile::Buffer 'makefile';
3712   #                                     # open makefile and make it visible
3713   #                                     # on the screen.
3714   #
3715   #     $abuf = new Vile::Buffer;       # Create an anonymous buffer
3716   #     print $abuf "Hello";            # put something in it
3717   #     Vile->current_buffer($abuf);    # make the anonymous buffer current
3718   #                                     #   (viewable).
3719   #
3720   #     Vile->current_buffer($abuf->edit('makefile'));
3721   #                                     # Now makefile is the current
3722   #                                     #   buffer
3723   #     $abuf->current_buffer(Vile::Buffer->new('makefile'));
3724   #                                     # Same thing
3725   #
3726   # =for html <br><br>
3727   #
3728 
3729 VileBuf *
3730 new(...)
3731 
3732     ALIAS:
3733 	edit = 1
3734 
3735     PREINIT:
3736 	char *name;
3737 	VileBuf *newvbp;
3738 
3739     CODE:
3740 	if (items > 2)
3741 	    croak("Too many arguments to %s", GvNAME(CvGV(cv)));
3742 
3743 	name = (items == 1) ? NULL : (char *)SvPV(ST(1),PL_na);
3744 
3745 	(void) api_edit(name, &newvbp);
3746 
3747 	RETVAL = newvbp;
3748 
3749     OUTPUT:
3750 	RETVAL
3751 
3752 
3753   #
3754   # =item print BUFOBJ STR1,..,STRN
3755   #
3756   # =item insert BUFOBJ STR1,...,STRN
3757   #
3758   # Inserts one or more strings the buffer object at the current
3759   # position of DOT.  DOT will be left at the end of the strings
3760   # just inserted.
3761   #
3762   # When STDERR or STDOUT are printed to, the output will be
3763   # directed to the message line.
3764   #
3765   # Examples:
3766   #
3767   #     print "Hello, world!";          # Print a well known greeting on
3768   #                                     # the message line.
3769   #     print $Vile::current_buffer "new text";
3770   #                                     # put some new text in the current
3771   #                                     # buffer.
3772   #
3773   #     my $passbuf = new Vile::Buffer '/etc/passwd';
3774   #                                     # Fetch the password file
3775   #     $passbuf->dot('$$');            # Set the position at the end
3776   #     print $passbuf "joeuser::1000:100:Joe User:/home/joeuser:/bin/bash
3777   #                                     # Add 'joeuser' to the this buffer
3778   #     Vile->current_buffer($passbuf); # Make it visible to the user.
3779   #
3780   # =for html <br><br>
3781   #
3782 
3783 void
3784 PRINT(vbp, ...)
3785     VileBuf *vbp
3786 
3787     ALIAS:
3788 	insert = 1
3789 
3790     PREINIT:
3791 	STRLEN ofs_len;
3792 	STRLEN ors_len;
3793 	char *ofs_str = SvPV(ofs_sv, ofs_len);
3794 	char *ors_str = SvPV(ors_sv, ors_len);
3795 
3796     CODE:
3797 	if (is_delinked_bp(vbp2bp(vbp))) {
3798 	    if (items > 0) {
3799 		SV *tmp = newSVsv(ST(1));
3800 		int i;
3801 
3802 		for (i = 2; i < items; i++) {
3803 		    if (ofs_len > 0)
3804 			sv_catpvn(tmp, ofs_str, ofs_len);
3805 
3806 		    sv_catsv(tmp, ST(i));
3807 		}
3808 
3809 		if (write_message("", tmp))
3810 		    use_ml_as_prompt = 1;
3811 
3812 		SvREFCNT_dec(tmp);
3813 	    }
3814 	}
3815 	else {
3816 	    int i;
3817 	    for (i = 1; i < items; ) {
3818 		STRLEN len;
3819 		char *arg = SvPV(ST(i), len);
3820 		api_dotinsert(vbp, arg, (int) len);
3821 		i++;
3822 		if (i < items && ofs_len > 0)
3823 		    api_dotinsert(vbp, ofs_str, (int) ofs_len);
3824 	    }
3825 
3826 	    if (ors_len)
3827 		api_dotinsert(vbp, ors_str, (int) ors_len);
3828 	}
3829 
3830   #
3831   # =item set_region BUFOBJ
3832   #
3833   # =item set_region BUFOBJ MOTIONSTR
3834   #
3835   # =item set_region BUFOBJ STARTLINE, ENDLINE
3836   #
3837   # =item set_region BUFOBJ STARTLINE, STARTOFFSET, ENDLINE, ENDOFFSET
3838   #
3839   # =item set_region BUFOBJ STARTLINE, STARTOFFSET, ENDLINE, ENDOFFSET, 'rectangle'
3840   #
3841   # =item set_region BUFOBJ STARTLINE, STARTOFFSET, ENDLINE, ENDOFFSET, 'exact'
3842   #
3843   # Sets the region upon which certain other methods will operate and
3844   # sets DOT to the beginning of the region.
3845   #
3846   # Either the line number or offset (or both) may be the special
3847   # string '$' which represents the last line in the buffer and the
3848   # last character on a line.
3849   #
3850   # Often times, however, the special string '$$' will be more useful.
3851   # It truly represents the farthest that it possible to go in both
3852   # the vertical and horizontal directions.  As a line number, this
3853   # represents the line beyond the last line of the buffer.
3854   # Characters inserted at this point will form a new line.  As an
3855   # offset, '$$' refers to the newline character at the end of a line.
3856   # Characters inserted at this point will be inserted before the
3857   # newline character.
3858   #
3859   # When used in an array context, returns a five element array with
3860   # the start line, start offset, end line, end offset, and a string
3861   # indicating the type of region (one of 'line', 'rectangle', or
3862   # 'exact').
3863   #
3864   # When used in a scalar context, returns the buffer object so that
3865   # cascading method calls may be performed, i.e,
3866   #
3867   #     $Vile::current_buffer->set_region(3,4)
3868   #                          ->attribute_cntl_a_sequences;
3869   #
3870   # There is a special form of set_region which may be used as follows:
3871   #
3872   #     $Vile::current_buffer->set_region('j2w');
3873   #
3874   # The above statement will set the region beginning at the current
3875   # location of DOT and ending at the location arrived at by moving
3876   # down one line and over two words.  This may be viewed as a
3877   # shorthand way of expressing the following (somewhat cumbersome)
3878   # statement:
3879   #
3880   #     $Vile::current_buffer->set_region(
3881   #             $Vile::current_buffer->motion('j2w'));
3882   #
3883   # Notes:
3884   #
3885   # =over 4
3886   #
3887   # =item *
3888   #
3889   # rectangular regions are not implemented yet.
3890   #
3891   # =item *
3892   #
3893   # setregion is an alias for set_region.
3894   #
3895   # =back
3896   #
3897   # =for html <br><br>
3898   #
3899 
3900 void
3901 set_region(vbp, ...)
3902     VileBuf *vbp
3903 
3904     ALIAS:
3905 	setregion = 1
3906 
3907     PREINIT:
3908 	I32 gimme;
3909 	char *shapestr;
3910 
3911     PPCODE:
3912 	api_setup_fake_win(vbp, TRUE);
3913 	switch (items) {
3914 	    case 1:
3915 		/* set DOT and recompute region */
3916 		DOT = vbp->region.r_orig;
3917 		MK  = vbp->region.r_end;
3918 		regionshape = vbp->regionshape;
3919 		break;
3920 	    case 2: {
3921 		/* Set up a "motion" region */
3922 		vbp->region.r_orig = DOT;	/* Remember DOT */
3923 		if (api_motion(vbp, SvPV(ST(1), PL_na))) {
3924 		    /* DOT is now at the other end of the motion */
3925 		    MK = vbp->region.r_orig;	/* Put remembered DOT in MK */
3926 		    regionshape = rgn_EXACT;
3927 		}
3928 		else {
3929 		    croak("set_region: Invalid motion");
3930 		}
3931 		break;
3932 	    }
3933 	    case 3:
3934 		/* Set up a full line region */
3935 		regionshape = rgn_FULLLINE;
3936 		api_gotoline(vbp, sv2linenum(ST(2)));
3937 		MK = DOT;
3938 		api_gotoline(vbp, sv2linenum(ST(1)));
3939 		break;
3940 	    case 5:
3941 		/* Set up an exact region */
3942 		regionshape = rgn_EXACT;
3943 		goto set_region_common;
3944 	    case 6:
3945 		/* Set up any kind of region (exact, fullline, or rectangle) */
3946 		shapestr = SvPV(ST(5), PL_na);
3947 		if (strcmp(shapestr, "exact"))
3948 		    regionshape = rgn_EXACT;
3949 		else if (strcmp(shapestr, "rectangle"))
3950 		    regionshape = rgn_RECTANGLE;
3951 		else if (strcmp(shapestr, "fullline"))
3952 		    regionshape = rgn_FULLLINE;
3953 		else {
3954 		    croak("Region shape argument not one of \"exact\", \"fullline\", or \"rectangle\"");
3955 		}
3956 	    set_region_common:
3957 		api_gotoline(vbp, sv2linenum(ST(3)));
3958 		DOT.o = sv2offset(ST(4));
3959 		MK = DOT;
3960 		api_gotoline(vbp, sv2linenum(ST(1)));
3961 		DOT.o = sv2offset(ST(2));
3962 		break;
3963 	    default:
3964 		croak("Invalid number of arguments to set_region");
3965 		break;
3966 	}
3967 	haveregion = NULL;
3968 	if (getregion(curbp, &vbp->region) != TRUE) {
3969 	    croak("set_region: Unable to set the region");
3970 	}
3971 	if (is_header_line(vbp->region.r_end, curbp)
3972 	    && !b_val(curbp, MDNEWLINE))
3973 		vbp->region.r_size -= (B_COUNT) len_record_sep(curbp);
3974 	IoLINES(GvIO((GV*)vbp->perl_handle)) = 0;  /* reset $. */
3975 	vbp->regionshape = regionshape;
3976 	DOT = vbp->region.r_orig;
3977 	vbp->dot_inited = 1;
3978 	gimme = GIMME_V;
3979 	if (gimme == G_SCALAR) {
3980 	    XPUSHs(ST(0));
3981 	}
3982 	else if (gimme == G_ARRAY) {
3983 	    /* Return range information */
3984 	    XPUSHs(sv_2mortal(newSViv((IV)line_no(curbp, vbp->region.r_orig.l))));
3985 	    XPUSHs(sv_2mortal(newSViv((IV)vbp->region.r_orig.o)));
3986 	    XPUSHs(sv_2mortal(newSViv((IV)line_no(curbp, vbp->region.r_end.l)
3987 						     - (vbp->regionshape == rgn_FULLLINE))));
3988 	    XPUSHs(sv_2mortal(newSViv((IV)vbp->region.r_end.o)));
3989 	    XPUSHs(sv_2mortal(newSVpv(
3990 		vbp->regionshape == rgn_FULLLINE ? "fullline" :
3991 		vbp->regionshape == rgn_EXACT    ? "exact"
3992 						 : "rectangle",
3993 		(size_t) 0 )));
3994 	}
3995 
3996 
3997   #
3998   # =item unmark
3999   #
4000   # Clear the "modified" status of the buffer.
4001   #
4002   # Returns the buffer object.
4003   #
4004   # =for html <br><br>
4005   #
4006 
4007 VileBuf *
4008 unmark(vbp)
4009     VileBuf *vbp
4010 
4011     CODE:
4012 	api_setup_fake_win(vbp, TRUE);
4013 	unmark(0,0);
4014 	RETVAL = vbp;
4015 
4016     OUTPUT:
4017 	RETVAL
4018 
4019 MODULE = Vile	PACKAGE = Vile::Window
4020 
4021   # =back
4022   #
4023   # =head2 Package Vile::Window
4024   #
4025   # The Vile::Window package contains methods for manipulating windows
4026   # in various ways.  For the purposes of this discussion, a window is
4027   # one of the areas of the screen in which a portion of a buffer may
4028   # be viewed by the user.
4029   #
4030   # This API allows you to do the following things to one of these
4031   # windows:
4032   #
4033   # =over 4
4034   #
4035   # =item *
4036   #
4037   # Create new windows (by splitting an existing window)
4038   #
4039   # =item *
4040   #
4041   # Delete windows
4042   #
4043   # =item *
4044   #
4045   # Obtain the buffer (Vile::Buffer) object associated
4046   # with a given window
4047   #
4048   # =item *
4049   #
4050   # Change the buffer associated with a window
4051   #
4052   # =item *
4053   #
4054   # Obtain list of all windows
4055   #
4056   # =item *
4057   #
4058   # Obtain window characteristics (width, height)
4059   #
4060   # =item *
4061   #
4062   # Change window characteristics (height)
4063   #
4064   # =item *
4065   #
4066   # Get/Set DOT for buffer associated with the window
4067   #
4068   # =item *
4069   #
4070   # Get/Set top line
4071   #
4072   # =back
4073   #
4074   # In the documentation below, WINOBJ refers to an object of
4075   # Vile::Window and BUFOBJ refers to an object of Vile::Buffer.
4076   #
4077   # =head2 Package Vile::Window Methods
4078   #
4079   # =over 4
4080   #
4081 
4082   #
4083   # =item buffer WINOBJ
4084   #
4085   # Returns the buffer associated with WINOBJ.
4086   #
4087   # E.g,
4088   #
4089   #     $buf = Vile::current_window->buffer
4090   #
4091   # would get you the buffer associated with the current window.
4092   #
4093   # =for html <br><br>
4094   #
4095   # =item buffer WINOBJ BUFOBJ
4096   #
4097   # Sets the buffer associated with WINOBJ to BUFOBJ.  Returns
4098   # BUFOBJ.
4099   #
4100   # =for html <br><br>
4101   #
4102 
4103 VileBuf *
4104 buffer(vw, ...)
4105     VileWin vw
4106 
4107     CODE:
4108 	if (items > 2)
4109 	    croak("Vile::Window::buffer: Too many arguments.");
4110 	else if (items == 2) {
4111 	    const char *croakmess;
4112 	    VileBuf *vbp;
4113 	    WINDOW *savewp = curwp;
4114 	    vbp = getVB(ST(1), &croakmess);
4115 	    if (vbp == 0)
4116 		croak("Vile::Window::buffer: %s", croakmess);
4117 	    set_curwp(vw);
4118 	    swbuffer_lfl(vbp2bp(vbp), FALSE, TRUE);
4119 	    curwp = savewp;
4120 	    curbp = curwp->w_bufp;
4121 	}
4122 
4123 	RETVAL = api_bp2vbp(vw->w_bufp);
4124 
4125     OUTPUT:
4126 	RETVAL
4127 
4128   #
4129   # =item current_window
4130   #
4131   # Returns the Vile::Window object representing the current window.
4132   #
4133   # Note: This method is also in the Vile:: package.
4134   #
4135   # =for html <br><br>
4136   #
4137   # =item current_window WINOBJ
4138   #
4139   # Sets the current window (window with focus) to WINOBJ; Returns
4140   # WINOBJ.
4141   #
4142   # Note:  You'd say
4143   #
4144   #     $curwin = Vile::current_window;
4145   #
4146   # to retrieve the current window and
4147   #
4148   #     $mywin->current_window;
4149   #
4150   # to set it.
4151   #
4152   # =for html <br><br>
4153   #
4154 
4155 VileWin
4156 current_window(...)
4157 
4158     ALIAS:
4159 	Vile::current_window = 1
4160     PREINIT:
4161 	int argno;
4162 
4163     CODE:
4164 	argno = 0;
4165 
4166 	if (strcmp(SvPV(ST(argno), PL_na), "Vile") == 0)
4167 	    argno++;
4168 
4169 	if (items - argno == 0) { /* getter */
4170 	    RETVAL = curwp_visible ? curwp_visible : curwp;
4171 	}
4172 	else if (items - argno == 1) { /* setter */
4173 	    VileWin vw;
4174 	    const char *croakmess;
4175 	    /* Need a window object */
4176 	    vw = getVW(ST(argno), &croakmess);
4177 
4178 	    if (vw == 0)
4179 		croak("Vile::%scurrent_window: %s",
4180 		      ix == 1 ? "Window::" : "",
4181 		      croakmess);
4182 	    set_curwp(vw);
4183 	    curwp_visible = curwp;
4184 	    RETVAL = curwp;
4185 	}
4186 	else {
4187 	    croak("Vile::%scurrent_window:  Incorrect number of arguments",
4188 		  ix == 1 ? "Window::" : "");
4189 	}
4190 
4191     OUTPUT:
4192 	RETVAL
4193 
4194   #
4195   # =item delete WINOBJ
4196   #
4197   # Removes the window in question.  Screen real estate allocated to
4198   # the window will be returned to the window from whence it came.
4199   #
4200   # Returns 1 if successful, undef otherwise.
4201   #
4202   # =for html <br><br>
4203   #
4204 
4205 void
4206 delete(vw)
4207     VileWin vw
4208 
4209     PREINIT:
4210 	WINDOW *wp;
4211 	int count;
4212 
4213     PPCODE:
4214 	/* See how many visible windows remain.  We can't simply test to
4215 	   see if wheadp->w_wndp is NULL because, there may be some fake
4216 	   windows pushed for Perl's purposes.  So we actually have to
4217 	   count them. */
4218 	count = 0;
4219 	for_each_visible_window(wp) {
4220 	    count++;
4221 	}
4222 	if (count <= 1 || !delwp(vw)) {
4223 	    XPUSHs(&PL_sv_undef);
4224 	}
4225 	else {
4226 	    XPUSHs(sv_2mortal(newSViv((IV)1)));
4227 	}
4228 
4229   #
4230   # =item dot WINOBJ
4231   #
4232   # =item current_position WINOBJ
4233   #
4234   # Retrieves DOT (the current position) for the current window.
4235   # In a scalar context, only the line number is returned.  In
4236   # an array context, a list containing both the line number and
4237   # offset within the line are returned.
4238   #
4239   # =for html <br><br>
4240   #
4241   # =item dot WINOBJ LINENUM, OFFSET
4242   #
4243   # =item current_position WINOBJ LINENUM, OFFSET
4244   #
4245   # Sets DOT (the current position) to the indicated values.
4246   #
4247   # When used in a scalar context, returns the line number.  When
4248   # used in a list context, returns both the line number and the
4249   # offset with in the line.
4250   #
4251   # Note: dot and current_position are aliases for each other.  Neither
4252   # provides any additional functionality over the other.
4253   #
4254   # =for html <br><br>
4255   #
4256 
4257 void
4258 dot(vw, ...)
4259     VileWin vw
4260 
4261     ALIAS:
4262 	current_position = 1
4263 
4264     PREINIT:
4265 	I32 gimme;
4266 
4267     PPCODE:
4268 	if (items > 3) {
4269 	    croak("Vile::Window::%s: Too many arguments",
4270 		  ix == 1 ? "current_position" : "dot");
4271 	}
4272 	else if (items > 1) {
4273 	    /* Setter: expect a line spec and possibly an offset */
4274 	    WINDOW *savewp = set_curwp0(vw);
4275 	    gotoline(TRUE, sv2linenum(ST(1)));
4276 
4277 	    if (items == 3)
4278 		DOT.o = sv2offset(ST(2));
4279 
4280 	    set_curwp0(savewp);
4281 	}
4282 	gimme = GIMME_V;
4283 	if (gimme == G_SCALAR || gimme == G_ARRAY) {
4284 	    /* Return line number when in either a scalar or an array context */
4285 	    XPUSHs(sv_2mortal(newSViv(
4286 		(IV)line_no(vw->w_bufp, vw->w_traits.w_dt.l))));
4287 	}
4288 	if (gimme == G_ARRAY) {
4289 	    /* When in an array context, also return the line offset */
4290 	    XPUSHs(sv_2mortal(newSViv((IV)vw->w_traits.w_dt.o)));
4291 	}
4292 
4293   #
4294   # =item index WINOBJ
4295   #
4296   # Returns the index of WINOBJ.  This will be a small integer, with
4297   # 0 representing the first (top-most) window, 1 representing the
4298   # window below it, and so on.
4299   #
4300   # =for html <br><br>
4301   #
4302 
4303 int
4304 index(win)
4305     VileWin win;
4306 
4307     CODE:
4308 	RETVAL = win2index(win);
4309 
4310     OUTPUT:
4311 	RETVAL
4312 
4313   #
4314   # =item new Vile::Window
4315   #
4316   # Allocates and returns a new window.  The editor will choose
4317   # where the window will be located.  (It will likely choose a
4318   # large window to split.)  If a new window could not be allocated,
4319   # return undef.
4320   #
4321   # =for html <br><br>
4322   #
4323   # =item new Vile::Window BUFOBJ
4324   #
4325   # Like above, but associate BUFOBJ with the new window.
4326   #
4327   # =for html <br><br>
4328   #
4329   # =item new WINOBJ
4330   #
4331   # Allocate and return a new window, using WINOBJ as the window
4332   # to split.  If this cannot be done, return undef.  If the split
4333   # is possible, the new window returned will be located below
4334   # WINOBJ.
4335   #
4336   # =for html <br><br>
4337   #
4338   # =item new WINOBJ BUFOBJ
4339   #
4340   # Like above, but associate BUFOBJ with the new window.
4341   #
4342   # =for html <br><br>
4343   #
4344 
4345 VileWin
4346 new(...)
4347 
4348     PREINIT:
4349 	VileBuf *vbp;
4350 	VileWin vw;
4351 
4352     CODE:
4353 	if (items == 2) {
4354 	    const char *croakmess;
4355 	    vbp = getVB(ST(1), &croakmess);
4356 	    if (!vbp)
4357 		croak("Vile::Window::new: %s",croakmess);
4358 	}
4359 	else
4360 	    vbp = 0;
4361 
4362 	if (items > 2)
4363 	    croak("Vile::Window::new: Too many arguments.");
4364 	else if (items < 1)
4365 	    croak("Vile::Window::new: Too few arguments.");
4366 	else if (strcmp(SvPV(ST(0),PL_na), "Vile::Window") == 0) {
4367 	    vw = wpopup();
4368 	}
4369 	else if (sv_isa(ST(0), "Vile::Window")) {
4370 	    const char *croakmess;
4371 	    vw = getVW(ST(0), &croakmess);	/* Fetch window object */
4372 	    if (vw == 0)
4373 		croak("Vile::Window::new: %s", croakmess);
4374 
4375 	    if (vw->w_ntrows < MINWLNS)
4376 		vw = NULL;		/* Can't split */
4377 	    else {
4378 		WINDOW *save_wp = set_curwp0(vw);
4379 		splitwind(TRUE, 1);	/* split window forcing new
4380 					   window to be on bottom */
4381 		vw = vw->w_wndp;
4382 		set_curwp0(save_wp);
4383 	    }
4384 	}
4385 	else
4386 	    croak("Vile::Window::new: Incorrect type for first argument");
4387 
4388 	if (vw && vbp) {
4389 	    WINDOW *savewp = set_curwp0(vw);
4390 	    swbuffer_lfl(vbp2bp(vbp), FALSE, TRUE);
4391 	    set_curwp0(savewp);
4392 	}
4393 
4394 	RETVAL = vw;
4395 
4396     OUTPUT:
4397 	RETVAL
4398 
4399   #
4400   # =item size WINOBJ
4401   #
4402   # In a scalar context, return the height of a window.  In a list
4403   # context, return both the height and width.
4404   #
4405   # =for html <br><br>
4406   #
4407   # =item size WINOBJ HEIGHT
4408   #
4409   # Set the height of a window.  It will attempt to change a windows
4410   # size by either adding or stealing lines from the window below.
4411   # (This means that the bottommost window can't be directly changed
4412   # since it doesn't have a window below it.)
4413   #
4414   # Returns the new size of the window.
4415   #
4416   # =for html <br><br>
4417   #
4418   # =item size WINOBJ HEIGHT WIDTH
4419   #
4420   # Unimplemented.  It is not possible to change the width at the
4421   # moment, but if the feature ever becomes available, this method
4422   # will do it.
4423   #
4424   # =for html <br><br>
4425   #
4426 
4427 void
4428 size(vw, ...)
4429     VileWin vw
4430 
4431     PREINIT:
4432 	I32 gimme;
4433 
4434     PPCODE:
4435 	if (items > 2) {
4436 	    croak("Vile::Window::size: Invalid number of arguments");
4437 	}
4438 	else if (items == 2) {
4439 	    WINDOW *savewp;
4440 	    int newheight = SvIV(ST(1));
4441 	    int maxheight;
4442 
4443 	    if (newheight < 1)
4444 		croak("Vile::Window::size: New height must be 1 or larger");
4445 	    if (vw->w_wndp == NULL)
4446 		croak("Vile::Window::size: Can't change bottom window");
4447 	    maxheight = vw->w_ntrows + vw->w_wndp->w_ntrows - 1;
4448 	    if (newheight > maxheight)
4449 		newheight = maxheight;
4450 
4451 	    savewp = set_curwp0(vw);
4452 	    resize(TRUE, newheight);
4453 	    set_curwp0(savewp);
4454 	}
4455 	gimme = GIMME_V;
4456 	if (gimme == G_SCALAR) {
4457 	    XPUSHs(sv_2mortal(newSViv((IV)vw->w_ntrows)));
4458 	}
4459 	else if (gimme == G_ARRAY) {
4460 	    XPUSHs(sv_2mortal(newSViv((IV)vw->w_ntrows)));
4461 	    XPUSHs(sv_2mortal(newSViv((IV)term.cols)));
4462 	}
4463 
4464   #
4465   # =item topline WINOBJ
4466   #
4467   # Returns the line number of the top line in the window.
4468   #
4469   # =for html <br><br>
4470   #
4471 
4472 int
4473 topline(vw, ...)
4474     VileWin vw
4475 
4476     CODE:
4477 	if (items > 2) {
4478 	    croak("Vile::Window::topline: Too many arguments");
4479 	}
4480 	else if (items > 1) {
4481 	    /* Setter: expect a line spec */
4482 	    WINDOW *savewp = set_curwp0(vw);
4483 	    int lcur;
4484 	    lcur = line_no(curwp->w_bufp, curwp->w_line.l);
4485 	    mvupwind(TRUE, lcur - sv2linenum(ST(1)));
4486 	    set_curwp0(savewp);
4487 	}
4488 	RETVAL = line_no(vw->w_bufp, vw->w_line.l);
4489 
4490     OUTPUT:
4491 	RETVAL
4492 
4493   #
4494   # =item window_at N
4495   #
4496   # Returns the Nth (starting at 0 from the top-most window) Vile::Window
4497   # object.  If there is no Nth window, undef is returned instead.
4498   #
4499   # Note: This method also appears in the Vile:: package.
4500   #
4501   # =for html <br><br>
4502   #
4503 
4504 VileWin
4505 window_at(idx)
4506     int idx
4507 
4508     ALIAS:
4509 	Vile::window_at = 1
4510 
4511     CODE:
4512 	RETVAL = index2win(idx);
4513 
4514     OUTPUT:
4515 	RETVAL
4516 
4517   #
4518   # =item window_count
4519   #
4520   # Returns number of (visible) windows.
4521   #
4522   # Note:  Non-visible windows are used to represent buffers
4523   # for the perl API.  They are also used for other purposes in
4524   # which modification of a buffer is desired, but disturbing
4525   # the position of the buffer within one of its windows is
4526   # not.
4527   #
4528   # Note: This method also appears in the Vile:: package.
4529   #
4530   # =for html <br><br>
4531   #
4532   # =back
4533 
4534 int
4535 window_count()
4536 
4537     ALIAS:
4538 	Vile::window_count = 1
4539 
4540     PREINIT:
4541 	int count;
4542 	WINDOW *wp;
4543 
4544     CODE:
4545 	count = 0;
4546 	for_each_visible_window(wp)
4547 	    count++;
4548 	RETVAL = count;
4549 
4550     OUTPUT:
4551 	RETVAL
4552