about summary refs log tree commit diff
path: root/pkgs/applications/editors
diff options
context:
space:
mode:
authorD. Guthrie <dguthrie@posteo.net>2020-04-21 19:04:51 +0100
committerD. Guthrie <dguthrie@posteo.net>2020-04-21 19:04:51 +0100
commitfcedd9f78e8072b629a5ff1da4f538f7e655f091 (patch)
treef9bfb35db6dd7fd2528d4746b3730f406ab36931 /pkgs/applications/editors
parentcdc8f3f3575f39849b09c741f0f269f33c0e7088 (diff)
downloadnixlib-fcedd9f78e8072b629a5ff1da4f538f7e655f091.tar
nixlib-fcedd9f78e8072b629a5ff1da4f538f7e655f091.tar.gz
nixlib-fcedd9f78e8072b629a5ff1da4f538f7e655f091.tar.bz2
nixlib-fcedd9f78e8072b629a5ff1da4f538f7e655f091.tar.lz
nixlib-fcedd9f78e8072b629a5ff1da4f538f7e655f091.tar.xz
nixlib-fcedd9f78e8072b629a5ff1da4f538f7e655f091.tar.zst
nixlib-fcedd9f78e8072b629a5ff1da4f538f7e655f091.zip
Fix the patch: when converting it to the new version (20200215), forgot to remove temporary files
Diffstat (limited to 'pkgs/applications/editors')
-rw-r--r--pkgs/applications/editors/mg/darwin_no_libbsd.patch2379
1 files changed, 18 insertions, 2361 deletions
diff --git a/pkgs/applications/editors/mg/darwin_no_libbsd.patch b/pkgs/applications/editors/mg/darwin_no_libbsd.patch
index 2484c03255b1..1863f2952b2b 100644
--- a/pkgs/applications/editors/mg/darwin_no_libbsd.patch
+++ b/pkgs/applications/editors/mg/darwin_no_libbsd.patch
@@ -1,6 +1,6 @@
 diff -Naur a/GNUmakefile b/GNUmakefile
 --- a/GNUmakefile	2020-04-20 21:09:41.000000000 +0100
-+++ b/GNUmakefile	2020-04-20 21:31:19.000000000 +0100
++++ b/GNUmakefile	2020-04-21 19:01:59.000000000 +0100
 @@ -18,7 +18,7 @@
  STRIP=		/usr/bin/strip
  
@@ -10,7 +10,7 @@ diff -Naur a/GNUmakefile b/GNUmakefile
    BSD_CPPFLAGS:=
    BSD_LIBS:=	-lutil
  else
-@@ -38,24 +38,21 @@
+@@ -38,10 +38,6 @@
    $(error You probably need to install "libncurses5-dev" or "libncurses6-devel" or something like that.)
  endif
  
@@ -21,11 +21,7 @@ diff -Naur a/GNUmakefile b/GNUmakefile
  CC?=		gcc
  CFLAGS?=	-O2 -pipe
  CFLAGS+=	-g -Wall
- CPPFLAGS=	-DREGEX
- CPPFLAGS+=	-D_GNU_SOURCE
--CPPFLAGS+=	$(BSD_CPPFLAGS)
-+CPPFLAGS+=	$(BSD_CPPFLAGS) -D__dead=__dead2
- LIBS=		$(CURSES_LIBS) $(BSD_LIBS)
+@@ -52,10 +48,11 @@
  
  
  OBJS=	autoexec.o basic.o bell.o buffer.o cinfo.o dir.o display.o \
@@ -41,109 +37,9 @@ diff -Naur a/GNUmakefile b/GNUmakefile
  OBJS+=	cmode.o cscope.o dired.o grep.o tags.o
  
  
-diff -Naur a/GNUmakefile~ b/GNUmakefile~
---- a/GNUmakefile~	1970-01-01 01:00:00.000000000 +0100
-+++ b/GNUmakefile~	2020-04-20 21:27:39.000000000 +0100
-@@ -0,0 +1,96 @@
-+# Makefile for mg
-+
-+# This Makefile has been written by Han Boetes
-+# <hboetes@gmail.com> and is released in Public Domain.
-+
-+# *sigh* Those debian folks are really tidy on their licenses.
-+
-+name=		mg
-+
-+prefix=		/usr/local
-+bindir=		$(prefix)/bin
-+libdir=		$(prefix)/lib
-+includedir=	$(prefix)/include
-+mandir=		$(prefix)/man
-+
-+PKG_CONFIG=	/usr/bin/pkg-config --silence-errors
-+INSTALL=	/usr/bin/install
-+STRIP=		/usr/bin/strip
-+
-+UNAME:=		$(shell uname)
-+ifeq ($(UNAME),FreeBSD)
-+  BSD_CPPFLAGS:=
-+  BSD_LIBS:=	-lutil
-+else
-+  BSD_CPPFLAGS:= $(shell $(PKG_CONFIG) --cflags libbsd-overlay)
-+  BSD_LIBS:=	 $(shell $(PKG_CONFIG) --libs libbsd-overlay)
-+endif
-+
-+# Test is some required libraries are installed. Rather bummer that
-+# they are also required to run make clean or uninstall. Oh well... Who
-+# does that?
-+ifeq ($(BSD_LIBS),)
-+  $(error You probably need to install "libbsd-dev" or "libbsd-devel" or something like that.)
-+endif
-+
-+CURSES_LIBS:= $(shell $(PKG_CONFIG) --libs ncurses)
-+ifeq ($(CURSES_LIBS),)
-+  $(error You probably need to install "libncurses5-dev" or "libncurses6-devel" or something like that.)
-+endif
-+
-+ifdef STATIC
-+  LDFLAGS=-static -static-libgcc
-+endif
-+
-+CC?=		gcc
-+CFLAGS?=	-O2 -pipe
-+CFLAGS+=	-g -Wall
-+CPPFLAGS=	-DREGEX
-+CPPFLAGS+=	-D_GNU_SOURCE
-+CPPFLAGS+=	$(BSD_CPPFLAGS)
-+LIBS=		$(CURSES_LIBS) $(BSD_LIBS)
-+
-+
-+OBJS=	autoexec.o basic.o bell.o buffer.o cinfo.o dir.o display.o \
-+	echo.o extend.o file.o fileio.o funmap.o interpreter.o help.o \
-+	kbd.o keymap.o line.o macro.o main.o match.o modes.o paragraph.o \
-+	re_search.o region.o search.o spawn.o tty.o ttyio.o ttykbd.o \
-+	undo.o util.o version.o window.o word.o yank.o
-+OBJS+=	cmode.o cscope.o dired.o grep.o tags.o
-+
-+
-+# Portability stuff.
-+CFLAGS+= 	 -Wno-strict-aliasing -Wno-deprecated-declarations
-+EXE_EXT=
-+
-+.c.o:
-+	$(CC) $(CFLAGS) $(CPPFLAGS) -c $<
-+
-+all: $(name)
-+
-+$(name): $(OBJS)
-+	$(CC) $(LDFLAGS) $(OBJS) -o $(name) $(LIBS)
-+
-+distclean: clean
-+	-rm -f *.core core.*
-+
-+clean:
-+	-rm -f *.o $(name)$(EXE_EXT)
-+
-+
-+install: $(name) $(name).1
-+	$(INSTALL) -d $(DESTDIR)$(bindir)
-+	$(INSTALL) -d $(DESTDIR)$(mandir)/man1
-+	$(INSTALL) -m 755 $(name)		$(DESTDIR)$(bindir)/$(name)
-+	$(INSTALL) -m 444 $(name).1		$(DESTDIR)$(mandir)/man1/$(name).1
-+
-+install-strip: install
-+	$(STRIP) $(DESTDIR)$(bindir)/$(name)
-+
-+uninstall:
-+	rm -f \
-+	$(DESTDIR)$(bindir)/$(name)$(EXE_EXT) \
-+	$(DESTDIR)$(mandir)/man1/$(name).1
-+
-+rebuild:
-+	make clean all
 diff -Naur a/_null.h b/_null.h
 --- a/_null.h	1970-01-01 01:00:00.000000000 +0100
-+++ b/_null.h	2020-04-20 21:26:10.000000000 +0100
++++ b/_null.h	2020-04-21 19:01:59.000000000 +0100
 @@ -0,0 +1,18 @@
 +/*	$OpenBSD: _null.h,v 1.2 2016/09/09 22:07:58 millert Exp $	*/
 +
@@ -165,7 +61,7 @@ diff -Naur a/_null.h b/_null.h
 +#endif
 diff -Naur a/apple.h b/apple.h
 --- a/apple.h	1970-01-01 01:00:00.000000000 +0100
