head	1.13;
access;
symbols
	perseant-exfatfs-base-20250801:1.13
	perseant-exfatfs-base-20240630:1.13
	perseant-exfatfs:1.13.0.36
	perseant-exfatfs-base:1.13
	cjep_sun2x:1.13.0.34
	cjep_sun2x-base:1.13
	cjep_staticlib_x-base1:1.13
	cjep_staticlib_x:1.13.0.32
	cjep_staticlib_x-base:1.13
	phil-wifi-20200421:1.13
	phil-wifi-20200411:1.13
	phil-wifi-20200406:1.13
	pgoyette-compat-merge-20190127:1.13
	pgoyette-compat-20190127:1.13
	pgoyette-compat-20190118:1.13
	pgoyette-compat-1226:1.13
	pgoyette-compat-1126:1.13
	pgoyette-compat-1020:1.13
	pgoyette-compat-0930:1.13
	pgoyette-compat-0906:1.13
	pgoyette-compat-0728:1.13
	pgoyette-compat-0625:1.13
	pgoyette-compat-0521:1.13
	pgoyette-compat-0502:1.13
	pgoyette-compat-0422:1.13
	pgoyette-compat-0415:1.13
	pgoyette-compat-0407:1.13
	pgoyette-compat-0330:1.13
	pgoyette-compat-0322:1.13
	pgoyette-compat-0315:1.13
	pgoyette-compat:1.13.0.30
	pgoyette-compat-base:1.13
	perseant-stdc-iso10646:1.13.0.28
	perseant-stdc-iso10646-base:1.13
	prg-localcount2-base3:1.13
	prg-localcount2-base2:1.13
	prg-localcount2-base1:1.13
	prg-localcount2:1.13.0.26
	prg-localcount2-base:1.13
	pgoyette-localcount-20170426:1.13
	bouyer-socketcan-base1:1.13
	pgoyette-localcount-20170320:1.13
	bouyer-socketcan:1.13.0.24
	bouyer-socketcan-base:1.13
	pgoyette-localcount-20170107:1.13
	pgoyette-localcount-20161104:1.13
	localcount-20160914:1.13
	pgoyette-localcount-20160806:1.13
	pgoyette-localcount-20160726:1.13
	pgoyette-localcount:1.13.0.22
	pgoyette-localcount-base:1.13
	netbsd-5-2-3-RELEASE:1.13
	netbsd-5-1-5-RELEASE:1.13
	yamt-pagecache-base9:1.13
	yamt-pagecache-tag8:1.13
	tls-earlyentropy:1.13.0.18
	tls-earlyentropy-base:1.13
	riastradh-xf86-video-intel-2-7-1-pre-2-21-15:1.13
	riastradh-drm2-base3:1.13
	netbsd-5-2-2-RELEASE:1.13
	netbsd-5-1-4-RELEASE:1.13
	netbsd-5-2-1-RELEASE:1.13
	netbsd-5-1-3-RELEASE:1.13
	agc-symver:1.13.0.20
	agc-symver-base:1.13
	tls-maxphys-base:1.13
	yamt-pagecache-base8:1.13
	netbsd-5-2:1.13.0.16
	yamt-pagecache-base7:1.13
	netbsd-5-2-RELEASE:1.13
	netbsd-5-2-RC1:1.13
	yamt-pagecache-base6:1.13
	yamt-pagecache-base5:1.13
	yamt-pagecache-base4:1.13
	netbsd-5-1-2-RELEASE:1.13
	netbsd-5-1-1-RELEASE:1.13
	yamt-pagecache-base3:1.13
	yamt-pagecache-base2:1.13
	yamt-pagecache:1.13.0.14
	yamt-pagecache-base:1.13
	bouyer-quota2-nbase:1.13
	bouyer-quota2:1.13.0.12
	bouyer-quota2-base:1.13
	matt-nb5-pq3:1.13.0.10
	matt-nb5-pq3-base:1.13
	netbsd-5-1:1.13.0.8
	netbsd-5-1-RELEASE:1.13
	netbsd-5-1-RC4:1.13
	netbsd-5-1-RC3:1.13
	netbsd-5-1-RC2:1.13
	netbsd-5-1-RC1:1.13
	netbsd-5-0-2-RELEASE:1.13
	netbsd-5-0-1-RELEASE:1.13
	jym-xensuspend-nbase:1.13
	netbsd-5-0:1.13.0.6
	netbsd-5-0-RELEASE:1.13
	netbsd-5-0-RC4:1.13
	netbsd-5-0-RC3:1.13
	netbsd-5-0-RC2:1.13
	jym-xensuspend:1.13.0.4
	jym-xensuspend-base:1.13
	netbsd-5-0-RC1:1.13
	netbsd-5:1.13.0.2
	netbsd-5-base:1.13
	matt-mips64-base2:1.12
	matt-mips64:1.12.0.26
	mjf-devfs2:1.12.0.24
	mjf-devfs2-base:1.12
	netbsd-4-0-1-RELEASE:1.12
	wrstuden-revivesa-base-3:1.12
	wrstuden-revivesa-base-2:1.12
	wrstuden-fixsa-newbase:1.12
	wrstuden-revivesa-base-1:1.12
	yamt-pf42-base4:1.12
	yamt-pf42-base3:1.12
	hpcarm-cleanup-nbase:1.12
	yamt-pf42-baseX:1.12
	yamt-pf42-base2:1.12
	wrstuden-revivesa:1.12.0.22
	wrstuden-revivesa-base:1.12
	yamt-pf42:1.12.0.20
	yamt-pf42-base:1.12
	keiichi-mipv6-nbase:1.12
	keiichi-mipv6:1.12.0.18
	keiichi-mipv6-base:1.12
	matt-armv6-nbase:1.12
	matt-armv6-prevmlocking:1.12
	wrstuden-fixsa-base-1:1.12
	netbsd-4-0:1.12.0.16
	netbsd-4-0-RELEASE:1.12
	cube-autoconf:1.12.0.14
	cube-autoconf-base:1.12
	netbsd-4-0-RC5:1.12
	netbsd-4-0-RC4:1.12
	netbsd-4-0-RC3:1.12
	netbsd-4-0-RC2:1.12
	netbsd-4-0-RC1:1.12
	matt-armv6:1.12.0.12
	matt-armv6-base:1.12
	matt-mips64-base:1.12
	hpcarm-cleanup:1.12.0.10
	hpcarm-cleanup-base:1.12
	netbsd-3-1-1-RELEASE:1.11
	netbsd-3-0-3-RELEASE:1.11
	wrstuden-fixsa:1.12.0.8
	wrstuden-fixsa-base:1.12
	abandoned-netbsd-4-base:1.12
	abandoned-netbsd-4:1.12.0.4
	netbsd-3-1:1.11.0.6
	netbsd-3-1-RELEASE:1.11
	netbsd-3-0-2-RELEASE:1.11
	netbsd-3-1-RC4:1.11
	netbsd-3-1-RC3:1.11
	netbsd-3-1-RC2:1.11
	netbsd-3-1-RC1:1.11
	netbsd-4:1.12.0.6
	netbsd-4-base:1.12
	chap-midi-nbase:1.12
	netbsd-3-0-1-RELEASE:1.11
	chap-midi:1.12.0.2
	chap-midi-base:1.12
	netbsd-3-0:1.11.0.4
	netbsd-3-0-RELEASE:1.11
	netbsd-3-0-RC6:1.11
	netbsd-3-0-RC5:1.11
	netbsd-3-0-RC4:1.11
	netbsd-3-0-RC3:1.11
	netbsd-3-0-RC2:1.11
	netbsd-3-0-RC1:1.11
	netbsd-2-0-3-RELEASE:1.10.2.2
	netbsd-2-1:1.10.4.1.0.2
	netbsd-2-1-RELEASE:1.10.4.1
	netbsd-2-1-RC6:1.10.4.1
	netbsd-2-1-RC5:1.10.4.1
	netbsd-2-1-RC4:1.10.4.1
	netbsd-2-1-RC3:1.10.4.1
	netbsd-2-1-RC2:1.10.4.1
	netbsd-2-1-RC1:1.10.4.1
	netbsd-2-0-2-RELEASE:1.10.2.2
	netbsd-3:1.11.0.2
	netbsd-3-base:1.11
	netbsd-2-0-1-RELEASE:1.10
	netbsd-2:1.10.0.4
	netbsd-2-base:1.10
	netbsd-2-0-RELEASE:1.10
	netbsd-2-0-RC5:1.10
	netbsd-2-0-RC4:1.10
	netbsd-2-0-RC3:1.10
	netbsd-2-0-RC2:1.10
	netbsd-2-0-RC1:1.10
	netbsd-2-0:1.10.0.2
	netbsd-2-0-base:1.10
	netbsd-1-6-PATCH002-RELEASE:1.9
	netbsd-1-6-PATCH002:1.9
	netbsd-1-6-PATCH002-RC4:1.9
	netbsd-1-6-PATCH002-RC3:1.9
	netbsd-1-6-PATCH002-RC2:1.9
	netbsd-1-6-PATCH002-RC1:1.9
	netbsd-1-6-PATCH001:1.9
	netbsd-1-6-PATCH001-RELEASE:1.9
	netbsd-1-6-PATCH001-RC3:1.9
	netbsd-1-6-PATCH001-RC2:1.9
	netbsd-1-6-PATCH001-RC1:1.9
	fvdl_fs64_base:1.10
	netbsd-1-6-RELEASE:1.9
	netbsd-1-6-RC3:1.9
	netbsd-1-6-RC2:1.9
	netbsd-1-6-RC1:1.9
	netbsd-1-6:1.9.0.2
	netbsd-1-6-base:1.9
	netbsd-1-5-PATCH003:1.7
	netbsd-1-5-PATCH002:1.7
	netbsd-1-5-PATCH001:1.7
	nvi_1_79:1.1.1.6
	netbsd-1-5-RELEASE:1.7
	netbsd-1-5-BETA2:1.7
	netbsd-1-5-BETA:1.7
	netbsd-1-4-PATCH003:1.7
	netbsd-1-5-ALPHA2:1.7
	netbsd-1-5:1.7.0.10
	netbsd-1-5-base:1.7
	minoura-xpg4dl-base:1.7
	minoura-xpg4dl:1.7.0.8
	netbsd-1-4-PATCH002:1.7
	wrstuden-devbsize-19991221:1.7
	wrstuden-devbsize:1.7.0.6
	wrstuden-devbsize-base:1.7
	comdex-fall-1999:1.7.0.4
	comdex-fall-1999-base:1.7
	netbsd-1-4-PATCH001:1.7
	netbsd-1-4-RELEASE:1.7
	netbsd-1-4:1.7.0.2
	netbsd-1-4-base:1.7
	netbsd-1-3-PATCH003:1.6
	netbsd-1-3-PATCH003-CANDIDATE2:1.6
	netbsd-1-3-PATCH003-CANDIDATE1:1.6
	netbsd-1-3-PATCH003-CANDIDATE0:1.6
	netbsd-1-3-PATCH002:1.6
	netbsd-1-3-PATCH001:1.6
	netbsd-1-3-RELEASE:1.6
	netbsd-1-3-BETA:1.6
	netbsd-1-3:1.6.0.2
	netbsd-1-3-base:1.6
	netbsd-1-2-PATCH001:1.6
	netbsd-1-2-RELEASE:1.6
	netbsd-1-2-BETA:1.6
	netbsd-1-2:1.6.0.4
	netbsd-1-2-base:1.6
	nvi_1_66:1.1.1.5
	BOSTIC:1.1.1
	netbsd-1-1-PATCH001:1.5
	netbsd-1-1-RELEASE:1.5
	netbsd-1-1:1.5.0.4
	netbsd-1-1-base:1.5
	netbsd-1-0-PATCH06:1.5
	netbsd-1-0-PATCH05:1.5
	netbsd-1-0-PATCH04:1.5
	netbsd-1-0-PATCH03:1.5
	netbsd-1-0-PATCH02:1.5
	netbsd-1-0-PATCH1:1.5
	netbsd-1-0-PATCH0:1.5
	netbsd-1-0-RELEASE:1.5
	netbsd-1-0:1.5.0.2
	nvi-1-34b:1.1.1.4
	nvi-1-33b:1.1.1.3
	netbsd-1-0-base:1.3
	nvi-1-11b:1.1.1.2
	nvi-1-03:1.1.1.1
	bostic-nvi:1.1.1;
