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, ®ion)) {
327 haveregion = ®ion;
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, ®ion) != TRUE) {
460 /* shouldn't ever get here. But just in case... */
461 perl_default_region();
462 if (getregion(curbp, ®ion) != 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