-+++ b/apple.h	2020-04-20 21:26:10.000000000 +0100
++++ b/apple.h	2020-04-21 19:01:59.000000000 +0100
 @@ -0,0 +1,27 @@
 +/*
 + * Mac OS X-specific support.
@@ -196,7 +92,7 @@ diff -Naur a/apple.h b/apple.h
 +extern int futimens(int, const struct timespec[2]);
 diff -Naur a/autoexec.c b/autoexec.c
 --- a/autoexec.c	2020-04-20 21:09:41.000000000 +0100
-+++ b/autoexec.c	2020-04-20 21:26:10.000000000 +0100
++++ b/autoexec.c	2020-04-21 19:01:59.000000000 +0100
 @@ -9,6 +9,9 @@
  #include <stdlib.h>
  #include <string.h>
@@ -209,7 +105,7 @@ diff -Naur a/autoexec.c b/autoexec.c
  
 diff -Naur a/basic.c b/basic.c
 --- a/basic.c	2020-04-20 21:09:41.000000000 +0100
-+++ b/basic.c	2020-04-20 21:26:10.000000000 +0100
++++ b/basic.c	2020-04-21 19:01:59.000000000 +0100
 @@ -19,6 +19,9 @@
  #include <stdio.h>
  #include <stdlib.h>
@@ -220,614 +116,9 @@ diff -Naur a/basic.c b/basic.c
  #include "def.h"
  
  #define percint(n1, n2)		((n1 * (int) n2) * 0.1)
-diff -Naur a/basic.c.orig b/basic.c.orig
---- a/basic.c.orig	1970-01-01 01:00:00.000000000 +0100
-+++ b/basic.c.orig	2020-04-20 21:26:06.000000000 +0100
-@@ -0,0 +1,601 @@
-+/*	$OpenBSD: basic.c,v 1.49 2019/06/17 11:39:26 lum Exp $	*/
-+
-+/* This file is in the public domain */
-+
-+/*
-+ *		Basic cursor motion commands.
-+ *
-+ * The routines in this file are the basic
-+ * command functions for moving the cursor around on
-+ * the screen, setting mark, and swapping dot with
-+ * mark. Only moves between lines, which might make the
-+ * current buffer framing bad, are hard.
-+ */
-+
-+#include <sys/queue.h>
-+#include <ctype.h>
-+#include <limits.h>
-+#include <signal.h>
-+#include <stdio.h>
-+#include <stdlib.h>
-+
-+#include "def.h"
-+
-+#define percint(n1, n2)		((n1 * (int) n2) * 0.1)
-+
-+/*
-+ * Go to beginning of line.
-+ */
-+/* ARGSUSED */
-+int
-+gotobol(int f, int n)
-+{
-+	if (n == 0)
-+		return (TRUE);
-+
-+	curwp->w_doto = 0;
-+	return (TRUE);
-+}
-+
-+/*
-+ * Move cursor backwards. Do the
-+ * right thing if the count is less than
-+ * 0. Error if you try to move back from
-+ * the beginning of the buffer.
-+ */
-+/* ARGSUSED */
-+int
-+backchar(int f, int n)
-+{
-+	struct line   *lp;
-+
-+	if (n < 0)
-+		return (forwchar(f, -n));
-+	while (n--) {
-+		if (curwp->w_doto == 0) {
-+			if ((lp = lback(curwp->w_dotp)) == curbp->b_headp) {
-+				if (!(f & FFRAND)) {
-+					dobeep();
-+					ewprintf("Beginning of buffer");
-+				}
-+				return (FALSE);
-+			}
-+			curwp->w_dotp = lp;
-+			curwp->w_doto = llength(lp);
-+			curwp->w_rflag |= WFMOVE;
-+			curwp->w_dotline--;
-+		} else
-+			curwp->w_doto--;
-+	}
-+	return (TRUE);
-+}
-+
-+/*
-+ * Go to end of line.
-+ */
-+/* ARGSUSED */
-+int
-+gotoeol(int f, int n)
-+{
-+	if (n == 0)
-+		return (TRUE);
-+
-+	curwp->w_doto = llength(curwp->w_dotp);
-+	return (TRUE);
-+}
-+
-+/*
-+ * Move cursor forwards. Do the
-+ * right thing if the count is less than
-+ * 0. Error if you try to move forward
-+ * from the end of the buffer.
-+ */
-+/* ARGSUSED */
-+int
-+forwchar(int f, int n)
-+{
-+	if (n < 0)
-+		return (backchar(f, -n));
-+	while (n--) {
-+		if (curwp->w_doto == llength(curwp->w_dotp)) {
-+			curwp->w_dotp = lforw(curwp->w_dotp);
-+			if (curwp->w_dotp == curbp->b_headp) {
-+				curwp->w_dotp = lback(curwp->w_dotp);
-+				if (!(f & FFRAND)) {
-+					dobeep();
-+					ewprintf("End of buffer");
-+				}
-+				return (FALSE);
-+			}
-+			curwp->w_doto = 0;
-+			curwp->w_dotline++;
-+			curwp->w_rflag |= WFMOVE;
-+		} else
-+			curwp->w_doto++;
-+	}
-+	return (TRUE);
-+}
-+
-+/*
-+ * Go to the beginning of the buffer. Setting WFFULL is conservative,
-+ * but almost always the case. A universal argument of higher than 9
-+ * puts the cursor back to the end of buffer.
-+ */
-+int
-+gotobob(int f, int n)
-+{
-+	if (!curwp->w_markp)
-+		(void) setmark(f, n);
-+	curwp->w_dotp = bfirstlp(curbp);
-+	curwp->w_doto = 0;
-+	curwp->w_rflag |= WFFULL;
-+	curwp->w_dotline = 1;
-+	if (f & FFOTHARG && n > 0) {
-+		if (n > 9)
-+			gotoeob(0, 0);
-+		else
-+			forwline(f, percint(curwp->w_bufp->b_lines, n) - 1);
-+	}
-+	return (TRUE);
-+}
-+
-+/*
-+ * Go to the end of the buffer. Leave dot 3 lines from the bottom of the
-+ * window if buffer length is longer than window length; same as emacs.
-+ * Setting WFFULL is conservative, but almost always the case. A universal
-+ * argument of higher than 9 puts the cursor back to the start of buffer.
-+ */
-+int
-+gotoeob(int f, int n)
-+{
-+	int		 ln;
-+	struct line	*lp;
-+
-+	if (!curwp->w_markp)
-+		(void) setmark(f, n);
-+	curwp->w_dotp = blastlp(curbp);
-+	curwp->w_doto = llength(curwp->w_dotp);
-+	curwp->w_dotline = curwp->w_bufp->b_lines;
-+
-+	lp = curwp->w_dotp;
-+	ln = curwp->w_ntrows - 3;
-+
-+	if (ln < curwp->w_bufp->b_lines && ln >= 3) {
-+		while (ln--)
-+			curwp->w_dotp = lback(curwp->w_dotp);
-+
-+		curwp->w_linep = curwp->w_dotp;
-+		curwp->w_dotp = lp;
-+	}
-+	if (f & FFOTHARG && n > 0) {
-+		if (n > 9)
-+			gotobob(0, 0);
-+		else
-+			backline(f, percint(curwp->w_bufp->b_lines, n));
-+	}
-+
-+	curwp->w_rflag |= WFFULL;
-+	return (TRUE);
-+}
-+
-+/*
-+ * Move forward by full lines.
-+ * If the number of lines to move is less
-+ * than zero, call the backward line function to
-+ * actually do it. The last command controls how
-+ * the goal column is set.
-+ */
-+/* ARGSUSED */
-+int
-+forwline(int f, int n)
-+{
-+	struct line  *dlp;
-+
-+	if (n < 0)
-+		return (backline(f | FFRAND, -n));
-+	if ((dlp = curwp->w_dotp) == curbp->b_headp) {
-+		if (!(f & FFRAND)) {
-+			dobeep();
-+			ewprintf("End of buffer");
-+		}
-+		return(TRUE);
-+	}
-+	if ((lastflag & CFCPCN) == 0)	/* Fix goal. */
-+		setgoal();
-+	thisflag |= CFCPCN;
-+	if (n == 0)
-+		return (TRUE);
-+	while (n--) {
-+		dlp = lforw(dlp);
-+		if (dlp == curbp->b_headp) {
-+			curwp->w_dotp = lback(dlp);
-+			curwp->w_doto = llength(curwp->w_dotp);
-+			curwp->w_rflag |= WFMOVE;
-+			if (!(f & FFRAND)) {
-+				dobeep();
-+				ewprintf("End of buffer");
-+			}
-+			return (TRUE);
-+		}
-+		curwp->w_dotline++;
-+	}
-+	curwp->w_rflag |= WFMOVE;
-+	curwp->w_dotp = dlp;
-+	curwp->w_doto = getgoal(dlp);
-+
-+	return (TRUE);
-+}
-+
-+/*
-+ * This function is like "forwline", but
-+ * goes backwards. The scheme is exactly the same.
-+ * Check for arguments that are less than zero and
-+ * call your alternate. Figure out the new line and
-+ * call "movedot" to perform the motion.
-+ */
-+/* ARGSUSED */
-+int
-+backline(int f, int n)
-+{
-+	struct line   *dlp;
-+
-+	if (n < 0)
-+		return (forwline(f | FFRAND, -n));
-+	if ((lastflag & CFCPCN) == 0)	/* Fix goal. */
-+		setgoal();
-+	thisflag |= CFCPCN;
-+	dlp = curwp->w_dotp;
-+	if (lback(dlp) == curbp->b_headp)  {
-+		if (!(f & FFRAND)) {
-+			dobeep();
-+			ewprintf("Beginning of buffer");
-+		}
-+		return(TRUE);
-+	}
-+	while (n-- && lback(dlp) != curbp->b_headp) {
-+		dlp = lback(dlp);
-+		curwp->w_dotline--;
-+	}
-+	if (n > 0 && !(f & FFRAND)) {
-+		dobeep();
-+		ewprintf("Beginning of buffer");
-+	}
-+	curwp->w_dotp = dlp;
-+	curwp->w_doto = getgoal(dlp);
-+	curwp->w_rflag |= WFMOVE;
-+	return (TRUE);
-+}
-+
-+/*
-+ * Set the current goal column, which is saved in the external variable
-+ * "curgoal", to the current cursor column. The column is never off
-+ * the edge of the screen; it's more like display then show position.
-+ */
-+void
-+setgoal(void)
-+{
-+	curgoal = getcolpos(curwp);	/* Get the position. */
-+	/* we can now display past end of display, don't chop! */
-+}
-+
-+/*
-+ * This routine looks at a line (pointed
-+ * to by the LINE pointer "dlp") and the current
-+ * vertical motion goal column (set by the "setgoal"
-+ * routine above) and returns the best offset to use
-+ * when a vertical motion is made into the line.
-+ */
-+int
-+getgoal(struct line *dlp)
-+{
-+	int c, i, col = 0;
-+	char tmp[5];
-+
-+
-+	for (i = 0; i < llength(dlp); i++) {
-+		c = lgetc(dlp, i);
-+		if (c == '\t'
-+#ifdef	NOTAB
-+		    && !(curbp->b_flag & BFNOTAB)
-+#endif
-+			) {
-+			col |= 0x07;
-+			col++;
-+		} else if (ISCTRL(c) != FALSE) {
-+			col += 2;
-+		} else if (isprint(c))
-+			col++;
-+		else {
-+			col += snprintf(tmp, sizeof(tmp), "\\%o", c);
-+		}
-+		if (col > curgoal)
-+			break;
-+	}
-+	return (i);
-+}
-+
-+/*
-+ * Scroll forward by a specified number
-+ * of lines, or by a full page if no argument.
-+ * The "2" is the window overlap (this is the default
-+ * value from ITS EMACS). Because the top line in
-+ * the window is zapped, we have to do a hard
-+ * update and get it back.
-+ */
-+/* ARGSUSED */
-+int
-+forwpage(int f, int n)
-+{
-+	struct line  *lp;
-+
-+	if (!(f & FFARG)) {
-+		n = curwp->w_ntrows - 2;	/* Default scroll.	 */
-+		if (n <= 0)			/* Forget the overlap	 */
-+			n = 1;			/* if tiny window.	 */
-+	} else if (n < 0)
-+		return (backpage(f | FFRAND, -n));
-+
-+	lp = curwp->w_linep;
-+	while (n--)
-+		if ((lp = lforw(lp)) == curbp->b_headp) {
-+			dobeep();
-+			ewprintf("End of buffer");
-+			return(TRUE);
-+		}
-+
-+	curwp->w_linep = lp;
-+	curwp->w_rflag |= WFFULL;
-+
-+	/* if in current window, don't move dot */
-+	for (n = curwp->w_ntrows; n-- && lp != curbp->b_headp; lp = lforw(lp))
-+		if (lp == curwp->w_dotp)
-+			return (TRUE);
-+
-+	/* Advance the dot the slow way, for line nos */
-+	while (curwp->w_dotp != curwp->w_linep) {
-+		curwp->w_dotp = lforw(curwp->w_dotp);
-+		curwp->w_dotline++;
-+	}
-+	curwp->w_doto = 0;
-+	return (TRUE);
-+}
-+
-+/*
-+ * This command is like "forwpage",
-+ * but it goes backwards. The "2", like above,
-+ * is the overlap between the two windows. The
-+ * value is from the ITS EMACS manual. The
-+ * hard update is done because the top line in
-+ * the window is zapped.
-+ */
-+/* ARGSUSED */
-+int
-+backpage(int f, int n)
-+{
-+	struct line  *lp, *lp2;
-+
-+	if (!(f & FFARG)) {
-+		n = curwp->w_ntrows - 2;	/* Default scroll.	 */
-+		if (n <= 0)			/* Don't blow up if the  */
-+			return (backline(f, 1));/* window is tiny.	 */
-+	} else if (n < 0)
-+		return (forwpage(f | FFRAND, -n));
-+
-+	lp = lp2 = curwp->w_linep;
-+
-+	while (n-- && lback(lp) != curbp->b_headp) {
-+		lp = lback(lp);
-+	}
-+	if (lp == curwp->w_linep) {
-+		dobeep();
-+		ewprintf("Beginning of buffer");
-+	}
-+	curwp->w_linep = lp;
-+	curwp->w_rflag |= WFFULL;
-+
-+	/* if in current window, don't move dot */
-+	for (n = curwp->w_ntrows; n-- && lp != curbp->b_headp; lp = lforw(lp))
-+		if (lp == curwp->w_dotp)
-+			return (TRUE);
-+
-+        lp2 = lforw(lp2);
-+
-+	/* Move the dot the slow way, for line nos */
-+	while (curwp->w_dotp != lp2) {
-+                if (curwp->w_dotline <= curwp->w_ntrows)
-+			goto out;
-+		curwp->w_dotp = lback(curwp->w_dotp);
-+		curwp->w_dotline--;
-+	}
-+out:
-+	curwp->w_doto = 0;
-+	return (TRUE);
-+}
-+
-+/*
-+ * These functions are provided for compatibility with Gosling's Emacs. They
-+ * are used to scroll the display up (or down) one line at a time.
-+ */
-+int
-+forw1page(int f, int n)
-+{
-+	if (!(f & FFARG)) {
-+		n = 1;
-+		f = FFUNIV;
-+	}
-+	forwpage(f | FFRAND, n);
-+	return (TRUE);
-+}
-+
-+int
-+back1page(int f, int n)
-+{
-+	if (!(f & FFARG)) {
-+		n = 1;
-+		f = FFUNIV;
-+	}
-+	backpage(f | FFRAND, n);
-+	return (TRUE);
-+}
-+
-+/*
-+ * Page the other window. Check to make sure it exists, then
-+ * nextwind, forwpage and restore window pointers.
-+ */
-+int
-+pagenext(int f, int n)
-+{
-+	struct mgwin *wp;
-+
-+	if (wheadp->w_wndp == NULL) {
-+		dobeep();
-+		ewprintf("No other window");
-+		return (FALSE);
-+	}
-+	wp = curwp;
-+	(void) nextwind(f, n);
-+	(void) forwpage(f, n);
-+	curwp = wp;
-+	curbp = wp->w_bufp;
-+	return (TRUE);
-+}
-+
-+/*
-+ * Internal set mark routine, used by other functions (daveb).
-+ */
-+void
-+isetmark(void)
-+{
-+	curwp->w_markp = curwp->w_dotp;
-+	curwp->w_marko = curwp->w_doto;
-+	curwp->w_markline = curwp->w_dotline;
-+}
-+
-+/*
-+ * Set the mark in the current window
-+ * to the value of dot. A message is written to
-+ * the echo line.  (ewprintf knows about macros)
-+ */
-+/* ARGSUSED */
-+int
-+setmark(int f, int n)
-+{
-+	isetmark();
-+	ewprintf("Mark set");
-+	return (TRUE);
-+}
-+
-+/* Clear the mark, if set. */
-+/* ARGSUSED */
-+int
-+clearmark(int f, int n)
-+{
-+	if (!curwp->w_markp)
-+		return (FALSE);
-+
-+	curwp->w_markp = NULL;
-+	curwp->w_marko = 0;
-+	curwp->w_markline = 0;
-+
-+	return (TRUE);
-+}
-+
-+/*
-+ * Swap the values of "dot" and "mark" in
-+ * the current window. This is pretty easy, because
-+ * all of the hard work gets done by the standard routine
-+ * that moves the mark about. The only possible
-+ * error is "no mark".
-+ */
-+/* ARGSUSED */
-+int
-+swapmark(int f, int n)
-+{
-+	struct line  *odotp;
-+	int odoto, odotline;
-+
-+	if (curwp->w_markp == NULL) {
-+		dobeep();
-+		ewprintf("No mark in this window");
-+		return (FALSE);
-+	}
-+	odotp = curwp->w_dotp;
-+	odoto = curwp->w_doto;
-+	odotline = curwp->w_dotline;
-+	curwp->w_dotp = curwp->w_markp;
-+	curwp->w_doto = curwp->w_marko;
-+	curwp->w_dotline = curwp->w_markline;
-+	curwp->w_markp = odotp;
-+	curwp->w_marko = odoto;
-+	curwp->w_markline = odotline;
-+	curwp->w_rflag |= WFMOVE;
-+	return (TRUE);
-+}
-+
-+/*
-+ * Go to a specific line, mostly for
-+ * looking up errors in C programs, which give the
-+ * error a line number. If an argument is present, then
-+ * it is the line number, else prompt for a line number
-+ * to use.
-+ */
-+/* ARGSUSED */
-+int
-+gotoline(int f, int n)
-+{
-+	char   buf[32], *bufp;
-+	const char *err;
-+
-+	if (!(f & FFARG)) {
-+		if ((bufp = eread("Goto line: ", buf, sizeof(buf),
-+		    EFNUL | EFNEW | EFCR)) == NULL)
-+			return (ABORT);
-+		if (bufp[0] == '\0')
-+			return (ABORT);
-+		n = (int)strtonum(buf, INT_MIN, INT_MAX, &err);
-+		if (err) {
-+			dobeep();
-+			ewprintf("Line number %s", err);
-+			return (FALSE);
-+		}
-+	}
-+	return(setlineno(n));
-+}
-+
-+/*
-+ * Set the line number and switch to it.
-+ */
-+int
-+setlineno(int n)
-+{
-+	struct line  *clp;
-+
-+	if (n >= 0) {
-+		if (n == 0)
-+			n++;
-+		curwp->w_dotline = n;
-+		clp = lforw(curbp->b_headp);	/* "clp" is first line */
-+		while (--n > 0) {
-+			if (lforw(clp) == curbp->b_headp) {
-+				curwp->w_dotline = curwp->w_bufp->b_lines;
-+				break;
-+			}
-+			clp = lforw(clp);
-+		}
-+	} else {
-+		curwp->w_dotline = curwp->w_bufp->b_lines + n;
-+		clp = lback(curbp->b_headp);	/* "clp" is last line */
-+		while (n < 0) {
-+			if (lback(clp) == curbp->b_headp) {
-+				curwp->w_dotline = 1;
-+				break;
-+			}
-+			clp = lback(clp);
-+			n++;
-+		}
-+	}
-+	curwp->w_dotp = clp;
-+	curwp->w_doto = 0;
-+	curwp->w_rflag |= WFMOVE;
-+	return (TRUE);
-+}
 diff -Naur a/cscope.c b/cscope.c
 --- a/cscope.c	2020-04-20 21:09:41.000000000 +0100
