diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 3 | ||||
-rw-r--r-- | src/Makefile.in | 227 | ||||
-rw-r--r-- | src/browser.c | 51 | ||||
-rw-r--r-- | src/chars.c | 47 | ||||
-rw-r--r-- | src/color.c | 204 | ||||
-rw-r--r-- | src/cut.c | 43 | ||||
-rw-r--r-- | src/files.c | 332 | ||||
-rw-r--r-- | src/global.c | 1340 | ||||
-rw-r--r-- | src/help.c | 149 | ||||
-rw-r--r-- | src/move.c | 53 | ||||
-rw-r--r-- | src/nano.c | 468 | ||||
-rw-r--r-- | src/nano.h | 462 | ||||
-rw-r--r-- | src/prompt.c | 191 | ||||
-rw-r--r-- | src/proto.h | 126 | ||||
-rw-r--r-- | src/rcfile.c | 663 | ||||
-rw-r--r-- | src/search.c | 78 | ||||
-rw-r--r-- | src/text.c | 801 | ||||
-rw-r--r-- | src/utils.c | 23 | ||||
-rw-r--r-- | src/winio.c | 356 |
19 files changed, 2949 insertions, 2668 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index f0b21c06..83ce0e7a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,5 +1,4 @@ -localedir = $(datadir)/locale -INCLUDES = -DLOCALEDIR=\"$(localedir)\" -DSYSCONFDIR=\"$(sysconfdir)\" +AM_CPPFLAGS = -DLOCALEDIR=\"$(localedir)\" -DSYSCONFDIR=\"$(sysconfdir)\" ACLOCAL_AMFLAGS = -I m4 diff --git a/src/Makefile.in b/src/Makefile.in index 096f34b8..80c688d4 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -1,9 +1,8 @@ -# Makefile.in generated by automake 1.11.6 from Makefile.am. +# Makefile.in generated by automake 1.13.3 from Makefile.am. # @configure_input@ -# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, -# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 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,23 +15,51 @@ @SET_MAKE@ VPATH = @srcdir@ -am__make_dryrun = \ - { \ - am__dry=no; \ +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 \ *\\[\ \ ]*) \ - echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ - | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ - *) \ - for am__flg in $$MAKEFLAGS; do \ - case $$am__flg in \ - *=*|--*) ;; \ - *n*) am__dry=yes; break;; \ - esac; \ - done;; \ + 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; \ - test $$am__dry = yes; \ - } + 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@ @@ -53,9 +80,11 @@ build_triplet = @build@ host_triplet = @host@ 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 \ @@ -76,14 +105,34 @@ 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 = \ @@ -91,11 +140,29 @@ am__can_run_installinfo = \ 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@ @@ -141,7 +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@ @@ -153,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@ @@ -182,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@ @@ -193,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@ @@ -210,7 +284,7 @@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ -INCLUDES = -DLOCALEDIR=\"$(localedir)\" -DSYSCONFDIR=\"$(sysconfdir)\" +AM_CPPFLAGS = -DLOCALEDIR=\"$(localedir)\" -DSYSCONFDIR=\"$(sysconfdir)\" ACLOCAL_AMFLAGS = -I m4 nano_SOURCES = browser.c \ chars.c \ @@ -274,10 +348,11 @@ install-binPROGRAMS: $(bin_PROGRAMS) 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 } \ @@ -298,16 +373,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) $(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) @@ -332,39 +409,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 $< .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 `$(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; \ @@ -376,15 +442,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 @@ -393,6 +455,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 @@ -537,19 +614,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 1d03c7c6..4b9d6301 100644 --- a/src/browser.c +++ b/src/browser.c @@ -1,9 +1,9 @@ -/* $Id: browser.c 4548 2012-12-30 19:20:10Z astyanax $ */ +/* $Id: browser.c 4923 2014-05-28 15:40:24Z 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) * @@ -161,8 +161,8 @@ char *do_browser(char *path, DIR *dir) } #endif /* !DISABLE_MOUSE */ - parse_browser_input(&kbinput, &meta_key, &func_key); - s = get_shortcut(MBROWSER, &kbinput, &meta_key, &func_key); + parse_browser_input(&kbinput, &meta_key); + s = get_shortcut(MBROWSER, &kbinput, &meta_key); if (!s) continue; f = sctofunc((sc *) s); @@ -173,10 +173,10 @@ char *do_browser(char *path, DIR *dir) total_redraw(); } else if (f->scfunc == do_help_void) { #ifndef DISABLE_HELP - do_browser_help(); + do_help_void(); curs_set(0); #else - nano_disabled_msg(); + nano_disabled_msg(); #endif /* Search for a filename. */ } else if (f->scfunc == do_search) { @@ -217,7 +217,8 @@ char *do_browser(char *path, DIR *dir) #ifndef NANO_TINY 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) @@ -540,29 +541,27 @@ void browser_init(const char *path, DIR *dir) } /* 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 + * (the key itself) and meta_key (whether the key is a meta sequence). + * Also convert certain non-shortcut keys into their corresponding * shortcut keys. */ -void parse_browser_input(int *kbinput, bool *meta_key, bool *func_key) +void parse_browser_input(int *kbinput, bool *meta_key) { - get_shortcut(MBROWSER, kbinput, meta_key, func_key); + get_shortcut(MBROWSER, kbinput, meta_key); /* Pico compatibility. */ if (!*meta_key) { switch (*kbinput) { case ' ': - *kbinput = sc_seq_or(do_page_down, 0); + *kbinput = KEY_NPAGE; break; case '-': - *kbinput = sc_seq_or(do_page_up, 0); + *kbinput = KEY_PPAGE; break; case '?': #ifndef DISABLE_HELP *kbinput = sc_seq_or(do_help_void, 0); #endif break; - /* Cancel equivalent to Exit here. */ case 'E': case 'e': *kbinput = sc_seq_or(do_exit, 0); @@ -635,7 +634,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 +709,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); @@ -798,25 +797,19 @@ int filesearch_init(void) #ifndef NANO_TINY &search_history, #endif - browser_refresh, "%s%s%s%s%s%s", _("Search"), + browser_refresh, "%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); + "", buf); /* Release buf now that we don't need it anymore. */ free(buf); @@ -830,7 +823,7 @@ int filesearch_init(void) statusbar(_("Cancelled")); return -1; } else { - s = get_shortcut(MBROWSER, &i, &meta_key, &func_key); + s = get_shortcut(MBROWSER, &i, &meta_key); if (i == -2 || i == 0) { #ifdef HAVE_REGEX_H /* Use last_search if answer is an empty string, or @@ -845,7 +838,7 @@ int filesearch_init(void) TOGGLE(CASE_SENSITIVE); backupstring = mallocstrcpy(backupstring, answer); return 1; - } else if (s && s->scfunc == backwards_void) { + } else if (s && s->scfunc == backwards_void) { TOGGLE(BACKWARDS_SEARCH); backupstring = mallocstrcpy(backupstring, answer); return 1; @@ -1070,7 +1063,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 5b5b34c3..443e7df9 100644 --- a/src/chars.c +++ b/src/chars.c @@ -1,9 +1,9 @@ -/* $Id: chars.c 4555 2013-01-03 04:23:10Z astyanax $ */ +/* $Id: chars.c 4908 2014-05-25 19:41:49Z 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) * @@ -43,6 +43,17 @@ static const wchar_t bad_wchar = 0xFFFD; static const char *const bad_mbchar = "\xEF\xBF\xBD"; static const int bad_mbchar_len = 3; +/* 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; +} + /* Enable UTF-8 support. */ void utf8_init(void) { @@ -54,7 +65,7 @@ bool using_utf8(void) { return use_utf8; } -#endif +#endif /* ENABLE_UTF8 */ #ifndef HAVE_ISBLANK /* This function is equivalent to isblank(). */ @@ -184,9 +195,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 +483,18 @@ 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 = 0, 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; - - 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 @@ -788,9 +794,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; @@ -893,7 +898,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 +940,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 +952,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 +965,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 e12efddf..19ef74b0 100644 --- a/src/color.c +++ b/src/color.c @@ -1,9 +1,9 @@ -/* $Id: color.c 4540 2011-03-05 05:01:13Z astyanax $ */ +/* $Id: color.c 4894 2014-05-16 10:34:05Z 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) * @@ -31,17 +31,53 @@ #include <magic.h> #endif -#ifdef ENABLE_COLOR +#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; @@ -56,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++; } } } @@ -71,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; @@ -107,7 +137,7 @@ void color_init(void) } } -/* Cleanup a regex we previously compiled */ +/* Clean up a regex we previously compiled. */ void nfreeregex(regex_t **r) { assert(r != NULL); @@ -123,17 +153,14 @@ void color_update(void) syntaxtype *tmpsyntax; syntaxtype *defsyntax = NULL; colortype *tmpcolor, *defcolor = NULL; - exttype *e; + regexlisttype *e; -/* libmagic structures */ -/* magicstring will be NULL if we fail to get magic result */ +/* Var magicstring will stay NULL if we fail to get a magic result. */ #ifdef HAVE_LIBMAGIC const char *magicstring = NULL; - const char *magicerr = NULL; - magic_t m; + magic_t cookie = NULL; struct stat fileinfo; -#endif /* HAVE_LIBMAGIC */ - +#endif assert(openfile != NULL); @@ -159,32 +186,9 @@ void color_update(void) } } -#ifdef HAVE_LIBMAGIC - - if (strcmp(openfile->filename,"") && stat(openfile->filename, &fileinfo) == 0) { - m = magic_open(MAGIC_SYMLINK | -#ifdef DEBUG - MAGIC_DEBUG | MAGIC_CHECK | -#endif /* DEBUG */ - MAGIC_ERROR); - if (m == NULL || magic_load(m, NULL) < 0) - fprintf(stderr, "something went wrong: %s [%s]\n", strerror(errno), openfile->filename); - else { - magicstring = magic_file(m,openfile->filename); - if (magicstring == NULL) { - magicerr = magic_error(m); - fprintf(stderr, "something went wrong: %s [%s]\n", magicerr, openfile->filename); - } -#ifdef DEBUG - fprintf(stderr, "magic string returned: %s\n", magicstring); -#endif /* DEBUG */ - } - } -#endif /* HAVE_LIBMAGIC */ - /* 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) { @@ -209,8 +213,7 @@ void color_update(void) regcomp(e->ext, fixbounds(e->ext_regex), REG_EXTENDED); } - /* Set colorstrings if we matched the extension - * regex. */ + /* 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; @@ -224,27 +227,27 @@ void color_update(void) } } - /* Check magic if we don't yet have an answer */ -#ifdef HAVE_LIBMAGIC + /* Check the headerline if the extension didn't match anything. */ if (openfile->colorstrings == NULL) { - #ifdef DEBUG - fprintf(stderr, "No match using extension, trying libmagic...\n"); -#endif /* DEBUG */ - + fprintf(stderr, "No result from file extension, trying headerline...\n"); +#endif for (tmpsyntax = syntaxes; tmpsyntax != NULL; tmpsyntax = tmpsyntax->next) { - for (e = tmpsyntax->magics; e != NULL; e = e->next) { + + for (e = tmpsyntax->headers; e != NULL; e = e->next) { bool not_compiled = (e->ext == NULL); + if (not_compiled) { 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 /* DEBUG */ - - if (magicstring && regexec(e->ext, magicstring, 0, NULL, 0) == 0) { + 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; @@ -255,52 +258,69 @@ void color_update(void) } } } -#endif /* HAVE_LIBMAGIC */ - /* If we haven't matched anything yet, try the headers */ +#ifdef HAVE_LIBMAGIC + /* Check magic if we don't have an answer yet. */ if (openfile->colorstrings == NULL) { #ifdef DEBUG - fprintf(stderr, "No match for file extensions, looking at headers...\n"); + 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->headers; e != NULL; e = e->next) { + for (e = tmpsyntax->magics; 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, "Matching regex \"%s\" against \"%s\"\n", e->ext_regex, magicstring); #endif - if (regexec(e->ext, openfile->fileage->data, 0, NULL, 0) == 0) { + /* 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; - } - - if (openfile->colorstrings != NULL) break; + } - /* Decompile e->ext_regex's specified regex if we aren't - * going to use it. */ 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; @@ -326,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; @@ -372,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); @@ -384,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; @@ -398,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; @@ -409,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) { @@ -424,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 */ @@ -1,9 +1,9 @@ -/* $Id: cut.c 4453 2009-12-02 03:36:22Z astyanax $ */ +/* $Id: cut.c 4911 2014-05-26 07:53:20Z bens $ */ /************************************************************************** * 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) * @@ -44,6 +44,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); @@ -125,7 +130,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,7 +167,6 @@ 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 * file into the cutbuffer. */ @@ -190,10 +194,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 +209,19 @@ 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_end ? CUT_EOF : CUT); + + /* Leave the text in the cutbuffer, and mark the file as + * modified. */ + if (!copy_text) { set_modified(); + } +#endif /* !NANO_TINY */ /* Update the screen. */ edit_refresh_needed = TRUE; -#ifdef ENABLE_COLOR +#ifndef DISABLE_COLOR reset_multis(openfile->current, FALSE); #endif @@ -247,9 +254,7 @@ void do_copy_text(void) /* Cut from the current cursor position to the end of the file. */ void do_cut_till_end(void) { -#ifndef NANO_TINY - add_undo(CUT); -#endif + add_undo(CUT_EOF); do_cut_text(FALSE, TRUE, FALSE); } #endif /* !NANO_TINY */ @@ -264,12 +269,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 +290,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 e9fd27f6..78c4f0c6 100644 --- a/src/files.c +++ b/src/files.c @@ -1,9 +1,9 @@ -/* $Id: files.c 4558 2013-01-03 04:50:49Z astyanax $ */ +/* $Id: files.c 4878 2014-05-13 21:11:59Z 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) * @@ -47,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. */ @@ -80,7 +82,7 @@ void initialize_buffer(void) openfile->current_undo = NULL; openfile->lock_filename = NULL; #endif -#ifdef ENABLE_COLOR +#ifndef DISABLE_COLOR openfile->colorstrings = NULL; #endif } @@ -98,26 +100,25 @@ 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 -/* Actyally write the lock file. This function will - ALWAYS annihilate any previous version of the file. - We'll borrow INSECURE_BACKUP here to decide about lock file - 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 - */ +/* 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; @@ -130,8 +131,8 @@ int write_lockfile(const char *lockfilename, const char *origfilename, bool modi ssize_t lockdatalen = 1024; ssize_t wroteamt; - /* Run things which might fail first before we try and blow away - the old state */ + /* 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)")); @@ -140,7 +141,7 @@ int write_lockfile(const char *lockfilename, const char *origfilename, bool modi mypid = getpid(); if (gethostname(myhostname, 31) < 0) { - statusbar(_("Couldn't determine hosttname for lock file: %s"), strerror(errno)); + statusbar(_("Couldn't determine hostname for lock file: %s"), strerror(errno)); return -1; } @@ -155,14 +156,14 @@ int write_lockfile(const char *lockfilename, const char *origfilename, bool modi fd = open(lockfilename, cflags, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); - /* Maybe we just don't have write access, don't stop us from - opening the file at all, just don't set the lock_filename - and return success */ + /* Maybe we just don't have write access. Don't stop us from + * opening the file at all, just don't set the lock_filename and + * return success. */ if (fd < 0 && errno == EACCES) return 1; - /* Now we've got a safe file stream. If the previous open() - call failed, this will return NULL. */ + /* 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) { @@ -171,25 +172,24 @@ int write_lockfile(const char *lockfilename, const char *origfilename, bool modi 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 - */ + /* 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. */ null_at(&lockdata, lockdatalen); lockdata[0] = 0x62; lockdata[1] = 0x30; @@ -211,7 +211,7 @@ int write_lockfile(const char *lockfilename, const char *origfilename, bool modi #ifdef DEBUG fprintf(stderr, "In write_lockfile(), write successful (wrote %d bytes)\n", wroteamt); -#endif /* DEBUG */ +#endif if (fclose(filestream) == EOF) { statusbar(_("Error writing lock file %s: %s"), @@ -224,10 +224,8 @@ int write_lockfile(const char *lockfilename, const char *origfilename, bool modi return 1; } - -/* Less exciting, delete the lock file. - Return -1 if successful and complain on the statusbar, 1 otherwite - */ +/* 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) { @@ -238,12 +236,10 @@ int delete_lockfile(const char *lockfilename) return 1; } - -/* Deal with lockfiles. Return -1 on refusing to override - the lock file, and 1 on successfully created the lockfile, 0 means - we were not successful on creating the lockfile but we should - continue to load the file and complain to the user. - */ +/* 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)); @@ -255,12 +251,11 @@ int do_lockfile(const char *filename) 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 /* DEBUG */ +#endif if (stat(lockfilename, &fileinfo) != -1) { ssize_t readtot = 0; ssize_t readamt = 0; @@ -268,7 +263,7 @@ int do_lockfile(const char *filename) char *promptstr = (char *) nmalloc(128); int ans; if ((lockfd = open(lockfilename, O_RDONLY)) < 0) { - statusbar(_("Error opening lockfile %s: %s"), + statusbar(_("Error opening lock file %s: %s"), lockfilename, strerror(errno)); return -1; } @@ -278,7 +273,7 @@ int do_lockfile(const char *filename) } while (readtot < 8192 && readamt > 0); if (readtot < 48) { - statusbar(_("Error reading lockfile %s: Not enough data read"), + statusbar(_("Error reading lock file %s: Not enough data read"), lockfilename); return -1; } @@ -291,7 +286,7 @@ int do_lockfile(const char *filename) lockprog); fprintf(stderr, "user which created this lock file should be %s\n", lockuser); -#endif /* DEBUG */ +#endif sprintf(promptstr, "File being edited (by %s, PID %d, user %s), continue?", lockprog, lockpid, lockuser); ans = do_yesno_prompt(FALSE, promptstr); @@ -303,15 +298,14 @@ int do_lockfile(const char *filename) return write_lockfile(lockfilename, filename, FALSE); } -#endif /* NANO_TINY */ - +#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 new_buffer = (openfile == NULL -#ifdef ENABLE_MULTIBUFFER +#ifndef DISABLE_MULTIBUFFER || ISSET(MULTIBUFFER) #endif ); @@ -336,10 +330,10 @@ void open_buffer(const char *filename, bool undoable) if (new_buffer) make_new_buffer(); - /* 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 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, &f) : -2; /* If we have a file, and we're loading into a new buffer, update * the filename. */ @@ -367,7 +361,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) @@ -414,7 +408,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(); @@ -424,7 +418,7 @@ 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) @@ -457,6 +451,7 @@ void switch_to_prevnext_buffer(bool next_buf) #ifdef DEBUG dump_filestruct(openfile->current); #endif + display_main_list(); } /* Switch to the previous entry in the openfile filebuffer. */ @@ -482,9 +477,9 @@ bool close_buffer(void) if (openfile == openfile->next) return FALSE; -#ifndef NANO_TINY +#if !defined(NANO_TINY) && !defined(DISABLE_NANORC) update_poshistory(openfile->filename, openfile->current->lineno, xplustabs()+1); -#endif /* NANO_TINY */ +#endif /* Switch to the next file buffer. */ switch_to_next_buffer_void(); @@ -492,18 +487,19 @@ bool close_buffer(void) /* 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 */ - -/* 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. - */ +#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. */ int is_file_writable(const char *filename) { struct stat fileinfo, fileinfo2; @@ -512,7 +508,6 @@ int is_file_writable(const char *filename) char *full_filename; bool ans = TRUE; - if (ISSET(VIEW_MODE)) return TRUE; @@ -522,7 +517,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); @@ -563,7 +558,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 @@ -596,9 +591,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; @@ -895,7 +890,7 @@ 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 */ + permissions, just try the relative one. */ if (full_filename == NULL || (stat(full_filename, &fileinfo) == -1 && stat(filename, &fileinfo2) != -1)) full_filename = mallocstrcpy(NULL, filename); @@ -908,8 +903,8 @@ int open_file(const char *filename, bool newfie, FILE **f) #endif 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")); free(full_filename); @@ -936,7 +931,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"); @@ -1026,7 +1021,7 @@ 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 @@ -1034,7 +1029,7 @@ void do_insertfile( } else { #endif msg = -#ifdef ENABLE_MULTIBUFFER +#ifndef DISABLE_MULTIBUFFER ISSET(MULTIBUFFER) ? _("File to insert into new buffer [from %s] ") : #endif @@ -1067,7 +1062,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 )) { @@ -1078,11 +1073,10 @@ void do_insertfile( ans = mallocstrcpy(ans, answer); - s = get_shortcut(currmenu, &i, &meta_key, &func_key); + s = get_shortcut(currmenu, &i, &meta_key); #ifndef NANO_TINY -#ifdef ENABLE_MULTIBUFFER - +#ifndef DISABLE_MULTIBUFFER if (s && s->scfunc == new_buffer_void) { /* Don't allow toggling if we're in view mode. */ if (!ISSET(VIEW_MODE)) @@ -1117,7 +1111,7 @@ 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 ) @@ -1138,7 +1132,7 @@ void do_insertfile( } #endif -#ifdef ENABLE_MULTIBUFFER +#ifndef DISABLE_MULTIBUFFER if (!ISSET(MULTIBUFFER)) { #endif /* If we're not inserting into a new buffer, partition @@ -1151,7 +1145,7 @@ void do_insertfile( openfile->current_x); edittop_inside = (openfile->edittop == openfile->fileage); -#ifdef ENABLE_MULTIBUFFER +#ifndef DISABLE_MULTIBUFFER } #endif @@ -1162,7 +1156,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); @@ -1171,7 +1165,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. */ @@ -1194,12 +1188,19 @@ void do_insertfile( } #endif -#ifdef ENABLE_MULTIBUFFER - if (ISSET(MULTIBUFFER)) +#if !defined(DISABLE_MULTIBUFFER) && !defined(DISABLE_NANORC) + if (ISSET(MULTIBUFFER)) { /* Update the screen to account for the current * buffer. */ display_buffer(); - else + +#ifndef NANO_TINY + ssize_t savedposline, savedposcol; + if (!execute && ISSET(POS_HISTORY) + && check_poshistory(answer, &savedposline, &savedposcol)) + do_gotolinecolumn(savedposline, savedposcol, FALSE, FALSE, FALSE, FALSE); +#endif + } else #endif { filestruct *top_save = openfile->fileage; @@ -1270,8 +1271,6 @@ void do_insertfile( break; } } - shortcut_init(FALSE); - free(ans); } @@ -1280,13 +1279,12 @@ void do_insertfile( * allow inserting a file into a new buffer. */ void do_insertfile_void(void) { - if (ISSET(RESTRICTED)) { nano_disabled_msg(); return; } -#ifdef ENABLE_MULTIBUFFER +#ifndef DISABLE_MULTIBUFFER if (ISSET(VIEW_MODE) && !ISSET(MULTIBUFFER)) statusbar(_("Key invalid in non-multibuffer mode")); else @@ -1314,7 +1312,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 @@ -1580,15 +1578,14 @@ 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. - */ - +/* 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 laast file we were paased so we don't keep asking this? - though maybe we should.... */ + 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) ")); @@ -1618,7 +1615,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 @@ -1732,17 +1729,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). */ + /* 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 @@ -1813,10 +1811,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); @@ -1828,8 +1827,8 @@ 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; @@ -1847,7 +1846,7 @@ bool write_file(const char *name, FILE *f_open, bool tmp, append_type 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) { @@ -1906,10 +1905,10 @@ bool write_file(const char *name, FILE *f_open, bool tmp, append_type 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; } @@ -2114,7 +2113,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. */ @@ -2134,7 +2133,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", @@ -2213,7 +2213,7 @@ bool do_writeout(bool exiting) 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; @@ -2291,7 +2291,7 @@ bool do_writeout(bool exiting) break; } else { ans = mallocstrcpy(ans, answer); - s = get_shortcut(currmenu, &i, &meta_key, &func_key); + s = get_shortcut(currmenu, &i, &meta_key); #ifndef DISABLE_BROWSER if (s && s->scfunc == to_files_void) { @@ -2333,7 +2333,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 @@ -2406,8 +2406,9 @@ 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 */ + /* 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, @@ -2521,7 +2522,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); } @@ -2896,7 +2897,7 @@ const char *tail(const char *foo) return tmp; } -#if !defined(NANO_TINY) && defined(ENABLE_NANORC) +#if !defined(NANO_TINY) && !defined(DISABLE_NANORC) /* Return the constructed dorfile path, or NULL if we can't find the home * directory. The string is dynamically allocated, and should be * freed. */ @@ -2913,7 +2914,6 @@ char *construct_filename(const char *str) } return newstr; - } char *histfilename(void) @@ -2921,9 +2921,8 @@ char *histfilename(void) return construct_filename("/.nano/search_history"); } -/* Construct the legacy history filename - * (Deprecate in 2.5, delete later - */ +/* Construct the legacy history filename. + * (Deprecate in 2.5, delete later.) */ char *legacyhistfilename(void) { return construct_filename("/.nano_history"); @@ -2934,8 +2933,6 @@ char *poshistfilename(void) return construct_filename("/.nano/filepos_history"); } - - void history_error(const char *msg, ...) { va_list ap; @@ -2947,13 +2944,11 @@ void history_error(const char *msg, ...) 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. - */ +/* 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; @@ -2981,7 +2976,7 @@ void load_history(void) if (stat(legacyhist, &hstat) != -1 && stat(nanohist, &hstat) == -1) { - if (rename(legacyhist, nanohist) == -1) + if (rename(legacyhist, nanohist) == -1) history_error(N_("Detected a legacy nano history file (%s) which I tried to move\nto the preferred location (%s) but encountered an error: %s"), legacyhist, nanohist, strerror(errno)); else @@ -2989,8 +2984,6 @@ void load_history(void) legacyhist, nanohist); } - - /* Assume do_rcfile() has reported a missing home directory. */ if (nanohist != NULL) { FILE *hist = fopen(nanohist, "rb"); @@ -3090,8 +3083,7 @@ void save_history(void) } } - -/* Analogs for the POS history */ +/* Analogs for the POS history. */ void save_poshistory(void) { char *poshist; @@ -3126,9 +3118,8 @@ void save_poshistory(void) } } -/* Update the POS history, given a filename line and column. - * If no entry is found, add a new entry on the end - */ +/* Update the POS history, given a filename line and column. If no + * entry is found, add a new entry on the end. */ void update_poshistory(char *filename, ssize_t lineno, ssize_t xpos) { poshiststruct *posptr, *posprev = NULL; @@ -3147,7 +3138,6 @@ void update_poshistory(char *filename, ssize_t lineno, ssize_t xpos) } /* Didn't find it, make a new node yo! */ - posptr = (poshiststruct *) nmalloc(sizeof(poshiststruct)); posptr->filename = mallocstrcpy(NULL, fullpath); posptr->lineno = lineno; @@ -3163,17 +3153,16 @@ void update_poshistory(char *filename, ssize_t lineno, ssize_t xpos) } -/* Check the POS history to see if file matches - * an existing entry. If so return 1 and set line and column - * to the right values Otherwise return 0 - */ +/* Check the POS history to see if file matches an existing entry. If + * so, return 1 and set line and column to the right 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; + return 0; for (posptr = poshistory; posptr != NULL; posptr = posptr->next) { if (!strcmp(posptr->filename, fullpath)) { @@ -3187,7 +3176,6 @@ int check_poshistory(const char *file, ssize_t *line, ssize_t *column) return 0; } - /* Load histories from ~/.nano_history. */ void load_poshistory(void) { @@ -3200,7 +3188,7 @@ void load_poshistory(void) if (hist == NULL) { if (errno != ENOENT) { /* Don't save history when we quit. */ - UNSET(HISTORYLOG); + UNSET(POS_HISTORY); history_error(N_("Error reading %s: %s"), nanohist, strerror(errno)); } @@ -3210,7 +3198,7 @@ void load_poshistory(void) ssize_t read, lineno, xno; poshiststruct *posptr; - /* See if we can find the file we're currently editing */ + /* See if we can find the file we're currently editing. */ while ((read = getline(&line, &buf_len, hist)) >= 0) { if (read > 0 && line[read - 1] == '\n') { read--; @@ -3248,4 +3236,4 @@ void load_poshistory(void) } } -#endif /* !NANO_TINY && ENABLE_NANORC */ +#endif /* !NANO_TINY && !DISABLE_NANORC */ diff --git a/src/global.c b/src/global.c index 00514671..e50cf5df 100644 --- a/src/global.c +++ b/src/global.c @@ -1,9 +1,9 @@ -/* $Id: global.c 4556 2013-01-03 04:36:39Z astyanax $ */ +/* $Id: global.c 4928 2014-05-28 21:02:39Z 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) * @@ -67,7 +67,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 +88,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 +118,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. */ @@ -132,9 +132,9 @@ 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 */ + /* Prefix of how to store the vim-style lock file. */ const char *locking_suffix = ".swp"; - /* Suffix of the vim-style lock file */ + /* Suffix of the vim-style lock file. */ #endif #ifndef DISABLE_OPERATINGDIR char *operating_dir = NULL; @@ -149,7 +149,7 @@ 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; @@ -157,19 +157,25 @@ char *syntaxstr = NULL; #endif -bool edit_refresh_needed = 0; +bool edit_refresh_needed = FALSE; /* Did a command mangle enough of the buffer refresh that we - should repaint the screen */ + * 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 */ + /* 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 NANO_TINY filestruct *search_history = NULL; @@ -185,7 +191,7 @@ filestruct *replaceage = NULL; filestruct *replacebot = NULL; /* The bottom of the replace string history list. */ poshiststruct *poshistory; - /* The cursor position history list */ + /* The cursor position history list. */ #endif /* Regular expressions. */ @@ -197,13 +203,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; @@ -220,19 +232,27 @@ size_t length_of_list(int menu) return i; } -/* Just throw this here */ +/* 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) { } @@ -251,12 +271,6 @@ void backup_file_void(void) void new_buffer_void(void) { } -void backwards_void(void) -{ -} -void goto_dir_void(void) -{ -} void no_replace_void(void) { } @@ -264,35 +278,32 @@ void ext_cmd_void(void) { } -/* Set type of function based on the string */ +/* Set type of function based on the string. */ function_type strtokeytype(const char *str) { - if (str[0] == 'M' || str[0] == 'm') - return META; - else if (str[0] == '^') + if (str[0] == '^') return CONTROL; - else if (str[0] == 'F' || str[0] == 'F') + else if (str[0] == 'M') + return META; + else if (str[0] == 'F') return FKEY; else return RAWINPUT; } -/* Add a string to the new function list strict. - Does not allow updates, yet anyway */ +/* Add a string to the function list struct. + * Does not allow updates, not yet anyway. */ void add_to_funcs(void (*func)(void), int menus, const char *desc, const char *help, bool blank_after, bool viewok) { - subnfunc *f; + subnfunc *f = 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; @@ -304,42 +315,30 @@ void add_to_funcs(void (*func)(void), int menus, const char *desc, const char *h #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, void (*func)(void)) { +/* 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; - const sc *metasc = NULL; - 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 */ + for (s = sclist; s != NULL; s = s->next) + if ((s->menu & menu) && s->scfunc == func) return s; - } - } - - /* If we're here we may have found only meta sequences, if so use one */ - if (metasc) - return metasc; #ifdef DEBUG - fprintf(stderr, "Whoops, returning null given func %ld in menu %d\n", (long) func, menu); + fprintf(stderr, "Whoops, returning null given func %ld in menu %x\n", (long) func, menu); #endif /* Otherwise... */ return NULL; } -/* Add a string to the new shortcut list implementation - Allows updates to existing entries in the list */ +/* Add a string to the shortcut list. + * Allows updates to existing entries in the list. */ void add_to_sclist(int menu, const char *scstring, void (*func)(void), int toggle, int execute) { sc *s; @@ -372,13 +371,23 @@ void add_to_sclist(int menu, const char *scstring, void (*func)(void), int toggl assign_keyinfo(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, "Setting sequence to %d for shortcut \"%s\" in menu %x\n", s->seq, scstring, (int) s->menu); #endif } +/* Assign one function's shortcuts to another function. */ +void replace_scs_for(void (*oldfunc)(void), void (*newfunc)(void)) +{ + sc *s; + + for (s = sclist; s != NULL; s = s->next) + if (s->scfunc == oldfunc) { + s->scfunc = newfunc; + } +} + /* Return the given menu's first shortcut sequence, or the default value - (2nd arg). Assumes currmenu for the menu to check*/ + * (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); @@ -387,11 +396,10 @@ int sc_seq_or (void (*func)(void), int defaultval) return s->seq; /* else */ return defaultval; - } -/* 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) { @@ -406,160 +414,99 @@ void assign_keyinfo(sc *s) } 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 == RAWINPUT && (!strcasecmp(s->keystr, "kup"))) - s->seq = KEY_UP; - else if (s->type == RAWINPUT && (!strcasecmp(s->keystr, "kdown"))) - s->seq = KEY_DOWN; - else if (s->type == RAWINPUT && (!strcasecmp(s->keystr, "kleft"))) - s->seq = KEY_LEFT; - else if (s->type == RAWINPUT && (!strcasecmp(s->keystr, "kright"))) - s->seq = KEY_RIGHT; - else if (s->type == RAWINPUT && (!strcasecmp(s->keystr, "kinsert"))) - s->seq = KEY_IC; - else if (s->type == RAWINPUT && (!strcasecmp(s->keystr, "kdel"))) - s->seq = KEY_DC; - else if (s->type == RAWINPUT && (!strcasecmp(s->keystr, "kbsp"))) - s->seq = KEY_BACKSPACE; - else if (s->type == RAWINPUT && (!strcasecmp(s->keystr, "kenter"))) - s->seq = KEY_ENTER; - else if (s->type == RAWINPUT && (!strcasecmp(s->keystr, "kpup"))) - s->seq = KEY_PPAGE; - else if (s->type == RAWINPUT && (!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 == RAWINPUT && (!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 == RAWINPUT && (!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"); + const char *fulljustify_tag = N_("FullJstify"); #endif - const char *refresh_msg = N_("Refresh"); -#ifndef NANO_TINY - const char *insert_file_msg = N_("Insert File"); -#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 = @@ -568,22 +515,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"); @@ -607,10 +557,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 = @@ -618,20 +566,14 @@ 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 @@ -671,28 +613,27 @@ 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"); +#endif #endif /* !DISABLE_HELP */ #ifndef DISABLE_HELP @@ -703,236 +644,231 @@ 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( do_cancel, - (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), FALSE, VIEW); + + add_to_funcs(do_cancel, ((MMOST & ~MMAIN & ~MBROWSER) | MYESNO), + N_("Cancel"), IFSCHELP(nano_cancel_msg), FALSE, 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); + exit_tag, IFSCHELP(nano_exit_msg), FALSE, 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), FALSE, 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), FALSE, 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), TRUE, +#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_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_search, MMAIN, + whereis_tag, IFSCHELP(nano_whereis_msg), FALSE, VIEW); + add_to_funcs(do_replace, MMAIN, + replace_tag, IFSCHELP(nano_replace_msg), FALSE, NOVIEW); - /* 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); +#ifndef DISABLE_BROWSER + add_to_funcs(do_search, MBROWSER, + whereis_tag, IFSCHELP(nano_browser_whereis_msg), FALSE, VIEW); - 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), TRUE, 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), FALSE, 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), TRUE, 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), FALSE, 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), FALSE, 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), TRUE, NOVIEW); #endif +#ifndef NANO_TINY + add_to_funcs(case_sens_void, MWHEREIS|MREPLACE, + N_("Case Sens"), IFSCHELP(nano_case_msg), FALSE, 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), FALSE, VIEW); +#endif #ifndef NANO_TINY - FALSE, -#else - TRUE, + add_to_funcs(backwards_void, MWHEREIS|MREPLACE, + N_("Backwards"), IFSCHELP(nano_reverse_msg), FALSE, VIEW); #endif - NOVIEW); -#ifndef NANO_TINY + add_to_funcs(do_replace, MWHEREIS, + replace_tag, IFSCHELP(nano_replace_msg), FALSE, VIEW); - add_to_funcs(do_mark, MMAIN, N_("Mark Text"), - IFSCHELP(nano_mark_msg), FALSE, VIEW); + add_to_funcs(no_replace_void, MREPLACE, + N_("No Replace"), IFSCHELP(nano_whereis_msg), FALSE, 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), FALSE, 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), FALSE, 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), TRUE, 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), FALSE, VIEW); + add_to_funcs(do_page_down, MMAIN|MHELP|MBROWSER, + N_("Next Page"), IFSCHELP(nano_nextpage_msg), FALSE, 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), FALSE, VIEW); + add_to_funcs(do_last_line, MMAIN|MHELP|MWHEREIS|MREPLACE|MREPLACEWITH|MGOTOLINE, + N_("Last Line"), IFSCHELP(nano_lastline_msg), TRUE, 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), FALSE, VIEW); -#endif + add_to_funcs(do_find_bracket, MMAIN, + N_("To Bracket"), IFSCHELP(nano_bracket_msg), FALSE, 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), FALSE, 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), TRUE, NOVIEW); - add_to_funcs(do_right, MALL, "", "", FALSE, VIEW); + add_to_funcs(do_indent_void, MMAIN, + N_("Indent Text"), IFSCHELP(nano_indent_msg), FALSE, NOVIEW); + add_to_funcs(do_unindent, MMAIN, + N_("Unindent Text"), IFSCHELP(nano_unindent_msg), TRUE, NOVIEW); + + if (ISSET(UNDOABLE)) { + add_to_funcs(do_undo, MMAIN, + N_("Undo"), IFSCHELP(nano_undo_msg), FALSE, NOVIEW); + add_to_funcs(do_redo, MMAIN, + N_("Redo"), IFSCHELP(nano_redo_msg), TRUE, NOVIEW); + } +#endif /* !NANO_TINY */ - add_to_funcs(do_left, MMAIN, N_("Back"), IFSCHELP(nano_back_msg), - FALSE, VIEW); + add_to_funcs(do_left, MMAIN, + N_("Back"), IFSCHELP(nano_back_msg), FALSE, VIEW); + add_to_funcs(do_right, MMAIN, + N_("Forward"), IFSCHELP(nano_forward_msg), FALSE, 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), FALSE, VIEW); + add_to_funcs(do_right, MBROWSER, + N_("Forward"), IFSCHELP(nano_forwardfile_msg), FALSE, 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), FALSE, VIEW); + add_to_funcs(do_next_word_void, MMAIN, + N_("Next Word"), IFSCHELP(nano_nextword_msg), FALSE, 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_end, MMAIN, + N_("End"), IFSCHELP(nano_end_msg), FALSE, VIEW); - add_to_funcs(do_home, MMAIN, N_("Home"), IFSCHELP(nano_home_msg), - FALSE, 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), FALSE, VIEW); + add_to_funcs(do_down_void, MMAIN|MBROWSER, + next_line_tag, IFSCHELP(nano_nextline_msg), TRUE, 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), FALSE, VIEW); + add_to_funcs(do_para_end_void, MMAIN|MWHEREIS, + N_("End of Par"), IFSCHELP(nano_paraend_msg), FALSE, 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_void, MMAIN, N_("Enter"), IFSCHELP(nano_enter_msg), - FALSE, NOVIEW); - add_to_funcs(do_enter_void, 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), FALSE, VIEW); + add_to_funcs(do_scroll_down, MMAIN, + N_("Scroll Down"), IFSCHELP(nano_scrolldown_msg), TRUE, VIEW); +#endif + +#ifndef DISABLE_MULTIBUFFER + add_to_funcs(switch_to_prev_buffer_void, MMAIN, + N_("Prev 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 + +#if defined(NANO_TINY) && !defined(DISABLE_COLOR) + add_to_funcs(do_gotolinecolumn_void, MMAIN|MWHEREIS, + gotoline_tag, IFSCHELP(nano_gotoline_msg), TRUE, VIEW); #endif - NOVIEW); - add_to_funcs(do_backspace, MALL, "", "", + add_to_funcs(do_verbatim_input, MMAIN, + N_("Verbatim"), IFSCHELP(nano_verbatim_msg), FALSE, NOVIEW); + + add_to_funcs(do_tab, MMAIN, + N_("Tab"), IFSCHELP(nano_tab_msg), FALSE, NOVIEW); + add_to_funcs(do_enter_void, MMAIN, + N_("Enter"), IFSCHELP(nano_enter_msg), FALSE, NOVIEW); + add_to_funcs(do_delete, MMAIN, + N_("Delete"), IFSCHELP(nano_delete_msg), FALSE, NOVIEW); + add_to_funcs(do_backspace, MMAIN, + N_("Backspace"), IFSCHELP(nano_backspace_msg), #ifndef NANO_TINY FALSE, #else @@ -941,67 +877,38 @@ void shortcut_init(bool unjustify) NOVIEW); #ifndef NANO_TINY - add_to_funcs(do_cut_till_end, MMAIN, N_("CutTillEnd"), - IFSCHELP(nano_cut_till_end_msg), TRUE, NOVIEW); + add_to_funcs(do_cut_till_end, MMAIN, + N_("CutTillEnd"), IFSCHELP(nano_cut_till_end_msg), TRUE, NOVIEW); #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); + add_to_funcs(do_full_justify, MMAIN, + fulljustify_tag, IFSCHELP(nano_fulljustify_msg), FALSE, NOVIEW); #endif #ifndef NANO_TINY - add_to_funcs(do_wordlinechar_count, MMAIN, N_("Word Count"), - IFSCHELP(nano_wordcount_msg), FALSE, VIEW); + add_to_funcs(do_wordlinechar_count, MMAIN, + N_("Word Count"), IFSCHELP(nano_wordcount_msg), FALSE, VIEW); #endif - add_to_funcs(total_refresh, (MMAIN|MHELP), refresh_msg, - IFSCHELP(nano_refresh_msg), FALSE, VIEW); + add_to_funcs(total_refresh, MMAIN, + refresh_tag, IFSCHELP(nano_refresh_msg), FALSE, VIEW); - add_to_funcs(do_suspend_void, MMAIN, suspend_msg, - IFSCHELP(nano_suspend_msg), TRUE, VIEW); - -#ifndef NANO_TINY - add_to_funcs(case_sens_void, - (MWHEREIS|MREPLACE|MWHEREISFILE), - case_sens_msg, IFSCHELP(nano_case_msg), FALSE, VIEW); - - add_to_funcs(backwards_void, - (MWHEREIS|MREPLACE|MWHEREISFILE), - backwards_msg, IFSCHELP(nano_reverse_msg), FALSE, VIEW); -#endif - -#ifdef HAVE_REGEX_H - add_to_funcs(regexp_void, - (MWHEREIS|MREPLACE|MWHEREISFILE), - regexp_msg, IFSCHELP(nano_regexp_msg), FALSE, VIEW); -#endif + add_to_funcs(do_suspend_void, MMAIN, + N_("Suspend"), IFSCHELP(nano_suspend_msg), TRUE, VIEW); #ifndef NANO_TINY add_to_funcs(get_history_older_void, - (MWHEREIS|MREPLACE|MREPLACE2|MWHEREISFILE), - prev_history_msg, IFSCHELP(nano_prev_history_msg), FALSE, VIEW); + (MWHEREIS|MREPLACE|MREPLACEWITH|MWHEREISFILE), + N_("PrevHstory"), IFSCHELP(nano_prev_history_msg), FALSE, VIEW); add_to_funcs(get_history_newer_void, - (MWHEREIS|MREPLACE|MREPLACE2|MWHEREISFILE), - next_history_msg, IFSCHELP(nano_next_history_msg), FALSE, VIEW); + (MWHEREIS|MREPLACE|MREPLACEWITH|MWHEREISFILE), + N_("NextHstory"), IFSCHELP(nano_next_history_msg), FALSE, VIEW); #endif - add_to_funcs(no_replace_void, MREPLACE, - no_replace_msg, IFSCHELP(nano_whereis_msg), FALSE, VIEW); - add_to_funcs(gototext_void, MGOTOLINE, - gototext_msg, IFSCHELP(nano_whereis_msg), TRUE, VIEW); - -#ifndef DISABLE_BROWSER - if (!ISSET(RESTRICTED)) - add_to_funcs(to_files_void, - (MGOTOLINE|MINSERTFILE), - to_files_msg, IFSCHELP(nano_tofiles_msg), FALSE, VIEW); -#endif + N_("Go To Text"), IFSCHELP(nano_whereis_msg), TRUE, VIEW); #ifndef NANO_TINY /* If we're using restricted mode, the DOS format, Mac format, @@ -1010,274 +917,281 @@ 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)) + if (!ISSET(RESTRICTED)) { add_to_funcs(dos_format_void, MWRITEFILE, - dos_format_msg, IFSCHELP(nano_dos_msg), FALSE, NOVIEW); + N_("DOS Format"), IFSCHELP(nano_dos_msg), FALSE, NOVIEW); - if (!ISSET(RESTRICTED)) add_to_funcs(mac_format_void, MWRITEFILE, - mac_format_msg, IFSCHELP(nano_mac_msg), FALSE, NOVIEW); + N_("Mac Format"), IFSCHELP(nano_mac_msg), FALSE, NOVIEW); - if (!ISSET(RESTRICTED)) - add_to_funcs( append_void, MWRITEFILE, - append_msg, IFSCHELP(nano_append_msg), FALSE, NOVIEW); + add_to_funcs(append_void, MWRITEFILE, + N_("Append"), IFSCHELP(nano_append_msg), FALSE, NOVIEW); + add_to_funcs(prepend_void, MWRITEFILE, + N_("Prepend"), IFSCHELP(nano_prepend_msg), FALSE, NOVIEW); - if (!ISSET(RESTRICTED)) - add_to_funcs( prepend_void, MWRITEFILE, - prepend_msg, IFSCHELP(nano_prepend_msg), FALSE, NOVIEW); + add_to_funcs(backup_file_void, MWRITEFILE, + N_("Backup File"), IFSCHELP(nano_backup_msg), FALSE, NOVIEW); + } - if (!ISSET(RESTRICTED)) - add_to_funcs( backup_file_void, 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(ext_cmd_void, MINSERTFILE, + N_("Execute Command"), IFSCHELP(nano_execute_msg), FALSE, 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_void, MINSERTFILE, - ext_cmd_msg, IFSCHELP(nano_execute_msg), FALSE, NOVIEW); + add_to_funcs(ext_cmd_void, MEXTCMD, + read_file_tag, IFSCHELP(nano_insert_msg), FALSE, 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_void, 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), FALSE, NOVIEW); #endif + } +#endif /* !NANO_TINY */ - add_to_funcs( do_insertfile_void, MEXTCMD, - insert_file_msg, IFSCHELP(nano_insert_msg), FALSE, VIEW); +#ifndef DISABLE_BROWSER + if (!ISSET(RESTRICTED)) + add_to_funcs(to_files_void, MWRITEFILE|MINSERTFILE, + N_("To Files"), IFSCHELP(nano_tofiles_msg), FALSE, VIEW); -#ifdef ENABLE_MULTIBUFFER - add_to_funcs( new_buffer_void, MEXTCMD, - new_buffer_msg, IFSCHELP(nano_multibuffer_msg), FALSE, NOVIEW); -#endif + add_to_funcs(do_first_file, (MBROWSER|MWHEREISFILE), + N_("First File"), IFSCHELP(nano_firstfile_msg), FALSE, VIEW); + add_to_funcs(do_last_file, (MBROWSER|MWHEREISFILE), + N_("Last File"), IFSCHELP(nano_lastfile_msg), FALSE, VIEW); #endif -#ifndef DISABLE_HELP - add_to_funcs(edit_refresh, MHELP, - refresh_msg, nano_refresh_msg, FALSE, VIEW); - - add_to_funcs(do_exit, MHELP, exit_msg, IFSCHELP(nano_exit_msg), FALSE, VIEW); - - +#if !defined(NANO_TINY) && !defined(DISABLE_BROWSER) + add_to_funcs(do_research, MBROWSER, + whereis_next_tag, IFSCHELP(nano_whereis_next_msg), FALSE, VIEW); #endif -#ifndef DISABLE_BROWSER - - add_to_funcs(do_first_file, - (MBROWSER|MWHEREISFILE), - first_file_msg, IFSCHELP(nano_firstfile_msg), FALSE, VIEW); - - add_to_funcs(do_last_file, - (MBROWSER|MWHEREISFILE), - last_file_msg, IFSCHELP(nano_lastfile_msg), FALSE, VIEW); - - add_to_funcs(goto_dir_void, MBROWSER, - goto_dir_msg, IFSCHELP(nano_gotodir_msg), FALSE, VIEW); +#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), FALSE, VIEW); + add_to_funcs(do_page_down, MLINTER, + N_("Next Lint Msg"), IFSCHELP(nano_nextlint_msg), FALSE, VIEW); #endif - currmenu = MMAIN; + /* Start associating key combos with functions in specific menus. */ - 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(MMOST, "^G", do_help_void, 0, TRUE); + add_to_sclist(MMOST, "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, "Ins", 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, "^\\", do_replace, 0, TRUE); + add_to_sclist(MMAIN, "M-R", do_replace, 0, TRUE); + add_to_sclist(MMAIN, "F14", do_replace, 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_JUSTIFY + add_to_sclist(MMAIN, "^J", do_justify_void, 0, TRUE); + add_to_sclist(MMAIN, "F4", do_justify_void, 0, TRUE); +#endif #ifndef DISABLE_SPELLER add_to_sclist(MMAIN, "^T", do_spell, 0, TRUE); add_to_sclist(MMAIN, "F12", do_spell, 0, TRUE); +#else +#ifndef DISABLE_COLOR + add_to_sclist(MMAIN, "^T", do_linter, 0, TRUE); + add_to_sclist(MMAIN, "F12", do_linter, 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_void, 0, FALSE); - add_to_sclist(MWHEREIS, "^T", do_gotolinecolumn_void, 0, FALSE); +#endif + add_to_sclist(MMAIN, "^C", do_cursorpos_void, 0, TRUE); + add_to_sclist(MMAIN, "F11", do_cursorpos_void, 0, TRUE); + add_to_sclist(MMAIN, "^_", do_gotolinecolumn_void, 0, TRUE); + add_to_sclist(MMAIN, "M-G", do_gotolinecolumn_void, 0, TRUE); + add_to_sclist(MMAIN, "F13", do_gotolinecolumn_void, 0, TRUE); + add_to_sclist(MMAIN|MBROWSER|MHELP|MWHEREISFILE|MLINTER, "^Y", do_page_up, 0, TRUE); + add_to_sclist(MMAIN|MBROWSER|MHELP|MWHEREISFILE|MLINTER, "F7", do_page_up, 0, TRUE); + add_to_sclist(MMAIN|MBROWSER|MHELP|MWHEREISFILE|MLINTER, "PgUp", do_page_up, 0, TRUE); + add_to_sclist(MMAIN|MBROWSER|MHELP|MWHEREISFILE|MLINTER, "^V", do_page_down, 0, TRUE); + add_to_sclist(MMAIN|MBROWSER|MHELP|MWHEREISFILE|MLINTER, "F8", do_page_down, 0, TRUE); + add_to_sclist(MMAIN|MBROWSER|MHELP|MWHEREISFILE|MLINTER, "PgDn", do_page_down, 0, TRUE); + add_to_sclist(MMAIN|MHELP, "M-\\", do_first_line, 0, TRUE); + add_to_sclist(MMAIN|MHELP, "M-|", do_first_line, 0, TRUE); + add_to_sclist(MMAIN|MHELP, "M-/", do_last_line, 0, TRUE); + add_to_sclist(MMAIN|MHELP, "M-?", do_last_line, 0, TRUE); #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_find_bracket, 0, TRUE); + add_to_sclist(MMAIN, "^^", do_mark, 0, TRUE); + add_to_sclist(MMAIN, "M-A", do_mark, 0, TRUE); + add_to_sclist(MMAIN, "F15", do_mark, 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(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); +#endif + add_to_sclist(MMOST, "^B", do_left, 0, TRUE); + add_to_sclist(MMOST, "^F", do_right, 0, TRUE); + add_to_sclist(MMOST, "Left", do_left, 0, TRUE); + add_to_sclist(MMOST, "Right", do_right, 0, TRUE); +#ifndef NANO_TINY 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(MMOST, "^A", do_home, 0, TRUE); + add_to_sclist(MMOST, "Home", do_home, 0, TRUE); + add_to_sclist(MMOST, "^E", do_end, 0, TRUE); + add_to_sclist(MMOST, "End", do_end, 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, "Up", 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", get_history_older_void, 0, FALSE); - add_to_sclist(MWHEREIS|MREPLACE|MREPLACE2|MWHEREISFILE, "kup", get_history_older_void, 0, FALSE); - add_to_sclist(MWHEREIS|MREPLACE|MREPLACE2|MWHEREISFILE, "^N", get_history_newer_void, 0, FALSE); - add_to_sclist(MWHEREIS|MREPLACE|MREPLACE2|MWHEREISFILE, "kdown", get_history_newer_void, 0, FALSE); -#endif + add_to_sclist(MMAIN|MHELP|MBROWSER, "Down", do_down_void, 0, TRUE); #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_void, 0, FALSE); - add_to_sclist(MREPLACE, - "M-C", case_sens_void, 0, FALSE); - add_to_sclist(MREPLACE2, - "M-C", case_sens_void, 0, FALSE); - add_to_sclist(MWHEREIS|MREPLACE|MREPLACE2, - "M-B", backwards_void, 0, FALSE); - add_to_sclist(MWHEREIS|MREPLACE|MREPLACE2, - "M-R", regexp_void, 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); - -#ifndef DISABLE_BROWSER - add_to_sclist(MBROWSER|MWHEREISFILE, "M-\\", do_first_file, 0, TRUE); - add_to_sclist(MBROWSER|MWHEREISFILE, "M-|", do_first_file, 0, TRUE); - add_to_sclist(MBROWSER|MWHEREISFILE, "M-/", do_last_file, 0, TRUE); - add_to_sclist(MBROWSER|MWHEREISFILE, "M-?", do_last_file, 0, TRUE); + add_to_sclist(MMAIN, "M-(", do_para_begin_void, 0, TRUE); + add_to_sclist(MMAIN, "M-9", do_para_begin_void, 0, TRUE); + add_to_sclist(MMAIN, "M-)", do_para_end_void, 0, TRUE); + add_to_sclist(MMAIN, "M-0", do_para_end_void, 0, TRUE); #endif - add_to_sclist(MBROWSER|MWHEREISFILE, "^_", goto_dir_void, 0, TRUE); - add_to_sclist(MBROWSER|MWHEREISFILE, "F13", goto_dir_void, 0, TRUE); - add_to_sclist(MBROWSER|MWHEREISFILE, "M-G", goto_dir_void, 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); #endif - -#ifdef ENABLE_MULTIBUFFER +#ifndef DISABLE_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); #endif - add_to_sclist(MALL, "M-V", do_verbatim_input, 0, TRUE); + add_to_sclist(MMOST, "M-V", do_verbatim_input, 0, TRUE); #ifndef NANO_TINY - add_to_sclist(MALL, "M-T", do_cut_till_end, 0, TRUE); + add_to_sclist(MMAIN, "M-T", do_cut_till_end, 0, TRUE); + add_to_sclist(MMAIN, "M-D", do_wordlinechar_count, 0, TRUE); +#endif #ifndef DISABLE_JUSTIFY - add_to_sclist(MALL, "M-J", do_full_justify, 0, TRUE); + add_to_sclist(MMAIN|MWHEREIS, "M-J", do_full_justify, 0, TRUE); #endif - add_to_sclist(MMAIN, "M-D", do_wordlinechar_count, 0, TRUE); + add_to_sclist(MMAIN|MHELP, "^L", total_refresh, 0, FALSE); + add_to_sclist(MMAIN, "^Z", do_suspend_void, 0, FALSE); + +#ifndef NANO_TINY + /* Group of "Appearance" toggles. */ add_to_sclist(MMAIN, "M-X", do_toggle_void, NO_HELP, TRUE); add_to_sclist(MMAIN, "M-C", do_toggle_void, CONST_UPDATE, TRUE); add_to_sclist(MMAIN, "M-O", do_toggle_void, MORE_SPACE, TRUE); add_to_sclist(MMAIN, "M-S", do_toggle_void, SMOOTH_SCROLL, TRUE); + add_to_sclist(MMAIN, "M-$", do_toggle_void, SOFTWRAP, TRUE); add_to_sclist(MMAIN, "M-P", do_toggle_void, WHITESPACE_DISPLAY, TRUE); +#ifndef DISABLE_COLOR add_to_sclist(MMAIN, "M-Y", do_toggle_void, NO_COLOR_SYNTAX, TRUE); +#endif + + /* Group of "Editing-behavior" toggles. */ add_to_sclist(MMAIN, "M-H", do_toggle_void, SMART_HOME, TRUE); add_to_sclist(MMAIN, "M-I", do_toggle_void, AUTOINDENT, TRUE); add_to_sclist(MMAIN, "M-K", do_toggle_void, CUT_TO_END, TRUE); +#ifndef DISABLE_WRAPPING add_to_sclist(MMAIN, "M-L", do_toggle_void, NO_WRAP, TRUE); +#endif add_to_sclist(MMAIN, "M-Q", do_toggle_void, TABS_TO_SPACES, TRUE); + + /* Group of "Peripheral-feature" toggles. */ add_to_sclist(MMAIN, "M-B", do_toggle_void, BACKUP_FILE, TRUE); +#ifndef DISABLE_MULTIBUFFER add_to_sclist(MMAIN, "M-F", do_toggle_void, MULTIBUFFER, TRUE); +#endif +#ifndef DISABLE_MOUSE add_to_sclist(MMAIN, "M-M", do_toggle_void, USE_MOUSE, TRUE); +#endif add_to_sclist(MMAIN, "M-N", do_toggle_void, NO_CONVERT, TRUE); add_to_sclist(MMAIN, "M-Z", do_toggle_void, SUSPEND, TRUE); - add_to_sclist(MMAIN, "M-$", do_toggle_void, SOFTWRAP, TRUE); +#endif /* !NANO_TINY */ + + add_to_sclist(MMAIN, "^Q", xon_complaint, 0, TRUE); + add_to_sclist(MMAIN, "^S", xoff_complaint, 0, TRUE); + + add_to_sclist(((MMOST & ~MMAIN & ~MBROWSER) | MYESNO), "^C", do_cancel, 0, FALSE); + +#ifndef NANO_TINY + add_to_sclist(MWHEREIS|MREPLACE, "M-B", backwards_void, 0, FALSE); + add_to_sclist(MWHEREIS|MREPLACE, "M-C", case_sens_void, 0, FALSE); #endif - add_to_sclist(MGOTOLINE, "^T", gototext_void, 0, FALSE); - add_to_sclist(MINSERTFILE|MEXTCMD, "M-F", new_buffer_void, 0, FALSE); - add_to_sclist((MWHEREIS|MREPLACE|MREPLACE2|MGOTOLINE|MWRITEFILE|MINSERTFILE|MEXTCMD|MSPELL|MWHEREISFILE|MGOTODIR|MYESNO), - "^C", do_cancel, 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_void, 0, FALSE); - add_to_sclist(MWRITEFILE, "M-M", mac_format_void, 0, FALSE); - add_to_sclist(MWRITEFILE, "M-A", append_void, 0, FALSE); - add_to_sclist(MWRITEFILE, "M-P", prepend_void, 0, FALSE); - add_to_sclist(MWRITEFILE, "M-B", backup_file_void, 0, FALSE); - add_to_sclist(MWRITEFILE, "^T", to_files_void, 0, FALSE); - add_to_sclist(MINSERTFILE, "^T", to_files_void, 0, FALSE); - add_to_sclist(MINSERTFILE, "^X", ext_cmd_void, 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_void, 0, TRUE); - add_to_sclist(MALL, "kenter", do_enter_void, 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); + add_to_sclist(MWHEREIS|MREPLACE, "M-R", regexp_void, 0, FALSE); + add_to_sclist(MWHEREIS, "^R", do_replace, 0, FALSE); + add_to_sclist(MREPLACE, "^R", no_replace_void, 0, FALSE); + add_to_sclist(MWHEREIS|MREPLACE|MREPLACEWITH|MGOTOLINE, "^Y", do_first_line, 0, TRUE); + add_to_sclist(MWHEREIS|MREPLACE|MREPLACEWITH|MGOTOLINE, "^V", do_last_line, 0, TRUE); +#ifndef DISABLE_JUSTIFY + add_to_sclist(MWHEREIS|MREPLACE|MREPLACEWITH, "^W", do_para_begin_void, 0, TRUE); + add_to_sclist(MWHEREIS|MREPLACE|MREPLACEWITH, "^O", do_para_end_void, 0, TRUE); +#endif + add_to_sclist(MWHEREIS, "^T", do_gotolinecolumn_void, 0, FALSE); + add_to_sclist(MGOTOLINE, "^T", gototext_void, 0, FALSE); +#ifndef NANO_TINY + add_to_sclist(MWHEREIS|MREPLACE|MREPLACEWITH|MWHEREISFILE, "^P", get_history_older_void, 0, FALSE); + add_to_sclist(MWHEREIS|MREPLACE|MREPLACEWITH|MWHEREISFILE, "Up", get_history_older_void, 0, FALSE); + add_to_sclist(MWHEREIS|MREPLACE|MREPLACEWITH|MWHEREISFILE, "^N", get_history_newer_void, 0, FALSE); + add_to_sclist(MWHEREIS|MREPLACE|MREPLACEWITH|MWHEREISFILE, "Down", get_history_newer_void, 0, FALSE); +#endif +#ifndef DISABLE_BROWSER + add_to_sclist(MBROWSER|MWHEREISFILE, "M-\\", do_first_file, 0, TRUE); + add_to_sclist(MBROWSER|MWHEREISFILE, "M-|", do_first_file, 0, TRUE); + add_to_sclist(MBROWSER|MWHEREISFILE, "M-/", do_last_file, 0, TRUE); + add_to_sclist(MBROWSER|MWHEREISFILE, "M-?", do_last_file, 0, TRUE); + add_to_sclist(MBROWSER|MWHEREISFILE, "^_", goto_dir_void, 0, TRUE); + add_to_sclist(MBROWSER|MWHEREISFILE, "M-G", goto_dir_void, 0, TRUE); + add_to_sclist(MBROWSER|MWHEREISFILE, "F13", goto_dir_void, 0, TRUE); +#endif + add_to_sclist(MWRITEFILE, "M-D", dos_format_void, 0, FALSE); + add_to_sclist(MWRITEFILE, "M-M", mac_format_void, 0, FALSE); + add_to_sclist(MWRITEFILE, "M-A", append_void, 0, FALSE); + add_to_sclist(MWRITEFILE, "M-P", prepend_void, 0, FALSE); + add_to_sclist(MWRITEFILE, "M-B", backup_file_void, 0, FALSE); +#ifndef DISABLE_BROWSER + add_to_sclist(MWRITEFILE|MINSERTFILE, "^T", to_files_void, 0, FALSE); +#endif + add_to_sclist(MINSERTFILE|MEXTCMD, "^X", ext_cmd_void, 0, FALSE); + add_to_sclist(MINSERTFILE|MEXTCMD, "M-F", new_buffer_void, 0, FALSE); + add_to_sclist(MHELP|MBROWSER, "^C", do_exit, 0, TRUE); +#ifndef DISABLE_HELP + add_to_sclist(MHELP, "^G", do_exit, 0, TRUE); +#endif + add_to_sclist(MMOST, "^I", do_tab, 0, TRUE); + add_to_sclist(MMOST, "^M", do_enter_void, 0, TRUE); + add_to_sclist(MMOST, "Enter", do_enter_void, 0, TRUE); + add_to_sclist(MMOST, "^D", do_delete, 0, TRUE); + add_to_sclist(MMOST, "Del", do_delete, 0, TRUE); + add_to_sclist(MMOST, "^H", do_backspace, 0, TRUE); + add_to_sclist(MMOST, "Bsp", do_backspace, 0, TRUE); #ifdef DEBUG print_sclist(); #endif - } -/* Free the given shortcut. */ -void free_shortcutage(shortcut **shortcutage) +#ifndef DISABLE_COLOR +void set_lint_shortcuts(void) { - assert(shortcutage != NULL); +#ifndef DISABLE_SPELLER + replace_scs_for(do_spell, do_linter); +#endif +} - while (*shortcutage != NULL) { - shortcut *ps = *shortcutage; - *shortcutage = (*shortcutage)->next; - free(ps); - } +void set_spell_shortcuts(void) +{ +#ifndef DISABLE_SPELLER + replace_scs_for(do_linter, do_spell); +#endif } +#endif const subnfunc *sctofunc(sc *s) { @@ -1290,12 +1204,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) { 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"); @@ -1303,6 +1219,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: @@ -1314,7 +1232,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: @@ -1327,23 +1245,21 @@ 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, complete with the proper value for execute. */ +sc *strtosc(char *input) { - sc *s; + sc *s; s = (sc *)nmalloc(sizeof(sc)); - s->execute = TRUE; /* overridden as needed below */ - + s->execute = TRUE; /* will be overridden as needed below */ #ifndef DISABLE_HELP if (!strcasecmp(input, "help")) @@ -1361,49 +1277,46 @@ sc *strtosc(int menu, char *input) 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; +#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; else if (!strcasecmp(input, "uncut")) s->scfunc = do_uncut_text; +#ifndef NANO_TINY + else if (!strcasecmp(input, "cutrestoffile")) + s->scfunc = do_cut_till_end; + 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")) + !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; else if (!strcasecmp(input, "gotoline")) s->scfunc = do_gotolinecolumn_void; - else if (!strcasecmp(input, "replace")) - s->scfunc = do_replace; #ifndef DISABLE_JUSTIFY else if (!strcasecmp(input, "justify")) 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; else if (!strcasecmp(input, "endpara")) s->scfunc = do_para_end_void; - else if (!strcasecmp(input, "fulljustify")) - s->scfunc = do_full_justify; #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; else if (!strcasecmp(input, "unindent")) @@ -1412,12 +1325,10 @@ sc *strtosc(int menu, char *input) 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; else if (!strcasecmp(input, "prevword")) 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; else if (!strcasecmp(input, "wordcount")) @@ -1432,8 +1343,7 @@ sc *strtosc(int menu, char *input) } else if (!strcasecmp(input, "nexthistory")) { s->scfunc = get_history_newer_void; s->execute = FALSE; - } else if (!strcasecmp(input, "nohelp") || - !strcasecmp(input, "nohelp")) { + } else if (!strcasecmp(input, "nohelp")) { s->scfunc = do_toggle_void; s->execute = FALSE; s->toggle = NO_HELP; @@ -1449,14 +1359,20 @@ sc *strtosc(int menu, char *input) s->scfunc = do_toggle_void; s->execute = FALSE; s->toggle = SMOOTH_SCROLL; + } else if (!strcasecmp(input, "softwrap")) { + s->scfunc = do_toggle_void; + s->execute = FALSE; + s->toggle = SOFTWRAP; } else if (!strcasecmp(input, "whitespacedisplay")) { s->scfunc = do_toggle_void; s->execute = FALSE; s->toggle = WHITESPACE_DISPLAY; +#ifndef DISABLE_COLOR } else if (!strcasecmp(input, "nosyntax")) { s->scfunc = do_toggle_void; s->execute = FALSE; s->toggle = NO_COLOR_SYNTAX; +#endif } else if (!strcasecmp(input, "smarthome")) { s->scfunc = do_toggle_void; s->execute = FALSE; @@ -1469,10 +1385,12 @@ sc *strtosc(int menu, char *input) s->scfunc = do_toggle_void; s->execute = FALSE; s->toggle = CUT_TO_END; +#ifndef DISABLE_WRAPPING } else if (!strcasecmp(input, "nowrap")) { s->scfunc = do_toggle_void; s->execute = FALSE; s->toggle = NO_WRAP; +#endif } else if (!strcasecmp(input, "tabstospaces")) { s->scfunc = do_toggle_void; s->execute = FALSE; @@ -1481,14 +1399,18 @@ sc *strtosc(int menu, char *input) s->scfunc = do_toggle_void; s->execute = FALSE; s->toggle = BACKUP_FILE; - } else if (!strcasecmp(input, "mutlibuffer")) { +#ifndef DISABLE_MULTIBUFFER + } else if (!strcasecmp(input, "multibuffer")) { s->scfunc = do_toggle_void; s->execute = FALSE; s->toggle = MULTIBUFFER; +#endif +#ifndef DISABLE_MOUSE } else if (!strcasecmp(input, "mouse")) { s->scfunc = do_toggle_void; s->execute = FALSE; s->toggle = USE_MOUSE; +#endif } else if (!strcasecmp(input, "noconvert")) { s->scfunc = do_toggle_void; s->execute = FALSE; @@ -1498,24 +1420,34 @@ sc *strtosc(int menu, char *input) s->execute = FALSE; s->toggle = SUSPEND; } -#endif /* NANO_TINY */ - else if (!strcasecmp(input, "right") || - !strcasecmp(input, "forward")) - s->scfunc = do_right; +#endif /* !NANO_TINY */ else if (!strcasecmp(input, "left") || - !strcasecmp(input, "back")) + !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")) + !strcasecmp(input, "prevline")) s->scfunc = do_up_void; else if (!strcasecmp(input, "down") || - !strcasecmp(input, "nextline")) + !strcasecmp(input, "nextline")) s->scfunc = do_down_void; else if (!strcasecmp(input, "home")) s->scfunc = do_home; else if (!strcasecmp(input, "end")) s->scfunc = do_end; -#ifdef ENABLE_MULTIBUFFER + 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; else if (!strcasecmp(input, "nextbuf")) @@ -1533,23 +1465,32 @@ sc *strtosc(int menu, char *input) s->scfunc = do_backspace; else if (!strcasecmp(input, "refresh")) s->scfunc = total_refresh; + else if (!strcasecmp(input, "suspend")) + s->scfunc = do_suspend_void; else if (!strcasecmp(input, "casesens")) { s->scfunc = case_sens_void; s->execute = FALSE; +#ifndef NANO_TINY } else if (!strcasecmp(input, "regexp") || - !strcasecmp(input, "regex")) { + !strcasecmp(input, "regex")) { s->scfunc = regexp_void; s->execute = FALSE; + } else if (!strcasecmp(input, "backwards")) { + s->scfunc = backwards_void; + s->execute = FALSE; +#endif } else if (!strcasecmp(input, "dontreplace")) { s->scfunc = no_replace_void; s->execute = FALSE; } else if (!strcasecmp(input, "gototext")) { s->scfunc = gototext_void; s->execute = FALSE; +#ifndef DISABLE_BROWSER } else if (!strcasecmp(input, "browser") || - !strcasecmp(input, "tofiles")) { + !strcasecmp(input, "tofiles")) { s->scfunc = to_files_void; s->execute = FALSE; +#endif } else if (!strcasecmp(input, "dosformat")) { s->scfunc = dos_format_void; s->execute = FALSE; @@ -1565,7 +1506,7 @@ sc *strtosc(int menu, char *input) } else if (!strcasecmp(input, "backup")) { s->scfunc = backup_file_void; s->execute = FALSE; -#ifdef ENABLE_MULTIBUFFER +#ifndef DISABLE_MULTIBUFFER } else if (!strcasecmp(input, "newbuffer")) { s->scfunc = new_buffer_void; s->execute = FALSE; @@ -1582,17 +1523,14 @@ sc *strtosc(int menu, char *input) free(s); return NULL; } - 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")) @@ -1600,8 +1538,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")) @@ -1609,22 +1547,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; +#endif +#ifndef DISABLE_SPELLER else if (!strcasecmp(input, "spell")) 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 @@ -1674,12 +1619,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) { @@ -1687,8 +1630,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) { @@ -1697,6 +1639,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; @@ -1717,7 +1679,7 @@ void thanks_for_all_the_fish(void) syntaxes = syntaxes->next; free(bill); } -#endif /* ENABLE_COLOR */ +#endif /* !DISABLE_COLOR */ #ifndef NANO_TINY /* Free the search and replace history lists. */ if (searchage != NULL) @@ -1725,11 +1687,21 @@ void thanks_for_all_the_fish(void) 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 */ - @@ -1,9 +1,9 @@ -/* $Id: help.c 4535 2011-02-26 14:22:37Z astyanax $ */ +/* $Id: help.c 4876 2014-05-13 20:34:15Z 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) * @@ -38,8 +38,6 @@ 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. */ size_t line = 0; /* The line number in help_text of the first displayed help * line. This variable is zero-based. */ @@ -47,8 +45,8 @@ void do_help(void (*refresh_func)(void)) /* 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; + /* The menu we were called from. */ #endif const char *ptr; /* The current line of the help text. */ @@ -59,7 +57,6 @@ void do_help(void (*refresh_func)(void)) curs_set(0); blank_edit(); - wattroff(bottomwin, reverse_attr); blank_statusbar(); /* Set help_text as the string to display. */ @@ -94,7 +91,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 @@ -129,25 +126,23 @@ void do_help(void (*refresh_func)(void)) kbinput = get_kbinput(edit, &meta_key, &func_key); #ifndef DISABLE_MOUSE - if (kbinput == KEY_MOUSE) { + if (kbinput == KEY_MOUSE) { int mouse_x, mouse_y; get_mouseinput(&mouse_x, &mouse_y, TRUE); - continue; - /* Redraw the screen. */ + continue; /* Redraw the screen. */ } #endif - parse_help_input(&kbinput, &meta_key, &func_key); - s = get_shortcut(MHELP, &kbinput, &meta_key, &func_key); + parse_help_input(&kbinput, &meta_key); + s = get_shortcut(MHELP, &kbinput, &meta_key); if (!s) continue; - f = sctofunc((sc *) s); + f = sctofunc((sc *) s); if (!f) continue; - if (f->scfunc == total_refresh) { + if (f->scfunc == total_refresh) { total_redraw(); - break; } else if (f->scfunc == do_page_up) { if (line > editwinrows - 2) line -= editwinrows - 2; @@ -165,17 +160,14 @@ void do_help(void (*refresh_func)(void)) } 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; + /* Abort the help browser. */ + break; } } @@ -201,14 +193,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 +208,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 +216,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 +376,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_void) - 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 +416,39 @@ 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, "")) + 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) { - - if (scsfound == 3) - continue; + /* Let's simply show the first two shortcuts from the list. */ + for (s = sclist, scsfound = 0; s != NULL; s = s->next) { - if (s->type == RAWINPUT) + 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,17 +460,19 @@ 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_void) - 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. */ @@ -495,27 +480,25 @@ void help_init(void) } /* 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 + * (the key itself) and meta_key (whether the key is a meta sequence). + * Also convert certain non-shortcut keys into their corresponding * shortcut keys. */ -void parse_help_input(int *kbinput, bool *meta_key, bool *func_key) +void parse_help_input(int *kbinput, bool *meta_key) { - get_shortcut(MHELP, kbinput, meta_key, func_key); + get_shortcut(MHELP, kbinput, meta_key); if (!*meta_key) { switch (*kbinput) { /* For consistency with the file browser. */ case ' ': - *kbinput = sc_seq_or(do_page_up, 0); + *kbinput = KEY_NPAGE; break; case '-': - *kbinput = sc_seq_or(do_page_down, 0);; + *kbinput = KEY_PPAGE; break; - /* Cancel is equivalent to Exit here. */ case 'E': case 'e': - *kbinput = sc_seq_or(do_exit, 0);; + *kbinput = sc_seq_or(do_exit, 0); break; } } @@ -547,17 +530,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 */ } @@ -1,9 +1,9 @@ -/* $Id: move.c 4548 2012-12-30 19:20:10Z astyanax $ */ +/* $Id: move.c 4894 2014-05-16 10:34:05Z 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. */ @@ -79,8 +79,8 @@ void do_page_up(void) 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 %lu len %d\n", + i, skipped, (unsigned long) openfile->current->lineno, strlenpt(openfile->current->data)); #endif } } @@ -89,7 +89,8 @@ openfile->current->lineno, strlenpt(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. */ @@ -563,13 +564,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,27 +580,43 @@ 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 ) { +#ifndef NANO_TINY + if (amount < 1 || scroll_only) + amount = 1; +#endif edit_scroll(DOWN_DIR, #ifndef NANO_TINY - (ISSET(SMOOTH_SCROLL) || scroll_only) ? 1 : + (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 @@ -1,9 +1,9 @@ -/* $Id: nano.c 4549 2013-01-01 03:24:39Z astyanax $ */ +/* $Id: nano.c 4924 2014-05-28 15:44:11Z 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 @@ -297,6 +297,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 +315,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 +324,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 @@ -369,7 +372,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 +385,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 +411,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 +422,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 +445,9 @@ 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. */ + openfile->fileage = copy_filestruct(somebuffer); openfile->filebot = openfile->fileage; while (openfile->filebot->next != NULL) openfile->filebot = openfile->filebot->next; @@ -465,7 +469,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; @@ -603,7 +612,7 @@ void finish(void) /* Restore the old terminal settings. */ tcsetattr(0, TCSANOW, &oldterm); -#if !defined(NANO_TINY) && defined(ENABLE_NANORC) +#if !defined(NANO_TINY) && !defined(DISABLE_NANORC) if (!no_rcfiles && ISSET(HISTORYLOG)) save_history(); if (!no_rcfiles && ISSET(POS_HISTORY)) { @@ -647,7 +656,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; @@ -713,6 +722,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 @@ -815,7 +826,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")); @@ -826,8 +837,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")); @@ -841,10 +853,10 @@ 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 DISABLE_NANORC #ifndef NANO_TINY print_opt("-G", "--locking", N_("Use (vim-style) lock files")); @@ -887,7 +899,7 @@ 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 @@ -895,6 +907,7 @@ void usage(void) print_opt("-d", "--rebinddelete", N_("Fix Backspace/Delete confusion problem")); #ifndef NANO_TINY + print_opt("-h", "--help", N_("Show this help text")); print_opt("-i", "--autoindent", N_("Automatically indent new lines")); print_opt("-k", "--cut", N_("Cut from cursor to end of line")); @@ -904,6 +917,7 @@ 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")); @@ -914,7 +928,7 @@ void usage(void) N_("Silently ignore startup issues like rc file errors")); #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>"), @@ -928,17 +942,13 @@ void usage(void) 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 @@ -948,26 +958,79 @@ 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(" (C) 1999..2014 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_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_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"); @@ -981,29 +1044,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"); @@ -1065,9 +1120,9 @@ void do_exit(void) #ifndef NANO_TINY if (ISSET(LOCKING) && openfile->lock_filename) delete_lockfile(openfile->lock_filename); -#endif /* NANO_TINY */ +#endif -#ifdef ENABLE_MULTIBUFFER +#ifndef DISABLE_MULTIBUFFER /* Exit only if there are no more open file buffers. */ if (!close_buffer()) #endif @@ -1076,11 +1131,10 @@ void do_exit(void) } else if (i != 1) statusbar(_("Cancelled")); - shortcut_init(FALSE); display_main_list(); } -/* Another placeholder for function mapping */ +/* Another placeholder for function mapping. */ void do_cancel(void) { ; @@ -1090,15 +1144,14 @@ static struct sigaction pager_oldaction, pager_newaction; /* Original and tempo 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"); @@ -1118,15 +1171,14 @@ void finish_stdin_pager(void) 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 */ + /* 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(); @@ -1135,8 +1187,8 @@ void stdin_pager(void) 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 @@ -1156,8 +1208,6 @@ void stdin_pager(void) finish_stdin_pager(); } - - /* Initialize the signal handlers. */ void signal_init(void) { @@ -1295,7 +1345,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 @@ -1353,11 +1403,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); @@ -1375,13 +1425,13 @@ 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; @@ -1393,25 +1443,24 @@ void do_toggle(int flag) 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")); } -/* Bleh */ +/* Bleh. */ void do_toggle_void(void) { -; + ; } #endif /* !NANO_TINY */ @@ -1517,15 +1566,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 + * meta sequence, set func_key to TRUE if the character is a function key. + * 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 *meta_key, bool *func_key, bool allow_funcs) { int input; /* The character we read in. */ @@ -1538,10 +1582,6 @@ int do_input(bool *meta_key, bool *func_key, bool *s_or_t, bool 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); @@ -1567,7 +1607,7 @@ int do_input(bool *meta_key, bool *func_key, bool *s_or_t, bool } /* Check for a shortcut in the main list. */ - s = get_shortcut(MMAIN, &input, meta_key, func_key); + s = get_shortcut(MMAIN, &input, meta_key); /* If we got a shortcut from the main list, or a "universal" * edit window shortcut, set have_shortcut to TRUE. */ @@ -1610,8 +1650,7 @@ int do_input(bool *meta_key, bool *func_key, bool *s_or_t, bool 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. */ + * for verbatim input, turn off prepending of wrapped text. */ if (have_shortcut && (!have_shortcut || s == NULL || s->scfunc != do_verbatim_input)) wrap_reset(); @@ -1640,11 +1679,7 @@ 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. */ + /* Handle the normal edit-window shortcuts. */ default: /* If the function associated with this shortcut is * cutting or copying text, indicate this. */ @@ -1658,19 +1693,17 @@ int do_input(bool *meta_key, bool *func_key, bool *s_or_t, bool if (s->scfunc != 0) { const subnfunc *f = sctofunc((sc *) s); - *ran_func = TRUE; if (ISSET(VIEW_MODE) && f && !f->viewok) print_view_warning(); else { #ifndef NANO_TINY if (s->scfunc == do_toggle_void) do_toggle(s->toggle); - else { -#else - { + else #endif + { s->scfunc(); -#ifdef ENABLE_COLOR +#ifndef DISABLE_COLOR if (f && !f->viewok && openfile->syntax != NULL && openfile->syntax->nmultis > 0) { reset_multis(openfile->current, FALSE); @@ -1678,16 +1711,14 @@ int do_input(bool *meta_key, bool *func_key, bool *s_or_t, bool #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; } - } } } - *finished = TRUE; break; } } @@ -1725,7 +1756,9 @@ int do_mouse(void) /* 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); @@ -1734,7 +1767,7 @@ int do_mouse(void) fprintf(stderr, "mouse_y = %d, current_y = %d\n", mouse_y, openfile->current_y); #endif - if (ISSET(SOFTWRAP)) { + if (ISSET(SOFTWRAP)) { int i = 0; for (openfile->current = openfile->edittop; openfile->current->next && i < mouse_y; @@ -1793,19 +1826,19 @@ int do_mouse(void) } #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)); } -/* 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; @@ -1813,30 +1846,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 %lu... ", (unsigned long) fileptr->lineno); #endif alloc_multidata_if_needed(fileptr); @@ -1844,38 +1873,39 @@ 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 %d... ", 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 %lu to find end... ", (unsigned 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; @@ -1883,18 +1913,16 @@ void precalc_multicolorinfo(void) 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); @@ -1907,21 +1935,19 @@ void precalc_multicolorinfo(void) #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 %lu as CBEGINBEFORE\n", (unsigned 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 %lu pos %d to continue\n", (unsigned long) fileptr->lineno, 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; @@ -1932,14 +1958,14 @@ 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, orig_lenpt = 0, i = 0; char *char_buf = charalloc(mb_cur_max()); int char_buf_len; @@ -1998,7 +2024,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 == @@ -2009,6 +2035,10 @@ 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)) @@ -2016,7 +2046,7 @@ void do_output(char *output, size_t output_len, bool allow_cntrls) 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)) @@ -2025,7 +2055,7 @@ void do_output(char *output, size_t output_len, bool allow_cntrls) } /* Well we might also need a full refresh if we've changed the - line length to be a new multiple of COLS */ + * 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) edit_refresh_needed = TRUE; @@ -2034,8 +2064,7 @@ void do_output(char *output, size_t output_len, bool allow_cntrls) openfile->placewewant = xplustabs(); - -#ifdef ENABLE_COLOR +#ifndef DISABLE_COLOR reset_multis(openfile->current, FALSE); #endif if (edit_refresh_needed == TRUE) { @@ -2056,7 +2085,7 @@ int main(int argc, char **argv) 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. */ @@ -2065,10 +2094,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'}, @@ -2080,7 +2109,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'}, @@ -2089,6 +2118,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 @@ -2151,7 +2181,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) @@ -2161,11 +2191,11 @@ int main(int argc, char **argv) while ((optchr = #ifdef HAVE_GETOPT_LONG getopt_long(argc, argv, - "h?ABC:DEFGHIKLNOPQ:RST:UVWY:abcdefgijklmo:pqr:s:tuvwxz$", + "ABC:DEFGHIKLNOPQ:RST:UVWY:abcdefghijklmno:pqr:s:tuvwxz$", long_options, NULL) #else getopt(argc, argv, - "h?ABC:DEFGHIKLNOPQ:RST:UVWY:abcdefgijklmo:pqr:s:tuvwxz$") + "ABC:DEFGHIKLNOPQ:RST:UVWY:abcdefghijklmno:pqr:s:tuvwxz$") #endif ) != -1) { switch (optchr) { @@ -2196,12 +2226,12 @@ 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 DISABLE_NANORC #ifndef NANO_TINY case 'G': SET(LOCKING); @@ -2266,7 +2296,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; @@ -2293,6 +2323,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); @@ -2333,11 +2366,9 @@ int main(int argc, char **argv) #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': @@ -2351,8 +2382,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); } } @@ -2367,20 +2402,19 @@ int main(int argc, char **argv) if (ISSET(RESTRICTED)) { UNSET(SUSPEND); UNSET(BACKUP_FILE); -#ifdef ENABLE_NANORC +#ifndef DISABLE_NANORC no_rcfiles = TRUE; #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; @@ -2463,7 +2497,7 @@ 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 @@ -2475,12 +2509,12 @@ 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 /* Set up the search/replace history. */ history_init(); -#ifdef ENABLE_NANORC +#ifndef DISABLE_NANORC if (!no_rcfiles) { if (ISSET(HISTORYLOG) || ISSET(POS_HISTORY)) { if (check_dotnano() == 0) { @@ -2493,10 +2527,8 @@ int main(int argc, char **argv) if (ISSET(POS_HISTORY)) load_poshistory(); } -#endif /* ENABLE_NANORC */ -#endif /* NANO_TINY */ +#endif /* !DISABLE_NANORC */ -#ifndef NANO_TINY /* Set up the backup directory (unless we're using restricted mode, * in which case backups are disabled, since they would allow * reading from or writing to files not specified on the command @@ -2504,7 +2536,7 @@ int main(int argc, char **argv) * that backup files will be saved there. */ if (!ISSET(RESTRICTED)) init_backup_dir(); -#endif +#endif /* !NANO_TINY */ #ifndef DISABLE_OPERATINGDIR /* Set up the operating directory. This entails chdir()ing there, @@ -2565,16 +2597,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) @@ -2609,6 +2653,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 @@ -2627,7 +2684,7 @@ int main(int argc, char **argv) optind++; } -#ifdef ENABLE_MULTIBUFFER +#ifndef DISABLE_MULTIBUFFER old_multibuffer = ISSET(MULTIBUFFER); SET(MULTIBUFFER); @@ -2653,19 +2710,19 @@ int main(int argc, char **argv) iline = 1; icol = 1; } -#ifndef NANO_TINY +#if !defined(NANO_TINY) && !defined(DISABLE_NANORC) else { - /* See if we have a POS history to use if we haven't overridden it */ + /* 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 /* NANO_TINY */ +#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 @@ -2682,7 +2739,7 @@ int main(int argc, char **argv) UNSET(VIEW_MODE); } -#ifdef ENABLE_MULTIBUFFER +#ifndef DISABLE_MULTIBUFFER if (!old_multibuffer) UNSET(MULTIBUFFER); #endif @@ -2691,29 +2748,30 @@ 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) do_gotolinecolumn(startline, startcol, FALSE, FALSE, FALSE, FALSE); -# ifndef NANO_TINY +#if !defined(NANO_TINY) && !defined(DISABLE_NANORC) else { - /* See if we have a POS history to use if we haven't overridden it */ + /* 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 /* NANO_TINY */ +#endif display_main_list(); display_buffer(); while (TRUE) { - bool meta_key, func_key, s_or_t, ran_func, finished; + bool meta_key, func_key; /* Make sure the cursor is in the edit window. */ reset_cursor(); @@ -2743,11 +2801,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(&meta_key, &func_key, TRUE); } /* We should never get here. */ assert(FALSE); } - @@ -1,9 +1,9 @@ -/* $Id: nano.h 4569 2013-03-17 22:09:38Z astyanax $ */ +/* $Id: nano.h 4908 2014-05-25 19:41:49Z bens $ */ /************************************************************************** * 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) * @@ -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) @@ -189,10 +188,18 @@ typedef enum { } function_type; typedef enum { - ADD, DEL, REPLACE, SPLIT, UNSPLIT, CUT, UNCUT, ENTER, INSERT, OTHER + ADD, DEL, REPLACE, SPLIT, UNSPLIT, CUT, CUT_EOF, PASTE, ENTER, INSERT, 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. */ @@ -215,50 +222,68 @@ 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 */ - exttype *magics; - /* Regexes to match libmagic results */ + 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. */ 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. */ @@ -271,8 +296,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; @@ -298,43 +324,44 @@ 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 */ + /* String type data we will use for copying the affected line back. */ char *strdata2; - /* Sigh, need this too it looks like */ + /* Sigh, need this too, it looks like. */ 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 */ + /* Was the marker set when we cut? */ bool to_end; - /* was this a cut to end */ + /* Was this a cut to end? */ 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; typedef struct poshiststruct { char *filename; - /* The file. */ + /* The file. */ ssize_t lineno; - /* Line number we left off on */ + /* Line number we left off on. */ ssize_t xno; - /* x position in the file we left off on */ + /* x position in the file we left off on. */ struct poshiststruct *next; } poshiststruct; -#endif /* NANO_TINY */ + +#endif /* !NANO_TINY */ typedef struct openfilestruct { @@ -353,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; @@ -371,16 +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 */ + /* 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 @@ -400,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); @@ -419,7 +435,7 @@ typedef struct shortcut { /* Next shortcut. */ } shortcut; -#ifdef ENABLE_NANORC +#ifndef DISABLE_NANORC typedef struct rcoption { const char *name; /* The name of the rcfile option. */ @@ -431,29 +447,29 @@ typedef struct rcoption { typedef struct sc { char *keystr; - /* The shortcut key for a function, ASCII version */ + /* The shortcut key for a function, ASCII version. */ function_type type; - /* What kind of function key is it for convenience later */ + /* What kind of function key it is, for convenience later. */ int seq; - /* The actual sequence to check on the type is determined */ + /* The actual sequence to check on the type is determined. */ int menu; - /* What list does this apply to */ + /* What list this applies to. */ void (*scfunc)(void); - /* The function we're going to run */ + /* 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 { void (*scfunc)(void); - /* What function is this */ + /* 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 @@ -464,16 +480,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, @@ -513,270 +537,50 @@ enum UNDOABLE, SOFTWRAP, POS_HISTORY, - LOCKING + 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 */ +#ifndef NANO_TINY +/* Extra bits for the undo function. */ #define UNdel_del (1<<0) #define UNdel_backspace (1<<1) #define UNsplit_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. */ - +#define UNcut_cutline (1<<3) #endif /* !NANO_TINY */ #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 8a67e51e..12366dd7 100644 --- a/src/prompt.c +++ b/src/prompt.c @@ -1,9 +1,9 @@ -/* $Id: prompt.c 4527 2011-02-07 14:45:56Z astyanax $ */ +/* $Id: prompt.c 4878 2014-05-13 21:11:59Z 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) * @@ -93,7 +93,7 @@ int do_statusbar_input(bool *meta_key, bool *func_key, bool *have_shortcut, } /* Check for a shortcut in the current list. */ - s = get_shortcut(currmenu, &input, meta_key, func_key); + s = get_shortcut(currmenu, &input, meta_key); /* If we got a shortcut from the current list, or a "universal" * statusbar prompt shortcut, set have_shortcut to TRUE. */ @@ -131,7 +131,7 @@ int do_statusbar_input(bool *meta_key, bool *func_key, bool *have_shortcut, /* 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 (*have_shortcut || get_key_buffer_len() == 0) { if (kbinput != NULL) { /* Display all the characters in the input buffer at * once, filtering out control characters. */ @@ -191,7 +191,7 @@ int do_statusbar_input(bool *meta_key, bool *func_key, bool *have_shortcut, 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. */ + * prompt, disable verbatim input. */ if (!ISSET(RESTRICTED) || openfile->filename[0] == '\0' || currmenu != MWRITEFILE) { @@ -225,15 +225,14 @@ 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 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. */ f = sctofunc((sc *) s); - if (s->scfunc != 0 && s->execute == TRUE) { - *ran_func = TRUE; + if (s->scfunc != 0 && s->execute == TRUE) { + *ran_func = TRUE; if (f && (!ISSET(VIEW_MODE) || (f->viewok))) f->scfunc(); } @@ -325,7 +324,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); @@ -859,7 +858,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(); @@ -872,7 +873,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); @@ -981,7 +983,7 @@ fprintf(stderr, "get_prompt_string: answer = \"%s\", statusbar_x = %lu\n", answe &ran_func, &finished, TRUE, refresh_func); assert(statusbar_x <= strlen(answer)); - s = get_shortcut(currmenu, &kbinput, meta_key, func_key); + s = get_shortcut(currmenu, &kbinput, meta_key); if (s) if (s->scfunc == do_cancel || s->scfunc == do_enter_void) @@ -990,106 +992,92 @@ fprintf(stderr, "get_prompt_string: answer = \"%s\", statusbar_x = %lu\n", answe #ifndef DISABLE_TABCOMP if (s && s->scfunc != 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); +#ifndef NANO_TINY + 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 + 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); + if (allow_tabs) + answer = input_tab(answer, allow_files, &statusbar_x, + &tabbed, refresh_func, list); - update_statusbar_line(answer, statusbar_x); + update_statusbar_line(answer, statusbar_x); } else #endif /* !DISABLE_TABCOMP */ #ifndef NANO_TINY if (s && s->scfunc == 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); - } + 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 (s && s->scfunc == 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); - } + 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); + 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; - } + /* 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); + 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; + /* 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; @@ -1103,8 +1091,8 @@ fprintf(stderr, "get_prompt_string: answer = \"%s\", statusbar_x = %lu\n", answe #ifndef NANO_TINY - /* Set the current position in the history list to the bottom and - * free magichistory, if we need to. */ + /* 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); @@ -1119,7 +1107,7 @@ fprintf(stderr, "get_prompt_string: answer = \"%s\", statusbar_x = %lu\n", answe * we've finished putting in an answer, reset the statusbar cursor * position too. */ if (s) { - if (s->scfunc == do_cancel || s->scfunc == do_enter_void || + if (s->scfunc == do_cancel || s->scfunc == do_enter_void || ran_func) { statusbar_x = old_statusbar_x; statusbar_pww = old_pww; @@ -1206,7 +1194,7 @@ int do_prompt(bool allow_tabs, /* If we left the prompt via Cancel or Enter, set the return value * properly. */ - if (s && s->scfunc == do_cancel) + if (s && s->scfunc == do_cancel) retval = -1; else if (s && s->scfunc == do_enter_void) retval = (*answer == '\0') ? -2 : 0; @@ -1293,12 +1281,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. */ @@ -1314,9 +1305,9 @@ int do_yesno_prompt(bool all, const char *msg) currmenu = MYESNO; kbinput = get_kbinput(bottomwin, &meta_key, &func_key); - s = get_shortcut(currmenu, &kbinput, &meta_key, &func_key); + s = get_shortcut(currmenu, &kbinput, &meta_key); - if (s && s->scfunc == do_cancel) + if (s && s->scfunc == do_cancel) ok = -1; #ifndef DISABLE_MOUSE else if (kbinput == KEY_MOUSE) { diff --git a/src/proto.h b/src/proto.h index ed574ade..e328f88f 100644 --- a/src/proto.h +++ b/src/proto.h @@ -1,9 +1,9 @@ -/* $Id: proto.h 4569 2013-03-17 22:09:38Z astyanax $ */ +/* $Id: proto.h 4919 2014-05-28 13:24:05Z 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) * @@ -60,13 +60,17 @@ 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; @@ -99,7 +103,9 @@ extern char *alt_speller; extern sc *sclist; extern subnfunc *allfuncs; -#ifdef ENABLE_COLOR +extern subnfunc *exitfunc; +extern subnfunc *uncutfunc; +#ifndef DISABLE_COLOR extern syntaxtype *syntaxes; extern char *syntaxstr; #endif @@ -124,7 +130,11 @@ 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; @@ -133,7 +143,7 @@ extern char *homedir; 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); +void parse_browser_input(int *kbinput, bool *meta_key); void browser_refresh(void); bool browser_select_filename(const char *needle); int filesearch_init(void); @@ -152,6 +162,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 @@ -218,19 +229,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); @@ -255,7 +266,6 @@ void do_cut_text_void(void); #ifndef NANO_TINY void do_copy_text(void); void do_cut_till_end(void); - #endif void do_uncut_text(void); @@ -268,7 +278,7 @@ void open_buffer(const char *filename, bool undoable); void replace_buffer(const char *filename); #endif void display_buffer(void); -#ifdef ENABLE_MULTIBUFFER +#ifndef DISABLE_MULTIBUFFER void switch_to_prevnext_buffer(bool next); void switch_to_prev_buffer_void(void); void switch_to_next_buffer_void(void); @@ -323,7 +333,7 @@ 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) +#if !defined(NANO_TINY) && !defined(DISABLE_NANORC) char *histfilename(void); void load_history(void); bool writehist(FILE *hist, filestruct *histhead); @@ -333,40 +343,26 @@ void load_poshistory(void); void save_poshistory(void); int check_poshistory(const char *file, ssize_t *line, ssize_t *column); #endif +#ifndef DISABLE_COLOR +void set_lint_shortcuts(void); +void set_spell_shortcuts(void); +#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 -#endif - , int metaval, int funcval, int miscval, bool view, void - (*func)(void)); -void shortcut_init(bool unjustify); -void free_shortcutage(shortcut **shortcutage); +void shortcut_init(void); #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); +void parse_help_input(int *kbinput, bool *meta_key); size_t help_line_len(const char *ptr); #endif +void do_help_void(void); /* All functions in move.c. */ void do_first_line(void); @@ -427,7 +423,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); @@ -468,8 +464,6 @@ 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); void do_toggle_void(void); #endif @@ -483,8 +477,7 @@ 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 *meta_key, bool *func_key, bool allow_funcs); #ifndef DISABLE_MOUSE int do_mouse(void); #endif @@ -549,24 +542,24 @@ int do_prompt(bool allow_tabs, void do_prompt_abort(void); int do_yesno_prompt(bool all, const char *msg); -/* All functions in rcfile.c. */ -#ifdef ENABLE_NANORC +/* Most functions in rcfile.c. */ +#ifndef DISABLE_NANORC void rcfile_error(const char *msg, ...); char *parse_next_word(char *ptr); 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_magic_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 ); @@ -590,7 +583,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 @@ -611,10 +604,11 @@ 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 +#ifndef DISABLE_NANORC bool history_has_changed(void); #endif void history_init(void); @@ -686,6 +680,9 @@ 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); +#endif #ifndef NANO_TINY void do_wordlinechar_count(void); #endif @@ -703,7 +700,7 @@ void sunder(char *str); #ifndef HAVE_GETLINE ssize_t ngetline(char **lineptr, size_t *n, FILE *stream); #endif -#if !defined(NANO_TINY) && defined(ENABLE_NANORC) +#if !defined(NANO_TINY) && !defined(DISABLE_NANORC) #ifndef HAVE_GETDELIM ssize_t ngetdelim(char **lineptr, size_t *n, int delim, FILE *stream); #endif @@ -766,8 +763,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 *get_shortcut(int menu, int *kbinput, bool *meta_key); const sc *first_sc_for(int menu, void (*func)(void)); void blank_line(WINDOW *win, int y, int x, int n); void blank_titlebar(void); @@ -803,7 +799,7 @@ 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); +sc *strtosc(char *input); function_type strtokeytype(const char *str); int strtomenu(char *input); void assign_keyinfo(sc *s); @@ -812,29 +808,6 @@ void xoff_complaint(void); int sc_seq_or (void (*func)(void), 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 enable_nodelay(void); void disable_nodelay(void); @@ -843,12 +816,14 @@ void disable_nodelay(void); extern const char *regexp_msg; #endif -#ifdef NANO_EXTRA +#ifndef DISABLE_EXTRA void do_credits(void); #endif -/* May as just throw these here since they are just placeholders */ +/* 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); @@ -864,5 +839,4 @@ void goto_dir_void(void); void no_replace_void(void); void ext_cmd_void(void); - #endif /* !PROTO_H */ diff --git a/src/rcfile.c b/src/rcfile.c index 9bcf7606..d4810df3 100644 --- a/src/rcfile.c +++ b/src/rcfile.c @@ -1,9 +1,9 @@ -/* $Id: rcfile.c 4569 2013-03-17 22:09:38Z astyanax $ */ +/* $Id: rcfile.c 4878 2014-05-13 21:11:59Z 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}, @@ -47,7 +48,7 @@ static const rcoption rcopts[] = { #ifndef DISABLE_MOUSE {"mouse", USE_MOUSE}, #endif -#ifdef ENABLE_MULTIBUFFER +#ifndef DISABLE_MULTIBUFFER {"multibuffer", MULTIBUFFER}, #endif {"morespace", MORE_SPACE}, @@ -99,6 +100,12 @@ static const rcoption rcopts[] = { {"wordbounds", WORD_BOUNDS}, {"softwrap", SOFTWRAP}, #endif +#ifndef DISABLE_COLOR + {"titlecolor", 0}, + {"statuscolor", 0}, + {"keycolor", 0}, + {"functioncolor", 0}, +#endif {NULL, 0} }; @@ -108,14 +115,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 @@ -197,7 +201,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) { @@ -253,7 +257,7 @@ void parse_syntax(char *ptr) { const char *fileregptr = NULL, *nameptr = NULL; syntaxtype *tmpsyntax, *prev_syntax; - exttype *endext = NULL; + regexlisttype *endext = NULL; /* The end of the extensions list for this syntax. */ assert(ptr != NULL); @@ -315,12 +319,12 @@ 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; #ifdef DEBUG fprintf(stderr, "Starting a new syntax type: \"%s\"\n", nameptr); @@ -340,10 +344,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++; @@ -358,7 +361,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)) { @@ -374,77 +377,8 @@ void parse_syntax(char *ptr) } else free(newext); } - -} - - -/* Parse the next syntax string from the line at ptr, and add it to the - * global list of color syntaxes. */ -void parse_magictype(char *ptr) -{ -#ifdef HAVE_LIBMAGIC - const char *fileregptr = NULL; - exttype *endext = 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 extensions into their part of the struct. */ - while (*ptr != '\0') { - exttype *newext; - /* The new extension structure. */ - - while (*ptr != '"' && *ptr != '\0') - ptr++; - - if (*ptr == '\0') - return; - - ptr++; - - fileregptr = ptr; - ptr = parse_next_regex(ptr); - if (ptr == NULL) - break; - - newext = (exttype *)nmalloc(sizeof(exttype)); - - /* Save the regex if it's valid. */ - if (nregcomp(fileregptr, REG_NOSUB)) { - newext->ext_regex = mallocstrcpy(NULL, fileregptr); - newext->ext = NULL; - - if (endext == NULL) - endsyntax->magics = newext; - else - endext->next = newext; - endext = newext; - endext->next = NULL; - } else - free(newext); - } -#endif /* HAVE_LIBMAGIC */ } +#endif /* !DISABLE_COLOR */ int check_bad_binding(sc *s) { @@ -454,20 +388,25 @@ int check_bad_binding(sc *s) 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) +/* 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; @@ -476,206 +415,182 @@ 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); + /* 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; + } + } - if (!strcmp(funcptr, "")) { - rcfile_error( - N_("Must specify function to bind key to")); + /* 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; } + if (dobind) { + funcptr = ptr; + ptr = parse_next_word(ptr); + + if (!strcmp(funcptr, "")) { + rcfile_error(N_("Must specify a function to bind the key to")); + 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\")")); + /* TRANSLATORS: Do not translate the word "all". */ + rcfile_error(N_("Must specify a menu (or \"all\") in which to bind/unbind the key")); 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) { + newsc = strtosc(funcptr); + if (newsc == NULL) { + rcfile_error(N_("Cannot map name \"%s\" to a function"), funcptr); + return; + } } + menu = strtomenu(menuptr); if (menu < 1) { - rcfile_error( - N_("Could not map name \"%s\" to a menu"), menuptr); + rcfile_error(N_("Cannot map name \"%s\" to a menu"), menuptr); return; } - #ifdef DEBUG - fprintf(stderr, "newsc now address %d, menu func assigned = %d, menu = %d\n", - &newsc, newsc->scfunc, menu); + 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 - - newsc->keystr = keycopy; - newsc->menu = menu; - newsc->type = strtokeytype(newsc->keystr); - assign_keyinfo(newsc); + if (dobind) { + 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); + 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); - return; + if (check_bad_binding(newsc)) { + rcfile_error(N_("Sorry, keystroke \"%s\" may not be rebound"), newsc->keystr); + free(newsc); + 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 */ + /* Now find and delete any existing same shortcut in the menu(s). */ for (s = sclist; s != NULL; s = s->next) { - if (((s->menu & newsc->menu)) && s->seq == newsc->seq) { - s->menu &= ~newsc->menu; + if (((s->menu & menu)) && !strcmp(s->keystr, keycopy)) { #ifdef DEBUG - fprintf(stderr, "replaced menu entry %d\n", s->menu); + fprintf(stderr, "deleting entry from menu %x\n", s->menu); #endif + s->menu &= ~menu; } } - 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")); - 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"); -#endif - - if (keycopy[0] != 'M' && keycopy[0] != '^' && keycopy[0] != 'F' && keycopy[0] != 'K') { - rcfile_error( - N_("keybindings must begin with \"^\", \"M\", or \"F\"")); - 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\")")); - return; - } - - menu = strtomenu(menuptr); - if (menu < 1) { - rcfile_error( - N_("Could not map name \"%s\" to a menu"), menuptr); - return; - } - - -#ifdef DEBUG - fprintf(stderr, "unbinding \"%s\" from menu = %d\n", keycopy, menu); -#endif - - /* Now find the apropriate entries in the menu to delete */ - for (s = sclist; s != NULL; s = s->next) { - if (((s->menu & menu)) && !strcmp(s->keystr,keycopy)) { - s->menu &= ~menu; -#ifdef DEBUG - fprintf(stderr, "deleted menu entry %d\n", s->menu); -#endif - } + 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, @@ -723,7 +638,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); @@ -741,36 +656,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")); @@ -781,7 +668,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; @@ -833,6 +720,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; } @@ -862,8 +753,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; @@ -871,17 +762,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 */ + /* 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); @@ -896,11 +825,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( @@ -911,39 +838,126 @@ 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); +} +#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; @@ -957,9 +971,10 @@ static void check_vitals_mapped(void) 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")); + 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; @@ -972,7 +987,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 ) @@ -980,6 +995,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; @@ -1004,9 +1022,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"), @@ -1015,7 +1056,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"), @@ -1024,7 +1065,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( @@ -1038,27 +1079,38 @@ void parse_rcfile(FILE *rcstream endsyntax->desc); parse_syntax(ptr); } - else if (strcasecmp(keyword, "magic") == 0) { - parse_magictype(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); +#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; } @@ -1102,6 +1154,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; @@ -1200,19 +1263,19 @@ 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 undo/redo was enabled, reinitialize the lists. */ if (strcasecmp(rcopts[i].name, "undo") == 0) - shortcut_init(0); + shortcut_init(); 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); @@ -1252,7 +1315,7 @@ void do_rcfile(void) rcstream = fopen(nanorc, "rb"); if (rcstream != NULL) parse_rcfile(rcstream -#ifdef ENABLE_COLOR +#ifndef DISABLE_COLOR , FALSE #endif ); @@ -1294,7 +1357,7 @@ void do_rcfile(void) strerror(errno)); } else parse_rcfile(rcstream -#ifdef ENABLE_COLOR +#ifndef DISABLE_COLOR , FALSE #endif ); @@ -1310,10 +1373,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 74bfb072..c8c97bf9 100644 --- a/src/search.c +++ b/src/search.c @@ -1,9 +1,9 @@ -/* $Id: search.c 4559 2013-01-03 05:00:34Z astyanax $ */ +/* $Id: search.c 4921 2014-05-28 14:34:11Z 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) +#if !defined(NANO_TINY) && !defined(DISABLE_NANORC) static bool history_changed = FALSE; /* Have any of the history lists changed? */ #endif @@ -181,26 +181,23 @@ int search_init(bool replacing, bool use_answer) #ifndef NANO_TINY &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); @@ -219,12 +216,12 @@ int search_init(bool replacing, bool use_answer) statusbar(_("Cancelled")); return -1; } else { - void (*func)(void); + void (*func)(void) = NULL; for (s = sclist; s != NULL; s = s->next) if ((s->menu & currmenu) && i == s->seq) { func = s->scfunc; - break; + break; } if (i == -2 || i == 0 ) { @@ -307,10 +304,10 @@ bool findnextstr( /* Look for needle in the current line we're searching. */ enable_nodelay(); while (TRUE) { - if (time(NULL) - lastkbcheck > 1) { - lastkbcheck = time(NULL); + if (time(NULL) - lastkbcheck > 1) { + lastkbcheck = time(NULL); f = getfuncfromkey(edit); - if (f && f->scfunc == do_cancel) { + if (f && f->scfunc == do_cancel) { statusbar(_("Cancelled")); return FALSE; } @@ -361,7 +358,7 @@ bool findnextstr( /* We've finished processing the file, so get out. */ if (search_last_line) { not_found_msg(needle); - disable_nodelay(); + disable_nodelay(); return FALSE; } @@ -525,7 +522,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 +570,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 +633,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 +716,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; @@ -781,6 +778,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); @@ -866,12 +864,12 @@ ssize_t do_replace_loop( 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 && @@ -954,11 +952,12 @@ void do_replace(void) #ifndef DISABLE_TABCOMP TRUE, #endif - MREPLACE2, last_replace, + MREPLACEWITH, last_replace, &meta_key, &func_key, #ifndef NANO_TINY &replace_history, #endif + /* TRANSLATORS: This is a prompt. */ edit_refresh, _("Replace with")); #ifndef NANO_TINY @@ -1008,6 +1007,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 @@ -1031,6 +1043,7 @@ void do_gotolinecolumn(ssize_t line, ssize_t column, bool use_answer, #ifndef NANO_TINY NULL, #endif + /* TRANSLATORS: This is a prompt. */ edit_refresh, _("Enter line number, column number")); free(ans); @@ -1042,9 +1055,9 @@ void do_gotolinecolumn(ssize_t line, ssize_t column, bool use_answer, return; } + s = get_shortcut(currmenu, &i, &meta_key); - s = get_shortcut(currmenu, &i, &meta_key, &func_key); - if (s && s->scfunc == gototext_void) { + if (s && s->scfunc == gototext_void) { /* Keep answer up on the statusbar. */ search_init(TRUE, TRUE); @@ -1083,10 +1096,11 @@ 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. */ @@ -1291,7 +1305,7 @@ void do_find_bracket(void) free(found_ch); } -#ifdef ENABLE_NANORC +#ifndef DISABLE_NANORC /* Indicate whether any of the history lists have changed. */ bool history_has_changed(void) { @@ -1394,7 +1408,7 @@ void update_history(filestruct **h, const char *s) *hbot = (*hbot)->next; (*hbot)->data = mallocstrcpy(NULL, ""); -#ifdef ENABLE_NANORC +#ifndef DISABLE_NANORC /* Indicate that the history's been changed. */ history_changed = TRUE; #endif @@ -1431,7 +1445,7 @@ char *get_history_newer(filestruct **h) return (*h)->data; } -/* More placeholders */ +/* More placeholders. */ void get_history_newer_void(void) { ; @@ -1,9 +1,9 @@ -/* $Id: text.c 4565 2013-01-20 07:51:34Z astyanax $ */ +/* $Id: text.c 4919 2014-05-28 13:24:05Z 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) * @@ -112,9 +112,8 @@ void do_delete(void) 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) { @@ -141,11 +140,11 @@ void do_delete(void) if (ISSET(SOFTWRAP) && edit_refresh_needed == FALSE) if (strlenpt(openfile->current->data) / COLS != orig_lenpt / COLS) - edit_refresh_needed = TRUE; + edit_refresh_needed = TRUE; set_modified(); - if (edit_refresh_needed == FALSE) + if (edit_refresh_needed == FALSE) update_line(openfile->current, openfile->current_x); } @@ -216,8 +215,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,69 +358,61 @@ 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 */ + /* Compute cutbottom for the uncut using our 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); + copy_from_filestruct(cutbuffer); free_filestruct(cutbuffer); cutbuffer = NULL; + if (u->xflags == UNcut_cutline) + 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); + goto_line_posx(u->lineno, u->begin); + + if (ISSET(NO_NEWLINES) && openfile->current->lineno != u->lineno) { + openfile->current_x = strlen(openfile->current->data); + openfile->placewewant = xplustabs(); + } + openfile->mark_set = u->mark_set; if (cutbuffer) free(cutbuffer); cutbuffer = 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; ) { + openfile->mark_begin = fsfromline(u->mark_begin_lineno); -#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; + if (!ISSET(CUT_TO_END)) openfile->mark_set = TRUE; - } - openfile->mark_begin_x = u->mark_begin_x; + openfile->mark_begin_x = (u->xflags == UNcut_cutline) ? 0 : u->mark_begin_x; do_cut_text(FALSE, u->to_end, TRUE); openfile->mark_set = FALSE; openfile->mark_begin = NULL; @@ -430,12 +420,13 @@ void redo_cut(undo *u) { edit_refresh_needed = TRUE; } -/* Undo the last thing(s) we did */ +/* Undo the last thing(s) we did. */ void do_undo(void) { + bool gotolinecolumn = FALSE; undo *u = openfile->current_undo; - filestruct *f = openfile->current, *t; - int len = 0; + filestruct *t = 0; + size_t len = 0; char *undidmsg, *data; filestruct *oldcutbuffer = cutbuffer, *oldcutbottom = cutbottom; @@ -444,15 +435,9 @@ void do_undo(void) 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,7 +446,7 @@ 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; @@ -470,19 +455,18 @@ void do_undo(void) 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 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 == UNdel_backspace) - openfile->current_x += strlen(u->strdata); + goto_line_posx(u->mark_begin_lineno, u->mark_begin_x); break; #ifndef DISABLE_WRAPPING case SPLIT: @@ -497,48 +481,51 @@ void do_undo(void) delete_node(foo); } renumber(f); + gotolinecolumn = TRUE; break; -#endif /* DISABLE_WRAPPING */ +#endif /* !DISABLE_WRAPPING */ case UNSPLIT: undidmsg = _("line join"); t = make_new_node(f); t->data = mallocstrcpy(NULL, u->strdata); - data = mallocstrncpy(NULL, f->data, u->begin); + data = mallocstrncpy(NULL, f->data, u->begin + 1); data[u->begin] = '\0'; free(f->data); f->data = data; splice_node(f, t, f->next); - renumber(f); + goto_line_posx(u->lineno, u->begin); break; + case CUT_EOF: case CUT: undidmsg = _("text cut"); undo_cut(u); break; - case UNCUT: + case PASTE: undidmsg = _("text uncut"); - redo_cut(u); + undo_paste(u); 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 = (char *) nrealloc(f->data, strlen(f->data) + strlen(&f->next->data[u->mark_begin_x]) + 1); + strcat(f->data, &f->next->data[u->mark_begin_x]); unlink_node(foo); delete_node(foo); } + goto_line_posx(u->lineno, u->begin); break; case INSERT: undidmsg = _("text insert"); 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(); u->cutbuffer = cutbuffer; u->cutbottom = cutbottom; @@ -548,28 +535,31 @@ 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; - } + renumber(f); - do_gotolinecolumn(u->lineno, u->begin, FALSE, FALSE, FALSE, TRUE); + if (gotolinecolumn) + 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; + set_modified(); } +/* Redo the last thing(s) we undid. */ void do_redo(void) { + bool gotolinecolumn = FALSE; undo *u = openfile->undotop; - filestruct *f = openfile->current; - int len = 0; + size_t len = 0; char *undidmsg, *data; for (; u != NULL && u->next != openfile->current_undo; u = u->next) @@ -579,18 +569,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,7 +583,7 @@ 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"); len = strlen(f->data) + strlen(u->strdata) + 1; @@ -608,6 +593,7 @@ void do_redo(void) 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 DEL: undidmsg = _("text delete"); @@ -617,10 +603,13 @@ void do_redo(void) strcpy(&data[u->begin], &f->data[u->begin + strlen(u->strdata)]); free(f->data); f->data = data; + openfile->current_x = u->begin; + openfile->placewewant = xplustabs(); + goto_line_posx(u->lineno, u->begin); break; case ENTER: undidmsg = _("line break"); - do_gotolinecolumn(u->lineno, u->begin+1, FALSE, FALSE, FALSE, FALSE); + goto_line_posx(u->lineno, u->begin); do_enter(TRUE); break; #ifndef DISABLE_WRAPPING @@ -630,54 +619,55 @@ void do_redo(void) prepend_wrap = TRUE; do_wrap(f, TRUE); renumber(f); + gotolinecolumn = TRUE; break; -#endif /* DISABLE_WRAPPING */ +#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; + 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; unlink_node(tmp); delete_node(tmp); } renumber(f); + goto_line_posx(u->lineno, u->begin); break; + case CUT_EOF: case CUT: undidmsg = _("text cut"); redo_cut(u); break; - case UNCUT: + case PASTE: undidmsg = _("text uncut"); - undo_cut(u); + redo_paste(u); break; case REPLACE: undidmsg = _("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(); + goto_line_posx(u->lineno, u->begin); + copy_from_filestruct(u->cutbuffer); break; default: - undidmsg = _("Internal error: unknown type. Please save your work"); + undidmsg = _("Internal error: unknown type. Please save your work."); break; - } - do_gotolinecolumn(u->lineno, u->begin, FALSE, FALSE, FALSE, TRUE); + + if (gotolinecolumn) + do_gotolinecolumn(u->lineno, u->begin, FALSE, FALSE, FALSE, TRUE); statusbar(_("Redid action (%s)"), undidmsg); openfile->current_undo = u; openfile->last_action = OTHER; - + set_modified(); } #endif /* !NANO_TINY */ @@ -693,7 +683,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 @@ -738,11 +727,17 @@ 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) { +void do_enter_void(void) +{ do_enter(FALSE); } @@ -768,13 +763,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"; @@ -840,26 +834,28 @@ 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 */ + /* Last thing we cut to set up the undo for uncut. */ + ssize_t wrap_loc; + /* For calculating split beginning. */ if (!ISSET(UNDOABLE)) return; - /* 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) || + (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; @@ -870,7 +866,7 @@ 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; @@ -881,30 +877,28 @@ void add_undo(undo_type current_action) u->strdata = NULL; u->strdata2 = NULL; u->cutbuffer = NULL; - u->cutbottom = NULL; + u->cutbottom = NULL; u->mark_set = 0; - u->mark_begin_lineno = 0; - u->mark_begin_x = 0; + 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 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); + char_buf[char_buf_len] = '\0'; + u->strdata = char_buf; /* Note: there is likely more memory allocated than necessary. */ + u->mark_begin_x += char_buf_len; break; } - /* Else purposely fall into unsplit code */ + /* Else purposely fall into unsplit code. */ current_action = u->type = UNSPLIT; case UNSPLIT: if (fs->current->next) { @@ -920,33 +914,43 @@ void add_undo(undo_type current_action) #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 */ + /* Don't bother 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; break; -#endif /* DISABLE_WRAPPING */ +#endif /* !DISABLE_WRAPPING */ case INSERT: case REPLACE: data = mallocstrcpy(NULL, fs->current->data); u->strdata = data; break; + case CUT_EOF: + u->to_end = TRUE; case CUT: 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) && !u->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(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: @@ -964,16 +968,13 @@ void add_undo(undo_type current_action) 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)) @@ -989,9 +990,9 @@ void update_undo(undo_type action) #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 && action != SPLIT && openfile->current->lineno != fs->current_undo->lineno)) { add_undo(action); return; @@ -1001,53 +1002,35 @@ 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; + 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); + } + 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 */ - if (!u->xflags) - u->xflags = UNdel_del; - else if (u->xflags != UNdel_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 = UNdel_backspace; - else if (u->xflags != UNdel_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--; + /* 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 */ + /* They deleted something else on the line. */ + free(char_buf); add_undo(DEL); return; } @@ -1055,48 +1038,65 @@ void update_undo(undo_type action) fprintf(stderr, "current undo data now \"%s\"\nu->begin = %d\n", u->strdata, u->begin); #endif break; + } + case CUT_EOF: case CUT: if (!cutbuffer) break; if (u->cutbuffer) free(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 if (!ISSET(CUT_TO_END)) { + /* Compute cutbottom for the uncut using our copy. */ + u->cutbottom = u->cutbuffer; + while (u->cutbottom->next != NULL) + u->cutbottom = u->cutbottom->next; + if (!u->to_end) + u->lineno++; + } 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; + case ENTER: + u->mark_begin_x = fs->current_x; + 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 */ + * and as such we should note that so we can destroy it later. */ u->xflags = UNsplit_madenew; break; -#endif /* DISABLE_WRAPPING */ +#endif /* !DISABLE_WRAPPING */ case UNSPLIT: - /* These cases are handled by the earlier check for a new line and action */ - case ENTER: + /* 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); + fprintf(stderr, "Done in update_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"); -#endif - add_undo(action); + } - fs->last_action = action; -} #endif /* !NANO_TINY */ @@ -1353,7 +1353,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 @@ -1362,17 +1362,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 @@ -1387,8 +1388,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) @@ -1397,34 +1398,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; + /* 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; @@ -1433,8 +1434,8 @@ 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; + char_len = parse_mbchar(line, NULL, NULL); + line += char_len; while (*line != '\0' && (is_blank_mbchar(line) #ifndef DISABLE_HELP @@ -1446,10 +1447,10 @@ ssize_t break_line(const char *line, ssize_t goal break; #endif - line_len = parse_mbchar(line, NULL, NULL); + char_len = parse_mbchar(line, NULL, NULL); - line += line_len; - blank_loc += line_len; + line += char_len; + blank_loc += char_len; } return blank_loc; @@ -1811,7 +1812,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 @@ -1969,7 +1970,7 @@ void do_justify(bool full_justify) bool modified_save = openfile->modified; int kbinput; - bool meta_key, func_key, s_or_t, ran_func, finished; + bool meta_key, func_key; const sc *s; /* Move to the beginning of the current line, so that justifying at @@ -1981,7 +1982,9 @@ 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; @@ -2281,14 +2284,13 @@ void do_justify(bool full_justify) do_cursorpos(TRUE); /* Display the shortcut list with UnJustify. */ - shortcut_init(TRUE); + uncutfunc->desc = unjust_tag; 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(&meta_key, &func_key, FALSE); + s = get_shortcut(MMAIN, &kbinput, &meta_key); if (s && s->scfunc == do_uncut_text) { /* Splice the justify buffer back into the file, but only if we @@ -2351,11 +2353,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. */ @@ -2704,7 +2707,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)) @@ -2955,6 +2958,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); @@ -2978,6 +2985,329 @@ 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; + const sc *s; + 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:%d bytes (%s)\n", 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! %d:%d:%s\n", tmplineno, 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 (1) { + ssize_t tmpcol = 1; + int kbinput; + bool meta_key, func_key; + + 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, &meta_key, &func_key); + s = get_shortcut(currmenu, &kbinput, &meta_key); + tmplint = curlint; + + if (!s) + continue; + else if (s->scfunc == do_cancel) + break; + else if (s->scfunc == do_help_void) { + tmplint = NULL; + do_help_void(); + } else if (s->scfunc == do_page_down) { + if (curlint->next != NULL) + curlint = curlint->next; + else { + statusbar(_("At last message")); + continue; + } + } else if (s->scfunc == do_page_up) { + if (curlint->prev != NULL) + curlint = curlint->prev; + else { + statusbar(_("At first message")); + continue; + } + } + } + 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(); +} +#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. */ @@ -3083,4 +3413,3 @@ void do_verbatim_input(void) free(output); } - diff --git a/src/utils.c b/src/utils.c index 675a70a4..e311db84 100644 --- a/src/utils.c +++ b/src/utils.c @@ -1,9 +1,9 @@ -/* $Id: utils.c 4563 2013-01-13 08:37:54Z astyanax $ */ +/* $Id: utils.c 4893 2014-05-15 20:00:46Z 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) * @@ -187,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(). */ @@ -247,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 @@ -259,8 +259,8 @@ 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. */ +/* 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; @@ -476,7 +476,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, @@ -546,7 +549,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; @@ -598,7 +601,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. */ @@ -630,7 +633,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 d3cf4e46..eb0cedc1 100644 --- a/src/winio.c +++ b/src/winio.c @@ -1,9 +1,9 @@ -/* $Id: winio.c 4569 2013-03-17 22:09:38Z astyanax $ */ +/* $Id: winio.c 4918 2014-05-28 01:35:51Z astyanax $ */ /************************************************************************** * 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,9 +120,10 @@ 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) + if ((input = wgetch(win)) == ERR) return; } else while ((input = wgetch(win)) == ERR) { @@ -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 @@ -304,14 +304,15 @@ int *get_input(WINDOW *win, size_t input_len) * [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. */ + * off. */ int get_kbinput(WINDOW *win, bool *meta_key, bool *func_key) { 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, meta_key, func_key)) == ERR) + ; /* If we read from the edit window, blank the statusbar if we need * to. */ @@ -324,7 +325,7 @@ 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. */ + * a function key. */ int parse_kbinput(WINDOW *win, bool *meta_key, bool *func_key) { static int escapes = 0, byte_digits = 0; @@ -339,7 +340,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: @@ -610,7 +612,7 @@ int parse_kbinput(WINDOW *win, bool *meta_key, bool *func_key) #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 @@ -761,12 +763,12 @@ int get_escape_seq_kbinput(const int *seq, size_t seq_len) 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. */ @@ -831,7 +833,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 +843,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/ @@ -980,7 +982,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,28 +1033,28 @@ 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);; + retval = sc_seq_or(do_page_down, 0); break; case '7': /* Esc [ 7 ~ == Home on rxvt. */ retval = sc_seq_or(do_home, 0); @@ -1061,10 +1063,10 @@ int get_escape_seq_kbinput(const int *seq, size_t seq_len) 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/ @@ -1220,13 +1222,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 +1303,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 +1531,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 +1558,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 +1639,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 +1659,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,43 +1679,44 @@ 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); + unget_kbinput(s->seq, s->type == META, FALSE); } } else /* Handle releases/clicks of the first mouse button that @@ -1746,8 +1743,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(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,21 +1760,16 @@ 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 menu, int *kbinput, bool *meta_key) { 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. */ @@ -1786,44 +1778,37 @@ const sc *get_shortcut(int menu, int *kbinput, bool && ((s->type == META && *meta_key == TRUE && *kbinput == s->seq) || (s->type != META && *kbinput == s->seq))) { #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, menu, 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 */ +/* Try to get a function back from a window. Just a wrapper. */ 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); + s = get_shortcut(currmenu, &kbinput, &meta_key); if (!s) return NULL; - f = sctofunc((sc *) s); - return f; - + return sctofunc((sc *) s); } - - /* 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 +1984,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 +2000,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 +2019,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 +2098,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 +2231,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(); @@ -2260,8 +2248,10 @@ void set_modified(void) titlebar(NULL); #ifndef NANO_TINY if (ISSET(LOCKING)) { - if (openfile->lock_filename == NULL) { - /* Translators: Try to keep this at most 80 characters. */ + if (!strcmp(openfile->filename, "")) + 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, @@ -2279,8 +2269,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 @@ -2296,7 +2286,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 @@ -2304,21 +2294,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); @@ -2385,7 +2377,7 @@ void bottombars(int menu) 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) { @@ -2418,9 +2410,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; @@ -2429,7 +2424,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); } } @@ -2477,7 +2477,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. */ @@ -2492,23 +2492,29 @@ 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); + /* 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. */ +#ifndef USE_SLANG + wredrawln(edit, line, 1); +#endif -#ifdef ENABLE_COLOR +#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 */ + /* 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; + 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 */ + fileptr->multidata[i] = -1; /* Assume this applies until we know otherwise. */ } for (; tmpcolor != NULL; tmpcolor = tmpcolor->next) { int x_start; @@ -2597,16 +2603,16 @@ void edit_draw(filestruct *fileptr, const char *converted, int if (md == -1) fileptr->multidata[tmpcolor->id] = CNONE; /* until we find out otherwise */ 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, @@ -2756,12 +2762,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. */ @@ -2826,10 +2832,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 */ @@ -2838,13 +2844,12 @@ 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. */ @@ -2900,10 +2905,10 @@ int update_line(filestruct *fileptr, size_t index) #ifdef DEBUG 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) @@ -2912,7 +2917,7 @@ int update_line(filestruct *fileptr, size_t index) /* Paint the line. */ edit_draw(fileptr, converted, line, index); - free(converted); + free(converted); extralinesused++; } } @@ -2946,8 +2951,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; @@ -2960,7 +2964,7 @@ void compute_maxrows(void) maxrows = 0; for (n = 0; n < editwinrows && foo; n++) { - maxrows ++; + maxrows++; n += strlenpt(foo->data) / COLS; foo = foo->next; } @@ -2969,7 +2973,7 @@ void compute_maxrows(void) maxrows += editwinrows - n; #ifdef DEBUG - fprintf(stderr, "compute_maxrows(): maxrows = %ld\n", maxrows); + fprintf(stderr, "compute_maxrows(): maxrows = %i\n", maxrows); #endif } @@ -2981,8 +2985,8 @@ void compute_maxrows(void) * 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. */ @@ -2992,36 +2996,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. */ @@ -3038,10 +3012,10 @@ 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)) { + /* Don't over-scroll on long lines. */ + if (ISSET(SOFTWRAP) && (direction == UP_DIR)) { ssize_t len = strlenpt(openfile->edittop->data) / COLS; - i -= len; + i -= len; if (len > 0) do_redraw = TRUE; } @@ -3113,6 +3087,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 @@ -3130,10 +3105,9 @@ 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 %d was offscreen, oldcurrent = %d edittop = %d", + openfile->current->lineno, old_current->lineno, openfile->edittop->lineno); #endif #ifndef NANO_TINY @@ -3221,7 +3195,7 @@ 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 || @@ -3323,6 +3297,13 @@ void total_refresh(void) * portion of the window. */ void display_main_list(void) { +#ifndef DISABLE_COLOR + if (openfile->syntax && openfile->syntax->linter) + set_lint_shortcuts(); + else + set_spell_shortcuts(); +#endif + bottombars(MMAIN); } @@ -3394,7 +3375,6 @@ void disable_nodelay(void) 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) @@ -3414,7 +3394,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) @@ -3426,11 +3406,11 @@ 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 +#ifndef DISABLE_EXTRA +#define CREDIT_LEN 57 #define XLCREDIT_LEN 8 /* Easter egg: Display credits. Assume nodelay(edit) and scrollok(edit) @@ -3454,9 +3434,10 @@ void do_credits(void) "David Lawrence Ramsey", "David Benbennick", "Mike Frysinger", + "Benno Schulenberg", "Ken Tyler", "Sven Guckes", - NULL, /* credits[15], handled below. */ + NULL, /* credits[16], handled below. */ "Pauli Virtanen", "Daniele Medri", "Clement Laforet", @@ -3470,6 +3451,7 @@ void do_credits(void) "Albert Chin", "", NULL, /* "Special thanks to:" */ + "Monique, Brielle & Joseph", "Plattsburgh State University", "Benet Laboratories", "Amy Allegretta", @@ -3489,7 +3471,7 @@ void do_credits(void) "", "", "", - "(C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007", + "(C) 1999 - 2014", "Free Software Foundation, Inc.", "", "", @@ -3509,10 +3491,10 @@ void do_credits(void) N_("Thank you for using nano!") }; - /* credits[15]: Make sure this name is displayed properly, since we + /* credits[16]: 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] = + credits[16] = #ifdef ENABLE_UTF8 using_utf8() ? "Florian K\xC3\xB6nig" : #endif @@ -3594,4 +3576,4 @@ void do_credits(void) total_refresh(); } -#endif /* NANO_EXTRA */ +#endif /* !DISABLE_EXTRA */ |