locks; strict;
comment	@ * @;


1.13
date	2008.10.29.16.49.36;	author christos;	state dead;
branches;
next	1.12;

1.12
date	2005.06.07.13.34.10;	author he;	state Exp;
branches;
next	1.11;

1.11
date	2005.02.12.12.53.22;	author aymeric;	state Exp;
branches;
next	1.10;

1.10
date	2002.12.06.03.24.42;	author thorpej;	state Exp;
branches
	1.10.2.1
	1.10.4.1;
next	1.9;

1.9
date	2002.04.09.01.47.32;	author thorpej;	state Exp;
branches;
next	1.8;

1.8
date	2001.03.31.11.37.49;	author aymeric;	state Exp;
branches;
next	1.7;

1.7
date	98.01.09.08.07.39;	author perry;	state Exp;
branches;
next	1.6;

1.6
date	96.05.20.03.47.21;	author mrg;	state Exp;
branches;
next	1.5;

1.5
date	94.08.17.20.12.08;	author cgd;	state Exp;
branches
	1.5.2.1;
next	1.4;

1.4
date	94.08.17.16.35.38;	author cgd;	state Exp;
branches;
next	1.3;

1.3
date	94.03.28.04.29.03;	author cgd;	state Exp;
branches;
next	1.2;

1.2
date	94.01.24.06.40.05;	author cgd;	state Exp;
branches;
next	1.1;

1.1
date	94.01.24.05.53.01;	author cgd;	state Exp;
branches
	1.1.1.1;
next	;

1.10.2.1
date	2005.02.12.12.24.12;	author aymeric;	state Exp;
branches;
next	1.10.2.2;

1.10.2.2
date	2005.02.12.12.46.26;	author aymeric;	state Exp;
branches;
next	;

1.10.4.1
date	2005.05.06.14.42.05;	author riz;	state Exp;
branches;
next	;