-+++ b/cscope.c	2020-04-20 21:26:10.000000000 +0100
++++ b/cscope.c	2020-04-21 19:01:59.000000000 +0100
 @@ -20,6 +20,9 @@
  #include <string.h>
  #include <unistd.h>
@@ -840,7 +131,7 @@ diff -Naur a/cscope.c b/cscope.c
  #define CSSYMBOL      0
 diff -Naur a/display.c b/display.c
 --- a/display.c	2020-04-20 21:09:41.000000000 +0100
-+++ b/display.c	2020-04-20 21:26:10.000000000 +0100
++++ b/display.c	2020-04-21 19:01:59.000000000 +0100
 @@ -19,6 +19,9 @@
  #include <string.h>
  #include <term.h>
@@ -853,7 +144,7 @@ diff -Naur a/display.c b/display.c
  
 diff -Naur a/fileio.c b/fileio.c
 --- a/fileio.c	2020-04-20 21:09:41.000000000 +0100
-+++ b/fileio.c	2020-04-20 21:26:10.000000000 +0100
++++ b/fileio.c	2020-04-21 19:01:59.000000000 +0100
 @@ -22,19 +22,13 @@
  #include <stdlib.h>
  #include <string.h>
@@ -913,774 +204,9 @@ diff -Naur a/fileio.c b/fileio.c
  				ewprintf("Path too long");
  				return (NULL);
  			}
