summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@baserock.org>2015-03-23 03:49:03 +0000
committer <>2015-03-25 17:06:51 +0000
commitfb040ea36cb8e2158ccd9100600652f94ae90af1 (patch)
treedba72a74e84a997c23fa0af7c07a4d831be2deb7 /src
parent8b74abeb02c01ddc768c465a826360cf33cec063 (diff)
downloadnano-tarball-fb040ea36cb8e2158ccd9100600652f94ae90af1.tar.gz
Imported from /home/lorry/working-area/delta_nano-tarball/nano-2.4.0.tar.gz.HEADnano-2.4.0master
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am5
-rw-r--r--src/Makefile.in248
-rw-r--r--src/browser.c569
-rw-r--r--src/chars.c64
-rw-r--r--src/color.c213
-rw-r--r--src/cut.c70
-rw-r--r--src/files.c816
-rw-r--r--src/global.c1995
-rw-r--r--src/help.c226
-rw-r--r--src/move.c77
-rw-r--r--src/nano.c801
-rw-r--r--src/nano.h661
-rw-r--r--src/prompt.c655
-rw-r--r--src/proto.h257
-rw-r--r--src/rcfile.c710
-rw-r--r--src/search.c170
-rw-r--r--src/text.c1391
-rw-r--r--src/utils.c48
-rw-r--r--src/winio.c649
19 files changed, 5168 insertions, 4457 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index f0b21c0..df65845 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,7 +1,4 @@
-localedir = $(datadir)/locale
-INCLUDES = -DLOCALEDIR=\"$(localedir)\" -DSYSCONFDIR=\"$(sysconfdir)\"
-
-ACLOCAL_AMFLAGS = -I m4
+AM_CPPFLAGS = -DLOCALEDIR=\"$(localedir)\" -DSYSCONFDIR=\"$(sysconfdir)\"
bin_PROGRAMS = nano
nano_SOURCES = browser.c \
diff --git a/src/Makefile.in b/src/Makefile.in
index acb3389..1837b1b 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -1,9 +1,8 @@
-# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
# @configure_input@
-# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
-# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
-# Inc.
+# Copyright (C) 1994-2013 Free Software Foundation, Inc.
+
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
@@ -16,6 +15,51 @@
@SET_MAKE@
VPATH = @srcdir@
+am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
@@ -34,12 +78,13 @@ PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
-target_triplet = @target@
bin_PROGRAMS = nano$(EXEEXT)
subdir = src
-DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
+ $(top_srcdir)/mkinstalldirs $(top_srcdir)/depcomp
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/ac_define_dir.m4 \
+ $(top_srcdir)/m4/ax_check_compile_flag.m4 \
$(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/glib-2.0.m4 \
$(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/isc-posix.m4 \
$(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \
@@ -60,21 +105,64 @@ am_nano_OBJECTS = browser.$(OBJEXT) chars.$(OBJEXT) color.$(OBJEXT) \
utils.$(OBJEXT) winio.$(OBJEXT)
nano_OBJECTS = $(am_nano_OBJECTS)
nano_DEPENDENCIES =
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+am__v_CC_1 =
CCLD = $(CC)
LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo " CCLD " $@;
+am__v_CCLD_1 =
SOURCES = $(nano_SOURCES)
DIST_SOURCES = $(nano_SOURCES)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
ETAGS = etags
CTAGS = ctags
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
@@ -120,6 +208,11 @@ MKDIR_P = @MKDIR_P@
MKINSTALLDIRS = @MKINSTALLDIRS@
MSGFMT = @MSGFMT@
MSGMERGE = @MSGMERGE@
+NCURSESW_CFLAGS = @NCURSESW_CFLAGS@
+NCURSESW_CONFIG = @NCURSESW_CONFIG@
+NCURSESW_LIBS = @NCURSESW_LIBS@
+NCURSES_CFLAGS = @NCURSES_CFLAGS@
+NCURSES_LIBS = @NCURSES_LIBS@
OBJEXT = @OBJEXT@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
@@ -131,6 +224,8 @@ PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PKGDATADIR = @PKGDATADIR@
PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
POSUB = @POSUB@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
@@ -160,6 +255,7 @@ datarootdir = @datarootdir@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
+haveit = @haveit@
host = @host@
host_alias = @host_alias@
host_cpu = @host_cpu@
@@ -171,7 +267,7 @@ infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
-localedir = $(datadir)/locale
+localedir = @localedir@
localstatedir = @localstatedir@
mandir = @mandir@
mkdir_p = @mkdir_p@
@@ -184,16 +280,11 @@ sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
sysconfdir = @sysconfdir@
-target = @target@
target_alias = @target_alias@
-target_cpu = @target_cpu@
-target_os = @target_os@
-target_vendor = @target_vendor@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
-INCLUDES = -DLOCALEDIR=\"$(localedir)\" -DSYSCONFDIR=\"$(sysconfdir)\"
-ACLOCAL_AMFLAGS = -I m4
+AM_CPPFLAGS = -DLOCALEDIR=\"$(localedir)\" -DSYSCONFDIR=\"$(sysconfdir)\"
nano_SOURCES = browser.c \
chars.c \
color.c \
@@ -249,14 +340,18 @@ $(ACLOCAL_M4): $(am__aclocal_m4_deps)
$(am__aclocal_m4_deps):
install-binPROGRAMS: $(bin_PROGRAMS)
@$(NORMAL_INSTALL)
- test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)"
@list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \
+ fi; \
for p in $$list; do echo "$$p $$p"; done | \
sed 's/$(EXEEXT)$$//' | \
- while read p p1; do if test -f $$p; \
- then echo "$$p"; echo "$$p"; else :; fi; \
+ while read p p1; do if test -f $$p \
+ ; then echo "$$p"; echo "$$p"; else :; fi; \
done | \
- sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \
+ sed -e 'p;s,.*/,,;n;h' \
+ -e 's|.*|.|' \
-e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
sed 'N;N;N;s,\n, ,g' | \
$(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
@@ -277,16 +372,18 @@ uninstall-binPROGRAMS:
@list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
files=`for p in $$list; do echo "$$p"; done | \
sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
- -e 's/$$/$(EXEEXT)/' `; \
+ -e 's/$$/$(EXEEXT)/' \
+ `; \
test -n "$$list" || exit 0; \
echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \
cd "$(DESTDIR)$(bindir)" && rm -f $$files
clean-binPROGRAMS:
-test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
-nano$(EXEEXT): $(nano_OBJECTS) $(nano_DEPENDENCIES)
+
+nano$(EXEEXT): $(nano_OBJECTS) $(nano_DEPENDENCIES) $(EXTRA_nano_DEPENDENCIES)
@rm -f nano$(EXEEXT)
- $(LINK) $(nano_OBJECTS) $(nano_LDADD) $(LIBS)
+ $(AM_V_CCLD)$(LINK) $(nano_OBJECTS) $(nano_LDADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
@@ -311,39 +408,28 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/winio.Po@am__quote@
.c.o:
-@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
.c.obj:
-@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
-
-ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
- list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
- unique=`for i in $$list; do \
- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
- done | \
- $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
- END { if (nonempty) { for (i in files) print i; }; }'`; \
- mkid -fID $$unique
-tags: TAGS
-
-TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
- $(TAGS_FILES) $(LISP)
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
set x; \
here=`pwd`; \
- list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
- unique=`for i in $$list; do \
- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
- done | \
- $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
- END { if (nonempty) { for (i in files) print i; }; }'`; \
+ $(am__define_uniq_tagged_files); \
shift; \
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
test -n "$$unique" || unique=$$empty_fix; \
@@ -355,15 +441,11 @@ TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$$unique; \
fi; \
fi
-ctags: CTAGS
-CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
- $(TAGS_FILES) $(LISP)
- list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
- unique=`for i in $$list; do \
- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
- done | \
- $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
- END { if (nonempty) { for (i in files) print i; }; }'`; \
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
test -z "$(CTAGS_ARGS)$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
$$unique
@@ -372,6 +454,21 @@ GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& $(am__cd) $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
@@ -423,10 +520,15 @@ install-am: all-am
installcheck: installcheck-am
install-strip:
- $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
- install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
- `test -z '$(STRIP)' || \
- echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
mostlyclean-generic:
clean-generic:
@@ -511,19 +613,19 @@ uninstall-am: uninstall-binPROGRAMS
$(MAKE) $(AM_MAKEFLAGS) uninstall-hook
.MAKE: install-am install-exec-am install-strip uninstall-am
-.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \
- clean-generic ctags distclean distclean-compile \
- distclean-generic distclean-tags distdir dvi dvi-am html \
- html-am info info-am install install-am install-binPROGRAMS \
- install-data install-data-am install-dvi install-dvi-am \
- install-exec install-exec-am install-exec-hook install-html \
- install-html-am install-info install-info-am install-man \
- install-pdf install-pdf-am install-ps install-ps-am \
- install-strip installcheck installcheck-am installdirs \
- maintainer-clean maintainer-clean-generic mostlyclean \
- mostlyclean-compile mostlyclean-generic pdf pdf-am ps ps-am \
- tags uninstall uninstall-am uninstall-binPROGRAMS \
- uninstall-hook
+.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean \
+ clean-binPROGRAMS clean-generic cscopelist-am ctags ctags-am \
+ distclean distclean-compile distclean-generic distclean-tags \
+ distdir dvi dvi-am html html-am info info-am install \
+ install-am install-binPROGRAMS install-data install-data-am \
+ install-dvi install-dvi-am install-exec install-exec-am \
+ install-exec-hook install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-ps install-ps-am install-strip installcheck \
+ installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic pdf pdf-am ps ps-am tags tags-am uninstall \
+ uninstall-am uninstall-binPROGRAMS uninstall-hook
install-exec-hook:
diff --git a/src/browser.c b/src/browser.c
index c43796b..1accb98 100644
--- a/src/browser.c
+++ b/src/browser.c
@@ -1,9 +1,9 @@
-/* $Id: browser.c 4461 2009-12-09 17:09:37Z astyanax $ */
+/* $Id: browser.c 5086 2014-07-31 20:49:32Z bens $ */
/**************************************************************************
* browser.c *
* *
- * Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 *
- * Free Software Foundation, Inc. *
+ * Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, *
+ * 2010, 2011, 2013, 2014 Free Software Foundation, Inc. *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 3, or (at your option) *
@@ -50,9 +50,7 @@ char *do_browser(char *path, DIR *dir)
{
char *retval = NULL;
int kbinput;
- bool meta_key, func_key, old_const_update = ISSET(CONST_UPDATE);
- bool abort = FALSE;
- /* Whether we should abort the file browser. */
+ bool old_const_update = ISSET(CONST_UPDATE);
char *prev_dir = NULL;
/* The directory we were in, if any, before backing up via
* browsing to "..". */
@@ -60,14 +58,12 @@ char *do_browser(char *path, DIR *dir)
/* The last answer the user typed at the statusbar prompt. */
size_t old_selected;
/* The selected file we had before the current selected file. */
- const sc *s;
- const subnfunc *f;
+ functionptrtype func;
+ /* The function of the key the user typed in. */
curs_set(0);
blank_statusbar();
-#if !defined(DISABLE_HELP) || !defined(DISABLE_MOUSE)
currmenu = MBROWSER;
-#endif
bottombars(MBROWSER);
wnoutrefresh(bottomwin);
@@ -108,7 +104,7 @@ char *do_browser(char *path, DIR *dir)
titlebar(path);
- while (!abort) {
+ while (TRUE) {
struct stat st;
int i;
size_t fileline = selected / width;
@@ -124,239 +120,220 @@ char *do_browser(char *path, DIR *dir)
old_selected = selected;
- kbinput = get_kbinput(edit, &meta_key, &func_key);
+ kbinput = get_kbinput(edit);
#ifndef DISABLE_MOUSE
- if (kbinput == KEY_MOUSE) {
-
- int mouse_x, mouse_y;
-
- /* We can click on the edit window to select a
- * filename. */
- if (get_mouseinput(&mouse_x, &mouse_y, TRUE) == 0 &&
- wmouse_trafo(edit, &mouse_y, &mouse_x, FALSE)) {
- /* longest is the width of each column. There
- * are two spaces between each column. */
- selected = (fileline / editwinrows) *
+ if (kbinput == KEY_MOUSE) {
+ int mouse_x, mouse_y;
+
+ /* We can click on the edit window to select a
+ * filename. */
+ if (get_mouseinput(&mouse_x, &mouse_y, TRUE) == 0 &&
+ wmouse_trafo(edit, &mouse_y, &mouse_x, FALSE)) {
+ /* longest is the width of each column. There
+ * are two spaces between each column. */
+ selected = (fileline / editwinrows) *
(editwinrows * width) + (mouse_y *
width) + (mouse_x / (longest + 2));
- /* If they clicked beyond the end of a row,
- * select the filename at the end of that
- * row. */
- if (mouse_x > width * (longest + 2))
- selected--;
-
- /* If we're off the screen, select the last
- * filename. */
- if (selected > filelist_len - 1)
- selected = filelist_len - 1;
-
- /* If we selected the same filename as last
- * time, put back the Enter key so that it's
- * read in. */
- if (old_selected == selected)
- unget_kbinput(sc_seq_or(DO_ENTER, 0), FALSE, FALSE);
- }
+ /* If they clicked beyond the end of a row,
+ * select the filename at the end of that
+ * row. */
+ if (mouse_x > width * (longest + 2))
+ selected--;
+
+ /* If we're off the screen, select the last
+ * filename. */
+ if (selected > filelist_len - 1)
+ selected = filelist_len - 1;
+
+ /* If we selected the same filename as last
+ * time, put back the Enter key so that it's
+ * read in. */
+ if (old_selected == selected)
+ unget_kbinput(sc_seq_or(do_enter_void, 0), FALSE, FALSE);
+ }
}
#endif /* !DISABLE_MOUSE */
- parse_browser_input(&kbinput, &meta_key, &func_key);
- s = get_shortcut(MBROWSER, &kbinput, &meta_key, &func_key);
- if (!s)
- continue;
- f = sctofunc((sc *) s);
- if (!f)
- break;
-
- if (f->scfunc == TOTAL_REFRESH) {
- total_redraw();
- } else if (f->scfunc == DO_HELP_VOID) {
+ func = parse_browser_input(&kbinput);
+
+ if (func == total_refresh) {
+ total_redraw();
+ } else if (func == do_help_void) {
#ifndef DISABLE_HELP
- do_browser_help();
+ do_help_void();
curs_set(0);
#else
- nano_disabled_msg();
+ nano_disabled_msg();
#endif
+ } else if (func == do_search) {
/* Search for a filename. */
- } else if (f->scfunc == DO_SEARCH) {
- curs_set(1);
- do_filesearch();
- curs_set(0);
+ curs_set(1);
+ do_filesearch();
+ curs_set(0);
+ } else if (func == do_research) {
/* Search for another filename. */
- } else if (f->scfunc == DO_RESEARCH) {
- do_fileresearch();
- } else if (f->scfunc == DO_PAGE_UP) {
- if (selected >= (editwinrows + fileline % editwinrows) *
- width)
- selected -= (editwinrows + fileline % editwinrows) *
- width;
- else
- selected = 0;
- } else if (f->scfunc == DO_PAGE_DOWN) {
- selected += (editwinrows - fileline % editwinrows) *
- width;
- if (selected > filelist_len - 1)
- selected = filelist_len - 1;
- } else if (f->scfunc == FIRST_FILE_MSG) {
- if (meta_key)
- selected = 0;
- } else if (f->scfunc == LAST_FILE_MSG) {
- if (meta_key)
- selected = filelist_len - 1;
+ do_fileresearch();
+ } else if (func == do_page_up) {
+ if (selected >= (editwinrows + fileline % editwinrows) * width)
+ selected -= (editwinrows + fileline % editwinrows) * width;
+ else
+ selected = 0;
+ } else if (func == do_page_down) {
+ selected += (editwinrows - fileline % editwinrows) * width;
+ if (selected > filelist_len - 1)
+ selected = filelist_len - 1;
+ } else if (func == do_first_file) {
+ selected = 0;
+ } else if (func == do_last_file) {
+ selected = filelist_len - 1;
+ } else if (func == goto_dir_void) {
/* Go to a specific directory. */
- } else if (f->scfunc == GOTO_DIR_MSG) {
- curs_set(1);
-
- i = do_prompt(TRUE,
+ curs_set(1);
+ i = do_prompt(TRUE,
#ifndef DISABLE_TABCOMP
FALSE,
#endif
MGOTODIR, ans,
- &meta_key, &func_key,
-#ifndef NANO_TINY
+#ifndef DISABLE_HISTORIES
NULL,
#endif
- browser_refresh, N_("Go To Directory"));
+ /* TRANSLATORS: This is a prompt. */
+ browser_refresh, _("Go To Directory"));
- curs_set(0);
-#if !defined(DISABLE_HELP) || !defined(DISABLE_MOUSE)
- currmenu = MBROWSER;
-#endif
- bottombars(MBROWSER);
-
- /* If the directory begins with a newline (i.e. an
- * encoded null), treat it as though it's blank. */
- if (i < 0 || *answer == '\n') {
- /* We canceled. Indicate that on the statusbar, and
- * blank out ans, since we're done with it. */
- statusbar(_("Cancelled"));
- ans = mallocstrcpy(ans, "");
- continue;
- } else if (i != 0) {
- /* Put back the "Go to Directory" key and save
- * answer in ans, so that the file list is displayed
- * again, the prompt is displayed again, and what we
- * typed before at the prompt is displayed again. */
- unget_kbinput(sc_seq_or(DO_GOTOLINECOLUMN_VOID, 0), FALSE, FALSE);
- ans = mallocstrcpy(ans, answer);
- continue;
- }
-
- /* We have a directory. Blank out ans, since we're done
- * with it. */
+ curs_set(0);
+ currmenu = MBROWSER;
+ bottombars(MBROWSER);
+
+ /* If the directory begins with a newline (i.e. an
+ * encoded null), treat it as though it's blank. */
+ if (i < 0 || *answer == '\n') {
+ /* We canceled. Indicate that on the statusbar, and
+ * blank out ans, since we're done with it. */
+ statusbar(_("Cancelled"));
ans = mallocstrcpy(ans, "");
+ continue;
+ } else if (i != 0) {
+ /* Put back the "Go to Directory" key and save
+ * answer in ans, so that the file list is displayed
+ * again, the prompt is displayed again, and what we
+ * typed before at the prompt is displayed again. */
+ unget_kbinput(sc_seq_or(do_gotolinecolumn_void, 0), FALSE, FALSE);
+ ans = mallocstrcpy(ans, answer);
+ continue;
+ }
+
+ /* We have a directory. Blank out ans, since we're done
+ * with it. */
+ ans = mallocstrcpy(ans, "");
- /* Convert newlines to nulls, just before we go to the
- * directory. */
- sunder(answer);
- align(&answer);
+ /* Convert newlines to nulls, just before we go to the
+ * directory. */
+ sunder(answer);
+ align(&answer);
- new_path = real_dir_from_tilde(answer);
+ new_path = real_dir_from_tilde(answer);
- if (new_path[0] != '/') {
- new_path = charealloc(new_path, strlen(path) +
- strlen(answer) + 1);
- sprintf(new_path, "%s%s", path, answer);
- }
+ if (new_path[0] != '/') {
+ new_path = charealloc(new_path, strlen(path) +
+ strlen(answer) + 1);
+ sprintf(new_path, "%s%s", path, answer);
+ }
#ifndef DISABLE_OPERATINGDIR
- if (check_operating_dir(new_path, FALSE)) {
- statusbar(
- _("Can't go outside of %s in restricted mode"),
- operating_dir);
- free(new_path);
- continue;
- }
+ if (check_operating_dir(new_path, FALSE)) {
+ statusbar(_("Can't go outside of %s in restricted mode"),
+ operating_dir);
+ free(new_path);
+ continue;
+ }
#endif
- dir = opendir(new_path);
- if (dir == NULL) {
- /* We can't open this directory for some reason.
- * Complain. */
- statusbar(_("Error reading %s: %s"), answer,
- strerror(errno));
- beep();
- free(new_path);
- continue;
- }
-
- /* Start over again with the new path value. */
- free(path);
- path = new_path;
- goto change_browser_directory;
- } else if (f->scfunc == DO_UP_VOID) {
- if (selected >= width)
- selected -= width;
- } else if (f->scfunc == DO_LEFT) {
- if (selected > 0)
- selected--;
- } else if (f->scfunc == DO_DOWN_VOID) {
- if (selected + width <= filelist_len - 1)
- selected += width;
- } else if (f->scfunc == DO_RIGHT) {
- if (selected < filelist_len - 1)
- selected++;
- } else if (f->scfunc == DO_ENTER) {
- /* We can't move up from "/". */
- if (strcmp(filelist[selected], "/..") == 0) {
- statusbar(_("Can't move up a directory"));
- beep();
- continue;
- }
+ dir = opendir(new_path);
+ if (dir == NULL) {
+ /* We can't open this directory for some reason.
+ * Complain. */
+ statusbar(_("Error reading %s: %s"), answer,
+ strerror(errno));
+ beep();
+ free(new_path);
+ continue;
+ }
+
+ /* Start over again with the new path value. */
+ free(path);
+ path = new_path;
+ goto change_browser_directory;
+ } else if (func == do_up_void) {
+ if (selected >= width)
+ selected -= width;
+ } else if (func == do_down_void) {
+ if (selected + width <= filelist_len - 1)
+ selected += width;
+ } else if (func == do_left) {
+ if (selected > 0)
+ selected--;
+ } else if (func == do_right) {
+ if (selected < filelist_len - 1)
+ selected++;
+ } else if (func == do_enter_void) {
+ /* We can't move up from "/". */
+ if (strcmp(filelist[selected], "/..") == 0) {
+ statusbar(_("Can't move up a directory"));
+ beep();
+ continue;
+ }
#ifndef DISABLE_OPERATINGDIR
- /* Note: The selected file can be outside the operating
- * directory if it's ".." or if it's a symlink to a
- * directory outside the operating directory. */
- if (check_operating_dir(filelist[selected], FALSE)) {
- statusbar(
- _("Can't go outside of %s in restricted mode"),
- operating_dir);
- beep();
- continue;
- }
+ /* Note: The selected file can be outside the operating
+ * directory if it's ".." or if it's a symlink to a
+ * directory outside the operating directory. */
+ if (check_operating_dir(filelist[selected], FALSE)) {
+ statusbar(_("Can't go outside of %s in restricted mode"),
+ operating_dir);
+ beep();
+ continue;
+ }
#endif
- if (stat(filelist[selected], &st) == -1) {
- /* We can't open this file for some reason.
- * Complain. */
- statusbar(_("Error reading %s: %s"),
- filelist[selected], strerror(errno));
- beep();
- continue;
- }
+ if (stat(filelist[selected], &st) == -1) {
+ /* We can't open this file for some reason.
+ * Complain. */
+ statusbar(_("Error reading %s: %s"),
+ filelist[selected], strerror(errno));
+ beep();
+ continue;
+ }
- /* If we've successfully opened a file, we're done, so
+ if (!S_ISDIR(st.st_mode)) {
+ /* We've successfully opened a file, we're done, so
* get out. */
- if (!S_ISDIR(st.st_mode)) {
- retval = mallocstrcpy(NULL, filelist[selected]);
- abort = TRUE;
- continue;
- /* If we've successfully opened a directory, and it's
- * "..", save the current directory in prev_dir, so that
- * we can select it later. */
- } else if (strcmp(tail(filelist[selected]), "..") == 0)
- prev_dir = mallocstrcpy(NULL,
- striponedir(filelist[selected]));
-
- dir = opendir(filelist[selected]);
- if (dir == NULL) {
- /* We can't open this directory for some reason.
- * Complain. */
- statusbar(_("Error reading %s: %s"),
- filelist[selected], strerror(errno));
- beep();
- continue;
- }
-
- path = mallocstrcpy(path, filelist[selected]);
-
- /* Start over again with the new path value. */
- goto change_browser_directory;
- /* Abort the file browser. */
- } else if (f->scfunc == DO_EXIT) {
- abort = TRUE;
+ retval = mallocstrcpy(NULL, filelist[selected]);
+ break;
+ } else if (strcmp(tail(filelist[selected]), "..") == 0)
+ /* We've successfully opened the parent directory,
+ * save the current directory in prev_dir, so that
+ * we can easily return to it by hitting Enter. */
+ prev_dir = mallocstrcpy(NULL, striponedir(filelist[selected]));
+
+ dir = opendir(filelist[selected]);
+ if (dir == NULL) {
+ /* We can't open this directory for some reason.
+ * Complain. */
+ statusbar(_("Error reading %s: %s"),
+ filelist[selected], strerror(errno));
+ beep();
+ continue;
+ }
+
+ path = mallocstrcpy(path, filelist[selected]);
+
+ /* Start over again with the new path value. */
+ goto change_browser_directory;
+ } else if (func == do_exit) {
+ /* Exit from the file browser. */
+ break;
}
}
titlebar(NULL);
@@ -460,7 +437,7 @@ void browser_init(const char *path, DIR *dir)
/* Don't show the "." entry. */
if (strcmp(nextdir->d_name, ".") == 0)
- continue;
+ continue;
d_len = strlenpt(nextdir->d_name);
if (d_len > longest)
@@ -487,7 +464,7 @@ void browser_init(const char *path, DIR *dir)
while ((nextdir = readdir(dir)) != NULL && i < filelist_len) {
/* Don't show the "." entry. */
if (strcmp(nextdir->d_name, ".") == 0)
- continue;
+ continue;
filelist[i] = charalloc(path_len + strlen(nextdir->d_name) + 1);
sprintf(filelist[i], "%s%s", path, nextdir->d_name);
@@ -539,48 +516,33 @@ void browser_init(const char *path, DIR *dir)
width = longest;
}
-/* Determine the shortcut key corresponding to the values of kbinput
- * (the key itself), meta_key (whether the key is a meta sequence), and
- * func_key (whether the key is a function key), if any. In the
- * process, convert certain non-shortcut keys into their corresponding
- * shortcut keys. */
-void parse_browser_input(int *kbinput, bool *meta_key, bool *func_key)
+/* Return the function that is bound to the given key, accepting certain
+ * plain characters too, for compatibility with Pico. */
+functionptrtype parse_browser_input(int *kbinput)
{
- get_shortcut(MBROWSER, kbinput, meta_key, func_key);
-
- /* Pico compatibility. */
- if (!*meta_key) {
+ if (!meta_key) {
switch (*kbinput) {
case ' ':
- *kbinput = sc_seq_or(DO_PAGE_DOWN, 0);
- break;
+ return do_page_down;
case '-':
- *kbinput = sc_seq_or(DO_PAGE_UP, 0);
- break;
+ return do_page_up;
case '?':
-#ifndef DISABLE_HELP
- *kbinput = sc_seq_or(DO_HELP_VOID, 0);
-#endif
- break;
- /* Cancel equivalent to Exit here. */
+ return do_help_void;
case 'E':
case 'e':
- *kbinput = sc_seq_or(DO_EXIT, 0);
- break;
+ return do_exit;
case 'G':
case 'g':
- *kbinput = sc_seq_or(GOTO_DIR_MSG, 0);
- break;
+ return goto_dir_void;
case 'S':
case 's':
- *kbinput = sc_seq_or(DO_ENTER, 0);
- break;
+ return do_enter_void;
case 'W':
case 'w':
- *kbinput = sc_seq_or(DO_SEARCH, 0);
- break;
+ return do_search;
}
}
+ return func_from_key(kbinput);
}
/* Set width to the number of files that we can display per line, if
@@ -619,8 +581,7 @@ void browser_refresh(void)
/* The maximum length of the file information in
* columns: seven for "--", "(dir)", or the file size,
* and 12 for "(parent dir)". */
- bool dots = (COLS >= 15 && filetaillen >= longest -
- foomaxlen - 1);
+ bool dots = (COLS >= 15 && filetaillen >= longest - foomaxlen - 1);
/* Do we put an ellipsis before the filename? Don't set
* this to TRUE if we have fewer than 15 columns (i.e.
* one column for padding, plus seven columns for a
@@ -635,7 +596,7 @@ void browser_refresh(void)
/* Start highlighting the currently selected file or
* directory. */
if (i == selected)
- wattron(edit, reverse_attr);
+ wattron(edit, hilite_attribute);
blank_line(edit, line, col, longest);
@@ -710,7 +671,7 @@ void browser_refresh(void)
/* Finish highlighting the currently selected file or
* directory. */
if (i == selected)
- wattroff(edit, reverse_attr);
+ wattroff(edit, hilite_attribute);
free(foo);
@@ -760,8 +721,6 @@ int filesearch_init(void)
{
int i = 0;
char *buf;
- bool meta_key, func_key;
- const sc *s;
static char *backupstring = NULL;
/* The search string we'll be using. */
@@ -794,29 +753,10 @@ int filesearch_init(void)
TRUE,
#endif
MWHEREISFILE, backupstring,
- &meta_key, &func_key,
-#ifndef NANO_TINY
+#ifndef DISABLE_HISTORIES
&search_history,
#endif
- browser_refresh, "%s%s%s%s%s%s", _("Search"),
-#ifndef NANO_TINY
- /* This string is just a modifier for the search prompt; no
- * grammar is implied. */
- ISSET(CASE_SENSITIVE) ? _(" [Case Sensitive]") :
-#endif
- "",
-#ifdef HAVE_REGEX_H
- /* This string is just a modifier for the search prompt; no
- * grammar is implied. */
- ISSET(USE_REGEXP) ? _(" [Regexp]") :
-#endif
- "",
-#ifndef NANO_TINY
- /* This string is just a modifier for the search prompt; no
- * grammar is implied. */
- ISSET(BACKWARDS_SEARCH) ? _(" [Backwards]") :
-#endif
- "", "", buf);
+ browser_refresh, "%s%s", _("Search"), buf);
/* Release buf now that we don't need it anymore. */
free(buf);
@@ -829,36 +769,6 @@ int filesearch_init(void)
*answer == '\0')) {
statusbar(_("Cancelled"));
return -1;
- } else {
- s = get_shortcut(MBROWSER, &i, &meta_key, &func_key);
- if (i == -2 || i == 0) {
-#ifdef HAVE_REGEX_H
- /* Use last_search if answer is an empty string, or
- * answer if it isn't. */
- if (ISSET(USE_REGEXP) && !regexp_init((i == -2) ?
- last_search : answer))
- return -1;
-#endif
- } else
-#ifndef NANO_TINY
- if (s && s->scfunc == CASE_SENS_MSG) {
- TOGGLE(CASE_SENSITIVE);
- backupstring = mallocstrcpy(backupstring, answer);
- return 1;
- } else if (s && s->scfunc == BACKWARDS_MSG) {
- TOGGLE(BACKWARDS_SEARCH);
- backupstring = mallocstrcpy(backupstring, answer);
- return 1;
- } else
-#endif
-#ifdef HAVE_REGEX_H
- if (s && s->scfunc == REGEXP_MSG) {
- TOGGLE(USE_REGEXP);
- backupstring = mallocstrcpy(backupstring, answer);
- return 1;
- } else
-#endif
- return -1;
}
return 0;
@@ -877,11 +787,6 @@ bool findnextfile(bool no_sameline, size_t begin, const char *needle)
/* The filename we display, minus the path. */
const char *rev_start = filetail, *found = NULL;
-#ifndef NANO_TINY
- if (ISSET(BACKWARDS_SEARCH))
- rev_start += strlen(rev_start);
-#endif
-
/* Look for needle in the current filename we're searching. */
while (TRUE) {
found = strstrwrapper(filetail, needle, rev_start);
@@ -898,27 +803,14 @@ bool findnextfile(bool no_sameline, size_t begin, const char *needle)
return FALSE;
}
- /* Move to the previous or next filename in the list. If we've
- * reached the start or end of the list, wrap around. */
-#ifndef NANO_TINY
- if (ISSET(BACKWARDS_SEARCH)) {
- if (currselected > 0)
- currselected--;
- else {
- currselected = filelist_len - 1;
- statusbar(_("Search Wrapped"));
- }
- } else {
-#endif
- if (currselected < filelist_len - 1)
- currselected++;
- else {
- currselected = 0;
- statusbar(_("Search Wrapped"));
- }
-#ifndef NANO_TINY
+ /* Move to the next filename in the list. If we've reached the
+ * end of the list, wrap around. */
+ if (currselected < filelist_len - 1)
+ currselected++;
+ else {
+ currselected = 0;
+ statusbar(_("Search Wrapped"));
}
-#endif
/* We've reached the original starting file. */
if (currselected == begin)
@@ -927,10 +819,6 @@ bool findnextfile(bool no_sameline, size_t begin, const char *needle)
filetail = tail(filelist[currselected]);
rev_start = filetail;
-#ifndef NANO_TINY
- if (ISSET(BACKWARDS_SEARCH))
- rev_start += strlen(rev_start);
-#endif
}
/* We've definitely found something. */
@@ -947,37 +835,28 @@ void findnextfile_wrap_reset(void)
}
/* Abort the current filename search. Clean up by setting the current
- * shortcut list to the browser shortcut list, displaying it, and
- * decompiling the compiled regular expression we used in the last
- * search, if any. */
+ * shortcut list to the browser shortcut list, and displaying it. */
void filesearch_abort(void)
{
currmenu = MBROWSER;
bottombars(MBROWSER);
-#ifdef HAVE_REGEX_H
- regexp_cleanup();
-#endif
}
/* Search for a filename. */
void do_filesearch(void)
{
size_t begin = selected;
- int i;
bool didfind;
- i = filesearch_init();
- if (i == -1) /* Cancel, blank search string, or regcomp()
- * failed. */
- filesearch_abort();
-#if !defined(NANO_TINY) || defined(HAVE_REGEX_H)
- else if (i == 1) /* Case Sensitive, Backwards, or Regexp search
- * toggle. */
- do_filesearch();
-#endif
+ UNSET(CASE_SENSITIVE);
+ UNSET(USE_REGEXP);
+ UNSET(BACKWARDS_SEARCH);
- if (i != 0)
+ if (filesearch_init() != 0) {
+ /* Cancelled or a blank search string. */
+ filesearch_abort();
return;
+ }
/* If answer is now "", copy last_search into answer. */
if (*answer == '\0')
@@ -985,7 +864,7 @@ void do_filesearch(void)
else
last_search = mallocstrcpy(last_search, answer);
-#ifndef NANO_TINY
+#ifndef DISABLE_HISTORIES
/* If answer is not "", add this search string to the search history
* list. */
if (answer[0] != '\0')
@@ -1018,12 +897,6 @@ void do_fileresearch(void)
search_init_globals();
if (last_search[0] != '\0') {
-#ifdef HAVE_REGEX_H
- /* Since answer is "", use last_search! */
- if (ISSET(USE_REGEXP) && !regexp_init(last_search))
- return;
-#endif
-
findnextfile_wrap_reset();
didfind = findnextfile(FALSE, begin, answer);
@@ -1070,7 +943,7 @@ char *striponedir(const char *path)
tmp = strrchr(retval, '/');
if (tmp != NULL)
- null_at(&retval, tmp - retval);
+ null_at(&retval, tmp - retval);
return retval;
}
diff --git a/src/chars.c b/src/chars.c
index 7d56117..088d612 100644
--- a/src/chars.c
+++ b/src/chars.c
@@ -1,9 +1,9 @@
-/* $Id: chars.c 4453 2009-12-02 03:36:22Z astyanax $ */
+/* $Id: chars.c 5147 2015-03-22 11:20:02Z bens $ */
/**************************************************************************
* chars.c *
* *
- * Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 *
- * Free Software Foundation, Inc. *
+ * Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, *
+ * 2010, 2011, 2013, 2014 Free Software Foundation, Inc. *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 3, or (at your option) *
@@ -54,7 +54,19 @@ bool using_utf8(void)
{
return use_utf8;
}
-#endif
+#endif /* ENABLE_UTF8 */
+
+/* Concatenate two allocated strings. */
+char* addstrings(char* str1, size_t len1, char* str2, size_t len2)
+{
+ str1 = charealloc(str1, len1 + len2 + 1);
+ str1[len1] = '\0';
+ strncat(&str1[len1], str2, len2);
+ free(str2);
+
+ return str1;
+}
+
#ifndef HAVE_ISBLANK
/* This function is equivalent to isblank(). */
@@ -79,12 +91,12 @@ bool is_byte(int c)
return ((unsigned int)c == (unsigned char)c);
}
-static void mbtowc_reset(void)
+void mbtowc_reset(void)
{
IGNORE_CALL_RESULT(mbtowc(NULL, NULL, 0));
}
-static void wctomb_reset(void)
+void wctomb_reset(void)
{
IGNORE_CALL_RESULT(wctomb(NULL, 0));
}
@@ -184,9 +196,8 @@ bool is_punct_mbchar(const char *c)
#ifdef ENABLE_UTF8
if (use_utf8) {
wchar_t wc;
- int c_mb_len = mbtowc(&wc, c, MB_CUR_MAX);
- if (c_mb_len < 0) {
+ if (mbtowc(&wc, c, MB_CUR_MAX) < 0) {
mbtowc_reset();
wc = bad_wchar;
}
@@ -473,22 +484,24 @@ int parse_mbchar(const char *buf, char *chr, size_t *col)
* before the one at pos. */
size_t move_mbleft(const char *buf, size_t pos)
{
- size_t pos_prev = pos;
+ size_t before, char_len = 0;
assert(buf != NULL && pos <= strlen(buf));
/* There is no library function to move backward one multibyte
- * character. Here is the naive, O(pos) way to do it. */
- while (TRUE) {
- int buf_mb_len = parse_mbchar(buf + pos - pos_prev, NULL, NULL);
-
- if (pos_prev <= buf_mb_len)
- break;
+ * character. So we just start groping for one at the farthest
+ * possible point. */
+ if (mb_cur_max() > pos)
+ before = 0;
+ else
+ before = pos - mb_cur_max();
- pos_prev -= buf_mb_len;
+ while (before < pos) {
+ char_len = parse_mbchar(buf + before, NULL, NULL);
+ before += char_len;
}
- return pos - pos_prev;
+ return before - char_len;
}
/* Return the index in buf of the beginning of the multibyte character
@@ -630,7 +643,7 @@ char *mbstrcasestr(const char *haystack, const char *needle)
return NULL;
} else
#endif
- return strcasestr(haystack, needle);
+ return (char *) strcasestr(haystack, needle);
}
#if !defined(NANO_TINY) || !defined(DISABLE_TABCOMP)
@@ -788,9 +801,8 @@ char *mbstrchr(const char *s, const char *c)
char *s_mb = charalloc(MB_CUR_MAX);
const char *q = s;
wchar_t ws, wc;
- int c_mb_len = mbtowc(&wc, c, MB_CUR_MAX);
- if (c_mb_len < 0) {
+ if (mbtowc(&wc, c, MB_CUR_MAX) < 0) {
mbtowc_reset();
wc = (unsigned char)*c;
bad_c_mb = TRUE;
@@ -820,7 +832,7 @@ char *mbstrchr(const char *s, const char *c)
return (char *)q;
} else
#endif
- return strchr(s, *c);
+ return (char *) strchr(s, *c);
}
#endif /* !NANO_TINY || !DISABLE_JUSTIFY */
@@ -840,7 +852,7 @@ char *mbstrpbrk(const char *s, const char *accept)
return NULL;
} else
#endif
- return strpbrk(s, accept);
+ return (char *) strpbrk(s, accept);
}
/* This function is equivalent to strpbrk(), except in that it scans the
@@ -893,7 +905,7 @@ char *mbrevstrpbrk(const char *s, const char *accept, const char
}
#endif /* !NANO_TINY */
-#if defined(ENABLE_NANORC) && (!defined(NANO_TINY) || !defined(DISABLE_JUSTIFY))
+#if !defined(DISABLE_NANORC) && (!defined(NANO_TINY) || !defined(DISABLE_JUSTIFY))
/* Return TRUE if the string s contains one or more blank characters,
* and FALSE otherwise. */
bool has_blank_chars(const char *s)
@@ -935,7 +947,7 @@ bool has_blank_mbchars(const char *s)
#endif
return has_blank_chars(s);
}
-#endif /* ENABLE_NANORC && (!NANO_TINY || !DISABLE_JUSTIFY) */
+#endif /* !DISABLE_NANORC && (!NANO_TINY || !DISABLE_JUSTIFY) */
#ifdef ENABLE_UTF8
/* Return TRUE if wc is valid Unicode, and FALSE otherwise. */
@@ -947,7 +959,7 @@ bool is_valid_unicode(wchar_t wc)
}
#endif
-#ifdef ENABLE_NANORC
+#ifndef DISABLE_NANORC
/* Check if the string s is a valid multibyte string. Return TRUE if it
* is, and FALSE otherwise. */
bool is_valid_mbstring(const char *s)
@@ -960,4 +972,4 @@ bool is_valid_mbstring(const char *s)
#endif
TRUE;
}
-#endif /* ENABLE_NANORC */
+#endif /* !DISABLE_NANORC */
diff --git a/src/color.c b/src/color.c
index 9d7ecff..13e2995 100644
--- a/src/color.c
+++ b/src/color.c
@@ -1,9 +1,9 @@
-/* $Id: color.c 4453 2009-12-02 03:36:22Z astyanax $ */
+/* $Id: color.c 5038 2014-06-30 17:49:53Z bens $ */
/**************************************************************************
* color.c *
* *
- * Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 *
- * Free Software Foundation, Inc. *
+ * Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, *
+ * 2010, 2011, 2013, 2014 Free Software Foundation, Inc. *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 3, or (at your option) *
@@ -25,18 +25,59 @@
#include <stdio.h>
#include <string.h>
+#include <errno.h>
-#ifdef ENABLE_COLOR
+#ifdef HAVE_MAGIC_H
+#include <magic.h>
+#endif
+
+#ifndef DISABLE_COLOR
/* For each syntax list entry, go through the list of colors and assign
* the color pairs. */
void set_colorpairs(void)
{
const syntaxtype *this_syntax = syntaxes;
+ bool defok = FALSE;
+ short fg, bg;
+ size_t i;
+
+ start_color();
+
+#ifdef HAVE_USE_DEFAULT_COLORS
+ /* Use the default colors, if available. */
+ defok = (use_default_colors() != ERR);
+#endif
+
+ for (i = 0; i < NUMBER_OF_ELEMENTS; i++) {
+ bool bright = FALSE;
+
+ if (parse_color_names(specified_color_combo[i], &fg, &bg, &bright)) {
+ if (fg == -1 && !defok)
+ fg = COLOR_WHITE;
+ if (bg == -1 && !defok)
+ bg = COLOR_BLACK;
+ init_pair(i + 1, fg, bg);
+ interface_color_pair[i].bright = bright;
+ interface_color_pair[i].pairnum = COLOR_PAIR(i + 1);
+ }
+ else {
+ interface_color_pair[i].bright = FALSE;
+ if (i != FUNCTION_TAG)
+ interface_color_pair[i].pairnum = hilite_attribute;
+ else
+ interface_color_pair[i].pairnum = A_NORMAL;
+ }
+
+ if (specified_color_combo[i] != NULL) {
+ free(specified_color_combo[i]);
+ specified_color_combo[i] = NULL;
+ }
+ }
for (; this_syntax != NULL; this_syntax = this_syntax->next) {
colortype *this_color = this_syntax->color;
- int color_pair = 1;
+ int clr_pair = NUMBER_OF_ELEMENTS + 1;
for (; this_color != NULL; this_color = this_color->next) {
const colortype *beforenow = this_syntax->color;
@@ -51,8 +92,8 @@ void set_colorpairs(void)
if (beforenow != this_color)
this_color->pairnum = beforenow->pairnum;
else {
- this_color->pairnum = color_pair;
- color_pair++;
+ this_color->pairnum = clr_pair;
+ clr_pair++;
}
}
}
@@ -66,14 +107,8 @@ void color_init(void)
if (has_colors()) {
const colortype *tmpcolor;
#ifdef HAVE_USE_DEFAULT_COLORS
- bool defok;
-#endif
-
- start_color();
-
-#ifdef HAVE_USE_DEFAULT_COLORS
/* Use the default colors, if available. */
- defok = (use_default_colors() != ERR);
+ bool defok = (use_default_colors() != ERR);
#endif
for (tmpcolor = openfile->colorstrings; tmpcolor != NULL;
@@ -102,18 +137,33 @@ void color_init(void)
}
}
+/* Clean up a regex we previously compiled. */
+void nfreeregex(regex_t **r)
+{
+ assert(r != NULL);
+
+ regfree(*r);
+ free(*r);
+ *r = NULL;
+}
+
/* Update the color information based on the current filename. */
void color_update(void)
{
syntaxtype *tmpsyntax;
syntaxtype *defsyntax = NULL;
colortype *tmpcolor, *defcolor = NULL;
+ regexlisttype *e;
assert(openfile != NULL);
openfile->syntax = NULL;
openfile->colorstrings = NULL;
+ /* If the rcfiles were not read, or contained no syntaxes, get out. */
+ if (syntaxes == NULL)
+ return;
+
/* If we specified a syntax override string, use it. */
if (syntaxstr != NULL) {
/* If the syntax override is "none", it's the same as not having
@@ -135,11 +185,10 @@ void color_update(void)
/* If we didn't specify a syntax override string, or if we did and
* there was no syntax by that name, get the syntax based on the
- * file extension, and then look in the header. */
+ * file extension, then try the headerline, and then try magic. */
if (openfile->colorstrings == NULL) {
for (tmpsyntax = syntaxes; tmpsyntax != NULL;
tmpsyntax = tmpsyntax->next) {
- exttype *e;
/* If this is the default syntax, it has no associated
* extensions, which we've checked for elsewhere. Skip over
@@ -161,75 +210,117 @@ void color_update(void)
regcomp(e->ext, fixbounds(e->ext_regex), REG_EXTENDED);
}
- /* Set colorstrings if we matched the extension
- * regex. */
- if (regexec(e->ext, openfile->filename, 0, NULL,
- 0) == 0) {
+ /* Set colorstrings if we match the extension regex. */
+ if (regexec(e->ext, openfile->filename, 0, NULL, 0) == 0) {
openfile->syntax = tmpsyntax;
openfile->colorstrings = tmpsyntax->color;
- }
-
- if (openfile->colorstrings != NULL)
break;
+ }
/* Decompile e->ext_regex's specified regex if we aren't
* going to use it. */
- if (not_compiled) {
- regfree(e->ext);
- free(e->ext);
- e->ext = NULL;
- }
+ if (not_compiled)
+ nfreeregex(&e->ext);
}
}
- /* If we haven't matched anything yet, try the headers */
+ /* Check the headerline if the extension didn't match anything. */
if (openfile->colorstrings == NULL) {
#ifdef DEBUG
- fprintf(stderr, "No match for file extensions, looking at headers...\n");
+ fprintf(stderr, "No result from file extension, trying headerline...\n");
#endif
for (tmpsyntax = syntaxes; tmpsyntax != NULL;
tmpsyntax = tmpsyntax->next) {
- exttype *e;
for (e = tmpsyntax->headers; e != NULL; e = e->next) {
bool not_compiled = (e->ext == NULL);
- /* e->ext_regex has already been checked for validity
- * elsewhere. Compile its specified regex if we haven't
- * already. */
if (not_compiled) {
e->ext = (regex_t *)nmalloc(sizeof(regex_t));
regcomp(e->ext, fixbounds(e->ext_regex), REG_EXTENDED);
}
-
- /* Set colorstrings if we matched the extension
- * regex. */
#ifdef DEBUG
- fprintf(stderr, "Comparing header regex \"%s\" to fileage \"%s\"...\n", e->ext_regex, openfile->fileage->data);
+ fprintf(stderr, "Comparing header regex \"%s\" to fileage \"%s\"...\n",
+ e->ext_regex, openfile->fileage->data);
#endif
+ /* Set colorstrings if we match the header-line regex. */
if (regexec(e->ext, openfile->fileage->data, 0, NULL, 0) == 0) {
openfile->syntax = tmpsyntax;
openfile->colorstrings = tmpsyntax->color;
+ break;
}
- if (openfile->colorstrings != NULL)
- break;
+ if (not_compiled)
+ nfreeregex(&e->ext);
+ }
+ }
+ }
+
+#ifdef HAVE_LIBMAGIC
+ /* Check magic if we don't have an answer yet. */
+ if (openfile->colorstrings == NULL) {
+ struct stat fileinfo;
+ magic_t cookie = NULL;
+ const char *magicstring = NULL;
+#ifdef DEBUG
+ fprintf(stderr, "No result from headerline either, trying libmagic...\n");
+#endif
+ if (stat(openfile->filename, &fileinfo) == 0) {
+ /* Open the magic database and get a diagnosis of the file. */
+ cookie = magic_open(MAGIC_SYMLINK |
+#ifdef DEBUG
+ MAGIC_DEBUG | MAGIC_CHECK |
+#endif
+ MAGIC_ERROR);
+ if (cookie == NULL || magic_load(cookie, NULL) < 0)
+ statusbar(_("magic_load() failed: %s"), strerror(errno));
+ else {
+ magicstring = magic_file(cookie, openfile->filename);
+ if (magicstring == NULL) {
+ statusbar(_("magic_file(%s) failed: %s"),
+ openfile->filename, magic_error(cookie));
+ }
+#ifdef DEBUG
+ fprintf(stderr, "Returned magic string is: %s\n", magicstring);
+#endif
+ }
+ }
+
+ /* Now try and find a syntax that matches the magicstring. */
+ for (tmpsyntax = syntaxes; tmpsyntax != NULL;
+ tmpsyntax = tmpsyntax->next) {
+
+ for (e = tmpsyntax->magics; e != NULL; e = e->next) {
+ bool not_compiled = (e->ext == NULL);
- /* Decompile e->ext_regex's specified regex if we aren't
- * going to use it. */
if (not_compiled) {
- regfree(e->ext);
- free(e->ext);
- e->ext = NULL;
+ e->ext = (regex_t *)nmalloc(sizeof(regex_t));
+ regcomp(e->ext, fixbounds(e->ext_regex), REG_EXTENDED);
}
+#ifdef DEBUG
+ fprintf(stderr, "Matching regex \"%s\" against \"%s\"\n", e->ext_regex, magicstring);
+#endif
+ /* Set colorstrings if we match the magic-string regex. */
+ if (magicstring && regexec(e->ext, magicstring, 0, NULL, 0) == 0) {
+ openfile->syntax = tmpsyntax;
+ openfile->colorstrings = tmpsyntax->color;
+ break;
+ }
+
+ if (not_compiled)
+ nfreeregex(&e->ext);
}
+ if (openfile->syntax != NULL)
+ break;
}
+ if (stat(openfile->filename, &fileinfo) == 0)
+ magic_close(cookie);
}
+#endif /* HAVE_LIBMAGIC */
}
-
- /* If we didn't get a syntax based on the file extension, and we
- * have a default syntax, use it. */
+ /* If we didn't find any syntax yet, and we do have a default one,
+ * use it. */
if (openfile->colorstrings == NULL && defcolor != NULL) {
openfile->syntax = defsyntax;
openfile->colorstrings = defcolor;
@@ -255,7 +346,7 @@ void color_update(void)
}
/* Reset the multicolor info cache for records for any lines which need
- to be recalculated */
+ * to be recalculated. */
void reset_multis_after(filestruct *fileptr, int mindex)
{
filestruct *oof;
@@ -301,11 +392,10 @@ void reset_multis_before(filestruct *fileptr, int mindex)
else
break;
}
-
edit_refresh_needed = TRUE;
}
-/* Reset one multiline regex info */
+/* Reset one multiline regex info. */
void reset_multis_for_id(filestruct *fileptr, int num)
{
reset_multis_before(fileptr, num);
@@ -313,9 +403,9 @@ void reset_multis_for_id(filestruct *fileptr, int num)
fileptr->multidata[num] = -1;
}
-/* Reset multi line strings around a filestruct ptr, trying to be smart about stopping
- force = reset everything regardless, useful when we don't know how much screen state
- has changed */
+/* Reset multi-line strings around a filestruct ptr, trying to be smart
+ * about stopping. Bool force means: reset everything regardless, useful
+ * when we don't know how much screen state has changed. */
void reset_multis(filestruct *fileptr, bool force)
{
int nobegin, noend;
@@ -327,7 +417,7 @@ void reset_multis(filestruct *fileptr, bool force)
for (; tmpcolor != NULL; tmpcolor = tmpcolor->next) {
- /* If it's not a multi-line regex, amscray */
+ /* If it's not a multi-line regex, amscray. */
if (tmpcolor->end == NULL)
continue;
@@ -338,10 +428,10 @@ void reset_multis(filestruct *fileptr, bool force)
}
/* Figure out where the first begin and end are to determine if
- things changed drastically for the precalculated multi values */
- nobegin = regexec(tmpcolor->start, fileptr->data, 1, &startmatch, 0);
- noend = regexec(tmpcolor->end, fileptr->data, 1, &endmatch, 0);
- if (fileptr->multidata[tmpcolor->id] == CWHOLELINE) {
+ * things changed drastically for the precalculated multi values. */
+ nobegin = regexec(tmpcolor->start, fileptr->data, 1, &startmatch, 0);
+ noend = regexec(tmpcolor->end, fileptr->data, 1, &endmatch, 0);
+ if (fileptr->multidata[tmpcolor->id] == CWHOLELINE) {
if (nobegin && noend)
continue;
} else if (fileptr->multidata[tmpcolor->id] == CNONE) {
@@ -353,8 +443,9 @@ void reset_multis(filestruct *fileptr, bool force)
continue;
}
- /* If we got here assume the worst */
+ /* If we got here, assume the worst. */
reset_multis_for_id(fileptr, tmpcolor->id);
}
}
-#endif /* ENABLE_COLOR */
+
+#endif /* !DISABLE_COLOR */
diff --git a/src/cut.c b/src/cut.c
index 8c21c8e..46a339c 100644
--- a/src/cut.c
+++ b/src/cut.c
@@ -1,9 +1,9 @@
-/* $Id: cut.c 4453 2009-12-02 03:36:22Z astyanax $ */
+/* $Id: cut.c 5112 2015-02-03 22:49:57Z astyanax $ */
/**************************************************************************
* cut.c *
* *
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
- * 2008, 2009 Free Software Foundation, Inc. *
+ * 2008, 2009, 2010, 2011, 2013, 2014 Free Software Foundation, Inc. *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 3, or (at your option) *
@@ -37,6 +37,12 @@ void cutbuffer_reset(void)
keep_cutbuffer = FALSE;
}
+/* Return the status of cutbuffer preservation. */
+inline bool keeping_cutbuffer(void)
+{
+ return keep_cutbuffer;
+}
+
/* If we aren't on the last line of the file, move all the text of the
* current line, plus the newline at the end, into the cutbuffer. If we
* are, move all of the text of the current line into the cutbuffer. In
@@ -44,6 +50,11 @@ void cutbuffer_reset(void)
* current line. */
void cut_line(void)
{
+#ifndef NANO_TINY
+ if (!openfile->mark_begin)
+ openfile->mark_begin = openfile->current;
+#endif
+
if (openfile->current != openfile->filebot)
move_to_filestruct(&cutbuffer, &cutbottom, openfile->current, 0,
openfile->current->next, 0);
@@ -109,11 +120,11 @@ void cut_to_eof(void)
/* Move text from the current filestruct into the cutbuffer. If
* copy_text is TRUE, copy the text back into the filestruct afterward.
- * If cut_till_end is TRUE, move all text from the current cursor
+ * If cut_till_eof is TRUE, move all text from the current cursor
* position to the end of the file into the cutbuffer. */
void do_cut_text(
#ifndef NANO_TINY
- bool copy_text, bool cut_till_end, bool undoing
+ bool copy_text, bool cut_till_eof, bool undoing
#else
void
#endif
@@ -125,7 +136,7 @@ void do_cut_text(
* it. */
size_t cb_save_len = 0;
/* The length of the string at the current end of the cutbuffer,
- * before we add text to it. */
+ * before we add text to it. */
bool old_no_newlines = ISSET(NO_NEWLINES);
#endif
@@ -162,9 +173,8 @@ void do_cut_text(
keep_cutbuffer = TRUE;
#ifndef NANO_TINY
-
- if (cut_till_end) {
- /* If cut_till_end is TRUE, move all text up to the end of the
+ if (cut_till_eof) {
+ /* If cut_till_eof is TRUE, move all text up to the end of the
* file into the cutbuffer. */
cut_to_eof();
} else if (openfile->mark_set) {
@@ -190,10 +200,10 @@ void do_cut_text(
if (cutbuffer != NULL) {
if (cb_save != NULL) {
cb_save->data += cb_save_len;
- copy_from_filestruct(cb_save, cutbottom);
+ copy_from_filestruct(cb_save);
cb_save->data -= cb_save_len;
} else
- copy_from_filestruct(cutbuffer, cutbottom);
+ copy_from_filestruct(cutbuffer);
/* Set the current place we want to where the text from the
* cutbuffer ends. */
@@ -205,16 +215,18 @@ void do_cut_text(
if (!old_no_newlines)
UNSET(NO_NEWLINES);
} else if (!undoing)
- update_undo(CUT);
-#endif
- /* Leave the text in the cutbuffer, and mark the file as
- * modified. */
+ update_undo(cut_till_eof ? CUT_EOF : CUT);
+
+ /* Leave the text in the cutbuffer, and mark the file as
+ * modified. */
+ if (!copy_text)
+#endif /* !NANO_TINY */
set_modified();
/* Update the screen. */
edit_refresh_needed = TRUE;
-#ifdef ENABLE_COLOR
+#ifndef DISABLE_COLOR
reset_multis(openfile->current, FALSE);
#endif
@@ -238,18 +250,26 @@ void do_cut_text_void(void)
#ifndef NANO_TINY
/* Move text from the current filestruct into the cutbuffer, and copy it
- * back into the filestruct afterward. */
+ * back into the filestruct afterward. If the mark is set or the cursor
+ * was moved, blow away previous contents of the cutbuffer. */
void do_copy_text(void)
{
+ static struct filestruct *next_contiguous_line = NULL;
+ bool mark_set = openfile->mark_set;
+
+ if (mark_set || openfile->current != next_contiguous_line)
+ cutbuffer_reset();
+
do_cut_text(TRUE, FALSE, FALSE);
+
+ /* If the mark was set, blow away the cutbuffer on the next copy. */
+ next_contiguous_line = (mark_set ? NULL : openfile->current);
}
/* Cut from the current cursor position to the end of the file. */
-void do_cut_till_end(void)
+void do_cut_till_eof(void)
{
-#ifndef NANO_TINY
- add_undo(CUT);
-#endif
+ add_undo(CUT_EOF);
do_cut_text(FALSE, TRUE, FALSE);
}
#endif /* !NANO_TINY */
@@ -264,12 +284,16 @@ void do_uncut_text(void)
return;
#ifndef NANO_TINY
- update_undo(UNCUT);
+ add_undo(PASTE);
#endif
/* Add a copy of the text in the cutbuffer to the current filestruct
* at the current cursor position. */
- copy_from_filestruct(cutbuffer, cutbottom);
+ copy_from_filestruct(cutbuffer);
+
+#ifndef NANO_TINY
+ update_undo(PASTE);
+#endif
/* Set the current place we want to where the text from the
* cutbuffer ends. */
@@ -281,7 +305,7 @@ void do_uncut_text(void)
/* Update the screen. */
edit_refresh_needed = TRUE;
-#ifdef ENABLE_COLOR
+#ifndef DISABLE_COLOR
reset_multis(openfile->current, FALSE);
#endif
diff --git a/src/files.c b/src/files.c
index c5b9d6a..bd07597 100644
--- a/src/files.c
+++ b/src/files.c
@@ -1,9 +1,9 @@
-/* $Id: files.c 4520 2010-11-12 06:23:14Z astyanax $ */
+/* $Id: files.c 5118 2015-02-15 16:28:08Z bens $ */
/**************************************************************************
* files.c *
* *
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
- * 2008, 2009 Free Software Foundation, Inc. *
+ * 2008, 2009, 2010, 2011, 2013, 2014 Free Software Foundation, Inc. *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 3, or (at your option) *
@@ -31,6 +31,7 @@
#include <errno.h>
#include <ctype.h>
#include <pwd.h>
+#include <libgen.h>
/* Add an entry to the openfile openfilestruct. This should only be
* called from open_buffer(). */
@@ -46,6 +47,8 @@ void make_new_buffer(void)
} else {
splice_opennode(openfile, make_new_opennode(), openfile->next);
openfile = openfile->next;
+ /* More than one file open, show Close in help lines. */
+ exitfunc->desc = close_tag;
}
/* Initialize the new buffer. */
@@ -77,8 +80,9 @@ void initialize_buffer(void)
openfile->current_stat = NULL;
openfile->undotop = NULL;
openfile->current_undo = NULL;
+ openfile->lock_filename = NULL;
#endif
-#ifdef ENABLE_COLOR
+#ifndef DISABLE_COLOR
openfile->colorstrings = NULL;
#endif
}
@@ -96,19 +100,229 @@ void initialize_buffer_text(void)
openfile->edittop = openfile->fileage;
openfile->current = openfile->fileage;
-#ifdef ENABLE_COLOR
+#ifndef DISABLE_COLOR
openfile->fileage->multidata = NULL;
#endif
openfile->totsize = 0;
}
+#ifndef NANO_TINY
+/* Actually write the lockfile. This function will ALWAYS annihilate
+ * any previous version of the file. We'll borrow INSECURE_BACKUP here
+ * to decide about lockfile paranoia here as well...
+ *
+ * Args:
+ * lockfilename: file name for lock
+ * origfilename: name of the file the lock is for
+ * modified: whether to set the modified bit in the file
+ *
+ * Returns: 1 on success, 0 on failure (but continue loading), -1 on
+ * failure and abort. */
+int write_lockfile(const char *lockfilename, const char *origfilename, bool modified)
+{
+ int cflags, fd;
+ FILE *filestream;
+ pid_t mypid;
+ uid_t myuid;
+ struct passwd *mypwuid;
+ struct stat fileinfo;
+ char *lockdata = charalloc(1024);
+ char myhostname[32];
+ ssize_t lockdatalen = 1024;
+ ssize_t wroteamt;
+
+ /* Run things which might fail first before we try and blow away the
+ * old state. */
+ myuid = geteuid();
+ if ((mypwuid = getpwuid(myuid)) == NULL) {
+ statusbar(_("Couldn't determine my identity for lock file (getpwuid() failed)"));
+ return -1;
+ }
+ mypid = getpid();
+
+ if (gethostname(myhostname, 31) < 0) {
+ statusbar(_("Couldn't determine hostname for lock file: %s"), strerror(errno));
+ return -1;
+ }
+
+ /* Check if the lock exists before we try to delete it...*/
+ if (stat(lockfilename, &fileinfo) != -1)
+ if (delete_lockfile(lockfilename) < 0)
+ return -1;
+
+ if (ISSET(INSECURE_BACKUP))
+ cflags = O_WRONLY | O_CREAT | O_APPEND;
+ else
+ cflags = O_WRONLY | O_CREAT | O_EXCL | O_APPEND;
+
+ fd = open(lockfilename, cflags,
+ S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
+
+ /* Maybe we just don't have write access. Print an error message
+ and continue. */
+ if (fd < 0) {
+ statusbar(_("Error writing lock file %s: %s"), lockfilename,
+ strerror(errno));
+ return 0;
+ }
+
+ /* Now we've got a safe file stream. If the previous open() call
+ * failed, this will return NULL. */
+ filestream = fdopen(fd, "wb");
+
+ if (fd < 0 || filestream == NULL) {
+ statusbar(_("Error writing lock file %s: %s"), lockfilename,
+ strerror(errno));
+ return -1;
+ }
+
+ /* Okay, so at the moment we're following this state for how to
+ * store the lock data:
+ *
+ * byte 0 - 0x62
+ * byte 1 - 0x30
+ * bytes 2-12 - program name which created the lock
+ * bytes 24,25 - little endian store of creator program's PID
+ * (b24 = 256^0 column, b25 = 256^1 column)
+ * bytes 28-44 - username of who created the lock
+ * bytes 68-100 - hostname of where the lock was created
+ * bytes 108-876 - filename the lock is for
+ * byte 1007 - 0x55 if file is modified
+ *
+ * Looks like VIM also stores undo state in this file, so we're
+ * gonna have to figure out how to slap a 'OMG don't use recover on
+ * our lockfile' message in here...
+ *
+ * This is likely very wrong, so this is a WIP. */
+ memset(lockdata, 0, lockdatalen);
+ lockdata[0] = 0x62;
+ lockdata[1] = 0x30;
+ lockdata[24] = mypid % 256;
+ lockdata[25] = mypid / 256;
+ snprintf(&lockdata[2], 11, "nano %s", VERSION);
+ strncpy(&lockdata[28], mypwuid->pw_name, 16);
+ strncpy(&lockdata[68], myhostname, 31);
+ strncpy(&lockdata[108], origfilename, 768);
+ if (modified == TRUE)
+ lockdata[1007] = 0x55;
+
+ wroteamt = fwrite(lockdata, sizeof(char), lockdatalen, filestream);
+ if (wroteamt < lockdatalen) {
+ statusbar(_("Error writing lock file %s: %s"),
+ lockfilename, ferror(filestream));
+ return -1;
+ }
+
+#ifdef DEBUG
+ fprintf(stderr, "In write_lockfile(), write successful (wrote %lu bytes)\n", (unsigned long)wroteamt);
+#endif
+
+ if (fclose(filestream) == EOF) {
+ statusbar(_("Error writing lock file %s: %s"),
+ lockfilename, strerror(errno));
+ return -1;
+ }
+
+ openfile->lock_filename = lockfilename;
+
+ return 1;
+}
+
+/* Less exciting, delete the lockfile. Return -1 if unsuccessful and
+ * complain on the statusbar, 1 otherwise. */
+int delete_lockfile(const char *lockfilename)
+{
+ if (unlink(lockfilename) < 0 && errno != ENOENT) {
+ statusbar(_("Error deleting lock file %s: %s"), lockfilename,
+ strerror(errno));
+ return -1;
+ }
+ return 1;
+}
+
+/* Deal with lockfiles. Return -1 on refusing to override the lockfile,
+ * and 1 on successfully creating it; 0 means we were not successful in
+ * creating the lockfile but we should continue to load the file and
+ * complain to the user. */
+int do_lockfile(const char *filename)
+{
+ char *lockdir = dirname((char *) mallocstrcpy(NULL, filename));
+ char *lockbase = basename((char *) mallocstrcpy(NULL, filename));
+ size_t lockfilesize = strlen(filename) + strlen(locking_prefix)
+ + strlen(locking_suffix) + 3;
+ char *lockfilename = charalloc(lockfilesize);
+ char *lockfiledir = NULL;
+ static char lockprog[11], lockuser[17];
+ struct stat fileinfo;
+ int lockfd, lockpid;
+
+ snprintf(lockfilename, lockfilesize, "%s/%s%s%s", lockdir,
+ locking_prefix, lockbase, locking_suffix);
+#ifdef DEBUG
+ fprintf(stderr, "lock file name is %s\n", lockfilename);
+#endif
+ if (stat(lockfilename, &fileinfo) != -1) {
+ ssize_t readtot = 0;
+ ssize_t readamt = 0;
+ char *lockbuf = charalloc(8192);
+ char *promptstr = charalloc(128);
+ int ans;
+ if ((lockfd = open(lockfilename, O_RDONLY)) < 0) {
+ statusbar(_("Error opening lock file %s: %s"),
+ lockfilename, strerror(errno));
+ return -1;
+ }
+ do {
+ readamt = read(lockfd, &lockbuf[readtot], BUFSIZ);
+ readtot += readamt;
+ } while (readtot < 8192 && readamt > 0);
+
+ if (readtot < 48) {
+ statusbar(_("Error reading lock file %s: Not enough data read"),
+ lockfilename);
+ return -1;
+ }
+ strncpy(lockprog, &lockbuf[2], 10);
+ lockpid = (unsigned char)lockbuf[25] * 256 + (unsigned char)lockbuf[24];
+ strncpy(lockuser, &lockbuf[28], 16);
+#ifdef DEBUG
+ fprintf(stderr, "lockpid = %d\n", lockpid);
+ fprintf(stderr, "program name which created this lock file should be %s\n",
+ lockprog);
+ fprintf(stderr, "user which created this lock file should be %s\n",
+ lockuser);
+#endif
+ /* TRANSLATORS: The second %s is the name of the user, the third that of the editor. */
+ sprintf(promptstr, _("File %s is being edited (by %s with %s, PID %d); continue?"),
+ filename, lockuser, lockprog, lockpid);
+ ans = do_yesno_prompt(FALSE, promptstr);
+ if (ans < 1) {
+ blank_statusbar();
+ return -1;
+ }
+ } else {
+ lockfiledir = mallocstrcpy(NULL, lockfilename);
+ lockfiledir = dirname(lockfiledir);
+ if (stat(lockfiledir, &fileinfo) == -1) {
+ statusbar(_("Error writing lock file: Directory \'%s\' doesn't exist"),
+ lockfiledir);
+ return 0;
+ }
+ }
+
+
+ return write_lockfile(lockfilename, filename, FALSE);
+}
+#endif /* !NANO_TINY */
+
/* If it's not "", filename is a file to open. We make a new buffer, if
* necessary, and then open and read the file, if applicable. */
void open_buffer(const char *filename, bool undoable)
{
+ bool quiet = FALSE;
bool new_buffer = (openfile == NULL
-#ifdef ENABLE_MULTIBUFFER
+#ifndef DISABLE_MULTIBUFFER
|| ISSET(MULTIBUFFER)
#endif
);
@@ -128,16 +342,34 @@ void open_buffer(const char *filename, bool undoable)
}
#endif
- /* If the filename isn't blank, open the file. Otherwise, treat it
- * as a new file. */
- rc = (filename[0] != '\0') ? open_file(filename, new_buffer, &f) :
- -2;
-
/* If we're loading into a new buffer, add a new entry to
* openfile. */
- if (new_buffer)
+ if (new_buffer) {
make_new_buffer();
+#ifndef NANO_TINY
+ if (ISSET(LOCKING) && filename[0] != '\0') {
+ int lockstatus = do_lockfile(filename);
+ if (lockstatus < 0) {
+#ifndef DISABLE_MULTIBUFFER
+ if (openfile->next) {
+ close_buffer(TRUE);
+ return;
+ }
+#endif
+ } else if (lockstatus == 0) {
+ quiet = TRUE;
+ }
+ }
+#endif
+ }
+
+
+ /* If the filename isn't blank, and we are not in NOREAD_MODE,
+ * open the file. Otherwise, treat it as a new file. */
+ rc = (filename[0] != '\0' && !ISSET(NOREAD_MODE)) ?
+ open_file(filename, new_buffer, quiet, &f) : -2;
+
/* If we have a file, and we're loading into a new buffer, update
* the filename. */
if (rc != -1 && new_buffer)
@@ -164,7 +396,7 @@ void open_buffer(const char *filename, bool undoable)
openfile->placewewant = 0;
}
-#ifdef ENABLE_COLOR
+#ifndef DISABLE_COLOR
/* If we're loading into a new buffer, update the colors to account
* for it, if applicable. */
if (new_buffer)
@@ -188,7 +420,7 @@ void replace_buffer(const char *filename)
/* If the filename isn't blank, open the file. Otherwise, treat it
* as a new file. */
- rc = (filename[0] != '\0') ? open_file(filename, TRUE, &f) : -2;
+ rc = (filename[0] != '\0') ? open_file(filename, TRUE, FALSE, &f) : -2;
/* Reinitialize the text of the current buffer. */
free_filestruct(openfile->fileage);
@@ -211,7 +443,7 @@ void display_buffer(void)
/* Update the titlebar, since the filename may have changed. */
titlebar(NULL);
-#ifdef ENABLE_COLOR
+#ifndef DISABLE_COLOR
/* Make sure we're using the buffer's associated colors, if
* applicable. */
color_init();
@@ -221,17 +453,18 @@ void display_buffer(void)
edit_refresh();
}
-#ifdef ENABLE_MULTIBUFFER
+#ifndef DISABLE_MULTIBUFFER
/* Switch to the next file buffer if next_buf is TRUE. Otherwise,
* switch to the previous file buffer. */
-void switch_to_prevnext_buffer(bool next_buf)
+void switch_to_prevnext_buffer(bool next_buf, bool quiet)
{
assert(openfile != NULL);
/* If only one file buffer is open, indicate it on the statusbar and
* get out. */
if (openfile == openfile->next) {
- statusbar(_("No more open file buffers"));
+ if (quiet == FALSE)
+ statusbar(_("No more open file buffers"));
return;
}
@@ -247,31 +480,35 @@ void switch_to_prevnext_buffer(bool next_buf)
display_buffer();
/* Indicate the switch on the statusbar. */
- statusbar(_("Switched to %s"),
- ((openfile->filename[0] == '\0') ? _("New Buffer") :
- openfile->filename));
+ if (quiet == FALSE)
+ statusbar(_("Switched to %s"),
+ ((openfile->filename[0] == '\0') ? _("New Buffer") :
+ openfile->filename));
#ifdef DEBUG
dump_filestruct(openfile->current);
#endif
+ display_main_list();
}
/* Switch to the previous entry in the openfile filebuffer. */
void switch_to_prev_buffer_void(void)
{
- switch_to_prevnext_buffer(FALSE);
+ switch_to_prevnext_buffer(FALSE, FALSE);
}
/* Switch to the next entry in the openfile filebuffer. */
void switch_to_next_buffer_void(void)
{
- switch_to_prevnext_buffer(TRUE);
+ switch_to_prevnext_buffer(TRUE, FALSE);
}
/* Delete an entry from the openfile filebuffer, and switch to the one
* after it. Return TRUE on success, or FALSE if there are no more open
- * file buffers. */
-bool close_buffer(void)
+ * file buffers.
+ * quiet - should we print messages switching bufers
+ */
+bool close_buffer(bool quiet)
{
assert(openfile != NULL);
@@ -279,24 +516,29 @@ bool close_buffer(void)
if (openfile == openfile->next)
return FALSE;
+#ifndef DISABLE_HISTORIES
+ update_poshistory(openfile->filename, openfile->current->lineno, xplustabs() + 1);
+#endif
+
/* Switch to the next file buffer. */
- switch_to_next_buffer_void();
+ switch_to_prevnext_buffer(TRUE, quiet);
/* Close the file buffer we had open before. */
unlink_opennode(openfile->prev);
- display_main_list();
+ /* If only one buffer is open now, show Exit in the help lines. */
+ if (openfile == openfile->next)
+ exitfunc->desc = exit_tag;
return TRUE;
}
-#endif /* ENABLE_MULTIBUFFER */
+#endif /* !DISABLE_MULTIBUFFER */
-/* A bit of a copy and paste from open_file(), is_file_writable()
- * just checks whether the file is appendable as a quick
- * permissions check, and we tend to err on the side of permissiveness
- * (reporting TRUE when it might be wrong) to not fluster users
- * editing on odd filesystems by printing incorrect warnings.
- */
+/* A bit of a copy and paste from open_file(), is_file_writable() just
+ * checks whether the file is appendable as a quick permissions check,
+ * and we tend to err on the side of permissiveness (reporting TRUE when
+ * it might be wrong) to not fluster users editing on odd filesystems by
+ * printing incorrect warnings. */
int is_file_writable(const char *filename)
{
struct stat fileinfo, fileinfo2;
@@ -305,7 +547,6 @@ int is_file_writable(const char *filename)
char *full_filename;
bool ans = TRUE;
-
if (ISSET(VIEW_MODE))
return TRUE;
@@ -315,7 +556,7 @@ int is_file_writable(const char *filename)
full_filename = get_full_path(filename);
/* Okay, if we can't stat the path due to a component's
- permissions, just try the relative one */
+ permissions, just try the relative one. */
if (full_filename == NULL
|| (stat(full_filename, &fileinfo) == -1 && stat(filename, &fileinfo2) != -1))
full_filename = mallocstrcpy(NULL, filename);
@@ -356,7 +597,7 @@ filestruct *read_line(char *buf, filestruct *prevnode, bool
fileptr->data[buf_len - 1] = '\0';
#endif
-#ifdef ENABLE_COLOR
+#ifndef DISABLE_COLOR
fileptr->multidata = NULL;
#endif
@@ -389,9 +630,9 @@ filestruct *read_line(char *buf, filestruct *prevnode, bool
/* Read an open file into the current buffer. f should be set to the
* open file, and filename should be set to the name of the file.
- * undoable means do we want to create undo records to try and undo this.
- * Will also attempt to check file writability if fd > 0 and checkwritable == TRUE
- */
+ * undoable means do we want to create undo records to try and undo
+ * this. Will also attempt to check file writability if fd > 0 and
+ * checkwritable == TRUE. */
void read_file(FILE *f, int fd, const char *filename, bool undoable, bool checkwritable)
{
size_t num_lines = 0;
@@ -674,9 +915,9 @@ void read_file(FILE *f, int fd, const char *filename, bool undoable, bool checkw
* found".
*
* Return -2 if we say "New File", -1 if the file isn't opened, and the
- * fd opened otherwise. The file might still have an error while reading
+ * fd opened otherwise. The file might still have an error while reading
* with a 0 return value. *f is set to the opened file. */
-int open_file(const char *filename, bool newfie, FILE **f)
+int open_file(const char *filename, bool newfie, bool quiet, FILE **f)
{
struct stat fileinfo, fileinfo2;
int fd;
@@ -688,22 +929,25 @@ int open_file(const char *filename, bool newfie, FILE **f)
full_filename = get_full_path(filename);
/* Okay, if we can't stat the path due to a component's
- permissions, just try the relative one */
- if (full_filename == NULL
+ permissions, just try the relative one. */
+ if (full_filename == NULL
|| (stat(full_filename, &fileinfo) == -1 && stat(filename, &fileinfo2) != -1))
full_filename = mallocstrcpy(NULL, filename);
+
if (stat(full_filename, &fileinfo) == -1) {
- /* Well, maybe we can open the file even if the OS
- says its not there */
+ /* Well, maybe we can open the file even if the OS says it's
+ * not there. */
if ((fd = open(filename, O_RDONLY)) != -1) {
- statusbar(_("Reading File"));
+ if (!quiet)
+ statusbar(_("Reading File"));
free(full_filename);
return 0;
}
if (newfie) {
- statusbar(_("New File"));
+ if (!quiet)
+ statusbar(_("New File"));
return -2;
}
statusbar(_("\"%s\" not found"), filename);
@@ -722,7 +966,7 @@ int open_file(const char *filename, bool newfie, FILE **f)
statusbar(_("Error reading %s: %s"), filename,
strerror(errno));
beep();
- return -1;
+ return -1;
} else {
/* The file is A-OK. Open it. */
*f = fdopen(fd, "rb");
@@ -800,8 +1044,7 @@ void do_insertfile(
filestruct *edittop_save = openfile->edittop;
size_t current_x_save = openfile->current_x;
ssize_t current_y_save = openfile->current_y;
- bool edittop_inside = FALSE, meta_key = FALSE, func_key = FALSE;
- const sc *s;
+ bool edittop_inside = FALSE;
#ifndef NANO_TINY
bool right_side_up = FALSE, single_line = FALSE;
#endif
@@ -812,22 +1055,21 @@ void do_insertfile(
#ifndef NANO_TINY
if (execute) {
msg =
-#ifdef ENABLE_MULTIBUFFER
+#ifndef DISABLE_MULTIBUFFER
ISSET(MULTIBUFFER) ?
_("Command to execute in new buffer [from %s] ") :
#endif
_("Command to execute [from %s] ");
- } else {
-#endif
+ } else
+#endif /* NANO_TINY */
+ {
msg =
-#ifdef ENABLE_MULTIBUFFER
+#ifndef DISABLE_MULTIBUFFER
ISSET(MULTIBUFFER) ?
_("File to insert into new buffer [from %s] ") :
#endif
_("File to insert [from %s] ");
-#ifndef NANO_TINY
}
-#endif
i = do_prompt(TRUE,
#ifndef DISABLE_TABCOMP
@@ -837,8 +1079,7 @@ void do_insertfile(
execute ? MEXTCMD :
#endif
MINSERTFILE, ans,
- &meta_key, &func_key,
-#ifndef NANO_TINY
+#ifndef DISABLE_HISTORIES
NULL,
#endif
edit_refresh, msg,
@@ -853,7 +1094,7 @@ void do_insertfile(
* filename or command begins with a newline (i.e. an encoded
* null), treat it as though it's blank. */
if (i == -1 || ((i == -2 || *answer == '\n')
-#ifdef ENABLE_MULTIBUFFER
+#ifndef DISABLE_MULTIBUFFER
&& !ISSET(MULTIBUFFER)
#endif
)) {
@@ -861,32 +1102,29 @@ void do_insertfile(
break;
} else {
size_t pww_save = openfile->placewewant;
+ functionptrtype func = func_from_key(&i);
ans = mallocstrcpy(ans, answer);
- s = get_shortcut(currmenu, &i, &meta_key, &func_key);
-
#ifndef NANO_TINY
-#ifdef ENABLE_MULTIBUFFER
-
- if (s && s->scfunc == NEW_BUFFER_MSG) {
+#ifndef DISABLE_MULTIBUFFER
+ if (func == new_buffer_void) {
/* Don't allow toggling if we're in view mode. */
if (!ISSET(VIEW_MODE))
TOGGLE(MULTIBUFFER);
+ else
+ beep();
continue;
- } else
+ }
#endif
- if (s && s->scfunc == EXT_CMD_MSG) {
+ if (func == flip_execute_void) {
execute = !execute;
continue;
}
-#ifndef DISABLE_BROWSER
- else
-#endif
#endif /* !NANO_TINY */
#ifndef DISABLE_BROWSER
- if (s && s->scfunc == TO_FILES_MSG) {
+ if (func == to_files_void) {
char *tmp = do_browse_from(answer);
if (tmp == NULL)
@@ -903,28 +1141,28 @@ void do_insertfile(
/* If we don't have a file yet, go back to the statusbar
* prompt. */
if (i != 0
-#ifdef ENABLE_MULTIBUFFER
+#ifndef DISABLE_MULTIBUFFER
&& (i != -2 || !ISSET(MULTIBUFFER))
#endif
)
continue;
#ifndef NANO_TINY
- /* Keep track of whether the mark begins inside the
- * partition and will need adjustment. */
- if (openfile->mark_set) {
- filestruct *top, *bot;
- size_t top_x, bot_x;
+ /* Keep track of whether the mark begins inside the
+ * partition and will need adjustment. */
+ if (openfile->mark_set) {
+ filestruct *top, *bot;
+ size_t top_x, bot_x;
- mark_order((const filestruct **)&top, &top_x,
+ mark_order((const filestruct **)&top, &top_x,
(const filestruct **)&bot, &bot_x,
&right_side_up);
- single_line = (top == bot);
- }
+ single_line = (top == bot);
+ }
#endif
-#ifdef ENABLE_MULTIBUFFER
+#ifndef DISABLE_MULTIBUFFER
if (!ISSET(MULTIBUFFER)) {
#endif
/* If we're not inserting into a new buffer, partition
@@ -937,7 +1175,7 @@ void do_insertfile(
openfile->current_x);
edittop_inside =
(openfile->edittop == openfile->fileage);
-#ifdef ENABLE_MULTIBUFFER
+#ifndef DISABLE_MULTIBUFFER
}
#endif
@@ -948,7 +1186,7 @@ void do_insertfile(
#ifndef NANO_TINY
if (execute) {
-#ifdef ENABLE_MULTIBUFFER
+#ifndef DISABLE_MULTIBUFFER
if (ISSET(MULTIBUFFER))
/* Open a blank buffer. */
open_buffer("", FALSE);
@@ -957,7 +1195,7 @@ void do_insertfile(
/* Save the command's output in the current buffer. */
execute_command(answer);
-#ifdef ENABLE_MULTIBUFFER
+#ifndef DISABLE_MULTIBUFFER
if (ISSET(MULTIBUFFER)) {
/* Move back to the beginning of the first line of
* the buffer. */
@@ -980,12 +1218,20 @@ void do_insertfile(
}
#endif
-#ifdef ENABLE_MULTIBUFFER
- if (ISSET(MULTIBUFFER))
+#if !defined(DISABLE_MULTIBUFFER) && !defined(DISABLE_HISTORIES)
+ if (ISSET(MULTIBUFFER)) {
/* Update the screen to account for the current
* buffer. */
display_buffer();
- else
+
+ ssize_t savedposline, savedposcol;
+ if (ISSET(POS_HISTORY) &&
+#ifndef NANO_TINY
+ !execute &&
+#endif
+ check_poshistory(answer, &savedposline, &savedposcol))
+ do_gotolinecolumn(savedposline, savedposcol, FALSE, FALSE, FALSE, FALSE);
+ } else
#endif
{
filestruct *top_save = openfile->fileage;
@@ -1056,8 +1302,6 @@ void do_insertfile(
break;
}
}
- shortcut_init(FALSE);
-
free(ans);
}
@@ -1066,13 +1310,12 @@ void do_insertfile(
* allow inserting a file into a new buffer. */
void do_insertfile_void(void)
{
-
if (ISSET(RESTRICTED)) {
- nano_disabled_msg();
+ nano_disabled_msg();
return;
}
-#ifdef ENABLE_MULTIBUFFER
+#ifndef DISABLE_MULTIBUFFER
if (ISSET(VIEW_MODE) && !ISSET(MULTIBUFFER))
statusbar(_("Key invalid in non-multibuffer mode"));
else
@@ -1100,7 +1343,7 @@ char *get_full_path(const char *origpath)
bool path_only;
if (origpath == NULL)
- return NULL;
+ return NULL;
/* Get the current directory. If it doesn't exist, back up and try
* again until we get a directory that does, and use that as the
@@ -1366,6 +1609,22 @@ bool check_operating_dir(const char *currpath, bool allow_tabcomp)
#endif
#ifndef NANO_TINY
+/* Although this sucks, it sucks less than having a single 'my system is
+ * messed up and I'm blanket allowing insecure file writing operations'. */
+int prompt_failed_backupwrite(const char *filename)
+{
+ static int i;
+ static char *prevfile = NULL; /* What was the last file we were
+ * passed so we don't keep asking
+ * this? Though maybe we should... */
+ if (prevfile == NULL || strcmp(filename, prevfile)) {
+ i = do_yesno_prompt(FALSE,
+ _("Failed to write backup file, continue saving? (Say N if unsure) "));
+ prevfile = mallocstrcpy(prevfile, filename);
+ }
+ return i;
+}
+
void init_backup_dir(void)
{
char *full_backup_dir;
@@ -1387,7 +1646,7 @@ void init_backup_dir(void)
backup_dir = full_backup_dir;
}
}
-#endif
+#endif /* !NANO_TINY */
/* Read from inn, write to out. We assume inn is opened for reading,
* and out for writing. We return 0 on success, -1 on read error, or -2
@@ -1447,12 +1706,14 @@ bool write_file(const char *name, FILE *f_open, bool tmp, append_type
/* The file descriptor we use. */
mode_t original_umask = 0;
/* Our umask, from when nano started. */
+#ifndef NANO_TINY
bool realexists;
/* The result of stat(). TRUE if the file exists, FALSE
* otherwise. If name is a link that points nowhere, realexists
* is FALSE. */
struct stat st;
/* The status fields filled in by stat(). */
+#endif
bool anyexists;
/* The result of lstat(). The same as realexists, unless name
* is a link. */
@@ -1464,7 +1725,6 @@ bool write_file(const char *name, FILE *f_open, bool tmp, append_type
/* The actual file, realname, we are writing to. */
char *tempname = NULL;
/* The temp file name we write to on prepend. */
- int backup_cflags;
assert(name != NULL);
@@ -1502,17 +1762,18 @@ bool write_file(const char *name, FILE *f_open, bool tmp, append_type
goto cleanup_and_exit;
}
- /* Save the state of the file at the end of the symlink (if there is
- * one). */
+#ifndef NANO_TINY
+ /* Check whether the file (at the end of the symlink) exists. */
realexists = (stat(realname, &st) != -1);
-#ifndef NANO_TINY
- /* if we have not stat()d this file before (say, the user just
- * specified it interactively), stat and save the value
- * or else we will chase null pointers when we do
- * modtime checks, preserve file times, etc. during backup */
- if (openfile->current_stat == NULL && !tmp && realexists)
+ /* If we haven't stat()d this file before (say, the user just
+ * specified it interactively), stat and save the value now,
+ * or else we will chase null pointers when we do modtime checks,
+ * preserve file times, and so on, during backup. */
+ if (openfile->current_stat == NULL && !tmp && realexists) {
+ openfile->current_stat = (struct stat *)nmalloc(sizeof(struct stat));
stat(realname, openfile->current_stat);
+ }
/* We backup only if the backup toggle is set, the file isn't
* temporary, and the file already exists. Furthermore, if we
@@ -1527,6 +1788,7 @@ bool write_file(const char *name, FILE *f_open, bool tmp, append_type
char *backupname;
struct utimbuf filetime;
int copy_status;
+ int backup_cflags;
/* Save the original file's access and modification times. */
filetime.actime = openfile->current_stat->st_atime;
@@ -1582,10 +1844,11 @@ bool write_file(const char *name, FILE *f_open, bool tmp, append_type
_("Too many backup files?"));
free(backuptemp);
free(backupname);
- /* If we can't write to the backup, DONT go on, since
- whatever caused the backup file to fail (e.g. disk
- full may well cause the real file write to fail, which
- means we could lose both the backup and the original! */
+ /* If we can't write to the backup, DON'T go on, since
+ * whatever caused the backup file to fail (e.g. disk
+ * full may well cause the real file write to fail,
+ * which means we could lose both the backup and the
+ * original! */
goto cleanup_and_exit;
} else {
free(backupname);
@@ -1597,9 +1860,11 @@ bool write_file(const char *name, FILE *f_open, bool tmp, append_type
}
/* First, unlink any existing backups. Next, open the backup
- file with O_CREAT and O_EXCL. If it succeeds, we
- have a file descriptor to a new backup file. */
+ * file with O_CREAT and O_EXCL. If it succeeds, we have a file
+ * descriptor to a new backup file. */
if (unlink(backupname) < 0 && errno != ENOENT && !ISSET(INSECURE_BACKUP)) {
+ if (prompt_failed_backupwrite(backupname))
+ goto skip_backup;
statusbar(_("Error writing backup file %s: %s"), backupname,
strerror(errno));
free(backupname);
@@ -1608,13 +1873,13 @@ bool write_file(const char *name, FILE *f_open, bool tmp, append_type
if (ISSET(INSECURE_BACKUP))
backup_cflags = O_WRONLY | O_CREAT | O_APPEND;
- else
+ else
backup_cflags = O_WRONLY | O_CREAT | O_EXCL | O_APPEND;
backup_fd = open(backupname, backup_cflags,
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
/* Now we've got a safe file stream. If the previous open()
- call failed, this will return NULL. */
+ * call failed, this will return NULL. */
backup_file = fdopen(backup_fd, "wb");
if (backup_fd < 0 || backup_file == NULL) {
@@ -1624,11 +1889,13 @@ bool write_file(const char *name, FILE *f_open, bool tmp, append_type
goto cleanup_and_exit;
}
- /* We shouldn't worry about chown()ing something if we're not
- root, since it's likely to fail! */
+ /* We shouldn't worry about chown()ing something if we're not
+ * root, since it's likely to fail! */
if (geteuid() == NANO_ROOT_UID && fchown(backup_fd,
openfile->current_stat->st_uid, openfile->current_stat->st_gid) == -1
- && !ISSET(INSECURE_BACKUP)) {
+ && !ISSET(INSECURE_BACKUP)) {
+ if (prompt_failed_backupwrite(backupname))
+ goto skip_backup;
statusbar(_("Error writing backup file %s: %s"), backupname,
strerror(errno));
free(backupname);
@@ -1636,7 +1903,10 @@ bool write_file(const char *name, FILE *f_open, bool tmp, append_type
goto cleanup_and_exit;
}
- if (fchmod(backup_fd, openfile->current_stat->st_mode) == -1 && !ISSET(INSECURE_BACKUP)) {
+ if (fchmod(backup_fd, openfile->current_stat->st_mode) == -1
+ && !ISSET(INSECURE_BACKUP)) {
+ if (prompt_failed_backupwrite(backupname))
+ goto skip_backup;
statusbar(_("Error writing backup file %s: %s"), backupname,
strerror(errno));
free(backupname);
@@ -1664,12 +1934,14 @@ bool write_file(const char *name, FILE *f_open, bool tmp, append_type
/* And set its metadata. */
if (utime(backupname, &filetime) == -1 && !ISSET(INSECURE_BACKUP)) {
+ if (prompt_failed_backupwrite(backupname))
+ goto skip_backup;
statusbar(_("Error writing backup file %s: %s"), backupname,
strerror(errno));
- /* If we can't write to the backup, DONT go on, since
- whatever caused the backup file to fail (e.g. disk
- full may well cause the real file write to fail, which
- means we could lose both the backup and the original! */
+ /* If we can't write to the backup, DON'T go on, since
+ * whatever caused the backup file to fail (e.g. disk full
+ * may well cause the real file write to fail, which means
+ * we could lose both the backup and the original! */
goto cleanup_and_exit;
}
@@ -1874,7 +2146,7 @@ bool write_file(const char *name, FILE *f_open, bool tmp, append_type
if (!nonamechange) {
openfile->filename = mallocstrcpy(openfile->filename,
realname);
-#ifdef ENABLE_COLOR
+#ifndef DISABLE_COLOR
/* We might have changed the filename, so update the colors
* to account for it, and then make sure we're using
* them. */
@@ -1894,7 +2166,8 @@ bool write_file(const char *name, FILE *f_open, bool tmp, append_type
if (openfile->current_stat == NULL)
openfile->current_stat =
(struct stat *)nmalloc(sizeof(struct stat));
- stat(realname, openfile->current_stat);
+ if (!openfile->mark_set)
+ stat(realname, openfile->current_stat);
#endif
statusbar(P_("Wrote %lu line", "Wrote %lu lines",
@@ -1960,23 +2233,24 @@ bool write_marked_file(const char *name, FILE *f_open, bool tmp,
return retval;
}
+
#endif /* !NANO_TINY */
/* Write the current file to disk. If the mark is on, write the current
* marked selection to disk. If exiting is TRUE, write the file to disk
* regardless of whether the mark is on, and without prompting if the
- * TEMP_FILE flag is set. Return TRUE on success or FALSE on error. */
+ * TEMP_FILE flag is set and the current file has a name. Return TRUE
+ * on success or FALSE on error. */
bool do_writeout(bool exiting)
{
int i;
append_type append = OVERWRITE;
char *ans;
/* The last answer the user typed at the statusbar prompt. */
-#ifdef NANO_EXTRA
+#ifndef DISABLE_EXTRA
static bool did_credits = FALSE;
#endif
- bool retval = FALSE, meta_key = FALSE, func_key = FALSE;
- const sc *s;
+ bool retval = FALSE;
currmenu = MWRITEFILE;
@@ -2030,8 +2304,7 @@ bool do_writeout(bool exiting)
TRUE,
#endif
MWRITEFILE, ans,
- &meta_key, &func_key,
-#ifndef NANO_TINY
+#ifndef DISABLE_HISTORIES
NULL,
#endif
edit_refresh, "%s%s%s", msg,
@@ -2049,11 +2322,12 @@ bool do_writeout(bool exiting)
retval = FALSE;
break;
} else {
+ functionptrtype func = func_from_key(&i);
+
ans = mallocstrcpy(ans, answer);
- s = get_shortcut(currmenu, &i, &meta_key, &func_key);
#ifndef DISABLE_BROWSER
- if (s && s->scfunc == TO_FILES_MSG) {
+ if (func == to_files_void) {
char *tmp = do_browse_from(answer);
if (tmp == NULL)
@@ -2065,26 +2339,26 @@ bool do_writeout(bool exiting)
} else
#endif /* !DISABLE_BROWSER */
#ifndef NANO_TINY
- if (s && s->scfunc == DOS_FORMAT_MSG) {
+ if (func == dos_format_void) {
openfile->fmt = (openfile->fmt == DOS_FILE) ? NIX_FILE :
DOS_FILE;
continue;
- } else if (s && s->scfunc == MAC_FORMAT_MSG) {
+ } else if (func == mac_format_void) {
openfile->fmt = (openfile->fmt == MAC_FILE) ? NIX_FILE :
MAC_FILE;
continue;
- } else if (s && s->scfunc == BACKUP_FILE_MSG) {
+ } else if (func == backup_file_void) {
TOGGLE(BACKUP_FILE);
continue;
} else
#endif /* !NANO_TINY */
- if (s && s->scfunc == PREPEND_MSG) {
+ if (func == prepend_void) {
append = (append == PREPEND) ? OVERWRITE : PREPEND;
continue;
- } else if (s && s->scfunc == APPEND_MSG) {
+ } else if (func == append_void) {
append = (append == APPEND) ? OVERWRITE : APPEND;
continue;
- } else if (s && s->scfunc == DO_HELP_VOID) {
+ } else if (func == do_help_void) {
continue;
}
@@ -2092,7 +2366,7 @@ bool do_writeout(bool exiting)
fprintf(stderr, "filename is %s\n", answer);
#endif
-#ifdef NANO_EXTRA
+#ifndef DISABLE_EXTRA
/* If the current file has been modified, we've pressed
* Ctrl-X at the edit window to exit, we've pressed "y" at
* the "Save modified buffer" prompt to save, we've entered
@@ -2165,10 +2439,13 @@ bool do_writeout(bool exiting)
}
}
#ifndef NANO_TINY
- /* Complain if the file exists, the name hasn't changed, and the
- stat information we had before does not match what we have now */
- else if (name_exists && openfile->current_stat && (openfile->current_stat->st_mtime < st.st_mtime ||
- openfile->current_stat->st_dev != st.st_dev || openfile->current_stat->st_ino != st.st_ino)) {
+ /* Complain if the file exists, the name hasn't changed,
+ * and the stat information we had before does not match
+ * what we have now. */
+ else if (name_exists && openfile->current_stat &&
+ (openfile->current_stat->st_mtime < st.st_mtime ||
+ openfile->current_stat->st_dev != st.st_dev ||
+ openfile->current_stat->st_ino != st.st_ino)) {
i = do_yesno_prompt(FALSE,
_("File was modified since you opened it, continue saving ? "));
if (i == 0 || i == -1)
@@ -2275,7 +2552,7 @@ int diralphasort(const void *va, const void *vb)
/* Standard function brain damage: We should be sorting
* alphabetically and case-insensitively according to the current
* locale, but there's no standard strcasecoll() function, so we
- * have to use multibyte strcasecmp() instead, */
+ * have to use multibyte strcasecmp() instead. */
return mbstrcasecmp(a, b);
}
@@ -2372,9 +2649,6 @@ char **cwd_tab_completion(const char *buf, bool allow_files, size_t
*num_matches, size_t buf_len)
{
char *dirname = mallocstrcpy(NULL, buf), *filename;
-#ifndef DISABLE_OPERATINGDIR
- size_t dirnamelen;
-#endif
size_t filenamelen;
char **matches = NULL;
DIR *dir;
@@ -2413,9 +2687,6 @@ char **cwd_tab_completion(const char *buf, bool allow_files, size_t
return NULL;
}
-#ifndef DISABLE_OPERATINGDIR
- dirnamelen = strlen(dirname);
-#endif
filenamelen = strlen(filename);
while ((nextdir = readdir(dir)) != NULL) {
@@ -2656,29 +2927,96 @@ const char *tail(const char *foo)
return tmp;
}
-#if !defined(NANO_TINY) && defined(ENABLE_NANORC)
-/* Return $HOME/.nano_history, or NULL if we can't find the home
+#ifndef DISABLE_HISTORIES
+/* Return the constructed dirfile path, or NULL if we can't find the home
* directory. The string is dynamically allocated, and should be
* freed. */
-char *histfilename(void)
+char *construct_filename(const char *str)
{
- char *nanohist = NULL;
+ char *newstr = NULL;
if (homedir != NULL) {
size_t homelen = strlen(homedir);
- nanohist = charalloc(homelen + 15);
- strcpy(nanohist, homedir);
- strcpy(nanohist + homelen, "/.nano_history");
+ newstr = charalloc(homelen + strlen(str) + 1);
+ strcpy(newstr, homedir);
+ strcpy(newstr + homelen, str);
}
- return nanohist;
+ return newstr;
+}
+
+char *histfilename(void)
+{
+ return construct_filename("/.nano/search_history");
+}
+
+/* Construct the legacy history filename.
+ * (Deprecate in 2.5, delete later.) */
+char *legacyhistfilename(void)
+{
+ return construct_filename("/.nano_history");
+}
+
+char *poshistfilename(void)
+{
+ return construct_filename("/.nano/filepos_history");
}
-/* Load histories from ~/.nano_history. */
+void history_error(const char *msg, ...)
+{
+ va_list ap;
+
+ va_start(ap, msg);
+ vfprintf(stderr, _(msg), ap);
+ va_end(ap);
+
+ fprintf(stderr, _("\nPress Enter to continue\n"));
+ while (getchar() != '\n')
+ ;
+}
+
+/* Now that we have more than one history file, let's just rely on a
+ * .nano dir for this stuff. Return 1 if the dir exists or was
+ * successfully created, and return 0 otherwise. */
+int check_dotnano(void)
+{
+ struct stat dirstat;
+ char *nanodir = construct_filename("/.nano");
+
+ if (stat(nanodir, &dirstat) == -1) {
+ if (mkdir(nanodir, S_IRWXU | S_IRWXG | S_IRWXO) == -1) {
+ history_error(N_("Unable to create directory %s: %s\n"
+ "It is required for saving/loading search history or cursor positions.\n"),
+ nanodir, strerror(errno));
+ return 0;
+ }
+ } else if (!S_ISDIR(dirstat.st_mode)) {
+ history_error(N_("Path %s is not a directory and needs to be.\n"
+ "Nano will be unable to load or save search history or cursor positions.\n"),
+ nanodir);
+ return 0;
+ }
+ return 1;
+}
+
+/* Load the search and replace histories from ~/.nano/search_history. */
void load_history(void)
{
char *nanohist = histfilename();
+ char *legacyhist = legacyhistfilename();
+ struct stat hstat;
+
+ if (stat(legacyhist, &hstat) != -1 && stat(nanohist, &hstat) == -1) {
+ if (rename(legacyhist, nanohist) == -1)
+ history_error(N_("Detected a legacy nano history file (%s) which I tried to move\n"
+ "to the preferred location (%s) but encountered an error: %s"),
+ legacyhist, nanohist, strerror(errno));
+ else
+ history_error(N_("Detected a legacy nano history file (%s) which I moved\n"
+ "to the preferred location (%s)\n(see the nano FAQ about this change)"),
+ legacyhist, nanohist);
+ }
/* Assume do_rcfile() has reported a missing home directory. */
if (nanohist != NULL) {
@@ -2688,12 +3026,8 @@ void load_history(void)
if (errno != ENOENT) {
/* Don't save history when we quit. */
UNSET(HISTORYLOG);
- rcfile_error(N_("Error reading %s: %s"), nanohist,
+ history_error(N_("Error reading %s: %s"), nanohist,
strerror(errno));
- fprintf(stderr,
- _("\nPress Enter to continue starting nano.\n"));
- while (getchar() != '\n')
- ;
}
} else {
/* Load a history list (first the search history, then the
@@ -2718,8 +3052,11 @@ void load_history(void)
fclose(hist);
free(line);
+ if (search_history->prev != NULL)
+ last_search = mallocstrcpy(NULL, search_history->prev->data);
}
free(nanohist);
+ free(legacyhist);
}
}
@@ -2745,7 +3082,7 @@ bool writehist(FILE *hist, filestruct *h)
return TRUE;
}
-/* Save histories to ~/.nano_history. */
+/* Save the search and replace histories to ~/.nano/search_history. */
void save_history(void)
{
char *nanohist;
@@ -2761,7 +3098,7 @@ void save_history(void)
FILE *hist = fopen(nanohist, "wb");
if (hist == NULL)
- rcfile_error(N_("Error writing %s: %s"), nanohist,
+ history_error(N_("Error writing %s: %s"), nanohist,
strerror(errno));
else {
/* Make sure no one else can read from or write to the
@@ -2770,7 +3107,7 @@ void save_history(void)
if (!writehist(hist, searchage) || !writehist(hist,
replaceage))
- rcfile_error(N_("Error writing %s: %s"), nanohist,
+ history_error(N_("Error writing %s: %s"), nanohist,
strerror(errno));
fclose(hist);
@@ -2779,4 +3116,155 @@ void save_history(void)
free(nanohist);
}
}
-#endif /* !NANO_TINY && ENABLE_NANORC */
+
+/* Save the recorded last file positions to ~/.nano/filepos_history. */
+void save_poshistory(void)
+{
+ char *poshist;
+ char *statusstr = NULL;
+ poshiststruct *posptr;
+
+ poshist = poshistfilename();
+
+ if (poshist != NULL) {
+ FILE *hist = fopen(poshist, "wb");
+
+ if (hist == NULL)
+ history_error(N_("Error writing %s: %s"), poshist,
+ strerror(errno));
+ else {
+ /* Make sure no one else can read from or write to the
+ * history file. */
+ chmod(poshist, S_IRUSR | S_IWUSR);
+
+ for (posptr = poshistory; posptr != NULL; posptr = posptr->next) {
+ statusstr = charalloc(strlen(posptr->filename) + 2 * sizeof(ssize_t) + 4);
+ sprintf(statusstr, "%s %ld %ld\n", posptr->filename, (long)posptr->lineno,
+ (long)posptr->xno);
+ if (fwrite(statusstr, sizeof(char), strlen(statusstr), hist) < strlen(statusstr))
+ history_error(N_("Error writing %s: %s"), poshist,
+ strerror(errno));
+ free(statusstr);
+ }
+ fclose(hist);
+ }
+ free(poshist);
+ }
+}
+
+/* Update the recorded last file positions, given a filename, a line
+ * and a column. If no entry is found, add a new one at the end. */
+void update_poshistory(char *filename, ssize_t lineno, ssize_t xpos)
+{
+ poshiststruct *posptr, *posprev = NULL;
+ char *fullpath = get_full_path(filename);
+
+ if (fullpath == NULL)
+ return;
+
+ for (posptr = poshistory; posptr != NULL; posptr = posptr->next) {
+ if (!strcmp(posptr->filename, fullpath)) {
+ posptr->lineno = lineno;
+ posptr->xno = xpos;
+ return;
+ }
+ posprev = posptr;
+ }
+
+ /* Didn't find it, make a new node yo! */
+ posptr = (poshiststruct *)nmalloc(sizeof(poshiststruct));
+ posptr->filename = mallocstrcpy(NULL, fullpath);
+ posptr->lineno = lineno;
+ posptr->xno = xpos;
+ posptr->next = NULL;
+
+ if (!poshistory)
+ poshistory = posptr;
+ else
+ posprev->next = posptr;
+
+ free(fullpath);
+}
+
+/* Check the recorded last file positions to see if the given file
+ * matches an existing entry. If so, return 1 and set line and column
+ * to the retrieved values. Otherwise, return 0. */
+int check_poshistory(const char *file, ssize_t *line, ssize_t *column)
+{
+ poshiststruct *posptr;
+ char *fullpath = get_full_path(file);
+
+ if (fullpath == NULL)
+ return 0;
+
+ for (posptr = poshistory; posptr != NULL; posptr = posptr->next) {
+ if (!strcmp(posptr->filename, fullpath)) {
+ *line = posptr->lineno;
+ *column = posptr->xno;
+ free(fullpath);
+ return 1;
+ }
+ }
+ free(fullpath);
+ return 0;
+}
+
+/* Load the recorded file positions from ~/.nano/filepos_history. */
+void load_poshistory(void)
+{
+ char *nanohist = poshistfilename();
+
+ /* Assume do_rcfile() has reported a missing home directory. */
+ if (nanohist != NULL) {
+ FILE *hist = fopen(nanohist, "rb");
+
+ if (hist == NULL) {
+ if (errno != ENOENT) {
+ /* Don't save history when we quit. */
+ UNSET(POS_HISTORY);
+ history_error(N_("Error reading %s: %s"), nanohist,
+ strerror(errno));
+ }
+ } else {
+ char *line = NULL, *lineptr, *xptr;
+ size_t buf_len = 0;
+ ssize_t read, lineno, xno;
+ poshiststruct *posptr;
+
+ /* Read and parse each line, and put the data into the
+ * positions history structure. */
+ while ((read = getline(&line, &buf_len, hist)) >= 0) {
+ if (read > 0 && line[read - 1] == '\n') {
+ read--;
+ line[read] = '\0';
+ }
+ if (read > 0)
+ unsunder(line, read);
+ lineptr = parse_next_word(line);
+ xptr = parse_next_word(lineptr);
+ lineno = atoi(lineptr);
+ xno = atoi(xptr);
+ if (poshistory == NULL) {
+ poshistory = (poshiststruct *)nmalloc(sizeof(poshiststruct));
+ poshistory->filename = mallocstrcpy(NULL, line);
+ poshistory->lineno = lineno;
+ poshistory->xno = xno;
+ poshistory->next = NULL;
+ } else {
+ for (posptr = poshistory; posptr->next != NULL; posptr = posptr->next)
+ ;
+ posptr->next = (poshiststruct *)nmalloc(sizeof(poshiststruct));
+ posptr->next->filename = mallocstrcpy(NULL, line);
+ posptr->next->lineno = lineno;
+ posptr->next->xno = xno;
+ posptr->next->next = NULL;
+ }
+ }
+
+ fclose(hist);
+ free(line);
+ }
+ free(nanohist);
+ }
+}
+#endif /* !DISABLE_HISTORIES */
diff --git a/src/global.c b/src/global.c
index ae14a49..9e7fec8 100644
--- a/src/global.c
+++ b/src/global.c
@@ -1,9 +1,9 @@
-/* $Id: global.c 4520 2010-11-12 06:23:14Z astyanax $ */
+/* $Id: global.c 5143 2015-03-20 12:22:49Z bens $ */
/**************************************************************************
* global.c *
* *
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
- * 2008, 2009 Free Software Foundation, Inc. *
+ * 2008, 2009, 2010, 2011, 2013, 2014 Free Software Foundation, Inc. *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 3, or (at your option) *
@@ -38,6 +38,11 @@ bool jump_buf_main = FALSE;
* SIGWINCH? */
#endif
+bool meta_key;
+ /* Whether the current keystroke is a Meta key. */
+bool func_key;
+ /* Whether the current keystroke is an extended keypad value. */
+
#ifndef DISABLE_WRAPJUSTIFY
ssize_t fill = 0;
/* The column where we will wrap lines. */
@@ -67,7 +72,7 @@ WINDOW *bottomwin;
int editwinrows = 0;
/* How many rows does the edit window take up? */
int maxrows = 0;
- /* How many usable lines are there (due to soft wrapping) */
+ /* How many usable lines there are (due to soft wrapping). */
filestruct *cutbuffer = NULL;
/* The buffer where we store cut text. */
@@ -88,7 +93,7 @@ char *matchbrackets = NULL;
* searches. */
#endif
-#if !defined(NANO_TINY) && defined(ENABLE_NANORC)
+#if !defined(NANO_TINY) && !defined(DISABLE_NANORC)
char *whitespace = NULL;
/* The characters used when displaying the first characters of
* tabs and spaces. */
@@ -118,7 +123,7 @@ size_t quotelen;
#endif
bool nodelay_mode = FALSE;
- /* Are we in nodelay mode (checking for a cancel wile doing something */
+ /* Are we checking for a cancel wile doing something? */
char *answer = NULL;
/* The answer string used by the statusbar prompt. */
@@ -130,6 +135,11 @@ ssize_t tabsize = -1;
#ifndef NANO_TINY
char *backup_dir = NULL;
/* The directory where we store backup files. */
+
+const char *locking_prefix = ".";
+ /* Prefix of how to store the vim-style lock file. */
+const char *locking_suffix = ".swp";
+ /* Suffix of the vim-style lock file. */
#endif
#ifndef DISABLE_OPERATINGDIR
char *operating_dir = NULL;
@@ -144,29 +154,31 @@ char *alt_speller = NULL;
/* The command to use for the alternate spell checker. */
#endif
-#ifdef ENABLE_COLOR
+#ifndef DISABLE_COLOR
syntaxtype *syntaxes = NULL;
/* The global list of color syntaxes. */
char *syntaxstr = NULL;
/* The color syntax name specified on the command line. */
-
#endif
-bool edit_refresh_needed = NULL;
- /* Did a command mangle enough of the buffer refresh that we
- should repaint the screen */
+bool edit_refresh_needed = FALSE;
+ /* Did a command mangle enough of the buffer refresh that we
+ * should repaint the screen? */
-const shortcut *currshortcut;
- /* The current shortcut list we're using. */
int currmenu;
- /* The currently loaded menu */
-
+ /* The currently loaded menu. */
sc *sclist = NULL;
- /* New shortcut key struct */
+ /* Pointer to the start of the shortcuts list. */
subnfunc *allfuncs = NULL;
- /* New struct for the function list */
-
-#ifndef NANO_TINY
+ /* Pointer to the start of the functions list. */
+subnfunc *tailfunc;
+ /* Pointer to the last function in the list. */
+subnfunc *exitfunc;
+ /* Pointer to the special Exit/Close item. */
+subnfunc *uncutfunc;
+ /* Pointer to the special Uncut/Unjustify item. */
+
+#ifndef DISABLE_HISTORIES
filestruct *search_history = NULL;
/* The search string history list. */
filestruct *searchage = NULL;
@@ -179,6 +191,8 @@ filestruct *replaceage = NULL;
/* The top of the replace string history list. */
filestruct *replacebot = NULL;
/* The bottom of the replace string history list. */
+poshiststruct *poshistory;
+ /* The cursor position history list. */
#endif
/* Regular expressions. */
@@ -190,13 +204,19 @@ regmatch_t regmatches[10];
* maximum, used in regular expression searches. */
#endif
-int reverse_attr = A_REVERSE;
+int hilite_attribute = A_REVERSE;
/* The curses attribute we use for reverse video. */
+#ifndef DISABLE_COLOR
+char* specified_color_combo[] = {};
+ /* The color combinations as specified in the rcfile. */
+#endif
+color_pair interface_color_pair[] = {};
+ /* The processed color pairs for the interface elements. */
char *homedir = NULL;
/* The user's home directory, from $HOME or /etc/passwd. */
-/* Return the number of entries in the shortcut list s for a given menu. */
+/* Return the number of entries in the shortcut list for a given menu. */
size_t length_of_list(int menu)
{
subnfunc *f;
@@ -213,35 +233,70 @@ size_t length_of_list(int menu)
return i;
}
-/* Set type of function based on the string */
-function_type strtokeytype(const char *str)
+/* To make the functions and shortcuts lists clearer. */
+#define VIEW TRUE /* Is allowed in view mode. */
+#define NOVIEW FALSE
+#define BLANKAFTER TRUE /* A blank line after this one. */
+#define TOGETHER FALSE
+
+/* Just throw this here. */
+void case_sens_void(void)
+{
+}
+void regexp_void(void)
+{
+}
+void backwards_void(void)
+{
+}
+void gototext_void(void)
+{
+}
+#ifndef DISABLE_BROWSER
+void to_files_void(void)
+{
+}
+void goto_dir_void(void)
+{
+}
+#endif
+void dos_format_void(void)
+{
+}
+void mac_format_void(void)
+{
+}
+void append_void(void)
+{
+}
+void prepend_void(void)
+{
+}
+void backup_file_void(void)
+{
+}
+void new_buffer_void(void)
+{
+}
+void flip_replace_void(void)
+{
+}
+void flip_execute_void(void)
{
- if (str[0] == 'M' || str[0] == 'm')
- return META;
- else if (str[0] == '^')
- return CONTROL;
- else if (str[0] == 'F' || str[0] == 'F')
- return FKEY;
- else
- return RAW;
}
-/* Add a string to the new function list strict.
- Does not allow updates, yet anyway */
-void add_to_funcs(short func, int menus, const char *desc, const char *help,
+/* Add a function to the function list. */
+void add_to_funcs(void (*func)(void), int menus, const char *desc, const char *help,
bool blank_after, bool viewok)
{
- subnfunc *f;
+ subnfunc *f = (subnfunc *)nmalloc(sizeof(subnfunc));
+
+ if (allfuncs == NULL)
+ allfuncs = f;
+ else
+ tailfunc->next = f;
+ tailfunc = f;
- if (allfuncs == NULL) {
- allfuncs = (subnfunc *) nmalloc(sizeof(subnfunc));
- f = allfuncs;
- } else {
- for (f = allfuncs; f->next != NULL; f = f->next)
- ;
- f->next = (subnfunc *)nmalloc(sizeof(subnfunc));
- f = f->next;
- }
f->next = NULL;
f->scfunc = func;
f->menus = menus;
@@ -253,94 +308,104 @@ void add_to_funcs(short func, int menus, const char *desc, const char *help,
#endif
#ifdef DEBUG
- fprintf(stderr, "Added func \"%s\"", f->desc);
+ fprintf(stderr, "Added func %ld (%s) for menus %x\n", (long)func, f->desc, menus);
#endif
}
-const sc *first_sc_for(int menu, short func) {
- const sc *s;
- const sc *metasc = NULL;
+/* Add a key combo to the shortcut list. */
+void add_to_sclist(int menu, const char *scstring, void (*func)(void), int toggle)
+{
+ static sc *tailsc;
+ sc *s = (sc *)nmalloc(sizeof(sc));
- for (s = sclist; s != NULL; s = s->next) {
- if ((s->menu & menu) && s->scfunc == func) {
- /* try to use a meta sequence as a last resort. Otherwise
- we will run into problems when we try and handle things like
- the arrow keys, home, etc, if for some reason the user bound
- them to a meta sequence first *shrug* */
- if (s->type == META) {
- metasc = s;
- continue;
- } /* otherwise it was something else, use it */
- return s;
- }
- }
+ /* Start the list, or tack on the next item. */
+ if (sclist == NULL)
+ sclist = s;
+ else
+ tailsc->next = s;
+ tailsc = s;
+ s->next = NULL;
- /* If we're here we may have found only meta sequences, if so use one */
- if (metasc)
- return metasc;
+ /* Fill in the data. */
+ s->menu = menu;
+ s->scfunc = func;
+ s->toggle = toggle;
+ s->keystr = (char *) scstring;
+ s->type = strtokeytype(scstring);
+ assign_keyinfo(s);
#ifdef DEBUG
- fprintf(stderr, "Whoops, returning null given func %ld in menu %d\n", (long) func, menu);
+ fprintf(stderr, "Setting sequence to %d for shortcut \"%s\" in menu %x\n", s->seq, scstring, (int)s->menu);
#endif
- /* Otherwise... */
- return NULL;
}
-
-/* Add a string to the new shortcut list implementation
- Allows updates to existing entries in the list */
-void add_to_sclist(int menu, const char *scstring, short func, int toggle, int execute)
+/* Assign one function's shortcuts to another function. */
+void replace_scs_for(void (*oldfunc)(void), void (*newfunc)(void))
{
sc *s;
- if (sclist == NULL) {
- sclist = (sc *) nmalloc(sizeof(sc));
- s = sclist;
- s->next = NULL;
- } else {
- for (s = sclist; s->next != NULL; s = s->next)
- if (s->menu == menu && s->keystr == scstring)
- break;
+ for (s = sclist; s != NULL; s = s->next)
+ if (s->scfunc == oldfunc)
+ s->scfunc = newfunc;
+}
- if (s->menu != menu || s->keystr != scstring) { /* i.e. this is not a replace... */
-#ifdef DEBUG
- fprintf(stderr, "No match found...\n");
-#endif
- s->next = (sc *)nmalloc(sizeof(sc));
- s = s->next;
- s->next = NULL;
- }
- }
+/* Return the first shortcut in the list of shortcuts that
+ * matches the given func in the given menu. */
+const sc *first_sc_for(int menu, void (*func)(void))
+{
+ const sc *s;
- s->type = strtokeytype(scstring);
- s->menu = menu;
- s->toggle = toggle;
- s->keystr = (char *) scstring;
- s->scfunc = func;
- s->execute = execute;
- assign_keyinfo(s);
+ for (s = sclist; s != NULL; s = s->next)
+ if ((s->menu & menu) && s->scfunc == func)
+ return s;
#ifdef DEBUG
- fprintf(stderr, "list val = %d\n", (int) s->menu);
- fprintf(stderr, "Hey, set sequence to %d for shortcut \"%s\"\n", s->seq, scstring);
+ fprintf(stderr, "Whoops, returning null given func %ld in menu %x\n", (long)func, menu);
#endif
+ /* Otherwise... */
+ return NULL;
}
/* Return the given menu's first shortcut sequence, or the default value
- (2nd arg). Assumes currmenu for the menu to check*/
-int sc_seq_or (short func, int defaultval)
+ * (2nd arg). Assumes currmenu for the menu to check. */
+int sc_seq_or(void (*func)(void), int defaultval)
{
const sc *s = first_sc_for(currmenu, func);
- if (s)
+ if (s) {
+ meta_key = (s->type == META);
return s->seq;
+ }
/* else */
return defaultval;
+}
+/* Return a pointer to the function that is bound to the given key. */
+functionptrtype func_from_key(int *kbinput)
+{
+ const sc *s = get_shortcut(kbinput);
+
+ if (s)
+ return s->scfunc;
+ else
+ return NULL;
+}
+
+/* Return the type of command key based on the given string. */
+key_type strtokeytype(const char *str)
+{
+ if (str[0] == '^')
+ return CONTROL;
+ else if (str[0] == 'M')
+ return META;
+ else if (str[0] == 'F')
+ return FKEY;
+ else
+ return RAWINPUT;
}
-/* Assign the info to the shortcut struct
- Assumes keystr is already assigned, naturally */
+/* Assign the info to the shortcut struct.
+ * Assumes keystr is already assigned, naturally. */
void assign_keyinfo(sc *s)
{
if (s->type == CONTROL) {
@@ -352,163 +417,102 @@ void assign_keyinfo(sc *s)
} else if (s->type == FKEY) {
assert(strlen(s->keystr) > 1);
s->seq = KEY_F0 + atoi(&s->keystr[1]);
- } else /* raw */
+ } else /* RAWINPUT */
s->seq = (int) s->keystr[0];
- /* Override some keys which don't bind as nicely as we'd like */
+ /* Override some keys which don't bind as easily as we'd like. */
if (s->type == CONTROL && (!strcasecmp(&s->keystr[1], "space")))
s->seq = 0;
else if (s->type == META && (!strcasecmp(&s->keystr[2], "space")))
s->seq = (int) ' ';
- else if (s->type == RAW && (!strcasecmp(s->keystr, "kup")))
- s->seq = KEY_UP;
- else if (s->type == RAW && (!strcasecmp(s->keystr, "kdown")))
- s->seq = KEY_DOWN;
- else if (s->type == RAW && (!strcasecmp(s->keystr, "kleft")))
- s->seq = KEY_LEFT;
- else if (s->type == RAW && (!strcasecmp(s->keystr, "kright")))
- s->seq = KEY_RIGHT;
- else if (s->type == RAW && (!strcasecmp(s->keystr, "kinsert")))
- s->seq = KEY_IC;
- else if (s->type == RAW && (!strcasecmp(s->keystr, "kdel")))
- s->seq = KEY_DC;
- else if (s->type == RAW && (!strcasecmp(s->keystr, "kbsp")))
- s->seq = KEY_BACKSPACE;
- else if (s->type == RAW && (!strcasecmp(s->keystr, "kenter")))
- s->seq = KEY_ENTER;
- else if (s->type == RAW && (!strcasecmp(s->keystr, "kpup")))
- s->seq = KEY_PPAGE;
- else if (s->type == RAW && (!strcasecmp(s->keystr, "kpdown")))
- s->seq = KEY_NPAGE;
+ else if (s->type == RAWINPUT) {
+ if (!strcasecmp(s->keystr, "Up"))
+ s->seq = KEY_UP;
+ else if (!strcasecmp(s->keystr, "Down"))
+ s->seq = KEY_DOWN;
+ else if (!strcasecmp(s->keystr, "Left"))
+ s->seq = KEY_LEFT;
+ else if (!strcasecmp(s->keystr, "Right"))
+ s->seq = KEY_RIGHT;
+ else if (!strcasecmp(s->keystr, "Ins"))
+ s->seq = KEY_IC;
+ else if (!strcasecmp(s->keystr, "Del"))
+ s->seq = KEY_DC;
+ else if (!strcasecmp(s->keystr, "Bsp"))
+ s->seq = KEY_BACKSPACE;
+ else if (!strcasecmp(s->keystr, "Enter"))
+ s->seq = KEY_ENTER;
+ else if (!strcasecmp(s->keystr, "PgUp"))
+ s->seq = KEY_PPAGE;
+ else if (!strcasecmp(s->keystr, "PgDn"))
+ s->seq = KEY_NPAGE;
#ifdef KEY_HOME
- else if (s->type == RAW && (!strcasecmp(s->keystr, "khome")))
- s->seq = KEY_HOME;
+ else if (!strcasecmp(s->keystr, "Home"))
+ s->seq = KEY_HOME;
#endif
#ifdef KEY_END
- else if (s->type == RAW && (!strcasecmp(s->keystr, "kend")))
- s->seq = KEY_END;
+ else if (!strcasecmp(s->keystr, "End"))
+ s->seq = KEY_END;
#endif
-
+ }
}
#ifdef DEBUG
-
void print_sclist(void)
{
sc *s;
const subnfunc *f;
- for (s = sclist; s->next != NULL; s = s->next) {
+ for (s = sclist; s != NULL; s = s->next) {
f = sctofunc(s);
- if (f)
- fprintf(stderr, "Shortcut \"%s\", function: %s, menus %d\n", s->keystr, f->desc, f->menus);
+ if (f)
+ fprintf(stderr, "Shortcut \"%s\", function: %s, menus %x\n", s->keystr, f->desc, f->menus);
else
- fprintf(stderr, "Hmm, didnt find a func for \"%s\"\n", s->keystr);
+ fprintf(stderr, "Hmm, didn't find a func for \"%s\"\n", s->keystr);
}
-
}
#endif
-
-/* Stuff we need to make at least static here so we can access it below */
-/* TRANSLATORS: Try to keep the next five strings at most 10 characters. */
-const char *cancel_msg = N_("Cancel");
-const char *replace_msg = N_("Replace");
-const char *no_replace_msg = N_("No Replace");
-
+/* TRANSLATORS: Try to keep the next four strings at most 10 characters. */
+const char *exit_tag = N_("Exit");
+const char *close_tag = N_("Close");
+const char *uncut_tag = N_("Uncut Text");
+#ifndef DISABLE_JUSITIFY
+const char *unjust_tag = N_("Unjustify");
+#endif
#ifndef NANO_TINY
-const char *case_sens_msg = N_("Case Sens");
-const char *backwards_msg = N_("Backwards");
+/* TRANSLATORS: Try to keep this at most 12 characters. */
+const char *whereis_next_tag = N_("WhereIs Next");
#endif
-#ifdef HAVE_REGEX_H
-const char *regexp_msg = N_("Regexp");
-#endif
-
-/* Stuff we want to just stun out if we're in TINY mode */
-#ifdef NANO_TINY
-const char *gototext_msg = "";
-const char *do_para_begin_msg = "";
-const char *do_para_end_msg = "";
-const char *case_sens_msg = "";
-const char *backwards_msg = "";
-const char *do_cut_till_end = "";
-const char *dos_format_msg = "";
-const char *mac_format_msg = "";
-const char *append_msg = "";
-const char *prepend_msg = "";
-const char *backup_file_msg = "";
-const char *to_files_msg = "";
-const char *first_file_msg = "";
-const char *whereis_next_msg = "";
-const char *last_file_msg = "";
-const char *new_buffer_msg = "";
-const char *goto_dir_msg;
-const char *ext_cmd_msg = "";
-
-#else
-/* TRANSLATORS: Try to keep the next five strings at most 10 characters. */
-const char *prev_history_msg = N_("PrevHstory");
-const char *next_history_msg = N_("NextHstory");
-const char *gototext_msg = N_("Go To Text");
-/* TRANSLATORS: Try to keep the next three strings at most 12 characters. */
-const char *whereis_next_msg = N_("WhereIs Next");
-#ifndef DISABLE_BROWSER
-const char *first_file_msg = N_("First File");
-const char *last_file_msg = N_("Last File");
-/* TRANSLATORS: Try to keep the next nine strings at most 16 characters. */
-const char *to_files_msg = N_("To Files");
-#endif
-const char *dos_format_msg = N_("DOS Format");
-const char *mac_format_msg = N_("Mac Format");
-const char *append_msg = N_("Append");
-const char *prepend_msg = N_("Prepend");
-const char *backup_file_msg = N_("Backup File");
-const char *ext_cmd_msg = N_("Execute Command");
-#ifdef ENABLE_MULTIBUFFER
-const char *new_buffer_msg = N_("New Buffer");
-#endif
-const char *goto_dir_msg = N_("Go To Dir");
-
-#endif /* NANO_TINY */
-
-/* Initialize all shortcut lists. If unjustify is TRUE, replace the
- * Uncut shortcut in the main shortcut list with UnJustify. */
-void shortcut_init(bool unjustify)
+/* Initialize the list of functions and the list of shortcuts. */
+void shortcut_init(void)
{
- /* TRANSLATORS: Try to keep the following strings at most 10 characters. */
- const char *get_help_msg = N_("Get Help");
- const char *exit_msg = N_("Exit");
- const char *whereis_msg = N_("Where Is");
- const char *prev_page_msg = N_("Prev Page");
- const char *next_page_msg = N_("Next Page");
- const char *first_line_msg = N_("First Line");
- const char *last_line_msg = N_("Last Line");
- const char *suspend_msg = N_("Suspend");
+ /* TRANSLATORS: Try to keep the next eight strings at most 10 characters. */
+ const char *whereis_tag = N_("Where Is");
+ const char *replace_tag = N_("Replace");
+ const char *gotoline_tag = N_("Go To Line");
+ const char *prev_line_tag = N_("Prev Line");
+ const char *next_line_tag = N_("Next Line");
+ const char *read_file_tag = N_("Read File");
#ifndef DISABLE_JUSTIFY
- const char *beg_of_par_msg = N_("Beg of Par");
- const char *end_of_par_msg = N_("End of Par");
- const char *fulljstify_msg = N_("FullJstify");
-#endif
- const char *refresh_msg = N_("Refresh");
-#ifndef NANO_TINY
- const char *insert_file_msg = N_("Insert File");
+ const char *fulljustify_tag = N_("FullJstify");
#endif
- const char *go_to_line_msg = N_("Go To Line");
+ const char *refresh_tag = N_("Refresh");
-#ifndef DISABLE_JUSTIFY
- const char *nano_justify_msg = N_("Justify the current paragraph");
-#endif
#ifndef DISABLE_HELP
+#ifndef DISABLE_JUSTIFY
/* TRANSLATORS: The next long series of strings are shortcut descriptions;
* they are best kept shorter than 56 characters, but may be longer. */
+ const char *nano_justify_msg = N_("Justify the current paragraph");
+#endif
const char *nano_cancel_msg = N_("Cancel the current function");
const char *nano_help_msg = N_("Display this help text");
const char *nano_exit_msg =
-#ifdef ENABLE_MULTIBUFFER
+#ifndef DISABLE_MULTIBUFFER
N_("Close the current file buffer / Exit from nano")
#else
- N_("Exit from nano")
+ N_("Exit from nano")
#endif
;
const char *nano_writeout_msg =
@@ -517,22 +521,25 @@ void shortcut_init(bool unjustify)
N_("Insert another file into the current one");
const char *nano_whereis_msg =
N_("Search for a string or a regular expression");
- const char *nano_prevpage_msg = N_("Go to previous screen");
- const char *nano_nextpage_msg = N_("Go to next screen");
+#ifndef DISABLE_BROWSER
+ const char *nano_browser_whereis_msg =
+ N_("Search for a string");
+#endif
+ const char *nano_prevpage_msg = N_("Go one screenful up");
+ const char *nano_nextpage_msg = N_("Go one screenful down");
const char *nano_cut_msg =
N_("Cut the current line and store it in the cutbuffer");
const char *nano_uncut_msg =
N_("Uncut from the cutbuffer into the current line");
- const char *nano_cursorpos_msg =
- N_("Display the position of the cursor");
- const char *nano_spell_msg =
- N_("Invoke the spell checker, if available");
- const char *nano_replace_msg =
- N_("Replace a string or a regular expression");
- const char *nano_gotoline_msg = N_("Go to line and column number");
+ const char *nano_cursorpos_msg = N_("Display the position of the cursor");
+#ifndef DISABLE_SPELLER
+ const char *nano_spell_msg = N_("Invoke the spell checker, if available");
+#endif
+ const char *nano_replace_msg = N_("Replace a string or a regular expression");
+ const char *nano_gotoline_msg = N_("Go to line and column number");
#ifndef NANO_TINY
- const char *nano_mark_msg = N_("Mark text at the cursor position");
- const char *nano_whereis_next_msg = N_("Repeat last search");
+ const char *nano_mark_msg = N_("Mark text starting from the cursor position");
+ const char *nano_whereis_next_msg = N_("Repeat the last search");
const char *nano_copy_msg =
N_("Copy the current line and store it in the cutbuffer");
const char *nano_indent_msg = N_("Indent the current line");
@@ -556,10 +563,8 @@ void shortcut_init(bool unjustify)
const char *nano_paraend_msg =
N_("Go just beyond end of paragraph; then of next paragraph");
#endif
- const char *nano_firstline_msg =
- N_("Go to the first line of the file");
- const char *nano_lastline_msg =
- N_("Go to the last line of the file");
+ const char *nano_firstline_msg = N_("Go to the first line of the file");
+ const char *nano_lastline_msg = N_("Go to the last line of the file");
#ifndef NANO_TINY
const char *nano_bracket_msg = N_("Go to the matching bracket");
const char *nano_scrollup_msg =
@@ -567,24 +572,18 @@ void shortcut_init(bool unjustify)
const char *nano_scrolldown_msg =
N_("Scroll down one line without scrolling the cursor");
#endif
-#ifdef ENABLE_MULTIBUFFER
- const char *nano_prevfile_msg =
- N_("Switch to the previous file buffer");
- const char *nano_nextfile_msg =
- N_("Switch to the next file buffer");
-#endif
- const char *nano_verbatim_msg =
- N_("Insert the next keystroke verbatim");
- const char *nano_tab_msg =
- N_("Insert a tab at the cursor position");
- const char *nano_enter_msg =
- N_("Insert a newline at the cursor position");
- const char *nano_delete_msg =
- N_("Delete the character under the cursor");
+#ifndef DISABLE_MULTIBUFFER
+ const char *nano_prevfile_msg = N_("Switch to the previous file buffer");
+ const char *nano_nextfile_msg = N_("Switch to the next file buffer");
+#endif
+ const char *nano_verbatim_msg = N_("Insert the next keystroke verbatim");
+ const char *nano_tab_msg = N_("Insert a tab at the cursor position");
+ const char *nano_enter_msg = N_("Insert a newline at the cursor position");
+ const char *nano_delete_msg = N_("Delete the character under the cursor");
const char *nano_backspace_msg =
N_("Delete the character to the left of the cursor");
#ifndef NANO_TINY
- const char *nano_cut_till_end_msg =
+ const char *nano_cut_till_eof_msg =
N_("Cut from the cursor position to the end of the file");
#endif
#ifndef DISABLE_JUSTIFY
@@ -608,7 +607,7 @@ void shortcut_init(bool unjustify)
const char *nano_regexp_msg =
N_("Toggle the use of regular expressions");
#endif
-#ifndef NANO_TINY
+#ifndef DISABLE_HISTORIES
const char *nano_prev_history_msg =
N_("Recall the previous search/replace string");
const char *nano_next_history_msg =
@@ -620,28 +619,28 @@ void shortcut_init(bool unjustify)
#ifndef NANO_TINY
const char *nano_dos_msg = N_("Toggle the use of DOS format");
const char *nano_mac_msg = N_("Toggle the use of Mac format");
-#endif
const char *nano_append_msg = N_("Toggle appending");
const char *nano_prepend_msg = N_("Toggle prepending");
-#ifndef NANO_TINY
- const char *nano_backup_msg =
- N_("Toggle backing up of the original file");
+ const char *nano_backup_msg = N_("Toggle backing up of the original file");
const char *nano_execute_msg = N_("Execute external command");
#endif
-#if !defined(NANO_TINY) && defined(ENABLE_MULTIBUFFER)
- const char *nano_multibuffer_msg =
- N_("Toggle the use of a new buffer");
+#ifndef DISABLE_MULTIBUFFER
+ const char *nano_multibuffer_msg = N_("Toggle the use of a new buffer");
#endif
#ifndef DISABLE_BROWSER
const char *nano_exitbrowser_msg = N_("Exit from the file browser");
- const char *nano_firstfile_msg =
- N_("Go to the first file in the list");
- const char *nano_lastfile_msg =
- N_("Go to the last file in the list");
- const char *nano_forwardfile_msg = N_("Go to the next file in the list");
+ const char *nano_firstfile_msg = N_("Go to the first file in the list");
+ const char *nano_lastfile_msg = N_("Go to the last file in the list");
const char *nano_backfile_msg = N_("Go to the previous file in the list");
+ const char *nano_forwardfile_msg = N_("Go to the next file in the list");
const char *nano_gotodir_msg = N_("Go to directory");
#endif
+#ifndef DISABLE_COLOR
+ const char *nano_lint_msg = N_("Invoke the linter, if available");
+ const char *nano_prevlint_msg = N_("Go to previous linter msg");
+ const char *nano_nextlint_msg = N_("Go to next linter msg");
+ const char *nano_formatter_msg = N_("Invoke formatter, if available");
+#endif
#endif /* !DISABLE_HELP */
#ifndef DISABLE_HELP
@@ -652,306 +651,271 @@ void shortcut_init(bool unjustify)
while (allfuncs != NULL) {
subnfunc *f = allfuncs;
- allfuncs = (allfuncs)->next;
+ allfuncs = allfuncs->next;
free(f);
}
- add_to_funcs(DO_HELP_VOID,
- (MMAIN|MWHEREIS|MREPLACE|MREPLACE2|MGOTOLINE|MWRITEFILE|MINSERTFILE|MEXTCMD|MSPELL|MBROWSER|MWHEREISFILE|MGOTODIR),
- get_help_msg, IFSCHELP(nano_help_msg), FALSE, VIEW);
+ /* Start populating the different menus with functions. */
- add_to_funcs( CANCEL_MSG,
- (MWHEREIS|MREPLACE|MREPLACE2|MGOTOLINE|MWRITEFILE|MINSERTFILE|MEXTCMD|MSPELL|MWHEREISFILE|MGOTODIR|MYESNO),
- cancel_msg, IFSCHELP(nano_cancel_msg), FALSE, VIEW);
+ add_to_funcs(do_help_void, MMOST,
+ /* TRANSLATORS: Try to keep the following strings at most 10 characters. */
+ N_("Get Help"), IFSCHELP(nano_help_msg), TOGETHER, VIEW);
- add_to_funcs(DO_EXIT, MMAIN,
-#ifdef ENABLE_MULTIBUFFER
- /* TRANSLATORS: Try to keep this at most 10 characters. */
- openfile != NULL && openfile != openfile->next ? N_("Close") :
-#endif
- exit_msg, IFSCHELP(nano_exit_msg), FALSE, VIEW);
+ add_to_funcs(do_cancel, ((MMOST & ~MMAIN & ~MBROWSER) | MYESNO),
+ N_("Cancel"), IFSCHELP(nano_cancel_msg), TOGETHER, VIEW);
+
+ add_to_funcs(do_exit, MMAIN,
+ exit_tag, IFSCHELP(nano_exit_msg), TOGETHER, VIEW);
+ /* Remember the entry for Exit, to be able to replace it with Close. */
+ exitfunc = tailfunc;
#ifndef DISABLE_BROWSER
- add_to_funcs(DO_EXIT, MBROWSER, exit_msg, IFSCHELP(nano_exitbrowser_msg), FALSE, VIEW);
+ add_to_funcs(do_exit, MBROWSER,
+ exit_tag, IFSCHELP(nano_exitbrowser_msg), TOGETHER, VIEW);
#endif
- /* TRANSLATORS: Try to keep this at most 10 characters. */
- add_to_funcs(DO_WRITEOUT_VOID, MMAIN, N_("WriteOut"),
- IFSCHELP(nano_writeout_msg), FALSE, NOVIEW);
-
-#ifndef DISABLE_JUSTIFY
- /* TRANSLATORS: Try to keep this at most 10 characters. */
- add_to_funcs(DO_JUSTIFY_VOID, MMAIN, N_("Justify"),
- nano_justify_msg, TRUE, NOVIEW);
-#endif
+ add_to_funcs(do_writeout_void, MMAIN,
+ N_("Write Out"), IFSCHELP(nano_writeout_msg), TOGETHER, NOVIEW);
/* We allow inserting files in view mode if multibuffers are
* available, so that we can view multiple files. If we're using
* restricted mode, inserting files is disabled, since it allows
* reading from or writing to files not specified on the command
* line. */
-
- add_to_funcs(DO_INSERTFILE_VOID,
- /* TRANSLATORS: Try to keep this at most 10 characters. */
- MMAIN, N_("Read File"), IFSCHELP(nano_insert_msg), FALSE,
-#ifdef ENABLE_MULTIBUFFER
+ add_to_funcs(do_insertfile_void, MMAIN,
+ read_file_tag, IFSCHELP(nano_insert_msg), BLANKAFTER,
+#ifndef DISABLE_MULTIBUFFER
VIEW);
#else
NOVIEW);
#endif
- add_to_funcs(DO_SEARCH, MMAIN|MBROWSER, whereis_msg,
- IFSCHELP(nano_whereis_msg), FALSE, VIEW);
+ add_to_funcs(do_search, MMAIN,
+ whereis_tag, IFSCHELP(nano_whereis_msg), TOGETHER, VIEW);
- add_to_funcs(DO_PAGE_UP, MMAIN|MHELP|MBROWSER,
- prev_page_msg, IFSCHELP(nano_prevpage_msg), FALSE, VIEW);
- add_to_funcs(DO_PAGE_DOWN, MMAIN|MHELP|MBROWSER,
- next_page_msg, IFSCHELP(nano_nextpage_msg), TRUE, VIEW);
+ add_to_funcs(do_replace, MMAIN,
+ replace_tag, IFSCHELP(nano_replace_msg), TOGETHER, NOVIEW);
+#ifndef DISABLE_BROWSER
+ add_to_funcs(do_search, MBROWSER,
+ whereis_tag, IFSCHELP(nano_browser_whereis_msg), TOGETHER, VIEW);
- /* TRANSLATORS: Try to keep this at most 10 characters. */
- add_to_funcs(DO_CUT_TEXT_VOID, MMAIN, N_("Cut Text"), IFSCHELP(nano_cut_msg),
- FALSE, NOVIEW);
-
- if (unjustify)
- /* TRANSLATORS: Try to keep this at most 10 characters. */
- add_to_funcs(DO_UNCUT_TEXT, MMAIN, N_("UnJustify"), "",
- FALSE, NOVIEW);
+ add_to_funcs(goto_dir_void, MBROWSER,
+ N_("Go To Dir"), IFSCHELP(nano_gotodir_msg), BLANKAFTER, VIEW);
+#endif
- else
- /* TRANSLATORS: Try to keep this at most 10 characters. */
- add_to_funcs(DO_UNCUT_TEXT, MMAIN, N_("UnCut Text"), IFSCHELP(nano_uncut_msg),
- FALSE, NOVIEW);
+#ifndef DISABLE_HELP
+ /* The description ("x") and blank_after (0) are irrelevant,
+ * because the help viewer does not have a help text. */
+ add_to_funcs(do_exit, MHELP, exit_tag, "x", 0, VIEW);
-#ifndef NANO_TINY
- /* TRANSLATORS: Try to keep this at most 10 characters. */
- add_to_funcs(DO_CURSORPOS_VOID, MMAIN, N_("Cur Pos"), IFSCHELP(nano_cursorpos_msg),
- FALSE, VIEW);
-#endif
+ add_to_funcs(total_refresh, MHELP, refresh_tag, "x", 0, VIEW);
- /* If we're using restricted mode, spell checking is disabled
- * because it allows reading from or writing to files not specified
- * on the command line. */
-#ifndef DISABLE_SPELLER
- /* TRANSLATORS: Try to keep this at most 10 characters. */
- add_to_funcs(DO_SPELL, MMAIN, N_("To Spell"), IFSCHELP(nano_spell_msg),
- TRUE, NOVIEW);
+ add_to_funcs(do_up_void, MHELP, prev_line_tag, "x", 0, VIEW);
+ add_to_funcs(do_down_void, MHELP, next_line_tag, "x" , 0, VIEW);
#endif
- add_to_funcs(DO_FIRST_LINE,
- (MMAIN|MWHEREIS|MREPLACE|MREPLACE2|MGOTOLINE),
- first_line_msg, IFSCHELP(nano_firstline_msg), FALSE, VIEW);
+ add_to_funcs(do_cut_text_void, MMAIN,
+ N_("Cut Text"), IFSCHELP(nano_cut_msg), TOGETHER, NOVIEW);
- add_to_funcs(DO_LAST_LINE,
- (MMAIN|MWHEREIS|MREPLACE|MREPLACE2|MGOTOLINE),
- last_line_msg, IFSCHELP(nano_lastline_msg), TRUE, VIEW);
+ add_to_funcs(do_uncut_text, MMAIN,
+ uncut_tag, IFSCHELP(nano_uncut_msg), BLANKAFTER, NOVIEW);
+ /* Remember the entry for Uncut, to be able to replace it with Unjustify. */
+ uncutfunc = tailfunc;
+#ifndef DISABLE_JUSTIFY
+ add_to_funcs(do_justify_void, MMAIN,
+ N_("Justify"), IFSCHELP(nano_justify_msg), TOGETHER, NOVIEW);
+#endif
- add_to_funcs(DO_GOTOLINECOLUMN_VOID, (MMAIN|MWHEREIS),
- go_to_line_msg, IFSCHELP(nano_gotoline_msg), FALSE, VIEW);
+#ifndef DISABLE_SPELLER
+ add_to_funcs(do_spell, MMAIN,
+ N_("To Spell"), IFSCHELP(nano_spell_msg), TOGETHER, NOVIEW);
+#endif
-#ifdef NANO_TINY
- /* TRANSLATORS: Try to keep this at most 10 characters. */
- add_to_funcs(DO_CURSORPOS_VOID, MMAIN, N_("Cur Pos"), IFSCHELP(nano_cursorpos_msg),
- FALSE, VIEW);
+#ifndef DISABLE_COLOR
+ add_to_funcs(do_linter, MMAIN,
+ N_("To Linter"), IFSCHELP(nano_lint_msg), TOGETHER, NOVIEW);
+ add_to_funcs(do_formatter, MMAIN,
+ N_("Formatter"), IFSCHELP(nano_formatter_msg), BLANKAFTER, NOVIEW);
#endif
+#ifndef NANO_TINY
+ add_to_funcs(case_sens_void, MWHEREIS|MREPLACE,
+ N_("Case Sens"), IFSCHELP(nano_case_msg), TOGETHER, VIEW);
+#endif
- add_to_funcs(DO_REPLACE, (MMAIN|MWHEREIS), replace_msg, IFSCHELP(nano_replace_msg),
+#ifdef HAVE_REGEX_H
+ add_to_funcs(regexp_void, MWHEREIS|MREPLACE,
+ N_("Regexp"), IFSCHELP(nano_regexp_msg), TOGETHER, VIEW);
+#endif
#ifndef NANO_TINY
- FALSE,
-#else
- TRUE,
+ add_to_funcs(backwards_void, MWHEREIS|MREPLACE,
+ N_("Backwards"), IFSCHELP(nano_reverse_msg), TOGETHER, VIEW);
#endif
- NOVIEW);
-#ifndef NANO_TINY
+ add_to_funcs(flip_replace_void, MWHEREIS,
+ replace_tag, IFSCHELP(nano_replace_msg), TOGETHER, VIEW);
- add_to_funcs(DO_MARK, MMAIN, N_("Mark Text"),
- IFSCHELP(nano_mark_msg), FALSE, VIEW);
+ add_to_funcs(flip_replace_void, MREPLACE,
+ N_("No Replace"), IFSCHELP(nano_whereis_msg), TOGETHER, VIEW);
- add_to_funcs(DO_RESEARCH, (MMAIN|MBROWSER), whereis_next_msg,
- IFSCHELP(nano_whereis_next_msg), TRUE, VIEW);
+#ifndef DISABLE_JUSTIFY
+ add_to_funcs(do_full_justify, MWHEREIS,
+ fulljustify_tag, IFSCHELP(nano_fulljustify_msg), TOGETHER, NOVIEW);
+#endif
- add_to_funcs(DO_COPY_TEXT, MMAIN, N_("Copy Text"),
- IFSCHELP(nano_copy_msg), FALSE, NOVIEW);
+ add_to_funcs(do_cursorpos_void, MMAIN,
+ N_("Cur Pos"), IFSCHELP(nano_cursorpos_msg), TOGETHER, VIEW);
- add_to_funcs(DO_INDENT_VOID, MMAIN, N_("Indent Text"),
- IFSCHELP(nano_indent_msg), FALSE, NOVIEW);
+#if !defined(NANO_TINY) || defined(DISABLE_COLOR)
+ /* Conditionally placing this one here or further on, to keep the
+ * help items nicely paired in most conditions. */
+ add_to_funcs(do_gotolinecolumn_void, MMAIN|MWHEREIS,
+ gotoline_tag, IFSCHELP(nano_gotoline_msg), BLANKAFTER, VIEW);
+#endif
- add_to_funcs(DO_UNINDENT, MMAIN, N_("Unindent Text"),
- IFSCHELP(nano_unindent_msg), FALSE, NOVIEW);
+ add_to_funcs(do_page_up, MMAIN|MHELP|MBROWSER,
+ N_("Prev Page"), IFSCHELP(nano_prevpage_msg), TOGETHER, VIEW);
+ add_to_funcs(do_page_down, MMAIN|MHELP|MBROWSER,
+ N_("Next Page"), IFSCHELP(nano_nextpage_msg), TOGETHER, VIEW);
- if (ISSET(UNDOABLE)) {
- add_to_funcs(DO_UNDO, MMAIN, N_("Undo"),
- IFSCHELP(nano_undo_msg), FALSE, NOVIEW);
+ add_to_funcs(do_first_line, MMAIN|MHELP|MWHEREIS|MREPLACE|MREPLACEWITH|MGOTOLINE,
+ N_("First Line"), IFSCHELP(nano_firstline_msg), TOGETHER, VIEW);
+ add_to_funcs(do_last_line, MMAIN|MHELP|MWHEREIS|MREPLACE|MREPLACEWITH|MGOTOLINE,
+ N_("Last Line"), IFSCHELP(nano_lastline_msg), BLANKAFTER, VIEW);
- add_to_funcs(DO_REDO, MMAIN, N_("Redo"),
- IFSCHELP(nano_redo_msg), TRUE, NOVIEW);
- }
+#ifndef NANO_TINY
+ add_to_funcs(do_research, MMAIN,
+ whereis_next_tag, IFSCHELP(nano_whereis_next_msg), TOGETHER, VIEW);
-#endif
+ add_to_funcs(do_find_bracket, MMAIN,
+ N_("To Bracket"), IFSCHELP(nano_bracket_msg), TOGETHER, VIEW);
- add_to_funcs(DO_RIGHT, MMAIN, N_("Forward"), IFSCHELP(nano_forward_msg),
- FALSE, VIEW);
+ add_to_funcs(do_mark, MMAIN,
+ N_("Mark Text"), IFSCHELP(nano_mark_msg), TOGETHER, VIEW);
-#ifndef DISABLE_BROWSER
- add_to_funcs(DO_RIGHT, MBROWSER, N_("Forward"), IFSCHELP(nano_forwardfile_msg),
- FALSE, VIEW);
-#endif
+ add_to_funcs(do_copy_text, MMAIN,
+ N_("Copy Text"), IFSCHELP(nano_copy_msg), BLANKAFTER, NOVIEW);
- add_to_funcs(DO_RIGHT, MALL, "", "", FALSE, VIEW);
+ add_to_funcs(do_indent_void, MMAIN,
+ N_("Indent Text"), IFSCHELP(nano_indent_msg), TOGETHER, NOVIEW);
+ add_to_funcs(do_unindent, MMAIN,
+ N_("Unindent Text"), IFSCHELP(nano_unindent_msg), BLANKAFTER, NOVIEW);
- add_to_funcs(DO_LEFT, MMAIN, N_("Back"), IFSCHELP(nano_back_msg),
- FALSE, VIEW);
+ add_to_funcs(do_undo, MMAIN,
+ N_("Undo"), IFSCHELP(nano_undo_msg), TOGETHER, NOVIEW);
+ add_to_funcs(do_redo, MMAIN,
+ N_("Redo"), IFSCHELP(nano_redo_msg), BLANKAFTER, NOVIEW);
+#endif /* !NANO_TINY */
+
+ add_to_funcs(do_left, MMAIN,
+ N_("Back"), IFSCHELP(nano_back_msg), TOGETHER, VIEW);
+ add_to_funcs(do_right, MMAIN,
+ N_("Forward"), IFSCHELP(nano_forward_msg), TOGETHER, VIEW);
#ifndef DISABLE_BROWSER
- add_to_funcs(DO_LEFT, MBROWSER, N_("Back"), IFSCHELP(nano_backfile_msg),
- FALSE, VIEW);
+ add_to_funcs(do_left, MBROWSER,
+ N_("Back"), IFSCHELP(nano_backfile_msg), TOGETHER, VIEW);
+ add_to_funcs(do_right, MBROWSER,
+ N_("Forward"), IFSCHELP(nano_forwardfile_msg), TOGETHER, VIEW);
#endif
- add_to_funcs(DO_LEFT, MALL, "", "", FALSE, VIEW);
-
#ifndef NANO_TINY
- add_to_funcs(DO_NEXT_WORD_VOID, MMAIN, N_("Next Word"),
- IFSCHELP(nano_nextword_msg), FALSE, VIEW);
-
- add_to_funcs(DO_PREV_WORD_VOID, MMAIN, N_("Prev Word"),
- IFSCHELP(nano_prevword_msg), FALSE, VIEW);
+ add_to_funcs(do_prev_word_void, MMAIN,
+ N_("Prev Word"), IFSCHELP(nano_prevword_msg), TOGETHER, VIEW);
+ add_to_funcs(do_next_word_void, MMAIN,
+ N_("Next Word"), IFSCHELP(nano_nextword_msg), TOGETHER, VIEW);
#endif
- add_to_funcs(DO_UP_VOID, (MMAIN|MHELP|MBROWSER), N_("Prev Line"),
- IFSCHELP(nano_prevline_msg), FALSE, VIEW);
-
- add_to_funcs(DO_DOWN_VOID, (MMAIN|MHELP|MBROWSER), N_("Next Line"),
- IFSCHELP(nano_nextline_msg), TRUE, VIEW);
-
- add_to_funcs(DO_HOME, MMAIN, N_("Home"), IFSCHELP(nano_home_msg),
- FALSE, VIEW);
+ add_to_funcs(do_home, MMAIN,
+ N_("Home"), IFSCHELP(nano_home_msg), TOGETHER, VIEW);
+ add_to_funcs(do_end, MMAIN,
+ N_("End"), IFSCHELP(nano_end_msg), TOGETHER, VIEW);
- add_to_funcs(DO_END, MMAIN, N_("End"), IFSCHELP(nano_end_msg),
- FALSE, VIEW);
+ add_to_funcs(do_up_void, MMAIN|MBROWSER,
+ prev_line_tag, IFSCHELP(nano_prevline_msg), TOGETHER, VIEW);
+ add_to_funcs(do_down_void, MMAIN|MBROWSER,
+ next_line_tag, IFSCHELP(nano_nextline_msg), BLANKAFTER, VIEW);
#ifndef DISABLE_JUSTIFY
- add_to_funcs(DO_PARA_BEGIN_VOID, (MMAIN|MWHEREIS), beg_of_par_msg,
- IFSCHELP(nano_parabegin_msg), FALSE, VIEW);
-
- add_to_funcs(DO_PARA_END_VOID, (MMAIN|MWHEREIS), end_of_par_msg,
- IFSCHELP(nano_paraend_msg), FALSE, VIEW);
+ add_to_funcs(do_para_begin_void, MMAIN|MWHEREIS,
+ N_("Beg of Par"), IFSCHELP(nano_parabegin_msg), TOGETHER, VIEW);
+ add_to_funcs(do_para_end_void, MMAIN|MWHEREIS,
+ N_("End of Par"), IFSCHELP(nano_paraend_msg), TOGETHER, VIEW);
#endif
#ifndef NANO_TINY
- add_to_funcs(DO_FIND_BRACKET, MMAIN, _("Find Other Bracket"),
- IFSCHELP(nano_bracket_msg), FALSE, VIEW);
-
- add_to_funcs(DO_SCROLL_UP, MMAIN, N_("Scroll Up"),
- IFSCHELP(nano_scrollup_msg), FALSE, VIEW);
-
- add_to_funcs(DO_SCROLL_DOWN, MMAIN, N_("Scroll Down"),
- IFSCHELP(nano_scrolldown_msg), FALSE, VIEW);
-#endif
-
-#ifdef ENABLE_MULTIBUFFER
- add_to_funcs(SWITCH_TO_PREV_BUFFER_VOID, MMAIN, _("Previous File"),
- IFSCHELP(nano_prevfile_msg), FALSE, VIEW);
- add_to_funcs(SWITCH_TO_NEXT_BUFFER_VOID, MMAIN, N_("Next File"),
- IFSCHELP(nano_nextfile_msg), TRUE, VIEW);
-#endif
-
- add_to_funcs(DO_VERBATIM_INPUT, MMAIN, N_("Verbatim Input"),
- IFSCHELP(nano_verbatim_msg), FALSE, NOVIEW);
- add_to_funcs(DO_VERBATIM_INPUT, MWHEREIS|MREPLACE|MREPLACE2|MEXTCMD|MSPELL,
- "", "", FALSE, NOVIEW);
-
- add_to_funcs(DO_TAB, MMAIN, N_("Tab"), IFSCHELP(nano_tab_msg),
- FALSE, NOVIEW);
- add_to_funcs(DO_TAB, MALL, "", "", FALSE, NOVIEW);
- add_to_funcs(DO_ENTER, MMAIN, N_("Enter"), IFSCHELP(nano_enter_msg),
- FALSE, NOVIEW);
- add_to_funcs(DO_ENTER, MALL, "", "", FALSE, NOVIEW);
- add_to_funcs(DO_DELETE, MMAIN, N_("Delete"), IFSCHELP(nano_delete_msg),
- FALSE, NOVIEW);
- add_to_funcs(DO_DELETE, MALL, "", "", FALSE, NOVIEW);
- add_to_funcs(DO_BACKSPACE, MMAIN, N_("Backspace"), IFSCHELP(nano_backspace_msg),
-#ifndef NANO_TINY
- FALSE,
-#else
- TRUE,
+ add_to_funcs(do_scroll_up, MMAIN,
+ N_("Scroll Up"), IFSCHELP(nano_scrollup_msg), TOGETHER, VIEW);
+ add_to_funcs(do_scroll_down, MMAIN,
+ N_("Scroll Down"), IFSCHELP(nano_scrolldown_msg), BLANKAFTER, VIEW);
#endif
- NOVIEW);
- add_to_funcs(DO_BACKSPACE, MALL, "", "",
-#ifndef NANO_TINY
- FALSE,
-#else
- TRUE,
+#ifndef DISABLE_MULTIBUFFER
+ add_to_funcs(switch_to_prev_buffer_void, MMAIN,
+ N_("Prev File"), IFSCHELP(nano_prevfile_msg), TOGETHER, VIEW);
+ add_to_funcs(switch_to_next_buffer_void, MMAIN,
+ N_("Next File"), IFSCHELP(nano_nextfile_msg), BLANKAFTER, VIEW);
#endif
- NOVIEW);
-#ifndef NANO_TINY
- add_to_funcs(DO_CUT_TILL_END, MMAIN, N_("CutTillEnd"),
- IFSCHELP(nano_cut_till_end_msg), TRUE, NOVIEW);
+#if defined(NANO_TINY) && !defined(DISABLE_COLOR)
+ add_to_funcs(do_gotolinecolumn_void, MMAIN|MWHEREIS,
+ gotoline_tag, IFSCHELP(nano_gotoline_msg), BLANKAFTER, VIEW);
#endif
- add_to_funcs(XON_COMPLAINT, MMAIN, "", "", FALSE, VIEW);
- add_to_funcs(XOFF_COMPLAINT, MMAIN, "", "", FALSE, VIEW);
-
-#ifndef DISABLE_JUSTIFY
- add_to_funcs(DO_FULL_JUSTIFY, (MMAIN|MWHEREIS), fulljstify_msg,
- IFSCHELP(nano_fulljustify_msg), FALSE, NOVIEW);
-#endif
+ add_to_funcs(do_verbatim_input, MMAIN,
+ N_("Verbatim"), IFSCHELP(nano_verbatim_msg), TOGETHER, NOVIEW);
+ add_to_funcs(do_tab, MMAIN,
+ N_("Tab"), IFSCHELP(nano_tab_msg), TOGETHER, NOVIEW);
+ add_to_funcs(do_enter_void, MMAIN,
+ N_("Enter"), IFSCHELP(nano_enter_msg), TOGETHER, NOVIEW);
+ add_to_funcs(do_delete, MMAIN,
+ N_("Delete"), IFSCHELP(nano_delete_msg), TOGETHER, NOVIEW);
+ add_to_funcs(do_backspace, MMAIN,
+ N_("Backspace"), IFSCHELP(nano_backspace_msg),
#ifndef NANO_TINY
- add_to_funcs(DO_WORDLINECHAR_COUNT, MMAIN, N_("Word Count"),
- IFSCHELP(nano_wordcount_msg), FALSE, VIEW);
+ TOGETHER,
+#else
+ BLANKAFTER,
#endif
-
- add_to_funcs(TOTAL_REFRESH, (MMAIN|MHELP), refresh_msg,
- IFSCHELP(nano_refresh_msg), FALSE, VIEW);
-
- add_to_funcs(DO_SUSPEND_VOID, MMAIN, suspend_msg,
- IFSCHELP(nano_suspend_msg), TRUE, VIEW);
+ NOVIEW);
#ifndef NANO_TINY
- add_to_funcs( CASE_SENS_MSG,
- (MWHEREIS|MREPLACE|MWHEREISFILE),
- case_sens_msg, IFSCHELP(nano_case_msg), FALSE, VIEW);
-
- add_to_funcs( BACKWARDS_MSG,
- (MWHEREIS|MREPLACE|MWHEREISFILE),
- backwards_msg, IFSCHELP(nano_reverse_msg), FALSE, VIEW);
+ add_to_funcs(do_cut_till_eof, MMAIN,
+ N_("CutTillEnd"), IFSCHELP(nano_cut_till_eof_msg), BLANKAFTER, NOVIEW);
#endif
-#ifdef HAVE_REGEX_H
- add_to_funcs( REGEXP_MSG,
- (MWHEREIS|MREPLACE|MWHEREISFILE),
- regexp_msg, IFSCHELP(nano_regexp_msg), FALSE, VIEW);
+#ifndef DISABLE_JUSTIFY
+ add_to_funcs(do_full_justify, MMAIN,
+ fulljustify_tag, IFSCHELP(nano_fulljustify_msg), TOGETHER, NOVIEW);
#endif
#ifndef NANO_TINY
- add_to_funcs( PREV_HISTORY_MSG,
- (MWHEREIS|MREPLACE|MREPLACE2|MWHEREISFILE),
- prev_history_msg, IFSCHELP(nano_prev_history_msg), FALSE, VIEW);
-
- add_to_funcs( NEXT_HISTORY_MSG,
- (MWHEREIS|MREPLACE|MREPLACE2|MWHEREISFILE),
- next_history_msg, IFSCHELP(nano_next_history_msg), FALSE, VIEW);
+ add_to_funcs(do_wordlinechar_count, MMAIN,
+ N_("Word Count"), IFSCHELP(nano_wordcount_msg), TOGETHER, VIEW);
#endif
- add_to_funcs( NO_REPLACE_MSG, MREPLACE,
- no_replace_msg, IFSCHELP(nano_whereis_msg), FALSE, VIEW);
+ add_to_funcs(total_refresh, MMAIN,
+ refresh_tag, IFSCHELP(nano_refresh_msg), TOGETHER, VIEW);
- add_to_funcs( GOTOTEXT_MSG, MGOTOLINE,
- gototext_msg, IFSCHELP(nano_whereis_msg), TRUE, VIEW);
+ add_to_funcs(do_suspend_void, MMAIN,
+ N_("Suspend"), IFSCHELP(nano_suspend_msg), BLANKAFTER, VIEW);
-#ifndef DISABLE_BROWSER
- if (!ISSET(RESTRICTED))
- add_to_funcs( TO_FILES_MSG,
- (MGOTOLINE|MINSERTFILE),
- to_files_msg, IFSCHELP(nano_tofiles_msg), FALSE, VIEW);
+#ifndef DISABLE_HISTORIES
+ add_to_funcs(get_history_older_void,
+ (MWHEREIS|MREPLACE|MREPLACEWITH|MWHEREISFILE),
+ N_("PrevHstory"), IFSCHELP(nano_prev_history_msg), TOGETHER, VIEW);
+ add_to_funcs(get_history_newer_void,
+ (MWHEREIS|MREPLACE|MREPLACEWITH|MWHEREISFILE),
+ N_("NextHstory"), IFSCHELP(nano_next_history_msg), TOGETHER, VIEW);
#endif
+ add_to_funcs(gototext_void, MGOTOLINE,
+ N_("Go To Text"), IFSCHELP(nano_whereis_msg), BLANKAFTER, VIEW);
+
#ifndef NANO_TINY
/* If we're using restricted mode, the DOS format, Mac format,
* append, prepend, and backup toggles are disabled. The first and
@@ -959,393 +923,287 @@ void shortcut_init(bool unjustify)
* and fourth are disabled because they allow writing to files not
* specified on the command line, and the fifth is useless since
* backups are disabled. */
- if (!ISSET(RESTRICTED))
- add_to_funcs( DOS_FORMAT_MSG, MWRITEFILE,
- dos_format_msg, IFSCHELP(nano_dos_msg), FALSE, NOVIEW);
+ if (!ISSET(RESTRICTED)) {
+ add_to_funcs(dos_format_void, MWRITEFILE,
+ N_("DOS Format"), IFSCHELP(nano_dos_msg), TOGETHER, NOVIEW);
- if (!ISSET(RESTRICTED))
- add_to_funcs( MAC_FORMAT_MSG, MWRITEFILE,
- mac_format_msg, IFSCHELP(nano_mac_msg), FALSE, NOVIEW);
+ add_to_funcs(mac_format_void, MWRITEFILE,
+ N_("Mac Format"), IFSCHELP(nano_mac_msg), TOGETHER, NOVIEW);
- if (!ISSET(RESTRICTED))
- add_to_funcs( APPEND_MSG, MWRITEFILE,
- append_msg, IFSCHELP(nano_append_msg), FALSE, NOVIEW);
+ add_to_funcs(append_void, MWRITEFILE,
+ N_("Append"), IFSCHELP(nano_append_msg), TOGETHER, NOVIEW);
+ add_to_funcs(prepend_void, MWRITEFILE,
+ N_("Prepend"), IFSCHELP(nano_prepend_msg), TOGETHER, NOVIEW);
- if (!ISSET(RESTRICTED))
- add_to_funcs( PREPEND_MSG, MWRITEFILE,
- prepend_msg, IFSCHELP(nano_prepend_msg), FALSE, NOVIEW);
+ add_to_funcs(backup_file_void, MWRITEFILE,
+ N_("Backup File"), IFSCHELP(nano_backup_msg), TOGETHER, NOVIEW);
+ }
- if (!ISSET(RESTRICTED))
- add_to_funcs( BACKUP_FILE_MSG, MWRITEFILE,
- backup_file_msg, IFSCHELP(nano_backup_msg), FALSE, NOVIEW);
-#endif
+ /* If we're using restricted mode, file insertion is disabled, and
+ * thus command execution and the multibuffer toggle have no place. */
+ if (!ISSET(RESTRICTED)) {
+ add_to_funcs(flip_execute_void, MINSERTFILE,
+ N_("Execute Command"), IFSCHELP(nano_execute_msg), TOGETHER, NOVIEW);
-#ifndef NANO_TINY
- /* If we're using restricted mode, command execution is disabled.
- * It's useless since inserting files is disabled. */
- if (!ISSET(RESTRICTED))
- add_to_funcs( EXT_CMD_MSG, MINSERTFILE,
- ext_cmd_msg, IFSCHELP(nano_execute_msg), FALSE, NOVIEW);
+ add_to_funcs(flip_execute_void, MEXTCMD,
+ read_file_tag, IFSCHELP(nano_insert_msg), TOGETHER, NOVIEW);
-#ifdef ENABLE_MULTIBUFFER
- /* If we're using restricted mode, the multibuffer toggle is
- * disabled. It's useless since inserting files is disabled. */
- if (!ISSET(RESTRICTED))
- add_to_funcs( NEW_BUFFER_MSG, MINSERTFILE,
- new_buffer_msg, IFSCHELP(nano_multibuffer_msg), FALSE, NOVIEW);
+#ifndef DISABLE_MULTIBUFFER
+ add_to_funcs(new_buffer_void, MINSERTFILE|MEXTCMD,
+ N_("New Buffer"), IFSCHELP(nano_multibuffer_msg), TOGETHER, NOVIEW);
#endif
+ }
+#endif /* !NANO_TINY */
- add_to_funcs( INSERT_FILE_MSG, MEXTCMD,
- insert_file_msg, IFSCHELP(nano_insert_msg), FALSE, VIEW);
-
-#ifdef ENABLE_MULTIBUFFER
- add_to_funcs( NEW_BUFFER_MSG, MEXTCMD,
- new_buffer_msg, IFSCHELP(nano_multibuffer_msg), FALSE, NOVIEW);
+#ifndef DISABLE_BROWSER
+ if (!ISSET(RESTRICTED))
+ add_to_funcs(to_files_void, MWRITEFILE|MINSERTFILE,
+ N_("To Files"), IFSCHELP(nano_tofiles_msg), TOGETHER, VIEW);
+
+ add_to_funcs(do_first_file, (MBROWSER|MWHEREISFILE),
+ N_("First File"), IFSCHELP(nano_firstfile_msg), TOGETHER, VIEW);
+ add_to_funcs(do_last_file, (MBROWSER|MWHEREISFILE),
+ N_("Last File"), IFSCHELP(nano_lastfile_msg), TOGETHER, VIEW);
+#endif
+
+#if !defined(NANO_TINY) && !defined(DISABLE_BROWSER)
+ add_to_funcs(do_research, MBROWSER,
+ whereis_next_tag, IFSCHELP(nano_whereis_next_msg), TOGETHER, VIEW);
+#endif
+
+#ifndef DISABLE_COLOR
+ /* TRANSLATORS: Try to keep the next two strings at most 20 characters. */
+ add_to_funcs(do_page_up, MLINTER,
+ N_("Prev Lint Msg"), IFSCHELP(nano_prevlint_msg), TOGETHER, VIEW);
+ add_to_funcs(do_page_down, MLINTER,
+ N_("Next Lint Msg"), IFSCHELP(nano_nextlint_msg), TOGETHER, VIEW);
+#endif
+
+ /* Start associating key combos with functions in specific menus. */
+
+ add_to_sclist(MMOST, "^G", do_help_void, 0);
+ add_to_sclist(MMOST, "F1", do_help_void, 0);
+ add_to_sclist(MMAIN|MHELP|MBROWSER, "^X", do_exit, 0);
+ add_to_sclist(MMAIN|MHELP|MBROWSER, "F2", do_exit, 0);
+ add_to_sclist(MMAIN, "^O", do_writeout_void, 0);
+ add_to_sclist(MMAIN, "F3", do_writeout_void, 0);
+ add_to_sclist(MMAIN, "^R", do_insertfile_void, 0);
+ add_to_sclist(MMAIN, "F5", do_insertfile_void, 0);
+ add_to_sclist(MMAIN, "Ins", do_insertfile_void, 0);
+ add_to_sclist(MMAIN|MBROWSER, "^W", do_search, 0);
+ add_to_sclist(MMAIN|MBROWSER, "F6", do_search, 0);
+ add_to_sclist(MMAIN, "^\\", do_replace, 0);
+ add_to_sclist(MMAIN, "M-R", do_replace, 0);
+ add_to_sclist(MMAIN, "F14", do_replace, 0);
+ add_to_sclist(MMOST, "^K", do_cut_text_void, 0);
+ add_to_sclist(MMOST, "F9", do_cut_text_void, 0);
+ add_to_sclist(MMAIN, "^U", do_uncut_text, 0);
+ add_to_sclist(MMAIN, "F10", do_uncut_text, 0);
+#ifndef DISABLE_JUSTIFY
+ add_to_sclist(MMAIN, "^J", do_justify_void, 0);
+ add_to_sclist(MMAIN, "F4", do_justify_void, 0);
#endif
+#ifndef DISABLE_SPELLER
+ add_to_sclist(MMAIN, "^T", do_spell, 0);
+ add_to_sclist(MMAIN, "F12", do_spell, 0);
+#else
+#ifndef DISABLE_COLOR
+ add_to_sclist(MMAIN, "^T", do_linter, 0);
+ add_to_sclist(MMAIN, "F12", do_linter, 0);
+ add_to_sclist(MMAIN, "^T", do_formatter, 0);
+ add_to_sclist(MMAIN, "F12", do_formatter, 0);
+#endif
+#endif
+ add_to_sclist(MMAIN, "^C", do_cursorpos_void, 0);
+ add_to_sclist(MMAIN, "F11", do_cursorpos_void, 0);
+ add_to_sclist(MMAIN, "^_", do_gotolinecolumn_void, 0);
+ add_to_sclist(MMAIN, "M-G", do_gotolinecolumn_void, 0);
+ add_to_sclist(MMAIN, "F13", do_gotolinecolumn_void, 0);
+ add_to_sclist(MMAIN|MBROWSER|MHELP|MWHEREISFILE|MLINTER, "^Y", do_page_up, 0);
+ add_to_sclist(MMAIN|MBROWSER|MHELP|MWHEREISFILE|MLINTER, "F7", do_page_up, 0);
+ add_to_sclist(MMAIN|MBROWSER|MHELP|MWHEREISFILE|MLINTER, "PgUp", do_page_up, 0);
+ add_to_sclist(MMAIN|MBROWSER|MHELP|MWHEREISFILE|MLINTER, "^V", do_page_down, 0);
+ add_to_sclist(MMAIN|MBROWSER|MHELP|MWHEREISFILE|MLINTER, "F8", do_page_down, 0);
+ add_to_sclist(MMAIN|MBROWSER|MHELP|MWHEREISFILE|MLINTER, "PgDn", do_page_down, 0);
+ add_to_sclist(MMAIN|MHELP, "M-\\", do_first_line, 0);
+ add_to_sclist(MMAIN|MHELP, "M-|", do_first_line, 0);
+ add_to_sclist(MMAIN|MHELP, "M-/", do_last_line, 0);
+ add_to_sclist(MMAIN|MHELP, "M-?", do_last_line, 0);
+#ifndef NANO_TINY
+ add_to_sclist(MMAIN|MBROWSER, "M-W", do_research, 0);
+ add_to_sclist(MMAIN|MBROWSER, "F16", do_research, 0);
+ add_to_sclist(MMAIN, "M-]", do_find_bracket, 0);
+ add_to_sclist(MMAIN, "^^", do_mark, 0);
+ add_to_sclist(MMAIN, "M-A", do_mark, 0);
+ add_to_sclist(MMAIN, "F15", do_mark, 0);
+ add_to_sclist(MMAIN, "M-^", do_copy_text, 0);
+ add_to_sclist(MMAIN, "M-6", do_copy_text, 0);
+ add_to_sclist(MMAIN, "M-}", do_indent_void, 0);
+ add_to_sclist(MMAIN, "M-{", do_unindent, 0);
+ add_to_sclist(MMAIN, "M-U", do_undo, 0);
+ add_to_sclist(MMAIN, "M-E", do_redo, 0);
+#endif
+ add_to_sclist(MMOST, "^B", do_left, 0);
+ add_to_sclist(MMOST, "Left", do_left, 0);
+ add_to_sclist(MMOST, "^F", do_right, 0);
+ add_to_sclist(MMOST, "Right", do_right, 0);
+#ifndef NANO_TINY
+ add_to_sclist(MMOST, "M-Space", do_prev_word_void, 0);
+ add_to_sclist(MMOST, "^Space", do_next_word_void, 0);
+#endif
+ add_to_sclist(MMOST, "^A", do_home, 0);
+ add_to_sclist(MMOST, "Home", do_home, 0);
+ add_to_sclist(MMOST, "^E", do_end, 0);
+ add_to_sclist(MMOST, "End", do_end, 0);
+ add_to_sclist(MMAIN|MHELP|MBROWSER, "^P", do_up_void, 0);
+ add_to_sclist(MMAIN|MHELP|MBROWSER, "Up", do_up_void, 0);
+ add_to_sclist(MMAIN|MHELP|MBROWSER, "^N", do_down_void, 0);
+ add_to_sclist(MMAIN|MHELP|MBROWSER, "Down", do_down_void, 0);
+#ifndef DISABLE_JUSTIFY
+ add_to_sclist(MMAIN, "M-(", do_para_begin_void, 0);
+ add_to_sclist(MMAIN, "M-9", do_para_begin_void, 0);
+ add_to_sclist(MMAIN, "M-)", do_para_end_void, 0);
+ add_to_sclist(MMAIN, "M-0", do_para_end_void, 0);
#endif
-
-#ifndef DISABLE_HELP
- add_to_funcs( REFRESH_MSG, MHELP,
- refresh_msg, nano_refresh_msg, FALSE, VIEW);
-
- add_to_funcs(DO_EXIT, MHELP, exit_msg, IFSCHELP(nano_exit_msg), FALSE, VIEW);
-
-
+#ifndef NANO_TINY
+ add_to_sclist(MMAIN, "M--", do_scroll_up, 0);
+ add_to_sclist(MMAIN, "M-_", do_scroll_up, 0);
+ add_to_sclist(MMAIN, "M-+", do_scroll_down, 0);
+ add_to_sclist(MMAIN, "M-=", do_scroll_down, 0);
+#endif
+#ifndef DISABLE_MULTIBUFFER
+ add_to_sclist(MMAIN, "M-<", switch_to_prev_buffer_void, 0);
+ add_to_sclist(MMAIN, "M-,", switch_to_prev_buffer_void, 0);
+ add_to_sclist(MMAIN, "M->", switch_to_next_buffer_void, 0);
+ add_to_sclist(MMAIN, "M-.", switch_to_next_buffer_void, 0);
+#endif
+ add_to_sclist(MMOST, "M-V", do_verbatim_input, 0);
+#ifndef NANO_TINY
+ add_to_sclist(MMAIN, "M-T", do_cut_till_eof, 0);
+ add_to_sclist(MMAIN, "M-D", do_wordlinechar_count, 0);
#endif
+#ifndef DISABLE_JUSTIFY
+ add_to_sclist(MMAIN|MWHEREIS, "M-J", do_full_justify, 0);
+#endif
+ add_to_sclist(MMAIN|MHELP, "^L", total_refresh, 0);
+ add_to_sclist(MMAIN, "^Z", do_suspend_void, 0);
-#ifndef DISABLE_BROWSER
-
- add_to_funcs( FIRST_FILE_MSG,
- (MBROWSER|MWHEREISFILE),
- first_file_msg, IFSCHELP(nano_firstfile_msg), FALSE, VIEW);
+#ifndef NANO_TINY
+ /* Group of "Appearance" toggles. */
+ add_to_sclist(MMAIN, "M-X", do_toggle_void, NO_HELP);
+ add_to_sclist(MMAIN, "M-C", do_toggle_void, CONST_UPDATE);
+ add_to_sclist(MMAIN, "M-O", do_toggle_void, MORE_SPACE);
+ add_to_sclist(MMAIN, "M-S", do_toggle_void, SMOOTH_SCROLL);
+ add_to_sclist(MMAIN, "M-$", do_toggle_void, SOFTWRAP);
+ add_to_sclist(MMAIN, "M-P", do_toggle_void, WHITESPACE_DISPLAY);
+#ifndef DISABLE_COLOR
+ add_to_sclist(MMAIN, "M-Y", do_toggle_void, NO_COLOR_SYNTAX);
+#endif
- add_to_funcs( LAST_FILE_MSG,
- (MBROWSER|MWHEREISFILE),
- last_file_msg, IFSCHELP(nano_lastfile_msg), FALSE, VIEW);
+ /* Group of "Editing-behavior" toggles. */
+ add_to_sclist(MMAIN, "M-H", do_toggle_void, SMART_HOME);
+ add_to_sclist(MMAIN, "M-I", do_toggle_void, AUTOINDENT);
+ add_to_sclist(MMAIN, "M-K", do_toggle_void, CUT_TO_END);
+#ifndef DISABLE_WRAPPING
+ add_to_sclist(MMAIN, "M-L", do_toggle_void, NO_WRAP);
+#endif
+ add_to_sclist(MMAIN, "M-Q", do_toggle_void, TABS_TO_SPACES);
- add_to_funcs( GOTO_DIR_MSG, MBROWSER,
- goto_dir_msg, IFSCHELP(nano_gotodir_msg), FALSE, VIEW);
+ /* Group of "Peripheral-feature" toggles. */
+ add_to_sclist(MMAIN, "M-B", do_toggle_void, BACKUP_FILE);
+#ifndef DISABLE_MULTIBUFFER
+ add_to_sclist(MMAIN, "M-F", do_toggle_void, MULTIBUFFER);
+#endif
+#ifndef DISABLE_MOUSE
+ add_to_sclist(MMAIN, "M-M", do_toggle_void, USE_MOUSE);
#endif
+ add_to_sclist(MMAIN, "M-N", do_toggle_void, NO_CONVERT);
+ add_to_sclist(MMAIN, "M-Z", do_toggle_void, SUSPEND);
+#endif /* !NANO_TINY */
- currmenu = MMAIN;
+ add_to_sclist(MMAIN, "^Q", xon_complaint, 0);
+ add_to_sclist(MMAIN, "^S", xoff_complaint, 0);
+
+ add_to_sclist(((MMOST & ~MMAIN & ~MBROWSER) | MYESNO), "^C", do_cancel, 0);
- add_to_sclist(MMAIN|MWHEREIS|MREPLACE|MREPLACE2|MGOTOLINE|MWRITEFILE|MINSERTFILE|MEXTCMD|MSPELL|MBROWSER|MWHEREISFILE|MGOTODIR,
- "^G", DO_HELP_VOID, 0, TRUE);
- add_to_sclist(MMAIN|MWHEREIS|MREPLACE|MREPLACE2|MGOTOLINE|MWRITEFILE|MINSERTFILE|MEXTCMD|MSPELL|MBROWSER|MWHEREISFILE|MGOTODIR,
- "F1", DO_HELP_VOID, 0, TRUE);
- add_to_sclist(MMAIN|MHELP|MBROWSER, "^X", DO_EXIT, 0, TRUE);
- add_to_sclist(MMAIN|MHELP|MBROWSER, "F2", DO_EXIT, 0, TRUE);
- add_to_sclist(MMAIN, "^_", DO_GOTOLINECOLUMN_VOID, 0, TRUE);
- add_to_sclist(MMAIN, "F13", DO_GOTOLINECOLUMN_VOID, 0, TRUE);
- add_to_sclist(MMAIN, "M-G", DO_GOTOLINECOLUMN_VOID, 0, TRUE);
- add_to_sclist(MMAIN, "^O", DO_WRITEOUT_VOID, 0, TRUE);
- add_to_sclist(MMAIN, "F3", DO_WRITEOUT_VOID, 0, TRUE);
-#ifndef DISABLE_JUSTIFY
- add_to_sclist(MMAIN, "^J", DO_JUSTIFY_VOID, 0, TRUE);
- add_to_sclist(MMAIN, "F4", DO_JUSTIFY_VOID, 0, TRUE);
-#endif
- add_to_sclist(MMAIN, "^R", DO_INSERTFILE_VOID, 0, TRUE);
- add_to_sclist(MMAIN, "F5", DO_INSERTFILE_VOID, 0, TRUE);
- add_to_sclist(MMAIN, "kinsert", DO_INSERTFILE_VOID, 0, TRUE);
- add_to_sclist(MMAIN|MBROWSER, "^W", DO_SEARCH, 0, TRUE);
- add_to_sclist(MMAIN|MBROWSER, "F6", DO_SEARCH, 0, TRUE);
- add_to_sclist(MMAIN|MBROWSER|MHELP|MWHEREISFILE, "^Y", DO_PAGE_UP, 0, TRUE);
- add_to_sclist(MMAIN|MBROWSER|MHELP|MWHEREISFILE, "F7", DO_PAGE_UP, 0, TRUE);
- add_to_sclist(MMAIN|MBROWSER|MHELP|MWHEREISFILE, "kpup", DO_PAGE_UP, 0, TRUE);
- add_to_sclist(MMAIN|MBROWSER|MHELP|MWHEREISFILE, "^V", DO_PAGE_DOWN, 0, TRUE);
- add_to_sclist(MMAIN|MBROWSER|MHELP|MWHEREISFILE, "F8", DO_PAGE_DOWN, 0, TRUE);
- add_to_sclist(MMAIN|MBROWSER|MHELP|MWHEREISFILE, "kpdown", DO_PAGE_DOWN, 0, TRUE);
- add_to_sclist(MMAIN, "^K", DO_CUT_TEXT_VOID, 0, TRUE);
- add_to_sclist(MMAIN, "F9", DO_CUT_TEXT_VOID, 0, TRUE);
- add_to_sclist(MMAIN, "^U", DO_UNCUT_TEXT, 0, TRUE);
- add_to_sclist(MMAIN, "F10", DO_UNCUT_TEXT, 0, TRUE);
- add_to_sclist(MMAIN, "^C", DO_CURSORPOS_VOID, 0, TRUE);
- add_to_sclist(MMAIN, "F11", DO_CURSORPOS_VOID, 0, TRUE);
-#ifndef DISABLE_SPELLER
- add_to_sclist(MMAIN, "^T", DO_SPELL, 0, TRUE);
- add_to_sclist(MMAIN, "F12", DO_SPELL, 0, TRUE);
-#endif
- add_to_sclist(MMAIN, "^\\", DO_REPLACE, 0, TRUE);
- add_to_sclist(MMAIN, "F14", DO_REPLACE, 0, TRUE);
- add_to_sclist(MMAIN, "M-R", DO_REPLACE, 0, TRUE);
- add_to_sclist(MWHEREIS, "^R", DO_REPLACE, 0, FALSE);
- add_to_sclist(MREPLACE, "^R", NO_REPLACE_MSG, 0, FALSE);
- add_to_sclist(MWHEREIS, "^T", DO_GOTOLINECOLUMN_VOID, 0, FALSE);
-#ifndef NANO_TINY
- add_to_sclist(MMAIN, "^^", DO_MARK, 0, TRUE);
- add_to_sclist(MMAIN, "F15", DO_MARK, 0, TRUE);
- add_to_sclist(MMAIN, "M-A", DO_MARK, 0, TRUE);
- add_to_sclist(MMAIN|MBROWSER, "M-W", DO_RESEARCH, 0, TRUE);
- add_to_sclist(MMAIN|MBROWSER, "F16", DO_RESEARCH, 0, TRUE);
- add_to_sclist(MMAIN, "M-^", DO_COPY_TEXT, 0, TRUE);
- add_to_sclist(MMAIN, "M-6", DO_COPY_TEXT, 0, TRUE);
- add_to_sclist(MMAIN, "M-}", DO_INDENT_VOID, 0, TRUE);
- add_to_sclist(MMAIN, "M-{", DO_UNINDENT, 0, TRUE);
- if (ISSET(UNDOABLE)) {
- add_to_sclist(MMAIN, "M-U", DO_UNDO, 0, TRUE);
- add_to_sclist(MMAIN, "M-E", DO_REDO, 0, TRUE);
- }
- add_to_sclist(MALL, "^F", DO_RIGHT, 0, TRUE);
- add_to_sclist(MALL, "^B", DO_LEFT, 0, TRUE);
- add_to_sclist(MMAIN, "^Space", DO_NEXT_WORD_VOID, 0, TRUE);
- add_to_sclist(MMAIN, "M-Space", DO_PREV_WORD_VOID, 0, TRUE);
-#endif
- add_to_sclist(MALL, "kright", DO_RIGHT, 0, TRUE);
- add_to_sclist(MALL, "kleft", DO_LEFT, 0, TRUE);
- add_to_sclist(MMAIN, "^Q", XON_COMPLAINT, 0, TRUE);
- add_to_sclist(MMAIN, "^S", XOFF_COMPLAINT, 0, TRUE);
- add_to_sclist(MMAIN|MHELP|MBROWSER, "^P", DO_UP_VOID, 0, TRUE);
- add_to_sclist(MMAIN|MHELP|MBROWSER, "kup", DO_UP_VOID, 0, TRUE);
- add_to_sclist(MMAIN|MHELP|MBROWSER, "^N", DO_DOWN_VOID, 0, TRUE);
- add_to_sclist(MMAIN|MHELP|MBROWSER, "kdown", DO_DOWN_VOID, 0, TRUE);
- add_to_sclist(MALL, "^A", DO_HOME, 0, TRUE);
- add_to_sclist(MALL, "khome", DO_HOME, 0, TRUE);
- add_to_sclist(MALL, "^E", DO_END, 0, TRUE);
- add_to_sclist(MALL, "kend", DO_END, 0, TRUE);
#ifndef NANO_TINY
- add_to_sclist(MWHEREIS|MREPLACE|MREPLACE2|MWHEREISFILE, "^P", PREV_HISTORY_MSG, 0, FALSE);
- add_to_sclist(MWHEREIS|MREPLACE|MREPLACE2|MWHEREISFILE, "kup", PREV_HISTORY_MSG, 0, FALSE);
- add_to_sclist(MWHEREIS|MREPLACE|MREPLACE2|MWHEREISFILE, "^N", NEXT_HISTORY_MSG, 0, FALSE);
- add_to_sclist(MWHEREIS|MREPLACE|MREPLACE2|MWHEREISFILE, "kdown", NEXT_HISTORY_MSG, 0, FALSE);
+ add_to_sclist(MWHEREIS|MREPLACE, "M-B", backwards_void, 0);
+ add_to_sclist(MWHEREIS|MREPLACE, "M-C", case_sens_void, 0);
#endif
+ add_to_sclist(MWHEREIS|MREPLACE, "M-R", regexp_void, 0);
+ add_to_sclist(MWHEREIS|MREPLACE, "^R", flip_replace_void, 0);
+ add_to_sclist(MWHEREIS|MREPLACE|MREPLACEWITH|MGOTOLINE, "^Y", do_first_line, 0);
+ add_to_sclist(MWHEREIS|MREPLACE|MREPLACEWITH|MGOTOLINE, "^V", do_last_line, 0);
#ifndef DISABLE_JUSTIFY
- add_to_sclist(MWHEREIS|MREPLACE|MREPLACE2,
- "^W", DO_PARA_BEGIN_VOID, 0, TRUE);
- add_to_sclist(MWHEREIS|MREPLACE|MREPLACE2,
- "^O", DO_PARA_END_VOID, 0, TRUE);
- add_to_sclist(MALL, "M-(", DO_PARA_BEGIN_VOID, 0, TRUE);
- add_to_sclist(MALL, "M-9", DO_PARA_BEGIN_VOID, 0, TRUE);
- add_to_sclist(MALL, "M-)", DO_PARA_END_VOID, 0, TRUE);
- add_to_sclist(MALL, "M-0", DO_PARA_END_VOID, 0, TRUE);
-#endif
- add_to_sclist(MWHEREIS,
- "M-C", CASE_SENS_MSG, 0, FALSE);
- add_to_sclist(MREPLACE,
- "M-C", CASE_SENS_MSG, 0, FALSE);
- add_to_sclist(MREPLACE2,
- "M-C", CASE_SENS_MSG, 0, FALSE);
- add_to_sclist(MWHEREIS|MREPLACE|MREPLACE2,
- "M-B", BACKWARDS_MSG, 0, FALSE);
- add_to_sclist(MWHEREIS|MREPLACE|MREPLACE2,
- "M-R", REGEXP_MSG, 0, FALSE);
-
- add_to_sclist(MMAIN, "M-\\", DO_FIRST_LINE, 0, TRUE);
- add_to_sclist(MMAIN, "M-|", DO_FIRST_LINE, 0, TRUE);
- add_to_sclist(MMAIN, "M-/", DO_LAST_LINE, 0, TRUE);
- add_to_sclist(MMAIN, "M-?", DO_LAST_LINE, 0, TRUE);
- add_to_sclist(MWHEREIS|MREPLACE|MREPLACE2|MGOTOLINE|MHELP,
- "^Y", DO_FIRST_LINE, 0, TRUE);
- add_to_sclist(MWHEREIS|MREPLACE|MREPLACE2|MGOTOLINE|MHELP,
- "^V", DO_LAST_LINE, 0, TRUE);
-
- add_to_sclist(MBROWSER|MWHEREISFILE, "M-\\", FIRST_FILE_MSG, 0, TRUE);
- add_to_sclist(MBROWSER|MWHEREISFILE, "M-|", FIRST_FILE_MSG, 0, TRUE);
- add_to_sclist(MBROWSER|MWHEREISFILE, "M-/", LAST_FILE_MSG, 0, TRUE);
- add_to_sclist(MBROWSER|MWHEREISFILE, "M-?", LAST_FILE_MSG, 0, TRUE);
- add_to_sclist(MBROWSER|MWHEREISFILE, "^_", GOTO_DIR_MSG, 0, TRUE);
- add_to_sclist(MBROWSER|MWHEREISFILE, "F13", GOTO_DIR_MSG, 0, TRUE);
- add_to_sclist(MBROWSER|MWHEREISFILE, "M-G", GOTO_DIR_MSG, 0, TRUE);
-#ifndef NANO_TINY
- add_to_sclist(MMAIN, "M-]", DO_FIND_BRACKET, 0, TRUE);
- add_to_sclist(MMAIN, "M--", DO_SCROLL_UP, 0, TRUE);
- add_to_sclist(MMAIN, "M-_", DO_SCROLL_UP, 0, TRUE);
- add_to_sclist(MMAIN, "M-+", DO_SCROLL_DOWN, 0, TRUE);
- add_to_sclist(MMAIN, "M-=", DO_SCROLL_DOWN, 0, TRUE);
+ add_to_sclist(MWHEREIS|MREPLACE|MREPLACEWITH, "^W", do_para_begin_void, 0);
+ add_to_sclist(MWHEREIS|MREPLACE|MREPLACEWITH, "^O", do_para_end_void, 0);
#endif
-
-#ifdef ENABLE_MULTIBUFFER
- add_to_sclist(MMAIN, "M-<", SWITCH_TO_PREV_BUFFER_VOID, 0, TRUE);
- add_to_sclist(MMAIN, "M-,", SWITCH_TO_PREV_BUFFER_VOID, 0, TRUE);
- add_to_sclist(MMAIN, "M->", SWITCH_TO_NEXT_BUFFER_VOID, 0, TRUE);
- add_to_sclist(MMAIN, "M-.", SWITCH_TO_NEXT_BUFFER_VOID, 0, TRUE);
+ add_to_sclist(MWHEREIS, "^T", do_gotolinecolumn_void, 0);
+ add_to_sclist(MGOTOLINE, "^T", gototext_void, 0);
+#ifndef DISABLE_HISTORIES
+ add_to_sclist(MWHEREIS|MREPLACE|MREPLACEWITH|MWHEREISFILE, "^P", get_history_older_void, 0);
+ add_to_sclist(MWHEREIS|MREPLACE|MREPLACEWITH|MWHEREISFILE, "Up", get_history_older_void, 0);
+ add_to_sclist(MWHEREIS|MREPLACE|MREPLACEWITH|MWHEREISFILE, "^N", get_history_newer_void, 0);
+ add_to_sclist(MWHEREIS|MREPLACE|MREPLACEWITH|MWHEREISFILE, "Down", get_history_newer_void, 0);
#endif
- add_to_sclist(MALL, "M-V", DO_VERBATIM_INPUT, 0, TRUE);
-#ifndef NANO_TINY
- add_to_sclist(MALL, "M-T", DO_CUT_TILL_END, 0, TRUE);
-#ifndef DISABLE_JUSTIFY
- add_to_sclist(MALL, "M-J", DO_FULL_JUSTIFY, 0, TRUE);
-#endif
- add_to_sclist(MMAIN, "M-D", DO_WORDLINECHAR_COUNT, 0, TRUE);
- add_to_sclist(MMAIN, "M-X", DO_TOGGLE, NO_HELP, TRUE);
- add_to_sclist(MMAIN, "M-C", DO_TOGGLE, CONST_UPDATE, TRUE);
- add_to_sclist(MMAIN, "M-O", DO_TOGGLE, MORE_SPACE, TRUE);
- add_to_sclist(MMAIN, "M-S", DO_TOGGLE, SMOOTH_SCROLL, TRUE);
- add_to_sclist(MMAIN, "M-P", DO_TOGGLE, WHITESPACE_DISPLAY, TRUE);
- add_to_sclist(MMAIN, "M-Y", DO_TOGGLE, NO_COLOR_SYNTAX, TRUE);
- add_to_sclist(MMAIN, "M-H", DO_TOGGLE, SMART_HOME, TRUE);
- add_to_sclist(MMAIN, "M-I", DO_TOGGLE, AUTOINDENT, TRUE);
- add_to_sclist(MMAIN, "M-K", DO_TOGGLE, CUT_TO_END, TRUE);
- add_to_sclist(MMAIN, "M-L", DO_TOGGLE, NO_WRAP, TRUE);
- add_to_sclist(MMAIN, "M-Q", DO_TOGGLE, TABS_TO_SPACES, TRUE);
- add_to_sclist(MMAIN, "M-B", DO_TOGGLE, BACKUP_FILE, TRUE);
- add_to_sclist(MMAIN, "M-F", DO_TOGGLE, MULTIBUFFER, TRUE);
- add_to_sclist(MMAIN, "M-M", DO_TOGGLE, USE_MOUSE, TRUE);
- add_to_sclist(MMAIN, "M-N", DO_TOGGLE, NO_CONVERT, TRUE);
- add_to_sclist(MMAIN, "M-Z", DO_TOGGLE, SUSPEND, TRUE);
- add_to_sclist(MMAIN, "M-$", DO_TOGGLE, SOFTWRAP, TRUE);
-#endif
- add_to_sclist(MGOTOLINE, "^T", GOTOTEXT_MSG, 0, FALSE);
- add_to_sclist(MINSERTFILE|MEXTCMD, "M-F", NEW_BUFFER_MSG, 0, FALSE);
- add_to_sclist((MWHEREIS|MREPLACE|MREPLACE2|MGOTOLINE|MWRITEFILE|MINSERTFILE|MEXTCMD|MSPELL|MWHEREISFILE|MGOTODIR|MYESNO),
- "^C", CANCEL_MSG, 0, FALSE);
- add_to_sclist(MHELP, "^X", DO_EXIT, 0, TRUE);
- add_to_sclist(MHELP, "F2", DO_EXIT, 0, TRUE);
- add_to_sclist(MWRITEFILE, "M-D", DOS_FORMAT_MSG, 0, FALSE);
- add_to_sclist(MWRITEFILE, "M-M", MAC_FORMAT_MSG, 0, FALSE);
- add_to_sclist(MWRITEFILE, "M-A", APPEND_MSG, 0, FALSE);
- add_to_sclist(MWRITEFILE, "M-P", PREPEND_MSG, 0, FALSE);
- add_to_sclist(MWRITEFILE, "M-B", BACKUP_FILE_MSG, 0, FALSE);
- add_to_sclist(MWRITEFILE, "^T", TO_FILES_MSG, 0, FALSE);
- add_to_sclist(MINSERTFILE, "^T", TO_FILES_MSG, 0, FALSE);
- add_to_sclist(MINSERTFILE, "^X", EXT_CMD_MSG, 0, FALSE);
- add_to_sclist(MMAIN, "^Z", DO_SUSPEND_VOID, 0, FALSE);
- add_to_sclist(MMAIN, "^L", TOTAL_REFRESH, 0, TRUE);
- add_to_sclist(MALL, "^I", DO_TAB, 0, TRUE);
- add_to_sclist(MALL, "^M", DO_ENTER, 0, TRUE);
- add_to_sclist(MALL, "kenter", DO_ENTER, 0, TRUE);
- add_to_sclist(MALL, "^D", DO_DELETE, 0, TRUE);
- add_to_sclist(MALL, "kdel", DO_DELETE, 0, TRUE);
- add_to_sclist(MALL, "^H", DO_BACKSPACE, 0, TRUE);
- add_to_sclist(MALL, "kbsp", DO_BACKSPACE, 0, TRUE);
+#ifndef DISABLE_BROWSER
+ add_to_sclist(MBROWSER|MWHEREISFILE, "M-\\", do_first_file, 0);
+ add_to_sclist(MBROWSER|MWHEREISFILE, "M-|", do_first_file, 0);
+ add_to_sclist(MBROWSER|MWHEREISFILE, "M-/", do_last_file, 0);
+ add_to_sclist(MBROWSER|MWHEREISFILE, "M-?", do_last_file, 0);
+ add_to_sclist(MBROWSER|MWHEREISFILE, "^_", goto_dir_void, 0);
+ add_to_sclist(MBROWSER|MWHEREISFILE, "M-G", goto_dir_void, 0);
+ add_to_sclist(MBROWSER|MWHEREISFILE, "F13", goto_dir_void, 0);
+#endif
+ add_to_sclist(MWRITEFILE, "M-D", dos_format_void, 0);
+ add_to_sclist(MWRITEFILE, "M-M", mac_format_void, 0);
+ add_to_sclist(MWRITEFILE, "M-A", append_void, 0);
+ add_to_sclist(MWRITEFILE, "M-P", prepend_void, 0);
+ add_to_sclist(MWRITEFILE, "M-B", backup_file_void, 0);
+#ifndef DISABLE_BROWSER
+ add_to_sclist(MWRITEFILE|MINSERTFILE, "^T", to_files_void, 0);
+#endif
+ add_to_sclist(MINSERTFILE|MEXTCMD, "^X", flip_execute_void, 0);
+ add_to_sclist(MINSERTFILE|MEXTCMD, "M-F", new_buffer_void, 0);
+ add_to_sclist(MHELP|MBROWSER, "^C", do_exit, 0);
+#ifndef DISABLE_HELP
+ add_to_sclist(MHELP, "^G", do_exit, 0);
+#endif
+ add_to_sclist(MMOST, "^I", do_tab, 0);
+ add_to_sclist(MMOST, "^M", do_enter_void, 0);
+ add_to_sclist(MMOST, "Enter", do_enter_void, 0);
+ add_to_sclist(MMOST, "^D", do_delete, 0);
+ add_to_sclist(MMOST, "Del", do_delete, 0);
+ add_to_sclist(MMOST, "^H", do_backspace, 0);
+ add_to_sclist(MMOST, "Bsp", do_backspace, 0);
#ifdef DEBUG
print_sclist();
#endif
-
}
-/* Given a function alias, execute the proper
- function, and then me */
-void iso_me_harder_funcmap(short func)
+#ifndef DISABLE_COLOR
+void set_lint_or_format_shortcuts(void)
{
- if (func == TOTAL_REFRESH)
- total_refresh();
- else if (func == DO_HELP_VOID)
- do_help_void();
- else if (func == DO_SEARCH)
- do_search();
- else if (func == DO_PAGE_UP)
- do_page_up();
- else if (func == DO_PAGE_DOWN)
- do_page_down();
- else if (func == DO_UP_VOID)
- do_up_void();
- else if (func == DO_LEFT)
- do_left();
- else if (func == DO_DOWN_VOID)
- do_down_void();
- else if (func == DO_RIGHT)
- do_right();
- else if (func == DO_ENTER)
- do_enter(FALSE);
- else if (func == DO_EXIT)
- do_exit();
- else if (func == DO_FIRST_LINE)
- do_first_line();
- else if (func == DO_LAST_LINE)
- do_last_line();
- else if (func == DO_BACKSPACE)
- do_backspace();
- else if (func == DO_DELETE)
- do_delete();
- else if (func == DO_TAB)
- do_tab();
- else if (func == DO_VERBATIM_INPUT)
- do_verbatim_input();
-#ifdef ENABLE_MULTIBUFFER
- else if (func == SWITCH_TO_NEXT_BUFFER_VOID)
- switch_to_next_buffer_void();
- else if (func == SWITCH_TO_PREV_BUFFER_VOID)
- switch_to_prev_buffer_void();
-#endif
- else if (func == DO_END)
- do_end();
- else if (func == DO_HOME)
- do_home();
- else if (func == DO_SUSPEND_VOID)
- do_suspend_void();
- else if (func == DO_WRITEOUT_VOID)
- do_writeout_void();
- else if (func == DO_INSERTFILE_VOID)
- do_insertfile_void();
- else if (func == DO_CUT_TEXT_VOID)
- do_cut_text_void();
- else if (func == DO_UNCUT_TEXT)
- do_uncut_text();
- else if (func == DO_CURSORPOS_VOID)
- do_cursorpos_void();
- else if (func == DO_GOTOLINECOLUMN_VOID)
- do_gotolinecolumn_void();
- else if (func == DO_REPLACE)
- do_replace();
- else if (func == XOFF_COMPLAINT)
- xoff_complaint();
- else if (func == XON_COMPLAINT)
- xon_complaint();
- else if (func == DO_CUT_TEXT)
- do_cut_text_void();
-#ifndef NANO_TINY
- else if (func == DO_CUT_TILL_END)
- do_cut_till_end();
- else if (func == DO_REDO)
- do_redo();
- else if (func == DO_UNDO)
- do_undo();
- else if (func == DO_WORDLINECHAR_COUNT)
- do_wordlinechar_count();
- else if (func == DO_FIND_BRACKET)
- do_find_bracket();
- else if (func == DO_PREV_WORD_VOID)
- do_prev_word_void();
-#ifndef DISABLE_JUSTIFY
- else if (func == DO_JUSTIFY_VOID)
- do_justify_void();
- else if (func == DO_PARA_BEGIN_VOID)
- do_para_begin_void();
- else if (func == DO_PARA_END_VOID)
- do_para_end_void();
- else if (func == DO_FULL_JUSTIFY)
- do_full_justify();
-#endif
- else if (func == DO_MARK)
- do_mark();
- else if (func == DO_RESEARCH)
- do_research();
- else if (func == DO_COPY_TEXT)
- do_copy_text();
- else if (func == DO_INDENT_VOID)
- do_indent_void();
- else if (func == DO_UNINDENT)
- do_unindent();
- else if (func == DO_SCROLL_UP)
- do_scroll_up();
- else if (func == DO_SCROLL_DOWN)
- do_scroll_down();
- else if (func == DO_NEXT_WORD_VOID)
- do_next_word_void();
#ifndef DISABLE_SPELLER
- else if (func == DO_SPELL)
- do_spell();
-#endif
- else if (func == DO_NEXT_WORD)
- do_next_word_void();
- else if (func == DO_PREV_WORD)
- do_prev_word_void();
+ if (openfile->syntax->formatter) {
+ replace_scs_for(do_spell, do_formatter);
+ replace_scs_for(do_linter, do_formatter);
+ } else {
+ replace_scs_for(do_spell, do_linter);
+ replace_scs_for(do_formatter, do_linter);
+ }
#endif
}
-
-/* Free the given shortcut. */
-void free_shortcutage(shortcut **shortcutage)
+void set_spell_shortcuts(void)
{
- assert(shortcutage != NULL);
-
- while (*shortcutage != NULL) {
- shortcut *ps = *shortcutage;
- *shortcutage = (*shortcutage)->next;
- free(ps);
- }
+#ifndef DISABLE_SPELLER
+ replace_scs_for(do_formatter, do_spell);
+ replace_scs_for(do_linter, do_spell);
+#endif
}
+#endif
const subnfunc *sctofunc(sc *s)
{
@@ -1358,12 +1216,14 @@ const subnfunc *sctofunc(sc *s)
}
#ifndef NANO_TINY
-/* Now lets come up with a single (hopefully)
- function to get a string for each flag */
+/* Now let's come up with a single (hopefully) function to get a string
+ * for each flag. */
const char *flagtostr(int flag)
{
- switch (flag) {
+ switch (flag) {
case NO_HELP:
+ /* TRANSLATORS: The next seventeen strings are toggle descriptions;
+ * they are best kept shorter than 40 characters, but may be longer. */
return N_("Help mode");
case CONST_UPDATE:
return N_("Constant cursor position display");
@@ -1371,6 +1231,8 @@ const char *flagtostr(int flag)
return N_("Use of one more line for editing");
case SMOOTH_SCROLL:
return N_("Smooth scrolling");
+ case SOFTWRAP:
+ return N_("Soft wrapping of overlong lines");
case WHITESPACE_DISPLAY:
return N_("Whitespace display");
case NO_COLOR_SYNTAX:
@@ -1382,7 +1244,7 @@ const char *flagtostr(int flag)
case CUT_TO_END:
return N_("Cut to end");
case NO_WRAP:
- return N_("Long line wrapping");
+ return N_("Hard wrapping of overlong lines");
case TABS_TO_SPACES:
return N_("Conversion of typed tabs to spaces");
case BACKUP_FILE:
@@ -1395,270 +1257,254 @@ const char *flagtostr(int flag)
return N_("No conversion from DOS/Mac format");
case SUSPEND:
return N_("Suspension");
- case SOFTWRAP:
- return N_("Soft line wrapping");
default:
return "?????";
}
}
-#endif /* NANO_TINY */
+#endif /* !NANO_TINY */
-/* Interpret the string given by the rc file and return a
- shortcut struct, complete with proper value for execute */
-sc *strtosc(int menu, char *input)
+#ifndef DISABLE_NANORC
+/* Interpret a function string given in the rc file, and return a
+ * shortcut struct with the corresponding function filled in. */
+sc *strtosc(char *input)
{
- sc *s;
+ sc *s;
s = (sc *)nmalloc(sizeof(sc));
- s->execute = TRUE; /* overridden as needed below */
-
#ifndef DISABLE_HELP
if (!strcasecmp(input, "help"))
- s->scfunc = DO_HELP_VOID;
- else
-#endif
- if (!strcasecmp(input, "cancel")) {
- s->scfunc = CANCEL_MSG;
- s->execute = FALSE;
- } else if (!strcasecmp(input, "exit"))
- s->scfunc = DO_EXIT;
+ s->scfunc = do_help_void;
+ else
+#endif
+ if (!strcasecmp(input, "cancel"))
+ s->scfunc = do_cancel;
+ else if (!strcasecmp(input, "exit"))
+ s->scfunc = do_exit;
else if (!strcasecmp(input, "writeout"))
- s->scfunc = DO_WRITEOUT_VOID;
+ s->scfunc = do_writeout_void;
else if (!strcasecmp(input, "insert"))
- s->scfunc = DO_INSERTFILE_VOID;
+ s->scfunc = do_insertfile_void;
else if (!strcasecmp(input, "whereis"))
- s->scfunc = DO_SEARCH;
- else if (!strcasecmp(input, "up"))
- s->scfunc = DO_UP_VOID;
- else if (!strcasecmp(input, "down"))
- s->scfunc = DO_DOWN_VOID;
- else if (!strcasecmp(input, "pageup")
- || !strcasecmp(input, "prevpage"))
- s->scfunc = DO_PAGE_UP;
- else if (!strcasecmp(input, "pagedown")
- || !strcasecmp(input, "nextpage"))
- s->scfunc = DO_PAGE_DOWN;
+ s->scfunc = do_search;
+#ifndef NANO_TINY
+ else if (!strcasecmp(input, "searchagain") ||
+ !strcasecmp(input, "research"))
+ s->scfunc = do_research;
+#endif
+ else if (!strcasecmp(input, "replace"))
+ s->scfunc = do_replace;
else if (!strcasecmp(input, "cut"))
- s->scfunc = DO_CUT_TEXT_VOID;
+ s->scfunc = do_cut_text_void;
else if (!strcasecmp(input, "uncut"))
- s->scfunc = DO_UNCUT_TEXT;
+ s->scfunc = do_uncut_text;
+#ifndef NANO_TINY
+ else if (!strcasecmp(input, "cutrestoffile"))
+ s->scfunc = do_cut_till_eof;
+ else if (!strcasecmp(input, "copytext"))
+ s->scfunc = do_copy_text;
+ else if (!strcasecmp(input, "mark"))
+ s->scfunc = do_mark;
+#endif
+#ifndef DISABLE_SPELLER
+ else if (!strcasecmp(input, "tospell") ||
+ !strcasecmp(input, "speller"))
+ s->scfunc = do_spell;
+#endif
else if (!strcasecmp(input, "curpos") ||
- !strcasecmp(input, "cursorpos"))
- s->scfunc = DO_CURSORPOS_VOID;
- else if (!strcasecmp(input, "firstline"))
- s->scfunc = DO_FIRST_LINE;
- else if (!strcasecmp(input, "lastline"))
- s->scfunc = DO_LAST_LINE;
+ !strcasecmp(input, "cursorpos"))
+ s->scfunc = do_cursorpos_void;
else if (!strcasecmp(input, "gotoline"))
- s->scfunc = DO_GOTOLINECOLUMN_VOID;
- else if (!strcasecmp(input, "replace"))
- s->scfunc = DO_REPLACE;
+ s->scfunc = do_gotolinecolumn_void;
#ifndef DISABLE_JUSTIFY
else if (!strcasecmp(input, "justify"))
- s->scfunc = DO_JUSTIFY_VOID;
+ s->scfunc = do_justify_void;
+ else if (!strcasecmp(input, "fulljustify"))
+ s->scfunc = do_full_justify;
else if (!strcasecmp(input, "beginpara"))
- s->scfunc = DO_PARA_BEGIN_VOID;
+ s->scfunc = do_para_begin_void;
else if (!strcasecmp(input, "endpara"))
- s->scfunc = DO_PARA_END_VOID;
- else if (!strcasecmp(input, "fulljustify"))
- s->scfunc = DO_FULL_JUSTIFY;
+ s->scfunc = do_para_end_void;
#endif
#ifndef NANO_TINY
- else if (!strcasecmp(input, "mark"))
- s->scfunc = DO_MARK;
- else if (!strcasecmp(input, "searchagain") ||
- !strcasecmp(input, "research"))
- s->scfunc = DO_RESEARCH;
- else if (!strcasecmp(input, "copytext"))
- s->scfunc = DO_COPY_TEXT;
else if (!strcasecmp(input, "indent"))
- s->scfunc = DO_INDENT_VOID;
+ s->scfunc = do_indent_void;
else if (!strcasecmp(input, "unindent"))
- s->scfunc = DO_UNINDENT;
+ s->scfunc = do_unindent;
else if (!strcasecmp(input, "scrollup"))
- s->scfunc = DO_SCROLL_UP;
+ s->scfunc = do_scroll_up;
else if (!strcasecmp(input, "scrolldown"))
- s->scfunc = DO_SCROLL_DOWN;
- else if (!strcasecmp(input, "nextword"))
- s->scfunc = DO_NEXT_WORD_VOID;
- else if (!strcasecmp(input, "suspend"))
- s->scfunc = DO_SUSPEND_VOID;
+ s->scfunc = do_scroll_down;
else if (!strcasecmp(input, "prevword"))
- s->scfunc = DO_PREV_WORD_VOID;
+ s->scfunc = do_prev_word_void;
+ else if (!strcasecmp(input, "nextword"))
+ s->scfunc = do_next_word_void;
else if (!strcasecmp(input, "findbracket"))
- s->scfunc = DO_FIND_BRACKET;
+ s->scfunc = do_find_bracket;
else if (!strcasecmp(input, "wordcount"))
- s->scfunc = DO_WORDLINECHAR_COUNT;
+ s->scfunc = do_wordlinechar_count;
else if (!strcasecmp(input, "undo"))
- s->scfunc = DO_UNDO;
+ s->scfunc = do_undo;
else if (!strcasecmp(input, "redo"))
- s->scfunc = DO_REDO;
- else if (!strcasecmp(input, "prevhistory")) {
- s->scfunc = PREV_HISTORY_MSG;
- s->execute = FALSE;
- } else if (!strcasecmp(input, "nexthistory")) {
- s->scfunc = NEXT_HISTORY_MSG;
- s->execute = FALSE;
- } else if (!strcasecmp(input, "nohelp") ||
- !strcasecmp(input, "nohelp")) {
- s->scfunc = DO_TOGGLE;
- s->execute = FALSE;
- s->toggle = NO_HELP;
- } else if (!strcasecmp(input, "constupdate")) {
- s->scfunc = DO_TOGGLE;
- s->execute = FALSE;
- s->toggle = CONST_UPDATE;
- } else if (!strcasecmp(input, "morespace")) {
- s->scfunc = DO_TOGGLE;
- s->execute = FALSE;
- s->toggle = MORE_SPACE;
- } else if (!strcasecmp(input, "smoothscroll")) {
- s->scfunc = DO_TOGGLE;
- s->execute = FALSE;
- s->toggle = SMOOTH_SCROLL;
- } else if (!strcasecmp(input, "whitespacedisplay")) {
- s->scfunc = DO_TOGGLE;
- s->execute = FALSE;
- s->toggle = WHITESPACE_DISPLAY;
- } else if (!strcasecmp(input, "nosyntax")) {
- s->scfunc = DO_TOGGLE;
- s->execute = FALSE;
- s->toggle = NO_COLOR_SYNTAX;
- } else if (!strcasecmp(input, "smarthome")) {
- s->scfunc = DO_TOGGLE;
- s->execute = FALSE;
- s->toggle = SMART_HOME;
- } else if (!strcasecmp(input, "autoindent")) {
- s->scfunc = DO_TOGGLE;
- s->execute = FALSE;
- s->toggle = AUTOINDENT;
- } else if (!strcasecmp(input, "cuttoend")) {
- s->scfunc = DO_TOGGLE;
- s->execute = FALSE;
- s->toggle = CUT_TO_END;
- } else if (!strcasecmp(input, "nowrap")) {
- s->scfunc = DO_TOGGLE;
- s->execute = FALSE;
- s->toggle = NO_WRAP;
- } else if (!strcasecmp(input, "tabstospaces")) {
- s->scfunc = DO_TOGGLE;
- s->execute = FALSE;
- s->toggle = TABS_TO_SPACES;
- } else if (!strcasecmp(input, "backupfile")) {
- s->scfunc = DO_TOGGLE;
- s->execute = FALSE;
- s->toggle = BACKUP_FILE;
- } else if (!strcasecmp(input, "mutlibuffer")) {
- s->scfunc = DO_TOGGLE;
- s->execute = FALSE;
- s->toggle = MULTIBUFFER;
- } else if (!strcasecmp(input, "mouse")) {
- s->scfunc = DO_TOGGLE;
- s->execute = FALSE;
- s->toggle = USE_MOUSE;
- } else if (!strcasecmp(input, "noconvert")) {
- s->scfunc = DO_TOGGLE;
- s->execute = FALSE;
- s->toggle = NO_CONVERT;
- } else if (!strcasecmp(input, "suspendenable")) {
- s->scfunc = DO_TOGGLE;
- s->execute = FALSE;
- s->toggle = SUSPEND;
- }
-#endif /* NANO_TINY */
- else if (!strcasecmp(input, "right") ||
- !strcasecmp(input, "forward"))
- s->scfunc = DO_RIGHT;
+ s->scfunc = do_redo;
+#endif
else if (!strcasecmp(input, "left") ||
- !strcasecmp(input, "back"))
- s->scfunc = DO_LEFT;
+ !strcasecmp(input, "back"))
+ s->scfunc = do_left;
+ else if (!strcasecmp(input, "right") ||
+ !strcasecmp(input, "forward"))
+ s->scfunc = do_right;
else if (!strcasecmp(input, "up") ||
- !strcasecmp(input, "prevline"))
- s->scfunc = DO_UP_VOID;
+ !strcasecmp(input, "prevline"))
+ s->scfunc = do_up_void;
else if (!strcasecmp(input, "down") ||
- !strcasecmp(input, "nextline"))
- s->scfunc = DO_DOWN_VOID;
+ !strcasecmp(input, "nextline"))
+ s->scfunc = do_down_void;
else if (!strcasecmp(input, "home"))
- s->scfunc = DO_HOME;
+ s->scfunc = do_home;
else if (!strcasecmp(input, "end"))
- s->scfunc = DO_END;
-#ifdef ENABLE_MULTIBUFFER
+ s->scfunc = do_end;
+ else if (!strcasecmp(input, "pageup") ||
+ !strcasecmp(input, "prevpage"))
+ s->scfunc = do_page_up;
+ else if (!strcasecmp(input, "pagedown") ||
+ !strcasecmp(input, "nextpage"))
+ s->scfunc = do_page_down;
+ else if (!strcasecmp(input, "firstline"))
+ s->scfunc = do_first_line;
+ else if (!strcasecmp(input, "lastline"))
+ s->scfunc = do_last_line;
+#ifndef DISABLE_MULTIBUFFER
else if (!strcasecmp(input, "prevbuf"))
- s->scfunc = SWITCH_TO_PREV_BUFFER_VOID;
+ s->scfunc = switch_to_prev_buffer_void;
else if (!strcasecmp(input, "nextbuf"))
- s->scfunc = SWITCH_TO_NEXT_BUFFER_VOID;
+ s->scfunc = switch_to_next_buffer_void;
#endif
else if (!strcasecmp(input, "verbatim"))
- s->scfunc = DO_VERBATIM_INPUT;
+ s->scfunc = do_verbatim_input;
else if (!strcasecmp(input, "tab"))
- s->scfunc = DO_TAB;
+ s->scfunc = do_tab;
else if (!strcasecmp(input, "enter"))
- s->scfunc = DO_ENTER;
+ s->scfunc = do_enter_void;
else if (!strcasecmp(input, "delete"))
- s->scfunc = DO_DELETE;
+ s->scfunc = do_delete;
else if (!strcasecmp(input, "backspace"))
- s->scfunc = DO_BACKSPACE;
+ s->scfunc = do_backspace;
else if (!strcasecmp(input, "refresh"))
- s->scfunc = TOTAL_REFRESH;
- else if (!strcasecmp(input, "casesens")) {
- s->scfunc = CASE_SENS_MSG;
- s->execute = FALSE;
- } else if (!strcasecmp(input, "regexp") ||
- !strcasecmp(input, "regex")) {
- s->scfunc = REGEXP_MSG;
- s->execute = FALSE;
- } else if (!strcasecmp(input, "dontreplace")) {
- s->scfunc = NO_REPLACE_MSG;
- s->execute = FALSE;
- } else if (!strcasecmp(input, "gototext")) {
- s->scfunc = GOTOTEXT_MSG;
- s->execute = FALSE;
- } else if (!strcasecmp(input, "browser") ||
- !strcasecmp(input, "tofiles")) {
- s->scfunc = TO_FILES_MSG;
- s->execute = FALSE;
- } else if (!strcasecmp(input, "dosformat")) {
- s->scfunc = DOS_FORMAT_MSG;
- s->execute = FALSE;
- } else if (!strcasecmp(input, "macformat")) {
- s->scfunc = MAC_FORMAT_MSG;
- s->execute = FALSE;
- } else if (!strcasecmp(input, "append")) {
- s->scfunc = APPEND_MSG;
- s->execute = FALSE;
- } else if (!strcasecmp(input, "prepend")) {
- s->scfunc = PREPEND_MSG;
- s->execute = FALSE;
- } else if (!strcasecmp(input, "backup")) {
- s->scfunc = BACKUP_FILE_MSG;
- s->execute = FALSE;
-#ifdef ENABLE_MULTIBUFFER
- } else if (!strcasecmp(input, "newbuffer")) {
- s->scfunc = NEW_BUFFER_MSG;
- s->execute = FALSE;
-#endif
- } else if (!strcasecmp(input, "firstfile")) {
- s->scfunc = FIRST_FILE_MSG;
- s->execute = FALSE;
- } else if (!strcasecmp(input, "lastfile")) {
- s->scfunc = LAST_FILE_MSG;
- s->execute = FALSE;
- } else {
- free(s);
- return NULL;
+ s->scfunc = total_refresh;
+ else if (!strcasecmp(input, "suspend"))
+ s->scfunc = do_suspend_void;
+ else if (!strcasecmp(input, "casesens"))
+ s->scfunc = case_sens_void;
+#ifndef NANO_TINY
+ else if (!strcasecmp(input, "regexp") ||
+ !strcasecmp(input, "regex"))
+ s->scfunc = regexp_void;
+ else if (!strcasecmp(input, "backwards"))
+ s->scfunc = backwards_void;
+#endif
+ else if (!strcasecmp(input, "flipreplace") ||
+ !strcasecmp(input, "dontreplace"))
+ s->scfunc = flip_replace_void;
+ else if (!strcasecmp(input, "gototext"))
+ s->scfunc = gototext_void;
+#ifndef DISABLE_HISTORIES
+ else if (!strcasecmp(input, "prevhistory"))
+ s->scfunc = get_history_older_void;
+ else if (!strcasecmp(input, "nexthistory"))
+ s->scfunc = get_history_newer_void;
+#endif
+ else if (!strcasecmp(input, "dosformat"))
+ s->scfunc = dos_format_void;
+ else if (!strcasecmp(input, "macformat"))
+ s->scfunc = mac_format_void;
+ else if (!strcasecmp(input, "append"))
+ s->scfunc = append_void;
+ else if (!strcasecmp(input, "prepend"))
+ s->scfunc = prepend_void;
+ else if (!strcasecmp(input, "backup"))
+ s->scfunc = backup_file_void;
+#ifndef ENABLE_TINY
+ else if (!strcasecmp(input, "flipexecute"))
+ s->scfunc = flip_execute_void;
+#endif
+#ifndef DISABLE_MULTIBUFFER
+ else if (!strcasecmp(input, "flipnewbuffer") ||
+ !strcasecmp(input, "newbuffer"))
+ s->scfunc = new_buffer_void;
+#endif
+#ifndef DISABLE_BROWSER
+ else if (!strcasecmp(input, "tofiles") ||
+ !strcasecmp(input, "browser"))
+ s->scfunc = to_files_void;
+ else if (!strcasecmp(input, "gotodir"))
+ s->scfunc = goto_dir_void;
+ else if (!strcasecmp(input, "firstfile"))
+ s->scfunc = do_first_file;
+ else if (!strcasecmp(input, "lastfile"))
+ s->scfunc = do_last_file;
+#endif
+#ifndef NANO_TINY
+ else {
+ s->scfunc = do_toggle_void;
+ if (!strcasecmp(input, "nohelp"))
+ s->toggle = NO_HELP;
+ else if (!strcasecmp(input, "constupdate"))
+ s->toggle = CONST_UPDATE;
+ else if (!strcasecmp(input, "morespace"))
+ s->toggle = MORE_SPACE;
+ else if (!strcasecmp(input, "smoothscroll"))
+ s->toggle = SMOOTH_SCROLL;
+ else if (!strcasecmp(input, "softwrap"))
+ s->toggle = SOFTWRAP;
+ else if (!strcasecmp(input, "whitespacedisplay"))
+ s->toggle = WHITESPACE_DISPLAY;
+#ifndef DISABLE_COLOR
+ else if (!strcasecmp(input, "nosyntax"))
+ s->toggle = NO_COLOR_SYNTAX;
+#endif
+ else if (!strcasecmp(input, "smarthome"))
+ s->toggle = SMART_HOME;
+ else if (!strcasecmp(input, "autoindent"))
+ s->toggle = AUTOINDENT;
+ else if (!strcasecmp(input, "cuttoend"))
+ s->toggle = CUT_TO_END;
+#ifndef DISABLE_WRAPPING
+ else if (!strcasecmp(input, "nowrap"))
+ s->toggle = NO_WRAP;
+#endif
+ else if (!strcasecmp(input, "tabstospaces"))
+ s->toggle = TABS_TO_SPACES;
+ else if (!strcasecmp(input, "backupfile"))
+ s->toggle = BACKUP_FILE;
+#ifndef DISABLE_MULTIBUFFER
+ else if (!strcasecmp(input, "multibuffer"))
+ s->toggle = MULTIBUFFER;
+#endif
+#ifndef DISABLE_MOUSE
+ else if (!strcasecmp(input, "mouse"))
+ s->toggle = USE_MOUSE;
+#endif
+ else if (!strcasecmp(input, "noconvert"))
+ s->toggle = NO_CONVERT;
+ else if (!strcasecmp(input, "suspendenable"))
+ s->toggle = SUSPEND;
+#endif /* !NANO_TINY */
+ else {
+ free(s);
+ return NULL;
+ }
+#ifndef NANO_TINY
}
-
+#endif
return s;
-
}
-#ifdef ENABLE_NANORC
-/* Same thing as abnove but for the menu */
+/* Interpret a menu name and return the corresponding menu flag. */
int strtomenu(char *input)
{
if (!strcasecmp(input, "all"))
- return MALL;
+ return (MMOST|MHELP|MYESNO);
else if (!strcasecmp(input, "main"))
return MMAIN;
else if (!strcasecmp(input, "search"))
@@ -1666,8 +1512,8 @@ int strtomenu(char *input)
else if (!strcasecmp(input, "replace"))
return MREPLACE;
else if (!strcasecmp(input, "replace2") ||
- !strcasecmp(input, "replacewith"))
- return MREPLACE2;
+ !strcasecmp(input, "replacewith"))
+ return MREPLACEWITH;
else if (!strcasecmp(input, "gotoline"))
return MGOTOLINE;
else if (!strcasecmp(input, "writeout"))
@@ -1675,22 +1521,29 @@ int strtomenu(char *input)
else if (!strcasecmp(input, "insert"))
return MINSERTFILE;
else if (!strcasecmp(input, "externalcmd") ||
- !strcasecmp(input, "extcmd"))
+ !strcasecmp(input, "extcmd"))
return MEXTCMD;
+#ifndef DISABLE_HELP
else if (!strcasecmp(input, "help"))
return MHELP;
- else if (!strcasecmp(input, "spell"))
+#endif
+#ifndef DISABLE_SPELLER
+ else if (!strcasecmp(input, "spell") || !strcasecmp(input, "formatter"))
return MSPELL;
+#endif
+ else if (!strcasecmp(input, "linter"))
+ return MLINTER;
+#ifndef DISABLE_BROWSER
else if (!strcasecmp(input, "browser"))
return MBROWSER;
else if (!strcasecmp(input, "whereisfile"))
return MWHEREISFILE;
else if (!strcasecmp(input, "gotodir"))
return MGOTODIR;
-
+#endif
return -1;
}
-#endif
+#endif /* !DISABLE_NANORC */
#ifdef DEBUG
@@ -1740,12 +1593,10 @@ void thanks_for_all_the_fish(void)
if (jusbuffer != NULL)
free_filestruct(jusbuffer);
#endif
-#ifdef DEBUG
/* Free the memory associated with each open file buffer. */
if (openfile != NULL)
free_openfilestruct(openfile);
-#endif
-#ifdef ENABLE_COLOR
+#ifndef DISABLE_COLOR
if (syntaxstr != NULL)
free(syntaxstr);
while (syntaxes != NULL) {
@@ -1753,8 +1604,7 @@ void thanks_for_all_the_fish(void)
free(syntaxes->desc);
while (syntaxes->extensions != NULL) {
- exttype *bob = syntaxes->extensions;
-
+ regexlisttype *bob = syntaxes->extensions;
syntaxes->extensions = bob->next;
free(bob->ext_regex);
if (bob->ext != NULL) {
@@ -1763,6 +1613,26 @@ void thanks_for_all_the_fish(void)
}
free(bob);
}
+ while (syntaxes->headers != NULL) {
+ regexlisttype *bob = syntaxes->headers;
+ syntaxes->headers = bob->next;
+ free(bob->ext_regex);
+ if (bob->ext != NULL) {
+ regfree(bob->ext);
+ free(bob->ext);
+ }
+ free(bob);
+ }
+ while (syntaxes->magics != NULL) {
+ regexlisttype *bob = syntaxes->magics;
+ syntaxes->magics = bob->next;
+ free(bob->ext_regex);
+ if (bob->ext != NULL) {
+ regfree(bob->ext);
+ free(bob->ext);
+ }
+ free(bob);
+ }
while (syntaxes->color != NULL) {
colortype *bob = syntaxes->color;
@@ -1783,18 +1653,29 @@ void thanks_for_all_the_fish(void)
syntaxes = syntaxes->next;
free(bill);
}
-#endif /* ENABLE_COLOR */
-#ifndef NANO_TINY
+#endif /* !DISABLE_COLOR */
+#ifndef DISABLE_HISTORIES
/* Free the search and replace history lists. */
if (searchage != NULL)
free_filestruct(searchage);
if (replaceage != NULL)
free_filestruct(replaceage);
#endif
-#ifdef ENABLE_NANORC
+ /* Free the functions and shortcuts lists. */
+ while (allfuncs != NULL) {
+ subnfunc *f = allfuncs;
+ allfuncs = allfuncs->next;
+ free(f);
+ }
+ while (sclist != NULL) {
+ sc *s = sclist;
+ sclist = sclist->next;
+ free(s);
+ }
+#ifndef DISABLE_NANORC
if (homedir != NULL)
free(homedir);
#endif
}
-#endif /* DEBUG */
+#endif /* DEBUG */
diff --git a/src/help.c b/src/help.c
index 0eede72..6b00fa2 100644
--- a/src/help.c
+++ b/src/help.c
@@ -1,9 +1,9 @@
-/* $Id: help.c 4453 2009-12-02 03:36:22Z astyanax $ */
+/* $Id: help.c 5051 2014-07-02 09:29:05Z bens $ */
/**************************************************************************
* help.c *
* *
* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, *
- * 2009 Free Software Foundation, Inc. *
+ * 2009, 2010, 2011, 2013, 2014 Free Software Foundation, Inc. *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 3, or (at your option) *
@@ -37,29 +37,24 @@ static char *help_text = NULL;
void do_help(void (*refresh_func)(void))
{
int kbinput = ERR;
- bool meta_key, func_key, old_no_help = ISSET(NO_HELP);
- bool abort = FALSE;
- /* Whether we should abort the help browser. */
+ bool old_no_help = ISSET(NO_HELP);
size_t line = 0;
/* The line number in help_text of the first displayed help
* line. This variable is zero-based. */
size_t last_line = 0;
/* The line number in help_text of the last help line. This
* variable is zero-based. */
-#ifndef DISABLE_MOUSE
- /* The current shortcut list. */
int oldmenu = currmenu;
-#endif
+ /* The menu we were called from. */
const char *ptr;
/* The current line of the help text. */
size_t old_line = (size_t)-1;
/* The line we were on before the current line. */
- const sc *s;
- const subnfunc *f;
+ functionptrtype func;
+ /* The function of the key the user typed in. */
curs_set(0);
blank_edit();
- wattroff(bottomwin, reverse_attr);
blank_statusbar();
/* Set help_text as the string to display. */
@@ -67,11 +62,9 @@ void do_help(void (*refresh_func)(void))
assert(help_text != NULL);
-#ifndef DISABLE_MOUSE
/* Set currmenu to allow clicking on the help screen's shortcut
* list, after help_init() is called. */
currmenu = MHELP;
-#endif
if (ISSET(NO_HELP)) {
/* Make sure that the help screen's shortcut list will actually
@@ -94,7 +87,7 @@ void do_help(void (*refresh_func)(void))
if (last_line > 0)
last_line--;
- while (!abort) {
+ while (TRUE) {
size_t i;
/* Display the help text if we don't have a key, or if the help
@@ -126,62 +119,46 @@ void do_help(void (*refresh_func)(void))
old_line = line;
- kbinput = get_kbinput(edit, &meta_key, &func_key);
+ kbinput = get_kbinput(edit);
#ifndef DISABLE_MOUSE
- if (kbinput == KEY_MOUSE) {
- int mouse_x, mouse_y;
- get_mouseinput(&mouse_x, &mouse_y, TRUE);
- continue;
- /* Redraw the screen. */
+ if (kbinput == KEY_MOUSE) {
+ int mouse_x, mouse_y;
+ get_mouseinput(&mouse_x, &mouse_y, TRUE);
+ continue; /* Redraw the screen. */
}
#endif
- parse_help_input(&kbinput, &meta_key, &func_key);
- s = get_shortcut(MHELP, &kbinput, &meta_key, &func_key);
- if (!s)
- continue;
- f = sctofunc((sc *) s);
- if (!f)
- continue;
-
- if (f->scfunc == TOTAL_REFRESH) {
- total_redraw();
- break;
- } else if (f->scfunc == DO_PAGE_UP) {
- if (line > editwinrows - 2)
- line -= editwinrows - 2;
- else
- line = 0;
- } else if (f->scfunc == DO_PAGE_DOWN) {
- if (line + (editwinrows - 1) < last_line)
- line += editwinrows - 2;
- } else if (f->scfunc == DO_UP_VOID) {
- if (line > 0)
- line--;
- } else if (f->scfunc == DO_DOWN_VOID) {
- if (line + (editwinrows - 1) < last_line)
- line++;
- } else if (f->scfunc == DO_FIRST_LINE) {
- if (meta_key)
- line = 0;
- break;
- } else if (f->scfunc == DO_LAST_LINE) {
- if (meta_key) {
- if (line + (editwinrows - 1) < last_line)
- line = last_line - (editwinrows - 1);
- }
- break;
- /* Abort the help browser. */
- } else if (f->scfunc == DO_EXIT) {
- abort = TRUE;
- break;
+ func = parse_help_input(&kbinput);
+
+ if (func == total_refresh) {
+ total_redraw();
+ } else if (func == do_page_up) {
+ if (line > editwinrows - 2)
+ line -= editwinrows - 2;
+ else
+ line = 0;
+ } else if (func == do_page_down) {
+ if (line + (editwinrows - 1) < last_line)
+ line += editwinrows - 2;
+ } else if (func == do_up_void) {
+ if (line > 0)
+ line--;
+ } else if (func == do_down_void) {
+ if (line + (editwinrows - 1) < last_line)
+ line++;
+ } else if (func == do_first_line) {
+ line = 0;
+ } else if (func == do_last_line) {
+ if (line + (editwinrows - 1) < last_line)
+ line = last_line - (editwinrows - 1);
+ } else if (func == do_exit) {
+ /* Exit from the help browser. */
+ break;
}
}
-#ifndef DISABLE_MOUSE
currmenu = oldmenu;
-#endif
if (old_no_help) {
blank_bottombars();
@@ -201,14 +178,6 @@ void do_help(void (*refresh_func)(void))
help_text = NULL;
}
-#ifndef DISABLE_BROWSER
-/* Start the help browser for the file browser. */
-void do_browser_help(void)
-{
- do_help(&browser_refresh);
-}
-#endif
-
/* This function allocates help_text, and stores the help string in it.
* help_text should be NULL initially. */
void help_init(void)
@@ -224,7 +193,7 @@ void help_init(void)
int scsfound = 0;
#ifndef NANO_TINY
-#ifdef ENABLE_NANORC
+#ifndef DISABLE_NANORC
bool old_whitespace = ISSET(WHITESPACE_DISPLAY);
UNSET(WHITESPACE_DISPLAY);
@@ -232,7 +201,7 @@ void help_init(void)
#endif
/* First, set up the initial help text for the current function. */
- if (currmenu == MWHEREIS || currmenu == MREPLACE || currmenu == MREPLACE2) {
+ if (currmenu == MWHEREIS || currmenu == MREPLACE || currmenu == MREPLACEWITH) {
htx[0] = N_("Search Command Help Text\n\n "
"Enter the words or characters you would like to "
"search for, and then press Enter. If there is a "
@@ -392,24 +361,23 @@ void help_init(void)
if (htx[2] != NULL)
allocsize += strlen(htx[2]);
- /* Count the shortcut help text. Each entry has up to three keys,
- * which fill 24 columns, plus translated text, plus one or two
- * \n's. */
+ /* Calculate the length of the shortcut help text. Each entry has
+ * one or two keys, which fill 16 columns, plus translated text,
+ * plus one or two \n's. */
for (f = allfuncs; f != NULL; f = f->next)
- if (f->menus & currmenu)
- allocsize += (24 * mb_cur_max()) + strlen(f->help) + 2;
+ if (f->menus & currmenu)
+ allocsize += (16 * mb_cur_max()) + strlen(f->help) + 2;
#ifndef NANO_TINY
/* If we're on the main list, we also count the toggle help text.
- * Each entry has "M-%c\t\t\t", which fills 24 columns, plus a
- * space, plus translated text, plus one or two '\n's. */
+ * Each entry has "M-%c\t\t", five chars which fill 16 columns,
+ * plus a space, plus translated text, plus one or two '\n's. */
if (currmenu == MMAIN) {
size_t endis_len = strlen(_("enable/disable"));
for (s = sclist; s != NULL; s = s->next)
- if (s->scfunc == DO_TOGGLE)
- allocsize += strlen(_(flagtostr(s->toggle))) + endis_len + 9;
-
+ if (s->scfunc == do_toggle_void)
+ allocsize += strlen(_(flagtostr(s->toggle))) + endis_len + 8;
}
#endif
@@ -433,39 +401,36 @@ void help_init(void)
/* Now add our shortcut info. */
for (f = allfuncs; f != NULL; f = f->next) {
- if ((f->menus & currmenu) == 0)
+ if ((f->menus & currmenu) == 0)
continue;
- if (!f->desc || !strcmp(f->desc, ""))
- continue;
-
- /* Lets just try and use the first 3 shortcuts
- from the new struct... */
- for (s = sclist, scsfound = 0; s != NULL; s = s->next) {
+ /* Let's simply show the first two shortcuts from the list. */
+ for (s = sclist, scsfound = 0; s != NULL; s = s->next) {
- if (scsfound == 3)
- continue;
-
- if (s->type == RAW)
+ if (s->type == RAWINPUT)
continue;
if ((s->menu & currmenu) == 0)
continue;
- if (s->scfunc == f->scfunc) {
+ if (s->scfunc == f->scfunc) {
scsfound++;
-
- if (scsfound == 1)
- ptr += sprintf(ptr, "%s", s->keystr);
- else
- ptr += sprintf(ptr, "(%s)", s->keystr);
- *(ptr++) = '\t';
+ /* Make the first column narrower (6) than the second (10),
+ * but allow it to spill into the second, for "M-Space". */
+ if (scsfound == 1) {
+ sprintf(ptr, "%s ", s->keystr);
+ ptr += 6;
+ } else {
+ ptr += sprintf(ptr, "(%s)\t", s->keystr);
+ break;
+ }
}
}
- /* Pad with tabs if we didnt find 3 */
- for (; scsfound < 3; scsfound++) {
- *(ptr++) = '\t';
- }
+
+ if (scsfound == 0)
+ ptr += sprintf(ptr, "\t\t");
+ else if (scsfound == 1)
+ ptr += 10;
/* The shortcut's help text. */
ptr += sprintf(ptr, "%s\n", _(f->help));
@@ -477,48 +442,41 @@ void help_init(void)
#ifndef NANO_TINY
/* And the toggles... */
if (currmenu == MMAIN)
- for (s = sclist; s != NULL; s = s->next)
- if (s->scfunc == DO_TOGGLE)
- ptr += sprintf(ptr, "(%s)\t\t\t%s %s\n",
- s->keystr, _(flagtostr(s->toggle)), _("enable/disable"));
-
+ for (s = sclist; s != NULL; s = s->next) {
+ if (s->scfunc == do_toggle_void)
+ ptr += sprintf(ptr, "%s\t\t%s %s\n", (s->menu == MMAIN ? s->keystr : ""),
+ _(flagtostr(s->toggle)), _("enable/disable"));
+ if (s->toggle == NO_COLOR_SYNTAX || s->toggle == TABS_TO_SPACES)
+ ptr += sprintf(ptr, "\n");
+ }
-#ifdef ENABLE_NANORC
+#ifndef DISABLE_NANORC
if (old_whitespace)
SET(WHITESPACE_DISPLAY);
#endif
-#endif
+#endif /* !NANO_TINY */
/* If all went well, we didn't overwrite the allocated space for
* help_text. */
assert(strlen(help_text) <= allocsize + 1);
}
-/* Determine the shortcut key corresponding to the values of kbinput
- * (the key itself), meta_key (whether the key is a meta sequence), and
- * func_key (whether the key is a function key), if any. In the
- * process, convert certain non-shortcut keys into their corresponding
- * shortcut keys. */
-void parse_help_input(int *kbinput, bool *meta_key, bool *func_key)
+/* Return the function that is bound to the given key, accepting certain
+ * plain characters too, for consistency with the file browser. */
+functionptrtype parse_help_input(int *kbinput)
{
- get_shortcut(MHELP, kbinput, meta_key, func_key);
-
- if (!*meta_key) {
+ if (!meta_key) {
switch (*kbinput) {
- /* For consistency with the file browser. */
case ' ':
- *kbinput = sc_seq_or(DO_PAGE_UP, 0);
- break;
+ return do_page_down;
case '-':
- *kbinput = sc_seq_or(DO_PAGE_DOWN, 0);;
- break;
- /* Cancel is equivalent to Exit here. */
+ return do_page_up;
case 'E':
case 'e':
- *kbinput = sc_seq_or(DO_EXIT, 0);;
- break;
+ return do_exit;
}
}
+ return func_from_key(kbinput);
}
/* Calculate the next line of help_text, starting at ptr. */
@@ -547,17 +505,21 @@ size_t help_line_len(const char *ptr)
#endif /* !DISABLE_HELP */
-/* Start the help browser for the edit window. */
+/* Start the help browser. */
void do_help_void(void)
{
-
#ifndef DISABLE_HELP
- /* Start the help browser for the edit window. */
- do_help(&edit_refresh);
+ /* Start the help browser, with the correct refresher for afterwards. */
+#ifndef DISABLE_BROWSER
+ if (currmenu == MBROWSER || currmenu == MWHEREISFILE || currmenu == MGOTODIR)
+ do_help(&browser_refresh);
+ else
+#endif
+ do_help(&edit_refresh);
#else
if (currmenu == MMAIN)
nano_disabled_msg();
else
beep();
-#endif
+#endif /* !DISABLE_HELP */
}
diff --git a/src/move.c b/src/move.c
index 468a02f..910ff83 100644
--- a/src/move.c
+++ b/src/move.c
@@ -1,9 +1,9 @@
-/* $Id: move.c 4486 2010-03-21 04:56:37Z astyanax $ */
+/* $Id: move.c 5013 2014-06-23 18:20:12Z bens $ */
/**************************************************************************
* move.c *
* *
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
- * 2008, 2009 Free Software Foundation, Inc. *
+ * 2008, 2009, 2010, 2011, 2013, 2014 Free Software Foundation, Inc. *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 3, or (at your option) *
@@ -33,7 +33,7 @@ void do_first_line(void)
openfile->current_x = 0;
openfile->placewewant = 0;
- edit_refresh_needed = 1;
+ edit_refresh_needed = TRUE;
}
/* Move to the last line of the file. */
@@ -44,7 +44,7 @@ void do_last_line(void)
openfile->placewewant = xplustabs();
openfile->current_y = editwinrows - 1;
- edit_refresh_needed = 1;
+ edit_refresh_needed = TRUE;
}
/* Move up one page. */
@@ -55,7 +55,10 @@ void do_page_up(void)
/* If there's less than a page of text left on the screen, put the
* cursor at the beginning of the first line of the file, and then
* update the edit window. */
- if (openfile->current->lineno == 1 || (!ISSET(SOFTWRAP) &&
+ if (openfile->current->lineno == 1 || (
+#ifndef NANO_TINY
+ !ISSET(SOFTWRAP) &&
+#endif
openfile->current->lineno <= editwinrows - 2)) {
do_first_line();
return;
@@ -63,7 +66,6 @@ void do_page_up(void)
/* If we're not in smooth scrolling mode, put the cursor at the
* beginning of the top line of the edit window, as Pico does. */
-
#ifndef NANO_TINY
if (!ISSET(SMOOTH_SCROLL)) {
#endif
@@ -76,20 +78,23 @@ void do_page_up(void)
for (i = editwinrows - 2; i - skipped > 0 && openfile->current !=
openfile->fileage; i--) {
openfile->current = openfile->current->prev;
+#ifndef NANO_TINY
if (ISSET(SOFTWRAP) && openfile->current) {
skipped += strlenpt(openfile->current->data) / COLS;
#ifdef DEBUG
- fprintf(stderr, "do_page_up: i = %d, skipped = %d based on line %ld len %d\n", i, (unsigned long) skipped,
-openfile->current->lineno, strlenpt(openfile->current->data));
+ fprintf(stderr, "do_page_up: i = %d, skipped = %d based on line %ld len %lu\n",
+ i, skipped, (long)openfile->current->lineno, (unsigned long)strlenpt(openfile->current->data));
#endif
}
+#endif
}
openfile->current_x = actual_x(openfile->current->data,
openfile->placewewant);
#ifdef DEBUG
- fprintf(stderr, "do_page_up: openfile->current->lineno = %lu, skipped = %d\n", (unsigned long) openfile->current->lineno, skipped);
+ fprintf(stderr, "do_page_up: openfile->current->lineno = %lu, skipped = %d\n",
+ (unsigned long)openfile->current->lineno, skipped);
#endif
/* Scroll the edit window up a page. */
@@ -125,7 +130,7 @@ void do_page_down(void)
openfile->filebot; i--) {
openfile->current = openfile->current->next;
#ifdef DEBUG
- fprintf(stderr, "do_page_down: moving to line %lu\n", (unsigned long) openfile->current->lineno);
+ fprintf(stderr, "do_page_down: moving to line %lu\n", (unsigned long)openfile->current->lineno);
#endif
}
@@ -513,12 +518,12 @@ void do_up(
* smooth scrolling mode, or up half a page if we're not. If
* scroll_only is TRUE, scroll the edit window up one line
* unconditionally. */
- if (openfile->current_y == 0 || (ISSET(SOFTWRAP) && openfile->edittop->lineno == openfile->current->next->lineno)
+ if (openfile->current_y == 0
#ifndef NANO_TINY
- || scroll_only
+ || (ISSET(SOFTWRAP) && openfile->edittop->lineno == openfile->current->next->lineno) || scroll_only
#endif
)
- edit_scroll(UP_DIR,
+ edit_scroll(UPWARD,
#ifndef NANO_TINY
(ISSET(SMOOTH_SCROLL) || scroll_only) ? 1 :
#endif
@@ -563,13 +568,15 @@ void do_down(
#endif
)
{
- bool onlastline = FALSE;
+#ifndef NANO_TINY
+ int amount = 0, enough;
+ filestruct *topline;
+#endif
/* If we're at the bottom of the file, get out. */
- if (openfile->current == openfile->filebot)
+ if (openfile->current == openfile->filebot || !openfile->current->next)
return;
-
assert(ISSET(SOFTWRAP) || openfile->current_y == openfile->current->lineno - openfile->edittop->lineno);
/* Move the current line of the edit window down. */
@@ -577,34 +584,54 @@ void do_down(
openfile->current_x = actual_x(openfile->current->data,
openfile->placewewant);
+#ifndef NANO_TINY
if (ISSET(SOFTWRAP)) {
- if (openfile->current->lineno - openfile->edittop->lineno >= maxrows)
- onlastline = TRUE;
+ /* Compute the amount to scroll. */
+ amount = (strlenpt(openfile->current->data) / COLS + openfile->current_y + 2
+ + strlenpt(openfile->current->prev->data) / COLS - editwinrows);
+ topline = openfile->edittop;
+ /* Reduce the amount when there are overlong lines at the top. */
+ for (enough = 1; enough < amount; enough++) {
+ if (amount <= strlenpt(topline->data) / COLS) {
+ amount = enough;
+ break;
+ }
+ amount -= strlenpt(topline->data) / COLS;
+ topline = topline->next;
+ }
}
+#endif
- /* If scroll_only is FALSE and if we're on the first line of the
+ /* If scroll_only is FALSE and if we're on the last line of the
* edit window, scroll the edit window down one line if we're in
* smooth scrolling mode, or down half a page if we're not. If
* scroll_only is TRUE, scroll the edit window down one line
* unconditionally. */
- if (onlastline || openfile->current_y == editwinrows - 1
+ if (openfile->current_y == editwinrows - 1
#ifndef NANO_TINY
- || scroll_only
+ || amount > 0 || scroll_only
#endif
) {
- edit_scroll(DOWN_DIR,
#ifndef NANO_TINY
- (ISSET(SMOOTH_SCROLL) || scroll_only) ? 1 :
+ if (amount < 1 || scroll_only)
+ amount = 1;
+#endif
+ edit_scroll(DOWNWARD,
+#ifndef NANO_TINY
+ (ISSET(SMOOTH_SCROLL) || scroll_only) ? amount :
#endif
editwinrows / 2 + 1);
-
edit_refresh_needed = TRUE;
}
/* If we're above the last line of the edit window, update the line
* we were on before and the line we're on now. The former needs to
* be redrawn if we're not on the first page, and the latter needs
* to be drawn unconditionally. */
- if (ISSET(SOFTWRAP) || openfile->current_y < editwinrows - 1) {
+ if (openfile->current_y < editwinrows - 1
+#ifndef NANO_TINY
+ || ISSET(SOFTWRAP)
+#endif
+ ) {
if (need_vertical_update(0))
update_line(openfile->current->prev, 0);
update_line(openfile->current, openfile->current_x);
diff --git a/src/nano.c b/src/nano.c
index e4e2222..6930425 100644
--- a/src/nano.c
+++ b/src/nano.c
@@ -1,9 +1,9 @@
-/* $Id: nano.c 4520 2010-11-12 06:23:14Z astyanax $ */
+/* $Id: nano.c 5141 2015-03-20 11:18:22Z bens $ */
/**************************************************************************
* nano.c *
* *
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
- * 2008, 2009 Free Software Foundation, Inc. *
+ * 2008, 2009, 2010, 2011, 2013, 2014 Free Software Foundation, Inc. *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 3, or (at your option) *
@@ -48,7 +48,7 @@
static int oldinterval = -1;
/* Used to store the user's original mouse click interval. */
#endif
-#ifdef ENABLE_NANORC
+#ifndef DISABLE_NANORC
static bool no_rcfiles = FALSE;
/* Should we ignore all rcfiles? */
#endif
@@ -68,7 +68,7 @@ filestruct *make_new_node(filestruct *prevnode)
newnode->next = NULL;
newnode->lineno = (prevnode != NULL) ? prevnode->lineno + 1 : 1;
-#ifdef ENABLE_COLOR
+#ifndef DISABLE_COLOR
newnode->multidata = NULL;
#endif
@@ -88,7 +88,7 @@ filestruct *copy_node(const filestruct *src)
dst->next = src->next;
dst->prev = src->prev;
dst->lineno = src->lineno;
-#ifdef ENABLE_COLOR
+#ifndef DISABLE_COLOR
dst->multidata = NULL;
#endif
@@ -127,7 +127,7 @@ void delete_node(filestruct *fileptr)
if (fileptr->data != NULL)
free(fileptr->data);
-#ifdef ENABLE_COLOR
+#ifndef DISABLE_COLOR
if (fileptr->multidata)
free(fileptr->multidata);
#endif
@@ -178,7 +178,8 @@ void renumber(filestruct *fileptr)
{
ssize_t line;
- assert(fileptr != NULL);
+ if (fileptr == NULL)
+ return;
line = (fileptr->prev == NULL) ? 0 : fileptr->prev->lineno;
@@ -297,6 +298,7 @@ void move_to_filestruct(filestruct **file_top, filestruct **file_bot,
bool edittop_inside;
#ifndef NANO_TINY
bool mark_inside = FALSE;
+ bool same_line = FALSE;
#endif
assert(file_top != NULL && file_bot != NULL && top != NULL && bot != NULL);
@@ -314,7 +316,7 @@ void move_to_filestruct(filestruct **file_top, filestruct **file_bot,
openfile->fileage->lineno && openfile->edittop->lineno <=
openfile->filebot->lineno);
#ifndef NANO_TINY
- if (openfile->mark_set)
+ if (openfile->mark_set) {
mark_inside = (openfile->mark_begin->lineno >=
openfile->fileage->lineno &&
openfile->mark_begin->lineno <=
@@ -323,6 +325,8 @@ void move_to_filestruct(filestruct **file_top, filestruct **file_bot,
openfile->mark_begin_x >= top_x) &&
(openfile->mark_begin != openfile->filebot ||
openfile->mark_begin_x <= bot_x));
+ same_line = (openfile->mark_begin == openfile->fileage);
+ }
#endif
/* Get the number of characters in the text, and subtract it from
@@ -357,10 +361,12 @@ void move_to_filestruct(filestruct **file_top, filestruct **file_bot,
*file_bot = openfile->filebot;
}
+ openfile->fileage->next = NULL;
+ free_filestruct(openfile->fileage);
+
/* Renumber starting with the line after the original
* file_bot. */
- if (file_bot_save->next != NULL)
- renumber(file_bot_save->next);
+ renumber(file_bot_save->next);
}
/* Since the text has now been saved, remove it from the
@@ -369,7 +375,7 @@ void move_to_filestruct(filestruct **file_top, filestruct **file_bot,
openfile->fileage->data = mallocstrcpy(NULL, "");
openfile->filebot = openfile->fileage;
-#ifdef ENABLE_COLOR
+#ifndef DISABLE_COLOR
openfile->fileage->multidata = NULL;
#endif
@@ -382,7 +388,9 @@ void move_to_filestruct(filestruct **file_top, filestruct **file_bot,
if (mark_inside) {
openfile->mark_begin = openfile->current;
openfile->mark_begin_x = openfile->current_x;
- }
+ } else if (same_line)
+ /* Update the content of this partially cut line. */
+ openfile->mark_begin = openfile->current;
#endif
top_save = openfile->fileage;
@@ -406,10 +414,9 @@ void move_to_filestruct(filestruct **file_top, filestruct **file_bot,
new_magicline();
}
-/* Copy all the text from the filestruct beginning with file_top and
- * ending with file_bot to the current filestruct at the current cursor
- * position. */
-void copy_from_filestruct(filestruct *file_top, filestruct *file_bot)
+/* Copy all text from the given filestruct to the current filestruct
+ * at the current cursor position. */
+void copy_from_filestruct(filestruct *somebuffer)
{
filestruct *top_save;
size_t current_x_save = openfile->current_x;
@@ -418,7 +425,7 @@ void copy_from_filestruct(filestruct *file_top, filestruct *file_bot)
bool right_side_up = FALSE, single_line = FALSE;
#endif
- assert(file_top != NULL && file_bot != NULL);
+ assert(somebuffer != NULL);
#ifndef NANO_TINY
/* Keep track of whether the mark begins inside the partition and
@@ -441,9 +448,10 @@ void copy_from_filestruct(filestruct *file_top, filestruct *file_bot)
openfile->current_x, openfile->current, openfile->current_x);
edittop_inside = (openfile->edittop == openfile->fileage);
- /* Put the top and bottom of the filestruct at copies of file_top
- * and file_bot. */
- openfile->fileage = copy_filestruct(file_top);
+ /* Put the top and bottom of the current filestruct at the top and
+ * bottom of a copy of the passed buffer. */
+ free_filestruct(openfile->fileage);
+ openfile->fileage = copy_filestruct(somebuffer);
openfile->filebot = openfile->fileage;
while (openfile->filebot->next != NULL)
openfile->filebot = openfile->filebot->next;
@@ -465,7 +473,12 @@ void copy_from_filestruct(filestruct *file_top, filestruct *file_bot)
}
#ifndef NANO_TINY
else if (openfile->mark_set) {
- if (!right_side_up) {
+ if (right_side_up) {
+ if (single_line)
+ /* Get the new data, stuff was inserted on the mark line. */
+ openfile->mark_begin = openfile->fileage;
+ /* The x is okay, it did not move. */
+ } else {
if (single_line) {
openfile->mark_begin = openfile->current;
openfile->mark_begin_x -= current_x_save;
@@ -520,6 +533,7 @@ openfilestruct *make_new_opennode(void)
#ifndef NANO_TINY
newnode->current_stat = NULL;
newnode->last_action = OTHER;
+ newnode->lock_filename = NULL;
#endif
return newnode;
@@ -602,9 +616,13 @@ void finish(void)
/* Restore the old terminal settings. */
tcsetattr(0, TCSANOW, &oldterm);
-#if !defined(NANO_TINY) && defined(ENABLE_NANORC)
- if (!no_rcfiles && ISSET(HISTORYLOG))
+#ifndef DISABLE_HISTORIES
+ if (ISSET(HISTORYLOG))
save_history();
+ if (ISSET(POS_HISTORY)) {
+ update_poshistory(openfile->filename, openfile->current->lineno, xplustabs() + 1);
+ save_poshistory();
+ }
#endif
#ifdef DEBUG
@@ -642,7 +660,7 @@ void die(const char *msg, ...)
);
}
-#ifdef ENABLE_MULTIBUFFER
+#ifndef DISABLE_MULTIBUFFER
/* Save all of the other modified file buffers, if any. */
if (openfile != NULL) {
openfilestruct *tmp = openfile;
@@ -708,6 +726,8 @@ void die_save_file(const char *die_filename
int shush;
shush = chmod(retval, die_stat->st_mode);
shush = chown(retval, die_stat->st_uid, die_stat->st_gid);
+ if (shush)
+ ;
}
#endif
@@ -718,7 +738,7 @@ void die_save_file(const char *die_filename
void window_init(void)
{
/* If the screen height is too small, get out. */
- editwinrows = LINES - 5 + no_more_space() + no_help();
+ editwinrows = LINES - 5 + more_space() + no_help();
if (COLS < MIN_EDITOR_COLS || editwinrows < MIN_EDITOR_ROWS)
die(_("Window size is too small for nano...\n"));
@@ -739,10 +759,10 @@ void window_init(void)
delwin(bottomwin);
/* Set up the windows. */
- topwin = newwin(2 - no_more_space(), COLS, 0, 0);
- edit = newwin(editwinrows, COLS, 2 - no_more_space(), 0);
+ topwin = newwin(2 - more_space(), COLS, 0, 0);
+ edit = newwin(editwinrows, COLS, 2 - more_space(), 0);
bottomwin = newwin(3 - no_help(), COLS, editwinrows + (2 -
- no_more_space()), 0);
+ more_space()), 0);
/* Turn the keypad on for the windows, if necessary. */
if (!ISSET(REBIND_KEYPAD)) {
@@ -810,7 +830,7 @@ void print_opt_full(const char *shortflag
printf("\n");
}
-/* Explain how to properly use nano and its command line options. */
+/* Explain how to properly use nano and its command-line options. */
void usage(void)
{
printf(_("Usage: nano [OPTIONS] [[+LINE,COLUMN] FILE]...\n\n"));
@@ -821,8 +841,9 @@ void usage(void)
_("Option\t\tMeaning\n")
#endif
);
- print_opt("-h, -?", "--help", N_("Show this message"));
print_opt(_("+LINE,COLUMN"), "",
+ /* TRANSLATORS: The next forty or so strings are option descriptions
+ * for the --help output. Try to keep them at most 40 characters. */
N_("Start at line LINE, column COLUMN"));
#ifndef NANO_TINY
print_opt("-A", "--smarthome", N_("Enable smart home key"));
@@ -836,14 +857,18 @@ void usage(void)
print_opt("-E", "--tabstospaces",
N_("Convert typed tabs to spaces"));
#endif
-#ifdef ENABLE_MULTIBUFFER
+#ifndef DISABLE_MULTIBUFFER
print_opt("-F", "--multibuffer", N_("Enable multiple file buffers"));
#endif
-#ifdef ENABLE_NANORC
#ifndef NANO_TINY
+ print_opt("-G", "--locking",
+ N_("Use (vim-style) lock files"));
+#endif
+#ifndef DISABLE_HISTORIES
print_opt("-H", "--historylog",
N_("Log & read search/replace string history"));
#endif
+#ifndef DISABLE_NANORC
print_opt("-I", "--ignorercfiles",
N_("Don't look at nanorc files"));
#endif
@@ -856,6 +881,10 @@ void usage(void)
N_("Don't convert files from DOS/Mac format"));
#endif
print_opt("-O", "--morespace", N_("Use one more line for editing"));
+#ifndef DISABLE_HISTORIES
+ print_opt("-P", "--poslog",
+ N_("Log & read location of cursor position"));
+#endif
#ifndef DISABLE_JUSTIFY
print_opt(_("-Q <str>"), _("--quotestr=<str>"),
N_("Quoting string"));
@@ -876,13 +905,14 @@ void usage(void)
print_opt("-W", "--wordbounds",
N_("Detect word boundaries more accurately"));
#endif
-#ifdef ENABLE_COLOR
+#ifndef DISABLE_COLOR
print_opt(_("-Y <str>"), _("--syntax=<str>"),
N_("Syntax definition to use for coloring"));
#endif
print_opt("-c", "--const", N_("Constantly show cursor position"));
print_opt("-d", "--rebinddelete",
N_("Fix Backspace/Delete confusion problem"));
+ print_opt("-h", "--help", N_("Show this help text"));
#ifndef NANO_TINY
print_opt("-i", "--autoindent",
N_("Automatically indent new lines"));
@@ -893,17 +923,20 @@ void usage(void)
#ifndef DISABLE_MOUSE
print_opt("-m", "--mouse", N_("Enable the use of the mouse"));
#endif
+ print_opt("-n", "--noread", N_("Do not read the file (only write it)"));
#ifndef DISABLE_OPERATINGDIR
print_opt(_("-o <dir>"), _("--operatingdir=<dir>"),
N_("Set operating directory"));
#endif
print_opt("-p", "--preserve",
N_("Preserve XON (^Q) and XOFF (^S) keys"));
+#ifndef DISABLE_NANORC
print_opt("-q", "--quiet",
N_("Silently ignore startup issues like rc file errors"));
+#endif
#ifndef DISABLE_WRAPJUSTIFY
print_opt(_("-r <#cols>"), _("--fill=<#cols>"),
- N_("Set wrapping point at column #cols"));
+ N_("Set hard-wrapping point at column #cols"));
#endif
#ifndef DISABLE_SPELLER
print_opt(_("-s <prog>"), _("--speller=<prog>"),
@@ -911,23 +944,15 @@ void usage(void)
#endif
print_opt("-t", "--tempfile",
N_("Auto save on exit, don't prompt"));
-#ifndef NANO_TINY
- print_opt("-u", "--undo", N_("Allow generic undo [EXPERIMENTAL]"));
-#endif
-
print_opt("-v", "--view", N_("View mode (read-only)"));
#ifndef DISABLE_WRAPPING
- print_opt("-w", "--nowrap", N_("Don't wrap long lines"));
+ print_opt("-w", "--nowrap", N_("Don't hard-wrap long lines"));
#endif
print_opt("-x", "--nohelp", N_("Don't show the two help lines"));
print_opt("-z", "--suspend", N_("Enable suspension"));
+#ifndef NANO_TINY
print_opt("-$", "--softwrap", N_("Enable soft line wrapping"));
-
- /* This is a special case. */
- print_opt("-a, -b, -e,", "", NULL);
- print_opt("-f, -g, -j", "", N_("(ignored, for Pico compatibility)"));
-
- exit(0);
+#endif
}
/* Display the current version of nano, the date and time it was
@@ -935,28 +960,86 @@ void usage(void)
* it was compiled with. */
void version(void)
{
- printf(_(" GNU nano version %s (compiled %s, %s)\n"), VERSION,
- __TIME__, __DATE__);
- printf(" (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,\n");
- printf(" 2008, 2009 Free Software Foundation, Inc.\n");
+ printf(_(" GNU nano, version %s\n"), VERSION);
+ printf(" (C) 1999..2015 Free Software Foundation, Inc.\n");
printf(
_(" Email: nano@nano-editor.org Web: http://www.nano-editor.org/"));
printf(_("\n Compiled options:"));
+#ifdef NANO_TINY
+ printf(" --enable-tiny");
+#ifndef DISABLE_BROWSER
+ printf(" --enable-browser");
+#endif
+#ifndef DISABLE_COLOR
+ printf(" --enable-color");
+#endif
+#ifndef DISABLE_EXTRA
+ printf(" --enable-extra");
+#endif
+#ifndef DISABLE_HELP
+ printf(" --enable-help");
+#endif
+#ifndef DISABLE_HISTORIES
+ printf(" --enable-histories");
+#endif
+#ifndef DISABLE_JUSTIFY
+ printf(" --enable-justify");
+#endif
+#ifdef HAVE_LIBMAGIC
+ printf(" --enable-libmagic");
+#endif
+#ifndef DISABLE_MOUSE
+ printf(" --enable-mouse");
+#endif
+#ifndef DISABLE_NANORC
+ printf(" --enable-nanorc");
+#endif
+#ifndef DISABLE_MULTIBUFFER
+ printf(" --enable-multibuffer");
+#endif
+#ifndef DISABLE_OPERATINGDIR
+ printf(" --enable-operatingdir");
+#endif
+#ifndef DISABLE_SPELLER
+ printf(" --enable-speller");
+#endif
+#ifndef DISABLE_TABCOMP
+ printf(" --enable-tabcomp");
+#endif
+#ifndef DISABLE_WRAPPING
+ printf(" --enable-wrapping");
+#endif
+#else /* !NANO_TINY */
#ifdef DISABLE_BROWSER
printf(" --disable-browser");
#endif
+#ifdef DISABLE_COLOR
+ printf(" --disable-color");
+#endif
+#ifdef DISABLE_EXTRA
+ printf(" --disable-extra");
+#endif
#ifdef DISABLE_HELP
printf(" --disable-help");
#endif
+#ifdef DISABLE_HISTORIES
+ printf(" --disable-histories");
+#endif
#ifdef DISABLE_JUSTIFY
printf(" --disable-justify");
#endif
+#ifndef HAVE_LIBMAGIC
+ printf(" --disable-libmagic");
+#endif
#ifdef DISABLE_MOUSE
printf(" --disable-mouse");
#endif
-#ifndef ENABLE_NLS
- printf(" --disable-nls");
+#ifdef DISABLE_MULTIBUFFER
+ printf(" --disable-multibuffer");
+#endif
+#ifdef DISABLE_NANORC
+ printf(" --disable-nanorc");
#endif
#ifdef DISABLE_OPERATINGDIR
printf(" --disable-operatingdir");
@@ -970,29 +1053,21 @@ void version(void)
#ifdef DISABLE_WRAPPING
printf(" --disable-wrapping");
#endif
+#endif /* !NANO_TINY */
+
#ifdef DISABLE_ROOTWRAPPING
printf(" --disable-wrapping-as-root");
#endif
-#ifdef ENABLE_COLOR
- printf(" --enable-color");
-#endif
#ifdef DEBUG
printf(" --enable-debug");
#endif
-#ifdef NANO_EXTRA
- printf(" --enable-extra");
-#endif
-#ifdef ENABLE_MULTIBUFFER
- printf(" --enable-multibuffer");
-#endif
-#ifdef ENABLE_NANORC
- printf(" --enable-nanorc");
-#endif
-#ifdef NANO_TINY
- printf(" --enable-tiny");
+#ifndef ENABLE_NLS
+ printf(" --disable-nls");
#endif
#ifdef ENABLE_UTF8
printf(" --enable-utf8");
+#else
+ printf(" --disable-utf8");
#endif
#ifdef USE_SLANG
printf(" --with-slang");
@@ -1001,16 +1076,15 @@ void version(void)
}
/* Return 1 if the MORE_SPACE flag is set, and 0 otherwise. This is
- * used to calculate the relative screen position while taking this flag
- * into account, since it adds one line to the edit window. */
-int no_more_space(void)
+ * used to calculate the sizes and Y coordinates of the subwindows. */
+int more_space(void)
{
return ISSET(MORE_SPACE) ? 1 : 0;
}
/* Return 2 if the NO_HELP flag is set, and 0 otherwise. This is used
- * to calculate the relative screen position while taking this flag into
- * account, since it removes two lines from the edit window. */
+ * to calculate the sizes and Y coordinates of the subwindows, because
+ * having NO_HELP adds two lines to the edit window. */
int no_help(void)
{
return ISSET(NO_HELP) ? 2 : 0;
@@ -1024,9 +1098,10 @@ void nano_disabled_msg(void)
/* If the current file buffer has been modified, and the TEMP_FILE flag
* isn't set, ask whether or not to save the file buffer. If the
- * TEMP_FILE flag is set, save it unconditionally. Then, if more than
- * one file buffer is open, close the current file buffer and switch to
- * the next one. If only one file buffer is open, exit from nano. */
+ * TEMP_FILE flag is set and the current file has a name, save it
+ * unconditionally. Then, if more than one file buffer is open, close
+ * the current file buffer and switch to the next one. If only one file
+ * buffer is open, exit from nano. */
void do_exit(void)
{
int i;
@@ -1035,13 +1110,31 @@ void do_exit(void)
* save. */
if (!openfile->modified)
i = 0;
- /* If the TEMP_FILE flag is set, pretend the user chose to save. */
- else if (ISSET(TEMP_FILE))
+ /* If the TEMP_FILE flag is set and the current file has a name,
+ * pretend the user chose to save. */
+ else if (openfile->filename[0] != '\0' && ISSET(TEMP_FILE))
i = 1;
/* Otherwise, ask the user whether or not to save. */
- else
+ else {
+ /* If the TEMP_FILE flag is set, and the current file doesn't
+ * have a name, handle it the same way Pico does. */
+ if (ISSET(TEMP_FILE)) {
+ curs_set(0);
+
+ /* Warn that the current file has no name. */
+ statusbar(_("No file name"));
+ beep();
+
+ /* Ensure that we see the warning. */
+ doupdate();
+ napms(2000);
+
+ curs_set(1);
+ }
+
i = do_yesno_prompt(FALSE,
_("Save modified buffer (ANSWERING \"No\" WILL DESTROY CHANGES) ? "));
+ }
#ifdef DEBUG
dump_filestruct(openfile->fileage);
@@ -1050,62 +1143,68 @@ void do_exit(void)
/* If the user chose not to save, or if the user chose to save and
* the save succeeded, we're ready to exit. */
if (i == 0 || (i == 1 && do_writeout(TRUE))) {
-#ifdef ENABLE_MULTIBUFFER
+
+#ifndef NANO_TINY
+ if (ISSET(LOCKING) && openfile->lock_filename)
+ delete_lockfile(openfile->lock_filename);
+#endif
+
+#ifndef DISABLE_MULTIBUFFER
/* Exit only if there are no more open file buffers. */
- if (!close_buffer())
+ if (!close_buffer(FALSE))
#endif
finish();
/* If the user canceled, we go on. */
} else if (i != 1)
statusbar(_("Cancelled"));
- shortcut_init(FALSE);
display_main_list();
}
-
+/* Another placeholder for function mapping. */
+void do_cancel(void)
+{
+ ;
+}
static struct sigaction pager_oldaction, pager_newaction; /* Original and temporary handlers for SIGINT. */
static bool pager_sig_failed = FALSE; /* Did sigaction() fail without changing the signal handlers? */
static bool pager_input_aborted = FALSE; /* Did someone invoke the pager and abort it via ^C? */
-
/* Things which need to be run regardless of whether
- we finished the stdin pipe correctly or not */
+ * we finished the stdin pipe correctly or not. */
void finish_stdin_pager(void)
{
FILE *f;
int ttystdin;
- /* Read whatever we did get from stdin */
+ /* Read whatever we did get from stdin. */
f = fopen("/dev/stdin", "rb");
- if (f == NULL)
- nperror("fopen");
+ if (f == NULL)
+ nperror("fopen");
read_file(f, 0, "stdin", TRUE, FALSE);
ttystdin = open("/dev/tty", O_RDONLY);
if (!ttystdin)
- die(_("Couldn't reopen stdin from keyboard, sorry\n"));
+ die(_("Couldn't reopen stdin from keyboard, sorry\n"));
dup2(ttystdin,0);
close(ttystdin);
if (!pager_input_aborted)
tcgetattr(0, &oldterm);
if (!pager_sig_failed && sigaction(SIGINT, &pager_oldaction, NULL) == -1)
- nperror("sigaction");
+ nperror("sigaction");
terminal_init();
doupdate();
}
-
-/* Cancel reading from stdin like a pager */
+/* Cancel reading from stdin like a pager. */
RETSIGTYPE cancel_stdin_pager(int signal)
{
- /* Currently do nothing, just handle the intr silently */
pager_input_aborted = TRUE;
}
-/* Let nano read stdin for the first file at least */
+/* Let nano read stdin for the first file at least. */
void stdin_pager(void)
{
endwin();
@@ -1113,13 +1212,13 @@ void stdin_pager(void)
tcsetattr(0, TCSANOW, &oldterm);
fprintf(stderr, _("Reading from stdin, ^C to abort\n"));
- /* Set things up so that Ctrl-C will cancel the new process. */
- /* Enable interpretation of the special control keys so that we get
- * SIGINT when Ctrl-C is pressed. */
+ /* Enable interpretation of the special control keys so that
+ * we get SIGINT when Ctrl-C is pressed. */
#ifndef NANO_TINY
enable_signals();
#endif
+ /* Set things up so that SIGINT will cancel the new process. */
if (sigaction(SIGINT, NULL, &pager_newaction) == -1) {
pager_sig_failed = TRUE;
nperror("sigaction");
@@ -1135,8 +1234,6 @@ void stdin_pager(void)
finish_stdin_pager();
}
-
-
/* Initialize the signal handlers. */
void signal_init(void)
{
@@ -1274,7 +1371,7 @@ RETSIGTYPE handle_sigwinch(int signal)
* otherwise. However, COLS and LINES are curses global variables,
* and in some cases curses has already updated them. But not in
* all cases. Argh. */
-#ifdef REDEFINIG_MACROS_OK
+#ifdef REDEFINING_MACROS_OK
COLS = win.ws_col;
LINES = win.ws_row;
#endif
@@ -1332,11 +1429,11 @@ void allow_pending_sigwinch(bool allow)
#endif /* !NANO_TINY */
#ifndef NANO_TINY
-/* Handle the global toggle specified in which. */
+/* Handle the global toggle specified in flag. */
void do_toggle(int flag)
{
bool enabled;
- char *desc;
+ const char *desc;
TOGGLE(flag);
@@ -1354,40 +1451,43 @@ void do_toggle(int flag)
case SUSPEND:
signal_init();
break;
-#ifdef ENABLE_NANORC
+#ifndef DISABLE_NANORC
case WHITESPACE_DISPLAY:
titlebar(NULL);
edit_refresh();
break;
#endif
-#ifdef ENABLE_COLOR
+#ifndef DISABLE_COLOR
case NO_COLOR_SYNTAX:
- edit_refresh();
- break;
#endif
case SOFTWRAP:
- total_refresh();
+ edit_refresh();
break;
}
enabled = ISSET(flag);
- if (flag == NO_HELP
+ if (flag == NO_HELP
#ifndef DISABLE_WRAPPING
|| flag == NO_WRAP
#endif
-#ifdef ENABLE_COLOR
+#ifndef DISABLE_COLOR
|| flag == NO_COLOR_SYNTAX
#endif
)
enabled = !enabled;
- desc = _(flagtostr(flag));
- statusbar("%s %s", desc, enabled ? _("enabled") :
- _("disabled"));
+ desc = (char *) _(flagtostr(flag));
+ statusbar("%s %s", desc, enabled ? _("enabled") : _("disabled"));
}
#endif /* !NANO_TINY */
+/* Bleh. */
+void do_toggle_void(void)
+{
+ ;
+}
+
/* Disable extended input and output processing in our terminal
* settings. */
void disable_extended_io(void)
@@ -1489,16 +1589,10 @@ void terminal_init(void)
}
/* Read in a character, interpret it as a shortcut or toggle if
- * necessary, and return it. Set meta_key to TRUE if the character is a
- * meta sequence, set func_key to TRUE if the character is a function
- * key, set s_or_t to TRUE if the character is a shortcut or toggle
- * key, set ran_func to TRUE if we ran a function associated with a
- * shortcut key, and set finished to TRUE if we're done after running
- * or trying to run a function associated with a shortcut key. If
- * allow_funcs is FALSE, don't actually run any functions associated
+ * necessary, and return it.
+ * If allow_funcs is FALSE, don't actually run any functions associated
* with shortcut keys. */
-int do_input(bool *meta_key, bool *func_key, bool *s_or_t, bool
- *ran_func, bool *finished, bool allow_funcs)
+int do_input(bool allow_funcs)
{
int input;
/* The character we read in. */
@@ -1506,36 +1600,29 @@ int do_input(bool *meta_key, bool *func_key, bool *s_or_t, bool
/* The input buffer. */
static size_t kbinput_len = 0;
/* The length of the input buffer. */
- bool cut_copy = FALSE;
- /* Are we cutting or copying text? */
+ bool preserve = FALSE;
+ /* Preserve the contents of the cutbuffer? */
const sc *s;
bool have_shortcut;
- *s_or_t = FALSE;
- *ran_func = FALSE;
- *finished = FALSE;
-
/* Read in a character. */
- input = get_kbinput(edit, meta_key, func_key);
+ input = get_kbinput(edit);
#ifndef DISABLE_MOUSE
- if (allow_funcs) {
- /* If we got a mouse click and it was on a shortcut, read in the
- * shortcut character. */
- if (*func_key && input == KEY_MOUSE) {
- if (do_mouse() == 1)
- input = get_kbinput(edit, meta_key, func_key);
- else {
- *meta_key = FALSE;
- *func_key = FALSE;
- input = ERR;
- }
- }
+ if (func_key && input == KEY_MOUSE) {
+ /* We received a mouse click. */
+ if (do_mouse() == 1)
+ /* The click was on a shortcut -- read in the character
+ * that it was converted into. */
+ input = get_kbinput(edit);
+ else
+ /* The click was invalid or has been handled -- get out. */
+ return ERR;
}
#endif
/* Check for a shortcut in the main list. */
- s = get_shortcut(MMAIN, &input, meta_key, func_key);
+ s = get_shortcut(&input);
/* If we got a shortcut from the main list, or a "universal"
* edit window shortcut, set have_shortcut to TRUE. */
@@ -1544,11 +1631,11 @@ int do_input(bool *meta_key, bool *func_key, bool *s_or_t, bool
/* If we got a non-high-bit control key, a meta key sequence, or a
* function key, and it's not a shortcut or toggle, throw it out. */
if (!have_shortcut) {
- if (is_ascii_cntrl_char(input) || *meta_key || *func_key) {
+ if (is_ascii_cntrl_char(input) || meta_key || func_key) {
statusbar(_("Unknown Command"));
beep();
- *meta_key = FALSE;
- *func_key = FALSE;
+ meta_key = FALSE;
+ func_key = FALSE;
input = ERR;
}
}
@@ -1575,13 +1662,11 @@ int do_input(bool *meta_key, bool *func_key, bool *s_or_t, bool
* output all the characters in the input buffer if it isn't
* empty. Note that it should be empty if we're in view
* mode. */
- if (have_shortcut || get_key_buffer_len() == 0) {
+ if (have_shortcut || get_key_buffer_len() == 0) {
#ifndef DISABLE_WRAPPING
/* If we got a shortcut or toggle, and it's not the shortcut
- * for verbatim input, turn off prepending of wrapped
- * text. */
- if (have_shortcut && (!have_shortcut || s == NULL || s->scfunc !=
- DO_VERBATIM_INPUT))
+ * for verbatim input, turn off prepending of wrapped text. */
+ if (have_shortcut && s->scfunc != do_verbatim_input)
wrap_reset();
#endif
@@ -1607,63 +1692,51 @@ int do_input(bool *meta_key, bool *func_key, bool *s_or_t, bool
}
if (have_shortcut) {
- switch (input) {
- /* Handle the normal edit window shortcuts, setting
- * ran_func to TRUE if we try to run their associated
- * functions and setting finished to TRUE to indicate
- * that we're done after running or trying to run their
- * associated functions. */
- default:
- /* If the function associated with this shortcut is
- * cutting or copying text, indicate this. */
- if (s->scfunc == DO_CUT_TEXT_VOID
-#ifndef NANO_TINY
- || s->scfunc == DO_COPY_TEXT || s->scfunc ==
- DO_CUT_TILL_END
-#endif
- )
- cut_copy = TRUE;
-
- if (s->scfunc != 0) {
- const subnfunc *f = sctofunc((sc *) s);
- *ran_func = TRUE;
- if (ISSET(VIEW_MODE) && f && !f->viewok)
- print_view_warning();
- else {
+ /* If the function associated with this shortcut is
+ * cutting or copying text, remember this. */
+ if (s->scfunc == do_cut_text_void
#ifndef NANO_TINY
- if (s->scfunc == DO_TOGGLE)
- do_toggle(s->toggle);
- else {
-#else
- {
+ || s->scfunc == do_copy_text || s->scfunc == do_cut_till_eof
#endif
- iso_me_harder_funcmap(s->scfunc);
-#ifdef ENABLE_COLOR
- if (f && !f->viewok && openfile->syntax != NULL
- && openfile->syntax->nmultis > 0) {
- reset_multis(openfile->current, FALSE);
- }
-#endif
- if (edit_refresh_needed) {
+ )
+ preserve = TRUE;
+
+ if (s->scfunc != 0) {
+ const subnfunc *f = sctofunc((sc *) s);
+ if (ISSET(VIEW_MODE) && f && !f->viewok)
+ print_view_warning();
+ else {
+#ifndef NANO_TINY
+ if (s->scfunc == do_toggle_void) {
+ do_toggle(s->toggle);
+ if (s->toggle != CUT_TO_END)
+ preserve = TRUE;
+ } else
+#endif
+ {
+ /* Execute the function of the shortcut. */
+ s->scfunc();
+#ifndef DISABLE_COLOR
+ if (f && !f->viewok && openfile->syntax != NULL
+ && openfile->syntax->nmultis > 0)
+ reset_multis(openfile->current, FALSE);
+#endif
+ if (edit_refresh_needed) {
#ifdef DEBUG
- fprintf(stderr, "running edit_refresh() as edit_refresh_needed is true\n");
+ fprintf(stderr, "running edit_refresh() as edit_refresh_needed is true\n");
#endif
- edit_refresh();
- edit_refresh_needed = FALSE;
- }
-
- }
+ edit_refresh();
+ edit_refresh_needed = FALSE;
}
}
- *finished = TRUE;
- break;
+ }
}
}
}
- /* If we aren't cutting or copying text, blow away the text in the
- * cutbuffer. */
- if (!cut_copy)
+ /* If we aren't cutting or copying text, and the key wasn't a toggle,
+ * blow away the text in the cutbuffer upon the next cutting action. */
+ if (!preserve)
cutbuffer_reset();
return input;
@@ -1687,32 +1760,39 @@ int do_mouse(void)
int mouse_x, mouse_y;
int retval = get_mouseinput(&mouse_x, &mouse_y, TRUE);
+ if (retval != 0)
+ /* The click is wrong or already handled. */
+ return retval;
+
/* We can click on the edit window to move the cursor. */
- if (retval == 0 && wmouse_trafo(edit, &mouse_y, &mouse_x, FALSE)) {
+ if (wmouse_trafo(edit, &mouse_y, &mouse_x, FALSE)) {
bool sameline;
/* Did they click on the line with the cursor? If they
* clicked on the cursor, we set the mark. */
filestruct *current_save = openfile->current;
+#ifndef NANO_TINY
size_t current_x_save = openfile->current_x;
+#endif
size_t pww_save = openfile->placewewant;
sameline = (mouse_y == openfile->current_y);
#ifdef DEBUG
- fprintf(stderr, "mouse_y = %d, current_y = %d\n", mouse_y, openfile->current_y);
+ fprintf(stderr, "mouse_y = %d, current_y = %ld\n", mouse_y, (long)openfile->current_y);
#endif
- if (ISSET(SOFTWRAP)) {
- int i = 0;
+#ifndef NANO_TINY
+ if (ISSET(SOFTWRAP)) {
+ size_t i = 0;
for (openfile->current = openfile->edittop;
openfile->current->next && i < mouse_y;
openfile->current = openfile->current->next, i++) {
openfile->current_y = i;
i += strlenpt(openfile->current->data) / COLS;
}
-
#ifdef DEBUG
- fprintf(stderr, "do_mouse(): moving to current_y = %d, i %d\n", openfile->current_y, i);
+ fprintf(stderr, "do_mouse(): moving to current_y = %ld, index i = %lu\n",
+ (long)openfile->current_y, (unsigned long)i);
fprintf(stderr, " openfile->current->data = \"%s\"\n", openfile->current->data);
#endif
@@ -1720,18 +1800,19 @@ int do_mouse(void)
openfile->current = openfile->current->prev;
openfile->current_x = actual_x(openfile->current->data, mouse_x + (mouse_y - openfile->current_y) * COLS);
#ifdef DEBUG
- fprintf(stderr, "do_mouse(): i > mouse_y, mouse_x = %d, current_x to = %d\n", mouse_x, openfile->current_x);
+ fprintf(stderr, "do_mouse(): i > mouse_y, mouse_x = %d, current_x to = %lu\n",
+ mouse_x, (unsigned long)openfile->current_x);
#endif
} else {
openfile->current_x = actual_x(openfile->current->data, mouse_x);
#ifdef DEBUG
- fprintf(stderr, "do_mouse(): i <= mouse_y, mouse_x = %d, setting current_x to = %d\n", mouse_x, openfile->current_x);
+ fprintf(stderr, "do_mouse(): i <= mouse_y, mouse_x = %d, setting current_x to = %lu\n",
+ mouse_x, (unsigned long)openfile->current_x);
#endif
}
-
- openfile->placewewant = xplustabs();
-
- } else {
+ } else
+#endif /* NANO_TINY */
+ {
/* Move to where the click occurred. */
for (; openfile->current_y < mouse_y && openfile->current !=
openfile->filebot; openfile->current_y++)
@@ -1742,38 +1823,42 @@ int do_mouse(void)
openfile->current_x = actual_x(openfile->current->data,
get_page_start(xplustabs()) + mouse_x);
-
- openfile->placewewant = xplustabs();
}
+ openfile->placewewant = xplustabs();
+
#ifndef NANO_TINY
/* Clicking where the cursor is toggles the mark, as does
* clicking beyond the line length with the cursor at the end of
* the line. */
if (sameline && openfile->current_x == current_x_save)
do_mark();
+ else
#endif
+ /* The cursor moved; clean the cutbuffer on the next cut. */
+ cutbuffer_reset();
edit_redraw(current_save, pww_save);
}
- return retval;
+ /* No more handling is needed. */
+ return 2;
}
#endif /* !DISABLE_MOUSE */
-#ifdef ENABLE_COLOR
+#ifndef DISABLE_COLOR
void alloc_multidata_if_needed(filestruct *fileptr)
{
if (!fileptr->multidata)
- fileptr->multidata = (short *) nmalloc(openfile->syntax->nmultis * sizeof(short));
+ fileptr->multidata = (short *)nmalloc(openfile->syntax->nmultis * sizeof(short));
}
-/* Precalculate the multi-line start and end regex info so we can speed up
- rendering (with any hope at all...) */
+/* Precalculate the multi-line start and end regex info so we can
+ * speed up rendering (with any hope at all...). */
void precalc_multicolorinfo(void)
{
#ifdef DEBUG
- fprintf(stderr, "entering precalc_multicolorinfo()\n");
+ fprintf(stderr, "Entering precalculation of multiline color info\n");
#endif
if (openfile->colorstrings != NULL && !ISSET(NO_COLOR_SYNTAX)) {
const colortype *tmpcolor = openfile->colorstrings;
@@ -1781,30 +1866,26 @@ void precalc_multicolorinfo(void)
filestruct *fileptr, *endptr;
time_t last_check = time(NULL), cur_check = 0;
- /* Let us get keypresses to see if the user is trying to
- start editing. We may want to throw up a statusbar
- message before starting this later if it takes
- too long to do this routine. For now silently
- abort if they hit a key */
- nodelay(edit, FALSE);
+ /* Let us get keypresses to see if the user is trying to start
+ * editing. Later we may want to throw up a statusbar message
+ * before starting this if it takes too long to do this routine.
+ * For now silently abort if they hit a key. */
+ nodelay(edit, TRUE);
for (; tmpcolor != NULL; tmpcolor = tmpcolor->next) {
- /* If it's not a multi-line regex, amscray */
+ /* If it's not a multi-line regex, amscray. */
if (tmpcolor->end == NULL)
continue;
#ifdef DEBUG
- fprintf(stderr, "working on color id %d\n", tmpcolor->id);
+ fprintf(stderr, "Starting work on color id %d\n", tmpcolor->id);
#endif
-
for (fileptr = openfile->fileage; fileptr != NULL; fileptr = fileptr->next) {
int startx = 0;
int nostart = 0;
-
-
#ifdef DEBUG
- fprintf(stderr, "working on lineno %lu\n", (unsigned long) fileptr->lineno);
+ fprintf(stderr, "working on lineno %ld... ", (long)fileptr->lineno);
#endif
alloc_multidata_if_needed(fileptr);
@@ -1812,84 +1893,81 @@ void precalc_multicolorinfo(void)
if ((cur_check = time(NULL)) - last_check > 1) {
last_check = cur_check;
if (wgetch(edit) != ERR)
- goto precalc_cleanup;
+ goto precalc_cleanup;
}
- while ((nostart = regexec(tmpcolor->start, &fileptr->data[startx], 1, &startmatch, 0)) == 0) {
- /* Look for end and start marking how many lines are encompassed
- whcih should speed up rendering later */
+ while ((nostart = regexec(tmpcolor->start, &fileptr->data[startx], 1, &startmatch,
+ (startx == 0) ? 0 : REG_NOTBOL)) == 0) {
+ /* Look for an end, and start marking how many lines are
+ * encompassed, which should speed up rendering later. */
startx += startmatch.rm_eo;
#ifdef DEBUG
- fprintf(stderr, "match found at pos %d...", startx);
+ fprintf(stderr, "start found at pos %lu... ", (unsigned long)startx);
#endif
- /* Look on this line first for end */
- if (regexec(tmpcolor->end, &fileptr->data[startx], 1, &endmatch, 0) == 0) {
+ /* Look first on this line for an end. */
+ if (regexec(tmpcolor->end, &fileptr->data[startx], 1, &endmatch,
+ (startx == 0) ? 0 : REG_NOTBOL) == 0) {
startx += endmatch.rm_eo;
fileptr->multidata[tmpcolor->id] |= CSTARTENDHERE;
#ifdef DEBUG
- fprintf(stderr, "end found on this line\n");
+ fprintf(stderr, "end found on this line\n");
#endif
continue;
}
- /* Nice, we didn't find the end regex on this line. Let's start looking for it */
+ /* Nice, we didn't find the end regex on this line. Let's start looking for it. */
for (endptr = fileptr->next; endptr != NULL; endptr = endptr->next) {
-
#ifdef DEBUG
- fprintf(stderr, "advancing to line %lu to find end...\n", (unsigned long) endptr->lineno);
+ fprintf(stderr, "\nadvancing to line %ld to find end... ", (long)endptr->lineno);
#endif
- /* Check for keyboard input again */
+ /* Check for keyboard input, again. */
if ((cur_check = time(NULL)) - last_check > 1) {
last_check = cur_check;
if (wgetch(edit) != ERR)
- goto precalc_cleanup;
+ goto precalc_cleanup;
}
if (regexec(tmpcolor->end, endptr->data, 1, &endmatch, 0) == 0)
- break;
+ break;
}
if (endptr == NULL) {
#ifdef DEBUG
- fprintf(stderr, "no end found, breaking out\n");
+ fprintf(stderr, "no end found, breaking out\n");
#endif
break;
}
-
#ifdef DEBUG
fprintf(stderr, "end found\n");
#endif
-
- /* We found it, we found it, la la la la la. Mark all the
- lines in between and the ends properly */
+ /* We found it, we found it, la la la la la. Mark all
+ * the lines in between and the end properly. */
fileptr->multidata[tmpcolor->id] |= CENDAFTER;
#ifdef DEBUG
- fprintf(stderr, "marking line %lu as CENDAFTER\n", (unsigned long) fileptr->lineno);
+ fprintf(stderr, "marking line %ld as CENDAFTER\n", (long)fileptr->lineno);
#endif
for (fileptr = fileptr->next; fileptr != endptr; fileptr = fileptr->next) {
alloc_multidata_if_needed(fileptr);
fileptr->multidata[tmpcolor->id] = CWHOLELINE;
#ifdef DEBUG
- fprintf(stderr, "marking intermediary line %lu as CWHOLELINE\n", (unsigned long) fileptr->lineno);
+ fprintf(stderr, "marking intermediary line %ld as CWHOLELINE\n", (long)fileptr->lineno);
#endif
}
alloc_multidata_if_needed(endptr);
+ fileptr->multidata[tmpcolor->id] |= CBEGINBEFORE;
#ifdef DEBUG
- fprintf(stderr, "marking line %lu as BEGINBEFORE\n", (unsigned long) fileptr->lineno);
+ fprintf(stderr, "marking line %ld as CBEGINBEFORE\n", (long)fileptr->lineno);
#endif
- endptr->multidata[tmpcolor->id] |= CBEGINBEFORE;
- /* We should be able to skip all the way to the line of the match.
- This may introduce more bugs but it's the Right Thing to do */
- fileptr = endptr;
+ /* Skip to the end point of the match. */
startx = endmatch.rm_eo;
#ifdef DEBUG
- fprintf(stderr, "jumping to line %lu pos %d to continue\n", (unsigned long) endptr->lineno, startx);
+ fprintf(stderr, "jumping to line %ld pos %lu to continue\n", (long)fileptr->lineno, (unsigned long)startx);
#endif
}
if (nostart && startx == 0) {
#ifdef DEBUG
- fprintf(stderr, "no start found on line %lu, continuing\n", (unsigned long) fileptr->lineno);
+ fprintf(stderr, "no match\n");
#endif
fileptr->multidata[tmpcolor->id] = CNONE;
continue;
@@ -1900,22 +1978,29 @@ void precalc_multicolorinfo(void)
precalc_cleanup:
nodelay(edit, FALSE);
}
-#endif /* ENABLE_COLOR */
+#endif /* !DISABLE_COLOR */
/* The user typed output_len multibyte characters. Add them to the edit
* buffer, filtering out all ASCII control characters if allow_cntrls is
* TRUE. */
void do_output(char *output, size_t output_len, bool allow_cntrls)
{
- size_t current_len, orig_lenpt, i = 0;
+ size_t current_len, i = 0;
+#ifndef NANO_TINY
+ size_t orig_lenpt = 0;
+#endif
+
char *char_buf = charalloc(mb_cur_max());
int char_buf_len;
assert(openfile->current != NULL && openfile->current->data != NULL);
current_len = strlen(openfile->current->data);
+
+#ifndef NANO_TINY
if (ISSET(SOFTWRAP))
orig_lenpt = strlenpt(openfile->current->data);
+#endif
while (i < output_len) {
/* If allow_cntrls is TRUE, convert nulls and newlines
@@ -1966,7 +2051,7 @@ void do_output(char *output, size_t output_len, bool allow_cntrls)
set_modified();
#ifndef NANO_TINY
- update_undo(ADD);
+ add_undo(ADD);
/* Note that current_x has not yet been incremented. */
if (openfile->mark_set && openfile->current ==
@@ -1977,14 +2062,18 @@ void do_output(char *output, size_t output_len, bool allow_cntrls)
openfile->current_x += char_buf_len;
+#ifndef NANO_TINY
+ update_undo(ADD);
+#endif
+
#ifndef DISABLE_WRAPPING
/* If we're wrapping text, we need to call edit_refresh(). */
if (!ISSET(NO_WRAP))
- if (do_wrap(openfile->current, FALSE))
+ if (do_wrap(openfile->current))
edit_refresh_needed = TRUE;
#endif
-#ifdef ENABLE_COLOR
+#ifndef DISABLE_COLOR
/* If color syntaxes are available and turned on, we need to
* call edit_refresh(). */
if (openfile->colorstrings != NULL && !ISSET(NO_COLOR_SYNTAX))
@@ -1992,18 +2081,19 @@ void do_output(char *output, size_t output_len, bool allow_cntrls)
#endif
}
- /* Well we might also need a full refresh if we've changed the
- line length to be a new multiple of COLS */
+#ifndef NANO_TINY
+ /* Well, we might also need a full refresh if we've changed the
+ * line length to be a new multiple of COLS. */
if (ISSET(SOFTWRAP) && edit_refresh_needed == FALSE)
- if (strlenpt(openfile->current->data) / COLS != orig_lenpt / COLS)
+ if (strlenpt(openfile->current->data) / COLS != orig_lenpt / COLS)
edit_refresh_needed = TRUE;
+#endif
free(char_buf);
openfile->placewewant = xplustabs();
-
-#ifdef ENABLE_COLOR
+#ifndef DISABLE_COLOR
reset_multis(openfile->current, FALSE);
#endif
if (edit_refresh_needed == TRUE) {
@@ -2016,15 +2106,13 @@ void do_output(char *output, size_t output_len, bool allow_cntrls)
int main(int argc, char **argv)
{
int optchr;
- ssize_t startline = 1;
- /* Line to try and start at. */
- ssize_t startcol = 1;
- /* Column to try and start at. */
+ ssize_t startline = 0, startcol = 0;
+ /* Target line and column when specified on the command line. */
#ifndef DISABLE_WRAPJUSTIFY
bool fill_used = FALSE;
/* Was the fill option used? */
#endif
-#ifdef ENABLE_MULTIBUFFER
+#ifndef DISABLE_MULTIBUFFER
bool old_multibuffer;
/* The old value of the multibuffer option, restored after we
* load all files on the command line. */
@@ -2033,10 +2121,10 @@ int main(int argc, char **argv)
const struct option long_options[] = {
{"help", 0, NULL, 'h'},
{"boldtext", 0, NULL, 'D'},
-#ifdef ENABLE_MULTIBUFFER
+#ifndef DISABLE_MULTIBUFFER
{"multibuffer", 0, NULL, 'F'},
#endif
-#ifdef ENABLE_NANORC
+#ifndef DISABLE_NANORC
{"ignorercfiles", 0, NULL, 'I'},
#endif
{"rebindkeypad", 0, NULL, 'K'},
@@ -2048,7 +2136,7 @@ int main(int argc, char **argv)
{"restricted", 0, NULL, 'R'},
{"tabsize", 1, NULL, 'T'},
{"version", 0, NULL, 'V'},
-#ifdef ENABLE_COLOR
+#ifndef DISABLE_COLOR
{"syntax", 1, NULL, 'Y'},
#endif
{"const", 0, NULL, 'c'},
@@ -2057,6 +2145,7 @@ int main(int argc, char **argv)
#ifndef DISABLE_MOUSE
{"mouse", 0, NULL, 'm'},
#endif
+ {"noread", 0, NULL, 'n'},
#ifndef DISABLE_OPERATINGDIR
{"operatingdir", 1, NULL, 'o'},
#endif
@@ -2080,8 +2169,10 @@ int main(int argc, char **argv)
{"backup", 0, NULL, 'B'},
{"backupdir", 1, NULL, 'C'},
{"tabstospaces", 0, NULL, 'E'},
+ {"locking", 0, NULL, 'G'},
{"historylog", 0, NULL, 'H'},
{"noconvert", 0, NULL, 'N'},
+ {"poslog", 0, NULL, 'P'},
{"smooth", 0, NULL, 'S'},
{"quickblank", 0, NULL, 'U'},
{"undo", 0, NULL, 'u'},
@@ -2117,7 +2208,7 @@ int main(int argc, char **argv)
textdomain(PACKAGE);
#endif
-#if !defined(ENABLE_NANORC) && defined(DISABLE_ROOTWRAPPING)
+#if defined(DISABLE_NANORC) && defined(DISABLE_ROOTWRAPPING)
/* If we don't have rcfile support, --disable-wrapping-as-root is
* used, and we're root, turn wrapping off. */
if (geteuid() == NANO_ROOT_UID)
@@ -2127,11 +2218,11 @@ int main(int argc, char **argv)
while ((optchr =
#ifdef HAVE_GETOPT_LONG
getopt_long(argc, argv,
- "h?ABC:DEFHIKLNOQ:RST:UVWY:abcdefgijklmo:pqr:s:tuvwxz$",
+ "ABC:DEFGHIKLNOPQ:RST:UVWY:abcdefghijklmno:pqr:s:tvwxz$",
long_options, NULL)
#else
getopt(argc, argv,
- "h?ABC:DEFHIKLNOQ:RST:UVWY:abcdefgijklmo:pqr:s:tuvwxz$")
+ "ABC:DEFGHIKLNOPQ:RST:UVWY:abcdefghijklmno:pqr:s:tvwxz$")
#endif
) != -1) {
switch (optchr) {
@@ -2162,17 +2253,22 @@ int main(int argc, char **argv)
SET(TABS_TO_SPACES);
break;
#endif
-#ifdef ENABLE_MULTIBUFFER
+#ifndef DISABLE_MULTIBUFFER
case 'F':
SET(MULTIBUFFER);
break;
#endif
-#ifdef ENABLE_NANORC
#ifndef NANO_TINY
+ case 'G':
+ SET(LOCKING);
+ break;
+#endif
+#ifndef DISABLE_HISTORIES
case 'H':
SET(HISTORYLOG);
break;
#endif
+#ifndef DISABLE_NANORC
case 'I':
no_rcfiles = TRUE;
break;
@@ -2191,6 +2287,11 @@ int main(int argc, char **argv)
case 'O':
SET(MORE_SPACE);
break;
+#ifndef DISABLE_HISTORIES
+ case 'P':
+ SET(POS_HISTORY);
+ break;
+#endif
#ifndef DISABLE_JUSTIFY
case 'Q':
quotestr = mallocstrcpy(quotestr, optarg);
@@ -2224,7 +2325,7 @@ int main(int argc, char **argv)
SET(WORD_BOUNDS);
break;
#endif
-#ifdef ENABLE_COLOR
+#ifndef DISABLE_COLOR
case 'Y':
syntaxstr = mallocstrcpy(syntaxstr, optarg);
break;
@@ -2251,6 +2352,9 @@ int main(int argc, char **argv)
SET(USE_MOUSE);
break;
#endif
+ case 'n':
+ SET(NOREAD_MODE);
+ break;
#ifndef DISABLE_OPERATINGDIR
case 'o':
operating_dir = mallocstrcpy(operating_dir, optarg);
@@ -2259,9 +2363,11 @@ int main(int argc, char **argv)
case 'p':
SET(PRESERVE);
break;
+#ifndef DISABLE_NANORC
case 'q':
SET(QUIET);
break;
+#endif
#ifndef DISABLE_WRAPJUSTIFY
case 'r':
if (!parse_num(optarg, &wrap_at)) {
@@ -2280,22 +2386,15 @@ int main(int argc, char **argv)
case 't':
SET(TEMP_FILE);
break;
-#ifndef NANO_TINY
- case 'u':
- SET(UNDOABLE);
- break;
-#endif
case 'v':
SET(VIEW_MODE);
break;
#ifndef DISABLE_WRAPPING
case 'w':
SET(NO_WRAP);
-
- /* If both --fill and --nowrap are given on the command line,
- the last option wins, */
+ /* If both --fill and --nowrap are given on the
+ * command line, the last given option wins. */
fill_used = FALSE;
-
break;
#endif
case 'x':
@@ -2309,8 +2408,12 @@ int main(int argc, char **argv)
SET(SOFTWRAP);
break;
#endif
- default:
+ case 'h':
usage();
+ exit(0);
+ default:
+ printf(_("Type '%s -h' for a list of available options.\n"), argv[0]);
+ exit(1);
}
}
@@ -2319,26 +2422,27 @@ int main(int argc, char **argv)
if (*(tail(argv[0])) == 'r')
SET(RESTRICTED);
- /* If we're using restricted mode, disable suspending, backups, and
- * reading rcfiles, since they all would allow reading from or
- * writing to files not specified on the command line. */
+ /* If we're using restricted mode, disable suspending, backups,
+ * rcfiles, and history files, since they all would allow reading
+ * from or writing to files not specified on the command line. */
if (ISSET(RESTRICTED)) {
UNSET(SUSPEND);
UNSET(BACKUP_FILE);
-#ifdef ENABLE_NANORC
+#ifndef DISABLE_NANORC
no_rcfiles = TRUE;
+ UNSET(HISTORYLOG);
+ UNSET(POS_HISTORY);
#endif
}
-
- /* Set up the shortcut lists.
- Need to do this before the rcfile */
- shortcut_init(FALSE);
+ /* Set up the function and shortcut lists. This needs to be done
+ * before reading the rcfile, to be able to rebind/unbind keys. */
+ shortcut_init();
/* We've read through the command line options. Now back up the flags
* and values that are set, and read the rcfile(s). If the values
* haven't changed afterward, restore the backed-up values. */
-#ifdef ENABLE_NANORC
+#ifndef DISABLE_NANORC
if (!no_rcfiles) {
#ifndef DISABLE_OPERATINGDIR
char *operating_dir_cpy = operating_dir;
@@ -2421,11 +2525,11 @@ int main(int argc, char **argv)
else if (geteuid() == NANO_ROOT_UID)
SET(NO_WRAP);
#endif
-#endif /* ENABLE_NANORC */
+#endif /* !DISABLE_NANORC */
#ifndef DISABLE_WRAPPING
/* Overwrite an rcfile "set nowrap" or --disable-wrapping-as-root
- if a --fill option was given on the command line. */
+ * if a --fill option was given on the command line. */
if (fill_used)
UNSET(NO_WRAP);
#endif
@@ -2433,16 +2537,24 @@ int main(int argc, char **argv)
/* If we're using bold text instead of reverse video text, set it up
* now. */
if (ISSET(BOLD_TEXT))
- reverse_attr = A_BOLD;
+ hilite_attribute = A_BOLD;
-#ifndef NANO_TINY
+#ifndef DISABLE_HISTORIES
/* Set up the search/replace history. */
history_init();
-#ifdef ENABLE_NANORC
- if (!no_rcfiles && ISSET(HISTORYLOG))
+ /* Verify that the home directory and ~/.nano subdir exist. */
+ if (ISSET(HISTORYLOG) || ISSET(POS_HISTORY)) {
+ get_homedir();
+ if (homedir == NULL || check_dotnano() == 0) {
+ UNSET(HISTORYLOG);
+ UNSET(POS_HISTORY);
+ }
+ }
+ if (ISSET(HISTORYLOG))
load_history();
-#endif
-#endif
+ if (ISSET(POS_HISTORY))
+ load_poshistory();
+#endif /* !DISABLE_HISTORIES */
#ifndef NANO_TINY
/* Set up the backup directory (unless we're using restricted mode,
@@ -2513,16 +2625,28 @@ int main(int argc, char **argv)
/* If matchbrackets wasn't specified, set its default value. */
if (matchbrackets == NULL)
matchbrackets = mallocstrcpy(NULL, "(<[{)>]}");
-#endif
-#if !defined(NANO_TINY) && defined(ENABLE_NANORC)
- /* If whitespace wasn't specified, set its default value. */
+#ifndef DISABLE_NANORC
+ /* If whitespace wasn't specified, set its default value. If we're
+ * using UTF-8, it's Unicode 00BB (Right-Pointing Double Angle
+ * Quotation Mark) and Unicode 00B7 (Middle Dot). Otherwise, it's
+ * ">" and ".". */
if (whitespace == NULL) {
- whitespace = mallocstrcpy(NULL, " ");
- whitespace_len[0] = 1;
- whitespace_len[1] = 1;
+#ifdef ENABLE_UTF8
+ if (using_utf8()) {
+ whitespace = mallocstrcpy(NULL, "\xC2\xBB\xC2\xB7");
+ whitespace_len[0] = 2;
+ whitespace_len[1] = 2;
+ } else
+#endif
+ {
+ whitespace = mallocstrcpy(NULL, ">.");
+ whitespace_len[0] = 1;
+ whitespace_len[1] = 1;
+ }
}
-#endif
+#endif /* !DISABLE_NANORC */
+#endif /* !NANO_TINY */
/* If tabsize wasn't specified, set its default value. */
if (tabsize == -1)
@@ -2557,6 +2681,19 @@ int main(int argc, char **argv)
mouse_init();
#endif
+#ifndef DISABLE_COLOR
+ set_colorpairs();
+#else
+ interface_color_pair[TITLE_BAR].pairnum = hilite_attribute;
+ interface_color_pair[STATUS_BAR].pairnum = hilite_attribute;
+ interface_color_pair[KEY_COMBO].pairnum = hilite_attribute;
+ interface_color_pair[FUNCTION_TAG].pairnum = A_NORMAL;
+ interface_color_pair[TITLE_BAR].bright = FALSE;
+ interface_color_pair[STATUS_BAR].bright = FALSE;
+ interface_color_pair[KEY_COMBO].bright = FALSE;
+ interface_color_pair[FUNCTION_TAG].bright = FALSE;
+#endif
+
#ifdef DEBUG
fprintf(stderr, "Main: open file\n");
#endif
@@ -2575,7 +2712,7 @@ int main(int argc, char **argv)
optind++;
}
-#ifdef ENABLE_MULTIBUFFER
+#ifndef DISABLE_MULTIBUFFER
old_multibuffer = ISSET(MULTIBUFFER);
SET(MULTIBUFFER);
@@ -2583,7 +2720,7 @@ int main(int argc, char **argv)
* new buffers. */
{
int i = optind + 1;
- ssize_t iline = 1, icol = 1;
+ ssize_t iline = 0, icol = 0;
for (; i < argc; i++) {
/* If there's a +LINE or +LINE,COLUMN flag here, it is
@@ -2595,16 +2732,25 @@ int main(int argc, char **argv)
else {
open_buffer(argv[i], FALSE);
- if (iline > 1 || icol > 1) {
+ if (iline > 0 || icol > 0) {
do_gotolinecolumn(iline, icol, FALSE, FALSE, FALSE,
FALSE);
iline = 1;
icol = 1;
}
+#ifndef DISABLE_HISTORIES
+ else {
+ /* See if we have a POS history to use if we haven't overridden it. */
+ ssize_t savedposline, savedposcol;
+ if (check_poshistory(argv[i], &savedposline, &savedposcol))
+ do_gotolinecolumn(savedposline, savedposcol, FALSE, FALSE, FALSE,
+ FALSE);
+ }
+#endif
}
}
}
-#endif
+#endif /* !DISABLE_MULTIBUFFER */
/* Read the first file on the command line into either the current
* buffer or a new buffer, depending on whether multibuffer mode is
@@ -2621,7 +2767,7 @@ int main(int argc, char **argv)
UNSET(VIEW_MODE);
}
-#ifdef ENABLE_MULTIBUFFER
+#ifndef DISABLE_MULTIBUFFER
if (!old_multibuffer)
UNSET(MULTIBUFFER);
#endif
@@ -2630,22 +2776,29 @@ int main(int argc, char **argv)
fprintf(stderr, "Main: top and bottom win\n");
#endif
-#ifdef ENABLE_COLOR
- if (openfile->syntax && openfile->syntax->nmultis > 0)
- precalc_multicolorinfo();
+#ifndef DISABLE_COLOR
+ if (openfile->syntax)
+ if (openfile->syntax->nmultis > 0)
+ precalc_multicolorinfo();
#endif
- if (startline > 1 || startcol > 1)
+ if (startline > 0 || startcol > 0)
do_gotolinecolumn(startline, startcol, FALSE, FALSE, FALSE,
FALSE);
+#ifndef DISABLE_HISTORIES
+ else {
+ /* See if we have a POS history to use if we haven't overridden it. */
+ ssize_t savedposline, savedposcol;
+ if (check_poshistory(argv[optind], &savedposline, &savedposcol))
+ do_gotolinecolumn(savedposline, savedposcol, FALSE, FALSE, FALSE, FALSE);
+ }
+#endif
display_main_list();
display_buffer();
while (TRUE) {
- bool meta_key, func_key, s_or_t, ran_func, finished;
-
/* Make sure the cursor is in the edit window. */
reset_cursor();
wnoutrefresh(edit);
@@ -2674,11 +2827,9 @@ int main(int argc, char **argv)
currmenu = MMAIN;
/* Read in and interpret characters. */
- do_input(&meta_key, &func_key, &s_or_t, &ran_func, &finished,
- TRUE);
+ do_input(TRUE);
}
/* We should never get here. */
assert(FALSE);
}
-
diff --git a/src/nano.h b/src/nano.h
index 12131fb..4b44fb8 100644
--- a/src/nano.h
+++ b/src/nano.h
@@ -1,9 +1,9 @@
-/* $Id: nano.h 4508 2010-06-21 03:10:10Z astyanax $ */
+/* $Id: nano.h 5100 2015-01-03 07:24:17Z astyanax $ */
/**************************************************************************
* nano.h *
* *
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
- * 2008, 2009 Free Software Foundation, Inc. *
+ * 2008, 2009, 2010, 2011, 2013, 2014 Free Software Foundation, Inc. *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 3, or (at your option) *
@@ -31,8 +31,8 @@
#ifdef NEED_XOPEN_SOURCE_EXTENDED
#ifndef _XOPEN_SOURCE_EXTENDED
#define _XOPEN_SOURCE_EXTENDED 1
-#endif /* _XOPEN_SOURCE_EXTENDED */
-#endif /* NEED_XOPEN_SOURCE_EXTENDED */
+#endif
+#endif
#ifdef __TANDEM
/* Tandem NonStop Kernel support. */
@@ -54,13 +54,12 @@
#include <stdarg.h>
#endif
-/* Suppress warnings for __attribute__((warn_unused_result)) */
+/* Suppress warnings for __attribute__((warn_unused_result)). */
#define IGNORE_CALL_RESULT(call) do { if (call) {} } while(0)
-/* Macros for flags. */
-#define FLAGOFF(flag) ((flag) / (sizeof(unsigned) * 8))
+/* Macros for flags, indexing each bit in a small array. */
+#define FLAGS(flag) flags[((flag) / (sizeof(unsigned) * 8))]
#define FLAGMASK(flag) (1 << ((flag) % (sizeof(unsigned) * 8)))
-#define FLAGS(flag) flags[FLAGOFF(flag)]
#define SET(flag) FLAGS(flag) |= FLAGMASK(flag)
#define UNSET(flag) FLAGS(flag) &= ~FLAGMASK(flag)
#define ISSET(flag) ((FLAGS(flag) & FLAGMASK(flag)) != 0)
@@ -85,6 +84,8 @@
#define KEY_DC SL_KEY_DELETE
#define KEY_IC SL_KEY_IC
/* Ncurses support. */
+#elif defined(HAVE_NCURSESW_NCURSES_H)
+#include <ncursesw/ncurses.h>
#elif defined(HAVE_NCURSES_H)
#include <ncurses.h>
#else
@@ -174,7 +175,7 @@ typedef enum {
} append_type;
typedef enum {
- UP_DIR, DOWN_DIR
+ UPWARD, DOWNWARD
} scroll_dir;
typedef enum {
@@ -182,14 +183,26 @@ typedef enum {
} update_type;
typedef enum {
- CONTROL, META, FKEY, RAW
-} function_type;
+ CONTROL, META, FKEY, RAWINPUT
+} key_type;
typedef enum {
- ADD, DEL, REPLACE, SPLIT, UNSPLIT, CUT, UNCUT, ENTER, INSERT, OTHER
+ ADD, DEL, BACK, CUT, CUT_EOF, REPLACE,
+#ifndef DISABLE_WRAPPING
+ SPLIT_BEGIN, SPLIT_END,
+#endif
+ JOIN, PASTE, INSERT, ENTER, OTHER
} undo_type;
-#ifdef ENABLE_COLOR
+typedef struct color_pair {
+ int pairnum;
+ /* The color pair number used for this foreground color and
+ * background color. */
+ bool bright;
+ /* Is this color A_BOLD? */
+} color_pair;
+
+#ifndef DISABLE_COLOR
typedef struct colortype {
short fg;
/* This syntax's foreground color. */
@@ -212,48 +225,70 @@ typedef struct colortype {
/* The compiled end (if any) of the regex string. */
struct colortype *next;
/* Next set of colors. */
- int id;
- /* basic id for assigning to lines later */
+ int id;
+ /* Basic id for assigning to lines later. */
} colortype;
-typedef struct exttype {
+typedef struct regexlisttype {
char *ext_regex;
- /* The extensions that match this syntax. */
+ /* The regexstrings for the things that match this syntax. */
regex_t *ext;
- /* The compiled extensions that match this syntax. */
- struct exttype *next;
- /* Next set of extensions. */
-} exttype;
+ /* The compiled regexes. */
+ struct regexlisttype *next;
+ /* Next set of regexes. */
+} regexlisttype;
typedef struct syntaxtype {
char *desc;
/* The name of this syntax. */
- exttype *extensions;
+ regexlisttype *extensions;
/* The list of extensions that this syntax applies to. */
- exttype *headers;
- /* Regexes to match on the 'header' (1st line) of the file */
+ regexlisttype *headers;
+ /* The list of headerlines that this syntax applies to. */
+ regexlisttype *magics;
+ /* The list of libmagic results that this syntax applies to. */
colortype *color;
/* The colors used in this syntax. */
+ char *linter;
+ /* The command to lint this type of file. */
+ char *formatter;
+ /* Use this formatter command (for programming lang mainly) */
int nmultis;
- /* How many multi line strings this syntax has */
+ /* How many multi-line strings this syntax has. */
struct syntaxtype *next;
/* Next syntax. */
} syntaxtype;
-#define CNONE (1<<1)
+typedef struct lintstruct {
+ ssize_t lineno;
+ /* Line number of the error. */
+ ssize_t colno;
+ /* Column # of the error. */
+ char *msg;
+ /* Error message text. */
+ char *filename;
+ /* Filename. */
+ struct lintstruct *next;
+ /* Next error. */
+ struct lintstruct *prev;
+ /* Previous error. */
+} lintstruct;
+
+
+#define CNONE (1<<1)
/* Yay, regex doesn't apply to this line at all! */
-#define CBEGINBEFORE (1<<2)
- /* regex starts on an earlier line, ends on this one */
-#define CENDAFTER (1<<3)
- /* regex sraers on this line and ends on a later one */
-#define CWHOLELINE (1<<4)
- /* whole line engulfed by the regex start < me, end > me */
-#define CSTARTENDHERE (1<<5)
- /* regex starts and ends within this line */
+#define CBEGINBEFORE (1<<2)
+ /* Regex starts on an earlier line, ends on this one. */
+#define CENDAFTER (1<<3)
+ /* Regex starts on this line and ends on a later one. */
+#define CWHOLELINE (1<<4)
+ /* Whole line engulfed by the regex, start < me, end > me. */
+#define CSTARTENDHERE (1<<5)
+ /* Regex starts and ends within this line. */
#define CWTF (1<<6)
- /* Something else */
+ /* Something else. */
-#endif /* ENABLE_COLOR */
+#endif /* !DISABLE_COLOR */
/* Structure types. */
@@ -266,8 +301,9 @@ typedef struct filestruct {
/* Next node. */
struct filestruct *prev;
/* Previous node. */
-#ifdef ENABLE_COLOR
- short *multidata; /* Array of which multi-line regexes apply to this line */
+#ifndef DISABLE_COLOR
+ short *multidata;
+ /* Array of which multi-line regexes apply to this line. */
#endif
} filestruct;
@@ -293,35 +329,40 @@ typedef struct partition {
typedef struct undo {
ssize_t lineno;
undo_type type;
- /* What type of undo was this */
- int begin;
- /* Where did this action begin or end */
+ /* What type of undo this was. */
+ size_t begin;
+ /* Where did this action begin or end. */
char *strdata;
- /* String type data we will use for ccopying the affected line back */
- char *strdata2;
- /* Sigh, need this too it looks like */
+ /* String type data we will use for copying the affected line back. */
int xflags;
- /* Some flag data we need */
+ /* Some flag data we need. */
- /* Cut specific stuff we need */
+ /* Cut-specific stuff we need. */
filestruct *cutbuffer;
- /* Copy of the cutbuffer */
+ /* Copy of the cutbuffer. */
filestruct *cutbottom;
- /* Copy of cutbottom */
+ /* Copy of cutbottom. */
bool mark_set;
- /* was the marker set when we cut */
- bool to_end;
- /* was this a cut to end */
+ /* Was the marker set when we cut? */
ssize_t mark_begin_lineno;
/* copy copy copy */
- ssize_t mark_begin_x;
- /* Another shadow variable */
+ size_t mark_begin_x;
+ /* Another shadow variable. */
struct undo *next;
} undo;
+#endif /* !NANO_TINY */
-
-#endif /* NANO_TINY */
-
+#ifndef DISABLE_HISTORIES
+typedef struct poshiststruct {
+ char *filename;
+ /* The file. */
+ ssize_t lineno;
+ /* Line number we left off on. */
+ ssize_t xno;
+ /* x position in the file we left off on. */
+ struct poshiststruct *next;
+} poshiststruct;
+#endif
typedef struct openfilestruct {
char *filename;
@@ -339,7 +380,7 @@ typedef struct openfilestruct {
size_t current_x;
/* The current file's x-coordinate position. */
size_t placewewant;
- /* The current file's place we want. */
+ /* The current file's x position we would like. */
ssize_t current_y;
/* The current file's y-coordinate position. */
bool modified;
@@ -357,14 +398,16 @@ typedef struct openfilestruct {
struct stat *current_stat;
/* The current file's stat. */
undo *undotop;
- /* Top of the undo list */
+ /* Top of the undo list. */
undo *current_undo;
- /* The current (i.e. n ext) level of undo */
+ /* The current (i.e. next) level of undo. */
undo_type last_action;
+ const char *lock_filename;
+ /* The path of the lockfile, if we created one. */
#endif
-#ifdef ENABLE_COLOR
+#ifndef DISABLE_COLOR
syntaxtype *syntax;
- /* The syntax struct for this file, if any */
+ /* The syntax struct for this file, if any. */
colortype *colorstrings;
/* The current file's associated colors. */
#endif
@@ -384,17 +427,6 @@ typedef struct shortcut {
/* Whether there should be a blank line after the help entry
* text for this function. */
#endif
- /* Note: Key values that aren't used should be set to
- * NANO_NO_KEY. */
- int ctrlval;
- /* The special sentinel key or control key we want bound, if
- * any. */
- int metaval;
- /* The meta key we want bound, if any. */
- int funcval;
- /* The function key we want bound, if any. */
- int miscval;
- /* The other meta key we want bound, if any. */
bool viewok;
/* Is this function allowed when in view mode? */
void (*func)(void);
@@ -403,41 +435,40 @@ typedef struct shortcut {
/* Next shortcut. */
} shortcut;
-#ifdef ENABLE_NANORC
+#ifndef DISABLE_NANORC
typedef struct rcoption {
const char *name;
/* The name of the rcfile option. */
long flag;
/* The flag associated with it, if any. */
} rcoption;
-
#endif
typedef struct sc {
char *keystr;
- /* The shortcut key for a function, ASCII version */
- function_type type;
- /* What kind of function key is it for convenience later */
+ /* The shortcut key for a function, ASCII version. */
+ key_type type;
+ /* What kind of command key it is, for convenience later. */
int seq;
- /* The actual sequence to check on the the type is determined */
+ /* The actual sequence to check on the type is determined. */
int menu;
- /* What list does this apply to */
- short scfunc;
- /* The function we're going to run */
+ /* What list this applies to. */
+ void (*scfunc)(void);
+ /* The function we're going to run. */
int toggle;
- /* If a toggle, what we're toggling */
+ /* If a toggle, what we're toggling. */
bool execute;
/* Whether to execute the function in question or just return
- so the sequence can be caught by the calling code */
+ * so the sequence can be caught by the calling code. */
struct sc *next;
- /* Next in the list */
+ /* Next in the list. */
} sc;
typedef struct subnfunc {
- short scfunc;
- /* What function is this */
+ void (*scfunc)(void);
+ /* What function this is. */
int menus;
- /* In what menus does this function applu */
+ /* In what menus this function applies. */
const char *desc;
/* The function's description, e.g. "Page Up". */
#ifndef DISABLE_HELP
@@ -448,16 +479,24 @@ typedef struct subnfunc {
* text for this function. */
#endif
bool viewok;
- /* Is this function allowed when in view mode? */
+ /* Is this function allowed when in view mode? */
long toggle;
- /* If this is a toggle, if nonzero what toggle to set */
+ /* If this is a toggle, if nonzero what toggle to set. */
struct subnfunc *next;
- /* next item in the list */
+ /* Next item in the list. */
} subnfunc;
+/* The elements of the interface that can be colored differently. */
+enum
+{
+ TITLE_BAR = 0,
+ STATUS_BAR,
+ KEY_COMBO,
+ FUNCTION_TAG,
+ NUMBER_OF_ELEMENTS
+};
-/* Enumeration to be used in flags table. See FLAGBIT and FLAGOFF
- * definitions. */
+/* Enumeration used in the flags array. See the definition of FLAGMASK. */
enum
{
DONTUSE,
@@ -494,425 +533,53 @@ enum
NO_NEWLINES,
BOLD_TEXT,
QUIET,
- UNDOABLE,
- SOFTWRAP
+ SOFTWRAP,
+ POS_HISTORY,
+ LOCKING,
+ NOREAD_MODE
};
-/* Flags for which menus in which a given function should be present */
-#define MMAIN (1<<0)
-#define MWHEREIS (1<<1)
-#define MREPLACE (1<<2)
-#define MREPLACE2 (1<<3)
-#define MGOTOLINE (1<<4)
-#define MWRITEFILE (1<<5)
-#define MINSERTFILE (1<<6)
-#define MEXTCMD (1<<7)
-#define MHELP (1<<8)
-#define MSPELL (1<<9)
-#define MBROWSER (1<<10)
-#define MWHEREISFILE (1<<11)
-#define MGOTODIR (1<<12)
-#define MYESNO (1<<13)
-/* This really isnt all but close enough */
-#define MALL (MMAIN|MWHEREIS|MREPLACE|MREPLACE2|MGOTOLINE|MWRITEFILE|MINSERTFILE|MEXTCMD|MSPELL|MBROWSER|MWHEREISFILE|MGOTODIR|MHELP)
+/* Flags for the menus in which a given function should be present. */
+#define MMAIN (1<<0)
+#define MWHEREIS (1<<1)
+#define MREPLACE (1<<2)
+#define MREPLACEWITH (1<<3)
+#define MGOTOLINE (1<<4)
+#define MWRITEFILE (1<<5)
+#define MINSERTFILE (1<<6)
+#define MEXTCMD (1<<7)
+#define MHELP (1<<8)
+#define MSPELL (1<<9)
+#define MBROWSER (1<<10)
+#define MWHEREISFILE (1<<11)
+#define MGOTODIR (1<<12)
+#define MYESNO (1<<13)
+#define MLINTER (1<<14)
+/* This is an abbreviation for all menus except Help and YesNo. */
+#define MMOST (MMAIN|MWHEREIS|MREPLACE|MREPLACEWITH|MGOTOLINE|MWRITEFILE|MINSERTFILE|MEXTCMD|MBROWSER|MWHEREISFILE|MGOTODIR|MSPELL|MLINTER)
/* Control key sequences. Changing these would be very, very bad. */
#define NANO_CONTROL_SPACE 0
-#define NANO_CONTROL_A 1
-#define NANO_CONTROL_B 2
-#define NANO_CONTROL_C 3
-#define NANO_CONTROL_D 4
-#define NANO_CONTROL_E 5
-#define NANO_CONTROL_F 6
-#define NANO_CONTROL_G 7
-#define NANO_CONTROL_H 8
#define NANO_CONTROL_I 9
-#define NANO_CONTROL_J 10
-#define NANO_CONTROL_K 11
-#define NANO_CONTROL_L 12
-#define NANO_CONTROL_M 13
-#define NANO_CONTROL_N 14
-#define NANO_CONTROL_O 15
-#define NANO_CONTROL_P 16
-#define NANO_CONTROL_Q 17
-#define NANO_CONTROL_R 18
-#define NANO_CONTROL_S 19
-#define NANO_CONTROL_T 20
-#define NANO_CONTROL_U 21
-#define NANO_CONTROL_V 22
-#define NANO_CONTROL_W 23
-#define NANO_CONTROL_X 24
-#define NANO_CONTROL_Y 25
-#define NANO_CONTROL_Z 26
#define NANO_CONTROL_3 27
-#define NANO_CONTROL_4 28
-#define NANO_CONTROL_5 29
-#define NANO_CONTROL_6 30
#define NANO_CONTROL_7 31
#define NANO_CONTROL_8 127
-/* Meta key sequences. */
-#define NANO_META_SPACE ' '
-#define NANO_META_LPARENTHESIS '('
-#define NANO_META_RPARENTHESIS ')'
-#define NANO_META_PLUS '+'
-#define NANO_META_COMMA ','
-#define NANO_META_MINUS '-'
-#define NANO_META_PERIOD '.'
-#define NANO_META_SLASH '/'
-#define NANO_META_0 '0'
-#define NANO_META_6 '6'
-#define NANO_META_9 '9'
-#define NANO_META_LCARET '<'
-#define NANO_META_EQUALS '='
-#define NANO_META_RCARET '>'
-#define NANO_META_QUESTION '?'
-#define NANO_META_BACKSLASH '\\'
-#define NANO_META_RBRACKET ']'
-#define NANO_META_CARET '^'
-#define NANO_META_UNDERSCORE '_'
-#define NANO_META_A 'a'
-#define NANO_META_B 'b'
-#define NANO_META_C 'c'
-#define NANO_META_D 'd'
-#define NANO_META_E 'e'
-#define NANO_META_F 'f'
-#define NANO_META_G 'g'
-#define NANO_META_H 'h'
-#define NANO_META_I 'i'
-#define NANO_META_J 'j'
-#define NANO_META_K 'k'
-#define NANO_META_L 'l'
-#define NANO_META_M 'm'
-#define NANO_META_N 'n'
-#define NANO_META_O 'o'
-#define NANO_META_P 'p'
-#define NANO_META_Q 'q'
-#define NANO_META_R 'r'
-#define NANO_META_S 's'
-#define NANO_META_T 't'
-#define NANO_META_U 'u'
-#define NANO_META_V 'v'
-#define NANO_META_W 'w'
-#define NANO_META_X 'x'
-#define NANO_META_Y 'y'
-#define NANO_META_Z 'z'
-#define NANO_META_LCURLYBRACKET '{'
-#define NANO_META_PIPE '|'
-#define NANO_META_RCURLYBRACKET '}'
-
-/* Some semi-changeable keybindings; don't play with these unless you're
- * sure you know what you're doing. Assume ERR is defined as -1. */
-
-/* No key at all. */
-#define NANO_NO_KEY -2
-
-/* Normal keys. */
-#define NANO_XON_KEY NANO_CONTROL_Q
-#define NANO_XOFF_KEY NANO_CONTROL_S
-#define NANO_CANCEL_KEY NANO_CONTROL_C
-#define NANO_EXIT_KEY NANO_CONTROL_X
-#define NANO_EXIT_FKEY KEY_F(2)
-#define NANO_INSERTFILE_KEY NANO_CONTROL_R
-#define NANO_INSERTFILE_FKEY KEY_F(5)
-#define NANO_TOOTHERINSERT_KEY NANO_CONTROL_X
-#define NANO_WRITEOUT_KEY NANO_CONTROL_O
-#define NANO_WRITEOUT_FKEY KEY_F(3)
-#define NANO_GOTOLINE_KEY NANO_CONTROL_7
-#define NANO_GOTOLINE_FKEY KEY_F(13)
-#define NANO_GOTOLINE_METAKEY NANO_META_G
-#define NANO_GOTODIR_KEY NANO_CONTROL_7
-#define NANO_GOTODIR_FKEY KEY_F(13)
-#define NANO_GOTODIR_METAKEY NANO_META_G
-#define NANO_TOGOTOLINE_KEY NANO_CONTROL_T
-#define NANO_HELP_KEY NANO_CONTROL_G
-#define NANO_HELP_FKEY KEY_F(1)
-#define NANO_WHEREIS_KEY NANO_CONTROL_W
-#define NANO_WHEREIS_FKEY KEY_F(6)
-#define NANO_WHEREIS_NEXT_KEY NANO_META_W
-#define NANO_WHEREIS_NEXT_FKEY KEY_F(16)
-#define NANO_TOOTHERWHEREIS_KEY NANO_CONTROL_T
-#define NANO_REGEXP_KEY NANO_META_R
-#define NANO_REPLACE_KEY NANO_CONTROL_4
-#define NANO_REPLACE_FKEY KEY_F(14)
-#define NANO_REPLACE_METAKEY NANO_META_R
-#define NANO_TOOTHERSEARCH_KEY NANO_CONTROL_R
-#define NANO_PREVPAGE_KEY NANO_CONTROL_Y
-#define NANO_PREVPAGE_FKEY KEY_F(7)
-#define NANO_NEXTPAGE_KEY NANO_CONTROL_V
-#define NANO_NEXTPAGE_FKEY KEY_F(8)
-#define NANO_CUT_KEY NANO_CONTROL_K
-#define NANO_CUT_FKEY KEY_F(9)
-#define NANO_COPY_KEY NANO_META_CARET
-#define NANO_COPY_METAKEY NANO_META_6
-#define NANO_UNCUT_KEY NANO_CONTROL_U
-#define NANO_UNCUT_FKEY KEY_F(10)
-#define NANO_CURSORPOS_KEY NANO_CONTROL_C
-#define NANO_CURSORPOS_FKEY KEY_F(11)
-#define NANO_SPELL_KEY NANO_CONTROL_T
-#define NANO_SPELL_FKEY KEY_F(12)
-#define NANO_FIRSTLINE_KEY NANO_PREVPAGE_KEY
-#define NANO_FIRSTLINE_FKEY NANO_PREVPAGE_FKEY
-#define NANO_FIRSTLINE_METAKEY NANO_META_BACKSLASH
-#define NANO_FIRSTLINE_METAKEY2 NANO_META_PIPE
-#define NANO_FIRSTFILE_KEY NANO_FIRSTLINE_KEY
-#define NANO_FIRSTFILE_FKEY NANO_FIRSTLINE_FKEY
-#define NANO_FIRSTFILE_METAKEY NANO_FIRSTLINE_METAKEY
-#define NANO_FIRSTFILE_METAKEY2 NANO_FIRSTLINE_METAKEY2
-#define NANO_LASTLINE_KEY NANO_NEXTPAGE_KEY
-#define NANO_LASTLINE_FKEY NANO_NEXTPAGE_FKEY
-#define NANO_LASTLINE_METAKEY NANO_META_SLASH
-#define NANO_LASTLINE_METAKEY2 NANO_META_QUESTION
-#define NANO_LASTFILE_KEY NANO_LASTLINE_KEY
-#define NANO_LASTFILE_FKEY NANO_LASTLINE_FKEY
-#define NANO_LASTFILE_METAKEY NANO_LASTLINE_METAKEY
-#define NANO_LASTFILE_METAKEY2 NANO_LASTLINE_METAKEY2
-#define NANO_REFRESH_KEY NANO_CONTROL_L
-#define NANO_JUSTIFY_KEY NANO_CONTROL_J
-#define NANO_JUSTIFY_FKEY KEY_F(4)
-#define NANO_UNJUSTIFY_KEY NANO_UNCUT_KEY
-#define NANO_UNJUSTIFY_FKEY NANO_UNCUT_FKEY
-#define NANO_PREVLINE_KEY NANO_CONTROL_P
-#define NANO_NEXTLINE_KEY NANO_CONTROL_N
-#define NANO_FORWARD_KEY NANO_CONTROL_F
-#define NANO_BACK_KEY NANO_CONTROL_B
-#define NANO_MARK_KEY NANO_CONTROL_6
-#define NANO_MARK_METAKEY NANO_META_A
-#define NANO_MARK_FKEY KEY_F(15)
-#define NANO_HOME_KEY NANO_CONTROL_A
-#define NANO_END_KEY NANO_CONTROL_E
-#define NANO_DELETE_KEY NANO_CONTROL_D
-#define NANO_BACKSPACE_KEY NANO_CONTROL_H
-#define NANO_TAB_KEY NANO_CONTROL_I
-#define NANO_INDENT_KEY NANO_META_RCURLYBRACKET
-#define NANO_UNINDENT_KEY NANO_META_LCURLYBRACKET
-#define NANO_SUSPEND_KEY NANO_CONTROL_Z
-#define NANO_ENTER_KEY NANO_CONTROL_M
-#define NANO_TOFILES_KEY NANO_CONTROL_T
-#define NANO_APPEND_KEY NANO_META_A
-#define NANO_PREPEND_KEY NANO_META_P
-#define NANO_PREVFILE_KEY NANO_META_LCARET
-#define NANO_PREVFILE_METAKEY NANO_META_COMMA
-#define NANO_NEXTFILE_KEY NANO_META_RCARET
-#define NANO_NEXTFILE_METAKEY NANO_META_PERIOD
-#define NANO_BRACKET_KEY NANO_META_RBRACKET
-#define NANO_NEXTWORD_KEY NANO_CONTROL_SPACE
-#define NANO_PREVWORD_KEY NANO_META_SPACE
-#define NANO_WORDCOUNT_KEY NANO_META_D
-#define NANO_SCROLLUP_KEY NANO_META_MINUS
-#define NANO_SCROLLDOWN_KEY NANO_META_PLUS
-#define NANO_SCROLLUP_METAKEY NANO_META_UNDERSCORE
-#define NANO_SCROLLDOWN_METAKEY NANO_META_EQUALS
-#define NANO_CUTTILLEND_METAKEY NANO_META_T
-#define NANO_PARABEGIN_KEY NANO_CONTROL_W
-#define NANO_PARABEGIN_METAKEY NANO_META_LPARENTHESIS
-#define NANO_PARABEGIN_METAKEY2 NANO_META_9
-#define NANO_PARAEND_KEY NANO_CONTROL_O
-#define NANO_PARAEND_METAKEY NANO_META_RPARENTHESIS
-#define NANO_PARAEND_METAKEY2 NANO_META_0
-#define NANO_FULLJUSTIFY_KEY NANO_CONTROL_U
-#define NANO_FULLJUSTIFY_METAKEY NANO_META_J
-#define NANO_VERBATIM_KEY NANO_META_V
-
-/* Toggles do not exist if NANO_TINY is defined. */
-#ifndef NANO_TINY
-
-/* No toggle at all. */
-#define TOGGLE_NO_KEY -2
-
-/* Normal toggles. */
-#define TOGGLE_NOHELP_KEY NANO_META_X
-#define TOGGLE_CONST_KEY NANO_META_C
-#define TOGGLE_MORESPACE_KEY NANO_META_O
-#define TOGGLE_SMOOTH_KEY NANO_META_S
-#define TOGGLE_WHITESPACE_KEY NANO_META_P
-#define TOGGLE_SYNTAX_KEY NANO_META_Y
-#define TOGGLE_SMARTHOME_KEY NANO_META_H
-#define TOGGLE_AUTOINDENT_KEY NANO_META_I
-#define TOGGLE_CUTTOEND_KEY NANO_META_K
-#define TOGGLE_WRAP_KEY NANO_META_L
-#define TOGGLE_TABSTOSPACES_KEY NANO_META_Q
-#define TOGGLE_BACKUP_KEY NANO_META_B
-#define TOGGLE_MULTIBUFFER_KEY NANO_META_F
-#define TOGGLE_MOUSE_KEY NANO_META_M
-#define TOGGLE_NOCONVERT_KEY NANO_META_N
-#define TOGGLE_SUSPEND_KEY NANO_META_Z
-#define TOGGLE_CASE_KEY NANO_META_C
-#define TOGGLE_BACKWARDS_KEY NANO_META_B
-#define TOGGLE_DOS_KEY NANO_META_D
-#define TOGGLE_MAC_KEY NANO_META_M
-
-/* Extra bits for the undo function */
-#define UNDO_DEL_DEL (1<<0)
-#define UNDO_DEL_BACKSPACE (1<<1)
-#define UNDO_SPLIT_MADENEW (1<<2)
-
-/* Since in ISO C you can't pass around function pointers anymore,
- let's make some integer macros for function names, and then I
- can go cut my wrists after writing the big switch statement
- that will necessitate. */
+/* Codes for "modified" Arrow keys. Chosen like this because some
+ * terminals produce them, and they are beyond KEY_MAX of ncurses. */
+#define CONTROL_LEFT 539
+#define CONTROL_RIGHT 554
+#ifndef NANO_TINY
+/* Extra bits for the undo function. */
+#define UNdel_del (1<<0)
+#define UNdel_backspace (1<<1)
+#define UNcut_marked_forward (1<<2)
+#define UNcut_cutline (1<<3)
#endif /* !NANO_TINY */
-#define CASE_SENS_MSG 1
-#define BACKWARDS_MSG 2
-#define REGEXP_MSG 3
-#define WHEREIS_NEXT_MSG 4
-#define FIRST_FILE_MSG 5
-#define LAST_FILE_MSG 6
-#define GOTO_DIR_MSG 7
-#define TOTAL_REFRESH 8
-#define DO_HELP_VOID 9
-#define DO_SEARCH 10
-#define DO_PAGE_UP 11
-#define DO_PAGE_DOWN 12
-#define DO_UP_VOID 13
-#define DO_LEFT 14
-#define DO_DOWN_VOID 15
-#define DO_RIGHT 16
-#define DO_ENTER 17
-#define DO_EXIT 18
-#define NEW_BUFFER_MSG 19
-#define EXT_CMD_MSG 20
-#define TO_FILES_MSG 21
-#define DOS_FORMAT_MSG 23
-#define MAC_FORMAT_MSG 24
-#define BACKUP_FILE_MSG 25
-#define PREPEND_MSG 26
-#define APPEND_MSG 27
-#define DO_FIRST_LINE 28
-#define DO_LAST_LINE 29
-#define DO_TOGGLE 30
-#define GOTOTEXT_MSG 31
-#define NO_REPLACE_MSG 32
-#define DO_BACKSPACE 33
-#define DO_DELETE 34
-#define DO_TAB 35
-#define DO_VERBATIM_INPUT 36
-#define SWITCH_TO_NEXT_BUFFER_VOID 37
-#define SWITCH_TO_PREV_BUFFER_VOID 38
-#define DO_END 39
-#define DO_HOME 40
-#define NEXT_HISTORY_MSG 41
-#define PREV_HISTORY_MSG 42
-#define DO_REDO 43
-#define DO_UNDO 44
-#define DO_WORDLINECHAR_COUNT 45
-#define DO_FIND_BRACKET 46
-#define DO_PREV_WORD_VOID 47
-#define DO_SUSPEND_VOID 48
-#define CANCEL_MSG 49
-#define DO_WRITEOUT_VOID 50
-#define DO_INSERTFILE_VOID 51
-#define DO_CUT_TEXT_VOID 52
-#define DO_UNCUT_TEXT 53
-#define DO_CURSORPOS_VOID 54
-#define DO_GOTOLINECOLUMN_VOID 55
-#define DO_REPLACE 56
-#define DO_JUSTIFY_VOID 57
-#define DO_PARA_BEGIN_VOID 58
-#define DO_PARA_END_VOID 59
-#define DO_FULL_JUSTIFY 60
-#define DO_MARK 61
-#define DO_RESEARCH 62
-#define DO_COPY_TEXT 63
-#define DO_INDENT_VOID 64
-#define DO_UNINDENT 65
-#define DO_SCROLL_UP 66
-#define DO_SCROLL_DOWN 67
-#define DO_NEXT_WORD_VOID 68
-#define DO_CUT_TILL_END 69
-#define NANO_GOTODIR_MSG 70
-#define NANO_LASTFILE_MSG 71
-#define NANO_FIRSTFILE_MSG 72
-#define INSERT_FILE_MSG 73
-#define NANO_MULTIBUFFER_MSG 74
-#define NANO_EXECUTE_MSG 75
-#define NANO_BACKUP_MSG 76
-#define NANO_PREPEND_MSG 77
-#define NANO_APPEND_MSG 78
-#define NANO_MAC_MSG 79
-#define NANO_DOS_MSG 80
-#define NANO_TOFILES_MSG 81
-#define NANO_NEXT_HISTORY_MSG 82
-#define NANO_PREV_HISTORY_MSG 83
-#define NANO_REGEXP_MSG 84
-#define NANO_REVERSE_MSG 85
-#define NANO_CASE_MSG 86
-#define NANO_SUSPEND_MSG 87
-#define SUSPEND_MSG 88
-#define NANO_REFRESH_MSG 89
-#define REFRESH_MSG 90
-#define NANO_WORDCOUNT_MSG 91
-#define NANO_FULLJUSTIFY_MSG 92
-#define FULLJSTIFY_MSG 93
-#define XOFF_COMPLAINT 94
-#define XON_COMPLAINT 95
-#define NANO_CUT_TILL_END_MSG 96
-#define NANO_BACKSPACE_MSG 97
-#define NANO_DELETE_MSG 98
-#define NANO_ENTER_MSG 99
-#define NANO_TAB_MSG 100
-#define NANO_VERBATIM_MSG 101
-#define NANO_NEXTFILE_MSG 102
-#define NANO_PREVFILE_MSG 103
-#define NANO_SCROLLDOWN_MSG 104
-#define NANO_SCROLLUP_MSG 105
-#define NANO_BRACKET_MSG 106
-#define NANO_PARAEND_MSG 107
-#define END_OF_PAR_MSG 108
-#define NANO_PARABEGIN_MSG 109
-#define BEG_OF_PAR_MSG 110
-#define NANO_END_MSG 111
-#define NANO_HOME_MSG 112
-#define NANO_NEXTLINE_MSG 113
-#define NANO_PREVLINE_MSG 114
-#define NANO_PREVWORD_MSG 115
-#define NANO_NEXTWORD_MSG 116
-#define NANO_BACK_MSG 117
-#define NANO_FORWARD_MSG 118
-#define NANO_REDO_MSG 119
-#define NANO_UNDO_MSG 120
-#define NANO_UNINDENT_MSG 121
-#define NANO_INDENT_MSG 122
-#define NANO_COPY_MSG 123
-#define NANO_WHEREIS_NEXT_MSG 124
-#define NANO_MARK_MSG 125
-#define NANO_REPLACE_MSG 126
-#define REPLACE_MSG 127
-#define NANO_GOTOLINE_MSG 128
-#define NANO_LASTLINE_MSG 129
-#define NANO_FIRSTLINE_MSG 130
-#define NANO_SPELL_MSG 131
-#define DO_SPELL 132
-#define NANO_CURSORPOS_MSG 133
-#define NANO_UNCUT_MSG 134
-#define GET_HELP_MSG 135
-#define NANO_HELP_MSG 136
-#define NANO_CANCEL_MSG 137
-#define NANO_EXIT_MSG 138
-#define EXIT_MSG 139
-#define NANO_EXITBROWSER_MSG 140
-#define NANO_WRITEOUT_MSG 141
-#define NANO_DISABLED_MSG 142
-#define NANO_INSERT_MSG 143
-#define WHEREIS_MSG 144
-#define NANO_WHEREIS_MSG 145
-#define NANO_PREVPAGE_MSG 146
-#define NANO_NEXTPAGE_MSG 147
-#define NANO_CUT_MSG 148
-#define DO_CUT_TEXT 149
-#define DO_NEXT_WORD 150
-#define DO_PREV_WORD 151
-
-
-
-
-#define VIEW TRUE
-#define NOVIEW FALSE
-
/* The maximum number of entries displayed in the main shortcut list. */
-#define MAIN_VISIBLE 12
+#define MAIN_VISIBLE (((COLS + 40) / 20) * 2)
/* The minimum editor window columns and rows required for nano to work
* correctly. */
diff --git a/src/prompt.c b/src/prompt.c
index afb36d6..e3d4f1f 100644
--- a/src/prompt.c
+++ b/src/prompt.c
@@ -1,9 +1,9 @@
-/* $Id: prompt.c 4475 2010-01-17 05:30:22Z astyanax $ */
+/* $Id: prompt.c 5086 2014-07-31 20:49:32Z bens $ */
/**************************************************************************
* prompt.c *
* *
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
- * 2008, 2009 Free Software Foundation, Inc. *
+ * 2008, 2009, 2010, 2011, 2013, 2014 Free Software Foundation, Inc. *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 3, or (at your option) *
@@ -42,18 +42,13 @@ static bool reset_statusbar_x = FALSE;
* prompt? */
/* Read in a character, interpret it as a shortcut or toggle if
- * necessary, and return it. Set meta_key to TRUE if the character is a
- * meta sequence, set func_key to TRUE if the character is a function
- * key, set have_shortcut to TRUE if the character is a shortcut
- * key, set ran_func to TRUE if we ran a function associated with a
+ * necessary, and return it.
+ * Set ran_func to TRUE if we ran a function associated with a
* shortcut key, and set finished to TRUE if we're done after running
- * or trying to run a function associated with a shortcut key. If
- * allow_funcs is FALSE, don't actually run any functions associated
- * with shortcut keys. refresh_func is the function we will call to
- * refresh the edit window. */
-int do_statusbar_input(bool *meta_key, bool *func_key, bool *have_shortcut,
- bool *ran_func, bool *finished, bool allow_funcs, void
- (*refresh_func)(void))
+ * or trying to run a function associated with a shortcut key.
+ * refresh_func is the function we will call to refresh the edit window. */
+int do_statusbar_input(bool *ran_func, bool *finished,
+ void (*refresh_func)(void))
{
int input;
/* The character we read in. */
@@ -62,157 +57,142 @@ int do_statusbar_input(bool *meta_key, bool *func_key, bool *have_shortcut,
static size_t kbinput_len = 0;
/* The length of the input buffer. */
const sc *s;
+ bool have_shortcut = FALSE;
const subnfunc *f;
- *have_shortcut = FALSE;
*ran_func = FALSE;
*finished = FALSE;
/* Read in a character. */
- input = get_kbinput(bottomwin, meta_key, func_key);
+ input = get_kbinput(bottomwin);
#ifndef DISABLE_MOUSE
- if (allow_funcs) {
- /* If we got a mouse click and it was on a shortcut, read in the
- * shortcut character. */
- if (*func_key && input == KEY_MOUSE) {
- if (do_statusbar_mouse() == 1)
- input = get_kbinput(bottomwin, meta_key, func_key);
- else {
- *meta_key = FALSE;
- *func_key = FALSE;
- input = ERR;
- }
+ /* If we got a mouse click and it was on a shortcut, read in the
+ * shortcut character. */
+ if (func_key && input == KEY_MOUSE) {
+ if (do_statusbar_mouse() == 1)
+ input = get_kbinput(bottomwin);
+ else {
+ meta_key = FALSE;
+ func_key = FALSE;
+ input = ERR;
}
}
#endif
/* Check for a shortcut in the current list. */
- s = get_shortcut(currmenu, &input, meta_key, func_key);
+ s = get_shortcut(&input);
/* If we got a shortcut from the current list, or a "universal"
* statusbar prompt shortcut, set have_shortcut to TRUE. */
- *have_shortcut = (s != NULL);
+ have_shortcut = (s != NULL);
/* If we got a non-high-bit control key, a meta key sequence, or a
* function key, and it's not a shortcut or toggle, throw it out. */
- if (!*have_shortcut) {
- if (is_ascii_cntrl_char(input) || *meta_key || *func_key) {
+ if (!have_shortcut) {
+ if (is_ascii_cntrl_char(input) || meta_key || func_key) {
beep();
- *meta_key = FALSE;
- *func_key = FALSE;
+ meta_key = FALSE;
+ func_key = FALSE;
input = ERR;
}
}
- if (allow_funcs) {
- /* If we got a character, and it isn't a shortcut or toggle,
- * it's a normal text character. Display the warning if we're
- * in view mode, or add the character to the input buffer if
- * we're not. */
- if (input != ERR && !*have_shortcut) {
- /* If we're using restricted mode, the filename isn't blank,
- * and we're at the "Write File" prompt, disable text
- * input. */
- if (!ISSET(RESTRICTED) || openfile->filename[0] == '\0' ||
+ /* If we got a character, and it isn't a shortcut or toggle,
+ * it's a normal text character. Display the warning if we're
+ * in view mode, or add the character to the input buffer if
+ * we're not. */
+ if (input != ERR && !have_shortcut) {
+ /* If we're using restricted mode, the filename isn't blank,
+ * and we're at the "Write File" prompt, disable text input. */
+ if (!ISSET(RESTRICTED) || openfile->filename[0] == '\0' ||
currmenu != MWRITEFILE) {
- kbinput_len++;
- kbinput = (int *)nrealloc(kbinput, kbinput_len *
- sizeof(int));
- kbinput[kbinput_len - 1] = input;
- }
+ kbinput_len++;
+ kbinput = (int *)nrealloc(kbinput, kbinput_len * sizeof(int));
+ kbinput[kbinput_len - 1] = input;
}
-
- /* If we got a shortcut, or if there aren't any other characters
- * waiting after the one we read in, we need to display all the
- * characters in the input buffer if it isn't empty. */
- if (*have_shortcut || get_key_buffer_len() == 0) {
- if (kbinput != NULL) {
- /* Display all the characters in the input buffer at
- * once, filtering out control characters. */
- char *output = charalloc(kbinput_len + 1);
- size_t i;
- bool got_enter;
- /* Whether we got the Enter key. */
-
- for (i = 0; i < kbinput_len; i++)
- output[i] = (char)kbinput[i];
- output[i] = '\0';
-
- do_statusbar_output(output, kbinput_len, &got_enter,
- FALSE);
-
- free(output);
-
- /* Empty the input buffer. */
- kbinput_len = 0;
- free(kbinput);
- kbinput = NULL;
- }
+ }
+
+ /* If we got a shortcut, or if there aren't any other characters
+ * waiting after the one we read in, we need to display all the
+ * characters in the input buffer if it isn't empty. */
+ if (have_shortcut || get_key_buffer_len() == 0) {
+ if (kbinput != NULL) {
+ /* Display all the characters in the input buffer at
+ * once, filtering out control characters. */
+ char *output = charalloc(kbinput_len + 1);
+ size_t i;
+ bool got_enter;
+ /* Whether we got the Enter key. */
+
+ for (i = 0; i < kbinput_len; i++)
+ output[i] = (char)kbinput[i];
+ output[i] = '\0';
+
+ do_statusbar_output(output, kbinput_len, &got_enter, FALSE);
+
+ free(output);
+
+ /* Empty the input buffer. */
+ kbinput_len = 0;
+ free(kbinput);
+ kbinput = NULL;
}
- if (*have_shortcut) {
- if (s->scfunc == DO_TAB || s->scfunc == DO_ENTER)
+ if (have_shortcut) {
+ if (s->scfunc == do_tab || s->scfunc == do_enter_void)
;
- else if (s->scfunc == TOTAL_REFRESH)
+ else if (s->scfunc == total_refresh)
total_statusbar_refresh(refresh_func);
- else if (s->scfunc == DO_CUT_TEXT) {
+ else if (s->scfunc == do_cut_text_void) {
/* If we're using restricted mode, the filename
* isn't blank, and we're at the "Write File"
* prompt, disable Cut. */
if (!ISSET(RESTRICTED) || openfile->filename[0] ==
'\0' || currmenu != MWRITEFILE)
do_statusbar_cut_text();
- } else if (s->scfunc == DO_RIGHT)
- do_statusbar_right();
- else if (s->scfunc == DO_LEFT)
+ } else if (s->scfunc == do_left)
do_statusbar_left();
-
+ else if (s->scfunc == do_right)
+ do_statusbar_right();
#ifndef NANO_TINY
- else if (s->scfunc == DO_NEXT_WORD)
+ else if (s->scfunc == do_prev_word_void)
+ do_statusbar_prev_word(FALSE);
+ else if (s->scfunc == do_next_word_void)
do_statusbar_next_word(FALSE);
- else if (s->scfunc == DO_PREV_WORD)
- do_statusbar_prev_word(FALSE);
-#endif
- else if (s->scfunc == DO_HOME)
- do_statusbar_home();
- else if (s->scfunc == DO_END)
- do_statusbar_end();
-
-#ifndef NANO_TINY
- else if (s->scfunc == DO_FIND_BRACKET)
- do_statusbar_find_bracket();
#endif
- else if (s->scfunc == DO_VERBATIM_INPUT) {
- /* If we're using restricted mode, the filename
- * isn't blank, and we're at the "Write File"
- * prompt, disable verbatim input. */
- if (!ISSET(RESTRICTED) ||
- openfile->filename[0] == '\0' ||
- currmenu != MWRITEFILE) {
- bool got_enter;
- /* Whether we got the Enter key. */
-
- do_statusbar_verbatim_input(&got_enter);
-
- /* If we got the Enter key, remove it from
- * the input buffer, set input to the key
- * value for Enter, and set finished to TRUE
- * to indicate that we're done. */
- if (got_enter) {
- get_input(NULL, 1);
- input = sc_seq_or(DO_ENTER, 0);
- *finished = TRUE;
- }
+ else if (s->scfunc == do_home)
+ do_statusbar_home();
+ else if (s->scfunc == do_end)
+ do_statusbar_end();
+ else if (s->scfunc == do_verbatim_input) {
+ /* If we're using restricted mode, the filename
+ * isn't blank, and we're at the "Write File"
+ * prompt, disable verbatim input. */
+ if (!ISSET(RESTRICTED) || currmenu != MWRITEFILE ||
+ openfile->filename[0] == '\0') {
+ bool got_enter;
+ /* Whether we got the Enter key. */
+
+ do_statusbar_verbatim_input(&got_enter);
+
+ /* If we got the Enter key, remove it from the input
+ * buffer, set input to the key value for Enter, and
+ * set finished to TRUE to indicate that we're done. */
+ if (got_enter) {
+ get_input(NULL, 1);
+ input = sc_seq_or(do_enter_void, 0);
+ *finished = TRUE;
}
- } else if (s->scfunc == DO_DELETE) {
+ }
+ } else if (s->scfunc == do_delete) {
/* If we're using restricted mode, the filename
* isn't blank, and we're at the "Write File"
* prompt, disable Delete. */
if (!ISSET(RESTRICTED) || openfile->filename[0] ==
'\0' || currmenu != MWRITEFILE)
do_statusbar_delete();
- } else if (s->scfunc == DO_BACKSPACE) {
+ } else if (s->scfunc == do_backspace) {
/* If we're using restricted mode, the filename
* isn't blank, and we're at the "Write File"
* prompt, disable Backspace. */
@@ -220,17 +200,17 @@ int do_statusbar_input(bool *meta_key, bool *func_key, bool *have_shortcut,
'\0' || currmenu != MWRITEFILE)
do_statusbar_backspace();
} else {
- /* Handle the normal statusbar prompt shortcuts, setting
- * ran_func to TRUE if we try to run their associated
- * functions and setting finished to TRUE to indicate
- * that we're done after running or trying to run their
- * associated functions. */
-
+ /* Handle any other shortcut in the current menu, setting
+ * ran_func to TRUE if we try to run their associated
+ * functions and setting finished to TRUE to indicate
+ * that we're done after running or trying to run their
+ * associated functions. */
f = sctofunc((sc *) s);
- if (s->scfunc != 0 && s->execute == TRUE) {
- *ran_func = TRUE;
- if (f && (!ISSET(VIEW_MODE) || (f->viewok)))
- iso_me_harder_funcmap(f->scfunc);
+ if (s->scfunc != NULL) {
+ *ran_func = TRUE;
+ if (f && (!ISSET(VIEW_MODE) || f->viewok) &&
+ f->scfunc != do_gotolinecolumn_void)
+ f->scfunc();
}
*finished = TRUE;
}
@@ -320,7 +300,7 @@ void do_statusbar_output(char *output, size_t output_len, bool
char_buf_len)))
continue;
- /* More dangerousness fun =) */
+ /* More dangerousness fun. =) */
answer = charealloc(answer, answer_len + (char_buf_len * 2));
assert(statusbar_x <= answer_len);
@@ -360,13 +340,12 @@ void do_statusbar_home(void)
statusbar_x = 0;
statusbar_pww = statusbar_xplustabs();
- } else {
+ } else
#endif
+ {
statusbar_x = 0;
statusbar_pww = statusbar_xplustabs();
-#ifndef NANO_TINY
}
-#endif
if (need_statusbar_horizontal_update(pww_save))
update_statusbar_line(answer, statusbar_x);
@@ -451,14 +430,13 @@ void do_statusbar_cut_text(void)
#ifndef NANO_TINY
if (ISSET(CUT_TO_END))
null_at(&answer, statusbar_x);
- else {
+ else
#endif
+ {
null_at(&answer, 0);
statusbar_x = 0;
statusbar_pww = statusbar_xplustabs();
-#ifndef NANO_TINY
}
-#endif
update_statusbar_line(answer, statusbar_x);
}
@@ -651,162 +629,6 @@ void do_statusbar_verbatim_input(bool *got_enter)
free(output);
}
-#ifndef NANO_TINY
-/* Search for a match to one of the two characters in bracket_set. If
- * reverse is TRUE, search backwards for the leftmost bracket.
- * Otherwise, search forwards for the rightmost bracket. Return TRUE if
- * we found a match, and FALSE otherwise. */
-bool find_statusbar_bracket_match(bool reverse, const char
- *bracket_set)
-{
- const char *rev_start = NULL, *found = NULL;
-
- assert(mbstrlen(bracket_set) == 2);
-
- /* rev_start might end up 1 character before the start or after the
- * end of the line. This won't be a problem because we'll skip over
- * it below in that case. */
- rev_start = reverse ? answer + (statusbar_x - 1) : answer +
- (statusbar_x + 1);
-
- while (TRUE) {
- /* Look for either of the two characters in bracket_set.
- * rev_start can be 1 character before the start or after the
- * end of the line. In either case, just act as though no match
- * is found. */
- found = ((rev_start > answer && *(rev_start - 1) == '\0') ||
- rev_start < answer) ? NULL : (reverse ?
- mbrevstrpbrk(answer, bracket_set, rev_start) :
- mbstrpbrk(rev_start, bracket_set));
-
- /* We've found a potential match. */
- if (found != NULL)
- break;
-
- /* We've reached the start or end of the statusbar text, so
- * get out. */
- return FALSE;
- }
-
- /* We've definitely found something. */
- statusbar_x = found - answer;
- statusbar_pww = statusbar_xplustabs();
-
- return TRUE;
-}
-
-/* Search for a match to the bracket at the current cursor position, if
- * there is one. */
-void do_statusbar_find_bracket(void)
-{
- size_t statusbar_x_save, pww_save;
- const char *ch;
- /* The location in matchbrackets of the bracket at the current
- * cursor position. */
- int ch_len;
- /* The length of ch in bytes. */
- const char *wanted_ch;
- /* The location in matchbrackets of the bracket complementing
- * the bracket at the current cursor position. */
- int wanted_ch_len;
- /* The length of wanted_ch in bytes. */
- char *bracket_set;
- /* The pair of characters in ch and wanted_ch. */
- size_t i;
- /* Generic loop variable. */
- size_t matchhalf;
- /* The number of single-byte characters in one half of
- * matchbrackets. */
- size_t mbmatchhalf;
- /* The number of multibyte characters in one half of
- * matchbrackets. */
- size_t count = 1;
- /* The initial bracket count. */
- bool reverse;
- /* The direction we search. */
- char *found_ch;
- /* The character we find. */
-
- assert(mbstrlen(matchbrackets) % 2 == 0);
-
- ch = answer + statusbar_x;
-
- if (ch == '\0' || (ch = mbstrchr(matchbrackets, ch)) == NULL)
- return;
-
- /* Save where we are. */
- statusbar_x_save = statusbar_x;
- pww_save = statusbar_pww;
-
- /* If we're on an opening bracket, which must be in the first half
- * of matchbrackets, we want to search forwards for a closing
- * bracket. If we're on a closing bracket, which must be in the
- * second half of matchbrackets, we want to search backwards for an
- * opening bracket. */
- matchhalf = 0;
- mbmatchhalf = mbstrlen(matchbrackets) / 2;
-
- for (i = 0; i < mbmatchhalf; i++)
- matchhalf += parse_mbchar(matchbrackets + matchhalf, NULL,
- NULL);
-
- reverse = ((ch - matchbrackets) >= matchhalf);
-
- /* If we're on an opening bracket, set wanted_ch to the character
- * that's matchhalf characters after ch. If we're on a closing
- * bracket, set wanted_ch to the character that's matchhalf
- * characters before ch. */
- wanted_ch = ch;
-
- while (mbmatchhalf > 0) {
- if (reverse)
- wanted_ch = matchbrackets + move_mbleft(matchbrackets,
- wanted_ch - matchbrackets);
- else
- wanted_ch += move_mbright(wanted_ch, 0);
-
- mbmatchhalf--;
- }
-
- ch_len = parse_mbchar(ch, NULL, NULL);
- wanted_ch_len = parse_mbchar(wanted_ch, NULL, NULL);
-
- /* Fill bracket_set in with the values of ch and wanted_ch. */
- bracket_set = charalloc((mb_cur_max() * 2) + 1);
- strncpy(bracket_set, ch, ch_len);
- strncpy(bracket_set + ch_len, wanted_ch, wanted_ch_len);
- null_at(&bracket_set, ch_len + wanted_ch_len);
-
- found_ch = charalloc(mb_cur_max() + 1);
-
- while (TRUE) {
- if (find_statusbar_bracket_match(reverse, bracket_set)) {
- /* If we found an identical bracket, increment count. If we
- * found a complementary bracket, decrement it. */
- parse_mbchar(answer + statusbar_x, found_ch, NULL);
- count += (strncmp(found_ch, ch, ch_len) == 0) ? 1 : -1;
-
- /* If count is zero, we've found a matching bracket. Update
- * the statusbar prompt and get out. */
- if (count == 0) {
- if (need_statusbar_horizontal_update(pww_save))
- update_statusbar_line(answer, statusbar_x);
- break;
- }
- } else {
- /* We didn't find either an opening or closing bracket.
- * Restore where we were, and get out. */
- statusbar_x = statusbar_x_save;
- statusbar_pww = pww_save;
- break;
- }
- }
-
- /* Clean up. */
- free(bracket_set);
- free(found_ch);
-}
-#endif /* !NANO_TINY */
/* Return the placewewant associated with statusbar_x, i.e. the
* zero-based column position of the cursor. The value will be no
@@ -854,7 +676,9 @@ void update_statusbar_line(const char *curranswer, size_t index)
index = strnlenpt(curranswer, index);
page_start = get_statusbar_page_start(start_col, start_col + index);
- wattron(bottomwin, reverse_attr);
+ if (interface_color_pair[TITLE_BAR].bright)
+ wattron(bottomwin, A_BOLD);
+ wattron(bottomwin, interface_color_pair[TITLE_BAR].pairnum);
blank_statusbar();
@@ -867,7 +691,8 @@ void update_statusbar_line(const char *curranswer, size_t index)
waddstr(bottomwin, expanded);
free(expanded);
- wattroff(bottomwin, reverse_attr);
+ wattroff(bottomwin, A_BOLD);
+ wattroff(bottomwin, interface_color_pair[TITLE_BAR].pairnum);
statusbar_pww = statusbar_xplustabs();
reset_statusbar_cursor();
wnoutrefresh(bottomwin);
@@ -894,30 +719,26 @@ void total_statusbar_refresh(void (*refresh_func)(void))
/* Get a string of input at the statusbar prompt. This should only be
* called from do_prompt(). */
-const sc *get_prompt_string(int *actual, bool allow_tabs,
+functionptrtype get_prompt_string(int *actual, bool allow_tabs,
#ifndef DISABLE_TABCOMP
bool allow_files,
+ bool *list,
#endif
const char *curranswer,
- bool *meta_key, bool *func_key,
-#ifndef NANO_TINY
+#ifndef DISABLE_HISTORIES
filestruct **history_list,
#endif
- void (*refresh_func)(void), int menu
-#ifndef DISABLE_TABCOMP
- , bool *list
-#endif
- )
+ void (*refresh_func)(void))
{
int kbinput = ERR;
- bool have_shortcut, ran_func, finished;
+ bool ran_func, finished;
size_t curranswer_len;
- const sc *s;
+ functionptrtype func;
#ifndef DISABLE_TABCOMP
bool tabbed = FALSE;
/* Whether we've pressed Tab. */
#endif
-#ifndef NANO_TINY
+#ifndef DISABLE_HISTORIES
char *history = NULL;
/* The current history string. */
char *magichistory = NULL;
@@ -930,7 +751,7 @@ const sc *get_prompt_string(int *actual, bool allow_tabs,
/* The length of the original string that we're trying to
* tab complete, if any. */
#endif
-#endif /* !NANO_TINY */
+#endif /* !DISABLE_HISTORIES */
answer = mallocstrcpy(answer, curranswer);
curranswer_len = strlen(answer);
@@ -953,10 +774,8 @@ const sc *get_prompt_string(int *actual, bool allow_tabs,
statusbar_pww = statusbar_xplustabs();
}
- currmenu = menu;
-
#ifdef DEBUG
-fprintf(stderr, "get_prompt_string: answer = \"%s\", statusbar_x = %lu\n", answer, (unsigned long) statusbar_x);
+ fprintf(stderr, "get_prompt_string: answer = \"%s\", statusbar_x = %lu\n", answer, (unsigned long) statusbar_x);
#endif
update_statusbar_line(answer, statusbar_x);
@@ -971,124 +790,108 @@ fprintf(stderr, "get_prompt_string: answer = \"%s\", statusbar_x = %lu\n", answe
* allow writing to files not specified on the command line. In
* this case, disable all keys that would change the text if the
* filename isn't blank and we're at the "Write File" prompt. */
- while (1) {
- kbinput = do_statusbar_input(meta_key, func_key, &have_shortcut,
- &ran_func, &finished, TRUE, refresh_func);
+ while (TRUE) {
+ kbinput = do_statusbar_input(&ran_func, &finished, refresh_func);
assert(statusbar_x <= strlen(answer));
- s = get_shortcut(currmenu, &kbinput, meta_key, func_key);
+ func = func_from_key(&kbinput);
- if (s)
- if (s->scfunc == CANCEL_MSG || s->scfunc == DO_ENTER)
- break;
+ if (func == do_cancel || func == do_enter_void)
+ break;
#ifndef DISABLE_TABCOMP
- if (s && s->scfunc != DO_TAB)
+ if (func != do_tab)
tabbed = FALSE;
-#endif
-#ifndef DISABLE_TABCOMP
-#ifndef NANO_TINY
- if (s && s->scfunc == DO_TAB) {
- if (history_list != NULL) {
- if (last_kbinput != sc_seq_or(DO_TAB, NANO_CONTROL_I))
- complete_len = strlen(answer);
+ if (func == do_tab) {
+#ifndef DISABLE_HISTORIES
+ if (history_list != NULL) {
+ if (last_kbinput != sc_seq_or(do_tab, NANO_CONTROL_I))
+ complete_len = strlen(answer);
- if (complete_len > 0) {
- answer = mallocstrcpy(answer,
+ if (complete_len > 0) {
+ answer = mallocstrcpy(answer,
get_history_completion(history_list,
- answer, complete_len));
- statusbar_x = strlen(answer);
- }
- } else
-#endif /* !NANO_TINY */
- if (allow_tabs)
- answer = input_tab(answer, allow_files,
- &statusbar_x, &tabbed, refresh_func, list);
+ answer, complete_len));
+ statusbar_x = strlen(answer);
+ }
+ } else
+#endif
+ if (allow_tabs)
+ answer = input_tab(answer, allow_files, &statusbar_x,
+ &tabbed, refresh_func, list);
- update_statusbar_line(answer, statusbar_x);
- } else
+ update_statusbar_line(answer, statusbar_x);
+ } else
#endif /* !DISABLE_TABCOMP */
-#ifndef NANO_TINY
- if (s && s->scfunc == PREV_HISTORY_MSG) {
- if (history_list != NULL) {
- /* If we're scrolling up at the bottom of the
- * history list and answer isn't blank, save answer
- * in magichistory. */
- if ((*history_list)->next == NULL &&
- answer[0] != '\0')
- magichistory = mallocstrcpy(magichistory,
- answer);
-
- /* Get the older search from the history list and
- * save it in answer. If there is no older search,
- * don't do anything. */
- if ((history =
- get_history_older(history_list)) != NULL) {
- answer = mallocstrcpy(answer, history);
- statusbar_x = strlen(answer);
- }
+#ifndef DISABLE_HISTORIES
+ if (func == get_history_older_void) {
+ if (history_list != NULL) {
+ /* If we're scrolling up at the bottom of the history list
+ * and answer isn't blank, save answer in magichistory. */
+ if ((*history_list)->next == NULL && answer[0] != '\0')
+ magichistory = mallocstrcpy(magichistory, answer);
+
+ /* Get the older search from the history list and save it in
+ * answer. If there is no older search, don't do anything. */
+ if ((history = get_history_older(history_list)) != NULL) {
+ answer = mallocstrcpy(answer, history);
+ statusbar_x = strlen(answer);
+ }
- update_statusbar_line(answer, statusbar_x);
+ update_statusbar_line(answer, statusbar_x);
- /* This key has a shortcut list entry when it's used
- * to move to an older search, which means that
- * finished has been set to TRUE. Set it back to
- * FALSE here, so that we aren't kicked out of the
- * statusbar prompt. */
- finished = FALSE;
+ /* This key has a shortcut-list entry when it's used to
+ * move to an older search, which means that finished has
+ * been set to TRUE. Set it back to FALSE here, so that
+ * we aren't kicked out of the statusbar prompt. */
+ finished = FALSE;
+ }
+ } else if (func == get_history_newer_void) {
+ if (history_list != NULL) {
+ /* Get the newer search from the history list and save it in
+ * answer. If there is no newer search, don't do anything. */
+ if ((history = get_history_newer(history_list)) != NULL) {
+ answer = mallocstrcpy(answer, history);
+ statusbar_x = strlen(answer);
}
- } else if (s && s->scfunc == NEXT_HISTORY_MSG) {
- if (history_list != NULL) {
- /* Get the newer search from the history list and
- * save it in answer. If there is no newer search,
- * don't do anything. */
- if ((history =
- get_history_newer(history_list)) != NULL) {
- answer = mallocstrcpy(answer, history);
- statusbar_x = strlen(answer);
- }
- /* If, after scrolling down, we're at the bottom of
- * the history list, answer is blank, and
- * magichistory is set, save magichistory in
- * answer. */
- if ((*history_list)->next == NULL &&
- *answer == '\0' && magichistory != NULL) {
+ /* If, after scrolling down, we're at the bottom of the
+ * history list, answer is blank, and magichistory is set,
+ * save magichistory in answer. */
+ if ((*history_list)->next == NULL &&
+ *answer == '\0' && magichistory != NULL) {
answer = mallocstrcpy(answer, magichistory);
statusbar_x = strlen(answer);
}
- update_statusbar_line(answer, statusbar_x);
-
- /* This key has a shortcut list entry when it's used
- * to move to a newer search, which means that
- * finished has been set to TRUE. Set it back to
- * FALSE here, so that we aren't kicked out of the
- * statusbar prompt. */
- finished = FALSE;
- }
- } else
-#endif /* !NANO_TINY */
- if (s && s->scfunc == DO_HELP_VOID) {
update_statusbar_line(answer, statusbar_x);
- /* This key has a shortcut list entry when it's used to
- * go to the help browser or display a message
- * indicating that help is disabled, which means that
- * finished has been set to TRUE. Set it back to FALSE
- * here, so that we aren't kicked out of the statusbar
- * prompt. */
+ /* This key has a shortcut-list entry when it's used to
+ * move to a newer search, which means that finished has
+ * been set to TRUE. Set it back to FALSE here, so that
+ * we aren't kicked out of the statusbar prompt. */
finished = FALSE;
+ }
+ } else
+#endif /* !DISABLE_HISTORIES */
+ if (func == do_help_void) {
+ update_statusbar_line(answer, statusbar_x);
+
+ /* This key has a shortcut-list entry when it's used to go to
+ * the help browser or display a message indicating that help
+ * is disabled, which means that finished has been set to TRUE.
+ * Set it back to FALSE here, so that we aren't kicked out of
+ * the statusbar prompt. */
+ finished = FALSE;
}
- /* If we have a shortcut with an associated function, break out
- * if we're finished after running or trying to run the
- * function. */
+ /* If we have a shortcut with an associated function, break out if
+ * we're finished after running or trying to run the function. */
if (finished)
break;
-#if !defined(NANO_TINY) && !defined(DISABLE_TABCOMP)
+#if !defined(DISABLE_HISTORIES) && !defined(DISABLE_TABCOMP)
last_kbinput = kbinput;
#endif
@@ -1096,10 +899,9 @@ fprintf(stderr, "get_prompt_string: answer = \"%s\", statusbar_x = %lu\n", answe
wnoutrefresh(bottomwin);
}
-
-#ifndef NANO_TINY
- /* Set the current position in the history list to the bottom and
- * free magichistory, if we need to. */
+#ifndef DISABLE_HISTORIES
+ /* Set the current position in the history list to the bottom,
+ * and free magichistory if we need to. */
if (history_list != NULL) {
history_reset(*history_list);
@@ -1108,14 +910,12 @@ fprintf(stderr, "get_prompt_string: answer = \"%s\", statusbar_x = %lu\n", answe
}
#endif
-
/* We've finished putting in an answer or run a normal shortcut's
* associated function, so reset statusbar_x and statusbar_pww. If
* we've finished putting in an answer, reset the statusbar cursor
* position too. */
- if (s) {
- if (s->scfunc == CANCEL_MSG || s->scfunc == DO_ENTER ||
- ran_func) {
+ if (func) {
+ if (func == do_cancel || func == do_enter_void || ran_func) {
statusbar_x = old_statusbar_x;
statusbar_pww = old_pww;
@@ -1129,7 +929,8 @@ fprintf(stderr, "get_prompt_string: answer = \"%s\", statusbar_x = %lu\n", answe
}
*actual = kbinput;
- return s;
+
+ return func;
}
/* Ask a question on the statusbar. The prompt will be stored in the
@@ -1149,15 +950,14 @@ int do_prompt(bool allow_tabs,
bool allow_files,
#endif
int menu, const char *curranswer,
- bool *meta_key, bool *func_key,
-#ifndef NANO_TINY
+#ifndef DISABLE_HISTORIES
filestruct **history_list,
#endif
void (*refresh_func)(void), const char *msg, ...)
{
va_list ap;
int retval;
- const sc *s;
+ functionptrtype func;
#ifndef DISABLE_TABCOMP
bool list = FALSE;
#endif
@@ -1169,6 +969,7 @@ int do_prompt(bool allow_tabs,
prompt = charalloc(((COLS - 4) * mb_cur_max()) + 1);
+ currmenu = menu;
bottombars(menu);
va_start(ap, msg);
@@ -1176,20 +977,16 @@ int do_prompt(bool allow_tabs,
va_end(ap);
null_at(&prompt, actual_x(prompt, COLS - 4));
- s = get_prompt_string(&retval, allow_tabs,
+ func = get_prompt_string(&retval, allow_tabs,
#ifndef DISABLE_TABCOMP
allow_files,
+ &list,
#endif
curranswer,
- meta_key, func_key,
-#ifndef NANO_TINY
+#ifndef DISABLE_HISTORIES
history_list,
#endif
- refresh_func, menu
-#ifndef DISABLE_TABCOMP
- , &list
-#endif
- );
+ refresh_func);
free(prompt);
prompt = NULL;
@@ -1201,9 +998,9 @@ int do_prompt(bool allow_tabs,
/* If we left the prompt via Cancel or Enter, set the return value
* properly. */
- if (s && s->scfunc == CANCEL_MSG)
+ if (func == do_cancel)
retval = -1;
- else if (s && s->scfunc == DO_ENTER)
+ else if (func == do_enter_void)
retval = (*answer == '\0') ? -2 : 0;
blank_statusbar();
@@ -1244,7 +1041,6 @@ int do_yesno_prompt(bool all, const char *msg)
const char *yesstr; /* String of Yes characters accepted. */
const char *nostr; /* Same for No. */
const char *allstr; /* And All, surprise! */
- const sc *s;
int oldmenu = currmenu;
assert(msg != NULL);
@@ -1288,12 +1084,15 @@ int do_yesno_prompt(bool all, const char *msg)
onekey("^C", _("Cancel"), width);
}
- wattron(bottomwin, reverse_attr);
+ if (interface_color_pair[TITLE_BAR].bright)
+ wattron(bottomwin, A_BOLD);
+ wattron(bottomwin, interface_color_pair[TITLE_BAR].pairnum);
blank_statusbar();
mvwaddnstr(bottomwin, 0, 0, msg, actual_x(msg, COLS - 1));
- wattroff(bottomwin, reverse_attr);
+ wattroff(bottomwin, A_BOLD);
+ wattroff(bottomwin, interface_color_pair[TITLE_BAR].pairnum);
/* Refresh the edit window and the statusbar before getting
* input. */
@@ -1302,16 +1101,16 @@ int do_yesno_prompt(bool all, const char *msg)
do {
int kbinput;
- bool meta_key, func_key;
+ functionptrtype func;
#ifndef DISABLE_MOUSE
int mouse_x, mouse_y;
#endif
currmenu = MYESNO;
- kbinput = get_kbinput(bottomwin, &meta_key, &func_key);
- s = get_shortcut(currmenu, &kbinput, &meta_key, &func_key);
+ kbinput = get_kbinput(bottomwin);
+ func = func_from_key(&kbinput);
- if (s && s->scfunc == CANCEL_MSG)
+ if (func == do_cancel)
ok = -1;
#ifndef DISABLE_MOUSE
else if (kbinput == KEY_MOUSE) {
@@ -1343,7 +1142,7 @@ int do_yesno_prompt(bool all, const char *msg)
}
}
#endif /* !DISABLE_MOUSE */
- else if (s && s->scfunc == TOTAL_REFRESH) {
+ else if (func == total_refresh) {
total_redraw();
continue;
} else {
diff --git a/src/proto.h b/src/proto.h
index e05eefe..aa79c56 100644
--- a/src/proto.h
+++ b/src/proto.h
@@ -1,9 +1,9 @@
-/* $Id: proto.h 4460 2009-12-09 16:51:43Z astyanax $ */
+/* $Id: proto.h 5133 2015-03-08 12:10:52Z bens $ */
/**************************************************************************
* proto.h *
* *
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
- * 2008, 2009 Free Software Foundation, Inc. *
+ * 2008, 2009, 2010, 2011, 2013, 2014 Free Software Foundation, Inc. *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 3, or (at your option) *
@@ -30,9 +30,11 @@
#ifndef NANO_TINY
extern sigjmp_buf jump_buf;
extern bool jump_buf_main;
-extern bool use_undo;
#endif
+extern bool meta_key;
+extern bool func_key;
+
#ifndef DISABLE_WRAPJUSTIFY
extern ssize_t fill;
extern ssize_t wrap_at;
@@ -60,13 +62,16 @@ extern openfilestruct *openfile;
extern char *matchbrackets;
#endif
-#if !defined(NANO_TINY) && defined(ENABLE_NANORC)
+#if !defined(NANO_TINY) && !defined(DISABLE_NANORC)
extern char *whitespace;
extern int whitespace_len[2];
-extern undo_type last_action;
#endif
+extern const char *exit_tag;
+extern const char *close_tag;
+extern const char *uncut_tag;
#ifndef DISABLE_JUSTIFY
+extern const char *unjust_tag;
extern char *punct;
extern char *brackets;
extern char *quotestr;
@@ -77,7 +82,8 @@ extern char *quoteerr;
#else
extern size_t quotelen;
#endif
-#endif
+#endif /* !DISABLE_JUSTIFY */
+
extern bool nodelay_mode;
extern char *answer;
@@ -85,6 +91,8 @@ extern ssize_t tabsize;
#ifndef NANO_TINY
extern char *backup_dir;
+extern const char *locking_prefix;
+extern const char *locking_suffix;
#endif
#ifndef DISABLE_OPERATINGDIR
extern char *operating_dir;
@@ -95,24 +103,27 @@ extern char *full_operating_dir;
extern char *alt_speller;
#endif
-extern sc *sclist;
-extern subnfunc *allfuncs;
-#ifdef ENABLE_COLOR
+#ifndef DISABLE_COLOR
extern syntaxtype *syntaxes;
extern char *syntaxstr;
#endif
extern bool edit_refresh_needed;
-extern const shortcut *currshortcut;
+
extern int currmenu;
+extern sc *sclist;
+extern subnfunc *allfuncs;
+extern subnfunc *exitfunc;
+extern subnfunc *uncutfunc;
-#ifndef NANO_TINY
+#ifndef DISABLE_HISTORIES
extern filestruct *search_history;
extern filestruct *searchage;
extern filestruct *searchbot;
extern filestruct *replace_history;
extern filestruct *replaceage;
extern filestruct *replacebot;
+extern poshiststruct *poshistory;
#endif
#ifdef HAVE_REGEX_H
@@ -120,16 +131,22 @@ extern regex_t search_regexp;
extern regmatch_t regmatches[10];
#endif
-extern int reverse_attr;
+extern int hilite_attribute;
+#ifndef DISABLE_COLOR
+extern char* specified_color_combo[NUMBER_OF_ELEMENTS];
+#endif
+extern color_pair interface_color_pair[NUMBER_OF_ELEMENTS];
extern char *homedir;
+typedef void (*functionptrtype)(void);
+
/* All functions in browser.c. */
#ifndef DISABLE_BROWSER
char *do_browser(char *path, DIR *dir);
char *do_browse_from(const char *inpath);
void browser_init(const char *path, DIR *dir);
-void parse_browser_input(int *kbinput, bool *meta_key, bool *func_key);
+functionptrtype parse_browser_input(int *kbinput);
void browser_refresh(void);
bool browser_select_filename(const char *needle);
int filesearch_init(void);
@@ -148,6 +165,7 @@ char *striponedir(const char *path);
void utf8_init(void);
bool using_utf8(void);
#endif
+char *addstrings(char* str1, size_t len1, char* str2, size_t len2);
#ifndef HAVE_ISBLANK
bool nisblank(int c);
#endif
@@ -214,19 +232,19 @@ char *revstrpbrk(const char *s, const char *accept, const char
char *mbrevstrpbrk(const char *s, const char *accept, const char
*rev_start);
#endif
-#if defined(ENABLE_NANORC) && (!defined(NANO_TINY) || !defined(DISABLE_JUSTIFY))
+#if !defined(DISABLE_NANORC) && (!defined(NANO_TINY) || !defined(DISABLE_JUSTIFY))
bool has_blank_chars(const char *s);
bool has_blank_mbchars(const char *s);
#endif
#ifdef ENABLE_UTF8
bool is_valid_unicode(wchar_t wc);
#endif
-#ifdef ENABLE_NANORC
+#ifndef DISABLE_NANORC
bool is_valid_mbstring(const char *s);
#endif
/* All functions in color.c. */
-#ifdef ENABLE_COLOR
+#ifndef DISABLE_COLOR
void set_colorpairs(void);
void color_init(void);
void color_update(void);
@@ -234,6 +252,7 @@ void color_update(void);
/* All functions in cut.c. */
void cutbuffer_reset(void);
+bool keeping_cutbuffer(void);
void cut_line(void);
#ifndef NANO_TINY
void cut_marked(void);
@@ -242,7 +261,7 @@ void cut_to_eof(void);
#endif
void do_cut_text(
#ifndef NANO_TINY
- bool copy_text, bool cut_till_end, bool undoing
+ bool copy_text, bool cut_till_eof, bool undoing
#else
void
#endif
@@ -250,7 +269,7 @@ void do_cut_text(
void do_cut_text_void(void);
#ifndef NANO_TINY
void do_copy_text(void);
-void do_cut_till_end(void);
+void do_cut_till_eof(void);
#endif
void do_uncut_text(void);
@@ -263,16 +282,16 @@ void open_buffer(const char *filename, bool undoable);
void replace_buffer(const char *filename);
#endif
void display_buffer(void);
-#ifdef ENABLE_MULTIBUFFER
-void switch_to_prevnext_buffer(bool next);
+#ifndef DISABLE_MULTIBUFFER
+void switch_to_prevnext_buffer(bool next, bool quiet);
void switch_to_prev_buffer_void(void);
void switch_to_next_buffer_void(void);
-bool close_buffer(void);
+bool close_buffer(bool quiet);
#endif
filestruct *read_line(char *buf, filestruct *prevnode, bool
*first_line_ins, size_t buf_len);
void read_file(FILE *f, int fd, const char *filename, bool undoable, bool checkwritable);
-int open_file(const char *filename, bool newfie, FILE **f);
+int open_file(const char *filename, bool newfie, bool quiet, FILE **f);
char *get_next_filename(const char *name, const char *suffix);
void do_insertfile(
#ifndef NANO_TINY
@@ -291,6 +310,8 @@ bool check_operating_dir(const char *currpath, bool allow_tabcomp);
#endif
#ifndef NANO_TINY
void init_backup_dir(void);
+int delete_lockfile(const char *lockfilename);
+int write_lockfile(const char *lockfilename, const char *origfilename, bool modified);
#endif
int copy_file(FILE *inn, FILE *out);
bool write_file(const char *name, FILE *f_open, bool tmp, append_type
@@ -316,46 +337,47 @@ char *input_tab(char *buf, bool allow_files, size_t *place, bool
*lastwastab, void (*refresh_func)(void), bool *list);
#endif
const char *tail(const char *foo);
-#if !defined(NANO_TINY) && defined(ENABLE_NANORC)
+#ifndef DISABLE_HISTORIES
char *histfilename(void);
void load_history(void);
bool writehist(FILE *hist, filestruct *histhead);
void save_history(void);
+int check_dotnano(void);
+void load_poshistory(void);
+void save_poshistory(void);
+void update_poshistory(char *filename, ssize_t lineno, ssize_t xpos);
+int check_poshistory(const char *file, ssize_t *line, ssize_t *column);
#endif
-/* All functions in global.c. */
+/* Some functions in global.c. */
size_t length_of_list(int menu);
-#ifndef NANO_TINY
-void toggle_init_one(int val
-#ifndef DISABLE_HELP
- , const char *desc, bool blank_after
-#endif
- , long flag);
-void toggle_init(void);
-#endif
-void sc_init_one(shortcut **shortcutage, int ctrlval, const char *desc
-#ifndef DISABLE_HELP
- , const char *help, bool blank_after
+key_type strtokeytype(const char *str);
+const sc *first_sc_for(int menu, void (*func)(void));
+int sc_seq_or(void (*func)(void), int defaultval);
+functionptrtype func_from_key(int *kbinput);
+void assign_keyinfo(sc *s);
+void print_sclist(void);
+void shortcut_init(void);
+#ifndef DISABLE_COLOR
+void set_lint_or_format_shortcuts(void);
+void set_spell_shortcuts(void);
#endif
- , int metaval, int funcval, int miscval, bool view, void
- (*func)(void));
-void shortcut_init(bool unjustify);
-void free_shortcutage(shortcut **shortcutage);
+const subnfunc *sctofunc(sc *s);
+const char *flagtostr(int flag);
+sc *strtosc(char *input);
+int strtomenu(char *input);
#ifdef DEBUG
void thanks_for_all_the_fish(void);
#endif
/* All functions in help.c. */
-#ifndef DISABLE_BROWSER
-void do_browser_help(void);
-#endif
-void do_help_void(void);
#ifndef DISABLE_HELP
void do_help(void (*refresh_func)(void));
void help_init(void);
-void parse_help_input(int *kbinput, bool *meta_key, bool *func_key);
+functionptrtype parse_help_input(int *kbinput);
size_t help_line_len(const char *ptr);
#endif
+void do_help_void(void);
/* All functions in move.c. */
void do_first_line(void);
@@ -416,7 +438,7 @@ partition *partition_filestruct(filestruct *top, size_t top_x,
void unpartition_filestruct(partition **p);
void move_to_filestruct(filestruct **file_top, filestruct **file_bot,
filestruct *top, size_t top_x, filestruct *bot, size_t bot_x);
-void copy_from_filestruct(filestruct *file_top, filestruct *file_bot);
+void copy_from_filestruct(filestruct *somebuffer);
openfilestruct *make_new_opennode(void);
void splice_opennode(openfilestruct *begin, openfilestruct *newnode,
openfilestruct *end);
@@ -446,7 +468,7 @@ void print_opt_full(const char *shortflag
, const char *desc);
void usage(void);
void version(void);
-int no_more_space(void);
+int more_space(void);
int no_help(void);
void nano_disabled_msg(void);
void do_exit(void);
@@ -457,10 +479,9 @@ RETSIGTYPE do_continue(int signal);
#ifndef NANO_TINY
RETSIGTYPE handle_sigwinch(int signal);
void allow_pending_sigwinch(bool allow);
-#endif
-#ifndef NANO_TINY
void do_toggle(int flag);
#endif
+void do_toggle_void(void);
void disable_extended_io(void);
#ifdef USE_SLANG
void disable_signals(void);
@@ -471,17 +492,15 @@ void enable_signals(void);
void disable_flow_control(void);
void enable_flow_control(void);
void terminal_init(void);
-int do_input(bool *meta_key, bool *func_key, bool *have_shortcut, bool
- *ran_func, bool *finished, bool allow_funcs);
+int do_input(bool allow_funcs);
#ifndef DISABLE_MOUSE
int do_mouse(void);
#endif
void do_output(char *output, size_t output_len, bool allow_cntrls);
/* All functions in prompt.c. */
-int do_statusbar_input(bool *meta_key, bool *func_key, bool *have_shortcut,
- bool *ran_func, bool *finished, bool allow_funcs, void
- (*refresh_func)(void));
+int do_statusbar_input(bool *ran_func, bool *finished,
+ void (*refresh_func)(void));
#ifndef DISABLE_MOUSE
int do_statusbar_mouse(void);
#endif
@@ -499,66 +518,59 @@ bool do_statusbar_next_word(bool allow_punct);
bool do_statusbar_prev_word(bool allow_punct);
#endif
void do_statusbar_verbatim_input(bool *got_enter);
-#ifndef NANO_TINY
-bool find_statusbar_bracket_match(bool reverse, const char
- *bracket_set);
-void do_statusbar_find_bracket(void);
-#endif
size_t statusbar_xplustabs(void);
size_t get_statusbar_page_start(size_t start_col, size_t column);
void reset_statusbar_cursor(void);
void update_statusbar_line(const char *curranswer, size_t index);
bool need_statusbar_horizontal_update(size_t pww_save);
void total_statusbar_refresh(void (*refresh_func)(void));
-const sc *get_prompt_string(int *value, bool allow_tabs,
+functionptrtype get_prompt_string(int *value, bool allow_tabs,
#ifndef DISABLE_TABCOMP
bool allow_files,
+ bool *list,
#endif
const char *curranswer,
- bool *meta_key, bool *func_key,
-#ifndef NANO_TINY
+#ifndef DISABLE_HISTORIES
filestruct **history_list,
#endif
- void (*refresh_func)(void), int menu
-#ifndef DISABLE_TABCOMP
- , bool *list
-#endif
- );
+ void (*refresh_func)(void));
int do_prompt(bool allow_tabs,
#ifndef DISABLE_TABCOMP
bool allow_files,
#endif
int menu, const char *curranswer,
- bool *meta_key, bool *func_key,
-#ifndef NANO_TINY
+#ifndef DISABLE_HISTORIES
filestruct **history_list,
#endif
void (*refresh_func)(void), const char *msg, ...);
void do_prompt_abort(void);
int do_yesno_prompt(bool all, const char *msg);
-/* All functions in rcfile.c. */
-#ifdef ENABLE_NANORC
-void rcfile_error(const char *msg, ...);
+/* Most functions in rcfile.c. */
+#if !defined(DISABLE_NANORC) || !defined(DISABLE_HISTORIES)
char *parse_next_word(char *ptr);
+#endif
+#ifndef DISABLE_NANORC
+void rcfile_error(const char *msg, ...);
char *parse_argument(char *ptr);
-#ifdef ENABLE_COLOR
+#ifndef DISABLE_COLOR
char *parse_next_regex(char *ptr);
bool nregcomp(const char *regex, int eflags);
void parse_syntax(char *ptr);
void parse_include(char *ptr);
short color_to_short(const char *colorname, bool *bright);
void parse_colors(char *ptr, bool icase);
+bool parse_color_names(char *combostr, short *fg, short *bg, bool *bright);
void reset_multis(filestruct *fileptr, bool force);
void alloc_multidata_if_needed(filestruct *fileptr);
#endif
void parse_rcfile(FILE *rcstream
-#ifdef ENABLE_COLOR
+#ifndef DISABLE_COLOR
, bool syntax_only
#endif
);
void do_rcfile(void);
-#endif
+#endif /* !DISABLE_NANORC */
/* All functions in search.c. */
#ifdef HAVE_REGEX_H
@@ -577,7 +589,7 @@ bool findnextstr(
char *needle, size_t *needle_len);
void findnextstr_wrap_reset(void);
void do_search(void);
-#ifndef NANO_TINY
+#if !defined(NANO_TINY) || !defined(DISABLE_BROWSER)
void do_research(void);
#endif
#ifdef HAVE_REGEX_H
@@ -598,12 +610,16 @@ void do_gotolinecolumn_void(void);
void do_gotopos(ssize_t pos_line, size_t pos_x, ssize_t pos_y, size_t
pos_pww);
#endif
+void goto_line_posx(ssize_t line, size_t pos_x);
#ifndef NANO_TINY
bool find_bracket_match(bool reverse, const char *bracket_set);
void do_find_bracket(void);
-#ifdef ENABLE_NANORC
-bool history_has_changed(void);
+#ifndef DISABLE_TABCOMP
+char *get_history_completion(filestruct **h, const char *s, size_t len);
+#endif
#endif
+#ifndef DISABLE_HISTORIES
+bool history_has_changed(void);
void history_init(void);
void history_reset(const filestruct *h);
filestruct *find_history(const filestruct *h_start, const filestruct
@@ -611,9 +627,8 @@ filestruct *find_history(const filestruct *h_start, const filestruct
void update_history(filestruct **h, const char *s);
char *get_history_older(filestruct **h);
char *get_history_newer(filestruct **h);
-#ifndef DISABLE_TABCOMP
-char *get_history_completion(filestruct **h, const char *s, size_t len);
-#endif
+void get_history_older_void(void);
+void get_history_newer_void(void);
#endif
/* All functions in text.c. */
@@ -631,13 +646,14 @@ void do_undo(void);
void do_redo(void);
#endif
void do_enter(bool undoing);
+void do_enter_void(void);
#ifndef NANO_TINY
RETSIGTYPE cancel_command(int signal);
bool execute_command(const char *command);
#endif
#ifndef DISABLE_WRAPPING
void wrap_reset(void);
-bool do_wrap(filestruct *line, bool undoing);
+bool do_wrap(filestruct *line);
#endif
#if !defined(DISABLE_HELP) || !defined(DISABLE_WRAPJUSTIFY)
ssize_t break_line(const char *line, ssize_t goal
@@ -670,6 +686,10 @@ const char *do_int_speller(const char *tempfile_name);
const char *do_alt_speller(char *tempfile_name);
void do_spell(void);
#endif
+#ifndef DISABLE_COLOR
+void do_linter(void);
+void do_formatter(void);
+#endif
#ifndef NANO_TINY
void do_wordlinechar_count(void);
#endif
@@ -684,7 +704,7 @@ void align(char **str);
void null_at(char **data, size_t index);
void unsunder(char *str, size_t true_len);
void sunder(char *str);
-#if !defined(NANO_TINY) && defined(ENABLE_NANORC)
+#if !defined(NANO_TINY) && !defined(DISABLE_NANORC)
#ifndef HAVE_GETLINE
ssize_t ngetline(char **lineptr, size_t *n, FILE *stream);
#endif
@@ -731,10 +751,10 @@ void dump_filestruct_reverse(void);
void get_key_buffer(WINDOW *win);
size_t get_key_buffer_len(void);
void unget_input(int *input, size_t input_len);
-void unget_kbinput(int kbinput, bool meta_key, bool func_key);
+void unget_kbinput(int kbinput, bool metakey, bool funckey);
int *get_input(WINDOW *win, size_t input_len);
-int get_kbinput(WINDOW *win, bool *meta_key, bool *func_key);
-int parse_kbinput(WINDOW *win, bool *meta_key, bool *func_key);
+int get_kbinput(WINDOW *win);
+int parse_kbinput(WINDOW *win);
int get_escape_seq_kbinput(const int *seq, size_t seq_len);
int get_escape_seq_abcd(int kbinput);
int parse_escape_seq_kbinput(WINDOW *win, int kbinput);
@@ -750,9 +770,7 @@ int *parse_verbatim_kbinput(WINDOW *win, size_t *kbinput_len);
#ifndef DISABLE_MOUSE
int get_mouseinput(int *mouse_x, int *mouse_y, bool allow_shortcuts);
#endif
-const sc *get_shortcut(int menu, int *kbinput, bool
- *meta_key, bool *func_key);
-const sc *first_sc_for(int menu, short func);
+const sc *get_shortcut(int *kbinput);
void blank_line(WINDOW *win, int y, int x, int n);
void blank_titlebar(void);
void blank_topbar(void);
@@ -763,7 +781,7 @@ void check_statusblank(void);
char *display_string(const char *buf, size_t start_col, size_t len, bool
dollars);
void titlebar(const char *path);
-void set_modified(void);
+extern void set_modified(void);
void statusbar(const char *msg, ...);
void bottombars(int menu);
void onekey(const char *keystroke, const char *desc, size_t len);
@@ -783,53 +801,32 @@ void display_main_list(void);
void do_cursorpos(bool constant);
void do_cursorpos_void(void);
void do_replace_highlight(bool highlight, const char *word);
-const char *flagtostr(int flag);
-const subnfunc *sctofunc(sc *s);
-const subnfunc *getfuncfromkey(WINDOW *win);
-void print_sclist(void);
-sc *strtosc(int menu, char *input);
-function_type strtokeytype(const char *str);
-int strtomenu(char *input);
-void assign_keyinfo(sc *s);
void xon_complaint(void);
void xoff_complaint(void);
-int sc_seq_or (short func, int defaultval);
void do_suspend_void(void);
-
-extern const char *cancel_msg;
-#ifndef NANO_TINY
-extern const char *case_sens_msg;
-extern const char *backwards_msg;
-extern const char *prev_history_msg;
-extern const char *next_history_msg;
-#endif
-extern const char *replace_msg;
-extern const char *no_replace_msg;
-extern const char *go_to_line_msg;
-extern const char *whereis_next_msg;
-extern const char *first_file_msg;
-extern const char *last_file_msg;
-extern const char *goto_dir_msg;
-extern const char *ext_cmd_msg;
-extern const char *to_files_msg;
-extern const char *dos_format_msg;
-extern const char *mac_format_msg;
-extern const char *append_msg;
-extern const char *prepend_msg;
-extern const char *backup_file_msg;
-extern const char *gototext_msg;
-extern const char *new_buffer_msg;
-
-void iso_me_harder_funcmap(short func);
void enable_nodelay(void);
void disable_nodelay(void);
-
-#ifdef HAVE_REGEX_H
-extern const char *regexp_msg;
-#endif
-
-#ifdef NANO_EXTRA
+#ifndef DISABLE_EXTRA
void do_credits(void);
#endif
+/* May as well throw these here, since they are just placeholders. */
+void do_cancel(void);
+void do_page_up(void);
+void do_page_down(void);
+void case_sens_void(void);
+void regexp_void(void);
+void gototext_void(void);
+void to_files_void(void);
+void dos_format_void(void);
+void mac_format_void(void);
+void append_void(void);
+void prepend_void(void);
+void backup_file_void(void);
+void new_buffer_void(void);
+void backwards_void(void);
+void goto_dir_void(void);
+void flip_replace_void(void);
+void flip_execute_void(void);
+
#endif /* !PROTO_H */
diff --git a/src/rcfile.c b/src/rcfile.c
index 5aff6d9..a60ea69 100644
--- a/src/rcfile.c
+++ b/src/rcfile.c
@@ -1,9 +1,9 @@
-/* $Id: rcfile.c 4508 2010-06-21 03:10:10Z astyanax $ */
+/* $Id: rcfile.c 5134 2015-03-08 15:42:52Z bens $ */
/**************************************************************************
* rcfile.c *
* *
- * Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 *
- * Free Software Foundation, Inc. *
+ * Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, *
+ * 2010, 2011, 2013, 2014 Free Software Foundation, Inc. *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 3, or (at your option) *
@@ -23,6 +23,7 @@
#include "proto.h"
+#include <glob.h>
#include <stdarg.h>
#include <string.h>
#include <stdio.h>
@@ -30,7 +31,7 @@
#include <unistd.h>
#include <ctype.h>
-#ifdef ENABLE_NANORC
+#ifndef DISABLE_NANORC
static const rcoption rcopts[] = {
{"boldtext", BOLD_TEXT},
@@ -41,10 +42,13 @@ static const rcoption rcopts[] = {
#ifndef DISABLE_WRAPJUSTIFY
{"fill", 0},
#endif
+#ifndef NANO_TINY
+ {"locking", LOCKING},
+#endif
#ifndef DISABLE_MOUSE
{"mouse", USE_MOUSE},
#endif
-#ifdef ENABLE_MULTIBUFFER
+#ifndef DISABLE_MULTIBUFFER
{"multibuffer", MULTIBUFFER},
#endif
{"morespace", MORE_SPACE},
@@ -85,16 +89,22 @@ static const rcoption rcopts[] = {
{"historylog", HISTORYLOG},
{"matchbrackets", 0},
{"noconvert", NO_CONVERT},
+ {"poslog", POS_HISTORY},
{"quiet", QUIET},
{"quickblank", QUICK_BLANK},
{"smarthome", SMART_HOME},
{"smooth", SMOOTH_SCROLL},
{"tabstospaces", TABS_TO_SPACES},
- {"undo", UNDOABLE},
{"whitespace", 0},
{"wordbounds", WORD_BOUNDS},
{"softwrap", SOFTWRAP},
#endif
+#ifndef DISABLE_COLOR
+ {"titlecolor", 0},
+ {"statuscolor", 0},
+ {"keycolor", 0},
+ {"functioncolor", 0},
+#endif
{NULL, 0}
};
@@ -104,14 +114,11 @@ static size_t lineno = 0;
/* If we did, the line number where the last error occurred. */
static char *nanorc = NULL;
/* The path to the rcfile we're parsing. */
-#ifdef ENABLE_COLOR
+#ifndef DISABLE_COLOR
static syntaxtype *endsyntax = NULL;
/* The end of the list of syntaxes. */
-static exttype *endheader = NULL;
- /* End of header list */
static colortype *endcolor = NULL;
/* The end of the color list for the current syntax. */
-
#endif
/* We have an error in some part of the rcfile. Print the error message
@@ -136,7 +143,9 @@ void rcfile_error(const char *msg, ...)
fprintf(stderr, "\n");
}
+#endif /* !DISABLE_NANORC */
+#if !defined(DISABLE_NANORC) || !defined(DISABLE_HISTORIES)
/* Parse the next word from the string, null-terminate it, and return
* a pointer to the first character after the null terminator. The
* returned pointer will point to '\0' if we hit the end of the line. */
@@ -156,7 +165,9 @@ char *parse_next_word(char *ptr)
return ptr;
}
+#endif /* !DISABLE_NANORC || !DISABLE_HISTORIES */
+#ifndef DISABLE_NANORC
/* Parse an argument, with optional quotes, after a keyword that takes
* one. If the next word starts with a ", we say that it ends with the
* last " of the line. Otherwise, we interpret it as usual, so that the
@@ -193,7 +204,7 @@ char *parse_argument(char *ptr)
return ptr;
}
-#ifdef ENABLE_COLOR
+#ifndef DISABLE_COLOR
/* Parse the next regex string from the line at ptr, and return it. */
char *parse_next_regex(char *ptr)
{
@@ -248,8 +259,8 @@ bool nregcomp(const char *regex, int eflags)
void parse_syntax(char *ptr)
{
const char *fileregptr = NULL, *nameptr = NULL;
- syntaxtype *tmpsyntax;
- exttype *endext = NULL;
+ syntaxtype *tmpsyntax, *prev_syntax;
+ regexlisttype *endext = NULL;
/* The end of the extensions list for this syntax. */
assert(ptr != NULL);
@@ -275,15 +286,26 @@ void parse_syntax(char *ptr)
/* Search for a duplicate syntax name. If we find one, free it, so
* that we always use the last syntax with a given name. */
+ prev_syntax = NULL;
for (tmpsyntax = syntaxes; tmpsyntax != NULL;
tmpsyntax = tmpsyntax->next) {
if (strcmp(nameptr, tmpsyntax->desc) == 0) {
- syntaxtype *prev_syntax = tmpsyntax;
+ syntaxtype *old_syntax = tmpsyntax;
+
+ if (endsyntax == tmpsyntax)
+ endsyntax = prev_syntax;
tmpsyntax = tmpsyntax->next;
- free(prev_syntax);
+ if (prev_syntax != NULL)
+ prev_syntax->next = tmpsyntax;
+ else
+ syntaxes = tmpsyntax;
+
+ free(old_syntax->desc);
+ free(old_syntax);
break;
}
+ prev_syntax = tmpsyntax;
}
if (syntaxes == NULL) {
@@ -300,11 +322,13 @@ void parse_syntax(char *ptr)
endsyntax->desc = mallocstrcpy(NULL, nameptr);
endsyntax->color = NULL;
endcolor = NULL;
- endheader = NULL;
endsyntax->extensions = NULL;
endsyntax->headers = NULL;
+ endsyntax->magics = NULL;
endsyntax->next = NULL;
endsyntax->nmultis = 0;
+ endsyntax->linter = NULL;
+ endsyntax->formatter = NULL;
#ifdef DEBUG
fprintf(stderr, "Starting a new syntax type: \"%s\"\n", nameptr);
@@ -324,10 +348,9 @@ void parse_syntax(char *ptr)
return;
}
- /* Now load the extensions into their part of the struct. */
+ /* Now load the extension regexes into their part of the struct. */
while (*ptr != '\0') {
- exttype *newext;
- /* The new extension structure. */
+ regexlisttype *newext;
while (*ptr != '"' && *ptr != '\0')
ptr++;
@@ -342,7 +365,7 @@ void parse_syntax(char *ptr)
if (ptr == NULL)
break;
- newext = (exttype *)nmalloc(sizeof(exttype));
+ newext = (regexlisttype *)nmalloc(sizeof(regexlisttype));
/* Save the extension regex if it's valid. */
if (nregcomp(fileregptr, REG_NOSUB)) {
@@ -359,29 +382,53 @@ void parse_syntax(char *ptr)
free(newext);
}
}
+#endif /* !DISABLE_COLOR */
int check_bad_binding(sc *s)
{
#define BADLISTLEN 1
- int badtypes[BADLISTLEN] = {META};
+ key_type badtypes[BADLISTLEN] = {META};
int badseqs[BADLISTLEN] = { 91 };
int i;
for (i = 0; i < BADLISTLEN; i++)
- if (s->type == badtypes[i] && s->seq == badseqs[i])
+ if (s->type == badtypes[i] && s->seq == badseqs[i])
return 1;
return 0;
}
-void parse_keybinding(char *ptr)
+/* Check whether the given executable function is "universal" (meaning
+ * any horizontal movement or deletion) and thus is present in almost
+ * all menus. */
+bool is_universal(void (*func))
+{
+ if (func == do_left || func == do_right ||
+ func == do_home || func == do_end ||
+#ifndef NANO_TINY
+ func == do_prev_word_void || func == do_next_word_void ||
+#endif
+ func == do_verbatim_input || func == do_cut_text_void ||
+ func == do_delete || func == do_backspace ||
+ func == do_tab || func == do_enter)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+/* Bind or unbind a key combo, to or from a function. */
+void parse_binding(char *ptr, bool dobind)
{
char *keyptr = NULL, *keycopy = NULL, *funcptr = NULL, *menuptr = NULL;
- sc *s, *newsc;
- int i, menu;
+ sc *s, *newsc = NULL;
+ int menu;
assert(ptr != NULL);
+#ifdef DEBUG
+ fprintf(stderr, "Starting the rebinding code...\n");
+#endif
+
if (*ptr == '\0') {
rcfile_error(N_("Missing key name"));
return;
@@ -390,206 +437,206 @@ void parse_keybinding(char *ptr)
keyptr = ptr;
ptr = parse_next_word(ptr);
keycopy = mallocstrcpy(NULL, keyptr);
- for (i = 0; i < strlen(keycopy); i++)
- keycopy[i] = toupper(keycopy[i]);
- if (keycopy[0] != 'M' && keycopy[0] != '^' && keycopy[0] != 'F' && keycopy[0] != 'K') {
- rcfile_error(
- N_("keybindings must begin with \"^\", \"M\", or \"F\""));
+ if (strlen(keycopy) < 2) {
+ rcfile_error(N_("Key name is too short"));
return;
}
- funcptr = ptr;
- ptr = parse_next_word(ptr);
-
- if (!strcmp(funcptr, "")) {
- rcfile_error(
- N_("Must specify function to bind key to"));
- return;
+ /* Uppercase only the first two or three characters of the key name. */
+ keycopy[0] = toupper(keycopy[0]);
+ keycopy[1] = toupper(keycopy[1]);
+ if (keycopy[0] == 'M' && keycopy[1] == '-') {
+ if (strlen(keycopy) > 2)
+ keycopy[2] = toupper(keycopy[2]);
+ else {
+ rcfile_error(N_("Key name is too short"));
+ return;
+ }
}
- menuptr = ptr;
- ptr = parse_next_word(ptr);
-
- if (!strcmp(menuptr, "")) {
- rcfile_error(
- /* Note to translators, do not translate the word "all"
- in the sentence below, everything else is fine */
- N_("Must specify menu to bind key to (or \"all\")"));
+ /* Allow the codes for Insert and Delete to be rebound, but apart
+ * from those two only Control, Meta and Function sequences. */
+ if (!strcasecmp(keycopy, "Ins") || !strcasecmp(keycopy, "Del"))
+ keycopy[1] = tolower(keycopy[1]);
+ else if (keycopy[0] != '^' && keycopy[0] != 'M' && keycopy[0] != 'F') {
+ rcfile_error(N_("Key name must begin with \"^\", \"M\", or \"F\""));
return;
}
- menu = strtomenu(menuptr);
- newsc = strtosc(menu, funcptr);
- if (newsc == NULL) {
- rcfile_error(
- N_("Could not map name \"%s\" to a function"), funcptr);
- return;
- }
+ if (dobind) {
+ funcptr = ptr;
+ ptr = parse_next_word(ptr);
- if (menu < 1) {
- rcfile_error(
- N_("Could not map name \"%s\" to a menu"), menuptr);
- return;
+ if (funcptr[0] == '\0') {
+ rcfile_error(N_("Must specify a function to bind the key to"));
+ return;
+ }
}
+ menuptr = ptr;
+ ptr = parse_next_word(ptr);
-#ifdef DEBUG
- fprintf(stderr, "newsc now address %d, menu func assigned = %d, menu = %d\n",
- &newsc, newsc->scfunc, menu);
-#endif
-
-
- newsc->keystr = keycopy;
- newsc->menu = menu;
- newsc->type = strtokeytype(newsc->keystr);
- assign_keyinfo(newsc);
-#ifdef DEBUG
- fprintf(stderr, "s->keystr = \"%s\"\n", newsc->keystr);
- fprintf(stderr, "s->seq = \"%d\"\n", newsc->seq);
-#endif
-
- if (check_bad_binding(newsc)) {
- rcfile_error(
- N_("Sorry, keystr \"%s\" is an illegal binding"), newsc->keystr);
+ if (menuptr[0] == '\0') {
+ /* TRANSLATORS: Do not translate the word "all". */
+ rcfile_error(N_("Must specify a menu (or \"all\") in which to bind/unbind the key"));
return;
}
- /* now let's have some fun. Try and delete the other entries
- we found for the same menu, then make this new new
- beginning */
- for (s = sclist; s != NULL; s = s->next) {
- if (((s->menu & newsc->menu)) && s->seq == newsc->seq) {
- s->menu &= ~newsc->menu;
-#ifdef DEBUG
- fprintf(stderr, "replaced menu entry %d\n", s->menu);
-#endif
+ if (dobind) {
+ newsc = strtosc(funcptr);
+ if (newsc == NULL) {
+ rcfile_error(N_("Cannot map name \"%s\" to a function"), funcptr);
+ return;
}
}
- newsc->next = sclist;
- sclist = newsc;
-}
-
-/* Let user unbind a sequence from a given (or all) menus */
-void parse_unbinding(char *ptr)
-{
- char *keyptr = NULL, *keycopy = NULL, *menuptr = NULL;
- sc *s;
- int i, menu;
- assert(ptr != NULL);
-
- if (*ptr == '\0') {
- rcfile_error(N_("Missing key name"));
+ menu = strtomenu(menuptr);
+ if (menu < 1) {
+ rcfile_error(N_("Cannot map name \"%s\" to a menu"), menuptr);
return;
}
- keyptr = ptr;
- ptr = parse_next_word(ptr);
- keycopy = mallocstrcpy(NULL, keyptr);
- for (i = 0; i < strlen(keycopy); i++)
- keycopy[i] = toupper(keycopy[i]);
-
#ifdef DEBUG
- fprintf(stderr, "Starting unbinding code");
+ if (dobind)
+ fprintf(stderr, "newsc address is now %ld, assigned func = %ld, menu = %x\n",
+ (long)&newsc, (long)newsc->scfunc, menu);
+ else
+ fprintf(stderr, "unbinding \"%s\" from menu %x\n", keycopy, menu);
#endif
- if (keycopy[0] != 'M' && keycopy[0] != '^' && keycopy[0] != 'F' && keycopy[0] != 'K') {
- rcfile_error(
- N_("keybindings must begin with \"^\", \"M\", or \"F\""));
- return;
- }
+ if (dobind) {
+ subnfunc *f;
+ int mask = 0;
- menuptr = ptr;
- ptr = parse_next_word(ptr);
+ /* Tally up the menus where the function exists. */
+ for (f = allfuncs; f != NULL; f = f->next)
+ if (f->scfunc == newsc->scfunc)
+ mask = mask | f->menus;
- if (!strcmp(menuptr, "")) {
- rcfile_error(
- /* Note to translators, do not translate the word "all"
- in the sentence below, everything else is fine */
- N_("Must specify menu to bind key to (or \"all\")"));
- return;
- }
+ /* Handle the special case of the toggles. */
+ if (newsc->scfunc == do_toggle_void)
+ mask = MMAIN;
- menu = strtomenu(menuptr);
- if (menu < 1) {
- rcfile_error(
- N_("Could not map name \"%s\" to a menu"), menuptr);
- return;
- }
+ /* Now limit the given menu to those where the function exists. */
+ if (is_universal(newsc->scfunc))
+ menu = menu & MMOST;
+ else
+ menu = menu & mask;
+ if (!menu) {
+ rcfile_error(N_("Function '%s' does not exist in menu '%s'"), funcptr, menuptr);
+ free(newsc);
+ return;
+ }
+ newsc->keystr = keycopy;
+ newsc->menu = menu;
+ newsc->type = strtokeytype(newsc->keystr);
+ assign_keyinfo(newsc);
#ifdef DEBUG
- fprintf(stderr, "unbinding \"%s\" from menu = %d\n", keycopy, menu);
+ fprintf(stderr, "s->keystr = \"%s\"\n", newsc->keystr);
+ fprintf(stderr, "s->seq = \"%d\"\n", newsc->seq);
#endif
- /* Now find the apropriate entries in the menu to delete */
+ if (check_bad_binding(newsc)) {
+ rcfile_error(N_("Sorry, keystroke \"%s\" may not be rebound"), newsc->keystr);
+ free(newsc);
+ return;
+ }
+ }
+
+ /* Now find and delete any existing same shortcut in the menu(s). */
for (s = sclist; s != NULL; s = s->next) {
- if (((s->menu & menu)) && !strcmp(s->keystr,keycopy)) {
- s->menu &= ~menu;
+ if (((s->menu & menu)) && !strcmp(s->keystr, keycopy)) {
#ifdef DEBUG
- fprintf(stderr, "deleted menu entry %d\n", s->menu);
+ fprintf(stderr, "deleting entry from menu %x\n", s->menu);
#endif
+ s->menu &= ~menu;
}
}
+
+ if (dobind) {
+ /* Add the new shortcut at the start of the list. */
+ newsc->next = sclist;
+ sclist = newsc;
+ }
}
+#ifndef DISABLE_COLOR
/* Read and parse additional syntax files. */
-void parse_include(char *ptr)
+static void _parse_include(char *file)
{
struct stat rcinfo;
FILE *rcstream;
- char *option, *nanorc_save = nanorc, *expanded;
- size_t lineno_save = lineno;
- option = ptr;
- if (*option == '"')
- option++;
- ptr = parse_argument(ptr);
-
- /* Can't get the specified file's full path cause it may screw up
- our cwd depending on the parent dirs' permissions, (see Savannah bug 25297) */
+ /* Can't get the specified file's full path because it may screw up
+ * our cwd depending on the parent directories' permissions (see
+ * Savannah bug #25297). */
/* Don't open directories, character files, or block files. */
- if (stat(option, &rcinfo) != -1) {
+ if (stat(file, &rcinfo) != -1) {
if (S_ISDIR(rcinfo.st_mode) || S_ISCHR(rcinfo.st_mode) ||
S_ISBLK(rcinfo.st_mode)) {
rcfile_error(S_ISDIR(rcinfo.st_mode) ?
_("\"%s\" is a directory") :
- _("\"%s\" is a device file"), option);
+ _("\"%s\" is a device file"), file);
}
}
- expanded = real_dir_from_tilde(option);
-
/* Open the new syntax file. */
- if ((rcstream = fopen(expanded, "rb")) == NULL) {
- rcfile_error(_("Error reading %s: %s"), expanded,
+ if ((rcstream = fopen(file, "rb")) == NULL) {
+ rcfile_error(_("Error reading %s: %s"), file,
strerror(errno));
return;
}
/* Use the name and line number position of the new syntax file
* while parsing it, so we can know where any errors in it are. */
- nanorc = expanded;
+ nanorc = file;
lineno = 0;
#ifdef DEBUG
- fprintf(stderr, "Parsing file \"%s\" (expanded from \"%s\")\n", expanded, option);
+ fprintf(stderr, "Parsing file \"%s\"\n", file);
#endif
parse_rcfile(rcstream
-#ifdef ENABLE_COLOR
+#ifndef DISABLE_COLOR
, TRUE
#endif
);
+}
+
+void parse_include(char *ptr)
+{
+ char *option, *nanorc_save = nanorc, *expanded;
+ size_t lineno_save = lineno, i;
+ glob_t files;
+
+ option = ptr;
+ if (*option == '"')
+ option++;
+ ptr = parse_argument(ptr);
+
+ /* Expand tildes first, then the globs. */
+ expanded = real_dir_from_tilde(option);
+
+ if (glob(expanded, GLOB_ERR|GLOB_NOSORT, NULL, &files) == 0) {
+ for (i = 0; i < files.gl_pathc; ++i)
+ _parse_include(files.gl_pathv[i]);
+ } else {
+ rcfile_error(_("Error expanding %s: %s"), option,
+ strerror(errno));
+ }
+
+ globfree(&files);
+ free(expanded);
/* We're done with the new syntax file. Restore the original
* filename and line number position. */
nanorc = nanorc_save;
lineno = lineno_save;
-
}
/* Return the short value corresponding to the color named in colorname,
@@ -637,7 +684,7 @@ short color_to_short(const char *colorname, bool *bright)
void parse_colors(char *ptr, bool icase)
{
short fg, bg;
- bool bright = FALSE, no_fgcolor = FALSE;
+ bool bright = FALSE;
char *fgstr;
assert(ptr != NULL);
@@ -655,36 +702,8 @@ void parse_colors(char *ptr, bool icase)
fgstr = ptr;
ptr = parse_next_word(ptr);
-
- if (strchr(fgstr, ',') != NULL) {
- char *bgcolorname;
-
- strtok(fgstr, ",");
- bgcolorname = strtok(NULL, ",");
- if (bgcolorname == NULL) {
- /* If we have a background color without a foreground color,
- * parse it properly. */
- bgcolorname = fgstr + 1;
- no_fgcolor = TRUE;
- }
- if (strncasecmp(bgcolorname, "bright", 6) == 0) {
- rcfile_error(
- N_("Background color \"%s\" cannot be bright"),
- bgcolorname);
- return;
- }
- bg = color_to_short(bgcolorname, &bright);
- } else
- bg = -1;
-
- if (!no_fgcolor) {
- fg = color_to_short(fgstr, &bright);
-
- /* Don't try to parse screwed-up foreground colors. */
- if (fg == -1)
- return;
- } else
- fg = -1;
+ if (!parse_color_names(fgstr, &fg, &bg, &bright))
+ return;
if (*ptr == '\0') {
rcfile_error(N_("Missing regex string"));
@@ -695,7 +714,7 @@ void parse_colors(char *ptr, bool icase)
* in the colorstrings array, woo! */
while (ptr != NULL && *ptr != '\0') {
colortype *newcolor;
- /* The new color structure. */
+ /* The container for a color plus its regexes. */
bool cancelled = FALSE;
/* The start expression was bad. */
bool expectend = FALSE;
@@ -747,6 +766,10 @@ void parse_colors(char *ptr, bool icase)
#ifdef DEBUG
fprintf(stderr, "Adding new entry for fg %hd, bg %hd\n", fg, bg);
#endif
+ /* Need to recompute endcolor now so we can extend
+ * colors to syntaxes. */
+ for (endcolor = endsyntax->color; endcolor->next != NULL; endcolor = endcolor->next)
+ ;
endcolor->next = newcolor;
}
@@ -776,8 +799,8 @@ void parse_colors(char *ptr, bool icase)
if (ptr == NULL)
break;
- /* If the start regex was invalid, skip past the end regex to
- * stay in sync. */
+ /* If the start regex was invalid, skip past the end regex
+ * to stay in sync. */
if (cancelled)
continue;
@@ -785,17 +808,55 @@ void parse_colors(char *ptr, bool icase)
newcolor->end_regex = (nregcomp(fgstr, icase ? REG_ICASE :
0)) ? mallocstrcpy(NULL, fgstr) : NULL;
- /* Lame way to skip another static counter */
- newcolor->id = endsyntax->nmultis;
- endsyntax->nmultis++;
+ /* Lame way to skip another static counter. */
+ newcolor->id = endsyntax->nmultis;
+ endsyntax->nmultis++;
}
}
}
-/* Parse the headers (1st line) of the file which may influence the regex used. */
-void parse_headers(char *ptr)
+/* Parse the color name, or pair of color names, in combostr. */
+bool parse_color_names(char *combostr, short *fg, short *bg, bool *bright)
{
- char *regstr;
+ bool no_fgcolor = FALSE;
+
+ if (combostr == NULL)
+ return FALSE;
+
+ if (strchr(combostr, ',') != NULL) {
+ char *bgcolorname;
+ strtok(combostr, ",");
+ bgcolorname = strtok(NULL, ",");
+ if (bgcolorname == NULL) {
+ /* If we have a background color without a foreground color,
+ * parse it properly. */
+ bgcolorname = combostr + 1;
+ no_fgcolor = TRUE;
+ }
+ if (strncasecmp(bgcolorname, "bright", 6) == 0) {
+ rcfile_error(N_("Background color \"%s\" cannot be bright"), bgcolorname);
+ return FALSE;
+ }
+ *bg = color_to_short(bgcolorname, bright);
+ } else
+ *bg = -1;
+
+ if (!no_fgcolor) {
+ *fg = color_to_short(combostr, bright);
+
+ /* Don't try to parse screwed-up foreground colors. */
+ if (*fg == -1)
+ return FALSE;
+ } else
+ *fg = -1;
+
+ return TRUE;
+}
+
+/* Parse the header-line regexes that may influence the choice of syntax. */
+void parse_header_exp(char *ptr)
+{
+ regexlisttype *endheader = NULL;
assert(ptr != NULL);
@@ -810,11 +871,9 @@ void parse_headers(char *ptr)
return;
}
- /* Now for the fun part. Start adding regexes to individual strings
- * in the colorstrings array, woo! */
- while (ptr != NULL && *ptr != '\0') {
- exttype *newheader;
- /* The new color structure. */
+ while (*ptr != '\0') {
+ const char *regexstring;
+ regexlisttype *newheader;
if (*ptr != '"') {
rcfile_error(
@@ -825,60 +884,173 @@ void parse_headers(char *ptr)
ptr++;
- regstr = ptr;
+ regexstring = ptr;
ptr = parse_next_regex(ptr);
if (ptr == NULL)
break;
- newheader = (exttype *)nmalloc(sizeof(exttype));
+ newheader = (regexlisttype *)nmalloc(sizeof(regexlisttype));
- /* Save the regex string if it's valid */
- if (nregcomp(regstr, 0)) {
- newheader->ext_regex = mallocstrcpy(NULL, regstr);
+ /* Save the regex string if it's valid. */
+ if (nregcomp(regexstring, 0)) {
+ newheader->ext_regex = mallocstrcpy(NULL, regexstring);
newheader->ext = NULL;
- newheader->next = NULL;
-
-#ifdef DEBUG
- fprintf(stderr, "Starting a new header entry: %s\n", newheader->ext_regex);
-#endif
- if (endheader == NULL) {
+ if (endheader == NULL)
endsyntax->headers = newheader;
- } else {
+ else
endheader->next = newheader;
- }
-
endheader = newheader;
+ endheader->next = NULL;
} else
free(newheader);
+ }
+}
+
+#ifndef DISABLE_COLOR
+/* Parse the magic regexes that may influence the choice of syntax. */
+void parse_magic_exp(char *ptr)
+{
+#ifdef HAVE_LIBMAGIC
+ regexlisttype *endmagic = NULL;
+ assert(ptr != NULL);
+
+ if (syntaxes == NULL) {
+ rcfile_error(
+ N_("Cannot add a magic string regex without a syntax command"));
+ return;
+ }
+
+ if (*ptr == '\0') {
+ rcfile_error(N_("Missing magic string name"));
+ return;
}
+
+ if (*ptr != '"') {
+ rcfile_error(
+ N_("Regex strings must begin and end with a \" character"));
+ return;
+ }
+
+#ifdef DEBUG
+ fprintf(stderr, "Starting a magic type: \"%s\"\n", ptr);
+#endif
+
+ /* Now load the magic regexes into their part of the struct. */
+ while (*ptr != '\0') {
+ const char *regexstring;
+ regexlisttype *newmagic;
+
+ while (*ptr != '"' && *ptr != '\0')
+ ptr++;
+
+ if (*ptr == '\0')
+ return;
+
+ ptr++;
+
+ regexstring = ptr;
+ ptr = parse_next_regex(ptr);
+ if (ptr == NULL)
+ break;
+
+ newmagic = (regexlisttype *)nmalloc(sizeof(regexlisttype));
+
+ /* Save the regex string if it's valid. */
+ if (nregcomp(regexstring, REG_NOSUB)) {
+ newmagic->ext_regex = mallocstrcpy(NULL, regexstring);
+ newmagic->ext = NULL;
+
+ if (endmagic == NULL)
+ endsyntax->magics = newmagic;
+ else
+ endmagic->next = newmagic;
+ endmagic = newmagic;
+ endmagic->next = NULL;
+ } else
+ free(newmagic);
+ }
+#endif /* HAVE_LIBMAGIC */
}
-#endif /* ENABLE_COLOR */
+#endif /* !DISABLE_COLOR */
+
+/* Parse the linter requested for this syntax. Simple? */
+void parse_linter(char *ptr)
+{
+ assert(ptr != NULL);
+
+ if (syntaxes == NULL) {
+ rcfile_error(
+ N_("Cannot add a linter without a syntax command"));
+ return;
+ }
+
+ if (*ptr == '\0') {
+ rcfile_error(N_("Missing linter command"));
+ return;
+ }
+
+ if (endsyntax->linter != NULL)
+ free(endsyntax->linter);
+
+ /* Let them unset the linter by using "". */
+ if (!strcmp(ptr, "\"\""))
+ endsyntax->linter = NULL;
+ else
+ endsyntax->linter = mallocstrcpy(syntaxes->linter, ptr);
+}
+
+void parse_formatter(char *ptr)
+{
+ assert(ptr != NULL);
+
+ if (syntaxes == NULL) {
+ rcfile_error(
+ N_("Cannot add formatter without a syntax command"));
+ return;
+ }
+
+ if (*ptr == '\0') {
+ rcfile_error(N_("Missing formatter command"));
+ return;
+ }
+
+ if (endsyntax->formatter != NULL)
+ free(endsyntax->formatter);
+
+ /* Let them unset the formatter by using "". */
+ if (!strcmp(ptr, "\"\""))
+ endsyntax->formatter = NULL;
+ else
+ endsyntax->formatter = mallocstrcpy(syntaxes->formatter, ptr);
+}
+#endif /* !DISABLE_COLOR */
/* Check whether the user has unmapped every shortcut for a
-sequence we consider 'vital', like the exit function */
+ * sequence we consider 'vital', like the exit function. */
static void check_vitals_mapped(void)
{
subnfunc *f;
int v;
#define VITALS 5
- short vitals[VITALS] = { DO_EXIT, DO_EXIT, CANCEL_MSG, CANCEL_MSG, CANCEL_MSG };
+ void (*vitals[VITALS])(void) = { do_exit, do_exit, do_cancel, do_cancel, do_cancel };
int inmenus[VITALS] = { MMAIN, MHELP, MWHEREIS, MREPLACE, MGOTOLINE };
for (v = 0; v < VITALS; v++) {
- for (f = allfuncs; f != NULL; f = f->next) {
- if (f->scfunc == vitals[v] && f->menus & inmenus[v]) {
- const sc *s = first_sc_for(inmenus[v], f->scfunc);
- if (!s) {
- rcfile_error(N_("Fatal error: no keys mapped for function \"%s\""),
- f->desc);
- fprintf(stderr, N_("Exiting. Please use nano with the -I option if needed to adjust your nanorc settings\n"));
- exit(1);
- }
- break;
- }
- }
+ for (f = allfuncs; f != NULL; f = f->next) {
+ if (f->scfunc == vitals[v] && f->menus & inmenus[v]) {
+ const sc *s = first_sc_for(inmenus[v], f->scfunc);
+ if (!s) {
+ fprintf(stderr, _("Fatal error: no keys mapped for function "
+ "\"%s\". Exiting.\n"), f->desc);
+ fprintf(stderr, _("If needed, use nano with the -I option "
+ "to adjust your nanorc settings.\n"));
+ exit(1);
+ }
+ break;
+ }
+ }
}
}
@@ -886,7 +1058,7 @@ static void check_vitals_mapped(void)
* and close it afterwards. If syntax_only is TRUE, only allow the file
* to contain color syntax commands: syntax, color, and icolor. */
void parse_rcfile(FILE *rcstream
-#ifdef ENABLE_COLOR
+#ifndef DISABLE_COLOR
, bool syntax_only
#endif
)
@@ -894,6 +1066,9 @@ void parse_rcfile(FILE *rcstream
char *buf = NULL;
ssize_t len;
size_t n = 0;
+#ifndef DISABLE_COLOR
+ syntaxtype *end_syn_save = NULL;
+#endif
while ((len = getline(&buf, &n, rcstream)) > 0) {
char *ptr, *keyword, *option;
@@ -918,9 +1093,32 @@ void parse_rcfile(FILE *rcstream
keyword = ptr;
ptr = parse_next_word(ptr);
+#ifndef DISABLE_COLOR
+ /* Handle extending first... */
+ if (strcasecmp(keyword, "extendsyntax") == 0) {
+ char *syntaxname = ptr;
+ syntaxtype *ts = NULL;
+
+ ptr = parse_next_word(ptr);
+ for (ts = syntaxes; ts != NULL; ts = ts->next)
+ if (!strcmp(ts->desc, syntaxname))
+ break;
+
+ if (ts == NULL) {
+ rcfile_error(N_("Could not find syntax \"%s\" to extend"), syntaxname);
+ continue;
+ } else {
+ end_syn_save = endsyntax;
+ endsyntax = ts;
+ keyword = ptr;
+ ptr = parse_next_word(ptr);
+ }
+ }
+#endif
+
/* Try to parse the keyword. */
if (strcasecmp(keyword, "set") == 0) {
-#ifdef ENABLE_COLOR
+#ifndef DISABLE_COLOR
if (syntax_only)
rcfile_error(
N_("Command \"%s\" not allowed in included file"),
@@ -929,7 +1127,7 @@ void parse_rcfile(FILE *rcstream
#endif
set = 1;
} else if (strcasecmp(keyword, "unset") == 0) {
-#ifdef ENABLE_COLOR
+#ifndef DISABLE_COLOR
if (syntax_only)
rcfile_error(
N_("Command \"%s\" not allowed in included file"),
@@ -938,7 +1136,7 @@ void parse_rcfile(FILE *rcstream
#endif
set = -1;
}
-#ifdef ENABLE_COLOR
+#ifndef DISABLE_COLOR
else if (strcasecmp(keyword, "include") == 0) {
if (syntax_only)
rcfile_error(
@@ -951,25 +1149,41 @@ void parse_rcfile(FILE *rcstream
rcfile_error(N_("Syntax \"%s\" has no color commands"),
endsyntax->desc);
parse_syntax(ptr);
- } else if (strcasecmp(keyword, "header") == 0)
- parse_headers(ptr);
+ }
+ else if (strcasecmp(keyword, "magic") == 0)
+ parse_magic_exp(ptr);
+ else if (strcasecmp(keyword, "header") == 0)
+ parse_header_exp(ptr);
else if (strcasecmp(keyword, "color") == 0)
parse_colors(ptr, FALSE);
else if (strcasecmp(keyword, "icolor") == 0)
parse_colors(ptr, TRUE);
+ else if (strcasecmp(keyword, "linter") == 0)
+ parse_linter(ptr);
+ else if (strcasecmp(keyword, "formatter") == 0)
+ parse_formatter(ptr);
+#endif /* !DISABLE_COLOR */
else if (strcasecmp(keyword, "bind") == 0)
- parse_keybinding(ptr);
+ parse_binding(ptr, TRUE);
else if (strcasecmp(keyword, "unbind") == 0)
- parse_unbinding(ptr);
-#endif /* ENABLE_COLOR */
+ parse_binding(ptr, FALSE);
else
rcfile_error(N_("Command \"%s\" not understood"), keyword);
+#ifndef DISABLE_COLOR
+ /* If we temporarily reset endsyntax to allow extending,
+ * restore the value here. */
+ if (end_syn_save != NULL) {
+ endsyntax = end_syn_save;
+ end_syn_save = NULL;
+ }
+#endif
+
if (set == 0)
continue;
if (*ptr == '\0') {
- rcfile_error(N_("Missing flag"));
+ rcfile_error(N_("Missing option"));
continue;
}
@@ -1013,6 +1227,17 @@ void parse_rcfile(FILE *rcstream
break;
}
+#ifndef DISABLE_COLOR
+ if (strcasecmp(rcopts[i].name, "titlecolor") == 0)
+ specified_color_combo[TITLE_BAR] = option;
+ else if (strcasecmp(rcopts[i].name, "statuscolor") == 0)
+ specified_color_combo[STATUS_BAR] = option;
+ else if (strcasecmp(rcopts[i].name, "keycolor") == 0)
+ specified_color_combo[KEY_COMBO] = option;
+ else if (strcasecmp(rcopts[i].name, "functioncolor") == 0)
+ specified_color_combo[FUNCTION_TAG] = option;
+ else
+#endif
#ifndef DISABLE_OPERATINGDIR
if (strcasecmp(rcopts[i].name, "operatingdir") == 0)
operating_dir = option;
@@ -1111,19 +1336,16 @@ void parse_rcfile(FILE *rcstream
} else if (rcopts[i].flag != 0)
UNSET(rcopts[i].flag);
else
- rcfile_error(N_("Cannot unset flag \"%s\""),
+ rcfile_error(N_("Cannot unset option \"%s\""),
rcopts[i].name);
- /* Looks like we still need this specific hack for undo */
- if (strcasecmp(rcopts[i].name, "undo") == 0)
- shortcut_init(0);
break;
}
}
if (rcopts[i].name == NULL)
- rcfile_error(N_("Unknown flag \"%s\""), option);
+ rcfile_error(N_("Unknown option \"%s\""), option);
}
-#ifdef ENABLE_COLOR
+#ifndef DISABLE_COLOR
if (endsyntax != NULL && endcolor == NULL)
rcfile_error(N_("Syntax \"%s\" has no color commands"),
endsyntax->desc);
@@ -1163,7 +1385,7 @@ void do_rcfile(void)
rcstream = fopen(nanorc, "rb");
if (rcstream != NULL)
parse_rcfile(rcstream
-#ifdef ENABLE_COLOR
+#ifndef DISABLE_COLOR
, FALSE
#endif
);
@@ -1205,7 +1427,7 @@ void do_rcfile(void)
strerror(errno));
} else
parse_rcfile(rcstream
-#ifdef ENABLE_COLOR
+#ifndef DISABLE_COLOR
, FALSE
#endif
);
@@ -1221,10 +1443,6 @@ void do_rcfile(void)
while (getchar() != '\n')
;
}
-
-#ifdef ENABLE_COLOR
- set_colorpairs();
-#endif
}
-#endif /* ENABLE_NANORC */
+#endif /* !DISABLE_NANORC */
diff --git a/src/search.c b/src/search.c
index 4b93045..eb3bfb2 100644
--- a/src/search.c
+++ b/src/search.c
@@ -1,9 +1,9 @@
-/* $Id: search.c 4472 2010-01-05 23:35:50Z astyanax $ */
+/* $Id: search.c 5148 2015-03-22 11:42:29Z bens $ */
/**************************************************************************
* search.c *
* *
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
- * 2008, 2009 Free Software Foundation, Inc. *
+ * 2008, 2009, 2010, 2011, 2013, 2014 Free Software Foundation, Inc. *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 3, or (at your option) *
@@ -32,7 +32,7 @@
static bool search_last_line = FALSE;
/* Have we gone past the last line while searching? */
-#if !defined(NANO_TINY) && defined(ENABLE_NANORC)
+#ifndef DISABLE_HISTORIES
static bool history_changed = FALSE;
/* Have any of the history lists changed? */
#endif
@@ -137,9 +137,6 @@ int search_init(bool replacing, bool use_answer)
{
int i = 0;
char *buf;
- sc *s;
- char func = 0;
- bool meta_key = FALSE, func_key = FALSE;
static char *backupstring = NULL;
/* The search string we'll be using. */
@@ -164,8 +161,7 @@ int search_init(bool replacing, bool use_answer)
char *disp = display_string(last_search, 0, COLS / 3, FALSE);
buf = charalloc(strlen(disp) + 7);
- /* We use (COLS / 3) here because we need to see more on the
- * line. */
+ /* We use (COLS / 3) here because we need to see more on the line. */
sprintf(buf, " [%s%s]", disp,
(strlenpt(last_search) > COLS / 3) ? "..." : "");
free(disp);
@@ -178,30 +174,26 @@ int search_init(bool replacing, bool use_answer)
TRUE,
#endif
replacing ? MREPLACE : MWHEREIS, backupstring,
- &meta_key, &func_key,
-#ifndef NANO_TINY
+#ifndef DISABLE_HISTORIES
&search_history,
#endif
+ /* TRANSLATORS: This is the main search prompt. */
edit_refresh, "%s%s%s%s%s%s", _("Search"),
#ifndef NANO_TINY
- /* TRANSLATORS: This string is just a modifier for the search
- * prompt; no grammar is implied. */
+ /* TRANSLATORS: The next three strings are modifiers of the search prompt. */
ISSET(CASE_SENSITIVE) ? _(" [Case Sensitive]") :
#endif
"",
#ifdef HAVE_REGEX_H
- /* TRANSLATORS: This string is just a modifier for the search
- * prompt; no grammar is implied. */
ISSET(USE_REGEXP) ? _(" [Regexp]") :
#endif
"",
#ifndef NANO_TINY
- /* TRANSLATORS: This string is just a modifier for the search
- * prompt; no grammar is implied. */
ISSET(BACKWARDS_SEARCH) ? _(" [Backwards]") :
#endif
"", replacing ?
#ifndef NANO_TINY
+ /* TRANSLATORS: The next two strings are modifiers of the search prompt. */
openfile->mark_set ? _(" (to replace) in selection") :
#endif
_(" (to replace)") : "", buf);
@@ -220,11 +212,7 @@ int search_init(bool replacing, bool use_answer)
statusbar(_("Cancelled"));
return -1;
} else {
- for (s = sclist; s != NULL; s = s->next)
- if ((s->menu & currmenu) && i == s->seq) {
- func = s->scfunc;
- break;
- }
+ functionptrtype func = func_from_key(&i);
if (i == -2 || i == 0 ) {
#ifdef HAVE_REGEX_H
@@ -236,26 +224,25 @@ int search_init(bool replacing, bool use_answer)
#endif
;
#ifndef NANO_TINY
- } else if (func == CASE_SENS_MSG) {
+ } else if (func == case_sens_void) {
TOGGLE(CASE_SENSITIVE);
backupstring = mallocstrcpy(backupstring, answer);
return 1;
- } else if (func == BACKWARDS_MSG) {
+ } else if (func == backwards_void) {
TOGGLE(BACKWARDS_SEARCH);
backupstring = mallocstrcpy(backupstring, answer);
return 1;
#endif
#ifdef HAVE_REGEX_H
- } else if (func == REGEXP_MSG) {
+ } else if (func == regexp_void) {
TOGGLE(USE_REGEXP);
backupstring = mallocstrcpy(backupstring, answer);
return 1;
#endif
- } else if (func == DO_REPLACE ||
- func == NO_REPLACE_MSG) {
+ } else if (func == do_replace || func == flip_replace_void) {
backupstring = mallocstrcpy(backupstring, answer);
return -2; /* Call the opposite search function. */
- } else if (func == DO_GOTOLINECOLUMN_VOID) {
+ } else if (func == do_gotolinecolumn_void) {
do_gotolinecolumn(openfile->current->lineno,
openfile->placewewant + 1, TRUE, TRUE, FALSE,
TRUE);
@@ -289,7 +276,6 @@ bool findnextstr(
ssize_t current_y_find = openfile->current_y;
filestruct *fileptr = openfile->current;
const char *rev_start = fileptr->data, *found = NULL;
- const subnfunc *f;
time_t lastkbcheck = time(NULL);
/* rev_start might end up 1 character before the start or after the
@@ -300,17 +286,19 @@ bool findnextstr(
rev_start +=
#ifndef NANO_TINY
ISSET(BACKWARDS_SEARCH) ?
- openfile->current_x - 1 :
+ ((openfile->current_x == 0) ? -1 : move_mbleft(fileptr->data, openfile->current_x)) :
#endif
- openfile->current_x + 1;
+ move_mbright(fileptr->data, openfile->current_x);
/* Look for needle in the current line we're searching. */
enable_nodelay();
while (TRUE) {
- if (time(NULL) - lastkbcheck > 1) {
- lastkbcheck = time(NULL);
- f = getfuncfromkey(edit);
- if (f && f->scfunc == CANCEL_MSG) {
+ if (time(NULL) - lastkbcheck > 1) {
+ int input = parse_kbinput(edit);
+
+ lastkbcheck = time(NULL);
+
+ if (input && func_from_key(&input) == do_cancel) {
statusbar(_("Cancelled"));
return FALSE;
}
@@ -358,10 +346,10 @@ bool findnextstr(
break;
}
- /* We've finished processing the file, so get out. */
if (search_last_line) {
+ /* We've finished processing the file, so get out. */
not_found_msg(needle);
- disable_nodelay();
+ disable_nodelay();
return FALSE;
}
@@ -378,9 +366,8 @@ bool findnextstr(
}
#endif
- /* We've reached the start or end of the buffer, so wrap
- * around. */
if (fileptr == NULL) {
+ /* We've reached the start or end of the buffer, so wrap around. */
#ifndef NANO_TINY
if (ISSET(BACKWARDS_SEARCH)) {
fileptr = openfile->filebot;
@@ -395,8 +382,8 @@ bool findnextstr(
statusbar(_("Search Wrapped"));
}
- /* We've reached the original starting line. */
if (fileptr == begin)
+ /* We've reached the original starting line. */
search_last_line = TRUE;
rev_start = fileptr->data;
@@ -456,8 +443,7 @@ void do_search(void)
i = search_init(FALSE, FALSE);
if (i == -1)
- /* Cancel, Go to Line, blank search string, or regcomp()
- * failed. */
+ /* Cancel, Go to Line, blank search string, or regcomp() failed. */
search_replace_abort();
else if (i == -2)
/* Replace. */
@@ -477,7 +463,7 @@ void do_search(void)
else
last_search = mallocstrcpy(last_search, answer);
-#ifndef NANO_TINY
+#ifndef DISABLE_HISTORIES
/* If answer is not "", add this search string to the search history
* list. */
if (answer[0] != '\0')
@@ -525,7 +511,7 @@ void do_search(void)
search_replace_abort();
}
-#ifndef NANO_TINY
+#if !defined(NANO_TINY) || !defined(DISABLE_BROWSER)
/* Search for the last string without prompting. */
void do_research(void)
{
@@ -573,20 +559,20 @@ void do_research(void)
openfile->current_x && !didfind)
statusbar(_("This is the only occurrence"));
} else {
-#endif
+#endif /* HAVE_REGEX_H */
statusbar(_("This is the only occurrence"));
#ifdef HAVE_REGEX_H
}
#endif
}
} else
- statusbar(_("No current search pattern"));
+ statusbar(_("No current search pattern"));
openfile->placewewant = xplustabs();
edit_redraw(fileptr, pww_save);
search_replace_abort();
}
-#endif
+#endif /* !NANO_TINY */
#ifdef HAVE_REGEX_H
int replace_regexp(char *string, bool create)
@@ -636,7 +622,7 @@ int replace_regexp(char *string, bool create)
return new_line_size;
}
-#endif
+#endif /* HAVE_REGEX_H */
char *replace_line(const char *needle)
{
@@ -719,12 +705,12 @@ ssize_t do_replace_loop(
filepart = partition_filestruct(top, top_x, bot, bot_x);
openfile->edittop = openfile->fileage;
openfile->mark_set = FALSE;
-#ifdef ENABLE_COLOR
+#ifndef DISABLE_COLOR
reset_multis(openfile->current, TRUE);
#endif
edit_refresh();
}
-#endif
+#endif /* !NANO_TINY */
if (canceled != NULL)
*canceled = FALSE;
@@ -751,12 +737,10 @@ ssize_t do_replace_loop(
* beginning line already, and we're still on the beginning line
* after the search, it means that we've wrapped around, so
* we're done. */
- if (bol_or_eol && begin_line && openfile->current ==
- real_current)
+ if (bol_or_eol && begin_line && openfile->current == real_current)
break;
/* Otherwise, set the begin_line flag if we've found a match on
- * the beginning line, reset the bol_or_eol flag, and
- * continue. */
+ * the beginning line, reset the bol_or_eol flag, and continue. */
else {
if (openfile->current == real_current)
begin_line = TRUE;
@@ -781,6 +765,7 @@ ssize_t do_replace_loop(
do_replace_highlight(TRUE, exp_word);
+ /* TRANSLATORS: This is a prompt. */
i = do_yesno_prompt(TRUE, _("Replace this instance?"));
do_replace_highlight(FALSE, exp_word);
@@ -860,18 +845,18 @@ ssize_t do_replace_loop(
#endif
openfile->current_x += match_len + length_change - 1;
- /* Cleanup. */
+ /* Clean up. */
openfile->totsize += mbstrlen(copy) -
mbstrlen(openfile->current->data);
free(openfile->current->data);
openfile->current->data = copy;
-#ifdef ENABLE_COLOR
+#ifndef DISABLE_COLOR
reset_multis(openfile->current, TRUE);
#endif
edit_refresh();
if (!replaceall) {
-#ifdef ENABLE_COLOR
+#ifndef DISABLE_COLOR
/* If color syntaxes are available and turned on, we
* need to call edit_refresh(). */
if (openfile->colorstrings != NULL &&
@@ -912,7 +897,6 @@ void do_replace(void)
{
filestruct *edittop_save, *begin;
size_t begin_x, pww_save;
- bool meta_key = FALSE, func_key = FALSE;
ssize_t numreplaced;
int i;
@@ -924,8 +908,7 @@ void do_replace(void)
i = search_init(TRUE, FALSE);
if (i == -1) {
- /* Cancel, Go to Line, blank search string, or regcomp()
- * failed. */
+ /* Cancel, Go to Line, blank search string, or regcomp() failed. */
search_replace_abort();
return;
} else if (i == -2) {
@@ -942,7 +925,7 @@ void do_replace(void)
/* If answer is not "", add answer to the search history list and
* copy answer into last_search. */
if (answer[0] != '\0') {
-#ifndef NANO_TINY
+#ifndef DISABLE_HISTORIES
update_history(&search_history, answer);
#endif
last_search = mallocstrcpy(last_search, answer);
@@ -954,16 +937,15 @@ void do_replace(void)
#ifndef DISABLE_TABCOMP
TRUE,
#endif
- MREPLACE2, last_replace,
- &meta_key, &func_key,
-#ifndef NANO_TINY
+ MREPLACEWITH, last_replace,
+#ifndef DISABLE_HISTORIES
&replace_history,
#endif
+ /* TRANSLATORS: This is a prompt. */
edit_refresh, _("Replace with"));
-#ifndef NANO_TINY
- /* Add this replace string to the replace history list. i == 0
- * means that the string is not "". */
+#ifndef DISABLE_HISTORIES
+ /* If the replace string is not "", add it to the replace history list. */
if (i == 0)
update_history(&replace_history, answer);
#endif
@@ -1008,6 +990,19 @@ void do_replace(void)
search_replace_abort();
}
+/* Go to the specified line and x position. */
+void goto_line_posx(ssize_t line, size_t pos_x)
+{
+ for (openfile->current = openfile->fileage; openfile->current != openfile->filebot &&
+ openfile->current->next != NULL && line > 1; line--)
+ openfile->current = openfile->current->next;
+
+ openfile->current_x = pos_x;
+ openfile->placewewant = xplustabs();
+
+ edit_refresh_needed = TRUE;
+}
+
/* Go to the specified line and column, or ask for them if interactive
* is TRUE. Save the x-coordinate and y-coordinate if save_pos is TRUE.
* Update the screen afterwards if allow_update is TRUE. Note that both
@@ -1015,11 +1010,9 @@ void do_replace(void)
void do_gotolinecolumn(ssize_t line, ssize_t column, bool use_answer,
bool interactive, bool save_pos, bool allow_update)
{
- bool meta_key = FALSE, func_key = FALSE;
- const sc *s;
-
if (interactive) {
char *ans = mallocstrcpy(NULL, answer);
+ functionptrtype func;
/* Ask for the line and column. */
int i = do_prompt(FALSE,
@@ -1027,10 +1020,10 @@ void do_gotolinecolumn(ssize_t line, ssize_t column, bool use_answer,
TRUE,
#endif
MGOTOLINE, use_answer ? ans : "",
- &meta_key, &func_key,
-#ifndef NANO_TINY
+#ifndef DISABLE_HISTORIES
NULL,
#endif
+ /* TRANSLATORS: This is a prompt. */
edit_refresh, _("Enter line number, column number"));
free(ans);
@@ -1042,9 +1035,9 @@ void do_gotolinecolumn(ssize_t line, ssize_t column, bool use_answer,
return;
}
+ func = func_from_key(&i);
- s = get_shortcut(currmenu, &i, &meta_key, &func_key);
- if (s && s->scfunc == GOTOTEXT_MSG) {
+ if (func == gototext_void) {
/* Keep answer up on the statusbar. */
search_init(TRUE, TRUE);
@@ -1083,10 +1076,10 @@ void do_gotolinecolumn(ssize_t line, ssize_t column, bool use_answer,
edit_update(save_pos ? NONE : CENTER);
/* If allow_update is TRUE, update the screen. */
- if (allow_update)
+ if (allow_update) {
edit_refresh();
-
- display_main_list();
+ display_main_list();
+ }
}
/* Go to the specified line and column, asking for them beforehand. */
@@ -1143,8 +1136,8 @@ bool find_bracket_match(bool reverse, const char *bracket_set)
mbrevstrpbrk(fileptr->data, bracket_set, rev_start) :
mbstrpbrk(rev_start, bracket_set));
- /* We've found a potential match. */
if (found != NULL)
+ /* We've found a potential match. */
break;
if (reverse) {
@@ -1155,8 +1148,8 @@ bool find_bracket_match(bool reverse, const char *bracket_set)
current_y_find++;
}
- /* We've reached the start or end of the buffer, so get out. */
if (fileptr == NULL)
+ /* We've reached the start or end of the buffer, so get out. */
return FALSE;
rev_start = fileptr->data;
@@ -1290,14 +1283,14 @@ void do_find_bracket(void)
free(bracket_set);
free(found_ch);
}
+#endif /* !NANO_TINY */
-#ifdef ENABLE_NANORC
+#ifndef DISABLE_HISTORIES
/* Indicate whether any of the history lists have changed. */
bool history_has_changed(void)
{
return history_changed;
}
-#endif
/* Initialize the search and replace history lists. */
void history_init(void)
@@ -1372,8 +1365,7 @@ void update_history(filestruct **h, const char *s)
bar = p->next;
unlink_node(foo);
delete_node(foo);
- if (bar != NULL)
- renumber(bar);
+ renumber(bar);
}
/* If the history is full, delete the beginning entry to make room
@@ -1394,10 +1386,8 @@ void update_history(filestruct **h, const char *s)
*hbot = (*hbot)->next;
(*hbot)->data = mallocstrcpy(NULL, "");
-#ifdef ENABLE_NANORC
/* Indicate that the history's been changed. */
history_changed = TRUE;
-#endif
/* Set the current position in the list to the bottom. */
*h = *hbot;
@@ -1431,6 +1421,16 @@ char *get_history_newer(filestruct **h)
return (*h)->data;
}
+/* More placeholders. */
+void get_history_newer_void(void)
+{
+ ;
+}
+void get_history_older_void(void)
+{
+ ;
+}
+
#ifndef DISABLE_TABCOMP
/* Move h to the next string that's a tab completion of the string s,
* looking at only the first len characters of s, and return that
@@ -1486,4 +1486,4 @@ char *get_history_completion(filestruct **h, const char *s, size_t len)
return (char *)s;
}
#endif /* !DISABLE_TABCOMP */
-#endif /* !NANO_TINY */
+#endif /* !DISABLE_HISTORIES */
diff --git a/src/text.c b/src/text.c
index 54da3f0..dd72308 100644
--- a/src/text.c
+++ b/src/text.c
@@ -1,9 +1,9 @@
-/* $Id: text.c 4520 2010-11-12 06:23:14Z astyanax $ */
+/* $Id: text.c 5145 2015-03-21 21:13:03Z bens $ */
/**************************************************************************
* text.c *
* *
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
- * 2008, 2009 Free Software Foundation, Inc. *
+ * 2008, 2009, 2010, 2011, 2013, 2014 Free Software Foundation, Inc. *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 3, or (at your option) *
@@ -64,12 +64,10 @@ void do_mark(void)
#endif /* !NANO_TINY */
/* Delete the character under the cursor. */
-void do_delete(void)
+void do_deletion(undo_type action)
{
- size_t orig_lenpt = 0;
-
#ifndef NANO_TINY
- update_undo(DEL);
+ size_t orig_lenpt = 0;
#endif
assert(openfile->current != NULL && openfile->current->data != NULL && openfile->current_x <= strlen(openfile->current->data));
@@ -84,8 +82,12 @@ void do_delete(void)
assert(openfile->current_x < strlen(openfile->current->data));
+#ifndef NANO_TINY
+ update_undo(action);
+
if (ISSET(SOFTWRAP))
orig_lenpt = strlenpt(openfile->current->data);
+#endif
/* Let's get dangerous. */
charmove(&openfile->current->data[openfile->current_x],
@@ -106,15 +108,17 @@ void do_delete(void)
assert(openfile->current_x == strlen(openfile->current->data));
+#ifndef NANO_TINY
+ add_undo(action);
+#endif
/* If we're deleting at the end of a line, we need to call
* edit_refresh(). */
if (openfile->current->data[openfile->current_x] == '\0')
edit_refresh_needed = TRUE;
openfile->current->data = charealloc(openfile->current->data,
- openfile->current_x + strlen(foo->data) + 1);
- strcpy(openfile->current->data + openfile->current_x,
- foo->data);
+ strlen(openfile->current->data) + strlen(foo->data) + 1);
+ strcat(openfile->current->data, foo->data);
#ifndef NANO_TINY
if (openfile->mark_set && openfile->mark_begin ==
openfile->current->next) {
@@ -139,16 +143,23 @@ void do_delete(void)
} else
return;
+#ifndef NANO_TINY
if (ISSET(SOFTWRAP) && edit_refresh_needed == FALSE)
if (strlenpt(openfile->current->data) / COLS != orig_lenpt / COLS)
- edit_refresh_needed = TRUE;
+ edit_refresh_needed = TRUE;
+#endif
set_modified();
- if (edit_refresh_needed == FALSE)
+ if (edit_refresh_needed == FALSE)
update_line(openfile->current, openfile->current_x);
}
+void do_delete(void)
+{
+ do_deletion(DEL);
+}
+
/* Backspace over one character. That is, move the cursor left one
* character, and then delete the character under the cursor. */
void do_backspace(void)
@@ -156,7 +167,7 @@ void do_backspace(void)
if (openfile->current != openfile->fileage ||
openfile->current_x > 0) {
do_left();
- do_delete();
+ do_deletion(BACK);
}
}
@@ -216,8 +227,7 @@ void do_indent(ssize_t cols)
if (cols == 0)
return;
- /* If cols is negative, make it positive and set unindent to
- * TRUE. */
+ /* If cols is negative, make it positive and set unindent to TRUE. */
if (cols < 0) {
cols = -cols;
unindent = TRUE;
@@ -360,99 +370,79 @@ void do_unindent(void)
do_indent(-tabsize);
}
-/* undo a cut, or re-do an uncut */
+#define redo_paste undo_cut
+#define undo_paste redo_cut
+
+/* Undo a cut, or redo an uncut. */
void undo_cut(undo *u)
{
- /* If we cut the magicline may was well not crash :/ */
+ /* If we cut the magicline, we may as well not crash. :/ */
if (!u->cutbuffer)
return;
- cutbuffer = copy_filestruct(u->cutbuffer);
-
- /* Compute cutbottom for the uncut using out copy */
- for (cutbottom = cutbuffer; cutbottom->next != NULL; cutbottom = cutbottom->next)
- ;
-
- /* Get to where we need to uncut from */
- if (u->mark_set && u->mark_begin_lineno < u->lineno)
- do_gotolinecolumn(u->mark_begin_lineno, u->mark_begin_x+1, FALSE, FALSE, FALSE, FALSE);
+ /* Get to where we need to uncut from. */
+ if (u->xflags == UNcut_cutline)
+ goto_line_posx(u->mark_begin_lineno, 0);
else
- do_gotolinecolumn(u->lineno, u->begin+1, FALSE, FALSE, FALSE, FALSE);
+ goto_line_posx(u->mark_begin_lineno, u->mark_begin_x);
- copy_from_filestruct(cutbuffer, cutbottom);
- free_filestruct(cutbuffer);
- cutbuffer = NULL;
+ copy_from_filestruct(u->cutbuffer);
+ if (u->xflags != UNcut_marked_forward && u->type != PASTE)
+ goto_line_posx(u->mark_begin_lineno, u->mark_begin_x);
}
-/* Re-do a cut, or undo an uncut */
-void redo_cut(undo *u) {
- int i;
- filestruct *t, *c;
-
- /* If we cut the magicline may was well not crash :/ */
+/* Redo a cut, or undo an uncut. */
+void redo_cut(undo *u)
+{
+ /* If we cut the magicline, we may as well not crash. :/ */
if (!u->cutbuffer)
return;
- do_gotolinecolumn(u->lineno, u->begin+1, FALSE, FALSE, FALSE, FALSE);
- openfile->mark_set = u->mark_set;
- if (cutbuffer)
- free(cutbuffer);
+ filestruct *oldcutbuffer = cutbuffer, *oldcutbottom = cutbottom;
cutbuffer = NULL;
+ cutbottom = NULL;
- /* Move ahead the same # lines we had if a marked cut */
- if (u->mark_set) {
- for (i = 1, t = openfile->fileage; i != u->mark_begin_lineno; i++)
- t = t->next;
- openfile->mark_begin = t;
- } else if (!u->to_end) {
- /* Here we have a regular old potentially multi-line ^K cut. We'll
- need to trick nano into thinking it's a marked cut to cut more
- than one line again */
- for (c = u->cutbuffer, t = openfile->current; c->next != NULL && t->next != NULL; ) {
+ goto_line_posx(u->lineno, u->begin);
-#ifdef DEBUG
- fprintf(stderr, "Advancing, lineno = %lu, data = \"%s\"\n", (unsigned long) t->lineno, t->data);
-#endif
- c = c->next;
- t = t->next;
- }
- openfile->mark_begin = t;
- openfile->mark_begin_x = 0;
- openfile->mark_set = TRUE;
+ if (ISSET(NO_NEWLINES) && openfile->current->lineno != u->lineno) {
+ openfile->current_x = strlen(openfile->current->data);
+ openfile->placewewant = xplustabs();
}
- openfile->mark_begin_x = u->mark_begin_x;
- do_cut_text(FALSE, u->to_end, TRUE);
+ openfile->mark_set = TRUE;
+ openfile->mark_begin = fsfromline(u->mark_begin_lineno);
+ openfile->mark_begin_x = (u->xflags == UNcut_cutline) ? 0 : u->mark_begin_x;
+
+ do_cut_text(FALSE, FALSE, TRUE);
+
openfile->mark_set = FALSE;
openfile->mark_begin = NULL;
openfile->mark_begin_x = 0;
edit_refresh_needed = TRUE;
+
+ if (cutbuffer != NULL)
+ free_filestruct(cutbuffer);
+ cutbuffer = oldcutbuffer;
+ cutbottom = oldcutbottom;
}
-/* Undo the last thing(s) we did */
+/* Undo the last thing(s) we did. */
void do_undo(void)
{
undo *u = openfile->current_undo;
- filestruct *f = openfile->current, *t;
- int len = 0;
- char *undidmsg, *data;
- filestruct *oldcutbuffer = cutbuffer, *oldcutbottom = cutbottom;
+ filestruct *t = 0;
+ size_t len = 0;
+ char *data, *undidmsg = NULL;
if (!u) {
statusbar(_("Nothing in undo buffer!"));
return;
}
-
- if (u->lineno <= f->lineno)
- for (; f->prev != NULL && f->lineno != u->lineno; f = f->prev)
- ;
- else
- for (; f->next != NULL && f->lineno != u->lineno; f = f->next)
- ;
- if (f->lineno != u->lineno) {
- statusbar(_("Internal error: can't match line %d. Please save your work"), u->lineno);
+ filestruct *f = fsfromline(u->mark_begin_lineno);
+ if (!f) {
+ statusbar(_("Internal error: can't match line %d. Please save your work."), u->mark_begin_lineno);
return;
}
#ifdef DEBUG
@@ -461,85 +451,94 @@ void do_undo(void)
#endif
openfile->current_x = u->begin;
- switch(u->type) {
+ switch (u->type) {
case ADD:
undidmsg = _("text add");
len = strlen(f->data) - strlen(u->strdata) + 1;
- data = charalloc(len);
- strncpy(data, f->data, u->begin);
+ data = charalloc(len);
+ strncpy(data, f->data, u->begin);
strcpy(&data[u->begin], &f->data[u->begin + strlen(u->strdata)]);
free(f->data);
f->data = data;
+ goto_line_posx(u->lineno, u->begin);
break;
+ case BACK:
case DEL:
undidmsg = _("text delete");
len = strlen(f->data) + strlen(u->strdata) + 1;
data = charalloc(len);
-
strncpy(data, f->data, u->begin);
strcpy(&data[u->begin], u->strdata);
strcpy(&data[u->begin + strlen(u->strdata)], &f->data[u->begin]);
free(f->data);
f->data = data;
- if (u->xflags == UNDO_DEL_BACKSPACE)
- openfile->current_x += strlen(u->strdata);
+ goto_line_posx(u->mark_begin_lineno, u->mark_begin_x);
break;
#ifndef DISABLE_WRAPPING
- case SPLIT:
- undidmsg = _("line wrap");
- f->data = (char *) nrealloc(f->data, strlen(f->data) + strlen(u->strdata) + 1);
- strcpy(&f->data[strlen(f->data) - 1], u->strdata);
- if (u->strdata2 != NULL)
- f->next->data = mallocstrcpy(f->next->data, u->strdata2);
- else {
- filestruct *foo = openfile->current->next;
- unlink_node(foo);
- delete_node(foo);
- }
- renumber(f);
+ case SPLIT_END:
+ goto_line_posx(u->lineno, u->begin);
+ openfile->current_undo = openfile->current_undo->next;
+ openfile->last_action = OTHER;
+ while (openfile->current_undo->type != SPLIT_BEGIN)
+ do_undo();
+ u = openfile->current_undo;
+ f = openfile->current;
+ case SPLIT_BEGIN:
+ undidmsg = _("text add");
break;
-#endif /* DISABLE_WRAPPING */
- case UNSPLIT:
+#endif /* !DISABLE_WRAPPING */
+ case JOIN:
undidmsg = _("line join");
t = make_new_node(f);
t->data = mallocstrcpy(NULL, u->strdata);
- data = mallocstrncpy(NULL, f->data, u->begin);
- data[u->begin] = '\0';
+ data = mallocstrncpy(NULL, f->data, u->mark_begin_x + 1);
+ data[u->mark_begin_x] = '\0';
free(f->data);
f->data = data;
splice_node(f, t, f->next);
- renumber(f);
+ if (f == openfile->filebot)
+ openfile->filebot = t;
+ goto_line_posx(u->lineno, u->begin);
break;
+ case CUT_EOF:
case CUT:
undidmsg = _("text cut");
- undo_cut(u);
+ undo_cut(u);
+ f = fsfromline(u->lineno);
break;
- case UNCUT:
+ case PASTE:
undidmsg = _("text uncut");
- redo_cut(u);
+ undo_paste(u);
+ f = fsfromline(u->lineno);
break;
case ENTER:
undidmsg = _("line break");
if (f->next) {
filestruct *foo = f->next;
- f->data = (char *) nrealloc(f->data, strlen(f->data) + strlen(f->next->data) + 1);
- strcat(f->data, f->next->data);
+ f->data = charealloc(f->data, strlen(f->data) + strlen(&f->next->data[u->mark_begin_x]) + 1);
+ strcat(f->data, &f->next->data[u->mark_begin_x]);
+ if (foo == openfile->filebot)
+ openfile->filebot = f;
unlink_node(foo);
delete_node(foo);
}
+ goto_line_posx(u->lineno, u->begin);
break;
case INSERT:
undidmsg = _("text insert");
+ filestruct *oldcutbuffer = cutbuffer, *oldcutbottom = cutbottom;
cutbuffer = NULL;
cutbottom = NULL;
- /* When we updated mark_begin_lineno in update_undo, it was effectively how many line
- were inserted due to being partitioned before read_file was called. So we
- add its value here */
+ /* When we updated mark_begin_lineno in update_undo, it was effectively
+ * how many lines were inserted due to being partitioned before read_file
+ * was called. So we add its value here. */
openfile->mark_begin = fsfromline(u->lineno + u->mark_begin_lineno - 1);
openfile->mark_begin_x = 0;
openfile->mark_set = TRUE;
- do_gotolinecolumn(u->lineno, u->begin+1, FALSE, FALSE, FALSE, FALSE);
+ goto_line_posx(u->lineno, u->begin);
cut_marked();
+ if (u->cutbuffer != NULL)
+ free_filestruct(u->cutbuffer);
u->cutbuffer = cutbuffer;
u->cutbottom = cutbottom;
cutbuffer = oldcutbuffer;
@@ -548,29 +547,32 @@ void do_undo(void)
break;
case REPLACE:
undidmsg = _("text replace");
+ goto_line_posx(u->lineno, u->begin);
data = u->strdata;
u->strdata = f->data;
f->data = data;
break;
-
default:
- undidmsg = _("Internal error: unknown type. Please save your work");
+ undidmsg = _("Internal error: unknown type. Please save your work.");
break;
-
}
+
+ if (undidmsg)
+ statusbar(_("Undid action (%s)"), undidmsg);
+
renumber(f);
- do_gotolinecolumn(u->lineno, u->begin, FALSE, FALSE, FALSE, TRUE);
- statusbar(_("Undid action (%s)"), undidmsg);
openfile->current_undo = openfile->current_undo->next;
openfile->last_action = OTHER;
+ openfile->placewewant = xplustabs();
+ set_modified();
}
+/* Redo the last thing(s) we undid. */
void do_redo(void)
{
undo *u = openfile->undotop;
- filestruct *f = openfile->current;
- int len = 0;
- char *undidmsg, *data;
+ size_t len = 0;
+ char *data, *redidmsg = NULL;
for (; u != NULL && u->next != openfile->current_undo; u = u->next)
;
@@ -579,18 +581,13 @@ void do_redo(void)
return;
}
if (u->next != openfile->current_undo) {
- statusbar(_("Internal error: Redo setup failed. Please save your work"));
+ statusbar(_("Internal error: cannot set up redo. Please save your work."));
return;
}
- if (u->lineno <= f->lineno)
- for (; f->prev != NULL && f->lineno != u->lineno; f = f->prev)
- ;
- else
- for (; f->next != NULL && f->lineno != u->lineno; f = f->next)
- ;
- if (f->lineno != u->lineno) {
- statusbar(_("Internal error: can't match line %d. Please save your work"), u->lineno);
+ filestruct *f = fsfromline(u->mark_begin_lineno);
+ if (!f) {
+ statusbar(_("Internal error: can't match line %d. Please save your work."), u->mark_begin_lineno);
return;
}
#ifdef DEBUG
@@ -598,86 +595,98 @@ void do_redo(void)
fprintf(stderr, "Redo running for type %d\n", u->type);
#endif
- switch(u->type) {
+ switch (u->type) {
case ADD:
- undidmsg = _("text add");
+ redidmsg = _("text add");
len = strlen(f->data) + strlen(u->strdata) + 1;
- data = charalloc(len);
+ data = charalloc(len);
strncpy(data, f->data, u->begin);
strcpy(&data[u->begin], u->strdata);
strcpy(&data[u->begin + strlen(u->strdata)], &f->data[u->begin]);
free(f->data);
f->data = data;
+ goto_line_posx(u->mark_begin_lineno, u->mark_begin_x);
break;
+ case BACK:
case DEL:
- undidmsg = _("text delete");
+ redidmsg = _("text delete");
len = strlen(f->data) + strlen(u->strdata) + 1;
data = charalloc(len);
- strncpy(data, f->data, u->begin);
+ strncpy(data, f->data, u->begin);
strcpy(&data[u->begin], &f->data[u->begin + strlen(u->strdata)]);
free(f->data);
f->data = data;
+ openfile->current_x = u->begin;
+ goto_line_posx(u->lineno, u->begin);
break;
case ENTER:
- undidmsg = _("line break");
- do_gotolinecolumn(u->lineno, u->begin+1, FALSE, FALSE, FALSE, FALSE);
+ redidmsg = _("line break");
+ goto_line_posx(u->lineno, u->begin);
do_enter(TRUE);
break;
#ifndef DISABLE_WRAPPING
- case SPLIT:
- undidmsg = _("line wrap");
- if (u->xflags & UNDO_SPLIT_MADENEW)
- prepend_wrap = TRUE;
- do_wrap(f, TRUE);
- renumber(f);
+ case SPLIT_BEGIN:
+ goto_line_posx(u->lineno, u->begin);
+ openfile->current_undo = u;
+ openfile->last_action = OTHER;
+ while (openfile->current_undo->type != SPLIT_END)
+ do_redo();
+ u = openfile->current_undo;
+ goto_line_posx(u->lineno, u->begin);
+ case SPLIT_END:
+ redidmsg = _("text add");
break;
-#endif /* DISABLE_WRAPPING */
- case UNSPLIT:
- undidmsg = _("line join");
- len = strlen(f->data) + strlen(u->strdata + 1);
- data = charalloc(len);
- strcpy(data, f->data);
- strcat(data, u->strdata);
- free(f->data);
- f->data = data;
+#endif /* !DISABLE_WRAPPING */
+ case JOIN:
+ redidmsg = _("line join");
+ len = strlen(f->data) + strlen(u->strdata) + 1;
+ f->data = charealloc(f->data, len);
+ strcat(f->data, u->strdata);
if (f->next != NULL) {
filestruct *tmp = f->next;
+ if (tmp == openfile->filebot)
+ openfile->filebot = f;
unlink_node(tmp);
delete_node(tmp);
}
renumber(f);
+ goto_line_posx(u->mark_begin_lineno, u->mark_begin_x);
break;
+ case CUT_EOF:
case CUT:
- undidmsg = _("text cut");
+ redidmsg = _("text cut");
redo_cut(u);
break;
- case UNCUT:
- undidmsg = _("text uncut");
- undo_cut(u);
+ case PASTE:
+ redidmsg = _("text uncut");
+ redo_paste(u);
break;
case REPLACE:
- undidmsg = _("text replace");
+ redidmsg = _("text replace");
data = u->strdata;
u->strdata = f->data;
f->data = data;
+ goto_line_posx(u->lineno, u->begin);
break;
case INSERT:
- undidmsg = _("text insert");
- do_gotolinecolumn(u->lineno, u->begin+1, FALSE, FALSE, FALSE, FALSE);
- copy_from_filestruct(u->cutbuffer, u->cutbottom);
- openfile->placewewant = xplustabs();
+ redidmsg = _("text insert");
+ goto_line_posx(u->lineno, u->begin);
+ copy_from_filestruct(u->cutbuffer);
+ free_filestruct(u->cutbuffer);
+ u->cutbuffer = NULL;
break;
default:
- undidmsg = _("Internal error: unknown type. Please save your work");
+ redidmsg = _("Internal error: unknown type. Please save your work.");
break;
-
}
- do_gotolinecolumn(u->lineno, u->begin, FALSE, FALSE, FALSE, TRUE);
- statusbar(_("Redid action (%s)"), undidmsg);
+
+ if (redidmsg)
+ statusbar(_("Redid action (%s)"), redidmsg);
openfile->current_undo = u;
openfile->last_action = OTHER;
-
+ openfile->placewewant = xplustabs();
+ set_modified();
}
#endif /* !NANO_TINY */
@@ -693,7 +702,6 @@ void do_enter(bool undoing)
if (!undoing)
add_undo(ENTER);
-
/* Do auto-indenting, like the neolithic Turbo Pascal editor. */
if (ISSET(AUTOINDENT)) {
/* If we are breaking the line in the indentation, the new
@@ -711,7 +719,7 @@ void do_enter(bool undoing)
#ifndef NANO_TINY
if (ISSET(AUTOINDENT)) {
strncpy(newnode->data, openfile->current->data, extra);
- openfile->totsize += mbstrlen(newnode->data);
+ openfile->totsize += extra;
}
#endif
null_at(&openfile->current->data, openfile->current_x);
@@ -738,9 +746,20 @@ void do_enter(bool undoing)
openfile->placewewant = xplustabs();
+#ifndef NANO_TINY
+ if (!undoing)
+ update_undo(ENTER);
+#endif
+
edit_refresh_needed = TRUE;
}
+/* Need this again... */
+void do_enter_void(void)
+{
+ do_enter(FALSE);
+}
+
#ifndef NANO_TINY
/* Send a SIGKILL (unconditional kill) to the forked process in
* execute_command(). */
@@ -763,13 +782,12 @@ bool execute_command(const char *command)
/* Make our pipes. */
if (pipe(fd) == -1) {
- statusbar(_("Could not pipe"));
+ statusbar(_("Could not create pipe"));
return FALSE;
}
- /* Check $SHELL for the shell to use. If it isn't set, use
- * /bin/sh. Note that $SHELL should contain only a path, with no
- * arguments. */
+ /* Check $SHELL for the shell to use. If it isn't set, use /bin/sh.
+ * Note that $SHELL should contain only a path, with no arguments. */
shellenv = getenv("SHELL");
if (shellenv == NULL)
shellenv = (char *) "/bin/sh";
@@ -835,26 +853,23 @@ bool execute_command(const char *command)
return TRUE;
}
-/* Add a new undo struct to the top of the current pile */
+/* Add a new undo struct to the top of the current pile. */
void add_undo(undo_type current_action)
{
undo *u;
char *data;
openfilestruct *fs = openfile;
- static undo *last_cutu = NULL; /* Last thing we cut to set up the undo for uncut */
- ssize_t wrap_loc; /* For calculating split beginning */
-
- if (!ISSET(UNDOABLE))
- return;
+ /* Last thing we cut to set up the undo for uncut. */
- /* Ugh, if we were called while cutting not-to-end, non-marked and on the same lineno,
- we need to abort here */
+ /* Ugh, if we were called while cutting not-to-end, non-marked, and
+ * on the same lineno, we need to abort here. */
u = fs->current_undo;
- if (current_action == CUT && u && u->type == CUT
- && !u->mark_set && u->lineno == fs->current->lineno)
+ if (u && u->mark_begin_lineno == fs->current->lineno &&
+ ((current_action == CUT && u->type == CUT && !u->mark_set && keeping_cutbuffer()) ||
+ (current_action == ADD && u->type == ADD && u->mark_begin_x == fs->current_x)))
return;
- /* Blow away the old undo stack if we are starting from the middle */
+ /* Blow away the old undo stack if we are starting from the middle. */
while (fs->undotop != NULL && fs->undotop != fs->current_undo) {
undo *u2 = fs->undotop;
fs->undotop = fs->undotop->next;
@@ -865,83 +880,101 @@ void add_undo(undo_type current_action)
free(u2);
}
- /* Allocate and initialize a new undo type */
+ /* Allocate and initialize a new undo type. */
u = (undo *) nmalloc(sizeof(undo));
u->type = current_action;
u->lineno = fs->current->lineno;
u->begin = fs->current_x;
- u->next = fs->undotop;
- fs->undotop = u;
- fs->current_undo = u;
+#ifndef DISABLE_WRAPPING
+ if (u->type == SPLIT_BEGIN) {
+ /* Some action, most likely an ADD, was performed that invoked
+ * do_wrap(). Rearrange the undo order so that this previous
+ * action is after the SPLIT_BEGIN undo. */
+ u->next = fs->undotop->next ;
+ fs->undotop->next = u;
+ } else
+#endif
+ {
+ u->next = fs->undotop;
+ fs->undotop = u;
+ fs->current_undo = u;
+ }
u->strdata = NULL;
- u->strdata2 = NULL;
u->cutbuffer = NULL;
- u->cutbottom = NULL;
- u->mark_set = 0;
- u->mark_begin_lineno = 0;
- u->mark_begin_x = 0;
+ u->cutbottom = NULL;
+ u->mark_set = FALSE;
+ u->mark_begin_lineno = fs->current->lineno;
+ u->mark_begin_x = fs->current_x;
u->xflags = 0;
- u->to_end = FALSE;
switch (u->type) {
- /* We need to start copying data into the undo buffer or we wont be able
- to restore it later */
+ /* We need to start copying data into the undo buffer
+ * or we won't be able to restore it later. */
case ADD:
- data = charalloc(2);
- data[0] = fs->current->data[fs->current_x];
- data[1] = '\0';
- u->strdata = data;
break;
+ case BACK:
case DEL:
if (u->begin != strlen(fs->current->data)) {
- data = mallocstrncpy(NULL, &fs->current->data[u->begin], 2);
- data[1] = '\0';
- u->strdata = data;
+ char *char_buf = charalloc(mb_cur_max() + 1);
+ int char_buf_len = parse_mbchar(&fs->current->data[u->begin], char_buf, NULL);
+ null_at(&char_buf, char_buf_len);
+ u->strdata = char_buf;
+ if (u->type == BACK)
+ u->mark_begin_x += char_buf_len;
break;
}
- /* Else purposely fall into unsplit code */
- current_action = u->type = UNSPLIT;
- case UNSPLIT:
+ /* Else purposely fall into the line-joining code. */
+ case JOIN:
if (fs->current->next) {
+ if (u->type == BACK) {
+ u->lineno = fs->current->next->lineno;
+ u->begin = 0;
+ }
data = mallocstrcpy(NULL, fs->current->next->data);
u->strdata = data;
}
+ current_action = u->type = JOIN;
break;
#ifndef DISABLE_WRAPPING
- case SPLIT:
- wrap_loc = break_line(openfile->current->data, fill
-#ifndef DISABLE_HELP
- , FALSE
-#endif
- );
- u->strdata = mallocstrcpy(NULL, &openfile->current->data[wrap_loc]);
- /* Don't both saving the next line if we're not prepending as a new line
- will be created */
- if (prepend_wrap)
- u->strdata2 = mallocstrcpy(NULL, fs->current->next->data);
- u->begin = wrap_loc;
+ case SPLIT_BEGIN:
+ current_action = fs->undotop->type;
+ break;
+ case SPLIT_END:
break;
-#endif /* DISABLE_WRAPPING */
+#endif /* !DISABLE_WRAPPING */
case INSERT:
+ break;
case REPLACE:
data = mallocstrcpy(NULL, fs->current->data);
u->strdata = data;
break;
+ case CUT_EOF:
+ cutbuffer_reset();
+ break;
case CUT:
+ cutbuffer_reset();
u->mark_set = openfile->mark_set;
if (u->mark_set) {
u->mark_begin_lineno = openfile->mark_begin->lineno;
u->mark_begin_x = openfile->mark_begin_x;
}
- u->to_end = (ISSET(CUT_TO_END)) ? TRUE : FALSE;
- last_cutu = u;
+ else if (!ISSET(CUT_TO_END)) {
+ /* The entire line is being cut regardless of the cursor position. */
+ u->begin = 0;
+ u->xflags = UNcut_cutline;
+ }
break;
- case UNCUT:
- if (!last_cutu)
- statusbar(_("Internal error: can't setup uncut. Please save your work."));
- else if (last_cutu->type == CUT) {
- u->cutbuffer = last_cutu->cutbuffer;
- u->cutbottom = last_cutu->cutbottom;
+ case PASTE:
+ if (!cutbuffer)
+ statusbar(_("Internal error: cannot set up uncut. Please save your work."));
+ else {
+ if (u->cutbuffer)
+ free_filestruct(u->cutbuffer);
+ u->cutbuffer = copy_filestruct(cutbuffer);
+ u->mark_begin_lineno = fs->current->lineno;
+ u->mark_begin_x = fs->current_x;
+ u->lineno = fs->current->lineno + cutbottom->lineno - cutbuffer->lineno;
+ u->mark_set = TRUE;
}
break;
case ENTER:
@@ -952,43 +985,37 @@ void add_undo(undo_type current_action)
}
#ifdef DEBUG
- fprintf(stderr, "fs->current->data = \"%s\", current_x = %lu, u->begin = %d, type = %d\n",
- fs->current->data, (unsigned long) fs->current_x, u->begin, current_action);
+ fprintf(stderr, "fs->current->data = \"%s\", current_x = %lu, u->begin = %lu, type = %d\n",
+ fs->current->data, (unsigned long)fs->current_x, (unsigned long)u->begin, current_action);
fprintf(stderr, "left add_undo...\n");
#endif
fs->last_action = current_action;
}
-/* Update an undo item, or determine whether a new one
- is really needed and bounce the data to add_undo
- instead. The latter functionality just feels
- gimmicky and may just be more hassle than
- it's worth, so it should be axed if needed. */
+/* Update an undo item, or determine whether a new one is really needed
+ * and bounce the data to add_undo instead. The latter functionality
+ * just feels gimmicky and may just be more hassle than it's worth,
+ * so it should be axed if needed. */
void update_undo(undo_type action)
{
undo *u;
- char *data;
- int len = 0;
openfilestruct *fs = openfile;
- if (!ISSET(UNDOABLE))
- return;
-
#ifdef DEBUG
- fprintf(stderr, "action = %d, fs->last_action = %d, openfile->current->lineno = %lu",
- action, fs->last_action, (unsigned long) openfile->current->lineno);
+fprintf(stderr, "action = %d, fs->last_action = %d, openfile->current->lineno = %ld",
+ action, fs->last_action, (long)openfile->current->lineno);
if (fs->current_undo)
- fprintf(stderr, "fs->current_undo->lineno = %lu\n", (unsigned long) fs->current_undo->lineno);
+ fprintf(stderr, "fs->current_undo->lineno = %ld\n", (long)fs->current_undo->lineno);
else
fprintf(stderr, "\n");
#endif
/* Change to an add if we're not using the same undo struct
- that we should be using */
+ * that we should be using. */
if (action != fs->last_action
- || (action != CUT && action != INSERT && action != SPLIT
+ || (action != ENTER && action != CUT && action != INSERT
&& openfile->current->lineno != fs->current_undo->lineno)) {
- add_undo(action);
+ add_undo(action);
return;
}
@@ -996,103 +1023,103 @@ void update_undo(undo_type action)
u = fs->undotop;
switch (u->type) {
- case ADD:
+ case ADD: {
#ifdef DEBUG
- fprintf(stderr, "fs->current->data = \"%s\", current_x = %lu, u->begin = %d\n",
- fs->current->data, (unsigned long) fs->current_x, u->begin);
-#endif
- len = strlen(u->strdata) + 2;
- data = (char *) nrealloc((void *) u->strdata, len * sizeof(char *));
- data[len-2] = fs->current->data[fs->current_x];
- data[len-1] = '\0';
- u->strdata = (char *) data;
+ fprintf(stderr, "fs->current->data = \"%s\", current_x = %lu, u->begin = %lu\n",
+ fs->current->data, (unsigned long)fs->current_x, (unsigned long)u->begin);
+#endif
+ char *char_buf = charalloc(mb_cur_max());
+ size_t char_buf_len = parse_mbchar(&fs->current->data[u->mark_begin_x], char_buf, NULL);
+ u->strdata = addstrings(u->strdata, u->strdata ? strlen(u->strdata) : 0, char_buf, char_buf_len);
#ifdef DEBUG
fprintf(stderr, "current undo data now \"%s\"\n", u->strdata);
#endif
+ u->mark_begin_lineno = fs->current->lineno;
+ u->mark_begin_x = fs->current_x;
break;
- case DEL:
- len = strlen(u->strdata) + 2;
- assert(len > 2);
- if (fs->current_x == u->begin) {
- /* They're deleting */
- if (!u->xflags)
- u->xflags = UNDO_DEL_DEL;
- else if (u->xflags != UNDO_DEL_DEL) {
- add_undo(action);
- return;
- }
- data = charalloc(len);
- strcpy(data, u->strdata);
- data[len-2] = fs->current->data[fs->current_x];;
- data[len-1] = '\0';
- free(u->strdata);
- u->strdata = data;
- } else if (fs->current_x == u->begin - 1) {
- /* They're backspacing */
- if (!u->xflags)
- u->xflags = UNDO_DEL_BACKSPACE;
- else if (u->xflags != UNDO_DEL_BACKSPACE) {
- add_undo(action);
- return;
- }
- data = charalloc(len);
- data[0] = fs->current->data[fs->current_x];
- strcpy(&data[1], u->strdata);
- free(u->strdata);
- u->strdata = data;
- u->begin--;
+ }
+ case BACK:
+ case DEL: {
+ char *char_buf = charalloc(mb_cur_max());
+ size_t char_buf_len = parse_mbchar(&fs->current->data[fs->current_x], char_buf, NULL);
+ if (fs->current_x == u->begin) {
+ /* They're deleting. */
+ u->strdata = addstrings(u->strdata, strlen(u->strdata), char_buf, char_buf_len);
+ u->mark_begin_x = fs->current_x;
+ } else if (fs->current_x == u->begin - char_buf_len) {
+ /* They're backspacing. */
+ u->strdata = addstrings(char_buf, char_buf_len, u->strdata, strlen(u->strdata));
+ u->begin = fs->current_x;
} else {
- /* They deleted something else on the line */
- add_undo(DEL);
+ /* They deleted something else on the line. */
+ free(char_buf);
+ add_undo(u->type);
return;
}
#ifdef DEBUG
- fprintf(stderr, "current undo data now \"%s\"\nu->begin = %d\n", u->strdata, u->begin);
+ fprintf(stderr, "current undo data now \"%s\"\nu->begin = %lu\n", u->strdata, (unsigned long)u->begin);
#endif
break;
+ }
+ case CUT_EOF:
case CUT:
if (!cutbuffer)
break;
if (u->cutbuffer)
- free(u->cutbuffer);
+ free_filestruct(u->cutbuffer);
u->cutbuffer = copy_filestruct(cutbuffer);
- /* Compute cutbottom for the uncut using out copy */
- for (u->cutbottom = u->cutbuffer; u->cutbottom->next != NULL; u->cutbottom = u->cutbottom->next)
- ;
+ if (u->mark_set) {
+ /* If the "marking" operation was from right-->left or
+ * bottom-->top, then swap the mark points. */
+ if ((u->lineno == u->mark_begin_lineno && u->begin < u->mark_begin_x)
+ || u->lineno < u->mark_begin_lineno) {
+ size_t x_loc = u->begin;
+ u->begin = u->mark_begin_x;
+ u->mark_begin_x = x_loc;
+
+ ssize_t line = u->lineno;
+ u->lineno = u->mark_begin_lineno;
+ u->mark_begin_lineno = line;
+ } else
+ u->xflags = UNcut_marked_forward;
+ } else {
+ /* Compute cutbottom for the uncut using our copy. */
+ u->cutbottom = u->cutbuffer;
+ while (u->cutbottom->next != NULL)
+ u->cutbottom = u->cutbottom->next;
+ u->lineno = u->mark_begin_lineno + u->cutbottom->lineno - u->cutbuffer->lineno;
+ if (ISSET(CUT_TO_END) || u->type == CUT_EOF) {
+ u->begin = strlen(u->cutbottom->data);
+ if(u->lineno == u->mark_begin_lineno)
+ u->begin += u->mark_begin_x;
+ }
+ }
break;
case REPLACE:
- case UNCUT:
- add_undo(action);
+ case PASTE:
+ u->begin = fs->current_x;
+ u->lineno = openfile->current->lineno;
break;
case INSERT:
u->mark_begin_lineno = openfile->current->lineno;
break;
-#ifndef DISABLE_WRAPPING
- case SPLIT:
- /* This will only be called if we made a completely new line,
- and as such we should note that so we can destroy it later */
- u->xflags = UNDO_SPLIT_MADENEW;
- break;
-#endif /* DISABLE_WRAPPING */
- case UNSPLIT:
- /* These cases are handled by the earlier check for a new line and action */
case ENTER:
+ u->mark_begin_x = fs->current_x;
+ break;
+#ifndef DISABLE_WRAPPING
+ case SPLIT_BEGIN:
+ case SPLIT_END:
+#endif /* !DISABLE_WRAPPING */
+ case JOIN:
+ /* These cases are handled by the earlier check for a new line and action. */
case OTHER:
break;
}
#ifdef DEBUG
- fprintf(stderr, "Done in udpate_undo (type was %d)\n", action);
-#endif
- if (fs->last_action != action) {
-#ifdef DEBUG
- fprintf(stderr, "Starting add_undo for new action as it does not match last_action\n");
+ fprintf(stderr, "Done in update_undo (type was %d)\n", action);
#endif
- add_undo(action);
- }
- fs->last_action = action;
}
-
#endif /* !NANO_TINY */
#ifndef DISABLE_WRAPPING
@@ -1103,10 +1130,8 @@ void wrap_reset(void)
prepend_wrap = FALSE;
}
-/* We wrap the given line. Precondition: we assume the cursor has been
- * moved forward since the last typed character. Return TRUE if we
- * wrapped, and FALSE otherwise. */
-bool do_wrap(filestruct *line, bool undoing)
+/* Try wrapping the given line. Return TRUE if wrapped, FALSE otherwise. */
+bool do_wrap(filestruct *line)
{
size_t line_len;
/* The length of the line we wrap. */
@@ -1122,16 +1147,10 @@ bool do_wrap(filestruct *line, bool undoing)
/* The text after the wrap point. */
size_t after_break_len;
/* The length of after_break. */
- bool prepending = FALSE;
- /* Do we prepend to the next line? */
const char *next_line = NULL;
/* The next line, minus indentation. */
size_t next_line_len = 0;
/* The length of next_line. */
- char *new_line = NULL;
- /* The line we create. */
- size_t new_line_len = 0;
- /* The eventual length of new_line. */
/* There are three steps. First, we decide where to wrap. Then, we
* create the new wrap line. Finally, we clean up. */
@@ -1171,9 +1190,6 @@ bool do_wrap(filestruct *line, bool undoing)
return FALSE;
#ifndef NANO_TINY
- if (!undoing)
- add_undo(SPLIT);
-
/* If autoindent is turned on, and we're on the character just after
* the indentation, we don't wrap. */
if (ISSET(AUTOINDENT)) {
@@ -1184,8 +1200,14 @@ bool do_wrap(filestruct *line, bool undoing)
if (wrap_loc == indent_len)
return FALSE;
}
+
+ add_undo(SPLIT_BEGIN);
#endif
+ size_t old_x = openfile->current_x;
+ filestruct * oldLine = openfile->current;
+ openfile->current = line;
+
/* Step 2, making the new wrap line. It will consist of indentation
* followed by the text after the wrap point, optionally followed by
* a space (if the text after the wrap point doesn't end in a blank)
@@ -1205,9 +1227,15 @@ bool do_wrap(filestruct *line, bool undoing)
const char *end = after_break + move_mbleft(after_break,
after_break_len);
+ /* Go to the end of the line. */
+ openfile->current_x = line_len;
+
/* If after_break doesn't end in a blank, make sure it ends in a
* space. */
if (!is_blank_mbchar(end)) {
+#ifndef NANO_TINY
+ add_undo(ADD);
+#endif
line_len++;
line->data = charealloc(line->data, line_len + 1);
line->data[line_len - 1] = ' ';
@@ -1215,126 +1243,42 @@ bool do_wrap(filestruct *line, bool undoing)
after_break = line->data + wrap_loc;
after_break_len++;
openfile->totsize++;
+ openfile->current_x++;
+#ifndef NANO_TINY
+ update_undo(ADD);
+#endif
}
next_line = line->next->data;
next_line_len = strlen(next_line);
if (after_break_len + next_line_len <= fill) {
- prepending = TRUE;
- new_line_len += next_line_len;
+ /* Delete the LF to join the two lines. */
+ do_delete();
+ /* Delete any leading blanks from the joined-on line. */
+ while (is_blank_mbchar(&line->data[openfile->current_x]))
+ do_delete();
+ renumber(line);
}
}
- /* new_line_len is now the length of the text that will be wrapped
- * to the next line, plus (if we're prepending to it) the length of
- * the text of the next line. */
- new_line_len += after_break_len;
+ /* Go to the wrap location and split the line there. */
+ openfile->current_x = wrap_loc;
+ do_enter(FALSE);
-#ifndef NANO_TINY
- if (ISSET(AUTOINDENT)) {
- if (prepending) {
- /* If we're prepending, the indentation will come from the
- * next line. */
- indent_string = next_line;
- indent_len = indent_length(indent_string);
- next_line += indent_len;
- } else {
- /* Otherwise, it will come from this line, in which case
- * we should increase new_line_len to make room for it. */
- new_line_len += indent_len;
- openfile->totsize += mbstrnlen(indent_string, indent_len);
- }
- }
-#endif
-
- /* Now we allocate the new line and copy the text into it. */
- new_line = charalloc(new_line_len + 1);
- new_line[0] = '\0';
-
-#ifndef NANO_TINY
- if (ISSET(AUTOINDENT)) {
- /* Copy the indentation. */
- strncpy(new_line, indent_string, indent_len);
- new_line[indent_len] = '\0';
- new_line_len += indent_len;
- }
-#endif
-
- /* Copy all the text after the wrap point of the current line. */
- strcat(new_line, after_break);
-
- /* Break the current line at the wrap point. */
- null_at(&line->data, wrap_loc);
-
- if (prepending) {
- if (!undoing)
- update_undo(SPLIT);
- /* If we're prepending, copy the text from the next line, minus
- * the indentation that we already copied above. */
- strcat(new_line, next_line);
-
- free(line->next->data);
- line->next->data = new_line;
-
- /* If the NO_NEWLINES flag isn't set, and text has been added to
- * the magicline, make a new magicline. */
- if (!ISSET(NO_NEWLINES) && openfile->filebot->data[0] != '\0')
- new_magicline();
+ if (old_x < wrap_loc) {
+ openfile->current_x = old_x;
+ openfile->current = oldLine;
+ prepend_wrap = TRUE;
} else {
- /* Otherwise, make a new line and copy the text after where we
- * broke this line to the beginning of the new line. */
- splice_node(openfile->current, make_new_node(openfile->current),
- openfile->current->next);
-
- /* If the current line is the last line of the file, move the
- * last line of the file down to the next line. */
- if (openfile->filebot == openfile->current)
- openfile->filebot = openfile->current->next;
-
- openfile->current->next->data = new_line;
-
- openfile->totsize++;
- }
-
- /* Step 3, clean up. Reposition the cursor and mark, and do some
- * other sundry things. */
-
- /* Set the prepend_wrap flag, so that later wraps of this line will
- * be prepended to the next line. */
- prepend_wrap = TRUE;
-
- /* Each line knows its number. We recalculate these if we inserted
- * a new line. */
- if (!prepending)
- renumber(line);
-
- /* If the cursor was after the break point, we must move it. We
- * also clear the prepend_wrap flag in this case. */
- if (openfile->current_x > wrap_loc) {
+ openfile->current_x += (old_x - wrap_loc);
prepend_wrap = FALSE;
-
- openfile->current = openfile->current->next;
- openfile->current_x -= wrap_loc
-#ifndef NANO_TINY
- - indent_len
-#endif
- ;
- openfile->placewewant = xplustabs();
}
+ openfile->placewewant = xplustabs();
+
#ifndef NANO_TINY
- /* If the mark was on this line after the wrap point, we move it
- * down. If it was on the next line and we prepended to that line,
- * we move it right. */
- if (openfile->mark_set) {
- if (openfile->mark_begin == line && openfile->mark_begin_x >
- wrap_loc) {
- openfile->mark_begin = line->next;
- openfile->mark_begin_x -= wrap_loc - indent_len + 1;
- } else if (prepending && openfile->mark_begin == line->next)
- openfile->mark_begin_x += after_break_len;
- }
+ add_undo(SPLIT_END);
#endif
return TRUE;
@@ -1346,7 +1290,7 @@ bool do_wrap(filestruct *line, bool undoing)
* that the display length to there is at most (goal + 1). If there is
* no such blank, then we find the first blank. We then take the last
* blank in that group of blanks. The terminating '\0' counts as a
- * blank, as does a '\n' if newline is TRUE. */
+ * blank, as does a '\n' if newln is TRUE. */
ssize_t break_line(const char *line, ssize_t goal
#ifndef DISABLE_HELP
, bool newln
@@ -1355,17 +1299,18 @@ ssize_t break_line(const char *line, ssize_t goal
{
ssize_t blank_loc = -1;
/* Current tentative return value. Index of the last blank we
- * found with short enough display width. */
+ * found with short enough display width. */
ssize_t cur_loc = 0;
/* Current index in line. */
size_t cur_pos = 0;
/* Current column position in line. */
- int line_len;
+ int char_len = 0;
+ /* Length of current character, in bytes. */
assert(line != NULL);
while (*line != '\0' && goal >= cur_pos) {
- line_len = parse_mbchar(line, NULL, &cur_pos);
+ char_len = parse_mbchar(line, NULL, &cur_pos);
if (is_blank_mbchar(line)
#ifndef DISABLE_HELP
@@ -1380,8 +1325,8 @@ ssize_t break_line(const char *line, ssize_t goal
#endif
}
- line += line_len;
- cur_loc += line_len;
+ line += char_len;
+ cur_loc += char_len;
}
if (goal >= cur_pos)
@@ -1390,34 +1335,34 @@ ssize_t break_line(const char *line, ssize_t goal
#ifndef DISABLE_HELP
if (newln && blank_loc <= 0) {
- /* If blank was not found or was found only first character,
- * force line break. */
- cur_loc -= line_len;
- return cur_loc;
+ /* If no blank was found, or was found only as the first
+ * character, force a line break. */
+ cur_loc -= char_len;
+ return cur_loc;
}
#endif
if (blank_loc == -1) {
- /* No blank was found that was short enough. */
+ /* No blank was found within the goal width,
+ * so now try and find a blank beyond it. */
bool found_blank = FALSE;
ssize_t found_blank_loc = 0;
while (*line != '\0') {
- line_len = parse_mbchar(line, NULL, NULL);
+ char_len = parse_mbchar(line, NULL, NULL);
if (is_blank_mbchar(line)
#ifndef DISABLE_HELP
|| (newln && *line == '\n')
#endif
) {
- if (!found_blank)
- found_blank = TRUE;
+ found_blank = TRUE;
found_blank_loc = cur_loc;
} else if (found_blank)
return found_blank_loc;
- line += line_len;
- cur_loc += line_len;
+ line += char_len;
+ cur_loc += char_len;
}
return -1;
@@ -1426,23 +1371,14 @@ ssize_t break_line(const char *line, ssize_t goal
/* Move to the last blank after blank_loc, if there is one. */
line -= cur_loc;
line += blank_loc;
- line_len = parse_mbchar(line, NULL, NULL);
- line += line_len;
-
- while (*line != '\0' && (is_blank_mbchar(line)
-#ifndef DISABLE_HELP
- || (newln && *line == '\n')
-#endif
- )) {
-#ifndef DISABLE_HELP
- if (newln && *line == '\n')
- break;
-#endif
+ char_len = parse_mbchar(line, NULL, NULL);
+ line += char_len;
- line_len = parse_mbchar(line, NULL, NULL);
+ while (*line != '\0' && is_blank_mbchar(line)) {
+ char_len = parse_mbchar(line, NULL, NULL);
- line += line_len;
- blank_loc += line_len;
+ line += char_len;
+ blank_loc += char_len;
}
return blank_loc;
@@ -1804,7 +1740,7 @@ void backup_lines(filestruct *first_line, size_t par_len)
/* Copy the paragraph back to the current buffer's filestruct from
* the justify buffer. */
- copy_from_filestruct(jusbuffer, jusbottom);
+ copy_from_filestruct(jusbuffer);
/* Move upward from the last line of the paragraph to the first
* line, putting first_line, edittop, current, and mark_begin at the
@@ -1947,6 +1883,10 @@ void do_justify(bool full_justify)
bool filebot_inpar = FALSE;
/* Whether the text at filebot is part of the current
* paragraph. */
+ int kbinput;
+ /* The first keystroke after a justification. */
+ functionptrtype func;
+ /* The function associated with that keystroke. */
/* We save these variables to be restored if the user
* unjustifies. */
@@ -1961,10 +1901,6 @@ void do_justify(bool full_justify)
#endif
bool modified_save = openfile->modified;
- int kbinput;
- bool meta_key, func_key, s_or_t, ran_func, finished;
- const sc *s;
-
/* Move to the beginning of the current line, so that justifying at
* the end of the last line of the file, if that line isn't blank,
* will work the first time through. */
@@ -1974,6 +1910,10 @@ void do_justify(bool full_justify)
if (full_justify)
openfile->current = openfile->fileage;
+#ifndef NANO_TINY
+ allow_pending_sigwinch(FALSE);
+#endif
+
while (TRUE) {
size_t i;
/* Generic loop variable. */
@@ -2272,16 +2212,16 @@ void do_justify(bool full_justify)
do_cursorpos(TRUE);
/* Display the shortcut list with UnJustify. */
- shortcut_init(TRUE);
+ uncutfunc->desc = unjust_tag;
+ currmenu = MMAIN;
display_main_list();
/* Now get a keystroke and see if it's unjustify. If not, put back
* the keystroke and return. */
- kbinput = do_input(&meta_key, &func_key, &s_or_t, &ran_func,
- &finished, FALSE);
- s = get_shortcut(currmenu, &kbinput, &meta_key, &func_key);
+ kbinput = do_input(FALSE);
+ func = func_from_key(&kbinput);
- if (s && s->scfunc == DO_UNCUT_TEXT) {
+ if (func == do_uncut_text) {
/* Splice the justify buffer back into the file, but only if we
* actually justified something. */
if (first_par_line != NULL) {
@@ -2342,8 +2282,12 @@ void do_justify(bool full_justify)
blank_statusbar();
/* Display the shortcut list with UnCut. */
- shortcut_init(FALSE);
+ uncutfunc->desc = uncut_tag;
display_main_list();
+
+#ifndef NANO_TINY
+ allow_pending_sigwinch(TRUE);
+#endif
}
/* Justify the current paragraph. */
@@ -2367,7 +2311,6 @@ bool do_int_spell_fix(const char *word)
char *save_search, *save_replace;
size_t match_len, current_x_save = openfile->current_x;
size_t pww_save = openfile->placewewant;
- bool meta_key = FALSE, func_key = FALSE;
filestruct *edittop_save = openfile->edittop;
filestruct *current_save = openfile->current;
/* Save where we are. */
@@ -2455,8 +2398,7 @@ bool do_int_spell_fix(const char *word)
TRUE,
#endif
MSPELL, word,
- &meta_key, &func_key,
-#ifndef NANO_TINY
+#ifndef DISABLE_HISTORIES
NULL,
#endif
edit_refresh, _("Edit a replacement")) == -1);
@@ -2692,7 +2634,7 @@ const char *do_int_speller(const char *tempfile_name)
if (WIFEXITED(spell_status) == 0 || WEXITSTATUS(spell_status))
return _("Error invoking \"spell\"");
- if (WIFEXITED(sort_status) == 0 || WEXITSTATUS(sort_status))
+ if (WIFEXITED(sort_status) == 0 || WEXITSTATUS(sort_status))
return _("Error invoking \"sort -f\"");
if (WIFEXITED(uniq_status) == 0 || WEXITSTATUS(uniq_status))
@@ -2719,9 +2661,10 @@ const char *do_alt_speller(char *tempfile_name)
{
int alt_spell_status;
size_t current_x_save = openfile->current_x;
- size_t pww_save = openfile->placewewant;
ssize_t current_y_save = openfile->current_y;
ssize_t lineno_save = openfile->current->lineno;
+ struct stat spellfileinfo;
+ __time_t timestamp;
pid_t pid_spell;
char *ptr;
static int arglen = 3;
@@ -2730,9 +2673,6 @@ const char *do_alt_speller(char *tempfile_name)
bool old_mark_set = openfile->mark_set;
bool added_magicline = FALSE;
/* Whether we added a magicline after filebot. */
- bool right_side_up = FALSE;
- /* TRUE if (mark_begin, mark_begin_x) is the top of the mark,
- * FALSE if (current, current_x) is. */
filestruct *top, *bot;
size_t top_x, bot_x;
ssize_t mb_lineno_save = 0;
@@ -2757,6 +2697,10 @@ const char *do_alt_speller(char *tempfile_name)
return NULL;
}
+ /* Get the timestamp of the temporary file. */
+ stat(tempfile_name, &spellfileinfo);
+ timestamp = spellfileinfo.st_mtime;
+
endwin();
/* Set up an argument list to pass execvp(). */
@@ -2834,7 +2778,7 @@ const char *do_alt_speller(char *tempfile_name)
* added when we're done correcting misspelled words; and
* turn the mark off. */
mark_order((const filestruct **)&top, &top_x,
- (const filestruct **)&bot, &bot_x, &right_side_up);
+ (const filestruct **)&bot, &bot_x, NULL);
filepart = partition_filestruct(top, top_x, bot, bot_x);
if (!ISSET(NO_NEWLINES))
added_magicline = (openfile->filebot->data[0] != '\0');
@@ -2858,18 +2802,6 @@ const char *do_alt_speller(char *tempfile_name)
if (!ISSET(NO_NEWLINES) && added_magicline)
remove_magicline();
- /* Put the beginning and the end of the mark at the beginning
- * and the end of the spell-checked text. */
- if (openfile->fileage == openfile->filebot)
- bot_x += top_x;
- if (right_side_up) {
- openfile->mark_begin_x = top_x;
- current_x_save = bot_x;
- } else {
- current_x_save = top_x;
- openfile->mark_begin_x = bot_x;
- }
-
/* Unpartition the filestruct so that it contains all the text
* again. Note that we've replaced the marked text originally
* in the partition with the spell-checked marked text in the
@@ -2885,8 +2817,7 @@ const char *do_alt_speller(char *tempfile_name)
openfile->totsize = totsize_save;
/* Assign mark_begin to the line where the mark began before. */
- do_gotopos(mb_lineno_save, openfile->mark_begin_x,
- current_y_save, 0);
+ goto_line_posx(mb_lineno_save, openfile->mark_begin_x);
openfile->mark_begin = openfile->current;
/* Assign mark_begin_x to the location in mark_begin where the
@@ -2899,9 +2830,16 @@ const char *do_alt_speller(char *tempfile_name)
}
#endif
- /* Go back to the old position, and mark the file as modified. */
- do_gotopos(lineno_save, current_x_save, current_y_save, pww_save);
- set_modified();
+ /* Go back to the old position. */
+ goto_line_posx(lineno_save, current_x_save);
+ openfile->current_y = current_y_save;
+ edit_update(NONE);
+
+ /* Stat the temporary file again, and mark the buffer as modified only
+ * if this file was changed since it was written. */
+ stat(tempfile_name, &spellfileinfo);
+ if (spellfileinfo.st_mtime != timestamp)
+ set_modified();
#ifndef NANO_TINY
/* Handle a pending SIGWINCH again. */
@@ -2921,7 +2859,7 @@ void do_spell(void)
const char *spell_msg;
if (ISSET(RESTRICTED)) {
- nano_disabled_msg();
+ nano_disabled_msg();
return;
}
@@ -2943,6 +2881,10 @@ void do_spell(void)
return;
}
+ blank_bottombars();
+ statusbar(_("Invoking spell checker, please wait"));
+ doupdate();
+
spell_msg = (alt_speller != NULL) ? do_alt_speller(temp) :
do_int_speller(temp);
unlink(temp);
@@ -2966,6 +2908,472 @@ void do_spell(void)
}
#endif /* !DISABLE_SPELLER */
+#ifndef DISABLE_COLOR
+/* Cleanup things to do after leaving the linter. */
+void lint_cleanup(void)
+{
+ currmenu = MMAIN;
+ display_main_list();
+}
+
+
+/* Run linter. Based on alt-speller code. Return NULL for normal
+ * termination, and the error string otherwise. */
+void do_linter(void)
+{
+ char *read_buff, *read_buff_ptr, *read_buff_word, *ptr;
+ size_t pipe_buff_size, read_buff_size, read_buff_read, bytesread;
+ size_t parsesuccess = 0;
+ int lint_fd[2];
+ pid_t pid_lint;
+ int lint_status;
+ static int arglen = 3;
+ static char **lintargs = NULL;
+ char *lintcopy;
+ char *convendptr = NULL;
+ lintstruct *lints = NULL, *tmplint = NULL, *curlint = NULL;
+
+ if (!openfile->syntax || !openfile->syntax->linter) {
+ statusbar(_("No linter defined for this type of file!"));
+ return;
+ }
+
+ if (ISSET(RESTRICTED)) {
+ nano_disabled_msg();
+ return;
+ }
+
+ if (openfile->modified) {
+ int i = do_yesno_prompt(FALSE, _("Save modified buffer before linting?"));
+ if (i == -1) {
+ statusbar(_("Cancelled"));
+ lint_cleanup();
+ return;
+ } else if (i == 1) {
+ if (do_writeout(FALSE) != TRUE) {
+ lint_cleanup();
+ return;
+ }
+ }
+ }
+
+ lintcopy = mallocstrcpy(NULL, openfile->syntax->linter);
+ /* Create pipe up front. */
+ if (pipe(lint_fd) == -1) {
+ statusbar(_("Could not create pipe"));
+ lint_cleanup();
+ return;
+ }
+
+ blank_bottombars();
+ statusbar(_("Invoking linter, please wait"));
+ doupdate();
+
+ /* Set up an argument list to pass execvp(). */
+ if (lintargs == NULL) {
+ lintargs = (char **)nmalloc(arglen * sizeof(char *));
+
+ lintargs[0] = strtok(lintcopy, " ");
+ while ((ptr = strtok(NULL, " ")) != NULL) {
+ arglen++;
+ lintargs = (char **)nrealloc(lintargs, arglen *
+ sizeof(char *));
+ lintargs[arglen - 3] = ptr;
+ }
+ lintargs[arglen - 1] = NULL;
+ }
+ lintargs[arglen - 2] = openfile->filename;
+
+ /* A new process to run linter. */
+ if ((pid_lint = fork()) == 0) {
+
+ /* Child continues (i.e. future spell process). */
+ close(lint_fd[0]);
+
+ /* Send spell's standard output/err to the pipe. */
+ if (dup2(lint_fd[1], STDOUT_FILENO) != STDOUT_FILENO)
+ exit(1);
+ if (dup2(lint_fd[1], STDERR_FILENO) != STDERR_FILENO)
+ exit(1);
+
+ close(lint_fd[1]);
+
+ /* Start the linter program; we are using $PATH. */
+ execvp(lintargs[0], lintargs);
+
+ /* This should not be reached if linter is found. */
+ exit(1);
+ }
+
+ /* Parent continues here. */
+ close(lint_fd[1]);
+
+ /* The child process was not forked successfully. */
+ if (pid_lint < 0) {
+ close(lint_fd[0]);
+ statusbar(_("Could not fork"));
+ lint_cleanup();
+ return;
+ }
+
+ /* Get the system pipe buffer size. */
+ if ((pipe_buff_size = fpathconf(lint_fd[0], _PC_PIPE_BUF)) < 1) {
+ close(lint_fd[0]);
+ statusbar(_("Could not get size of pipe buffer"));
+ lint_cleanup();
+ return;
+ }
+
+ /* Read in the returned spelling errors. */
+ read_buff_read = 0;
+ read_buff_size = pipe_buff_size + 1;
+ read_buff = read_buff_ptr = charalloc(read_buff_size);
+
+ while ((bytesread = read(lint_fd[0], read_buff_ptr,
+ pipe_buff_size)) > 0) {
+#ifdef DEBUG
+ fprintf(stderr, "text.c:do_linter:%ld bytes (%s)\n", (long)bytesread, read_buff_ptr);
+#endif
+ read_buff_read += bytesread;
+ read_buff_size += pipe_buff_size;
+ read_buff = read_buff_ptr = charealloc(read_buff,
+ read_buff_size);
+ read_buff_ptr += read_buff_read;
+ }
+
+ *read_buff_ptr = '\0';
+ close(lint_fd[0]);
+
+#ifdef DEBUG
+ fprintf(stderr, "text.c:do_lint:Raw output: %s\n", read_buff);
+#endif
+
+ /* Process output. */
+ read_buff_word = read_buff_ptr = read_buff;
+
+ while (*read_buff_ptr != '\0') {
+ if ((*read_buff_ptr == '\r') || (*read_buff_ptr == '\n')) {
+ *read_buff_ptr = '\0';
+ if (read_buff_word != read_buff_ptr) {
+ char *filename = NULL, *linestr = NULL, *maybecol = NULL;
+ char *message = mallocstrcpy(NULL, read_buff_word);
+
+ /* At the moment we're assuming the following formats:
+ *
+ * filenameorcategory:line:column:message (e.g. splint)
+ * filenameorcategory:line:message (e.g. pyflakes)
+ * filenameorcategory:line,col:message (e.g. pylint)
+ *
+ * This could be turned into some scanf() based parser,
+ * but ugh. */
+ if ((filename = strtok(read_buff_word, ":")) != NULL) {
+ if ((linestr = strtok(NULL, ":")) != NULL) {
+ if ((maybecol = strtok(NULL, ":")) != NULL) {
+ ssize_t tmplineno = 0, tmpcolno = 0;
+ char *tmplinecol;
+
+ tmplineno = strtol(linestr, NULL, 10);
+ if (tmplineno <= 0) {
+ read_buff_ptr++;
+ free(message);
+ continue;
+ }
+
+ tmpcolno = strtol(maybecol, &convendptr, 10);
+ if (*convendptr != '\0') {
+ /* Previous field might still be
+ * line,col format. */
+ strtok(linestr, ",");
+ if ((tmplinecol = strtok(NULL, ",")) != NULL)
+ tmpcolno = strtol(tmplinecol, NULL, 10);
+ }
+
+#ifdef DEBUG
+ fprintf(stderr, "text.c:do_lint:Successful parse! %ld:%ld:%s\n", (long)tmplineno, (long)tmpcolno, message);
+#endif
+ /* Nice. We have a lint message we can use. */
+ parsesuccess++;
+ tmplint = curlint;
+ curlint = nmalloc(sizeof(lintstruct));
+ curlint->next = NULL;
+ curlint->prev = tmplint;
+ if (curlint->prev != NULL)
+ curlint->prev->next = curlint;
+ curlint->msg = mallocstrcpy(NULL, message);
+ curlint->lineno = tmplineno;
+ curlint->colno = tmpcolno;
+ curlint->filename = mallocstrcpy(NULL, filename);
+
+ if (lints == NULL)
+ lints = curlint;
+ }
+ }
+ } else
+ free(message);
+ }
+ read_buff_word = read_buff_ptr + 1;
+ }
+ read_buff_ptr++;
+ }
+
+ /* Process the end of the lint process. */
+ waitpid(pid_lint, &lint_status, 0);
+
+ free(read_buff);
+
+ if (parsesuccess == 0) {
+ statusbar(_("Got 0 parsable lines from command: %s"), openfile->syntax->linter);
+ lint_cleanup();
+ return;
+ }
+
+ currmenu = MLINTER;
+ bottombars(MLINTER);
+ tmplint = NULL;
+ curlint = lints;
+ while (TRUE) {
+ ssize_t tmpcol = 1;
+ int kbinput;
+ functionptrtype func;
+
+ if (curlint->colno > 0)
+ tmpcol = curlint->colno;
+
+ if (tmplint != curlint) {
+#ifndef NANO_TINY
+ struct stat lintfileinfo;
+
+ new_lint_loop:
+ if (stat(curlint->filename, &lintfileinfo) != -1) {
+ if (openfile->current_stat->st_ino != lintfileinfo.st_ino) {
+ openfilestruct *tmpof = openfile;
+ while (tmpof != openfile->next) {
+ if (tmpof->current_stat->st_ino == lintfileinfo.st_ino)
+ break;
+ tmpof = tmpof->next;
+ }
+ if (tmpof->current_stat->st_ino != lintfileinfo.st_ino) {
+ char *msg = charalloc(1024 + strlen(curlint->filename));
+ int i;
+
+ sprintf(msg, _("This message is for unopened file %s, open it in a new buffer?"),
+ curlint->filename);
+ i = do_yesno_prompt(FALSE, msg);
+ free(msg);
+ if (i == -1) {
+ statusbar(_("Cancelled"));
+ goto free_lints_and_return;
+ } else if (i == 1) {
+ SET(MULTIBUFFER);
+ open_buffer(curlint->filename, FALSE);
+ } else {
+ char *dontwantfile = curlint->filename;
+
+ while (curlint != NULL && !strcmp(curlint->filename, dontwantfile))
+ curlint = curlint->next;
+ if (curlint == NULL) {
+ statusbar("No more errors in un-opened filed, cancelling");
+ break;
+ } else
+ goto new_lint_loop;
+ }
+ } else
+ openfile = tmpof;
+ }
+ }
+#endif /* !NANO_TINY */
+ do_gotolinecolumn(curlint->lineno, tmpcol, FALSE, FALSE, FALSE, FALSE);
+ titlebar(NULL);
+ edit_refresh();
+ statusbar(curlint->msg);
+ bottombars(MLINTER);
+ }
+
+ kbinput = get_kbinput(bottomwin);
+ func = func_from_key(&kbinput);
+ tmplint = curlint;
+
+ if (func == do_cancel)
+ break;
+ else if (func == do_help_void) {
+ tmplint = NULL;
+ do_help_void();
+ } else if (func == do_page_down) {
+ if (curlint->next != NULL)
+ curlint = curlint->next;
+ else
+ statusbar(_("At last message"));
+ } else if (func == do_page_up) {
+ if (curlint->prev != NULL)
+ curlint = curlint->prev;
+ else
+ statusbar(_("At first message"));
+ }
+ }
+ blank_statusbar();
+#ifndef NANO_TINY
+free_lints_and_return:
+#endif
+ for (tmplint = lints; tmplint != NULL; tmplint = tmplint->next) {
+ free(tmplint->msg);
+ free(tmplint->filename);
+ free(tmplint);
+ }
+ lint_cleanup();
+}
+
+/* Run a formatter for the given syntax.
+ * Expects the formatter to be non-interactive and
+ * operate on a file in-place, which we'll pass it
+ * on the command line. Another mashup of the speller
+ * and alt_speller routines.
+ */
+void do_formatter(void)
+{
+ bool status;
+ FILE *temp_file;
+ char *temp = safe_tempfile(&temp_file);
+ int format_status;
+ size_t current_x_save = openfile->current_x;
+ size_t pww_save = openfile->placewewant;
+ ssize_t current_y_save = openfile->current_y;
+ ssize_t lineno_save = openfile->current->lineno;
+ pid_t pid_format;
+ char *ptr;
+ static int arglen = 3;
+ static char **formatargs = NULL;
+ char *finalstatus = NULL;
+
+ /* Check whether we're using syntax highlighting
+ * and the formatter option is set. */
+ if (openfile->syntax == NULL || openfile->syntax->formatter == NULL) {
+ statusbar(_("Error: no formatter defined"));
+ return;
+ }
+
+ if (ISSET(RESTRICTED)) {
+ nano_disabled_msg();
+ return;
+ }
+
+ if (temp == NULL) {
+ statusbar(_("Error writing temp file: %s"), strerror(errno));
+ return;
+ }
+
+ /* We're not supporting partial formatting, oi vey. */
+ openfile->mark_set = FALSE;
+ status = write_file(temp, temp_file, TRUE, OVERWRITE, FALSE);
+
+ if (!status) {
+ statusbar(_("Error writing temp file: %s"), strerror(errno));
+ free(temp);
+ return;
+ }
+
+ if (openfile->totsize == 0) {
+ statusbar(_("Finished"));
+ return;
+ }
+
+ blank_bottombars();
+ statusbar(_("Invoking formatter, please wait"));
+ doupdate();
+
+ endwin();
+
+ /* Set up an argument list to pass execvp(). */
+ if (formatargs == NULL) {
+ formatargs = (char **)nmalloc(arglen * sizeof(char *));
+
+ formatargs[0] = strtok(openfile->syntax->formatter, " ");
+ while ((ptr = strtok(NULL, " ")) != NULL) {
+ arglen++;
+ formatargs = (char **)nrealloc(formatargs, arglen *
+ sizeof(char *));
+ formatargs[arglen - 3] = ptr;
+ }
+ formatargs[arglen - 1] = NULL;
+ }
+ formatargs[arglen - 2] = temp;
+
+ /* Start a new process for the formatter. */
+ if ((pid_format = fork()) == 0) {
+ /* Start the formatting program; we are using $PATH. */
+ execvp(formatargs[0], formatargs);
+
+ /* Should not be reached, if the formatter is found! */
+ exit(1);
+ }
+
+ /* If we couldn't fork, get out. */
+ if (pid_format < 0) {
+ statusbar(_("Could not fork"));
+ return;
+ }
+
+#ifndef NANO_TINY
+ /* Don't handle a pending SIGWINCH until the alternate format checker
+ * is finished and we've loaded the format-checked file back in. */
+ allow_pending_sigwinch(FALSE);
+#endif
+
+ /* Wait for the formatter to finish. */
+ wait(&format_status);
+
+ /* Reenter curses mode. */
+ doupdate();
+
+ /* Restore the terminal to its previous state. */
+ terminal_init();
+
+ /* Turn the cursor back on for sure. */
+ curs_set(1);
+
+ /* The screen might have been resized. If it has, reinitialize all
+ * the windows based on the new screen dimensions. */
+ window_init();
+
+ if (!WIFEXITED(format_status) ||
+ WEXITSTATUS(format_status) != 0) {
+ char *format_error;
+ char *invoke_error = _("Error invoking \"%s\"");
+
+ format_error =
+ charalloc(strlen(invoke_error) +
+ strlen(openfile->syntax->formatter) + 1);
+ sprintf(format_error, invoke_error, openfile->syntax->formatter);
+ finalstatus = format_error;
+ } else {
+ /* Replace the text of the current buffer with the formatted text. */
+ replace_buffer(temp);
+
+ /* Go back to the old position, and mark the file as modified. */
+ do_gotopos(lineno_save, current_x_save, current_y_save, pww_save);
+ set_modified();
+
+#ifndef NANO_TINY
+ /* Handle a pending SIGWINCH again. */
+ allow_pending_sigwinch(TRUE);
+#endif
+
+ finalstatus = _("Finished formatting");
+ }
+
+ unlink(temp);
+ free(temp);
+
+ currmenu = MMAIN;
+
+ /* If the formatter printed any error messages onscreen, make
+ * sure that they're cleared off. */
+ total_refresh();
+
+ statusbar(finalstatus);
+}
+
+#endif /* !DISABLE_COLOR */
+
#ifndef NANO_TINY
/* Our own version of "wc". Note that its character counts are in
* multibyte characters instead of single-byte characters. */
@@ -3071,4 +3479,3 @@ void do_verbatim_input(void)
free(output);
}
-
diff --git a/src/utils.c b/src/utils.c
index ff13a41..bed5f91 100644
--- a/src/utils.c
+++ b/src/utils.c
@@ -1,9 +1,9 @@
-/* $Id: utils.c 4453 2009-12-02 03:36:22Z astyanax $ */
+/* $Id: utils.c 4948 2014-06-09 14:23:53Z bens $ */
/**************************************************************************
* utils.c *
* *
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
- * 2008, 2009 Free Software Foundation, Inc. *
+ * 2008, 2009, 2010, 2011, 2013, 2014 Free Software Foundation, Inc. *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 3, or (at your option) *
@@ -72,6 +72,10 @@ bool parse_num(const char *str, ssize_t *val)
assert(str != NULL);
+ /* The manual page for strtol() says this is required, and
+ * it looks like it is! */
+ errno = 0;
+
j = (ssize_t)strtol(str, &first_error, 10);
if (errno == ERANGE || *str == '\0' || *first_error != '\0')
@@ -183,7 +187,7 @@ void sunder(char *str)
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301, USA. */
-#ifdef ENABLE_NANORC
+#ifndef DISABLE_NANORC
#ifndef HAVE_GETDELIM
/* This function is equivalent to getdelim(). */
@@ -243,7 +247,7 @@ ssize_t ngetline(char **lineptr, size_t *n, FILE *stream)
return getdelim(lineptr, n, '\n', stream);
}
#endif
-#endif /* ENABLE_NANORC */
+#endif /* !DISABLE_NANORC */
#ifdef HAVE_REGEX_H
/* Do the compiled regex in preg and the regex in string match the
@@ -255,9 +259,10 @@ bool regexp_bol_or_eol(const regex_t *preg, const char *string)
REG_NOMATCH);
}
-/* Fix the regex if we're on platforms which requires an adjustment
- * from GNU-style to BSD-style word boundaries. */
-const char *fixbounds(const char *r) {
+/* Fix the regex if we're on platforms which require an adjustment
+ * from GNU-style to BSD-style word boundaries. */
+const char *fixbounds(const char *r)
+{
#ifndef GNU_WORDBOUNDS
int i, j = 0;
char *r2 = charalloc(strlen(r) * 5);
@@ -268,15 +273,15 @@ const char *fixbounds(const char *r) {
#endif
for (i = 0; i < strlen(r); i++) {
- if (r[i] != '\0' && r[i] == '\\' && (r[i+1] == '>' || r[i+1] == '<')) {
- strcpy(&r2[j], "[[:");
- r2[j+3] = r[i+1];
- strcpy(&r2[j+4], ":]]");
- i++;
- j += 6;
- } else
- r2[j] = r[i];
- j++;
+ if (r[i] != '\0' && r[i] == '\\' && (r[i + 1] == '>' || r[i + 1] == '<')) {
+ strcpy(&r2[j], "[[:");
+ r2[j + 3] = r[i + 1];
+ strcpy(&r2[j + 4], ":]]");
+ i++;
+ j += 6;
+ } else
+ r2[j] = r[i];
+ j++;
}
r2[j] = '\0';
r3 = mallocstrcpy(NULL, r2);
@@ -472,7 +477,10 @@ size_t get_page_start(size_t column)
* current_x. */
size_t xplustabs(void)
{
- return strnlenpt(openfile->current->data, openfile->current_x);
+ if (openfile->current)
+ return strnlenpt(openfile->current->data, openfile->current_x);
+ else
+ return 0;
}
/* Return the index in s of the character displayed at the given column,
@@ -542,7 +550,7 @@ void new_magicline(void)
openfile->filebot->next->prev = openfile->filebot;
openfile->filebot->next->next = NULL;
openfile->filebot->next->lineno = openfile->filebot->lineno + 1;
-#ifdef ENABLE_COLOR
+#ifndef DISABLE_COLOR
openfile->filebot->next->multidata = NULL;
#endif
openfile->filebot = openfile->filebot->next;
@@ -594,7 +602,7 @@ void mark_order(const filestruct **top, size_t *top_x, const filestruct
*right_side_up = FALSE;
}
}
-#endif
+#endif /* !NANO_TINY */
/* Calculate the number of characters between begin and end, and return
* it. */
@@ -626,7 +634,7 @@ size_t get_totsize(const filestruct *begin, const filestruct *end)
return totsize;
}
-/* Get back a pointer given a line number in the current openfilestruct */
+/* Get back a pointer given a line number in the current openfilestruct. */
filestruct *fsfromline(ssize_t lineno)
{
filestruct *f = openfile->current;
diff --git a/src/winio.c b/src/winio.c
index 1aef2a9..086af41 100644
--- a/src/winio.c
+++ b/src/winio.c
@@ -1,9 +1,9 @@
-/* $Id: winio.c 4484 2010-03-07 19:35:46Z astyanax $ */
+/* $Id: winio.c 5149 2015-03-22 13:23:42Z bens $ */
/**************************************************************************
* winio.c *
* *
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
- * 2008, 2009 Free Software Foundation, Inc. *
+ * 2008, 2009, 2010, 2011, 2013, 2014 Free Software Foundation, Inc. *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 3, or (at your option) *
@@ -112,7 +112,6 @@ void get_key_buffer(WINDOW *win)
if (key_buffer != NULL)
return;
- /* Read in the first character using blocking input. */
#ifndef NANO_TINY
allow_pending_sigwinch(TRUE);
#endif
@@ -121,10 +120,11 @@ void get_key_buffer(WINDOW *win)
* screen updates. */
doupdate();
+ /* Read in the first character using whatever mode we're in. */
errcount = 0;
if (nodelay_mode) {
- if ((input = wgetch(win)) == ERR)
- return;
+ if ((input = wgetch(win)) == ERR)
+ return;
} else
while ((input = wgetch(win)) == ERR) {
errcount++;
@@ -174,7 +174,7 @@ void get_key_buffer(WINDOW *win)
#endif
}
- /* Switch back to non-blocking input. */
+ /* Switch back to waiting mode for input. */
nodelay(win, FALSE);
#ifdef DEBUG
@@ -224,17 +224,17 @@ void unget_input(int *input, size_t input_len)
}
/* Put back the character stored in kbinput, putting it in byte range
- * beforehand. If meta_key is TRUE, put back the Escape character after
- * putting back kbinput. If func_key is TRUE, put back the function key
+ * beforehand. If metakey is TRUE, put back the Escape character after
+ * putting back kbinput. If funckey is TRUE, put back the function key
* (a value outside byte range) without putting it in byte range. */
-void unget_kbinput(int kbinput, bool meta_key, bool func_key)
+void unget_kbinput(int kbinput, bool metakey, bool funckey)
{
- if (!func_key)
+ if (!funckey)
kbinput = (char)kbinput;
unget_input(&kbinput, 1);
- if (meta_key) {
+ if (metakey) {
kbinput = NANO_CONTROL_3;
unget_input(&kbinput, 1);
}
@@ -298,20 +298,20 @@ int *get_input(WINDOW *win, size_t input_len)
/* Read in a single character. If it's ignored, swallow it and go on.
* Otherwise, try to translate it from ASCII, meta key sequences, escape
- * sequences, and/or extended keypad values. Set meta_key to TRUE when
- * we get a meta key sequence, and set func_key to TRUE when we get an
- * extended keypad value. Supported extended keypad values consist of
+ * sequences, and/or extended keypad values. Supported extended keypad
+ * values consist of
* [arrow key], Ctrl-[arrow key], Shift-[arrow key], Enter, Backspace,
* the editing keypad (Insert, Delete, Home, End, PageUp, and PageDown),
* the function keypad (F1-F16), and the numeric keypad with NumLock
- * off. Assume nodelay(win) is FALSE. */
-int get_kbinput(WINDOW *win, bool *meta_key, bool *func_key)
+ * off. */
+int get_kbinput(WINDOW *win)
{
int kbinput;
/* Read in a character and interpret it. Continue doing this until
* we get a recognized value or sequence. */
- while ((kbinput = parse_kbinput(win, meta_key, func_key)) == ERR);
+ while ((kbinput = parse_kbinput(win)) == ERR)
+ ;
/* If we read from the edit window, blank the statusbar if we need
* to. */
@@ -324,14 +324,14 @@ int get_kbinput(WINDOW *win, bool *meta_key, bool *func_key)
/* Translate ASCII characters, extended keypad values, and escape
* sequences into their corresponding key values. Set meta_key to TRUE
* when we get a meta key sequence, and set func_key to TRUE when we get
- * a function key. Assume nodelay(win) is FALSE. */
-int parse_kbinput(WINDOW *win, bool *meta_key, bool *func_key)
+ * a function key. */
+int parse_kbinput(WINDOW *win)
{
static int escapes = 0, byte_digits = 0;
int *kbinput, retval = ERR;
- *meta_key = FALSE;
- *func_key = FALSE;
+ meta_key = FALSE;
+ func_key = FALSE;
/* Read in a character. */
if (nodelay_mode) {
@@ -339,7 +339,8 @@ int parse_kbinput(WINDOW *win, bool *meta_key, bool *func_key)
if (kbinput == 0)
return 0;
} else
- while ((kbinput = get_input(win, 1)) == NULL);
+ while ((kbinput = get_input(win, 1)) == NULL)
+ ;
switch (*kbinput) {
case ERR:
@@ -377,7 +378,7 @@ int parse_kbinput(WINDOW *win, bool *meta_key, bool *func_key)
* meta key sequence mode. Set meta_key to
* TRUE, and save the lowercase version of the
* non-escape character as the result. */
- *meta_key = TRUE;
+ meta_key = TRUE;
retval = tolower(*kbinput);
} else
/* One escape followed by a non-escape, and
@@ -467,7 +468,7 @@ int parse_kbinput(WINDOW *win, bool *meta_key, bool *func_key)
* escape counter, set meta_key to TRUE, and
* interpret the escape sequence. */
escapes = 0;
- *meta_key = TRUE;
+ meta_key = TRUE;
retval = parse_escape_seq_kbinput(win,
*kbinput);
}
@@ -497,36 +498,36 @@ int parse_kbinput(WINDOW *win, bool *meta_key, bool *func_key)
if (retval != ERR) {
switch (retval) {
case NANO_CONTROL_8:
- retval = ISSET(REBIND_DELETE) ? sc_seq_or(DO_DELETE, 0) :
- sc_seq_or(DO_BACKSPACE, 0);
+ retval = ISSET(REBIND_DELETE) ? sc_seq_or(do_delete, 0) :
+ sc_seq_or(do_backspace, 0);
break;
case KEY_DOWN:
#ifdef KEY_SDOWN
/* ncurses and Slang don't support KEY_SDOWN. */
case KEY_SDOWN:
#endif
- retval = sc_seq_or(DO_DOWN_VOID, *kbinput);
+ retval = sc_seq_or(do_down_void, *kbinput);
break;
case KEY_UP:
#ifdef KEY_SUP
/* ncurses and Slang don't support KEY_SUP. */
case KEY_SUP:
#endif
- retval = sc_seq_or(DO_UP_VOID, *kbinput);
+ retval = sc_seq_or(do_up_void, *kbinput);
break;
case KEY_LEFT:
#ifdef KEY_SLEFT
/* Slang doesn't support KEY_SLEFT. */
case KEY_SLEFT:
#endif
- retval = sc_seq_or(DO_LEFT, *kbinput);
+ retval = sc_seq_or(do_left, *kbinput);
break;
case KEY_RIGHT:
#ifdef KEY_SRIGHT
/* Slang doesn't support KEY_SRIGHT. */
case KEY_SRIGHT:
#endif
- retval = sc_seq_or(DO_RIGHT, *kbinput);
+ retval = sc_seq_or(do_right, *kbinput);
break;
#ifdef KEY_SHOME
/* HP-UX 10-11 and Slang don't support KEY_SHOME. */
@@ -534,36 +535,36 @@ int parse_kbinput(WINDOW *win, bool *meta_key, bool *func_key)
#endif
case KEY_A1: /* Home (7) on numeric keypad with
* NumLock off. */
- retval = sc_seq_or(DO_HOME, *kbinput);
+ retval = sc_seq_or(do_home, *kbinput);
break;
case KEY_BACKSPACE:
- retval = sc_seq_or(DO_BACKSPACE, *kbinput);
+ retval = sc_seq_or(do_backspace, *kbinput);
break;
#ifdef KEY_SDC
/* Slang doesn't support KEY_SDC. */
case KEY_SDC:
if (ISSET(REBIND_DELETE))
- retval = sc_seq_or(DO_DELETE, *kbinput);
+ retval = sc_seq_or(do_delete, *kbinput);
else
- retval = sc_seq_or(DO_BACKSPACE, *kbinput);
+ retval = sc_seq_or(do_backspace, *kbinput);
break;
#endif
#ifdef KEY_SIC
/* Slang doesn't support KEY_SIC. */
case KEY_SIC:
- retval = sc_seq_or(DO_INSERTFILE_VOID, *kbinput);
+ retval = sc_seq_or(do_insertfile_void, *kbinput);
break;
#endif
case KEY_C3: /* PageDown (4) on numeric keypad with
* NumLock off. */
- retval = sc_seq_or(DO_PAGE_DOWN, *kbinput);
+ retval = sc_seq_or(do_page_down, *kbinput);
break;
case KEY_A3: /* PageUp (9) on numeric keypad with
* NumLock off. */
- retval = sc_seq_or(DO_PAGE_UP, *kbinput);
+ retval = sc_seq_or(do_page_up, *kbinput);
break;
case KEY_ENTER:
- retval = sc_seq_or(DO_ENTER, *kbinput);
+ retval = sc_seq_or(do_enter_void, *kbinput);
break;
case KEY_B2: /* Center (5) on numeric keypad with
* NumLock off. */
@@ -575,7 +576,7 @@ int parse_kbinput(WINDOW *win, bool *meta_key, bool *func_key)
/* HP-UX 10-11 and Slang don't support KEY_SEND. */
case KEY_SEND:
#endif
- retval = sc_seq_or(DO_END, *kbinput);
+ retval = sc_seq_or(do_end, *kbinput);
break;
#ifdef KEY_BEG
/* Slang doesn't support KEY_BEG. */
@@ -591,7 +592,7 @@ int parse_kbinput(WINDOW *win, bool *meta_key, bool *func_key)
/* Slang doesn't support KEY_SCANCEL. */
case KEY_SCANCEL:
#endif
- retval = first_sc_for(currmenu, CANCEL_MSG)->seq;
+ retval = first_sc_for(currmenu, do_cancel)->seq;
break;
#endif
#ifdef KEY_SBEG
@@ -604,13 +605,13 @@ int parse_kbinput(WINDOW *win, bool *meta_key, bool *func_key)
#ifdef KEY_SSUSPEND
/* Slang doesn't support KEY_SSUSPEND. */
case KEY_SSUSPEND:
- retval = sc_seq_or(DO_SUSPEND_VOID, 0);
+ retval = sc_seq_or(do_suspend_void, 0);
break;
#endif
#ifdef KEY_SUSPEND
/* Slang doesn't support KEY_SUSPEND. */
case KEY_SUSPEND:
- retval = sc_seq_or(DO_SUSPEND_VOID, 0);
+ retval = sc_seq_or(do_suspend_void, 0);
break;
#endif
#ifdef PDCURSES
@@ -632,16 +633,26 @@ int parse_kbinput(WINDOW *win, bool *meta_key, bool *func_key)
retval = ERR;
break;
#endif
+ case CONTROL_LEFT:
+#ifndef NANO_TINY
+ retval = sc_seq_or(do_prev_word_void, 0);
+#endif
+ break;
+ case CONTROL_RIGHT:
+#ifndef NANO_TINY
+ retval = sc_seq_or(do_next_word_void, 0);
+#endif
+ break;
}
/* If our result is an extended keypad value (i.e. a value
* outside of byte range), set func_key to TRUE. */
if (retval != ERR)
- *func_key = !is_byte(retval);
+ func_key = !is_byte(retval);
}
#ifdef DEBUG
- fprintf(stderr, "parse_kbinput(): kbinput = %d, meta_key = %s, func_key = %s, escapes = %d, byte_digits = %d, retval = %d\n", *kbinput, *meta_key ? "TRUE" : "FALSE", *func_key ? "TRUE" : "FALSE", escapes, byte_digits, retval);
+ fprintf(stderr, "parse_kbinput(): kbinput = %d, meta_key = %s, func_key = %s, escapes = %d, byte_digits = %d, retval = %d\n", *kbinput, meta_key ? "TRUE" : "FALSE", func_key ? "TRUE" : "FALSE", escapes, byte_digits, retval);
#endif
free(kbinput);
@@ -707,11 +718,15 @@ int get_escape_seq_kbinput(const int *seq, size_t seq_len)
* Terminal. */
case 'B': /* Esc O 1 ; 5 B == Ctrl-Down on
* Terminal. */
+ retval = get_escape_seq_abcd(seq[4]);
+ break;
case 'C': /* Esc O 1 ; 5 C == Ctrl-Right on
* Terminal. */
+ retval = CONTROL_RIGHT;
+ break;
case 'D': /* Esc O 1 ; 5 D == Ctrl-Left on
* Terminal. */
- retval = get_escape_seq_abcd(seq[4]);
+ retval = CONTROL_LEFT;
break;
}
}
@@ -758,15 +773,15 @@ int get_escape_seq_kbinput(const int *seq, size_t seq_len)
retval = KEY_B2;
break;
case 'F': /* Esc O F == End on xterm/Terminal. */
- retval = sc_seq_or(DO_END, 0);
+ retval = sc_seq_or(do_end, 0);
break;
case 'H': /* Esc O H == Home on xterm/Terminal. */
- retval = sc_seq_or(DO_HOME, 0);;
+ retval = sc_seq_or(do_home, 0);
break;
case 'M': /* Esc O M == Enter on numeric keypad with
* NumLock off on VT100/VT220/VT320/xterm/
* rxvt/Eterm. */
- retval = sc_seq_or(DO_HOME, 0);;
+ retval = sc_seq_or(do_home, 0);
break;
case 'P': /* Esc O P == F1 on VT100/VT220/VT320/Mach
* console. */
@@ -804,9 +819,13 @@ int get_escape_seq_kbinput(const int *seq, size_t seq_len)
break;
case 'a': /* Esc O a == Ctrl-Up on rxvt. */
case 'b': /* Esc O b == Ctrl-Down on rxvt. */
+ retval = get_escape_seq_abcd(seq[1]);
+ break;
case 'c': /* Esc O c == Ctrl-Right on rxvt. */
+ retval = CONTROL_RIGHT;
+ break;
case 'd': /* Esc O d == Ctrl-Left on rxvt. */
- retval = get_escape_seq_abcd(seq[1]);
+ retval = CONTROL_LEFT;
break;
case 'j': /* Esc O j == '*' on numeric keypad with
* NumLock off on VT100/VT220/VT320/xterm/
@@ -831,7 +850,7 @@ int get_escape_seq_kbinput(const int *seq, size_t seq_len)
case 'n': /* Esc O n == Delete (.) on numeric keypad
* with NumLock off on VT100/VT220/VT320/
* xterm/rxvt/Eterm/Terminal. */
- retval = sc_seq_or(DO_DELETE, 0);;
+ retval = sc_seq_or(do_delete, 0);
break;
case 'o': /* Esc O o == '/' on numeric keypad with
* NumLock off on VT100/VT220/VT320/xterm/
@@ -841,27 +860,27 @@ int get_escape_seq_kbinput(const int *seq, size_t seq_len)
case 'p': /* Esc O p == Insert (0) on numeric keypad
* with NumLock off on VT100/VT220/VT320/
* rxvt/Eterm/Terminal. */
- retval = sc_seq_or(DO_INSERTFILE_VOID, 0);;
+ retval = sc_seq_or(do_insertfile_void, 0);
break;
case 'q': /* Esc O q == End (1) on numeric keypad
* with NumLock off on VT100/VT220/VT320/
* rxvt/Eterm/Terminal. */
- retval = sc_seq_or(DO_END, 0);;
+ retval = sc_seq_or(do_end, 0);
break;
case 'r': /* Esc O r == Down (2) on numeric keypad
* with NumLock off on VT100/VT220/VT320/
* rxvt/Eterm/Terminal. */
- retval = sc_seq_or(DO_DOWN_VOID, 0);;
+ retval = sc_seq_or(do_down_void, 0);
break;
case 's': /* Esc O s == PageDown (3) on numeric
* keypad with NumLock off on VT100/VT220/
* VT320/rxvt/Eterm/Terminal. */
- retval = sc_seq_or(DO_PAGE_DOWN, 0);;
+ retval = sc_seq_or(do_page_down, 0);
break;
case 't': /* Esc O t == Left (4) on numeric keypad
* with NumLock off on VT100/VT220/VT320/
* rxvt/Eterm/Terminal. */
- retval = sc_seq_or(DO_LEFT, 0);;
+ retval = sc_seq_or(do_left, 0);
break;
case 'u': /* Esc O u == Center (5) on numeric keypad
* with NumLock off on VT100/VT220/VT320/
@@ -871,22 +890,22 @@ int get_escape_seq_kbinput(const int *seq, size_t seq_len)
case 'v': /* Esc O v == Right (6) on numeric keypad
* with NumLock off on VT100/VT220/VT320/
* rxvt/Eterm/Terminal. */
- retval = sc_seq_or(DO_RIGHT, 0);
+ retval = sc_seq_or(do_right, 0);
break;
case 'w': /* Esc O w == Home (7) on numeric keypad
* with NumLock off on VT100/VT220/VT320/
* rxvt/Eterm/Terminal. */
- retval = sc_seq_or(DO_HOME, 0);
+ retval = sc_seq_or(do_home, 0);
break;
case 'x': /* Esc O x == Up (8) on numeric keypad
* with NumLock off on VT100/VT220/VT320/
* rxvt/Eterm/Terminal. */
- retval = sc_seq_or(DO_UP_VOID, 0);
+ retval = sc_seq_or(do_up_void, 0);
break;
case 'y': /* Esc O y == PageUp (9) on numeric keypad
* with NumLock off on VT100/VT220/VT320/
* rxvt/Eterm/Terminal. */
- retval = sc_seq_or(DO_PAGE_UP, 0);
+ retval = sc_seq_or(do_page_up, 0);
break;
}
break;
@@ -894,9 +913,13 @@ int get_escape_seq_kbinput(const int *seq, size_t seq_len)
switch (seq[1]) {
case 'a': /* Esc o a == Ctrl-Up on Eterm. */
case 'b': /* Esc o b == Ctrl-Down on Eterm. */
+ retval = get_escape_seq_abcd(seq[1]);
+ break;
case 'c': /* Esc o c == Ctrl-Right on Eterm. */
+ retval = CONTROL_RIGHT;
+ break;
case 'd': /* Esc o d == Ctrl-Left on Eterm. */
- retval = get_escape_seq_abcd(seq[1]);
+ retval = CONTROL_LEFT;
break;
}
break;
@@ -966,11 +989,15 @@ int get_escape_seq_kbinput(const int *seq, size_t seq_len)
* xterm. */
case 'B': /* Esc [ 1 ; 5 B == Ctrl-Down on
* xterm. */
+ retval = get_escape_seq_abcd(seq[4]);
+ break;
case 'C': /* Esc [ 1 ; 5 C == Ctrl-Right on
* xterm. */
+ retval = CONTROL_RIGHT;
+ break;
case 'D': /* Esc [ 1 ; 5 D == Ctrl-Left on
* xterm. */
- retval = get_escape_seq_abcd(seq[4]);
+ retval = CONTROL_LEFT;
break;
}
}
@@ -980,7 +1007,7 @@ int get_escape_seq_kbinput(const int *seq, size_t seq_len)
break;
default: /* Esc [ 1 ~ == Home on
* VT320/Linux console. */
- retval = sc_seq_or(DO_HOME, 0);;
+ retval = sc_seq_or(do_home, 0);
break;
}
}
@@ -1031,40 +1058,40 @@ int get_escape_seq_kbinput(const int *seq, size_t seq_len)
default: /* Esc [ 2 ~ == Insert on
* VT220/VT320/Linux console/
* xterm/Terminal. */
- retval = sc_seq_or(DO_INSERTFILE_VOID, 0);;
+ retval = sc_seq_or(do_insertfile_void, 0);
break;
}
}
break;
case '3': /* Esc [ 3 ~ == Delete on VT220/VT320/
* Linux console/xterm/Terminal. */
- retval = sc_seq_or(DO_DELETE, 0);;
+ retval = sc_seq_or(do_delete, 0);
break;
case '4': /* Esc [ 4 ~ == End on VT220/VT320/Linux
* console/xterm. */
- retval = sc_seq_or(DO_END, 0);;
+ retval = sc_seq_or(do_end, 0);
break;
case '5': /* Esc [ 5 ~ == PageUp on VT220/VT320/
* Linux console/xterm/Terminal;
* Esc [ 5 ^ == PageUp on Eterm. */
- retval = sc_seq_or(DO_PAGE_UP, 0);;
+ retval = sc_seq_or(do_page_up, 0);
break;
case '6': /* Esc [ 6 ~ == PageDown on VT220/VT320/
* Linux console/xterm/Terminal;
- * Esc [ 6 ^ == PageDown on Eterm. */
- retval = sc_seq_or(DO_PAGE_DOWN, 0);;
+ * Esc [ 6 ^ == PageDown on Eterm. */
+ retval = sc_seq_or(do_page_down, 0);
break;
case '7': /* Esc [ 7 ~ == Home on rxvt. */
- retval = sc_seq_or(DO_HOME, 0);
+ retval = sc_seq_or(do_home, 0);
break;
case '8': /* Esc [ 8 ~ == End on rxvt. */
- retval = sc_seq_or(DO_END, 0);
+ retval = sc_seq_or(do_end, 0);
break;
case '9': /* Esc [ 9 == Delete on Mach console. */
- retval = sc_seq_or(DO_DELETE, 0);;
+ retval = sc_seq_or(do_delete, 0);
break;
case '@': /* Esc [ @ == Insert on Mach console. */
- retval = sc_seq_or(DO_INSERTFILE_VOID, 0);;
+ retval = sc_seq_or(do_insertfile_void, 0);
break;
case 'A': /* Esc [ A == Up on ANSI/VT220/Linux
* console/FreeBSD console/Mach console/
@@ -1087,23 +1114,23 @@ int get_escape_seq_kbinput(const int *seq, size_t seq_len)
break;
case 'F': /* Esc [ F == End on FreeBSD
* console/Eterm. */
- retval = sc_seq_or(DO_END, 0);
+ retval = sc_seq_or(do_end, 0);
break;
case 'G': /* Esc [ G == PageDown on FreeBSD
* console. */
- retval = sc_seq_or(DO_PAGE_DOWN, 0);
+ retval = sc_seq_or(do_page_down, 0);
break;
case 'H': /* Esc [ H == Home on ANSI/VT220/FreeBSD
* console/Mach console/Eterm. */
- retval = sc_seq_or(DO_HOME, 0);
+ retval = sc_seq_or(do_home, 0);
break;
case 'I': /* Esc [ I == PageUp on FreeBSD
* console. */
- retval = sc_seq_or(DO_PAGE_UP, 0);
+ retval = sc_seq_or(do_page_up, 0);
break;
case 'L': /* Esc [ L == Insert on ANSI/FreeBSD
* console. */
- retval = sc_seq_or(DO_INSERTFILE_VOID, 0);
+ retval = sc_seq_or(do_insertfile_void, 0);
break;
case 'M': /* Esc [ M == F1 on FreeBSD console. */
retval = KEY_F(1);
@@ -1151,10 +1178,10 @@ int get_escape_seq_kbinput(const int *seq, size_t seq_len)
retval = KEY_F(8);
break;
case 'U': /* Esc [ U == PageDown on Mach console. */
- retval = sc_seq_or(DO_PAGE_DOWN, 0);
+ retval = sc_seq_or(do_page_down, 0);
break;
case 'V': /* Esc [ V == PageUp on Mach console. */
- retval = sc_seq_or(DO_PAGE_UP, 0);
+ retval = sc_seq_or(do_page_up, 0);
break;
case 'W': /* Esc [ W == F11 on FreeBSD console. */
retval = KEY_F(11);
@@ -1163,7 +1190,7 @@ int get_escape_seq_kbinput(const int *seq, size_t seq_len)
retval = KEY_F(12);
break;
case 'Y': /* Esc [ Y == End on Mach console. */
- retval = sc_seq_or(DO_END, 0);
+ retval = sc_seq_or(do_end, 0);
break;
case 'Z': /* Esc [ Z == F14 on FreeBSD console. */
retval = KEY_F(14);
@@ -1220,13 +1247,13 @@ int get_escape_seq_abcd(int kbinput)
{
switch (tolower(kbinput)) {
case 'a':
- return sc_seq_or(DO_UP_VOID, 0);;
+ return sc_seq_or(do_up_void, 0);
case 'b':
- return sc_seq_or(DO_DOWN_VOID, 0);;
+ return sc_seq_or(do_down_void, 0);
case 'c':
- return sc_seq_or(DO_RIGHT, 0);;
+ return sc_seq_or(do_right, 0);
case 'd':
- return sc_seq_or(DO_LEFT, 0);;
+ return sc_seq_or(do_left, 0);
default:
return ERR;
}
@@ -1301,15 +1328,13 @@ int get_byte_kbinput(int kbinput)
break;
case 3:
/* Third digit: This must be from zero to five if the first
- * was two and the second was between zero and five, and may
- * be any decimal value if the first was zero or one and the
- * second was between six and nine. Put it in the 1's
- * position of the byte sequence holder. */
+ * was two and the second was five, and may be any decimal
+ * value otherwise. Put it in the 1's position of the byte
+ * sequence holder. */
if (('0' <= kbinput && kbinput <= '5') || (byte < 250 &&
'6' <= kbinput && kbinput <= '9')) {
byte += kbinput - '0';
- /* If this character is a valid decimal value, then the
- * byte sequence is complete. */
+ /* The byte sequence is complete. */
retval = byte;
} else
/* This isn't the third digit of a byte sequence.
@@ -1531,7 +1556,8 @@ int *parse_verbatim_kbinput(WINDOW *win, size_t *kbinput_len)
int *kbinput, *retval;
/* Read in the first keystroke. */
- while ((kbinput = get_input(win, 1)) == NULL);
+ while ((kbinput = get_input(win, 1)) == NULL)
+ ;
#ifdef ENABLE_UTF8
if (using_utf8()) {
@@ -1557,8 +1583,8 @@ int *parse_verbatim_kbinput(WINDOW *win, size_t *kbinput_len)
statusbar(_("Unicode Input"));
while (uni == ERR) {
- while ((kbinput = get_input(win, 1)) == NULL);
-
+ while ((kbinput = get_input(win, 1)) == NULL)
+ ;
uni = get_unicode_kbinput(*kbinput);
}
@@ -1638,8 +1664,7 @@ int get_mouseinput(int *mouse_x, int *mouse_y, bool allow_shortcuts)
/* The width of all the shortcuts, except for the last
* two, in the shortcut list in bottomwin. */
int j;
- /* The y-coordinate relative to the beginning of the
- * shortcut list in bottomwin. */
+ /* The calculated index number of the clicked item. */
size_t currslen;
/* The number of shortcuts in the current shortcut
* list. */
@@ -1659,10 +1684,6 @@ int get_mouseinput(int *mouse_x, int *mouse_y, bool allow_shortcuts)
return 0;
}
- /* Calculate the y-coordinate relative to the beginning of
- * the shortcut list in bottomwin. */
- j = *mouse_y - 1;
-
/* Get the shortcut lists' length. */
if (currmenu == MMAIN)
currslen = MAIN_VISIBLE;
@@ -1683,44 +1704,46 @@ int get_mouseinput(int *mouse_x, int *mouse_y, bool allow_shortcuts)
else
i = COLS / ((currslen / 2) + (currslen % 2));
- /* Calculate the x-coordinate relative to the beginning of
- * the shortcut list in bottomwin, and add it to j. j
- * should now be the index in the shortcut list of the
- * shortcut we released/clicked on. */
- j = (*mouse_x / i) * 2 + j;
+ /* Calculate the one-based index in the shortcut list. */
+ j = (*mouse_x / i) * 2 + *mouse_y;
- /* Adjust j if we released on the last two shortcuts. */
- if ((j >= currslen) && (*mouse_x % i < COLS % i))
+ /* Adjust the index if we hit the last two wider ones. */
+ if ((j > currslen) && (*mouse_x % i < COLS % i))
j -= 2;
-
+#ifdef DEBUG
+ fprintf(stderr, "Calculated %i as index in shortcut list, currmenu = %x.\n", j, currmenu);
+#endif
/* Ignore releases/clicks of the first mouse button beyond
* the last shortcut. */
- if (j >= currslen)
+ if (j > currslen)
return 2;
- /* Go through the shortcut list to determine which shortcut
- * we released/clicked on. */
- f = allfuncs;
-
- for (; j > 0; j--) {
- if (f->next != NULL)
- f = f->next;
-
- while (f->next != NULL && ((f->menus & currmenu) == 0
+ /* Go through the list of functions to determine which
+ * shortcut in the current menu we released/clicked on. */
+ for (f = allfuncs; f != NULL; f = f->next) {
+ if ((f->menus & currmenu) == 0)
+ continue;
#ifndef DISABLE_HELP
- || strlen(f->help) == 0
+ if (!f->help || strlen(f->help) == 0)
+ continue;
#endif
- ))
- f = f->next;
+ if (first_sc_for(currmenu, f->scfunc) == NULL)
+ continue;
+ /* Tick off an actually shown shortcut. */
+ j -= 1;
+ if (j == 0)
+ break;
}
+#ifdef DEBUG
+ fprintf(stderr, "Stopped on func %ld present in menus %x\n", (long)f->scfunc, f->menus);
+#endif
-
- /* And put back the equivalent key. */
+ /* And put the corresponding key into the keyboard buffer. */
if (f != NULL) {
- const sc *s = first_sc_for(currmenu, f->scfunc);
- if (s != NULL)
- unget_kbinput(s->seq, s->type == META, FALSE);
+ const sc *s = first_sc_for(currmenu, f->scfunc);
+ unget_kbinput(s->seq, s->type == META, s->type == FKEY);
}
+ return 1;
} else
/* Handle releases/clicks of the first mouse button that
* aren't on the current shortcut list elsewhere. */
@@ -1746,8 +1769,8 @@ int get_mouseinput(int *mouse_x, int *mouse_y, bool allow_shortcuts)
* wheel is equivalent to moving down three lines. */
for (i = 0; i < 3; i++)
unget_kbinput((mevent.bstate & BUTTON4_PRESSED) ?
- sc_seq_or(DO_UP_VOID, 0) : sc_seq_or(DO_DOWN_VOID, 0), FALSE,
- FALSE);
+ sc_seq_or(do_up_void, 0) : sc_seq_or(do_down_void, 0),
+ FALSE, FALSE);
return 1;
} else
@@ -1763,67 +1786,35 @@ int get_mouseinput(int *mouse_x, int *mouse_y, bool allow_shortcuts)
}
#endif /* !DISABLE_MOUSE */
-/* Return the shortcut corresponding to the values of kbinput (the key
- * itself), meta_key (whether the key is a meta sequence), and func_key
- * (whether the key is a function key), if any. The shortcut will be
- * the first one in the list (control key, meta key sequence, function
- * key, other meta key sequence) for the corresponding function. For
- * example, passing in a meta key sequence that corresponds to a
- * function with a control key, a function key, and a meta key sequence
- * will return the control key corresponding to that function. */
-const sc *get_shortcut(int menu, int *kbinput, bool
- *meta_key, bool *func_key)
+/* Return the shortcut that corresponds to the values of kbinput (the
+ * key itself) and meta_key (whether the key is a meta sequence). The
+ * returned shortcut will be the first in the list that corresponds to
+ * the given sequence. */
+const sc *get_shortcut(int *kbinput)
{
sc *s;
#ifdef DEBUG
- fprintf(stderr, "get_shortcut(): kbinput = %d, meta_key = %s, func_key = %s\n", *kbinput, *meta_key ? "TRUE" : "FALSE", *func_key ? "TRUE" : "FALSE");
+ fprintf(stderr, "get_shortcut(): kbinput = %d, meta_key = %s -- ", *kbinput, meta_key ? "TRUE" : "FALSE");
#endif
- /* Check for shortcuts. */
for (s = sclist; s != NULL; s = s->next) {
- if ((menu & s->menu)
- && ((s->type == META && *meta_key == TRUE && *kbinput == s->seq)
- || (s->type != META && *kbinput == s->seq))) {
+ if ((currmenu & s->menu) && *kbinput == s->seq
+ && meta_key == (s->type == META)) {
#ifdef DEBUG
- fprintf (stderr, "matched seq \"%s\" and btw meta was %d (menus %d = %d)\n", s->keystr, *meta_key, menu, s->menu);
+ fprintf (stderr, "matched seq \"%s\", and btw meta was %d (menu is %x from %x)\n",
+ s->keystr, meta_key, currmenu, s->menu);
#endif
return s;
}
}
#ifdef DEBUG
- fprintf (stderr, "matched nothing btw meta was %d\n", *meta_key);
+ fprintf (stderr, "matched nothing, btw meta was %d\n", meta_key);
#endif
return NULL;
}
-
-/* Try to get a function back from a window. Just a wrapper so
- functions to need to create function_key meta_key blah blah
- mmenu - what menu name to look through for valid funcs */
-const subnfunc *getfuncfromkey(WINDOW *win)
-{
- int kbinput;
- bool func_key = FALSE, meta_key = FALSE;
- const sc *s;
- const subnfunc *f;
-
- kbinput = parse_kbinput(win, &meta_key, &func_key);
- if (kbinput == 0)
- return NULL;
-
- s = get_shortcut(currmenu, &kbinput, &meta_key, &func_key);
- if (!s)
- return NULL;
-
- f = sctofunc((sc *) s);
- return f;
-
-}
-
-
-
/* Move to (x, y) in win, and display a line of n spaces with the
* current attributes. */
void blank_line(WINDOW *win, int y, int x, int n)
@@ -1999,7 +1990,7 @@ char *display_string(const char *buf, size_t start_col, size_t len, bool
/* If buf contains a tab character, interpret it. */
if (*buf_mb == '\t') {
-#if !defined(NANO_TINY) && defined(ENABLE_NANORC)
+#if !defined(NANO_TINY) && !defined(DISABLE_NANORC)
if (ISSET(WHITESPACE_DISPLAY)) {
int i;
@@ -2015,7 +2006,7 @@ char *display_string(const char *buf, size_t start_col, size_t len, bool
}
/* If buf contains a control character, interpret it. If buf
* contains an invalid multibyte control character, display it
- * as such.*/
+ * as such. */
} else if (is_cntrl_mbchar(buf_mb)) {
char *ctrl_buf_mb = charalloc(mb_cur_max());
int ctrl_buf_mb_len, i;
@@ -2034,7 +2025,7 @@ char *display_string(const char *buf, size_t start_col, size_t len, bool
free(ctrl_buf_mb);
/* If buf contains a space character, interpret it. */
} else if (*buf_mb == ' ') {
-#if !defined(NANO_TINY) && defined(ENABLE_NANORC)
+#if !defined(NANO_TINY) && !defined(DISABLE_NANORC)
if (ISSET(WHITESPACE_DISPLAY)) {
int i;
@@ -2113,7 +2104,9 @@ void titlebar(const char *path)
assert(path != NULL || openfile->filename != NULL);
- wattron(topwin, reverse_attr);
+ if (interface_color_pair[TITLE_BAR].bright)
+ wattron(topwin, A_BOLD);
+ wattron(topwin, interface_color_pair[TITLE_BAR].pairnum);
blank_titlebar();
@@ -2244,7 +2237,8 @@ void titlebar(const char *path)
}
}
- wattroff(topwin, reverse_attr);
+ wattroff(topwin, A_BOLD);
+ wattroff(topwin, interface_color_pair[TITLE_BAR].pairnum);
wnoutrefresh(topwin);
reset_cursor();
@@ -2258,6 +2252,19 @@ void set_modified(void)
if (!openfile->modified) {
openfile->modified = TRUE;
titlebar(NULL);
+#ifndef NANO_TINY
+ if (ISSET(LOCKING)) {
+ if (openfile->filename[0] == '\0')
+ return;
+ else if (openfile->lock_filename == NULL) {
+ /* TRANSLATORS: Try to keep this at most 76 characters. */
+ statusbar(_("Warning: Modifying a file which is not locked, check directory permission?"));
+ } else {
+ write_lockfile(openfile->lock_filename,
+ get_full_path(openfile->filename), TRUE);
+ }
+ }
+#endif
}
}
@@ -2268,8 +2275,8 @@ void statusbar(const char *msg, ...)
{
va_list ap;
char *bar, *foo;
- size_t start_x, foo_len;
-#if !defined(NANO_TINY) && defined(ENABLE_NANORC)
+ size_t start_x;
+#if !defined(NANO_TINY) && !defined(DISABLE_NANORC)
bool old_whitespace;
#endif
@@ -2285,7 +2292,7 @@ void statusbar(const char *msg, ...)
blank_statusbar();
-#if !defined(NANO_TINY) && defined(ENABLE_NANORC)
+#if !defined(NANO_TINY) && !defined(DISABLE_NANORC)
old_whitespace = ISSET(WHITESPACE_DISPLAY);
UNSET(WHITESPACE_DISPLAY);
#endif
@@ -2293,21 +2300,23 @@ void statusbar(const char *msg, ...)
vsnprintf(bar, mb_cur_max() * (COLS - 3), msg, ap);
va_end(ap);
foo = display_string(bar, 0, COLS - 4, FALSE);
-#if !defined(NANO_TINY) && defined(ENABLE_NANORC)
+ free(bar);
+#if !defined(NANO_TINY) && !defined(DISABLE_NANORC)
if (old_whitespace)
SET(WHITESPACE_DISPLAY);
#endif
- free(bar);
- foo_len = strlenpt(foo);
- start_x = (COLS - foo_len - 4) / 2;
+ start_x = (COLS - strlenpt(foo) - 4) / 2;
wmove(bottomwin, 0, start_x);
- wattron(bottomwin, reverse_attr);
+ if (interface_color_pair[STATUS_BAR].bright)
+ wattron(bottomwin, A_BOLD);
+ wattron(bottomwin, interface_color_pair[STATUS_BAR].pairnum);
waddstr(bottomwin, "[ ");
waddstr(bottomwin, foo);
free(foo);
waddstr(bottomwin, " ]");
- wattroff(bottomwin, reverse_attr);
+ wattroff(bottomwin, A_BOLD);
+ wattroff(bottomwin, interface_color_pair[STATUS_BAR].pairnum);
wnoutrefresh(bottomwin);
reset_cursor();
wnoutrefresh(edit);
@@ -2365,30 +2374,27 @@ void bottombars(int menu)
for (f = allfuncs, i = 0; i < slen && f != NULL; f = f->next) {
#ifdef DEBUG
- fprintf(stderr, "Checking menu items....");
+ fprintf(stderr, "Checking menu items....");
#endif
- if ((f->menus & menu) == 0)
- continue;
-
- if (!f->desc || strlen(f->desc) == 0)
+ if ((f->menus & menu) == 0)
continue;
#ifdef DEBUG
- fprintf(stderr, "found one! f->menus = %d, desc = \"%s\"\n", f->menus, f->desc);
+ fprintf(stderr, "found one! f->menus = %x, desc = \"%s\"\n", f->menus, f->desc);
#endif
- s = first_sc_for(menu, f->scfunc);
- if (s == NULL) {
+ s = first_sc_for(menu, f->scfunc);
+ if (s == NULL) {
#ifdef DEBUG
fprintf(stderr, "Whoops, guess not, no shortcut key found for func!\n");
#endif
- continue;
- }
+ continue;
+ }
wmove(bottomwin, 1 + i % 2, (i / 2) * colwidth);
#ifdef DEBUG
- fprintf(stderr, "Calling onekey with keystr \"%s\" and desc \"%s\"\n", s->keystr, f->desc);
+ fprintf(stderr, "Calling onekey with keystr \"%s\" and desc \"%s\"\n", s->keystr, f->desc);
#endif
onekey(s->keystr, _(f->desc), colwidth + (COLS % colwidth));
- i++;
+ i++;
}
wnoutrefresh(bottomwin);
@@ -2407,9 +2413,12 @@ void onekey(const char *keystroke, const char *desc, size_t len)
assert(keystroke != NULL && desc != NULL);
- wattron(bottomwin, reverse_attr);
+ if (interface_color_pair[KEY_COMBO].bright)
+ wattron(bottomwin, A_BOLD);
+ wattron(bottomwin, interface_color_pair[KEY_COMBO].pairnum);
waddnstr(bottomwin, keystroke, actual_x(keystroke, len));
- wattroff(bottomwin, reverse_attr);
+ wattroff(bottomwin, A_BOLD);
+ wattroff(bottomwin, interface_color_pair[KEY_COMBO].pairnum);
if (len > keystroke_len)
len -= keystroke_len;
@@ -2418,7 +2427,12 @@ void onekey(const char *keystroke, const char *desc, size_t len)
if (len > 0) {
waddch(bottomwin, ' ');
+ if (interface_color_pair[FUNCTION_TAG].bright)
+ wattron(bottomwin, A_BOLD);
+ wattron(bottomwin, interface_color_pair[FUNCTION_TAG].pairnum);
waddnstr(bottomwin, desc, actual_x(desc, len));
+ wattroff(bottomwin, A_BOLD);
+ wattroff(bottomwin, interface_color_pair[FUNCTION_TAG].pairnum);
}
}
@@ -2436,17 +2450,20 @@ void reset_cursor(void)
xpt = xplustabs();
+#ifndef NANO_TINY
if (ISSET(SOFTWRAP)) {
filestruct *tmp;
openfile->current_y = 0;
for (tmp = openfile->edittop; tmp && tmp != openfile->current; tmp = tmp->next)
- openfile->current_y += 1 + strlenpt(tmp->data) / COLS;
+ openfile->current_y += (strlenpt(tmp->data) / COLS) + 1;
openfile->current_y += xplustabs() / COLS;
if (openfile->current_y < editwinrows)
wmove(edit, openfile->current_y, xpt % COLS);
- } else {
+ } else
+#endif
+ {
openfile->current_y = openfile->current->lineno -
openfile->edittop->lineno;
@@ -2466,7 +2483,7 @@ void reset_cursor(void)
void edit_draw(filestruct *fileptr, const char *converted, int
line, size_t start)
{
-#if !defined(NANO_TINY) || defined(ENABLE_COLOR)
+#if !defined(NANO_TINY) || !defined(DISABLE_COLOR)
size_t startpos = actual_x(fileptr->data, start);
/* The position in fileptr->data of the leftmost character
* that displays at least partially on the window. */
@@ -2481,23 +2498,32 @@ void edit_draw(filestruct *fileptr, const char *converted, int
assert(openfile != NULL && fileptr != NULL && converted != NULL);
assert(strlenpt(converted) <= COLS);
- /* Just paint the string in any case (we'll add color or reverse on
- * just the text that needs it). */
+ /* First simply paint the line -- then we'll add colors or the
+ * marking highlight on just the pieces that need it. */
mvwaddstr(edit, line, 0, converted);
-#ifdef ENABLE_COLOR
+#ifndef USE_SLANG
+ /* Tell ncurses to really redraw the line without trying to optimize
+ * for what it thinks is already there, because it gets it wrong in
+ * the case of a wide character in column zero. See bug #31743. */
+ wredrawln(edit, line, 1);
+#endif
+
+#ifndef DISABLE_COLOR
/* If color syntaxes are available and turned on, we need to display
* them. */
if (openfile->colorstrings != NULL && !ISSET(NO_COLOR_SYNTAX)) {
const colortype *tmpcolor = openfile->colorstrings;
- /* Set up multi-line color data for this line if it's not yet calculated */
- if (fileptr->multidata == NULL && openfile->syntax
+ /* Set up multi-line color data for this line if it's not yet
+ * calculated. */
+ if (fileptr->multidata == NULL && openfile->syntax
&& openfile->syntax->nmultis > 0) {
- int i;
- fileptr->multidata = (short *) nmalloc(openfile->syntax->nmultis * sizeof(short));
- for (i = 0; i < openfile->syntax->nmultis; i++)
- fileptr->multidata[i] = -1; /* Assue this applies until we know otherwise */
+ int i;
+ fileptr->multidata = (short *)nmalloc(openfile->syntax->nmultis * sizeof(short));
+ for (i = 0; i < openfile->syntax->nmultis; i++)
+ /* Assume this applies until we know otherwise. */
+ fileptr->multidata[i] = -1;
}
for (; tmpcolor != NULL; tmpcolor = tmpcolor->next) {
int x_start;
@@ -2584,18 +2610,19 @@ void edit_draw(filestruct *fileptr, const char *converted, int
short md = fileptr->multidata[tmpcolor->id];
if (md == -1)
- fileptr->multidata[tmpcolor->id] = CNONE; /* until we find out otherwise */
+ /* Assume this until we know otherwise. */
+ fileptr->multidata[tmpcolor->id] = CNONE;
else if (md == CNONE)
- continue;
+ goto end_of_loop;
else if (md == CWHOLELINE) {
mvwaddnstr(edit, line, 0, converted, -1);
- continue;
+ goto end_of_loop;
} else if (md == CBEGINBEFORE) {
regexec(tmpcolor->end, fileptr->data, 1, &endmatch, 0);
paintlen = actual_x(converted, strnlenpt(fileptr->data,
endmatch.rm_eo) - start);
mvwaddnstr(edit, line, 0, converted, paintlen);
- continue;
+ goto end_of_loop;
}
while (start_line != NULL && regexec(tmpcolor->start,
@@ -2745,12 +2772,12 @@ void edit_draw(filestruct *fileptr, const char *converted, int
}
}
}
-
+ end_of_loop:
wattroff(edit, A_BOLD);
wattroff(edit, COLOR_PAIR(tmpcolor->pairnum));
}
}
-#endif /* ENABLE_COLOR */
+#endif /* !DISABLE_COLOR */
#ifndef NANO_TINY
/* If the mark is on, we need to display it. */
@@ -2815,10 +2842,10 @@ void edit_draw(filestruct *fileptr, const char *converted, int
if (paintlen > 0)
paintlen = actual_x(converted + index, paintlen);
- wattron(edit, reverse_attr);
+ wattron(edit, hilite_attribute);
mvwaddnstr(edit, line, x_start, converted + index,
paintlen);
- wattroff(edit, reverse_attr);
+ wattroff(edit, hilite_attribute);
}
}
#endif /* !NANO_TINY */
@@ -2827,26 +2854,27 @@ void edit_draw(filestruct *fileptr, const char *converted, int
/* Just update one line in the edit buffer. This is basically a wrapper
* for edit_draw(). The line will be displayed starting with
* fileptr->data[index]. Likely arguments are current_x or zero.
- * Returns: Number of additiona lines consumed (needed for SOFTWRAP)
- */
+ * Returns: Number of additional lines consumed (needed for SOFTWRAP). */
int update_line(filestruct *fileptr, size_t index)
{
int line = 0;
- int extralinesused = 0;
/* The line in the edit window that we want to update. */
+ int extralinesused = 0;
char *converted;
/* fileptr->data converted to have tabs and control characters
* expanded. */
size_t page_start;
- filestruct *tmp;
assert(fileptr != NULL);
+#ifndef NANO_TINY
if (ISSET(SOFTWRAP)) {
- for (tmp = openfile->edittop; tmp && tmp != fileptr; tmp = tmp->next) {
- line += 1 + (strlenpt(tmp->data) / COLS);
- }
+ filestruct *tmp;
+
+ for (tmp = openfile->edittop; tmp && tmp != fileptr; tmp = tmp->next)
+ line += (strlenpt(tmp->data) / COLS) + 1;
} else
+#endif
line = fileptr->lineno - openfile->edittop->lineno;
if (line < 0 || line >= editwinrows)
@@ -2857,42 +2885,49 @@ int update_line(filestruct *fileptr, size_t index)
/* Next, convert variables that index the line to their equivalent
* positions in the expanded line. */
+#ifndef NANO_TINY
if (ISSET(SOFTWRAP))
index = 0;
else
+#endif
index = strnlenpt(fileptr->data, index);
page_start = get_page_start(index);
/* Expand the line, replacing tabs with spaces, and control
* characters with their displayed forms. */
+#ifdef NANO_TINY
+ converted = display_string(fileptr->data, page_start, COLS, TRUE);
+#else
converted = display_string(fileptr->data, page_start, COLS, !ISSET(SOFTWRAP));
-
#ifdef DEBUG
if (ISSET(SOFTWRAP) && strlen(converted) >= COLS - 2)
- fprintf(stderr, "update_line(): converted(1) line = %s\n", converted);
+ fprintf(stderr, "update_line(): converted(1) line = %s\n", converted);
#endif
-
+#endif /* !NANO_TINY */
/* Paint the line. */
edit_draw(fileptr, converted, line, page_start);
free(converted);
+#ifndef NANO_TINY
if (!ISSET(SOFTWRAP)) {
+#endif
if (page_start > 0)
mvwaddch(edit, line, 0, '$');
if (strlenpt(fileptr->data) > page_start + COLS)
mvwaddch(edit, line, COLS - 1, '$');
+#ifndef NANO_TINY
} else {
- int full_length = strlenpt(fileptr->data);
+ size_t full_length = strlenpt(fileptr->data);
for (index += COLS; index <= full_length && line < editwinrows; index += COLS) {
line++;
#ifdef DEBUG
- fprintf(stderr, "update_line(): Softwrap code, moving to %d index %lu\n", line, (unsigned long) index);
+ fprintf(stderr, "update_line(): softwrap code, moving to %d index %lu\n", line, (unsigned long)index);
#endif
- blank_line(edit, line, 0, COLS);
+ blank_line(edit, line, 0, COLS);
/* Expand the line, replacing tabs with spaces, and control
- * characters with their displayed forms. */
+ * characters with their displayed forms. */
converted = display_string(fileptr->data, index, COLS, !ISSET(SOFTWRAP));
#ifdef DEBUG
if (ISSET(SOFTWRAP) && strlen(converted) >= COLS - 2)
@@ -2901,10 +2936,11 @@ int update_line(filestruct *fileptr, size_t index)
/* Paint the line. */
edit_draw(fileptr, converted, line, index);
- free(converted);
+ free(converted);
extralinesused++;
}
}
+#endif /* !NANO_TINY */
return extralinesused;
}
@@ -2935,8 +2971,7 @@ bool need_vertical_update(size_t pww_save)
}
/* When edittop changes, try and figure out how many lines
- * we really have to work with (i.e. set maxrows)
- */
+ * we really have to work with (i.e. set maxrows). */
void compute_maxrows(void)
{
int n;
@@ -2949,7 +2984,7 @@ void compute_maxrows(void)
maxrows = 0;
for (n = 0; n < editwinrows && foo; n++) {
- maxrows ++;
+ maxrows++;
n += strlenpt(foo->data) / COLS;
foo = foo->next;
}
@@ -2958,20 +2993,20 @@ void compute_maxrows(void)
maxrows += editwinrows - n;
#ifdef DEBUG
- fprintf(stderr, "compute_maxrows(): maxrows = %ld\n", maxrows);
+ fprintf(stderr, "compute_maxrows(): maxrows = %d\n", maxrows);
#endif
}
/* Scroll the edit window in the given direction and the given number
* of lines, and draw new lines on the blank lines left after the
- * scrolling. direction is the direction to scroll, either UP_DIR or
- * DOWN_DIR, and nlines is the number of lines to scroll. We change
+ * scrolling. direction is the direction to scroll, either UPWARD or
+ * DOWNWARD, and nlines is the number of lines to scroll. We change
* edittop, and assume that current and current_x are up to date. We
* also assume that scrollok(edit) is FALSE. */
void edit_scroll(scroll_dir direction, ssize_t nlines)
{
+ ssize_t i;
filestruct *foo;
- ssize_t i, extracuzsoft = 0;
bool do_redraw = FALSE;
/* Don't bother scrolling less than one line. */
@@ -2981,36 +3016,6 @@ void edit_scroll(scroll_dir direction, ssize_t nlines)
if (need_vertical_update(0))
do_redraw = TRUE;
-
- /* If using soft wrapping, we want to scroll down enough to display the entire next
- line, if possible... */
- if (ISSET(SOFTWRAP) && direction == DOWN_DIR) {
-#ifdef DEBUG
- fprintf(stderr, "Softwrap: Entering check for extracuzsoft\n");
-#endif
- for (i = maxrows, foo = openfile->edittop; foo && i > 0; i--, foo = foo->next)
- ;
-
- if (foo) {
- extracuzsoft += strlenpt(foo->data) / COLS;
-#ifdef DEBUG
- fprintf(stderr, "Setting extracuzsoft to %lu due to strlen %lu of line %lu\n", (unsigned long) extracuzsoft,
- (unsigned long) strlenpt(foo->data), (unsigned long) foo->lineno);
-#endif
-
- /* Now account for whether the edittop line itself is >COLS, if scrolling down */
- for (foo = openfile->edittop; foo && extracuzsoft > 0; nlines++) {
- extracuzsoft -= 1 + strlenpt(foo->data) / COLS;
-#ifdef DEBUG
- fprintf(stderr, "Edittop adjustment, setting nlines to %lu\n", (unsigned long) nlines);
-#endif
- if (foo == openfile->filebot)
- break;
- foo = foo->next;
- }
- }
- }
-
/* Part 1: nlines is the number of lines we're going to scroll the
* text of the edit window. */
@@ -3018,7 +3023,7 @@ void edit_scroll(scroll_dir direction, ssize_t nlines)
* value of direction) nlines lines, or as many lines as we can if
* there are fewer than nlines lines available. */
for (i = nlines; i > 0; i--) {
- if (direction == UP_DIR) {
+ if (direction == UPWARD) {
if (openfile->edittop == openfile->fileage)
break;
openfile->edittop = openfile->edittop->prev;
@@ -3027,13 +3032,16 @@ void edit_scroll(scroll_dir direction, ssize_t nlines)
break;
openfile->edittop = openfile->edittop->next;
}
- /* Don't over-scroll on long lines */
- if (ISSET(SOFTWRAP)) {
+
+#ifndef NANO_TINY
+ /* Don't over-scroll on long lines. */
+ if (ISSET(SOFTWRAP) && direction == UPWARD) {
ssize_t len = strlenpt(openfile->edittop->data) / COLS;
- i -= len;
+ i -= len;
if (len > 0)
do_redraw = TRUE;
}
+#endif
}
/* Limit nlines to the number of lines we could scroll. */
@@ -3051,7 +3059,7 @@ void edit_scroll(scroll_dir direction, ssize_t nlines)
/* Scroll the text of the edit window up or down nlines lines,
* depending on the value of direction. */
scrollok(edit, TRUE);
- wscrl(edit, (direction == UP_DIR) ? -nlines : nlines);
+ wscrl(edit, (direction == UPWARD) ? -nlines : nlines);
scrollok(edit, FALSE);
/* Part 2: nlines is the number of lines in the scrolled region of
@@ -3059,8 +3067,8 @@ void edit_scroll(scroll_dir direction, ssize_t nlines)
/* If the top or bottom line of the file is now visible in the edit
* window, we need to draw the entire edit window. */
- if ((direction == UP_DIR && openfile->edittop ==
- openfile->fileage) || (direction == DOWN_DIR &&
+ if ((direction == UPWARD && openfile->edittop ==
+ openfile->fileage) || (direction == DOWNWARD &&
openfile->edittop->lineno + editwinrows - 1 >=
openfile->filebot->lineno))
nlines = editwinrows;
@@ -3081,7 +3089,7 @@ void edit_scroll(scroll_dir direction, ssize_t nlines)
/* If we scrolled down, move down to the line before the scrolled
* region. */
- if (direction == DOWN_DIR) {
+ if (direction == DOWNWARD) {
for (i = editwinrows - nlines; i > 0 && foo != NULL; i--)
foo = foo->next;
}
@@ -3092,8 +3100,8 @@ void edit_scroll(scroll_dir direction, ssize_t nlines)
* blank, so we don't need to draw it unless the mark is on or we're
* not on the first page. */
for (i = nlines; i > 0 && foo != NULL; i--) {
- if ((i == nlines && direction == DOWN_DIR) || (i == 1 &&
- direction == UP_DIR)) {
+ if ((i == nlines && direction == DOWNWARD) || (i == 1 &&
+ direction == UPWARD)) {
if (do_redraw)
update_line(foo, (foo == openfile->current) ?
openfile->current_x : 0);
@@ -3102,6 +3110,7 @@ void edit_scroll(scroll_dir direction, ssize_t nlines)
openfile->current_x : 0);
foo = foo->next;
}
+ compute_maxrows();
}
/* Update any lines between old_current and current that need to be
@@ -3119,13 +3128,10 @@ void edit_redraw(filestruct *old_current, size_t pww_save)
maxrows || openfile->current->lineno <
openfile->edittop->lineno || openfile->current->lineno >=
openfile->edittop->lineno + maxrows) {
-
#ifdef DEBUG
- fprintf(stderr, "edit_redraw(): line %lu was offscreen, oldcurrent = %lu edittop = %lu", openfile->current->lineno,
- old_current->lineno, openfile->edittop->lineno);
+ fprintf(stderr, "edit_redraw(): line %ld was offscreen, oldcurrent = %ld edittop = %ld",
+ (long)openfile->current->lineno, (long)old_current->lineno, (long)openfile->edittop->lineno);
#endif
- filestruct *old_edittop = openfile->edittop;
- ssize_t nlines;
#ifndef NANO_TINY
/* If the mark is on, update all the lines between old_current
@@ -3133,6 +3139,7 @@ void edit_redraw(filestruct *old_current, size_t pww_save)
* whether we've scrolled up or down) of the edit window. */
if (openfile->mark_set) {
ssize_t old_lineno;
+ filestruct *old_edittop = openfile->edittop;
if (old_edittop->lineno < openfile->edittop->lineno)
old_lineno = old_edittop->lineno;
@@ -3153,10 +3160,11 @@ void edit_redraw(filestruct *old_current, size_t pww_save)
}
#endif /* !NANO_TINY */
- /* Put edittop in range of current, get the difference in lines
- * between the original edittop and the current edittop, and
- * then restore the original edittop. */
- edit_update(CENTER);
+ /* Make sure the current line is on the screen. */
+ if (ISSET(SMOOTH_SCROLL))
+ edit_update(NONE);
+ else
+ edit_update(CENTER);
/* Update old_current if we're not on the same page as
* before. */
@@ -3211,19 +3219,18 @@ void edit_refresh(void)
filestruct *foo;
int nlines;
- /* Figure out what maxrows should really be */
+ /* Figure out what maxrows should really be. */
compute_maxrows();
if (openfile->current->lineno < openfile->edittop->lineno ||
openfile->current->lineno >= openfile->edittop->lineno +
maxrows) {
-
#ifdef DEBUG
- fprintf(stderr, "edit_refresh(): line = %d, edittop %d + maxrows %d\n", openfile->current->lineno, openfile->edittop->lineno, maxrows);
+ fprintf(stderr, "edit_refresh(): line = %ld, edittop %ld + maxrows %d\n",
+ (long)openfile->current->lineno, (long)openfile->edittop->lineno, maxrows);
#endif
- /* Put the top line of the edit window in range of the current
- * line. */
+ /* Make sure the current line is on the screen. */
edit_update(CENTER);
}
@@ -3275,12 +3282,14 @@ void edit_update(update_type location)
for (; goal > 0 && foo->prev != NULL; goal--) {
foo = foo->prev;
+#ifndef NANO_TINY
if (ISSET(SOFTWRAP) && foo)
goal -= strlenpt(foo->data) / COLS;
+#endif
}
openfile->edittop = foo;
#ifdef DEBUG
- fprintf(stderr, "edit_udpate(), setting edittop to lineno %d\n", openfile->edittop->lineno);
+ fprintf(stderr, "edit_update(): setting edittop to lineno %ld\n", (long)openfile->edittop->lineno);
#endif
compute_maxrows();
edit_refresh_needed = TRUE;
@@ -3313,6 +3322,14 @@ void total_refresh(void)
* portion of the window. */
void display_main_list(void)
{
+#ifndef DISABLE_COLOR
+ if (openfile->syntax
+ && (openfile->syntax->formatter || openfile->syntax->linter))
+ set_lint_or_format_shortcuts();
+ else
+ set_spell_shortcuts();
+#endif
+
bottombars(MMAIN);
}
@@ -3374,17 +3391,16 @@ void do_cursorpos_void(void)
void enable_nodelay(void)
{
- nodelay_mode = TRUE;
- nodelay(edit, TRUE);
+ nodelay_mode = TRUE;
+ nodelay(edit, TRUE);
}
void disable_nodelay(void)
{
- nodelay_mode = FALSE;
- nodelay(edit, FALSE);
+ nodelay_mode = FALSE;
+ nodelay(edit, FALSE);
}
-
/* Highlight the current word being replaced or spell checked. We
* expect word to have tabs and control characters expanded. */
void do_replace_highlight(bool highlight, const char *word)
@@ -3404,7 +3420,7 @@ void do_replace_highlight(bool highlight, const char *word)
wnoutrefresh(edit);
if (highlight)
- wattron(edit, reverse_attr);
+ wattron(edit, hilite_attribute);
/* This is so we can show zero-length matches. */
if (word_len == 0)
@@ -3416,12 +3432,12 @@ void do_replace_highlight(bool highlight, const char *word)
waddch(edit, '$');
if (highlight)
- wattroff(edit, reverse_attr);
+ wattroff(edit, hilite_attribute);
}
-#ifdef NANO_EXTRA
-#define CREDIT_LEN 55
-#define XLCREDIT_LEN 8
+#ifndef DISABLE_EXTRA
+#define CREDIT_LEN 54
+#define XLCREDIT_LEN 9
/* Easter egg: Display credits. Assume nodelay(edit) and scrollok(edit)
* are FALSE. */
@@ -3443,14 +3459,11 @@ void do_credits(void)
"Rocco Corsi",
"David Lawrence Ramsey",
"David Benbennick",
+ "Mark Majeres",
"Mike Frysinger",
+ "Benno Schulenberg",
"Ken Tyler",
"Sven Guckes",
- NULL, /* credits[15], handled below. */
- "Pauli Virtanen",
- "Daniele Medri",
- "Clement Laforet",
- "Tedi Heriyanto",
"Bill Soudan",
"Christian Weisgerber",
"Erik Andersen",
@@ -3460,6 +3473,7 @@ void do_credits(void)
"Albert Chin",
"",
NULL, /* "Special thanks to:" */
+ "Monique, Brielle & Joseph",
"Plattsburgh State University",
"Benet Laboratories",
"Amy Allegretta",
@@ -3468,6 +3482,7 @@ void do_credits(void)
"Richard Kolb II",
NULL, /* "The Free Software Foundation" */
"Linus Torvalds",
+ NULL, /* "the many translators and the TP" */
NULL, /* "For ncurses:" */
"Thomas Dickey",
"Pavel Curtis",
@@ -3479,7 +3494,7 @@ void do_credits(void)
"",
"",
"",
- "(C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007",
+ "(C) 1999 - 2015",
"Free Software Foundation, Inc.",
"",
"",
@@ -3494,20 +3509,12 @@ void do_credits(void)
N_("Brought to you by:"),
N_("Special thanks to:"),
N_("The Free Software Foundation"),
+ N_("the many translators and the TP"),
N_("For ncurses:"),
N_("and anyone else we forgot..."),
N_("Thank you for using nano!")
};
- /* credits[15]: Make sure this name is displayed properly, since we
- * can't dynamically assign it above, using Unicode 00F6 (Latin
- * Small Letter O with Diaresis) if applicable. */
- credits[15] =
-#ifdef ENABLE_UTF8
- using_utf8() ? "Florian K\xC3\xB6nig" :
-#endif
- "Florian K\xF6nig";
-
if (!old_more_space || !old_no_help) {
SET(MORE_SPACE);
SET(NO_HELP);
@@ -3584,4 +3591,4 @@ void do_credits(void)
total_refresh();
}
-#endif /* NANO_EXTRA */
+#endif /* !DISABLE_EXTRA */