1.5.2.1
date	94.08.17.20.12.08;	author cgd;	state dead;
branches;
next	1.5.2.2;

1.5.2.2
date	94.08.17.20.12.09;	author cgd;	state Exp;
branches;
next	;

1.1.1.1
date	94.01.24.05.53.02;	author cgd;	state Exp;
branches;
next	1.1.1.2;

1.1.1.2
date	94.03.28.02.53.01;	author cgd;	state Exp;
branches;
next	1.1.1.3;

1.1.1.3
date	94.08.17.16.16.16;	author cgd;	state Exp;
branches;
next	1.1.1.4;

1.1.1.4
date	94.08.17.19.16.59;	author cgd;	state Exp;
branches;
next	1.1.1.5;

1.1.1.5
date	96.05.20.01.53.50;	author mrg;	state Exp;
branches;
next	1.1.1.6;

1.1.1.6
date	2001.03.31.11.29.45;	author aymeric;	state Exp;
branches;
next	;


desc
@@


1.13
log
@bye old vi!
@
text
@/*	$NetBSD: ex_append.c,v 1.12 2005/06/07 13:34:10 he Exp $	*/

/*-
 * Copyright (c) 1992, 1993, 1994
 *	The Regents of the University of California.  All rights reserved.
 * Copyright (c) 1992, 1993, 1994, 1995, 1996
 *	Keith Bostic.  All rights reserved.
 *
 * See the LICENSE file for redistribution information.
 */

#include "config.h"

#include <sys/cdefs.h>
#ifndef lint
#if 0
static const char sccsid[] = "@@(#)ex_append.c	10.30 (Berkeley) 10/23/96";
#else
__RCSID("$NetBSD: ex_append.c,v 1.12 2005/06/07 13:34:10 he Exp $");
#endif
#endif /* not lint */

#include <sys/types.h>
#include <sys/queue.h>

#include <bitstring.h>
#include <limits.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

#include "../common/common.h"

enum which {APPEND, CHANGE, INSERT};

static int ex_aci __P((SCR *, EXCMD *, enum which));

/*
 * ex_append -- :[line] a[ppend][!]
 *	Append one or more lines of new text after the specified line,
 *	or the current line if no address is specified.
 *
 * PUBLIC: int ex_append __P((SCR *, EXCMD *));
 */
int
ex_append(sp, cmdp)
	SCR *sp;
	EXCMD *cmdp;
{
	return (ex_aci(sp, cmdp, APPEND));
}

/*
 * ex_change -- :[line[,line]] c[hange][!] [count]
 *	Change one or more lines to the input text.
 *
 * PUBLIC: int ex_change __P((SCR *, EXCMD *));
 */
int
ex_change(sp, cmdp)
	SCR *sp;
	EXCMD *cmdp;
{
	return (ex_aci(sp, cmdp, CHANGE));
}

/*
 * ex_insert -- :[line] i[nsert][!]
 *	Insert one or more lines of new text before the specified line,
 *	or the current line if no address is specified.
 *
 * PUBLIC: int ex_insert __P((SCR *, EXCMD *));
 */
int
ex_insert(sp, cmdp)
	SCR *sp;
	EXCMD *cmdp;
{
	return (ex_aci(sp, cmdp, INSERT));
}

/*
 * ex_aci --
 *	Append, change, insert in ex.
 */
static int
ex_aci(sp, cmdp, cmd)
	SCR *sp;
	EXCMD *cmdp;
	enum which cmd;
{
	CHAR_T *p, *t;
	GS *gp;
	TEXT *tp;
	TEXTH tiq;
	recno_t cnt, lno;
	size_t len;
	u_int32_t flags;
	int need_newline;

	t = NULL;	/* XXXGCC -Wuninitialized [sun2] */

	gp = sp->gp;
	NEEDFILE(sp, cmdp);

	/*
	 * If doing a change, replace lines for as long as possible.  Then,
	 * append more lines or delete remaining lines.  Changes to an empty
	 * file are appends, inserts are the same as appends to the previous
	 * line.
	 *
	 * !!!
	 * Set the address to which we'll append.  We set sp->lno to this
	 * address as well so that autoindent works correctly when get text
	 * from the user.
	 */
	lno = cmdp->addr1.lno;
	sp->lno = lno;
	if ((cmd == CHANGE || cmd == INSERT) && lno != 0)
		--lno;

	/*
	 * !!!
	 * If the file isn't empty, cut changes into the unnamed buffer.
	 */
	if (cmd == CHANGE && cmdp->addr1.lno != 0 &&
	    (cut(sp, NULL, &cmdp->addr1, &cmdp->addr2, CUT_LINEMODE) ||
	    del(sp, &cmdp->addr1, &cmdp->addr2, 1)))
		return (1);

	/*
	 * !!!
	 * Anything that was left after the command separator becomes part
	 * of the inserted text.  Apparently, it was common usage to enter:
	 *
	 *	:g/pattern/append|stuff1
	 *
	 * and append the line of text "stuff1" to the lines containing the
	 * pattern.  It was also historically legal to enter:
	 *
	 *	:append|stuff1
	 *	stuff2
	 *	.
	 *
	 * and the text on the ex command line would be appended as well as
	 * the text inserted after it.  There was an historic bug however,
	 * that the user had to enter *two* terminating lines (the '.' lines)
	 * to terminate text input mode, in this case.  This whole thing
	 * could be taken too far, however.  Entering:
	 *
	 *	:append|stuff1\
	 *	stuff2
	 *	stuff3
	 *	.
	 *
	 * i.e. mixing and matching the forms confused the historic vi, and,
	 * not only did it take two terminating lines to terminate text input
	 * mode, but the trailing backslashes were retained on the input.  We
	 * match historic practice except that we discard the backslashes.
	 *
	 * Input lines specified on the ex command line lines are separated by
	 * <newline>s.  If there is a trailing delimiter an empty line was
	 * inserted.  There may also be a leading delimiter, which is ignored
	 * unless it's also a trailing delimiter.  It is possible to encounter
	 * a termination line, i.e. a single '.', in a global command, but not
	 * necessary if the text insert command was the last of the global
	 * commands.
	 */
	if (cmdp->save_cmdlen != 0) {
		for (p = cmdp->save_cmd,
		    len = cmdp->save_cmdlen; len > 0; p = t) {
			for (t = p; len > 0 && t[0] != '\n'; ++t, --len);
			if (t != p || len == 0) {
				if (F_ISSET(sp, SC_EX_GLOBAL) &&
				    t - p == 1 && p[0] == '.') {
					++t;
					if (len > 0)
						--len;
					break;
				}
				if (db_append(sp, 1, lno++, p, t - p))
					return (1);
			}
			if (len != 0) {
				++t;
				if (--len == 0 &&
				    db_append(sp, 1, lno++, "", 0))
					return (1);
			}
		}
		/*
		 * If there's any remaining text, we're in a global, and
		 * there's more command to parse.
		 *
		 * !!!
		 * We depend on the fact that non-global commands will eat the
		 * rest of the command line as text input, and before getting
		 * any text input from the user.  Otherwise, we'd have to save
		 * off the command text before or during the call to the text
		 * input function below.
		 */
		if (len != 0)
			cmdp->save_cmd = t;
		cmdp->save_cmdlen = len;
	}