-diff -Naur a/fileio.c.orig b/fileio.c.orig
---- a/fileio.c.orig	1970-01-01 01:00:00.000000000 +0100
-+++ b/fileio.c.orig	2020-04-20 21:26:06.000000000 +0100
-@@ -0,0 +1,761 @@
-+/*	$OpenBSD: fileio.c,v 1.106 2019/06/22 10:21:57 lum Exp $	*/
-+
-+/* This file is in the public domain. */
-+
-+/*
-+ *	POSIX fileio.c
-+ */
-+
-+#include <sys/queue.h>
-+#include <sys/resource.h>
-+#include <sys/stat.h>
-+#include <sys/time.h>
-+#include <sys/types.h>
-+#include <sys/wait.h>
-+#include <dirent.h>
-+#include <errno.h>
-+#include <fcntl.h>
-+#include <limits.h>
-+#include <pwd.h>
-+#include <signal.h>
-+#include <stdio.h>
-+#include <stdlib.h>
-+#include <string.h>
-+#include <unistd.h>
-+
-+#include "def.h"
-+#include "kbd.h"
-+#include "pathnames.h"
-+
-+#ifndef MAXNAMLEN
-+#define MAXNAMLEN 255
-+#endif
-+
-+#ifndef DEFFILEMODE
-+#define DEFFILEMODE 0666
-+#endif
-+
-+static char *bkuplocation(const char *);
-+static int   bkupleavetmp(const char *);
-+
-+static char *bkupdir;
-+static int   leavetmp = 0;	/* 1 = leave any '~' files in tmp dir */
-+
-+/*
-+ * Open a file for reading.
-+ */
-+int
-+ffropen(FILE ** ffp, const char *fn, struct buffer *bp)
-+{
-+	if ((*ffp = fopen(fn, "r")) == NULL) {
-+		if (errno == ENOENT)
-+			return (FIOFNF);
-+		return (FIOERR);
-+	}
-+
-+	/* If 'fn' is a directory open it with dired. */
-+	if (fisdir(fn) == TRUE)
-+		return (FIODIR);
-+
-+	ffstat(*ffp, bp);
-+
-+	return (FIOSUC);
-+}
-+
-+/*
-+ * Update stat/dirty info
-+ */
-+void
-+ffstat(FILE *ffp, struct buffer *bp)
-+{
-+	struct stat	sb;
-+
-+	if (bp && fstat(fileno(ffp), &sb) == 0) {
-+		/* set highorder bit to make sure this isn't all zero */
-+		bp->b_fi.fi_mode = sb.st_mode | 0x8000;
-+		bp->b_fi.fi_uid = sb.st_uid;
-+		bp->b_fi.fi_gid = sb.st_gid;
-+		/* bp->b_fi.fi_mtime = sb.st_mtimespec; */
-+		bp->b_fi.fi_mtime.tv_sec = sb.st_mtime;
-+		bp->b_fi.fi_mtime.tv_nsec = 0;
-+		/* Clear the ignore flag */
-+		bp->b_flag &= ~(BFIGNDIRTY | BFDIRTY);
-+	}
-+}
-+
-+/*
-+ * Update the status/dirty info. If there is an error,
-+ * there's not a lot we can do.
-+ */
-+int
-+fupdstat(struct buffer *bp)
-+{
-+	FILE *ffp;
-+
-+	if ((ffp = fopen(bp->b_fname, "r")) == NULL) {
-+		if (errno == ENOENT)
-+			return (FIOFNF);
-+		return (FIOERR);
-+	}
-+	ffstat(ffp, bp);
-+	(void)ffclose(ffp, bp);
-+	return (FIOSUC);
-+}
-+
-+/*
-+ * Open a file for writing.
-+ */
-+int
-+ffwopen(FILE ** ffp, const char *fn, struct buffer *bp)
-+{
-+	int	fd;
-+	mode_t	fmode = DEFFILEMODE;
-+
-+	if (bp && bp->b_fi.fi_mode)
-+		fmode = bp->b_fi.fi_mode & 07777;
-+
-+	fd = open(fn, O_RDWR | O_CREAT | O_TRUNC, fmode);
-+	if (fd == -1) {
-+		ffp = NULL;
-+		dobeep();
-+		ewprintf("Cannot open file for writing : %s", strerror(errno));
-+		return (FIOERR);
-+	}
-+
-+	if ((*ffp = fdopen(fd, "w")) == NULL) {
-+		dobeep();
-+		ewprintf("Cannot open file for writing : %s", strerror(errno));
-+		close(fd);
-+		return (FIOERR);
-+	}
-+
-+	/*
-+	 * If we have file information, use it.  We don't bother to check for
-+	 * errors, because there's no a lot we can do about it.  Certainly
-+	 * trying to change ownership will fail if we aren't root.  That's
-+	 * probably OK.  If we don't have info, no need to get it, since any
-+	 * future writes will do the same thing.
-+	 */
-+	if (bp && bp->b_fi.fi_mode) {
-+		fchmod(fd, bp->b_fi.fi_mode & 07777);
-+		fchown(fd, bp->b_fi.fi_uid, bp->b_fi.fi_gid);
-+	}
-+	return (FIOSUC);
-+}
-+
-+/*
-+ * Close a file.
-+ */
-+/* ARGSUSED */
-+int
-+ffclose(FILE *ffp, struct buffer *bp)
-+{
-+	if (fclose(ffp) == 0)
-+		return (FIOSUC);
-+	return (FIOERR);
-+}
-+
-+/*
-+ * Write a buffer to the already opened file. bp points to the
-+ * buffer. Return the status.
-+ */
-+int
-+ffputbuf(FILE *ffp, struct buffer *bp, int eobnl)
-+{
-+	struct line	*lp, *lpend;
-+
-+	lpend = bp->b_headp;
-+
-+	for (lp = lforw(lpend); lp != lpend; lp = lforw(lp)) {
-+		if (fwrite(ltext(lp), 1, llength(lp), ffp) != llength(lp)) {
-+			dobeep();
-+			ewprintf("Write I/O error");
-+			return (FIOERR);
-+		}
-+		if (lforw(lp) != lpend)		/* no implied \n on last line */
-+			putc('\n', ffp);
-+	}
-+	if (eobnl) {
-+		lnewline_at(lback(lpend), llength(lback(lpend)));
-+		putc('\n', ffp);
-+	}
-+	return (FIOSUC);
-+}
-+
-+/*
-+ * Read a line from a file, and store the bytes
-+ * in the supplied buffer. Stop on end of file or end of
-+ * line.  When FIOEOF is returned, there is a valid line
-+ * of data without the normally implied \n.
-+ * If the line length exceeds nbuf, FIOLONG is returned.
-+ */
-+int
-+ffgetline(FILE *ffp, char *buf, int nbuf, int *nbytes)
-+{
-+	int	c, i;
-+
-+	i = 0;
-+	while ((c = getc(ffp)) != EOF && c != '\n') {
-+		buf[i++] = c;
-+		if (i >= nbuf)
-+			return (FIOLONG);
-+	}
-+	if (c == EOF && ferror(ffp) != FALSE) {
-+		dobeep();
-+		ewprintf("File read error");
-+		return (FIOERR);
-+	}
-+	*nbytes = i;
-+	return (c == EOF ? FIOEOF : FIOSUC);
-+}
-+
-+/*
-+ * Make a backup copy of "fname".  On Unix the backup has the same
-+ * name as the original file, with a "~" on the end; this seems to
-+ * be newest of the new-speak. The error handling is all in "file.c".
-+ * We do a copy instead of a rename since otherwise another process
-+ * with an open fd will get the backup, not the new file.  This is
-+ * a problem when using mg with things like crontab and vipw.
-+ */
-+int
-+fbackupfile(const char *fn)
-+{
-+	struct stat	 sb;
-+	struct timespec	 new_times[2];
-+	int		 from, to, serrno;
-+	ssize_t		 nread;
-+	char		 buf[BUFSIZ];
-+	char		*nname, *tname, *bkpth;
-+
-+	if (stat(fn, &sb) == -1) {
-+		dobeep();
-+		ewprintf("Can't stat %s : %s", fn, strerror(errno));
-+		return (FALSE);
-+	}
-+
-+	if ((bkpth = bkuplocation(fn)) == NULL)
-+		return (FALSE);
-+
-+	if (asprintf(&nname, "%s~", bkpth) == -1) {
-+		dobeep();
-+		ewprintf("Can't allocate backup file name : %s", strerror(errno));
-+		free(bkpth);
-+		return (ABORT);
-+	}
-+	if (asprintf(&tname, "%s.XXXXXXXXXX", bkpth) == -1) {
-+		dobeep();
-+		ewprintf("Can't allocate temp file name : %s", strerror(errno));
-+		free(bkpth);
-+		free(nname);
-+		return (ABORT);
-+	}
-+	free(bkpth);
-+
-+	if ((from = open(fn, O_RDONLY)) == -1) {
-+		free(nname);
-+		free(tname);
-+		return (FALSE);
-+	}
-+	to = mkstemp(tname);
-+	if (to == -1) {
-+		serrno = errno;
-+		close(from);
-+		free(nname);
-+		free(tname);
-+		errno = serrno;
-+		return (FALSE);
-+	}
-+	while ((nread = read(from, buf, sizeof(buf))) > 0) {
-+		if (write(to, buf, (size_t)nread) != nread) {
-+			nread = -1;
-+			break;
-+		}
-+	}
-+	serrno = errno;
-+	(void) fchmod(to, (sb.st_mode & 0777));
-+
-+	/* copy the mtime to the backupfile */
-+	new_times[0] = sb.st_atim;
-+	new_times[1] = sb.st_mtim;
-+	futimens(to, new_times);
-+
-+	close(from);
-+	close(to);
-+	if (nread == -1) {
-+		if (unlink(tname) == -1)
-+			ewprintf("Can't unlink temp : %s", strerror(errno));
-+	} else {
-+		if (rename(tname, nname) == -1) {
-+			ewprintf("Can't rename temp : %s", strerror(errno));
-+			(void) unlink(tname);
-+			nread = -1;
-+		}
-+	}
-+	free(nname);
-+	free(tname);
-+	errno = serrno;
-+
-+	return (nread == -1 ? FALSE : TRUE);
-+}
-+
-+/*
-+ * Convert "fn" to a canonicalized absolute filename, replacing
-+ * a leading ~/ with the user's home dir, following symlinks, and
-+ * remove all occurrences of /./ and /../
-+ */
-+char *
-+adjustname(const char *fn, int slashslash)
-+{
-+	static char	 fnb[PATH_MAX];
-+	const char	*cp, *ep = NULL;
-+	char		*path;
-+
-+	if (slashslash == TRUE) {
-+		cp = fn + strlen(fn) - 1;
-+		for (; cp >= fn; cp--) {
-+			if (ep && (*cp == '/')) {
-+				fn = ep;
-+				break;
-+			}
-+			if (*cp == '/' || *cp == '~')
-+				ep = cp;
-+			else
-+				ep = NULL;
-+		}
-+	}
-+	if ((path = expandtilde(fn)) == NULL)
-+		return (NULL);
-+
-+	if (realpath(path, fnb) == NULL)
-+		(void)strlcpy(fnb, path, sizeof(fnb));
-+
-+	free(path);
-+	return (fnb);
-+}
-+
-+/*
-+ * Find a startup file for the user and return its name. As a service
-+ * to other pieces of code that may want to find a startup file (like
-+ * the terminal driver in particular), accepts a suffix to be appended
-+ * to the startup file name.
-+ */
-+char *
-+startupfile(char *suffix)
-+{
-+	static char	 file[NFILEN];
-+	char		*home;
-+	int		 ret;
-+
-+	if ((home = getenv("HOME")) == NULL || *home == '\0')
-+		goto nohome;
-+
-+	if (suffix == NULL) {
-+		ret = snprintf(file, sizeof(file), _PATH_MG_STARTUP, home);
-+		if (ret < 0 || ret >= sizeof(file))
-+			return (NULL);
-+	} else {
-+		ret = snprintf(file, sizeof(file), _PATH_MG_TERM, home, suffix);
-+		if (ret < 0 || ret >= sizeof(file))
-+			return (NULL);
-+	}
-+
-+	if (access(file, R_OK) == 0)
-+		return (file);
-+nohome:
-+#ifdef STARTUPFILE
-+	if (suffix == NULL) {
-+		ret = snprintf(file, sizeof(file), "%s", STARTUPFILE);
-+		if (ret < 0 || ret >= sizeof(file))
-+			return (NULL);
-+	} else {
-+		ret = snprintf(file, sizeof(file), "%s%s", STARTUPFILE,
-+		    suffix);
-+		if (ret < 0 || ret >= sizeof(file))
-+			return (NULL);
-+	}
-+
-+	if (access(file, R_OK) == 0)
-+		return (file);
-+#endif /* STARTUPFILE */
-+	return (NULL);
-+}
-+
-+int
-+copy(char *frname, char *toname)
-+{
-+	int	ifd, ofd;
-+	char	buf[BUFSIZ];
-+	mode_t	fmode = DEFFILEMODE;	/* XXX?? */
-+	struct	stat orig;
-+	ssize_t	sr;
-+
-+	if ((ifd = open(frname, O_RDONLY)) == -1)
-+		return (FALSE);
-+	if (fstat(ifd, &orig) == -1) {
-+		dobeep();
-+		ewprintf("fstat: %s", strerror(errno));
-+		close(ifd);
-+		return (FALSE);
-+	}
-+
-+	if ((ofd = open(toname, O_WRONLY|O_CREAT|O_TRUNC, fmode)) == -1) {
-+		close(ifd);
-+		return (FALSE);
-+	}
-+	while ((sr = read(ifd, buf, sizeof(buf))) > 0) {
-+		if (write(ofd, buf, (size_t)sr) != sr) {
-+			ewprintf("write error : %s", strerror(errno));
-+			break;
-+		}
-+	}
-+	if (fchmod(ofd, orig.st_mode) == -1)
-+		ewprintf("Cannot set original mode : %s", strerror(errno));
-+
-+	if (sr == -1) {
-+		ewprintf("Read error : %s", strerror(errno));
-+		close(ifd);
-+		close(ofd);
-+		return (FALSE);
-+	}
-+	/*
-+	 * It is "normal" for this to fail since we can't guarantee that
-+	 * we will be running as root.
-+	 */
-+	if (fchown(ofd, orig.st_uid, orig.st_gid) && errno != EPERM)
-+		ewprintf("Cannot set owner : %s", strerror(errno));
-+
-+	(void) close(ifd);
-+	(void) close(ofd);
-+
-+	return (TRUE);
-+}
-+
-+/*
-+ * return list of file names that match the name in buf.
-+ */
-+struct list *
-+make_file_list(char *buf)
-+{
-+	char		*dir, *file, *cp;
-+	size_t		 len, preflen;
-+	int		 ret;
-+	DIR		*dirp;
-+	struct dirent	*dent;
-+	struct list	*last, *current;
-+	char		 fl_name[NFILEN + 2];
-+	char		 prefixx[NFILEN + 1];
-+
-+	/*
-+	 * We need three different strings:
-+
-+	 * dir - the name of the directory containing what the user typed.
-+	 *  Must be a real unix file name, e.g. no ~user, etc..
-+	 *  Must not end in /.
-+	 * prefix - the portion of what the user typed that is before the
-+	 *  names we are going to find in the directory.  Must have a
-+	 * trailing / if the user typed it.
-+	 * names from the directory - We open dir, and return prefix
-+	 * concatenated with names.
-+	 */
-+
-+	/* first we get a directory name we can look up */
-+	/*
-+	 * Names ending in . are potentially odd, because adjustname will
-+	 * treat foo/bar/.. as a foo/, whereas we are
-+	 * interested in names starting with ..
-+	 */
-+	len = strlen(buf);
-+	if (len && buf[len - 1] == '.') {
-+		buf[len - 1] = 'x';
-+		dir = adjustname(buf, TRUE);
-+		buf[len - 1] = '.';
-+	} else
-+		dir = adjustname(buf, TRUE);
-+	if (dir == NULL)
-+		return (NULL);
-+	/*
-+	 * If the user typed a trailing / or the empty string
-+	 * he wants us to use his file spec as a directory name.
-+	 */
-+	if (len && buf[len - 1] != '/') {
-+		file = strrchr(dir, '/');
-+		if (file) {
-+			*file = '\0';
-+			if (*dir == '\0')
-+				dir = "/";
-+		} else
-+			return (NULL);
-+	}
-+	/* Now we get the prefix of the name the user typed. */
-+	if (strlcpy(prefixx, buf, sizeof(prefixx)) >= sizeof(prefixx))
-+		return (NULL);
-+	cp = strrchr(prefixx, '/');
-+	if (cp == NULL)
-+		prefixx[0] = '\0';
-+	else
-+		cp[1] = '\0';
-+
-+	preflen = strlen(prefixx);
-+	/* cp is the tail of buf that really needs to be compared. */
-+	cp = buf + preflen;
-+	len = strlen(cp);
-+
-+	/*
-+	 * Now make sure that file names will fit in the buffers allocated.
-+	 * SV files are fairly short.  For BSD, something more general would
-+	 * be required.
-+	 */
-+	if (preflen > NFILEN - MAXNAMLEN)
-+		return (NULL);
-+
-+	/* loop over the specified directory, making up the list of files */
-+
-+	/*
-+	 * Note that it is worth our time to filter out names that don't
-+	 * match, even though our caller is going to do so again, and to
-+	 * avoid doing the stat if completion is being done, because stat'ing
-+	 * every file in the directory is relatively expensive.
-+	 */
-+
-+	dirp = opendir(dir);
-+	if (dirp == NULL)
-+		return (NULL);
-+	last = NULL;
-+
-+	while ((dent = readdir(dirp)) != NULL) {
-+		int isdir;
-+		if (strncmp(cp, dent->d_name, len) != 0)
-+			continue;
-+		isdir = 0;
-+		if (dent->d_type == DT_DIR) {
-+			isdir = 1;
-+		} else if (dent->d_type == DT_LNK ||
-+			    dent->d_type == DT_UNKNOWN) {
-+			struct stat	statbuf;
-+
-+			if (fstatat(dirfd(dirp), dent->d_name, &statbuf, 0) < 0)
-+				continue;
-+			if (S_ISDIR(statbuf.st_mode))
-+				isdir = 1;
-+		}
-+
-+		if ((current = malloc(sizeof(struct list))) == NULL) {
-+			free_file_list(last);
-+			closedir(dirp);
-+			return (NULL);
-+		}
-+		ret = snprintf(fl_name, sizeof(fl_name),
-+		    "%s%s%s", prefixx, dent->d_name, isdir ? "/" : "");
-+		if (ret < 0 || ret >= sizeof(fl_name)) {
-+			free(current);
-+			continue;
-+		}
-+		current->l_next = last;
-+		current->l_name = strdup(fl_name);
-+		last = current;
-+	}
-+	closedir(dirp);
-+
-+	return (last);
-+}
-+
-+/*
-+ * Test if a supplied filename refers to a directory
-+ * Returns ABORT on error, TRUE if directory. FALSE otherwise
-+ */
-+int
-+fisdir(const char *fname)
-+{
-+	struct stat	statbuf;
-+
-+	if (stat(fname, &statbuf) != 0)
-+		return (ABORT);
-+
-+	if (S_ISDIR(statbuf.st_mode))
-+		return (TRUE);
-+
-+	return (FALSE);
-+}
-+
-+/*
-+ * Check the mtime of the supplied filename.
-+ * Return TRUE if last mtime matches, FALSE if not,
-+ * If the stat fails, return TRUE and try the save anyway
-+ */
-+int
-+fchecktime(struct buffer *bp)
-+{
-+	struct stat sb;
-+
-+	if (stat(bp->b_fname, &sb) == -1)
-+		return (TRUE);
-+
-+	/* if (bp->b_fi.fi_mtime.tv_sec != sb.st_mtimespec.tv_sec ||
-+	   bp->b_fi.fi_mtime.tv_nsec != sb.st_mtimespec.tv_nsec) */
-+	if (bp->b_fi.fi_mtime.tv_sec != sb.st_mtime)
-+		return (FALSE);
-+
-+	return (TRUE);
-+
-+}
-+
-+/*
-+ * Location of backup file. This function creates the correct path.
-+ */
-+static char *
-+bkuplocation(const char *fn)
-+{
-+	struct stat sb;
-+	char *ret;
-+
-+	if (bkupdir != NULL && (stat(bkupdir, &sb) == 0) &&
-+	    S_ISDIR(sb.st_mode) && !bkupleavetmp(fn)) {
-+		char fname[NFILEN];
-+		const char *c;
-+		int i = 0, len;
-+
-+		c = fn;
-+		len = strlen(bkupdir);
-+
-+		while (*c != '\0') {
-+			/* Make sure we don't go over combined:
-+		 	* strlen(bkupdir + '/' + fname + '\0')
-+		 	*/
-+			if (i >= NFILEN - len - 1)
-+				return (NULL);
-+			if (*c == '/') {
-+				fname[i] = '!';
-+			} else if (*c == '!') {
-+				if (i >= NFILEN - len - 2)
-+					return (NULL);
-+				fname[i++] = '!';
-+				fname[i] = '!';
-+			} else
-+				fname[i] = *c;
-+			i++;
-+			c++;
-+		}
-+		fname[i] = '\0';
-+		if (asprintf(&ret, "%s/%s", bkupdir, fname) == -1)
-+			return (NULL);
-+
-+	} else if ((ret = strndup(fn, NFILEN)) == NULL)
-+		return (NULL);
-+
-+	return (ret);
-+}
-+
-+int
-+backuptohomedir(int f, int n)
-+{
-+	const char	*c = _PATH_MG_DIR;
-+	char		*p;
-+
-+	if (bkupdir == NULL) {
-+		p = adjustname(c, TRUE);
-+		bkupdir = strndup(p, NFILEN);
-+		if (bkupdir == NULL)
-+			return(FALSE);
-+
-+		if (mkdir(bkupdir, 0700) == -1 && errno != EEXIST) {
-+			free(bkupdir);
-+			bkupdir = NULL;
-+		}
-+	} else {
-+		free(bkupdir);
-+		bkupdir = NULL;
-+	}
-+
-+	return (TRUE);
-+}
-+
-+/*
-+ * For applications that use mg as the editor and have a desire to keep
-+ * '~' files in /tmp, toggle the location: /tmp | ~/.mg.d
-+ */
-+int
-+toggleleavetmp(int f, int n)
-+{
-+	leavetmp = !leavetmp;
-+
-+	return (TRUE);
-+}
-+
-+/*
-+ * Returns TRUE if fn is located in the temp directory and we want to save
-+ * those backups there.
-+ */
-+int
-+bkupleavetmp(const char *fn)
-+{
-+	if (!leavetmp)
-+		return(FALSE);
-+
-+	if (strncmp(fn, "/tmp", 4) == 0)
-+		return (TRUE);
-+
-+	return (FALSE);
-+}
-+
-+/*
-+ * Expand file names beginning with '~' if appropriate:
-+ *   1, if ./~fn exists, continue without expanding tilde.
-+ *   2, else, if username 'fn' exists, expand tilde with home directory path.
-+ *   3, otherwise, continue and create new buffer called ~fn.
-+ */
-+char *
-+expandtilde(const char *fn)
-+{
-+	struct passwd	*pw;
-+	struct stat	 statbuf;
-+	const char	*cp;
-+	char		 user[LOGIN_NAME_MAX], path[NFILEN];
-+	char		*ret;
-+	size_t		 ulen, plen;
-+
-+	path[0] = '\0';
-+
-+	if (fn[0] != '~' || stat(fn, &statbuf) == 0) {
-+		if ((ret = strndup(fn, NFILEN)) == NULL)
-+			return (NULL);
-+		return(ret);
-+	}
-+	cp = strchr(fn, '/');
-+	if (cp == NULL)
-+		cp = fn + strlen(fn); /* point to the NUL byte */
-+	ulen = cp - &fn[1];
-+	if (ulen >= sizeof(user)) {
-+		if ((ret = strndup(fn, NFILEN)) == NULL)
-+			return (NULL);
-+		return(ret);
-+	}
-+	if (ulen == 0) /* ~/ or ~ */
-+		pw = getpwuid(geteuid());
-+	else { /* ~user/ or ~user */
-+		memcpy(user, &fn[1], ulen);
-+		user[ulen] = '\0';
-+		pw = getpwnam(user);
-+	}
-+	if (pw != NULL) {
-+		plen = strlcpy(path, pw->pw_dir, sizeof(path));
-+		if (plen == 0 || path[plen - 1] != '/') {
-+			if (strlcat(path, "/", sizeof(path)) >= sizeof(path)) {
-+				dobeep();
-+				ewprintf("Path too long");
-+				return (NULL);
-+			}
-+		}
-+		fn = cp;
-+		if (*fn == '/')
-+			fn++;
-+	}
-+	if (strlcat(path, fn, sizeof(path)) >= sizeof(path)) {
-+		dobeep();
-+		ewprintf("Path too long");
-+		return (NULL);
-+	}
-+	if ((ret = strndup(path, NFILEN)) == NULL)
-+		return (NULL);
-+
-+	return (ret);
-+}
 diff -Naur a/futimens.c b/futimens.c
 --- a/futimens.c	1970-01-01 01:00:00.000000000 +0100
