Home | History | Annotate | Line # | Download | only in ex
      1 /*	$NetBSD: ex_edit.c,v 1.7 2014/01/26 21:43:45 christos Exp $ */
      2 /*-
      3  * Copyright (c) 1992, 1993, 1994
      4  *	The Regents of the University of California.  All rights reserved.
      5  * Copyright (c) 1992, 1993, 1994, 1995, 1996
      6  *	Keith Bostic.  All rights reserved.
      7  *
      8  * See the LICENSE file for redistribution information.
      9  */
     10 
     11 #include "config.h"
     12 
     13 #include <sys/cdefs.h>
     14 #if 0
     15 #ifndef lint
     16 static const char sccsid[] = "Id: ex_edit.c,v 10.14 2001/08/28 13:29:15 skimo Exp  (Berkeley) Date: 2001/08/28 13:29:15 ";
     17 #endif /* not lint */
     18 #else
     19 __RCSID("$NetBSD: ex_edit.c,v 1.7 2014/01/26 21:43:45 christos Exp $");
     20 #endif
     21 
     22 #include <sys/types.h>
     23 #include <sys/queue.h>
     24 #include <sys/time.h>
     25 
     26 #include <bitstring.h>
     27 #include <errno.h>
     28 #include <limits.h>
     29 #include <stdio.h>
     30 #include <stdlib.h>
     31 #include <string.h>
     32 
     33 #include "../common/common.h"
     34 #include "../vi/vi.h"
     35 
     36 static int ex_N_edit __P((SCR *, EXCMD *, FREF *, int));
     37 
     38 /*
     39  * ex_edit --	:e[dit][!] [+cmd] [file]
     40  *		:ex[!] [+cmd] [file]
     41  *		:vi[sual][!] [+cmd] [file]
     42  *
     43  * Edit a file; if none specified, re-edit the current file.  The third
     44  * form of the command can only be executed while in vi mode.  See the
     45  * hack in ex.c:ex_cmd().
     46  *
     47  * !!!
     48  * Historic vi didn't permit the '+' command form without specifying
     49  * a file name as well.  This seems unreasonable, so we support it
     50  * regardless.
     51  *
     52  * PUBLIC: int ex_edit __P((SCR *, EXCMD *));
     53  */
     54 int
     55 ex_edit(SCR *sp, EXCMD *cmdp)
     56 {
     57 	FREF *frp;
     58 	int attach, setalt;
     59 	const char *np;
     60 	size_t nlen;
     61 
     62 	switch (cmdp->argc) {
     63 	case 0:
     64 		/*
     65 		 * If the name has been changed, we edit that file, not the
     66 		 * original name.  If the user was editing a temporary file
     67 		 * (or wasn't editing any file), create another one.  The
     68 		 * reason for not reusing temporary files is that there is
     69 		 * special exit processing of them, and reuse is tricky.
     70 		 */
     71 		frp = sp->frp;
     72 		if (sp->ep == NULL || F_ISSET(frp, FR_TMPFILE)) {
     73 			if ((frp = file_add(sp, NULL)) == NULL)
     74 				return (1);
     75 			attach = 0;
     76 		} else
     77 			attach = 1;
     78 		setalt = 0;
     79 		break;
     80 	case 1:
     81 		INT2CHAR(sp, cmdp->argv[0]->bp, cmdp->argv[0]->len + 1,
     82 			 np, nlen);
     83 		if ((frp = file_add(sp, np)) == NULL)
     84 			return (1);
     85 		attach = 0;
     86 		setalt = 1;
     87 		set_alt_name(sp, np);
     88 		break;
     89 	default:
     90 		abort();
     91 	}
     92 
     93 	if (F_ISSET(cmdp, E_NEWSCREEN) || cmdp->cmd == &cmds[C_VSPLIT])
     94 		return (ex_N_edit(sp, cmdp, frp, attach));
     95 
     96 	/*
     97 	 * Check for modifications.
     98 	 *
     99 	 * !!!
    100 	 * Contrary to POSIX 1003.2-1992, autowrite did not affect :edit.
    101 	 */
    102 	if (file_m2(sp, FL_ISSET(cmdp->iflags, E_C_FORCE)))
    103 		return (1);
    104 
    105 	/* Switch files. */
    106 	if (file_init(sp, frp, NULL, (setalt ? FS_SETALT : 0) |
    107 	    (FL_ISSET(cmdp->iflags, E_C_FORCE) ? FS_FORCE : 0)))
    108 		return (1);
    109 
    110 	F_SET(sp, SC_FSWITCH);
    111 	return (0);
    112 }
    113 
    114 /*
    115  * ex_N_edit --
    116  *	New screen version of ex_edit.
    117  */
    118 static int
    119 ex_N_edit(SCR *sp, EXCMD *cmdp, FREF *frp, int attach)
    120 {
    121 	SCR *new;
    122 
    123 	/* Get a new screen. */
    124 	if (screen_init(sp->gp, sp, &new))
    125 		return (1);
    126 	if ((cmdp->cmd == &cmds[C_VSPLIT] && vs_vsplit(sp, new)) ||
    127 	    (cmdp->cmd != &cmds[C_VSPLIT] && vs_split(sp, new, 0))) {
    128 		(void)screen_fini(new);
    129 		return (1);
    130 	}
    131 
    132 	/* Get a backing file. */
    133 	if (attach) {
    134 		/* Copy file state, keep the screen and cursor the same. */
    135 		new->ep = sp->ep;
    136 		++new->ep->refcnt;
    137 		TAILQ_INSERT_HEAD(&new->ep->scrq, new, eq);
    138 
    139 		new->frp = frp;
    140 		new->frp->flags = sp->frp->flags;
    141 
    142 		new->lno = sp->lno;
    143 		new->cno = sp->cno;
    144 	} else if (file_init(new, frp, NULL,
    145 	    (FL_ISSET(cmdp->iflags, E_C_FORCE) ? FS_FORCE : 0))) {
    146 		(void)vs_discard(new, NULL);
    147 		(void)screen_end(new);
    148 		return (1);
    149 	}
    150 
    151 	/* Create the argument list. */
    152 	new->cargv = new->argv = ex_buildargv(sp, NULL, frp->name);
    153 
    154 	/* Set up the switch. */
    155 	sp->nextdisp = new;
    156 	F_SET(sp, SC_SSWITCH);
    157 
    158 	return (0);
    159 }
    160