	if (F_ISSET(sp, SC_EX_GLOBAL)) {
		if ((sp->lno = lno) == 0 && db_exist(sp, 1))
			sp->lno = 1;
		return (0);
	}

	/*
	 * If not in a global command, read from the terminal.
	 *
	 * If this code is called by vi, we want to reset the terminal and use
	 * ex's line get routine.  It actually works fine if we use vi's get
	 * routine, but it doesn't look as nice.  Maybe if we had a separate
	 * window or something, but getting a line at a time looks awkward.
	 * However, depending on the screen that we're using, that may not
	 * be possible.
	 */
	if (F_ISSET(sp, SC_VI)) {
		if (gp->scr_screen(sp, SC_EX)) {
			ex_emsg(sp, cmdp->cmd->name, EXM_NOCANON);
			return (1);
		}

		/* If we're still in the vi screen, move out explicitly. */
		need_newline = !F_ISSET(sp, SC_SCR_EXWROTE);
		F_SET(sp, SC_SCR_EX | SC_SCR_EXWROTE);
		if (need_newline)
			(void)ex_puts(sp, "\n");

		/*
		 * !!!
		 * Users of historical versions of vi sometimes get confused
		 * when they enter append mode, and can't seem to get out of
		 * it.  Give them an informational message.
		 */
		(void)ex_puts(sp,
		    msg_cat(sp, "273|Entering ex input mode.", NULL));
		(void)ex_puts(sp, "\n");
		(void)ex_fflush(sp);
	}

	/*
	 * Set input flags; the ! flag turns off autoindent for append,
	 * change and insert.
	 */
	LF_INIT(TXT_DOTTERM | TXT_NUMBER);
	if (!FL_ISSET(cmdp->iflags, E_C_FORCE) && O_ISSET(sp, O_AUTOINDENT))
		LF_SET(TXT_AUTOINDENT);
	if (O_ISSET(sp, O_BEAUTIFY))
		LF_SET(TXT_BEAUTIFY);

	/*
	 * This code can't use the common screen TEXTH structure (sp->tiq),
	 * as it may already be in use, e.g. ":append|s/abc/ABC/" would fail
	 * as we are only halfway through the text when the append code fires.
	 * Use a local structure instead.  (The ex code would have to use a
	 * local structure except that we're guaranteed to finish remaining
	 * characters in the common TEXTH structure when they were inserted
	 * into the file, above.)
	 */
	memset(&tiq, 0, sizeof(TEXTH));
	CIRCLEQ_INIT(&tiq);

	if (ex_txt(sp, &tiq, 0, flags))
		return (1);

	for (cnt = 0, tp = tiq.cqh_first;
	    tp != (void *)&tiq; ++cnt, tp = tp->q.cqe_next)
		if (db_append(sp, 1, lno++, tp->lb, tp->len))
			return (1);

	/*
	 * Set sp->lno to the final line number value (correcting for a
	 * possible 0 value) as that's historically correct for the final
	 * line value, whether or not the user entered any text.
	 */
	if ((sp->lno = lno) == 0 && db_exist(sp, 1))
		sp->lno = 1;

	return (0);
}
@


1.12
log
@Initialize a local variable to appease -Wuninitialized.
Marked with XXXGCC for sun2 (found while compiling for it).

Reviewed by lukem.
@
text
@d1 1
a1 1
/*	$NetBSD: ex_append.c,v 1.11 2005/02/12 12:53:22 aymeric Exp $	*/
d19 1
a19 1
__RCSID("$NetBSD: ex_append.c,v 1.11 2005/02/12 12:53:22 aymeric Exp $");
@


1.11
log
@Fix the RCSID's to be $NetBSD$ instead of $NetBSD
@
text
@d1 1
a1 1
/*	$NetBSD: ex_append.c,v 1.10 2002/12/06 03:24:42 thorpej Exp $	*/
d19 1
a19 1
__RCSID("$NetBSD$");
d101 2
@


1.10
log
@Avoid a strict alias warning.
@
text
@d1 1
a1 1
/*	$NetBSD: ex_append.c,v 1.9 2002/04/09 01:47:32 thorpej Exp $	*/
d19 1
a19 1
__RCSID("$NetBSD");
@


1.10.4.1
log
@Pull up revision 1.11 (requested by aymeric in ticket #1195):
Fix the RCSID's to be $NetBSD$ instead of $NetBSD
@
text
@d1 1
a1 1
/*	$NetBSD: ex_append.c,v 1.10 2002/12/06 03:24:42 thorpej Exp $	*/
d19 1
a19 1
__RCSID("$NetBSD$");
@


1.10.2.1
log
@Fix the RCSID's to be $NetBSD$ instead of $NetBSD
@
text
@d1 1
a1 1
/*	$NetBSD: ex_append.c,v 1.10 2002/12/06 03:24:42 thorpej Exp $	*/
d19 1
a19 1
__RCSID("$NetBSD$");
@


1.10.2.2
log
@Backout previous. Sorry.
@
text
@d19 1
a19 1
__RCSID("$NetBSD");
@


1.9
log
@Use __RCSID() and __COPYRIGHT().
@
text
@d1 1
a1 1
/*	$NetBSD: ex_append.c,v 1.8 2001/03/31 11:37:49 aymeric Exp $	*/
d271 1
a271 1
	    tp != (TEXT *)&tiq; ++cnt, tp = tp->q.cqe_next)
@


1.8
log
@merge changes after import of nvi 1.79
@
text
@d1 1
a1 1
/*	$NetBSD: ex_append.c,v 1.7 1998/01/09 08:07:39 perry Exp $	*/
d14 1
d16 1
d18 3
@


1.7
log
@RCS Id Police.
@
text
@d1 1
a1 1
/*	$NetBSD$	*/
d15 1
a15 1
static const char sccsid[] = "@@(#)ex_append.c	10.27 (Berkeley) 4/27/96";
d88 1
d96 1
d121 1
a121 1
	    delete(sp, &cmdp->addr1, &cmdp->addr2, 1)))