-+++ b/futimens.c	2020-04-20 21:26:10.000000000 +0100
++++ b/futimens.c	2020-04-21 19:01:59.000000000 +0100
 @@ -0,0 +1,14 @@
 +/* This file is in the public domain. */
 +
@@ -1698,7 +224,7 @@ diff -Naur a/futimens.c b/futimens.c
 +}
 diff -Naur a/grep.c b/grep.c
 --- a/grep.c	2020-04-20 21:09:41.000000000 +0100
-+++ b/grep.c	2020-04-20 21:26:10.000000000 +0100
++++ b/grep.c	2020-04-21 19:01:59.000000000 +0100
 @@ -15,6 +15,9 @@
  #include <time.h>
  #include <unistd.h>
@@ -1709,375 +235,9 @@ diff -Naur a/grep.c b/grep.c
  #include "def.h"
  #include "kbd.h"
  #include "funmap.h"
-diff -Naur a/grep.c.orig b/grep.c.orig
---- a/grep.c.orig	1970-01-01 01:00:00.000000000 +0100
-+++ b/grep.c.orig	2020-04-20 21:26:06.000000000 +0100
-@@ -0,0 +1,362 @@
-+/*	$OpenBSD: grep.c,v 1.48 2019/07/11 18:20:18 lum Exp $	*/
-+
-+/* This file is in the public domain */
-+
-+#include <sys/queue.h>
-+#include <sys/types.h>
-+#include <sys/wait.h>
-+
-+#include <ctype.h>
-+#include <limits.h>
-+#include <signal.h>
-+#include <stdio.h>
-+#include <stdlib.h>
-+#include <string.h>
-+#include <time.h>
-+#include <unistd.h>
-+
-+#include "def.h"
-+#include "kbd.h"
-+#include "funmap.h"
-+
-+int	 globalwd = FALSE;
-+static int	 compile_goto_error(int, int);
-+int		 next_error(int, int);
-+static int	 grep(int, int);
-+static int	 gid(int, int);
-+static struct buffer	*compile_mode(const char *, const char *);
-+void grep_init(void);
-+
-+static char compile_last_command[NFILEN] = "make ";
-+
-+/*
-+ * Hints for next-error
-+ *
-+ * XXX - need some kind of callback to find out when those get killed.
-+ */
-+struct mgwin	*compile_win;
-+struct buffer	*compile_buffer;
-+
-+static PF compile_pf[] = {
-+	compile_goto_error
-+};
-+
-+static struct KEYMAPE (1) compilemap = {
-+	1,
-+	1,
-+	rescan,
-+	{
-+		{ CCHR('M'), CCHR('M'), compile_pf, NULL }
-+	}
-+};
-+
-+void
-+grep_init(void)
-+{
-+	funmap_add(compile_goto_error, "compile-goto-error", 0);
-+	funmap_add(next_error, "next-error", 0);
-+	funmap_add(grep, "grep", 1);
-+	funmap_add(compile, "compile", 0);
-+	funmap_add(gid, "gid", 1);
-+	maps_add((KEYMAP *)&compilemap, "compile");
-+}
-+
-+/* ARGSUSED */
-+static int
-+grep(int f, int n)
-+{
-+	char	 cprompt[NFILEN], *bufp;
-+	struct buffer	*bp;
-+	struct mgwin	*wp;
-+
-+	(void)strlcpy(cprompt, "grep -n ", sizeof(cprompt));
-+	if ((bufp = eread("Run grep: ", cprompt, NFILEN,
-+	    EFDEF | EFNEW | EFCR)) == NULL)
-+		return (ABORT);
-+	else if (bufp[0] == '\0')
-+		return (FALSE);
-+	if (strlcat(cprompt, " /dev/null", sizeof(cprompt)) >= sizeof(cprompt))
-+		return (FALSE);
-+
-+	if ((bp = compile_mode("*grep*", cprompt)) == NULL)
-+		return (FALSE);
-+	if ((wp = popbuf(bp, WNONE)) == NULL)
-+		return (FALSE);
-+	curbp = bp;
-+	compile_win = curwp = wp;
-+	return (TRUE);
-+}
-+
-+/* ARGSUSED */
-+int
-+compile(int f, int n)
-+{
-+	char	 cprompt[NFILEN], *bufp;
-+	struct buffer	*bp;
-+	struct mgwin	*wp;
-+
-+	(void)strlcpy(cprompt, compile_last_command, sizeof(cprompt));
-+	if ((bufp = eread("Compile command: ", cprompt, NFILEN,
-+	    EFDEF | EFNEW | EFCR)) == NULL)
-+		return (ABORT);
-+	else if (bufp[0] == '\0')
-+		return (FALSE);
-+	if (savebuffers(f, n) == ABORT)
-+		return (ABORT);
-+	(void)strlcpy(compile_last_command, bufp, sizeof(compile_last_command));
-+
-+	if ((bp = compile_mode("*compile*", cprompt)) == NULL)
-+		return (FALSE);
-+	if ((wp = popbuf(bp, WNONE)) == NULL)
-+		return (FALSE);
-+	curbp = bp;
-+	compile_win = curwp = wp;
-+	gotoline(FFARG, 0);
-+	return (TRUE);
-+}
-+
-+/* id-utils foo. */
-+/* ARGSUSED */
-+static int
-+gid(int f, int n)
-+{
-+	char	 command[NFILEN];
-+	char	 cprompt[NFILEN], *bufp;
-+	int	c;
-+	struct buffer	*bp;
-+	struct mgwin	*wp;
-+	int	 i, j, len;
-+
-+	/* catch ([^\s(){}]+)[\s(){}]* */
-+
-+	i = curwp->w_doto;
-+	/* Skip backwards over delimiters we are currently on */
-+	while (i > 0) {
-+		c = lgetc(curwp->w_dotp, i);
-+		if (isalnum(c) || c == '_')
-+			break;
-+
-+		i--;
-+	}
-+
-+	/* Skip the symbol itself */
-+	for (; i > 0; i--) {
-+		c = lgetc(curwp->w_dotp, i - 1);
-+		if (!isalnum(c) && c != '_')
-+			break;
-+	}
-+	/* Fill the symbol in cprompt[] */
-+	for (j = 0; j < sizeof(cprompt) - 1 && i < llength(curwp->w_dotp);
-+	    j++, i++) {
-+		c = lgetc(curwp->w_dotp, i);
-+		if (!isalnum(c) && c != '_')
-+			break;
-+		cprompt[j] = c;
-+	}
-+	cprompt[j] = '\0';
-+
-+	if ((bufp = eread("Run gid (with args): ", cprompt, NFILEN,
-+	    (j ? EFDEF : 0) | EFNEW | EFCR)) == NULL)
-+		return (ABORT);
-+	else if (bufp[0] == '\0')
-+		return (FALSE);
-+	len = snprintf(command, sizeof(command), "gid %s", cprompt);
-+	if (len < 0 || len >= sizeof(command))
-+		return (FALSE);
-+
-+	if ((bp = compile_mode("*gid*", command)) == NULL)
-+		return (FALSE);
-+	if ((wp = popbuf(bp, WNONE)) == NULL)
-+		return (FALSE);
-+	curbp = bp;
-+	compile_win = curwp = wp;
-+	return (TRUE);
-+}
-+
-+struct buffer *
-+compile_mode(const char *name, const char *command)
-+{
-+	struct buffer	*bp;
-+	FILE	*fpipe;
-+	char	*buf;
-+	size_t	 sz;
-+	ssize_t	 len;
-+	int	 ret, n, status;
-+	char	 cwd[NFILEN], qcmd[NFILEN];
-+	char	 timestr[NTIME];
-+	time_t	 t;
-+
-+	buf = NULL;
-+	sz = 0;
-+
-+	n = snprintf(qcmd, sizeof(qcmd), "%s 2>&1", command);
-+	if (n < 0 || n >= sizeof(qcmd))
-+		return (NULL);
-+
-+	bp = bfind(name, TRUE);
-+	if (bclear(bp) != TRUE)
-+		return (NULL);
-+
-+	if (getbufcwd(bp->b_cwd, sizeof(bp->b_cwd)) != TRUE)
-+		return (NULL);
-+	addlinef(bp, "cd %s", bp->b_cwd);
-+	addline(bp, qcmd);
-+	addline(bp, "");
-+
-+	if (getcwd(cwd, sizeof(cwd)) == NULL)
-+		panic("Can't get current directory!");
-+	if (chdir(bp->b_cwd) == -1) {
-+		dobeep();
-+		ewprintf("Can't change dir to %s", bp->b_cwd);
-+		return (NULL);
-+	}
-+	if ((fpipe = popen(qcmd, "r")) == NULL) {
-+		dobeep();
-+		ewprintf("Problem opening pipe");
-+		return (NULL);
-+	}
-+	while ((len = getline(&buf, &sz, fpipe)) != -1) {
-+		if (buf[len - 1] == '\n')
-+			buf[len - 1] = '\0';
-+		addline(bp, buf);
-+	}
-+	free(buf);
-+	if (ferror(fpipe))
-+		ewprintf("Problem reading pipe");
-+	ret = pclose(fpipe);
-+	t = time(NULL);
-+	strftime(timestr, sizeof(timestr), "%a %b %e %T %Y", localtime(&t));
-+	addline(bp, "");
-+	if (WIFEXITED(ret)) {
-+		status = WEXITSTATUS(ret);
-+		if (status == 0)
-+			addlinef(bp, "Command finished at %s", timestr);
-+		else
-+			addlinef(bp, "Command exited abnormally with code %d "
-+			    "at %s", status, timestr);
-+	} else
-+		addlinef(bp, "Subshell killed by signal %d at %s",
-+		    WTERMSIG(ret), timestr);
-+
-+	bp->b_dotp = bfirstlp(bp);
-+	bp->b_modes[0] = name_mode("fundamental");
-+	bp->b_modes[1] = name_mode("compile");
-+	bp->b_nmodes = 1;
-+
-+	compile_buffer = bp;
-+
-+	if (chdir(cwd) == -1) {
-+		dobeep();
-+		ewprintf("Can't change dir back to %s", cwd);
-+		return (NULL);
-+	}
-+	return (bp);
-+}
-+
-+/* ARGSUSED */
-+static int
-+compile_goto_error(int f, int n)
-+{
-+	struct buffer	*bp;
-+	struct mgwin	*wp;
-+	char	*fname, *line, *lp, *ln;
-+	int	 lineno;
-+	char	*adjf, path[NFILEN];
-+	const char *errstr;
-+	struct line	*last;
-+
-+	compile_win = curwp;
-+	compile_buffer = curbp;
-+	last = blastlp(compile_buffer);
-+
-+ retry:
-+	/* last line is compilation result */
-+	if (curwp->w_dotp == last)
-+		return (FALSE);
-+
-+	if ((line = linetostr(curwp->w_dotp)) == NULL)
-+		return (FALSE);
-+	lp = line;
-+	if ((fname = strsep(&lp, ":")) == NULL || *fname == '\0')
-+		goto fail;
-+	if ((ln = strsep(&lp, ":")) == NULL || *ln == '\0')
-+		goto fail;
-+	lineno = (int)strtonum(ln, INT_MIN, INT_MAX, &errstr);
-+	if (errstr)
-+		goto fail;
-+
-+	if (fname && fname[0] != '/') {
-+		if (getbufcwd(path, sizeof(path)) == FALSE)
-+			goto fail;
-+		if (strlcat(path, fname, sizeof(path)) >= sizeof(path))
-+			goto fail;
-+		adjf = path;
-+	} else {
-+		adjf = adjustname(fname, TRUE);
-+	}
-+	free(line);
-+
-+	if (adjf == NULL)
-+		return (FALSE);
-+
-+	if ((bp = findbuffer(adjf)) == NULL)
-+		return (FALSE);
-+	if ((wp = popbuf(bp, WNONE)) == NULL)
-+		return (FALSE);
-+	curbp = bp;
-+	curwp = wp;
-+	if (bp->b_fname[0] == '\0')
-+		readin(adjf);
-+	gotoline(FFARG, lineno);
-+	return (TRUE);
-+fail:
-+	free(line);
-+	if (curwp->w_dotp != blastlp(curbp)) {
-+		curwp->w_dotp = lforw(curwp->w_dotp);
-+		curwp->w_rflag |= WFMOVE;
-+		goto retry;
-+	}
-+	dobeep();
-+	ewprintf("No more hits");
-+	return (FALSE);
-+}
-+
-+/* ARGSUSED */
-+int
-+next_error(int f, int n)
-+{
-+	if (compile_win == NULL || compile_buffer == NULL) {
-+		dobeep();
-+		ewprintf("No compilation active");
-+		return (FALSE);
-+	}
-+	curwp = compile_win;
-+	curbp = compile_buffer;
-+	if (curwp->w_dotp == blastlp(curbp)) {
-+		dobeep();
-+		ewprintf("No more hits");
-+		return (FALSE);
-+	}
-+	curwp->w_dotp = lforw(curwp->w_dotp);
-+	curwp->w_rflag |= WFMOVE;
-+
-+	return (compile_goto_error(f, n));
-+}
-+
-+/*
-+ * Since we don't have variables (we probably should) these are command
-+ * processors for changing the values of mode flags.
-+ */
-+/* ARGSUSED */
-+int
-+globalwdtoggle(int f, int n)
-+{
-+	if (f & FFARG)
-+		globalwd = n > 0;
-+	else
-+		globalwd = !globalwd;
-+
-+	sgarbf = TRUE;
-+
-+	return (TRUE);
-+}
 diff -Naur a/main.c b/main.c
 --- a/main.c	2020-04-20 21:09:41.000000000 +0100
