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 -+# 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 #include @@ -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 #include @@ -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 -+#include -+#include -+#include -+#include -+#include -+ -+#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 #include @@ -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 #include @@ -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 #include @@ -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 -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#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 #include @@ -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 -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#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 #include @@ -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 #include @@ -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 -+#include -+#include -+#include -+#include -+#include -+ -+#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 @@ -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 $ */ +/*