d217 1
a217 1
		if (sp->gp->scr_screen(sp, SC_EX)) {
@


1.6
log
@merge in nvi 1.66
@
text
@d1 2
@


1.5
log
@clean up import.
@
text
@d4 2
d7 1
a7 27
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *	This product includes software developed by the University of
 *	California, Berkeley and its contributors.
 * 4. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
d10 2
d13 1
a13 1
static char sccsid[] = "@@(#)ex_append.c	8.24 (Berkeley) 8/17/94";
a17 1
#include <sys/time.h>
a20 1
#include <signal.h>
a22 1
#include <termios.h>
d25 1
a25 7
#include "compat.h"
#include <db.h>
#include <regex.h>

#include "vi.h"
#include "excmd.h"
#include "../sex/sex_screen.h"
d29 1
a29 1
static int aci __P((SCR *, EXF *, EXCMDARG *, enum which));
d35 2
d39 1
a39 1
ex_append(sp, ep, cmdp)
d41 1
a41 2
	EXF *ep;
	EXCMDARG *cmdp;
d43 1
a43 1
	return (aci(sp, ep, cmdp, APPEND));
d49 2
d53 1
a53 1
ex_change(sp, ep, cmdp)
d55 1
a55 2
	EXF *ep;
	EXCMDARG *cmdp;
d57 1
a57 1
	return (aci(sp, ep, cmdp, CHANGE));
d64 2
d68 1
a68 1
ex_insert(sp, ep, cmdp)
d70 1
a70 2
	EXF *ep;
	EXCMDARG *cmdp;
d72 1
a72 1
	return (aci(sp, ep, cmdp, INSERT));
d75 4
d80 1
a80 1
aci(sp, ep, cmdp, cmd)
d82 1
a82 2
	EXF *ep;
	EXCMDARG *cmdp;
d85 1
a85 2
	MARK m;
	TEXTH *sv_tiqp, tiq;
d87 5
a91 3
	struct termios t;
	u_int flags;
	int rval;
d93 1
a93 1
	rval = 0;
d96 61
a156 2
	 * Set input flags; the ! flag turns off autoindent for append,
	 * change and insert.
d158 37
a194 5
	LF_INIT(TXT_DOTTERM | TXT_NLECHO);
	if (!F_ISSET(cmdp, E_FORCE) && O_ISSET(sp, O_AUTOINDENT))
		LF_SET(TXT_AUTOINDENT);
	if (O_ISSET(sp, O_BEAUTIFY))
		LF_SET(TXT_BEAUTIFY);
d196 5
a200 2
	/* Input is interruptible. */
	F_SET(sp, S_INTERRUPTIBLE);
d203 1
a203 4
	 * If this code is called by vi, the screen TEXTH structure (sp->tiqp)
	 * may already be in use, e.g. ":append|s/abc/ABC/" would fail as we're
	 * only halfway through the line when the append code fires.  Use the
	 * local structure instead.
d206 1
a206 1
	 * ex's s_get() routine.  It actually works fine if we use vi's s_get()
d209 2
d212 5
a216 10
	if (IN_VI_MODE(sp)) {
		memset(&tiq, 0, sizeof(TEXTH));
		CIRCLEQ_INIT(&tiq);
		sv_tiqp = sp->tiqp;
		sp->tiqp = &tiq;

		if (F_ISSET(sp->gp, G_STDIN_TTY))
			SEX_RAW(t);
		(void)write(STDOUT_FILENO, "\n", 1);
		LF_SET(TXT_NLECHO);
d218 16
d236 9
a244 2
	/* Set the line number, so that autoindent works correctly. */
	sp->lno = cmdp->addr1.lno;
a245 3
	if (sex_get(sp, ep, sp->tiqp, 0, flags) != INP_OK)
		goto err;
	
d247 18
a264 26
	 * If doing a change, replace lines for as long as possible.  Then,
	 * append more lines or delete remaining lines.  Changes to an empty
	 * file are just appends, and inserts are the same as appends to the
	 * previous line.
	 *
	 * !!!
	 * Adjust the current line number for the commands to match historic
	 * practice if the user doesn't enter anything, and set the address
	 * to which we'll append.  This is safe because an address of 0 is
	 * illegal for change and insert.
	 */
	m = cmdp->addr1;
	switch (cmd) {
	case INSERT:
		--m.lno;
		/* FALLTHROUGH */
	case APPEND:
		if (sp->lno == 0)
			sp->lno = 1;
		break;
	case CHANGE:
		--m.lno;
		if (sp->lno != 1)
			--sp->lno;
		break;
	}
d267 3
a269 2
	 * !!!
	 * Cut into the unnamed buffer.
d271 2
a272 13
	if (cmd == CHANGE &&
	    (cut(sp, ep, NULL, &cmdp->addr1, &cmdp->addr2, CUT_LINEMODE) ||
	    delete(sp, ep, &cmdp->addr1, &cmdp->addr2, 1)))
		goto err;

	for (tp = sp->tiqp->cqh_first;
	    tp != (TEXT *)sp->tiqp; tp = tp->q.cqe_next) {
		if (file_aline(sp, ep, 1, m.lno, tp->lb, tp->len)) {
err:			rval = 1;
			break;
		}
		sp->lno = ++m.lno;
	}
d274 1
a274 12
	if (IN_VI_MODE(sp)) {
		sp->tiqp = sv_tiqp;
		text_lfree(&tiq);

		/* Reset the terminal state. */
		if (F_ISSET(sp->gp, G_STDIN_TTY)) {
			if (SEX_NORAW(t))
				rval = 1;
			F_SET(sp, S_REFRESH);
		}
	}
	return (rval);
@


1.5.2.1
log
@file ex_append.c was added on branch netbsd-1-0 on 1994-08-17 20:12:09 +0000
@
text
@d1 220
@


1.5.2.2
log
@clean up import.
@
text
@a0 220
/*-
 * Copyright (c) 1992, 1993, 1994
 *	The Regents of the University of California.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *	This product includes software developed by the University of
 *	California, Berkeley and its contributors.
 * 4. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#ifndef lint
static char sccsid[] = "@@(#)ex_append.c	8.24 (Berkeley) 8/17/94";
#endif /* not lint */

#include <sys/types.h>
#include <sys/queue.h>
#include <sys/time.h>

#include <bitstring.h>
#include <limits.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>

#include "compat.h"
#include <db.h>
#include <regex.h>

#include "vi.h"
#include "excmd.h"
#include "../sex/sex_screen.h"

enum which {APPEND, CHANGE, INSERT};

static int aci __P((SCR *, EXF *, EXCMDARG *, enum which));

/*
 * ex_append -- :[line] a[ppend][!]
 *	Append one or more lines of new text after the specified line,
 *	or the current line if no address is specified.
 */
int
ex_append(sp, ep, cmdp)
	SCR *sp;
	EXF *ep;
	EXCMDARG *cmdp;
{
	return (aci(sp, ep, cmdp, APPEND));
}

/*
 * ex_change -- :[line[,line]] c[hange][!] [count]
 *	Change one or more lines to the input text.
 */
int
ex_change(sp, ep, cmdp)
	SCR *sp;
	EXF *ep;
	EXCMDARG *cmdp;
{
	return (aci(sp, ep, cmdp, CHANGE));
}

/*
 * ex_insert -- :[line] i[nsert][!]
 *	Insert one or more lines of new text before the specified line,
 *	or the current line if no address is specified.
 */
int
ex_insert(sp, ep, cmdp)
	SCR *sp;
	EXF *ep;
	EXCMDARG *cmdp;
{
	return (aci(sp, ep, cmdp, INSERT));
}

static int
aci(sp, ep, cmdp, cmd)
	SCR *sp;
	EXF *ep;
	EXCMDARG *cmdp;
	enum which cmd;
{
	MARK m;
	TEXTH *sv_tiqp, tiq;
	TEXT *tp;
	struct termios t;
	u_int flags;
	int rval;

	rval = 0;

	/*
	 * Set input flags; the ! flag turns off autoindent for append,
	 * change and insert.
	 */
	LF_INIT(TXT_DOTTERM | TXT_NLECHO);
	if (!F_ISSET(cmdp, E_FORCE) && O_ISSET(sp, O_AUTOINDENT))
		LF_SET(TXT_AUTOINDENT);
	if (O_ISSET(sp, O_BEAUTIFY))
		LF_SET(TXT_BEAUTIFY);

	/* Input is interruptible. */
	F_SET(sp, S_INTERRUPTIBLE);

	/*
	 * If this code is called by vi, the screen TEXTH structure (sp->tiqp)
	 * may already be in use, e.g. ":append|s/abc/ABC/" would fail as we're
	 * only halfway through the line when the append code fires.  Use the
	 * local structure instead.
	 *
	 * If this code is called by vi, we want to reset the terminal and use
	 * ex's s_get() routine.  It actually works fine if we use vi's s_get()
	 * routine, but it doesn't look as nice.  Maybe if we had a separate
	 * window or something, but getting a line at a time looks awkward.
	 */
	if (IN_VI_MODE(sp)) {
		memset(&tiq, 0, sizeof(TEXTH));
		CIRCLEQ_INIT(&tiq);
		sv_tiqp = sp->tiqp;
		sp->tiqp = &tiq;

		if (F_ISSET(sp->gp, G_STDIN_TTY))
			SEX_RAW(t);
		(void)write(STDOUT_FILENO, "\n", 1);
		LF_SET(TXT_NLECHO);

	}

	/* Set the line number, so that autoindent works correctly. */
	sp->lno = cmdp->addr1.lno;

	if (sex_get(sp, ep, sp->tiqp, 0, flags) != INP_OK)
		goto err;
	
	/*
	 * If doing a change, replace lines for as long as possible.  Then,
	 * append more lines or delete remaining lines.  Changes to an empty
	 * file are just appends, and inserts are the same as appends to the
	 * previous line.
	 *
	 * !!!
	 * Adjust the current line number for the commands to match historic
	 * practice if the user doesn't enter anything, and set the address
	 * to which we'll append.  This is safe because an address of 0 is
	 * illegal for change and insert.
	 */
	m = cmdp->addr1;
	switch (cmd) {
	case INSERT:
		--m.lno;
		/* FALLTHROUGH */
	case APPEND:
		if (sp->lno == 0)
			sp->lno = 1;
		break;
	case CHANGE:
		--m.lno;
		if (sp->lno != 1)
			--sp->lno;
		break;
	}

	/*
	 * !!!
	 * Cut into the unnamed buffer.
	 */
	if (cmd == CHANGE &&
	    (cut(sp, ep, NULL, &cmdp->addr1, &cmdp->addr2, CUT_LINEMODE) ||
	    delete(sp, ep, &cmdp->addr1, &cmdp->addr2, 1)))
		goto err;

	for (tp = sp->tiqp->cqh_first;
	    tp != (TEXT *)sp->tiqp; tp = tp->q.cqe_next) {
		if (file_aline(sp, ep, 1, m.lno, tp->lb, tp->len)) {
err:			rval = 1;
			break;
		}
		sp->lno = ++m.lno;
	}

	if (IN_VI_MODE(sp)) {
		sp->tiqp = sv_tiqp;
		text_lfree(&tiq);

		/* Reset the terminal state. */
		if (F_ISSET(sp->gp, G_STDIN_TTY)) {
			if (SEX_NORAW(t))
				rval = 1;
			F_SET(sp, S_REFRESH);
		}
	}
	return (rval);
}
@


1.4
log
@clean up import.  still have to hack some things.
@
text
@d35 1
a35 1
static const char sccsid[] = "@@(#)ex_append.c	8.23 (Berkeley) 8/17/94";
@


1.3
log
@nvi 1.11(beta) from bostic.  reconcile conflicts/kill rcsids.
@
text
@d35 1
a35 1
static char sccsid[] = "@@(#)ex_append.c	8.9 (Berkeley) 3/14/94";
d46 1
d48 1
d56 1
d111 1
d113 1
a113 1
	recno_t cnt;
d115 3
a117 1
	int rval, aiset;
d120 2
a121 2
	 * The ! flag turns off autoindent for append, change and
	 * insert.
d123 8
a130 5
	if (F_ISSET(cmdp, E_FORCE)) {
		aiset = O_ISSET(sp, O_AUTOINDENT);
		O_CLR(sp, O_AUTOINDENT);
	} else
		aiset = 0;
d133 40
a172 3
	 * If doing a change, replace lines as long as possible.
	 * Then, append more lines or delete remaining lines.
	 * Inserts are the same as appends to the previous line.
a173 1
	rval = 0;
d175 9
a183 1
	if (cmd == INSERT) {
d185 3
a187 1
		cmd = APPEND;
d190 14
a203 33
	LF_INIT(TXT_CR | TXT_NLECHO);
	if (O_ISSET(sp, O_BEAUTIFY))
		LF_SET(TXT_BEAUTIFY);

	if (cmd == CHANGE)
		for (;; ++m.lno) {
			if (m.lno > cmdp->addr2.lno) {
				cmd = APPEND;
				--m.lno;
				break;
			}
			switch (sp->s_get(sp, ep, &sp->tiq, 0, flags)) {
			case INP_OK:
				break;
			case INP_EOF:
			case INP_ERR:
				rval = 1;
				goto done;
			}
			tp = sp->tiq.cqh_first;
			if (tp->len == 1 && tp->lb[0] == '.') {
				for (cnt =
				    (cmdp->addr2.lno - m.lno) + 1; cnt--;)
					if (file_dline(sp, ep, m.lno)) {
						rval = 1;
						goto done;
					}
				goto done;
			}
			if (file_sline(sp, ep, m.lno, tp->lb, tp->len)) {
				rval = 1;
				goto done;
			}
d205 2
d208 7
a214 14
	if (cmd == APPEND)
		for (;; ++m.lno) {
			switch (sp->s_get(sp, ep, &sp->tiq, 0, flags)) {
			case INP_OK:
				break;
			case INP_EOF:
			case INP_ERR:
				rval = 1;
				goto done;
			}
			tp = sp->tiq.cqh_first;
			if (tp->len == 1 && tp->lb[0] == '.')
				break;
			if (file_aline(sp, ep, 1, m.lno, tp->lb, tp->len)) {
d216 1
a216 2
				goto done;
			}
d218 1
a218 7

done:	if (rval == 0)
		sp->lno = m.lno;

	if (aiset)
		O_SET(sp, O_AUTOINDENT);

@


1.2
log
@more Ids than you'll ever want.
@
text
@d2 1
a2 1
 * Copyright (c) 1992, 1993
d35 1
a35 2
/* from: static char sccsid[] = "@@(#)ex_append.c	8.6 (Berkeley) 11/23/93"; */
static char *rcsid = "$Id$";
d39 12
d110 1
d134 5
d146 1
a146 2
			switch (sp->s_get(sp, ep, &sp->tiq, 0,
			    TXT_BEAUTIFY | TXT_CR | TXT_NLECHO)) {
d172 1
a172 2
			switch (sp->s_get(sp, ep, &sp->tiq, 0,
			    TXT_BEAUTIFY | TXT_CR | TXT_NLECHO)) {
@


1.1
log
@Initial revision
@
text
@d35 2
a36 1
static char sccsid[] = "@@(#)ex_append.c	8.6 (Berkeley) 11/23/93";
@


1.1.1.1
log
@nvi 1.03, from ftp.cs.berkeley.edu, per keith bostic's permission.
@
text
@@


1.1.1.2
log
@nvi/nex 1.11beta from bostic.
@
text
@d2 1
a2 1
 * Copyright (c) 1992, 1993, 1994
d35 1
a35 1
static char sccsid[] = "@@(#)ex_append.c	8.9 (Berkeley) 3/14/94";
a38 12
#include <sys/queue.h>
#include <sys/time.h>

#include <bitstring.h>
#include <limits.h>
#include <signal.h>
#include <stdio.h>
#include <termios.h>

#include "compat.h"
#include <db.h>
#include <regex.h>
a97 1
	u_int flags;
a120 5

	LF_INIT(TXT_CR | TXT_NLECHO);
	if (O_ISSET(sp, O_BEAUTIFY))
		LF_SET(TXT_BEAUTIFY);

d128 2
a129 1
			switch (sp->s_get(sp, ep, &sp->tiq, 0, flags)) {
d155 2
a156 1
			switch (sp->s_get(sp, ep, &sp->tiq, 0, flags)) {
@


1.1.1.3
log
@new public version of nvi
@
text
@d35 1
a35 1
static const char sccsid[] = "@@(#)ex_append.c	8.23 (Berkeley) 8/17/94";
a45 1
#include <string.h>
a46 1
#include <unistd.h>
a53 1
#include "../sex/sex_screen.h"
a107 1
	TEXTH *sv_tiqp, tiq;
d109 1
a109 1
	struct termios t;
d111 1
a111 3
	int rval;

	rval = 0;
d114 2
a115 2
	 * Set input flags; the ! flag turns off autoindent for append,
	 * change and insert.
d117 5
a121 8
	LF_INIT(TXT_DOTTERM | TXT_NLECHO);
	if (!F_ISSET(cmdp, E_FORCE) && O_ISSET(sp, O_AUTOINDENT))
		LF_SET(TXT_AUTOINDENT);
	if (O_ISSET(sp, O_BEAUTIFY))
		LF_SET(TXT_BEAUTIFY);

	/* Input is interruptible. */
	F_SET(sp, S_INTERRUPTIBLE);
d124 3
a126 40
	 * If this code is called by vi, the screen TEXTH structure (sp->tiqp)
	 * may already be in use, e.g. ":append|s/abc/ABC/" would fail as we're
	 * only halfway through the line when the append code fires.  Use the
	 * local structure instead.
	 *
	 * If this code is called by vi, we want to reset the terminal and use
	 * ex's s_get() routine.  It actually works fine if we use vi's s_get()
	 * routine, but it doesn't look as nice.  Maybe if we had a separate
	 * window or something, but getting a line at a time looks awkward.
	 */
	if (IN_VI_MODE(sp)) {
		memset(&tiq, 0, sizeof(TEXTH));
		CIRCLEQ_INIT(&tiq);
		sv_tiqp = sp->tiqp;
		sp->tiqp = &tiq;

		if (F_ISSET(sp->gp, G_STDIN_TTY))
			SEX_RAW(t);
		(void)write(STDOUT_FILENO, "\n", 1);
		LF_SET(TXT_NLECHO);

	}

	/* Set the line number, so that autoindent works correctly. */
	sp->lno = cmdp->addr1.lno;

	if (sex_get(sp, ep, sp->tiqp, 0, flags) != INP_OK)
		goto err;
	
	/*
	 * If doing a change, replace lines for as long as possible.  Then,
	 * append more lines or delete remaining lines.  Changes to an empty
	 * file are just appends, and inserts are the same as appends to the
	 * previous line.
	 *
	 * !!!
	 * Adjust the current line number for the commands to match historic
	 * practice if the user doesn't enter anything, and set the address
	 * to which we'll append.  This is safe because an address of 0 is
	 * illegal for change and insert.
d128 1
d130 1
a130 9
	switch (cmd) {
	case INSERT:
		--m.lno;
		/* FALLTHROUGH */
	case APPEND:
		if (sp->lno == 0)
			sp->lno = 1;
		break;
	case CHANGE:
d132 1
a132 3
		if (sp->lno != 1)
			--sp->lno;
		break;
d135 33
a167 14
	/*
	 * !!!
	 * Cut into the unnamed buffer.
	 */
	if (cmd == CHANGE &&
	    (cut(sp, ep, NULL, &cmdp->addr1, &cmdp->addr2, CUT_LINEMODE) ||
	    delete(sp, ep, &cmdp->addr1, &cmdp->addr2, 1)))
		goto err;

	for (tp = sp->tiqp->cqh_first;
	    tp != (TEXT *)sp->tiqp; tp = tp->q.cqe_next) {
		if (file_aline(sp, ep, 1, m.lno, tp->lb, tp->len)) {
err:			rval = 1;
			break;
a168 2
		sp->lno = ++m.lno;
	}
d170 14
a183 7
	if (IN_VI_MODE(sp)) {
		sp->tiqp = sv_tiqp;
		text_lfree(&tiq);

		/* Reset the terminal state. */
		if (F_ISSET(sp->gp, G_STDIN_TTY)) {
			if (SEX_NORAW(t))
d185 2
a186 1
			F_SET(sp, S_REFRESH);
d188 7
a194 1
	}
@


1.1.1.4
log
@new public version of nvi
@
text
@d35 1
a35 1
static char sccsid[] = "@@(#)ex_append.c	8.24 (Berkeley) 8/17/94";
@


1.1.1.5
log
@import of nvi 1.66
@
text
@a3 2
 * Copyright (c) 1992, 1993, 1994, 1995, 1996
 *	Keith Bostic.  All rights reserved.
d5 27
a31 1
 * See the LICENSE file for redistribution information.
a33 2
#include "config.h"

d35 1
a35 1
static const char sccsid[] = "@@(#)ex_append.c	10.27 (Berkeley) 4/27/96";
d40 1
d44 1
d47 1
d50 7
a56 1
#include "../common/common.h"
d60 1
a60 1
static int ex_aci __P((SCR *, EXCMD *, enum which));
a65 2
 *
 * PUBLIC: int ex_append __P((SCR *, EXCMD *));
d68 1
a68 1
ex_append(sp, cmdp)
d70 2
a71 1
	EXCMD *cmdp;
d73 1
a73 1
	return (ex_aci(sp, cmdp, APPEND));
a78 2
 *
 * PUBLIC: int ex_change __P((SCR *, EXCMD *));
d81 1
a81 1
ex_change(sp, cmdp)
d83 2
a84 1
	EXCMD *cmdp;
d86 1
a86 1
	return (ex_aci(sp, cmdp, CHANGE));
a92 2
 *
 * PUBLIC: int ex_insert __P((SCR *, EXCMD *));
d95 1
a95 1
ex_insert(sp, cmdp)
d97 2
a98 1
	EXCMD *cmdp;
d100 1
a100 1
	return (ex_aci(sp, cmdp, INSERT));
a102 4
/*
 * ex_aci --
 *	Append, change, insert in ex.
 */
d104 1
a104 1
ex_aci(sp, cmdp, cmd)
d106 2
a107 1
	EXCMD *cmdp;
d110 2
a111 1
	CHAR_T *p, *t;
d113 3
a115 5
	TEXTH tiq;
	recno_t cnt, lno;
	size_t len;
	u_int32_t flags;
	int need_newline;
d117 1
a117 1
	NEEDFILE(sp, cmdp);
d120 2
a121 9
	 * If doing a change, replace lines for as long as possible.  Then,
	 * append more lines or delete remaining lines.  Changes to an empty
	 * file are appends, inserts are the same as appends to the previous
	 * line.
	 *
	 * !!!
	 * Set the address to which we'll append.  We set sp->lno to this
	 * address as well so that autoindent works correctly when get text
	 * from the user.
d123 5
a127 4
	lno = cmdp->addr1.lno;
	sp->lno = lno;
	if ((cmd == CHANGE || cmd == INSERT) && lno != 0)
		--lno;
d129 2
a130 8
	/*
	 * !!!
	 * If the file isn't empty, cut changes into the unnamed buffer.
	 */
	if (cmd == CHANGE && cmdp->addr1.lno != 0 &&
	    (cut(sp, NULL, &cmdp->addr1, &cmdp->addr2, CUT_LINEMODE) ||
	    delete(sp, &cmdp->addr1, &cmdp->addr2, 1)))
		return (1);
d133 4
a136 83
	 * !!!
	 * Anything that was left after the command separator becomes part
	 * of the inserted text.  Apparently, it was common usage to enter:
	 *
	 *	:g/pattern/append|stuff1
	 *
	 * and append the line of text "stuff1" to the lines containing the
	 * pattern.  It was also historically legal to enter:
	 *
	 *	:append|stuff1
	 *	stuff2
	 *	.
	 *
	 * and the text on the ex command line would be appended as well as
	 * the text inserted after it.  There was an historic bug however,
	 * that the user had to enter *two* terminating lines (the '.' lines)
	 * to terminate text input mode, in this case.  This whole thing
	 * could be taken too far, however.  Entering:
	 *
	 *	:append|stuff1\
	 *	stuff2
	 *	stuff3
	 *	.
	 *
	 * i.e. mixing and matching the forms confused the historic vi, and,
	 * not only did it take two terminating lines to terminate text input
	 * mode, but the trailing backslashes were retained on the input.  We
	 * match historic practice except that we discard the backslashes.
	 *
	 * Input lines specified on the ex command line lines are separated by
	 * <newline>s.  If there is a trailing delimiter an empty line was
	 * inserted.  There may also be a leading delimiter, which is ignored
	 * unless it's also a trailing delimiter.  It is possible to encounter
	 * a termination line, i.e. a single '.', in a global command, but not
	 * necessary if the text insert command was the last of the global
	 * commands.
	 */
	if (cmdp->save_cmdlen != 0) {
		for (p = cmdp->save_cmd,
		    len = cmdp->save_cmdlen; len > 0; p = t) {
			for (t = p; len > 0 && t[0] != '\n'; ++t, --len);
			if (t != p || len == 0) {
				if (F_ISSET(sp, SC_EX_GLOBAL) &&
				    t - p == 1 && p[0] == '.') {
					++t;
					if (len > 0)
						--len;
					break;
				}
				if (db_append(sp, 1, lno++, p, t - p))
					return (1);
			}
			if (len != 0) {
				++t;
				if (--len == 0 &&
				    db_append(sp, 1, lno++, "", 0))
					return (1);
			}
		}
		/*
		 * If there's any remaining text, we're in a global, and
		 * there's more command to parse.
		 *
		 * !!!
		 * We depend on the fact that non-global commands will eat the
		 * rest of the command line as text input, and before getting
		 * any text input from the user.  Otherwise, we'd have to save
		 * off the command text before or during the call to the text
		 * input function below.
		 */
		if (len != 0)
			cmdp->save_cmd = t;
		cmdp->save_cmdlen = len;
	}

	if (F_ISSET(sp, SC_EX_GLOBAL)) {
		if ((sp->lno = lno) == 0 && db_exist(sp, 1))
			sp->lno = 1;
		return (0);
	}

	/*
	 * If not in a global command, read from the terminal.
d139 1
a139 1
	 * ex's line get routine.  It actually works fine if we use vi's get
a141 2
	 * However, depending on the screen that we're using, that may not
	 * be possible.
d143 10
a152 5
	if (F_ISSET(sp, SC_VI)) {
		if (sp->gp->scr_screen(sp, SC_EX)) {
			ex_emsg(sp, cmdp->cmd->name, EXM_NOCANON);
			return (1);
		}
a153 16
		/* If we're still in the vi screen, move out explicitly. */
		need_newline = !F_ISSET(sp, SC_SCR_EXWROTE);
		F_SET(sp, SC_SCR_EX | SC_SCR_EXWROTE);
		if (need_newline)
			(void)ex_puts(sp, "\n");

		/*
		 * !!!
		 * Users of historical versions of vi sometimes get confused
		 * when they enter append mode, and can't seem to get out of
		 * it.  Give them an informational message.
		 */
		(void)ex_puts(sp,
		    msg_cat(sp, "273|Entering ex input mode.", NULL));
		(void)ex_puts(sp, "\n");
		(void)ex_fflush(sp);
d156 2
a157 9
	/*
	 * Set input flags; the ! flag turns off autoindent for append,
	 * change and insert.
	 */
	LF_INIT(TXT_DOTTERM | TXT_NUMBER);
	if (!FL_ISSET(cmdp->iflags, E_C_FORCE) && O_ISSET(sp, O_AUTOINDENT))
		LF_SET(TXT_AUTOINDENT);
	if (O_ISSET(sp, O_BEAUTIFY))
		LF_SET(TXT_BEAUTIFY);
d159 3
d163 26
a188 18
	 * This code can't use the common screen TEXTH structure (sp->tiq),
	 * as it may already be in use, e.g. ":append|s/abc/ABC/" would fail
	 * as we are only halfway through the text when the append code fires.
	 * Use a local structure instead.  (The ex code would have to use a
	 * local structure except that we're guaranteed to finish remaining
	 * characters in the common TEXTH structure when they were inserted
	 * into the file, above.)
	 */
	memset(&tiq, 0, sizeof(TEXTH));
	CIRCLEQ_INIT(&tiq);

	if (ex_txt(sp, &tiq, 0, flags))
		return (1);

	for (cnt = 0, tp = tiq.cqh_first;
	    tp != (TEXT *)&tiq; ++cnt, tp = tp->q.cqe_next)
		if (db_append(sp, 1, lno++, tp->lb, tp->len))
			return (1);
d191 2
a192 3
	 * Set sp->lno to the final line number value (correcting for a
	 * possible 0 value) as that's historically correct for the final
	 * line value, whether or not the user entered any text.
d194 13
a206 2
	if ((sp->lno = lno) == 0 && db_exist(sp, 1))
		sp->lno = 1;
d208 12
a219 1
	return (0);
@


1.1.1.6
log
@import of nvi 1.79
@
text
@d13 1
a13 1
static const char sccsid[] = "@@(#)ex_append.c	10.30 (Berkeley) 10/23/96";
a85 1
	GS *gp;
a92 1
	gp = sp->gp;
d117 1
a117 1
	    del(sp, &cmdp->addr1, &cmdp->addr2, 1)))
d213 1
a213 1
		if (gp->scr_screen(sp, SC_EX)) {
@