-+++ b/main.c	2020-04-20 21:26:10.000000000 +0100
++++ b/main.c	2020-04-21 19:01:59.000000000 +0100
 @@ -16,6 +16,9 @@
  #include <string.h>
  #include <unistd.h>
@@ -2090,7 +250,7 @@ diff -Naur a/main.c b/main.c
  #include "funmap.h"
 diff -Naur a/paragraph.c b/paragraph.c
 --- a/paragraph.c	2020-04-20 21:09:41.000000000 +0100
-+++ b/paragraph.c	2020-04-20 21:26:10.000000000 +0100
++++ b/paragraph.c	2020-04-21 19:01:59.000000000 +0100
 @@ -14,6 +14,9 @@
  #include <stdio.h>
  #include <stdlib.h>
@@ -2101,512 +261,9 @@ diff -Naur a/paragraph.c b/paragraph.c
  #include "def.h"
  
  static int	fillcol = 70;
-diff -Naur a/paragraph.c.orig b/paragraph.c.orig
---- a/paragraph.c.orig	1970-01-01 01:00:00.000000000 +0100
-+++ b/paragraph.c.orig	2020-04-20 21:26:06.000000000 +0100
-@@ -0,0 +1,499 @@
-+/*	$OpenBSD: paragraph.c,v 1.46 2018/11/17 09:52:34 lum Exp $	*/
-+
-+/* This file is in the public domain. */
-+
-+/*
-+ * Code for dealing with paragraphs and filling. Adapted from MicroEMACS 3.6
-+ * and GNU-ified by mwm@ucbvax.	 Several bug fixes by blarson@usc-oberon.
-+ */
-+
-+#include <sys/queue.h>
-+#include <ctype.h>
-+#include <limits.h>
-+#include <signal.h>
-+#include <stdio.h>
-+#include <stdlib.h>
-+
-+#include "def.h"
-+
-+static int	fillcol = 70;
-+
-+#define MAXWORD 256
-+
-+static int	findpara(void);
-+static int 	do_gotoeop(int, int, int *);
-+
-+/*
-+ * Move to start of paragraph.
-+ * Move backwards by line, checking from the 1st character forwards for the
-+ * existence a non-space. If a non-space character is found, move to the 
-+ * preceding line. Keep doing this until a line with only spaces is found or
-+ * the start of buffer.
-+ */
-+/* ARGSUSED */
-+int
-+gotobop(int f, int n)
-+{
-+	int col, nospace;
-+
-+	/* the other way... */
-+	if (n < 0)
-+		return (gotoeop(f, -n));
-+
-+	while (n-- > 0) {
-+		nospace = 0;
-+		while (lback(curwp->w_dotp) != curbp->b_headp) {
-+			curwp->w_doto = 0;
-+			col = 0;
-+
-+			while (col < llength(curwp->w_dotp) &&
-+			    (isspace(lgetc(curwp->w_dotp, col))))
-+				col++;
-+
-+			if (col >= llength(curwp->w_dotp)) {
-+				if (nospace)
-+					break;
-+			} else
-+				nospace = 1;
-+
-+			curwp->w_dotline--;
-+			curwp->w_dotp = lback(curwp->w_dotp);
-+		}
-+	}
-+	/* force screen update */
-+	curwp->w_rflag |= WFMOVE;
-+	return (TRUE);
-+}
-+
-+/*
-+ * Move to end of paragraph.
-+ * See comments for gotobop(). Same, but moving forwards.
-+ */
-+/* ARGSUSED */
-+int
-+gotoeop(int f, int n)
-+{
-+	int i;
-+
-+	return(do_gotoeop(f, n, &i));
-+}
-+
-+int
-+do_gotoeop(int f, int n, int *i)
-+{
-+	int col, nospace, j = 0;
-+
-+	/* the other way... */
-+	if (n < 0)
-+		return (gotobop(f, -n));
-+
-+	/* for each one asked for */
-+	while (n-- > 0) {
-+		*i = ++j;
-+		nospace = 0;
-+		while (lforw(curwp->w_dotp) != curbp->b_headp) {
-+			col = 0;
-+			curwp->w_doto = 0;
-+
-+			while (col < llength(curwp->w_dotp) &&
-+			    (isspace(lgetc(curwp->w_dotp, col))))
-+				col++;
-+
-+			if (col >= llength(curwp->w_dotp)) {
-+				if (nospace)
-+					break;
-+			} else
-+				nospace = 1;
-+
-+			curwp->w_dotp = lforw(curwp->w_dotp);
-+			curwp->w_dotline++;
-+
-+		}
-+	}
-+	/* do not continue after end of buffer */
-+	if (lforw(curwp->w_dotp) == curbp->b_headp) {
-+		gotoeol(FFRAND, 1);
-+		curwp->w_rflag |= WFMOVE;
-+		return (FALSE);
-+	}
-+
-+	/* force screen update */
-+	curwp->w_rflag |= WFMOVE;
-+	return (TRUE);
-+}
-+
-+/*
-+ * Justify a paragraph.  Fill the current paragraph according to the current
-+ * fill column.
-+ */
-+/* ARGSUSED */
-+int
-+fillpara(int f, int n)
-+{
-+	int	 c;		/* current char during scan		*/
-+	int	 wordlen;	/* length of current word		*/
-+	int	 clength;	/* position on line during fill		*/
-+	int	 i;		/* index during word copy		*/
-+	int	 eopflag;	/* Are we at the End-Of-Paragraph?	*/
-+	int	 firstflag;	/* first word? (needs no space)		*/
-+	int	 newlength;	/* tentative new line length		*/
-+	int	 eolflag;	/* was at end of line			*/
-+	int	 retval;	/* return value				*/
-+	struct line	*eopline;	/* pointer to line just past EOP	*/
-+	char	 wbuf[MAXWORD];	/* buffer for current word		*/
-+
-+	if (n == 0)
-+		return (TRUE);
-+
-+	undo_boundary_enable(FFRAND, 0);
-+
-+	/* record the pointer to the line just past the EOP */
-+	(void)gotoeop(FFRAND, 1);
-+	if (curwp->w_doto != 0) {
-+		/* paragraph ends at end of buffer */
-+		(void)lnewline();
-+		eopline = lforw(curwp->w_dotp);
-+	} else
-+		eopline = curwp->w_dotp;
-+
-+	/* and back top the beginning of the paragraph */
-+	(void)gotobop(FFRAND, 1);
-+
-+	/* initialize various info */
-+	while (inword() == 0 && forwchar(FFRAND, 1));
-+
-+	clength = curwp->w_doto;
-+	wordlen = 0;
-+
-+	/* scan through lines, filling words */
-+	firstflag = TRUE;
-+	eopflag = FALSE;
-+	while (!eopflag) {
-+
-+		/* get the next character in the paragraph */
-+		if ((eolflag = (curwp->w_doto == llength(curwp->w_dotp)))) {
-+			c = ' ';
-+			if (lforw(curwp->w_dotp) == eopline)
-+				eopflag = TRUE;
-+		} else
-+			c = lgetc(curwp->w_dotp, curwp->w_doto);
-+
-+		/* and then delete it */
-+		if (ldelete((RSIZE) 1, KNONE) == FALSE && !eopflag) {
-+			retval = FALSE;
-+			goto cleanup;
-+		}
-+
-+		/* if not a separator, just add it in */
-+		if (c != ' ' && c != '\t') {
-+			if (wordlen < MAXWORD - 1)
-+				wbuf[wordlen++] = c;
-+			else {
-+				/*
-+				 * You lose chars beyond MAXWORD if the word
-+				 * is too long. I'm too lazy to fix it now; it
-+				 * just silently truncated the word before,
-+				 * so I get to feel smug.
-+				 */
-+				ewprintf("Word too long!");
-+			}
-+		} else if (wordlen) {
-+
-+			/* calculate tentative new length with word added */
-+			newlength = clength + 1 + wordlen;
-+
-+			/*
-+			 * if at end of line or at doublespace and previous
-+			 * character was one of '.','?','!' doublespace here.
-+			 * behave the same way if a ')' is preceded by a
-+			 * [.?!] and followed by a doublespace.
-+			 */
-+			if (dblspace && (!eopflag && ((eolflag ||
-+			    curwp->w_doto == llength(curwp->w_dotp) ||
-+			    (c = lgetc(curwp->w_dotp, curwp->w_doto)) == ' '
-+			    || c == '\t') && (ISEOSP(wbuf[wordlen - 1]) ||
-+			    (wbuf[wordlen - 1] == ')' && wordlen >= 2 &&
-+			    ISEOSP(wbuf[wordlen - 2])))) &&
-+			    wordlen < MAXWORD - 1))
-+				wbuf[wordlen++] = ' ';
-+
-+			/* at a word break with a word waiting */
-+			if (newlength <= fillcol) {
-+				/* add word to current line */
-+				if (!firstflag) {
-+					(void)linsert(1, ' ');
-+					++clength;
-+				}
-+				firstflag = FALSE;
-+			} else {
-+				if (curwp->w_doto > 0 &&
-+				    lgetc(curwp->w_dotp, curwp->w_doto - 1) == ' ') {
-+					curwp->w_doto -= 1;
-+					(void)ldelete((RSIZE) 1, KNONE);
-+				}
-+				/* start a new line */
-+				(void)lnewline();
-+				clength = 0;
-+			}
-+
-+			/* and add the word in in either case */
-+			for (i = 0; i < wordlen; i++) {
-+				(void)linsert(1, wbuf[i]);
-+				++clength;
-+			}
-+			wordlen = 0;
-+		}
-+	}
-+	/* and add a last newline for the end of our new paragraph */
-+	(void)lnewline();
-+
-+	/*
-+	 * We really should wind up where we started, (which is hard to keep
-+	 * track of) but I think the end of the last line is better than the
-+	 * beginning of the blank line.
-+	 */
-+	(void)backchar(FFRAND, 1);
-+	retval = TRUE;
-+cleanup:
-+	undo_boundary_enable(FFRAND, 1);
-+	return (retval);
-+}
-+
-+/*
-+ * Delete n paragraphs. Move to the beginning of the current paragraph, or if
-+ * the cursor is on an empty line, move down the buffer to the first line with
-+ * non-space characters. Then mark n paragraphs and delete.
-+ */
-+/* ARGSUSED */
-+int
-+killpara(int f, int n)
-+{
-+	int	lineno, status;
-+
-+	if (n == 0)
-+		return (TRUE);
-+
-+	if (findpara() == FALSE)
-+		return (TRUE);
-+
-+	/* go to the beginning of the paragraph */
-+	(void)gotobop(FFRAND, 1);
-+
-+	/* take a note of the line number for after deletions and set mark */
-+	lineno = curwp->w_dotline;
-+	curwp->w_markp = curwp->w_dotp;
-+	curwp->w_marko = curwp->w_doto;
-+
-+	(void)gotoeop(FFRAND, n);
-+
-+	if ((status = killregion(FFRAND, 1)) != TRUE)
-+		return (status);
-+
-+	curwp->w_dotline = lineno;
-+	return (TRUE);
-+}
-+
-+/*
-+ * Mark n paragraphs starting with the n'th and working our way backwards.
-+ * This leaves the cursor at the beginning of the paragraph where markpara()
-+ * was invoked.
-+ */
-+/* ARGSUSED */
-+int
-+markpara(int f, int n)
-+{
-+	int i = 0;
-+
-+	if (n == 0)
-+		return (TRUE);
-+
-+	clearmark(FFARG, 0);
-+
-+	if (findpara() == FALSE)
-+		return (TRUE);
-+
-+	(void)do_gotoeop(FFRAND, n, &i);
-+
-+	/* set the mark here */
-+	curwp->w_markp = curwp->w_dotp;
-+	curwp->w_marko = curwp->w_doto;
-+
-+	(void)gotobop(FFRAND, i);
-+
-+	return (TRUE);
-+}
-+
-+/*
-+ * Transpose the current paragraph with the following paragraph. If invoked
-+ * multiple times, transpose to the n'th paragraph. If invoked between 
-+ * paragraphs, move to the previous paragraph, then continue.
-+ */
-+/* ARGSUSED */
-+int
-+transposepara(int f, int n)
-+{
-+	int	i = 0, status;
-+	char	flg;
-+
-+	if (n == 0)
-+		return (TRUE);
-+
-+	undo_boundary_enable(FFRAND, 0);
-+
-+	/* find a paragraph, set mark, then goto the end */
-+	gotobop(FFRAND, 1);
-+	curwp->w_markp = curwp->w_dotp;
-+	curwp->w_marko = curwp->w_doto;
-+	(void)gotoeop(FFRAND, 1);
-+
-+	/* take a note of buffer flags - we may need them */
-+	flg = curbp->b_flag;	
-+
-+	/* clean out kill buffer then kill region */
-+	kdelete();
-+	if ((status = killregion(FFRAND, 1)) != TRUE)
-+		return (status);
-+
-+	/* 
-+	 * Now step through n paragraphs. If we reach the end of buffer,
-+	 * stop and paste the killed region back, then display a message.
-+	 */
-+	if (do_gotoeop(FFRAND, n, &i) == FALSE) {
-+		ewprintf("Cannot transpose paragraph, end of buffer reached.");
-+		(void)gotobop(FFRAND, i);
-+		(void)yank(FFRAND, 1);
-+		curbp->b_flag = flg;	
-+		return (FALSE);
-+	}
-+	(void)yank(FFRAND, 1);
-+
-+	undo_boundary_enable(FFRAND, 1);
-+
-+	return (TRUE);
-+}
-+
-+/*
-+ * Go down the buffer until we find a line with non-space characters.
-+ */
-+int
-+findpara(void)
-+{
-+	int	col, nospace = 0;
-+
-+	/* we move forward to find a para to mark */
-+	do {
-+		curwp->w_doto = 0;
-+		col = 0;
-+
-+		/* check if we are on a blank line */
-+		while (col < llength(curwp->w_dotp)) {
-+			if (!isspace(lgetc(curwp->w_dotp, col)))
-+				nospace = 1;
-+			col++;
-+		}
-+		if (nospace)
-+			break;
-+
-+		if (lforw(curwp->w_dotp) == curbp->b_headp)
-+			return (FALSE);
-+
-+		curwp->w_dotp = lforw(curwp->w_dotp);	
-+		curwp->w_dotline++;
-+	} while (1);
-+
-+	return (TRUE);
-+}
-+
-+/*
-+ * Insert char with work wrap.  Check to see if we're past fillcol, and if so,
-+ * justify this line.  As a last step, justify the line.
-+ */
-+/* ARGSUSED */
-+int
-+fillword(int f, int n)
-+{
-+	char	c;
-+	int	col, i, nce;
-+
-+	for (i = col = 0; col <= fillcol; ++i, ++col) {
-+		if (i == curwp->w_doto)
-+			return selfinsert(f, n);
-+		c = lgetc(curwp->w_dotp, i);
-+		if (c == '\t'
-+#ifdef NOTAB
-+		    && !(curbp->b_flag & BFNOTAB)
-+#endif
-+			)
-+			col |= 0x07;
-+		else if (ISCTRL(c) != FALSE)
-+			++col;
-+	}
-+	if (curwp->w_doto != llength(curwp->w_dotp)) {
-+		(void)selfinsert(f, n);
-+		nce = llength(curwp->w_dotp) - curwp->w_doto;
-+	} else
-+		nce = 0;
-+	curwp->w_doto = i;
-+
-+	if ((c = lgetc(curwp->w_dotp, curwp->w_doto)) != ' ' && c != '\t')
-+		do {
-+			(void)backchar(FFRAND, 1);
-+		} while ((c = lgetc(curwp->w_dotp, curwp->w_doto)) != ' ' &&
-+		    c != '\t' && curwp->w_doto > 0);
-+
-+	if (curwp->w_doto == 0)
-+		do {
-+			(void)forwchar(FFRAND, 1);
-+		} while ((c = lgetc(curwp->w_dotp, curwp->w_doto)) != ' ' &&
-+		    c != '\t' && curwp->w_doto < llength(curwp->w_dotp));
-+
-+	(void)delwhite(FFRAND, 1);
-+	(void)lnewline();
-+	i = llength(curwp->w_dotp) - nce;
-+	curwp->w_doto = i > 0 ? i : 0;
-+	curwp->w_rflag |= WFMOVE;
-+	if (nce == 0 && curwp->w_doto != 0)
-+		return (fillword(f, n));
-+	return (TRUE);
-+}
-+
-+/*
-+ * Set fill column to n for justify.
-+ */
-+int
-+setfillcol(int f, int n)
-+{
-+	char buf[32], *rep;
-+	const char *es;
-+	int nfill;
-+
-+	if ((f & FFARG) != 0) {
-+		fillcol = n;
-+	} else {
-+		if ((rep = eread("Set fill-column: ", buf, sizeof(buf),
-+		    EFNEW | EFCR)) == NULL)
-+			return (ABORT);
-+		else if (rep[0] == '\0')
-+			return (FALSE);
-+		nfill = strtonum(rep, 0, INT_MAX, &es);
-+		if (es != NULL) {
-+			dobeep();
-+			ewprintf("Invalid fill column: %s", rep);
-+			return (FALSE);
-+		}
-+		fillcol = nfill;
-+		ewprintf("Fill column set to %d", fillcol);
-+	}
-+	return (TRUE);
-+}
-+
-+int
-+sentencespace(int f, int n)
-+{
-+	if (f & FFARG)
-+		dblspace = n > 1;
-+	else
-+		dblspace = !dblspace;
-+
-+	return (TRUE);
-+}
 diff -Naur a/reallocarray.c b/reallocarray.c
 --- a/reallocarray.c	1970-01-01 01:00:00.000000000 +0100
-+++ b/reallocarray.c	2020-04-20 21:26:10.000000000 +0100
++++ b/reallocarray.c	2020-04-21 19:01:59.000000000 +0100
 @@ -0,0 +1,38 @@
 +/*	$OpenBSD: reallocarray.c,v 1.3 2015/09/13 08:31:47 guenther Exp $	*/
 +/*
@@ -2648,7 +305,7 @@ diff -Naur a/reallocarray.c b/reallocarray.c
 +}
 diff -Naur a/strtonum.c b/strtonum.c
 --- a/strtonum.c	1970-01-01 01:00:00.000000000 +0100
-+++ b/strtonum.c	2020-04-20 21:26:10.000000000 +0100
++++ b/strtonum.c	2020-04-21 19:01:59.000000000 +0100
 @@ -0,0 +1,65 @@
 +/*	$OpenBSD: strtonum.c,v 1.7 2013/04/17 18:40:58 tedu Exp $	*/
 +
@@ -2717,7 +374,7 @@ diff -Naur a/strtonum.c b/strtonum.c
 +}
 diff -Naur a/tags.c b/tags.c
 --- a/tags.c	2020-04-20 21:09:41.000000000 +0100
-+++ b/tags.c	2020-04-20 21:26:10.000000000 +0100
++++ b/tags.c	2020-04-21 19:01:59.000000000 +0100
 @@ -8,7 +8,11 @@
  
  #include <sys/queue.h>
@@ -2759,7 +416,7 @@ diff -Naur a/tags.c b/tags.c
  struct tagpos {
 diff -Naur a/tree.h b/tree.h
 --- a/tree.h	1970-01-01 01:00:00.000000000 +0100
-+++ b/tree.h	2020-04-20 21:26:10.000000000 +0100
++++ b/tree.h	2020-04-21 19:01:59.000000000 +0100
 @@ -0,0 +1,1006 @@
 +/*	$OpenBSD: tree.h,v 1.29 2017/07/30 19:27:20 deraadt Exp $	*/
 +/*