From 87206c0607b4c8d5bdfc21e41397ecbeca5f3152 Mon Sep 17 00:00:00 2001 From: Benno Schulenberg Date: Fri, 29 Dec 2017 19:27:33 +0100 Subject: [PATCH] tweaks: convert the indentation to use only tabs Each leading tab is converted to two tabs, and any leading four spaces is converted to one tab. The intended tab size (for keeping most lines within 80 columns) is now four. --- configure.ac | 742 +++---- src/browser.c | 1136 +++++----- src/chars.c | 762 +++---- src/color.c | 576 ++--- src/cut.c | 290 +-- src/files.c | 3764 ++++++++++++++++----------------- src/global.c | 2340 ++++++++++----------- src/help.c | 946 ++++----- src/history.c | 798 +++---- src/move.c | 664 +++--- src/nano.c | 3260 ++++++++++++++--------------- src/nano.h | 570 ++--- src/prompt.c | 986 ++++----- src/proto.h | 32 +- src/rcfile.c | 1744 ++++++++-------- src/search.c | 1542 +++++++------- src/text.c | 5576 ++++++++++++++++++++++++------------------------- src/utils.c | 624 +++--- src/winio.c | 5158 ++++++++++++++++++++++----------------------- 19 files changed, 15755 insertions(+), 15755 deletions(-) diff --git a/configure.ac b/configure.ac index 03079964..ba8a99e2 100644 --- a/configure.ac +++ b/configure.ac @@ -65,105 +65,105 @@ dnl Checks for options. AC_ARG_ENABLE(browser, AS_HELP_STRING([--disable-browser], [Disable the built-in file browser])) if test "x$enable_tiny" = xyes; then - if test "x$enable_browser" != xyes; then - enable_browser=no - fi + if test "x$enable_browser" != xyes; then + enable_browser=no + fi fi if test "x$enable_browser" != xno; then - AC_DEFINE(ENABLE_BROWSER, 1, [Define this to enable the built-in file browser.]) + AC_DEFINE(ENABLE_BROWSER, 1, [Define this to enable the built-in file browser.]) fi AC_ARG_ENABLE(color, AS_HELP_STRING([--disable-color], [Disable color and syntax highlighting])) if test "x$enable_tiny" = xyes; then - if test "x$enable_color" = xyes; then - if test "x$enable_nanorc" != xyes; then - AC_MSG_ERROR([--enable-color needs --enable-nanorc to work]) + if test "x$enable_color" = xyes; then + if test "x$enable_nanorc" != xyes; then + AC_MSG_ERROR([--enable-color needs --enable-nanorc to work]) + fi + else + enable_color=no fi - else - enable_color=no - fi fi if test "x$enable_nanorc" = xno; then - if test "x$enable_color" = xyes; then - AC_MSG_ERROR([--enable-color cannot work with --disable-nanorc]) - else - # Disabling nanorc silently disables color support. - enable_color=no - fi + if test "x$enable_color" = xyes; then + AC_MSG_ERROR([--enable-color cannot work with --disable-nanorc]) + else + # Disabling nanorc silently disables color support. + enable_color=no + fi fi if test "x$enable_color" != xno; then - AC_DEFINE(ENABLE_COLOR, 1, [Define this to have syntax highlighting.]) - color_support=yes + AC_DEFINE(ENABLE_COLOR, 1, [Define this to have syntax highlighting.]) + color_support=yes fi AC_ARG_ENABLE(comment, AS_HELP_STRING([--disable-comment], [Disable the comment/uncomment function])) if test "x$enable_tiny" = xyes; then - if test "x$enable_comment" = xyes; then - AC_MSG_ERROR([--enable-comment cannot work with --enable-tiny]) - else - enable_comment=no - fi + if test "x$enable_comment" = xyes; then + AC_MSG_ERROR([--enable-comment cannot work with --enable-tiny]) + else + enable_comment=no + fi fi if test "x$enable_comment" != xno; then - AC_DEFINE(ENABLE_COMMENT, 1, [Define this to enable the comment/uncomment function.]) + AC_DEFINE(ENABLE_COMMENT, 1, [Define this to enable the comment/uncomment function.]) fi AC_ARG_ENABLE(extra, AS_HELP_STRING([--disable-extra], [Disable the Easter egg])) if test "x$enable_tiny" = xyes; then - if test "x$enable_extra" != xyes; then - enable_extra=no - fi + if test "x$enable_extra" != xyes; then + enable_extra=no + fi fi if test "x$enable_extra" != xno; then - AC_DEFINE(ENABLE_EXTRA, 1, [Define this to have an Easter egg.]) + AC_DEFINE(ENABLE_EXTRA, 1, [Define this to have an Easter egg.]) fi AC_ARG_ENABLE(help, AS_HELP_STRING([--disable-help], [Disable the built-in help texts])) if test "x$enable_tiny" = xyes; then - if test "x$enable_help" = xyes; then - if test "x$enable_multibuffer" != xyes; then - AC_MSG_ERROR([--enable-help needs --enable-multibuffer to work]) + if test "x$enable_help" = xyes; then + if test "x$enable_multibuffer" != xyes; then + AC_MSG_ERROR([--enable-help needs --enable-multibuffer to work]) + fi + else + enable_help=no fi - else - enable_help=no - fi fi if test "x$enable_multibuffer" = xno; then - if test "x$enable_help" = xyes; then - AC_MSG_ERROR([--enable-help cannot work with --disable-multibuffer]) - else - # Disabling multibuffer silently disables the help texts. - enable_help=no - fi + if test "x$enable_help" = xyes; then + AC_MSG_ERROR([--enable-help cannot work with --disable-multibuffer]) + else + # Disabling multibuffer silently disables the help texts. + enable_help=no + fi fi if test "x$enable_help" != xno; then - AC_DEFINE(ENABLE_HELP, 1, [Define this to enable the Ctrl+G help texts.]) + AC_DEFINE(ENABLE_HELP, 1, [Define this to enable the Ctrl+G help texts.]) fi AC_ARG_ENABLE(histories, AS_HELP_STRING([--disable-histories], [Disable search and position histories])) if test "x$enable_tiny" = xyes; then - if test "x$enable_histories" != xyes; then - enable_histories=no - fi + if test "x$enable_histories" != xyes; then + enable_histories=no + fi fi if test "x$enable_histories" != xno; then - AC_DEFINE(ENABLE_HISTORIES, 1, [Define this to have search and position histories.]) + AC_DEFINE(ENABLE_HISTORIES, 1, [Define this to have search and position histories.]) fi AC_ARG_ENABLE(justify, AS_HELP_STRING([--disable-justify], [Disable the justify/unjustify functions])) if test "x$enable_tiny" = xyes; then - if test "x$enable_justify" != xyes; then - enable_justify=no - fi + if test "x$enable_justify" != xyes; then + enable_justify=no + fi fi if test "x$enable_justify" != xno; then - AC_DEFINE(ENABLE_JUSTIFY, 1, [Define this to have the routines for justifying.]) + AC_DEFINE(ENABLE_JUSTIFY, 1, [Define this to have the routines for justifying.]) fi AC_ARG_ENABLE(libmagic, @@ -172,126 +172,126 @@ AS_HELP_STRING([--disable-libmagic], [Disable detection of file types via libmag AC_ARG_ENABLE(linenumbers, AS_HELP_STRING([--disable-linenumbers], [Disable line numbering])) if test "x$enable_tiny" = xyes; then - if test "x$enable_linenumbers" != xyes; then - enable_linenumbers=no - fi + if test "x$enable_linenumbers" != xyes; then + enable_linenumbers=no + fi fi if test "x$enable_linenumbers" != xno; then - AC_DEFINE(ENABLE_LINENUMBERS, 1, [Define this to enable line numbering.]) + AC_DEFINE(ENABLE_LINENUMBERS, 1, [Define this to enable line numbering.]) fi AC_ARG_ENABLE(mouse, AS_HELP_STRING([--disable-mouse], [Disable mouse support])) if test "x$enable_tiny" = xyes; then - if test "x$enable_mouse" != xyes; then - enable_mouse=no - fi + if test "x$enable_mouse" != xyes; then + enable_mouse=no + fi fi if test "x$enable_mouse" != xno; then - AC_DEFINE(ENABLE_MOUSE, 1, [Define this to enable mouse support.]) + AC_DEFINE(ENABLE_MOUSE, 1, [Define this to enable mouse support.]) fi AC_ARG_ENABLE(multibuffer, AS_HELP_STRING([--disable-multibuffer], [Disable multiple file buffers])) if test "x$enable_tiny" = xyes; then - if test "x$enable_multibuffer" != xyes; then - enable_multibuffer=no - fi + if test "x$enable_multibuffer" != xyes; then + enable_multibuffer=no + fi fi if test "x$enable_multibuffer" != xno; then - AC_DEFINE(ENABLE_MULTIBUFFER, 1, [Define this to enable multiple file buffers.]) + AC_DEFINE(ENABLE_MULTIBUFFER, 1, [Define this to enable multiple file buffers.]) fi AC_ARG_ENABLE(nanorc, AS_HELP_STRING([--disable-nanorc], [Disable the use of .nanorc files])) if test "x$enable_tiny" = xyes; then - if test "x$enable_nanorc" != xyes; then - enable_nanorc=no - fi + if test "x$enable_nanorc" != xyes; then + enable_nanorc=no + fi fi if test "x$enable_nanorc" != xno; then - AC_DEFINE(ENABLE_NANORC, 1, [Define this to enable the use of .nanorc files.]) - nanorc_support=yes + AC_DEFINE(ENABLE_NANORC, 1, [Define this to enable the use of .nanorc files.]) + nanorc_support=yes fi AC_ARG_ENABLE(operatingdir, AS_HELP_STRING([--disable-operatingdir], [Disable the setting of an operating directory])) if test "x$enable_tiny" = xyes; then - if test "x$enable_operatingdir" != xyes; then - enable_operatingdir=no - fi + if test "x$enable_operatingdir" != xyes; then + enable_operatingdir=no + fi fi if test "x$enable_operatingdir" != xno; then - AC_DEFINE(ENABLE_OPERATINGDIR, 1, [Define this to allow setting an operating directory (a chroot of sorts).]) + AC_DEFINE(ENABLE_OPERATINGDIR, 1, [Define this to allow setting an operating directory (a chroot of sorts).]) fi AC_ARG_ENABLE(speller, AS_HELP_STRING([--disable-speller], [Disable the spell-checker functions])) if test "x$enable_tiny" = xyes; then - if test "x$enable_speller" != xyes; then - enable_speller=no - fi + if test "x$enable_speller" != xyes; then + enable_speller=no + fi fi if test "x$enable_speller" != xno; then - AC_DEFINE(ENABLE_SPELLER, 1, [Define this to have the spell-checker functions.]) + AC_DEFINE(ENABLE_SPELLER, 1, [Define this to have the spell-checker functions.]) fi AC_ARG_ENABLE(tabcomp, AS_HELP_STRING([--disable-tabcomp], [Disable the tab-completion functions])) if test "x$enable_tiny" = xyes; then - if test "x$enable_tabcomp" != xyes; then - enable_tabcomp=no - fi + if test "x$enable_tabcomp" != xyes; then + enable_tabcomp=no + fi fi if test "x$enable_tabcomp" != xno; then - AC_DEFINE(ENABLE_TABCOMP, 1, [Define this to have tab completion for filenames and search strings.]) + AC_DEFINE(ENABLE_TABCOMP, 1, [Define this to have tab completion for filenames and search strings.]) fi AC_ARG_ENABLE(wordcomp, AS_HELP_STRING([--disable-wordcomp], [Disable the word-completion function])) if test "x$enable_tiny" = xyes; then - if test "x$enable_wordcomp" = xyes; then - AC_MSG_ERROR([--enable-wordcomp cannot work with --enable-tiny]) - else - enable_wordcomp=no - fi + if test "x$enable_wordcomp" = xyes; then + AC_MSG_ERROR([--enable-wordcomp cannot work with --enable-tiny]) + else + enable_wordcomp=no + fi fi if test "x$enable_wordcomp" != xno; then - AC_DEFINE(ENABLE_WORDCOMPLETION, 1, [Define this to enable the word-completion function.]) + AC_DEFINE(ENABLE_WORDCOMPLETION, 1, [Define this to enable the word-completion function.]) fi AC_ARG_ENABLE(wrapping, AS_HELP_STRING([--disable-wrapping], [Disable all hard-wrapping of text])) if test "x$enable_tiny" = xyes; then - if test "x$enable_wrapping" != xyes; then - enable_wrapping=no - fi + if test "x$enable_wrapping" != xyes; then + enable_wrapping=no + fi fi if test "x$enable_wrapping" != xno; then - AC_DEFINE(ENABLE_WRAPPING, 1, [Define this to have hard text wrapping.]) + AC_DEFINE(ENABLE_WRAPPING, 1, [Define this to have hard text wrapping.]) fi AC_ARG_ENABLE(wrapping-as-root, AS_HELP_STRING([--disable-wrapping-as-root], [Disable wrapping of text as root by default])) if test "x$enable_wrapping_as_root" = xno; then - AC_DEFINE(DISABLE_ROOTWRAPPING, 1, [Define this to disable text wrapping as root by default.]) + AC_DEFINE(DISABLE_ROOTWRAPPING, 1, [Define this to disable text wrapping as root by default.]) fi AC_ARG_ENABLE(debug, AS_HELP_STRING([--enable-debug], [Enable debugging (disabled by default)])) if test "x$enable_debug" = xyes; then - AC_DEFINE(DEBUG, 1, [Define this to enable debug messages and abortion on failing asserts.]) + AC_DEFINE(DEBUG, 1, [Define this to enable debug messages and abortion on failing asserts.]) else - AC_DEFINE(NDEBUG, 1, [Shut up assert warnings :-)]) + AC_DEFINE(NDEBUG, 1, [Shut up assert warnings :-)]) fi AC_ARG_ENABLE(tiny, AS_HELP_STRING([--enable-tiny], [Disable features for the sake of size])) if test "x$enable_tiny" = xyes; then - AC_DEFINE(NANO_TINY, 1, [Define this to make the nano executable as small as possible.]) - if test "x$enable_libmagic" != xyes; then - enable_libmagic=no - fi + AC_DEFINE(NANO_TINY, 1, [Define this to make the nano executable as small as possible.]) + if test "x$enable_libmagic" != xyes; then + enable_libmagic=no + fi fi AM_CONDITIONAL(USE_COLOR, test x$color_support = xyes) @@ -304,7 +304,7 @@ AC_MSG_RESULT(${enable_utf8:-auto}) AC_ARG_ENABLE(altrcname, AS_HELP_STRING([--enable-altrcname], [Specify an alternate rcfile name (default: .nanorc)]), [if test x$enableval != no; then - AC_DEFINE_UNQUOTED(RCFILE_NAME, "$enableval", [Specify an alternate rcfile name (default: .nanorc).]) rcfilename=$enableval + AC_DEFINE_UNQUOTED(RCFILE_NAME, "$enableval", [Specify an alternate rcfile name (default: .nanorc).]) rcfilename=$enableval fi]) @@ -313,193 +313,193 @@ CURSES_LIB_NAME="" AC_ARG_WITH(slang, AS_HELP_STRING([--with-slang[=DIR]], [Use the slang library instead of curses]), [ case "$with_slang" in - no) - AC_MSG_RESULT(no) - ;; - *) - AC_MSG_RESULT(yes) + no) + AC_MSG_RESULT(no) + ;; + *) + AC_MSG_RESULT(yes) - if test x$with_slang != xyes; then - # Add additional search path. - LDFLAGS="-L$with_slang/lib $LDFLAGS" - CPPFLAGS="-I$with_slang/include $CPPFLAGS" - fi + if test x$with_slang != xyes; then + # Add additional search path. + LDFLAGS="-L$with_slang/lib $LDFLAGS" + CPPFLAGS="-I$with_slang/include $CPPFLAGS" + fi - if test "x$enable_utf8" != xno; then - AC_CHECK_HEADER(slcurses.h, - AC_MSG_CHECKING([for SLutf8_enable in -lslang]) - _libs=$LIBS - LIBS="$LIBS -lslang" - AC_TRY_RUN([ + if test "x$enable_utf8" != xno; then + AC_CHECK_HEADER(slcurses.h, + AC_MSG_CHECKING([for SLutf8_enable in -lslang]) + _libs=$LIBS + LIBS="$LIBS -lslang" + AC_TRY_RUN([ #include int main(void) { - SLutf8_enable(1); - return 0; + SLutf8_enable(1); + return 0; }], - [AC_MSG_RESULT(yes) - AC_DEFINE(USE_SLANG, 1, [Define this to use the slang wrappers for curses instead of native curses.]) - CURSES_LIB_WIDE=yes - if test x$with_slang != xyes; then - CURSES_LIB="-L${with_slang}/lib -lslang" - else - CURSES_LIB="-lslang" - fi - CURSES_LIB_NAME=slang], - [AC_MSG_RESULT(no) + [AC_MSG_RESULT(yes) + AC_DEFINE(USE_SLANG, 1, [Define this to use the slang wrappers for curses instead of native curses.]) + CURSES_LIB_WIDE=yes + if test x$with_slang != xyes; then + CURSES_LIB="-L${with_slang}/lib -lslang" + else + CURSES_LIB="-lslang" + fi + CURSES_LIB_NAME=slang], + [AC_MSG_RESULT(no) - # We might need the term library. - for termlib in ncurses curses termcap terminfo termlib; do - AC_CHECK_LIB([${termlib}], tputs, [tcap="-l$termlib"]) - test -n "$tcap" && break - done + # We might need the term library. + for termlib in ncurses curses termcap terminfo termlib; do + AC_CHECK_LIB([${termlib}], tputs, [tcap="-l$termlib"]) + test -n "$tcap" && break + done - AC_MSG_CHECKING([for SLutf8_enable in -lslang $tcap]) - LIBS="$LIBS $tcap" - AC_TRY_RUN([ + AC_MSG_CHECKING([for SLutf8_enable in -lslang $tcap]) + LIBS="$LIBS $tcap" + AC_TRY_RUN([ #include int main(void) { - SLutf8_enable(1); - return 0; + SLutf8_enable(1); + return 0; }], - [AC_MSG_RESULT(yes) - AC_DEFINE(USE_SLANG, 1, [Define this to use the slang wrappers for curses instead of native curses.]) - CURSES_LIB_WIDE=yes - if test x$with_slang != xyes; then - CURSES_LIB="-L${with_slang}/lib -lslang $tcap" - else - CURSES_LIB="-lslang $tcap" - fi - CURSES_LIB_NAME=slang], - [AC_MSG_RESULT(no) + [AC_MSG_RESULT(yes) + AC_DEFINE(USE_SLANG, 1, [Define this to use the slang wrappers for curses instead of native curses.]) + CURSES_LIB_WIDE=yes + if test x$with_slang != xyes; then + CURSES_LIB="-L${with_slang}/lib -lslang $tcap" + else + CURSES_LIB="-lslang $tcap" + fi + CURSES_LIB_NAME=slang], + [AC_MSG_RESULT(no) - # We might need the math library. - AC_MSG_CHECKING([for SLutf8_enable in -lslang $tcap -lm]) - LIBS="$LIBS -lm" - AC_TRY_RUN([ + # We might need the math library. + AC_MSG_CHECKING([for SLutf8_enable in -lslang $tcap -lm]) + LIBS="$LIBS -lm" + AC_TRY_RUN([ #include int main(void) { - SLutf8_enable(1); - return 0; + SLutf8_enable(1); + return 0; }], - [AC_MSG_RESULT(yes) - AC_DEFINE(USE_SLANG, 1, [Define this to use the slang wrappers for curses instead of native curses.]) - CURSES_LIB_WIDE=yes - if test x$with_slang != xyes; then - CURSES_LIB="-L${with_slang}/lib -lslang $tcap -lm" - else - CURSES_LIB="-lslang $tcap -lm" - fi - CURSES_LIB_NAME=slang], - [AC_MSG_RESULT(no)], - AC_MSG_WARN([*** Can not use slang when cross-compiling]))], - AC_MSG_WARN([*** Can not use slang when cross-compiling]))], - AC_MSG_WARN([*** Can not use slang when cross-compiling])), - AC_MSG_ERROR([ + [AC_MSG_RESULT(yes) + AC_DEFINE(USE_SLANG, 1, [Define this to use the slang wrappers for curses instead of native curses.]) + CURSES_LIB_WIDE=yes + if test x$with_slang != xyes; then + CURSES_LIB="-L${with_slang}/lib -lslang $tcap -lm" + else + CURSES_LIB="-lslang $tcap -lm" + fi + CURSES_LIB_NAME=slang], + [AC_MSG_RESULT(no)], + AC_MSG_WARN([*** Can not use slang when cross-compiling]))], + AC_MSG_WARN([*** Can not use slang when cross-compiling]))], + AC_MSG_WARN([*** Can not use slang when cross-compiling])), + AC_MSG_ERROR([ *** The header file slcurses.h was not found. If you wish to use *** slang support this header file is required. Please either *** install a version of slang that includes the slcurses.h file or *** do not call the configure script with --with-slang.])) - fi + fi - if eval "test x$CURSES_LIB_NAME = x"; then - # Reset libs if the above slang tests failed. - if test "x$enable_utf8" != xno; then - LIBS=$_libs - fi - - AC_CHECK_HEADER(slcurses.h, - AC_MSG_CHECKING([for SLtt_initialize in -lslang]) - _libs=$LIBS - LIBS="$LIBS -lslang" - AC_TRY_RUN([ -#include -int main(void) -{ - SLtt_initialize(NULL); - return 0; -}], - [AC_MSG_RESULT(yes) - AC_DEFINE(USE_SLANG, 1, [Define this to use the slang wrappers for curses instead of native curses.]) - if test x$with_slang != xyes; then - CURSES_LIB="-L${with_slang}/lib -lslang" - else - CURSES_LIB="-lslang" - fi - CURSES_LIB_NAME=slang], - [AC_MSG_RESULT(no) - - # We might need the term library. - for termlib in ncurses curses termcap terminfo termlib; do - AC_CHECK_LIB([${termlib}], tputs, [tcap="-l$termlib"]) - test -n "$tcap" && break - done - - AC_MSG_CHECKING([for SLtt_initialize in -lslang $tcap]) - LIBS="$LIBS $tcap" - AC_TRY_RUN([ -#include -int main(void) -{ - SLtt_initialize(NULL); - return 0; -}], - [AC_MSG_RESULT(yes) - AC_DEFINE(USE_SLANG, 1, [Define this to use the slang wrappers for curses instead of native curses.]) - if test x$with_slang != xyes; then - CURSES_LIB="-L${with_slang}/lib -lslang $tcap" - else - CURSES_LIB="-lslang $tcap" + if eval "test x$CURSES_LIB_NAME = x"; then + # Reset libs if the above slang tests failed. + if test "x$enable_utf8" != xno; then + LIBS=$_libs fi - CURSES_LIB_NAME=slang], - [AC_MSG_RESULT(no) - # We might need the math library. - AC_MSG_CHECKING([for SLtt_initialize in -lslang $tcap -lm]) - LIBS="$LIBS -lm" - AC_TRY_RUN([ + AC_CHECK_HEADER(slcurses.h, + AC_MSG_CHECKING([for SLtt_initialize in -lslang]) + _libs=$LIBS + LIBS="$LIBS -lslang" + AC_TRY_RUN([ #include int main(void) { - SLtt_initialize(NULL); - return 0; + SLtt_initialize(NULL); + return 0; }], - [AC_MSG_RESULT(yes) - AC_DEFINE(USE_SLANG, 1, [Define this to use the slang wrappers for curses instead of native curses.]) - if test x$with_slang != xyes; then - CURSES_LIB="-L${with_slang}/lib -lslang $tcap -lm" - else - CURSES_LIB="-lslang $tcap -lm" - fi - CURSES_LIB_NAME=slang], - [AC_MSG_RESULT(no)], - AC_MSG_WARN([*** Can not use slang when cross-compiling]))], - AC_MSG_WARN([*** Can not use slang when cross-compiling]))], - AC_MSG_WARN([*** Can not use slang when cross-compiling])), - AC_MSG_ERROR([ + [AC_MSG_RESULT(yes) + AC_DEFINE(USE_SLANG, 1, [Define this to use the slang wrappers for curses instead of native curses.]) + if test x$with_slang != xyes; then + CURSES_LIB="-L${with_slang}/lib -lslang" + else + CURSES_LIB="-lslang" + fi + CURSES_LIB_NAME=slang], + [AC_MSG_RESULT(no) + + # We might need the term library. + for termlib in ncurses curses termcap terminfo termlib; do + AC_CHECK_LIB([${termlib}], tputs, [tcap="-l$termlib"]) + test -n "$tcap" && break + done + + AC_MSG_CHECKING([for SLtt_initialize in -lslang $tcap]) + LIBS="$LIBS $tcap" + AC_TRY_RUN([ +#include +int main(void) +{ + SLtt_initialize(NULL); + return 0; +}], + [AC_MSG_RESULT(yes) + AC_DEFINE(USE_SLANG, 1, [Define this to use the slang wrappers for curses instead of native curses.]) + if test x$with_slang != xyes; then + CURSES_LIB="-L${with_slang}/lib -lslang $tcap" + else + CURSES_LIB="-lslang $tcap" + fi + CURSES_LIB_NAME=slang], + [AC_MSG_RESULT(no) + + # We might need the math library. + AC_MSG_CHECKING([for SLtt_initialize in -lslang $tcap -lm]) + LIBS="$LIBS -lm" + AC_TRY_RUN([ +#include +int main(void) +{ + SLtt_initialize(NULL); + return 0; +}], + [AC_MSG_RESULT(yes) + AC_DEFINE(USE_SLANG, 1, [Define this to use the slang wrappers for curses instead of native curses.]) + if test x$with_slang != xyes; then + CURSES_LIB="-L${with_slang}/lib -lslang $tcap -lm" + else + CURSES_LIB="-lslang $tcap -lm" + fi + CURSES_LIB_NAME=slang], + [AC_MSG_RESULT(no)], + AC_MSG_WARN([*** Can not use slang when cross-compiling]))], + AC_MSG_WARN([*** Can not use slang when cross-compiling]))], + AC_MSG_WARN([*** Can not use slang when cross-compiling])), + AC_MSG_ERROR([ *** The header file slcurses.h was not found. If you wish to use *** slang support this header file is required. Please either *** install a version of slang that includes the slcurses.h file or *** do not call the configure script with --with-slang.])) - fi + fi - if test "${_libs+set}" = "set"; then - LIBS=$_libs - fi + if test "${_libs+set}" = "set"; then + LIBS=$_libs + fi - if test x$with_slang != xyes; then - LDFLAGS=${_ldflags} - fi - ;; - esac], [AC_MSG_RESULT(no)]) + if test x$with_slang != xyes; then + LDFLAGS=${_ldflags} + fi + ;; + esac], [AC_MSG_RESULT(no)]) dnl Checks for functions. if test "x$enable_utf8" != xno; then - AC_CHECK_FUNCS(iswalnum iswpunct mblen mbstowcs mbtowc wctomb) + AC_CHECK_FUNCS(iswalnum iswpunct mblen mbstowcs mbtowc wctomb) fi dnl Checks for typedefs, structures, and compiler characteristics. @@ -514,74 +514,74 @@ AC_TYPE_SIGNAL dnl Checks for libraries. if eval "test x$CURSES_LIB_NAME = x"; then - if test "x$enable_utf8" != xno; then - PKG_CHECK_MODULES([NCURSESW], [ncursesw], [ - CURSES_LIB=$NCURSESW_LIBS - CPPFLAGS="$NCURSESW_CFLAGS $CPPFLAGS" - CURSES_LIB_NAME=ncursesw - CURSES_LIB_WIDE=yes - ], [:]) - else - PKG_CHECK_MODULES([NCURSES], [ncurses], [ - CURSES_LIB=$NCURSES_LIBS - CPPFLAGS="$NCURSES_CFLAGS $CPPFLAGS" - CURSES_LIB_NAME=ncurses - ], [:]) - fi -fi - -if eval "test x$CURSES_LIB_NAME = x"; then - AC_CHECK_HEADERS(ncurses.h) - - if test "x$enable_utf8" != xno; then - OLDLIBS="$LIBS" - AC_CHECK_TOOL(NCURSESW_CONFIG, ncursesw5-config, no) - if test "x$NCURSESW_CONFIG" != xno; then - CURSES_LIB=`$NCURSESW_CONFIG --libs` - LIBS="$CURSES_LIB $LIBS" - CPPFLAGS="`$NCURSESW_CONFIG --cflags` $CPPFLAGS" - AC_CHECK_LIB(ncursesw, get_wch, [CURSES_LIB_NAME=ncursesw CURSES_LIB_WIDE=yes]) + if test "x$enable_utf8" != xno; then + PKG_CHECK_MODULES([NCURSESW], [ncursesw], [ + CURSES_LIB=$NCURSESW_LIBS + CPPFLAGS="$NCURSESW_CFLAGS $CPPFLAGS" + CURSES_LIB_NAME=ncursesw + CURSES_LIB_WIDE=yes + ], [:]) else - AC_CHECK_LIB(ncursesw, get_wch, [CURSES_LIB="-lncursesw" CURSES_LIB_NAME=ncursesw CURSES_LIB_WIDE=yes]) + PKG_CHECK_MODULES([NCURSES], [ncurses], [ + CURSES_LIB=$NCURSES_LIBS + CPPFLAGS="$NCURSES_CFLAGS $CPPFLAGS" + CURSES_LIB_NAME=ncurses + ], [:]) fi - LIBS="$OLDLIBS" - fi - - if eval "test x$CURSES_LIB_NAME = x"; then - AC_CHECK_LIB(ncurses, initscr, [CURSES_LIB="-lncurses" CURSES_LIB_NAME=ncurses]) - fi fi if eval "test x$CURSES_LIB_NAME = x"; then - AC_CHECK_HEADERS(curses.h) + AC_CHECK_HEADERS(ncurses.h) - if test "x$enable_utf8" != xno; then - AC_CHECK_LIB(curses, get_wch, [CURSES_LIB="-lcurses" CURSES_LIB_NAME=curses CURSES_LIB_WIDE=yes]) - fi + if test "x$enable_utf8" != xno; then + OLDLIBS="$LIBS" + AC_CHECK_TOOL(NCURSESW_CONFIG, ncursesw5-config, no) + if test "x$NCURSESW_CONFIG" != xno; then + CURSES_LIB=`$NCURSESW_CONFIG --libs` + LIBS="$CURSES_LIB $LIBS" + CPPFLAGS="`$NCURSESW_CONFIG --cflags` $CPPFLAGS" + AC_CHECK_LIB(ncursesw, get_wch, [CURSES_LIB_NAME=ncursesw CURSES_LIB_WIDE=yes]) + else + AC_CHECK_LIB(ncursesw, get_wch, [CURSES_LIB="-lncursesw" CURSES_LIB_NAME=ncursesw CURSES_LIB_WIDE=yes]) + fi + LIBS="$OLDLIBS" + fi - if eval "test x$CURSES_LIB_NAME = x"; then - AC_CHECK_LIB(curses, initscr, [CURSES_LIB="-lcurses" CURSES_LIB_NAME=curses]) - fi + if eval "test x$CURSES_LIB_NAME = x"; then + AC_CHECK_LIB(ncurses, initscr, [CURSES_LIB="-lncurses" CURSES_LIB_NAME=ncurses]) + fi fi if eval "test x$CURSES_LIB_NAME = x"; then - AC_MSG_WARN([ + AC_CHECK_HEADERS(curses.h) + + if test "x$enable_utf8" != xno; then + AC_CHECK_LIB(curses, get_wch, [CURSES_LIB="-lcurses" CURSES_LIB_NAME=curses CURSES_LIB_WIDE=yes]) + fi + + if eval "test x$CURSES_LIB_NAME = x"; then + AC_CHECK_LIB(curses, initscr, [CURSES_LIB="-lcurses" CURSES_LIB_NAME=curses]) + fi +fi + +if eval "test x$CURSES_LIB_NAME = x"; then + AC_MSG_WARN([ *** No curses lib available. Consider getting the official ncurses *** distribution from ftp://ftp.gnu.org/pub/gnu/ncurses if you get *** errors compiling nano.]) else - AC_MSG_RESULT([Using $CURSES_LIB_NAME as the curses library]) + AC_MSG_RESULT([Using $CURSES_LIB_NAME as the curses library]) fi AC_CHECK_LIB([$CURSES_LIB_NAME], [use_default_colors], - [AC_DEFINE(HAVE_USE_DEFAULT_COLORS, 1, [Define this if your curses library has the use_default_colors() function.])], - [], [$CURSES_LIB]) + [AC_DEFINE(HAVE_USE_DEFAULT_COLORS, 1, [Define this if your curses library has the use_default_colors() function.])], + [], [$CURSES_LIB]) AC_CHECK_LIB([$CURSES_LIB_NAME], [set_escdelay], - [AC_DEFINE(HAVE_SET_ESCDELAY, 1, [Define this if your curses library has the set_escdelay() function.])], - [], [$CURSES_LIB]) + [AC_DEFINE(HAVE_SET_ESCDELAY, 1, [Define this if your curses library has the set_escdelay() function.])], + [], [$CURSES_LIB]) AC_CHECK_LIB([$CURSES_LIB_NAME], [key_defined], - [AC_DEFINE(HAVE_KEY_DEFINED, 1, [Define this if your curses library has the key_defined() function.])], - [], [$CURSES_LIB]) + [AC_DEFINE(HAVE_KEY_DEFINED, 1, [Define this if your curses library has the key_defined() function.])], + [], [$CURSES_LIB]) dnl Parse any configure options. @@ -590,129 +590,129 @@ LIBS="$LIBS $CURSES_LIB" AC_SUBST(CURSES_LIB) if test "x$enable_utf8" != xno && \ - test x$CURSES_LIB_WIDE = xyes && \ - test x$ac_cv_func_iswalnum = xyes && \ - test x$ac_cv_func_iswpunct = xyes && \ - test x$ac_cv_func_mblen = xyes && \ - test x$ac_cv_func_mbstowcs = xyes && \ - test x$ac_cv_func_mbtowc = xyes && \ - test x$ac_cv_func_wctomb = xyes; then - AC_DEFINE(ENABLE_UTF8, 1, [Define this if your system has sufficient UTF-8 support.]) + test x$CURSES_LIB_WIDE = xyes && \ + test x$ac_cv_func_iswalnum = xyes && \ + test x$ac_cv_func_iswpunct = xyes && \ + test x$ac_cv_func_mblen = xyes && \ + test x$ac_cv_func_mbstowcs = xyes && \ + test x$ac_cv_func_mbtowc = xyes && \ + test x$ac_cv_func_wctomb = xyes; then + AC_DEFINE(ENABLE_UTF8, 1, [Define this if your system has sufficient UTF-8 support.]) else - if test "x$enable_utf8" = xyes; then - AC_MSG_ERROR([ + if test "x$enable_utf8" = xyes; then + AC_MSG_ERROR([ *** UTF-8 support was requested, but insufficient UTF-8 support was *** detected in your curses and/or C libraries. Please verify that your *** slang was built with UTF-8 support or your curses was built with *** wide character support, and that your C library was built with wide *** character support.]) - elif test "x$enable_utf8" != xno; then - AC_MSG_WARN([ + elif test "x$enable_utf8" != xno; then + AC_MSG_WARN([ *** Insufficient UTF-8 support was detected in your curses and/or C *** libraries. If you want UTF-8 support, please verify that your slang *** was built with UTF-8 support or your curses was built with wide *** character support, and that your C library was built with wide *** character support.]) - fi + fi fi AC_CACHE_CHECK([for enhanced regular expression flag], nano_cv_flag_reg_enhanced, - [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], - [[ - #ifndef REG_ENHANCED - error: No REG_ENHANCED support! - #endif - ]])], - [nano_cv_flag_reg_enhanced=yes], - [nano_cv_flag_reg_enhanced=no])]) + [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], + [[ + #ifndef REG_ENHANCED + error: No REG_ENHANCED support! + #endif + ]])], + [nano_cv_flag_reg_enhanced=yes], + [nano_cv_flag_reg_enhanced=no])]) dnl The bundled gnulib regex module doesn't support REG_ENHANCED. if test "$ac_use_included_regex" = "yes"; then - nano_cv_flag_reg_enhanced="no" + nano_cv_flag_reg_enhanced="no" fi if test "$nano_cv_flag_reg_enhanced" = "yes"; then - nano_reg_extended="REG_EXTENDED | REG_ENHANCED" + nano_reg_extended="REG_EXTENDED | REG_ENHANCED" else - nano_reg_extended="REG_EXTENDED" + nano_reg_extended="REG_EXTENDED" fi AC_DEFINE_UNQUOTED(NANO_REG_EXTENDED, $nano_reg_extended, - [Flag(s) to use to get the full range of extended regular expressions]) + [Flag(s) to use to get the full range of extended regular expressions]) # Check for word-boundary support (/< and />). AC_MSG_CHECKING([for GNU-style word boundary regex support]) AC_ARG_WITH(wordbounds, AS_HELP_STRING([--with-wordbounds], [Use GNU-style word boundary delimiters]), - [with_wordbounds=$withval], [with_wordbounds=auto]) + [with_wordbounds=$withval], [with_wordbounds=auto]) if test "$with_wordbounds" != "no"; then - dnl If we're using the bundled gnulib regex module, we know it's supported. - if test "$ac_use_included_regex" = "yes"; then - with_wordbounds="yes" - fi + dnl If we're using the bundled gnulib regex module, we know it's supported. + if test "$ac_use_included_regex" = "yes"; then + with_wordbounds="yes" + fi - dnl We explicitly don't check if the user forced the option, because - dnl this is needed for cross compilers and we can't test the target. - if test "$with_wordbounds" != "yes"; then - AC_TRY_RUN([ + dnl We explicitly don't check if the user forced the option, because + dnl this is needed for cross compilers and we can't test the target. + if test "$with_wordbounds" != "yes"; then + AC_TRY_RUN([ #ifdef HAVE_SYS_TYPES_H #include #endif #include int main(void) { - regex_t r; - size_t nmatch; - regmatch_t pmatch; + regex_t r; + size_t nmatch; + regmatch_t pmatch; - if (regcomp(&r, "\\\\>", $nano_reg_extended|REG_NOSUB)) - return 1; - if (regexec(&r, "word boundary", nmatch, &pmatch, 0)) - return 1; - return 0; + if (regcomp(&r, "\\\\>", $nano_reg_extended|REG_NOSUB)) + return 1; + if (regexec(&r, "word boundary", nmatch, &pmatch, 0)) + return 1; + return 0; }], - with_wordbounds="yes", - with_wordbounds="no", - with_wordbounds="cross") - fi + with_wordbounds="yes", + with_wordbounds="no", + with_wordbounds="cross") + fi fi case $with_wordbounds in yes) - AC_MSG_RESULT(yes) - AC_DEFINE(GNU_WORDBOUNDS, 1, [Define this if the system supports GNU-style word boundaries in regexes.]) - ;; + AC_MSG_RESULT(yes) + AC_DEFINE(GNU_WORDBOUNDS, 1, [Define this if the system supports GNU-style word boundaries in regexes.]) + ;; no) - AC_MSG_RESULT(no) - ;; + AC_MSG_RESULT(no) + ;; cross) - AC_MSG_WARN([*** Can't check for GNU-style word boundary support when cross-compiling]) - ;; + AC_MSG_WARN([*** Can't check for GNU-style word boundary support when cross-compiling]) + ;; esac if test x$color_support = xyes; then # if test x$CURSES_LIB_NAME = xcurses; then - AC_MSG_CHECKING([whether _XOPEN_SOURCE_EXTENDED is needed]) - AC_TRY_RUN([ + AC_MSG_CHECKING([whether _XOPEN_SOURCE_EXTENDED is needed]) + AC_TRY_RUN([ #include int main(void) { - int testcolor = COLOR_WHITE; - return 0; + int testcolor = COLOR_WHITE; + return 0; }], AC_MSG_RESULT(no), - AC_TRY_RUN([ + AC_TRY_RUN([ #ifndef _XOPEN_SOURCE_EXTENDED #define _XOPEN_SOURCE_EXTENDED 1 #endif #include int main(void) { - int testcolor = COLOR_WHITE; - return 0; + int testcolor = COLOR_WHITE; + return 0; }], - AC_DEFINE(NEED_XOPEN_SOURCE_EXTENDED, 1, [Define this if you need the _XOPEN_SOURCE_EXTENDED macro for color support.]) - AC_MSG_RESULT(yes), - AC_MSG_RESULT(not sure) - AC_MSG_WARN([*** Couldn't successfully compile basic color test with or without _XOPEN_SOURCE_EXTENDED]) - AC_MSG_WARN([*** This build may not compile. Consider configuring with --disable-color or installing ncurses])), - AC_MSG_WARN([*** Can't check need for _XOPEN_SOURCE_EXTENDED when cross-compiling])) + AC_DEFINE(NEED_XOPEN_SOURCE_EXTENDED, 1, [Define this if you need the _XOPEN_SOURCE_EXTENDED macro for color support.]) + AC_MSG_RESULT(yes), + AC_MSG_RESULT(not sure) + AC_MSG_WARN([*** Couldn't successfully compile basic color test with or without _XOPEN_SOURCE_EXTENDED]) + AC_MSG_WARN([*** This build may not compile. Consider configuring with --disable-color or installing ncurses])), + AC_MSG_WARN([*** Can't check need for _XOPEN_SOURCE_EXTENDED when cross-compiling])) # fi fi @@ -721,9 +721,9 @@ AC_TRY_RUN([ #include int main(void) { - LINES = 80; - COLS = 25; - return 0; + LINES = 80; + COLS = 25; + return 0; }], AC_DEFINE(REDEFINING_MACROS_OK, 1, [Define this if you know your curses library allows LINES and COLS to be redefined to deal with a resizing bug.]) AC_MSG_RESULT(yes), @@ -741,24 +741,24 @@ AS_IF([test "x$enable_libmagic" != "xno"], [ AC_MSG_CHECKING([for HTML support in groff]) groff -t -mandoc -Thtml /dev/null if test $? -ne 0 ; then - AC_MSG_RESULT([no]) - AC_MSG_WARN([*** Will not generate HTML version of man pages *** + AC_MSG_RESULT([no]) + AC_MSG_WARN([*** Will not generate HTML version of man pages *** *** Consider installing a newer version of groff with HTML support ***]) - groff_html_support=no + groff_html_support=no else - AC_MSG_RESULT([yes]) - groff_html_support=yes + AC_MSG_RESULT([yes]) + groff_html_support=yes fi AM_CONDITIONAL(GROFF_HTML, test x$groff_html_support = xyes) # Check whether this is a git repository. AC_MSG_CHECKING([whether building from git]) if test -d .git ; then - AC_MSG_RESULT([yes]) - from_git=yes + AC_MSG_RESULT([yes]) + from_git=yes else - AC_MSG_RESULT([no]) - from_git=no + AC_MSG_RESULT([no]) + from_git=no fi AM_CONDITIONAL(BUILDING_FROM_GIT, test x$from_git = xyes) diff --git a/src/browser.c b/src/browser.c index a6e09590..ab6bec29 100644 --- a/src/browser.c +++ b/src/browser.c @@ -29,311 +29,311 @@ #ifdef ENABLE_BROWSER static char **filelist = NULL; - /* The list of files to display in the file browser. */ + /* The list of files to display in the file browser. */ static size_t filelist_len = 0; - /* The number of files in the list. */ + /* The number of files in the list. */ static int width = 0; - /* The number of files that we can display per screen row. */ + /* The number of files that we can display per screen row. */ static int longest = 0; - /* The number of columns in the longest filename in the list. */ + /* The number of columns in the longest filename in the list. */ static size_t selected = 0; - /* The currently selected filename in the list; zero-based. */ + /* The currently selected filename in the list; zero-based. */ /* Our main file browser function. path is the tilde-expanded path we * start browsing from. */ char *do_browser(char *path) { - char *retval = NULL; - int kbinput; - char *present_name = NULL; - /* The name of the currently selected file, or of the directory we - * were in before backing up to "..". */ - size_t old_selected; - /* The number of the selected file before the current selected file. */ - functionptrtype func; - /* The function of the key the user typed in. */ - DIR *dir; - /* The directory whose contents we are showing. */ + char *retval = NULL; + int kbinput; + char *present_name = NULL; + /* The name of the currently selected file, or of the directory we + * were in before backing up to "..". */ + size_t old_selected; + /* The number of the selected file before the current selected file. */ + functionptrtype func; + /* The function of the key the user typed in. */ + DIR *dir; + /* The directory whose contents we are showing. */ read_directory_contents: - /* We come here when we refresh or select a new directory. */ + /* We come here when we refresh or select a new directory. */ - path = free_and_assign(path, get_full_path(path)); + path = free_and_assign(path, get_full_path(path)); - if (path != NULL) - dir = opendir(path); + if (path != NULL) + dir = opendir(path); - if (path == NULL || dir == NULL) { - statusline(ALERT, _("Cannot open directory: %s"), strerror(errno)); - /* If we don't have a file list yet, there is nothing to show. */ - if (filelist == NULL) { - napms(1200); - lastmessage = HUSH; - free(path); - free(present_name); - return NULL; + if (path == NULL || dir == NULL) { + statusline(ALERT, _("Cannot open directory: %s"), strerror(errno)); + /* If we don't have a file list yet, there is nothing to show. */ + if (filelist == NULL) { + napms(1200); + lastmessage = HUSH; + free(path); + free(present_name); + return NULL; + } + path = mallocstrcpy(path, present_path); + present_name = mallocstrcpy(present_name, filelist[selected]); } - path = mallocstrcpy(path, present_path); - present_name = mallocstrcpy(present_name, filelist[selected]); - } - assert(path != NULL && path[strlen(path) - 1] == '/'); + assert(path != NULL && path[strlen(path) - 1] == '/'); - if (dir != NULL) { - /* Get the file list, and set longest and width in the process. */ - read_the_list(path, dir); - closedir(dir); - dir = NULL; - } + if (dir != NULL) { + /* Get the file list, and set longest and width in the process. */ + read_the_list(path, dir); + closedir(dir); + dir = NULL; + } - /* If given, reselect the present_name and then discard it. */ - if (present_name != NULL) { - browser_select_dirname(present_name); + /* If given, reselect the present_name and then discard it. */ + if (present_name != NULL) { + browser_select_dirname(present_name); - free(present_name); - present_name = NULL; - /* Otherwise, select the first file or directory in the list. */ - } else - selected = 0; + free(present_name); + present_name = NULL; + /* Otherwise, select the first file or directory in the list. */ + } else + selected = 0; - old_selected = (size_t)-1; + old_selected = (size_t)-1; - present_path = mallocstrcpy(present_path, path); + present_path = mallocstrcpy(present_path, path); - titlebar(path); + titlebar(path); - while (TRUE) { - lastmessage = HUSH; + while (TRUE) { + lastmessage = HUSH; - bottombars(MBROWSER); + bottombars(MBROWSER); - /* Display (or redisplay) the file list if the list itself or - * the selected file has changed. */ - if (old_selected != selected || ISSET(SHOW_CURSOR)) - browser_refresh(); + /* Display (or redisplay) the file list if the list itself or + * the selected file has changed. */ + if (old_selected != selected || ISSET(SHOW_CURSOR)) + browser_refresh(); - old_selected = selected; + old_selected = selected; - kbinput = get_kbinput(edit, ISSET(SHOW_CURSOR)); + kbinput = get_kbinput(edit, ISSET(SHOW_CURSOR)); #ifdef ENABLE_MOUSE - if (kbinput == KEY_MOUSE) { - int mouse_x, mouse_y; + if (kbinput == KEY_MOUSE) { + int mouse_x, mouse_y; - /* We can click on the edit window to select a filename. */ - if (get_mouseinput(&mouse_x, &mouse_y, TRUE) == 0 && - wmouse_trafo(edit, &mouse_y, &mouse_x, FALSE)) { - /* longest is the width of each column. There - * are two spaces between each column. */ - selected = selected - selected % (editwinrows * width) + - (mouse_y * width) + (mouse_x / (longest + 2)); + /* We can click on the edit window to select a filename. */ + if (get_mouseinput(&mouse_x, &mouse_y, TRUE) == 0 && + wmouse_trafo(edit, &mouse_y, &mouse_x, FALSE)) { + /* longest is the width of each column. There + * are two spaces between each column. */ + selected = selected - selected % (editwinrows * width) + + (mouse_y * width) + (mouse_x / (longest + 2)); - /* If they clicked beyond the end of a row, - * select the last filename in that row. */ - if (mouse_x > width * (longest + 2)) - selected--; + /* If they clicked beyond the end of a row, + * select the last filename in that row. */ + if (mouse_x > width * (longest + 2)) + selected--; - /* If we're beyond the list, select the last filename. */ - if (selected > filelist_len - 1) - selected = filelist_len - 1; + /* If we're beyond the list, select the last filename. */ + if (selected > filelist_len - 1) + selected = filelist_len - 1; - /* If we selected the same filename as last time, fake a - * press of the Enter key so that the file is read in. */ - if (old_selected == selected) - unget_kbinput(KEY_ENTER, FALSE); - } + /* If we selected the same filename as last time, fake a + * press of the Enter key so that the file is read in. */ + if (old_selected == selected) + unget_kbinput(KEY_ENTER, FALSE); + } - continue; - } + continue; + } #endif /* ENABLE_MOUSE */ - func = parse_browser_input(&kbinput); + func = parse_browser_input(&kbinput); - if (func == total_refresh) { - total_redraw(); + if (func == total_refresh) { + total_redraw(); #ifndef NANO_TINY - /* Simulate a window resize to force a directory reread. */ - kbinput = KEY_WINCH; + /* Simulate a window resize to force a directory reread. */ + kbinput = KEY_WINCH; #endif - } else if (func == do_help_void) { + } else if (func == do_help_void) { #ifdef ENABLE_HELP - do_help_void(); + do_help_void(); #ifndef NANO_TINY - /* The window dimensions might have changed, so act as if. */ - kbinput = KEY_WINCH; + /* The window dimensions might have changed, so act as if. */ + kbinput = KEY_WINCH; #endif #else - say_there_is_no_help(); + say_there_is_no_help(); #endif - } else if (func == do_search_forward) { - do_filesearch(); - } else if (func == do_research) { - do_fileresearch(TRUE); + } else if (func == do_search_forward) { + do_filesearch(); + } else if (func == do_research) { + do_fileresearch(TRUE); #ifndef NANO_TINY - } else if (func == do_findprevious) { - do_fileresearch(FALSE); - } else if (func == do_findnext) { - do_fileresearch(TRUE); + } else if (func == do_findprevious) { + do_fileresearch(FALSE); + } else if (func == do_findnext) { + do_fileresearch(TRUE); #endif - } else if (func == do_left) { - if (selected > 0) - selected--; - } else if (func == do_right) { - if (selected < filelist_len - 1) - selected++; - } else if (func == do_prev_word_void) { - selected -= (selected % width); - } else if (func == do_next_word_void) { - selected += width - 1 - (selected % width); - if (selected >= filelist_len) - selected = filelist_len - 1; - } else if (func == do_up_void) { - if (selected >= width) - selected -= width; - } else if (func == do_down_void) { - if (selected + width <= filelist_len - 1) - selected += width; - } else if (func == do_prev_block) { - selected = ((selected / (editwinrows * width)) * - editwinrows * width) + selected % width; - } else if (func == do_next_block) { - selected = ((selected / (editwinrows * width)) * - editwinrows * width) + selected % width + - editwinrows * width - width; - if (selected >= filelist_len) - selected = (filelist_len / width) * width + selected % width; - if (selected >= filelist_len) - selected -= width; - } else if (func == do_page_up) { - if (selected < width) - selected = 0; - else if (selected < editwinrows * width) - selected = selected % width; - else - selected -= editwinrows * width; - } else if (func == do_page_down) { - if (selected + width >= filelist_len - 1) - selected = filelist_len - 1; - else if (selected + editwinrows * width >= filelist_len) - selected = (selected + editwinrows * width - filelist_len) % - width + filelist_len - width; - else - selected += editwinrows * width; - } else if (func == to_first_file) { - selected = 0; - } else if (func == to_last_file) { - selected = filelist_len - 1; - } else if (func == goto_dir_void) { - /* Ask for the directory to go to. */ - int i = do_prompt(TRUE, FALSE, MGOTODIR, NULL, NULL, - /* TRANSLATORS: This is a prompt. */ - browser_refresh, _("Go To Directory")); + } else if (func == do_left) { + if (selected > 0) + selected--; + } else if (func == do_right) { + if (selected < filelist_len - 1) + selected++; + } else if (func == do_prev_word_void) { + selected -= (selected % width); + } else if (func == do_next_word_void) { + selected += width - 1 - (selected % width); + if (selected >= filelist_len) + selected = filelist_len - 1; + } else if (func == do_up_void) { + if (selected >= width) + selected -= width; + } else if (func == do_down_void) { + if (selected + width <= filelist_len - 1) + selected += width; + } else if (func == do_prev_block) { + selected = ((selected / (editwinrows * width)) * + editwinrows * width) + selected % width; + } else if (func == do_next_block) { + selected = ((selected / (editwinrows * width)) * + editwinrows * width) + selected % width + + editwinrows * width - width; + if (selected >= filelist_len) + selected = (filelist_len / width) * width + selected % width; + if (selected >= filelist_len) + selected -= width; + } else if (func == do_page_up) { + if (selected < width) + selected = 0; + else if (selected < editwinrows * width) + selected = selected % width; + else + selected -= editwinrows * width; + } else if (func == do_page_down) { + if (selected + width >= filelist_len - 1) + selected = filelist_len - 1; + else if (selected + editwinrows * width >= filelist_len) + selected = (selected + editwinrows * width - filelist_len) % + width + filelist_len - width; + else + selected += editwinrows * width; + } else if (func == to_first_file) { + selected = 0; + } else if (func == to_last_file) { + selected = filelist_len - 1; + } else if (func == goto_dir_void) { + /* Ask for the directory to go to. */ + int i = do_prompt(TRUE, FALSE, MGOTODIR, NULL, NULL, + /* TRANSLATORS: This is a prompt. */ + browser_refresh, _("Go To Directory")); - if (i < 0) { - statusbar(_("Cancelled")); - continue; - } + if (i < 0) { + statusbar(_("Cancelled")); + continue; + } - path = free_and_assign(path, real_dir_from_tilde(answer)); + path = free_and_assign(path, real_dir_from_tilde(answer)); - /* If the given path is relative, join it with the current path. */ - if (*path != '/') { - path = charealloc(path, strlen(present_path) + - strlen(answer) + 1); - sprintf(path, "%s%s", present_path, answer); - } + /* If the given path is relative, join it with the current path. */ + if (*path != '/') { + path = charealloc(path, strlen(present_path) + + strlen(answer) + 1); + sprintf(path, "%s%s", present_path, answer); + } #ifdef ENABLE_OPERATINGDIR - if (outside_of_confinement(path, FALSE)) { - /* TRANSLATORS: This refers to the confining effect of the - * option --operatingdir, not of --restricted. */ - statusline(ALERT, _("Can't go outside of %s"), operating_dir); - path = mallocstrcpy(path, present_path); - continue; - } + if (outside_of_confinement(path, FALSE)) { + /* TRANSLATORS: This refers to the confining effect of the + * option --operatingdir, not of --restricted. */ + statusline(ALERT, _("Can't go outside of %s"), operating_dir); + path = mallocstrcpy(path, present_path); + continue; + } #endif - /* Snip any trailing slashes, so the name can be compared. */ - while (strlen(path) > 1 && path[strlen(path) - 1] == '/') - path[strlen(path) - 1] = '\0'; + /* Snip any trailing slashes, so the name can be compared. */ + while (strlen(path) > 1 && path[strlen(path) - 1] == '/') + path[strlen(path) - 1] = '\0'; - /* In case the specified directory cannot be entered, select it - * (if it is in the current list) so it will be highlighted. */ - for (i = 0; i < filelist_len; i++) - if (strcmp(filelist[i], path) == 0) - selected = i; + /* In case the specified directory cannot be entered, select it + * (if it is in the current list) so it will be highlighted. */ + for (i = 0; i < filelist_len; i++) + if (strcmp(filelist[i], path) == 0) + selected = i; - /* Try opening and reading the specified directory. */ - goto read_directory_contents; - } else if (func == do_enter) { - struct stat st; + /* Try opening and reading the specified directory. */ + goto read_directory_contents; + } else if (func == do_enter) { + struct stat st; - /* It isn't possible to move up from the root directory. */ - if (strcmp(filelist[selected], "/..") == 0) { - statusline(ALERT, _("Can't move up a directory")); - continue; - } + /* It isn't possible to move up from the root directory. */ + if (strcmp(filelist[selected], "/..") == 0) { + statusline(ALERT, _("Can't move up a directory")); + continue; + } #ifdef ENABLE_OPERATINGDIR - /* Note: The selected file can be outside the operating - * directory if it's ".." or if it's a symlink to a - * directory outside the operating directory. */ - if (outside_of_confinement(filelist[selected], FALSE)) { - statusline(ALERT, _("Can't go outside of %s"), operating_dir); - continue; - } + /* Note: The selected file can be outside the operating + * directory if it's ".." or if it's a symlink to a + * directory outside the operating directory. */ + if (outside_of_confinement(filelist[selected], FALSE)) { + statusline(ALERT, _("Can't go outside of %s"), operating_dir); + continue; + } #endif - /* If for some reason the file is inaccessible, complain. */ - if (stat(filelist[selected], &st) == -1) { - statusline(ALERT, _("Error reading %s: %s"), - filelist[selected], strerror(errno)); - continue; - } + /* If for some reason the file is inaccessible, complain. */ + if (stat(filelist[selected], &st) == -1) { + statusline(ALERT, _("Error reading %s: %s"), + filelist[selected], strerror(errno)); + continue; + } - /* If it isn't a directory, a file was selected -- we're done. */ - if (!S_ISDIR(st.st_mode)) { - retval = mallocstrcpy(NULL, filelist[selected]); - break; - } + /* If it isn't a directory, a file was selected -- we're done. */ + if (!S_ISDIR(st.st_mode)) { + retval = mallocstrcpy(NULL, filelist[selected]); + break; + } - /* If we are moving up one level, remember where we came from, so - * this directory can be highlighted and easily reentered. */ - if (strcmp(tail(filelist[selected]), "..") == 0) - present_name = strip_last_component(filelist[selected]); + /* If we are moving up one level, remember where we came from, so + * this directory can be highlighted and easily reentered. */ + if (strcmp(tail(filelist[selected]), "..") == 0) + present_name = strip_last_component(filelist[selected]); - /* Try opening and reading the selected directory. */ - path = mallocstrcpy(path, filelist[selected]); - goto read_directory_contents; - } else if (func == do_exit) { - /* Exit from the file browser. */ - break; + /* Try opening and reading the selected directory. */ + path = mallocstrcpy(path, filelist[selected]); + goto read_directory_contents; + } else if (func == do_exit) { + /* Exit from the file browser. */ + break; #ifndef NANO_TINY - } else if (kbinput == KEY_WINCH) { - ; + } else if (kbinput == KEY_WINCH) { + ; #endif - } else - unbound_key(kbinput); + } else + unbound_key(kbinput); #ifndef NANO_TINY - /* If the window resized, refresh the file list. */ - if (kbinput == KEY_WINCH) { - /* Remember the selected file, to be able to reselect it. */ - present_name = mallocstrcpy(NULL, filelist[selected]); - /* Reread the contents of the current directory. */ - goto read_directory_contents; + /* If the window resized, refresh the file list. */ + if (kbinput == KEY_WINCH) { + /* Remember the selected file, to be able to reselect it. */ + present_name = mallocstrcpy(NULL, filelist[selected]); + /* Reread the contents of the current directory. */ + goto read_directory_contents; + } +#endif } -#endif - } - titlebar(NULL); - edit_refresh(); + titlebar(NULL); + edit_refresh(); - free(path); + free(path); - free_chararray(filelist, filelist_len); - filelist = NULL; - filelist_len = 0; + free_chararray(filelist, filelist_len); + filelist = NULL; + filelist_len = 0; - return retval; + return retval; } /* The file browser front end. We check to see if inpath has a @@ -341,45 +341,45 @@ char *do_browser(char *path) * Otherwise, we start do_browser() from the current directory. */ char *do_browse_from(const char *inpath) { - struct stat st; - char *path; - /* This holds the tilde-expanded version of inpath. */ + struct stat st; + char *path; + /* This holds the tilde-expanded version of inpath. */ - path = real_dir_from_tilde(inpath); - - /* Perhaps path is a directory. If so, we'll pass it to - * do_browser(). Or perhaps path is a directory / a file. If so, - * we'll try stripping off the last path element and passing it to - * do_browser(). Or perhaps path doesn't have a directory portion - * at all. If so, we'll just pass the current directory to - * do_browser(). */ - if (stat(path, &st) == -1 || !S_ISDIR(st.st_mode)) { - path = free_and_assign(path, strip_last_component(path)); + path = real_dir_from_tilde(inpath); + /* Perhaps path is a directory. If so, we'll pass it to + * do_browser(). Or perhaps path is a directory / a file. If so, + * we'll try stripping off the last path element and passing it to + * do_browser(). Or perhaps path doesn't have a directory portion + * at all. If so, we'll just pass the current directory to + * do_browser(). */ if (stat(path, &st) == -1 || !S_ISDIR(st.st_mode)) { - char * currentdir = charalloc(PATH_MAX + 1); + path = free_and_assign(path, strip_last_component(path)); - free(path); - path = getcwd(currentdir, PATH_MAX + 1); + if (stat(path, &st) == -1 || !S_ISDIR(st.st_mode)) { + char * currentdir = charalloc(PATH_MAX + 1); - if (path == NULL) { - free(currentdir); - statusline(MILD, _("The working directory has disappeared")); - beep(); - napms(1200); - return NULL; - } + free(path); + path = getcwd(currentdir, PATH_MAX + 1); + + if (path == NULL) { + free(currentdir); + statusline(MILD, _("The working directory has disappeared")); + beep(); + napms(1200); + return NULL; + } + } } - } #ifdef ENABLE_OPERATINGDIR - /* If the resulting path isn't in the operating directory, use - * the operating directory instead. */ - if (outside_of_confinement(path, FALSE)) - path = mallocstrcpy(path, operating_dir); + /* If the resulting path isn't in the operating directory, use + * the operating directory instead. */ + if (outside_of_confinement(path, FALSE)) + path = mallocstrcpy(path, operating_dir); #endif - return do_browser(path); + return do_browser(path); } /* Set filelist to the list of files contained in the directory path, @@ -389,270 +389,270 @@ char *do_browse_from(const char *inpath) * per screen row. And sort the list too. */ void read_the_list(const char *path, DIR *dir) { - const struct dirent *nextdir; - size_t i = 0, path_len = strlen(path); + const struct dirent *nextdir; + size_t i = 0, path_len = strlen(path); - assert(path != NULL && path[strlen(path) - 1] == '/' && dir != NULL); + assert(path != NULL && path[strlen(path) - 1] == '/' && dir != NULL); - longest = 0; + longest = 0; - /* Find the length of the longest filename in the current folder. */ - while ((nextdir = readdir(dir)) != NULL) { - size_t name_len = strlenpt(nextdir->d_name); + /* Find the length of the longest filename in the current folder. */ + while ((nextdir = readdir(dir)) != NULL) { + size_t name_len = strlenpt(nextdir->d_name); - if (name_len > longest) - longest = name_len; + if (name_len > longest) + longest = name_len; - i++; - } + i++; + } - /* Put 10 characters' worth of blank space between columns of filenames - * in the list whenever possible, as Pico does. */ - longest += 10; + /* Put 10 characters' worth of blank space between columns of filenames + * in the list whenever possible, as Pico does. */ + longest += 10; - /* If needed, make room for ".. (parent dir)". */ - if (longest < 15) - longest = 15; - /* Make sure we're not wider than the window. */ - if (longest > COLS) - longest = COLS; + /* If needed, make room for ".. (parent dir)". */ + if (longest < 15) + longest = 15; + /* Make sure we're not wider than the window. */ + if (longest > COLS) + longest = COLS; - rewinddir(dir); + rewinddir(dir); - free_chararray(filelist, filelist_len); + free_chararray(filelist, filelist_len); - filelist_len = i; + filelist_len = i; - filelist = (char **)nmalloc(filelist_len * sizeof(char *)); + filelist = (char **)nmalloc(filelist_len * sizeof(char *)); - i = 0; + i = 0; - while ((nextdir = readdir(dir)) != NULL && i < filelist_len) { - /* Don't show the "." entry. */ - if (strcmp(nextdir->d_name, ".") == 0) - continue; + while ((nextdir = readdir(dir)) != NULL && i < filelist_len) { + /* Don't show the "." entry. */ + if (strcmp(nextdir->d_name, ".") == 0) + continue; - filelist[i] = charalloc(path_len + strlen(nextdir->d_name) + 1); - sprintf(filelist[i], "%s%s", path, nextdir->d_name); + filelist[i] = charalloc(path_len + strlen(nextdir->d_name) + 1); + sprintf(filelist[i], "%s%s", path, nextdir->d_name); - i++; - } + i++; + } - /* Maybe the number of files in the directory changed between the - * first time we scanned and the second. i is the actual length of - * filelist, so record it. */ - filelist_len = i; + /* Maybe the number of files in the directory changed between the + * first time we scanned and the second. i is the actual length of + * filelist, so record it. */ + filelist_len = i; - assert(filelist != NULL); + assert(filelist != NULL); - /* Sort the list of names. */ - qsort(filelist, filelist_len, sizeof(char *), diralphasort); + /* Sort the list of names. */ + qsort(filelist, filelist_len, sizeof(char *), diralphasort); - /* Calculate how many files fit on a line -- feigning room for two - * spaces beyond the right edge, and adding two spaces of padding - * between columns. */ - width = (COLS + 2) / (longest + 2); + /* Calculate how many files fit on a line -- feigning room for two + * spaces beyond the right edge, and adding two spaces of padding + * between columns. */ + width = (COLS + 2) / (longest + 2); } /* Return the function that is bound to the given key, accepting certain * plain characters too, for compatibility with Pico. */ functionptrtype parse_browser_input(int *kbinput) { - if (!meta_key) { - switch (*kbinput) { - case ' ': - return do_page_down; - case '-': - return do_page_up; - case '?': - return do_help_void; - case 'E': - case 'e': - case 'Q': - case 'q': - case 'X': - case 'x': - return do_exit; - case 'G': - case 'g': - return goto_dir_void; - case 'S': - case 's': - return do_enter; - case 'W': - case 'w': - case '/': - return do_search_forward; - case 'N': + if (!meta_key) { + switch (*kbinput) { + case ' ': + return do_page_down; + case '-': + return do_page_up; + case '?': + return do_help_void; + case 'E': + case 'e': + case 'Q': + case 'q': + case 'X': + case 'x': + return do_exit; + case 'G': + case 'g': + return goto_dir_void; + case 'S': + case 's': + return do_enter; + case 'W': + case 'w': + case '/': + return do_search_forward; + case 'N': #ifndef NANO_TINY - return do_findprevious; + return do_findprevious; #endif - case 'n': - return do_research; + case 'n': + return do_research; + } } - } - return func_from_key(kbinput); + return func_from_key(kbinput); } /* Set width to the number of files that we can display per screen row, * if necessary, and display the list of files. */ void browser_refresh(void) { - size_t i; - int row = 0, col = 0; - /* The current row and column while the list is getting displayed. */ - int the_row = 0, the_column = 0; - /* The row and column of the selected item. */ - char *info; - /* The additional information that we'll display about a file. */ + size_t i; + int row = 0, col = 0; + /* The current row and column while the list is getting displayed. */ + int the_row = 0, the_column = 0; + /* The row and column of the selected item. */ + char *info; + /* The additional information that we'll display about a file. */ - titlebar(present_path); - blank_edit(); + titlebar(present_path); + blank_edit(); - wmove(edit, 0, 0); + wmove(edit, 0, 0); - i = selected - selected % (editwinrows * width); + i = selected - selected % (editwinrows * width); - for (; i < filelist_len && row < editwinrows; i++) { - struct stat st; - const char *thename = tail(filelist[i]); - /* The filename we display, minus the path. */ - size_t namelen = strlenpt(thename); - /* The length of the filename in columns. */ - size_t infolen; - /* The length of the file information in columns. */ - int infomaxlen = 7; - /* The maximum length of the file information in columns: - * normally seven, but will be twelve for "(parent dir)". */ - bool dots = (COLS >= 15 && namelen >= longest - infomaxlen); - /* Whether to put an ellipsis before the filename? We don't - * waste space on dots when there are fewer than 15 columns. */ - char *disp = display_string(thename, dots ? - namelen + infomaxlen + 4 - longest : 0, longest, FALSE); - /* The filename (or a fragment of it) in displayable format. - * When a fragment, account for dots plus one space padding. */ + for (; i < filelist_len && row < editwinrows; i++) { + struct stat st; + const char *thename = tail(filelist[i]); + /* The filename we display, minus the path. */ + size_t namelen = strlenpt(thename); + /* The length of the filename in columns. */ + size_t infolen; + /* The length of the file information in columns. */ + int infomaxlen = 7; + /* The maximum length of the file information in columns: + * normally seven, but will be twelve for "(parent dir)". */ + bool dots = (COLS >= 15 && namelen >= longest - infomaxlen); + /* Whether to put an ellipsis before the filename? We don't + * waste space on dots when there are fewer than 15 columns. */ + char *disp = display_string(thename, dots ? + namelen + infomaxlen + 4 - longest : 0, longest, FALSE); + /* The filename (or a fragment of it) in displayable format. + * When a fragment, account for dots plus one space padding. */ - /* If this is the selected item, start its highlighting, and - * remember its location to be able to place the cursor on it. */ - if (i == selected) { - wattron(edit, interface_color_pair[SELECTED_TEXT]); - the_row = row; - the_column = col; + /* If this is the selected item, start its highlighting, and + * remember its location to be able to place the cursor on it. */ + if (i == selected) { + wattron(edit, interface_color_pair[SELECTED_TEXT]); + the_row = row; + the_column = col; + } + + blank_row(edit, row, col, longest); + + /* If the name is too long, we display something like "...ename". */ + if (dots) + mvwaddstr(edit, row, col, "..."); + mvwaddstr(edit, row, dots ? col + 3 : col, disp); + + free(disp); + + col += longest; + + /* Show information about the file: "--" for symlinks (except when + * they point to a directory) and for files that have disappeared, + * "(dir)" for directories, and the file size for normal files. */ + if (lstat(filelist[i], &st) == -1 || S_ISLNK(st.st_mode)) { + if (stat(filelist[i], &st) == -1 || !S_ISDIR(st.st_mode)) + info = mallocstrcpy(NULL, "--"); + else + /* TRANSLATORS: Try to keep this at most 7 characters. */ + info = mallocstrcpy(NULL, _("(dir)")); + } else if (S_ISDIR(st.st_mode)) { + if (strcmp(thename, "..") == 0) { + /* TRANSLATORS: Try to keep this at most 12 characters. */ + info = mallocstrcpy(NULL, _("(parent dir)")); + infomaxlen = 12; + } else + info = mallocstrcpy(NULL, _("(dir)")); + } else { + off_t result = st.st_size; + char modifier; + + info = charalloc(infomaxlen + 1); + + /* Massage the file size into a human-readable form. */ + if (st.st_size < (1 << 10)) + modifier = ' '; /* bytes */ + else if (st.st_size < (1 << 20)) { + result >>= 10; + modifier = 'K'; /* kilobytes */ + } else if (st.st_size < (1 << 30)) { + result >>= 20; + modifier = 'M'; /* megabytes */ + } else { + result >>= 30; + modifier = 'G'; /* gigabytes */ + } + + /* Show the size if less than a terabyte, else show "(huge)". */ + if (result < (1 << 10)) + sprintf(info, "%4ju %cB", (intmax_t)result, modifier); + else + /* TRANSLATORS: Try to keep this at most 7 characters. + * If necessary, you can leave out the parentheses. */ + info = mallocstrcpy(info, _("(huge)")); + } + + /* Make sure info takes up no more than infomaxlen columns. */ + infolen = strlenpt(info); + if (infolen > infomaxlen) { + info[actual_x(info, infomaxlen)] = '\0'; + infolen = infomaxlen; + } + + mvwaddstr(edit, row, col - infolen, info); + + /* If this is the selected item, finish its highlighting. */ + if (i == selected) + wattroff(edit, interface_color_pair[SELECTED_TEXT]); + + free(info); + + /* Add some space between the columns. */ + col += 2; + + /* If the next entry isn't going to fit on the current row, + * move to the next row. */ + if (col > COLS - longest) { + row++; + col = 0; + } } - blank_row(edit, row, col, longest); - - /* If the name is too long, we display something like "...ename". */ - if (dots) - mvwaddstr(edit, row, col, "..."); - mvwaddstr(edit, row, dots ? col + 3 : col, disp); - - free(disp); - - col += longest; - - /* Show information about the file: "--" for symlinks (except when - * they point to a directory) and for files that have disappeared, - * "(dir)" for directories, and the file size for normal files. */ - if (lstat(filelist[i], &st) == -1 || S_ISLNK(st.st_mode)) { - if (stat(filelist[i], &st) == -1 || !S_ISDIR(st.st_mode)) - info = mallocstrcpy(NULL, "--"); - else - /* TRANSLATORS: Try to keep this at most 7 characters. */ - info = mallocstrcpy(NULL, _("(dir)")); - } else if (S_ISDIR(st.st_mode)) { - if (strcmp(thename, "..") == 0) { - /* TRANSLATORS: Try to keep this at most 12 characters. */ - info = mallocstrcpy(NULL, _("(parent dir)")); - infomaxlen = 12; - } else - info = mallocstrcpy(NULL, _("(dir)")); - } else { - off_t result = st.st_size; - char modifier; - - info = charalloc(infomaxlen + 1); - - /* Massage the file size into a human-readable form. */ - if (st.st_size < (1 << 10)) - modifier = ' '; /* bytes */ - else if (st.st_size < (1 << 20)) { - result >>= 10; - modifier = 'K'; /* kilobytes */ - } else if (st.st_size < (1 << 30)) { - result >>= 20; - modifier = 'M'; /* megabytes */ - } else { - result >>= 30; - modifier = 'G'; /* gigabytes */ - } - - /* Show the size if less than a terabyte, else show "(huge)". */ - if (result < (1 << 10)) - sprintf(info, "%4ju %cB", (intmax_t)result, modifier); - else - /* TRANSLATORS: Try to keep this at most 7 characters. - * If necessary, you can leave out the parentheses. */ - info = mallocstrcpy(info, _("(huge)")); + /* If requested, put the cursor on the selected item and switch it on. */ + if (ISSET(SHOW_CURSOR)) { + wmove(edit, the_row, the_column); + curs_set(1); } - /* Make sure info takes up no more than infomaxlen columns. */ - infolen = strlenpt(info); - if (infolen > infomaxlen) { - info[actual_x(info, infomaxlen)] = '\0'; - infolen = infomaxlen; - } - - mvwaddstr(edit, row, col - infolen, info); - - /* If this is the selected item, finish its highlighting. */ - if (i == selected) - wattroff(edit, interface_color_pair[SELECTED_TEXT]); - - free(info); - - /* Add some space between the columns. */ - col += 2; - - /* If the next entry isn't going to fit on the current row, - * move to the next row. */ - if (col > COLS - longest) { - row++; - col = 0; - } - } - - /* If requested, put the cursor on the selected item and switch it on. */ - if (ISSET(SHOW_CURSOR)) { - wmove(edit, the_row, the_column); - curs_set(1); - } - - wnoutrefresh(edit); + wnoutrefresh(edit); } /* Look for needle. If we find it, set selected to its location. * Note that needle must be an exact match for a file in the list. */ void browser_select_dirname(const char *needle) { - size_t looking_at = 0; + size_t looking_at = 0; - for (; looking_at < filelist_len; looking_at++) { - if (strcmp(filelist[looking_at], needle) == 0) { - selected = looking_at; - break; + for (; looking_at < filelist_len; looking_at++) { + if (strcmp(filelist[looking_at], needle) == 0) { + selected = looking_at; + break; + } } - } - /* If the sought name isn't found, move the highlight so that the - * changed selection will be noticed. */ - if (looking_at == filelist_len) { - --selected; + /* If the sought name isn't found, move the highlight so that the + * changed selection will be noticed. */ + if (looking_at == filelist_len) { + --selected; - /* Make sure we stay within the available range. */ - if (selected >= filelist_len) - selected = filelist_len - 1; - } + /* Make sure we stay within the available range. */ + if (selected >= filelist_len) + selected = filelist_len - 1; + } } /* Set up the system variables for a filename search. Return -1 or -2 if @@ -661,152 +661,152 @@ void browser_select_dirname(const char *needle) * function was run. */ int filesearch_init(void) { - int input; - char *buf; + int input; + char *buf; - if (*last_search != '\0') { - char *disp = display_string(last_search, 0, COLS / 3, FALSE); + if (*last_search != '\0') { + char *disp = display_string(last_search, 0, COLS / 3, FALSE); - buf = charalloc(strlen(disp) + 7); - /* We use (COLS / 3) here because we need to see more on the line. */ - sprintf(buf, " [%s%s]", disp, - (strlenpt(last_search) > COLS / 3) ? "..." : ""); - free(disp); - } else - buf = mallocstrcpy(NULL, ""); + buf = charalloc(strlen(disp) + 7); + /* We use (COLS / 3) here because we need to see more on the line. */ + sprintf(buf, " [%s%s]", disp, + (strlenpt(last_search) > COLS / 3) ? "..." : ""); + free(disp); + } else + buf = mallocstrcpy(NULL, ""); - /* This is now one simple call. It just does a lot. */ - input = do_prompt(FALSE, FALSE, MWHEREISFILE, NULL, &search_history, - browser_refresh, "%s%s", _("Search"), buf); + /* This is now one simple call. It just does a lot. */ + input = do_prompt(FALSE, FALSE, MWHEREISFILE, NULL, &search_history, + browser_refresh, "%s%s", _("Search"), buf); - /* Release buf now that we don't need it anymore. */ - free(buf); + /* Release buf now that we don't need it anymore. */ + free(buf); - /* If only Enter was pressed but we have a previous string, it's okay. */ - if (input == -2 && *last_search != '\0') - return 0; + /* If only Enter was pressed but we have a previous string, it's okay. */ + if (input == -2 && *last_search != '\0') + return 0; - /* Otherwise negative inputs are a bailout. */ - if (input < 0) - statusbar(_("Cancelled")); + /* Otherwise negative inputs are a bailout. */ + if (input < 0) + statusbar(_("Cancelled")); - return input; + return input; } /* Look for the given needle in the list of files. If forwards is TRUE, * search forward in the list; otherwise, search backward. */ void findfile(const char *needle, bool forwards) { - size_t looking_at = selected; - /* The location in the file list of the filename we're looking at. */ - const char *thename; - /* The plain filename, without the path. */ - unsigned stash[sizeof(flags) / sizeof(flags[0])]; - /* A storage place for the current flag settings. */ + size_t looking_at = selected; + /* The location in the file list of the filename we're looking at. */ + const char *thename; + /* The plain filename, without the path. */ + unsigned stash[sizeof(flags) / sizeof(flags[0])]; + /* A storage place for the current flag settings. */ - /* Save the settings of all flags. */ - memcpy(stash, flags, sizeof(flags)); + /* Save the settings of all flags. */ + memcpy(stash, flags, sizeof(flags)); - /* Search forward, case insensitive, and without regexes. */ - UNSET(BACKWARDS_SEARCH); - UNSET(CASE_SENSITIVE); - UNSET(USE_REGEXP); + /* Search forward, case insensitive, and without regexes. */ + UNSET(BACKWARDS_SEARCH); + UNSET(CASE_SENSITIVE); + UNSET(USE_REGEXP); - /* Step through each filename in the list until a match is found or - * we've come back to the point where we started. */ - while (TRUE) { - if (forwards) { - if (looking_at++ == filelist_len - 1) { - looking_at = 0; - statusbar(_("Search Wrapped")); - } - } else { - if (looking_at-- == 0) { - looking_at = filelist_len - 1; - statusbar(_("Search Wrapped")); - } + /* Step through each filename in the list until a match is found or + * we've come back to the point where we started. */ + while (TRUE) { + if (forwards) { + if (looking_at++ == filelist_len - 1) { + looking_at = 0; + statusbar(_("Search Wrapped")); + } + } else { + if (looking_at-- == 0) { + looking_at = filelist_len - 1; + statusbar(_("Search Wrapped")); + } + } + + /* Get the bare filename, without the path. */ + thename = tail(filelist[looking_at]); + + /* If the needle matches, we're done. And if we're back at the file + * where we started, it is the only occurrence. */ + if (strstrwrapper(thename, needle, thename)) { + if (looking_at == selected) + statusbar(_("This is the only occurrence")); + break; + } + + /* If we're back at the beginning and didn't find any match... */ + if (looking_at == selected) { + not_found_msg(needle); + break; + } } - /* Get the bare filename, without the path. */ - thename = tail(filelist[looking_at]); + /* Restore the settings of all flags. */ + memcpy(flags, stash, sizeof(flags)); - /* If the needle matches, we're done. And if we're back at the file - * where we started, it is the only occurrence. */ - if (strstrwrapper(thename, needle, thename)) { - if (looking_at == selected) - statusbar(_("This is the only occurrence")); - break; - } - - /* If we're back at the beginning and didn't find any match... */ - if (looking_at == selected) { - not_found_msg(needle); - break; - } - } - - /* Restore the settings of all flags. */ - memcpy(flags, stash, sizeof(flags)); - - /* Select the one we've found. */ - selected = looking_at; + /* Select the one we've found. */ + selected = looking_at; } /* Search for a filename. */ void do_filesearch(void) { - /* If the user cancelled or jumped to first or last file, don't search. */ - if (filesearch_init() != 0) - return; + /* If the user cancelled or jumped to first or last file, don't search. */ + if (filesearch_init() != 0) + return; - /* If answer is now "", copy last_search into answer. */ - if (*answer == '\0') - answer = mallocstrcpy(answer, last_search); - else - last_search = mallocstrcpy(last_search, answer); + /* If answer is now "", copy last_search into answer. */ + if (*answer == '\0') + answer = mallocstrcpy(answer, last_search); + else + last_search = mallocstrcpy(last_search, answer); #ifdef ENABLE_HISTORIES - /* If answer is not empty, add the string to the search history list. */ - if (*answer != '\0') - update_history(&search_history, answer); + /* If answer is not empty, add the string to the search history list. */ + if (*answer != '\0') + update_history(&search_history, answer); #endif - findfile(answer, TRUE); + findfile(answer, TRUE); } /* Search again without prompting for the last given search string, * either forwards or backwards. */ void do_fileresearch(bool forwards) { - if (*last_search == '\0') - statusbar(_("No current search pattern")); - else - findfile(last_search, forwards); + if (*last_search == '\0') + statusbar(_("No current search pattern")); + else + findfile(last_search, forwards); } /* Select the first file in the list. */ void to_first_file(void) { - selected = 0; + selected = 0; } /* Select the last file in the list. */ void to_last_file(void) { - selected = filelist_len - 1; + selected = filelist_len - 1; } /* Strip one element from the end of path, and return the stripped path. * The returned string is dynamically allocated, and should be freed. */ char *strip_last_component(const char *path) { - char *copy = mallocstrcpy(NULL, path); - char *last_slash = strrchr(copy, '/'); + char *copy = mallocstrcpy(NULL, path); + char *last_slash = strrchr(copy, '/'); - if (last_slash != NULL) - *last_slash = '\0'; + if (last_slash != NULL) + *last_slash = '\0'; - return copy; + return copy; } #endif /* ENABLE_BROWSER */ diff --git a/src/chars.c b/src/chars.c index 96df5318..385accfa 100644 --- a/src/chars.c +++ b/src/chars.c @@ -29,110 +29,110 @@ #include static bool use_utf8 = FALSE; - /* Whether we've enabled UTF-8 support. */ + /* Whether we've enabled UTF-8 support. */ /* Enable UTF-8 support. */ void utf8_init(void) { - use_utf8 = TRUE; + use_utf8 = TRUE; } /* Is UTF-8 support enabled? */ bool using_utf8(void) { - return use_utf8; + return use_utf8; } #endif /* ENABLE_UTF8 */ /* Concatenate two allocated strings, and free the second. */ char *addstrings(char* str1, size_t len1, char* str2, size_t len2) { - str1 = charealloc(str1, len1 + len2 + 1); - str1[len1] = '\0'; + str1 = charealloc(str1, len1 + len2 + 1); + str1[len1] = '\0'; - strncat(&str1[len1], str2, len2); - free(str2); + strncat(&str1[len1], str2, len2); + free(str2); - return str1; + return str1; } /* Return TRUE if the value of c is in byte range, and FALSE otherwise. */ bool is_byte(int c) { - return ((unsigned int)c == (unsigned char)c); + return ((unsigned int)c == (unsigned char)c); } void mbtowc_reset(void) { - IGNORE_CALL_RESULT(mbtowc(NULL, NULL, 0)); + IGNORE_CALL_RESULT(mbtowc(NULL, NULL, 0)); } /* This function is equivalent to isalpha() for multibyte characters. */ bool is_alpha_mbchar(const char *c) { #ifdef ENABLE_UTF8 - if (use_utf8) { - wchar_t wc; + if (use_utf8) { + wchar_t wc; - if (mbtowc(&wc, c, MAXCHARLEN) < 0) { - mbtowc_reset(); - return 0; - } + if (mbtowc(&wc, c, MAXCHARLEN) < 0) { + mbtowc_reset(); + return 0; + } - return iswalpha(wc); - } else + return iswalpha(wc); + } else #endif - return isalpha((unsigned char)*c); + return isalpha((unsigned char)*c); } /* This function is equivalent to isalnum() for multibyte characters. */ bool is_alnum_mbchar(const char *c) { #ifdef ENABLE_UTF8 - if (use_utf8) { - wchar_t wc; + if (use_utf8) { + wchar_t wc; - if (mbtowc(&wc, c, MAXCHARLEN) < 0) { - mbtowc_reset(); - return 0; - } + if (mbtowc(&wc, c, MAXCHARLEN) < 0) { + mbtowc_reset(); + return 0; + } - return iswalnum(wc); - } else + return iswalnum(wc); + } else #endif - return isalnum((unsigned char)*c); + return isalnum((unsigned char)*c); } /* This function is equivalent to isblank() for multibyte characters. */ bool is_blank_mbchar(const char *c) { #ifdef ENABLE_UTF8 - if (use_utf8) { - wchar_t wc; + if (use_utf8) { + wchar_t wc; - if (mbtowc(&wc, c, MAXCHARLEN) < 0) { - mbtowc_reset(); - return 0; - } + if (mbtowc(&wc, c, MAXCHARLEN) < 0) { + mbtowc_reset(); + return 0; + } - return iswblank(wc); - } else + return iswblank(wc); + } else #endif - return isblank((unsigned char)*c); + return isblank((unsigned char)*c); } /* This function is equivalent to iscntrl(), except in that it only * handles non-high-bit control characters. */ bool is_ascii_cntrl_char(int c) { - return (0 <= c && c < 32); + return (0 <= c && c < 32); } /* This function is equivalent to iscntrl(), except in that it also * handles high-bit control characters. */ bool is_cntrl_char(int c) { - return ((c & 0x60) == 0 || c == 127); + return ((c & 0x60) == 0 || c == 127); } /* This function is equivalent to iscntrl() for multibyte characters, @@ -141,30 +141,30 @@ bool is_cntrl_char(int c) bool is_cntrl_mbchar(const char *c) { #ifdef ENABLE_UTF8 - if (use_utf8) { - return ((c[0] & 0xE0) == 0 || c[0] == 127 || - ((signed char)c[0] == -62 && (signed char)c[1] < -96)); - } else + if (use_utf8) { + return ((c[0] & 0xE0) == 0 || c[0] == 127 || + ((signed char)c[0] == -62 && (signed char)c[1] < -96)); + } else #endif - return is_cntrl_char((unsigned char)*c); + return is_cntrl_char((unsigned char)*c); } /* This function is equivalent to ispunct() for multibyte characters. */ bool is_punct_mbchar(const char *c) { #ifdef ENABLE_UTF8 - if (use_utf8) { - wchar_t wc; + if (use_utf8) { + wchar_t wc; - if (mbtowc(&wc, c, MAXCHARLEN) < 0) { - mbtowc_reset(); - return 0; - } + if (mbtowc(&wc, c, MAXCHARLEN) < 0) { + mbtowc_reset(); + return 0; + } - return iswpunct(wc); - } else + return iswpunct(wc); + } else #endif - return ispunct((unsigned char)*c); + return ispunct((unsigned char)*c); } /* Return TRUE when the given multibyte character c is a word-forming @@ -172,52 +172,52 @@ bool is_punct_mbchar(const char *c) * punctuation when allow_punct is TRUE), and FALSE otherwise. */ bool is_word_mbchar(const char *c, bool allow_punct) { - if (*c == '\0') - return FALSE; + if (*c == '\0') + return FALSE; - if (is_alnum_mbchar(c)) - return TRUE; + if (is_alnum_mbchar(c)) + return TRUE; - if (word_chars != NULL && *word_chars != '\0') { - char symbol[MAXCHARLEN + 1]; - int symlen = parse_mbchar(c, symbol, NULL); + if (word_chars != NULL && *word_chars != '\0') { + char symbol[MAXCHARLEN + 1]; + int symlen = parse_mbchar(c, symbol, NULL); - symbol[symlen] = '\0'; - return (strstr(word_chars, symbol) != NULL); - } + symbol[symlen] = '\0'; + return (strstr(word_chars, symbol) != NULL); + } - return (allow_punct && is_punct_mbchar(c)); + return (allow_punct && is_punct_mbchar(c)); } /* Return the visible representation of control character c. */ char control_rep(const signed char c) { - if (c == DEL_CODE) - return '?'; - else if (c == -97) - return '='; - else if (c < 0) - return c + 224; - else - return c + 64; + if (c == DEL_CODE) + return '?'; + else if (c == -97) + return '='; + else if (c < 0) + return c + 224; + else + return c + 64; } /* Return the visible representation of multibyte control character c. */ char control_mbrep(const char *c, bool isdata) { - /* An embedded newline is an encoded NUL if it is data. */ - if (*c == '\n' && (isdata || as_an_at)) - return '@'; + /* An embedded newline is an encoded NUL if it is data. */ + if (*c == '\n' && (isdata || as_an_at)) + return '@'; #ifdef ENABLE_UTF8 - if (use_utf8) { - if ((unsigned char)c[0] < 128) - return control_rep(c[0]); - else - return control_rep(c[1]); - } else + if (use_utf8) { + if ((unsigned char)c[0] < 128) + return control_rep(c[0]); + else + return control_rep(c[1]); + } else #endif - return control_rep(*c); + return control_rep(*c); } /* Assess how many bytes the given (multibyte) character occupies. Return -1 @@ -227,53 +227,53 @@ char control_mbrep(const char *c, bool isdata) int length_of_char(const char *c, int *width) { #ifdef ENABLE_UTF8 - if (use_utf8) { - wchar_t wc; - int charlen = mbtowc(&wc, c, MAXCHARLEN); + if (use_utf8) { + wchar_t wc; + int charlen = mbtowc(&wc, c, MAXCHARLEN); - /* If the sequence is invalid... */ - if (charlen < 0) { - mbtowc_reset(); - return -1; - } + /* If the sequence is invalid... */ + if (charlen < 0) { + mbtowc_reset(); + return -1; + } - /* If the codepoint is invalid... */ - if (!is_valid_unicode(wc)) - return charlen - 8; - else { - *width = wcwidth(wc); - /* If the codepoint is unassigned, assume a width of one. */ - if (*width < 0) - *width = 1; - return charlen; - } - } else + /* If the codepoint is invalid... */ + if (!is_valid_unicode(wc)) + return charlen - 8; + else { + *width = wcwidth(wc); + /* If the codepoint is unassigned, assume a width of one. */ + if (*width < 0) + *width = 1; + return charlen; + } + } else #endif - return 1; + return 1; } /* This function is equivalent to wcwidth() for multibyte characters. */ int mbwidth(const char *c) { #ifdef ENABLE_UTF8 - if (use_utf8) { - wchar_t wc; - int width; + if (use_utf8) { + wchar_t wc; + int width; - if (mbtowc(&wc, c, MAXCHARLEN) < 0) { - mbtowc_reset(); - return 1; - } + if (mbtowc(&wc, c, MAXCHARLEN) < 0) { + mbtowc_reset(); + return 1; + } - width = wcwidth(wc); + width = wcwidth(wc); - if (width == -1) - return 1; + if (width == -1) + return 1; - return width; - } else + return width; + } else #endif - return 1; + return 1; } /* Convert the Unicode value in chr to a multibyte character, if possible. @@ -282,26 +282,26 @@ int mbwidth(const char *c) * allocated) multibyte character and a length of zero. */ char *make_mbchar(long chr, int *chr_mb_len) { - char *chr_mb; + char *chr_mb; #ifdef ENABLE_UTF8 - if (use_utf8) { - chr_mb = charalloc(MAXCHARLEN); - *chr_mb_len = wctomb(chr_mb, (wchar_t)chr); + if (use_utf8) { + chr_mb = charalloc(MAXCHARLEN); + *chr_mb_len = wctomb(chr_mb, (wchar_t)chr); - /* Reject invalid Unicode characters. */ - if (*chr_mb_len < 0 || !is_valid_unicode((wchar_t)chr)) { - IGNORE_CALL_RESULT(wctomb(NULL, 0)); - *chr_mb_len = 0; - } - } else + /* Reject invalid Unicode characters. */ + if (*chr_mb_len < 0 || !is_valid_unicode((wchar_t)chr)) { + IGNORE_CALL_RESULT(wctomb(NULL, 0)); + *chr_mb_len = 0; + } + } else #endif - { - *chr_mb_len = 1; - chr_mb = mallocstrncpy(NULL, (char *)&chr, 1); - } + { + *chr_mb_len = 1; + chr_mb = mallocstrncpy(NULL, (char *)&chr, 1); + } - return chr_mb; + return chr_mb; } /* Parse a multibyte character from buf. Return the number of bytes @@ -310,64 +310,64 @@ char *make_mbchar(long chr, int *chr_mb_len) int parse_mbchar(const char *buf, char *chr, size_t *col) { #ifdef ENABLE_UTF8 - if (use_utf8) { - /* Get the number of bytes in the multibyte character. */ - int length = mblen(buf, MAXCHARLEN); + if (use_utf8) { + /* Get the number of bytes in the multibyte character. */ + int length = mblen(buf, MAXCHARLEN); - /* When the multibyte sequence is invalid, only take the first byte. */ - if (length <= 0) { - IGNORE_CALL_RESULT(mblen(NULL, 0)); - length = 1; - } + /* When the multibyte sequence is invalid, only take the first byte. */ + if (length <= 0) { + IGNORE_CALL_RESULT(mblen(NULL, 0)); + length = 1; + } - /* When requested, store the multibyte character in chr. */ - if (chr != NULL) { - int i; + /* When requested, store the multibyte character in chr. */ + if (chr != NULL) { + int i; - for (i = 0; i < length; i++) - chr[i] = buf[i]; - } + for (i = 0; i < length; i++) + chr[i] = buf[i]; + } - /* When requested, add the width of the character to col. */ - if (col != NULL) { - /* If we have a tab, compute its width in columns based on the - * current value of col. */ - if (*buf == '\t') - *col += tabsize - *col % tabsize; - /* If we have a control character, it's two columns wide: one - * column for the "^", and one for the visible character. */ - else if (is_cntrl_mbchar(buf)) { - *col += 2; - /* If we have a normal character, get its width normally. */ - } else - *col += mbwidth(buf); - } + /* When requested, add the width of the character to col. */ + if (col != NULL) { + /* If we have a tab, compute its width in columns based on the + * current value of col. */ + if (*buf == '\t') + *col += tabsize - *col % tabsize; + /* If we have a control character, it's two columns wide: one + * column for the "^", and one for the visible character. */ + else if (is_cntrl_mbchar(buf)) { + *col += 2; + /* If we have a normal character, get its width normally. */ + } else + *col += mbwidth(buf); + } - return length; - } else + return length; + } else #endif - { - /* When requested, store the byte character in chr. */ - if (chr != NULL) - *chr = *buf; + { + /* When requested, store the byte character in chr. */ + if (chr != NULL) + *chr = *buf; - /* When requested, add the width of the character to col. */ - if (col != NULL) { - /* If we have a tab, compute its width in columns using the - * current value of col. */ - if (*buf == '\t') - *col += tabsize - *col % tabsize; - /* If we have a control character, it's two columns wide: one - * column for the "^", and one for the visible character. */ - else if (is_cntrl_char((unsigned char)*buf)) - *col += 2; - /* If we have a normal character, it's one column wide. */ - else - (*col)++; + /* When requested, add the width of the character to col. */ + if (col != NULL) { + /* If we have a tab, compute its width in columns using the + * current value of col. */ + if (*buf == '\t') + *col += tabsize - *col % tabsize; + /* If we have a control character, it's two columns wide: one + * column for the "^", and one for the visible character. */ + else if (is_cntrl_char((unsigned char)*buf)) + *col += 2; + /* If we have a normal character, it's one column wide. */ + else + (*col)++; + } + + return 1; } - - return 1; - } } /* Return the index in buf of the beginning of the multibyte character @@ -375,208 +375,208 @@ int parse_mbchar(const char *buf, char *chr, size_t *col) size_t move_mbleft(const char *buf, size_t pos) { #ifdef ENABLE_UTF8 - if (use_utf8) { - size_t before, char_len = 0; + if (use_utf8) { + size_t before, char_len = 0; - if (pos < 4) - before = 0; - else { - const char *ptr = buf + pos; + if (pos < 4) + before = 0; + else { + const char *ptr = buf + pos; - /* Probe for a valid starter byte in the preceding four bytes. */ - if ((signed char)*(--ptr) > -65) - before = pos - 1; - else if ((signed char)*(--ptr) > -65) - before = pos - 2; - else if ((signed char)*(--ptr) > -65) - before = pos - 3; - else if ((signed char)*(--ptr) > -65) - before = pos - 4; - else - before = pos - 1; - } + /* Probe for a valid starter byte in the preceding four bytes. */ + if ((signed char)*(--ptr) > -65) + before = pos - 1; + else if ((signed char)*(--ptr) > -65) + before = pos - 2; + else if ((signed char)*(--ptr) > -65) + before = pos - 3; + else if ((signed char)*(--ptr) > -65) + before = pos - 4; + else + before = pos - 1; + } - /* Move forward again until we reach the original character, - * so we know the length of its preceding character. */ - while (before < pos) { - char_len = parse_mbchar(buf + before, NULL, NULL); - before += char_len; - } + /* Move forward again until we reach the original character, + * so we know the length of its preceding character. */ + while (before < pos) { + char_len = parse_mbchar(buf + before, NULL, NULL); + before += char_len; + } - return before - char_len; - } else + return before - char_len; + } else #endif - return (pos == 0 ? 0 : pos - 1); + return (pos == 0 ? 0 : pos - 1); } /* Return the index in buf of the beginning of the multibyte character * after the one at pos. */ size_t move_mbright(const char *buf, size_t pos) { - return pos + parse_mbchar(buf + pos, NULL, NULL); + return pos + parse_mbchar(buf + pos, NULL, NULL); } /* This function is equivalent to strcasecmp() for multibyte strings. */ int mbstrcasecmp(const char *s1, const char *s2) { - return mbstrncasecmp(s1, s2, HIGHEST_POSITIVE); + return mbstrncasecmp(s1, s2, HIGHEST_POSITIVE); } /* This function is equivalent to strncasecmp() for multibyte strings. */ int mbstrncasecmp(const char *s1, const char *s2, size_t n) { #ifdef ENABLE_UTF8 - if (use_utf8) { - wchar_t wc1, wc2; + if (use_utf8) { + wchar_t wc1, wc2; - while (*s1 != '\0' && *s2 != '\0' && n > 0) { - bool bad1 = FALSE, bad2 = FALSE; + while (*s1 != '\0' && *s2 != '\0' && n > 0) { + bool bad1 = FALSE, bad2 = FALSE; - if (mbtowc(&wc1, s1, MAXCHARLEN) < 0) { - mbtowc_reset(); - bad1 = TRUE; - } + if (mbtowc(&wc1, s1, MAXCHARLEN) < 0) { + mbtowc_reset(); + bad1 = TRUE; + } - if (mbtowc(&wc2, s2, MAXCHARLEN) < 0) { - mbtowc_reset(); - bad2 = TRUE; - } + if (mbtowc(&wc2, s2, MAXCHARLEN) < 0) { + mbtowc_reset(); + bad2 = TRUE; + } - if (bad1 || bad2) { - if (*s1 != *s2) - return (unsigned char)*s1 - (unsigned char)*s2; + if (bad1 || bad2) { + if (*s1 != *s2) + return (unsigned char)*s1 - (unsigned char)*s2; - if (bad1 != bad2) - return (bad1 ? 1 : -1); - } else { - int difference = towlower(wc1) - towlower(wc2); + if (bad1 != bad2) + return (bad1 ? 1 : -1); + } else { + int difference = towlower(wc1) - towlower(wc2); - if (difference != 0) - return difference; - } + if (difference != 0) + return difference; + } - s1 += move_mbright(s1, 0); - s2 += move_mbright(s2, 0); - n--; - } + s1 += move_mbright(s1, 0); + s2 += move_mbright(s2, 0); + n--; + } - return (n > 0) ? ((unsigned char)*s1 - (unsigned char)*s2) : 0; - } else + return (n > 0) ? ((unsigned char)*s1 - (unsigned char)*s2) : 0; + } else #endif - return strncasecmp(s1, s2, n); + return strncasecmp(s1, s2, n); } /* This function is equivalent to strcasestr() for multibyte strings. */ char *mbstrcasestr(const char *haystack, const char *needle) { #ifdef ENABLE_UTF8 - if (use_utf8) { - size_t needle_len = mbstrlen(needle); + if (use_utf8) { + size_t needle_len = mbstrlen(needle); - while (*haystack != '\0') { - if (mbstrncasecmp(haystack, needle, needle_len) == 0) - return (char *)haystack; + while (*haystack != '\0') { + if (mbstrncasecmp(haystack, needle, needle_len) == 0) + return (char *)haystack; - haystack += move_mbright(haystack, 0); - } + haystack += move_mbright(haystack, 0); + } - return NULL; - } else + return NULL; + } else #endif - return (char *) strcasestr(haystack, needle); + return (char *) strcasestr(haystack, needle); } /* This function is equivalent to strstr(), except in that it scans the * string in reverse, starting at pointer. */ char *revstrstr(const char *haystack, const char *needle, - const char *pointer) + const char *pointer) { - size_t needle_len = strlen(needle); - size_t tail_len = strlen(pointer); + size_t needle_len = strlen(needle); + size_t tail_len = strlen(pointer); - if (tail_len < needle_len) - pointer += tail_len - needle_len; + if (tail_len < needle_len) + pointer += tail_len - needle_len; - while (pointer >= haystack) { - if (strncmp(pointer, needle, needle_len) == 0) - return (char *)pointer; - pointer--; - } + while (pointer >= haystack) { + if (strncmp(pointer, needle, needle_len) == 0) + return (char *)pointer; + pointer--; + } - return NULL; + return NULL; } /* This function is equivalent to strcasestr(), except in that it scans * the string in reverse, starting at pointer. */ char *revstrcasestr(const char *haystack, const char *needle, - const char *pointer) + const char *pointer) { - size_t needle_len = strlen(needle); - size_t tail_len = strlen(pointer); + size_t needle_len = strlen(needle); + size_t tail_len = strlen(pointer); - if (tail_len < needle_len) - pointer += tail_len - needle_len; + if (tail_len < needle_len) + pointer += tail_len - needle_len; - while (pointer >= haystack) { - if (strncasecmp(pointer, needle, needle_len) == 0) - return (char *)pointer; - pointer--; - } + while (pointer >= haystack) { + if (strncasecmp(pointer, needle, needle_len) == 0) + return (char *)pointer; + pointer--; + } - return NULL; + return NULL; } /* This function is equivalent to strcasestr() for multibyte strings, * except in that it scans the string in reverse, starting at pointer. */ char *mbrevstrcasestr(const char *haystack, const char *needle, - const char *pointer) + const char *pointer) { #ifdef ENABLE_UTF8 - if (use_utf8) { - size_t needle_len = mbstrlen(needle); - size_t tail_len = mbstrlen(pointer); + if (use_utf8) { + size_t needle_len = mbstrlen(needle); + size_t tail_len = mbstrlen(pointer); - if (tail_len < needle_len) - pointer += tail_len - needle_len; + if (tail_len < needle_len) + pointer += tail_len - needle_len; - if (pointer < haystack) - return NULL; + if (pointer < haystack) + return NULL; - while (TRUE) { - if (mbstrncasecmp(pointer, needle, needle_len) == 0) - return (char *)pointer; + while (TRUE) { + if (mbstrncasecmp(pointer, needle, needle_len) == 0) + return (char *)pointer; - if (pointer == haystack) - return NULL; + if (pointer == haystack) + return NULL; - pointer = haystack + move_mbleft(haystack, pointer - haystack); - } - } else + pointer = haystack + move_mbleft(haystack, pointer - haystack); + } + } else #endif - return revstrcasestr(haystack, needle, pointer); + return revstrcasestr(haystack, needle, pointer); } /* This function is equivalent to strlen() for multibyte strings. */ size_t mbstrlen(const char *s) { - return mbstrnlen(s, (size_t)-1); + return mbstrnlen(s, (size_t)-1); } /* This function is equivalent to strnlen() for multibyte strings. */ size_t mbstrnlen(const char *s, size_t maxlen) { #ifdef ENABLE_UTF8 - if (use_utf8) { - size_t n = 0; + if (use_utf8) { + size_t n = 0; - for (; *s != '\0' && maxlen > 0; s += move_mbright(s, 0), - maxlen--, n++) - ; + for (; *s != '\0' && maxlen > 0; s += move_mbright(s, 0), + maxlen--, n++) + ; - return n; - } else + return n; + } else #endif - return strnlen(s, maxlen); + return strnlen(s, maxlen); } #if !defined(NANO_TINY) || defined(ENABLE_JUSTIFY) @@ -584,41 +584,41 @@ size_t mbstrnlen(const char *s, size_t maxlen) char *mbstrchr(const char *s, const char *c) { #ifdef ENABLE_UTF8 - if (use_utf8) { - bool bad_s_mb = FALSE, bad_c_mb = FALSE; - char symbol[MAXCHARLEN]; - const char *q = s; - wchar_t ws, wc; + if (use_utf8) { + bool bad_s_mb = FALSE, bad_c_mb = FALSE; + char symbol[MAXCHARLEN]; + const char *q = s; + wchar_t ws, wc; - if (mbtowc(&wc, c, MAXCHARLEN) < 0) { - mbtowc_reset(); - wc = (unsigned char)*c; - bad_c_mb = TRUE; - } + if (mbtowc(&wc, c, MAXCHARLEN) < 0) { + mbtowc_reset(); + wc = (unsigned char)*c; + bad_c_mb = TRUE; + } - while (*s != '\0') { - int sym_len = parse_mbchar(s, symbol, NULL); + while (*s != '\0') { + int sym_len = parse_mbchar(s, symbol, NULL); - if (mbtowc(&ws, symbol, sym_len) < 0) { - mbtowc_reset(); - ws = (unsigned char)*s; - bad_s_mb = TRUE; - } + if (mbtowc(&ws, symbol, sym_len) < 0) { + mbtowc_reset(); + ws = (unsigned char)*s; + bad_s_mb = TRUE; + } - if (bad_s_mb == bad_c_mb && ws == wc) - break; + if (bad_s_mb == bad_c_mb && ws == wc) + break; - s += sym_len; - q += sym_len; - } + s += sym_len; + q += sym_len; + } - if (*s == '\0') - q = NULL; + if (*s == '\0') + q = NULL; - return (char *)q; - } else + return (char *)q; + } else #endif - return (char *) strchr(s, *c); + return (char *) strchr(s, *c); } #endif /* !NANO_TINY || ENABLE_JUSTIFY */ @@ -627,16 +627,16 @@ char *mbstrchr(const char *s, const char *c) char *mbstrpbrk(const char *s, const char *accept) { #ifdef ENABLE_UTF8 - if (use_utf8) { - for (; *s != '\0'; s += move_mbright(s, 0)) { - if (mbstrchr(accept, s) != NULL) - return (char *)s; - } + if (use_utf8) { + for (; *s != '\0'; s += move_mbright(s, 0)) { + if (mbstrchr(accept, s) != NULL) + return (char *)s; + } - return NULL; - } else + return NULL; + } else #endif - return (char *) strpbrk(s, accept); + return (char *) strpbrk(s, accept); } /* Locate, in the string that starts at head, the first occurrence of any of @@ -644,45 +644,45 @@ char *mbstrpbrk(const char *s, const char *accept) * backwards. */ char *revstrpbrk(const char *head, const char *accept, const char *pointer) { - if (*pointer == '\0') { - if (pointer == head) - return NULL; - pointer--; - } + if (*pointer == '\0') { + if (pointer == head) + return NULL; + pointer--; + } - while (pointer >= head) { - if (strchr(accept, *pointer) != NULL) - return (char *)pointer; - pointer--; - } + while (pointer >= head) { + if (strchr(accept, *pointer) != NULL) + return (char *)pointer; + pointer--; + } - return NULL; + return NULL; } /* The same as the preceding function but then for multibyte strings. */ char *mbrevstrpbrk(const char *head, const char *accept, const char *pointer) { #ifdef ENABLE_UTF8 - if (use_utf8) { - if (*pointer == '\0') { - if (pointer == head) - return NULL; - pointer = head + move_mbleft(head, pointer - head); - } + if (use_utf8) { + if (*pointer == '\0') { + if (pointer == head) + return NULL; + pointer = head + move_mbleft(head, pointer - head); + } - while (TRUE) { - if (mbstrchr(accept, pointer) != NULL) - return (char *)pointer; + while (TRUE) { + if (mbstrchr(accept, pointer) != NULL) + return (char *)pointer; - /* If we've reached the head of the string, we found nothing. */ - if (pointer == head) - return NULL; + /* If we've reached the head of the string, we found nothing. */ + if (pointer == head) + return NULL; - pointer = head + move_mbleft(head, pointer - head); - } - } else + pointer = head + move_mbleft(head, pointer - head); + } + } else #endif - return revstrpbrk(head, accept, pointer); + return revstrpbrk(head, accept, pointer); } #endif /* !NANO_TINY */ @@ -691,12 +691,12 @@ char *mbrevstrpbrk(const char *head, const char *accept, const char *pointer) * and FALSE otherwise. */ bool has_blank_chars(const char *s) { - for (; *s != '\0'; s++) { - if (isblank((unsigned char)*s)) - return TRUE; - } + for (; *s != '\0'; s++) { + if (isblank((unsigned char)*s)) + return TRUE; + } - return FALSE; + return FALSE; } /* Return TRUE if the multibyte string s contains one or more blank @@ -704,20 +704,20 @@ bool has_blank_chars(const char *s) bool has_blank_mbchars(const char *s) { #ifdef ENABLE_UTF8 - if (use_utf8) { - char symbol[MAXCHARLEN]; + if (use_utf8) { + char symbol[MAXCHARLEN]; - for (; *s != '\0'; s += move_mbright(s, 0)) { - parse_mbchar(s, symbol, NULL); + for (; *s != '\0'; s += move_mbright(s, 0)) { + parse_mbchar(s, symbol, NULL); - if (is_blank_mbchar(symbol)) - return TRUE; - } + if (is_blank_mbchar(symbol)) + return TRUE; + } - return FALSE; - } else + return FALSE; + } else #endif - return has_blank_chars(s); + return has_blank_chars(s); } #endif /* ENABLE_NANORC && (!NANO_TINY || ENABLE_JUSTIFY) */ @@ -725,10 +725,10 @@ bool has_blank_mbchars(const char *s) /* Return TRUE if wc is valid Unicode, and FALSE otherwise. */ bool is_valid_unicode(wchar_t wc) { - return ((0 <= wc && wc <= 0xD7FF) || - (0xE000 <= wc && wc <= 0xFDCF) || - (0xFDF0 <= wc && wc <= 0xFFFD) || - (0xFFFF < wc && wc <= 0x10FFFF && (wc & 0xFFFF) <= 0xFFFD)); + return ((0 <= wc && wc <= 0xD7FF) || + (0xE000 <= wc && wc <= 0xFDCF) || + (0xFDF0 <= wc && wc <= 0xFFFD) || + (0xFFFF < wc && wc <= 0x10FFFF && (wc & 0xFFFF) <= 0xFFFD)); } #endif @@ -738,10 +738,10 @@ bool is_valid_unicode(wchar_t wc) bool is_valid_mbstring(const char *s) { #ifdef ENABLE_UTF8 - if (use_utf8) - return (mbstowcs(NULL, s, 0) != (size_t)-1); - else + if (use_utf8) + return (mbstowcs(NULL, s, 0) != (size_t)-1); + else #endif - return TRUE; + return TRUE; } #endif /* ENABLE_NANORC */ diff --git a/src/color.c b/src/color.c index 0ecde591..a3a0a3fe 100644 --- a/src/color.c +++ b/src/color.c @@ -33,7 +33,7 @@ /* For early versions of ncurses-6.0, use an additional A_PROTECT attribute * for all colors, in order to work around an ncurses miscoloring bug. */ #if defined(NCURSES_VERSION_MAJOR) && (NCURSES_VERSION_MAJOR == 6) && \ - (NCURSES_VERSION_MINOR == 0) && (NCURSES_VERSION_PATCH < 20151017) + (NCURSES_VERSION_MINOR == 0) && (NCURSES_VERSION_PATCH < 20151017) #define A_BANDAID A_PROTECT #else #define A_BANDAID A_NORMAL @@ -43,394 +43,394 @@ * for the colors in each syntax. */ void set_colorpairs(void) { - const syntaxtype *sint; - bool using_defaults = FALSE; - short foreground, background; - size_t i; + const syntaxtype *sint; + bool using_defaults = FALSE; + short foreground, background; + size_t i; - /* Tell ncurses to enable colors. */ - start_color(); + /* Tell ncurses to enable colors. */ + start_color(); #ifdef HAVE_USE_DEFAULT_COLORS - /* Allow using the default colors, if available. */ - using_defaults = (use_default_colors() != ERR); + /* Allow using the default colors, if available. */ + using_defaults = (use_default_colors() != ERR); #endif - /* Initialize the color pairs for nano's interface elements. */ - for (i = 0; i < NUMBER_OF_ELEMENTS; i++) { - bool bright = FALSE; + /* Initialize the color pairs for nano's interface elements. */ + for (i = 0; i < NUMBER_OF_ELEMENTS; i++) { + bool bright = FALSE; - if (specified_color_combo[i] != NULL && - parse_color_names(specified_color_combo[i], - &foreground, &background, &bright)) { - if (foreground == -1 && !using_defaults) - foreground = COLOR_WHITE; - if (background == -1 && !using_defaults) - background = COLOR_BLACK; - init_pair(i + 1, foreground, background); - interface_color_pair[i] = COLOR_PAIR(i + 1) | A_BANDAID | - (bright ? A_BOLD : A_NORMAL); - } else { - if (i != FUNCTION_TAG) - interface_color_pair[i] = hilite_attribute; - else - interface_color_pair[i] = A_NORMAL; + if (specified_color_combo[i] != NULL && + parse_color_names(specified_color_combo[i], + &foreground, &background, &bright)) { + if (foreground == -1 && !using_defaults) + foreground = COLOR_WHITE; + if (background == -1 && !using_defaults) + background = COLOR_BLACK; + init_pair(i + 1, foreground, background); + interface_color_pair[i] = COLOR_PAIR(i + 1) | A_BANDAID | + (bright ? A_BOLD : A_NORMAL); + } else { + if (i != FUNCTION_TAG) + interface_color_pair[i] = hilite_attribute; + else + interface_color_pair[i] = A_NORMAL; + } + + free(specified_color_combo[i]); + specified_color_combo[i] = NULL; } - free(specified_color_combo[i]); - specified_color_combo[i] = NULL; - } + /* For each syntax, go through its list of colors and assign each + * its pair number, giving identical color pairs the same number. */ + for (sint = syntaxes; sint != NULL; sint = sint->next) { + colortype *ink; + int new_number = NUMBER_OF_ELEMENTS + 1; - /* For each syntax, go through its list of colors and assign each - * its pair number, giving identical color pairs the same number. */ - for (sint = syntaxes; sint != NULL; sint = sint->next) { - colortype *ink; - int new_number = NUMBER_OF_ELEMENTS + 1; + for (ink = sint->color; ink != NULL; ink = ink->next) { + const colortype *beforenow = sint->color; - for (ink = sint->color; ink != NULL; ink = ink->next) { - const colortype *beforenow = sint->color; + while (beforenow != ink && (beforenow->fg != ink->fg || + beforenow->bg != ink->bg || + beforenow->bright != ink->bright)) + beforenow = beforenow->next; - while (beforenow != ink && (beforenow->fg != ink->fg || - beforenow->bg != ink->bg || - beforenow->bright != ink->bright)) - beforenow = beforenow->next; + if (beforenow != ink) + ink->pairnum = beforenow->pairnum; + else + ink->pairnum = new_number++; - if (beforenow != ink) - ink->pairnum = beforenow->pairnum; - else - ink->pairnum = new_number++; - - ink->attributes = COLOR_PAIR(ink->pairnum) | A_BANDAID | - (ink->bright ? A_BOLD : A_NORMAL); + ink->attributes = COLOR_PAIR(ink->pairnum) | A_BANDAID | + (ink->bright ? A_BOLD : A_NORMAL); + } } - } } /* Initialize the color information. */ void color_init(void) { - const colortype *ink; - bool using_defaults = FALSE; - short foreground, background; + const colortype *ink; + bool using_defaults = FALSE; + short foreground, background; - /* If the terminal is not capable of colors, forget it. */ - if (!has_colors()) - return; + /* If the terminal is not capable of colors, forget it. */ + if (!has_colors()) + return; #ifdef HAVE_USE_DEFAULT_COLORS - /* Allow using the default colors, if available. */ - using_defaults = (use_default_colors() != ERR); + /* Allow using the default colors, if available. */ + using_defaults = (use_default_colors() != ERR); #endif - /* For each coloring expression, initialize the color pair. */ - for (ink = openfile->colorstrings; ink != NULL; ink = ink->next) { - foreground = ink->fg; - background = ink->bg; + /* For each coloring expression, initialize the color pair. */ + for (ink = openfile->colorstrings; ink != NULL; ink = ink->next) { + foreground = ink->fg; + background = ink->bg; - if (foreground == -1 && !using_defaults) - foreground = COLOR_WHITE; + if (foreground == -1 && !using_defaults) + foreground = COLOR_WHITE; - if (background == -1 && !using_defaults) - background = COLOR_BLACK; + if (background == -1 && !using_defaults) + background = COLOR_BLACK; - init_pair(ink->pairnum, foreground, background); - } + init_pair(ink->pairnum, foreground, background); + } - have_palette = TRUE; + have_palette = TRUE; } /* Try to match the given shibboleth string with one of the regexes in * the list starting at head. Return TRUE upon success. */ bool found_in_list(regexlisttype *head, const char *shibboleth) { - regexlisttype *item; - regex_t rgx; + regexlisttype *item; + regex_t rgx; - for (item = head; item != NULL; item = item->next) { - regcomp(&rgx, fixbounds(item->full_regex), NANO_REG_EXTENDED); + for (item = head; item != NULL; item = item->next) { + regcomp(&rgx, fixbounds(item->full_regex), NANO_REG_EXTENDED); - if (regexec(&rgx, shibboleth, 0, NULL, 0) == 0) { - regfree(&rgx); - return TRUE; + if (regexec(&rgx, shibboleth, 0, NULL, 0) == 0) { + regfree(&rgx); + return TRUE; + } + + regfree(&rgx); } - regfree(&rgx); - } - - return FALSE; + return FALSE; } /* Update the color information based on the current filename and content. */ void color_update(void) { - syntaxtype *sint = NULL; - colortype *ink; + syntaxtype *sint = NULL; + colortype *ink; - /* If the rcfiles were not read, or contained no syntaxes, get out. */ - if (syntaxes == NULL) - return; + /* If the rcfiles were not read, or contained no syntaxes, get out. */ + if (syntaxes == NULL) + return; - /* If we specified a syntax-override string, use it. */ - if (syntaxstr != NULL) { - /* An override of "none" is like having no syntax at all. */ - if (strcmp(syntaxstr, "none") == 0) - return; + /* If we specified a syntax-override string, use it. */ + if (syntaxstr != NULL) { + /* An override of "none" is like having no syntax at all. */ + if (strcmp(syntaxstr, "none") == 0) + return; - for (sint = syntaxes; sint != NULL; sint = sint->next) { - if (strcmp(sint->name, syntaxstr) == 0) - break; + for (sint = syntaxes; sint != NULL; sint = sint->next) { + if (strcmp(sint->name, syntaxstr) == 0) + break; + } + + if (sint == NULL && !inhelp) + statusline(ALERT, _("Unknown syntax name: %s"), syntaxstr); } - if (sint == NULL && !inhelp) - statusline(ALERT, _("Unknown syntax name: %s"), syntaxstr); - } + /* If no syntax-override string was specified, or it didn't match, + * try finding a syntax based on the filename (extension). */ + if (sint == NULL && !inhelp) { + char *reserved = charalloc(PATH_MAX + 1); + char *currentdir = getcwd(reserved, PATH_MAX + 1); + char *joinednames = charalloc(PATH_MAX + 1); + char *fullname = NULL; - /* If no syntax-override string was specified, or it didn't match, - * try finding a syntax based on the filename (extension). */ - if (sint == NULL && !inhelp) { - char *reserved = charalloc(PATH_MAX + 1); - char *currentdir = getcwd(reserved, PATH_MAX + 1); - char *joinednames = charalloc(PATH_MAX + 1); - char *fullname = NULL; + if (currentdir == NULL) + free(reserved); + else { + /* Concatenate the current working directory with the + * specified filename, and canonicalize the result. */ + sprintf(joinednames, "%s/%s", currentdir, openfile->filename); + fullname = get_full_path(joinednames); + free(currentdir); + } - if (currentdir == NULL) - free(reserved); - else { - /* Concatenate the current working directory with the - * specified filename, and canonicalize the result. */ - sprintf(joinednames, "%s/%s", currentdir, openfile->filename); - fullname = get_full_path(joinednames); - free(currentdir); + if (fullname == NULL) + fullname = mallocstrcpy(fullname, openfile->filename); + + for (sint = syntaxes; sint != NULL; sint = sint->next) { + if (found_in_list(sint->extensions, fullname)) + break; + } + + free(joinednames); + free(fullname); } - if (fullname == NULL) - fullname = mallocstrcpy(fullname, openfile->filename); - - for (sint = syntaxes; sint != NULL; sint = sint->next) { - if (found_in_list(sint->extensions, fullname)) - break; + /* If the filename didn't match anything, try the first line. */ + if (sint == NULL && !inhelp) { + for (sint = syntaxes; sint != NULL; sint = sint->next) { + if (found_in_list(sint->headers, openfile->fileage->data)) + break; + } } - free(joinednames); - free(fullname); - } - - /* If the filename didn't match anything, try the first line. */ - if (sint == NULL && !inhelp) { - for (sint = syntaxes; sint != NULL; sint = sint->next) { - if (found_in_list(sint->headers, openfile->fileage->data)) - break; - } - } - #ifdef HAVE_LIBMAGIC - /* If we still don't have an answer, try using magic. */ - if (sint == NULL && !inhelp) { - struct stat fileinfo; - magic_t cookie = NULL; - const char *magicstring = NULL; + /* If we still don't have an answer, try using magic. */ + if (sint == NULL && !inhelp) { + struct stat fileinfo; + magic_t cookie = NULL; + const char *magicstring = NULL; - if (stat(openfile->filename, &fileinfo) == 0) { - /* Open the magic database and get a diagnosis of the file. */ - cookie = magic_open(MAGIC_SYMLINK | + 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 | + MAGIC_DEBUG | MAGIC_CHECK | #endif - MAGIC_ERROR); - if (cookie == NULL || magic_load(cookie, NULL) < 0) - statusline(ALERT, _("magic_load() failed: %s"), strerror(errno)); - else { - magicstring = magic_file(cookie, openfile->filename); - if (magicstring == NULL) - statusline(ALERT, _("magic_file(%s) failed: %s"), - openfile->filename, magic_error(cookie)); - } - } + MAGIC_ERROR); + if (cookie == NULL || magic_load(cookie, NULL) < 0) + statusline(ALERT, _("magic_load() failed: %s"), strerror(errno)); + else { + magicstring = magic_file(cookie, openfile->filename); + if (magicstring == NULL) + statusline(ALERT, _("magic_file(%s) failed: %s"), + openfile->filename, magic_error(cookie)); + } + } - /* Now try and find a syntax that matches the magic string. */ - if (magicstring != NULL) { - for (sint = syntaxes; sint != NULL; sint = sint->next) { - if (found_in_list(sint->magics, magicstring)) - break; - } - } + /* Now try and find a syntax that matches the magic string. */ + if (magicstring != NULL) { + for (sint = syntaxes; sint != NULL; sint = sint->next) { + if (found_in_list(sint->magics, magicstring)) + break; + } + } - if (stat(openfile->filename, &fileinfo) == 0) - magic_close(cookie); - } + if (stat(openfile->filename, &fileinfo) == 0) + magic_close(cookie); + } #endif /* HAVE_LIBMAGIC */ - /* If nothing at all matched, see if there is a default syntax. */ - if (sint == NULL && !inhelp) { - for (sint = syntaxes; sint != NULL; sint = sint->next) { - if (strcmp(sint->name, "default") == 0) - break; - } - } - - openfile->syntax = sint; - openfile->colorstrings = (sint == NULL ? NULL : sint->color); - - /* If a syntax was found, compile its specified regexes (which have - * already been checked for validity when they were read in). */ - for (ink = openfile->colorstrings; ink != NULL; ink = ink->next) { - if (ink->start == NULL) { - ink->start = (regex_t *)nmalloc(sizeof(regex_t)); - regcomp(ink->start, fixbounds(ink->start_regex), ink->rex_flags); + /* If nothing at all matched, see if there is a default syntax. */ + if (sint == NULL && !inhelp) { + for (sint = syntaxes; sint != NULL; sint = sint->next) { + if (strcmp(sint->name, "default") == 0) + break; + } } - if (ink->end_regex != NULL && ink->end == NULL) { - ink->end = (regex_t *)nmalloc(sizeof(regex_t)); - regcomp(ink->end, fixbounds(ink->end_regex), ink->rex_flags); + openfile->syntax = sint; + openfile->colorstrings = (sint == NULL ? NULL : sint->color); + + /* If a syntax was found, compile its specified regexes (which have + * already been checked for validity when they were read in). */ + for (ink = openfile->colorstrings; ink != NULL; ink = ink->next) { + if (ink->start == NULL) { + ink->start = (regex_t *)nmalloc(sizeof(regex_t)); + regcomp(ink->start, fixbounds(ink->start_regex), ink->rex_flags); + } + + if (ink->end_regex != NULL && ink->end == NULL) { + ink->end = (regex_t *)nmalloc(sizeof(regex_t)); + regcomp(ink->end, fixbounds(ink->end_regex), ink->rex_flags); + } } - } } /* Determine whether the matches of multiline regexes are still the same, * and if not, schedule a screen refresh, so things will be repainted. */ void check_the_multis(filestruct *line) { - const colortype *ink; - bool astart, anend; - regmatch_t startmatch, endmatch; + const colortype *ink; + bool astart, anend; + regmatch_t startmatch, endmatch; - /* If there is no syntax or no multiline regex, there is nothing to do. */ - if (openfile->syntax == NULL || openfile->syntax->nmultis == 0) - return; + /* If there is no syntax or no multiline regex, there is nothing to do. */ + if (openfile->syntax == NULL || openfile->syntax->nmultis == 0) + return; - for (ink = openfile->colorstrings; ink != NULL; ink = ink->next) { - /* If it's not a multiline regex, skip. */ - if (ink->end == NULL) - continue; + for (ink = openfile->colorstrings; ink != NULL; ink = ink->next) { + /* If it's not a multiline regex, skip. */ + if (ink->end == NULL) + continue; - alloc_multidata_if_needed(line); + alloc_multidata_if_needed(line); - astart = (regexec(ink->start, line->data, 1, &startmatch, 0) == 0); - anend = (regexec(ink->end, line->data, 1, &endmatch, 0) == 0); + astart = (regexec(ink->start, line->data, 1, &startmatch, 0) == 0); + anend = (regexec(ink->end, line->data, 1, &endmatch, 0) == 0); - /* Check whether the multidata still matches the current situation. */ - if (line->multidata[ink->id] == CNONE || - line->multidata[ink->id] == CWHOLELINE) { - if (!astart && !anend) - continue; - } else if (line->multidata[ink->id] == CSTARTENDHERE) { - if (astart && anend && startmatch.rm_so < endmatch.rm_so) - continue; - } else if (line->multidata[ink->id] == CBEGINBEFORE) { - if (!astart && anend) - continue; - } else if (line->multidata[ink->id] == CENDAFTER) { - if (astart && !anend) - continue; + /* Check whether the multidata still matches the current situation. */ + if (line->multidata[ink->id] == CNONE || + line->multidata[ink->id] == CWHOLELINE) { + if (!astart && !anend) + continue; + } else if (line->multidata[ink->id] == CSTARTENDHERE) { + if (astart && anend && startmatch.rm_so < endmatch.rm_so) + continue; + } else if (line->multidata[ink->id] == CBEGINBEFORE) { + if (!astart && anend) + continue; + } else if (line->multidata[ink->id] == CENDAFTER) { + if (astart && !anend) + continue; + } + + /* There is a mismatch, so something changed: repaint. */ + refresh_needed = TRUE; + return; } - - /* There is a mismatch, so something changed: repaint. */ - refresh_needed = TRUE; - return; - } } /* Allocate (for one line) the cache space for multiline color regexes. */ void alloc_multidata_if_needed(filestruct *fileptr) { - int i; + int i; - if (fileptr->multidata == NULL) { - fileptr->multidata = (short *)nmalloc(openfile->syntax->nmultis * sizeof(short)); + if (fileptr->multidata == NULL) { + fileptr->multidata = (short *)nmalloc(openfile->syntax->nmultis * sizeof(short)); - for (i = 0; i < openfile->syntax->nmultis; i++) - fileptr->multidata[i] = -1; - } + for (i = 0; i < openfile->syntax->nmultis; i++) + fileptr->multidata[i] = -1; + } } /* Precalculate the multi-line start and end regex info so we can * speed up rendering (with any hope at all...). */ void precalc_multicolorinfo(void) { - const colortype *ink; - regmatch_t startmatch, endmatch; - filestruct *line, *tailline; + const colortype *ink; + regmatch_t startmatch, endmatch; + filestruct *line, *tailline; - if (openfile->colorstrings == NULL || ISSET(NO_COLOR_SYNTAX)) - return; + if (openfile->colorstrings == NULL || ISSET(NO_COLOR_SYNTAX)) + return; #ifdef DEBUG - fprintf(stderr, "Precalculating the multiline color info...\n"); + fprintf(stderr, "Precalculating the multiline color info...\n"); #endif - for (ink = openfile->colorstrings; ink != NULL; ink = ink->next) { - /* If this is not a multi-line regex, skip it. */ - if (ink->end == NULL) - continue; + for (ink = openfile->colorstrings; ink != NULL; ink = ink->next) { + /* If this is not a multi-line regex, skip it. */ + if (ink->end == NULL) + continue; - for (line = openfile->fileage; line != NULL; line = line->next) { - int index = 0; + for (line = openfile->fileage; line != NULL; line = line->next) { + int index = 0; - alloc_multidata_if_needed(line); - /* Assume nothing applies until proven otherwise below. */ - line->multidata[ink->id] = CNONE; + alloc_multidata_if_needed(line); + /* Assume nothing applies until proven otherwise below. */ + line->multidata[ink->id] = CNONE; - /* For an unpaired start match, mark all remaining lines. */ - if (line->prev && line->prev->multidata[ink->id] == CWOULDBE) { - line->multidata[ink->id] = CWOULDBE; - continue; - } + /* For an unpaired start match, mark all remaining lines. */ + if (line->prev && line->prev->multidata[ink->id] == CWOULDBE) { + line->multidata[ink->id] = CWOULDBE; + continue; + } - /* When the line contains a start match, look for an end, and if - * found, mark all the lines that are affected. */ - while (regexec(ink->start, line->data + index, 1, - &startmatch, (index == 0) ? 0 : REG_NOTBOL) == 0) { - /* Begin looking for an end match after the start match. */ - index += startmatch.rm_eo; + /* When the line contains a start match, look for an end, and if + * found, mark all the lines that are affected. */ + while (regexec(ink->start, line->data + index, 1, + &startmatch, (index == 0) ? 0 : REG_NOTBOL) == 0) { + /* Begin looking for an end match after the start match. */ + index += startmatch.rm_eo; - /* If there is an end match on this line, mark the line, but - * continue looking for other starts after it. */ - if (regexec(ink->end, line->data + index, 1, - &endmatch, (index == 0) ? 0 : REG_NOTBOL) == 0) { - line->multidata[ink->id] = CSTARTENDHERE; - index += endmatch.rm_eo; - /* If both start and end are mere anchors, step ahead. */ - if (startmatch.rm_so == startmatch.rm_eo && - endmatch.rm_so == endmatch.rm_eo) { - /* When at end-of-line, we're done. */ - if (line->data[index] == '\0') - break; - index = move_mbright(line->data, index); - } - continue; + /* If there is an end match on this line, mark the line, but + * continue looking for other starts after it. */ + if (regexec(ink->end, line->data + index, 1, + &endmatch, (index == 0) ? 0 : REG_NOTBOL) == 0) { + line->multidata[ink->id] = CSTARTENDHERE; + index += endmatch.rm_eo; + /* If both start and end are mere anchors, step ahead. */ + if (startmatch.rm_so == startmatch.rm_eo && + endmatch.rm_so == endmatch.rm_eo) { + /* When at end-of-line, we're done. */ + if (line->data[index] == '\0') + break; + index = move_mbright(line->data, index); + } + continue; + } + + /* Look for an end match on later lines. */ + tailline = line->next; + + while (tailline != NULL) { + if (regexec(ink->end, tailline->data, 1, &endmatch, 0) == 0) + break; + tailline = tailline->next; + } + + if (tailline == NULL) { + line->multidata[ink->id] = CWOULDBE; + break; + } + + /* We found it, we found it, la la la la la. Mark all + * the lines in between and the end properly. */ + line->multidata[ink->id] = CENDAFTER; + + for (line = line->next; line != tailline; line = line->next) { + alloc_multidata_if_needed(line); + line->multidata[ink->id] = CWHOLELINE; + } + + alloc_multidata_if_needed(tailline); + tailline->multidata[ink->id] = CBEGINBEFORE; + + /* Begin looking for a new start after the end match. */ + index = endmatch.rm_eo; + } } - - /* Look for an end match on later lines. */ - tailline = line->next; - - while (tailline != NULL) { - if (regexec(ink->end, tailline->data, 1, &endmatch, 0) == 0) - break; - tailline = tailline->next; - } - - if (tailline == NULL) { - line->multidata[ink->id] = CWOULDBE; - break; - } - - /* We found it, we found it, la la la la la. Mark all - * the lines in between and the end properly. */ - line->multidata[ink->id] = CENDAFTER; - - for (line = line->next; line != tailline; line = line->next) { - alloc_multidata_if_needed(line); - line->multidata[ink->id] = CWHOLELINE; - } - - alloc_multidata_if_needed(tailline); - tailline->multidata[ink->id] = CBEGINBEFORE; - - /* Begin looking for a new start after the end match. */ - index = endmatch.rm_eo; - } } - } } #endif /* ENABLE_COLOR */ diff --git a/src/cut.c b/src/cut.c index bf55787f..adf31e0c 100644 --- a/src/cut.c +++ b/src/cut.c @@ -25,18 +25,18 @@ #include static bool keep_cutbuffer = FALSE; - /* Should we keep the contents of the cutbuffer? */ + /* Should we keep the contents of the cutbuffer? */ /* Indicate that we should no longer keep the contents of the cutbuffer. */ void cutbuffer_reset(void) { - keep_cutbuffer = FALSE; + keep_cutbuffer = FALSE; } /* Return the status of cutbuffer preservation. */ inline bool keeping_cutbuffer(void) { - return keep_cutbuffer; + return keep_cutbuffer; } /* If we aren't on the last line of the file, move all the text of the @@ -46,13 +46,13 @@ inline bool keeping_cutbuffer(void) * current line. */ void cut_line(void) { - if (openfile->current != openfile->filebot) - extract_buffer(&cutbuffer, &cutbottom, openfile->current, 0, - openfile->current->next, 0); - else - extract_buffer(&cutbuffer, &cutbottom, openfile->current, 0, - openfile->current, strlen(openfile->current->data)); - openfile->placewewant = 0; + if (openfile->current != openfile->filebot) + extract_buffer(&cutbuffer, &cutbottom, openfile->current, 0, + openfile->current->next, 0); + else + extract_buffer(&cutbuffer, &cutbottom, openfile->current, 0, + openfile->current, strlen(openfile->current->data)); + openfile->placewewant = 0; } #ifndef NANO_TINY @@ -60,14 +60,14 @@ void cut_line(void) * current place we want to where the text used to start. */ void cut_marked(bool *right_side_up) { - filestruct *top, *bot; - size_t top_x, bot_x; + filestruct *top, *bot; + size_t top_x, bot_x; - mark_order((const filestruct **)&top, &top_x, - (const filestruct **)&bot, &bot_x, right_side_up); + mark_order((const filestruct **)&top, &top_x, + (const filestruct **)&bot, &bot_x, right_side_up); - extract_buffer(&cutbuffer, &cutbottom, top, top_x, bot, bot_x); - openfile->placewewant = xplustabs(); + extract_buffer(&cutbuffer, &cutbottom, top, top_x, bot, bot_x); + openfile->placewewant = xplustabs(); } /* If we aren't at the end of the current line, move all the text from @@ -78,32 +78,32 @@ void cut_marked(bool *right_side_up) * newline used to be. */ void cut_to_eol(void) { - size_t data_len = strlen(openfile->current->data); + size_t data_len = strlen(openfile->current->data); - if (openfile->current_x < data_len) - /* If we're not at the end of the line, move all the text from - * the current position up to it, not counting the newline at - * the end, into the cutbuffer. */ - extract_buffer(&cutbuffer, &cutbottom, openfile->current, - openfile->current_x, openfile->current, data_len); - else if (openfile->current != openfile->filebot) { - /* If we're at the end of the line, and it isn't the last line - * of the file, move all the text from the current position up - * to the beginning of the next line, i.e. the newline at the - * end, into the cutbuffer. */ - extract_buffer(&cutbuffer, &cutbottom, openfile->current, - openfile->current_x, openfile->current->next, 0); - openfile->placewewant = xplustabs(); - } + if (openfile->current_x < data_len) + /* If we're not at the end of the line, move all the text from + * the current position up to it, not counting the newline at + * the end, into the cutbuffer. */ + extract_buffer(&cutbuffer, &cutbottom, openfile->current, + openfile->current_x, openfile->current, data_len); + else if (openfile->current != openfile->filebot) { + /* If we're at the end of the line, and it isn't the last line + * of the file, move all the text from the current position up + * to the beginning of the next line, i.e. the newline at the + * end, into the cutbuffer. */ + extract_buffer(&cutbuffer, &cutbottom, openfile->current, + openfile->current_x, openfile->current->next, 0); + openfile->placewewant = xplustabs(); + } } /* Move all the text from the current cursor position to the end of the * file into the cutbuffer. */ void cut_to_eof(void) { - extract_buffer(&cutbuffer, &cutbottom, - openfile->current, openfile->current_x, - openfile->filebot, strlen(openfile->filebot->data)); + extract_buffer(&cutbuffer, &cutbottom, + openfile->current, openfile->current_x, + openfile->filebot, strlen(openfile->filebot->data)); } #endif /* !NANO_TINY */ @@ -114,86 +114,86 @@ void cut_to_eof(void) void do_cut_text(bool copy_text, bool cut_till_eof) { #ifndef NANO_TINY - filestruct *cb_save = NULL; - /* The current end of the cutbuffer, before we add text to 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. */ - bool old_no_newlines = ISSET(NO_NEWLINES); - bool right_side_up = TRUE; - /* There *is* no region, *or* it is marked forward. */ + filestruct *cb_save = NULL; + /* The current end of the cutbuffer, before we add text to 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. */ + bool old_no_newlines = ISSET(NO_NEWLINES); + bool right_side_up = TRUE; + /* There *is* no region, *or* it is marked forward. */ #endif - size_t was_totsize = openfile->totsize; + size_t was_totsize = openfile->totsize; - /* If a chain of cuts was broken, empty the cutbuffer. */ - if (!keep_cutbuffer) { - free_filestruct(cutbuffer); - cutbuffer = NULL; - /* Indicate that future cuts should add to the cutbuffer. */ - keep_cutbuffer = TRUE; - } + /* If a chain of cuts was broken, empty the cutbuffer. */ + if (!keep_cutbuffer) { + free_filestruct(cutbuffer); + cutbuffer = NULL; + /* Indicate that future cuts should add to the cutbuffer. */ + keep_cutbuffer = TRUE; + } #ifndef NANO_TINY - if (copy_text) { - /* If the cutbuffer isn't empty, remember where it currently ends. */ - if (cutbuffer != NULL) { - cb_save = cutbottom; - cb_save_len = strlen(cutbottom->data); + if (copy_text) { + /* If the cutbuffer isn't empty, remember where it currently ends. */ + if (cutbuffer != NULL) { + cb_save = cutbottom; + cb_save_len = strlen(cutbottom->data); + } + /* Don't add a magicline when moving text to the cutbuffer. */ + SET(NO_NEWLINES); } - /* Don't add a magicline when moving text to the cutbuffer. */ - SET(NO_NEWLINES); - } - if (cut_till_eof) { - /* Move all text up to the end of the file into the cutbuffer. */ - cut_to_eof(); - } else if (openfile->mark) { - /* Move the marked text to the cutbuffer, and turn the mark off. */ - cut_marked(&right_side_up); - openfile->mark = NULL; - } else if (ISSET(CUT_FROM_CURSOR)) - /* Move all text up to the end of the line into the cutbuffer. */ - cut_to_eol(); - else + if (cut_till_eof) { + /* Move all text up to the end of the file into the cutbuffer. */ + cut_to_eof(); + } else if (openfile->mark) { + /* Move the marked text to the cutbuffer, and turn the mark off. */ + cut_marked(&right_side_up); + openfile->mark = NULL; + } else if (ISSET(CUT_FROM_CURSOR)) + /* Move all text up to the end of the line into the cutbuffer. */ + cut_to_eol(); + else #endif - /* Move the entire line into the cutbuffer. */ - cut_line(); + /* Move the entire line into the cutbuffer. */ + cut_line(); #ifndef NANO_TINY - if (copy_text) { - /* Copy the text that is in the cutbuffer (starting at its saved end, - * if there is one) back into the current buffer. This effectively - * uncuts the text we just cut. */ - if (cutbuffer != NULL) { - if (cb_save != NULL) { - cb_save->data += cb_save_len; - copy_from_buffer(cb_save); - cb_save->data -= cb_save_len; - } else - copy_from_buffer(cutbuffer); + if (copy_text) { + /* Copy the text that is in the cutbuffer (starting at its saved end, + * if there is one) back into the current buffer. This effectively + * uncuts the text we just cut. */ + if (cutbuffer != NULL) { + if (cb_save != NULL) { + cb_save->data += cb_save_len; + copy_from_buffer(cb_save); + cb_save->data -= cb_save_len; + } else + copy_from_buffer(cutbuffer); - /* If the copied region was marked forward, put the new desired - * x position at its end; otherwise, leave it at its beginning. */ - if (right_side_up) - openfile->placewewant = xplustabs(); - } - /* Restore the magicline behavior now that we're done fiddling. */ - if (!old_no_newlines) - UNSET(NO_NEWLINES); - } else + /* If the copied region was marked forward, put the new desired + * x position at its end; otherwise, leave it at its beginning. */ + if (right_side_up) + openfile->placewewant = xplustabs(); + } + /* Restore the magicline behavior now that we're done fiddling. */ + if (!old_no_newlines) + UNSET(NO_NEWLINES); + } else #endif /* !NANO_TINY */ - /* Only set the modification flag if actually something was cut. */ - if (openfile->totsize != was_totsize) - set_modified(); + /* Only set the modification flag if actually something was cut. */ + if (openfile->totsize != was_totsize) + set_modified(); - refresh_needed = TRUE; + refresh_needed = TRUE; #ifdef ENABLE_COLOR - check_the_multis(openfile->current); + check_the_multis(openfile->current); #endif #ifdef DEBUG - dump_filestruct(cutbuffer); + dump_filestruct(cutbuffer); #endif } @@ -201,11 +201,11 @@ void do_cut_text(bool copy_text, bool cut_till_eof) void do_cut_text_void(void) { #ifndef NANO_TINY - add_undo(CUT); + add_undo(CUT); #endif - do_cut_text(FALSE, FALSE); + do_cut_text(FALSE, FALSE); #ifndef NANO_TINY - update_undo(CUT); + update_undo(CUT); #endif } @@ -215,79 +215,79 @@ void do_cut_text_void(void) * was moved, blow away previous contents of the cutbuffer. */ void do_copy_text(void) { - static struct filestruct *next_contiguous_line = NULL; - bool mark_is_set = (openfile->mark != NULL); + static struct filestruct *next_contiguous_line = NULL; + bool mark_is_set = (openfile->mark != NULL); - /* Remember the current viewport and cursor position. */ - ssize_t is_edittop_lineno = openfile->edittop->lineno; - size_t is_firstcolumn = openfile->firstcolumn; - ssize_t is_current_lineno = openfile->current->lineno; - size_t is_current_x = openfile->current_x; + /* Remember the current viewport and cursor position. */ + ssize_t is_edittop_lineno = openfile->edittop->lineno; + size_t is_firstcolumn = openfile->firstcolumn; + ssize_t is_current_lineno = openfile->current->lineno; + size_t is_current_x = openfile->current_x; - if (mark_is_set || openfile->current != next_contiguous_line) - cutbuffer_reset(); + if (mark_is_set || openfile->current != next_contiguous_line) + cutbuffer_reset(); - do_cut_text(TRUE, FALSE); + do_cut_text(TRUE, FALSE); - /* If the mark was set, blow away the cutbuffer on the next copy. */ - next_contiguous_line = (mark_is_set ? NULL : openfile->current); + /* If the mark was set, blow away the cutbuffer on the next copy. */ + next_contiguous_line = (mark_is_set ? NULL : openfile->current); - /* If the mark was set, restore the viewport and cursor position. */ - if (mark_is_set) { - openfile->edittop = fsfromline(is_edittop_lineno); - openfile->firstcolumn = is_firstcolumn; - openfile->current = fsfromline(is_current_lineno); - openfile->current_x = is_current_x; - } + /* If the mark was set, restore the viewport and cursor position. */ + if (mark_is_set) { + openfile->edittop = fsfromline(is_edittop_lineno); + openfile->firstcolumn = is_firstcolumn; + openfile->current = fsfromline(is_current_lineno); + openfile->current_x = is_current_x; + } } /* Cut from the current cursor position to the end of the file. */ void do_cut_till_eof(void) { - add_undo(CUT_TO_EOF); - do_cut_text(FALSE, TRUE); - update_undo(CUT_TO_EOF); + add_undo(CUT_TO_EOF); + do_cut_text(FALSE, TRUE); + update_undo(CUT_TO_EOF); } #endif /* !NANO_TINY */ /* Copy text from the cutbuffer into the current buffer. */ void do_uncut_text(void) { - ssize_t was_lineno = openfile->current->lineno; - /* The line number where we started the paste. */ - size_t was_leftedge = 0; - /* The leftedge where we started the paste. */ + ssize_t was_lineno = openfile->current->lineno; + /* The line number where we started the paste. */ + size_t was_leftedge = 0; + /* The leftedge where we started the paste. */ - /* If the cutbuffer is empty, there is nothing to do. */ - if (cutbuffer == NULL) - return; + /* If the cutbuffer is empty, there is nothing to do. */ + if (cutbuffer == NULL) + return; #ifndef NANO_TINY - add_undo(PASTE); + add_undo(PASTE); - if (ISSET(SOFTWRAP)) - was_leftedge = leftedge_for(xplustabs(), openfile->current); + if (ISSET(SOFTWRAP)) + was_leftedge = leftedge_for(xplustabs(), openfile->current); #endif - /* Add a copy of the text in the cutbuffer to the current buffer - * at the current cursor position. */ - copy_from_buffer(cutbuffer); + /* Add a copy of the text in the cutbuffer to the current buffer + * at the current cursor position. */ + copy_from_buffer(cutbuffer); #ifndef NANO_TINY - update_undo(PASTE); + update_undo(PASTE); #endif - /* If we pasted less than a screenful, don't center the cursor. */ - if (less_than_a_screenful(was_lineno, was_leftedge)) - focusing = FALSE; + /* If we pasted less than a screenful, don't center the cursor. */ + if (less_than_a_screenful(was_lineno, was_leftedge)) + focusing = FALSE; - /* Set the desired x position to where the pasted text ends. */ - openfile->placewewant = xplustabs(); + /* Set the desired x position to where the pasted text ends. */ + openfile->placewewant = xplustabs(); - set_modified(); - refresh_needed = TRUE; + set_modified(); + refresh_needed = TRUE; #ifdef ENABLE_COLOR - check_the_multis(openfile->current); + check_the_multis(openfile->current); #endif } diff --git a/src/files.c b/src/files.c index c6d00a34..9439a663 100644 --- a/src/files.c +++ b/src/files.c @@ -35,117 +35,117 @@ /* Verify that the containing directory of the given filename exists. */ bool has_valid_path(const char *filename) { - char *namecopy = mallocstrcpy(NULL, filename); - char *parentdir = dirname(namecopy); - struct stat parentinfo; - bool validity = FALSE; + char *namecopy = mallocstrcpy(NULL, filename); + char *parentdir = dirname(namecopy); + struct stat parentinfo; + bool validity = FALSE; - if (stat(parentdir, &parentinfo) == -1) { - if (errno == ENOENT) - statusline(ALERT, _("Directory '%s' does not exist"), parentdir); + if (stat(parentdir, &parentinfo) == -1) { + if (errno == ENOENT) + statusline(ALERT, _("Directory '%s' does not exist"), parentdir); + else + statusline(ALERT, _("Path '%s': %s"), parentdir, strerror(errno)); + } else if (!S_ISDIR(parentinfo.st_mode)) + statusline(ALERT, _("Path '%s' is not a directory"), parentdir); + else if (access(parentdir, X_OK) == -1) + statusline(ALERT, _("Path '%s' is not accessible"), parentdir); + else if (ISSET(LOCKING) && access(parentdir, W_OK) == -1) + statusline(MILD, _("Directory '%s' is not writable"), parentdir); else - statusline(ALERT, _("Path '%s': %s"), parentdir, strerror(errno)); - } else if (!S_ISDIR(parentinfo.st_mode)) - statusline(ALERT, _("Path '%s' is not a directory"), parentdir); - else if (access(parentdir, X_OK) == -1) - statusline(ALERT, _("Path '%s' is not accessible"), parentdir); - else if (ISSET(LOCKING) && access(parentdir, W_OK) == -1) - statusline(MILD, _("Directory '%s' is not writable"), parentdir); - else - validity = TRUE; + validity = TRUE; - free(namecopy); + free(namecopy); - return validity; + return validity; } /* Add an item to the circular list of openfile structs. */ void make_new_buffer(void) { - openfilestruct *newnode = make_new_opennode(); + openfilestruct *newnode = make_new_opennode(); - if (openfile == NULL) { - /* Make the first open file the only element in the list. */ - newnode->prev = newnode; - newnode->next = newnode; - firstfile = newnode; - } else { - /* Add the new open file after the current one in the list. */ - newnode->prev = openfile; - newnode->next = openfile->next; - openfile->next->prev = newnode; - openfile->next = newnode; + if (openfile == NULL) { + /* Make the first open file the only element in the list. */ + newnode->prev = newnode; + newnode->next = newnode; + firstfile = newnode; + } else { + /* Add the new open file after the current one in the list. */ + newnode->prev = openfile; + newnode->next = openfile->next; + openfile->next->prev = newnode; + openfile->next = newnode; - /* There is more than one file open: show "Close" in help lines. */ - exitfunc->desc = close_tag; - more_than_one = !inhelp || more_than_one; - } + /* There is more than one file open: show "Close" in help lines. */ + exitfunc->desc = close_tag; + more_than_one = !inhelp || more_than_one; + } - /* Make the new buffer the current one, and start initializing it. */ - openfile = newnode; + /* Make the new buffer the current one, and start initializing it. */ + openfile = newnode; - openfile->filename = mallocstrcpy(NULL, ""); + openfile->filename = mallocstrcpy(NULL, ""); - initialize_buffer_text(); + initialize_buffer_text(); - openfile->placewewant = 0; - openfile->current_y = 0; + openfile->placewewant = 0; + openfile->current_y = 0; - openfile->modified = FALSE; + openfile->modified = FALSE; #ifndef NANO_TINY - openfile->mark = NULL; + openfile->mark = NULL; - openfile->fmt = NIX_FILE; + openfile->fmt = NIX_FILE; - openfile->undotop = NULL; - openfile->current_undo = NULL; - openfile->last_saved = NULL; - openfile->last_action = OTHER; + openfile->undotop = NULL; + openfile->current_undo = NULL; + openfile->last_saved = NULL; + openfile->last_action = OTHER; - openfile->current_stat = NULL; - openfile->lock_filename = NULL; + openfile->current_stat = NULL; + openfile->lock_filename = NULL; #endif #ifdef ENABLE_COLOR - openfile->syntax = NULL; - openfile->colorstrings = NULL; + openfile->syntax = NULL; + openfile->colorstrings = NULL; #endif } /* Initialize the text and pointers of the current openfile struct. */ void initialize_buffer_text(void) { - openfile->fileage = make_new_node(NULL); - openfile->fileage->data = mallocstrcpy(NULL, ""); + openfile->fileage = make_new_node(NULL); + openfile->fileage->data = mallocstrcpy(NULL, ""); - openfile->filebot = openfile->fileage; - openfile->edittop = openfile->fileage; - openfile->current = openfile->fileage; + openfile->filebot = openfile->fileage; + openfile->edittop = openfile->fileage; + openfile->current = openfile->fileage; - openfile->firstcolumn = 0; - openfile->current_x = 0; - openfile->totsize = 0; + openfile->firstcolumn = 0; + openfile->current_x = 0; + openfile->totsize = 0; } /* Mark the current file as modified if it isn't already, and then * update the titlebar to display the file's new status. */ void set_modified(void) { - if (openfile->modified) - return; + if (openfile->modified) + return; - openfile->modified = TRUE; - titlebar(NULL); + openfile->modified = TRUE; + titlebar(NULL); #ifndef NANO_TINY - if (!ISSET(LOCKING) || openfile->filename[0] == '\0') - return; + if (!ISSET(LOCKING) || openfile->filename[0] == '\0') + return; - if (openfile->lock_filename != NULL) { - char *fullname = get_full_path(openfile->filename); + if (openfile->lock_filename != NULL) { + char *fullname = get_full_path(openfile->filename); - write_lockfile(openfile->lock_filename, fullname, TRUE); - free(fullname); - } + write_lockfile(openfile->lock_filename, fullname, TRUE); + free(fullname); + } #endif } @@ -163,133 +163,133 @@ void set_modified(void) int write_lockfile(const char *lockfilename, const char *origfilename, bool modified) { #ifdef HAVE_PWD_H - int cflags, fd; - FILE *filestream; - pid_t mypid; - uid_t myuid; - struct passwd *mypwuid; - struct stat fileinfo; - char *lockdata = charalloc(1024); - char myhostname[32]; - size_t lockdatalen = 1024; - size_t wroteamt; + int cflags, fd; + FILE *filestream; + pid_t mypid; + uid_t myuid; + struct passwd *mypwuid; + struct stat fileinfo; + char *lockdata = charalloc(1024); + char myhostname[32]; + size_t lockdatalen = 1024; + size_t wroteamt; - mypid = getpid(); - myuid = geteuid(); + mypid = getpid(); + myuid = geteuid(); - /* First run things that might fail before blowing away the old state. */ - if ((mypwuid = getpwuid(myuid)) == NULL) { - /* TRANSLATORS: Keep the next eight messages at most 76 characters. */ - statusline(MILD, _("Couldn't determine my identity for lock file " - "(getpwuid() failed)")); - goto free_the_data; - } - - if (gethostname(myhostname, 31) < 0) { - if (errno == ENAMETOOLONG) - myhostname[31] = '\0'; - else { - statusline(MILD, _("Couldn't determine hostname for lock file: %s"), - strerror(errno)); - goto free_the_data; + /* First run things that might fail before blowing away the old state. */ + if ((mypwuid = getpwuid(myuid)) == NULL) { + /* TRANSLATORS: Keep the next eight messages at most 76 characters. */ + statusline(MILD, _("Couldn't determine my identity for lock file " + "(getpwuid() failed)")); + goto free_the_data; } - } - /* If the lockfile exists, try to delete it. */ - if (stat(lockfilename, &fileinfo) != -1) - if (delete_lockfile(lockfilename) < 0) - goto free_the_data; + if (gethostname(myhostname, 31) < 0) { + if (errno == ENAMETOOLONG) + myhostname[31] = '\0'; + else { + statusline(MILD, _("Couldn't determine hostname for lock file: %s"), + strerror(errno)); + goto free_the_data; + } + } - if (ISSET(INSECURE_BACKUP)) - cflags = O_WRONLY | O_CREAT | O_APPEND; - else - cflags = O_WRONLY | O_CREAT | O_EXCL | O_APPEND; + /* If the lockfile exists, try to delete it. */ + if (stat(lockfilename, &fileinfo) != -1) + if (delete_lockfile(lockfilename) < 0) + goto free_the_data; - /* Try to create the lockfile. */ - fd = open(lockfilename, cflags, - S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); - if (fd < 0) { - statusline(MILD, _("Error writing lock file %s: %s"), - lockfilename, strerror(errno)); - goto free_the_data; - } + if (ISSET(INSECURE_BACKUP)) + cflags = O_WRONLY | O_CREAT | O_APPEND; + else + cflags = O_WRONLY | O_CREAT | O_EXCL | O_APPEND; - /* Try to associate a stream with the now open lockfile. */ - filestream = fdopen(fd, "wb"); + /* Try to create the lockfile. */ + fd = open(lockfilename, cflags, + S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); + if (fd < 0) { + statusline(MILD, _("Error writing lock file %s: %s"), + lockfilename, strerror(errno)); + goto free_the_data; + } - if (filestream == NULL) { - statusline(MILD, _("Error writing lock file %s: %s"), lockfilename, - strerror(errno)); - goto free_the_data; - } + /* Try to associate a stream with the now open lockfile. */ + filestream = fdopen(fd, "wb"); - /* This is the lock data we will store: - * - * byte 0 - 0x62 - * byte 1 - 0x30 - * bytes 2-12 - program name which created the lock - * bytes 24-27 - PID (little endian) of creator process - * bytes 28-44 - username of who created the lock - * bytes 68-100 - hostname of where the lock was created - * bytes 108-876 - filename the lock is for - * byte 1007 - 0x55 if file is modified - * - * Looks like VIM also stores undo state in this file, so we're - * gonna have to figure out how to slap a 'OMG don't use recover on - * our lockfile' message in here... - * - * This is likely very wrong, so this is a WIP. */ - memset(lockdata, 0, lockdatalen); - lockdata[0] = 0x62; - lockdata[1] = 0x30; - lockdata[24] = mypid % 256; - lockdata[25] = (mypid / 256) % 256; - lockdata[26] = (mypid / (256 * 256)) % 256; - lockdata[27] = mypid / (256 * 256 * 256); - snprintf(&lockdata[2], 11, "nano %s", VERSION); - strncpy(&lockdata[28], mypwuid->pw_name, 16); - strncpy(&lockdata[68], myhostname, 31); - if (origfilename != NULL) - strncpy(&lockdata[108], origfilename, 768); - if (modified == TRUE) - lockdata[1007] = 0x55; + if (filestream == NULL) { + statusline(MILD, _("Error writing lock file %s: %s"), lockfilename, + strerror(errno)); + goto free_the_data; + } - wroteamt = fwrite(lockdata, sizeof(char), lockdatalen, filestream); - if (wroteamt < lockdatalen) { - statusline(MILD, _("Error writing lock file %s: %s"), - lockfilename, ferror(filestream)); + /* This is the lock data we will store: + * + * byte 0 - 0x62 + * byte 1 - 0x30 + * bytes 2-12 - program name which created the lock + * bytes 24-27 - PID (little endian) of creator process + * bytes 28-44 - username of who created the lock + * bytes 68-100 - hostname of where the lock was created + * bytes 108-876 - filename the lock is for + * byte 1007 - 0x55 if file is modified + * + * Looks like VIM also stores undo state in this file, so we're + * gonna have to figure out how to slap a 'OMG don't use recover on + * our lockfile' message in here... + * + * This is likely very wrong, so this is a WIP. */ + memset(lockdata, 0, lockdatalen); + lockdata[0] = 0x62; + lockdata[1] = 0x30; + lockdata[24] = mypid % 256; + lockdata[25] = (mypid / 256) % 256; + lockdata[26] = (mypid / (256 * 256)) % 256; + lockdata[27] = mypid / (256 * 256 * 256); + snprintf(&lockdata[2], 11, "nano %s", VERSION); + strncpy(&lockdata[28], mypwuid->pw_name, 16); + strncpy(&lockdata[68], myhostname, 31); + if (origfilename != NULL) + strncpy(&lockdata[108], origfilename, 768); + if (modified == TRUE) + lockdata[1007] = 0x55; + + wroteamt = fwrite(lockdata, sizeof(char), lockdatalen, filestream); + if (wroteamt < lockdatalen) { + statusline(MILD, _("Error writing lock file %s: %s"), + lockfilename, ferror(filestream)); fclose(filestream); - goto free_the_data; - } + goto free_the_data; + } - if (fclose(filestream) == EOF) { - statusline(MILD, _("Error writing lock file %s: %s"), - lockfilename, strerror(errno)); - goto free_the_data; - } + if (fclose(filestream) == EOF) { + statusline(MILD, _("Error writing lock file %s: %s"), + lockfilename, strerror(errno)); + goto free_the_data; + } - openfile->lock_filename = (char *) lockfilename; + openfile->lock_filename = (char *) lockfilename; - free(lockdata); - return 1; + free(lockdata); + return 1; free_the_data: - free(lockdata); - return 0; + free(lockdata); + return 0; #else - return 1; + return 1; #endif } /* Delete the lockfile. Return -1 if unsuccessful, and 1 otherwise. */ int delete_lockfile(const char *lockfilename) { - if (unlink(lockfilename) < 0 && errno != ENOENT) { - statusline(MILD, _("Error deleting lock file %s: %s"), lockfilename, - strerror(errno)); - return -1; - } - return 1; + if (unlink(lockfilename) < 0 && errno != ENOENT) { + statusline(MILD, _("Error deleting lock file %s: %s"), lockfilename, + strerror(errno)); + return -1; + } + return 1; } /* Deal with lockfiles. Return -1 on refusing to override the lockfile, @@ -297,95 +297,95 @@ int delete_lockfile(const char *lockfilename) * creating the lockfile but we should continue to load the file. */ int do_lockfile(const char *filename) { - char *namecopy = (char *) mallocstrcpy(NULL, filename); - char *secondcopy = (char *) mallocstrcpy(NULL, filename); - size_t locknamesize = strlen(filename) + strlen(locking_prefix) - + strlen(locking_suffix) + 3; - char *lockfilename = charalloc(locknamesize); - static char lockprog[11], lockuser[17]; - struct stat fileinfo; - int lockfd, lockpid, retval = -1; + char *namecopy = (char *) mallocstrcpy(NULL, filename); + char *secondcopy = (char *) mallocstrcpy(NULL, filename); + size_t locknamesize = strlen(filename) + strlen(locking_prefix) + + strlen(locking_suffix) + 3; + char *lockfilename = charalloc(locknamesize); + static char lockprog[11], lockuser[17]; + struct stat fileinfo; + int lockfd, lockpid, retval = -1; - snprintf(lockfilename, locknamesize, "%s/%s%s%s", dirname(namecopy), - locking_prefix, basename(secondcopy), locking_suffix); + snprintf(lockfilename, locknamesize, "%s/%s%s%s", dirname(namecopy), + locking_prefix, basename(secondcopy), locking_suffix); - if (stat(lockfilename, &fileinfo) != -1) { - size_t readtot = 0; - size_t readamt = 0; - char *lockbuf, *question, *pidstring, *postedname, *promptstr; - int room, response; + if (stat(lockfilename, &fileinfo) != -1) { + size_t readtot = 0; + size_t readamt = 0; + char *lockbuf, *question, *pidstring, *postedname, *promptstr; + int room, response; - if ((lockfd = open(lockfilename, O_RDONLY)) < 0) { - statusline(MILD, _("Error opening lock file %s: %s"), - lockfilename, strerror(errno)); - goto free_the_name; + if ((lockfd = open(lockfilename, O_RDONLY)) < 0) { + statusline(MILD, _("Error opening lock file %s: %s"), + lockfilename, strerror(errno)); + goto free_the_name; + } + + lockbuf = charalloc(LOCKBUFSIZE); + do { + readamt = read(lockfd, &lockbuf[readtot], LOCKBUFSIZE - readtot); + readtot += readamt; + } while (readamt > 0 && readtot < LOCKBUFSIZE); + + close(lockfd); + + if (readtot < 48) { + statusline(MILD, _("Error reading lock file %s: " + "Not enough data read"), lockfilename); + free(lockbuf); + goto free_the_name; + } + + strncpy(lockprog, &lockbuf[2], 10); + lockpid = (((unsigned char)lockbuf[27] * 256 + (unsigned char)lockbuf[26]) * 256 + + (unsigned char)lockbuf[25]) * 256 + (unsigned char)lockbuf[24]; + strncpy(lockuser, &lockbuf[28], 16); + free(lockbuf); + + pidstring = charalloc(11); + sprintf (pidstring, "%u", (unsigned int)lockpid); + + /* TRANSLATORS: The second %s is the name of the user, the third that of the editor. */ + question = _("File %s is being edited (by %s with %s, PID %s); continue?"); + room = COLS - strlenpt(question) + 7 - strlenpt(lockuser) - + strlenpt(lockprog) - strlenpt(pidstring); + if (room < 4) + postedname = mallocstrcpy(NULL, "_"); + else if (room < strlenpt(filename)) { + char *fragment = display_string(filename, + strlenpt(filename) - room + 3, room, FALSE); + postedname = charalloc(strlen(fragment) + 4); + strcpy(postedname, "..."); + strcat(postedname, fragment); + free(fragment); + } else + postedname = mallocstrcpy(NULL, filename); + + /* Allow extra space for username (14), program name (8), PID (8), + * and terminating \0 (1), minus the %s (2) for the file name. */ + promptstr = charalloc(strlen(question) + 29 + strlen(postedname)); + sprintf(promptstr, question, postedname, lockuser, lockprog, pidstring); + free(postedname); + free(pidstring); + + response = do_yesno_prompt(FALSE, promptstr); + free(promptstr); + + if (response < 1) { + wipe_statusbar(); + goto free_the_name; + } } - lockbuf = charalloc(LOCKBUFSIZE); - do { - readamt = read(lockfd, &lockbuf[readtot], LOCKBUFSIZE - readtot); - readtot += readamt; - } while (readamt > 0 && readtot < LOCKBUFSIZE); - - close(lockfd); - - if (readtot < 48) { - statusline(MILD, _("Error reading lock file %s: " - "Not enough data read"), lockfilename); - free(lockbuf); - goto free_the_name; - } - - strncpy(lockprog, &lockbuf[2], 10); - lockpid = (((unsigned char)lockbuf[27] * 256 + (unsigned char)lockbuf[26]) * 256 + - (unsigned char)lockbuf[25]) * 256 + (unsigned char)lockbuf[24]; - strncpy(lockuser, &lockbuf[28], 16); - free(lockbuf); - - pidstring = charalloc(11); - sprintf (pidstring, "%u", (unsigned int)lockpid); - - /* TRANSLATORS: The second %s is the name of the user, the third that of the editor. */ - question = _("File %s is being edited (by %s with %s, PID %s); continue?"); - room = COLS - strlenpt(question) + 7 - strlenpt(lockuser) - - strlenpt(lockprog) - strlenpt(pidstring); - if (room < 4) - postedname = mallocstrcpy(NULL, "_"); - else if (room < strlenpt(filename)) { - char *fragment = display_string(filename, - strlenpt(filename) - room + 3, room, FALSE); - postedname = charalloc(strlen(fragment) + 4); - strcpy(postedname, "..."); - strcat(postedname, fragment); - free(fragment); - } else - postedname = mallocstrcpy(NULL, filename); - - /* Allow extra space for username (14), program name (8), PID (8), - * and terminating \0 (1), minus the %s (2) for the file name. */ - promptstr = charalloc(strlen(question) + 29 + strlen(postedname)); - sprintf(promptstr, question, postedname, lockuser, lockprog, pidstring); - free(postedname); - free(pidstring); - - response = do_yesno_prompt(FALSE, promptstr); - free(promptstr); - - if (response < 1) { - wipe_statusbar(); - goto free_the_name; - } - } - - retval = write_lockfile(lockfilename, filename, FALSE); + retval = write_lockfile(lockfilename, filename, FALSE); free_the_name: - free(namecopy); - free(secondcopy); - if (retval < 1) - free(lockfilename); + free(namecopy); + free(secondcopy); + if (retval < 1) + free(lockfilename); - return retval; + return retval; } /* Perform a stat call on the given filename, allocating a stat struct @@ -393,13 +393,13 @@ int do_lockfile(const char *filename) * failure, *pstat is freed and made NULL. */ void stat_with_alloc(const char *filename, struct stat **pstat) { - if (*pstat == NULL) - *pstat = (struct stat *)nmalloc(sizeof(struct stat)); + if (*pstat == NULL) + *pstat = (struct stat *)nmalloc(sizeof(struct stat)); - if (stat(filename, *pstat) != 0) { - free(*pstat); - *pstat = NULL; - } + if (stat(filename, *pstat) != 0) { + free(*pstat); + *pstat = NULL; + } } #endif /* !NANO_TINY */ @@ -408,100 +408,100 @@ void stat_with_alloc(const char *filename, struct stat **pstat) * or into a new buffer when MULTIBUFFER is set or there is no buffer yet. */ bool open_buffer(const char *filename, bool undoable) { - bool new_buffer = (openfile == NULL || ISSET(MULTIBUFFER)); - /* Whether we load into the current buffer or a new one. */ - char *realname; - /* The filename after tilde expansion. */ - FILE *f; - int rc; - /* rc == -2 means that we have a new file. -1 means that the - * open() failed. 0 means that the open() succeeded. */ + bool new_buffer = (openfile == NULL || ISSET(MULTIBUFFER)); + /* Whether we load into the current buffer or a new one. */ + char *realname; + /* The filename after tilde expansion. */ + FILE *f; + int rc; + /* rc == -2 means that we have a new file. -1 means that the + * open() failed. 0 means that the open() succeeded. */ - /* Display newlines in filenames as ^J. */ - as_an_at = FALSE; + /* Display newlines in filenames as ^J. */ + as_an_at = FALSE; #ifdef ENABLE_OPERATINGDIR - if (outside_of_confinement(filename, FALSE)) { - statusline(ALERT, _("Can't read file from outside of %s"), - operating_dir); - return FALSE; - } -#endif - - realname = real_dir_from_tilde(filename); - - /* When the specified filename is not empty, and the corresponding - * file exists, verify that it is a normal file. */ - if (strcmp(filename, "") != 0) { - struct stat fileinfo; - - if (stat(realname, &fileinfo) == 0 && !S_ISREG(fileinfo.st_mode)) { - if (S_ISDIR(fileinfo.st_mode)) - statusline(ALERT, _("\"%s\" is a directory"), realname); - else - statusline(ALERT, _("\"%s\" is not a normal file"), realname); - free(realname); - return FALSE; + if (outside_of_confinement(filename, FALSE)) { + statusline(ALERT, _("Can't read file from outside of %s"), + operating_dir); + return FALSE; } - } - - /* If we're going to load into a new buffer, first create the new - * buffer and (if possible) lock the corresponding file. */ - if (new_buffer) { - make_new_buffer(); - - if (!inhelp && has_valid_path(realname)) { -#ifndef NANO_TINY - if (ISSET(LOCKING) && filename[0] != '\0') { - /* When not overriding an existing lock, discard the buffer. */ - if (do_lockfile(realname) < 0) { -#ifdef ENABLE_MULTIBUFFER - close_buffer(); #endif - free(realname); - return FALSE; + + realname = real_dir_from_tilde(filename); + + /* When the specified filename is not empty, and the corresponding + * file exists, verify that it is a normal file. */ + if (strcmp(filename, "") != 0) { + struct stat fileinfo; + + if (stat(realname, &fileinfo) == 0 && !S_ISREG(fileinfo.st_mode)) { + if (S_ISDIR(fileinfo.st_mode)) + statusline(ALERT, _("\"%s\" is a directory"), realname); + else + statusline(ALERT, _("\"%s\" is not a normal file"), realname); + free(realname); + return FALSE; } - } -#endif /* !NANO_TINY */ } - } - /* 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(realname, new_buffer, inhelp, &f) : -2; + /* If we're going to load into a new buffer, first create the new + * buffer and (if possible) lock the corresponding file. */ + if (new_buffer) { + make_new_buffer(); - /* If we have a file, and we're loading into a new buffer, update - * the filename. */ - if (rc != -1 && new_buffer) - openfile->filename = mallocstrcpy(openfile->filename, realname); - - /* If we have a non-new file, read it in. Then, if the buffer has - * no stat, update the stat, if applicable. */ - if (rc > 0) { - read_file(f, rc, realname, undoable, new_buffer); + if (!inhelp && has_valid_path(realname)) { #ifndef NANO_TINY - if (openfile->current_stat == NULL) - stat_with_alloc(realname, &openfile->current_stat); + if (ISSET(LOCKING) && filename[0] != '\0') { + /* When not overriding an existing lock, discard the buffer. */ + if (do_lockfile(realname) < 0) { +#ifdef ENABLE_MULTIBUFFER + close_buffer(); #endif - } + free(realname); + return FALSE; + } + } +#endif /* !NANO_TINY */ + } + } - /* If we have a file, and we're loading into a new buffer, move back - * to the beginning of the first line of the buffer. */ - if (rc != -1 && new_buffer) { - openfile->current = openfile->fileage; - openfile->current_x = 0; - openfile->placewewant = 0; - } + /* 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(realname, new_buffer, inhelp, &f) : -2; + + /* If we have a file, and we're loading into a new buffer, update + * the filename. */ + if (rc != -1 && new_buffer) + openfile->filename = mallocstrcpy(openfile->filename, realname); + + /* If we have a non-new file, read it in. Then, if the buffer has + * no stat, update the stat, if applicable. */ + if (rc > 0) { + read_file(f, rc, realname, undoable, new_buffer); +#ifndef NANO_TINY + if (openfile->current_stat == NULL) + stat_with_alloc(realname, &openfile->current_stat); +#endif + } + + /* If we have a file, and we're loading into a new buffer, move back + * to the beginning of the first line of the buffer. */ + if (rc != -1 && new_buffer) { + openfile->current = openfile->fileage; + openfile->current_x = 0; + openfile->placewewant = 0; + } #ifdef ENABLE_COLOR - /* If we're loading into a new buffer, update the colors to account - * for it, if applicable. */ - if (new_buffer) - color_update(); + /* If we're loading into a new buffer, update the colors to account + * for it, if applicable. */ + if (new_buffer) + color_update(); #endif - free(realname); - return TRUE; + free(realname); + return TRUE; } #ifdef ENABLE_SPELLER @@ -509,25 +509,25 @@ bool open_buffer(const char *filename, bool undoable) * the current buffer and read the file contents into its place. */ void replace_buffer(const char *filename) { - FILE *f; - int descriptor; + FILE *f; + int descriptor; - /* Open the file quietly. */ - descriptor = open_file(filename, FALSE, TRUE, &f); + /* Open the file quietly. */ + descriptor = open_file(filename, FALSE, TRUE, &f); - /* If opening failed, forget it. */ - if (descriptor < 0) - return; + /* If opening failed, forget it. */ + if (descriptor < 0) + return; - /* Reinitialize the text of the current buffer. */ - free_filestruct(openfile->fileage); - initialize_buffer_text(); + /* Reinitialize the text of the current buffer. */ + free_filestruct(openfile->fileage); + initialize_buffer_text(); - /* Insert the processed file into its place. */ - read_file(f, descriptor, filename, FALSE, TRUE); + /* Insert the processed file into its place. */ + read_file(f, descriptor, filename, FALSE, TRUE); - /* Put current at a place that is certain to exist. */ - openfile->current = openfile->fileage; + /* Put current at a place that is certain to exist. */ + openfile->current = openfile->fileage; } #ifndef NANO_TINY @@ -535,31 +535,31 @@ void replace_buffer(const char *filename) * the current buffer at the given coordinates and read the file * contents into its place. */ void replace_marked_buffer(const char *filename, filestruct *top, size_t top_x, - filestruct *bot, size_t bot_x) + filestruct *bot, size_t bot_x) { - FILE *f; - int descriptor; - bool old_no_newlines = ISSET(NO_NEWLINES); - filestruct *trash_top = NULL; - filestruct *trash_bot = NULL; + FILE *f; + int descriptor; + bool old_no_newlines = ISSET(NO_NEWLINES); + filestruct *trash_top = NULL; + filestruct *trash_bot = NULL; - descriptor = open_file(filename, FALSE, TRUE, &f); + descriptor = open_file(filename, FALSE, TRUE, &f); - if (descriptor < 0) - return; + if (descriptor < 0) + return; - /* Don't add a magicline when replacing text in the buffer. */ - SET(NO_NEWLINES); + /* Don't add a magicline when replacing text in the buffer. */ + SET(NO_NEWLINES); - /* Throw away the text under the mark, and insert the processed file - * where the marked text was. */ - extract_buffer(&trash_top, &trash_bot, top, top_x, bot, bot_x); - free_filestruct(trash_top); - read_file(f, descriptor, filename, FALSE, TRUE); + /* Throw away the text under the mark, and insert the processed file + * where the marked text was. */ + extract_buffer(&trash_top, &trash_bot, top, top_x, bot, bot_x); + free_filestruct(trash_top); + read_file(f, descriptor, filename, FALSE, TRUE); - /* Restore the magicline behavior now that we're done fiddling. */ - if (!old_no_newlines) - UNSET(NO_NEWLINES); + /* Restore the magicline behavior now that we're done fiddling. */ + if (!old_no_newlines) + UNSET(NO_NEWLINES); } #endif /* !NANO_TINY */ #endif /* ENABLE_SPELLER */ @@ -567,20 +567,20 @@ void replace_marked_buffer(const char *filename, filestruct *top, size_t top_x, /* Update the titlebar and the multiline cache to match the current buffer. */ void prepare_for_display(void) { - /* Update the titlebar, since the filename may have changed. */ - if (!inhelp) - titlebar(NULL); + /* Update the titlebar, since the filename may have changed. */ + if (!inhelp) + titlebar(NULL); #ifdef ENABLE_COLOR - /* If there are multiline coloring regexes, and there is no - * multiline cache data yet, precalculate it now. */ - if (openfile->syntax && openfile->syntax->nmultis > 0 && - openfile->fileage->multidata == NULL) - precalc_multicolorinfo(); + /* If there are multiline coloring regexes, and there is no + * multiline cache data yet, precalculate it now. */ + if (openfile->syntax && openfile->syntax->nmultis > 0 && + openfile->fileage->multidata == NULL) + precalc_multicolorinfo(); - have_palette = FALSE; + have_palette = FALSE; #endif - refresh_needed = TRUE; + refresh_needed = TRUE; } #ifdef ENABLE_MULTIBUFFER @@ -588,52 +588,52 @@ void prepare_for_display(void) * otherwise, to the previous one. */ void switch_to_adjacent_buffer(bool to_next) { - /* If only one file buffer is open, say so and get out. */ - if (openfile == openfile->next && !inhelp) { - statusbar(_("No more open file buffers")); - return; - } + /* If only one file buffer is open, say so and get out. */ + if (openfile == openfile->next && !inhelp) { + statusbar(_("No more open file buffers")); + return; + } - /* Switch to the next or previous file buffer. */ - openfile = to_next ? openfile->next : openfile->prev; + /* Switch to the next or previous file buffer. */ + openfile = to_next ? openfile->next : openfile->prev; #ifndef NANO_TINY - /* When not in softwrap mode, make sure firstcolumn is zero. It might - * be nonzero if we had softwrap mode on while in this buffer, and then - * turned softwrap mode off while in a different buffer. */ - if (!ISSET(SOFTWRAP)) - openfile->firstcolumn = 0; + /* When not in softwrap mode, make sure firstcolumn is zero. It might + * be nonzero if we had softwrap mode on while in this buffer, and then + * turned softwrap mode off while in a different buffer. */ + if (!ISSET(SOFTWRAP)) + openfile->firstcolumn = 0; #endif - /* Update titlebar and multiline info to match the current buffer. */ - prepare_for_display(); + /* Update titlebar and multiline info to match the current buffer. */ + prepare_for_display(); - if (inhelp) - return; + if (inhelp) + return; - /* Ensure that the main loop will redraw the help lines. */ - currmenu = MMOST; + /* Ensure that the main loop will redraw the help lines. */ + currmenu = MMOST; - /* Indicate the switch on the statusbar. */ - statusline(HUSH, _("Switched to %s"), - ((openfile->filename[0] == '\0') ? - _("New Buffer") : openfile->filename)); + /* Indicate the switch on the statusbar. */ + statusline(HUSH, _("Switched to %s"), + ((openfile->filename[0] == '\0') ? + _("New Buffer") : openfile->filename)); #ifdef DEBUG - dump_filestruct(openfile->current); + dump_filestruct(openfile->current); #endif } /* Switch to the previous entry in the list of open files. */ void switch_to_prev_buffer(void) { - switch_to_adjacent_buffer(BACKWARD); + switch_to_adjacent_buffer(BACKWARD); } /* Switch to the next entry in the list of open files. */ void switch_to_next_buffer(void) { - switch_to_adjacent_buffer(FORWARD); + switch_to_adjacent_buffer(FORWARD); } /* Delete an entry from the circular list of open files, and switch to the @@ -641,29 +641,29 @@ void switch_to_next_buffer(void) * open buffers. */ bool close_buffer(void) { - /* If only one file buffer is open, get out. */ - if (openfile == openfile->next) - return FALSE; + /* If only one file buffer is open, get out. */ + if (openfile == openfile->next) + return FALSE; #ifdef ENABLE_HISTORIES - if (ISSET(POS_HISTORY)) - update_poshistory(openfile->filename, - openfile->current->lineno, xplustabs() + 1); + if (ISSET(POS_HISTORY)) + update_poshistory(openfile->filename, + openfile->current->lineno, xplustabs() + 1); #endif - /* Switch to the next file buffer. */ - switch_to_adjacent_buffer(TRUE); + /* Switch to the next file buffer. */ + switch_to_adjacent_buffer(TRUE); - /* Delete the old file buffer, and adjust the count in the top bar. */ - unlink_opennode(openfile->prev); - if (!inhelp) - titlebar(NULL); + /* Delete the old file buffer, and adjust the count in the top bar. */ + unlink_opennode(openfile->prev); + if (!inhelp) + titlebar(NULL); - /* If now just one buffer remains open, show "Exit" in the help lines. */ - if (openfile == openfile->next) - exitfunc->desc = exit_tag; + /* If now just one buffer remains open, show "Exit" in the help lines. */ + if (openfile == openfile->next) + exitfunc->desc = exit_tag; - return TRUE; + return TRUE; } #endif /* ENABLE_MULTIBUFFER */ @@ -673,43 +673,43 @@ bool close_buffer(void) * warnings. */ int is_file_writable(const char *filename) { - char *full_filename; - struct stat fileinfo; - int fd; - FILE *f; - bool result = TRUE; + char *full_filename; + struct stat fileinfo; + int fd; + FILE *f; + bool result = TRUE; - if (ISSET(VIEW_MODE)) - return TRUE; + if (ISSET(VIEW_MODE)) + return TRUE; - full_filename = get_full_path(filename); + full_filename = get_full_path(filename); - /* If the absolute path is unusable, use the given relative one. */ - if (full_filename == NULL || stat(full_filename, &fileinfo) == -1) - full_filename = mallocstrcpy(NULL, filename); + /* If the absolute path is unusable, use the given relative one. */ + if (full_filename == NULL || stat(full_filename, &fileinfo) == -1) + full_filename = mallocstrcpy(NULL, filename); - if ((fd = open(full_filename, O_WRONLY | O_CREAT | O_APPEND, S_IRUSR | - S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)) == -1) - result = FALSE; - else if ((f = fdopen(fd, "a")) == NULL) { - result = FALSE; - close(fd); - } else - fclose(f); + if ((fd = open(full_filename, O_WRONLY | O_CREAT | O_APPEND, S_IRUSR | + S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)) == -1) + result = FALSE; + else if ((f = fdopen(fd, "a")) == NULL) { + result = FALSE; + close(fd); + } else + fclose(f); - free(full_filename); + free(full_filename); - return result; + return result; } /* Encode any NUL bytes in the given line of text, which is of length buf_len, * and return a dynamically allocated copy of the resultant string. */ char *encode_data(char *buf, size_t buf_len) { - unsunder(buf, buf_len); - buf[buf_len] = '\0'; + unsunder(buf, buf_len); + buf[buf_len] = '\0'; - return mallocstrcpy(NULL, buf); + return mallocstrcpy(NULL, buf); } /* Read an open file into the current buffer. f should be set to the @@ -718,206 +718,206 @@ char *encode_data(char *buf, size_t buf_len) * 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) + bool checkwritable) { - ssize_t was_lineno = openfile->current->lineno; - /* The line number where we start the insertion. */ - size_t was_leftedge = 0; - /* The leftedge where we start the insertion. */ - size_t num_lines = 0; - /* The number of lines in the file. */ - size_t len = 0; - /* The length of the current line of the file. */ - char input = '\0'; - /* The current input character. */ - char *buf; - /* The buffer in which we assemble each line of the file. */ - size_t bufx = MAX_BUF_SIZE; - /* The allocated size of the line buffer; increased as needed. */ - filestruct *topline; - /* The top of the new buffer where we store the read file. */ - filestruct *bottomline; - /* The bottom of the new buffer. */ - int input_int; - /* The current value we read from the file, whether an input - * character or EOF. */ - bool writable = TRUE; - /* Whether the file is writable (in case we care). */ + ssize_t was_lineno = openfile->current->lineno; + /* The line number where we start the insertion. */ + size_t was_leftedge = 0; + /* The leftedge where we start the insertion. */ + size_t num_lines = 0; + /* The number of lines in the file. */ + size_t len = 0; + /* The length of the current line of the file. */ + char input = '\0'; + /* The current input character. */ + char *buf; + /* The buffer in which we assemble each line of the file. */ + size_t bufx = MAX_BUF_SIZE; + /* The allocated size of the line buffer; increased as needed. */ + filestruct *topline; + /* The top of the new buffer where we store the read file. */ + filestruct *bottomline; + /* The bottom of the new buffer. */ + int input_int; + /* The current value we read from the file, whether an input + * character or EOF. */ + bool writable = TRUE; + /* Whether the file is writable (in case we care). */ #ifndef NANO_TINY - int format = 0; - /* 0 = *nix, 1 = DOS, 2 = Mac, 3 = both DOS and Mac. */ + int format = 0; + /* 0 = *nix, 1 = DOS, 2 = Mac, 3 = both DOS and Mac. */ #endif - buf = charalloc(bufx); + buf = charalloc(bufx); #ifndef NANO_TINY - if (undoable) - add_undo(INSERT); + if (undoable) + add_undo(INSERT); - if (ISSET(SOFTWRAP)) - was_leftedge = leftedge_for(xplustabs(), openfile->current); + if (ISSET(SOFTWRAP)) + was_leftedge = leftedge_for(xplustabs(), openfile->current); #endif - /* Create an empty buffer. */ - topline = make_new_node(NULL); - bottomline = topline; + /* Create an empty buffer. */ + topline = make_new_node(NULL); + bottomline = topline; - /* Read the entire file into the new buffer. */ - while ((input_int = getc(f)) != EOF) { - input = (char)input_int; + /* Read the entire file into the new buffer. */ + while ((input_int = getc(f)) != EOF) { + input = (char)input_int; - /* If it's a *nix file ("\n") or a DOS file ("\r\n"), and file - * conversion isn't disabled, handle it! */ - if (input == '\n') { + /* If it's a *nix file ("\n") or a DOS file ("\r\n"), and file + * conversion isn't disabled, handle it! */ + if (input == '\n') { #ifndef NANO_TINY - /* If it's a DOS file or a DOS/Mac file ('\r' before '\n' on - * the first line if we think it's a *nix file, or on any - * line otherwise), and file conversion isn't disabled, - * handle it! */ - if ((num_lines == 0 || format != 0) && !ISSET(NO_CONVERT) && - len > 0 && buf[len - 1] == '\r') { - if (format == 0 || format == 2) - format++; - } - /* If it's a Mac file ('\r' without '\n' on the first line if we - * think it's a *nix file, or on any line otherwise), and file - * conversion isn't disabled, handle it! */ - } else if ((num_lines == 0 || format != 0) && !ISSET(NO_CONVERT) && - len > 0 && buf[len - 1] == '\r') { - /* If we currently think the file is a *nix file, set format - * to Mac. If we currently think the file is a DOS file, - * set format to both DOS and Mac. */ - if (format == 0 || format == 1) - format += 2; + /* If it's a DOS file or a DOS/Mac file ('\r' before '\n' on + * the first line if we think it's a *nix file, or on any + * line otherwise), and file conversion isn't disabled, + * handle it! */ + if ((num_lines == 0 || format != 0) && !ISSET(NO_CONVERT) && + len > 0 && buf[len - 1] == '\r') { + if (format == 0 || format == 2) + format++; + } + /* If it's a Mac file ('\r' without '\n' on the first line if we + * think it's a *nix file, or on any line otherwise), and file + * conversion isn't disabled, handle it! */ + } else if ((num_lines == 0 || format != 0) && !ISSET(NO_CONVERT) && + len > 0 && buf[len - 1] == '\r') { + /* If we currently think the file is a *nix file, set format + * to Mac. If we currently think the file is a DOS file, + * set format to both DOS and Mac. */ + if (format == 0 || format == 1) + format += 2; #endif - } else { - /* Store the character. */ - buf[len] = input; + } else { + /* Store the character. */ + buf[len] = input; - /* Keep track of the total length of the line. It might have - * nulls in it, so we can't just use strlen() later. */ - len++; + /* Keep track of the total length of the line. It might have + * nulls in it, so we can't just use strlen() later. */ + len++; - /* If needed, increase the buffer size, MAX_BUF_SIZE characters at - * a time. Don't bother decreasing it; it is freed at the end. */ - if (len == bufx) { - bufx += MAX_BUF_SIZE; - buf = charealloc(buf, bufx); - } - continue; + /* If needed, increase the buffer size, MAX_BUF_SIZE characters at + * a time. Don't bother decreasing it; it is freed at the end. */ + if (len == bufx) { + bufx += MAX_BUF_SIZE; + buf = charealloc(buf, bufx); + } + continue; + } + +#ifndef NANO_TINY + /* If it's a DOS or Mac line, strip the '\r' from it. */ + if (len > 0 && buf[len - 1] == '\r' && !ISSET(NO_CONVERT)) + buf[--len] = '\0'; +#endif + + /* Store the data and make a new line. */ + bottomline->data = encode_data(buf, len); + bottomline->next = make_new_node(bottomline); + bottomline = bottomline->next; + num_lines++; + + /* Reset the length in preparation for the next line. */ + len = 0; + +#ifndef NANO_TINY + /* If it happens to be a Mac line, store the character after the \r + * as the first character of the next line. */ + if (input != '\n') + buf[len++] = input; +#endif } + /* Perhaps this could use some better handling. */ + if (ferror(f)) + nperror(filename); + fclose(f); + if (fd > 0 && checkwritable) { + close(fd); + writable = is_file_writable(filename); + } + + /* If the file ended with newline, or it was entirely empty, make the + * last line blank. Otherwise, put the last read data in. */ + if (len == 0) + bottomline->data = mallocstrcpy(NULL, ""); + else { + bool mac_line_needs_newline = FALSE; + #ifndef NANO_TINY - /* If it's a DOS or Mac line, strip the '\r' from it. */ - if (len > 0 && buf[len - 1] == '\r' && !ISSET(NO_CONVERT)) - buf[--len] = '\0'; + /* If the final character is '\r', and file conversion isn't disabled, + * set format to Mac if we currently think the file is a *nix file, or + * to DOS-and-Mac if we currently think it is a DOS file. */ + if (buf[len - 1] == '\r' && !ISSET(NO_CONVERT)) { + if (format < 2) + format += 2; + + /* Strip the carriage return. */ + buf[--len] = '\0'; + + /* Indicate we need to put a blank line in after this one. */ + mac_line_needs_newline = TRUE; + } #endif + /* Store the data of the final line. */ + bottomline->data = encode_data(buf, len); + num_lines++; - /* Store the data and make a new line. */ - bottomline->data = encode_data(buf, len); - bottomline->next = make_new_node(bottomline); - bottomline = bottomline->next; - num_lines++; + if (mac_line_needs_newline) { + bottomline->next = make_new_node(bottomline); + bottomline = bottomline->next; + bottomline->data = mallocstrcpy(NULL, ""); + } + } - /* Reset the length in preparation for the next line. */ - len = 0; + free(buf); + /* Insert the just read buffer into the current one. */ + ingraft_buffer(topline); + + /* Set the desired x position at the end of what was inserted. */ + openfile->placewewant = xplustabs(); + + /* If we've read a help file, don't give any feedback. */ + if (inhelp) + return; + + if (!writable) + statusline(ALERT, _("File '%s' is unwritable"), filename); #ifndef NANO_TINY - /* If it happens to be a Mac line, store the character after the \r - * as the first character of the next line. */ - if (input != '\n') - buf[len++] = input; -#endif - } - - /* Perhaps this could use some better handling. */ - if (ferror(f)) - nperror(filename); - fclose(f); - if (fd > 0 && checkwritable) { - close(fd); - writable = is_file_writable(filename); - } - - /* If the file ended with newline, or it was entirely empty, make the - * last line blank. Otherwise, put the last read data in. */ - if (len == 0) - bottomline->data = mallocstrcpy(NULL, ""); - else { - bool mac_line_needs_newline = FALSE; - -#ifndef NANO_TINY - /* If the final character is '\r', and file conversion isn't disabled, - * set format to Mac if we currently think the file is a *nix file, or - * to DOS-and-Mac if we currently think it is a DOS file. */ - if (buf[len - 1] == '\r' && !ISSET(NO_CONVERT)) { - if (format < 2) - format += 2; - - /* Strip the carriage return. */ - buf[--len] = '\0'; - - /* Indicate we need to put a blank line in after this one. */ - mac_line_needs_newline = TRUE; + else if (format == 3) { + /* TRANSLATORS: Keep the next four messages at most 78 characters. */ + statusline(HUSH, P_("Read %zu line (Converted from DOS and Mac format)", + "Read %zu lines (Converted from DOS and Mac format)", + num_lines), num_lines); + } else if (format == 2) { + openfile->fmt = MAC_FILE; + statusline(HUSH, P_("Read %zu line (Converted from Mac format)", + "Read %zu lines (Converted from Mac format)", + num_lines), num_lines); + } else if (format == 1) { + openfile->fmt = DOS_FILE; + statusline(HUSH, P_("Read %zu line (Converted from DOS format)", + "Read %zu lines (Converted from DOS format)", + num_lines), num_lines); } #endif - /* Store the data of the final line. */ - bottomline->data = encode_data(buf, len); - num_lines++; + else + statusline(HUSH, P_("Read %zu line", "Read %zu lines", + num_lines), num_lines); - if (mac_line_needs_newline) { - bottomline->next = make_new_node(bottomline); - bottomline = bottomline->next; - bottomline->data = mallocstrcpy(NULL, ""); - } - } - - free(buf); - - /* Insert the just read buffer into the current one. */ - ingraft_buffer(topline); - - /* Set the desired x position at the end of what was inserted. */ - openfile->placewewant = xplustabs(); - - /* If we've read a help file, don't give any feedback. */ - if (inhelp) - return; - - if (!writable) - statusline(ALERT, _("File '%s' is unwritable"), filename); -#ifndef NANO_TINY - else if (format == 3) { - /* TRANSLATORS: Keep the next four messages at most 78 characters. */ - statusline(HUSH, P_("Read %zu line (Converted from DOS and Mac format)", - "Read %zu lines (Converted from DOS and Mac format)", - num_lines), num_lines); - } else if (format == 2) { - openfile->fmt = MAC_FILE; - statusline(HUSH, P_("Read %zu line (Converted from Mac format)", - "Read %zu lines (Converted from Mac format)", - num_lines), num_lines); - } else if (format == 1) { - openfile->fmt = DOS_FILE; - statusline(HUSH, P_("Read %zu line (Converted from DOS format)", - "Read %zu lines (Converted from DOS format)", - num_lines), num_lines); - } -#endif - else - statusline(HUSH, P_("Read %zu line", "Read %zu lines", - num_lines), num_lines); - - /* If we inserted less than a screenful, don't center the cursor. */ - if (undoable && less_than_a_screenful(was_lineno, was_leftedge)) - focusing = FALSE; + /* If we inserted less than a screenful, don't center the cursor. */ + if (undoable && less_than_a_screenful(was_lineno, was_leftedge)) + focusing = FALSE; #ifndef NANO_TINY - if (undoable) - update_undo(INSERT); + if (undoable) + update_undo(INSERT); - if (ISSET(MAKE_IT_UNIX)) - openfile->fmt = NIX_FILE; + if (ISSET(MAKE_IT_UNIX)) + openfile->fmt = NIX_FILE; #endif } @@ -927,58 +927,58 @@ void read_file(FILE *f, int fd, const char *filename, bool undoable, * obtained fd otherwise. *f is set to the opened file. */ int open_file(const char *filename, bool newfie, bool quiet, FILE **f) { - struct stat fileinfo, fileinfo2; - int fd; - char *full_filename = get_full_path(filename); + struct stat fileinfo, fileinfo2; + int fd; + char *full_filename = get_full_path(filename); - /* If the full path is unusable (due to some component's permissions), - * but the relative path is okay, then just use that one. */ - if (full_filename == NULL || (stat(full_filename, &fileinfo) == -1 && - stat(filename, &fileinfo2) != -1)) - full_filename = mallocstrcpy(full_filename, filename); + /* If the full path is unusable (due to some component's permissions), + * but the relative path is okay, then just use that one. */ + if (full_filename == NULL || (stat(full_filename, &fileinfo) == -1 && + stat(filename, &fileinfo2) != -1)) + full_filename = mallocstrcpy(full_filename, filename); - if (stat(full_filename, &fileinfo) == -1) { - if (newfie) { - if (!quiet) - statusbar(_("New File")); - free(full_filename); - return -2; + if (stat(full_filename, &fileinfo) == -1) { + if (newfie) { + if (!quiet) + statusbar(_("New File")); + free(full_filename); + return -2; + } + + statusline(ALERT, _("File \"%s\" not found"), filename); + free(full_filename); + return -1; + } + + /* Don't open directories, character files, or block files. */ + if (S_ISDIR(fileinfo.st_mode) || S_ISCHR(fileinfo.st_mode) || + S_ISBLK(fileinfo.st_mode)) { + statusline(ALERT, S_ISDIR(fileinfo.st_mode) ? + _("\"%s\" is a directory") : + _("\"%s\" is a device file"), filename); + free(full_filename); + return -1; + } + + /* Try opening the file. */ + fd = open(full_filename, O_RDONLY); + + if (fd == -1) + statusline(ALERT, _("Error reading %s: %s"), filename, strerror(errno)); + else { + /* The file is A-OK. Associate a stream with it. */ + *f = fdopen(fd, "rb"); + + if (*f == NULL) { + statusline(ALERT, _("Error reading %s: %s"), filename, strerror(errno)); + close(fd); + } else if (!inhelp) + statusbar(_("Reading File")); } - statusline(ALERT, _("File \"%s\" not found"), filename); free(full_filename); - return -1; - } - /* Don't open directories, character files, or block files. */ - if (S_ISDIR(fileinfo.st_mode) || S_ISCHR(fileinfo.st_mode) || - S_ISBLK(fileinfo.st_mode)) { - statusline(ALERT, S_ISDIR(fileinfo.st_mode) ? - _("\"%s\" is a directory") : - _("\"%s\" is a device file"), filename); - free(full_filename); - return -1; - } - - /* Try opening the file. */ - fd = open(full_filename, O_RDONLY); - - if (fd == -1) - statusline(ALERT, _("Error reading %s: %s"), filename, strerror(errno)); - else { - /* The file is A-OK. Associate a stream with it. */ - *f = fdopen(fd, "rb"); - - if (*f == NULL) { - statusline(ALERT, _("Error reading %s: %s"), filename, strerror(errno)); - close(fd); - } else if (!inhelp) - statusbar(_("Reading File")); - } - - free(full_filename); - - return fd; + return fd; } /* This function will return the name of the first available extension @@ -987,217 +987,217 @@ int open_file(const char *filename, bool newfie, bool quiet, FILE **f) * extension exists, we return "". */ char *get_next_filename(const char *name, const char *suffix) { - unsigned long i = 0; - char *buf; - size_t wholenamelen; + unsigned long i = 0; + char *buf; + size_t wholenamelen; - wholenamelen = strlen(name) + strlen(suffix); + wholenamelen = strlen(name) + strlen(suffix); - /* Reserve space for: the name plus the suffix plus a dot plus - * possibly five digits plus a null byte. */ - buf = charalloc(wholenamelen + 7); - sprintf(buf, "%s%s", name, suffix); + /* Reserve space for: the name plus the suffix plus a dot plus + * possibly five digits plus a null byte. */ + buf = charalloc(wholenamelen + 7); + sprintf(buf, "%s%s", name, suffix); - while (TRUE) { - struct stat fs; + while (TRUE) { + struct stat fs; - if (stat(buf, &fs) == -1) - return buf; + if (stat(buf, &fs) == -1) + return buf; - /* Limit the number of backup files to a hundred thousand. */ - if (++i == 100000) - break; + /* Limit the number of backup files to a hundred thousand. */ + if (++i == 100000) + break; - sprintf(buf + wholenamelen, ".%lu", i); - } + sprintf(buf + wholenamelen, ".%lu", i); + } - /* There is no possible save file: blank out the filename. */ - *buf = '\0'; + /* There is no possible save file: blank out the filename. */ + *buf = '\0'; - return buf; + return buf; } /* Insert a file into the current buffer, or into a new buffer when * the MULTIBUFFER flag is set. */ void do_insertfile(void) { - int i; - const char *msg; - char *given = mallocstrcpy(NULL, ""); - /* The last answer the user typed at the statusbar prompt. */ + int i; + const char *msg; + char *given = mallocstrcpy(NULL, ""); + /* The last answer the user typed at the statusbar prompt. */ #ifndef NANO_TINY - file_format original_fmt = openfile->fmt; - bool execute = FALSE; + file_format original_fmt = openfile->fmt; + bool execute = FALSE; #endif - /* Display newlines in filenames as ^J. */ - as_an_at = FALSE; + /* Display newlines in filenames as ^J. */ + as_an_at = FALSE; - while (TRUE) { + while (TRUE) { #ifndef NANO_TINY - if (execute) { + if (execute) { #ifdef ENABLE_MULTIBUFFER - if (ISSET(MULTIBUFFER)) - /* TRANSLATORS: The next four messages are prompts. */ - msg = _("Command to execute in new buffer"); - else + if (ISSET(MULTIBUFFER)) + /* TRANSLATORS: The next four messages are prompts. */ + msg = _("Command to execute in new buffer"); + else #endif - msg = _("Command to execute"); - } else + msg = _("Command to execute"); + } else #endif - { + { #ifdef ENABLE_MULTIBUFFER - if (ISSET(MULTIBUFFER)) - msg = _("File to insert into new buffer [from %s]"); - else + if (ISSET(MULTIBUFFER)) + msg = _("File to insert into new buffer [from %s]"); + else #endif - msg = _("File to insert [from %s]"); - } + msg = _("File to insert [from %s]"); + } - present_path = mallocstrcpy(present_path, "./"); + present_path = mallocstrcpy(present_path, "./"); - i = do_prompt(TRUE, TRUE, + i = do_prompt(TRUE, TRUE, #ifndef NANO_TINY - execute ? MEXTCMD : + execute ? MEXTCMD : #endif - MINSERTFILE, given, + MINSERTFILE, given, #ifndef NANO_TINY - execute ? &execute_history : + execute ? &execute_history : #endif - NULL, edit_refresh, msg, + NULL, edit_refresh, msg, #ifdef ENABLE_OPERATINGDIR - operating_dir != NULL ? operating_dir : + operating_dir != NULL ? operating_dir : #endif - "./"); + "./"); - /* If we're in multibuffer mode and the filename or command is - * blank, open a new buffer instead of canceling. */ - if (i == -1 || (i == -2 && !ISSET(MULTIBUFFER))) { - statusbar(_("Cancelled")); - break; - } else { - ssize_t was_current_lineno = openfile->current->lineno; - size_t was_current_x = openfile->current_x; + /* If we're in multibuffer mode and the filename or command is + * blank, open a new buffer instead of canceling. */ + if (i == -1 || (i == -2 && !ISSET(MULTIBUFFER))) { + statusbar(_("Cancelled")); + break; + } else { + ssize_t was_current_lineno = openfile->current->lineno; + size_t was_current_x = openfile->current_x; #if !defined(NANO_TINY) || defined(ENABLE_BROWSER) || defined(ENABLE_MULTIBUFFER) - functionptrtype func = func_from_key(&i); + functionptrtype func = func_from_key(&i); #endif - given = mallocstrcpy(given, answer); + given = mallocstrcpy(given, answer); #ifdef ENABLE_MULTIBUFFER - if (func == flip_newbuffer) { - /* Allow toggling only when not in view mode. */ - if (!ISSET(VIEW_MODE)) - TOGGLE(MULTIBUFFER); - else - beep(); - continue; - } + if (func == flip_newbuffer) { + /* Allow toggling only when not in view mode. */ + if (!ISSET(VIEW_MODE)) + TOGGLE(MULTIBUFFER); + else + beep(); + continue; + } #endif #ifndef NANO_TINY - if (func == flip_execute) { - execute = !execute; - continue; - } + if (func == flip_execute) { + execute = !execute; + continue; + } #endif #ifdef ENABLE_BROWSER - if (func == to_files_void) { - char *chosen = do_browse_from(answer); + if (func == to_files_void) { + char *chosen = do_browse_from(answer); - /* If no file was chosen, go back to the prompt. */ - if (chosen == NULL) - continue; + /* If no file was chosen, go back to the prompt. */ + if (chosen == NULL) + continue; - free(answer); - answer = chosen; - i = 0; - } + free(answer); + answer = chosen; + i = 0; + } #endif - /* If we don't have a file yet, go back to the prompt. */ - if (i != 0 && (!ISSET(MULTIBUFFER) || i != -2)) - continue; + /* If we don't have a file yet, go back to the prompt. */ + if (i != 0 && (!ISSET(MULTIBUFFER) || i != -2)) + continue; #ifndef NANO_TINY - if (execute) { + if (execute) { #ifdef ENABLE_MULTIBUFFER - /* When in multibuffer mode, first open a blank buffer. */ - if (ISSET(MULTIBUFFER)) - open_buffer("", FALSE); + /* When in multibuffer mode, first open a blank buffer. */ + if (ISSET(MULTIBUFFER)) + open_buffer("", FALSE); #endif - /* If the command is not empty, execute it and read its output - * into the buffer, and add the command to the history list. */ - if (*answer != '\0') { - execute_command(answer); + /* If the command is not empty, execute it and read its output + * into the buffer, and add the command to the history list. */ + if (*answer != '\0') { + execute_command(answer); #ifdef ENABLE_HISTORIES - update_history(&execute_history, answer); + update_history(&execute_history, answer); #endif - } + } #ifdef ENABLE_MULTIBUFFER - /* If this is a new buffer, put the cursor at the top. */ - if (ISSET(MULTIBUFFER)) { - openfile->current = openfile->fileage; - openfile->current_x = 0; - openfile->placewewant = 0; + /* If this is a new buffer, put the cursor at the top. */ + if (ISSET(MULTIBUFFER)) { + openfile->current = openfile->fileage; + openfile->current_x = 0; + openfile->placewewant = 0; - set_modified(); - } + set_modified(); + } #endif - } else + } else #endif /* !NANO_TINY */ - { - /* Make sure the specified path is tilde-expanded. */ - answer = free_and_assign(answer, real_dir_from_tilde(answer)); + { + /* Make sure the specified path is tilde-expanded. */ + answer = free_and_assign(answer, real_dir_from_tilde(answer)); - /* Read the specified file into the current buffer. */ - open_buffer(answer, TRUE); - } + /* Read the specified file into the current buffer. */ + open_buffer(answer, TRUE); + } #ifdef ENABLE_MULTIBUFFER - if (ISSET(MULTIBUFFER)) { + if (ISSET(MULTIBUFFER)) { #ifdef ENABLE_HISTORIES - if (ISSET(POS_HISTORY)) { - ssize_t priorline, priorcol; + if (ISSET(POS_HISTORY)) { + ssize_t priorline, priorcol; #ifndef NANO_TINY - if (!execute) + if (!execute) #endif - if (has_old_position(answer, &priorline, &priorcol)) - do_gotolinecolumn(priorline, priorcol, FALSE, FALSE); - } + if (has_old_position(answer, &priorline, &priorcol)) + do_gotolinecolumn(priorline, priorcol, FALSE, FALSE); + } #endif - /* Update title bar and color info for this new buffer. */ - prepare_for_display(); - } else + /* Update title bar and color info for this new buffer. */ + prepare_for_display(); + } else #endif /* ENABLE_MULTIBUFFER */ - { - /* If the file actually changed, mark it as modified. */ - if (openfile->current->lineno != was_current_lineno || - openfile->current_x != was_current_x) - set_modified(); + { + /* If the file actually changed, mark it as modified. */ + if (openfile->current->lineno != was_current_lineno || + openfile->current_x != was_current_x) + set_modified(); #ifndef NANO_TINY - /* Ensure that the buffer retains the format that it had. */ - openfile->fmt = original_fmt; + /* Ensure that the buffer retains the format that it had. */ + openfile->fmt = original_fmt; #endif - refresh_needed = TRUE; - } + refresh_needed = TRUE; + } - break; + break; + } } - } - free(given); + free(given); } /* If the current mode of operation allows it, go insert a file. */ void do_insertfile_void(void) { - if (ISSET(RESTRICTED)) - show_restricted_warning(); + if (ISSET(RESTRICTED)) + show_restricted_warning(); #ifdef ENABLE_MULTIBUFFER - else if (ISSET(VIEW_MODE) && !ISSET(MULTIBUFFER)) - statusbar(_("Key invalid in non-multibuffer mode")); + else if (ISSET(VIEW_MODE) && !ISSET(MULTIBUFFER)) + statusbar(_("Key invalid in non-multibuffer mode")); #endif - else - do_insertfile(); + else + do_insertfile(); } /* When passed "[relative path]" or "[relative path][filename]" in @@ -1208,128 +1208,128 @@ void do_insertfile_void(void) * able to go there. */ char *get_full_path(const char *origpath) { - int attempts = 0; - /* How often we've tried climbing back up the tree. */ - struct stat fileinfo; - char *currentdir, *d_here, *d_there, *d_there_file = NULL; - char *last_slash; - bool path_only; + int attempts = 0; + /* How often we've tried climbing back up the tree. */ + struct stat fileinfo; + char *currentdir, *d_here, *d_there, *d_there_file = NULL; + char *last_slash; + bool path_only; - if (origpath == NULL) - return NULL; + if (origpath == 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 - * current directory. */ - currentdir = charalloc(PATH_MAX + 1); - d_here = getcwd(currentdir, PATH_MAX + 1); - - while (d_here == NULL && attempts < 20) { - IGNORE_CALL_RESULT(chdir("..")); + /* 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 + * current directory. */ + currentdir = charalloc(PATH_MAX + 1); d_here = getcwd(currentdir, PATH_MAX + 1); - attempts++; - } - /* If we succeeded, canonicalize it in d_here. */ - if (d_here != NULL) { - /* If the current directory isn't "/", tack a slash onto the end - * of it. */ - if (strcmp(d_here, "/") != 0) { - d_here = charealloc(d_here, strlen(d_here) + 2); - strcat(d_here, "/"); + while (d_here == NULL && attempts < 20) { + IGNORE_CALL_RESULT(chdir("..")); + d_here = getcwd(currentdir, PATH_MAX + 1); + attempts++; } - /* Otherwise, set d_here to "". */ - } else { - d_here = mallocstrcpy(NULL, ""); - free(currentdir); - } - d_there = real_dir_from_tilde(origpath); - - /* If stat()ing d_there fails, assume that d_there refers to a new - * file that hasn't been saved to disk yet. Set path_only to TRUE - * if d_there refers to a directory, and FALSE otherwise. */ - path_only = (stat(d_there, &fileinfo) != -1 && S_ISDIR(fileinfo.st_mode)); - - /* If path_only is TRUE, make sure d_there ends in a slash. */ - if (path_only) { - size_t d_there_len = strlen(d_there); - - if (d_there[d_there_len - 1] != '/') { - d_there = charealloc(d_there, d_there_len + 2); - strcat(d_there, "/"); - } - } - - /* Search for the last slash in d_there. */ - last_slash = strrchr(d_there, '/'); - - /* If we didn't find one, then make sure the answer is in the format - * "d_here/d_there". */ - if (last_slash == NULL) { - assert(!path_only); - - d_there_file = d_there; - d_there = d_here; - } else { - /* If path_only is FALSE, then save the filename portion of the - * answer (everything after the last slash) in d_there_file. */ - if (!path_only) - d_there_file = mallocstrcpy(NULL, last_slash + 1); - - /* Remove the filename portion of the answer from d_there. */ - *(last_slash + 1) = '\0'; - - /* Go to the path specified in d_there. */ - if (chdir(d_there) == -1) { - free(d_there); - d_there = NULL; - } else { - free(d_there); - - /* Get the full path. */ - currentdir = charalloc(PATH_MAX + 1); - d_there = getcwd(currentdir, PATH_MAX + 1); - - /* If we succeeded, canonicalize it in d_there. */ - if (d_there != NULL) { - /* If the current directory isn't "/", tack a slash onto - * the end of it. */ - if (strcmp(d_there, "/") != 0) { - d_there = charealloc(d_there, strlen(d_there) + 2); - strcat(d_there, "/"); + /* If we succeeded, canonicalize it in d_here. */ + if (d_here != NULL) { + /* If the current directory isn't "/", tack a slash onto the end + * of it. */ + if (strcmp(d_here, "/") != 0) { + d_here = charealloc(d_here, strlen(d_here) + 2); + strcat(d_here, "/"); } - /* Otherwise, make sure that we return NULL. */ - } else { - path_only = TRUE; + /* Otherwise, set d_here to "". */ + } else { + d_here = mallocstrcpy(NULL, ""); free(currentdir); - } - - /* Finally, go back to the path specified in d_here, - * where we were before. We don't check for a chdir() - * error, since we can do nothing if we get one. */ - IGNORE_CALL_RESULT(chdir(d_here)); } - /* Free d_here, since we're done using it. */ - free(d_here); - } + d_there = real_dir_from_tilde(origpath); - /* At this point, if path_only is FALSE and d_there isn't NULL, - * d_there contains the path portion of the answer and d_there_file - * contains the filename portion of the answer. If this is the - * case, tack the latter onto the end of the former. d_there will - * then contain the complete answer. */ - if (!path_only && d_there != NULL) { - d_there = charealloc(d_there, strlen(d_there) + - strlen(d_there_file) + 1); - strcat(d_there, d_there_file); - } + /* If stat()ing d_there fails, assume that d_there refers to a new + * file that hasn't been saved to disk yet. Set path_only to TRUE + * if d_there refers to a directory, and FALSE otherwise. */ + path_only = (stat(d_there, &fileinfo) != -1 && S_ISDIR(fileinfo.st_mode)); - /* Free d_there_file, since we're done using it. */ - free(d_there_file); + /* If path_only is TRUE, make sure d_there ends in a slash. */ + if (path_only) { + size_t d_there_len = strlen(d_there); - return d_there; + if (d_there[d_there_len - 1] != '/') { + d_there = charealloc(d_there, d_there_len + 2); + strcat(d_there, "/"); + } + } + + /* Search for the last slash in d_there. */ + last_slash = strrchr(d_there, '/'); + + /* If we didn't find one, then make sure the answer is in the format + * "d_here/d_there". */ + if (last_slash == NULL) { + assert(!path_only); + + d_there_file = d_there; + d_there = d_here; + } else { + /* If path_only is FALSE, then save the filename portion of the + * answer (everything after the last slash) in d_there_file. */ + if (!path_only) + d_there_file = mallocstrcpy(NULL, last_slash + 1); + + /* Remove the filename portion of the answer from d_there. */ + *(last_slash + 1) = '\0'; + + /* Go to the path specified in d_there. */ + if (chdir(d_there) == -1) { + free(d_there); + d_there = NULL; + } else { + free(d_there); + + /* Get the full path. */ + currentdir = charalloc(PATH_MAX + 1); + d_there = getcwd(currentdir, PATH_MAX + 1); + + /* If we succeeded, canonicalize it in d_there. */ + if (d_there != NULL) { + /* If the current directory isn't "/", tack a slash onto + * the end of it. */ + if (strcmp(d_there, "/") != 0) { + d_there = charealloc(d_there, strlen(d_there) + 2); + strcat(d_there, "/"); + } + /* Otherwise, make sure that we return NULL. */ + } else { + path_only = TRUE; + free(currentdir); + } + + /* Finally, go back to the path specified in d_here, + * where we were before. We don't check for a chdir() + * error, since we can do nothing if we get one. */ + IGNORE_CALL_RESULT(chdir(d_here)); + } + + /* Free d_here, since we're done using it. */ + free(d_here); + } + + /* At this point, if path_only is FALSE and d_there isn't NULL, + * d_there contains the path portion of the answer and d_there_file + * contains the filename portion of the answer. If this is the + * case, tack the latter onto the end of the former. d_there will + * then contain the complete answer. */ + if (!path_only && d_there != NULL) { + d_there = charealloc(d_there, strlen(d_there) + + strlen(d_there_file) + 1); + strcat(d_there, d_there_file); + } + + /* Free d_there_file, since we're done using it. */ + free(d_there_file); + + return d_there; } /* Return the full version of path, as returned by get_full_path(). On @@ -1337,19 +1337,19 @@ char *get_full_path(const char *origpath) * isn't writable, return NULL. */ char *check_writable_directory(const char *path) { - char *full_path = get_full_path(path); + char *full_path = get_full_path(path); - if (full_path == NULL) - return NULL; + if (full_path == NULL) + return NULL; - /* If we can't write to path or path isn't a directory, return NULL. */ - if (access(full_path, W_OK) != 0 || - full_path[strlen(full_path) - 1] != '/') { - free(full_path); - return NULL; - } + /* If we can't write to path or path isn't a directory, return NULL. */ + if (access(full_path, W_OK) != 0 || + full_path[strlen(full_path) - 1] != '/') { + free(full_path); + return NULL; + } - return full_path; + return full_path; } /* This function calls mkstemp(($TMPDIR|P_tmpdir|/tmp/)"nano.XXXXXX"). @@ -1358,58 +1358,58 @@ char *check_writable_directory(const char *path) * filename and leaves the FILE stream unchanged. */ char *safe_tempfile(FILE **f) { - char *full_tempdir = NULL; - const char *tmpdir_env; - int fd; - mode_t original_umask = 0; + char *full_tempdir = NULL; + const char *tmpdir_env; + int fd; + mode_t original_umask = 0; - /* If $TMPDIR is set, set tempdir to it, run it through - * get_full_path(), and save the result in full_tempdir. Otherwise, - * leave full_tempdir set to NULL. */ - tmpdir_env = getenv("TMPDIR"); - if (tmpdir_env != NULL) - full_tempdir = check_writable_directory(tmpdir_env); + /* If $TMPDIR is set, set tempdir to it, run it through + * get_full_path(), and save the result in full_tempdir. Otherwise, + * leave full_tempdir set to NULL. */ + tmpdir_env = getenv("TMPDIR"); + if (tmpdir_env != NULL) + full_tempdir = check_writable_directory(tmpdir_env); - /* If $TMPDIR is unset, empty, or not a writable directory, and - * full_tempdir is NULL, try P_tmpdir instead. */ - if (full_tempdir == NULL) - full_tempdir = check_writable_directory(P_tmpdir); + /* If $TMPDIR is unset, empty, or not a writable directory, and + * full_tempdir is NULL, try P_tmpdir instead. */ + if (full_tempdir == NULL) + full_tempdir = check_writable_directory(P_tmpdir); - /* if P_tmpdir is NULL, use /tmp. */ - if (full_tempdir == NULL) - full_tempdir = mallocstrcpy(NULL, "/tmp/"); + /* if P_tmpdir is NULL, use /tmp. */ + if (full_tempdir == NULL) + full_tempdir = mallocstrcpy(NULL, "/tmp/"); - full_tempdir = charealloc(full_tempdir, strlen(full_tempdir) + 12); - strcat(full_tempdir, "nano.XXXXXX"); + full_tempdir = charealloc(full_tempdir, strlen(full_tempdir) + 12); + strcat(full_tempdir, "nano.XXXXXX"); - original_umask = umask(0); - umask(S_IRWXG | S_IRWXO); + original_umask = umask(0); + umask(S_IRWXG | S_IRWXO); - fd = mkstemp(full_tempdir); + fd = mkstemp(full_tempdir); - if (fd != -1) - *f = fdopen(fd, "r+b"); - else { - free(full_tempdir); - full_tempdir = NULL; - } + if (fd != -1) + *f = fdopen(fd, "r+b"); + else { + free(full_tempdir); + full_tempdir = NULL; + } - umask(original_umask); + umask(original_umask); - return full_tempdir; + return full_tempdir; } #ifdef ENABLE_OPERATINGDIR /* Change to the specified operating directory, when it's valid. */ void init_operating_dir(void) { - operating_dir = free_and_assign(operating_dir, get_full_path(operating_dir)); + operating_dir = free_and_assign(operating_dir, get_full_path(operating_dir)); - /* If the operating directory is inaccessible, fail. */ - if (operating_dir == NULL || chdir(operating_dir) == -1) - die(_("Invalid operating directory\n")); + /* If the operating directory is inaccessible, fail. */ + if (operating_dir == NULL || chdir(operating_dir) == -1) + die(_("Invalid operating directory\n")); - snuggly_fit(&operating_dir); + snuggly_fit(&operating_dir); } /* Check whether the given path is outside of the operating directory. @@ -1418,31 +1418,31 @@ void init_operating_dir(void) * are considered to be inside, so that tab completion will work. */ bool outside_of_confinement(const char *currpath, bool allow_tabcomp) { - char *fullpath; - bool is_inside, begins_to_be; + char *fullpath; + bool is_inside, begins_to_be; - /* If no operating directory is set, there is nothing to check. */ - if (operating_dir == NULL) - return FALSE; + /* If no operating directory is set, there is nothing to check. */ + if (operating_dir == NULL) + return FALSE; - fullpath = get_full_path(currpath); + fullpath = get_full_path(currpath); - /* If fullpath is NULL, it means some directory in the path doesn't - * exist or is unreadable. If allow_tabcomp is FALSE, then currpath - * is what the user typed somewhere. We don't want to report a - * non-existent directory as being outside the operating directory, - * so we return FALSE. If allow_tabcomp is TRUE, then currpath - * exists, but is not executable. So we say it is outside the - * operating directory. */ - if (fullpath == NULL) - return allow_tabcomp; + /* If fullpath is NULL, it means some directory in the path doesn't + * exist or is unreadable. If allow_tabcomp is FALSE, then currpath + * is what the user typed somewhere. We don't want to report a + * non-existent directory as being outside the operating directory, + * so we return FALSE. If allow_tabcomp is TRUE, then currpath + * exists, but is not executable. So we say it is outside the + * operating directory. */ + if (fullpath == NULL) + return allow_tabcomp; - is_inside = (strstr(fullpath, operating_dir) == fullpath); - begins_to_be = (allow_tabcomp && - strstr(operating_dir, fullpath) == operating_dir); - free(fullpath); + is_inside = (strstr(fullpath, operating_dir) == fullpath); + begins_to_be = (allow_tabcomp && + strstr(operating_dir, fullpath) == operating_dir); + free(fullpath); - return (!is_inside && !begins_to_be); + return (!is_inside && !begins_to_be); } #endif @@ -1451,31 +1451,31 @@ bool outside_of_confinement(const char *currpath, bool allow_tabcomp) * messed up and I'm blanket allowing insecure file writing operations'. */ int prompt_failed_backupwrite(const char *filename) { - static int response; - 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)) { - response = do_yesno_prompt(FALSE, _("Failed to write backup file; " - "continue saving? (Say N if unsure.) ")); - prevfile = mallocstrcpy(prevfile, filename); - } + static int response; + 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)) { + response = do_yesno_prompt(FALSE, _("Failed to write backup file; " + "continue saving? (Say N if unsure.) ")); + prevfile = mallocstrcpy(prevfile, filename); + } - return response; + return response; } /* Transform the specified backup directory to an absolute path, * and verify that it is usable. */ void init_backup_dir(void) { - backup_dir = free_and_assign(backup_dir, get_full_path(backup_dir)); + backup_dir = free_and_assign(backup_dir, get_full_path(backup_dir)); - /* If we can't get an absolute path (which means it doesn't exist or - isn't accessible), or it's not a directory, fail. */ - if (backup_dir == NULL || backup_dir[strlen(backup_dir) - 1] != '/') - die(_("Invalid backup directory\n")); + /* If we can't get an absolute path (which means it doesn't exist or + isn't accessible), or it's not a directory, fail. */ + if (backup_dir == NULL || backup_dir[strlen(backup_dir) - 1] != '/') + die(_("Invalid backup directory\n")); - snuggly_fit(&backup_dir); + snuggly_fit(&backup_dir); } #endif /* !NANO_TINY */ @@ -1485,31 +1485,31 @@ void init_backup_dir(void) * only if close_out is true. */ int copy_file(FILE *inn, FILE *out, bool close_out) { - int retval = 0; - char buf[BUFSIZ]; - size_t charsread; - int (*flush_out_fnc)(FILE *) = (close_out) ? fclose : fflush; + int retval = 0; + char buf[BUFSIZ]; + size_t charsread; + int (*flush_out_fnc)(FILE *) = (close_out) ? fclose : fflush; - assert(inn != NULL && out != NULL && inn != out); + assert(inn != NULL && out != NULL && inn != out); - do { - charsread = fread(buf, sizeof(char), BUFSIZ, inn); - if (charsread == 0 && ferror(inn)) { - retval = -1; - break; - } - if (fwrite(buf, sizeof(char), charsread, out) < charsread) { - retval = -2; - break; - } - } while (charsread > 0); + do { + charsread = fread(buf, sizeof(char), BUFSIZ, inn); + if (charsread == 0 && ferror(inn)) { + retval = -1; + break; + } + if (fwrite(buf, sizeof(char), charsread, out) < charsread) { + retval = -2; + break; + } + } while (charsread > 0); - if (fclose(inn) == EOF) - retval = -1; - if (flush_out_fnc(out) == EOF) - retval = -2; + if (fclose(inn) == EOF) + retval = -1; + if (flush_out_fnc(out) == EOF) + retval = -2; - return retval; + return retval; } /* Write a file out to disk. If f_open isn't NULL, we assume that it is @@ -1528,487 +1528,487 @@ int copy_file(FILE *inn, FILE *out, bool close_out) * * Return TRUE on success or FALSE on error. */ bool write_file(const char *name, FILE *f_open, bool tmp, - kind_of_writing_type method, bool fullbuffer) + kind_of_writing_type method, bool fullbuffer) { - bool retval = FALSE; - /* Instead of returning in this function, you should always - * set retval and then goto cleanup_and_exit. */ - size_t lineswritten = 0; - const filestruct *fileptr = openfile->fileage; - int fd; - /* The file descriptor we use. */ - mode_t original_umask = 0; - /* Our umask, from when nano started. */ + bool retval = FALSE; + /* Instead of returning in this function, you should always + * set retval and then goto cleanup_and_exit. */ + size_t lineswritten = 0; + const filestruct *fileptr = openfile->fileage; + int fd; + /* The file descriptor we use. */ + mode_t original_umask = 0; + /* Our umask, from when nano started. */ #ifndef NANO_TINY - bool realexists; - /* The result of stat(). TRUE if the file exists, FALSE - * otherwise. If name is a link that points nowhere, realexists - * is FALSE. */ + bool realexists; + /* The result of stat(). TRUE if the file exists, FALSE + * otherwise. If name is a link that points nowhere, realexists + * is FALSE. */ #endif - struct stat st; - /* The status fields filled in by stat(). */ - char *realname; - /* The filename after tilde expansion. */ - FILE *f = f_open; - /* The actual file, realname, we are writing to. */ - char *tempname = NULL; - /* The name of the temporary file we write to on prepend. */ + struct stat st; + /* The status fields filled in by stat(). */ + char *realname; + /* The filename after tilde expansion. */ + FILE *f = f_open; + /* The actual file, realname, we are writing to. */ + char *tempname = NULL; + /* The name of the temporary file we write to on prepend. */ - if (*name == '\0') - return -1; + if (*name == '\0') + return -1; - if (!tmp) - titlebar(NULL); + if (!tmp) + titlebar(NULL); - realname = real_dir_from_tilde(name); + realname = real_dir_from_tilde(name); #ifdef ENABLE_OPERATINGDIR - /* If we're writing a temporary file, we're probably going outside - * the operating directory, so skip the operating directory test. */ - if (!tmp && outside_of_confinement(realname, FALSE)) { - statusline(ALERT, _("Can't write outside of %s"), operating_dir); - goto cleanup_and_exit; - } + /* If we're writing a temporary file, we're probably going outside + * the operating directory, so skip the operating directory test. */ + if (!tmp && outside_of_confinement(realname, FALSE)) { + statusline(ALERT, _("Can't write outside of %s"), operating_dir); + goto cleanup_and_exit; + } #endif - /* If the temp file exists and isn't already open, give up. */ - if (tmp && (lstat(realname, &st) != -1) && f_open == NULL) - goto cleanup_and_exit; + /* If the temp file exists and isn't already open, give up. */ + if (tmp && (lstat(realname, &st) != -1) && f_open == NULL) + goto cleanup_and_exit; #ifndef NANO_TINY - /* Check whether the file (at the end of the symlink) exists. */ - realexists = (stat(realname, &st) != -1); + /* Check whether the file (at the end of the symlink) exists. */ + realexists = (stat(realname, &st) != -1); - /* 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) - stat_with_alloc(realname, &openfile->current_stat); + /* 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) + stat_with_alloc(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 - * aren't appending, prepending, or writing a selection, we backup - * only if the file has not been modified by someone else since nano - * opened it. */ - if (ISSET(BACKUP_FILE) && !tmp && realexists && openfile->current_stat && - (method != OVERWRITE || openfile->mark || - openfile->current_stat->st_mtime == st.st_mtime)) { - static struct timespec filetime[2]; - char *backupname; - int backup_cflags, backup_fd; - FILE *backup_file = NULL; + /* We backup only if the backup toggle is set, the file isn't + * temporary, and the file already exists. Furthermore, if we + * aren't appending, prepending, or writing a selection, we backup + * only if the file has not been modified by someone else since nano + * opened it. */ + if (ISSET(BACKUP_FILE) && !tmp && realexists && openfile->current_stat && + (method != OVERWRITE || openfile->mark || + openfile->current_stat->st_mtime == st.st_mtime)) { + static struct timespec filetime[2]; + char *backupname; + int backup_cflags, backup_fd; + FILE *backup_file = NULL; - /* Save the original file's access and modification times. */ - filetime[0].tv_sec = openfile->current_stat->st_atime; - filetime[1].tv_sec = openfile->current_stat->st_mtime; + /* Save the original file's access and modification times. */ + filetime[0].tv_sec = openfile->current_stat->st_atime; + filetime[1].tv_sec = openfile->current_stat->st_mtime; - if (f_open == NULL) { - /* Open the original file to copy to the backup. */ - f = fopen(realname, "rb"); + if (f_open == NULL) { + /* Open the original file to copy to the backup. */ + f = fopen(realname, "rb"); - if (f == NULL) { - statusline(ALERT, _("Error reading %s: %s"), realname, - strerror(errno)); - /* If we can't read from the original file, go on, since - * only saving the current buffer is better than saving - * nothing. */ - goto skip_backup; - } - } - - /* If backup_dir is set, we set backupname to - * backup_dir/backupname~[.number], where backupname is the - * canonicalized absolute pathname of realname with every '/' - * replaced with a '!'. This means that /home/foo/file is - * backed up in backup_dir/!home!foo!file~[.number]. */ - if (backup_dir != NULL) { - char *backuptemp = get_full_path(realname); - - /* If we can't get a canonical absolute path, just use the - * filename portion of the given path. Otherwise, replace - * slashes with exclamation marks in the full path. */ - if (backuptemp == NULL) - backuptemp = mallocstrcpy(NULL, tail(realname)); - else { - size_t i = 0; - - for (; backuptemp[i] != '\0'; i++) { - if (backuptemp[i] == '/') - backuptemp[i] = '!'; + if (f == NULL) { + statusline(ALERT, _("Error reading %s: %s"), realname, + strerror(errno)); + /* If we can't read from the original file, go on, since + * only saving the current buffer is better than saving + * nothing. */ + goto skip_backup; + } } - } - backupname = charalloc(strlen(backup_dir) + strlen(backuptemp) + 1); - sprintf(backupname, "%s%s", backup_dir, backuptemp); - free(backuptemp); - backuptemp = get_next_filename(backupname, "~"); - if (*backuptemp == '\0') { - statusline(HUSH, _("Error writing backup file %s: %s"), - backupname, _("Too many backup files?")); - free(backuptemp); - free(backupname); - /* If we can't write to the backup, DON'T go on, since - * whatever caused the backup-file write to fail (e.g. - * disk full) may well cause the real file write to fail - * too, which means we could lose the original! */ - goto cleanup_and_exit; - } else { - free(backupname); - backupname = backuptemp; - } - } else { - backupname = charalloc(strlen(realname) + 2); - sprintf(backupname, "%s~", realname); - } + /* If backup_dir is set, we set backupname to + * backup_dir/backupname~[.number], where backupname is the + * canonicalized absolute pathname of realname with every '/' + * replaced with a '!'. This means that /home/foo/file is + * backed up in backup_dir/!home!foo!file~[.number]. */ + if (backup_dir != NULL) { + char *backuptemp = get_full_path(realname); - /* 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. */ - if (unlink(backupname) < 0 && errno != ENOENT && !ISSET(INSECURE_BACKUP)) { - if (prompt_failed_backupwrite(backupname)) - goto skip_backup; - statusline(HUSH, _("Error writing backup file %s: %s"), - backupname, strerror(errno)); - free(backupname); - goto cleanup_and_exit; - } + /* If we can't get a canonical absolute path, just use the + * filename portion of the given path. Otherwise, replace + * slashes with exclamation marks in the full path. */ + if (backuptemp == NULL) + backuptemp = mallocstrcpy(NULL, tail(realname)); + else { + size_t i = 0; - if (ISSET(INSECURE_BACKUP)) - backup_cflags = O_WRONLY | O_CREAT | O_APPEND; - else - backup_cflags = O_WRONLY | O_CREAT | O_EXCL | O_APPEND; + for (; backuptemp[i] != '\0'; i++) { + if (backuptemp[i] == '/') + backuptemp[i] = '!'; + } + } - backup_fd = open(backupname, backup_cflags, - S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); + backupname = charalloc(strlen(backup_dir) + strlen(backuptemp) + 1); + sprintf(backupname, "%s%s", backup_dir, backuptemp); + free(backuptemp); + backuptemp = get_next_filename(backupname, "~"); + if (*backuptemp == '\0') { + statusline(HUSH, _("Error writing backup file %s: %s"), + backupname, _("Too many backup files?")); + free(backuptemp); + free(backupname); + /* If we can't write to the backup, DON'T go on, since + * whatever caused the backup-file write to fail (e.g. + * disk full) may well cause the real file write to fail + * too, which means we could lose the original! */ + goto cleanup_and_exit; + } else { + free(backupname); + backupname = backuptemp; + } + } else { + backupname = charalloc(strlen(realname) + 2); + sprintf(backupname, "%s~", realname); + } - if (backup_fd >= 0) - backup_file = fdopen(backup_fd, "wb"); + /* 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. */ + if (unlink(backupname) < 0 && errno != ENOENT && !ISSET(INSECURE_BACKUP)) { + if (prompt_failed_backupwrite(backupname)) + goto skip_backup; + statusline(HUSH, _("Error writing backup file %s: %s"), + backupname, strerror(errno)); + free(backupname); + goto cleanup_and_exit; + } - if (backup_file == NULL) { - statusline(HUSH, _("Error writing backup file %s: %s"), - backupname, strerror(errno)); - free(backupname); - goto cleanup_and_exit; - } + if (ISSET(INSECURE_BACKUP)) + backup_cflags = O_WRONLY | O_CREAT | O_APPEND; + else + backup_cflags = O_WRONLY | O_CREAT | O_EXCL | O_APPEND; - /* Only try chowning the backup when we're root. */ - if (geteuid() == NANO_ROOT_UID && - fchown(backup_fd, openfile->current_stat->st_uid, - openfile->current_stat->st_gid) == -1 && - !ISSET(INSECURE_BACKUP)) { - fclose(backup_file); - if (prompt_failed_backupwrite(backupname)) - goto skip_backup; - statusline(HUSH, _("Error writing backup file %s: %s"), - backupname, strerror(errno)); - free(backupname); - goto cleanup_and_exit; - } + backup_fd = open(backupname, backup_cflags, + S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); - /* Set the backup's mode bits. */ - if (fchmod(backup_fd, openfile->current_stat->st_mode) == -1 && - !ISSET(INSECURE_BACKUP)) { - fclose(backup_file); - if (prompt_failed_backupwrite(backupname)) - goto skip_backup; - statusline(HUSH, _("Error writing backup file %s: %s"), - backupname, strerror(errno)); - free(backupname); - goto cleanup_and_exit; - } + if (backup_fd >= 0) + backup_file = fdopen(backup_fd, "wb"); + + if (backup_file == NULL) { + statusline(HUSH, _("Error writing backup file %s: %s"), + backupname, strerror(errno)); + free(backupname); + goto cleanup_and_exit; + } + + /* Only try chowning the backup when we're root. */ + if (geteuid() == NANO_ROOT_UID && + fchown(backup_fd, openfile->current_stat->st_uid, + openfile->current_stat->st_gid) == -1 && + !ISSET(INSECURE_BACKUP)) { + fclose(backup_file); + if (prompt_failed_backupwrite(backupname)) + goto skip_backup; + statusline(HUSH, _("Error writing backup file %s: %s"), + backupname, strerror(errno)); + free(backupname); + goto cleanup_and_exit; + } + + /* Set the backup's mode bits. */ + if (fchmod(backup_fd, openfile->current_stat->st_mode) == -1 && + !ISSET(INSECURE_BACKUP)) { + fclose(backup_file); + if (prompt_failed_backupwrite(backupname)) + goto skip_backup; + statusline(HUSH, _("Error writing backup file %s: %s"), + backupname, strerror(errno)); + free(backupname); + goto cleanup_and_exit; + } #ifdef DEBUG - fprintf(stderr, "Backing up %s to %s\n", realname, backupname); + fprintf(stderr, "Backing up %s to %s\n", realname, backupname); #endif - /* Copy the file. */ - if (copy_file(f, backup_file, FALSE) != 0) { - fclose(backup_file); - statusline(ALERT, _("Error reading %s: %s"), realname, - strerror(errno)); - goto cleanup_and_exit; + /* Copy the file. */ + if (copy_file(f, backup_file, FALSE) != 0) { + fclose(backup_file); + statusline(ALERT, _("Error reading %s: %s"), realname, + strerror(errno)); + goto cleanup_and_exit; + } + + /* And set the backup's timestamps. */ + if (futimens(backup_fd, filetime) == -1 && !ISSET(INSECURE_BACKUP)) { + fclose(backup_file); + if (prompt_failed_backupwrite(backupname)) + goto skip_backup; + statusline(HUSH, _("Error writing backup file %s: %s"), + backupname, strerror(errno)); + goto cleanup_and_exit; + } + + fclose(backup_file); + free(backupname); } - /* And set the backup's timestamps. */ - if (futimens(backup_fd, filetime) == -1 && !ISSET(INSECURE_BACKUP)) { - fclose(backup_file); - if (prompt_failed_backupwrite(backupname)) - goto skip_backup; - statusline(HUSH, _("Error writing backup file %s: %s"), - backupname, strerror(errno)); - goto cleanup_and_exit; - } - - fclose(backup_file); - free(backupname); - } - - skip_backup: + skip_backup: #endif /* !NANO_TINY */ - if (f_open == NULL) { - original_umask = umask(0); + if (f_open == NULL) { + original_umask = umask(0); - /* If we create a temp file, we don't let anyone else access it. */ - if (tmp) - umask(S_IRWXG | S_IRWXO); - else - umask(original_umask); - } - - /* If we're prepending, copy the file to a temp file. */ - if (method == PREPEND) { - int fd_source; - FILE *f_source = NULL; - - if (f == NULL) { - f = fopen(realname, "rb"); - - if (f == NULL) { - statusline(ALERT, _("Error reading %s: %s"), realname, - strerror(errno)); - goto cleanup_and_exit; - } + /* If we create a temp file, we don't let anyone else access it. */ + if (tmp) + umask(S_IRWXG | S_IRWXO); + else + umask(original_umask); } - tempname = safe_tempfile(&f); + /* If we're prepending, copy the file to a temp file. */ + if (method == PREPEND) { + int fd_source; + FILE *f_source = NULL; - if (tempname == NULL) { - statusline(ALERT, _("Error writing temp file: %s"), - strerror(errno)); - goto cleanup_and_exit; + if (f == NULL) { + f = fopen(realname, "rb"); + + if (f == NULL) { + statusline(ALERT, _("Error reading %s: %s"), realname, + strerror(errno)); + goto cleanup_and_exit; + } + } + + tempname = safe_tempfile(&f); + + if (tempname == NULL) { + statusline(ALERT, _("Error writing temp file: %s"), + strerror(errno)); + goto cleanup_and_exit; + } + + if (f_open == NULL) { + fd_source = open(realname, O_RDONLY | O_CREAT, S_IRUSR | S_IWUSR); + + if (fd_source != -1) { + f_source = fdopen(fd_source, "rb"); + if (f_source == NULL) { + statusline(ALERT, _("Error reading %s: %s"), realname, + strerror(errno)); + close(fd_source); + fclose(f); + unlink(tempname); + goto cleanup_and_exit; + } + } + } + + if (f_source == NULL || copy_file(f_source, f, TRUE) != 0) { + statusline(ALERT, _("Error writing temp file: %s"), + strerror(errno)); + unlink(tempname); + goto cleanup_and_exit; + } } if (f_open == NULL) { - fd_source = open(realname, O_RDONLY | O_CREAT, S_IRUSR | S_IWUSR); + /* Now open the file in place. Use O_EXCL if tmp is TRUE. This + * is copied from joe, because wiggy says so *shrug*. */ + fd = open(realname, O_WRONLY | O_CREAT | ((method == APPEND) ? + O_APPEND : (tmp ? O_EXCL : O_TRUNC)), S_IRUSR | + S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); + + /* Set the umask back to the user's original value. */ + umask(original_umask); + + /* If we couldn't open the file, give up. */ + if (fd == -1) { + statusline(ALERT, _("Error writing %s: %s"), realname, + strerror(errno)); + if (tempname != NULL) + unlink(tempname); + goto cleanup_and_exit; + } + + f = fdopen(fd, (method == APPEND) ? "ab" : "wb"); + + if (f == NULL) { + statusline(ALERT, _("Error writing %s: %s"), realname, + strerror(errno)); + close(fd); + goto cleanup_and_exit; + } + } + + while (fileptr != NULL) { + size_t data_len = strlen(fileptr->data), size; + + /* Convert newlines to nulls, just before we write to disk. */ + sunder(fileptr->data); + + size = fwrite(fileptr->data, sizeof(char), data_len, f); + + /* Convert nulls to newlines. data_len is the string's real + * length. */ + unsunder(fileptr->data, data_len); + + if (size < data_len) { + statusline(ALERT, _("Error writing %s: %s"), realname, + strerror(errno)); + fclose(f); + goto cleanup_and_exit; + } + + /* If we're on the last line of the file, don't write a newline + * character after it. If the last line of the file is blank, + * this means that zero bytes are written, in which case we + * don't count the last line in the total lines written. */ + if (fileptr == openfile->filebot) { + if (fileptr->data[0] == '\0') + lineswritten--; + } else { +#ifndef NANO_TINY + if (openfile->fmt == DOS_FILE || openfile->fmt == MAC_FILE) { + if (putc('\r', f) == EOF) { + statusline(ALERT, _("Error writing %s: %s"), realname, + strerror(errno)); + fclose(f); + goto cleanup_and_exit; + } + } + + if (openfile->fmt != MAC_FILE) +#endif + if (putc('\n', f) == EOF) { + statusline(ALERT, _("Error writing %s: %s"), realname, + strerror(errno)); + fclose(f); + goto cleanup_and_exit; + } + } + + fileptr = fileptr->next; + lineswritten++; + } + + /* If we're prepending, open the temp file, and append it to f. */ + if (method == PREPEND) { + int fd_source; + FILE *f_source = NULL; + + fd_source = open(tempname, O_RDONLY | O_CREAT, S_IRUSR | S_IWUSR); + + if (fd_source != -1) { + f_source = fdopen(fd_source, "rb"); + if (f_source == NULL) + close(fd_source); + } - if (fd_source != -1) { - f_source = fdopen(fd_source, "rb"); if (f_source == NULL) { - statusline(ALERT, _("Error reading %s: %s"), realname, - strerror(errno)); - close(fd_source); - fclose(f); - unlink(tempname); - goto cleanup_and_exit; + statusline(ALERT, _("Error reading %s: %s"), tempname, + strerror(errno)); + fclose(f); + goto cleanup_and_exit; } - } - } - if (f_source == NULL || copy_file(f_source, f, TRUE) != 0) { - statusline(ALERT, _("Error writing temp file: %s"), - strerror(errno)); - unlink(tempname); - goto cleanup_and_exit; - } - } + if (copy_file(f_source, f, TRUE) != 0) { + statusline(ALERT, _("Error writing %s: %s"), realname, + strerror(errno)); + goto cleanup_and_exit; + } - if (f_open == NULL) { - /* Now open the file in place. Use O_EXCL if tmp is TRUE. This - * is copied from joe, because wiggy says so *shrug*. */ - fd = open(realname, O_WRONLY | O_CREAT | ((method == APPEND) ? - O_APPEND : (tmp ? O_EXCL : O_TRUNC)), S_IRUSR | - S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); - - /* Set the umask back to the user's original value. */ - umask(original_umask); - - /* If we couldn't open the file, give up. */ - if (fd == -1) { - statusline(ALERT, _("Error writing %s: %s"), realname, - strerror(errno)); - if (tempname != NULL) unlink(tempname); - goto cleanup_and_exit; + } else if (fclose(f) != 0) { + statusline(ALERT, _("Error writing %s: %s"), realname, + strerror(errno)); + goto cleanup_and_exit; } - f = fdopen(fd, (method == APPEND) ? "ab" : "wb"); - - if (f == NULL) { - statusline(ALERT, _("Error writing %s: %s"), realname, - strerror(errno)); - close(fd); - goto cleanup_and_exit; - } - } - - while (fileptr != NULL) { - size_t data_len = strlen(fileptr->data), size; - - /* Convert newlines to nulls, just before we write to disk. */ - sunder(fileptr->data); - - size = fwrite(fileptr->data, sizeof(char), data_len, f); - - /* Convert nulls to newlines. data_len is the string's real - * length. */ - unsunder(fileptr->data, data_len); - - if (size < data_len) { - statusline(ALERT, _("Error writing %s: %s"), realname, - strerror(errno)); - fclose(f); - goto cleanup_and_exit; - } - - /* If we're on the last line of the file, don't write a newline - * character after it. If the last line of the file is blank, - * this means that zero bytes are written, in which case we - * don't count the last line in the total lines written. */ - if (fileptr == openfile->filebot) { - if (fileptr->data[0] == '\0') - lineswritten--; - } else { -#ifndef NANO_TINY - if (openfile->fmt == DOS_FILE || openfile->fmt == MAC_FILE) { - if (putc('\r', f) == EOF) { - statusline(ALERT, _("Error writing %s: %s"), realname, - strerror(errno)); - fclose(f); - goto cleanup_and_exit; - } - } - - if (openfile->fmt != MAC_FILE) -#endif - if (putc('\n', f) == EOF) { - statusline(ALERT, _("Error writing %s: %s"), realname, - strerror(errno)); - fclose(f); - goto cleanup_and_exit; - } - } - - fileptr = fileptr->next; - lineswritten++; - } - - /* If we're prepending, open the temp file, and append it to f. */ - if (method == PREPEND) { - int fd_source; - FILE *f_source = NULL; - - fd_source = open(tempname, O_RDONLY | O_CREAT, S_IRUSR | S_IWUSR); - - if (fd_source != -1) { - f_source = fdopen(fd_source, "rb"); - if (f_source == NULL) - close(fd_source); - } - - if (f_source == NULL) { - statusline(ALERT, _("Error reading %s: %s"), tempname, - strerror(errno)); - fclose(f); - goto cleanup_and_exit; - } - - if (copy_file(f_source, f, TRUE) != 0) { - statusline(ALERT, _("Error writing %s: %s"), realname, - strerror(errno)); - goto cleanup_and_exit; - } - - unlink(tempname); - } else if (fclose(f) != 0) { - statusline(ALERT, _("Error writing %s: %s"), realname, - strerror(errno)); - goto cleanup_and_exit; - } - - if (method == OVERWRITE && !tmp) { - /* If we must set the filename, and it changed, adjust things. */ - if (fullbuffer && strcmp(openfile->filename, realname) != 0) { + if (method == OVERWRITE && !tmp) { + /* If we must set the filename, and it changed, adjust things. */ + if (fullbuffer && strcmp(openfile->filename, realname) != 0) { #ifdef ENABLE_COLOR - const char *oldname, *newname; + const char *oldname, *newname; - oldname = openfile->syntax ? openfile->syntax->name : ""; + oldname = openfile->syntax ? openfile->syntax->name : ""; #endif - openfile->filename = mallocstrcpy(openfile->filename, realname); + openfile->filename = mallocstrcpy(openfile->filename, realname); #ifdef ENABLE_COLOR - /* See if the applicable syntax has changed. */ - color_update(); - color_init(); + /* See if the applicable syntax has changed. */ + color_update(); + color_init(); - newname = openfile->syntax ? openfile->syntax->name : ""; + newname = openfile->syntax ? openfile->syntax->name : ""; - /* If the syntax changed, discard and recompute the multidata. */ - if (strcmp(oldname, newname) != 0) { - filestruct *line = openfile->fileage; + /* If the syntax changed, discard and recompute the multidata. */ + if (strcmp(oldname, newname) != 0) { + filestruct *line = openfile->fileage; - while (line != NULL) { - free(line->multidata); - line->multidata = NULL; - line = line->next; + while (line != NULL) { + free(line->multidata); + line->multidata = NULL; + line = line->next; + } + precalc_multicolorinfo(); + refresh_needed = TRUE; + } +#endif } - precalc_multicolorinfo(); - refresh_needed = TRUE; - } -#endif - } - if (fullbuffer) { + if (fullbuffer) { #ifndef NANO_TINY - /* Get or update the stat info to reflect the current state. */ - stat_with_alloc(realname, &openfile->current_stat); + /* Get or update the stat info to reflect the current state. */ + stat_with_alloc(realname, &openfile->current_stat); - /* Record at which point in the undo stack the file was saved. */ - openfile->last_saved = openfile->current_undo; - openfile->last_action = OTHER; + /* Record at which point in the undo stack the file was saved. */ + openfile->last_saved = openfile->current_undo; + openfile->last_action = OTHER; #endif - openfile->modified = FALSE; - titlebar(NULL); + openfile->modified = FALSE; + titlebar(NULL); + } + + statusline(HUSH, P_("Wrote %zu line", "Wrote %zu lines", + lineswritten), lineswritten); } - statusline(HUSH, P_("Wrote %zu line", "Wrote %zu lines", - lineswritten), lineswritten); - } - - retval = TRUE; + retval = TRUE; cleanup_and_exit: - free(realname); - free(tempname); + free(realname); + free(tempname); - return retval; + return retval; } #ifndef NANO_TINY /* Write a marked selection from a file out to disk. Return TRUE on * success or FALSE on error. */ bool write_marked_file(const char *name, FILE *f_open, bool tmp, - kind_of_writing_type method) + kind_of_writing_type method) { - bool retval; - bool added_magicline = FALSE; - /* Whether we added a magicline after filebot. */ - filestruct *top, *bot; - size_t top_x, bot_x; + bool retval; + bool added_magicline = FALSE; + /* Whether we added a magicline after filebot. */ + filestruct *top, *bot; + size_t top_x, bot_x; - /* Partition the buffer so that it contains only the marked text. */ - mark_order((const filestruct **)&top, &top_x, - (const filestruct **)&bot, &bot_x, NULL); - filepart = partition_filestruct(top, top_x, bot, bot_x); + /* Partition the buffer so that it contains only the marked text. */ + mark_order((const filestruct **)&top, &top_x, + (const filestruct **)&bot, &bot_x, NULL); + filepart = partition_filestruct(top, top_x, bot, bot_x); - /* If we are doing magicline, and the last line of the partition - * isn't blank, then add a newline at the end of the buffer. */ - if (!ISSET(NO_NEWLINES) && openfile->filebot->data[0] != '\0') { - new_magicline(); - added_magicline = TRUE; - } + /* If we are doing magicline, and the last line of the partition + * isn't blank, then add a newline at the end of the buffer. */ + if (!ISSET(NO_NEWLINES) && openfile->filebot->data[0] != '\0') { + new_magicline(); + added_magicline = TRUE; + } - retval = write_file(name, f_open, tmp, method, FALSE); + retval = write_file(name, f_open, tmp, method, FALSE); - /* If we added a magicline, remove it now. */ - if (added_magicline) - remove_magicline(); + /* If we added a magicline, remove it now. */ + if (added_magicline) + remove_magicline(); - /* Unpartition the buffer so that it contains all the text again. */ - unpartition_filestruct(&filepart); + /* Unpartition the buffer so that it contains all the text again. */ + unpartition_filestruct(&filepart); - return retval; + return retval; } #endif /* !NANO_TINY */ @@ -2021,302 +2021,302 @@ bool write_marked_file(const char *name, FILE *f_open, bool tmp, * the buffer is to be discarded. */ int do_writeout(bool exiting, bool withprompt) { - bool result = FALSE; - kind_of_writing_type method = OVERWRITE; - char *given; - /* The filename we offer, or what the user typed so far. */ - bool maychange = (openfile->filename[0] == '\0'); - /* Whether it's okay to save the file under a different name. */ + bool result = FALSE; + kind_of_writing_type method = OVERWRITE; + char *given; + /* The filename we offer, or what the user typed so far. */ + bool maychange = (openfile->filename[0] == '\0'); + /* Whether it's okay to save the file under a different name. */ #ifdef ENABLE_EXTRA - static bool did_credits = FALSE; + static bool did_credits = FALSE; #endif - /* Display newlines in filenames as ^J. */ - as_an_at = FALSE; + /* Display newlines in filenames as ^J. */ + as_an_at = FALSE; - given = mallocstrcpy(NULL, + given = mallocstrcpy(NULL, #ifndef NANO_TINY - (openfile->mark && !exiting) ? "" : + (openfile->mark && !exiting) ? "" : #endif - openfile->filename); + openfile->filename); - while (TRUE) { - const char *msg; - int i = 0; - functionptrtype func; + while (TRUE) { + const char *msg; + int i = 0; + functionptrtype func; #ifndef NANO_TINY - const char *formatstr, *backupstr; + const char *formatstr, *backupstr; - formatstr = (openfile->fmt == DOS_FILE) ? _(" [DOS Format]") : - (openfile->fmt == MAC_FILE) ? _(" [Mac Format]") : ""; - backupstr = ISSET(BACKUP_FILE) ? _(" [Backup]") : ""; + formatstr = (openfile->fmt == DOS_FILE) ? _(" [DOS Format]") : + (openfile->fmt == MAC_FILE) ? _(" [Mac Format]") : ""; + backupstr = ISSET(BACKUP_FILE) ? _(" [Backup]") : ""; - /* When the mark is on, offer to write the selection to disk, but - * not when in restricted mode, because it would allow writing to - * a file not specified on the command line. */ - if (openfile->mark && !exiting && !ISSET(RESTRICTED)) - /* TRANSLATORS: The next six strings are prompts. */ - msg = (method == PREPEND) ? _("Prepend Selection to File") : - (method == APPEND) ? _("Append Selection to File") : - _("Write Selection to File"); - else if (method != OVERWRITE) - msg = (method == PREPEND) ? _("File Name to Prepend to") : - _("File Name to Append to"); - else + /* When the mark is on, offer to write the selection to disk, but + * not when in restricted mode, because it would allow writing to + * a file not specified on the command line. */ + if (openfile->mark && !exiting && !ISSET(RESTRICTED)) + /* TRANSLATORS: The next six strings are prompts. */ + msg = (method == PREPEND) ? _("Prepend Selection to File") : + (method == APPEND) ? _("Append Selection to File") : + _("Write Selection to File"); + else if (method != OVERWRITE) + msg = (method == PREPEND) ? _("File Name to Prepend to") : + _("File Name to Append to"); + else #endif /* !NANO_TINY */ - msg = _("File Name to Write"); + msg = _("File Name to Write"); - present_path = mallocstrcpy(present_path, "./"); + present_path = mallocstrcpy(present_path, "./"); - /* When we shouldn't prompt, use the existing filename. */ - if ((!withprompt || (ISSET(TEMP_FILE) && exiting)) && - openfile->filename[0] != '\0') - answer = mallocstrcpy(answer, openfile->filename); - else { - /* Ask for (confirmation of) the filename. Disable tab completion - * when using restricted mode and the filename isn't blank. */ - i = do_prompt(!ISSET(RESTRICTED) || openfile->filename[0] == '\0', - TRUE, MWRITEFILE, given, NULL, - edit_refresh, "%s%s%s", msg, + /* When we shouldn't prompt, use the existing filename. */ + if ((!withprompt || (ISSET(TEMP_FILE) && exiting)) && + openfile->filename[0] != '\0') + answer = mallocstrcpy(answer, openfile->filename); + else { + /* Ask for (confirmation of) the filename. Disable tab completion + * when using restricted mode and the filename isn't blank. */ + i = do_prompt(!ISSET(RESTRICTED) || openfile->filename[0] == '\0', + TRUE, MWRITEFILE, given, NULL, + edit_refresh, "%s%s%s", msg, #ifndef NANO_TINY - formatstr, backupstr + formatstr, backupstr #else - "", "" + "", "" #endif - ); - } + ); + } - if (i < 0) { - statusbar(_("Cancelled")); - break; - } + if (i < 0) { + statusbar(_("Cancelled")); + break; + } - func = func_from_key(&i); + func = func_from_key(&i); - /* Upon request, abandon the buffer. */ - if (func == discard_buffer) { - free(given); - return 2; - } + /* Upon request, abandon the buffer. */ + if (func == discard_buffer) { + free(given); + return 2; + } - given = mallocstrcpy(given, answer); + given = mallocstrcpy(given, answer); #ifdef ENABLE_BROWSER - if (func == to_files_void) { - char *chosen = do_browse_from(answer); + if (func == to_files_void) { + char *chosen = do_browse_from(answer); - if (chosen == NULL) - continue; + if (chosen == NULL) + continue; - free(answer); - answer = chosen; - } else + free(answer); + answer = chosen; + } else #endif #ifndef NANO_TINY - if (func == dos_format_void) { - openfile->fmt = (openfile->fmt == DOS_FILE) ? NIX_FILE : DOS_FILE; - continue; - } else if (func == mac_format_void) { - openfile->fmt = (openfile->fmt == MAC_FILE) ? NIX_FILE : MAC_FILE; - continue; - } else if (func == backup_file_void) { - TOGGLE(BACKUP_FILE); - continue; - } else if (func == prepend_void) { - method = (method == PREPEND) ? OVERWRITE : PREPEND; - continue; - } else if (func == append_void) { - method = (method == APPEND) ? OVERWRITE : APPEND; - continue; - } -#endif /* !NANO_TINY */ - if (func == do_help_void) { - continue; - } -#ifdef ENABLE_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 - * "zzy" as the filename to save under (hence "xyzzy"), and - * this is the first time we've done this, show an Easter - * egg. Display the credits. */ - if (!did_credits && exiting && !ISSET(TEMP_FILE) && - strcasecmp(answer, "zzy") == 0) { - do_credits(); - did_credits = TRUE; - break; - } -#endif - - if (method == OVERWRITE) { - bool name_exists, do_warning; - char *full_answer, *full_filename; - struct stat st; - - full_answer = get_full_path(answer); - full_filename = get_full_path(openfile->filename); - name_exists = (stat((full_answer == NULL) ? - answer : full_answer, &st) != -1); - if (openfile->filename[0] == '\0') - do_warning = name_exists; - else - do_warning = (strcmp((full_answer == NULL) ? - answer : full_answer, (full_filename == NULL) ? - openfile->filename : full_filename) != 0); - - free(full_filename); - free(full_answer); - - if (do_warning) { - /* When in restricted mode, we aren't allowed to overwrite - * an existing file with the current buffer, nor to change - * the name of the current file if it already has one. */ - if (ISSET(RESTRICTED)) { - /* TRANSLATORS: Restricted mode forbids overwriting. */ - warn_and_shortly_pause(_("File exists -- " - "cannot overwrite")); - continue; - } - - if (!maychange) { -#ifndef NANO_TINY - if (exiting || !openfile->mark) -#endif - { - if (do_yesno_prompt(FALSE, _("Save file under " - "DIFFERENT NAME? ")) < 1) - continue; - maychange = TRUE; - } - } - - if (name_exists) { - char *question = _("File \"%s\" exists; OVERWRITE? "); - char *message = charalloc(strlen(question) + - strlen(answer) + 1); - sprintf(message, question, answer); - - i = do_yesno_prompt(FALSE, message); - free(message); - - if (i < 1) + if (func == dos_format_void) { + openfile->fmt = (openfile->fmt == DOS_FILE) ? NIX_FILE : DOS_FILE; + continue; + } else if (func == mac_format_void) { + openfile->fmt = (openfile->fmt == MAC_FILE) ? NIX_FILE : MAC_FILE; + continue; + } else if (func == backup_file_void) { + TOGGLE(BACKUP_FILE); + continue; + } else if (func == prepend_void) { + method = (method == PREPEND) ? OVERWRITE : PREPEND; + continue; + } else if (func == append_void) { + method = (method == APPEND) ? OVERWRITE : APPEND; continue; } - } -#ifndef NANO_TINY - /* Complain if the file exists, the name hasn't changed, - * and the stat information we had before does not match - * what we have now. */ - else if (name_exists && openfile->current_stat && - (openfile->current_stat->st_mtime < st.st_mtime || - openfile->current_stat->st_dev != st.st_dev || - openfile->current_stat->st_ino != st.st_ino)) { - int response; - - warn_and_shortly_pause(_("File on disk has changed")); - - response = do_yesno_prompt(FALSE, _("File was modified " - "since you opened it; continue saving? ")); - wipe_statusbar(); - - /* When in tool mode and not called by 'savefile', - * overwrite the file right here when requested. */ - if (ISSET(TEMP_FILE) && withprompt) { - free(given); - if (response == 1) - return write_file(openfile->filename, - NULL, FALSE, OVERWRITE, TRUE); - else if (response == 0) - return 2; - else - return 0; - } else if (response != 1) { - free(given); - return 1; +#endif /* !NANO_TINY */ + if (func == do_help_void) { + continue; + } +#ifdef ENABLE_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 + * "zzy" as the filename to save under (hence "xyzzy"), and + * this is the first time we've done this, show an Easter + * egg. Display the credits. */ + if (!did_credits && exiting && !ISSET(TEMP_FILE) && + strcasecmp(answer, "zzy") == 0) { + do_credits(); + did_credits = TRUE; + break; } - } #endif + + if (method == OVERWRITE) { + bool name_exists, do_warning; + char *full_answer, *full_filename; + struct stat st; + + full_answer = get_full_path(answer); + full_filename = get_full_path(openfile->filename); + name_exists = (stat((full_answer == NULL) ? + answer : full_answer, &st) != -1); + if (openfile->filename[0] == '\0') + do_warning = name_exists; + else + do_warning = (strcmp((full_answer == NULL) ? + answer : full_answer, (full_filename == NULL) ? + openfile->filename : full_filename) != 0); + + free(full_filename); + free(full_answer); + + if (do_warning) { + /* When in restricted mode, we aren't allowed to overwrite + * an existing file with the current buffer, nor to change + * the name of the current file if it already has one. */ + if (ISSET(RESTRICTED)) { + /* TRANSLATORS: Restricted mode forbids overwriting. */ + warn_and_shortly_pause(_("File exists -- " + "cannot overwrite")); + continue; + } + + if (!maychange) { +#ifndef NANO_TINY + if (exiting || !openfile->mark) +#endif + { + if (do_yesno_prompt(FALSE, _("Save file under " + "DIFFERENT NAME? ")) < 1) + continue; + maychange = TRUE; + } + } + + if (name_exists) { + char *question = _("File \"%s\" exists; OVERWRITE? "); + char *message = charalloc(strlen(question) + + strlen(answer) + 1); + sprintf(message, question, answer); + + i = do_yesno_prompt(FALSE, message); + free(message); + + if (i < 1) + continue; + } + } +#ifndef NANO_TINY + /* Complain if the file exists, the name hasn't changed, + * and the stat information we had before does not match + * what we have now. */ + else if (name_exists && openfile->current_stat && + (openfile->current_stat->st_mtime < st.st_mtime || + openfile->current_stat->st_dev != st.st_dev || + openfile->current_stat->st_ino != st.st_ino)) { + int response; + + warn_and_shortly_pause(_("File on disk has changed")); + + response = do_yesno_prompt(FALSE, _("File was modified " + "since you opened it; continue saving? ")); + wipe_statusbar(); + + /* When in tool mode and not called by 'savefile', + * overwrite the file right here when requested. */ + if (ISSET(TEMP_FILE) && withprompt) { + free(given); + if (response == 1) + return write_file(openfile->filename, + NULL, FALSE, OVERWRITE, TRUE); + else if (response == 0) + return 2; + else + return 0; + } else if (response != 1) { + free(given); + return 1; + } + } +#endif + } + + /* Here's where we allow the selected text to be written to + * a separate file. If we're using restricted mode, this + * function is disabled, since it allows reading from or + * writing to files not specified on the command line. */ +#ifndef NANO_TINY + if (openfile->mark && !exiting && withprompt && !ISSET(RESTRICTED)) + result = write_marked_file(answer, NULL, FALSE, method); + else +#endif + result = write_file(answer, NULL, FALSE, method, TRUE); + + break; } - /* Here's where we allow the selected text to be written to - * a separate file. If we're using restricted mode, this - * function is disabled, since it allows reading from or - * writing to files not specified on the command line. */ -#ifndef NANO_TINY - if (openfile->mark && !exiting && withprompt && !ISSET(RESTRICTED)) - result = write_marked_file(answer, NULL, FALSE, method); - else -#endif - result = write_file(answer, NULL, FALSE, method, TRUE); + free(given); - break; - } - - free(given); - - return result ? 1 : 0; + return result ? 1 : 0; } /* Write the current buffer to disk, or discard it. */ void do_writeout_void(void) { - /* If the user chose to discard the buffer, close it. */ - if (do_writeout(FALSE, TRUE) == 2) - close_and_go(); + /* If the user chose to discard the buffer, close it. */ + if (do_writeout(FALSE, TRUE) == 2) + close_and_go(); } /* If it has a name, write the current file to disk without prompting. */ void do_savefile(void) { - if (do_writeout(FALSE, FALSE) == 2) - close_and_go(); + if (do_writeout(FALSE, FALSE) == 2) + close_and_go(); } /* Return a malloc()ed string containing the actual directory, used to * convert ~user/ and ~/ notation. */ char *real_dir_from_tilde(const char *buf) { - char *retval; + char *retval; - if (*buf == '~') { - size_t i = 1; - char *tilde_dir; + if (*buf == '~') { + size_t i = 1; + char *tilde_dir; - /* Figure out how much of the string we need to compare. */ - for (; buf[i] != '/' && buf[i] != '\0'; i++) - ; + /* Figure out how much of the string we need to compare. */ + for (; buf[i] != '/' && buf[i] != '\0'; i++) + ; - /* Get the home directory. */ - if (i == 1) { - get_homedir(); - tilde_dir = mallocstrcpy(NULL, homedir); - } else { + /* Get the home directory. */ + if (i == 1) { + get_homedir(); + tilde_dir = mallocstrcpy(NULL, homedir); + } else { #ifdef HAVE_PWD_H - const struct passwd *userdata; + const struct passwd *userdata; - tilde_dir = mallocstrncpy(NULL, buf, i + 1); - tilde_dir[i] = '\0'; + tilde_dir = mallocstrncpy(NULL, buf, i + 1); + tilde_dir[i] = '\0'; - do { - userdata = getpwent(); - } while (userdata != NULL && - strcmp(userdata->pw_name, tilde_dir + 1) != 0); - endpwent(); - if (userdata != NULL) - tilde_dir = mallocstrcpy(tilde_dir, userdata->pw_dir); + do { + userdata = getpwent(); + } while (userdata != NULL && + strcmp(userdata->pw_name, tilde_dir + 1) != 0); + endpwent(); + if (userdata != NULL) + tilde_dir = mallocstrcpy(tilde_dir, userdata->pw_dir); #else - tilde_dir = strdup(""); + tilde_dir = strdup(""); #endif - } + } - retval = charalloc(strlen(tilde_dir) + strlen(buf + i) + 1); - sprintf(retval, "%s%s", tilde_dir, buf + i); + retval = charalloc(strlen(tilde_dir) + strlen(buf + i) + 1); + sprintf(retval, "%s%s", tilde_dir, buf + i); - free(tilde_dir); - } else - retval = mallocstrcpy(NULL, buf); + free(tilde_dir); + } else + retval = mallocstrcpy(NULL, buf); - return retval; + return retval; } #if defined(ENABLE_TABCOMP) || defined(ENABLE_BROWSER) @@ -2324,22 +2324,22 @@ char *real_dir_from_tilde(const char *buf) * case-insensitively, and sort directories before filenames. */ int diralphasort(const void *va, const void *vb) { - struct stat fileinfo; - const char *a = *(const char *const *)va; - const char *b = *(const char *const *)vb; - bool aisdir = stat(a, &fileinfo) != -1 && S_ISDIR(fileinfo.st_mode); - bool bisdir = stat(b, &fileinfo) != -1 && S_ISDIR(fileinfo.st_mode); + struct stat fileinfo; + const char *a = *(const char *const *)va; + const char *b = *(const char *const *)vb; + bool aisdir = stat(a, &fileinfo) != -1 && S_ISDIR(fileinfo.st_mode); + bool bisdir = stat(b, &fileinfo) != -1 && S_ISDIR(fileinfo.st_mode); - if (aisdir && !bisdir) - return -1; - if (!aisdir && bisdir) - return 1; + if (aisdir && !bisdir) + return -1; + if (!aisdir && bisdir) + return 1; - /* 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. */ - return mbstrcasecmp(a, b); + /* 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. */ + return mbstrcasecmp(a, b); } #endif @@ -2347,17 +2347,17 @@ int diralphasort(const void *va, const void *vb) /* Is the given path a directory? */ bool is_dir(const char *buf) { - char *dirptr; - struct stat fileinfo; - bool retval; + char *dirptr; + struct stat fileinfo; + bool retval; - dirptr = real_dir_from_tilde(buf); + dirptr = real_dir_from_tilde(buf); - retval = (stat(dirptr, &fileinfo) != -1 && S_ISDIR(fileinfo.st_mode)); + retval = (stat(dirptr, &fileinfo) != -1 && S_ISDIR(fileinfo.st_mode)); - free(dirptr); + free(dirptr); - return retval; + return retval; } /* These functions, username_tab_completion(), cwd_tab_completion() @@ -2381,286 +2381,286 @@ bool is_dir(const char *buf) /* We consider the first buf_len characters of buf for ~username tab * completion. */ char **username_tab_completion(const char *buf, size_t *num_matches, - size_t buf_len) + size_t buf_len) { - char **matches = NULL; + char **matches = NULL; #ifdef HAVE_PWD_H - const struct passwd *userdata; + const struct passwd *userdata; #endif - assert(buf != NULL && num_matches != NULL && buf_len > 0); + assert(buf != NULL && num_matches != NULL && buf_len > 0); - *num_matches = 0; + *num_matches = 0; #ifdef HAVE_PWD_H - while ((userdata = getpwent()) != NULL) { - if (strncmp(userdata->pw_name, buf + 1, buf_len - 1) == 0) { - /* Cool, found a match. Add it to the list. This makes a - * lot more sense to me (Chris) this way... */ + while ((userdata = getpwent()) != NULL) { + if (strncmp(userdata->pw_name, buf + 1, buf_len - 1) == 0) { + /* Cool, found a match. Add it to the list. This makes a + * lot more sense to me (Chris) this way... */ #ifdef ENABLE_OPERATINGDIR - /* ...unless the match exists outside the operating - * directory, in which case just go to the next match. */ - if (outside_of_confinement(userdata->pw_dir, TRUE)) - continue; + /* ...unless the match exists outside the operating + * directory, in which case just go to the next match. */ + if (outside_of_confinement(userdata->pw_dir, TRUE)) + continue; #endif - matches = (char **)nrealloc(matches, (*num_matches + 1) * - sizeof(char *)); - matches[*num_matches] = charalloc(strlen(userdata->pw_name) + 2); - sprintf(matches[*num_matches], "~%s", userdata->pw_name); - ++(*num_matches); + matches = (char **)nrealloc(matches, (*num_matches + 1) * + sizeof(char *)); + matches[*num_matches] = charalloc(strlen(userdata->pw_name) + 2); + sprintf(matches[*num_matches], "~%s", userdata->pw_name); + ++(*num_matches); + } } - } - endpwent(); + endpwent(); #endif - return matches; + return matches; } /* We consider the first buf_len characters of buf for filename tab * completion. */ char **cwd_tab_completion(const char *buf, bool allow_files, size_t - *num_matches, size_t buf_len) + *num_matches, size_t buf_len) { - char *dirname = mallocstrcpy(NULL, buf); - char *slash, *filename; - size_t filenamelen; - char **matches = NULL; - DIR *dir; - const struct dirent *nextdir; + char *dirname = mallocstrcpy(NULL, buf); + char *slash, *filename; + size_t filenamelen; + char **matches = NULL; + DIR *dir; + const struct dirent *nextdir; - *num_matches = 0; - dirname[buf_len] = '\0'; + *num_matches = 0; + dirname[buf_len] = '\0'; - /* If there's a / in the name, split out filename and directory parts. */ - slash = strrchr(dirname, '/'); - if (slash != NULL) { - char *wasdirname = dirname; + /* If there's a / in the name, split out filename and directory parts. */ + slash = strrchr(dirname, '/'); + if (slash != NULL) { + char *wasdirname = dirname; - filename = mallocstrcpy(NULL, ++slash); - /* Cut off the filename part after the slash. */ - *slash = '\0'; - dirname = real_dir_from_tilde(dirname); - /* A non-absolute path is relative to the current browser directory. */ - if (dirname[0] != '/') { - dirname = charealloc(dirname, strlen(present_path) + - strlen(wasdirname) + 1); - sprintf(dirname, "%s%s", present_path, wasdirname); + filename = mallocstrcpy(NULL, ++slash); + /* Cut off the filename part after the slash. */ + *slash = '\0'; + dirname = real_dir_from_tilde(dirname); + /* A non-absolute path is relative to the current browser directory. */ + if (dirname[0] != '/') { + dirname = charealloc(dirname, strlen(present_path) + + strlen(wasdirname) + 1); + sprintf(dirname, "%s%s", present_path, wasdirname); + } + free(wasdirname); + } else { + filename = dirname; + dirname = mallocstrcpy(NULL, present_path); } - free(wasdirname); - } else { - filename = dirname; - dirname = mallocstrcpy(NULL, present_path); - } - assert(dirname[strlen(dirname) - 1] == '/'); + assert(dirname[strlen(dirname) - 1] == '/'); - dir = opendir(dirname); + dir = opendir(dirname); - if (dir == NULL) { - /* Don't print an error, just shut up and return. */ - beep(); - free(filename); - free(dirname); - return NULL; - } + if (dir == NULL) { + /* Don't print an error, just shut up and return. */ + beep(); + free(filename); + free(dirname); + return NULL; + } - filenamelen = strlen(filename); + filenamelen = strlen(filename); - while ((nextdir = readdir(dir)) != NULL) { - bool skip_match = FALSE; + while ((nextdir = readdir(dir)) != NULL) { + bool skip_match = FALSE; - /* See if this matches. */ - if (strncmp(nextdir->d_name, filename, filenamelen) == 0 && - (*filename == '.' || (strcmp(nextdir->d_name, ".") != 0 && - strcmp(nextdir->d_name, "..") != 0))) { - /* Cool, found a match. Add it to the list. This makes a - * lot more sense to me (Chris) this way... */ + /* See if this matches. */ + if (strncmp(nextdir->d_name, filename, filenamelen) == 0 && + (*filename == '.' || (strcmp(nextdir->d_name, ".") != 0 && + strcmp(nextdir->d_name, "..") != 0))) { + /* Cool, found a match. Add it to the list. This makes a + * lot more sense to me (Chris) this way... */ - char *tmp = charalloc(strlen(dirname) + strlen(nextdir->d_name) + 1); - sprintf(tmp, "%s%s", dirname, nextdir->d_name); + char *tmp = charalloc(strlen(dirname) + strlen(nextdir->d_name) + 1); + sprintf(tmp, "%s%s", dirname, nextdir->d_name); #ifdef ENABLE_OPERATINGDIR - /* ...unless the match exists outside the operating - * directory, in which case just go to the next match. */ - skip_match = outside_of_confinement(tmp, TRUE); + /* ...unless the match exists outside the operating + * directory, in which case just go to the next match. */ + skip_match = outside_of_confinement(tmp, TRUE); #endif - /* ...or unless the match isn't a directory and allow_files - * isn't set, in which case just go to the next match. */ - skip_match = skip_match || (!allow_files && !is_dir(tmp)); + /* ...or unless the match isn't a directory and allow_files + * isn't set, in which case just go to the next match. */ + skip_match = skip_match || (!allow_files && !is_dir(tmp)); - free(tmp); + free(tmp); - if (skip_match) - continue; + if (skip_match) + continue; - matches = (char **)nrealloc(matches, (*num_matches + 1) * - sizeof(char *)); - matches[*num_matches] = mallocstrcpy(NULL, nextdir->d_name); - ++(*num_matches); + matches = (char **)nrealloc(matches, (*num_matches + 1) * + sizeof(char *)); + matches[*num_matches] = mallocstrcpy(NULL, nextdir->d_name); + ++(*num_matches); + } } - } - closedir(dir); - free(dirname); - free(filename); + closedir(dir); + free(dirname); + free(filename); - return matches; + return matches; } /* Do tab completion. place refers to how much the statusbar cursor * position should be advanced. refresh_func is the function we will * call to refresh the edit window. */ char *input_tab(char *buf, bool allow_files, size_t *place, - bool *lastwastab, void (*refresh_func)(void), bool *listed) + bool *lastwastab, void (*refresh_func)(void), bool *listed) { - size_t num_matches = 0, buf_len; - char **matches = NULL; + size_t num_matches = 0, buf_len; + char **matches = NULL; - assert(buf != NULL && place != NULL && *place <= strlen(buf) && - lastwastab != NULL && refresh_func != NULL && listed != NULL); + assert(buf != NULL && place != NULL && *place <= strlen(buf) && + lastwastab != NULL && refresh_func != NULL && listed != NULL); - *listed = FALSE; + *listed = FALSE; - /* If the word starts with `~' and there is no slash in the word, - * then try completing this word as a username. */ - if (*place > 0 && *buf == '~') { - const char *slash = strchr(buf, '/'); + /* If the word starts with `~' and there is no slash in the word, + * then try completing this word as a username. */ + if (*place > 0 && *buf == '~') { + const char *slash = strchr(buf, '/'); - if (slash == NULL || slash >= buf + *place) - matches = username_tab_completion(buf, &num_matches, *place); - } - - /* Match against files relative to the current working directory. */ - if (matches == NULL) - matches = cwd_tab_completion(buf, allow_files, &num_matches, *place); - - buf_len = strlen(buf); - - if (num_matches == 0 || *place != buf_len) - beep(); - else { - size_t match, common_len = 0; - char *mzero, *glued; - const char *lastslash = revstrstr(buf, "/", buf + *place); - size_t lastslash_len = (lastslash == NULL) ? 0 : lastslash - buf + 1; - char char1[MAXCHARLEN], char2[MAXCHARLEN]; - int len1, len2; - - /* Get the number of characters that all matches have in common. */ - while (TRUE) { - len1 = parse_mbchar(matches[0] + common_len, char1, NULL); - - for (match = 1; match < num_matches; match++) { - len2 = parse_mbchar(matches[match] + common_len, char2, NULL); - - if (len1 != len2 || strncmp(char1, char2, len2) != 0) - break; - } - - if (match < num_matches || matches[0][common_len] == '\0') - break; - - common_len += len1; + if (slash == NULL || slash >= buf + *place) + matches = username_tab_completion(buf, &num_matches, *place); } - mzero = charalloc(lastslash_len + common_len + 1); + /* Match against files relative to the current working directory. */ + if (matches == NULL) + matches = cwd_tab_completion(buf, allow_files, &num_matches, *place); - strncpy(mzero, buf, lastslash_len); - strncpy(mzero + lastslash_len, matches[0], common_len); + buf_len = strlen(buf); - common_len += lastslash_len; - mzero[common_len] = '\0'; + if (num_matches == 0 || *place != buf_len) + beep(); + else { + size_t match, common_len = 0; + char *mzero, *glued; + const char *lastslash = revstrstr(buf, "/", buf + *place); + size_t lastslash_len = (lastslash == NULL) ? 0 : lastslash - buf + 1; + char char1[MAXCHARLEN], char2[MAXCHARLEN]; + int len1, len2; - /* Cover also the case of the user specifying a relative path. */ - glued = charalloc(strlen(present_path) + strlen(mzero) + 1); - sprintf(glued, "%s%s", present_path, mzero); + /* Get the number of characters that all matches have in common. */ + while (TRUE) { + len1 = parse_mbchar(matches[0] + common_len, char1, NULL); - assert(common_len >= *place); + for (match = 1; match < num_matches; match++) { + len2 = parse_mbchar(matches[match] + common_len, char2, NULL); - if (num_matches == 1 && (is_dir(mzero) || is_dir(glued))) { - mzero[common_len++] = '/'; + if (len1 != len2 || strncmp(char1, char2, len2) != 0) + break; + } - assert(common_len > *place); - } + if (match < num_matches || matches[0][common_len] == '\0') + break; - if (num_matches > 1 && (common_len != *place || !*lastwastab)) - beep(); - - /* If the matches have something in common, show that part. */ - if (common_len != *place) { - buf = charealloc(buf, common_len + buf_len - *place + 1); - charmove(buf + common_len, buf + *place, buf_len - *place + 1); - strncpy(buf, mzero, common_len); - *place = common_len; - } - - if (!*lastwastab) - *lastwastab = TRUE; - else if (num_matches > 1) { - int longest_name = 0, ncols, editline = 0; - - /* Sort the list of available choices. */ - qsort(matches, num_matches, sizeof(char *), diralphasort); - - /* Find the length of the longest among the choices. */ - for (match = 0; match < num_matches; match++) { - size_t namelen = strlenpt(matches[match]); - - if (namelen > longest_name) - longest_name = namelen; - } - - if (longest_name > COLS - 1) - longest_name = COLS - 1; - - /* Each column will be (longest_name + 2) columns wide, i.e. - * two spaces between columns, except that there will be - * only one space after the last column. */ - ncols = (COLS + 1) / (longest_name + 2); - - /* Blank the edit window and hide the cursor. */ - blank_edit(); - curs_set(0); - wmove(edit, 0, 0); - - /* Now print the list of matches out there. */ - for (match = 0; match < num_matches; match++) { - char *disp; - - wmove(edit, editline, (longest_name + 2) * (match % ncols)); - - if (match % ncols == 0 && editline == editwinrows - 1 && - num_matches - match > ncols) { - waddstr(edit, _("(more)")); - break; + common_len += len1; } - disp = display_string(matches[match], 0, longest_name, FALSE); - waddstr(edit, disp); - free(disp); + mzero = charalloc(lastslash_len + common_len + 1); - if ((match + 1) % ncols == 0) - editline++; - } + strncpy(mzero, buf, lastslash_len); + strncpy(mzero + lastslash_len, matches[0], common_len); - wnoutrefresh(edit); - *listed = TRUE; + common_len += lastslash_len; + mzero[common_len] = '\0'; + + /* Cover also the case of the user specifying a relative path. */ + glued = charalloc(strlen(present_path) + strlen(mzero) + 1); + sprintf(glued, "%s%s", present_path, mzero); + + assert(common_len >= *place); + + if (num_matches == 1 && (is_dir(mzero) || is_dir(glued))) { + mzero[common_len++] = '/'; + + assert(common_len > *place); + } + + if (num_matches > 1 && (common_len != *place || !*lastwastab)) + beep(); + + /* If the matches have something in common, show that part. */ + if (common_len != *place) { + buf = charealloc(buf, common_len + buf_len - *place + 1); + charmove(buf + common_len, buf + *place, buf_len - *place + 1); + strncpy(buf, mzero, common_len); + *place = common_len; + } + + if (!*lastwastab) + *lastwastab = TRUE; + else if (num_matches > 1) { + int longest_name = 0, ncols, editline = 0; + + /* Sort the list of available choices. */ + qsort(matches, num_matches, sizeof(char *), diralphasort); + + /* Find the length of the longest among the choices. */ + for (match = 0; match < num_matches; match++) { + size_t namelen = strlenpt(matches[match]); + + if (namelen > longest_name) + longest_name = namelen; + } + + if (longest_name > COLS - 1) + longest_name = COLS - 1; + + /* Each column will be (longest_name + 2) columns wide, i.e. + * two spaces between columns, except that there will be + * only one space after the last column. */ + ncols = (COLS + 1) / (longest_name + 2); + + /* Blank the edit window and hide the cursor. */ + blank_edit(); + curs_set(0); + wmove(edit, 0, 0); + + /* Now print the list of matches out there. */ + for (match = 0; match < num_matches; match++) { + char *disp; + + wmove(edit, editline, (longest_name + 2) * (match % ncols)); + + if (match % ncols == 0 && editline == editwinrows - 1 && + num_matches - match > ncols) { + waddstr(edit, _("(more)")); + break; + } + + disp = display_string(matches[match], 0, longest_name, FALSE); + waddstr(edit, disp); + free(disp); + + if ((match + 1) % ncols == 0) + editline++; + } + + wnoutrefresh(edit); + *listed = TRUE; + } + + free(glued); + free(mzero); } - free(glued); - free(mzero); - } + free_chararray(matches, num_matches); - free_chararray(matches, num_matches); + /* When we didn't list any matches now, refresh the edit window, just + * in case a previous tab showed a list, so we know where we are. */ + if (!*listed) + refresh_func(); - /* When we didn't list any matches now, refresh the edit window, just - * in case a previous tab showed a list, so we know where we are. */ - if (!*listed) - refresh_func(); - - return buf; + return buf; } #endif /* ENABLE_TABCOMP */ diff --git a/src/global.c b/src/global.c index 07976e50..70b71bfe 100644 --- a/src/global.c +++ b/src/global.c @@ -28,50 +28,50 @@ /* Global variables. */ #ifndef NANO_TINY volatile sig_atomic_t the_window_resized = FALSE; - /* Set to TRUE by the handler whenever a SIGWINCH occurs. */ + /* Set to TRUE by the handler whenever a SIGWINCH occurs. */ #endif #ifdef __linux__ bool console; - /* Whether we're running on a Linux VC (TRUE) or under X (FALSE). */ + /* Whether we're running on a Linux VC (TRUE) or under X (FALSE). */ #endif bool meta_key; - /* Whether the current keystroke is a Meta key. */ + /* Whether the current keystroke is a Meta key. */ bool shift_held; - /* Whether Shift was being held together with a movement key. */ + /* Whether Shift was being held together with a movement key. */ bool focusing = TRUE; - /* Whether an update of the edit window should center the cursor. */ + /* Whether an update of the edit window should center the cursor. */ bool as_an_at = TRUE; - /* Whether a 0x0A byte should be shown as a ^@ instead of a ^J. */ + /* Whether a 0x0A byte should be shown as a ^@ instead of a ^J. */ int margin = 0; - /* The amount of space reserved at the left for line numbers. */ + /* The amount of space reserved at the left for line numbers. */ int editwincols = -1; - /* The number of usable columns in the edit window: COLS - margin. */ + /* The number of usable columns in the edit window: COLS - margin. */ bool suppress_cursorpos = FALSE; - /* Should we skip constant position display for current keystroke? */ + /* Should we skip constant position display for current keystroke? */ message_type lastmessage = HUSH; - /* Messages of type HUSH should not overwrite type MILD nor ALERT. */ + /* Messages of type HUSH should not overwrite type MILD nor ALERT. */ filestruct *pletion_line = NULL; - /* The line where the last completion was found, if any. */ + /* The line where the last completion was found, if any. */ bool inhelp = FALSE; - /* Whether we are in the help viewer. */ + /* Whether we are in the help viewer. */ char *title = NULL; - /* When not NULL: the title of the current help text. */ + /* When not NULL: the title of the current help text. */ bool more_than_one = FALSE; - /* Whether more than one buffer is or has been open. */ + /* Whether more than one buffer is or has been open. */ bool also_the_last = FALSE; - /* Whether indenting/commenting should include the last line of - * the marked region. */ + /* Whether indenting/commenting should include the last line of + * the marked region. */ int didfind = 0; - /* Whether the last search found something. */ + /* Whether the last search found something. */ int controlleft, controlright, controlup, controldown, controlhome, controlend; #ifndef NANO_TINY @@ -83,136 +83,136 @@ int shiftaltleft, shiftaltright, shiftaltup, shiftaltdown; #ifdef ENABLED_WRAPORJUSTIFY ssize_t fill = 0; - /* The column where we will wrap lines. */ + /* The column where we will wrap lines. */ ssize_t wrap_at = -CHARS_FROM_EOL; - /* The position where we will wrap lines. fill is equal to this - * if it's greater than zero, and equal to (COLS + this) if it - * isn't. */ + /* The position where we will wrap lines. fill is equal to this + * if it's greater than zero, and equal to (COLS + this) if it + * isn't. */ #endif char *last_search = NULL; - /* The last string we searched for. */ + /* The last string we searched for. */ char *present_path = NULL; - /* The current browser directory when trying to do tab completion. */ + /* The current browser directory when trying to do tab completion. */ unsigned flags[4] = {0, 0, 0, 0}; - /* Our flag containing the states of all global options. */ + /* Our flag containing the states of all global options. */ WINDOW *topwin = NULL; - /* The top portion of the window, where we display the version - * number of nano, the name of the current file, and whether the - * current file has been modified. */ + /* The top portion of the window, where we display the version + * number of nano, the name of the current file, and whether the + * current file has been modified. */ WINDOW *edit = NULL; - /* The middle portion of the window, i.e. the edit window, where - * we display the current file we're editing. */ + /* The middle portion of the window, i.e. the edit window, where + * we display the current file we're editing. */ WINDOW *bottomwin = NULL; - /* The bottom portion of the window, where we display statusbar - * messages, the statusbar prompt, and a list of shortcuts. */ + /* The bottom portion of the window, where we display statusbar + * messages, the statusbar prompt, and a list of shortcuts. */ int editwinrows = 0; - /* How many rows does the edit window take up? */ + /* How many rows does the edit window take up? */ filestruct *cutbuffer = NULL; - /* The buffer where we store cut text. */ + /* The buffer where we store cut text. */ filestruct *cutbottom = NULL; - /* The last line in the cutbuffer. */ + /* The last line in the cutbuffer. */ partition *filepart = NULL; - /* The "partition" where we store a portion of the current file. */ + /* The "partition" where we store a portion of the current file. */ openfilestruct *openfile = NULL; - /* The list of all open file buffers. */ + /* The list of all open file buffers. */ openfilestruct *firstfile = NULL; - /* The first open buffer. */ + /* The first open buffer. */ #ifndef NANO_TINY char *matchbrackets = NULL; - /* The opening and closing brackets that can be found by bracket - * searches. */ + /* The opening and closing brackets that can be found by bracket + * searches. */ char *whitespace = NULL; - /* The characters used when visibly showing tabs and spaces. */ + /* The characters used when visibly showing tabs and spaces. */ int whitespace_len[2]; - /* The length in bytes of these characters. */ + /* The length in bytes of these characters. */ #endif #ifdef ENABLE_JUSTIFY char *punct = NULL; - /* The closing punctuation that can end sentences. */ + /* The closing punctuation that can end sentences. */ char *brackets = NULL; - /* The closing brackets that can follow closing punctuation and - * can end sentences. */ + /* The closing brackets that can follow closing punctuation and + * can end sentences. */ char *quotestr = NULL; - /* The quoting string. The default value is set in main(). */ + /* The quoting string. The default value is set in main(). */ regex_t quotereg; - /* The compiled regular expression from the quoting string. */ + /* The compiled regular expression from the quoting string. */ int quoterc; - /* Whether it was compiled successfully. */ + /* Whether it was compiled successfully. */ char *quoteerr = NULL; - /* The error message, if it didn't. */ + /* The error message, if it didn't. */ #endif char *word_chars = NULL; - /* Nonalphanumeric characters that also form words. */ + /* Nonalphanumeric characters that also form words. */ char *answer = NULL; - /* The answer string used by the statusbar prompt. */ + /* The answer string used by the statusbar prompt. */ ssize_t tabsize = -1; - /* The width of a tab in spaces. The default is set in main(). */ + /* The width of a tab in spaces. The default is set in main(). */ #ifndef NANO_TINY char *backup_dir = NULL; - /* The directory where we store backup files. */ + /* 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 #ifdef ENABLE_OPERATINGDIR char *operating_dir = NULL; - /* The path to our confining "operating" directory, when given. */ + /* The path to our confining "operating" directory, when given. */ #endif #ifdef ENABLE_SPELLER char *alt_speller = NULL; - /* The command to use for the alternate spell checker. */ + /* The command to use for the alternate spell checker. */ #endif #ifdef ENABLE_COLOR syntaxtype *syntaxes = NULL; - /* The global list of color syntaxes. */ + /* The global list of color syntaxes. */ char *syntaxstr = NULL; - /* The color syntax name specified on the command line. */ + /* The color syntax name specified on the command line. */ bool have_palette = FALSE; - /* Whether the colors for the current syntax have been initialized. */ + /* Whether the colors for the current syntax have been initialized. */ #endif bool refresh_needed = FALSE; - /* Did a command mangle enough of the buffer that we should - * repaint the screen? */ + /* Did a command mangle enough of the buffer that we should + * repaint the screen? */ int currmenu = MMOST; - /* The currently active menu, initialized to a dummy value. */ + /* The currently active menu, initialized to a dummy value. */ sc *sclist = NULL; - /* The start of the shortcuts list. */ + /* The start of the shortcuts list. */ subnfunc *allfuncs = NULL; - /* The start of the functions list. */ + /* The start of the functions list. */ subnfunc *tailfunc; - /* The last function in the list. */ + /* The last function in the list. */ subnfunc *exitfunc; - /* A pointer to the special Exit/Close item. */ + /* A pointer to the special Exit/Close item. */ subnfunc *uncutfunc; - /* A pointer to the special Uncut/Unjustify item. */ + /* A pointer to the special Uncut/Unjustify item. */ filestruct *search_history = NULL; - /* The current item in the list of strings that were searched for. */ + /* The current item in the list of strings that were searched for. */ filestruct *execute_history = NULL; - /* The current item in the list of commands that were run with ^R ^X. */ + /* The current item in the list of commands that were run with ^R ^X. */ filestruct *replace_history = NULL; - /* The current item in the list of replace strings. */ + /* The current item in the list of replace strings. */ #ifdef ENABLE_HISTORIES filestruct *searchtop = NULL; - /* The oldest item in the list of search strings. */ + /* The oldest item in the list of search strings. */ filestruct *searchbot = NULL; - /* The newest item in the list of search strings. */ + /* The newest item in the list of search strings. */ filestruct *replacetop = NULL; filestruct *replacebot = NULL; @@ -221,43 +221,43 @@ filestruct *executetop = NULL; filestruct *executebot = NULL; poshiststruct *position_history = NULL; - /* The list of filenames with their last cursor positions. */ + /* The list of filenames with their last cursor positions. */ #endif regex_t search_regexp; - /* The compiled regular expression to use in searches. */ + /* The compiled regular expression to use in searches. */ regmatch_t regmatches[10]; - /* The match positions for parenthetical subexpressions, 10 - * maximum, used in regular expression searches. */ + /* The match positions for parenthetical subexpressions, 10 + * maximum, used in regular expression searches. */ int hilite_attribute = A_REVERSE; - /* The curses attribute we use to highlight something. */ + /* The curses attribute we use to highlight something. */ #ifdef ENABLE_COLOR char* specified_color_combo[] = {NULL}; - /* The color combinations as specified in the rcfile. */ + /* The color combinations as specified in the rcfile. */ #endif int interface_color_pair[] = {0}; - /* The processed color pairs for the interface elements. */ + /* The processed color pairs for the interface elements. */ char *homedir = NULL; - /* The user's home directory, from $HOME or /etc/passwd. */ + /* The user's home directory, from $HOME or /etc/passwd. */ char *statedir = NULL; - /* The directory for nano's history files. */ + /* The directory for nano's history files. */ char *rcfile_with_errors = NULL; - /* The first nanorc file, if any, that produced warnings. */ + /* The first nanorc file, if any, that produced warnings. */ /* Return the number of entries in the shortcut list for a given menu. */ size_t length_of_list(int menu) { - subnfunc *f; - size_t i = 0; + subnfunc *f; + size_t i = 0; - for (f = allfuncs; f != NULL; f = f->next) - if ((f->menus & menu) && first_sc_for(menu, f->scfunc) != NULL) - i++; + for (f = allfuncs; f != NULL; f = f->next) + if ((f->menus & menu) && first_sc_for(menu, f->scfunc) != NULL) + i++; - return i; + return i; } /* To make the functions and shortcuts lists clearer. */ @@ -321,173 +321,173 @@ void discard_buffer(void) /* Add a function to the function list. */ void add_to_funcs(void (*func)(void), int menus, const char *desc, const char *help, - bool blank_after, bool viewok) + bool blank_after, bool viewok) { - subnfunc *f = nmalloc(sizeof(subnfunc)); + subnfunc *f = nmalloc(sizeof(subnfunc)); - if (allfuncs == NULL) - allfuncs = f; - else - tailfunc->next = f; - tailfunc = f; + if (allfuncs == NULL) + allfuncs = f; + else + tailfunc->next = f; + tailfunc = f; - f->next = NULL; - f->scfunc = func; - f->menus = menus; - f->desc = desc; - f->viewok = viewok; + f->next = NULL; + f->scfunc = func; + f->menus = menus; + f->desc = desc; + f->viewok = viewok; #ifdef ENABLE_HELP - f->help = help; - f->blank_after = blank_after; + f->help = help; + f->blank_after = blank_after; #endif #ifdef DEBUG - fprintf(stderr, "Added func %ld (%s) for menus %x\n", (long)func, f->desc, menus); + fprintf(stderr, "Added func %ld (%s) for menus %x\n", (long)func, f->desc, menus); #endif } /* Add a key combo to the shortcut list. */ void add_to_sclist(int menus, const char *scstring, const int keycode, - void (*func)(void), int toggle) + void (*func)(void), int toggle) { - static sc *tailsc; + static sc *tailsc; #ifndef NANO_TINY - static int counter = 0; + static int counter = 0; #endif - sc *s = nmalloc(sizeof(sc)); + sc *s = nmalloc(sizeof(sc)); - /* Start the list, or tack on the next item. */ - if (sclist == NULL) - sclist = s; - else - tailsc->next = s; - tailsc = s; - s->next = NULL; + /* Start the list, or tack on the next item. */ + if (sclist == NULL) + sclist = s; + else + tailsc->next = s; + tailsc = s; + s->next = NULL; - /* Fill in the data. */ - s->menus = menus; - s->scfunc = func; + /* Fill in the data. */ + s->menus = menus; + s->scfunc = func; #ifndef NANO_TINY - s->toggle = toggle; - if (toggle) - s->ordinal = ++counter; + s->toggle = toggle; + if (toggle) + s->ordinal = ++counter; #endif - assign_keyinfo(s, scstring, keycode); + assign_keyinfo(s, scstring, keycode); #ifdef DEBUG - fprintf(stderr, "Setting keycode to %d for shortcut \"%s\" in menus %x\n", s->keycode, scstring, s->menus); + fprintf(stderr, "Setting keycode to %d for shortcut \"%s\" in menus %x\n", s->keycode, scstring, s->menus); #endif } /* Assign one function's shortcuts to another function. */ void replace_scs_for(void (*oldfunc)(void), void (*newfunc)(void)) { - sc *s; + sc *s; - for (s = sclist; s != NULL; s = s->next) - if (s->scfunc == oldfunc) - s->scfunc = newfunc; + for (s = sclist; s != NULL; s = s->next) + if (s->scfunc == oldfunc) + s->scfunc = newfunc; } /* 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 *s; - for (s = sclist; s != NULL; s = s->next) - if ((s->menus & menu) && s->scfunc == func) - return s; + for (s = sclist; s != NULL; s = s->next) + if ((s->menus & menu) && s->scfunc == func) + return s; #ifdef DEBUG - fprintf(stderr, "Whoops, returning null given func %ld in menu %x\n", (long)func, menu); + fprintf(stderr, "Whoops, returning null given func %ld in menu %x\n", (long)func, menu); #endif - /* Otherwise... */ - return NULL; + /* Otherwise... */ + return NULL; } /* Return the first keycode that is bound to the given function in the * current menu, if any; otherwise, return the given default value. */ int the_code_for(void (*func)(void), int defaultval) { - const sc *s = first_sc_for(currmenu, func); + const sc *s = first_sc_for(currmenu, func); - if (s == NULL) - return defaultval; + if (s == NULL) + return defaultval; - meta_key = s->meta; - return s->keycode; + meta_key = s->meta; + return s->keycode; } /* Return a pointer to the function that is bound to the given key. */ functionptrtype func_from_key(int *kbinput) { - const sc *s = get_shortcut(kbinput); + const sc *s = get_shortcut(kbinput); - if (s) - return s->scfunc; - else - return NULL; + if (s) + return s->scfunc; + else + return NULL; } /* Set the string and its corresponding keycode for the given shortcut s. */ void assign_keyinfo(sc *s, const char *keystring, const int keycode) { - s->keystr = keystring; - s->meta = (keystring[0] == 'M' && keystring[2] != '\xE2'); + s->keystr = keystring; + s->meta = (keystring[0] == 'M' && keystring[2] != '\xE2'); - assert(strlen(keystring) > 1 && (!s->meta || strlen(keystring) > 2)); + assert(strlen(keystring) > 1 && (!s->meta || strlen(keystring) > 2)); - if (keycode) - s->keycode = keycode; - else - s->keycode = keycode_from_string(keystring); + if (keycode) + s->keycode = keycode; + else + s->keycode = keycode_from_string(keystring); } /* Parse the given keystring and return the corresponding keycode, * or return -1 when the string is invalid. */ int keycode_from_string(const char *keystring) { - if (keystring[0] == '^') { - if (strcasecmp(keystring, "^Space") == 0) - return 0; - if (strlen(keystring) == 2) - return keystring[1] - 64; + if (keystring[0] == '^') { + if (strcasecmp(keystring, "^Space") == 0) + return 0; + if (strlen(keystring) == 2) + return keystring[1] - 64; + else + return -1; + } else if (keystring[0] == 'M') { + if (strcasecmp(keystring, "M-Space") == 0) + return (int)' '; + if (keystring[1] == '-') + return tolower((unsigned char)keystring[2]); + else + return -1; + } else if (keystring[0] == 'F') { + int fn = atoi(&keystring[1]); + if (fn < 0 || fn > 63) + return -1; + return KEY_F0 + fn; + } else if (!strcasecmp(keystring, "Ins")) + return KEY_IC; + else if (!strcasecmp(keystring, "Del")) + return KEY_DC; else - return -1; - } else if (keystring[0] == 'M') { - if (strcasecmp(keystring, "M-Space") == 0) - return (int)' '; - if (keystring[1] == '-') - return tolower((unsigned char)keystring[2]); - else - return -1; - } else if (keystring[0] == 'F') { - int fn = atoi(&keystring[1]); - if (fn < 0 || fn > 63) - return -1; - return KEY_F0 + fn; - } else if (!strcasecmp(keystring, "Ins")) - return KEY_IC; - else if (!strcasecmp(keystring, "Del")) - return KEY_DC; - else - return -1; + return -1; } #ifdef DEBUG void print_sclist(void) { - sc *s; - const subnfunc *f; + sc *s; + const subnfunc *f; - for (s = sclist; s != NULL; s = s->next) { - f = sctofunc(s); - if (f) - fprintf(stderr, "Shortcut \"%s\", function: %s, menus %x\n", s->keystr, f->desc, f->menus); - else - fprintf(stderr, "Hmm, didn't find a func for \"%s\"\n", s->keystr); - } + for (s = sclist; s != NULL; s = s->next) { + f = sctofunc(s); + if (f) + fprintf(stderr, "Shortcut \"%s\", function: %s, menus %x\n", s->keystr, f->desc, f->menus); + else + fprintf(stderr, "Hmm, didn't find a func for \"%s\"\n", s->keystr); + } } #endif @@ -503,182 +503,182 @@ const char *unjust_tag = N_("Unjustify"); /* Initialize the list of functions and the list of shortcuts. */ void shortcut_init(void) { - const char *readfile_tag = N_("Read File"); - const char *whereis_tag = N_("Where Is"); - const char *replace_tag = N_("Replace"); - const char *gotoline_tag = N_("Go To Line"); - const char *prevline_tag = N_("Prev Line"); - const char *nextline_tag = N_("Next Line"); - const char *prevpage_tag = N_("Prev Page"); - const char *nextpage_tag = N_("Next Page"); + const char *readfile_tag = N_("Read File"); + const char *whereis_tag = N_("Where Is"); + const char *replace_tag = N_("Replace"); + const char *gotoline_tag = N_("Go To Line"); + const char *prevline_tag = N_("Prev Line"); + const char *nextline_tag = N_("Next Line"); + const char *prevpage_tag = N_("Prev Page"); + const char *nextpage_tag = N_("Next Page"); #ifdef ENABLE_JUSTIFY - const char *justify_tag = N_("Justify"); - const char *fulljustify_tag = N_("FullJstify"); + const char *justify_tag = N_("Justify"); + const char *fulljustify_tag = N_("FullJstify"); #endif - const char *refresh_tag = N_("Refresh"); - /* TRANSLATORS: Try to keep this string at most 12 characters. */ - const char *whereisnext_tag = N_("WhereIs Next"); + const char *refresh_tag = N_("Refresh"); + /* TRANSLATORS: Try to keep this string at most 12 characters. */ + const char *whereisnext_tag = N_("WhereIs Next"); #ifdef ENABLE_HELP - /* TRANSLATORS: The next long series of strings are shortcut descriptions; - * they are best kept shorter than 56 characters, but may be longer. */ - const char *cancel_gist = N_("Cancel the current function"); - const char *help_gist = N_("Display this help text"); - const char *exit_gist = + /* TRANSLATORS: The next long series of strings are shortcut descriptions; + * they are best kept shorter than 56 characters, but may be longer. */ + const char *cancel_gist = N_("Cancel the current function"); + const char *help_gist = N_("Display this help text"); + const char *exit_gist = #ifdef ENABLE_MULTIBUFFER - N_("Close the current file buffer / Exit from nano") + N_("Close the current file buffer / Exit from nano") #else - N_("Exit from nano") + N_("Exit from nano") #endif - ; - const char *writeout_gist = - N_("Write the current file to disk"); - const char *readfile_gist = - N_("Insert another file into the current one"); - const char *whereis_gist = - N_("Search forward for a string or a regular expression"); - const char *wherewas_gist = - N_("Search backward for a string or a regular expression"); + ; + const char *writeout_gist = + N_("Write the current file to disk"); + const char *readfile_gist = + N_("Insert another file into the current one"); + const char *whereis_gist = + N_("Search forward for a string or a regular expression"); + const char *wherewas_gist = + N_("Search backward for a string or a regular expression"); #ifdef ENABLE_BROWSER - const char *browserwhereis_gist = N_("Search for a string"); - const char *browserrefresh_gist = N_("Refresh the file list"); + const char *browserwhereis_gist = N_("Search for a string"); + const char *browserrefresh_gist = N_("Refresh the file list"); #ifndef NANO_TINY - const char *browserlefthand_gist = N_("Go to lefthand column"); - const char *browserrighthand_gist = N_("Go to righthand column"); - const char *browsertoprow_gist = N_("Go to first row in this column"); - const char *browserbottomrow_gist = N_("Go to last row in this column"); + const char *browserlefthand_gist = N_("Go to lefthand column"); + const char *browserrighthand_gist = N_("Go to righthand column"); + const char *browsertoprow_gist = N_("Go to first row in this column"); + const char *browserbottomrow_gist = N_("Go to last row in this column"); #endif #endif - const char *prevpage_gist = N_("Go one screenful up"); - const char *nextpage_gist = N_("Go one screenful down"); - const char *cut_gist = - N_("Cut the current line and store it in the cutbuffer"); - const char *uncut_gist = - N_("Uncut from the cutbuffer into the current line"); - const char *cursorpos_gist = N_("Display the position of the cursor"); + const char *prevpage_gist = N_("Go one screenful up"); + const char *nextpage_gist = N_("Go one screenful down"); + const char *cut_gist = + N_("Cut the current line and store it in the cutbuffer"); + const char *uncut_gist = + N_("Uncut from the cutbuffer into the current line"); + const char *cursorpos_gist = N_("Display the position of the cursor"); #ifdef ENABLE_SPELLER - const char *spell_gist = N_("Invoke the spell checker, if available"); + const char *spell_gist = N_("Invoke the spell checker, if available"); #endif - const char *replace_gist = N_("Replace a string or a regular expression"); - const char *gotoline_gist = N_("Go to line and column number"); - const char *whereisnext_gist = N_("Repeat the last search"); + const char *replace_gist = N_("Replace a string or a regular expression"); + const char *gotoline_gist = N_("Go to line and column number"); + const char *whereisnext_gist = N_("Repeat the last search"); #ifndef NANO_TINY - const char *mark_gist = N_("Mark text starting from the cursor position"); - const char *copy_gist = - N_("Copy the current line and store it in the cutbuffer"); - const char *indent_gist = N_("Indent the current line (or marked lines)"); - const char *unindent_gist = N_("Unindent the current line (or marked lines)"); - const char *undo_gist = N_("Undo the last operation"); - const char *redo_gist = N_("Redo the last undone operation"); + const char *mark_gist = N_("Mark text starting from the cursor position"); + const char *copy_gist = + N_("Copy the current line and store it in the cutbuffer"); + const char *indent_gist = N_("Indent the current line (or marked lines)"); + const char *unindent_gist = N_("Unindent the current line (or marked lines)"); + const char *undo_gist = N_("Undo the last operation"); + const char *redo_gist = N_("Redo the last undone operation"); #endif - const char *back_gist = N_("Go back one character"); - const char *forward_gist = N_("Go forward one character"); - const char *prevword_gist = N_("Go back one word"); - const char *nextword_gist = N_("Go forward one word"); - const char *prevline_gist = N_("Go to previous line"); - const char *nextline_gist = N_("Go to next line"); - const char *home_gist = N_("Go to beginning of current line"); - const char *end_gist = N_("Go to end of current line"); - const char *prevblock_gist = N_("Go to previous block of text"); - const char *nextblock_gist = N_("Go to next block of text"); + const char *back_gist = N_("Go back one character"); + const char *forward_gist = N_("Go forward one character"); + const char *prevword_gist = N_("Go back one word"); + const char *nextword_gist = N_("Go forward one word"); + const char *prevline_gist = N_("Go to previous line"); + const char *nextline_gist = N_("Go to next line"); + const char *home_gist = N_("Go to beginning of current line"); + const char *end_gist = N_("Go to end of current line"); + const char *prevblock_gist = N_("Go to previous block of text"); + const char *nextblock_gist = N_("Go to next block of text"); #ifdef ENABLE_JUSTIFY - const char *parabegin_gist = - N_("Go to beginning of paragraph; then of previous paragraph"); - const char *paraend_gist = - N_("Go just beyond end of paragraph; then of next paragraph"); + const char *parabegin_gist = + N_("Go to beginning of paragraph; then of previous paragraph"); + const char *paraend_gist = + N_("Go just beyond end of paragraph; then of next paragraph"); #endif - const char *firstline_gist = N_("Go to the first line of the file"); - const char *lastline_gist = N_("Go to the last line of the file"); + const char *firstline_gist = N_("Go to the first line of the file"); + const char *lastline_gist = N_("Go to the last line of the file"); #ifndef NANO_TINY - const char *bracket_gist = N_("Go to the matching bracket"); - const char *scrollup_gist = - N_("Scroll up one line without scrolling the cursor"); - const char *scrolldown_gist = - N_("Scroll down one line without scrolling the cursor"); + const char *bracket_gist = N_("Go to the matching bracket"); + const char *scrollup_gist = + N_("Scroll up one line without scrolling the cursor"); + const char *scrolldown_gist = + N_("Scroll down one line without scrolling the cursor"); #endif #ifdef ENABLE_MULTIBUFFER - const char *prevfile_gist = N_("Switch to the previous file buffer"); - const char *nextfile_gist = N_("Switch to the next file buffer"); + const char *prevfile_gist = N_("Switch to the previous file buffer"); + const char *nextfile_gist = N_("Switch to the next file buffer"); #endif - const char *verbatim_gist = N_("Insert the next keystroke verbatim"); - const char *tab_gist = N_("Insert a tab at the cursor position"); - const char *enter_gist = N_("Insert a newline at the cursor position"); - const char *delete_gist = N_("Delete the character under the cursor"); - const char *backspace_gist = - N_("Delete the character to the left of the cursor"); + const char *verbatim_gist = N_("Insert the next keystroke verbatim"); + const char *tab_gist = N_("Insert a tab at the cursor position"); + const char *enter_gist = N_("Insert a newline at the cursor position"); + const char *delete_gist = N_("Delete the character under the cursor"); + const char *backspace_gist = + N_("Delete the character to the left of the cursor"); #ifndef NANO_TINY - const char *cutwordleft_gist = - N_("Cut backward from cursor to word start"); - const char *cutwordright_gist = - N_("Cut forward from cursor to next word start"); - const char *cuttilleof_gist = - N_("Cut from the cursor position to the end of the file"); + const char *cutwordleft_gist = + N_("Cut backward from cursor to word start"); + const char *cutwordright_gist = + N_("Cut forward from cursor to next word start"); + const char *cuttilleof_gist = + N_("Cut from the cursor position to the end of the file"); #endif #ifdef ENABLE_JUSTIFY - const char *justify_gist = N_("Justify the current paragraph"); - const char *fulljustify_gist = N_("Justify the entire file"); + const char *justify_gist = N_("Justify the current paragraph"); + const char *fulljustify_gist = N_("Justify the entire file"); #endif #ifndef NANO_TINY - const char *wordcount_gist = - N_("Count the number of words, lines, and characters"); + const char *wordcount_gist = + N_("Count the number of words, lines, and characters"); #endif - const char *refresh_gist = - N_("Refresh (redraw) the current screen"); - const char *suspend_gist = - N_("Suspend the editor (if suspension is enabled)"); + const char *refresh_gist = + N_("Refresh (redraw) the current screen"); + const char *suspend_gist = + N_("Suspend the editor (if suspension is enabled)"); #ifdef ENABLE_WORDCOMPLETION - const char *completion_gist = N_("Try and complete the current word"); + const char *completion_gist = N_("Try and complete the current word"); #endif #ifdef ENABLE_COMMENT - const char *comment_gist = - N_("Comment/uncomment the current line (or marked lines)"); + const char *comment_gist = + N_("Comment/uncomment the current line (or marked lines)"); #endif #ifndef NANO_TINY - const char *savefile_gist = N_("Save file without prompting"); - const char *findprev_gist = N_("Search next occurrence backward"); - const char *findnext_gist = N_("Search next occurrence forward"); - const char *recordmacro_gist = N_("Start/stop recording a macro"); - const char *runmacro_gist = N_("Run the last recorded macro"); + const char *savefile_gist = N_("Save file without prompting"); + const char *findprev_gist = N_("Search next occurrence backward"); + const char *findnext_gist = N_("Search next occurrence forward"); + const char *recordmacro_gist = N_("Start/stop recording a macro"); + const char *runmacro_gist = N_("Run the last recorded macro"); #endif - const char *case_gist = - N_("Toggle the case sensitivity of the search"); - const char *reverse_gist = - N_("Reverse the direction of the search"); - const char *regexp_gist = - N_("Toggle the use of regular expressions"); + const char *case_gist = + N_("Toggle the case sensitivity of the search"); + const char *reverse_gist = + N_("Reverse the direction of the search"); + const char *regexp_gist = + N_("Toggle the use of regular expressions"); #ifdef ENABLE_HISTORIES - const char *prevhistory_gist = - N_("Recall the previous search/replace string"); - const char *nexthistory_gist = - N_("Recall the next search/replace string"); + const char *prevhistory_gist = + N_("Recall the previous search/replace string"); + const char *nexthistory_gist = + N_("Recall the next search/replace string"); #endif #ifndef NANO_TINY - const char *dos_gist = N_("Toggle the use of DOS format"); - const char *mac_gist = N_("Toggle the use of Mac format"); - const char *append_gist = N_("Toggle appending"); - const char *prepend_gist = N_("Toggle prepending"); - const char *backup_gist = N_("Toggle backing up of the original file"); - const char *execute_gist = N_("Execute external command"); + const char *dos_gist = N_("Toggle the use of DOS format"); + const char *mac_gist = N_("Toggle the use of Mac format"); + const char *append_gist = N_("Toggle appending"); + const char *prepend_gist = N_("Toggle prepending"); + const char *backup_gist = N_("Toggle backing up of the original file"); + const char *execute_gist = N_("Execute external command"); #endif #ifdef ENABLE_MULTIBUFFER - const char *newbuffer_gist = N_("Toggle the use of a new buffer"); + const char *newbuffer_gist = N_("Toggle the use of a new buffer"); #endif - const char *discardbuffer_gist = N_("Close buffer without saving it"); + const char *discardbuffer_gist = N_("Close buffer without saving it"); #ifdef ENABLE_BROWSER - const char *tofiles_gist = N_("Go to file browser"); - const char *exitbrowser_gist = N_("Exit from the file browser"); - const char *firstfile_gist = N_("Go to the first file in the list"); - const char *lastfile_gist = N_("Go to the last file in the list"); - const char *backfile_gist = N_("Go to the previous file in the list"); - const char *forwardfile_gist = N_("Go to the next file in the list"); - const char *gotodir_gist = N_("Go to directory"); + const char *tofiles_gist = N_("Go to file browser"); + const char *exitbrowser_gist = N_("Exit from the file browser"); + const char *firstfile_gist = N_("Go to the first file in the list"); + const char *lastfile_gist = N_("Go to the last file in the list"); + const char *backfile_gist = N_("Go to the previous file in the list"); + const char *forwardfile_gist = N_("Go to the next file in the list"); + const char *gotodir_gist = N_("Go to directory"); #endif #ifdef ENABLE_COLOR - const char *lint_gist = N_("Invoke the linter, if available"); - const char *prevlint_gist = N_("Go to previous linter msg"); - const char *nextlint_gist = N_("Go to next linter msg"); + const char *lint_gist = N_("Invoke the linter, if available"); + const char *prevlint_gist = N_("Go to previous linter msg"); + const char *nextlint_gist = N_("Go to next linter msg"); #ifdef ENABLE_SPELLER - const char *formatter_gist = N_("Invoke formatter, if available"); + const char *formatter_gist = N_("Invoke formatter, if available"); #endif #endif #endif /* ENABLE_HELP */ @@ -689,678 +689,678 @@ void shortcut_init(void) #define WITHORSANS(help) "" #endif - /* Start populating the different menus with functions. */ + /* Start populating the different menus with functions. */ - add_to_funcs(do_help_void, MMOST & ~MFINDINHELP, - /* TRANSLATORS: Try to keep the following strings at most 10 characters. */ - N_("Get Help"), WITHORSANS(help_gist), TOGETHER, VIEW); + add_to_funcs(do_help_void, MMOST & ~MFINDINHELP, + /* TRANSLATORS: Try to keep the following strings at most 10 characters. */ + N_("Get Help"), WITHORSANS(help_gist), TOGETHER, VIEW); - add_to_funcs(do_cancel, ((MMOST & ~MMAIN & ~MBROWSER) | MYESNO), - N_("Cancel"), WITHORSANS(cancel_gist), BLANKAFTER, VIEW); + add_to_funcs(do_cancel, ((MMOST & ~MMAIN & ~MBROWSER) | MYESNO), + N_("Cancel"), WITHORSANS(cancel_gist), BLANKAFTER, VIEW); - add_to_funcs(do_exit, MMAIN, - exit_tag, WITHORSANS(exit_gist), TOGETHER, VIEW); - /* Remember the entry for Exit, to be able to replace it with Close. */ - exitfunc = tailfunc; + add_to_funcs(do_exit, MMAIN, + exit_tag, WITHORSANS(exit_gist), TOGETHER, VIEW); + /* Remember the entry for Exit, to be able to replace it with Close. */ + exitfunc = tailfunc; #ifdef ENABLE_BROWSER - add_to_funcs(do_exit, MBROWSER, - exit_tag, WITHORSANS(exitbrowser_gist), TOGETHER, VIEW); + add_to_funcs(do_exit, MBROWSER, + exit_tag, WITHORSANS(exitbrowser_gist), TOGETHER, VIEW); #endif - add_to_funcs(do_writeout_void, MMAIN, - N_("Write Out"), WITHORSANS(writeout_gist), TOGETHER, NOVIEW); + add_to_funcs(do_writeout_void, MMAIN, + N_("Write Out"), WITHORSANS(writeout_gist), TOGETHER, NOVIEW); #ifdef ENABLE_JUSTIFY - if (!ISSET(RESTRICTED)) { + if (!ISSET(RESTRICTED)) { #else - /* If we can't replace Insert with Justify, show Insert anyway, to - * keep the help items nicely paired also in restricted mode. */ - if (TRUE) { + /* If we can't replace Insert with Justify, show Insert anyway, to + * keep the help items nicely paired also in restricted mode. */ + if (TRUE) { #endif - add_to_funcs(do_insertfile_void, MMAIN, - readfile_tag, WITHORSANS(readfile_gist), BLANKAFTER, - /* We allow inserting files in view mode if multibuffer mode - * is switched on, so that we can view multiple files. */ + add_to_funcs(do_insertfile_void, MMAIN, + readfile_tag, WITHORSANS(readfile_gist), BLANKAFTER, + /* We allow inserting files in view mode if multibuffer mode + * is switched on, so that we can view multiple files. */ #ifdef ENABLE_MULTIBUFFER - VIEW); + VIEW); #else - NOVIEW); + NOVIEW); #endif - } else { + } else { #ifdef ENABLE_JUSTIFY - add_to_funcs(do_justify_void, MMAIN, - justify_tag, WITHORSANS(justify_gist), BLANKAFTER, NOVIEW); + add_to_funcs(do_justify_void, MMAIN, + justify_tag, WITHORSANS(justify_gist), BLANKAFTER, NOVIEW); #endif - } + } - add_to_funcs(do_search_forward, MMAIN, - whereis_tag, WITHORSANS(whereis_gist), TOGETHER, VIEW); + add_to_funcs(do_search_forward, MMAIN, + whereis_tag, WITHORSANS(whereis_gist), TOGETHER, VIEW); - add_to_funcs(do_replace, MMAIN, - replace_tag, WITHORSANS(replace_gist), TOGETHER, NOVIEW); + add_to_funcs(do_replace, MMAIN, + replace_tag, WITHORSANS(replace_gist), TOGETHER, NOVIEW); #ifdef ENABLE_BROWSER - add_to_funcs(do_search_forward, MBROWSER, - whereis_tag, WITHORSANS(browserwhereis_gist), TOGETHER, VIEW); + add_to_funcs(do_search_forward, MBROWSER, + whereis_tag, WITHORSANS(browserwhereis_gist), TOGETHER, VIEW); - add_to_funcs(do_research, MBROWSER, - whereisnext_tag, WITHORSANS(whereisnext_gist), BLANKAFTER, VIEW); + add_to_funcs(do_research, MBROWSER, + whereisnext_tag, WITHORSANS(whereisnext_gist), BLANKAFTER, VIEW); - add_to_funcs(goto_dir_void, MBROWSER, - N_("Go To Dir"), WITHORSANS(gotodir_gist), TOGETHER, VIEW); + add_to_funcs(goto_dir_void, MBROWSER, + N_("Go To Dir"), WITHORSANS(gotodir_gist), TOGETHER, VIEW); - add_to_funcs(total_refresh, MBROWSER, - refresh_tag, WITHORSANS(browserrefresh_gist), BLANKAFTER, VIEW); + add_to_funcs(total_refresh, MBROWSER, + refresh_tag, WITHORSANS(browserrefresh_gist), BLANKAFTER, VIEW); #endif #ifdef ENABLE_HELP - /* The description ("x") and blank_after (0) are irrelevant, - * because the help viewer does not have a help text. */ - add_to_funcs(total_refresh, MHELP, refresh_tag, "x", 0, VIEW); - add_to_funcs(do_exit, MHELP, close_tag, "x", 0, VIEW); + /* The description ("x") and blank_after (0) are irrelevant, + * because the help viewer does not have a help text. */ + add_to_funcs(total_refresh, MHELP, refresh_tag, "x", 0, VIEW); + add_to_funcs(do_exit, MHELP, close_tag, "x", 0, VIEW); - add_to_funcs(do_search_forward, MHELP, whereis_tag, "x", 0, VIEW); - add_to_funcs(do_research, MHELP, whereisnext_tag, "x", 0, VIEW); + add_to_funcs(do_search_forward, MHELP, whereis_tag, "x", 0, VIEW); + add_to_funcs(do_research, MHELP, whereisnext_tag, "x", 0, VIEW); #endif - add_to_funcs(do_cut_text_void, MMAIN, - N_("Cut Text"), WITHORSANS(cut_gist), TOGETHER, NOVIEW); + add_to_funcs(do_cut_text_void, MMAIN, + N_("Cut Text"), WITHORSANS(cut_gist), TOGETHER, NOVIEW); - add_to_funcs(do_uncut_text, MMAIN, - uncut_tag, WITHORSANS(uncut_gist), BLANKAFTER, NOVIEW); - /* Remember the entry for Uncut, to be able to replace it with Unjustify. */ - uncutfunc = tailfunc; + add_to_funcs(do_uncut_text, MMAIN, + uncut_tag, WITHORSANS(uncut_gist), BLANKAFTER, NOVIEW); + /* Remember the entry for Uncut, to be able to replace it with Unjustify. */ + uncutfunc = tailfunc; - if (!ISSET(RESTRICTED)) { + if (!ISSET(RESTRICTED)) { #ifdef ENABLE_JUSTIFY - add_to_funcs(do_justify_void, MMAIN, - justify_tag, WITHORSANS(justify_gist), TOGETHER, NOVIEW); + add_to_funcs(do_justify_void, MMAIN, + justify_tag, WITHORSANS(justify_gist), TOGETHER, NOVIEW); #endif #ifdef ENABLE_SPELLER - add_to_funcs(do_spell, MMAIN, - N_("To Spell"), WITHORSANS(spell_gist), TOGETHER, NOVIEW); + add_to_funcs(do_spell, MMAIN, + N_("To Spell"), WITHORSANS(spell_gist), TOGETHER, NOVIEW); #endif #ifdef ENABLE_COLOR - add_to_funcs(do_linter, MMAIN, - N_("To Linter"), WITHORSANS(lint_gist), TOGETHER, NOVIEW); + add_to_funcs(do_linter, MMAIN, + N_("To Linter"), WITHORSANS(lint_gist), TOGETHER, NOVIEW); #ifdef ENABLE_SPELLER - add_to_funcs(do_formatter, MMAIN, - N_("Formatter"), WITHORSANS(formatter_gist), BLANKAFTER, NOVIEW); + add_to_funcs(do_formatter, MMAIN, + N_("Formatter"), WITHORSANS(formatter_gist), BLANKAFTER, NOVIEW); #endif #endif - } + } - add_to_funcs(do_cursorpos_void, MMAIN, - N_("Cur Pos"), WITHORSANS(cursorpos_gist), TOGETHER, VIEW); + add_to_funcs(do_cursorpos_void, MMAIN, + N_("Cur Pos"), WITHORSANS(cursorpos_gist), TOGETHER, VIEW); #if (defined(ENABLE_JUSTIFY) && (defined(ENABLE_SPELLER) || defined(ENABLE_COLOR)) || \ - !defined(ENABLE_JUSTIFY) && !defined(ENABLE_SPELLER) && !defined(ENABLE_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, - gotoline_tag, WITHORSANS(gotoline_gist), BLANKAFTER, VIEW); + !defined(ENABLE_JUSTIFY) && !defined(ENABLE_SPELLER) && !defined(ENABLE_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, + gotoline_tag, WITHORSANS(gotoline_gist), BLANKAFTER, VIEW); #endif #ifndef NANO_TINY - add_to_funcs(do_undo, MMAIN, - N_("Undo"), WITHORSANS(undo_gist), TOGETHER, NOVIEW); - add_to_funcs(do_redo, MMAIN, - N_("Redo"), WITHORSANS(redo_gist), BLANKAFTER, NOVIEW); + add_to_funcs(do_undo, MMAIN, + N_("Undo"), WITHORSANS(undo_gist), TOGETHER, NOVIEW); + add_to_funcs(do_redo, MMAIN, + N_("Redo"), WITHORSANS(redo_gist), BLANKAFTER, NOVIEW); - add_to_funcs(do_mark, MMAIN, - N_("Mark Text"), WITHORSANS(mark_gist), TOGETHER, VIEW); - add_to_funcs(do_copy_text, MMAIN, - N_("Copy Text"), WITHORSANS(copy_gist), BLANKAFTER, NOVIEW); + add_to_funcs(do_mark, MMAIN, + N_("Mark Text"), WITHORSANS(mark_gist), TOGETHER, VIEW); + add_to_funcs(do_copy_text, MMAIN, + N_("Copy Text"), WITHORSANS(copy_gist), BLANKAFTER, NOVIEW); #endif - add_to_funcs(case_sens_void, MWHEREIS|MREPLACE, - N_("Case Sens"), WITHORSANS(case_gist), TOGETHER, VIEW); - add_to_funcs(regexp_void, MWHEREIS|MREPLACE, - N_("Regexp"), WITHORSANS(regexp_gist), TOGETHER, VIEW); - add_to_funcs(backwards_void, MWHEREIS|MREPLACE, - N_("Backwards"), WITHORSANS(reverse_gist), TOGETHER, VIEW); + add_to_funcs(case_sens_void, MWHEREIS|MREPLACE, + N_("Case Sens"), WITHORSANS(case_gist), TOGETHER, VIEW); + add_to_funcs(regexp_void, MWHEREIS|MREPLACE, + N_("Regexp"), WITHORSANS(regexp_gist), TOGETHER, VIEW); + add_to_funcs(backwards_void, MWHEREIS|MREPLACE, + N_("Backwards"), WITHORSANS(reverse_gist), TOGETHER, VIEW); - add_to_funcs(flip_replace, MWHEREIS, - replace_tag, WITHORSANS(replace_gist), BLANKAFTER, VIEW); + add_to_funcs(flip_replace, MWHEREIS, + replace_tag, WITHORSANS(replace_gist), BLANKAFTER, VIEW); - add_to_funcs(flip_replace, MREPLACE, - N_("No Replace"), WITHORSANS(whereis_gist), BLANKAFTER, VIEW); + add_to_funcs(flip_replace, MREPLACE, + N_("No Replace"), WITHORSANS(whereis_gist), BLANKAFTER, VIEW); #ifdef ENABLE_JUSTIFY - add_to_funcs(do_full_justify, MWHEREIS, - fulljustify_tag, WITHORSANS(fulljustify_gist), TOGETHER, NOVIEW); + add_to_funcs(do_full_justify, MWHEREIS, + fulljustify_tag, WITHORSANS(fulljustify_gist), TOGETHER, NOVIEW); - add_to_funcs(do_gotolinecolumn_void, MWHEREIS, - gotoline_tag, WITHORSANS(gotoline_gist), BLANKAFTER, VIEW); + add_to_funcs(do_gotolinecolumn_void, MWHEREIS, + gotoline_tag, WITHORSANS(gotoline_gist), BLANKAFTER, VIEW); #endif #ifndef NANO_TINY - add_to_funcs(do_find_bracket, MMAIN, - N_("To Bracket"), WITHORSANS(bracket_gist), BLANKAFTER, VIEW); + add_to_funcs(do_find_bracket, MMAIN, + N_("To Bracket"), WITHORSANS(bracket_gist), BLANKAFTER, VIEW); - add_to_funcs(do_research, MMAIN, - whereisnext_tag, WITHORSANS(whereisnext_gist), TOGETHER, VIEW); + add_to_funcs(do_research, MMAIN, + whereisnext_tag, WITHORSANS(whereisnext_gist), TOGETHER, VIEW); - add_to_funcs(do_findprevious, MMAIN, - N_("Previous"), WITHORSANS(findprev_gist), TOGETHER, VIEW); - add_to_funcs(do_findnext, MMAIN, - N_("Next"), WITHORSANS(findnext_gist), BLANKAFTER, VIEW); + add_to_funcs(do_findprevious, MMAIN, + N_("Previous"), WITHORSANS(findprev_gist), TOGETHER, VIEW); + add_to_funcs(do_findnext, MMAIN, + N_("Next"), WITHORSANS(findnext_gist), BLANKAFTER, VIEW); #endif /* !NANO_TINY */ - add_to_funcs(do_left, MMAIN, - N_("Back"), WITHORSANS(back_gist), TOGETHER, VIEW); - add_to_funcs(do_right, MMAIN, - N_("Forward"), WITHORSANS(forward_gist), TOGETHER, VIEW); + add_to_funcs(do_left, MMAIN, + N_("Back"), WITHORSANS(back_gist), TOGETHER, VIEW); + add_to_funcs(do_right, MMAIN, + N_("Forward"), WITHORSANS(forward_gist), TOGETHER, VIEW); #ifdef ENABLE_BROWSER - add_to_funcs(do_left, MBROWSER, - N_("Back"), WITHORSANS(backfile_gist), TOGETHER, VIEW); - add_to_funcs(do_right, MBROWSER, - N_("Forward"), WITHORSANS(forwardfile_gist), TOGETHER, VIEW); + add_to_funcs(do_left, MBROWSER, + N_("Back"), WITHORSANS(backfile_gist), TOGETHER, VIEW); + add_to_funcs(do_right, MBROWSER, + N_("Forward"), WITHORSANS(forwardfile_gist), TOGETHER, VIEW); #endif - add_to_funcs(do_prev_word_void, MMAIN, - N_("Prev Word"), WITHORSANS(prevword_gist), TOGETHER, VIEW); - add_to_funcs(do_next_word_void, MMAIN, - N_("Next Word"), WITHORSANS(nextword_gist), TOGETHER, VIEW); + add_to_funcs(do_prev_word_void, MMAIN, + N_("Prev Word"), WITHORSANS(prevword_gist), TOGETHER, VIEW); + add_to_funcs(do_next_word_void, MMAIN, + N_("Next Word"), WITHORSANS(nextword_gist), TOGETHER, VIEW); - add_to_funcs(do_home, MMAIN, - N_("Home"), WITHORSANS(home_gist), TOGETHER, VIEW); - add_to_funcs(do_end, MMAIN, - N_("End"), WITHORSANS(end_gist), BLANKAFTER, VIEW); + add_to_funcs(do_home, MMAIN, + N_("Home"), WITHORSANS(home_gist), TOGETHER, VIEW); + add_to_funcs(do_end, MMAIN, + N_("End"), WITHORSANS(end_gist), BLANKAFTER, VIEW); - add_to_funcs(do_up_void, MMAIN|MHELP|MBROWSER, - prevline_tag, WITHORSANS(prevline_gist), TOGETHER, VIEW); - add_to_funcs(do_down_void, MMAIN|MHELP|MBROWSER, - nextline_tag, WITHORSANS(nextline_gist), TOGETHER, VIEW); + add_to_funcs(do_up_void, MMAIN|MHELP|MBROWSER, + prevline_tag, WITHORSANS(prevline_gist), TOGETHER, VIEW); + add_to_funcs(do_down_void, MMAIN|MHELP|MBROWSER, + nextline_tag, WITHORSANS(nextline_gist), TOGETHER, VIEW); #ifndef NANO_TINY - add_to_funcs(do_scroll_up, MMAIN, - N_("Scroll Up"), WITHORSANS(scrollup_gist), TOGETHER, VIEW); - add_to_funcs(do_scroll_down, MMAIN, - N_("Scroll Down"), WITHORSANS(scrolldown_gist), BLANKAFTER, VIEW); + add_to_funcs(do_scroll_up, MMAIN, + N_("Scroll Up"), WITHORSANS(scrollup_gist), TOGETHER, VIEW); + add_to_funcs(do_scroll_down, MMAIN, + N_("Scroll Down"), WITHORSANS(scrolldown_gist), BLANKAFTER, VIEW); #endif - add_to_funcs(do_prev_block, MMAIN, - N_("Prev Block"), WITHORSANS(prevblock_gist), TOGETHER, VIEW); - add_to_funcs(do_next_block, MMAIN, - N_("Next Block"), WITHORSANS(nextblock_gist), TOGETHER, VIEW); + add_to_funcs(do_prev_block, MMAIN, + N_("Prev Block"), WITHORSANS(prevblock_gist), TOGETHER, VIEW); + add_to_funcs(do_next_block, MMAIN, + N_("Next Block"), WITHORSANS(nextblock_gist), TOGETHER, VIEW); #ifdef ENABLE_JUSTIFY - add_to_funcs(do_para_begin_void, MMAIN|MWHEREIS, - N_("Beg of Par"), WITHORSANS(parabegin_gist), TOGETHER, VIEW); - add_to_funcs(do_para_end_void, MMAIN|MWHEREIS, - N_("End of Par"), WITHORSANS(paraend_gist), BLANKAFTER, VIEW); + add_to_funcs(do_para_begin_void, MMAIN|MWHEREIS, + N_("Beg of Par"), WITHORSANS(parabegin_gist), TOGETHER, VIEW); + add_to_funcs(do_para_end_void, MMAIN|MWHEREIS, + N_("End of Par"), WITHORSANS(paraend_gist), BLANKAFTER, VIEW); #endif - add_to_funcs(do_page_up, MMAIN|MHELP, - prevpage_tag, WITHORSANS(prevpage_gist), TOGETHER, VIEW); - add_to_funcs(do_page_down, MMAIN|MHELP, - nextpage_tag, WITHORSANS(nextpage_gist), TOGETHER, VIEW); + add_to_funcs(do_page_up, MMAIN|MHELP, + prevpage_tag, WITHORSANS(prevpage_gist), TOGETHER, VIEW); + add_to_funcs(do_page_down, MMAIN|MHELP, + nextpage_tag, WITHORSANS(nextpage_gist), TOGETHER, VIEW); - add_to_funcs(to_first_line, MMAIN|MHELP|MWHEREIS|MREPLACE|MREPLACEWITH|MGOTOLINE, - N_("First Line"), WITHORSANS(firstline_gist), TOGETHER, VIEW); - add_to_funcs(to_last_line, MMAIN|MHELP|MWHEREIS|MREPLACE|MREPLACEWITH|MGOTOLINE, - N_("Last Line"), WITHORSANS(lastline_gist), BLANKAFTER, VIEW); + add_to_funcs(to_first_line, MMAIN|MHELP|MWHEREIS|MREPLACE|MREPLACEWITH|MGOTOLINE, + N_("First Line"), WITHORSANS(firstline_gist), TOGETHER, VIEW); + add_to_funcs(to_last_line, MMAIN|MHELP|MWHEREIS|MREPLACE|MREPLACEWITH|MGOTOLINE, + N_("Last Line"), WITHORSANS(lastline_gist), BLANKAFTER, VIEW); #ifdef ENABLE_MULTIBUFFER - add_to_funcs(switch_to_prev_buffer, MMAIN, - N_("Prev File"), WITHORSANS(prevfile_gist), TOGETHER, VIEW); - add_to_funcs(switch_to_next_buffer, MMAIN, - N_("Next File"), WITHORSANS(nextfile_gist), BLANKAFTER, VIEW); + add_to_funcs(switch_to_prev_buffer, MMAIN, + N_("Prev File"), WITHORSANS(prevfile_gist), TOGETHER, VIEW); + add_to_funcs(switch_to_next_buffer, MMAIN, + N_("Next File"), WITHORSANS(nextfile_gist), BLANKAFTER, VIEW); #endif #if (!defined(ENABLE_JUSTIFY) && (defined(ENABLE_SPELLER) || defined(ENABLE_COLOR)) || \ - defined(ENABLE_JUSTIFY) && !defined(ENABLE_SPELLER) && !defined(ENABLE_COLOR)) - add_to_funcs(do_gotolinecolumn_void, MMAIN, - gotoline_tag, WITHORSANS(gotoline_gist), BLANKAFTER, VIEW); + defined(ENABLE_JUSTIFY) && !defined(ENABLE_SPELLER) && !defined(ENABLE_COLOR)) + add_to_funcs(do_gotolinecolumn_void, MMAIN, + gotoline_tag, WITHORSANS(gotoline_gist), BLANKAFTER, VIEW); #endif #ifdef NANO_TINY - /* Place this one here only in the tiny version; otherwise further up. */ - add_to_funcs(do_research, MMAIN, - whereisnext_tag, WITHORSANS(whereisnext_gist), TOGETHER, VIEW); + /* Place this one here only in the tiny version; otherwise further up. */ + add_to_funcs(do_research, MMAIN, + whereisnext_tag, WITHORSANS(whereisnext_gist), TOGETHER, VIEW); #endif - add_to_funcs(do_tab, MMAIN, - N_("Tab"), WITHORSANS(tab_gist), TOGETHER, NOVIEW); - add_to_funcs(do_enter, MMAIN, - N_("Enter"), WITHORSANS(enter_gist), BLANKAFTER, NOVIEW); + add_to_funcs(do_tab, MMAIN, + N_("Tab"), WITHORSANS(tab_gist), TOGETHER, NOVIEW); + add_to_funcs(do_enter, MMAIN, + N_("Enter"), WITHORSANS(enter_gist), BLANKAFTER, NOVIEW); - add_to_funcs(do_delete, MMAIN, - N_("Delete"), WITHORSANS(delete_gist), TOGETHER, NOVIEW); - add_to_funcs(do_backspace, MMAIN, - N_("Backspace"), WITHORSANS(backspace_gist), + add_to_funcs(do_delete, MMAIN, + N_("Delete"), WITHORSANS(delete_gist), TOGETHER, NOVIEW); + add_to_funcs(do_backspace, MMAIN, + N_("Backspace"), WITHORSANS(backspace_gist), #ifndef NANO_TINY - TOGETHER, + TOGETHER, #else - BLANKAFTER, + BLANKAFTER, #endif - NOVIEW); + NOVIEW); #ifndef NANO_TINY - add_to_funcs(do_cut_prev_word, MMAIN, - /* TRANSLATORS: The next two strings refer to cutting words. */ - N_("Cut Left"), WITHORSANS(cutwordleft_gist), TOGETHER, NOVIEW); - add_to_funcs(do_cut_next_word, MMAIN, - N_("Cut Right"), WITHORSANS(cutwordright_gist), TOGETHER, NOVIEW); - add_to_funcs(do_cut_till_eof, MMAIN, - N_("CutTillEnd"), WITHORSANS(cuttilleof_gist), BLANKAFTER, NOVIEW); + add_to_funcs(do_cut_prev_word, MMAIN, + /* TRANSLATORS: The next two strings refer to cutting words. */ + N_("Cut Left"), WITHORSANS(cutwordleft_gist), TOGETHER, NOVIEW); + add_to_funcs(do_cut_next_word, MMAIN, + N_("Cut Right"), WITHORSANS(cutwordright_gist), TOGETHER, NOVIEW); + add_to_funcs(do_cut_till_eof, MMAIN, + N_("CutTillEnd"), WITHORSANS(cuttilleof_gist), BLANKAFTER, NOVIEW); #endif #ifdef ENABLE_JUSTIFY - add_to_funcs(do_full_justify, MMAIN, - fulljustify_tag, WITHORSANS(fulljustify_gist), TOGETHER, NOVIEW); + add_to_funcs(do_full_justify, MMAIN, + fulljustify_tag, WITHORSANS(fulljustify_gist), TOGETHER, NOVIEW); #endif #ifndef NANO_TINY - add_to_funcs(do_wordlinechar_count, MMAIN, - N_("Word Count"), WITHORSANS(wordcount_gist), TOGETHER, VIEW); + add_to_funcs(do_wordlinechar_count, MMAIN, + N_("Word Count"), WITHORSANS(wordcount_gist), TOGETHER, VIEW); #endif - add_to_funcs(do_verbatim_input, MMAIN, - N_("Verbatim"), WITHORSANS(verbatim_gist), BLANKAFTER, NOVIEW); + add_to_funcs(do_verbatim_input, MMAIN, + N_("Verbatim"), WITHORSANS(verbatim_gist), BLANKAFTER, NOVIEW); - add_to_funcs(total_refresh, MMAIN, - refresh_tag, WITHORSANS(refresh_gist), TOGETHER, VIEW); + add_to_funcs(total_refresh, MMAIN, + refresh_tag, WITHORSANS(refresh_gist), TOGETHER, VIEW); - add_to_funcs(do_suspend_void, MMAIN, - N_("Suspend"), WITHORSANS(suspend_gist), BLANKAFTER, VIEW); + add_to_funcs(do_suspend_void, MMAIN, + N_("Suspend"), WITHORSANS(suspend_gist), BLANKAFTER, VIEW); #ifndef NANO_TINY - add_to_funcs(do_indent, MMAIN, - N_("Indent Text"), WITHORSANS(indent_gist), TOGETHER, NOVIEW); - add_to_funcs(do_unindent, MMAIN, - N_("Unindent Text"), WITHORSANS(unindent_gist), BLANKAFTER, NOVIEW); + add_to_funcs(do_indent, MMAIN, + N_("Indent Text"), WITHORSANS(indent_gist), TOGETHER, NOVIEW); + add_to_funcs(do_unindent, MMAIN, + N_("Unindent Text"), WITHORSANS(unindent_gist), BLANKAFTER, NOVIEW); #endif #ifdef ENABLE_COMMENT - add_to_funcs(do_comment, MMAIN, - N_("Comment Lines"), WITHORSANS(comment_gist), TOGETHER, NOVIEW); + add_to_funcs(do_comment, MMAIN, + N_("Comment Lines"), WITHORSANS(comment_gist), TOGETHER, NOVIEW); #endif #ifdef ENABLE_WORDCOMPLETION - add_to_funcs(complete_a_word, MMAIN, - N_("Complete"), WITHORSANS(completion_gist), BLANKAFTER, NOVIEW); + add_to_funcs(complete_a_word, MMAIN, + N_("Complete"), WITHORSANS(completion_gist), BLANKAFTER, NOVIEW); #endif #ifndef NANO_TINY - add_to_funcs(record_macro, MMAIN, - N_("Record"), WITHORSANS(recordmacro_gist), TOGETHER, VIEW); - add_to_funcs(run_macro, MMAIN, - N_("Run Macro"), WITHORSANS(runmacro_gist), BLANKAFTER, VIEW); + add_to_funcs(record_macro, MMAIN, + N_("Record"), WITHORSANS(recordmacro_gist), TOGETHER, VIEW); + add_to_funcs(run_macro, MMAIN, + N_("Run Macro"), WITHORSANS(runmacro_gist), BLANKAFTER, VIEW); - add_to_funcs(do_search_backward, MMAIN, - /* TRANSLATORS: This starts a backward search. */ - N_("Where Was"), WITHORSANS(wherewas_gist), BLANKAFTER, VIEW); + add_to_funcs(do_search_backward, MMAIN, + /* TRANSLATORS: This starts a backward search. */ + N_("Where Was"), WITHORSANS(wherewas_gist), BLANKAFTER, VIEW); - add_to_funcs(do_savefile, MMAIN, - N_("Save"), WITHORSANS(savefile_gist), BLANKAFTER, NOVIEW); + add_to_funcs(do_savefile, MMAIN, + N_("Save"), WITHORSANS(savefile_gist), BLANKAFTER, NOVIEW); #endif #ifdef ENABLE_HISTORIES - add_to_funcs(get_history_older_void, MWHEREIS|MREPLACE|MREPLACEWITH|MWHEREISFILE, - N_("PrevHstory"), WITHORSANS(prevhistory_gist), TOGETHER, VIEW); - add_to_funcs(get_history_newer_void, MWHEREIS|MREPLACE|MREPLACEWITH|MWHEREISFILE, - N_("NextHstory"), WITHORSANS(nexthistory_gist), BLANKAFTER, VIEW); + add_to_funcs(get_history_older_void, MWHEREIS|MREPLACE|MREPLACEWITH|MWHEREISFILE, + N_("PrevHstory"), WITHORSANS(prevhistory_gist), TOGETHER, VIEW); + add_to_funcs(get_history_newer_void, MWHEREIS|MREPLACE|MREPLACEWITH|MWHEREISFILE, + N_("NextHstory"), WITHORSANS(nexthistory_gist), BLANKAFTER, VIEW); #endif #ifndef ENABLE_JUSTIFY - add_to_funcs(do_gotolinecolumn_void, MWHEREIS, - gotoline_tag, WITHORSANS(gotoline_gist), BLANKAFTER, VIEW); + add_to_funcs(do_gotolinecolumn_void, MWHEREIS, + gotoline_tag, WITHORSANS(gotoline_gist), BLANKAFTER, VIEW); #endif - add_to_funcs(gototext_void, MGOTOLINE, - N_("Go To Text"), WITHORSANS(whereis_gist), BLANKAFTER, VIEW); + add_to_funcs(gototext_void, MGOTOLINE, + N_("Go To Text"), WITHORSANS(whereis_gist), BLANKAFTER, VIEW); #ifndef NANO_TINY - add_to_funcs(dos_format_void, MWRITEFILE, - N_("DOS Format"), WITHORSANS(dos_gist), TOGETHER, NOVIEW); - add_to_funcs(mac_format_void, MWRITEFILE, - N_("Mac Format"), WITHORSANS(mac_gist), TOGETHER, NOVIEW); + add_to_funcs(dos_format_void, MWRITEFILE, + N_("DOS Format"), WITHORSANS(dos_gist), TOGETHER, NOVIEW); + add_to_funcs(mac_format_void, MWRITEFILE, + N_("Mac Format"), WITHORSANS(mac_gist), TOGETHER, NOVIEW); - /* If we're using restricted mode, the Append, Prepend, and Backup toggles - * are disabled. The first and second are not useful as they only allow - * reduplicating the current file, and the third is not allowed as it - * would write to a file not specified on the command line. */ - if (!ISSET(RESTRICTED)) { - add_to_funcs(append_void, MWRITEFILE, - N_("Append"), WITHORSANS(append_gist), TOGETHER, NOVIEW); - add_to_funcs(prepend_void, MWRITEFILE, - N_("Prepend"), WITHORSANS(prepend_gist), TOGETHER, NOVIEW); + /* If we're using restricted mode, the Append, Prepend, and Backup toggles + * are disabled. The first and second are not useful as they only allow + * reduplicating the current file, and the third is not allowed as it + * would write to a file not specified on the command line. */ + if (!ISSET(RESTRICTED)) { + add_to_funcs(append_void, MWRITEFILE, + N_("Append"), WITHORSANS(append_gist), TOGETHER, NOVIEW); + add_to_funcs(prepend_void, MWRITEFILE, + N_("Prepend"), WITHORSANS(prepend_gist), TOGETHER, NOVIEW); - add_to_funcs(backup_file_void, MWRITEFILE, - N_("Backup File"), WITHORSANS(backup_gist), BLANKAFTER, NOVIEW); - } + add_to_funcs(backup_file_void, MWRITEFILE, + N_("Backup File"), WITHORSANS(backup_gist), BLANKAFTER, NOVIEW); + } - /* If we're using restricted mode, file insertion is disabled, and - * thus command execution and the multibuffer toggle have no place. */ - if (!ISSET(RESTRICTED)) { - add_to_funcs(flip_execute, MINSERTFILE, - N_("Execute Command"), WITHORSANS(execute_gist), TOGETHER, NOVIEW); + /* If we're using restricted mode, file insertion is disabled, and + * thus command execution and the multibuffer toggle have no place. */ + if (!ISSET(RESTRICTED)) { + add_to_funcs(flip_execute, MINSERTFILE, + N_("Execute Command"), WITHORSANS(execute_gist), TOGETHER, NOVIEW); - add_to_funcs(flip_execute, MEXTCMD, - readfile_tag, WITHORSANS(readfile_gist), TOGETHER, NOVIEW); - } + add_to_funcs(flip_execute, MEXTCMD, + readfile_tag, WITHORSANS(readfile_gist), TOGETHER, NOVIEW); + } #endif /* !NANO_TINY */ #ifdef ENABLE_MULTIBUFFER - if (!ISSET(RESTRICTED)) - add_to_funcs(flip_newbuffer, MINSERTFILE|MEXTCMD, - N_("New Buffer"), WITHORSANS(newbuffer_gist), TOGETHER, NOVIEW); + if (!ISSET(RESTRICTED)) + add_to_funcs(flip_newbuffer, MINSERTFILE|MEXTCMD, + N_("New Buffer"), WITHORSANS(newbuffer_gist), TOGETHER, NOVIEW); #endif #ifdef ENABLE_BROWSER - if (!ISSET(RESTRICTED)) - add_to_funcs(to_files_void, MWRITEFILE|MINSERTFILE, - N_("To Files"), WITHORSANS(tofiles_gist), TOGETHER, VIEW); + if (!ISSET(RESTRICTED)) + add_to_funcs(to_files_void, MWRITEFILE|MINSERTFILE, + N_("To Files"), WITHORSANS(tofiles_gist), TOGETHER, VIEW); - add_to_funcs(do_page_up, MBROWSER, - prevpage_tag, WITHORSANS(prevpage_gist), TOGETHER, VIEW); - add_to_funcs(do_page_down, MBROWSER, - nextpage_tag, WITHORSANS(nextpage_gist), TOGETHER, VIEW); + add_to_funcs(do_page_up, MBROWSER, + prevpage_tag, WITHORSANS(prevpage_gist), TOGETHER, VIEW); + add_to_funcs(do_page_down, MBROWSER, + nextpage_tag, WITHORSANS(nextpage_gist), TOGETHER, VIEW); - add_to_funcs(to_first_file, MBROWSER|MWHEREISFILE, - N_("First File"), WITHORSANS(firstfile_gist), TOGETHER, VIEW); - add_to_funcs(to_last_file, MBROWSER|MWHEREISFILE, - N_("Last File"), WITHORSANS(lastfile_gist), BLANKAFTER, VIEW); + add_to_funcs(to_first_file, MBROWSER|MWHEREISFILE, + N_("First File"), WITHORSANS(firstfile_gist), TOGETHER, VIEW); + add_to_funcs(to_last_file, MBROWSER|MWHEREISFILE, + N_("Last File"), WITHORSANS(lastfile_gist), BLANKAFTER, VIEW); #ifndef NANO_TINY - add_to_funcs(do_prev_word_void, MBROWSER, - N_("Left Column"), WITHORSANS(browserlefthand_gist), TOGETHER, VIEW); - add_to_funcs(do_next_word_void, MBROWSER, - N_("Right Column"), WITHORSANS(browserrighthand_gist), TOGETHER, VIEW); - add_to_funcs(do_prev_block, MBROWSER, - N_("Top Row"), WITHORSANS(browsertoprow_gist), TOGETHER, VIEW); - add_to_funcs(do_next_block, MBROWSER, - N_("Bottom Row"), WITHORSANS(browserbottomrow_gist), BLANKAFTER, VIEW); + add_to_funcs(do_prev_word_void, MBROWSER, + N_("Left Column"), WITHORSANS(browserlefthand_gist), TOGETHER, VIEW); + add_to_funcs(do_next_word_void, MBROWSER, + N_("Right Column"), WITHORSANS(browserrighthand_gist), TOGETHER, VIEW); + add_to_funcs(do_prev_block, MBROWSER, + N_("Top Row"), WITHORSANS(browsertoprow_gist), TOGETHER, VIEW); + add_to_funcs(do_next_block, MBROWSER, + N_("Bottom Row"), WITHORSANS(browserbottomrow_gist), BLANKAFTER, VIEW); #endif #endif /* ENABLE_BROWSER */ - add_to_funcs(discard_buffer, MWRITEFILE, - N_("Discard buffer"), WITHORSANS(discardbuffer_gist), BLANKAFTER, NOVIEW); + add_to_funcs(discard_buffer, MWRITEFILE, + N_("Discard buffer"), WITHORSANS(discardbuffer_gist), BLANKAFTER, NOVIEW); #ifdef ENABLE_COLOR - add_to_funcs(do_page_up, MLINTER, - /* TRANSLATORS: Try to keep the next two strings at most 20 characters. */ - N_("Prev Lint Msg"), WITHORSANS(prevlint_gist), TOGETHER, VIEW); - add_to_funcs(do_page_down, MLINTER, - N_("Next Lint Msg"), WITHORSANS(nextlint_gist), TOGETHER, VIEW); + add_to_funcs(do_page_up, MLINTER, + /* TRANSLATORS: Try to keep the next two strings at most 20 characters. */ + N_("Prev Lint Msg"), WITHORSANS(prevlint_gist), TOGETHER, VIEW); + add_to_funcs(do_page_down, MLINTER, + N_("Next Lint Msg"), WITHORSANS(nextlint_gist), TOGETHER, VIEW); #endif - /* Link key combos to functions in certain menus. */ - add_to_sclist(MMOST, "^M", 0, do_enter, 0); - add_to_sclist(MMOST, "Enter", KEY_ENTER, do_enter, 0); - add_to_sclist(MMOST, "^H", 0, do_backspace, 0); - add_to_sclist(MMOST, "Bsp", KEY_BACKSPACE, do_backspace, 0); - add_to_sclist(MMOST, "^D", 0, do_delete, 0); - add_to_sclist(MMOST, "Del", 0, do_delete, 0); - add_to_sclist(MMOST, "^I", 0, do_tab, 0); - add_to_sclist(MMOST, "Tab", TAB_CODE, do_tab, 0); - add_to_sclist(MMOST & ~MFINDINHELP, "^G", 0, do_help_void, 0); - add_to_sclist(MMOST & ~MFINDINHELP, "F1", 0, do_help_void, 0); - add_to_sclist(MMAIN|MHELP|MBROWSER, "^X", 0, do_exit, 0); - add_to_sclist(MMAIN|MHELP|MBROWSER, "F2", 0, do_exit, 0); - add_to_sclist(MMAIN, "^S", 0, do_savefile, 0); - add_to_sclist(MMAIN, "^O", 0, do_writeout_void, 0); - add_to_sclist(MMAIN, "F3", 0, do_writeout_void, 0); - add_to_sclist(MMAIN, "^R", 0, do_insertfile_void, 0); - add_to_sclist(MMAIN, "F5", 0, do_insertfile_void, 0); - add_to_sclist(MMAIN, "Ins", 0, do_insertfile_void, 0); - add_to_sclist(MMAIN, "^Q", 0, do_search_backward, 0); - add_to_sclist(MMAIN|MHELP|MBROWSER, "^W", 0, do_search_forward, 0); - add_to_sclist(MMAIN|MHELP|MBROWSER, "F6", 0, do_search_forward, 0); - add_to_sclist(MMAIN, "^\\", 0, do_replace, 0); - add_to_sclist(MMAIN, "M-R", 0, do_replace, 0); - add_to_sclist(MMAIN, "F14", 0, do_replace, 0); - add_to_sclist(MMOST, "^K", 0, do_cut_text_void, 0); - add_to_sclist(MMOST, "F9", 0, do_cut_text_void, 0); - add_to_sclist(MMOST, "^U", 0, do_uncut_text, 0); - add_to_sclist(MMOST, "F10", 0, do_uncut_text, 0); + /* Link key combos to functions in certain menus. */ + add_to_sclist(MMOST, "^M", 0, do_enter, 0); + add_to_sclist(MMOST, "Enter", KEY_ENTER, do_enter, 0); + add_to_sclist(MMOST, "^H", 0, do_backspace, 0); + add_to_sclist(MMOST, "Bsp", KEY_BACKSPACE, do_backspace, 0); + add_to_sclist(MMOST, "^D", 0, do_delete, 0); + add_to_sclist(MMOST, "Del", 0, do_delete, 0); + add_to_sclist(MMOST, "^I", 0, do_tab, 0); + add_to_sclist(MMOST, "Tab", TAB_CODE, do_tab, 0); + add_to_sclist(MMOST & ~MFINDINHELP, "^G", 0, do_help_void, 0); + add_to_sclist(MMOST & ~MFINDINHELP, "F1", 0, do_help_void, 0); + add_to_sclist(MMAIN|MHELP|MBROWSER, "^X", 0, do_exit, 0); + add_to_sclist(MMAIN|MHELP|MBROWSER, "F2", 0, do_exit, 0); + add_to_sclist(MMAIN, "^S", 0, do_savefile, 0); + add_to_sclist(MMAIN, "^O", 0, do_writeout_void, 0); + add_to_sclist(MMAIN, "F3", 0, do_writeout_void, 0); + add_to_sclist(MMAIN, "^R", 0, do_insertfile_void, 0); + add_to_sclist(MMAIN, "F5", 0, do_insertfile_void, 0); + add_to_sclist(MMAIN, "Ins", 0, do_insertfile_void, 0); + add_to_sclist(MMAIN, "^Q", 0, do_search_backward, 0); + add_to_sclist(MMAIN|MHELP|MBROWSER, "^W", 0, do_search_forward, 0); + add_to_sclist(MMAIN|MHELP|MBROWSER, "F6", 0, do_search_forward, 0); + add_to_sclist(MMAIN, "^\\", 0, do_replace, 0); + add_to_sclist(MMAIN, "M-R", 0, do_replace, 0); + add_to_sclist(MMAIN, "F14", 0, do_replace, 0); + add_to_sclist(MMOST, "^K", 0, do_cut_text_void, 0); + add_to_sclist(MMOST, "F9", 0, do_cut_text_void, 0); + add_to_sclist(MMOST, "^U", 0, do_uncut_text, 0); + add_to_sclist(MMOST, "F10", 0, do_uncut_text, 0); #ifdef ENABLE_JUSTIFY - add_to_sclist(MMAIN, "^J", 0, do_justify_void, 0); - add_to_sclist(MMAIN, "F4", 0, do_justify_void, 0); + add_to_sclist(MMAIN, "^J", 0, do_justify_void, 0); + add_to_sclist(MMAIN, "F4", 0, do_justify_void, 0); #endif #ifdef ENABLE_SPELLER - add_to_sclist(MMAIN, "^T", 0, do_spell, 0); - add_to_sclist(MMAIN, "F12", 0, do_spell, 0); + add_to_sclist(MMAIN, "^T", 0, do_spell, 0); + add_to_sclist(MMAIN, "F12", 0, do_spell, 0); #else #ifdef ENABLE_COLOR - add_to_sclist(MMAIN, "^T", 0, do_linter, 0); - add_to_sclist(MMAIN, "F12", 0, do_linter, 0); + add_to_sclist(MMAIN, "^T", 0, do_linter, 0); + add_to_sclist(MMAIN, "F12", 0, do_linter, 0); #endif #endif - add_to_sclist(MMAIN, "^C", 0, do_cursorpos_void, 0); - add_to_sclist(MMAIN, "F11", 0, do_cursorpos_void, 0); - add_to_sclist(MMAIN, "^_", 0, do_gotolinecolumn_void, 0); - add_to_sclist(MMAIN, "M-G", 0, do_gotolinecolumn_void, 0); - add_to_sclist(MMAIN, "F13", 0, do_gotolinecolumn_void, 0); - add_to_sclist(MMAIN|MHELP|MBROWSER|MLINTER, "^Y", 0, do_page_up, 0); - add_to_sclist(MMAIN|MHELP|MBROWSER|MLINTER, "F7", 0, do_page_up, 0); - add_to_sclist(MMAIN|MHELP|MBROWSER|MLINTER, "PgUp", KEY_PPAGE, do_page_up, 0); - add_to_sclist(MHELP|MBROWSER, "Bsp", KEY_BACKSPACE, do_page_up, 0); - add_to_sclist(MMAIN|MHELP|MBROWSER|MLINTER, "^V", 0, do_page_down, 0); - add_to_sclist(MMAIN|MHELP|MBROWSER|MLINTER, "F8", 0, do_page_down, 0); - add_to_sclist(MMAIN|MHELP|MBROWSER|MLINTER, "PgDn", KEY_NPAGE, do_page_down, 0); - add_to_sclist(MMAIN|MHELP, "M-\\", 0, to_first_line, 0); - add_to_sclist(MMAIN|MHELP, "^Home", CONTROL_HOME, to_first_line, 0); - add_to_sclist(MMAIN|MHELP, "M-|", 0, to_first_line, 0); - add_to_sclist(MMAIN|MHELP, "M-/", 0, to_last_line, 0); - add_to_sclist(MMAIN|MHELP, "^End", CONTROL_END, to_last_line, 0); - add_to_sclist(MMAIN|MHELP, "M-?", 0, to_last_line, 0); - add_to_sclist(MMAIN|MHELP|MBROWSER, "M-W", 0, do_research, 0); - add_to_sclist(MMAIN|MHELP|MBROWSER, "F16", 0, do_research, 0); + add_to_sclist(MMAIN, "^C", 0, do_cursorpos_void, 0); + add_to_sclist(MMAIN, "F11", 0, do_cursorpos_void, 0); + add_to_sclist(MMAIN, "^_", 0, do_gotolinecolumn_void, 0); + add_to_sclist(MMAIN, "M-G", 0, do_gotolinecolumn_void, 0); + add_to_sclist(MMAIN, "F13", 0, do_gotolinecolumn_void, 0); + add_to_sclist(MMAIN|MHELP|MBROWSER|MLINTER, "^Y", 0, do_page_up, 0); + add_to_sclist(MMAIN|MHELP|MBROWSER|MLINTER, "F7", 0, do_page_up, 0); + add_to_sclist(MMAIN|MHELP|MBROWSER|MLINTER, "PgUp", KEY_PPAGE, do_page_up, 0); + add_to_sclist(MHELP|MBROWSER, "Bsp", KEY_BACKSPACE, do_page_up, 0); + add_to_sclist(MMAIN|MHELP|MBROWSER|MLINTER, "^V", 0, do_page_down, 0); + add_to_sclist(MMAIN|MHELP|MBROWSER|MLINTER, "F8", 0, do_page_down, 0); + add_to_sclist(MMAIN|MHELP|MBROWSER|MLINTER, "PgDn", KEY_NPAGE, do_page_down, 0); + add_to_sclist(MMAIN|MHELP, "M-\\", 0, to_first_line, 0); + add_to_sclist(MMAIN|MHELP, "^Home", CONTROL_HOME, to_first_line, 0); + add_to_sclist(MMAIN|MHELP, "M-|", 0, to_first_line, 0); + add_to_sclist(MMAIN|MHELP, "M-/", 0, to_last_line, 0); + add_to_sclist(MMAIN|MHELP, "^End", CONTROL_END, to_last_line, 0); + add_to_sclist(MMAIN|MHELP, "M-?", 0, to_last_line, 0); + add_to_sclist(MMAIN|MHELP|MBROWSER, "M-W", 0, do_research, 0); + add_to_sclist(MMAIN|MHELP|MBROWSER, "F16", 0, do_research, 0); #ifndef NANO_TINY - add_to_sclist(MMAIN, "M-]", 0, do_find_bracket, 0); - add_to_sclist(MMAIN, "M-A", 0, do_mark, 0); - add_to_sclist(MMAIN, "^6", 0, do_mark, 0); - add_to_sclist(MMAIN, "^^", 0, do_mark, 0); - add_to_sclist(MMAIN, "F15", 0, do_mark, 0); - add_to_sclist(MMAIN, "M-6", 0, do_copy_text, 0); - add_to_sclist(MMAIN, "M-^", 0, do_copy_text, 0); - add_to_sclist(MMAIN, "M-}", 0, do_indent, 0); - add_to_sclist(MMAIN, "Tab", TAB_CODE, do_indent, 0); - add_to_sclist(MMAIN, "M-{", 0, do_unindent, 0); - add_to_sclist(MMAIN, "Sh-Tab", SHIFT_TAB, do_unindent, 0); - add_to_sclist(MMAIN, "M-:", 0, record_macro, 0); - add_to_sclist(MMAIN, "M-;", 0, run_macro, 0); - add_to_sclist(MMAIN, "M-U", 0, do_undo, 0); - add_to_sclist(MMAIN, "M-E", 0, do_redo, 0); + add_to_sclist(MMAIN, "M-]", 0, do_find_bracket, 0); + add_to_sclist(MMAIN, "M-A", 0, do_mark, 0); + add_to_sclist(MMAIN, "^6", 0, do_mark, 0); + add_to_sclist(MMAIN, "^^", 0, do_mark, 0); + add_to_sclist(MMAIN, "F15", 0, do_mark, 0); + add_to_sclist(MMAIN, "M-6", 0, do_copy_text, 0); + add_to_sclist(MMAIN, "M-^", 0, do_copy_text, 0); + add_to_sclist(MMAIN, "M-}", 0, do_indent, 0); + add_to_sclist(MMAIN, "Tab", TAB_CODE, do_indent, 0); + add_to_sclist(MMAIN, "M-{", 0, do_unindent, 0); + add_to_sclist(MMAIN, "Sh-Tab", SHIFT_TAB, do_unindent, 0); + add_to_sclist(MMAIN, "M-:", 0, record_macro, 0); + add_to_sclist(MMAIN, "M-;", 0, run_macro, 0); + add_to_sclist(MMAIN, "M-U", 0, do_undo, 0); + add_to_sclist(MMAIN, "M-E", 0, do_redo, 0); #endif #ifdef ENABLE_WORDCOMPLETION - add_to_sclist(MMAIN, "^]", 0, complete_a_word, 0); + add_to_sclist(MMAIN, "^]", 0, complete_a_word, 0); #endif #ifdef ENABLE_COMMENT - add_to_sclist(MMAIN, "M-3", 0, do_comment, 0); + add_to_sclist(MMAIN, "M-3", 0, do_comment, 0); #endif - add_to_sclist(MMOST, "^B", 0, do_left, 0); - add_to_sclist(MMOST, "^F", 0, do_right, 0); + add_to_sclist(MMOST, "^B", 0, do_left, 0); + add_to_sclist(MMOST, "^F", 0, do_right, 0); #ifdef ENABLE_UTF8 - if (using_utf8()) { - add_to_sclist(MMOST, "\xE2\x97\x80", KEY_LEFT, do_left, 0); - add_to_sclist(MMOST, "\xE2\x96\xb6", KEY_RIGHT, do_right, 0); - add_to_sclist(MSOME, "^\xE2\x97\x80", CONTROL_LEFT, do_prev_word_void, 0); - add_to_sclist(MSOME, "^\xE2\x96\xb6", CONTROL_RIGHT, do_next_word_void, 0); + if (using_utf8()) { + add_to_sclist(MMOST, "\xE2\x97\x80", KEY_LEFT, do_left, 0); + add_to_sclist(MMOST, "\xE2\x96\xb6", KEY_RIGHT, do_right, 0); + add_to_sclist(MSOME, "^\xE2\x97\x80", CONTROL_LEFT, do_prev_word_void, 0); + add_to_sclist(MSOME, "^\xE2\x96\xb6", CONTROL_RIGHT, do_next_word_void, 0); #ifdef ENABLE_MULTIBUFFER - add_to_sclist(MMAIN, "M-\xE2\x97\x80", ALT_LEFT, switch_to_prev_buffer, 0); - add_to_sclist(MMAIN, "M-\xE2\x96\xb6", ALT_RIGHT, switch_to_next_buffer, 0); + add_to_sclist(MMAIN, "M-\xE2\x97\x80", ALT_LEFT, switch_to_prev_buffer, 0); + add_to_sclist(MMAIN, "M-\xE2\x96\xb6", ALT_RIGHT, switch_to_next_buffer, 0); #endif #ifndef NANO_TINY - add_to_sclist(MMAIN|MHELP|MBROWSER, "M-\xE2\x96\xb2", ALT_UP, do_findprevious, 0); - add_to_sclist(MMAIN|MHELP|MBROWSER, "M-\xE2\x96\xbc", ALT_DOWN, do_findnext, 0); + add_to_sclist(MMAIN|MHELP|MBROWSER, "M-\xE2\x96\xb2", ALT_UP, do_findprevious, 0); + add_to_sclist(MMAIN|MHELP|MBROWSER, "M-\xE2\x96\xbc", ALT_DOWN, do_findnext, 0); #endif - } else + } else #endif - { - add_to_sclist(MMOST, "Left", KEY_LEFT, do_left, 0); - add_to_sclist(MMOST, "Right", KEY_RIGHT, do_right, 0); - add_to_sclist(MSOME, "^Left", CONTROL_LEFT, do_prev_word_void, 0); - add_to_sclist(MSOME, "^Right", CONTROL_RIGHT, do_next_word_void, 0); - } - add_to_sclist(MMOST, "M-Space", 0, do_prev_word_void, 0); - add_to_sclist(MMOST, "^Space", 0, do_next_word_void, 0); - add_to_sclist((MMOST & ~MBROWSER), "^A", 0, do_home, 0); - add_to_sclist((MMOST & ~MBROWSER), "Home", KEY_HOME, do_home, 0); - add_to_sclist((MMOST & ~MBROWSER), "^E", 0, do_end, 0); - add_to_sclist((MMOST & ~MBROWSER), "End", KEY_END, do_end, 0); - add_to_sclist(MMAIN|MHELP|MBROWSER, "^P", 0, do_up_void, 0); - add_to_sclist(MMAIN|MHELP|MBROWSER, "^N", 0, do_down_void, 0); + { + add_to_sclist(MMOST, "Left", KEY_LEFT, do_left, 0); + add_to_sclist(MMOST, "Right", KEY_RIGHT, do_right, 0); + add_to_sclist(MSOME, "^Left", CONTROL_LEFT, do_prev_word_void, 0); + add_to_sclist(MSOME, "^Right", CONTROL_RIGHT, do_next_word_void, 0); + } + add_to_sclist(MMOST, "M-Space", 0, do_prev_word_void, 0); + add_to_sclist(MMOST, "^Space", 0, do_next_word_void, 0); + add_to_sclist((MMOST & ~MBROWSER), "^A", 0, do_home, 0); + add_to_sclist((MMOST & ~MBROWSER), "Home", KEY_HOME, do_home, 0); + add_to_sclist((MMOST & ~MBROWSER), "^E", 0, do_end, 0); + add_to_sclist((MMOST & ~MBROWSER), "End", KEY_END, do_end, 0); + add_to_sclist(MMAIN|MHELP|MBROWSER, "^P", 0, do_up_void, 0); + add_to_sclist(MMAIN|MHELP|MBROWSER, "^N", 0, do_down_void, 0); #ifdef ENABLE_UTF8 - if (using_utf8()) { - add_to_sclist(MMAIN|MHELP|MBROWSER, "\xE2\x96\xb2", KEY_UP, do_up_void, 0); - add_to_sclist(MMAIN|MHELP|MBROWSER, "\xE2\x96\xbc", KEY_DOWN, do_down_void, 0); - add_to_sclist(MMAIN|MBROWSER, "^\xE2\x96\xb2", CONTROL_UP, do_prev_block, 0); - add_to_sclist(MMAIN|MBROWSER, "^\xE2\x96\xbc", CONTROL_DOWN, do_next_block, 0); - } else + if (using_utf8()) { + add_to_sclist(MMAIN|MHELP|MBROWSER, "\xE2\x96\xb2", KEY_UP, do_up_void, 0); + add_to_sclist(MMAIN|MHELP|MBROWSER, "\xE2\x96\xbc", KEY_DOWN, do_down_void, 0); + add_to_sclist(MMAIN|MBROWSER, "^\xE2\x96\xb2", CONTROL_UP, do_prev_block, 0); + add_to_sclist(MMAIN|MBROWSER, "^\xE2\x96\xbc", CONTROL_DOWN, do_next_block, 0); + } else #endif - { - add_to_sclist(MMAIN|MHELP|MBROWSER, "Up", KEY_UP, do_up_void, 0); - add_to_sclist(MMAIN|MHELP|MBROWSER, "Down", KEY_DOWN, do_down_void, 0); - add_to_sclist(MMAIN|MBROWSER, "^Up", CONTROL_UP, do_prev_block, 0); - add_to_sclist(MMAIN|MBROWSER, "^Down", CONTROL_DOWN, do_next_block, 0); - } - add_to_sclist(MMAIN, "M-7", 0, do_prev_block, 0); - add_to_sclist(MMAIN, "M-8", 0, do_next_block, 0); + { + add_to_sclist(MMAIN|MHELP|MBROWSER, "Up", KEY_UP, do_up_void, 0); + add_to_sclist(MMAIN|MHELP|MBROWSER, "Down", KEY_DOWN, do_down_void, 0); + add_to_sclist(MMAIN|MBROWSER, "^Up", CONTROL_UP, do_prev_block, 0); + add_to_sclist(MMAIN|MBROWSER, "^Down", CONTROL_DOWN, do_next_block, 0); + } + add_to_sclist(MMAIN, "M-7", 0, do_prev_block, 0); + add_to_sclist(MMAIN, "M-8", 0, do_next_block, 0); #ifdef ENABLE_JUSTIFY - add_to_sclist(MMAIN, "M-(", 0, do_para_begin_void, 0); - add_to_sclist(MMAIN, "M-9", 0, do_para_begin_void, 0); - add_to_sclist(MMAIN, "M-)", 0, do_para_end_void, 0); - add_to_sclist(MMAIN, "M-0", 0, do_para_end_void, 0); + add_to_sclist(MMAIN, "M-(", 0, do_para_begin_void, 0); + add_to_sclist(MMAIN, "M-9", 0, do_para_begin_void, 0); + add_to_sclist(MMAIN, "M-)", 0, do_para_end_void, 0); + add_to_sclist(MMAIN, "M-0", 0, do_para_end_void, 0); #endif #ifndef NANO_TINY - add_to_sclist(MMAIN, "M--", 0, do_scroll_up, 0); - add_to_sclist(MMAIN, "M-_", 0, do_scroll_up, 0); - add_to_sclist(MMAIN, "M-+", 0, do_scroll_down, 0); - add_to_sclist(MMAIN, "M-=", 0, do_scroll_down, 0); + add_to_sclist(MMAIN, "M--", 0, do_scroll_up, 0); + add_to_sclist(MMAIN, "M-_", 0, do_scroll_up, 0); + add_to_sclist(MMAIN, "M-+", 0, do_scroll_down, 0); + add_to_sclist(MMAIN, "M-=", 0, do_scroll_down, 0); #endif #ifdef ENABLE_MULTIBUFFER - add_to_sclist(MMAIN, "M-<", 0, switch_to_prev_buffer, 0); - add_to_sclist(MMAIN, "M-,", 0, switch_to_prev_buffer, 0); - add_to_sclist(MMAIN, "M->", 0, switch_to_next_buffer, 0); - add_to_sclist(MMAIN, "M-.", 0, switch_to_next_buffer, 0); + add_to_sclist(MMAIN, "M-<", 0, switch_to_prev_buffer, 0); + add_to_sclist(MMAIN, "M-,", 0, switch_to_prev_buffer, 0); + add_to_sclist(MMAIN, "M->", 0, switch_to_next_buffer, 0); + add_to_sclist(MMAIN, "M-.", 0, switch_to_next_buffer, 0); #endif - add_to_sclist(MMOST, "M-V", 0, do_verbatim_input, 0); + add_to_sclist(MMOST, "M-V", 0, do_verbatim_input, 0); #ifndef NANO_TINY - add_to_sclist(MMAIN, "M-T", 0, do_cut_till_eof, 0); - add_to_sclist(MMAIN, "M-D", 0, do_wordlinechar_count, 0); + add_to_sclist(MMAIN, "M-T", 0, do_cut_till_eof, 0); + add_to_sclist(MMAIN, "M-D", 0, do_wordlinechar_count, 0); #endif #ifdef ENABLE_JUSTIFY - add_to_sclist(MMAIN|MWHEREIS, "M-J", 0, do_full_justify, 0); + add_to_sclist(MMAIN|MWHEREIS, "M-J", 0, do_full_justify, 0); #endif - add_to_sclist(MMAIN|MHELP|MBROWSER, "^L", 0, total_refresh, 0); - add_to_sclist(MMAIN, "^Z", 0, do_suspend_void, 0); + add_to_sclist(MMAIN|MHELP|MBROWSER, "^L", 0, total_refresh, 0); + add_to_sclist(MMAIN, "^Z", 0, do_suspend_void, 0); #ifndef NANO_TINY - /* Group of "Appearance" toggles. */ - add_to_sclist(MMAIN, "M-X", 0, do_toggle_void, NO_HELP); - add_to_sclist(MMAIN, "M-C", 0, do_toggle_void, CONSTANT_SHOW); - add_to_sclist(MMAIN, "M-O", 0, do_toggle_void, MORE_SPACE); - add_to_sclist(MMAIN, "M-S", 0, do_toggle_void, SMOOTH_SCROLL); - add_to_sclist(MMAIN, "M-$", 0, do_toggle_void, SOFTWRAP); + /* Group of "Appearance" toggles. */ + add_to_sclist(MMAIN, "M-X", 0, do_toggle_void, NO_HELP); + add_to_sclist(MMAIN, "M-C", 0, do_toggle_void, CONSTANT_SHOW); + add_to_sclist(MMAIN, "M-O", 0, do_toggle_void, MORE_SPACE); + add_to_sclist(MMAIN, "M-S", 0, do_toggle_void, SMOOTH_SCROLL); + add_to_sclist(MMAIN, "M-$", 0, do_toggle_void, SOFTWRAP); #ifdef ENABLE_LINENUMBERS - add_to_sclist(MMAIN, "M-#", 0, do_toggle_void, LINE_NUMBERS); + add_to_sclist(MMAIN, "M-#", 0, do_toggle_void, LINE_NUMBERS); #endif - add_to_sclist(MMAIN, "M-P", 0, do_toggle_void, WHITESPACE_DISPLAY); + add_to_sclist(MMAIN, "M-P", 0, do_toggle_void, WHITESPACE_DISPLAY); #ifdef ENABLE_COLOR - add_to_sclist(MMAIN, "M-Y", 0, do_toggle_void, NO_COLOR_SYNTAX); + add_to_sclist(MMAIN, "M-Y", 0, do_toggle_void, NO_COLOR_SYNTAX); #endif - /* Group of "Editing-behavior" toggles. */ - add_to_sclist(MMAIN, "M-H", 0, do_toggle_void, SMART_HOME); - add_to_sclist(MMAIN, "M-I", 0, do_toggle_void, AUTOINDENT); - add_to_sclist(MMAIN, "M-K", 0, do_toggle_void, CUT_FROM_CURSOR); + /* Group of "Editing-behavior" toggles. */ + add_to_sclist(MMAIN, "M-H", 0, do_toggle_void, SMART_HOME); + add_to_sclist(MMAIN, "M-I", 0, do_toggle_void, AUTOINDENT); + add_to_sclist(MMAIN, "M-K", 0, do_toggle_void, CUT_FROM_CURSOR); #ifdef ENABLE_WRAPPING - add_to_sclist(MMAIN, "M-L", 0, do_toggle_void, NO_WRAP); + add_to_sclist(MMAIN, "M-L", 0, do_toggle_void, NO_WRAP); #endif - add_to_sclist(MMAIN, "M-Q", 0, do_toggle_void, TABS_TO_SPACES); + add_to_sclist(MMAIN, "M-Q", 0, do_toggle_void, TABS_TO_SPACES); - /* Group of "Peripheral-feature" toggles. */ - add_to_sclist(MMAIN, "M-B", 0, do_toggle_void, BACKUP_FILE); + /* Group of "Peripheral-feature" toggles. */ + add_to_sclist(MMAIN, "M-B", 0, do_toggle_void, BACKUP_FILE); #ifdef ENABLE_MULTIBUFFER - add_to_sclist(MMAIN, "M-F", 0, do_toggle_void, MULTIBUFFER); + add_to_sclist(MMAIN, "M-F", 0, do_toggle_void, MULTIBUFFER); #endif #ifdef ENABLE_MOUSE - add_to_sclist(MMAIN, "M-M", 0, do_toggle_void, USE_MOUSE); + add_to_sclist(MMAIN, "M-M", 0, do_toggle_void, USE_MOUSE); #endif - add_to_sclist(MMAIN, "M-N", 0, do_toggle_void, NO_CONVERT); - add_to_sclist(MMAIN, "M-Z", 0, do_toggle_void, SUSPEND); + add_to_sclist(MMAIN, "M-N", 0, do_toggle_void, NO_CONVERT); + add_to_sclist(MMAIN, "M-Z", 0, do_toggle_void, SUSPEND); #endif /* !NANO_TINY */ - add_to_sclist(((MMOST & ~MMAIN & ~MBROWSER) | MYESNO), "^C", 0, do_cancel, 0); + add_to_sclist(((MMOST & ~MMAIN & ~MBROWSER) | MYESNO), "^C", 0, do_cancel, 0); - add_to_sclist(MWHEREIS|MREPLACE, "M-C", 0, case_sens_void, 0); - add_to_sclist(MWHEREIS|MREPLACE, "M-R", 0, regexp_void, 0); - add_to_sclist(MWHEREIS|MREPLACE, "M-B", 0, backwards_void, 0); - add_to_sclist(MWHEREIS|MREPLACE, "^R", 0, flip_replace, 0); - add_to_sclist(MWHEREIS|MREPLACE|MREPLACEWITH|MGOTOLINE|MFINDINHELP, "^Y", 0, to_first_line, 0); - add_to_sclist(MWHEREIS|MREPLACE|MREPLACEWITH|MGOTOLINE|MFINDINHELP, "^V", 0, to_last_line, 0); + add_to_sclist(MWHEREIS|MREPLACE, "M-C", 0, case_sens_void, 0); + add_to_sclist(MWHEREIS|MREPLACE, "M-R", 0, regexp_void, 0); + add_to_sclist(MWHEREIS|MREPLACE, "M-B", 0, backwards_void, 0); + add_to_sclist(MWHEREIS|MREPLACE, "^R", 0, flip_replace, 0); + add_to_sclist(MWHEREIS|MREPLACE|MREPLACEWITH|MGOTOLINE|MFINDINHELP, "^Y", 0, to_first_line, 0); + add_to_sclist(MWHEREIS|MREPLACE|MREPLACEWITH|MGOTOLINE|MFINDINHELP, "^V", 0, to_last_line, 0); #ifdef ENABLE_JUSTIFY - add_to_sclist(MWHEREIS|MREPLACE|MREPLACEWITH, "^W", 0, do_para_begin_void, 0); - add_to_sclist(MWHEREIS|MREPLACE|MREPLACEWITH, "^O", 0, do_para_end_void, 0); + add_to_sclist(MWHEREIS|MREPLACE|MREPLACEWITH, "^W", 0, do_para_begin_void, 0); + add_to_sclist(MWHEREIS|MREPLACE|MREPLACEWITH, "^O", 0, do_para_end_void, 0); #endif - add_to_sclist(MWHEREIS, "^T", 0, do_gotolinecolumn_void, 0); - add_to_sclist(MGOTOLINE, "^T", 0, gototext_void, 0); + add_to_sclist(MWHEREIS, "^T", 0, do_gotolinecolumn_void, 0); + add_to_sclist(MGOTOLINE, "^T", 0, gototext_void, 0); #ifdef ENABLE_HISTORIES - add_to_sclist(MWHEREIS|MREPLACE|MREPLACEWITH|MWHEREISFILE|MFINDINHELP|MEXTCMD, "^P", 0, get_history_older_void, 0); - add_to_sclist(MWHEREIS|MREPLACE|MREPLACEWITH|MWHEREISFILE|MFINDINHELP|MEXTCMD, "^N", 0, get_history_newer_void, 0); + add_to_sclist(MWHEREIS|MREPLACE|MREPLACEWITH|MWHEREISFILE|MFINDINHELP|MEXTCMD, "^P", 0, get_history_older_void, 0); + add_to_sclist(MWHEREIS|MREPLACE|MREPLACEWITH|MWHEREISFILE|MFINDINHELP|MEXTCMD, "^N", 0, get_history_newer_void, 0); #ifdef ENABLE_UTF8 - if (using_utf8()) { - add_to_sclist(MWHEREIS|MREPLACE|MREPLACEWITH|MWHEREISFILE|MFINDINHELP|MEXTCMD, "\xE2\x96\xb2", KEY_UP, get_history_older_void, 0); - add_to_sclist(MWHEREIS|MREPLACE|MREPLACEWITH|MWHEREISFILE|MFINDINHELP|MEXTCMD, "\xE2\x96\xbc", KEY_DOWN, get_history_newer_void, 0); - } else + if (using_utf8()) { + add_to_sclist(MWHEREIS|MREPLACE|MREPLACEWITH|MWHEREISFILE|MFINDINHELP|MEXTCMD, "\xE2\x96\xb2", KEY_UP, get_history_older_void, 0); + add_to_sclist(MWHEREIS|MREPLACE|MREPLACEWITH|MWHEREISFILE|MFINDINHELP|MEXTCMD, "\xE2\x96\xbc", KEY_DOWN, get_history_newer_void, 0); + } else #endif - { - add_to_sclist(MWHEREIS|MREPLACE|MREPLACEWITH|MWHEREISFILE|MFINDINHELP|MEXTCMD, "Up", KEY_UP, get_history_older_void, 0); - add_to_sclist(MWHEREIS|MREPLACE|MREPLACEWITH|MWHEREISFILE|MFINDINHELP|MEXTCMD, "Down", KEY_DOWN, get_history_newer_void, 0); - } + { + add_to_sclist(MWHEREIS|MREPLACE|MREPLACEWITH|MWHEREISFILE|MFINDINHELP|MEXTCMD, "Up", KEY_UP, get_history_older_void, 0); + add_to_sclist(MWHEREIS|MREPLACE|MREPLACEWITH|MWHEREISFILE|MFINDINHELP|MEXTCMD, "Down", KEY_DOWN, get_history_newer_void, 0); + } #endif #ifdef ENABLE_BROWSER - add_to_sclist(MWHEREISFILE, "^Y", 0, to_first_file, 0); - add_to_sclist(MWHEREISFILE, "^V", 0, to_last_file, 0); - add_to_sclist(MBROWSER|MWHEREISFILE, "M-\\", 0, to_first_file, 0); - add_to_sclist(MBROWSER|MWHEREISFILE, "M-/", 0, to_last_file, 0); - add_to_sclist(MBROWSER, "Home", KEY_HOME, to_first_file, 0); - add_to_sclist(MBROWSER, "End", KEY_END, to_last_file, 0); - add_to_sclist(MBROWSER|MWHEREISFILE, "M-|", 0, to_first_file, 0); - add_to_sclist(MBROWSER|MWHEREISFILE, "M-?", 0, to_last_file, 0); - add_to_sclist(MBROWSER, "^Home", CONTROL_HOME, to_first_file, 0); - add_to_sclist(MBROWSER, "^End", CONTROL_END, to_last_file, 0); - add_to_sclist(MBROWSER, "^_", 0, goto_dir_void, 0); - add_to_sclist(MBROWSER, "M-G", 0, goto_dir_void, 0); - add_to_sclist(MBROWSER, "F13", 0, goto_dir_void, 0); + add_to_sclist(MWHEREISFILE, "^Y", 0, to_first_file, 0); + add_to_sclist(MWHEREISFILE, "^V", 0, to_last_file, 0); + add_to_sclist(MBROWSER|MWHEREISFILE, "M-\\", 0, to_first_file, 0); + add_to_sclist(MBROWSER|MWHEREISFILE, "M-/", 0, to_last_file, 0); + add_to_sclist(MBROWSER, "Home", KEY_HOME, to_first_file, 0); + add_to_sclist(MBROWSER, "End", KEY_END, to_last_file, 0); + add_to_sclist(MBROWSER|MWHEREISFILE, "M-|", 0, to_first_file, 0); + add_to_sclist(MBROWSER|MWHEREISFILE, "M-?", 0, to_last_file, 0); + add_to_sclist(MBROWSER, "^Home", CONTROL_HOME, to_first_file, 0); + add_to_sclist(MBROWSER, "^End", CONTROL_END, to_last_file, 0); + add_to_sclist(MBROWSER, "^_", 0, goto_dir_void, 0); + add_to_sclist(MBROWSER, "M-G", 0, goto_dir_void, 0); + add_to_sclist(MBROWSER, "F13", 0, goto_dir_void, 0); #endif - if (ISSET(TEMP_FILE)) - add_to_sclist(MWRITEFILE, "^Q", 0, discard_buffer, 0); + if (ISSET(TEMP_FILE)) + add_to_sclist(MWRITEFILE, "^Q", 0, discard_buffer, 0); #ifndef NANO_TINY - add_to_sclist(MWRITEFILE, "M-D", 0, dos_format_void, 0); - add_to_sclist(MWRITEFILE, "M-M", 0, mac_format_void, 0); - /* In restricted mode, don't allow Appending, Prepending, nor making - * backups, nor executing a command, nor opening a new buffer. */ - if (!ISSET(RESTRICTED)) { - add_to_sclist(MWRITEFILE, "M-A", 0, append_void, 0); - add_to_sclist(MWRITEFILE, "M-P", 0, prepend_void, 0); - add_to_sclist(MWRITEFILE, "M-B", 0, backup_file_void, 0); - add_to_sclist(MINSERTFILE|MEXTCMD, "^X", 0, flip_execute, 0); - } + add_to_sclist(MWRITEFILE, "M-D", 0, dos_format_void, 0); + add_to_sclist(MWRITEFILE, "M-M", 0, mac_format_void, 0); + /* In restricted mode, don't allow Appending, Prepending, nor making + * backups, nor executing a command, nor opening a new buffer. */ + if (!ISSET(RESTRICTED)) { + add_to_sclist(MWRITEFILE, "M-A", 0, append_void, 0); + add_to_sclist(MWRITEFILE, "M-P", 0, prepend_void, 0); + add_to_sclist(MWRITEFILE, "M-B", 0, backup_file_void, 0); + add_to_sclist(MINSERTFILE|MEXTCMD, "^X", 0, flip_execute, 0); + } #endif #ifdef ENABLE_MULTIBUFFER - if (!ISSET(RESTRICTED)) - add_to_sclist(MINSERTFILE|MEXTCMD, "M-F", 0, flip_newbuffer, 0); + if (!ISSET(RESTRICTED)) + add_to_sclist(MINSERTFILE|MEXTCMD, "M-F", 0, flip_newbuffer, 0); #endif #ifdef ENABLE_BROWSER - /* In restricted mode, don't allow entering the file browser. */ - if (!ISSET(RESTRICTED)) - add_to_sclist(MWRITEFILE|MINSERTFILE, "^T", 0, to_files_void, 0); + /* In restricted mode, don't allow entering the file browser. */ + if (!ISSET(RESTRICTED)) + add_to_sclist(MWRITEFILE|MINSERTFILE, "^T", 0, to_files_void, 0); #endif - add_to_sclist(MHELP|MBROWSER, "^C", 0, do_exit, 0); - /* Allow exiting from the file browser and the help viewer with - * the same key as they were entered. */ + add_to_sclist(MHELP|MBROWSER, "^C", 0, do_exit, 0); + /* Allow exiting from the file browser and the help viewer with + * the same key as they were entered. */ #ifdef ENABLE_BROWSER - add_to_sclist(MBROWSER, "^T", 0, do_exit, 0); + add_to_sclist(MBROWSER, "^T", 0, do_exit, 0); #endif #ifdef ENABLE_HELP - add_to_sclist(MHELP, "^G", 0, do_exit, 0); - add_to_sclist(MHELP, "F1", 0, do_exit, 0); - add_to_sclist(MHELP, "Home", KEY_HOME, to_first_line, 0); - add_to_sclist(MHELP, "End", KEY_END, to_last_line, 0); + add_to_sclist(MHELP, "^G", 0, do_exit, 0); + add_to_sclist(MHELP, "F1", 0, do_exit, 0); + add_to_sclist(MHELP, "Home", KEY_HOME, to_first_line, 0); + add_to_sclist(MHELP, "End", KEY_END, to_last_line, 0); #endif #ifdef DEBUG - print_sclist(); + print_sclist(); #endif } @@ -1368,33 +1368,33 @@ void shortcut_init(void) void set_lint_or_format_shortcuts(void) { #ifdef ENABLE_SPELLER - if (openfile->syntax->formatter) { - replace_scs_for(do_spell, do_formatter); - replace_scs_for(do_linter, do_formatter); - } else { - replace_scs_for(do_spell, do_linter); - replace_scs_for(do_formatter, do_linter); - } + if (openfile->syntax->formatter) { + replace_scs_for(do_spell, do_formatter); + replace_scs_for(do_linter, do_formatter); + } else { + replace_scs_for(do_spell, do_linter); + replace_scs_for(do_formatter, do_linter); + } #endif } void set_spell_shortcuts(void) { #ifdef ENABLE_SPELLER - replace_scs_for(do_formatter, do_spell); - replace_scs_for(do_linter, do_spell); + replace_scs_for(do_formatter, do_spell); + replace_scs_for(do_linter, do_spell); #endif } #endif /* ENABLE_COLOR */ const subnfunc *sctofunc(const sc *s) { - subnfunc *f = allfuncs; + subnfunc *f = allfuncs; - while (f != NULL && f->scfunc != s->scfunc) - f = f->next; + while (f != NULL && f->scfunc != s->scfunc) + f = f->next; - return f; + return f; } #ifndef NANO_TINY @@ -1402,48 +1402,48 @@ const subnfunc *sctofunc(const sc *s) * for each flag. */ const char *flagtostr(int flag) { - switch (flag) { - case NO_HELP: - /* TRANSLATORS: The next eighteen strings are toggle descriptions; - * they are best kept shorter than 40 characters, but may be longer. */ - return N_("Help mode"); - case CONSTANT_SHOW: - return N_("Constant cursor position display"); - case MORE_SPACE: - 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: - return N_("Color syntax highlighting"); - case SMART_HOME: - return N_("Smart home key"); - case AUTOINDENT: - return N_("Auto indent"); - case CUT_FROM_CURSOR: - return N_("Cut to end"); - case NO_WRAP: - return N_("Hard wrapping of overlong lines"); - case TABS_TO_SPACES: - return N_("Conversion of typed tabs to spaces"); - case BACKUP_FILE: - return N_("Backup files"); - case MULTIBUFFER: - return N_("Reading file into separate buffer"); - case USE_MOUSE: - return N_("Mouse support"); - case NO_CONVERT: - return N_("No conversion from DOS/Mac format"); - case SUSPEND: - return N_("Suspension"); - case LINE_NUMBERS: - return N_("Line numbering"); - default: - return "Bad toggle -- please report a bug"; - } + switch (flag) { + case NO_HELP: + /* TRANSLATORS: The next eighteen strings are toggle descriptions; + * they are best kept shorter than 40 characters, but may be longer. */ + return N_("Help mode"); + case CONSTANT_SHOW: + return N_("Constant cursor position display"); + case MORE_SPACE: + 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: + return N_("Color syntax highlighting"); + case SMART_HOME: + return N_("Smart home key"); + case AUTOINDENT: + return N_("Auto indent"); + case CUT_FROM_CURSOR: + return N_("Cut to end"); + case NO_WRAP: + return N_("Hard wrapping of overlong lines"); + case TABS_TO_SPACES: + return N_("Conversion of typed tabs to spaces"); + case BACKUP_FILE: + return N_("Backup files"); + case MULTIBUFFER: + return N_("Reading file into separate buffer"); + case USE_MOUSE: + return N_("Mouse support"); + case NO_CONVERT: + return N_("No conversion from DOS/Mac format"); + case SUSPEND: + return N_("Suspension"); + case LINE_NUMBERS: + return N_("Line numbering"); + default: + return "Bad toggle -- please report a bug"; + } } #endif /* !NANO_TINY */ @@ -1452,315 +1452,315 @@ const char *flagtostr(int flag) * shortcut struct with the corresponding function filled in. */ sc *strtosc(const char *input) { - sc *s = nmalloc(sizeof(sc)); + sc *s = nmalloc(sizeof(sc)); #ifndef NANO_TINY - s->toggle = 0; + s->toggle = 0; #endif #ifdef ENABLE_HELP - if (!strcasecmp(input, "help")) - s->scfunc = do_help_void; - else + if (!strcasecmp(input, "help")) + s->scfunc = do_help_void; + else #endif - if (!strcasecmp(input, "cancel")) - s->scfunc = do_cancel; - else if (!strcasecmp(input, "exit")) - s->scfunc = do_exit; - else if (!strcasecmp(input, "discardbuffer")) - s->scfunc = discard_buffer; - else if (!strcasecmp(input, "writeout")) - s->scfunc = do_writeout_void; + if (!strcasecmp(input, "cancel")) + s->scfunc = do_cancel; + else if (!strcasecmp(input, "exit")) + s->scfunc = do_exit; + else if (!strcasecmp(input, "discardbuffer")) + s->scfunc = discard_buffer; + else if (!strcasecmp(input, "writeout")) + s->scfunc = do_writeout_void; #ifndef NANO_TINY - else if (!strcasecmp(input, "savefile")) - s->scfunc = do_savefile; + else if (!strcasecmp(input, "savefile")) + s->scfunc = do_savefile; #endif - else if (!strcasecmp(input, "insert")) - s->scfunc = do_insertfile_void; - else if (!strcasecmp(input, "whereis")) - s->scfunc = do_search_forward; - else if (!strcasecmp(input, "wherewas")) - s->scfunc = do_search_backward; - else if (!strcasecmp(input, "searchagain") || - !strcasecmp(input, "research")) /* Deprecated. Remove in 2018. */ - s->scfunc = do_research; + else if (!strcasecmp(input, "insert")) + s->scfunc = do_insertfile_void; + else if (!strcasecmp(input, "whereis")) + s->scfunc = do_search_forward; + else if (!strcasecmp(input, "wherewas")) + s->scfunc = do_search_backward; + else if (!strcasecmp(input, "searchagain") || + !strcasecmp(input, "research")) /* Deprecated. Remove in 2018. */ + s->scfunc = do_research; #ifndef NANO_TINY - else if (!strcasecmp(input, "findprevious")) - s->scfunc = do_findprevious; - else if (!strcasecmp(input, "findnext")) - s->scfunc = do_findnext; + else if (!strcasecmp(input, "findprevious")) + s->scfunc = do_findprevious; + else if (!strcasecmp(input, "findnext")) + s->scfunc = do_findnext; #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; + 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_eof; - else if (!strcasecmp(input, "copytext")) - s->scfunc = do_copy_text; - else if (!strcasecmp(input, "mark")) - s->scfunc = do_mark; + else if (!strcasecmp(input, "cutrestoffile")) + s->scfunc = do_cut_till_eof; + else if (!strcasecmp(input, "copytext")) + s->scfunc = do_copy_text; + else if (!strcasecmp(input, "mark")) + s->scfunc = do_mark; #endif #ifdef ENABLE_SPELLER - else if (!strcasecmp(input, "tospell") || - !strcasecmp(input, "speller")) - s->scfunc = do_spell; + else if (!strcasecmp(input, "tospell") || + !strcasecmp(input, "speller")) + s->scfunc = do_spell; #endif #ifdef ENABLE_COLOR - else if (!strcasecmp(input, "linter")) - s->scfunc = do_linter; + else if (!strcasecmp(input, "linter")) + s->scfunc = do_linter; #endif - else if (!strcasecmp(input, "curpos") || - !strcasecmp(input, "cursorpos")) /* Deprecated. Remove in 2018. */ - s->scfunc = do_cursorpos_void; - else if (!strcasecmp(input, "gotoline")) - s->scfunc = do_gotolinecolumn_void; + else if (!strcasecmp(input, "curpos") || + !strcasecmp(input, "cursorpos")) /* Deprecated. Remove in 2018. */ + s->scfunc = do_cursorpos_void; + else if (!strcasecmp(input, "gotoline")) + s->scfunc = do_gotolinecolumn_void; #ifdef ENABLE_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, "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; #endif #ifdef ENABLE_COMMENT - else if (!strcasecmp(input, "comment")) - s->scfunc = do_comment; + else if (!strcasecmp(input, "comment")) + s->scfunc = do_comment; #endif #ifdef ENABLE_WORDCOMPLETION - else if (!strcasecmp(input, "complete")) - s->scfunc = complete_a_word; + else if (!strcasecmp(input, "complete")) + s->scfunc = complete_a_word; #endif #ifndef NANO_TINY - else if (!strcasecmp(input, "indent")) - s->scfunc = do_indent; - else if (!strcasecmp(input, "unindent")) - s->scfunc = do_unindent; - else if (!strcasecmp(input, "scrollup")) - s->scfunc = do_scroll_up; - else if (!strcasecmp(input, "scrolldown")) - s->scfunc = do_scroll_down; - else if (!strcasecmp(input, "cutwordleft")) - s->scfunc = do_cut_prev_word; - else if (!strcasecmp(input, "cutwordright")) - s->scfunc = do_cut_next_word; - else if (!strcasecmp(input, "findbracket")) - s->scfunc = do_find_bracket; - else if (!strcasecmp(input, "wordcount")) - s->scfunc = do_wordlinechar_count; - else if (!strcasecmp(input, "recordmacro")) - s->scfunc = record_macro; - else if (!strcasecmp(input, "runmacro")) - s->scfunc = run_macro; - else if (!strcasecmp(input, "undo")) - s->scfunc = do_undo; - else if (!strcasecmp(input, "redo")) - s->scfunc = do_redo; + else if (!strcasecmp(input, "indent")) + s->scfunc = do_indent; + else if (!strcasecmp(input, "unindent")) + s->scfunc = do_unindent; + else if (!strcasecmp(input, "scrollup")) + s->scfunc = do_scroll_up; + else if (!strcasecmp(input, "scrolldown")) + s->scfunc = do_scroll_down; + else if (!strcasecmp(input, "cutwordleft")) + s->scfunc = do_cut_prev_word; + else if (!strcasecmp(input, "cutwordright")) + s->scfunc = do_cut_next_word; + else if (!strcasecmp(input, "findbracket")) + s->scfunc = do_find_bracket; + else if (!strcasecmp(input, "wordcount")) + s->scfunc = do_wordlinechar_count; + else if (!strcasecmp(input, "recordmacro")) + s->scfunc = record_macro; + else if (!strcasecmp(input, "runmacro")) + s->scfunc = run_macro; + else if (!strcasecmp(input, "undo")) + s->scfunc = do_undo; + else if (!strcasecmp(input, "redo")) + s->scfunc = do_redo; #endif - else if (!strcasecmp(input, "left") || - !strcasecmp(input, "back")) - s->scfunc = do_left; - else if (!strcasecmp(input, "right") || - !strcasecmp(input, "forward")) - s->scfunc = do_right; - else if (!strcasecmp(input, "up") || - !strcasecmp(input, "prevline")) - s->scfunc = do_up_void; - else if (!strcasecmp(input, "down") || - !strcasecmp(input, "nextline")) - s->scfunc = do_down_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, "home")) - s->scfunc = do_home; - else if (!strcasecmp(input, "end")) - s->scfunc = do_end; - else if (!strcasecmp(input, "prevblock")) - s->scfunc = do_prev_block; - else if (!strcasecmp(input, "nextblock")) - s->scfunc = do_next_block; - 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 = to_first_line; - else if (!strcasecmp(input, "lastline")) - s->scfunc = to_last_line; + else if (!strcasecmp(input, "left") || + !strcasecmp(input, "back")) + s->scfunc = do_left; + else if (!strcasecmp(input, "right") || + !strcasecmp(input, "forward")) + s->scfunc = do_right; + else if (!strcasecmp(input, "up") || + !strcasecmp(input, "prevline")) + s->scfunc = do_up_void; + else if (!strcasecmp(input, "down") || + !strcasecmp(input, "nextline")) + s->scfunc = do_down_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, "home")) + s->scfunc = do_home; + else if (!strcasecmp(input, "end")) + s->scfunc = do_end; + else if (!strcasecmp(input, "prevblock")) + s->scfunc = do_prev_block; + else if (!strcasecmp(input, "nextblock")) + s->scfunc = do_next_block; + 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 = to_first_line; + else if (!strcasecmp(input, "lastline")) + s->scfunc = to_last_line; #ifdef ENABLE_MULTIBUFFER - else if (!strcasecmp(input, "prevbuf")) - s->scfunc = switch_to_prev_buffer; - else if (!strcasecmp(input, "nextbuf")) - s->scfunc = switch_to_next_buffer; + else if (!strcasecmp(input, "prevbuf")) + s->scfunc = switch_to_prev_buffer; + else if (!strcasecmp(input, "nextbuf")) + s->scfunc = switch_to_next_buffer; #endif - else if (!strcasecmp(input, "verbatim")) - s->scfunc = do_verbatim_input; - else if (!strcasecmp(input, "tab")) - s->scfunc = do_tab; - else if (!strcasecmp(input, "enter")) - s->scfunc = do_enter; - else if (!strcasecmp(input, "delete")) - s->scfunc = do_delete; - else if (!strcasecmp(input, "backspace")) - 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; - else if (!strcasecmp(input, "regexp") || - !strcasecmp(input, "regex")) /* Deprecated. Remove in 2018. */ - s->scfunc = regexp_void; - else if (!strcasecmp(input, "backwards")) - s->scfunc = backwards_void; - else if (!strcasecmp(input, "flipreplace") || - !strcasecmp(input, "dontreplace")) /* Deprecated. Remove in 2018. */ - s->scfunc = flip_replace; - else if (!strcasecmp(input, "gototext")) - s->scfunc = gototext_void; + else if (!strcasecmp(input, "verbatim")) + s->scfunc = do_verbatim_input; + else if (!strcasecmp(input, "tab")) + s->scfunc = do_tab; + else if (!strcasecmp(input, "enter")) + s->scfunc = do_enter; + else if (!strcasecmp(input, "delete")) + s->scfunc = do_delete; + else if (!strcasecmp(input, "backspace")) + 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; + else if (!strcasecmp(input, "regexp") || + !strcasecmp(input, "regex")) /* Deprecated. Remove in 2018. */ + s->scfunc = regexp_void; + else if (!strcasecmp(input, "backwards")) + s->scfunc = backwards_void; + else if (!strcasecmp(input, "flipreplace") || + !strcasecmp(input, "dontreplace")) /* Deprecated. Remove in 2018. */ + s->scfunc = flip_replace; + else if (!strcasecmp(input, "gototext")) + s->scfunc = gototext_void; #ifdef ENABLE_HISTORIES - else if (!strcasecmp(input, "prevhistory")) - s->scfunc = get_history_older_void; - else if (!strcasecmp(input, "nexthistory")) - s->scfunc = get_history_newer_void; + else if (!strcasecmp(input, "prevhistory")) + s->scfunc = get_history_older_void; + else if (!strcasecmp(input, "nexthistory")) + s->scfunc = get_history_newer_void; #endif #ifndef NANO_TINY - else if (!strcasecmp(input, "dosformat")) - s->scfunc = dos_format_void; - else if (!strcasecmp(input, "macformat")) - s->scfunc = mac_format_void; - else if (!strcasecmp(input, "append")) - s->scfunc = append_void; - else if (!strcasecmp(input, "prepend")) - s->scfunc = prepend_void; - else if (!strcasecmp(input, "backup")) - s->scfunc = backup_file_void; - else if (!strcasecmp(input, "flipexecute")) - s->scfunc = flip_execute; + else if (!strcasecmp(input, "dosformat")) + s->scfunc = dos_format_void; + else if (!strcasecmp(input, "macformat")) + s->scfunc = mac_format_void; + else if (!strcasecmp(input, "append")) + s->scfunc = append_void; + else if (!strcasecmp(input, "prepend")) + s->scfunc = prepend_void; + else if (!strcasecmp(input, "backup")) + s->scfunc = backup_file_void; + else if (!strcasecmp(input, "flipexecute")) + s->scfunc = flip_execute; #endif #ifdef ENABLE_MULTIBUFFER - else if (!strcasecmp(input, "flipnewbuffer") || - !strcasecmp(input, "newbuffer")) /* Deprecated. Remove in 2018. */ - s->scfunc = flip_newbuffer; + else if (!strcasecmp(input, "flipnewbuffer") || + !strcasecmp(input, "newbuffer")) /* Deprecated. Remove in 2018. */ + s->scfunc = flip_newbuffer; #endif #ifdef ENABLE_BROWSER - else if (!strcasecmp(input, "tofiles") || - !strcasecmp(input, "browser")) - s->scfunc = to_files_void; - else if (!strcasecmp(input, "gotodir")) - s->scfunc = goto_dir_void; - else if (!strcasecmp(input, "firstfile")) - s->scfunc = to_first_file; - else if (!strcasecmp(input, "lastfile")) - s->scfunc = to_last_file; + else if (!strcasecmp(input, "tofiles") || + !strcasecmp(input, "browser")) + s->scfunc = to_files_void; + else if (!strcasecmp(input, "gotodir")) + s->scfunc = goto_dir_void; + else if (!strcasecmp(input, "firstfile")) + s->scfunc = to_first_file; + else if (!strcasecmp(input, "lastfile")) + s->scfunc = to_last_file; #endif - else { + else { #ifndef NANO_TINY - s->scfunc = do_toggle_void; - if (!strcasecmp(input, "nohelp")) - s->toggle = NO_HELP; - else if (!strcasecmp(input, "constupdate")) - s->toggle = CONSTANT_SHOW; - else if (!strcasecmp(input, "morespace")) - s->toggle = MORE_SPACE; - else if (!strcasecmp(input, "smoothscroll")) - s->toggle = SMOOTH_SCROLL; - else if (!strcasecmp(input, "softwrap")) - s->toggle = SOFTWRAP; - else if (!strcasecmp(input, "whitespacedisplay")) - s->toggle = WHITESPACE_DISPLAY; + s->scfunc = do_toggle_void; + if (!strcasecmp(input, "nohelp")) + s->toggle = NO_HELP; + else if (!strcasecmp(input, "constupdate")) + s->toggle = CONSTANT_SHOW; + else if (!strcasecmp(input, "morespace")) + s->toggle = MORE_SPACE; + else if (!strcasecmp(input, "smoothscroll")) + s->toggle = SMOOTH_SCROLL; + else if (!strcasecmp(input, "softwrap")) + s->toggle = SOFTWRAP; + else if (!strcasecmp(input, "whitespacedisplay")) + s->toggle = WHITESPACE_DISPLAY; #ifdef ENABLE_COLOR - else if (!strcasecmp(input, "nosyntax")) - s->toggle = NO_COLOR_SYNTAX; + else if (!strcasecmp(input, "nosyntax")) + s->toggle = NO_COLOR_SYNTAX; #endif - else if (!strcasecmp(input, "smarthome")) - s->toggle = SMART_HOME; - else if (!strcasecmp(input, "autoindent")) - s->toggle = AUTOINDENT; - else if (!strcasecmp(input, "cuttoend")) - s->toggle = CUT_FROM_CURSOR; + else if (!strcasecmp(input, "smarthome")) + s->toggle = SMART_HOME; + else if (!strcasecmp(input, "autoindent")) + s->toggle = AUTOINDENT; + else if (!strcasecmp(input, "cuttoend")) + s->toggle = CUT_FROM_CURSOR; #ifdef ENABLE_WRAPPING - else if (!strcasecmp(input, "nowrap")) - s->toggle = NO_WRAP; + else if (!strcasecmp(input, "nowrap")) + s->toggle = NO_WRAP; #endif - else if (!strcasecmp(input, "tabstospaces")) - s->toggle = TABS_TO_SPACES; - else if (!strcasecmp(input, "backupfile")) - s->toggle = BACKUP_FILE; + else if (!strcasecmp(input, "tabstospaces")) + s->toggle = TABS_TO_SPACES; + else if (!strcasecmp(input, "backupfile")) + s->toggle = BACKUP_FILE; #ifdef ENABLE_MULTIBUFFER - else if (!strcasecmp(input, "multibuffer")) - s->toggle = MULTIBUFFER; + else if (!strcasecmp(input, "multibuffer")) + s->toggle = MULTIBUFFER; #endif #ifdef ENABLE_MOUSE - else if (!strcasecmp(input, "mouse")) - s->toggle = USE_MOUSE; + else if (!strcasecmp(input, "mouse")) + s->toggle = USE_MOUSE; #endif - else if (!strcasecmp(input, "noconvert")) - s->toggle = NO_CONVERT; - else if (!strcasecmp(input, "suspendenable")) - s->toggle = SUSPEND; - else + else if (!strcasecmp(input, "noconvert")) + s->toggle = NO_CONVERT; + else if (!strcasecmp(input, "suspendenable")) + s->toggle = SUSPEND; + else #endif /* !NANO_TINY */ - { - free(s); - return NULL; + { + free(s); + return NULL; + } } - } - return s; + return s; } /* Interpret a menu name and return the corresponding menu flag. */ int strtomenu(const char *input) { - if (!strcasecmp(input, "all")) - return (MMOST|MHELP|MYESNO); - else if (!strcasecmp(input, "main")) - return MMAIN; - else if (!strcasecmp(input, "search")) - return MWHEREIS; - else if (!strcasecmp(input, "replace")) - return MREPLACE; - else if (!strcasecmp(input, "replace2") || /* Deprecated. Remove in 2018. */ - !strcasecmp(input, "replacewith")) - return MREPLACEWITH; - else if (!strcasecmp(input, "gotoline")) - return MGOTOLINE; - else if (!strcasecmp(input, "writeout")) - return MWRITEFILE; - else if (!strcasecmp(input, "insert")) - return MINSERTFILE; - else if (!strcasecmp(input, "externalcmd") || - !strcasecmp(input, "extcmd")) - return MEXTCMD; + if (!strcasecmp(input, "all")) + return (MMOST|MHELP|MYESNO); + else if (!strcasecmp(input, "main")) + return MMAIN; + else if (!strcasecmp(input, "search")) + return MWHEREIS; + else if (!strcasecmp(input, "replace")) + return MREPLACE; + else if (!strcasecmp(input, "replace2") || /* Deprecated. Remove in 2018. */ + !strcasecmp(input, "replacewith")) + return MREPLACEWITH; + else if (!strcasecmp(input, "gotoline")) + return MGOTOLINE; + else if (!strcasecmp(input, "writeout")) + return MWRITEFILE; + else if (!strcasecmp(input, "insert")) + return MINSERTFILE; + else if (!strcasecmp(input, "externalcmd") || + !strcasecmp(input, "extcmd")) + return MEXTCMD; #ifdef ENABLE_HELP - else if (!strcasecmp(input, "help")) - return MHELP; + else if (!strcasecmp(input, "help")) + return MHELP; #endif #ifdef ENABLE_SPELLER - else if (!strcasecmp(input, "spell")) - return MSPELL; + else if (!strcasecmp(input, "spell")) + return MSPELL; #endif - else if (!strcasecmp(input, "linter")) - return MLINTER; + else if (!strcasecmp(input, "linter")) + return MLINTER; #ifdef ENABLE_BROWSER - else if (!strcasecmp(input, "browser")) - return MBROWSER; - else if (!strcasecmp(input, "whereisfile")) - return MWHEREISFILE; - else if (!strcasecmp(input, "gotodir")) - return MGOTODIR; + else if (!strcasecmp(input, "browser")) + return MBROWSER; + else if (!strcasecmp(input, "whereisfile")) + return MWHEREISFILE; + else if (!strcasecmp(input, "gotodir")) + return MGOTODIR; #endif - return -1; + return -1; } #endif /* ENABLE_NANORC */ @@ -1773,102 +1773,102 @@ int strtomenu(const char *input) * function unless debugging is turned on. */ void thanks_for_all_the_fish(void) { - if (topwin != NULL) - delwin(topwin); - delwin(edit); - delwin(bottomwin); + if (topwin != NULL) + delwin(topwin); + delwin(edit); + delwin(bottomwin); - free(word_chars); + free(word_chars); #ifdef ENABLE_JUSTIFY - free(quotestr); - regfree("ereg); - free(quoteerr); + free(quotestr); + regfree("ereg); + free(quoteerr); #endif #ifndef NANO_TINY - free(backup_dir); + free(backup_dir); #endif #ifdef ENABLE_OPERATINGDIR - free(operating_dir); + free(operating_dir); #endif - free(answer); - free(last_search); - free(present_path); + free(answer); + free(last_search); + free(present_path); #ifdef ENABLE_SPELLER - free(alt_speller); + free(alt_speller); #endif - free_filestruct(cutbuffer); - /* Free the memory associated with each open file buffer. */ - while (openfile != openfile->next) { - openfile = openfile->next; - delete_opennode(openfile->prev); - } - delete_opennode(openfile); + free_filestruct(cutbuffer); + /* Free the memory associated with each open file buffer. */ + while (openfile != openfile->next) { + openfile = openfile->next; + delete_opennode(openfile->prev); + } + delete_opennode(openfile); #ifdef ENABLE_COLOR - free(syntaxstr); - while (syntaxes != NULL) { - syntaxtype *sint = syntaxes; - syntaxes = syntaxes->next; + free(syntaxstr); + while (syntaxes != NULL) { + syntaxtype *sint = syntaxes; + syntaxes = syntaxes->next; - free(sint->name); - free(sint->linter); - free(sint->formatter); + free(sint->name); + free(sint->linter); + free(sint->formatter); - while (sint->extensions != NULL) { - regexlisttype *item = sint->extensions; - sint->extensions = sint->extensions->next; - free(item->full_regex); - free(item); - } - while (sint->headers != NULL) { - regexlisttype *item = sint->headers; - sint->headers = sint->headers->next; - free(item->full_regex); - free(item); - } - while (sint->magics != NULL) { - regexlisttype *item = sint->magics; - sint->magics = sint->magics->next; - free(item->full_regex); - free(item); - } + while (sint->extensions != NULL) { + regexlisttype *item = sint->extensions; + sint->extensions = sint->extensions->next; + free(item->full_regex); + free(item); + } + while (sint->headers != NULL) { + regexlisttype *item = sint->headers; + sint->headers = sint->headers->next; + free(item->full_regex); + free(item); + } + while (sint->magics != NULL) { + regexlisttype *item = sint->magics; + sint->magics = sint->magics->next; + free(item->full_regex); + free(item); + } - while (sint->color != NULL) { - colortype *ink = sint->color; - sint->color = sint->color->next; - free(ink->start_regex); - if (ink->start != NULL) { - regfree(ink->start); - free(ink->start); - } - free(ink->end_regex); - if (ink->end != NULL) { - regfree(ink->end); - free(ink->end); - } - free(ink); - } + while (sint->color != NULL) { + colortype *ink = sint->color; + sint->color = sint->color->next; + free(ink->start_regex); + if (ink->start != NULL) { + regfree(ink->start); + free(ink->start); + } + free(ink->end_regex); + if (ink->end != NULL) { + regfree(ink->end); + free(ink->end); + } + free(ink); + } - free(sint); - } + free(sint); + } #endif /* ENABLE_COLOR */ #ifdef ENABLE_HISTORIES - /* Free the search, replace, and execute history lists. */ - free_filestruct(searchtop); - free_filestruct(replacetop); - free_filestruct(executetop); + /* Free the search, replace, and execute history lists. */ + free_filestruct(searchtop); + free_filestruct(replacetop); + free_filestruct(executetop); #endif - /* Free the list of functions. */ - while (allfuncs != NULL) { - subnfunc *f = allfuncs; - allfuncs = allfuncs->next; - free(f); - } - /* Free the list of shortcuts. */ - while (sclist != NULL) { - sc *s = sclist; - sclist = sclist->next; - free(s); - } - free(homedir); + /* Free the list of functions. */ + while (allfuncs != NULL) { + subnfunc *f = allfuncs; + allfuncs = allfuncs->next; + free(f); + } + /* Free the list of shortcuts. */ + while (sclist != NULL) { + sc *s = sclist; + sclist = sclist->next; + free(s); + } + free(homedir); } #endif /* DEBUG */ diff --git a/src/help.c b/src/help.c index 77239055..aebf730a 100644 --- a/src/help.c +++ b/src/help.c @@ -28,599 +28,599 @@ #ifdef ENABLE_HELP static char *help_text = NULL; - /* The text displayed in the help window. */ + /* The text displayed in the help window. */ static const char *start_of_body = NULL; - /* The point in the help text just after the title. */ + /* The point in the help text just after the title. */ static char *end_of_intro = NULL; - /* The point in the help text where the shortcut descriptions begin. */ + /* The point in the help text where the shortcut descriptions begin. */ static size_t location; - /* The offset (in bytes) of the topleft of the shown help text. */ + /* The offset (in bytes) of the topleft of the shown help text. */ char *tempfilename = NULL; - /* Name of the temporary file used for wrapping the help text. */ + /* Name of the temporary file used for wrapping the help text. */ /* Hard-wrap the help text, write it to the existing temporary file, and * read that file into a new buffer. */ void wrap_the_help_text(bool redisplaying) { - int sum = 0; - const char *ptr = start_of_body; - FILE *tempfile = fopen(tempfilename, "w+b"); + int sum = 0; + const char *ptr = start_of_body; + FILE *tempfile = fopen(tempfilename, "w+b"); - /* If re-opening the temporary file failed, give up. */ - if (tempfile == NULL) { - statusline(ALERT, _("Error writing temp file: %s"), strerror(errno)); - return; - } + /* If re-opening the temporary file failed, give up. */ + if (tempfile == NULL) { + statusline(ALERT, _("Error writing temp file: %s"), strerror(errno)); + return; + } - /* Write the body of the help_text into the temporary file. */ - while (*ptr != '\0') { - int length = help_line_len(ptr); + /* Write the body of the help_text into the temporary file. */ + while (*ptr != '\0') { + int length = help_line_len(ptr); - fwrite(ptr, sizeof(char), length, tempfile); - ptr += length; + fwrite(ptr, sizeof(char), length, tempfile); + ptr += length; - /* Hard-wrap the lines in the help text. */ - if (*ptr != '\n') - fwrite("\n", sizeof(char), 1, tempfile); - else while (*ptr == '\n') - fwrite(ptr++, sizeof(char), 1, tempfile); - } + /* Hard-wrap the lines in the help text. */ + if (*ptr != '\n') + fwrite("\n", sizeof(char), 1, tempfile); + else while (*ptr == '\n') + fwrite(ptr++, sizeof(char), 1, tempfile); + } - fclose(tempfile); + fclose(tempfile); - if (redisplaying) - close_buffer(); + if (redisplaying) + close_buffer(); - open_buffer(tempfilename, FALSE); - remove_magicline(); + open_buffer(tempfilename, FALSE); + remove_magicline(); - prepare_for_display(); + prepare_for_display(); - /* Move to the position in the file where we were before. */ - while (TRUE) { - sum += strlen(openfile->current->data); - if (sum > location) - break; - openfile->current = openfile->current->next; - } + /* Move to the position in the file where we were before. */ + while (TRUE) { + sum += strlen(openfile->current->data); + if (sum > location) + break; + openfile->current = openfile->current->next; + } - openfile->edittop = openfile->current; + openfile->edittop = openfile->current; } /* Our main help-viewer function. */ void do_help(void) { - int kbinput = ERR; - functionptrtype func; - /* The function of the key the user typed in. */ - int oldmenu = currmenu; - /* The menu we were called from. */ + int kbinput = ERR; + functionptrtype func; + /* The function of the key the user typed in. */ + int oldmenu = currmenu; + /* The menu we were called from. */ #ifdef ENABLE_LINENUMBERS - int was_margin = margin; + int was_margin = margin; #endif - ssize_t was_tabsize = tabsize; + ssize_t was_tabsize = tabsize; #ifdef ENABLE_COLOR - char *was_syntax = syntaxstr; + char *was_syntax = syntaxstr; #endif - char *saved_answer = (answer != NULL) ? strdup(answer) : NULL; - /* The current answer when the user invokes help at the prompt. */ - unsigned stash[sizeof(flags) / sizeof(flags[0])]; - /* A storage place for the current flag settings. */ - filestruct *line; - int length; - FILE *fp; + char *saved_answer = (answer != NULL) ? strdup(answer) : NULL; + /* The current answer when the user invokes help at the prompt. */ + unsigned stash[sizeof(flags) / sizeof(flags[0])]; + /* A storage place for the current flag settings. */ + filestruct *line; + int length; + FILE *fp; - blank_statusbar(); + blank_statusbar(); - /* Get a temporary file for the help text. If it fails, give up. */ - tempfilename = safe_tempfile(&fp); - if (tempfilename == NULL) { - statusline(ALERT, _("Error writing temp file: %s"), strerror(errno)); - free(saved_answer); - return; - } + /* Get a temporary file for the help text. If it fails, give up. */ + tempfilename = safe_tempfile(&fp); + if (tempfilename == NULL) { + statusline(ALERT, _("Error writing temp file: %s"), strerror(errno)); + free(saved_answer); + return; + } - fclose(fp); + fclose(fp); - /* Save the settings of all flags. */ - memcpy(stash, flags, sizeof(flags)); + /* Save the settings of all flags. */ + memcpy(stash, flags, sizeof(flags)); - /* Ensure that the help screen's shortcut list can be displayed. */ - if (ISSET(NO_HELP) && LINES > 4) { - UNSET(NO_HELP); - window_init(); - } + /* Ensure that the help screen's shortcut list can be displayed. */ + if (ISSET(NO_HELP) && LINES > 4) { + UNSET(NO_HELP); + window_init(); + } - /* When searching, do it forward, case insensitive, and without regexes. */ - UNSET(BACKWARDS_SEARCH); - UNSET(CASE_SENSITIVE); - UNSET(USE_REGEXP); + /* When searching, do it forward, case insensitive, and without regexes. */ + UNSET(BACKWARDS_SEARCH); + UNSET(CASE_SENSITIVE); + UNSET(USE_REGEXP); - UNSET(WHITESPACE_DISPLAY); - UNSET(NOREAD_MODE); - SET(MULTIBUFFER); + UNSET(WHITESPACE_DISPLAY); + UNSET(NOREAD_MODE); + SET(MULTIBUFFER); #ifdef ENABLE_LINENUMBERS - UNSET(LINE_NUMBERS); - margin = 0; + UNSET(LINE_NUMBERS); + margin = 0; #endif - tabsize = 8; + tabsize = 8; #ifdef ENABLE_COLOR - syntaxstr = "nanohelp"; + syntaxstr = "nanohelp"; #endif - curs_set(0); + curs_set(0); - /* Compose the help text from all the pieces. */ - help_init(); - inhelp = TRUE; - location = 0; - didfind = 0; - - bottombars(MHELP); - wnoutrefresh(bottomwin); - - /* Extract the title from the head of the help text. */ - length = break_line(help_text, MAX_BUF_SIZE, TRUE); - title = charalloc(length * sizeof(char) + 1); - strncpy(title, help_text, length); - title[length] = '\0'; - - titlebar(title); - - /* Skip over the title to point at the start of the body text. */ - start_of_body = help_text + length; - while (*start_of_body == '\n') - start_of_body++; - - wrap_the_help_text(FALSE); - edit_refresh(); - - while (TRUE) { - lastmessage = HUSH; - focusing = TRUE; - - /* Show the cursor when we searched and found something. */ - kbinput = get_kbinput(edit, didfind == 1); + /* Compose the help text from all the pieces. */ + help_init(); + inhelp = TRUE; + location = 0; didfind = 0; - func = parse_help_input(&kbinput); + bottombars(MHELP); + wnoutrefresh(bottomwin); - if (func == total_refresh) { - total_redraw(); - } else if (func == do_up_void) { - do_up(TRUE); - } else if (func == do_down_void) { - if (openfile->edittop->lineno + editwinrows - 1 < - openfile->filebot->lineno) - do_down(TRUE); - } else if (func == do_page_up) { - do_page_up(); - } else if (func == do_page_down) { - do_page_down(); - } else if (func == to_first_line) { - to_first_line(); - } else if (func == to_last_line) { - to_last_line(); - } else if (func == do_search_forward) { - do_search(); - bottombars(MHELP); - } else if (func == do_research) { - do_research(); -#ifndef NANO_TINY - } else if (func == do_findprevious) { - do_findprevious(); - } else if (func == do_findnext) { - do_findnext(); - } else if (kbinput == KEY_WINCH) { - ; /* Nothing to do. */ -#endif -#ifdef ENABLE_MOUSE - } else if (kbinput == KEY_MOUSE) { - int dummy_x, dummy_y; - get_mouseinput(&dummy_x, &dummy_y, TRUE); -#endif - } else if (func == do_exit) { - /* Exit from the help viewer. */ - close_buffer(); - curs_set(0); - break; - } else - unbound_key(kbinput); + /* Extract the title from the head of the help text. */ + length = break_line(help_text, MAX_BUF_SIZE, TRUE); + title = charalloc(length * sizeof(char) + 1); + strncpy(title, help_text, length); + title[length] = '\0'; - currmenu = MHELP; + titlebar(title); + + /* Skip over the title to point at the start of the body text. */ + start_of_body = help_text + length; + while (*start_of_body == '\n') + start_of_body++; + + wrap_the_help_text(FALSE); edit_refresh(); - location = 0; - line = openfile->fileage; + while (TRUE) { + lastmessage = HUSH; + focusing = TRUE; - /* Count how far (in bytes) edittop is into the file. */ - while (line != openfile->edittop) { - location += strlen(line->data); - line = line->next; + /* Show the cursor when we searched and found something. */ + kbinput = get_kbinput(edit, didfind == 1); + didfind = 0; + + func = parse_help_input(&kbinput); + + if (func == total_refresh) { + total_redraw(); + } else if (func == do_up_void) { + do_up(TRUE); + } else if (func == do_down_void) { + if (openfile->edittop->lineno + editwinrows - 1 < + openfile->filebot->lineno) + do_down(TRUE); + } else if (func == do_page_up) { + do_page_up(); + } else if (func == do_page_down) { + do_page_down(); + } else if (func == to_first_line) { + to_first_line(); + } else if (func == to_last_line) { + to_last_line(); + } else if (func == do_search_forward) { + do_search(); + bottombars(MHELP); + } else if (func == do_research) { + do_research(); +#ifndef NANO_TINY + } else if (func == do_findprevious) { + do_findprevious(); + } else if (func == do_findnext) { + do_findnext(); + } else if (kbinput == KEY_WINCH) { + ; /* Nothing to do. */ +#endif +#ifdef ENABLE_MOUSE + } else if (kbinput == KEY_MOUSE) { + int dummy_x, dummy_y; + get_mouseinput(&dummy_x, &dummy_y, TRUE); +#endif + } else if (func == do_exit) { + /* Exit from the help viewer. */ + close_buffer(); + curs_set(0); + break; + } else + unbound_key(kbinput); + + currmenu = MHELP; + edit_refresh(); + + location = 0; + line = openfile->fileage; + + /* Count how far (in bytes) edittop is into the file. */ + while (line != openfile->edittop) { + location += strlen(line->data); + line = line->next; + } } - } - /* Restore the settings of all flags. */ - memcpy(flags, stash, sizeof(flags)); + /* Restore the settings of all flags. */ + memcpy(flags, stash, sizeof(flags)); #ifdef ENABLE_LINENUMBERS - margin = was_margin; + margin = was_margin; #endif - tabsize = was_tabsize; + tabsize = was_tabsize; #ifdef ENABLE_COLOR - syntaxstr = was_syntax; + syntaxstr = was_syntax; #endif - /* Switch back to the buffer we were invoked from. */ - switch_to_prev_buffer(); + /* Switch back to the buffer we were invoked from. */ + switch_to_prev_buffer(); - if (ISSET(NO_HELP)) { - currmenu = oldmenu; - window_init(); - } else - bottombars(oldmenu); + if (ISSET(NO_HELP)) { + currmenu = oldmenu; + window_init(); + } else + bottombars(oldmenu); - free(title); - title = NULL; - inhelp = FALSE; + free(title); + title = NULL; + inhelp = FALSE; #ifdef ENABLE_BROWSER - if (oldmenu == MBROWSER || oldmenu == MWHEREISFILE || oldmenu == MGOTODIR) - browser_refresh(); - else + if (oldmenu == MBROWSER || oldmenu == MWHEREISFILE || oldmenu == MGOTODIR) + browser_refresh(); + else #endif - total_refresh(); + total_refresh(); - free(answer); - answer = saved_answer; + free(answer); + answer = saved_answer; - remove(tempfilename); - free(tempfilename); + remove(tempfilename); + free(tempfilename); - free(help_text); + free(help_text); } /* Allocate space for the help text for the current menu, and concatenate * the different pieces of text into it. */ void help_init(void) { - size_t allocsize = 0; - /* Space needed for help_text. */ - const char *htx[3]; - /* Untranslated help introduction. We break it up into three chunks - * in case the full string is too long for the compiler to handle. */ - char *ptr; - const subnfunc *f; - const sc *s; + size_t allocsize = 0; + /* Space needed for help_text. */ + const char *htx[3]; + /* Untranslated help introduction. We break it up into three chunks + * in case the full string is too long for the compiler to handle. */ + char *ptr; + const subnfunc *f; + const sc *s; - /* First, set up the initial help text for the current function. */ - 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 " - "match for the text you entered, the screen will be " - "updated to the location of the nearest match for the " - "search string.\n\n The previous search string will be " - "shown in brackets after the search prompt. Hitting " - "Enter without entering any text will perform the " - "previous search. "); - htx[1] = N_("If you have selected text with the mark and then " - "search to replace, only matches in the selected text " - "will be replaced.\n\n The following function keys are " - "available in Search mode:\n\n"); - htx[2] = NULL; - } else if (currmenu == MGOTOLINE) { - htx[0] = N_("Go To Line Help Text\n\n " - "Enter the line number that you wish to go to and hit " - "Enter. If there are fewer lines of text than the " - "number you entered, you will be brought to the last " - "line of the file.\n\n The following function keys are " - "available in Go To Line mode:\n\n"); - htx[1] = NULL; - htx[2] = NULL; - } else if (currmenu == MINSERTFILE) { - htx[0] = N_("Insert File Help Text\n\n " - "Type in the name of a file to be inserted into the " - "current file buffer at the current cursor " - "location.\n\n If you have compiled nano with multiple " - "file buffer support, and enable multiple file buffers " - "with the -F or --multibuffer command line flags, the " - "Meta-F toggle, or a nanorc file, inserting a file " - "will cause it to be loaded into a separate buffer " - "(use Meta-< and > to switch between file buffers). "); - htx[1] = N_("If you need another blank buffer, do not enter " - "any filename, or type in a nonexistent filename at " - "the prompt and press Enter.\n\n The following " - "function keys are available in Insert File mode:\n\n"); - htx[2] = NULL; - } else if (currmenu == MWRITEFILE) { - htx[0] = N_("Write File Help Text\n\n " - "Type the name that you wish to save the current file " - "as and press Enter to save the file.\n\n If you have " - "selected text with the mark, you will be prompted to " - "save only the selected portion to a separate file. To " - "reduce the chance of overwriting the current file with " - "just a portion of it, the current filename is not the " - "default in this mode.\n\n The following function keys " - "are available in Write File mode:\n\n"); - htx[1] = NULL; - htx[2] = NULL; - } + /* First, set up the initial help text for the current function. */ + 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 " + "match for the text you entered, the screen will be " + "updated to the location of the nearest match for the " + "search string.\n\n The previous search string will be " + "shown in brackets after the search prompt. Hitting " + "Enter without entering any text will perform the " + "previous search. "); + htx[1] = N_("If you have selected text with the mark and then " + "search to replace, only matches in the selected text " + "will be replaced.\n\n The following function keys are " + "available in Search mode:\n\n"); + htx[2] = NULL; + } else if (currmenu == MGOTOLINE) { + htx[0] = N_("Go To Line Help Text\n\n " + "Enter the line number that you wish to go to and hit " + "Enter. If there are fewer lines of text than the " + "number you entered, you will be brought to the last " + "line of the file.\n\n The following function keys are " + "available in Go To Line mode:\n\n"); + htx[1] = NULL; + htx[2] = NULL; + } else if (currmenu == MINSERTFILE) { + htx[0] = N_("Insert File Help Text\n\n " + "Type in the name of a file to be inserted into the " + "current file buffer at the current cursor " + "location.\n\n If you have compiled nano with multiple " + "file buffer support, and enable multiple file buffers " + "with the -F or --multibuffer command line flags, the " + "Meta-F toggle, or a nanorc file, inserting a file " + "will cause it to be loaded into a separate buffer " + "(use Meta-< and > to switch between file buffers). "); + htx[1] = N_("If you need another blank buffer, do not enter " + "any filename, or type in a nonexistent filename at " + "the prompt and press Enter.\n\n The following " + "function keys are available in Insert File mode:\n\n"); + htx[2] = NULL; + } else if (currmenu == MWRITEFILE) { + htx[0] = N_("Write File Help Text\n\n " + "Type the name that you wish to save the current file " + "as and press Enter to save the file.\n\n If you have " + "selected text with the mark, you will be prompted to " + "save only the selected portion to a separate file. To " + "reduce the chance of overwriting the current file with " + "just a portion of it, the current filename is not the " + "default in this mode.\n\n The following function keys " + "are available in Write File mode:\n\n"); + htx[1] = NULL; + htx[2] = NULL; + } #ifdef ENABLE_BROWSER - else if (currmenu == MBROWSER) { - htx[0] = N_("File Browser Help Text\n\n " - "The file browser is used to visually browse the " - "directory structure to select a file for reading " - "or writing. You may use the arrow keys or Page Up/" - "Down to browse through the files, and S or Enter to " - "choose the selected file or enter the selected " - "directory. To move up one level, select the " - "directory called \"..\" at the top of the file " - "list.\n\n The following function keys are available " - "in the file browser:\n\n"); - htx[1] = NULL; - htx[2] = NULL; - } else if (currmenu == MWHEREISFILE) { - htx[0] = N_("Browser 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 " - "match for the text you entered, the screen will be " - "updated to the location of the nearest match for the " - "search string.\n\n The previous search string will be " - "shown in brackets after the search prompt. Hitting " - "Enter without entering any text will perform the " - "previous search.\n\n"); - htx[1] = N_(" The following function keys are available in " - "Browser Search mode:\n\n"); - htx[2] = NULL; - } else if (currmenu == MGOTODIR) { - htx[0] = N_("Browser Go To Directory Help Text\n\n " - "Enter the name of the directory you would like to " - "browse to.\n\n If tab completion has not been " - "disabled, you can use the Tab key to (attempt to) " - "automatically complete the directory name.\n\n The " - "following function keys are available in Browser Go " - "To Directory mode:\n\n"); - htx[1] = NULL; - htx[2] = NULL; - } + else if (currmenu == MBROWSER) { + htx[0] = N_("File Browser Help Text\n\n " + "The file browser is used to visually browse the " + "directory structure to select a file for reading " + "or writing. You may use the arrow keys or Page Up/" + "Down to browse through the files, and S or Enter to " + "choose the selected file or enter the selected " + "directory. To move up one level, select the " + "directory called \"..\" at the top of the file " + "list.\n\n The following function keys are available " + "in the file browser:\n\n"); + htx[1] = NULL; + htx[2] = NULL; + } else if (currmenu == MWHEREISFILE) { + htx[0] = N_("Browser 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 " + "match for the text you entered, the screen will be " + "updated to the location of the nearest match for the " + "search string.\n\n The previous search string will be " + "shown in brackets after the search prompt. Hitting " + "Enter without entering any text will perform the " + "previous search.\n\n"); + htx[1] = N_(" The following function keys are available in " + "Browser Search mode:\n\n"); + htx[2] = NULL; + } else if (currmenu == MGOTODIR) { + htx[0] = N_("Browser Go To Directory Help Text\n\n " + "Enter the name of the directory you would like to " + "browse to.\n\n If tab completion has not been " + "disabled, you can use the Tab key to (attempt to) " + "automatically complete the directory name.\n\n The " + "following function keys are available in Browser Go " + "To Directory mode:\n\n"); + htx[1] = NULL; + htx[2] = NULL; + } #endif /* ENABLE_BROWSER */ #ifdef ENABLE_SPELLER - else if (currmenu == MSPELL) { - htx[0] = N_("Spell Check Help Text\n\n " - "The spell checker checks the spelling of all text in " - "the current file. When an unknown word is " - "encountered, it is highlighted and a replacement can " - "be edited. It will then prompt to replace every " - "instance of the given misspelled word in the current " - "file, or, if you have selected text with the mark, in " - "the selected text.\n\n The following function keys " - "are available in Spell Check mode:\n\n"); - htx[1] = NULL; - htx[2] = NULL; - } + else if (currmenu == MSPELL) { + htx[0] = N_("Spell Check Help Text\n\n " + "The spell checker checks the spelling of all text in " + "the current file. When an unknown word is " + "encountered, it is highlighted and a replacement can " + "be edited. It will then prompt to replace every " + "instance of the given misspelled word in the current " + "file, or, if you have selected text with the mark, in " + "the selected text.\n\n The following function keys " + "are available in Spell Check mode:\n\n"); + htx[1] = NULL; + htx[2] = NULL; + } #endif /* ENABLE_SPELLER */ #ifndef NANO_TINY - else if (currmenu == MEXTCMD) { - htx[0] = N_("Execute Command Help Text\n\n " - "This mode allows you to insert the output of a " - "command run by the shell into the current buffer (or " - "a new buffer in multiple file buffer mode). If you " - "need another blank buffer, do not enter any " - "command.\n\n The following function keys are " - "available in Execute Command mode:\n\n"); - htx[1] = NULL; - htx[2] = NULL; - } + else if (currmenu == MEXTCMD) { + htx[0] = N_("Execute Command Help Text\n\n " + "This mode allows you to insert the output of a " + "command run by the shell into the current buffer (or " + "a new buffer in multiple file buffer mode). If you " + "need another blank buffer, do not enter any " + "command.\n\n The following function keys are " + "available in Execute Command mode:\n\n"); + htx[1] = NULL; + htx[2] = NULL; + } #endif /* !NANO_TINY */ - else { - /* Default to the main help list. */ - htx[0] = N_("Main nano help text\n\n " - "The nano editor is designed to emulate the " - "functionality and ease-of-use of the UW Pico text " - "editor. There are four main sections of the editor. " - "The top line shows the program version, the current " - "filename being edited, and whether or not the file " - "has been modified. Next is the main editor window " - "showing the file being edited. The status line is " - "the third line from the bottom and shows important " - "messages. "); - htx[1] = N_("The bottom two lines show the most commonly used " - "shortcuts in the editor.\n\n Shortcuts are written as " - "follows: Control-key sequences are notated with a '^' " - "and can be entered either by using the Ctrl key or " - "pressing the Esc key twice. Meta-key sequences are " - "notated with 'M-' and can be entered using either the " - "Alt, Cmd, or Esc key, depending on your keyboard setup. "); - htx[2] = N_("Also, pressing Esc twice and then typing a " - "three-digit decimal number from 000 to 255 will enter " - "the character with the corresponding value. The " - "following keystrokes are available in the main editor " - "window. Alternative keys are shown in " - "parentheses:\n\n"); - } + else { + /* Default to the main help list. */ + htx[0] = N_("Main nano help text\n\n " + "The nano editor is designed to emulate the " + "functionality and ease-of-use of the UW Pico text " + "editor. There are four main sections of the editor. " + "The top line shows the program version, the current " + "filename being edited, and whether or not the file " + "has been modified. Next is the main editor window " + "showing the file being edited. The status line is " + "the third line from the bottom and shows important " + "messages. "); + htx[1] = N_("The bottom two lines show the most commonly used " + "shortcuts in the editor.\n\n Shortcuts are written as " + "follows: Control-key sequences are notated with a '^' " + "and can be entered either by using the Ctrl key or " + "pressing the Esc key twice. Meta-key sequences are " + "notated with 'M-' and can be entered using either the " + "Alt, Cmd, or Esc key, depending on your keyboard setup. "); + htx[2] = N_("Also, pressing Esc twice and then typing a " + "three-digit decimal number from 000 to 255 will enter " + "the character with the corresponding value. The " + "following keystrokes are available in the main editor " + "window. Alternative keys are shown in " + "parentheses:\n\n"); + } - htx[0] = _(htx[0]); - if (htx[1] != NULL) - htx[1] = _(htx[1]); - if (htx[2] != NULL) - htx[2] = _(htx[2]); + htx[0] = _(htx[0]); + if (htx[1] != NULL) + htx[1] = _(htx[1]); + if (htx[2] != NULL) + htx[2] = _(htx[2]); - allocsize += strlen(htx[0]); - if (htx[1] != NULL) - allocsize += strlen(htx[1]); - if (htx[2] != NULL) - allocsize += strlen(htx[2]); + allocsize += strlen(htx[0]); + if (htx[1] != NULL) + allocsize += strlen(htx[1]); + if (htx[2] != NULL) + allocsize += strlen(htx[2]); - /* 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 += (16 * MAXCHARLEN) + strlen(_(f->help)) + 2; + /* 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 += (16 * MAXCHARLEN) + 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", 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")); + /* If we're on the main list, we also count the toggle help text. + * 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 + 8; - } + for (s = sclist; s != NULL; s = s->next) + if (s->scfunc == do_toggle_void) + allocsize += strlen(_(flagtostr(s->toggle))) + endis_len + 8; + } #endif - /* Allocate memory for the help text. */ - help_text = charalloc(allocsize + 1); + /* Allocate memory for the help text. */ + help_text = charalloc(allocsize + 1); - /* Now add the text we want. */ - strcpy(help_text, htx[0]); - if (htx[1] != NULL) - strcat(help_text, htx[1]); - if (htx[2] != NULL) - strcat(help_text, htx[2]); + /* Now add the text we want. */ + strcpy(help_text, htx[0]); + if (htx[1] != NULL) + strcat(help_text, htx[1]); + if (htx[2] != NULL) + strcat(help_text, htx[2]); - ptr = help_text + strlen(help_text); + ptr = help_text + strlen(help_text); - /* Remember this end-of-introduction, start-of-shortcuts. */ - end_of_intro = ptr; + /* Remember this end-of-introduction, start-of-shortcuts. */ + end_of_intro = ptr; - /* Now add our shortcut info. */ - for (f = allfuncs; f != NULL; f = f->next) { - int scsfound = 0; + /* Now add our shortcut info. */ + for (f = allfuncs; f != NULL; f = f->next) { + int scsfound = 0; - if ((f->menus & currmenu) == 0) - continue; + if ((f->menus & currmenu) == 0) + continue; - /* Let's simply show the first two shortcuts from the list. */ - for (s = sclist; s != NULL; s = s->next) { + /* Let's simply show the first two shortcuts from the list. */ + for (s = sclist; s != NULL; s = s->next) { - if ((s->menus & currmenu) == 0) - continue; + if ((s->menus & currmenu) == 0) + continue; - if (s->scfunc == f->scfunc) { - scsfound++; - /* 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); - /* Unicode arrows take three bytes instead of one. */ - if (strstr(s->keystr, "\xE2") != NULL) - ptr += 8; - else - ptr += 6; - } else { - ptr += sprintf(ptr, "(%s)\t", s->keystr); - break; + if (s->scfunc == f->scfunc) { + scsfound++; + /* 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); + /* Unicode arrows take three bytes instead of one. */ + if (strstr(s->keystr, "\xE2") != NULL) + ptr += 8; + else + ptr += 6; + } else { + ptr += sprintf(ptr, "(%s)\t", s->keystr); + break; + } + } } - } + + 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)); + + if (f->blank_after) + ptr += sprintf(ptr, "\n"); } - 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)); - - if (f->blank_after) - ptr += sprintf(ptr, "\n"); - } - #ifndef NANO_TINY - /* And the toggles... */ - if (currmenu == MMAIN) { - int maximum = 0, counter = 0; + /* And the toggles... */ + if (currmenu == MMAIN) { + int maximum = 0, counter = 0; - /* First see how many toggles there are. */ - for (s = sclist; s != NULL; s = s->next) - maximum = (s->toggle && s->ordinal > maximum) ? s->ordinal : maximum; + /* First see how many toggles there are. */ + for (s = sclist; s != NULL; s = s->next) + maximum = (s->toggle && s->ordinal > maximum) ? s->ordinal : maximum; - /* Now show them in the original order. */ - while (counter < maximum) { - counter++; - for (s = sclist; s != NULL; s = s->next) - if (s->toggle && s->ordinal == counter) { - ptr += sprintf(ptr, "%s\t\t%s %s\n", (s->menus == MMAIN ? s->keystr : ""), - _(flagtostr(s->toggle)), _("enable/disable")); - if (s->toggle == NO_COLOR_SYNTAX || s->toggle == TABS_TO_SPACES) - ptr += sprintf(ptr, "\n"); - break; + /* Now show them in the original order. */ + while (counter < maximum) { + counter++; + for (s = sclist; s != NULL; s = s->next) + if (s->toggle && s->ordinal == counter) { + ptr += sprintf(ptr, "%s\t\t%s %s\n", (s->menus == MMAIN ? s->keystr : ""), + _(flagtostr(s->toggle)), _("enable/disable")); + if (s->toggle == NO_COLOR_SYNTAX || s->toggle == TABS_TO_SPACES) + ptr += sprintf(ptr, "\n"); + break; + } } } - } #endif /* !NANO_TINY */ - if (strlen(help_text) > allocsize) - statusline(ALERT, "Help text spilled over -- please report a bug"); + if (strlen(help_text) > allocsize) + statusline(ALERT, "Help text spilled over -- please report a bug"); } /* Return the function that is bound to the given key, accepting certain * plain characters too, for consistency with the file browser. */ functionptrtype parse_help_input(int *kbinput) { - if (!meta_key) { - switch (*kbinput) { - case ' ': - return do_page_down; - case '-': - return do_page_up; - case 'W': - case 'w': - case '/': - return do_search_forward; - case 'N': + if (!meta_key) { + switch (*kbinput) { + case ' ': + return do_page_down; + case '-': + return do_page_up; + case 'W': + case 'w': + case '/': + return do_search_forward; + case 'N': #ifndef NANO_TINY - return do_findprevious; + return do_findprevious; #endif - case 'n': - return do_research; - case 'E': - case 'e': - case 'Q': - case 'q': - case 'X': - case 'x': - return do_exit; + case 'n': + return do_research; + case 'E': + case 'e': + case 'Q': + case 'q': + case 'X': + case 'x': + return do_exit; + } } - } - return func_from_key(kbinput); + return func_from_key(kbinput); } /* Calculate the displayable length of the help-text line starting at ptr. */ size_t help_line_len(const char *ptr) { - size_t wrapping_point = (COLS > 24) ? COLS - 1 : 24; - /* The target width for wrapping long lines. */ - ssize_t wrap_location; - /* Actual position where the line can be wrapped. */ - size_t length = 0; - /* Full length of the line, until the first newline. */ + size_t wrapping_point = (COLS > 24) ? COLS - 1 : 24; + /* The target width for wrapping long lines. */ + ssize_t wrap_location; + /* Actual position where the line can be wrapped. */ + size_t length = 0; + /* Full length of the line, until the first newline. */ - /* Avoid overwide paragraphs in the introductory text. */ - if (ptr < end_of_intro && COLS > 74) - wrapping_point = 74; + /* Avoid overwide paragraphs in the introductory text. */ + if (ptr < end_of_intro && COLS > 74) + wrapping_point = 74; - wrap_location = break_line(ptr, wrapping_point, TRUE); + wrap_location = break_line(ptr, wrapping_point, TRUE); - /* Get the length of the entire line up to a null or a newline. */ - while (*(ptr + length) != '\0' && *(ptr + length) != '\n') - length = move_mbright(ptr, length); + /* Get the length of the entire line up to a null or a newline. */ + while (*(ptr + length) != '\0' && *(ptr + length) != '\n') + length = move_mbright(ptr, length); - /* If the entire line will just fit the screen, don't wrap it. */ - if (strnlenpt(ptr, length) <= wrapping_point + 1) - return length; - else if (wrap_location > 0) - return wrap_location; - else - return 0; + /* If the entire line will just fit the screen, don't wrap it. */ + if (strnlenpt(ptr, length) <= wrapping_point + 1) + return length; + else if (wrap_location > 0) + return wrap_location; + else + return 0; } #endif /* ENABLE_HELP */ @@ -629,11 +629,11 @@ size_t help_line_len(const char *ptr) void do_help_void(void) { #ifdef ENABLE_HELP - do_help(); + do_help(); #else - if (currmenu == MMAIN) - say_there_is_no_help(); - else - beep(); + if (currmenu == MMAIN) + say_there_is_no_help(); + else + beep(); #endif } diff --git a/src/history.c b/src/history.c index a561f8d6..f88789b2 100644 --- a/src/history.c +++ b/src/history.c @@ -35,146 +35,146 @@ #endif static bool history_changed = FALSE; - /* Whether any of the history lists has changed. */ + /* Whether any of the history lists has changed. */ static struct stat stat_of_positions_file; - /* The last-obtained stat information of the positions file. */ + /* The last-obtained stat information of the positions file. */ static char *poshistname = NULL; - /* The name of the positions-history file. */ + /* The name of the positions-history file. */ /* Initialize the lists of historical search and replace strings * and the list of historical executed commands. */ void history_init(void) { - search_history = make_new_node(NULL); - search_history->data = mallocstrcpy(NULL, ""); - searchtop = search_history; - searchbot = search_history; + search_history = make_new_node(NULL); + search_history->data = mallocstrcpy(NULL, ""); + searchtop = search_history; + searchbot = search_history; - replace_history = make_new_node(NULL); - replace_history->data = mallocstrcpy(NULL, ""); - replacetop = replace_history; - replacebot = replace_history; + replace_history = make_new_node(NULL); + replace_history->data = mallocstrcpy(NULL, ""); + replacetop = replace_history; + replacebot = replace_history; - execute_history = make_new_node(NULL); - execute_history->data = mallocstrcpy(NULL, ""); - executetop = execute_history; - executebot = execute_history; + execute_history = make_new_node(NULL); + execute_history->data = mallocstrcpy(NULL, ""); + executetop = execute_history; + executebot = execute_history; } /* Set the current position in the given history list to the bottom. */ void history_reset(const filestruct *list) { - if (list == search_history) - search_history = searchbot; - else if (list == replace_history) - replace_history = replacebot; - else if (list == execute_history) - execute_history = executebot; + if (list == search_history) + search_history = searchbot; + else if (list == replace_history) + replace_history = replacebot; + else if (list == execute_history) + execute_history = executebot; } /* Return from the history list that starts at start and ends at end * the first node that contains the first len characters of the given * text, or NULL if there is no such node. */ filestruct *find_history(const filestruct *start, const filestruct *end, - const char *text, size_t len) + const char *text, size_t len) { - const filestruct *item; + const filestruct *item; - for (item = start; item != end->prev && item != NULL; item = item->prev) { - if (strncmp(item->data, text, len) == 0) - return (filestruct *)item; - } + for (item = start; item != end->prev && item != NULL; item = item->prev) { + if (strncmp(item->data, text, len) == 0) + return (filestruct *)item; + } - return NULL; + return NULL; } /* Update a history list (the one in which item is the current position) * with a fresh string text. That is: add text, or move it to the end. */ void update_history(filestruct **item, const char *text) { - filestruct **htop = NULL, **hbot = NULL, *thesame; + filestruct **htop = NULL, **hbot = NULL, *thesame; - if (*item == search_history) { - htop = &searchtop; - hbot = &searchbot; - } else if (*item == replace_history) { - htop = &replacetop; - hbot = &replacebot; - } else if (*item == execute_history) { - htop = &executetop; - hbot = &executebot; - } + if (*item == search_history) { + htop = &searchtop; + hbot = &searchbot; + } else if (*item == replace_history) { + htop = &replacetop; + hbot = &replacebot; + } else if (*item == execute_history) { + htop = &executetop; + hbot = &executebot; + } - /* See if the string is already in the history. */ - thesame = find_history(*hbot, *htop, text, HIGHEST_POSITIVE); + /* See if the string is already in the history. */ + thesame = find_history(*hbot, *htop, text, HIGHEST_POSITIVE); - /* If an identical string was found, delete that item. */ - if (thesame != NULL) { - filestruct *after = thesame->next; + /* If an identical string was found, delete that item. */ + if (thesame != NULL) { + filestruct *after = thesame->next; - /* If the string is at the head of the list, move the head. */ - if (thesame == *htop) - *htop = after; + /* If the string is at the head of the list, move the head. */ + if (thesame == *htop) + *htop = after; - unlink_node(thesame); - renumber(after); - } + unlink_node(thesame); + renumber(after); + } - /* If the history is full, delete the oldest item (the one at the - * head of the list), to make room for a new item at the end. */ - if ((*hbot)->lineno == MAX_SEARCH_HISTORY + 1) { - filestruct *oldest = *htop; + /* If the history is full, delete the oldest item (the one at the + * head of the list), to make room for a new item at the end. */ + if ((*hbot)->lineno == MAX_SEARCH_HISTORY + 1) { + filestruct *oldest = *htop; - *htop = (*htop)->next; - unlink_node(oldest); - renumber(*htop); - } + *htop = (*htop)->next; + unlink_node(oldest); + renumber(*htop); + } - /* Store the fresh string in the last item, then create a new item. */ - (*hbot)->data = mallocstrcpy((*hbot)->data, text); - splice_node(*hbot, make_new_node(*hbot)); - *hbot = (*hbot)->next; - (*hbot)->data = mallocstrcpy(NULL, ""); + /* Store the fresh string in the last item, then create a new item. */ + (*hbot)->data = mallocstrcpy((*hbot)->data, text); + splice_node(*hbot, make_new_node(*hbot)); + *hbot = (*hbot)->next; + (*hbot)->data = mallocstrcpy(NULL, ""); - /* Indicate that the history needs to be saved on exit. */ - history_changed = TRUE; + /* Indicate that the history needs to be saved on exit. */ + history_changed = TRUE; - /* Set the current position in the list to the bottom. */ - *item = *hbot; + /* Set the current position in the list to the bottom. */ + *item = *hbot; } /* Move h to the string in the history list just before it, and return * that string. If there isn't one, don't move h and return NULL. */ char *get_history_older(filestruct **h) { - if ((*h)->prev == NULL) - return NULL; + if ((*h)->prev == NULL) + return NULL; - *h = (*h)->prev; + *h = (*h)->prev; - return (*h)->data; + return (*h)->data; } /* Move h to the string in the history list just after it, and return * that string. If there isn't one, don't move h and return NULL. */ char *get_history_newer(filestruct **h) { - if ((*h)->next == NULL) - return NULL; + if ((*h)->next == NULL) + return NULL; - *h = (*h)->next; + *h = (*h)->next; - return (*h)->data; + return (*h)->data; } /* More placeholders. */ void get_history_newer_void(void) { - ; + ; } void get_history_older_void(void) { - ; + ; } #ifdef ENABLE_TABCOMP @@ -184,408 +184,408 @@ void get_history_older_void(void) * s. */ char *get_history_completion(filestruct **h, char *s, size_t len) { - if (len > 0) { - filestruct *htop = NULL, *hbot = NULL, *p; + if (len > 0) { + filestruct *htop = NULL, *hbot = NULL, *p; - if (*h == search_history) { - htop = searchtop; - hbot = searchbot; - } else if (*h == replace_history) { - htop = replacetop; - hbot = replacebot; - } else if (*h == execute_history) { - htop = executetop; - hbot = executebot; + if (*h == search_history) { + htop = searchtop; + hbot = searchbot; + } else if (*h == replace_history) { + htop = replacetop; + hbot = replacebot; + } else if (*h == execute_history) { + htop = executetop; + hbot = executebot; + } + + /* Search the history list from the current position to the top + * for a match of len characters. Skip over an exact match. */ + p = find_history((*h)->prev, htop, s, len); + + while (p != NULL && strcmp(p->data, s) == 0) + p = find_history(p->prev, htop, s, len); + + if (p != NULL) { + *h = p; + return mallocstrcpy(s, (*h)->data); + } + + /* Search the history list from the bottom to the current position + * for a match of len characters. Skip over an exact match. */ + p = find_history(hbot, *h, s, len); + + while (p != NULL && strcmp(p->data, s) == 0) + p = find_history(p->prev, *h, s, len); + + if (p != NULL) { + *h = p; + return mallocstrcpy(s, (*h)->data); + } } - /* Search the history list from the current position to the top - * for a match of len characters. Skip over an exact match. */ - p = find_history((*h)->prev, htop, s, len); - - while (p != NULL && strcmp(p->data, s) == 0) - p = find_history(p->prev, htop, s, len); - - if (p != NULL) { - *h = p; - return mallocstrcpy(s, (*h)->data); - } - - /* Search the history list from the bottom to the current position - * for a match of len characters. Skip over an exact match. */ - p = find_history(hbot, *h, s, len); - - while (p != NULL && strcmp(p->data, s) == 0) - p = find_history(p->prev, *h, s, len); - - if (p != NULL) { - *h = p; - return mallocstrcpy(s, (*h)->data); - } - } - - /* If we're here, we didn't find a match, we didn't find an inexact - * match, or len is 0. Return s. */ - return (char *)s; + /* If we're here, we didn't find a match, we didn't find an inexact + * match, or len is 0. Return s. */ + return (char *)s; } #endif /* ENSABLE_TABCOMP */ void history_error(const char *msg, ...) { - va_list ap; + va_list ap; - va_start(ap, msg); - vfprintf(stderr, _(msg), ap); - va_end(ap); + va_start(ap, msg); + vfprintf(stderr, _(msg), ap); + va_end(ap); - fprintf(stderr, _("\nPress Enter to continue\n")); - while (getchar() != '\n') - ; + fprintf(stderr, _("\nPress Enter to continue\n")); + while (getchar() != '\n') + ; } /* Check whether we have or could make a directory for history files. */ bool have_statedir(void) { - struct stat dirstat; - const char *xdgdatadir; + struct stat dirstat; + const char *xdgdatadir; - get_homedir(); + get_homedir(); - if (homedir != NULL) { - statedir = concatenate(homedir, "/.nano/"); + if (homedir != NULL) { + statedir = concatenate(homedir, "/.nano/"); - if (stat(statedir, &dirstat) == 0 && S_ISDIR(dirstat.st_mode)) { - poshistname = concatenate(statedir, POSITION_HISTORY); - return TRUE; + if (stat(statedir, &dirstat) == 0 && S_ISDIR(dirstat.st_mode)) { + poshistname = concatenate(statedir, POSITION_HISTORY); + return TRUE; + } } - } - free(statedir); - xdgdatadir = getenv("XDG_DATA_HOME"); + free(statedir); + xdgdatadir = getenv("XDG_DATA_HOME"); - if (homedir == NULL && xdgdatadir == NULL) - return FALSE; + if (homedir == NULL && xdgdatadir == NULL) + return FALSE; - if (xdgdatadir != NULL) - statedir = concatenate(xdgdatadir, "/nano/"); - else - statedir = concatenate(homedir, "/.local/share/nano/"); + if (xdgdatadir != NULL) + statedir = concatenate(xdgdatadir, "/nano/"); + else + statedir = concatenate(homedir, "/.local/share/nano/"); - if (stat(statedir, &dirstat) == -1) { - if (xdgdatadir == NULL) { - char *statepath = concatenate(homedir, "/.local"); - mkdir(statepath, S_IRWXU | S_IRWXG | S_IRWXO); - free(statepath); - statepath = concatenate(homedir, "/.local/share"); - mkdir(statepath, S_IRWXU); - free(statepath); + if (stat(statedir, &dirstat) == -1) { + if (xdgdatadir == NULL) { + char *statepath = concatenate(homedir, "/.local"); + mkdir(statepath, S_IRWXU | S_IRWXG | S_IRWXO); + free(statepath); + statepath = concatenate(homedir, "/.local/share"); + mkdir(statepath, S_IRWXU); + free(statepath); + } + if (mkdir(statedir, S_IRWXU) == -1) { + history_error(N_("Unable to create directory %s: %s\n" + "It is required for saving/loading " + "search history or cursor positions.\n"), + statedir, strerror(errno)); + return FALSE; + } + } else if (!S_ISDIR(dirstat.st_mode)) { + history_error(N_("Path %s is not a directory and needs to be.\n" + "Nano will be unable to load or save " + "search history or cursor positions.\n"), + statedir); + return FALSE; } - if (mkdir(statedir, S_IRWXU) == -1) { - history_error(N_("Unable to create directory %s: %s\n" - "It is required for saving/loading " - "search history or cursor positions.\n"), - statedir, strerror(errno)); - return FALSE; - } - } else if (!S_ISDIR(dirstat.st_mode)) { - history_error(N_("Path %s is not a directory and needs to be.\n" - "Nano will be unable to load or save " - "search history or cursor positions.\n"), - statedir); - return FALSE; - } - poshistname = concatenate(statedir, POSITION_HISTORY); - return TRUE; + poshistname = concatenate(statedir, POSITION_HISTORY); + return TRUE; } /* Load the histories for Search and Replace and Execute Command. */ void load_history(void) { - char *histname = concatenate(statedir, SEARCH_HISTORY); - FILE *hisfile = fopen(histname, "rb"); + char *histname = concatenate(statedir, SEARCH_HISTORY); + FILE *hisfile = fopen(histname, "rb"); - if (hisfile == NULL) { - if (errno != ENOENT) { - /* When reading failed, don't save history when we quit. */ - UNSET(HISTORYLOG); - history_error(N_("Error reading %s: %s"), histname, - strerror(errno)); - } - } else { - /* Load the three history lists -- first search, then replace, - * then execute -- from oldest entry to newest. Between two - * lists there is an empty line. */ - filestruct **history = &search_history; - char *line = NULL; - size_t buf_len = 0; - ssize_t read; + if (hisfile == NULL) { + if (errno != ENOENT) { + /* When reading failed, don't save history when we quit. */ + UNSET(HISTORYLOG); + history_error(N_("Error reading %s: %s"), histname, + strerror(errno)); + } + } else { + /* Load the three history lists -- first search, then replace, + * then execute -- from oldest entry to newest. Between two + * lists there is an empty line. */ + filestruct **history = &search_history; + char *line = NULL; + size_t buf_len = 0; + ssize_t read; - while ((read = getline(&line, &buf_len, hisfile)) > 0) { - line[--read] = '\0'; - if (read > 0) { - /* Encode any embedded NUL as 0x0A. */ - unsunder(line, read); - update_history(history, line); - } else if (history == &search_history) - history = &replace_history; - else - history = &execute_history; + while ((read = getline(&line, &buf_len, hisfile)) > 0) { + line[--read] = '\0'; + if (read > 0) { + /* Encode any embedded NUL as 0x0A. */ + unsunder(line, read); + update_history(history, line); + } else if (history == &search_history) + history = &replace_history; + else + history = &execute_history; + } + + fclose(hisfile); + free(line); } - fclose(hisfile); - free(line); - } + /* After reading them in, set the status of the lists to "unchanged". */ + history_changed = FALSE; - /* After reading them in, set the status of the lists to "unchanged". */ - history_changed = FALSE; - - free(histname); + free(histname); } /* Write the lines of a history list, starting at head, from oldest to newest, * to the given file. Return TRUE if writing succeeded, and FALSE otherwise. */ bool write_list(const filestruct *head, FILE *hisfile) { - const filestruct *item; + const filestruct *item; - for (item = head; item != NULL; item = item->next) { - size_t length = strlen(item->data); + for (item = head; item != NULL; item = item->next) { + size_t length = strlen(item->data); - /* Decode 0x0A bytes as embedded NULs. */ - sunder(item->data); + /* Decode 0x0A bytes as embedded NULs. */ + sunder(item->data); - if (fwrite(item->data, sizeof(char), length, hisfile) < length) - return FALSE; - if (putc('\n', hisfile) == EOF) - return FALSE; - } + if (fwrite(item->data, sizeof(char), length, hisfile) < length) + return FALSE; + if (putc('\n', hisfile) == EOF) + return FALSE; + } - return TRUE; + return TRUE; } /* Save the histories for Search and Replace and Execute Command. */ void save_history(void) { - char *histname; - FILE *hisfile; + char *histname; + FILE *hisfile; - /* If the histories are unchanged, don't bother saving them. */ - if (!history_changed) - return; + /* If the histories are unchanged, don't bother saving them. */ + if (!history_changed) + return; - histname = concatenate(statedir, SEARCH_HISTORY); - hisfile = fopen(histname, "wb"); + histname = concatenate(statedir, SEARCH_HISTORY); + hisfile = fopen(histname, "wb"); - if (hisfile == NULL) - fprintf(stderr, _("Error writing %s: %s\n"), histname, - strerror(errno)); - else { - /* Don't allow others to read or write the history file. */ - chmod(histname, S_IRUSR | S_IWUSR); + if (hisfile == NULL) + fprintf(stderr, _("Error writing %s: %s\n"), histname, + strerror(errno)); + else { + /* Don't allow others to read or write the history file. */ + chmod(histname, S_IRUSR | S_IWUSR); - if (!write_list(searchtop, hisfile) || - !write_list(replacetop, hisfile) || - !write_list(executetop, hisfile)) - fprintf(stderr, _("Error writing %s: %s\n"), histname, - strerror(errno)); + if (!write_list(searchtop, hisfile) || + !write_list(replacetop, hisfile) || + !write_list(executetop, hisfile)) + fprintf(stderr, _("Error writing %s: %s\n"), histname, + strerror(errno)); - fclose(hisfile); - } + fclose(hisfile); + } - free(histname); + free(histname); } /* Load the recorded cursor positions for files that were edited. */ void load_poshistory(void) { - FILE *hisfile = fopen(poshistname, "rb"); + FILE *hisfile = fopen(poshistname, "rb"); - if (hisfile == NULL) { - if (errno != ENOENT) { - /* When reading failed, don't save history when we quit. */ - UNSET(POS_HISTORY); - history_error(N_("Error reading %s: %s"), poshistname, strerror(errno)); + if (hisfile == NULL) { + if (errno != ENOENT) { + /* When reading failed, don't save history when we quit. */ + UNSET(POS_HISTORY); + history_error(N_("Error reading %s: %s"), poshistname, strerror(errno)); + } + } else { + char *line = NULL, *lineptr, *xptr; + size_t buf_len = 0; + ssize_t read, count = 0; + poshiststruct *record_ptr = NULL, *newrecord; + + /* Read and parse each line, and store the extracted data. */ + while ((read = getline(&line, &buf_len, hisfile)) > 5) { + /* Decode nulls as embedded newlines. */ + unsunder(line, read); + + /* Find where the x index and line number are in the line. */ + xptr = revstrstr(line, " ", line + read - 3); + if (xptr == NULL) + continue; + lineptr = revstrstr(line, " ", xptr - 2); + if (lineptr == NULL) + continue; + + /* Now separate the three elements of the line. */ + *(xptr++) = '\0'; + *(lineptr++) = '\0'; + + /* Create a new position record. */ + newrecord = (poshiststruct *)nmalloc(sizeof(poshiststruct)); + newrecord->filename = mallocstrcpy(NULL, line); + newrecord->lineno = atoi(lineptr); + newrecord->xno = atoi(xptr); + newrecord->next = NULL; + + /* Add the record to the list. */ + if (position_history == NULL) + position_history = newrecord; + else + record_ptr->next = newrecord; + + record_ptr = newrecord; + + /* Impose a limit, so the file will not grow indefinitely. */ + if (++count > 200) { + poshiststruct *drop_record = position_history; + + position_history = position_history->next; + + free(drop_record->filename); + free(drop_record); + } + } + fclose(hisfile); + free(line); + + stat(poshistname, &stat_of_positions_file); } - } else { - char *line = NULL, *lineptr, *xptr; - size_t buf_len = 0; - ssize_t read, count = 0; - poshiststruct *record_ptr = NULL, *newrecord; - - /* Read and parse each line, and store the extracted data. */ - while ((read = getline(&line, &buf_len, hisfile)) > 5) { - /* Decode nulls as embedded newlines. */ - unsunder(line, read); - - /* Find where the x index and line number are in the line. */ - xptr = revstrstr(line, " ", line + read - 3); - if (xptr == NULL) - continue; - lineptr = revstrstr(line, " ", xptr - 2); - if (lineptr == NULL) - continue; - - /* Now separate the three elements of the line. */ - *(xptr++) = '\0'; - *(lineptr++) = '\0'; - - /* Create a new position record. */ - newrecord = (poshiststruct *)nmalloc(sizeof(poshiststruct)); - newrecord->filename = mallocstrcpy(NULL, line); - newrecord->lineno = atoi(lineptr); - newrecord->xno = atoi(xptr); - newrecord->next = NULL; - - /* Add the record to the list. */ - if (position_history == NULL) - position_history = newrecord; - else - record_ptr->next = newrecord; - - record_ptr = newrecord; - - /* Impose a limit, so the file will not grow indefinitely. */ - if (++count > 200) { - poshiststruct *drop_record = position_history; - - position_history = position_history->next; - - free(drop_record->filename); - free(drop_record); - } - } - fclose(hisfile); - free(line); - - stat(poshistname, &stat_of_positions_file); - } } /* Save the recorded cursor positions for files that were edited. */ void save_poshistory(void) { - poshiststruct *posptr; - FILE *hisfile = fopen(poshistname, "wb"); + poshiststruct *posptr; + FILE *hisfile = fopen(poshistname, "wb"); - if (hisfile == NULL) - fprintf(stderr, _("Error writing %s: %s\n"), poshistname, strerror(errno)); - else { - /* Don't allow others to read or write the history file. */ - chmod(poshistname, S_IRUSR | S_IWUSR); + if (hisfile == NULL) + fprintf(stderr, _("Error writing %s: %s\n"), poshistname, strerror(errno)); + else { + /* Don't allow others to read or write the history file. */ + chmod(poshistname, S_IRUSR | S_IWUSR); - for (posptr = position_history; posptr != NULL; posptr = posptr->next) { - char *path_and_place; - size_t length; + for (posptr = position_history; posptr != NULL; posptr = posptr->next) { + char *path_and_place; + size_t length; - /* Assume 20 decimal positions each for line and column number, - * plus two spaces, plus the line feed, plus the null byte. */ - path_and_place = charalloc(strlen(posptr->filename) + 44); - sprintf(path_and_place, "%s %zd %zd\n", - posptr->filename, posptr->lineno, posptr->xno); - length = strlen(path_and_place); + /* Assume 20 decimal positions each for line and column number, + * plus two spaces, plus the line feed, plus the null byte. */ + path_and_place = charalloc(strlen(posptr->filename) + 44); + sprintf(path_and_place, "%s %zd %zd\n", + posptr->filename, posptr->lineno, posptr->xno); + length = strlen(path_and_place); - /* Encode newlines in filenames as nulls. */ - sunder(path_and_place); - /* Restore the terminating newline. */ - path_and_place[length - 1] = '\n'; + /* Encode newlines in filenames as nulls. */ + sunder(path_and_place); + /* Restore the terminating newline. */ + path_and_place[length - 1] = '\n'; - if (fwrite(path_and_place, sizeof(char), length, hisfile) < length) - fprintf(stderr, _("Error writing %s: %s\n"), - poshistname, strerror(errno)); - free(path_and_place); + if (fwrite(path_and_place, sizeof(char), length, hisfile) < length) + fprintf(stderr, _("Error writing %s: %s\n"), + poshistname, strerror(errno)); + free(path_and_place); + } + fclose(hisfile); + + stat(poshistname, &stat_of_positions_file); } - fclose(hisfile); - - stat(poshistname, &stat_of_positions_file); - } } /* Reload the position history file if it has been modified since last load. */ void reload_positions_if_needed(void) { - struct stat newstat; + struct stat newstat; - stat(poshistname, &newstat); + stat(poshistname, &newstat); - if (newstat.st_mtime != stat_of_positions_file.st_mtime) { - poshiststruct *ptr, *nextone; + if (newstat.st_mtime != stat_of_positions_file.st_mtime) { + poshiststruct *ptr, *nextone; - for (ptr = position_history; ptr != NULL; ptr = nextone) { - nextone = ptr->next; - free(ptr->filename); - free(ptr); + for (ptr = position_history; ptr != NULL; ptr = nextone) { + nextone = ptr->next; + free(ptr->filename); + free(ptr); + } + position_history = NULL; + + load_poshistory(); } - position_history = NULL; - - load_poshistory(); - } } /* Update the recorded last file positions, given a filename, a line * and a column. If no entry is found, add a new one at the end. */ void update_poshistory(char *filename, ssize_t lineno, ssize_t xpos) { - poshiststruct *posptr, *theone, *posprev = NULL; - char *fullpath = get_full_path(filename); + poshiststruct *posptr, *theone, *posprev = NULL; + char *fullpath = get_full_path(filename); - if (fullpath == NULL || fullpath[strlen(fullpath) - 1] == '/' || inhelp) { - free(fullpath); - return; - } - - reload_positions_if_needed(); - - /* Look for a matching filename in the list. */ - for (posptr = position_history; posptr != NULL; posptr = posptr->next) { - if (!strcmp(posptr->filename, fullpath)) - break; - posprev = posptr; - } - - /* Don't record files that have the default cursor position. */ - if (lineno == 1 && xpos == 1) { - if (posptr != NULL) { - if (posprev == NULL) - position_history = posptr->next; - else - posprev->next = posptr->next; - free(posptr->filename); - free(posptr); - save_poshistory(); + if (fullpath == NULL || fullpath[strlen(fullpath) - 1] == '/' || inhelp) { + free(fullpath); + return; } + + reload_positions_if_needed(); + + /* Look for a matching filename in the list. */ + for (posptr = position_history; posptr != NULL; posptr = posptr->next) { + if (!strcmp(posptr->filename, fullpath)) + break; + posprev = posptr; + } + + /* Don't record files that have the default cursor position. */ + if (lineno == 1 && xpos == 1) { + if (posptr != NULL) { + if (posprev == NULL) + position_history = posptr->next; + else + posprev->next = posptr->next; + free(posptr->filename); + free(posptr); + save_poshistory(); + } + free(fullpath); + return; + } + + theone = posptr; + + /* If we didn't find it, make a new node; otherwise, if we're + * not at the end, move the matching one to the end. */ + if (theone == NULL) { + theone = (poshiststruct *)nmalloc(sizeof(poshiststruct)); + theone->filename = mallocstrcpy(NULL, fullpath); + if (position_history == NULL) + position_history = theone; + else + posprev->next = theone; + } else if (posptr->next != NULL) { + if (posprev == NULL) + position_history = posptr->next; + else + posprev->next = posptr->next; + while (posptr->next != NULL) + posptr = posptr->next; + posptr->next = theone; + } + + /* Store the last cursor position. */ + theone->lineno = lineno; + theone->xno = xpos; + theone->next = NULL; + free(fullpath); - return; - } - theone = posptr; - - /* If we didn't find it, make a new node; otherwise, if we're - * not at the end, move the matching one to the end. */ - if (theone == NULL) { - theone = (poshiststruct *)nmalloc(sizeof(poshiststruct)); - theone->filename = mallocstrcpy(NULL, fullpath); - if (position_history == NULL) - position_history = theone; - else - posprev->next = theone; - } else if (posptr->next != NULL) { - if (posprev == NULL) - position_history = posptr->next; - else - posprev->next = posptr->next; - while (posptr->next != NULL) - posptr = posptr->next; - posptr->next = theone; - } - - /* Store the last cursor position. */ - theone->lineno = lineno; - theone->xno = xpos; - theone->next = NULL; - - free(fullpath); - - save_poshistory(); + save_poshistory(); } /* Check whether the given file matches an existing entry in the recorded @@ -593,24 +593,24 @@ void update_poshistory(char *filename, ssize_t lineno, ssize_t xpos) * set line and column to the retrieved values. */ bool has_old_position(const char *file, ssize_t *line, ssize_t *column) { - poshiststruct *posptr = position_history; - char *fullpath = get_full_path(file); + poshiststruct *posptr = position_history; + char *fullpath = get_full_path(file); - if (fullpath == NULL) - return FALSE; + if (fullpath == NULL) + return FALSE; - reload_positions_if_needed(); + reload_positions_if_needed(); - while (posptr != NULL && strcmp(posptr->filename, fullpath) != 0) - posptr = posptr->next; + while (posptr != NULL && strcmp(posptr->filename, fullpath) != 0) + posptr = posptr->next; - free(fullpath); + free(fullpath); - if (posptr == NULL) - return FALSE; + if (posptr == NULL) + return FALSE; - *line = posptr->lineno; - *column = posptr->xno; - return TRUE; + *line = posptr->lineno; + *column = posptr->xno; + return TRUE; } #endif /* ENABLE_HISTORIES */ diff --git a/src/move.c b/src/move.c index b464e57d..179152c2 100644 --- a/src/move.c +++ b/src/move.c @@ -26,42 +26,42 @@ /* Move to the first line of the file. */ void to_first_line(void) { - openfile->current = openfile->fileage; - openfile->current_x = 0; - openfile->placewewant = 0; + openfile->current = openfile->fileage; + openfile->current_x = 0; + openfile->placewewant = 0; - refresh_needed = TRUE; + refresh_needed = TRUE; } /* Move to the last line of the file. */ void to_last_line(void) { - openfile->current = openfile->filebot; - openfile->current_x = strlen(openfile->filebot->data); - openfile->placewewant = xplustabs(); + openfile->current = openfile->filebot; + openfile->current_x = strlen(openfile->filebot->data); + openfile->placewewant = xplustabs(); - /* Set the last line of the screen as the target for the cursor. */ - openfile->current_y = editwinrows - 1; + /* Set the last line of the screen as the target for the cursor. */ + openfile->current_y = editwinrows - 1; - refresh_needed = TRUE; - focusing = FALSE; + refresh_needed = TRUE; + focusing = FALSE; } /* Determine the actual current chunk and the target column. */ void get_edge_and_target(size_t *leftedge, size_t *target_column) { #ifndef NANO_TINY - if (ISSET(SOFTWRAP)) { - size_t shim = editwincols * (1 + (tabsize / editwincols)); + if (ISSET(SOFTWRAP)) { + size_t shim = editwincols * (1 + (tabsize / editwincols)); - *leftedge = leftedge_for(xplustabs(), openfile->current); - *target_column = (openfile->placewewant + shim - *leftedge) % editwincols; - } else + *leftedge = leftedge_for(xplustabs(), openfile->current); + *target_column = (openfile->placewewant + shim - *leftedge) % editwincols; + } else #endif - { - *leftedge = 0; - *target_column = openfile->placewewant; - } + { + *leftedge = 0; + *target_column = openfile->placewewant; + } } /* Return the index in line->data that corresponds to the given column on the @@ -69,104 +69,104 @@ void get_edge_and_target(size_t *leftedge, size_t *target_column) * on a tab, prevent the cursor from falling back a row when moving forward, * or from skipping a row when moving backward, by incrementing the index. */ size_t proper_x(filestruct *line, size_t *leftedge, bool forward, - size_t column, bool *shifted) + size_t column, bool *shifted) { - size_t index = actual_x(line->data, column); + size_t index = actual_x(line->data, column); #ifndef NANO_TINY - if (ISSET(SOFTWRAP) && line->data[index] == '\t' && - ((forward && strnlenpt(line->data, index) < *leftedge) || - (!forward && column / tabsize == (*leftedge - 1) / tabsize && - column / tabsize < (*leftedge + editwincols - 1) / tabsize))) { - index++; + if (ISSET(SOFTWRAP) && line->data[index] == '\t' && + ((forward && strnlenpt(line->data, index) < *leftedge) || + (!forward && column / tabsize == (*leftedge - 1) / tabsize && + column / tabsize < (*leftedge + editwincols - 1) / tabsize))) { + index++; - if (shifted != NULL) - *shifted = TRUE; - } + if (shifted != NULL) + *shifted = TRUE; + } - if (ISSET(SOFTWRAP)) - *leftedge = leftedge_for(strnlenpt(line->data, index), line); + if (ISSET(SOFTWRAP)) + *leftedge = leftedge_for(strnlenpt(line->data, index), line); #endif - return index; + return index; } /* Adjust the values for current_x and placewewant in case we have landed in * the middle of a tab that crosses a row boundary. */ void set_proper_index_and_pww(size_t *leftedge, size_t target, bool forward) { - bool shifted = FALSE; - size_t was_edge = *leftedge; + bool shifted = FALSE; + size_t was_edge = *leftedge; - openfile->current_x = proper_x(openfile->current, leftedge, forward, - actual_last_column(*leftedge, target), &shifted); - - /* If the index was incremented, try going to the target column. */ - if (shifted || *leftedge < was_edge) openfile->current_x = proper_x(openfile->current, leftedge, forward, - actual_last_column(*leftedge, target), &shifted); + actual_last_column(*leftedge, target), &shifted); - openfile->placewewant = *leftedge + target; + /* If the index was incremented, try going to the target column. */ + if (shifted || *leftedge < was_edge) + openfile->current_x = proper_x(openfile->current, leftedge, forward, + actual_last_column(*leftedge, target), &shifted); + + openfile->placewewant = *leftedge + target; } /* Move up nearly one screenful. */ void do_page_up(void) { - int mustmove = (editwinrows < 3) ? 1 : editwinrows - 2; - size_t leftedge, target_column; + int mustmove = (editwinrows < 3) ? 1 : editwinrows - 2; + size_t leftedge, target_column; - /* If we're not in smooth scrolling mode, put the cursor at the - * beginning of the top line of the edit window, as Pico does. */ - if (!ISSET(SMOOTH_SCROLL)) { - openfile->current = openfile->edittop; - leftedge = openfile->firstcolumn; - openfile->current_y = 0; - target_column = 0; - } else - get_edge_and_target(&leftedge, &target_column); + /* If we're not in smooth scrolling mode, put the cursor at the + * beginning of the top line of the edit window, as Pico does. */ + if (!ISSET(SMOOTH_SCROLL)) { + openfile->current = openfile->edittop; + leftedge = openfile->firstcolumn; + openfile->current_y = 0; + target_column = 0; + } else + get_edge_and_target(&leftedge, &target_column); - /* Move up the required number of lines or chunks. If we can't, we're - * at the top of the file, so put the cursor there and get out. */ - if (go_back_chunks(mustmove, &openfile->current, &leftedge) > 0) { - to_first_line(); - return; - } + /* Move up the required number of lines or chunks. If we can't, we're + * at the top of the file, so put the cursor there and get out. */ + if (go_back_chunks(mustmove, &openfile->current, &leftedge) > 0) { + to_first_line(); + return; + } - set_proper_index_and_pww(&leftedge, target_column, FALSE); + set_proper_index_and_pww(&leftedge, target_column, FALSE); - /* Move the viewport so that the cursor stays immobile, if possible. */ - adjust_viewport(STATIONARY); - refresh_needed = TRUE; + /* Move the viewport so that the cursor stays immobile, if possible. */ + adjust_viewport(STATIONARY); + refresh_needed = TRUE; } /* Move down nearly one screenful. */ void do_page_down(void) { - int mustmove = (editwinrows < 3) ? 1 : editwinrows - 2; - size_t leftedge, target_column; + int mustmove = (editwinrows < 3) ? 1 : editwinrows - 2; + size_t leftedge, target_column; - /* If we're not in smooth scrolling mode, put the cursor at the - * beginning of the top line of the edit window, as Pico does. */ - if (!ISSET(SMOOTH_SCROLL)) { - openfile->current = openfile->edittop; - leftedge = openfile->firstcolumn; - openfile->current_y = 0; - target_column = 0; - } else - get_edge_and_target(&leftedge, &target_column); + /* If we're not in smooth scrolling mode, put the cursor at the + * beginning of the top line of the edit window, as Pico does. */ + if (!ISSET(SMOOTH_SCROLL)) { + openfile->current = openfile->edittop; + leftedge = openfile->firstcolumn; + openfile->current_y = 0; + target_column = 0; + } else + get_edge_and_target(&leftedge, &target_column); - /* Move down the required number of lines or chunks. If we can't, we're - * at the bottom of the file, so put the cursor there and get out. */ - if (go_forward_chunks(mustmove, &openfile->current, &leftedge) > 0) { - to_last_line(); - return; - } + /* Move down the required number of lines or chunks. If we can't, we're + * at the bottom of the file, so put the cursor there and get out. */ + if (go_forward_chunks(mustmove, &openfile->current, &leftedge) > 0) { + to_last_line(); + return; + } - set_proper_index_and_pww(&leftedge, target_column, TRUE); + set_proper_index_and_pww(&leftedge, target_column, TRUE); - /* Move the viewport so that the cursor stays immobile, if possible. */ - adjust_viewport(STATIONARY); - refresh_needed = TRUE; + /* Move the viewport so that the cursor stays immobile, if possible. */ + adjust_viewport(STATIONARY); + refresh_needed = TRUE; } #ifdef ENABLE_JUSTIFY @@ -174,18 +174,18 @@ void do_page_down(void) * current line. If update_screen is TRUE, update the screen afterwards. */ void do_para_begin(bool update_screen) { - filestruct *was_current = openfile->current; + filestruct *was_current = openfile->current; - if (openfile->current != openfile->fileage) - openfile->current = openfile->current->prev; + if (openfile->current != openfile->fileage) + openfile->current = openfile->current->prev; - while (!begpar(openfile->current)) - openfile->current = openfile->current->prev; + while (!begpar(openfile->current)) + openfile->current = openfile->current->prev; - openfile->current_x = 0; + openfile->current_x = 0; - if (update_screen) - edit_redraw(was_current, CENTERING); + if (update_screen) + edit_redraw(was_current, CENTERING); } /* Move down to the beginning of the last line of the current paragraph. @@ -196,122 +196,122 @@ void do_para_begin(bool update_screen) * paragraph or isn't in a paragraph. */ void do_para_end(bool update_screen) { - filestruct *was_current = openfile->current; + filestruct *was_current = openfile->current; - while (openfile->current != openfile->filebot && - !inpar(openfile->current)) - openfile->current = openfile->current->next; + while (openfile->current != openfile->filebot && + !inpar(openfile->current)) + openfile->current = openfile->current->next; - while (openfile->current != openfile->filebot && - inpar(openfile->current->next) && - !begpar(openfile->current->next)) { - openfile->current = openfile->current->next; - } + while (openfile->current != openfile->filebot && + inpar(openfile->current->next) && + !begpar(openfile->current->next)) { + openfile->current = openfile->current->next; + } - if (openfile->current != openfile->filebot) { - openfile->current = openfile->current->next; - openfile->current_x = 0; - } else - openfile->current_x = strlen(openfile->current->data); + if (openfile->current != openfile->filebot) { + openfile->current = openfile->current->next; + openfile->current_x = 0; + } else + openfile->current_x = strlen(openfile->current->data); - if (update_screen) - edit_redraw(was_current, CENTERING); + if (update_screen) + edit_redraw(was_current, CENTERING); } /* Move up to first start of a paragraph before the current line. */ void do_para_begin_void(void) { - do_para_begin(TRUE); + do_para_begin(TRUE); } /* Move down to just after the first end of a paragraph. */ void do_para_end_void(void) { - do_para_end(TRUE); + do_para_end(TRUE); } #endif /* ENABLE_JUSTIFY */ /* Move to the preceding block of text. */ void do_prev_block(void) { - filestruct *was_current = openfile->current; - bool is_text = FALSE, seen_text = FALSE; + filestruct *was_current = openfile->current; + bool is_text = FALSE, seen_text = FALSE; - /* Skip backward until first blank line after some nonblank line(s). */ - while (openfile->current->prev != NULL && (!seen_text || is_text)) { - openfile->current = openfile->current->prev; - is_text = !white_string(openfile->current->data); - seen_text = seen_text || is_text; - } + /* Skip backward until first blank line after some nonblank line(s). */ + while (openfile->current->prev != NULL && (!seen_text || is_text)) { + openfile->current = openfile->current->prev; + is_text = !white_string(openfile->current->data); + seen_text = seen_text || is_text; + } - /* Step forward one line again if this one is blank. */ - if (openfile->current->next != NULL && - white_string(openfile->current->data)) - openfile->current = openfile->current->next; + /* Step forward one line again if this one is blank. */ + if (openfile->current->next != NULL && + white_string(openfile->current->data)) + openfile->current = openfile->current->next; - openfile->current_x = 0; - edit_redraw(was_current, CENTERING); + openfile->current_x = 0; + edit_redraw(was_current, CENTERING); } /* Move to the next block of text. */ void do_next_block(void) { - filestruct *was_current = openfile->current; - bool is_white = white_string(openfile->current->data); - bool seen_white = is_white; + filestruct *was_current = openfile->current; + bool is_white = white_string(openfile->current->data); + bool seen_white = is_white; - /* Skip forward until first nonblank line after some blank line(s). */ - while (openfile->current->next != NULL && (!seen_white || is_white)) { - openfile->current = openfile->current->next; - is_white = white_string(openfile->current->data); - seen_white = seen_white || is_white; - } + /* Skip forward until first nonblank line after some blank line(s). */ + while (openfile->current->next != NULL && (!seen_white || is_white)) { + openfile->current = openfile->current->next; + is_white = white_string(openfile->current->data); + seen_white = seen_white || is_white; + } - openfile->current_x = 0; - edit_redraw(was_current, CENTERING); + openfile->current_x = 0; + edit_redraw(was_current, CENTERING); } /* Move to the previous word. If allow_punct is TRUE, treat punctuation * as part of a word. When requested, update the screen afterwards. */ void do_prev_word(bool allow_punct, bool update_screen) { - filestruct *was_current = openfile->current; - bool seen_a_word = FALSE, step_forward = FALSE; + filestruct *was_current = openfile->current; + bool seen_a_word = FALSE, step_forward = FALSE; - /* Move backward until we pass over the start of a word. */ - while (TRUE) { - /* If at the head of a line, move to the end of the preceding one. */ - if (openfile->current_x == 0) { - if (openfile->current->prev == NULL) - break; - openfile->current = openfile->current->prev; - openfile->current_x = strlen(openfile->current->data); + /* Move backward until we pass over the start of a word. */ + while (TRUE) { + /* If at the head of a line, move to the end of the preceding one. */ + if (openfile->current_x == 0) { + if (openfile->current->prev == NULL) + break; + openfile->current = openfile->current->prev; + openfile->current_x = strlen(openfile->current->data); + } + + /* Step back one character. */ + openfile->current_x = move_mbleft(openfile->current->data, + openfile->current_x); + + if (is_word_mbchar(openfile->current->data + openfile->current_x, + allow_punct)) { + seen_a_word = TRUE; + /* If at the head of a line now, this surely is a word start. */ + if (openfile->current_x == 0) + break; + } else if (seen_a_word) { + /* This is space now: we've overshot the start of the word. */ + step_forward = TRUE; + break; + } } - /* Step back one character. */ - openfile->current_x = move_mbleft(openfile->current->data, - openfile->current_x); + if (step_forward) + /* Move one character forward again to sit on the start of the word. */ + openfile->current_x = move_mbright(openfile->current->data, + openfile->current_x); - if (is_word_mbchar(openfile->current->data + openfile->current_x, - allow_punct)) { - seen_a_word = TRUE; - /* If at the head of a line now, this surely is a word start. */ - if (openfile->current_x == 0) - break; - } else if (seen_a_word) { - /* This is space now: we've overshot the start of the word. */ - step_forward = TRUE; - break; - } - } - - if (step_forward) - /* Move one character forward again to sit on the start of the word. */ - openfile->current_x = move_mbright(openfile->current->data, - openfile->current_x); - - if (update_screen) - edit_redraw(was_current, FLOWING); + if (update_screen) + edit_redraw(was_current, FLOWING); } /* Move to the next word. If allow_punct is TRUE, treat punctuation @@ -319,55 +319,55 @@ void do_prev_word(bool allow_punct, bool update_screen) * Return TRUE if we started on a word, and FALSE otherwise. */ bool do_next_word(bool allow_punct, bool update_screen) { - filestruct *was_current = openfile->current; - bool started_on_word = is_word_mbchar(openfile->current->data + - openfile->current_x, allow_punct); - bool seen_space = !started_on_word; + filestruct *was_current = openfile->current; + bool started_on_word = is_word_mbchar(openfile->current->data + + openfile->current_x, allow_punct); + bool seen_space = !started_on_word; - /* Move forward until we reach the start of a word. */ - while (TRUE) { - /* If at the end of a line, move to the beginning of the next one. */ - if (openfile->current->data[openfile->current_x] == '\0') { - /* When at end of file, stop. */ - if (openfile->current->next == NULL) - break; - openfile->current = openfile->current->next; - openfile->current_x = 0; - seen_space = TRUE; - } else { - /* Step forward one character. */ - openfile->current_x = move_mbright(openfile->current->data, - openfile->current_x); + /* Move forward until we reach the start of a word. */ + while (TRUE) { + /* If at the end of a line, move to the beginning of the next one. */ + if (openfile->current->data[openfile->current_x] == '\0') { + /* When at end of file, stop. */ + if (openfile->current->next == NULL) + break; + openfile->current = openfile->current->next; + openfile->current_x = 0; + seen_space = TRUE; + } else { + /* Step forward one character. */ + openfile->current_x = move_mbright(openfile->current->data, + openfile->current_x); + } + + /* If this is not a word character, then it's a separator; else + * if we've already seen a separator, then it's a word start. */ + if (!is_word_mbchar(openfile->current->data + openfile->current_x, + allow_punct)) + seen_space = TRUE; + else if (seen_space) + break; } - /* If this is not a word character, then it's a separator; else - * if we've already seen a separator, then it's a word start. */ - if (!is_word_mbchar(openfile->current->data + openfile->current_x, - allow_punct)) - seen_space = TRUE; - else if (seen_space) - break; - } + if (update_screen) + edit_redraw(was_current, FLOWING); - if (update_screen) - edit_redraw(was_current, FLOWING); - - /* Return whether we started on a word. */ - return started_on_word; + /* Return whether we started on a word. */ + return started_on_word; } /* Move to the previous word in the file, treating punctuation as part of a * word if the WORD_BOUNDS flag is set, and update the screen afterwards. */ void do_prev_word_void(void) { - do_prev_word(ISSET(WORD_BOUNDS), TRUE); + do_prev_word(ISSET(WORD_BOUNDS), TRUE); } /* Move to the next word in the file, treating punctuation as part of a word * if the WORD_BOUNDS flag is set, and update the screen afterwards. */ void do_next_word_void(void) { - do_next_word(ISSET(WORD_BOUNDS), TRUE); + do_next_word(ISSET(WORD_BOUNDS), TRUE); } /* Move to the beginning of the current line (or softwrapped chunk). @@ -375,59 +375,59 @@ void do_next_word_void(void) * of the full line when already at the start of a chunk. */ void do_home(void) { - filestruct *was_current = openfile->current; - size_t was_column = xplustabs(); - bool moved_off_chunk = TRUE; + filestruct *was_current = openfile->current; + size_t was_column = xplustabs(); + bool moved_off_chunk = TRUE; #ifndef NANO_TINY - bool moved = FALSE; - size_t leftedge = 0, leftedge_x = 0; + bool moved = FALSE; + size_t leftedge = 0, leftedge_x = 0; - if (ISSET(SOFTWRAP)) { - leftedge = leftedge_for(was_column, openfile->current); - leftedge_x = proper_x(openfile->current, &leftedge, FALSE, leftedge, - NULL); - } - - if (ISSET(SMART_HOME)) { - size_t indent_x = indent_length(openfile->current->data); - - if (openfile->current->data[indent_x] != '\0') { - /* If we're exactly on the indent, move fully home. Otherwise, - * when not softwrapping or not after the first nonblank chunk, - * move to the first nonblank character. */ - if (openfile->current_x == indent_x) { - openfile->current_x = 0; - moved = TRUE; - } else if (!ISSET(SOFTWRAP) || leftedge_x <= indent_x) { - openfile->current_x = indent_x; - moved = TRUE; - } + if (ISSET(SOFTWRAP)) { + leftedge = leftedge_for(was_column, openfile->current); + leftedge_x = proper_x(openfile->current, &leftedge, FALSE, leftedge, + NULL); } - } - if (!moved && ISSET(SOFTWRAP)) { - /* If already at the left edge of the screen, move fully home. - * Otherwise, move to the left edge. */ - if (openfile->current_x == leftedge_x) - openfile->current_x = 0; - else { - openfile->current_x = leftedge_x; - openfile->placewewant = leftedge; - moved_off_chunk = FALSE; + if (ISSET(SMART_HOME)) { + size_t indent_x = indent_length(openfile->current->data); + + if (openfile->current->data[indent_x] != '\0') { + /* If we're exactly on the indent, move fully home. Otherwise, + * when not softwrapping or not after the first nonblank chunk, + * move to the first nonblank character. */ + if (openfile->current_x == indent_x) { + openfile->current_x = 0; + moved = TRUE; + } else if (!ISSET(SOFTWRAP) || leftedge_x <= indent_x) { + openfile->current_x = indent_x; + moved = TRUE; + } + } } - } else if (!moved) + + if (!moved && ISSET(SOFTWRAP)) { + /* If already at the left edge of the screen, move fully home. + * Otherwise, move to the left edge. */ + if (openfile->current_x == leftedge_x) + openfile->current_x = 0; + else { + openfile->current_x = leftedge_x; + openfile->placewewant = leftedge; + moved_off_chunk = FALSE; + } + } else if (!moved) #endif - openfile->current_x = 0; + openfile->current_x = 0; - if (moved_off_chunk) - openfile->placewewant = xplustabs(); + if (moved_off_chunk) + openfile->placewewant = xplustabs(); - /* If we changed chunk, we might be offscreen. Otherwise, - * update current if the mark is on or we changed "page". */ - if (ISSET(SOFTWRAP) && moved_off_chunk) - edit_redraw(was_current, FLOWING); - else if (line_needs_update(was_column, openfile->placewewant)) - update_line(openfile->current, openfile->current_x); + /* If we changed chunk, we might be offscreen. Otherwise, + * update current if the mark is on or we changed "page". */ + if (ISSET(SOFTWRAP) && moved_off_chunk) + edit_redraw(was_current, FLOWING); + else if (line_needs_update(was_column, openfile->placewewant)) + update_line(openfile->current, openfile->current_x); } /* Move to the end of the current line (or softwrapped chunk). @@ -435,159 +435,159 @@ void do_home(void) * end of the full line. */ void do_end(void) { - filestruct *was_current = openfile->current; - size_t was_column = xplustabs(); - size_t line_len = strlen(openfile->current->data); - bool moved_off_chunk = TRUE; + filestruct *was_current = openfile->current; + size_t was_column = xplustabs(); + size_t line_len = strlen(openfile->current->data); + bool moved_off_chunk = TRUE; #ifndef NANO_TINY - if (ISSET(SOFTWRAP)) { - bool last_chunk = FALSE; - size_t leftedge = leftedge_for(was_column, openfile->current); - size_t rightedge = get_softwrap_breakpoint(openfile->current->data, - leftedge, &last_chunk); - size_t rightedge_x; + if (ISSET(SOFTWRAP)) { + bool last_chunk = FALSE; + size_t leftedge = leftedge_for(was_column, openfile->current); + size_t rightedge = get_softwrap_breakpoint(openfile->current->data, + leftedge, &last_chunk); + size_t rightedge_x; - /* If we're on the last chunk, we're already at the end of the line. - * Otherwise, we're one column past the end of the line. Shifting - * backwards one column might put us in the middle of a multi-column - * character, but actual_x() will fix that. */ - if (!last_chunk) - rightedge--; + /* If we're on the last chunk, we're already at the end of the line. + * Otherwise, we're one column past the end of the line. Shifting + * backwards one column might put us in the middle of a multi-column + * character, but actual_x() will fix that. */ + if (!last_chunk) + rightedge--; - rightedge_x = actual_x(openfile->current->data, rightedge); + rightedge_x = actual_x(openfile->current->data, rightedge); - /* If already at the right edge of the screen, move fully to - * the end of the line. Otherwise, move to the right edge. */ - if (openfile->current_x == rightedge_x) - openfile->current_x = line_len; - else { - openfile->current_x = rightedge_x; - openfile->placewewant = rightedge; - moved_off_chunk = FALSE; - } - } else + /* If already at the right edge of the screen, move fully to + * the end of the line. Otherwise, move to the right edge. */ + if (openfile->current_x == rightedge_x) + openfile->current_x = line_len; + else { + openfile->current_x = rightedge_x; + openfile->placewewant = rightedge; + moved_off_chunk = FALSE; + } + } else #endif - openfile->current_x = line_len; + openfile->current_x = line_len; - if (moved_off_chunk) - openfile->placewewant = xplustabs(); + if (moved_off_chunk) + openfile->placewewant = xplustabs(); - /* If we changed chunk, we might be offscreen. Otherwise, - * update current if the mark is on or we changed "page". */ - if (ISSET(SOFTWRAP) && moved_off_chunk) - edit_redraw(was_current, FLOWING); - else if (line_needs_update(was_column, openfile->placewewant)) - update_line(openfile->current, openfile->current_x); + /* If we changed chunk, we might be offscreen. Otherwise, + * update current if the mark is on or we changed "page". */ + if (ISSET(SOFTWRAP) && moved_off_chunk) + edit_redraw(was_current, FLOWING); + else if (line_needs_update(was_column, openfile->placewewant)) + update_line(openfile->current, openfile->current_x); } /* Move the cursor to the preceding line or chunk. If scroll_only is TRUE, * also scroll the screen one row, so the cursor stays in the same spot. */ void do_up(bool scroll_only) { - filestruct *was_current = openfile->current; - size_t leftedge, target_column; + filestruct *was_current = openfile->current; + size_t leftedge, target_column; - /* When just scrolling and the top of the file is onscreen, get out. */ - if (scroll_only && openfile->edittop == openfile->fileage && - openfile->firstcolumn == 0) - return; + /* When just scrolling and the top of the file is onscreen, get out. */ + if (scroll_only && openfile->edittop == openfile->fileage && + openfile->firstcolumn == 0) + return; - get_edge_and_target(&leftedge, &target_column); + get_edge_and_target(&leftedge, &target_column); - /* If we can't move up one line or chunk, we're at top of file. */ - if (go_back_chunks(1, &openfile->current, &leftedge) > 0) - return; + /* If we can't move up one line or chunk, we're at top of file. */ + if (go_back_chunks(1, &openfile->current, &leftedge) > 0) + return; - set_proper_index_and_pww(&leftedge, target_column, FALSE); + set_proper_index_and_pww(&leftedge, target_column, FALSE); - if (scroll_only) - edit_scroll(BACKWARD, 1); + if (scroll_only) + edit_scroll(BACKWARD, 1); - edit_redraw(was_current, FLOWING); + edit_redraw(was_current, FLOWING); - /* should not change placewewant, so restore it. */ - openfile->placewewant = leftedge + target_column; + /* should not change placewewant, so restore it. */ + openfile->placewewant = leftedge + target_column; } /* Move the cursor to next line or chunk. If scroll_only is TRUE, also * scroll the screen one row, so the cursor stays in the same spot. */ void do_down(bool scroll_only) { - filestruct *was_current = openfile->current; - size_t leftedge, target_column; + filestruct *was_current = openfile->current; + size_t leftedge, target_column; - get_edge_and_target(&leftedge, &target_column); + get_edge_and_target(&leftedge, &target_column); - /* If we can't move down one line or chunk, we're at bottom of file. */ - if (go_forward_chunks(1, &openfile->current, &leftedge) > 0) - return; + /* If we can't move down one line or chunk, we're at bottom of file. */ + if (go_forward_chunks(1, &openfile->current, &leftedge) > 0) + return; - set_proper_index_and_pww(&leftedge, target_column, TRUE); + set_proper_index_and_pww(&leftedge, target_column, TRUE); - if (scroll_only) - edit_scroll(FORWARD, 1); + if (scroll_only) + edit_scroll(FORWARD, 1); - edit_redraw(was_current, FLOWING); + edit_redraw(was_current, FLOWING); - /* should not change placewewant, so restore it. */ - openfile->placewewant = leftedge + target_column; + /* should not change placewewant, so restore it. */ + openfile->placewewant = leftedge + target_column; } /* Move up one line or chunk. */ void do_up_void(void) { - do_up(FALSE); + do_up(FALSE); } /* Move down one line or chunk. */ void do_down_void(void) { - do_down(FALSE); + do_down(FALSE); } #ifndef NANO_TINY /* Scroll up one line or chunk without scrolling the cursor. */ void do_scroll_up(void) { - do_up(TRUE); + do_up(TRUE); } /* Scroll down one line or chunk without scrolling the cursor. */ void do_scroll_down(void) { - do_down(TRUE); + do_down(TRUE); } #endif /* Move left one character. */ void do_left(void) { - filestruct *was_current = openfile->current; + filestruct *was_current = openfile->current; - if (openfile->current_x > 0) - openfile->current_x = move_mbleft(openfile->current->data, - openfile->current_x); - else if (openfile->current != openfile->fileage) { - openfile->current = openfile->current->prev; - openfile->current_x = strlen(openfile->current->data); - } + if (openfile->current_x > 0) + openfile->current_x = move_mbleft(openfile->current->data, + openfile->current_x); + else if (openfile->current != openfile->fileage) { + openfile->current = openfile->current->prev; + openfile->current_x = strlen(openfile->current->data); + } - edit_redraw(was_current, FLOWING); + edit_redraw(was_current, FLOWING); } /* Move right one character. */ void do_right(void) { - filestruct *was_current = openfile->current; + filestruct *was_current = openfile->current; - if (openfile->current->data[openfile->current_x] != '\0') - openfile->current_x = move_mbright(openfile->current->data, - openfile->current_x); - else if (openfile->current != openfile->filebot) { - openfile->current = openfile->current->next; - openfile->current_x = 0; - } + if (openfile->current->data[openfile->current_x] != '\0') + openfile->current_x = move_mbright(openfile->current->data, + openfile->current_x); + else if (openfile->current != openfile->filebot) { + openfile->current = openfile->current->next; + openfile->current_x = 0; + } - edit_redraw(was_current, FLOWING); + edit_redraw(was_current, FLOWING); } diff --git a/src/nano.c b/src/nano.c index d23b7bad..bf3ca128 100644 --- a/src/nano.c +++ b/src/nano.c @@ -41,241 +41,241 @@ #ifdef ENABLE_MOUSE static int oldinterval = -1; - /* Used to store the user's original mouse click interval. */ + /* Used to store the user's original mouse click interval. */ #endif #ifdef ENABLE_NANORC static bool no_rcfiles = FALSE; - /* Should we ignore all rcfiles? */ + /* Should we ignore all rcfiles? */ #endif #ifdef HAVE_TERMIOS_H static struct termios oldterm; - /* The user's original terminal settings. */ + /* The user's original terminal settings. */ #else # define tcsetattr(...) # define tcgetattr(...) #endif static struct sigaction act; - /* Used to set up all our fun signal handlers. */ + /* Used to set up all our fun signal handlers. */ static bool input_was_aborted = FALSE; - /* Whether reading from standard input was aborted via ^C. */ + /* Whether reading from standard input was aborted via ^C. */ /* Create a new linestruct node. Note that we do not set prevnode->next * to the new line. */ filestruct *make_new_node(filestruct *prevnode) { - filestruct *newnode = nmalloc(sizeof(filestruct)); + filestruct *newnode = nmalloc(sizeof(filestruct)); - newnode->data = NULL; - newnode->prev = prevnode; - newnode->next = NULL; - newnode->lineno = (prevnode != NULL) ? prevnode->lineno + 1 : 1; + newnode->data = NULL; + newnode->prev = prevnode; + newnode->next = NULL; + newnode->lineno = (prevnode != NULL) ? prevnode->lineno + 1 : 1; #ifdef ENABLE_COLOR - newnode->multidata = NULL; + newnode->multidata = NULL; #endif - return newnode; + return newnode; } /* Make a copy of a linestruct node. */ filestruct *copy_node(const filestruct *src) { - filestruct *dst = nmalloc(sizeof(filestruct)); + filestruct *dst = nmalloc(sizeof(filestruct)); - dst->data = mallocstrcpy(NULL, src->data); - dst->next = src->next; - dst->prev = src->prev; - dst->lineno = src->lineno; + dst->data = mallocstrcpy(NULL, src->data); + dst->next = src->next; + dst->prev = src->prev; + dst->lineno = src->lineno; #ifdef ENABLE_COLOR - dst->multidata = NULL; + dst->multidata = NULL; #endif - return dst; + return dst; } /* Splice a new node into an existing linked list of linestructs. */ void splice_node(filestruct *afterthis, filestruct *newnode) { - newnode->next = afterthis->next; - newnode->prev = afterthis; - if (afterthis->next != NULL) - afterthis->next->prev = newnode; - afterthis->next = newnode; + newnode->next = afterthis->next; + newnode->prev = afterthis; + if (afterthis->next != NULL) + afterthis->next->prev = newnode; + afterthis->next = newnode; - /* Update filebot when inserting a node at the end of file. */ - if (openfile && openfile->filebot == afterthis) - openfile->filebot = newnode; + /* Update filebot when inserting a node at the end of file. */ + if (openfile && openfile->filebot == afterthis) + openfile->filebot = newnode; } /* Disconnect a node from a linked list of linestructs and delete it. */ void unlink_node(filestruct *fileptr) { - if (fileptr->prev != NULL) - fileptr->prev->next = fileptr->next; - if (fileptr->next != NULL) - fileptr->next->prev = fileptr->prev; + if (fileptr->prev != NULL) + fileptr->prev->next = fileptr->next; + if (fileptr->next != NULL) + fileptr->next->prev = fileptr->prev; - /* Update filebot when removing a node at the end of file. */ - if (openfile && openfile->filebot == fileptr) - openfile->filebot = fileptr->prev; + /* Update filebot when removing a node at the end of file. */ + if (openfile && openfile->filebot == fileptr) + openfile->filebot = fileptr->prev; - delete_node(fileptr); + delete_node(fileptr); } /* Free the data structures in the given node. */ void delete_node(filestruct *fileptr) { - free(fileptr->data); + free(fileptr->data); #ifdef ENABLE_COLOR - free(fileptr->multidata); + free(fileptr->multidata); #endif - free(fileptr); + free(fileptr); } /* Duplicate an entire linked list of linestructs. */ filestruct *copy_filestruct(const filestruct *src) { - filestruct *head, *copy; - - copy = copy_node(src); - copy->prev = NULL; - head = copy; - src = src->next; - - while (src != NULL) { - copy->next = copy_node(src); - copy->next->prev = copy; - copy = copy->next; + filestruct *head, *copy; + copy = copy_node(src); + copy->prev = NULL; + head = copy; src = src->next; - } - copy->next = NULL; + while (src != NULL) { + copy->next = copy_node(src); + copy->next->prev = copy; + copy = copy->next; - return head; + src = src->next; + } + + copy->next = NULL; + + return head; } /* Free an entire linked list of linestructs. */ void free_filestruct(filestruct *src) { - if (src == NULL) - return; + if (src == NULL) + return; - while (src->next != NULL) { - src = src->next; - delete_node(src->prev); - } + while (src->next != NULL) { + src = src->next; + delete_node(src->prev); + } - delete_node(src); + delete_node(src); } /* Renumber the lines in a buffer, starting with fileptr. */ void renumber(filestruct *fileptr) { - ssize_t line; + ssize_t line; - if (fileptr == NULL) - return; + if (fileptr == NULL) + return; - line = (fileptr->prev == NULL) ? 0 : fileptr->prev->lineno; + line = (fileptr->prev == NULL) ? 0 : fileptr->prev->lineno; - assert(fileptr != fileptr->next); + assert(fileptr != fileptr->next); - for (; fileptr != NULL; fileptr = fileptr->next) - fileptr->lineno = ++line; + for (; fileptr != NULL; fileptr = fileptr->next) + fileptr->lineno = ++line; } /* Partition the current buffer so that it appears to begin at (top, top_x) * and appears to end at (bot, bot_x). */ partition *partition_filestruct(filestruct *top, size_t top_x, - filestruct *bot, size_t bot_x) + filestruct *bot, size_t bot_x) { - partition *p; + partition *p; - assert(top != NULL && bot != NULL && openfile->fileage != NULL && openfile->filebot != NULL); + assert(top != NULL && bot != NULL && openfile->fileage != NULL && openfile->filebot != NULL); - /* Initialize the partition. */ - p = (partition *)nmalloc(sizeof(partition)); + /* Initialize the partition. */ + p = (partition *)nmalloc(sizeof(partition)); - /* If the top and bottom of the partition are different from the top - * and bottom of the buffer, save the latter and then set them - * to top and bot. */ - if (top != openfile->fileage) { - p->fileage = openfile->fileage; - openfile->fileage = top; - } else - p->fileage = NULL; - if (bot != openfile->filebot) { - p->filebot = openfile->filebot; - openfile->filebot = bot; - } else - p->filebot = NULL; + /* If the top and bottom of the partition are different from the top + * and bottom of the buffer, save the latter and then set them + * to top and bot. */ + if (top != openfile->fileage) { + p->fileage = openfile->fileage; + openfile->fileage = top; + } else + p->fileage = NULL; + if (bot != openfile->filebot) { + p->filebot = openfile->filebot; + openfile->filebot = bot; + } else + p->filebot = NULL; - /* Remember which line is above the top of the partition, detach the - * top of the partition from it, and save the text before top_x. */ - p->top_prev = top->prev; - top->prev = NULL; - p->top_data = mallocstrncpy(NULL, top->data, top_x + 1); - p->top_data[top_x] = '\0'; + /* Remember which line is above the top of the partition, detach the + * top of the partition from it, and save the text before top_x. */ + p->top_prev = top->prev; + top->prev = NULL; + p->top_data = mallocstrncpy(NULL, top->data, top_x + 1); + p->top_data[top_x] = '\0'; - /* Remember which line is below the bottom of the partition, detach the - * bottom of the partition from it, and save the text after bot_x. */ - p->bot_next = bot->next; - bot->next = NULL; - p->bot_data = mallocstrcpy(NULL, bot->data + bot_x); + /* Remember which line is below the bottom of the partition, detach the + * bottom of the partition from it, and save the text after bot_x. */ + p->bot_next = bot->next; + bot->next = NULL; + p->bot_data = mallocstrcpy(NULL, bot->data + bot_x); - /* Remove all text after bot_x at the bottom of the partition. */ - bot->data[bot_x] = '\0'; + /* Remove all text after bot_x at the bottom of the partition. */ + bot->data[bot_x] = '\0'; - /* Remove all text before top_x at the top of the partition. */ - charmove(top->data, top->data + top_x, strlen(top->data) - top_x + 1); + /* Remove all text before top_x at the top of the partition. */ + charmove(top->data, top->data + top_x, strlen(top->data) - top_x + 1); - /* Return the partition. */ - return p; + /* Return the partition. */ + return p; } /* Unpartition the current buffer so that it stretches from (fileage, 0) * to (filebot, $) again. */ void unpartition_filestruct(partition **p) { - assert(p != NULL && openfile->fileage != NULL && openfile->filebot != NULL); + assert(p != NULL && openfile->fileage != NULL && openfile->filebot != NULL); - /* Reattach the line above the top of the partition, and restore the - * text before top_x from top_data. Free top_data when we're done - * with it. */ - openfile->fileage->prev = (*p)->top_prev; - if (openfile->fileage->prev != NULL) - openfile->fileage->prev->next = openfile->fileage; - openfile->fileage->data = charealloc(openfile->fileage->data, - strlen((*p)->top_data) + strlen(openfile->fileage->data) + 1); - charmove(openfile->fileage->data + strlen((*p)->top_data), - openfile->fileage->data, strlen(openfile->fileage->data) + 1); - strncpy(openfile->fileage->data, (*p)->top_data, strlen((*p)->top_data)); - free((*p)->top_data); + /* Reattach the line above the top of the partition, and restore the + * text before top_x from top_data. Free top_data when we're done + * with it. */ + openfile->fileage->prev = (*p)->top_prev; + if (openfile->fileage->prev != NULL) + openfile->fileage->prev->next = openfile->fileage; + openfile->fileage->data = charealloc(openfile->fileage->data, + strlen((*p)->top_data) + strlen(openfile->fileage->data) + 1); + charmove(openfile->fileage->data + strlen((*p)->top_data), + openfile->fileage->data, strlen(openfile->fileage->data) + 1); + strncpy(openfile->fileage->data, (*p)->top_data, strlen((*p)->top_data)); + free((*p)->top_data); - /* Reattach the line below the bottom of the partition, and restore - * the text after bot_x from bot_data. Free bot_data when we're - * done with it. */ - openfile->filebot->next = (*p)->bot_next; - if (openfile->filebot->next != NULL) - openfile->filebot->next->prev = openfile->filebot; - openfile->filebot->data = charealloc(openfile->filebot->data, - strlen(openfile->filebot->data) + strlen((*p)->bot_data) + 1); - strcat(openfile->filebot->data, (*p)->bot_data); - free((*p)->bot_data); + /* Reattach the line below the bottom of the partition, and restore + * the text after bot_x from bot_data. Free bot_data when we're + * done with it. */ + openfile->filebot->next = (*p)->bot_next; + if (openfile->filebot->next != NULL) + openfile->filebot->next->prev = openfile->filebot; + openfile->filebot->data = charealloc(openfile->filebot->data, + strlen(openfile->filebot->data) + strlen((*p)->bot_data) + 1); + strcat(openfile->filebot->data, (*p)->bot_data); + free((*p)->bot_data); - /* Restore the top and bottom of the buffer, if they were - * different from the top and bottom of the partition. */ - if ((*p)->fileage != NULL) - openfile->fileage = (*p)->fileage; - if ((*p)->filebot != NULL) - openfile->filebot = (*p)->filebot; + /* Restore the top and bottom of the buffer, if they were + * different from the top and bottom of the partition. */ + if ((*p)->fileage != NULL) + openfile->fileage = (*p)->fileage; + if ((*p)->filebot != NULL) + openfile->filebot = (*p)->filebot; - /* Uninitialize the partition. */ - free(*p); - *p = NULL; + /* Uninitialize the partition. */ + free(*p); + *p = NULL; } /* Move all the text between (top, top_x) and (bot, bot_x) in the @@ -283,472 +283,472 @@ void unpartition_filestruct(partition **p) * with file_bot. If no text is between (top, top_x) and (bot, bot_x), * don't do anything. */ void extract_buffer(filestruct **file_top, filestruct **file_bot, - filestruct *top, size_t top_x, filestruct *bot, size_t bot_x) + filestruct *top, size_t top_x, filestruct *bot, size_t bot_x) { - filestruct *top_save; - bool edittop_inside; + filestruct *top_save; + bool edittop_inside; #ifndef NANO_TINY - bool mark_inside = FALSE; - bool same_line = FALSE; + bool mark_inside = FALSE; + bool same_line = FALSE; #endif - assert(file_top != NULL && file_bot != NULL && top != NULL && bot != NULL); + assert(file_top != NULL && file_bot != NULL && top != NULL && bot != NULL); - /* If (top, top_x)-(bot, bot_x) doesn't cover any text, get out. */ - if (top == bot && top_x == bot_x) - return; + /* If (top, top_x)-(bot, bot_x) doesn't cover any text, get out. */ + if (top == bot && top_x == bot_x) + return; - /* Partition the buffer so that it contains only the text from - * (top, top_x) to (bot, bot_x), keep track of whether the top of - * the edit window is inside the partition, and keep track of - * whether the mark begins inside the partition. */ - filepart = partition_filestruct(top, top_x, bot, bot_x); - edittop_inside = (openfile->edittop->lineno >= openfile->fileage->lineno && - openfile->edittop->lineno <= openfile->filebot->lineno); + /* Partition the buffer so that it contains only the text from + * (top, top_x) to (bot, bot_x), keep track of whether the top of + * the edit window is inside the partition, and keep track of + * whether the mark begins inside the partition. */ + filepart = partition_filestruct(top, top_x, bot, bot_x); + edittop_inside = (openfile->edittop->lineno >= openfile->fileage->lineno && + openfile->edittop->lineno <= openfile->filebot->lineno); #ifndef NANO_TINY - if (openfile->mark) { - mark_inside = (openfile->mark->lineno >= openfile->fileage->lineno && - openfile->mark->lineno <= openfile->filebot->lineno && - (openfile->mark != openfile->fileage || - openfile->mark_x >= top_x) && - (openfile->mark != openfile->filebot || - openfile->mark_x <= bot_x)); - same_line = (openfile->mark == openfile->fileage); - } + if (openfile->mark) { + mark_inside = (openfile->mark->lineno >= openfile->fileage->lineno && + openfile->mark->lineno <= openfile->filebot->lineno && + (openfile->mark != openfile->fileage || + openfile->mark_x >= top_x) && + (openfile->mark != openfile->filebot || + openfile->mark_x <= bot_x)); + same_line = (openfile->mark == openfile->fileage); + } #endif - /* Subtract the number of characters in the text from the file size. */ - openfile->totsize -= get_totsize(top, bot); + /* Subtract the number of characters in the text from the file size. */ + openfile->totsize -= get_totsize(top, bot); - if (*file_top == NULL) { - /* If file_top is empty, just move all the text directly into - * it. This is equivalent to tacking the text in top onto the - * (lack of) text at the end of file_top. */ - *file_top = openfile->fileage; - *file_bot = openfile->filebot; + if (*file_top == NULL) { + /* If file_top is empty, just move all the text directly into + * it. This is equivalent to tacking the text in top onto the + * (lack of) text at the end of file_top. */ + *file_top = openfile->fileage; + *file_bot = openfile->filebot; - /* Renumber, starting with file_top. */ - renumber(*file_top); - } else { - filestruct *file_bot_save = *file_bot; + /* Renumber, starting with file_top. */ + renumber(*file_top); + } else { + filestruct *file_bot_save = *file_bot; - /* Otherwise, tack the text in top onto the text at the end of - * file_bot. */ - (*file_bot)->data = charealloc((*file_bot)->data, - strlen((*file_bot)->data) + - strlen(openfile->fileage->data) + 1); - strcat((*file_bot)->data, openfile->fileage->data); + /* Otherwise, tack the text in top onto the text at the end of + * file_bot. */ + (*file_bot)->data = charealloc((*file_bot)->data, + strlen((*file_bot)->data) + + strlen(openfile->fileage->data) + 1); + strcat((*file_bot)->data, openfile->fileage->data); - /* Attach the line after top to the line after file_bot. Then, - * if there's more than one line after top, move file_bot down - * to bot. */ - (*file_bot)->next = openfile->fileage->next; - if ((*file_bot)->next != NULL) { - (*file_bot)->next->prev = *file_bot; - *file_bot = openfile->filebot; + /* Attach the line after top to the line after file_bot. Then, + * if there's more than one line after top, move file_bot down + * to bot. */ + (*file_bot)->next = openfile->fileage->next; + if ((*file_bot)->next != NULL) { + (*file_bot)->next->prev = *file_bot; + *file_bot = openfile->filebot; + } + + delete_node(openfile->fileage); + + /* Renumber, starting with the line after the original file_bot. */ + renumber(file_bot_save->next); } - delete_node(openfile->fileage); + /* Since the text has now been saved, remove it from the buffer. */ + openfile->fileage = make_new_node(NULL); + openfile->fileage->data = mallocstrcpy(NULL, ""); + openfile->filebot = openfile->fileage; - /* Renumber, starting with the line after the original file_bot. */ - renumber(file_bot_save->next); - } - - /* Since the text has now been saved, remove it from the buffer. */ - openfile->fileage = make_new_node(NULL); - openfile->fileage->data = mallocstrcpy(NULL, ""); - openfile->filebot = openfile->fileage; - - /* Restore the current line and cursor position. If the mark begins - * inside the partition, set the beginning of the mark to where the - * saved text used to start. */ - openfile->current = openfile->fileage; - openfile->current_x = top_x; + /* Restore the current line and cursor position. If the mark begins + * inside the partition, set the beginning of the mark to where the + * saved text used to start. */ + openfile->current = openfile->fileage; + openfile->current_x = top_x; #ifndef NANO_TINY - if (mark_inside) { - openfile->mark = openfile->current; - openfile->mark_x = openfile->current_x; - } else if (same_line) - /* Update the pointer to this partially cut line. */ - openfile->mark = openfile->current; + if (mark_inside) { + openfile->mark = openfile->current; + openfile->mark_x = openfile->current_x; + } else if (same_line) + /* Update the pointer to this partially cut line. */ + openfile->mark = openfile->current; #endif - top_save = openfile->fileage; + top_save = openfile->fileage; - /* Unpartition the buffer so that it contains all the text - * again, minus the saved text. */ - unpartition_filestruct(&filepart); + /* Unpartition the buffer so that it contains all the text + * again, minus the saved text. */ + unpartition_filestruct(&filepart); - /* If the top of the edit window was inside the old partition, put - * it in range of current. */ - if (edittop_inside) { - adjust_viewport(STATIONARY); - refresh_needed = TRUE; - } + /* If the top of the edit window was inside the old partition, put + * it in range of current. */ + if (edittop_inside) { + adjust_viewport(STATIONARY); + refresh_needed = TRUE; + } - /* Renumber, starting with the beginning line of the old partition. */ - renumber(top_save); + /* Renumber, starting with the beginning line of the old partition. */ + renumber(top_save); - /* If the text doesn't end with a magicline, and it should, add one. */ - if (!ISSET(NO_NEWLINES) && openfile->filebot->data[0] != '\0') - new_magicline(); + /* If the text doesn't end with a magicline, and it should, add one. */ + if (!ISSET(NO_NEWLINES) && openfile->filebot->data[0] != '\0') + new_magicline(); } /* Meld the given buffer into the current file buffer * at the current cursor position. */ void ingraft_buffer(filestruct *somebuffer) { - filestruct *top_save; - size_t current_x_save = openfile->current_x; - bool edittop_inside; + filestruct *top_save; + size_t current_x_save = openfile->current_x; + bool edittop_inside; #ifndef NANO_TINY - bool right_side_up = FALSE, single_line = FALSE; + bool right_side_up = FALSE, single_line = FALSE; #endif - assert(somebuffer != NULL); + assert(somebuffer != NULL); #ifndef NANO_TINY - /* Keep track of whether the mark begins inside the partition and - * will need adjustment. */ - if (openfile->mark) { - filestruct *top, *bot; - size_t top_x, bot_x; + /* Keep track of whether the mark begins inside the partition and + * will need adjustment. */ + if (openfile->mark) { + filestruct *top, *bot; + size_t top_x, bot_x; - mark_order((const filestruct **)&top, &top_x, - (const filestruct **)&bot, &bot_x, &right_side_up); + mark_order((const filestruct **)&top, &top_x, + (const filestruct **)&bot, &bot_x, &right_side_up); - single_line = (top == bot); - } -#endif - - /* Partition the buffer so that it contains no text, and remember - * whether the current line is at the top of the edit window. */ - filepart = partition_filestruct(openfile->current, openfile->current_x, - openfile->current, openfile->current_x); - edittop_inside = (openfile->edittop == openfile->fileage); - free_filestruct(openfile->fileage); - - /* Put the top and bottom of the current buffer at the top and - * bottom of the passed buffer. */ - openfile->fileage = somebuffer; - openfile->filebot = openfile->fileage; - while (openfile->filebot->next != NULL) - openfile->filebot = openfile->filebot->next; - - /* Put the cursor at the end of the pasted text. */ - openfile->current = openfile->filebot; - openfile->current_x = strlen(openfile->filebot->data); - - /* Refresh the mark's pointer, and compensate the mark's - * x coordinate for the change in the current line. */ - if (openfile->fileage == openfile->filebot) { -#ifndef NANO_TINY - if (openfile->mark && single_line) { - openfile->mark = openfile->current; - if (!right_side_up) - openfile->mark_x += openfile->current_x; + single_line = (top == bot); } #endif - /* When the pasted stuff contains no newline, adjust the cursor's - * x coordinate for the text that is before the pasted stuff. */ - openfile->current_x += current_x_save; - } + + /* Partition the buffer so that it contains no text, and remember + * whether the current line is at the top of the edit window. */ + filepart = partition_filestruct(openfile->current, openfile->current_x, + openfile->current, openfile->current_x); + edittop_inside = (openfile->edittop == openfile->fileage); + free_filestruct(openfile->fileage); + + /* Put the top and bottom of the current buffer at the top and + * bottom of the passed buffer. */ + openfile->fileage = somebuffer; + openfile->filebot = openfile->fileage; + while (openfile->filebot->next != NULL) + openfile->filebot = openfile->filebot->next; + + /* Put the cursor at the end of the pasted text. */ + openfile->current = openfile->filebot; + openfile->current_x = strlen(openfile->filebot->data); + + /* Refresh the mark's pointer, and compensate the mark's + * x coordinate for the change in the current line. */ + if (openfile->fileage == openfile->filebot) { #ifndef NANO_TINY - else if (openfile->mark && single_line) { - if (right_side_up) - openfile->mark = openfile->fileage; - else { - openfile->mark = openfile->current; - openfile->mark_x += openfile->current_x - current_x_save; + if (openfile->mark && single_line) { + openfile->mark = openfile->current; + if (!right_side_up) + openfile->mark_x += openfile->current_x; + } +#endif + /* When the pasted stuff contains no newline, adjust the cursor's + * x coordinate for the text that is before the pasted stuff. */ + openfile->current_x += current_x_save; + } +#ifndef NANO_TINY + else if (openfile->mark && single_line) { + if (right_side_up) + openfile->mark = openfile->fileage; + else { + openfile->mark = openfile->current; + openfile->mark_x += openfile->current_x - current_x_save; + } } - } #endif - /* Add the number of characters in the copied text to the file size. */ - openfile->totsize += get_totsize(openfile->fileage, openfile->filebot); + /* Add the number of characters in the copied text to the file size. */ + openfile->totsize += get_totsize(openfile->fileage, openfile->filebot); - /* If we pasted onto the first line of the edit window, the corresponding - * struct has been freed, so... point at the start of the copied text. */ - if (edittop_inside) - openfile->edittop = openfile->fileage; + /* If we pasted onto the first line of the edit window, the corresponding + * struct has been freed, so... point at the start of the copied text. */ + if (edittop_inside) + openfile->edittop = openfile->fileage; - top_save = openfile->fileage; + top_save = openfile->fileage; - /* Unpartition the buffer so that it contains all the text - * again, plus the copied text. */ - unpartition_filestruct(&filepart); + /* Unpartition the buffer so that it contains all the text + * again, plus the copied text. */ + unpartition_filestruct(&filepart); - /* Renumber, starting with the beginning line of the old partition. */ - renumber(top_save); + /* Renumber, starting with the beginning line of the old partition. */ + renumber(top_save); - /* If the text doesn't end with a magicline, and it should, add one. */ - if (!ISSET(NO_NEWLINES) && openfile->filebot->data[0] != '\0') - new_magicline(); + /* If the text doesn't end with a magicline, and it should, add one. */ + if (!ISSET(NO_NEWLINES) && openfile->filebot->data[0] != '\0') + new_magicline(); } /* Meld a copy of the given buffer into the current file buffer. */ void copy_from_buffer(filestruct *somebuffer) { - filestruct *the_copy = copy_filestruct(somebuffer); + filestruct *the_copy = copy_filestruct(somebuffer); - ingraft_buffer(the_copy); + ingraft_buffer(the_copy); } /* Create a new openfile node. */ openfilestruct *make_new_opennode(void) { - return (openfilestruct *)nmalloc(sizeof(openfilestruct)); + return (openfilestruct *)nmalloc(sizeof(openfilestruct)); } /* Unlink a node from the rest of the circular list, and delete it. */ void unlink_opennode(openfilestruct *fileptr) { - assert(fileptr != fileptr->prev && fileptr != fileptr->next); + assert(fileptr != fileptr->prev && fileptr != fileptr->next); - if (fileptr == firstfile) - firstfile = firstfile->next; + if (fileptr == firstfile) + firstfile = firstfile->next; - fileptr->prev->next = fileptr->next; - fileptr->next->prev = fileptr->prev; + fileptr->prev->next = fileptr->next; + fileptr->next->prev = fileptr->prev; - delete_opennode(fileptr); + delete_opennode(fileptr); } /* Free all the memory in the given open-file node. */ void delete_opennode(openfilestruct *fileptr) { - free(fileptr->filename); - free_filestruct(fileptr->fileage); + free(fileptr->filename); + free_filestruct(fileptr->fileage); #ifndef NANO_TINY - free(fileptr->current_stat); - free(fileptr->lock_filename); - /* Free the undo stack. */ - discard_until(NULL, fileptr, TRUE); + free(fileptr->current_stat); + free(fileptr->lock_filename); + /* Free the undo stack. */ + discard_until(NULL, fileptr, TRUE); #endif - free(fileptr); + free(fileptr); } /* Display a warning about a key disabled in view mode. */ void print_view_warning(void) { - statusbar(_("Key is invalid in view mode")); + statusbar(_("Key is invalid in view mode")); } /* Indicate that something is disabled in restricted mode. */ void show_restricted_warning(void) { - statusbar(_("This function is disabled in restricted mode")); - beep(); + statusbar(_("This function is disabled in restricted mode")); + beep(); } #ifndef ENABLE_HELP /* Indicate that help texts are unavailable. */ void say_there_is_no_help(void) { - statusbar(_("Help is not available")); + statusbar(_("Help is not available")); } #endif /* Make nano exit gracefully. */ void finish(void) { - /* Blank the statusbar and (if applicable) the shortcut list, - * and move the cursor to the last line of the screen. */ - blank_statusbar(); - blank_bottombars(); - wrefresh(bottomwin); - curs_set(1); - endwin(); + /* Blank the statusbar and (if applicable) the shortcut list, + * and move the cursor to the last line of the screen. */ + blank_statusbar(); + blank_bottombars(); + wrefresh(bottomwin); + curs_set(1); + endwin(); - /* Restore the old terminal settings. */ - tcsetattr(0, TCSANOW, &oldterm); + /* Restore the old terminal settings. */ + tcsetattr(0, TCSANOW, &oldterm); #ifdef ENABLE_HISTORIES - /* If the user wants history persistence, write the relevant files. */ - if (ISSET(HISTORYLOG)) - save_history(); - if (ISSET(POS_HISTORY)) { - update_poshistory(openfile->filename, openfile->current->lineno, xplustabs() + 1); - } + /* If the user wants history persistence, write the relevant files. */ + if (ISSET(HISTORYLOG)) + save_history(); + if (ISSET(POS_HISTORY)) { + update_poshistory(openfile->filename, openfile->current->lineno, xplustabs() + 1); + } #endif #ifdef DEBUG - thanks_for_all_the_fish(); + thanks_for_all_the_fish(); #endif - /* Get out. */ - exit(0); + /* Get out. */ + exit(0); } /* Make nano die gracefully. */ void die(const char *msg, ...) { - va_list ap; + va_list ap; - curs_set(1); - endwin(); + curs_set(1); + endwin(); - /* Restore the old terminal settings. */ - tcsetattr(0, TCSANOW, &oldterm); + /* Restore the old terminal settings. */ + tcsetattr(0, TCSANOW, &oldterm); - va_start(ap, msg); - vfprintf(stderr, msg, ap); - va_end(ap); + va_start(ap, msg); + vfprintf(stderr, msg, ap); + va_end(ap); #ifndef NANO_TINY - /* If the current buffer has a lockfile, remove it. */ - if (openfile && ISSET(LOCKING) && openfile->lock_filename) - delete_lockfile(openfile->lock_filename); -#endif - - /* If the current file buffer was modified, save it. */ - if (openfile && openfile->modified) { - /* If the buffer is partitioned, unpartition it first. */ - if (filepart != NULL) - unpartition_filestruct(&filepart); - - die_save_file(openfile->filename, openfile->current_stat); - } - -#ifdef ENABLE_MULTIBUFFER - /* Save all of the other modified file buffers, if any. */ - if (openfile != NULL) { - openfilestruct *firstone = openfile; - - while (openfile->next != firstone) { - openfile = openfile->next; - -#ifndef NANO_TINY - if (ISSET(LOCKING) && openfile->lock_filename) + /* If the current buffer has a lockfile, remove it. */ + if (openfile && ISSET(LOCKING) && openfile->lock_filename) delete_lockfile(openfile->lock_filename); #endif - if (openfile->modified) + + /* If the current file buffer was modified, save it. */ + if (openfile && openfile->modified) { + /* If the buffer is partitioned, unpartition it first. */ + if (filepart != NULL) + unpartition_filestruct(&filepart); + die_save_file(openfile->filename, openfile->current_stat); } - } + +#ifdef ENABLE_MULTIBUFFER + /* Save all of the other modified file buffers, if any. */ + if (openfile != NULL) { + openfilestruct *firstone = openfile; + + while (openfile->next != firstone) { + openfile = openfile->next; + +#ifndef NANO_TINY + if (ISSET(LOCKING) && openfile->lock_filename) + delete_lockfile(openfile->lock_filename); +#endif + if (openfile->modified) + die_save_file(openfile->filename, openfile->current_stat); + } + } #endif - /* Abandon the building. */ - exit(1); + /* Abandon the building. */ + exit(1); } /* Save the current file under the name specified in die_filename, which * is modified to be unique if necessary. */ void die_save_file(const char *die_filename, struct stat *die_stat) { - char *targetname; - bool failed = TRUE; + char *targetname; + bool failed = TRUE; - /* If we're using restricted mode, don't write any emergency backup - * files, since that would allow reading from or writing to files - * not specified on the command line. */ - if (ISSET(RESTRICTED)) - return; + /* If we're using restricted mode, don't write any emergency backup + * files, since that would allow reading from or writing to files + * not specified on the command line. */ + if (ISSET(RESTRICTED)) + return; - /* If we can't save, we have really bad problems, but we might as - * well try. */ - if (*die_filename == '\0') - die_filename = "nano"; + /* If we can't save, we have really bad problems, but we might as + * well try. */ + if (*die_filename == '\0') + die_filename = "nano"; - targetname = get_next_filename(die_filename, ".save"); + targetname = get_next_filename(die_filename, ".save"); - if (*targetname != '\0') - failed = !write_file(targetname, NULL, TRUE, OVERWRITE, FALSE); + if (*targetname != '\0') + failed = !write_file(targetname, NULL, TRUE, OVERWRITE, FALSE); - if (!failed) - fprintf(stderr, _("\nBuffer written to %s\n"), targetname); - else if (*targetname != '\0') - fprintf(stderr, _("\nBuffer not written to %s: %s\n"), targetname, - strerror(errno)); - else - fprintf(stderr, _("\nBuffer not written: %s\n"), - _("Too many backup files?")); + if (!failed) + fprintf(stderr, _("\nBuffer written to %s\n"), targetname); + else if (*targetname != '\0') + fprintf(stderr, _("\nBuffer not written to %s: %s\n"), targetname, + strerror(errno)); + else + fprintf(stderr, _("\nBuffer not written: %s\n"), + _("Too many backup files?")); #ifndef NANO_TINY - /* Try and chmod/chown the save file to the values of the original file, - * but don't worry if it fails because we're supposed to be bailing as - * fast as possible. */ - if (die_stat) { - IGNORE_CALL_RESULT(chmod(targetname, die_stat->st_mode)); - IGNORE_CALL_RESULT(chown(targetname, die_stat->st_uid, - die_stat->st_gid)); - } + /* Try and chmod/chown the save file to the values of the original file, + * but don't worry if it fails because we're supposed to be bailing as + * fast as possible. */ + if (die_stat) { + IGNORE_CALL_RESULT(chmod(targetname, die_stat->st_mode)); + IGNORE_CALL_RESULT(chown(targetname, die_stat->st_uid, + die_stat->st_gid)); + } #endif - free(targetname); + free(targetname); } /* Initialize the three window portions nano uses. */ void window_init(void) { - /* When resizing, first delete the existing windows. */ - if (edit != NULL) { - if (topwin != NULL) - delwin(topwin); - delwin(edit); - delwin(bottomwin); - } + /* When resizing, first delete the existing windows. */ + if (edit != NULL) { + if (topwin != NULL) + delwin(topwin); + delwin(edit); + delwin(bottomwin); + } - /* If the terminal is very flat, don't set up a titlebar. */ - if (LINES < 3) { - topwin = NULL; - editwinrows = 1; - /* Set up two subwindows. If the terminal is just one line, - * edit window and statusbar window will cover each other. */ - edit = newwin(1, COLS, 0, 0); - bottomwin = newwin(1, COLS, LINES - 1, 0); - } else { - int toprows = (ISSET(MORE_SPACE) ? 1 : (LINES < 6) ? 1 : 2); - int bottomrows = (ISSET(NO_HELP) ? 1 : (LINES < 5) ? 1 : 3); + /* If the terminal is very flat, don't set up a titlebar. */ + if (LINES < 3) { + topwin = NULL; + editwinrows = 1; + /* Set up two subwindows. If the terminal is just one line, + * edit window and statusbar window will cover each other. */ + edit = newwin(1, COLS, 0, 0); + bottomwin = newwin(1, COLS, LINES - 1, 0); + } else { + int toprows = (ISSET(MORE_SPACE) ? 1 : (LINES < 6) ? 1 : 2); + int bottomrows = (ISSET(NO_HELP) ? 1 : (LINES < 5) ? 1 : 3); - editwinrows = LINES - toprows - bottomrows; + editwinrows = LINES - toprows - bottomrows; - /* Set up the normal three subwindows. */ - topwin = newwin(toprows, COLS, 0, 0); - edit = newwin(editwinrows, COLS, toprows, 0); - bottomwin = newwin(bottomrows, COLS, toprows + editwinrows, 0); - } + /* Set up the normal three subwindows. */ + topwin = newwin(toprows, COLS, 0, 0); + edit = newwin(editwinrows, COLS, toprows, 0); + bottomwin = newwin(bottomrows, COLS, toprows + editwinrows, 0); + } - /* In case the terminal shrunk, make sure the status line is clear. */ - wipe_statusbar(); + /* In case the terminal shrunk, make sure the status line is clear. */ + wipe_statusbar(); - /* Turn the keypad on for the windows, if necessary. */ - if (!ISSET(REBIND_KEYPAD)) { - keypad(topwin, TRUE); - keypad(edit, TRUE); - keypad(bottomwin, TRUE); - } + /* Turn the keypad on for the windows, if necessary. */ + if (!ISSET(REBIND_KEYPAD)) { + keypad(topwin, TRUE); + keypad(edit, TRUE); + keypad(bottomwin, TRUE); + } #ifdef ENABLED_WRAPORJUSTIFY - /* Set up the wrapping point, accounting for screen width when negative. */ - fill = wrap_at; - if (fill <= 0) - fill += COLS; - if (fill < 0) - fill = 0; + /* Set up the wrapping point, accounting for screen width when negative. */ + fill = wrap_at; + if (fill <= 0) + fill += COLS; + if (fill < 0) + fill = 0; #endif } #ifdef ENABLE_MOUSE void disable_mouse_support(void) { - mousemask(0, NULL); - mouseinterval(oldinterval); + mousemask(0, NULL); + mouseinterval(oldinterval); } void enable_mouse_support(void) { - mousemask(ALL_MOUSE_EVENTS, NULL); - oldinterval = mouseinterval(50); + mousemask(ALL_MOUSE_EVENTS, NULL); + oldinterval = mouseinterval(50); } /* Switch mouse support on or off, as needed. */ void mouse_init(void) { - if (ISSET(USE_MOUSE)) - enable_mouse_support(); - else - disable_mouse_support(); + if (ISSET(USE_MOUSE)) + enable_mouse_support(); + else + disable_mouse_support(); } #endif /* ENABLE_MOUSE */ @@ -757,149 +757,149 @@ void mouse_init(void) * translatable (i.e. the flag names). */ void print_opt(const char *shortflag, const char *longflag, const char *desc) { - printf(" %s\t", shortflag); - if (strlenpt(shortflag) < 8) - printf("\t"); + printf(" %s\t", shortflag); + if (strlenpt(shortflag) < 8) + printf("\t"); - printf("%s\t", longflag); - if (strlenpt(longflag) < 8) - printf("\t\t"); - else if (strlenpt(longflag) < 16) - printf("\t"); + printf("%s\t", longflag); + if (strlenpt(longflag) < 8) + printf("\t\t"); + else if (strlenpt(longflag) < 16) + printf("\t"); - if (desc != NULL) - printf("%s", _(desc)); - printf("\n"); + if (desc != NULL) + printf("%s", _(desc)); + printf("\n"); } /* Explain how to properly use nano and its command-line options. */ void usage(void) { - printf(_("Usage: nano [OPTIONS] [[+LINE[,COLUMN]] FILE]...\n\n")); - /* TRANSLATORS: The next two strings are part of the --help output. - * It's best to keep its lines within 80 characters. */ - printf(_("To place the cursor on a specific line of a file, put the line number with\n" - "a '+' before the filename. The column number can be added after a comma.\n")); - printf(_("When a filename is '-', nano reads data from standard input.\n\n")); - printf(_("Option\t\tGNU long option\t\tMeaning\n")); + printf(_("Usage: nano [OPTIONS] [[+LINE[,COLUMN]] FILE]...\n\n")); + /* TRANSLATORS: The next two strings are part of the --help output. + * It's best to keep its lines within 80 characters. */ + printf(_("To place the cursor on a specific line of a file, put the line number with\n" + "a '+' before the filename. The column number can be added after a comma.\n")); + printf(_("When a filename is '-', nano reads data from standard input.\n\n")); + printf(_("Option\t\tGNU long option\t\tMeaning\n")); #ifndef NANO_TINY - print_opt("-A", "--smarthome", - /* TRANSLATORS: The next forty or so strings are option descriptions - * for the --help output. Try to keep them at most 40 characters. */ - N_("Enable smart home key")); - if (!ISSET(RESTRICTED)) { - print_opt("-B", "--backup", N_("Save backups of existing files")); - print_opt(_("-C "), _("--backupdir="), - N_("Directory for saving unique backup files")); - } + print_opt("-A", "--smarthome", + /* TRANSLATORS: The next forty or so strings are option descriptions + * for the --help output. Try to keep them at most 40 characters. */ + N_("Enable smart home key")); + if (!ISSET(RESTRICTED)) { + print_opt("-B", "--backup", N_("Save backups of existing files")); + print_opt(_("-C "), _("--backupdir="), + N_("Directory for saving unique backup files")); + } #endif - print_opt("-D", "--boldtext", N_("Use bold instead of reverse video text")); + print_opt("-D", "--boldtext", N_("Use bold instead of reverse video text")); #ifndef NANO_TINY - print_opt("-E", "--tabstospaces", N_("Convert typed tabs to spaces")); + print_opt("-E", "--tabstospaces", N_("Convert typed tabs to spaces")); #endif #ifdef ENABLE_MULTIBUFFER - if (!ISSET(RESTRICTED)) - print_opt("-F", "--multibuffer", - N_("Read a file into a new buffer by default")); + if (!ISSET(RESTRICTED)) + print_opt("-F", "--multibuffer", + N_("Read a file into a new buffer by default")); #endif #ifndef NANO_TINY - print_opt("-G", "--locking", N_("Use (vim-style) lock files")); + print_opt("-G", "--locking", N_("Use (vim-style) lock files")); #endif #ifdef ENABLE_HISTORIES - if (!ISSET(RESTRICTED)) - print_opt("-H", "--historylog", - N_("Log & read search/replace string history")); + if (!ISSET(RESTRICTED)) + print_opt("-H", "--historylog", + N_("Log & read search/replace string history")); #endif #ifdef ENABLE_NANORC - if (!ISSET(RESTRICTED)) - print_opt("-I", "--ignorercfiles", N_("Don't look at nanorc files")); + if (!ISSET(RESTRICTED)) + print_opt("-I", "--ignorercfiles", N_("Don't look at nanorc files")); #endif - print_opt("-K", "--rebindkeypad", - N_("Fix numeric keypad key confusion problem")); - print_opt("-L", "--nonewlines", - N_("Don't add newlines to the ends of files")); + print_opt("-K", "--rebindkeypad", + N_("Fix numeric keypad key confusion problem")); + print_opt("-L", "--nonewlines", + N_("Don't add newlines to the ends of files")); #ifndef NANO_TINY - print_opt("-N", "--noconvert", - N_("Don't convert files from DOS/Mac format")); + print_opt("-N", "--noconvert", + N_("Don't convert files from DOS/Mac format")); #endif - print_opt("-O", "--morespace", N_("Use one more line for editing")); + print_opt("-O", "--morespace", N_("Use one more line for editing")); #ifdef ENABLE_HISTORIES - if (!ISSET(RESTRICTED)) - print_opt("-P", "--positionlog", - N_("Log & read location of cursor position")); + if (!ISSET(RESTRICTED)) + print_opt("-P", "--positionlog", + N_("Log & read location of cursor position")); #endif #ifdef ENABLE_JUSTIFY - print_opt(_("-Q "), _("--quotestr="), N_("Quoting string")); + print_opt(_("-Q "), _("--quotestr="), N_("Quoting string")); #endif - if (!ISSET(RESTRICTED)) - print_opt("-R", "--restricted", N_("Restricted mode")); + if (!ISSET(RESTRICTED)) + print_opt("-R", "--restricted", N_("Restricted mode")); #ifndef NANO_TINY - print_opt("-S", "--smooth", N_("Scroll by line instead of half-screen")); + print_opt("-S", "--smooth", N_("Scroll by line instead of half-screen")); #endif - print_opt(_("-T <#cols>"), _("--tabsize=<#cols>"), - N_("Set width of a tab to #cols columns")); - print_opt("-U", "--quickblank", N_("Do quick statusbar blanking")); - print_opt("-V", "--version", N_("Print version information and exit")); + print_opt(_("-T <#cols>"), _("--tabsize=<#cols>"), + N_("Set width of a tab to #cols columns")); + print_opt("-U", "--quickblank", N_("Do quick statusbar blanking")); + print_opt("-V", "--version", N_("Print version information and exit")); #ifndef NANO_TINY - print_opt("-W", "--wordbounds", - N_("Detect word boundaries more accurately")); - print_opt(_("-X "), _("--wordchars="), - N_("Which other characters are word parts")); + print_opt("-W", "--wordbounds", + N_("Detect word boundaries more accurately")); + print_opt(_("-X "), _("--wordchars="), + N_("Which other characters are word parts")); #endif #ifdef ENABLE_COLOR - if (!ISSET(RESTRICTED)) - print_opt(_("-Y "), _("--syntax="), - N_("Syntax definition to use for coloring")); + if (!ISSET(RESTRICTED)) + print_opt(_("-Y "), _("--syntax="), + N_("Syntax definition to use for coloring")); #endif #ifndef NANO_TINY - print_opt("-a", "--atblanks", N_("When soft-wrapping, do it at whitespace")); + print_opt("-a", "--atblanks", N_("When soft-wrapping, do it at whitespace")); #endif - print_opt("-c", "--constantshow", N_("Constantly show cursor position")); - print_opt("-d", "--rebinddelete", - N_("Fix Backspace/Delete confusion problem")); + print_opt("-c", "--constantshow", N_("Constantly show cursor position")); + print_opt("-d", "--rebinddelete", + N_("Fix Backspace/Delete confusion problem")); #ifdef ENABLE_BROWSER - if (!ISSET(RESTRICTED)) - print_opt("-g", "--showcursor", N_("Show cursor in file browser")); + if (!ISSET(RESTRICTED)) + print_opt("-g", "--showcursor", N_("Show cursor in file browser")); #endif - print_opt("-h", "--help", N_("Show this help text and exit")); + print_opt("-h", "--help", N_("Show this help text and exit")); #ifndef NANO_TINY - print_opt("-i", "--autoindent", N_("Automatically indent new lines")); - print_opt("-k", "--cutfromcursor", N_("Cut from cursor to end of line")); + print_opt("-i", "--autoindent", N_("Automatically indent new lines")); + print_opt("-k", "--cutfromcursor", N_("Cut from cursor to end of line")); #endif #ifdef ENABLE_LINENUMBERS - print_opt("-l", "--linenumbers", N_("Show line numbers in front of the text")); + print_opt("-l", "--linenumbers", N_("Show line numbers in front of the text")); #endif #ifdef ENABLE_MOUSE - print_opt("-m", "--mouse", N_("Enable the use of the 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)")); + print_opt("-n", "--noread", N_("Do not read the file (only write it)")); #ifdef ENABLE_OPERATINGDIR - print_opt(_("-o "), _("--operatingdir="), - N_("Set operating directory")); + print_opt(_("-o "), _("--operatingdir="), + N_("Set operating directory")); #endif - print_opt("-p", "--preserve", N_("Preserve XON (^Q) and XOFF (^S) keys")); + print_opt("-p", "--preserve", N_("Preserve XON (^Q) and XOFF (^S) keys")); #ifdef ENABLED_WRAPORJUSTIFY - print_opt(_("-r <#cols>"), _("--fill=<#cols>"), - N_("Set hard-wrapping point at column #cols")); + print_opt(_("-r <#cols>"), _("--fill=<#cols>"), + N_("Set hard-wrapping point at column #cols")); #endif #ifdef ENABLE_SPELLER - if (!ISSET(RESTRICTED)) - print_opt(_("-s "), _("--speller="), - N_("Enable alternate speller")); + if (!ISSET(RESTRICTED)) + print_opt(_("-s "), _("--speller="), + N_("Enable alternate speller")); #endif - print_opt("-t", "--tempfile", N_("Auto save on exit, don't prompt")); + print_opt("-t", "--tempfile", N_("Auto save on exit, don't prompt")); #ifndef NANO_TINY - print_opt("-u", "--unix", N_("Save a file by default in Unix format")); + print_opt("-u", "--unix", N_("Save a file by default in Unix format")); #endif - print_opt("-v", "--view", N_("View mode (read-only)")); + print_opt("-v", "--view", N_("View mode (read-only)")); #ifdef ENABLE_WRAPPING - print_opt("-w", "--nowrap", N_("Don't hard-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")); - if (!ISSET(RESTRICTED)) - print_opt("-z", "--suspend", N_("Enable suspension")); + print_opt("-x", "--nohelp", N_("Don't show the two help lines")); + if (!ISSET(RESTRICTED)) + print_opt("-z", "--suspend", N_("Enable suspension")); #ifndef NANO_TINY - print_opt("-$", "--softwrap", N_("Enable soft line wrapping")); + print_opt("-$", "--softwrap", N_("Enable soft line wrapping")); #endif } @@ -909,134 +909,134 @@ void usage(void) void version(void) { #ifdef REVISION - printf(" GNU nano from git, %s\n", REVISION); + printf(" GNU nano from git, %s\n", REVISION); #else - printf(_(" GNU nano, version %s\n"), VERSION); + printf(_(" GNU nano, version %s\n"), VERSION); #endif - printf(" (C) 1999-2011, 2013-2017 Free Software Foundation, Inc.\n"); - printf(_(" (C) 2014-%s the contributors to nano\n"), "2017"); - printf(_(" Email: nano@nano-editor.org Web: https://nano-editor.org/")); - printf(_("\n Compiled options:")); + printf(" (C) 1999-2011, 2013-2017 Free Software Foundation, Inc.\n"); + printf(_(" (C) 2014-%s the contributors to nano\n"), "2017"); + printf(_(" Email: nano@nano-editor.org Web: https://nano-editor.org/")); + printf(_("\n Compiled options:")); #ifdef NANO_TINY - printf(" --enable-tiny"); + printf(" --enable-tiny"); #ifdef ENABLE_BROWSER - printf(" --enable-browser"); + printf(" --enable-browser"); #endif #ifdef ENABLE_COLOR - printf(" --enable-color"); + printf(" --enable-color"); #endif #ifdef ENABLE_EXTRA - printf(" --enable-extra"); + printf(" --enable-extra"); #endif #ifdef ENABLE_HELP - printf(" --enable-help"); + printf(" --enable-help"); #endif #ifdef ENABLE_HISTORIES - printf(" --enable-histories"); + printf(" --enable-histories"); #endif #ifdef ENABLE_JUSTIFY - printf(" --enable-justify"); + printf(" --enable-justify"); #endif #ifdef HAVE_LIBMAGIC - printf(" --enable-libmagic"); + printf(" --enable-libmagic"); #endif #ifdef ENABLE_LINENUMBERS - printf(" --enable-linenumbers"); + printf(" --enable-linenumbers"); #endif #ifdef ENABLE_MOUSE - printf(" --enable-mouse"); + printf(" --enable-mouse"); #endif #ifdef ENABLE_NANORC - printf(" --enable-nanorc"); + printf(" --enable-nanorc"); #endif #ifdef ENABLE_MULTIBUFFER - printf(" --enable-multibuffer"); + printf(" --enable-multibuffer"); #endif #ifdef ENABLE_OPERATINGDIR - printf(" --enable-operatingdir"); + printf(" --enable-operatingdir"); #endif #ifdef ENABLE_SPELLER - printf(" --enable-speller"); + printf(" --enable-speller"); #endif #ifdef ENABLE_TABCOMP - printf(" --enable-tabcomp"); + printf(" --enable-tabcomp"); #endif #ifdef ENABLE_WRAPPING - printf(" --enable-wrapping"); + printf(" --enable-wrapping"); #endif #else /* !NANO_TINY */ #ifndef ENABLE_BROWSER - printf(" --disable-browser"); + printf(" --disable-browser"); #endif #ifndef ENABLE_COLOR - printf(" --disable-color"); + printf(" --disable-color"); #endif #ifndef ENABLE_COMMENT - printf(" --disable-comment"); + printf(" --disable-comment"); #endif #ifndef ENABLE_EXTRA - printf(" --disable-extra"); + printf(" --disable-extra"); #endif #ifndef ENABLE_HELP - printf(" --disable-help"); + printf(" --disable-help"); #endif #ifndef ENABLE_HISTORIES - printf(" --disable-histories"); + printf(" --disable-histories"); #endif #ifndef ENABLE_JUSTIFY - printf(" --disable-justify"); + printf(" --disable-justify"); #endif #ifndef HAVE_LIBMAGIC - printf(" --disable-libmagic"); + printf(" --disable-libmagic"); #endif #ifndef ENABLE_LINENUMBERS - printf(" --disable-linenumbers"); + printf(" --disable-linenumbers"); #endif #ifndef ENABLE_MOUSE - printf(" --disable-mouse"); + printf(" --disable-mouse"); #endif #ifndef ENABLE_MULTIBUFFER - printf(" --disable-multibuffer"); + printf(" --disable-multibuffer"); #endif #ifndef ENABLE_NANORC - printf(" --disable-nanorc"); + printf(" --disable-nanorc"); #endif #ifndef ENABLE_OPERATINGDIR - printf(" --disable-operatingdir"); + printf(" --disable-operatingdir"); #endif #ifndef ENABLE_SPELLER - printf(" --disable-speller"); + printf(" --disable-speller"); #endif #ifndef ENABLE_TABCOMP - printf(" --disable-tabcomp"); + printf(" --disable-tabcomp"); #endif #ifndef ENABLE_WORDCOMPLETION - printf(" --disable-wordcomp"); + printf(" --disable-wordcomp"); #endif #ifndef ENABLE_WRAPPING - printf(" --disable-wrapping"); + printf(" --disable-wrapping"); #endif #endif /* !NANO_TINY */ #ifdef DISABLE_ROOTWRAPPING - printf(" --disable-wrapping-as-root"); + printf(" --disable-wrapping-as-root"); #endif #ifdef DEBUG - printf(" --enable-debug"); + printf(" --enable-debug"); #endif #ifndef ENABLE_NLS - printf(" --disable-nls"); + printf(" --disable-nls"); #endif #ifdef ENABLE_UTF8 - printf(" --enable-utf8"); + printf(" --enable-utf8"); #else - printf(" --disable-utf8"); + printf(" --disable-utf8"); #endif #ifdef USE_SLANG - printf(" --with-slang"); + printf(" --with-slang"); #endif - printf("\n"); + printf("\n"); } /* If the current file buffer has been modified, and the TEMP_FILE flag @@ -1047,373 +1047,373 @@ void version(void) * buffer is open, exit from nano. */ void do_exit(void) { - int i; + int i; - /* If the file hasn't been modified, pretend the user chose not to - * save. */ - if (!openfile->modified) - i = 0; - /* If the TEMP_FILE flag is set and the current file has a name, - * pretend the user chose to save. */ - else if (openfile->filename[0] != '\0' && ISSET(TEMP_FILE)) - i = 1; - /* Otherwise, ask the user whether or not to save. */ - else { - /* If the TEMP_FILE flag is set, and the current file doesn't - * have a name, warn the user before prompting for a name. */ - if (ISSET(TEMP_FILE)) - warn_and_shortly_pause(_("No file name")); + /* If the file hasn't been modified, pretend the user chose not to + * save. */ + if (!openfile->modified) + i = 0; + /* If the TEMP_FILE flag is set and the current file has a name, + * pretend the user chose to save. */ + else if (openfile->filename[0] != '\0' && ISSET(TEMP_FILE)) + i = 1; + /* Otherwise, ask the user whether or not to save. */ + else { + /* If the TEMP_FILE flag is set, and the current file doesn't + * have a name, warn the user before prompting for a name. */ + if (ISSET(TEMP_FILE)) + warn_and_shortly_pause(_("No file name")); - i = do_yesno_prompt(FALSE, _("Save modified buffer? " - "(Answering \"No\" will DISCARD changes.) ")); - } + i = do_yesno_prompt(FALSE, _("Save modified buffer? " + "(Answering \"No\" will DISCARD changes.) ")); + } #ifdef DEBUG - dump_filestruct(openfile->fileage); + dump_filestruct(openfile->fileage); #endif - /* If the user chose not to save, or if the user chose to save and - * the save succeeded, we're ready to exit. */ - if (i == 0 || (i == 1 && do_writeout(TRUE, TRUE) > 0)) - close_and_go(); - else if (i != 1) - statusbar(_("Cancelled")); + /* If the user chose not to save, or if the user chose to save and + * the save succeeded, we're ready to exit. */ + if (i == 0 || (i == 1 && do_writeout(TRUE, TRUE) > 0)) + close_and_go(); + else if (i != 1) + statusbar(_("Cancelled")); } /* Close the current buffer, and terminate nano if it was the last. */ void close_and_go(void) { #ifndef NANO_TINY - /* If there is a lockfile, remove it. */ - if (ISSET(LOCKING) && openfile->lock_filename) - delete_lockfile(openfile->lock_filename); + /* If there is a lockfile, remove it. */ + if (ISSET(LOCKING) && openfile->lock_filename) + delete_lockfile(openfile->lock_filename); #endif #ifdef ENABLE_MULTIBUFFER - /* If there are no more open file buffers, jump off a cliff. */ - if (!close_buffer()) + /* If there are no more open file buffers, jump off a cliff. */ + if (!close_buffer()) #endif - finish(); + finish(); } /* Another placeholder for function mapping. */ void do_cancel(void) { - ; + ; } /* Make a note that reading from stdin was concluded with ^C. */ RETSIGTYPE make_a_note(int signal) { - input_was_aborted = TRUE; + input_was_aborted = TRUE; } /* Read whatever comes from standard input into a new buffer. */ bool scoop_stdin(void) { - struct sigaction oldaction, newaction; - /* Original and temporary handlers for SIGINT. */ - bool setup_failed = FALSE; - /* Whether setting up the SIGINT handler failed. */ - FILE *stream; - int thetty; + struct sigaction oldaction, newaction; + /* Original and temporary handlers for SIGINT. */ + bool setup_failed = FALSE; + /* Whether setting up the SIGINT handler failed. */ + FILE *stream; + int thetty; - /* Exit from curses mode and put the terminal into its original state. */ - endwin(); - tcsetattr(0, TCSANOW, &oldterm); + /* Exit from curses mode and put the terminal into its original state. */ + endwin(); + tcsetattr(0, TCSANOW, &oldterm); - fprintf(stderr, _("Reading from stdin, ^C to abort\n")); + fprintf(stderr, _("Reading from stdin, ^C to abort\n")); #ifndef NANO_TINY - /* Enable interpretation of the special control keys so that - * we get SIGINT when Ctrl-C is pressed. */ - enable_signals(); + /* Enable interpretation of the special control keys so that + * we get SIGINT when Ctrl-C is pressed. */ + enable_signals(); #endif - /* Set things up so that SIGINT will cancel the reading. */ - if (sigaction(SIGINT, NULL, &newaction) == -1) { - setup_failed = TRUE; - nperror("sigaction"); - } else { - newaction.sa_handler = make_a_note; - if (sigaction(SIGINT, &newaction, &oldaction) == -1) { - setup_failed = TRUE; - nperror("sigaction"); + /* Set things up so that SIGINT will cancel the reading. */ + if (sigaction(SIGINT, NULL, &newaction) == -1) { + setup_failed = TRUE; + nperror("sigaction"); + } else { + newaction.sa_handler = make_a_note; + if (sigaction(SIGINT, &newaction, &oldaction) == -1) { + setup_failed = TRUE; + nperror("sigaction"); + } } - } - /* Open standard input. */ - stream = fopen("/dev/stdin", "rb"); - if (stream == NULL) { - int errnumber = errno; + /* Open standard input. */ + stream = fopen("/dev/stdin", "rb"); + if (stream == NULL) { + int errnumber = errno; + + terminal_init(); + doupdate(); + statusline(ALERT, _("Failed to open stdin: %s"), strerror(errnumber)); + return FALSE; + } + + /* Read the input into a new buffer. */ + open_buffer("", FALSE); + read_file(stream, 0, "stdin", TRUE, FALSE); + openfile->edittop = openfile->fileage; + + /* Reconnect the tty as the input source. */ + thetty = open("/dev/tty", O_RDONLY); + if (!thetty) + die(_("Couldn't reopen stdin from keyboard, sorry\n")); + dup2(thetty, 0); + close(thetty); + + /* If things went well, store the current state of the terminal. */ + if (!input_was_aborted) + tcgetattr(0, &oldterm); + + /* If it was changed, restore the handler for SIGINT. */ + if (!setup_failed && sigaction(SIGINT, &oldaction, NULL) == -1) + nperror("sigaction"); terminal_init(); doupdate(); - statusline(ALERT, _("Failed to open stdin: %s"), strerror(errnumber)); - return FALSE; - } - /* Read the input into a new buffer. */ - open_buffer("", FALSE); - read_file(stream, 0, "stdin", TRUE, FALSE); - openfile->edittop = openfile->fileage; + if (!ISSET(VIEW_MODE) && openfile->totsize > 0) + set_modified(); - /* Reconnect the tty as the input source. */ - thetty = open("/dev/tty", O_RDONLY); - if (!thetty) - die(_("Couldn't reopen stdin from keyboard, sorry\n")); - dup2(thetty, 0); - close(thetty); - - /* If things went well, store the current state of the terminal. */ - if (!input_was_aborted) - tcgetattr(0, &oldterm); - - /* If it was changed, restore the handler for SIGINT. */ - if (!setup_failed && sigaction(SIGINT, &oldaction, NULL) == -1) - nperror("sigaction"); - - terminal_init(); - doupdate(); - - if (!ISSET(VIEW_MODE) && openfile->totsize > 0) - set_modified(); - - return TRUE; + return TRUE; } /* Register half a dozen signal handlers. */ void signal_init(void) { - /* Trap SIGINT and SIGQUIT because we want them to do useful things. */ - memset(&act, 0, sizeof(struct sigaction)); - act.sa_handler = SIG_IGN; - sigaction(SIGINT, &act, NULL); + /* Trap SIGINT and SIGQUIT because we want them to do useful things. */ + memset(&act, 0, sizeof(struct sigaction)); + act.sa_handler = SIG_IGN; + sigaction(SIGINT, &act, NULL); #ifdef SIGQUIT - sigaction(SIGQUIT, &act, NULL); + sigaction(SIGQUIT, &act, NULL); #endif - /* Trap SIGHUP and SIGTERM because we want to write the file out. */ - act.sa_handler = handle_hupterm; + /* Trap SIGHUP and SIGTERM because we want to write the file out. */ + act.sa_handler = handle_hupterm; #ifdef SIGHUP - sigaction(SIGHUP, &act, NULL); + sigaction(SIGHUP, &act, NULL); #endif - sigaction(SIGTERM, &act, NULL); + sigaction(SIGTERM, &act, NULL); #ifndef NANO_TINY - /* Trap SIGWINCH because we want to handle window resizes. */ - act.sa_handler = handle_sigwinch; - sigaction(SIGWINCH, &act, NULL); + /* Trap SIGWINCH because we want to handle window resizes. */ + act.sa_handler = handle_sigwinch; + sigaction(SIGWINCH, &act, NULL); #endif - if (ISSET(SUSPEND)) { - /* Block all other signals in the suspend and continue handlers. - * If we don't do this, other stuff interrupts them! */ - sigfillset(&act.sa_mask); + if (ISSET(SUSPEND)) { + /* Block all other signals in the suspend and continue handlers. + * If we don't do this, other stuff interrupts them! */ + sigfillset(&act.sa_mask); #ifdef SIGTSTP - /* Trap a normal suspend (^Z) so we can handle it ourselves. */ - act.sa_handler = do_suspend; - sigaction(SIGTSTP, &act, NULL); + /* Trap a normal suspend (^Z) so we can handle it ourselves. */ + act.sa_handler = do_suspend; + sigaction(SIGTSTP, &act, NULL); #endif #ifdef SIGCONT - act.sa_handler = do_continue; - sigaction(SIGCONT, &act, NULL); + act.sa_handler = do_continue; + sigaction(SIGCONT, &act, NULL); #endif - } else { + } else { #ifdef SIGTSTP - act.sa_handler = SIG_IGN; - sigaction(SIGTSTP, &act, NULL); + act.sa_handler = SIG_IGN; + sigaction(SIGTSTP, &act, NULL); #endif - } + } } /* Handler for SIGHUP (hangup) and SIGTERM (terminate). */ RETSIGTYPE handle_hupterm(int signal) { - die(_("Received SIGHUP or SIGTERM\n")); + die(_("Received SIGHUP or SIGTERM\n")); } /* Handler for SIGTSTP (suspend). */ RETSIGTYPE do_suspend(int signal) { #ifdef ENABLE_MOUSE - disable_mouse_support(); + disable_mouse_support(); #endif - /* Move the cursor to the last line of the screen. */ - move(LINES - 1, 0); - endwin(); + /* Move the cursor to the last line of the screen. */ + move(LINES - 1, 0); + endwin(); - /* Display our helpful message. */ - printf(_("Use \"fg\" to return to nano.\n")); - fflush(stdout); + /* Display our helpful message. */ + printf(_("Use \"fg\" to return to nano.\n")); + fflush(stdout); - /* Restore the old terminal settings. */ - tcsetattr(0, TCSANOW, &oldterm); + /* Restore the old terminal settings. */ + tcsetattr(0, TCSANOW, &oldterm); #ifdef SIGSTOP - /* Do what mutt does: send ourselves a SIGSTOP. */ - kill(0, SIGSTOP); + /* Do what mutt does: send ourselves a SIGSTOP. */ + kill(0, SIGSTOP); #endif } /* Put nano to sleep (if suspension is enabled). */ void do_suspend_void(void) { - if (ISSET(SUSPEND)) - do_suspend(0); - else { - statusbar(_("Suspension is not enabled")); - beep(); - } + if (ISSET(SUSPEND)) + do_suspend(0); + else { + statusbar(_("Suspension is not enabled")); + beep(); + } } /* Handler for SIGCONT (continue after suspend). */ RETSIGTYPE do_continue(int signal) { #ifdef ENABLE_MOUSE - if (ISSET(USE_MOUSE)) - enable_mouse_support(); + if (ISSET(USE_MOUSE)) + enable_mouse_support(); #endif #ifndef NANO_TINY - /* Perhaps the user resized the window while we slept. */ - the_window_resized = TRUE; + /* Perhaps the user resized the window while we slept. */ + the_window_resized = TRUE; #else - /* Put the terminal in the desired state again. */ - terminal_init(); + /* Put the terminal in the desired state again. */ + terminal_init(); #endif - /* Tickle the input routine so it will update the screen. */ - ungetch(KEY_FLUSH); + /* Tickle the input routine so it will update the screen. */ + ungetch(KEY_FLUSH); } #ifndef NANO_TINY /* Handler for SIGWINCH (window size change). */ RETSIGTYPE handle_sigwinch(int signal) { - /* Let the input routine know that a SIGWINCH has occurred. */ - the_window_resized = TRUE; + /* Let the input routine know that a SIGWINCH has occurred. */ + the_window_resized = TRUE; } /* Reinitialize and redraw the screen completely. */ void regenerate_screen(void) { - const char *tty = ttyname(0); - int fd, result = 0; - struct winsize win; + const char *tty = ttyname(0); + int fd, result = 0; + struct winsize win; - /* Reset the trigger. */ - the_window_resized = FALSE; + /* Reset the trigger. */ + the_window_resized = FALSE; - if (tty == NULL) - return; - fd = open(tty, O_RDWR); - if (fd == -1) - return; - result = ioctl(fd, TIOCGWINSZ, &win); - close(fd); - if (result == -1) - return; + if (tty == NULL) + return; + fd = open(tty, O_RDWR); + if (fd == -1) + return; + result = ioctl(fd, TIOCGWINSZ, &win); + close(fd); + if (result == -1) + return; - /* We could check whether the COLS or LINES changed, and return - * otherwise. However, COLS and LINES are curses global variables, - * and in some cases curses has already updated them. But not in - * all cases. Argh. */ + /* We could check whether the COLS or LINES changed, and return + * 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 REDEFINING_MACROS_OK - COLS = win.ws_col; - LINES = win.ws_row; + COLS = win.ws_col; + LINES = win.ws_row; #endif - editwincols = COLS - margin; + editwincols = COLS - margin; - /* Ensure that firstcolumn is the starting column of its chunk. */ - ensure_firstcolumn_is_aligned(); + /* Ensure that firstcolumn is the starting column of its chunk. */ + ensure_firstcolumn_is_aligned(); #ifdef USE_SLANG - /* Slang curses emulation brain damage, part 1: If we just do what - * curses does here, it'll only work properly if the resize made the - * window smaller. Do what mutt does: Leave and immediately reenter - * Slang screen management mode. */ - SLsmg_reset_smg(); - SLsmg_init_smg(); + /* Slang curses emulation brain damage, part 1: If we just do what + * curses does here, it'll only work properly if the resize made the + * window smaller. Do what mutt does: Leave and immediately reenter + * Slang screen management mode. */ + SLsmg_reset_smg(); + SLsmg_init_smg(); #else - /* Do the equivalent of what Minimum Profit does: leave and immediately - * reenter curses mode. */ - endwin(); - doupdate(); + /* Do the equivalent of what Minimum Profit does: leave and immediately + * reenter curses mode. */ + endwin(); + doupdate(); #endif - /* Put the terminal in the desired state again, recreate the subwindows - * with their (new) sizes, and redraw the contents of these windows. */ - terminal_init(); - window_init(); - total_refresh(); + /* Put the terminal in the desired state again, recreate the subwindows + * with their (new) sizes, and redraw the contents of these windows. */ + terminal_init(); + window_init(); + total_refresh(); } /* If allow is FALSE, block any SIGWINCH signal. If allow is TRUE, * unblock SIGWINCH so any pending ones can be dealt with. */ void allow_sigwinch(bool allow) { - sigset_t winch; + sigset_t winch; - sigemptyset(&winch); - sigaddset(&winch, SIGWINCH); - sigprocmask(allow ? SIG_UNBLOCK : SIG_BLOCK, &winch, NULL); + sigemptyset(&winch); + sigaddset(&winch, SIGWINCH); + sigprocmask(allow ? SIG_UNBLOCK : SIG_BLOCK, &winch, NULL); } /* Handle the global toggle specified in flag. */ void do_toggle(int flag) { - bool enabled; + bool enabled; - if (ISSET(RESTRICTED) && (flag == SUSPEND || flag == MULTIBUFFER || - flag == BACKUP_FILE || flag == NO_COLOR_SYNTAX)) { - show_restricted_warning(); - return; - } + if (ISSET(RESTRICTED) && (flag == SUSPEND || flag == MULTIBUFFER || + flag == BACKUP_FILE || flag == NO_COLOR_SYNTAX)) { + show_restricted_warning(); + return; + } - TOGGLE(flag); + TOGGLE(flag); - switch (flag) { + switch (flag) { #ifdef ENABLE_MOUSE - case USE_MOUSE: - mouse_init(); - break; + case USE_MOUSE: + mouse_init(); + break; #endif - case MORE_SPACE: - case NO_HELP: - window_init(); - focusing = FALSE; - total_refresh(); - break; - case SUSPEND: - signal_init(); - break; - case SOFTWRAP: - if (!ISSET(SOFTWRAP)) - openfile->firstcolumn = 0; - refresh_needed = TRUE; - break; - case WHITESPACE_DISPLAY: - titlebar(NULL); /* Fall through. */ + case MORE_SPACE: + case NO_HELP: + window_init(); + focusing = FALSE; + total_refresh(); + break; + case SUSPEND: + signal_init(); + break; + case SOFTWRAP: + if (!ISSET(SOFTWRAP)) + openfile->firstcolumn = 0; + refresh_needed = TRUE; + break; + case WHITESPACE_DISPLAY: + titlebar(NULL); /* Fall through. */ #ifdef ENABLE_COLOR - case NO_COLOR_SYNTAX: + case NO_COLOR_SYNTAX: #endif - refresh_needed = TRUE; - break; - } + refresh_needed = TRUE; + break; + } - enabled = ISSET(flag); + enabled = ISSET(flag); - if (flag == NO_HELP || flag == NO_WRAP || flag == NO_COLOR_SYNTAX) - enabled = !enabled; + if (flag == NO_HELP || flag == NO_WRAP || flag == NO_COLOR_SYNTAX) + enabled = !enabled; - statusline(HUSH, "%s %s", _(flagtostr(flag)), - enabled ? _("enabled") : _("disabled")); + statusline(HUSH, "%s %s", _(flagtostr(flag)), + enabled ? _("enabled") : _("disabled")); } /* Bleh. */ void do_toggle_void(void) { - ; + ; } #endif /* !NANO_TINY */ @@ -1422,12 +1422,12 @@ void do_toggle_void(void) void disable_extended_io(void) { #ifdef HAVE_TERMIOS_H - struct termios term; + struct termios term; - tcgetattr(0, &term); - term.c_lflag &= ~IEXTEN; - term.c_oflag &= ~OPOST; - tcsetattr(0, TCSANOW, &term); + tcgetattr(0, &term); + term.c_lflag &= ~IEXTEN; + term.c_oflag &= ~OPOST; + tcsetattr(0, TCSANOW, &term); #endif } @@ -1436,11 +1436,11 @@ void disable_extended_io(void) void disable_signals(void) { #ifdef HAVE_TERMIOS_H - struct termios term; + struct termios term; - tcgetattr(0, &term); - term.c_lflag &= ~ISIG; - tcsetattr(0, TCSANOW, &term); + tcgetattr(0, &term); + term.c_lflag &= ~ISIG; + tcsetattr(0, TCSANOW, &term); #endif } @@ -1450,11 +1450,11 @@ void disable_signals(void) void enable_signals(void) { #ifdef HAVE_TERMIOS_H - struct termios term; + struct termios term; - tcgetattr(0, &term); - term.c_lflag |= ISIG; - tcsetattr(0, TCSANOW, &term); + tcgetattr(0, &term); + term.c_lflag |= ISIG; + tcsetattr(0, TCSANOW, &term); #endif } #endif @@ -1464,11 +1464,11 @@ void enable_signals(void) void disable_flow_control(void) { #ifdef HAVE_TERMIOS_H - struct termios term; + struct termios term; - tcgetattr(0, &term); - term.c_iflag &= ~IXON; - tcsetattr(0, TCSANOW, &term); + tcgetattr(0, &term); + term.c_iflag &= ~IXON; + tcsetattr(0, TCSANOW, &term); #endif } @@ -1477,11 +1477,11 @@ void disable_flow_control(void) void enable_flow_control(void) { #ifdef HAVE_TERMIOS_H - struct termios term; + struct termios term; - tcgetattr(0, &term); - term.c_iflag |= IXON; - tcsetattr(0, TCSANOW, &term); + tcgetattr(0, &term); + term.c_iflag |= IXON; + tcsetattr(0, TCSANOW, &term); #endif } @@ -1496,34 +1496,34 @@ void enable_flow_control(void) void terminal_init(void) { #ifdef USE_SLANG - /* Slang curses emulation brain damage, part 2: Slang doesn't - * implement raw(), nonl(), or noecho() properly, so there's no way - * to properly reinitialize the terminal using them. We have to - * disable the special control keys and interpretation of the flow - * control characters using termios, save the terminal state after - * the first call, and restore it on subsequent calls. */ - static struct termios newterm; - static bool newterm_set = FALSE; + /* Slang curses emulation brain damage, part 2: Slang doesn't + * implement raw(), nonl(), or noecho() properly, so there's no way + * to properly reinitialize the terminal using them. We have to + * disable the special control keys and interpretation of the flow + * control characters using termios, save the terminal state after + * the first call, and restore it on subsequent calls. */ + static struct termios newterm; + static bool newterm_set = FALSE; - if (!newterm_set) { + if (!newterm_set) { #endif - raw(); - nonl(); - noecho(); - disable_extended_io(); - if (ISSET(PRESERVE)) - enable_flow_control(); + raw(); + nonl(); + noecho(); + disable_extended_io(); + if (ISSET(PRESERVE)) + enable_flow_control(); - disable_signals(); + disable_signals(); #ifdef USE_SLANG - if (!ISSET(PRESERVE)) - disable_flow_control(); + if (!ISSET(PRESERVE)) + disable_flow_control(); - tcgetattr(0, &newterm); - newterm_set = TRUE; - } else - tcsetattr(0, TCSANOW, &newterm); + tcgetattr(0, &newterm); + newterm_set = TRUE; + } else + tcsetattr(0, TCSANOW, &newterm); #endif } @@ -1531,29 +1531,29 @@ void terminal_init(void) int get_keycode(const char *keyname, const int standard) { #ifdef HAVE_KEY_DEFINED - const char *keyvalue = tigetstr(keyname); + const char *keyvalue = tigetstr(keyname); - if (keyvalue != 0 && keyvalue != (char *)-1 && key_defined(keyvalue)) - return key_defined(keyvalue); - else + if (keyvalue != 0 && keyvalue != (char *)-1 && key_defined(keyvalue)) + return key_defined(keyvalue); + else #endif - return standard; + return standard; } /* Say that an unbound key was struck, and if possible which one. */ void unbound_key(int code) { - if (!is_byte(code)) - statusline(ALERT, _("Unbound key")); - else if (meta_key) { - if (code == '[') - statusline(ALERT, _("Unbindable key: M-[")); - else - statusline(ALERT, _("Unbound key: M-%c"), toupper(code)); - } else if (code < 0x20) - statusline(ALERT, _("Unbound key: ^%c"), code + 0x40); - else if (currmenu != MHELP) - statusline(ALERT, _("Unbound key: %c"), code); + if (!is_byte(code)) + statusline(ALERT, _("Unbound key")); + else if (meta_key) { + if (code == '[') + statusline(ALERT, _("Unbindable key: M-[")); + else + statusline(ALERT, _("Unbound key: M-%c"), toupper(code)); + } else if (code < 0x20) + statusline(ALERT, _("Unbound key: ^%c"), code + 0x40); + else if (currmenu != MHELP) + statusline(ALERT, _("Unbound key: %c"), code); } /* Read in a keystroke. Act on the keystroke if it is a shortcut or a toggle; @@ -1561,227 +1561,227 @@ void unbound_key(int code) * do anything with the keystroke -- just return it. */ int do_input(bool allow_funcs) { - int input; - /* The keystroke we read in: a character or a shortcut. */ - static char *puddle = NULL; - /* The input buffer for actual characters. */ - static size_t depth = 0; - /* The length of the input buffer. */ - bool retain_cuts = FALSE; - /* Whether to conserve the current contents of the cutbuffer. */ - const sc *s; - bool have_shortcut; + int input; + /* The keystroke we read in: a character or a shortcut. */ + static char *puddle = NULL; + /* The input buffer for actual characters. */ + static size_t depth = 0; + /* The length of the input buffer. */ + bool retain_cuts = FALSE; + /* Whether to conserve the current contents of the cutbuffer. */ + const sc *s; + bool have_shortcut; - /* Read in a keystroke, and show the cursor while waiting. */ - input = get_kbinput(edit, VISIBLE); + /* Read in a keystroke, and show the cursor while waiting. */ + input = get_kbinput(edit, VISIBLE); #ifndef NANO_TINY - if (input == KEY_WINCH) - return KEY_WINCH; + if (input == KEY_WINCH) + return KEY_WINCH; #endif #ifdef ENABLE_MOUSE - if (input == KEY_MOUSE) { - /* We received a mouse click. */ - if (do_mouse() == 1) - /* The click was on a shortcut -- read in the character - * that it was converted into. */ - input = get_kbinput(edit, BLIND); - else - /* The click was invalid or has been handled -- get out. */ - return ERR; - } + if (input == KEY_MOUSE) { + /* We received a mouse click. */ + if (do_mouse() == 1) + /* The click was on a shortcut -- read in the character + * that it was converted into. */ + input = get_kbinput(edit, BLIND); + else + /* The click was invalid or has been handled -- get out. */ + return ERR; + } #endif - /* Check for a shortcut in the main list. */ - s = get_shortcut(&input); + /* Check for a shortcut in the main list. */ + s = get_shortcut(&input); - /* If we got a shortcut from the main list, or a "universal" - * edit window shortcut, set have_shortcut to TRUE. */ - have_shortcut = (s != NULL); + /* If we got a shortcut from the main list, or a "universal" + * edit window shortcut, set have_shortcut to TRUE. */ + have_shortcut = (s != NULL); - /* If we got a non-high-bit control key, a meta key sequence, or a - * function key, and it's not a shortcut or toggle, throw it out. */ - if (!have_shortcut) { - if (is_ascii_cntrl_char(input) || meta_key || !is_byte(input)) { - unbound_key(input); - input = ERR; + /* If we got a non-high-bit control key, a meta key sequence, or a + * function key, and it's not a shortcut or toggle, throw it out. */ + if (!have_shortcut) { + if (is_ascii_cntrl_char(input) || meta_key || !is_byte(input)) { + unbound_key(input); + input = ERR; + } } - } - if (!allow_funcs) - return input; + if (!allow_funcs) + return input; - /* If the keystroke isn't a shortcut nor a toggle, it's a normal text - * character: add the character to the input buffer -- or display a - * warning when we're in view mode. */ - if (input != ERR && !have_shortcut) { - if (ISSET(VIEW_MODE)) - print_view_warning(); + /* If the keystroke isn't a shortcut nor a toggle, it's a normal text + * character: add the character to the input buffer -- or display a + * warning when we're in view mode. */ + if (input != ERR && !have_shortcut) { + if (ISSET(VIEW_MODE)) + print_view_warning(); + else { + /* Store the byte, and leave room for a terminating zero. */ + puddle = charealloc(puddle, depth + 2); + puddle[depth++] = (char)input; + } +#ifndef NANO_TINY + if (openfile->mark && openfile->kind_of_mark == SOFTMARK) { + openfile->mark = NULL; + refresh_needed = TRUE; + } +#endif + } + + /* If we got a shortcut or toggle, or if there aren't any other + * characters waiting after the one we read in, we need to output + * all available characters in the input puddle. Note that this + * puddle will be empty if we're in view mode. */ + if (have_shortcut || get_key_buffer_len() == 0) { + if (puddle != NULL) { + /* Insert all bytes in the input buffer into the edit buffer + * at once, filtering out any low control codes. */ + puddle[depth] = '\0'; + do_output(puddle, depth, FALSE); + + /* Empty the input buffer. */ + free(puddle); + puddle = NULL; + depth = 0; + } + } + + if (!have_shortcut) + pletion_line = NULL; else { - /* Store the byte, and leave room for a terminating zero. */ - puddle = charealloc(puddle, depth + 2); - puddle[depth++] = (char)input; - } + const subnfunc *f = sctofunc(s); + + if (ISSET(VIEW_MODE) && f && !f->viewok) { + print_view_warning(); + return ERR; + } + + /* If the function associated with this shortcut is + * cutting or copying text, remember this. */ + if (s->scfunc == do_cut_text_void #ifndef NANO_TINY - if (openfile->mark && openfile->kind_of_mark == SOFTMARK) { - openfile->mark = NULL; - refresh_needed = TRUE; - } + || s->scfunc == do_copy_text || s->scfunc == do_cut_till_eof #endif - } - - /* If we got a shortcut or toggle, or if there aren't any other - * characters waiting after the one we read in, we need to output - * all available characters in the input puddle. Note that this - * puddle will be empty if we're in view mode. */ - if (have_shortcut || get_key_buffer_len() == 0) { - if (puddle != NULL) { - /* Insert all bytes in the input buffer into the edit buffer - * at once, filtering out any low control codes. */ - puddle[depth] = '\0'; - do_output(puddle, depth, FALSE); - - /* Empty the input buffer. */ - free(puddle); - puddle = NULL; - depth = 0; - } - } - - if (!have_shortcut) - pletion_line = NULL; - else { - const subnfunc *f = sctofunc(s); - - if (ISSET(VIEW_MODE) && f && !f->viewok) { - print_view_warning(); - return ERR; - } - - /* If the function associated with this shortcut is - * cutting or copying text, remember this. */ - if (s->scfunc == do_cut_text_void -#ifndef NANO_TINY - || s->scfunc == do_copy_text || s->scfunc == do_cut_till_eof -#endif - ) - retain_cuts = TRUE; + ) + retain_cuts = TRUE; #ifdef ENABLE_WORDCOMPLETION - if (s->scfunc != complete_a_word) - pletion_line = NULL; + if (s->scfunc != complete_a_word) + pletion_line = NULL; #endif #ifndef NANO_TINY - if (s->scfunc == do_toggle_void) { - do_toggle(s->toggle); - if (s->toggle != CUT_FROM_CURSOR) - retain_cuts = TRUE; - } else + if (s->scfunc == do_toggle_void) { + do_toggle(s->toggle); + if (s->toggle != CUT_FROM_CURSOR) + retain_cuts = TRUE; + } else #endif - { + { #ifdef ENABLE_WRAPPING - filestruct *was_next = openfile->current->next; + filestruct *was_next = openfile->current->next; #endif #ifndef NANO_TINY - filestruct *was_current = openfile->current; - size_t was_x = openfile->current_x; + filestruct *was_current = openfile->current; + size_t was_x = openfile->current_x; - /* If Shifted movement occurs, set the mark. */ - if (shift_held && !openfile->mark) { - openfile->mark = openfile->current; - openfile->mark_x = openfile->current_x; - openfile->kind_of_mark = SOFTMARK; - } + /* If Shifted movement occurs, set the mark. */ + if (shift_held && !openfile->mark) { + openfile->mark = openfile->current; + openfile->mark_x = openfile->current_x; + openfile->kind_of_mark = SOFTMARK; + } #endif - /* Execute the function of the shortcut. */ - s->scfunc(); + /* Execute the function of the shortcut. */ + s->scfunc(); #ifndef NANO_TINY - /* When the marked region changes without Shift being held, - * discard a soft mark. And when the marked region covers a - * different set of lines, reset the "last line too" flag. */ - if (openfile->mark && (openfile->current != was_current || - openfile->current_x != was_x)) { - if (!shift_held && openfile->kind_of_mark == SOFTMARK) { - openfile->mark = NULL; - refresh_needed = TRUE; - } else if (openfile->current != was_current) - also_the_last = FALSE; - } + /* When the marked region changes without Shift being held, + * discard a soft mark. And when the marked region covers a + * different set of lines, reset the "last line too" flag. */ + if (openfile->mark && (openfile->current != was_current || + openfile->current_x != was_x)) { + if (!shift_held && openfile->kind_of_mark == SOFTMARK) { + openfile->mark = NULL; + refresh_needed = TRUE; + } else if (openfile->current != was_current) + also_the_last = FALSE; + } #endif #ifdef ENABLE_WRAPPING - /* If the cursor moved to another line, clear the prepend flag. */ - if (openfile->current->next != was_next) - wrap_reset(); + /* If the cursor moved to another line, clear the prepend flag. */ + if (openfile->current->next != was_next) + wrap_reset(); #endif #ifdef ENABLE_COLOR - if (f && !f->viewok) - check_the_multis(openfile->current); + if (f && !f->viewok) + check_the_multis(openfile->current); #endif - if (!refresh_needed && (s->scfunc == do_delete || s->scfunc == do_backspace)) - update_line(openfile->current, openfile->current_x); + if (!refresh_needed && (s->scfunc == do_delete || s->scfunc == do_backspace)) + update_line(openfile->current, openfile->current_x); + } } - } - /* If we aren't cutting or copying text, and the key wasn't a toggle, - * blow away the text in the cutbuffer upon the next cutting action. */ - if (!retain_cuts) - cutbuffer_reset(); + /* If we aren't cutting or copying text, and the key wasn't a toggle, + * blow away the text in the cutbuffer upon the next cutting action. */ + if (!retain_cuts) + cutbuffer_reset(); - return input; + return input; } #ifdef ENABLE_MOUSE /* Handle a mouse click on the edit window or the shortcut list. */ int do_mouse(void) { - int mouse_col, mouse_row; - int retval = get_mouseinput(&mouse_col, &mouse_row, TRUE); + int mouse_col, mouse_row; + int retval = get_mouseinput(&mouse_col, &mouse_row, TRUE); - /* If the click is wrong or already handled, we're done. */ - if (retval != 0) - return retval; + /* If the click is wrong or already handled, we're done. */ + if (retval != 0) + return retval; - /* If the click was in the edit window, put the cursor in that spot. */ - if (wmouse_trafo(edit, &mouse_row, &mouse_col, FALSE)) { - filestruct *current_save = openfile->current; - ssize_t row_count = mouse_row - openfile->current_y; - size_t leftedge; + /* If the click was in the edit window, put the cursor in that spot. */ + if (wmouse_trafo(edit, &mouse_row, &mouse_col, FALSE)) { + filestruct *current_save = openfile->current; + ssize_t row_count = mouse_row - openfile->current_y; + size_t leftedge; #ifndef NANO_TINY - size_t current_x_save = openfile->current_x; - bool sameline = (mouse_row == openfile->current_y); - /* Whether the click was on the row where the cursor is. */ + size_t current_x_save = openfile->current_x; + bool sameline = (mouse_row == openfile->current_y); + /* Whether the click was on the row where the cursor is. */ - if (ISSET(SOFTWRAP)) - leftedge = leftedge_for(xplustabs(), openfile->current); - else + if (ISSET(SOFTWRAP)) + leftedge = leftedge_for(xplustabs(), openfile->current); + else #endif - leftedge = get_page_start(xplustabs()); + leftedge = get_page_start(xplustabs()); - /* Move current up or down to the row corresponding to mouse_row. */ - if (row_count < 0) - go_back_chunks(-row_count, &openfile->current, &leftedge); - else - go_forward_chunks(row_count, &openfile->current, &leftedge); + /* Move current up or down to the row corresponding to mouse_row. */ + if (row_count < 0) + go_back_chunks(-row_count, &openfile->current, &leftedge); + else + go_forward_chunks(row_count, &openfile->current, &leftedge); - openfile->current_x = actual_x(openfile->current->data, - actual_last_column(leftedge, mouse_col)); + openfile->current_x = actual_x(openfile->current->data, + actual_last_column(leftedge, mouse_col)); #ifndef NANO_TINY - /* Clicking where the cursor is toggles the mark, as does clicking - * beyond the line length with the cursor at the end of the line. */ - if (sameline && openfile->current_x == current_x_save) - do_mark(); - else + /* Clicking where the cursor is toggles the mark, as does clicking + * beyond the line length with the cursor at the end of the line. */ + if (sameline && openfile->current_x == current_x_save) + do_mark(); + else #endif - /* The cursor moved; clean the cutbuffer on the next cut. */ - cutbuffer_reset(); + /* The cursor moved; clean the cutbuffer on the next cut. */ + cutbuffer_reset(); - edit_redraw(current_save, CENTERING); - } + edit_redraw(current_save, CENTERING); + } - /* No more handling is needed. */ - return 2; + /* No more handling is needed. */ + return 2; } #endif /* ENABLE_MOUSE */ @@ -1790,868 +1790,868 @@ int do_mouse(void) * TRUE. */ void do_output(char *output, size_t output_len, bool allow_cntrls) { - char onechar[MAXCHARLEN]; - int char_len; - size_t current_len = strlen(openfile->current->data); - size_t i = 0; + char onechar[MAXCHARLEN]; + int char_len; + size_t current_len = strlen(openfile->current->data); + size_t i = 0; #ifndef NANO_TINY - size_t original_row = 0, old_amount = 0; + size_t original_row = 0, old_amount = 0; - if (ISSET(SOFTWRAP)) { - if (openfile->current_y == editwinrows - 1) - original_row = chunk_for(xplustabs(), openfile->current); - old_amount = number_of_chunks_in(openfile->current); - } -#endif - - while (i < output_len) { - /* Encode an embedded NUL byte as 0x0A. */ - if (output[i] == '\0') - output[i] = '\n'; - - /* Get the next multibyte character. */ - char_len = parse_mbchar(output + i, onechar, NULL); - - i += char_len; - - /* If controls are not allowed, ignore an ASCII control character. */ - if (!allow_cntrls && is_ascii_cntrl_char(*(output + i - char_len))) - continue; - - /* Make room for the new character and copy it into the line. */ - openfile->current->data = charealloc(openfile->current->data, - current_len + char_len + 1); - charmove(openfile->current->data + openfile->current_x + char_len, - openfile->current->data + openfile->current_x, - current_len - openfile->current_x + 1); - strncpy(openfile->current->data + openfile->current_x, onechar, - char_len); - current_len += char_len; - openfile->totsize++; - set_modified(); - -#ifndef NANO_TINY - add_undo(ADD); - - /* Note that current_x has not yet been incremented. */ - if (openfile->current == openfile->mark && - openfile->current_x < openfile->mark_x) - openfile->mark_x += char_len; - - /* When the cursor is on the top row and not on the first chunk - * of a line, adding text there might change the preceding chunk - * and thus require an adjustment of firstcolumn. */ - if (openfile->current == openfile->edittop && - openfile->firstcolumn > 0) { - ensure_firstcolumn_is_aligned(); - refresh_needed = TRUE; + if (ISSET(SOFTWRAP)) { + if (openfile->current_y == editwinrows - 1) + original_row = chunk_for(xplustabs(), openfile->current); + old_amount = number_of_chunks_in(openfile->current); } #endif - openfile->current_x += char_len; + while (i < output_len) { + /* Encode an embedded NUL byte as 0x0A. */ + if (output[i] == '\0') + output[i] = '\n'; + + /* Get the next multibyte character. */ + char_len = parse_mbchar(output + i, onechar, NULL); + + i += char_len; + + /* If controls are not allowed, ignore an ASCII control character. */ + if (!allow_cntrls && is_ascii_cntrl_char(*(output + i - char_len))) + continue; + + /* Make room for the new character and copy it into the line. */ + openfile->current->data = charealloc(openfile->current->data, + current_len + char_len + 1); + charmove(openfile->current->data + openfile->current_x + char_len, + openfile->current->data + openfile->current_x, + current_len - openfile->current_x + 1); + strncpy(openfile->current->data + openfile->current_x, onechar, + char_len); + current_len += char_len; + openfile->totsize++; + set_modified(); #ifndef NANO_TINY - update_undo(ADD); + add_undo(ADD); + + /* Note that current_x has not yet been incremented. */ + if (openfile->current == openfile->mark && + openfile->current_x < openfile->mark_x) + openfile->mark_x += char_len; + + /* When the cursor is on the top row and not on the first chunk + * of a line, adding text there might change the preceding chunk + * and thus require an adjustment of firstcolumn. */ + if (openfile->current == openfile->edittop && + openfile->firstcolumn > 0) { + ensure_firstcolumn_is_aligned(); + refresh_needed = TRUE; + } #endif - /* If we've added text to the magicline, create a new magicline. */ - if (openfile->filebot == openfile->current && !ISSET(NO_NEWLINES)) { - new_magicline(); - if (margin > 0) - refresh_needed = TRUE; - } + openfile->current_x += char_len; + +#ifndef NANO_TINY + update_undo(ADD); +#endif + + /* If we've added text to the magicline, create a new magicline. */ + if (openfile->filebot == openfile->current && !ISSET(NO_NEWLINES)) { + new_magicline(); + if (margin > 0) + refresh_needed = TRUE; + } #ifdef ENABLE_WRAPPING - /* If text gets wrapped, the edit window needs a refresh. */ - if (!ISSET(NO_WRAP) && do_wrap(openfile->current)) - refresh_needed = TRUE; + /* If text gets wrapped, the edit window needs a refresh. */ + if (!ISSET(NO_WRAP) && do_wrap(openfile->current)) + refresh_needed = TRUE; #endif - } + } #ifndef NANO_TINY - /* If the number of screen rows that a softwrapped line occupies has - * changed, we need a full refresh. And if we were on the last line - * of the edit window, and we moved one screen row, we're now below - * the last line of the edit window, so we need a full refresh too. */ - if (ISSET(SOFTWRAP) && refresh_needed == FALSE && - (number_of_chunks_in(openfile->current) != old_amount || - (openfile->current_y == editwinrows - 1 && - chunk_for(xplustabs(), openfile->current) != original_row))) - refresh_needed = TRUE; + /* If the number of screen rows that a softwrapped line occupies has + * changed, we need a full refresh. And if we were on the last line + * of the edit window, and we moved one screen row, we're now below + * the last line of the edit window, so we need a full refresh too. */ + if (ISSET(SOFTWRAP) && refresh_needed == FALSE && + (number_of_chunks_in(openfile->current) != old_amount || + (openfile->current_y == editwinrows - 1 && + chunk_for(xplustabs(), openfile->current) != original_row))) + refresh_needed = TRUE; #endif - openfile->placewewant = xplustabs(); + openfile->placewewant = xplustabs(); #ifdef ENABLE_COLOR - check_the_multis(openfile->current); + check_the_multis(openfile->current); #endif - if (!refresh_needed) - update_line(openfile->current, openfile->current_x); + if (!refresh_needed) + update_line(openfile->current, openfile->current_x); } int main(int argc, char **argv) { - int stdin_flags, optchr; + int stdin_flags, optchr; #if defined(ENABLED_WRAPORJUSTIFY) && defined(ENABLE_NANORC) - bool fill_used = FALSE; - /* Was the fill option used on the command line? */ + bool fill_used = FALSE; + /* Was the fill option used on the command line? */ #endif #ifdef ENABLE_WRAPPING - bool forced_wrapping = FALSE; - /* Should long lines be automatically hard wrapped? */ + bool forced_wrapping = FALSE; + /* Should long lines be automatically hard wrapped? */ #endif #ifdef ENABLE_MULTIBUFFER - bool is_multibuffer; - /* The actual value of the multibuffer option, restored after - * we've loaded all files given on the command line. */ + bool is_multibuffer; + /* The actual value of the multibuffer option, restored after + * we've loaded all files given on the command line. */ #endif - const struct option long_options[] = { - {"boldtext", 0, NULL, 'D'}, + const struct option long_options[] = { + {"boldtext", 0, NULL, 'D'}, #ifdef ENABLE_MULTIBUFFER - {"multibuffer", 0, NULL, 'F'}, + {"multibuffer", 0, NULL, 'F'}, #endif #ifdef ENABLE_NANORC - {"ignorercfiles", 0, NULL, 'I'}, + {"ignorercfiles", 0, NULL, 'I'}, #endif - {"rebindkeypad", 0, NULL, 'K'}, - {"nonewlines", 0, NULL, 'L'}, - {"morespace", 0, NULL, 'O'}, + {"rebindkeypad", 0, NULL, 'K'}, + {"nonewlines", 0, NULL, 'L'}, + {"morespace", 0, NULL, 'O'}, #ifdef ENABLE_JUSTIFY - {"quotestr", 1, NULL, 'Q'}, + {"quotestr", 1, NULL, 'Q'}, #endif - {"restricted", 0, NULL, 'R'}, - {"tabsize", 1, NULL, 'T'}, - {"quickblank", 0, NULL, 'U'}, - {"version", 0, NULL, 'V'}, + {"restricted", 0, NULL, 'R'}, + {"tabsize", 1, NULL, 'T'}, + {"quickblank", 0, NULL, 'U'}, + {"version", 0, NULL, 'V'}, #ifdef ENABLE_COLOR - {"syntax", 1, NULL, 'Y'}, + {"syntax", 1, NULL, 'Y'}, #endif - {"constantshow", 0, NULL, 'c'}, - {"rebinddelete", 0, NULL, 'd'}, + {"constantshow", 0, NULL, 'c'}, + {"rebinddelete", 0, NULL, 'd'}, #ifdef ENABLE_BROWSER - {"showcursor", 0, NULL, 'g'}, + {"showcursor", 0, NULL, 'g'}, #endif - {"help", 0, NULL, 'h'}, + {"help", 0, NULL, 'h'}, #ifdef ENABLE_LINENUMBERS - {"linenumbers", 0, NULL, 'l'}, + {"linenumbers", 0, NULL, 'l'}, #endif #ifdef ENABLE_MOUSE - {"mouse", 0, NULL, 'm'}, + {"mouse", 0, NULL, 'm'}, #endif - {"noread", 0, NULL, 'n'}, + {"noread", 0, NULL, 'n'}, #ifdef ENABLE_OPERATINGDIR - {"operatingdir", 1, NULL, 'o'}, + {"operatingdir", 1, NULL, 'o'}, #endif - {"preserve", 0, NULL, 'p'}, - {"quiet", 0, NULL, 'q'}, + {"preserve", 0, NULL, 'p'}, + {"quiet", 0, NULL, 'q'}, #ifdef ENABLED_WRAPORJUSTIFY - {"fill", 1, NULL, 'r'}, + {"fill", 1, NULL, 'r'}, #endif #ifdef ENABLE_SPELLER - {"speller", 1, NULL, 's'}, + {"speller", 1, NULL, 's'}, #endif - {"tempfile", 0, NULL, 't'}, - {"view", 0, NULL, 'v'}, + {"tempfile", 0, NULL, 't'}, + {"view", 0, NULL, 'v'}, #ifdef ENABLE_WRAPPING - {"nowrap", 0, NULL, 'w'}, + {"nowrap", 0, NULL, 'w'}, #endif - {"nohelp", 0, NULL, 'x'}, - {"suspend", 0, NULL, 'z'}, + {"nohelp", 0, NULL, 'x'}, + {"suspend", 0, NULL, 'z'}, #ifndef NANO_TINY - {"smarthome", 0, NULL, 'A'}, - {"backup", 0, NULL, 'B'}, - {"backupdir", 1, NULL, 'C'}, - {"tabstospaces", 0, NULL, 'E'}, - {"locking", 0, NULL, 'G'}, - {"historylog", 0, NULL, 'H'}, - {"noconvert", 0, NULL, 'N'}, - {"poslog", 0, NULL, 'P'}, /* deprecated form, remove in 2018 */ - {"positionlog", 0, NULL, 'P'}, - {"smooth", 0, NULL, 'S'}, - {"wordbounds", 0, NULL, 'W'}, - {"wordchars", 1, NULL, 'X'}, - {"atblanks", 0, NULL, 'a'}, - {"autoindent", 0, NULL, 'i'}, - {"cutfromcursor", 0, NULL, 'k'}, - {"unix", 0, NULL, 'u'}, - {"softwrap", 0, NULL, '$'}, + {"smarthome", 0, NULL, 'A'}, + {"backup", 0, NULL, 'B'}, + {"backupdir", 1, NULL, 'C'}, + {"tabstospaces", 0, NULL, 'E'}, + {"locking", 0, NULL, 'G'}, + {"historylog", 0, NULL, 'H'}, + {"noconvert", 0, NULL, 'N'}, + {"poslog", 0, NULL, 'P'}, /* deprecated form, remove in 2018 */ + {"positionlog", 0, NULL, 'P'}, + {"smooth", 0, NULL, 'S'}, + {"wordbounds", 0, NULL, 'W'}, + {"wordchars", 1, NULL, 'X'}, + {"atblanks", 0, NULL, 'a'}, + {"autoindent", 0, NULL, 'i'}, + {"cutfromcursor", 0, NULL, 'k'}, + {"unix", 0, NULL, 'u'}, + {"softwrap", 0, NULL, '$'}, #endif - {NULL, 0, NULL, 0} - }; + {NULL, 0, NULL, 0} + }; - /* Back up the terminal settings so that they can be restored. */ - tcgetattr(0, &oldterm); + /* Back up the terminal settings so that they can be restored. */ + tcgetattr(0, &oldterm); - /* Get the state of standard input and ensure it uses blocking mode. */ - stdin_flags = fcntl(0, F_GETFL, 0); - if (stdin_flags != -1) - fcntl(0, F_SETFL, stdin_flags & ~O_NONBLOCK); + /* Get the state of standard input and ensure it uses blocking mode. */ + stdin_flags = fcntl(0, F_GETFL, 0); + if (stdin_flags != -1) + fcntl(0, F_SETFL, stdin_flags & ~O_NONBLOCK); #ifdef ENABLE_UTF8 - /* If setting the locale is successful and it uses UTF-8, we need - * to use the multibyte functions for text processing. */ - if (setlocale(LC_ALL, "") != NULL && - strcmp(nl_langinfo(CODESET), "UTF-8") == 0) { + /* If setting the locale is successful and it uses UTF-8, we need + * to use the multibyte functions for text processing. */ + if (setlocale(LC_ALL, "") != NULL && + strcmp(nl_langinfo(CODESET), "UTF-8") == 0) { #ifdef USE_SLANG - SLutf8_enable(1); + SLutf8_enable(1); #endif - utf8_init(); - } + utf8_init(); + } #else - setlocale(LC_ALL, ""); + setlocale(LC_ALL, ""); #endif #ifdef ENABLE_NLS - bindtextdomain(PACKAGE, LOCALEDIR); - textdomain(PACKAGE); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); #endif #if defined(ENABLE_UTF8) && !defined(NANO_TINY) - if (MB_CUR_MAX > MAXCHARLEN) - fprintf(stderr, "Unexpected large character size: %i bytes" - " -- please report a bug\n", (int)MB_CUR_MAX); + if (MB_CUR_MAX > MAXCHARLEN) + fprintf(stderr, "Unexpected large character size: %i bytes" + " -- please report a bug\n", (int)MB_CUR_MAX); #endif #if !defined(ENABLE_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) - SET(NO_WRAP); + /* 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) + SET(NO_WRAP); #endif - /* If the executable's name starts with 'r', activate restricted mode. */ - if (*(tail(argv[0])) == 'r') - SET(RESTRICTED); + /* If the executable's name starts with 'r', activate restricted mode. */ + if (*(tail(argv[0])) == 'r') + SET(RESTRICTED); - while ((optchr = - getopt_long(argc, argv, - "ABC:DEFGHIKLNOPQ:RST:UVWX:Y:abcdefghijklmno:pqr:s:tuvwxz$", - long_options, NULL)) != -1) { - switch (optchr) { - case 'b': - case 'e': - case 'f': - case 'j': - /* Pico compatibility flags. */ - break; + while ((optchr = + getopt_long(argc, argv, + "ABC:DEFGHIKLNOPQ:RST:UVWX:Y:abcdefghijklmno:pqr:s:tuvwxz$", + long_options, NULL)) != -1) { + switch (optchr) { + case 'b': + case 'e': + case 'f': + case 'j': + /* Pico compatibility flags. */ + break; #ifndef NANO_TINY - case 'A': - SET(SMART_HOME); - break; - case 'B': - SET(BACKUP_FILE); - break; - case 'C': - backup_dir = mallocstrcpy(backup_dir, optarg); - break; + case 'A': + SET(SMART_HOME); + break; + case 'B': + SET(BACKUP_FILE); + break; + case 'C': + backup_dir = mallocstrcpy(backup_dir, optarg); + break; #endif - case 'D': - SET(BOLD_TEXT); - break; + case 'D': + SET(BOLD_TEXT); + break; #ifndef NANO_TINY - case 'E': - SET(TABS_TO_SPACES); - break; + case 'E': + SET(TABS_TO_SPACES); + break; #endif #ifdef ENABLE_MULTIBUFFER - case 'F': - SET(MULTIBUFFER); - break; + case 'F': + SET(MULTIBUFFER); + break; #endif #ifndef NANO_TINY - case 'G': - SET(LOCKING); - break; + case 'G': + SET(LOCKING); + break; #endif #ifdef ENABLE_HISTORIES - case 'H': - SET(HISTORYLOG); - break; + case 'H': + SET(HISTORYLOG); + break; #endif #ifdef ENABLE_NANORC - case 'I': - no_rcfiles = TRUE; - break; + case 'I': + no_rcfiles = TRUE; + break; #endif - case 'K': - SET(REBIND_KEYPAD); - break; - case 'L': - SET(NO_NEWLINES); - break; + case 'K': + SET(REBIND_KEYPAD); + break; + case 'L': + SET(NO_NEWLINES); + break; #ifndef NANO_TINY - case 'N': - SET(NO_CONVERT); - break; + case 'N': + SET(NO_CONVERT); + break; #endif - case 'O': - SET(MORE_SPACE); - break; + case 'O': + SET(MORE_SPACE); + break; #ifdef ENABLE_HISTORIES - case 'P': - SET(POS_HISTORY); - break; + case 'P': + SET(POS_HISTORY); + break; #endif #ifdef ENABLE_JUSTIFY - case 'Q': - quotestr = mallocstrcpy(quotestr, optarg); - break; + case 'Q': + quotestr = mallocstrcpy(quotestr, optarg); + break; #endif - case 'R': - SET(RESTRICTED); - break; + case 'R': + SET(RESTRICTED); + break; #ifndef NANO_TINY - case 'S': - SET(SMOOTH_SCROLL); - break; + case 'S': + SET(SMOOTH_SCROLL); + break; #endif - case 'T': - if (!parse_num(optarg, &tabsize) || tabsize <= 0) { - fprintf(stderr, _("Requested tab size \"%s\" is invalid"), optarg); - fprintf(stderr, "\n"); - exit(1); - } - break; - case 'U': - SET(QUICK_BLANK); - break; - case 'V': - version(); - exit(0); + case 'T': + if (!parse_num(optarg, &tabsize) || tabsize <= 0) { + fprintf(stderr, _("Requested tab size \"%s\" is invalid"), optarg); + fprintf(stderr, "\n"); + exit(1); + } + break; + case 'U': + SET(QUICK_BLANK); + break; + case 'V': + version(); + exit(0); #ifndef NANO_TINY - case 'W': - SET(WORD_BOUNDS); - break; - case 'X': - word_chars = mallocstrcpy(word_chars, optarg); - break; + case 'W': + SET(WORD_BOUNDS); + break; + case 'X': + word_chars = mallocstrcpy(word_chars, optarg); + break; #endif #ifdef ENABLE_COLOR - case 'Y': - syntaxstr = mallocstrcpy(syntaxstr, optarg); - break; + case 'Y': + syntaxstr = mallocstrcpy(syntaxstr, optarg); + break; #endif #ifndef NANO_TINY - case 'a': - SET(AT_BLANKS); - break; + case 'a': + SET(AT_BLANKS); + break; #endif - case 'c': - SET(CONSTANT_SHOW); - break; - case 'd': - SET(REBIND_DELETE); - break; - case 'g': - SET(SHOW_CURSOR); - break; + case 'c': + SET(CONSTANT_SHOW); + break; + case 'd': + SET(REBIND_DELETE); + break; + case 'g': + SET(SHOW_CURSOR); + break; #ifndef NANO_TINY - case 'i': - SET(AUTOINDENT); - break; - case 'k': - SET(CUT_FROM_CURSOR); - break; + case 'i': + SET(AUTOINDENT); + break; + case 'k': + SET(CUT_FROM_CURSOR); + break; #endif #ifdef ENABLE_MOUSE - case 'm': - SET(USE_MOUSE); - break; + case 'm': + SET(USE_MOUSE); + break; #endif - case 'n': - SET(NOREAD_MODE); - break; + case 'n': + SET(NOREAD_MODE); + break; #ifdef ENABLE_OPERATINGDIR - case 'o': - operating_dir = mallocstrcpy(operating_dir, optarg); - break; + case 'o': + operating_dir = mallocstrcpy(operating_dir, optarg); + break; #endif - case 'p': - SET(PRESERVE); - break; + case 'p': + SET(PRESERVE); + break; #ifdef ENABLE_NANORC - case 'q': /* obsolete, ignored */ - break; + case 'q': /* obsolete, ignored */ + break; #endif #ifdef ENABLED_WRAPORJUSTIFY - case 'r': - if (!parse_num(optarg, &wrap_at)) { - fprintf(stderr, _("Requested fill size \"%s\" is invalid"), optarg); - fprintf(stderr, "\n"); - exit(1); - } + case 'r': + if (!parse_num(optarg, &wrap_at)) { + fprintf(stderr, _("Requested fill size \"%s\" is invalid"), optarg); + fprintf(stderr, "\n"); + exit(1); + } #ifdef ENABLE_NANORC - fill_used = TRUE; + fill_used = TRUE; #endif #ifdef ENABLE_WRAPPING - forced_wrapping = TRUE; + forced_wrapping = TRUE; #endif - break; + break; #endif #ifdef ENABLE_SPELLER - case 's': - alt_speller = mallocstrcpy(alt_speller, optarg); - break; + case 's': + alt_speller = mallocstrcpy(alt_speller, optarg); + break; #endif - case 't': - SET(TEMP_FILE); - break; + case 't': + SET(TEMP_FILE); + break; #ifndef NANO_TINY - case 'u': - SET(MAKE_IT_UNIX); - break; + case 'u': + SET(MAKE_IT_UNIX); + break; #endif - case 'v': - SET(VIEW_MODE); - break; + case 'v': + SET(VIEW_MODE); + break; #ifdef ENABLE_WRAPPING - case 'w': - SET(NO_WRAP); - /* If both --fill and --nowrap are given on the - * command line, the last given option wins. */ - forced_wrapping = FALSE; - break; + case 'w': + SET(NO_WRAP); + /* If both --fill and --nowrap are given on the + * command line, the last given option wins. */ + forced_wrapping = FALSE; + break; #endif - case 'x': - SET(NO_HELP); - break; - case 'z': - SET(SUSPEND); - break; + case 'x': + SET(NO_HELP); + break; + case 'z': + SET(SUSPEND); + break; #ifndef NANO_TINY - case '$': - SET(SOFTWRAP); - break; + case '$': + SET(SOFTWRAP); + break; #endif #ifdef ENABLE_LINENUMBERS - case 'l': - SET(LINE_NUMBERS); - break; + case 'l': + SET(LINE_NUMBERS); + break; #endif - case 'h': - usage(); - exit(0); - default: - printf(_("Type '%s -h' for a list of available options.\n"), argv[0]); - exit(1); + case 'h': + usage(); + exit(0); + default: + printf(_("Type '%s -h' for a list of available options.\n"), argv[0]); + exit(1); + } } - } - /* If we're using restricted mode, disable suspending, backups, - * rcfiles, and history files, since they all would allow reading - * from or writing to files not specified on the command line. */ - if (ISSET(RESTRICTED)) { - UNSET(SUSPEND); - UNSET(BACKUP_FILE); + /* If we're using restricted mode, disable suspending, backups, + * rcfiles, and history files, since they all would allow reading + * from or writing to files not specified on the command line. */ + if (ISSET(RESTRICTED)) { + UNSET(SUSPEND); + UNSET(BACKUP_FILE); #ifdef ENABLE_NANORC - no_rcfiles = TRUE; - UNSET(HISTORYLOG); - UNSET(POS_HISTORY); + no_rcfiles = TRUE; + UNSET(HISTORYLOG); + UNSET(POS_HISTORY); #endif - } + } - /* 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(); + /* 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(); #ifdef ENABLE_NANORC - if (!no_rcfiles) { - /* Back up the command-line options, then read the rcfile(s). */ + if (!no_rcfiles) { + /* Back up the command-line options, then read the rcfile(s). */ #ifdef ENABLE_OPERATINGDIR - char *operating_dir_cpy = operating_dir; + char *operating_dir_cpy = operating_dir; #endif #ifdef ENABLED_WRAPORJUSTIFY - ssize_t wrap_at_cpy = wrap_at; + ssize_t wrap_at_cpy = wrap_at; #endif #ifndef NANO_TINY - char *backup_dir_cpy = backup_dir; - char *word_chars_cpy = word_chars; + char *backup_dir_cpy = backup_dir; + char *word_chars_cpy = word_chars; #endif #ifdef ENABLE_JUSTIFY - char *quotestr_cpy = quotestr; + char *quotestr_cpy = quotestr; #endif #ifdef ENABLE_SPELLER - char *alt_speller_cpy = alt_speller; + char *alt_speller_cpy = alt_speller; #endif - ssize_t tabsize_cpy = tabsize; - unsigned flags_cpy[sizeof(flags) / sizeof(flags[0])]; - size_t i; + ssize_t tabsize_cpy = tabsize; + unsigned flags_cpy[sizeof(flags) / sizeof(flags[0])]; + size_t i; - memcpy(flags_cpy, flags, sizeof(flags_cpy)); + memcpy(flags_cpy, flags, sizeof(flags_cpy)); #ifdef ENABLE_OPERATINGDIR - operating_dir = NULL; + operating_dir = NULL; #endif #ifndef NANO_TINY - backup_dir = NULL; - word_chars = NULL; + backup_dir = NULL; + word_chars = NULL; #endif #ifdef ENABLE_JUSTIFY - quotestr = NULL; + quotestr = NULL; #endif #ifdef ENABLE_SPELLER - alt_speller = NULL; + alt_speller = NULL; #endif - do_rcfiles(); + do_rcfiles(); #ifdef DEBUG - fprintf(stderr, "After rebinding keys...\n"); - print_sclist(); + fprintf(stderr, "After rebinding keys...\n"); + print_sclist(); #endif - /* If the backed-up command-line options have a value, restore them. */ + /* If the backed-up command-line options have a value, restore them. */ #ifdef ENABLE_OPERATINGDIR - if (operating_dir_cpy != NULL) { - free(operating_dir); - operating_dir = operating_dir_cpy; - } + if (operating_dir_cpy != NULL) { + free(operating_dir); + operating_dir = operating_dir_cpy; + } #endif #ifdef ENABLED_WRAPORJUSTIFY - if (fill_used) - wrap_at = wrap_at_cpy; + if (fill_used) + wrap_at = wrap_at_cpy; #endif #ifndef NANO_TINY - if (backup_dir_cpy != NULL) { - free(backup_dir); - backup_dir = backup_dir_cpy; - } - if (word_chars_cpy != NULL) { - free(word_chars); - word_chars = word_chars_cpy; - } + if (backup_dir_cpy != NULL) { + free(backup_dir); + backup_dir = backup_dir_cpy; + } + if (word_chars_cpy != NULL) { + free(word_chars); + word_chars = word_chars_cpy; + } #endif #ifdef ENABLE_JUSTIFY - if (quotestr_cpy != NULL) { - free(quotestr); - quotestr = quotestr_cpy; - } + if (quotestr_cpy != NULL) { + free(quotestr); + quotestr = quotestr_cpy; + } #endif #ifdef ENABLE_SPELLER - if (alt_speller_cpy != NULL) { - free(alt_speller); - alt_speller = alt_speller_cpy; - } + if (alt_speller_cpy != NULL) { + free(alt_speller); + alt_speller = alt_speller_cpy; + } #endif - if (tabsize_cpy != -1) - tabsize = tabsize_cpy; + if (tabsize_cpy != -1) + tabsize = tabsize_cpy; - /* Simply OR the boolean flags from rcfile and command line. */ - for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) - flags[i] |= flags_cpy[i]; - } + /* Simply OR the boolean flags from rcfile and command line. */ + for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) + flags[i] |= flags_cpy[i]; + } #ifdef DISABLE_ROOTWRAPPING - /* If we don't have any rcfiles, --disable-wrapping-as-root is used, - * and we're root, turn wrapping off. */ - else if (geteuid() == NANO_ROOT_UID) - SET(NO_WRAP); + /* If we don't have any rcfiles, --disable-wrapping-as-root is used, + * and we're root, turn wrapping off. */ + else if (geteuid() == NANO_ROOT_UID) + SET(NO_WRAP); #endif #endif /* ENABLE_NANORC */ #ifdef ENABLE_WRAPPING - /* Override a "set nowrap" in an rcfile (or a --disable-wrapping-as-root) - * if --fill was given on the command line and not undone by --nowrap. */ - if (forced_wrapping) - UNSET(NO_WRAP); + /* Override a "set nowrap" in an rcfile (or a --disable-wrapping-as-root) + * if --fill was given on the command line and not undone by --nowrap. */ + if (forced_wrapping) + UNSET(NO_WRAP); #endif - /* If the user wants bold instead of reverse video for hilited text... */ - if (ISSET(BOLD_TEXT)) - hilite_attribute = A_BOLD; + /* If the user wants bold instead of reverse video for hilited text... */ + if (ISSET(BOLD_TEXT)) + hilite_attribute = A_BOLD; #ifdef ENABLE_HISTORIES - /* Initialize the pointers for the Search/Replace/Execute histories. */ - history_init(); + /* Initialize the pointers for the Search/Replace/Execute histories. */ + history_init(); - /* If we need history files, verify that we have a directory for them, - * and when not, cancel the options. */ - if ((ISSET(HISTORYLOG) || ISSET(POS_HISTORY)) && !have_statedir()) { - UNSET(HISTORYLOG); - UNSET(POS_HISTORY); - } + /* If we need history files, verify that we have a directory for them, + * and when not, cancel the options. */ + if ((ISSET(HISTORYLOG) || ISSET(POS_HISTORY)) && !have_statedir()) { + UNSET(HISTORYLOG); + UNSET(POS_HISTORY); + } - /* If the user wants history persistence, read the relevant files. */ - if (ISSET(HISTORYLOG)) - load_history(); - if (ISSET(POS_HISTORY)) - load_poshistory(); + /* If the user wants history persistence, read the relevant files. */ + if (ISSET(HISTORYLOG)) + load_history(); + if (ISSET(POS_HISTORY)) + load_poshistory(); #endif /* ENABLE_HISTORIES */ #ifndef NANO_TINY - /* If backups are enabled and a backup directory was specified and - * we're not in restricted mode, make sure the path exists and is - * a directory, so that backup files can be saved there. */ - if (ISSET(BACKUP_FILE) && backup_dir != NULL && !ISSET(RESTRICTED)) - init_backup_dir(); + /* If backups are enabled and a backup directory was specified and + * we're not in restricted mode, make sure the path exists and is + * a directory, so that backup files can be saved there. */ + if (ISSET(BACKUP_FILE) && backup_dir != NULL && !ISSET(RESTRICTED)) + init_backup_dir(); #endif #ifdef ENABLE_OPERATINGDIR - /* Set up the operating directory. This entails chdir()ing there, - * so that file reads and writes will be based there. */ - if (operating_dir != NULL) - init_operating_dir(); + /* Set up the operating directory. This entails chdir()ing there, + * so that file reads and writes will be based there. */ + if (operating_dir != NULL) + init_operating_dir(); #endif #ifdef ENABLE_JUSTIFY - /* If punct wasn't specified, set its default value. */ - if (punct == NULL) - punct = mallocstrcpy(NULL, "!.?"); + /* If punct wasn't specified, set its default value. */ + if (punct == NULL) + punct = mallocstrcpy(NULL, "!.?"); - /* If brackets wasn't specified, set its default value. */ - if (brackets == NULL) - brackets = mallocstrcpy(NULL, "\"')>]}"); + /* If brackets wasn't specified, set its default value. */ + if (brackets == NULL) + brackets = mallocstrcpy(NULL, "\"')>]}"); - /* If quotestr wasn't specified, set its default value. */ - if (quotestr == NULL) - quotestr = mallocstrcpy(NULL, "^([ \t]*[#:>|}])+"); - quoterc = regcomp("ereg, quotestr, NANO_REG_EXTENDED); + /* If quotestr wasn't specified, set its default value. */ + if (quotestr == NULL) + quotestr = mallocstrcpy(NULL, "^([ \t]*[#:>|}])+"); + quoterc = regcomp("ereg, quotestr, NANO_REG_EXTENDED); - if (quoterc == 0) { - /* We no longer need quotestr, just quotereg. */ - free(quotestr); - quotestr = NULL; - } else { - size_t size = regerror(quoterc, "ereg, NULL, 0); + if (quoterc == 0) { + /* We no longer need quotestr, just quotereg. */ + free(quotestr); + quotestr = NULL; + } else { + size_t size = regerror(quoterc, "ereg, NULL, 0); - quoteerr = charalloc(size); - regerror(quoterc, "ereg, quoteerr, size); - } + quoteerr = charalloc(size); + regerror(quoterc, "ereg, quoteerr, size); + } #endif /* ENABLE_JUSTIFY */ #ifdef ENABLE_SPELLER - /* If we don't have an alternative spell checker after reading the - * command line and/or rcfile(s), check $SPELL for one, as Pico - * does (unless we're using restricted mode, in which case spell - * checking is disabled, since it would allow reading from or - * writing to files not specified on the command line). */ - if (!ISSET(RESTRICTED) && alt_speller == NULL) { - const char *spellenv = getenv("SPELL"); - if (spellenv != NULL) - alt_speller = mallocstrcpy(NULL, spellenv); - } + /* If we don't have an alternative spell checker after reading the + * command line and/or rcfile(s), check $SPELL for one, as Pico + * does (unless we're using restricted mode, in which case spell + * checking is disabled, since it would allow reading from or + * writing to files not specified on the command line). */ + if (!ISSET(RESTRICTED) && alt_speller == NULL) { + const char *spellenv = getenv("SPELL"); + if (spellenv != NULL) + alt_speller = mallocstrcpy(NULL, spellenv); + } #endif #ifndef NANO_TINY - /* If matchbrackets wasn't specified, set its default value. */ - if (matchbrackets == NULL) - matchbrackets = mallocstrcpy(NULL, "(<[{)>]}"); + /* If matchbrackets wasn't specified, set its default value. */ + if (matchbrackets == NULL) + matchbrackets = mallocstrcpy(NULL, "(<[{)>]}"); - /* If the whitespace option wasn't specified, set its default value. */ - if (whitespace == NULL) { + /* If the whitespace option wasn't specified, set its default value. */ + if (whitespace == NULL) { #ifdef ENABLE_UTF8 - if (using_utf8()) { - /* A tab is shown as a Right-Pointing Double Angle Quotation Mark - * (U+00BB), and a space as a Middle Dot (U+00B7). */ - whitespace = mallocstrcpy(NULL, "\xC2\xBB\xC2\xB7"); - whitespace_len[0] = 2; - whitespace_len[1] = 2; - } else + if (using_utf8()) { + /* A tab is shown as a Right-Pointing Double Angle Quotation Mark + * (U+00BB), and a space as a Middle Dot (U+00B7). */ + 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; + { + whitespace = mallocstrcpy(NULL, ">."); + whitespace_len[0] = 1; + whitespace_len[1] = 1; + } } - } #endif /* !NANO_TINY */ - /* Initialize the search string. */ - last_search = mallocstrcpy(NULL, ""); - UNSET(BACKWARDS_SEARCH); + /* Initialize the search string. */ + last_search = mallocstrcpy(NULL, ""); + UNSET(BACKWARDS_SEARCH); - /* If tabsize wasn't specified, set its default value. */ - if (tabsize == -1) - tabsize = WIDTH_OF_TAB; + /* If tabsize wasn't specified, set its default value. */ + if (tabsize == -1) + tabsize = WIDTH_OF_TAB; - /* Initialize curses mode. If this fails, get out. */ - if (initscr() == NULL) - exit(1); + /* Initialize curses mode. If this fails, get out. */ + if (initscr() == NULL) + exit(1); - /* Set up the terminal state. */ - terminal_init(); + /* Set up the terminal state. */ + terminal_init(); #ifdef __linux__ - /* Check whether we're running on a Linux console. */ - console = (getenv("DISPLAY") == NULL); + /* Check whether we're running on a Linux console. */ + console = (getenv("DISPLAY") == NULL); #endif #ifdef DEBUG - fprintf(stderr, "Main: set up windows\n"); + fprintf(stderr, "Main: set up windows\n"); #endif - /* Create the three subwindows, based on the current screen dimensions. */ - window_init(); - curs_set(0); + /* Create the three subwindows, based on the current screen dimensions. */ + window_init(); + curs_set(0); - editwincols = COLS; + editwincols = COLS; - /* Set up the signal handlers. */ - signal_init(); + /* Set up the signal handlers. */ + signal_init(); #ifdef ENABLE_MOUSE - /* Initialize mouse support. */ - mouse_init(); + /* Initialize mouse support. */ + mouse_init(); #endif #ifdef ENABLE_COLOR - set_colorpairs(); + set_colorpairs(); #else - interface_color_pair[TITLE_BAR] = hilite_attribute; - interface_color_pair[LINE_NUMBER] = hilite_attribute; - interface_color_pair[SELECTED_TEXT] = hilite_attribute; - interface_color_pair[STATUS_BAR] = hilite_attribute; - interface_color_pair[KEY_COMBO] = hilite_attribute; - interface_color_pair[FUNCTION_TAG] = A_NORMAL; + interface_color_pair[TITLE_BAR] = hilite_attribute; + interface_color_pair[LINE_NUMBER] = hilite_attribute; + interface_color_pair[SELECTED_TEXT] = hilite_attribute; + interface_color_pair[STATUS_BAR] = hilite_attribute; + interface_color_pair[KEY_COMBO] = hilite_attribute; + interface_color_pair[FUNCTION_TAG] = A_NORMAL; #endif - /* Ask ncurses for the key codes for Control+Left/Right/Up/Down. */ - controlleft = get_keycode("kLFT5", CONTROL_LEFT); - controlright = get_keycode("kRIT5", CONTROL_RIGHT); - controlup = get_keycode("kUP5", CONTROL_UP); - controldown = get_keycode("kDN5", CONTROL_DOWN); - /* Ask for the codes for Control+Home/End. */ - controlhome = get_keycode("kHOM5", CONTROL_HOME); - controlend = get_keycode("kEND5", CONTROL_END); + /* Ask ncurses for the key codes for Control+Left/Right/Up/Down. */ + controlleft = get_keycode("kLFT5", CONTROL_LEFT); + controlright = get_keycode("kRIT5", CONTROL_RIGHT); + controlup = get_keycode("kUP5", CONTROL_UP); + controldown = get_keycode("kDN5", CONTROL_DOWN); + /* Ask for the codes for Control+Home/End. */ + controlhome = get_keycode("kHOM5", CONTROL_HOME); + controlend = get_keycode("kEND5", CONTROL_END); #ifndef NANO_TINY - /* Ask for the codes for Shift+Control+Left/Right/Up/Down. */ - shiftcontrolleft = get_keycode("kLFT6", SHIFT_CONTROL_LEFT); - shiftcontrolright = get_keycode("kRIT6", SHIFT_CONTROL_RIGHT); - shiftcontrolup = get_keycode("kUP6", SHIFT_CONTROL_UP); - shiftcontroldown = get_keycode("kDN6", SHIFT_CONTROL_DOWN); - /* Ask for the codes for Shift+Control+Home/End. */ - shiftcontrolhome = get_keycode("kHOM6", SHIFT_CONTROL_HOME); - shiftcontrolend = get_keycode("kEND6", SHIFT_CONTROL_END); - /* Ask for the codes for Alt+Left/Right/Up/Down. */ - altleft = get_keycode("kLFT3", ALT_LEFT); - altright = get_keycode("kRIT3", ALT_RIGHT); - altup = get_keycode("kUP3", ALT_UP); - altdown = get_keycode("kDN3", ALT_DOWN); - /* Ask for the codes for Shift+Alt+Left/Right/Up/Down. */ - shiftaltleft = get_keycode("kLFT4", SHIFT_ALT_LEFT); - shiftaltright = get_keycode("kRIT4", SHIFT_ALT_RIGHT); - shiftaltup = get_keycode("kUP4", SHIFT_ALT_UP); - shiftaltdown = get_keycode("kDN4", SHIFT_ALT_DOWN); + /* Ask for the codes for Shift+Control+Left/Right/Up/Down. */ + shiftcontrolleft = get_keycode("kLFT6", SHIFT_CONTROL_LEFT); + shiftcontrolright = get_keycode("kRIT6", SHIFT_CONTROL_RIGHT); + shiftcontrolup = get_keycode("kUP6", SHIFT_CONTROL_UP); + shiftcontroldown = get_keycode("kDN6", SHIFT_CONTROL_DOWN); + /* Ask for the codes for Shift+Control+Home/End. */ + shiftcontrolhome = get_keycode("kHOM6", SHIFT_CONTROL_HOME); + shiftcontrolend = get_keycode("kEND6", SHIFT_CONTROL_END); + /* Ask for the codes for Alt+Left/Right/Up/Down. */ + altleft = get_keycode("kLFT3", ALT_LEFT); + altright = get_keycode("kRIT3", ALT_RIGHT); + altup = get_keycode("kUP3", ALT_UP); + altdown = get_keycode("kDN3", ALT_DOWN); + /* Ask for the codes for Shift+Alt+Left/Right/Up/Down. */ + shiftaltleft = get_keycode("kLFT4", SHIFT_ALT_LEFT); + shiftaltright = get_keycode("kRIT4", SHIFT_ALT_RIGHT); + shiftaltup = get_keycode("kUP4", SHIFT_ALT_UP); + shiftaltdown = get_keycode("kDN4", SHIFT_ALT_DOWN); #endif #ifdef HAVE_SET_ESCDELAY - /* Tell ncurses to pass the Esc key quickly. */ - set_escdelay(50); + /* Tell ncurses to pass the Esc key quickly. */ + set_escdelay(50); #endif #ifdef DEBUG - fprintf(stderr, "Main: open file\n"); + fprintf(stderr, "Main: open file\n"); #endif #ifdef ENABLE_MULTIBUFFER - is_multibuffer = ISSET(MULTIBUFFER); - SET(MULTIBUFFER); + is_multibuffer = ISSET(MULTIBUFFER); + SET(MULTIBUFFER); #endif - /* Read the files mentioned on the command line into new buffers. */ - while (optind < argc && (!openfile || ISSET(MULTIBUFFER))) { - ssize_t givenline = 0, givencol = 0; + /* Read the files mentioned on the command line into new buffers. */ + while (optind < argc && (!openfile || ISSET(MULTIBUFFER))) { + ssize_t givenline = 0, givencol = 0; - /* If there's a +LINE[,COLUMN] argument here, eat it up. */ - if (optind < argc - 1 && argv[optind][0] == '+') { - if (!parse_line_column(&argv[optind++][1], &givenline, &givencol)) - statusline(ALERT, _("Invalid line or column number")); - } + /* If there's a +LINE[,COLUMN] argument here, eat it up. */ + if (optind < argc - 1 && argv[optind][0] == '+') { + if (!parse_line_column(&argv[optind++][1], &givenline, &givencol)) + statusline(ALERT, _("Invalid line or column number")); + } - /* If the filename is a dash, read from standard input; otherwise, - * open the file; skip positioning the cursor if either failed. */ - if (strcmp(argv[optind], "-") == 0) { - if (!scoop_stdin()) - continue; - optind++; - } else if (!open_buffer(argv[optind++], FALSE)) - continue; + /* If the filename is a dash, read from standard input; otherwise, + * open the file; skip positioning the cursor if either failed. */ + if (strcmp(argv[optind], "-") == 0) { + if (!scoop_stdin()) + continue; + optind++; + } else if (!open_buffer(argv[optind++], FALSE)) + continue; - /* If a position was given on the command line, go there. */ - if (givenline != 0 || givencol != 0) - do_gotolinecolumn(givenline, givencol, FALSE, FALSE); + /* If a position was given on the command line, go there. */ + if (givenline != 0 || givencol != 0) + do_gotolinecolumn(givenline, givencol, FALSE, FALSE); #ifdef ENABLE_HISTORIES - else if (ISSET(POS_HISTORY) && openfile->filename[0] != '\0') { - ssize_t savedline, savedcol; - /* If edited before, restore the last cursor position. */ - if (has_old_position(argv[optind - 1], &savedline, &savedcol)) - do_gotolinecolumn(savedline, savedcol, FALSE, FALSE); - } + else if (ISSET(POS_HISTORY) && openfile->filename[0] != '\0') { + ssize_t savedline, savedcol; + /* If edited before, restore the last cursor position. */ + if (has_old_position(argv[optind - 1], &savedline, &savedcol)) + do_gotolinecolumn(savedline, savedcol, FALSE, FALSE); + } #endif - } + } - /* If no filenames were given, or all of them were invalid things like - * directories, then open a blank buffer and allow editing. Otherwise, - * switch from the last opened file to the next, that is: the first. */ - if (openfile == NULL) { - open_buffer("", FALSE); - UNSET(VIEW_MODE); - } + /* If no filenames were given, or all of them were invalid things like + * directories, then open a blank buffer and allow editing. Otherwise, + * switch from the last opened file to the next, that is: the first. */ + if (openfile == NULL) { + open_buffer("", FALSE); + UNSET(VIEW_MODE); + } #ifdef ENABLE_MULTIBUFFER - else - openfile = openfile->next; + else + openfile = openfile->next; - if (!is_multibuffer) - UNSET(MULTIBUFFER); + if (!is_multibuffer) + UNSET(MULTIBUFFER); #endif #ifdef DEBUG - fprintf(stderr, "Main: show title bar, and enter main loop\n"); + fprintf(stderr, "Main: show title bar, and enter main loop\n"); #endif - prepare_for_display(); + prepare_for_display(); - if (rcfile_with_errors != NULL) - statusline(ALERT, _("Mistakes in '%s'"), rcfile_with_errors); + if (rcfile_with_errors != NULL) + statusline(ALERT, _("Mistakes in '%s'"), rcfile_with_errors); - while (TRUE) { + while (TRUE) { #ifdef ENABLE_LINENUMBERS - int needed_margin = digits(openfile->filebot->lineno) + 1; + int needed_margin = digits(openfile->filebot->lineno) + 1; - /* Suppress line numbers when there is not enough room for them. */ - if (!ISSET(LINE_NUMBERS) || needed_margin > COLS - 4) - needed_margin = 0; + /* Suppress line numbers when there is not enough room for them. */ + if (!ISSET(LINE_NUMBERS) || needed_margin > COLS - 4) + needed_margin = 0; - if (needed_margin != margin) { - margin = needed_margin; - editwincols = COLS - margin; + if (needed_margin != margin) { + margin = needed_margin; + editwincols = COLS - margin; #ifndef NANO_TINY - /* Ensure that firstcolumn is the starting column of its chunk. */ - ensure_firstcolumn_is_aligned(); + /* Ensure that firstcolumn is the starting column of its chunk. */ + ensure_firstcolumn_is_aligned(); #endif - /* The margin has changed -- schedule a full refresh. */ - refresh_needed = TRUE; + /* The margin has changed -- schedule a full refresh. */ + refresh_needed = TRUE; + } +#endif + + if (currmenu != MMAIN) + display_main_list(); + + lastmessage = HUSH; + as_an_at = TRUE; + + /* Update the displayed current cursor position only when there + * are no keys waiting in the input buffer. */ + if (ISSET(CONSTANT_SHOW) && get_key_buffer_len() == 0) + do_cursorpos(FALSE); + + /* Refresh just the cursor position or the entire edit window. */ + if (!refresh_needed) { + place_the_cursor(); + wnoutrefresh(edit); + } else + edit_refresh(); + + focusing = TRUE; + + /* Forget any earlier statusbar x position. */ + reinit_statusbar_x(); + + /* Read in and interpret keystrokes. */ + do_input(TRUE); } -#endif - if (currmenu != MMAIN) - display_main_list(); - - lastmessage = HUSH; - as_an_at = TRUE; - - /* Update the displayed current cursor position only when there - * are no keys waiting in the input buffer. */ - if (ISSET(CONSTANT_SHOW) && get_key_buffer_len() == 0) - do_cursorpos(FALSE); - - /* Refresh just the cursor position or the entire edit window. */ - if (!refresh_needed) { - place_the_cursor(); - wnoutrefresh(edit); - } else - edit_refresh(); - - focusing = TRUE; - - /* Forget any earlier statusbar x position. */ - reinit_statusbar_x(); - - /* Read in and interpret keystrokes. */ - do_input(TRUE); - } - - /* We should never get here. */ - assert(FALSE); + /* We should never get here. */ + assert(FALSE); } diff --git a/src/nano.h b/src/nano.h index 62867b26..9f3f4c39 100644 --- a/src/nano.h +++ b/src/nano.h @@ -111,7 +111,7 @@ #endif #define gettext_noop(string) (string) #define N_(string) gettext_noop(string) - /* Mark a string that will be sent to gettext() later. */ + /* Mark a string that will be sent to gettext() later. */ #include #include @@ -144,393 +144,393 @@ /* Enumeration types. */ typedef enum { - NIX_FILE, DOS_FILE, MAC_FILE + NIX_FILE, DOS_FILE, MAC_FILE } file_format; typedef enum { - HUSH, MILD, ALERT + HUSH, MILD, ALERT } message_type; typedef enum { - OVERWRITE, APPEND, PREPEND + OVERWRITE, APPEND, PREPEND } kind_of_writing_type; typedef enum { - SOFTMARK, HARDMARK + SOFTMARK, HARDMARK } mark_type; typedef enum { - CENTERING, FLOWING, STATIONARY + CENTERING, FLOWING, STATIONARY } update_type; typedef enum { - ADD, DEL, BACK, CUT, CUT_TO_EOF, REPLACE, + ADD, DEL, BACK, CUT, CUT_TO_EOF, REPLACE, #ifdef ENABLE_WRAPPING - SPLIT_BEGIN, SPLIT_END, + SPLIT_BEGIN, SPLIT_END, #endif - INDENT, UNINDENT, + INDENT, UNINDENT, #ifdef ENABLE_COMMENT - COMMENT, UNCOMMENT, PREFLIGHT, + COMMENT, UNCOMMENT, PREFLIGHT, #endif - JOIN, PASTE, INSERT, ENTER, OTHER + JOIN, PASTE, INSERT, ENTER, OTHER } undo_type; /* Structure types. */ #ifdef ENABLE_COLOR typedef struct colortype { - short fg; - /* This syntax's foreground color. */ - short bg; - /* This syntax's background color. */ - bool bright; - /* Is this color A_BOLD? */ - int pairnum; - /* The color pair number used for this foreground color and - * background color. */ - int attributes; - /* Pair number and brightness composed into ready-to-use attributes. */ - int rex_flags; - /* The regex compilation flags (with or without REG_ICASE). */ - char *start_regex; - /* The start (or all) of the regex string. */ - regex_t *start; - /* The compiled start (or all) of the regex string. */ - char *end_regex; - /* The end (if any) of the regex string. */ - regex_t *end; - /* 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. */ + short fg; + /* This syntax's foreground color. */ + short bg; + /* This syntax's background color. */ + bool bright; + /* Is this color A_BOLD? */ + int pairnum; + /* The color pair number used for this foreground color and + * background color. */ + int attributes; + /* Pair number and brightness composed into ready-to-use attributes. */ + int rex_flags; + /* The regex compilation flags (with or without REG_ICASE). */ + char *start_regex; + /* The start (or all) of the regex string. */ + regex_t *start; + /* The compiled start (or all) of the regex string. */ + char *end_regex; + /* The end (if any) of the regex string. */ + regex_t *end; + /* 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. */ } colortype; typedef struct regexlisttype { - char *full_regex; - /* A regex string to match things that imply a certain syntax. */ - struct regexlisttype *next; - /* The next regex. */ + char *full_regex; + /* A regex string to match things that imply a certain syntax. */ + struct regexlisttype *next; + /* The next regex. */ } regexlisttype; typedef struct syntaxtype { - char *name; - /* The name of this syntax. */ - regexlisttype *extensions; - /* The list of extensions that this syntax applies to. */ - regexlisttype *headers; - /* The list of headerlines that this syntax applies to. */ - regexlisttype *magics; - /* The list of libmagic results that this syntax applies to. */ - char *linter; - /* The command with which to lint this type of file. */ - char *formatter; - /* The formatting command (for programming languages mainly). */ + char *name; + /* The name of this syntax. */ + regexlisttype *extensions; + /* The list of extensions that this syntax applies to. */ + regexlisttype *headers; + /* The list of headerlines that this syntax applies to. */ + regexlisttype *magics; + /* The list of libmagic results that this syntax applies to. */ + char *linter; + /* The command with which to lint this type of file. */ + char *formatter; + /* The formatting command (for programming languages mainly). */ #ifdef ENABLE_COMMENT - char *comment; - /* The line comment prefix (and postfix) for this type of file. */ + char *comment; + /* The line comment prefix (and postfix) for this type of file. */ #endif - colortype *color; - /* The colors and their regexes used in this syntax. */ - int nmultis; - /* How many multiline regex strings this syntax has. */ - struct syntaxtype *next; - /* Next syntax. */ + colortype *color; + /* The colors and their regexes used in this syntax. */ + int nmultis; + /* How many multiline regex strings this syntax has. */ + struct syntaxtype *next; + /* Next syntax. */ } syntaxtype; 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. */ + 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; /* Flags that indicate how a multiline regex applies to a line. */ #define CNONE (1<<1) - /* Yay, regex doesn't apply to this line at all! */ + /* Yay, regex doesn't apply to this line at all! */ #define CBEGINBEFORE (1<<2) - /* Regex starts on an earlier line, ends on this one. */ + /* 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. */ + /* 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. */ + /* Whole line engulfed by the regex, start < me, end > me. */ #define CSTARTENDHERE (1<<5) - /* Regex starts and ends within this line. */ + /* Regex starts and ends within this line. */ #define CWOULDBE (1<<6) - /* An unpaired start match on or before this line. */ + /* An unpaired start match on or before this line. */ #endif /* ENABLE_COLOR */ /* More structure types. */ typedef struct filestruct { - char *data; - /* The text of this line. */ - ssize_t lineno; - /* The number of this line. */ - struct filestruct *next; - /* Next node. */ - struct filestruct *prev; - /* Previous node. */ + char *data; + /* The text of this line. */ + ssize_t lineno; + /* The number of this line. */ + struct filestruct *next; + /* Next node. */ + struct filestruct *prev; + /* Previous node. */ #ifdef ENABLE_COLOR - short *multidata; - /* Array of which multi-line regexes apply to this line. */ + short *multidata; + /* Array of which multi-line regexes apply to this line. */ #endif } filestruct; typedef struct partition { - filestruct *fileage; - /* The top line of this portion of the file. */ - filestruct *top_prev; - /* The line before the top line of this portion of the file. */ - char *top_data; - /* The text before the beginning of the top line of this portion - * of the file. */ - filestruct *filebot; - /* The bottom line of this portion of the file. */ - filestruct *bot_next; - /* The line after the bottom line of this portion of the - * file. */ - char *bot_data; - /* The text after the end of the bottom line of this portion of - * the file. */ + filestruct *fileage; + /* The top line of this portion of the file. */ + filestruct *top_prev; + /* The line before the top line of this portion of the file. */ + char *top_data; + /* The text before the beginning of the top line of this portion + * of the file. */ + filestruct *filebot; + /* The bottom line of this portion of the file. */ + filestruct *bot_next; + /* The line after the bottom line of this portion of the + * file. */ + char *bot_data; + /* The text after the end of the bottom line of this portion of + * the file. */ } partition; #ifndef NANO_TINY typedef struct undo_group { - ssize_t top_line; - /* First line of group. */ - ssize_t bottom_line; - /* Last line of group. */ - char **indentations; - /* String data used to restore the affected lines; one per line. */ - struct undo_group *next; + ssize_t top_line; + /* First line of group. */ + ssize_t bottom_line; + /* Last line of group. */ + char **indentations; + /* String data used to restore the affected lines; one per line. */ + struct undo_group *next; } undo_group; typedef struct undo { - ssize_t lineno; - undo_type type; - /* 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 copying the affected line back. */ - size_t wassize; - /* The file size before the action. */ - size_t newsize; - /* The file size after the action. */ - int xflags; - /* Some flag data we need. */ - undo_group *grouping; - /* Undo info specific to groups of lines. */ + ssize_t lineno; + undo_type type; + /* 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 copying the affected line back. */ + size_t wassize; + /* The file size before the action. */ + size_t newsize; + /* The file size after the action. */ + int xflags; + /* Some flag data we need. */ + undo_group *grouping; + /* Undo info specific to groups of lines. */ - /* Cut-specific stuff we need. */ - filestruct *cutbuffer; - /* Copy of the cutbuffer. */ - filestruct *cutbottom; - /* Copy of cutbottom. */ - ssize_t mark_begin_lineno; - /* Mostly the line number of the current line; sometimes something else. */ - size_t mark_begin_x; - /* The x position corresponding to the above line number. */ - struct undo *next; - /* A pointer to the undo item of the preceding action. */ + /* Cut-specific stuff we need. */ + filestruct *cutbuffer; + /* Copy of the cutbuffer. */ + filestruct *cutbottom; + /* Copy of cutbottom. */ + ssize_t mark_begin_lineno; + /* Mostly the line number of the current line; sometimes something else. */ + size_t mark_begin_x; + /* The x position corresponding to the above line number. */ + struct undo *next; + /* A pointer to the undo item of the preceding action. */ } undo; #endif /* !NANO_TINY */ #ifdef ENABLE_HISTORIES typedef struct poshiststruct { - char *filename; - /* The file. */ - ssize_t lineno; - /* Line number we left off on. */ - ssize_t xno; - /* x position in the file we left off on. */ - struct poshiststruct *next; + char *filename; + /* The file. */ + ssize_t lineno; + /* Line number we left off on. */ + ssize_t xno; + /* x position in the file we left off on. */ + struct poshiststruct *next; } poshiststruct; #endif typedef struct openfilestruct { - char *filename; - /* The file's name. */ - filestruct *fileage; - /* The file's first line. */ - filestruct *filebot; - /* The file's last line. */ - filestruct *edittop; - /* The current top of the edit window for this file. */ - filestruct *current; - /* The current line for this file. */ - size_t totsize; - /* The file's total number of characters. */ - size_t firstcolumn; - /* The starting column of the top line of the edit window. - * When not in softwrap mode, it's always zero. */ - size_t current_x; - /* The file's x-coordinate position. */ - size_t placewewant; - /* The file's x position we would like. */ - ssize_t current_y; - /* The file's y-coordinate position. */ - bool modified; - /* Whether the file has been modified. */ - struct stat *current_stat; - /* The file's current stat information. */ + char *filename; + /* The file's name. */ + filestruct *fileage; + /* The file's first line. */ + filestruct *filebot; + /* The file's last line. */ + filestruct *edittop; + /* The current top of the edit window for this file. */ + filestruct *current; + /* The current line for this file. */ + size_t totsize; + /* The file's total number of characters. */ + size_t firstcolumn; + /* The starting column of the top line of the edit window. + * When not in softwrap mode, it's always zero. */ + size_t current_x; + /* The file's x-coordinate position. */ + size_t placewewant; + /* The file's x position we would like. */ + ssize_t current_y; + /* The file's y-coordinate position. */ + bool modified; + /* Whether the file has been modified. */ + struct stat *current_stat; + /* The file's current stat information. */ #ifndef NANO_TINY - filestruct *mark; - /* The line in the file where the mark is set; NULL if not set. */ - size_t mark_x; - /* The mark's x position in the above line. */ - mark_type kind_of_mark; - /* Whether it is a soft (with Shift) or a hard mark. */ - file_format fmt; - /* The file's format -- Unix or DOS or Mac or mixed. */ - undo *undotop; - /* The top of the undo list. */ - undo *current_undo; - /* The current (i.e. next) level of undo. */ - undo *last_saved; - /* The undo item at which the file was last saved. */ - undo_type last_action; - /* The type of the last action the user performed. */ - char *lock_filename; - /* The path of the lockfile, if we created one. */ + filestruct *mark; + /* The line in the file where the mark is set; NULL if not set. */ + size_t mark_x; + /* The mark's x position in the above line. */ + mark_type kind_of_mark; + /* Whether it is a soft (with Shift) or a hard mark. */ + file_format fmt; + /* The file's format -- Unix or DOS or Mac or mixed. */ + undo *undotop; + /* The top of the undo list. */ + undo *current_undo; + /* The current (i.e. next) level of undo. */ + undo *last_saved; + /* The undo item at which the file was last saved. */ + undo_type last_action; + /* The type of the last action the user performed. */ + char *lock_filename; + /* The path of the lockfile, if we created one. */ #endif #ifdef ENABLE_COLOR - syntaxtype *syntax; - /* The syntax struct for this file, if any. */ - colortype *colorstrings; - /* The file's associated colors. */ + syntaxtype *syntax; + /* The syntax struct for this file, if any. */ + colortype *colorstrings; + /* The file's associated colors. */ #endif - struct openfilestruct *next; - /* The next open file, if any. */ - struct openfilestruct *prev; - /* The preceding open file, if any. */ + struct openfilestruct *next; + /* The next open file, if any. */ + struct openfilestruct *prev; + /* The preceding open file, if any. */ } openfilestruct; #ifdef ENABLE_NANORC typedef struct rcoption { - const char *name; - /* The name of the rcfile option. */ - long flag; - /* The flag associated with it, if any. */ + const char *name; + /* The name of the rcfile option. */ + long flag; + /* The flag associated with it, if any. */ } rcoption; #endif typedef struct sc { - const char *keystr; - /* The string that describes a keystroke, like "^C" or "M-R". */ - bool meta; - /* Whether this is a Meta keystroke. */ - int keycode; - /* The integer that, together with meta, identifies the keystroke. */ - int menus; - /* Which menus this applies to. */ - void (*scfunc)(void); - /* The function we're going to run. */ + const char *keystr; + /* The string that describes a keystroke, like "^C" or "M-R". */ + bool meta; + /* Whether this is a Meta keystroke. */ + int keycode; + /* The integer that, together with meta, identifies the keystroke. */ + int menus; + /* Which menus this applies to. */ + void (*scfunc)(void); + /* The function we're going to run. */ #ifndef NANO_TINY - int toggle; - /* If a toggle, what we're toggling. */ - int ordinal; - /* The how-manieth toggle this is, in order to be able to - * keep them in sequence. */ + int toggle; + /* If a toggle, what we're toggling. */ + int ordinal; + /* The how-manieth toggle this is, in order to be able to + * keep them in sequence. */ #endif - struct sc *next; - /* Next in the list. */ + struct sc *next; + /* Next in the list. */ } sc; typedef struct subnfunc { - void (*scfunc)(void); - /* The actual function to call. */ - int menus; - /* In what menus this function applies. */ - const char *desc; - /* The function's short description, for example "Where Is". */ + void (*scfunc)(void); + /* The actual function to call. */ + int menus; + /* In what menus this function applies. */ + const char *desc; + /* The function's short description, for example "Where Is". */ #ifdef ENABLE_HELP - const char *help; - /* The help-screen text for this function. */ - bool blank_after; - /* Whether there should be a blank line after the help text - * for this function. */ + const char *help; + /* The help-screen text for this function. */ + bool blank_after; + /* Whether there should be a blank line after the help text + * for this function. */ #endif - bool viewok; - /* Is this function allowed when in view mode? */ - long toggle; - /* If this is a toggle, which toggle to affect. */ - struct subnfunc *next; - /* Next item in the list. */ + bool viewok; + /* Is this function allowed when in view mode? */ + long toggle; + /* If this is a toggle, which toggle to affect. */ + struct subnfunc *next; + /* Next item in the list. */ } subnfunc; #ifdef ENABLE_WORDCOMPLETION typedef struct completion_word { - char *word; - struct completion_word *next; + char *word; + struct completion_word *next; } completion_word; #endif /* The elements of the interface that can be colored differently. */ enum { - TITLE_BAR = 0, - LINE_NUMBER, - SELECTED_TEXT, - STATUS_BAR, - KEY_COMBO, - FUNCTION_TAG, - NUMBER_OF_ELEMENTS + TITLE_BAR = 0, + LINE_NUMBER, + SELECTED_TEXT, + STATUS_BAR, + KEY_COMBO, + FUNCTION_TAG, + NUMBER_OF_ELEMENTS }; /* Enumeration used in the flags array. See the definition of FLAGMASK. */ enum { - DONTUSE, - CASE_SENSITIVE, - CONSTANT_SHOW, - NO_HELP, - SUSPEND, - NO_WRAP, - AUTOINDENT, - VIEW_MODE, - USE_MOUSE, - USE_REGEXP, - TEMP_FILE, - CUT_FROM_CURSOR, - BACKWARDS_SEARCH, - MULTIBUFFER, - SMOOTH_SCROLL, - REBIND_DELETE, - REBIND_KEYPAD, - NO_CONVERT, - BACKUP_FILE, - INSECURE_BACKUP, - NO_COLOR_SYNTAX, - PRESERVE, - HISTORYLOG, - RESTRICTED, - SMART_HOME, - WHITESPACE_DISPLAY, - MORE_SPACE, - TABS_TO_SPACES, - QUICK_BLANK, - WORD_BOUNDS, - NO_NEWLINES, - BOLD_TEXT, - QUIET, - SOFTWRAP, - POS_HISTORY, - LOCKING, - NOREAD_MODE, - MAKE_IT_UNIX, - TRIM_BLANKS, - SHOW_CURSOR, - LINE_NUMBERS, - NO_PAUSES, - AT_BLANKS + DONTUSE, + CASE_SENSITIVE, + CONSTANT_SHOW, + NO_HELP, + SUSPEND, + NO_WRAP, + AUTOINDENT, + VIEW_MODE, + USE_MOUSE, + USE_REGEXP, + TEMP_FILE, + CUT_FROM_CURSOR, + BACKWARDS_SEARCH, + MULTIBUFFER, + SMOOTH_SCROLL, + REBIND_DELETE, + REBIND_KEYPAD, + NO_CONVERT, + BACKUP_FILE, + INSECURE_BACKUP, + NO_COLOR_SYNTAX, + PRESERVE, + HISTORYLOG, + RESTRICTED, + SMART_HOME, + WHITESPACE_DISPLAY, + MORE_SPACE, + TABS_TO_SPACES, + QUICK_BLANK, + WORD_BOUNDS, + NO_NEWLINES, + BOLD_TEXT, + QUIET, + SOFTWRAP, + POS_HISTORY, + LOCKING, + NOREAD_MODE, + MAKE_IT_UNIX, + TRIM_BLANKS, + SHOW_CURSOR, + LINE_NUMBERS, + NO_PAUSES, + AT_BLANKS }; /* Flags for the menus in which a given function should be present. */ @@ -552,7 +552,7 @@ enum #define MFINDINHELP (1<<15) /* This is an abbreviation for all menus except Help and YesNo. */ #define MMOST (MMAIN|MWHEREIS|MREPLACE|MREPLACEWITH|MGOTOLINE|MWRITEFILE|MINSERTFILE|\ - MEXTCMD|MBROWSER|MWHEREISFILE|MGOTODIR|MFINDINHELP|MSPELL|MLINTER) + MEXTCMD|MBROWSER|MWHEREISFILE|MGOTODIR|MFINDINHELP|MSPELL|MLINTER) #ifndef NANO_TINY #define MSOME MMOST #else diff --git a/src/prompt.c b/src/prompt.c index 4223bf73..e5a3dc5e 100644 --- a/src/prompt.c +++ b/src/prompt.c @@ -24,9 +24,9 @@ #include static char *prompt = NULL; - /* The prompt string used for statusbar questions. */ + /* The prompt string used for statusbar questions. */ static size_t statusbar_x = HIGHEST_POSITIVE; - /* The cursor position in answer. */ + /* The cursor position in answer. */ /* Read in a keystroke, interpret it if it is a shortcut or toggle, and * return it. Set ran_func to TRUE if we ran a function associated with @@ -34,351 +34,351 @@ static size_t statusbar_x = HIGHEST_POSITIVE; * or trying to run a function associated with a shortcut key. */ int do_statusbar_input(bool *ran_func, bool *finished) { - int input; - /* The character we read in. */ - static int *kbinput = NULL; - /* The input buffer. */ - static size_t kbinput_len = 0; - /* The length of the input buffer. */ - const sc *s; - bool have_shortcut = FALSE; - const subnfunc *f; + int input; + /* The character we read in. */ + static int *kbinput = NULL; + /* The input buffer. */ + static size_t kbinput_len = 0; + /* The length of the input buffer. */ + const sc *s; + bool have_shortcut = FALSE; + const subnfunc *f; - *ran_func = FALSE; - *finished = FALSE; + *ran_func = FALSE; + *finished = FALSE; - /* Read in a character. */ - input = get_kbinput(bottomwin, VISIBLE); + /* Read in a character. */ + input = get_kbinput(bottomwin, VISIBLE); #ifndef NANO_TINY - if (input == KEY_WINCH) - return KEY_WINCH; + if (input == KEY_WINCH) + return KEY_WINCH; #endif #ifdef ENABLE_MOUSE - /* If we got a mouse click and it was on a shortcut, read in the - * shortcut character. */ - if (input == KEY_MOUSE) { - if (do_statusbar_mouse() == 1) - input = get_kbinput(bottomwin, BLIND); - else - return ERR; - } + /* If we got a mouse click and it was on a shortcut, read in the + * shortcut character. */ + if (input == KEY_MOUSE) { + if (do_statusbar_mouse() == 1) + input = get_kbinput(bottomwin, BLIND); + else + return ERR; + } #endif - /* Check for a shortcut in the current list. */ - s = get_shortcut(&input); + /* Check for a shortcut in the current list. */ + s = get_shortcut(&input); - /* If we got a shortcut from the current list, or a "universal" - * statusbar prompt shortcut, set have_shortcut to TRUE. */ - have_shortcut = (s != NULL); + /* If we got a shortcut from the current list, or a "universal" + * statusbar prompt shortcut, set have_shortcut to TRUE. */ + have_shortcut = (s != NULL); - /* If we got a non-high-bit control key, a meta key sequence, or a - * function key, and it's not a shortcut or toggle, throw it out. */ - if (!have_shortcut) { - if (is_ascii_cntrl_char(input) || meta_key || !is_byte(input)) { - beep(); - input = ERR; + /* If we got a non-high-bit control key, a meta key sequence, or a + * function key, and it's not a shortcut or toggle, throw it out. */ + if (!have_shortcut) { + if (is_ascii_cntrl_char(input) || meta_key || !is_byte(input)) { + beep(); + input = ERR; + } } - } - /* If the keystroke isn't a shortcut nor a toggle, it's a normal text - * character: add the it to the input buffer, when allowed. */ - if (input != ERR && !have_shortcut) { - /* Only accept input when not in restricted mode, or when not at - * the "Write File" prompt, or when there is no filename yet. */ - if (!ISSET(RESTRICTED) || currmenu != MWRITEFILE || - openfile->filename[0] == '\0') { - kbinput_len++; - kbinput = (int *)nrealloc(kbinput, kbinput_len * sizeof(int)); - kbinput[kbinput_len - 1] = input; + /* If the keystroke isn't a shortcut nor a toggle, it's a normal text + * character: add the it to the input buffer, when allowed. */ + if (input != ERR && !have_shortcut) { + /* Only accept input when not in restricted mode, or when not at + * the "Write File" prompt, or when there is no filename yet. */ + if (!ISSET(RESTRICTED) || currmenu != MWRITEFILE || + openfile->filename[0] == '\0') { + kbinput_len++; + kbinput = (int *)nrealloc(kbinput, kbinput_len * sizeof(int)); + kbinput[kbinput_len - 1] = input; + } } - } - /* If we got a shortcut, or if there aren't any other keystrokes waiting - * after the one we read in, we need to insert all the characters in the - * input buffer (if not empty) into the answer. */ - if ((have_shortcut || get_key_buffer_len() == 0) && kbinput != NULL) { - /* Inject all characters in the input buffer at once, filtering out - * control characters. */ - do_statusbar_output(kbinput, kbinput_len, TRUE); + /* If we got a shortcut, or if there aren't any other keystrokes waiting + * after the one we read in, we need to insert all the characters in the + * input buffer (if not empty) into the answer. */ + if ((have_shortcut || get_key_buffer_len() == 0) && kbinput != NULL) { + /* Inject all characters in the input buffer at once, filtering out + * control characters. */ + do_statusbar_output(kbinput, kbinput_len, TRUE); - /* Empty the input buffer. */ - kbinput_len = 0; - free(kbinput); - kbinput = NULL; - } + /* Empty the input buffer. */ + kbinput_len = 0; + free(kbinput); + kbinput = NULL; + } - if (have_shortcut) { - if (s->scfunc == do_tab || s->scfunc == do_enter) - ; - else if (s->scfunc == do_left) - do_statusbar_left(); - else if (s->scfunc == do_right) - do_statusbar_right(); + if (have_shortcut) { + if (s->scfunc == do_tab || s->scfunc == do_enter) + ; + else if (s->scfunc == do_left) + do_statusbar_left(); + else if (s->scfunc == do_right) + do_statusbar_right(); #ifndef NANO_TINY - else if (s->scfunc == do_prev_word_void) - do_statusbar_prev_word(); - else if (s->scfunc == do_next_word_void) - do_statusbar_next_word(); + else if (s->scfunc == do_prev_word_void) + do_statusbar_prev_word(); + else if (s->scfunc == do_next_word_void) + do_statusbar_next_word(); #endif - else if (s->scfunc == do_home) - do_statusbar_home(); - else if (s->scfunc == do_end) - do_statusbar_end(); - /* When in restricted mode at the "Write File" prompt and the - * filename isn't blank, disallow any input and deletion. */ - else if (ISSET(RESTRICTED) && currmenu == MWRITEFILE && - openfile->filename[0] != '\0' && - (s->scfunc == do_verbatim_input || - s->scfunc == do_cut_text_void || - s->scfunc == do_delete || - s->scfunc == do_backspace)) - ; - else if (s->scfunc == do_verbatim_input) - do_statusbar_verbatim_input(); - else if (s->scfunc == do_cut_text_void) - do_statusbar_cut_text(); - else if (s->scfunc == do_delete) - do_statusbar_delete(); - else if (s->scfunc == do_backspace) - do_statusbar_backspace(); - else if (s->scfunc == do_uncut_text) { - if (cutbuffer != NULL) - do_statusbar_uncut_text(); - } else { - /* Handle any other shortcut in the current menu, setting - * ran_func to TRUE if we try to run their associated functions, - * and setting finished to TRUE to indicatethat we're done after - * running or trying to run their associated functions. */ - f = sctofunc(s); - if (s->scfunc != NULL) { - *ran_func = TRUE; - if (f && (!ISSET(VIEW_MODE) || f->viewok) && - f->scfunc != do_gotolinecolumn_void) - f->scfunc(); - } - *finished = TRUE; + else if (s->scfunc == do_home) + do_statusbar_home(); + else if (s->scfunc == do_end) + do_statusbar_end(); + /* When in restricted mode at the "Write File" prompt and the + * filename isn't blank, disallow any input and deletion. */ + else if (ISSET(RESTRICTED) && currmenu == MWRITEFILE && + openfile->filename[0] != '\0' && + (s->scfunc == do_verbatim_input || + s->scfunc == do_cut_text_void || + s->scfunc == do_delete || + s->scfunc == do_backspace)) + ; + else if (s->scfunc == do_verbatim_input) + do_statusbar_verbatim_input(); + else if (s->scfunc == do_cut_text_void) + do_statusbar_cut_text(); + else if (s->scfunc == do_delete) + do_statusbar_delete(); + else if (s->scfunc == do_backspace) + do_statusbar_backspace(); + else if (s->scfunc == do_uncut_text) { + if (cutbuffer != NULL) + do_statusbar_uncut_text(); + } else { + /* Handle any other shortcut in the current menu, setting + * ran_func to TRUE if we try to run their associated functions, + * and setting finished to TRUE to indicatethat we're done after + * running or trying to run their associated functions. */ + f = sctofunc(s); + if (s->scfunc != NULL) { + *ran_func = TRUE; + if (f && (!ISSET(VIEW_MODE) || f->viewok) && + f->scfunc != do_gotolinecolumn_void) + f->scfunc(); + } + *finished = TRUE; + } } - } - return input; + return input; } #ifdef ENABLE_MOUSE /* Handle a mouse click on the statusbar prompt or the shortcut list. */ int do_statusbar_mouse(void) { - int mouse_x, mouse_y; - int retval = get_mouseinput(&mouse_x, &mouse_y, TRUE); + int mouse_x, mouse_y; + int retval = get_mouseinput(&mouse_x, &mouse_y, TRUE); - /* We can click on the statusbar window text to move the cursor. */ - if (retval == 0 && wmouse_trafo(bottomwin, &mouse_y, &mouse_x, FALSE)) { - size_t start_col; + /* We can click on the statusbar window text to move the cursor. */ + if (retval == 0 && wmouse_trafo(bottomwin, &mouse_y, &mouse_x, FALSE)) { + size_t start_col; - start_col = strlenpt(prompt) + 2; + start_col = strlenpt(prompt) + 2; - /* Move to where the click occurred. */ - if (mouse_x >= start_col && mouse_y == 0) { - statusbar_x = actual_x(answer, - get_statusbar_page_start(start_col, start_col + - statusbar_xplustabs()) + mouse_x - start_col); - update_the_statusbar(); + /* Move to where the click occurred. */ + if (mouse_x >= start_col && mouse_y == 0) { + statusbar_x = actual_x(answer, + get_statusbar_page_start(start_col, start_col + + statusbar_xplustabs()) + mouse_x - start_col); + update_the_statusbar(); + } } - } - return retval; + return retval; } #endif /* The user typed input_len multibyte characters. Add them to the answer, * filtering out ASCII control characters if filtering is TRUE. */ void do_statusbar_output(int *the_input, size_t input_len, - bool filtering) + bool filtering) { - char *output = charalloc(input_len + 1); - char onechar[MAXCHARLEN]; - int i, char_len; + char *output = charalloc(input_len + 1); + char onechar[MAXCHARLEN]; + int i, char_len; - /* Copy the typed stuff so it can be treated. */ - for (i = 0; i < input_len; i++) - output[i] = (char)the_input[i]; - output[i] = '\0'; + /* Copy the typed stuff so it can be treated. */ + for (i = 0; i < input_len; i++) + output[i] = (char)the_input[i]; + output[i] = '\0'; - i = 0; + i = 0; - while (i < input_len) { - /* Encode any NUL byte as 0x0A. */ - if (output[i] == '\0') - output[i] = '\n'; + while (i < input_len) { + /* Encode any NUL byte as 0x0A. */ + if (output[i] == '\0') + output[i] = '\n'; - /* Interpret the next multibyte character. */ - char_len = parse_mbchar(output + i, onechar, NULL); + /* Interpret the next multibyte character. */ + char_len = parse_mbchar(output + i, onechar, NULL); - i += char_len; + i += char_len; - /* When filtering, skip any ASCII control character. */ - if (filtering && is_ascii_cntrl_char(*(output + i - char_len))) - continue; + /* When filtering, skip any ASCII control character. */ + if (filtering && is_ascii_cntrl_char(*(output + i - char_len))) + continue; - /* Insert the typed character into the existing answer string. */ - answer = charealloc(answer, strlen(answer) + char_len + 1); - charmove(answer + statusbar_x + char_len, answer + statusbar_x, - strlen(answer) - statusbar_x + 1); - strncpy(answer + statusbar_x, onechar, char_len); + /* Insert the typed character into the existing answer string. */ + answer = charealloc(answer, strlen(answer) + char_len + 1); + charmove(answer + statusbar_x + char_len, answer + statusbar_x, + strlen(answer) - statusbar_x + 1); + strncpy(answer + statusbar_x, onechar, char_len); - statusbar_x += char_len; - } + statusbar_x += char_len; + } - free(output); + free(output); - update_the_statusbar(); + update_the_statusbar(); } /* Move to the beginning of the answer. */ void do_statusbar_home(void) { - statusbar_x = 0; - update_the_statusbar(); + statusbar_x = 0; + update_the_statusbar(); } /* Move to the end of the answer. */ void do_statusbar_end(void) { - statusbar_x = strlen(answer); - update_the_statusbar(); + statusbar_x = strlen(answer); + update_the_statusbar(); } /* Move left one character. */ void do_statusbar_left(void) { - if (statusbar_x > 0) { - statusbar_x = move_mbleft(answer, statusbar_x); - update_the_statusbar(); - } + if (statusbar_x > 0) { + statusbar_x = move_mbleft(answer, statusbar_x); + update_the_statusbar(); + } } /* Move right one character. */ void do_statusbar_right(void) { - if (answer[statusbar_x] != '\0') { - statusbar_x = move_mbright(answer, statusbar_x); - update_the_statusbar(); - } + if (answer[statusbar_x] != '\0') { + statusbar_x = move_mbright(answer, statusbar_x); + update_the_statusbar(); + } } /* Backspace over one character. */ void do_statusbar_backspace(void) { - if (statusbar_x > 0) { - statusbar_x = move_mbleft(answer, statusbar_x); - do_statusbar_delete(); - } + if (statusbar_x > 0) { + statusbar_x = move_mbleft(answer, statusbar_x); + do_statusbar_delete(); + } } /* Delete one character. */ void do_statusbar_delete(void) { - if (answer[statusbar_x] != '\0') { - int char_len = parse_mbchar(answer + statusbar_x, NULL, NULL); + if (answer[statusbar_x] != '\0') { + int char_len = parse_mbchar(answer + statusbar_x, NULL, NULL); - charmove(answer + statusbar_x, answer + statusbar_x + char_len, - strlen(answer) - statusbar_x - char_len + 1); + charmove(answer + statusbar_x, answer + statusbar_x + char_len, + strlen(answer) - statusbar_x - char_len + 1); - update_the_statusbar(); - } + update_the_statusbar(); + } } /* Zap some or all text from the answer. */ void do_statusbar_cut_text(void) { - if (!ISSET(CUT_FROM_CURSOR)) - statusbar_x = 0; + if (!ISSET(CUT_FROM_CURSOR)) + statusbar_x = 0; - answer[statusbar_x] = '\0'; + answer[statusbar_x] = '\0'; - update_the_statusbar(); + update_the_statusbar(); } #ifndef NANO_TINY /* Move to the next word in the answer. */ void do_statusbar_next_word(void) { - bool seen_space = !is_word_mbchar(answer + statusbar_x, FALSE); + bool seen_space = !is_word_mbchar(answer + statusbar_x, FALSE); - /* Move forward until we reach the start of a word. */ - while (answer[statusbar_x] != '\0') { - statusbar_x = move_mbright(answer, statusbar_x); + /* Move forward until we reach the start of a word. */ + while (answer[statusbar_x] != '\0') { + statusbar_x = move_mbright(answer, statusbar_x); - /* If this is not a word character, then it's a separator; else - * if we've already seen a separator, then it's a word start. */ - if (!is_word_mbchar(answer + statusbar_x, FALSE)) - seen_space = TRUE; - else if (seen_space) - break; - } + /* If this is not a word character, then it's a separator; else + * if we've already seen a separator, then it's a word start. */ + if (!is_word_mbchar(answer + statusbar_x, FALSE)) + seen_space = TRUE; + else if (seen_space) + break; + } - update_the_statusbar(); + update_the_statusbar(); } /* Move to the previous word in the answer. */ void do_statusbar_prev_word(void) { - bool seen_a_word = FALSE, step_forward = FALSE; + bool seen_a_word = FALSE, step_forward = FALSE; - /* Move backward until we pass over the start of a word. */ - while (statusbar_x != 0) { - statusbar_x = move_mbleft(answer, statusbar_x); + /* Move backward until we pass over the start of a word. */ + while (statusbar_x != 0) { + statusbar_x = move_mbleft(answer, statusbar_x); - if (is_word_mbchar(answer + statusbar_x, FALSE)) - seen_a_word = TRUE; - else if (seen_a_word) { - /* This is space now: we've overshot the start of the word. */ - step_forward = TRUE; - break; + if (is_word_mbchar(answer + statusbar_x, FALSE)) + seen_a_word = TRUE; + else if (seen_a_word) { + /* This is space now: we've overshot the start of the word. */ + step_forward = TRUE; + break; + } } - } - if (step_forward) - /* Move one character forward again to sit on the start of the word. */ - statusbar_x = move_mbright(answer, statusbar_x); + if (step_forward) + /* Move one character forward again to sit on the start of the word. */ + statusbar_x = move_mbright(answer, statusbar_x); - update_the_statusbar(); + update_the_statusbar(); } #endif /* !NANO_TINY */ /* Get verbatim input and inject it into the answer, without filtering. */ void do_statusbar_verbatim_input(void) { - int *kbinput; - size_t kbinput_len; + int *kbinput; + size_t kbinput_len; - kbinput = get_verbatim_kbinput(bottomwin, &kbinput_len); + kbinput = get_verbatim_kbinput(bottomwin, &kbinput_len); - do_statusbar_output(kbinput, kbinput_len, FALSE); + do_statusbar_output(kbinput, kbinput_len, FALSE); } /* Return the zero-based column position of the cursor in the answer. */ size_t statusbar_xplustabs(void) { - return strnlenpt(answer, statusbar_x); + return strnlenpt(answer, statusbar_x); } /* Paste the first line of the cutbuffer into the current answer. */ void do_statusbar_uncut_text(void) { - size_t pastelen = strlen(cutbuffer->data); - char *fusion = charalloc(strlen(answer) + pastelen + 1); + size_t pastelen = strlen(cutbuffer->data); + char *fusion = charalloc(strlen(answer) + pastelen + 1); - /* Concatenate: the current answer before the cursor, the first line - * of the cutbuffer, plus the rest of the current answer. */ - strncpy(fusion, answer, statusbar_x); - strncpy(fusion + statusbar_x, cutbuffer->data, pastelen); - strcpy(fusion + statusbar_x + pastelen, answer + statusbar_x); + /* Concatenate: the current answer before the cursor, the first line + * of the cutbuffer, plus the rest of the current answer. */ + strncpy(fusion, answer, statusbar_x); + strncpy(fusion + statusbar_x, cutbuffer->data, pastelen); + strcpy(fusion + statusbar_x + pastelen, answer + statusbar_x); - free(answer); - answer = fusion; - statusbar_x += pastelen; + free(answer); + answer = fusion; + statusbar_x += pastelen; } /* Return the column number of the first character of the answer that is @@ -387,209 +387,209 @@ void do_statusbar_uncut_text(void) * (0 <= column - get_statusbar_page_start(column) < COLS). */ size_t get_statusbar_page_start(size_t base, size_t column) { - if (column == base || column < COLS - 1) - return 0; - else if (COLS > base + 2) - return column - base - 1 - (column - base - 1) % (COLS - base - 2); - else - return column - 2; + if (column == base || column < COLS - 1) + return 0; + else if (COLS > base + 2) + return column - base - 1 - (column - base - 1) % (COLS - base - 2); + else + return column - 2; } /* Reinitialize the cursor position in the answer. */ void reinit_statusbar_x(void) { - statusbar_x = HIGHEST_POSITIVE; + statusbar_x = HIGHEST_POSITIVE; } /* Redraw the promptbar and place the cursor at the right spot. */ void update_the_statusbar(void) { - size_t base = strlenpt(prompt) + 2; - size_t the_page, end_page, column; - char *expanded; + size_t base = strlenpt(prompt) + 2; + size_t the_page, end_page, column; + char *expanded; - the_page = get_statusbar_page_start(base, base + strnlenpt(answer, statusbar_x)); - end_page = get_statusbar_page_start(base, base + strlenpt(answer) - 1); + the_page = get_statusbar_page_start(base, base + strnlenpt(answer, statusbar_x)); + end_page = get_statusbar_page_start(base, base + strlenpt(answer) - 1); - /* Color the promptbar over its full width. */ - wattron(bottomwin, interface_color_pair[TITLE_BAR]); - blank_statusbar(); + /* Color the promptbar over its full width. */ + wattron(bottomwin, interface_color_pair[TITLE_BAR]); + blank_statusbar(); - mvwaddstr(bottomwin, 0, 0, prompt); - waddch(bottomwin, ':'); - waddch(bottomwin, (the_page == 0) ? ' ' : '<'); + mvwaddstr(bottomwin, 0, 0, prompt); + waddch(bottomwin, ':'); + waddch(bottomwin, (the_page == 0) ? ' ' : '<'); - expanded = display_string(answer, the_page, COLS - base - 1, FALSE); - waddstr(bottomwin, expanded); - free(expanded); + expanded = display_string(answer, the_page, COLS - base - 1, FALSE); + waddstr(bottomwin, expanded); + free(expanded); - waddch(bottomwin, (the_page >= end_page) ? ' ' : '>'); + waddch(bottomwin, (the_page >= end_page) ? ' ' : '>'); - wattroff(bottomwin, interface_color_pair[TITLE_BAR]); + wattroff(bottomwin, interface_color_pair[TITLE_BAR]); - /* Work around a cursor-misplacement bug in VTEs. */ - wmove(bottomwin, 0, 0); - wrefresh(bottomwin); + /* Work around a cursor-misplacement bug in VTEs. */ + wmove(bottomwin, 0, 0); + wrefresh(bottomwin); - /* Place the cursor at statusbar_x in the answer. */ - column = base + statusbar_xplustabs(); - wmove(bottomwin, 0, column - get_statusbar_page_start(base, column)); - wnoutrefresh(bottomwin); + /* Place the cursor at statusbar_x in the answer. */ + column = base + statusbar_xplustabs(); + wmove(bottomwin, 0, column - get_statusbar_page_start(base, column)); + wnoutrefresh(bottomwin); } /* Get a string of input at the statusbar prompt. */ functionptrtype acquire_an_answer(int *actual, bool allow_tabs, - bool allow_files, bool *listed, filestruct **history_list, - void (*refresh_func)(void)) + bool allow_files, bool *listed, filestruct **history_list, + void (*refresh_func)(void)) { - int kbinput = ERR; - bool ran_func, finished; - functionptrtype func; + int kbinput = ERR; + bool ran_func, finished; + functionptrtype func; #ifdef ENABLE_TABCOMP - bool tabbed = FALSE; - /* Whether we've pressed Tab. */ + bool tabbed = FALSE; + /* Whether we've pressed Tab. */ #endif #ifdef ENABLE_HISTORIES - char *history = NULL; - /* The current history string. */ - char *magichistory = NULL; - /* The temporary string typed at the bottom of the history, if - * any. */ + char *history = NULL; + /* The current history string. */ + char *magichistory = NULL; + /* The temporary string typed at the bottom of the history, if + * any. */ #ifdef ENABLE_TABCOMP - int last_kbinput = ERR; - /* The key we pressed before the current key. */ - size_t complete_len = 0; - /* The length of the original string that we're trying to - * tab complete, if any. */ + int last_kbinput = ERR; + /* The key we pressed before the current key. */ + size_t complete_len = 0; + /* The length of the original string that we're trying to + * tab complete, if any. */ #endif #endif /* ENABLE_HISTORIES */ - if (statusbar_x > strlen(answer)) - statusbar_x = strlen(answer); - - update_the_statusbar(); - - while (TRUE) { - kbinput = do_statusbar_input(&ran_func, &finished); - -#ifndef NANO_TINY - /* If the window size changed, go reformat the prompt string. */ - if (kbinput == KEY_WINCH) { - refresh_func(); - *actual = KEY_WINCH; -#ifdef ENABLE_HISTORIES - free(magichistory); -#endif - return NULL; - } -#endif /* !NANO_TINY */ - - func = func_from_key(&kbinput); - - if (func == do_cancel || func == do_enter) - break; - -#ifdef ENABLE_TABCOMP - if (func != do_tab) - tabbed = FALSE; - - if (func == do_tab) { -#ifdef ENABLE_HISTORIES - if (history_list != NULL) { - if (last_kbinput != the_code_for(do_tab, TAB_CODE)) - complete_len = strlen(answer); - - if (complete_len > 0) { - answer = get_history_completion(history_list, - answer, complete_len); - statusbar_x = strlen(answer); - } - } else -#endif - if (allow_tabs) - answer = input_tab(answer, allow_files, &statusbar_x, - &tabbed, refresh_func, listed); - } else -#endif /* ENABLE_TABCOMP */ -#ifdef ENABLE_HISTORIES - if (func == get_history_older_void) { - if (history_list != NULL) { - /* If we're scrolling up at the bottom of the history list - * and answer isn't blank, save answer in magichistory. */ - if ((*history_list)->next == NULL && *answer != '\0') - 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); - } - - /* This key has a shortcut-list entry when it's used to - * move to an older search, which means that finished has - * been set to TRUE. Set it back to FALSE here, so that - * we aren't kicked out of the statusbar prompt. */ - finished = FALSE; - } - } else if (func == get_history_newer_void) { - if (history_list != NULL) { - /* Get the newer search from the history list and save it in - * answer. If there is no newer search, don't do anything. */ - if ((history = get_history_newer(history_list)) != NULL) { - answer = mallocstrcpy(answer, history); - statusbar_x = strlen(answer); - } - - /* 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); - } - - /* 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 /* ENABLE_HISTORIES */ - if (func == do_help_void) { - /* 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 (finished) - break; + if (statusbar_x > strlen(answer)) + statusbar_x = strlen(answer); update_the_statusbar(); -#if defined(ENABLE_HISTORIES) && defined(ENABLE_TABCOMP) - last_kbinput = kbinput; + while (TRUE) { + kbinput = do_statusbar_input(&ran_func, &finished); + +#ifndef NANO_TINY + /* If the window size changed, go reformat the prompt string. */ + if (kbinput == KEY_WINCH) { + refresh_func(); + *actual = KEY_WINCH; +#ifdef ENABLE_HISTORIES + free(magichistory); #endif - } + return NULL; + } +#endif /* !NANO_TINY */ + + func = func_from_key(&kbinput); + + if (func == do_cancel || func == do_enter) + break; + +#ifdef ENABLE_TABCOMP + if (func != do_tab) + tabbed = FALSE; + + if (func == do_tab) { +#ifdef ENABLE_HISTORIES + if (history_list != NULL) { + if (last_kbinput != the_code_for(do_tab, TAB_CODE)) + complete_len = strlen(answer); + + if (complete_len > 0) { + answer = get_history_completion(history_list, + answer, complete_len); + statusbar_x = strlen(answer); + } + } else +#endif + if (allow_tabs) + answer = input_tab(answer, allow_files, &statusbar_x, + &tabbed, refresh_func, listed); + } else +#endif /* ENABLE_TABCOMP */ +#ifdef ENABLE_HISTORIES + if (func == get_history_older_void) { + if (history_list != NULL) { + /* If we're scrolling up at the bottom of the history list + * and answer isn't blank, save answer in magichistory. */ + if ((*history_list)->next == NULL && *answer != '\0') + 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); + } + + /* This key has a shortcut-list entry when it's used to + * move to an older search, which means that finished has + * been set to TRUE. Set it back to FALSE here, so that + * we aren't kicked out of the statusbar prompt. */ + finished = FALSE; + } + } else if (func == get_history_newer_void) { + if (history_list != NULL) { + /* Get the newer search from the history list and save it in + * answer. If there is no newer search, don't do anything. */ + if ((history = get_history_newer(history_list)) != NULL) { + answer = mallocstrcpy(answer, history); + statusbar_x = strlen(answer); + } + + /* 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); + } + + /* 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 /* ENABLE_HISTORIES */ + if (func == do_help_void) { + /* 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 (finished) + break; + + update_the_statusbar(); + +#if defined(ENABLE_HISTORIES) && defined(ENABLE_TABCOMP) + last_kbinput = kbinput; +#endif + } #ifdef ENABLE_HISTORIES - /* Set the current position in the history list to the bottom. */ - if (history_list != NULL) { - history_reset(*history_list); - free(magichistory); - } + /* Set the current position in the history list to the bottom. */ + if (history_list != NULL) { + history_reset(*history_list); + free(magichistory); + } #endif - *actual = kbinput; + *actual = kbinput; - return func; + return func; } /* Ask a question on the statusbar. The prompt will be stored in the @@ -604,63 +604,63 @@ functionptrtype acquire_an_answer(int *actual, bool allow_tabs, * interpreted. The allow_files parameter indicates whether we should * allow all files (as opposed to just directories) to be tab completed. */ int do_prompt(bool allow_tabs, bool allow_files, - int menu, const char *curranswer, filestruct **history_list, - void (*refresh_func)(void), const char *msg, ...) + int menu, const char *curranswer, filestruct **history_list, + void (*refresh_func)(void), const char *msg, ...) { - va_list ap; - int retval; - functionptrtype func = NULL; - bool listed = FALSE; - /* Save a possible current statusbar x position and prompt. */ - size_t was_statusbar_x = statusbar_x; - char *saved_prompt = prompt; + va_list ap; + int retval; + functionptrtype func = NULL; + bool listed = FALSE; + /* Save a possible current statusbar x position and prompt. */ + size_t was_statusbar_x = statusbar_x; + char *saved_prompt = prompt; - bottombars(menu); + bottombars(menu); - answer = mallocstrcpy(answer, curranswer); + answer = mallocstrcpy(answer, curranswer); #ifndef NANO_TINY redo_theprompt: #endif - prompt = charalloc((COLS * MAXCHARLEN) + 1); - va_start(ap, msg); - vsnprintf(prompt, COLS * MAXCHARLEN, msg, ap); - va_end(ap); - /* Reserve five columns for colon plus angles plus answer, ":". */ - prompt[actual_x(prompt, (COLS < 5) ? 0 : COLS - 5)] = '\0'; + prompt = charalloc((COLS * MAXCHARLEN) + 1); + va_start(ap, msg); + vsnprintf(prompt, COLS * MAXCHARLEN, msg, ap); + va_end(ap); + /* Reserve five columns for colon plus angles plus answer, ":". */ + prompt[actual_x(prompt, (COLS < 5) ? 0 : COLS - 5)] = '\0'; - func = acquire_an_answer(&retval, allow_tabs, allow_files, &listed, - history_list, refresh_func); - free(prompt); - prompt = saved_prompt; + func = acquire_an_answer(&retval, allow_tabs, allow_files, &listed, + history_list, refresh_func); + free(prompt); + prompt = saved_prompt; #ifndef NANO_TINY - if (retval == KEY_WINCH) - goto redo_theprompt; + if (retval == KEY_WINCH) + goto redo_theprompt; #endif - /* If we're done with this prompt, restore the x position to what - * it was at a possible previous prompt. */ - if (func == do_cancel || func == do_enter) - statusbar_x = was_statusbar_x; + /* If we're done with this prompt, restore the x position to what + * it was at a possible previous prompt. */ + if (func == do_cancel || func == do_enter) + statusbar_x = was_statusbar_x; - /* If we left the prompt via Cancel or Enter, set the return value - * properly. */ - if (func == do_cancel) - retval = -1; - else if (func == do_enter) - retval = (*answer == '\0') ? -2 : 0; + /* If we left the prompt via Cancel or Enter, set the return value + * properly. */ + if (func == do_cancel) + retval = -1; + else if (func == do_enter) + retval = (*answer == '\0') ? -2 : 0; - wipe_statusbar(); + wipe_statusbar(); #ifdef ENABLE_TABCOMP - /* If we've done tab completion, there might still be a list of - * filename matches on the edit window. Clear them off. */ - if (listed) - refresh_func(); + /* If we've done tab completion, there might still be a list of + * filename matches on the edit window. Clear them off. */ + if (listed) + refresh_func(); #endif - return retval; + return retval; } /* Ask a simple Yes/No (and optionally All) question, specified in msg, @@ -668,94 +668,94 @@ int do_prompt(bool allow_tabs, bool allow_files, * TRUE when passed in), and -1 for Cancel. */ int do_yesno_prompt(bool all, const char *msg) { - int response = -2, width = 16; - char *message = display_string(msg, 0, COLS, FALSE); + int response = -2, width = 16; + char *message = display_string(msg, 0, COLS, FALSE); - /* TRANSLATORS: For the next three strings, if possible, specify - * the single-byte letters for both your language and English. - * For example, in French: "OoYy", for both "Oui" and "Yes". */ - const char *yesstr = _("Yy"); - const char *nostr = _("Nn"); - const char *allstr = _("Aa"); + /* TRANSLATORS: For the next three strings, if possible, specify + * the single-byte letters for both your language and English. + * For example, in French: "OoYy", for both "Oui" and "Yes". */ + const char *yesstr = _("Yy"); + const char *nostr = _("Nn"); + const char *allstr = _("Aa"); - /* The above three variables consist of all the single-byte characters - * that are accepted for the corresponding answer. Of each variable, - * the first character is displayed in the help lines. */ + /* The above three variables consist of all the single-byte characters + * that are accepted for the corresponding answer. Of each variable, + * the first character is displayed in the help lines. */ - while (response == -2) { - int kbinput; + while (response == -2) { + int kbinput; - if (!ISSET(NO_HELP)) { - char shortstr[MAXCHARLEN + 2]; - /* Temporary string for (translated) " Y", " N" and " A". */ + if (!ISSET(NO_HELP)) { + char shortstr[MAXCHARLEN + 2]; + /* Temporary string for (translated) " Y", " N" and " A". */ - if (COLS < 32) - width = COLS / 2; + if (COLS < 32) + width = COLS / 2; - /* Clear the shortcut list from the bottom of the screen. */ - blank_bottombars(); + /* Clear the shortcut list from the bottom of the screen. */ + blank_bottombars(); - /* Now show the ones for "Yes", "No", "Cancel" and maybe "All". */ - sprintf(shortstr, " %c", yesstr[0]); - wmove(bottomwin, 1, 0); - post_one_key(shortstr, _("Yes"), width); + /* Now show the ones for "Yes", "No", "Cancel" and maybe "All". */ + sprintf(shortstr, " %c", yesstr[0]); + wmove(bottomwin, 1, 0); + post_one_key(shortstr, _("Yes"), width); - if (all) { - shortstr[1] = allstr[0]; - wmove(bottomwin, 1, width); - post_one_key(shortstr, _("All"), width); - } + if (all) { + shortstr[1] = allstr[0]; + wmove(bottomwin, 1, width); + post_one_key(shortstr, _("All"), width); + } - shortstr[1] = nostr[0]; - wmove(bottomwin, 2, 0); - post_one_key(shortstr, _("No"), width); + shortstr[1] = nostr[0]; + wmove(bottomwin, 2, 0); + post_one_key(shortstr, _("No"), width); - wmove(bottomwin, 2, width); - post_one_key("^C", _("Cancel"), width); - } + wmove(bottomwin, 2, width); + post_one_key("^C", _("Cancel"), width); + } - /* Color the statusbar over its full width and display the question. */ - wattron(bottomwin, interface_color_pair[TITLE_BAR]); - blank_statusbar(); - mvwaddnstr(bottomwin, 0, 0, message, actual_x(message, COLS - 1)); - wattroff(bottomwin, interface_color_pair[TITLE_BAR]); - wnoutrefresh(bottomwin); + /* Color the statusbar over its full width and display the question. */ + wattron(bottomwin, interface_color_pair[TITLE_BAR]); + blank_statusbar(); + mvwaddnstr(bottomwin, 0, 0, message, actual_x(message, COLS - 1)); + wattroff(bottomwin, interface_color_pair[TITLE_BAR]); + wnoutrefresh(bottomwin); - currmenu = MYESNO; + currmenu = MYESNO; - /* When not replacing, show the cursor while waiting for a key. */ - kbinput = get_kbinput(bottomwin, !all); + /* When not replacing, show the cursor while waiting for a key. */ + kbinput = get_kbinput(bottomwin, !all); - /* See if the pressed key is in the Yes, No, or All strings. */ - if (strchr(yesstr, kbinput) != NULL) - response = 1; - else if (strchr(nostr, kbinput) != NULL) - response = 0; - else if (all && strchr(allstr, kbinput) != NULL) - response = 2; - else if (func_from_key(&kbinput) == do_cancel) - response = -1; + /* See if the pressed key is in the Yes, No, or All strings. */ + if (strchr(yesstr, kbinput) != NULL) + response = 1; + else if (strchr(nostr, kbinput) != NULL) + response = 0; + else if (all && strchr(allstr, kbinput) != NULL) + response = 2; + else if (func_from_key(&kbinput) == do_cancel) + response = -1; #ifdef ENABLE_MOUSE - else if (kbinput == KEY_MOUSE) { - int mouse_x, mouse_y; - /* We can click on the Yes/No/All shortcuts to select an answer. */ - if (get_mouseinput(&mouse_x, &mouse_y, FALSE) == 0 && - wmouse_trafo(bottomwin, &mouse_y, &mouse_x, FALSE) && - mouse_x < (width * 2) && mouse_y > 0) { - int x = mouse_x / width; - int y = mouse_y - 1; + else if (kbinput == KEY_MOUSE) { + int mouse_x, mouse_y; + /* We can click on the Yes/No/All shortcuts to select an answer. */ + if (get_mouseinput(&mouse_x, &mouse_y, FALSE) == 0 && + wmouse_trafo(bottomwin, &mouse_y, &mouse_x, FALSE) && + mouse_x < (width * 2) && mouse_y > 0) { + int x = mouse_x / width; + int y = mouse_y - 1; - /* x == 0 means Yes or No, y == 0 means Yes or All. */ - response = -2 * x * y + x - y + 1; + /* x == 0 means Yes or No, y == 0 means Yes or All. */ + response = -2 * x * y + x - y + 1; - if (response == 2 && !all) - response = -2; - } - } + if (response == 2 && !all) + response = -2; + } + } #endif /* ENABLE_MOUSE */ - } + } - free(message); + free(message); - return response; + return response; } diff --git a/src/proto.h b/src/proto.h index f585f0ff..e9ff05f2 100644 --- a/src/proto.h +++ b/src/proto.h @@ -272,7 +272,7 @@ bool open_buffer(const char *filename, bool undoable); void replace_buffer(const char *filename); #ifndef NANO_TINY void replace_marked_buffer(const char *filename, filestruct *top, size_t top_x, - filestruct *bot, size_t bot_x); + filestruct *bot, size_t bot_x); #endif #endif void prepare_for_display(void); @@ -282,7 +282,7 @@ void switch_to_next_buffer(void); bool close_buffer(void); #endif void read_file(FILE *f, int fd, const char *filename, bool undoable, - bool checkwritable); + bool checkwritable); int open_file(const char *filename, bool newfie, bool quiet, FILE **f); char *get_next_filename(const char *name, const char *suffix); void do_insertfile_void(void); @@ -299,10 +299,10 @@ int write_lockfile(const char *lockfilename, const char *origfilename, bool modi #endif int copy_file(FILE *inn, FILE *out, bool close_out); bool write_file(const char *name, FILE *f_open, bool tmp, - kind_of_writing_type method, bool fullbuffer); + kind_of_writing_type method, bool fullbuffer); #ifndef NANO_TINY bool write_marked_file(const char *name, FILE *f_open, bool tmp, - kind_of_writing_type method); + kind_of_writing_type method); #endif int do_writeout(bool exiting, bool withprompt); void do_writeout_void(void); @@ -313,7 +313,7 @@ int diralphasort(const void *va, const void *vb); #endif #ifdef ENABLE_TABCOMP char *input_tab(char *buf, bool allow_files, size_t *place, - bool *lastwastab, void (*refresh_func)(void), bool *listed); + bool *lastwastab, void (*refresh_func)(void), bool *listed); #endif /* Some functions in global.c. */ @@ -406,10 +406,10 @@ filestruct *copy_filestruct(const filestruct *src); void free_filestruct(filestruct *src); void renumber(filestruct *fileptr); partition *partition_filestruct(filestruct *top, size_t top_x, - filestruct *bot, size_t bot_x); + filestruct *bot, size_t bot_x); void unpartition_filestruct(partition **p); void extract_buffer(filestruct **file_top, filestruct **file_bot, - filestruct *top, size_t top_x, filestruct *bot, size_t bot_x); + filestruct *top, size_t top_x, filestruct *bot, size_t bot_x); void ingraft_buffer(filestruct *somebuffer); void copy_from_buffer(filestruct *somebuffer); openfilestruct *make_new_opennode(void); @@ -470,8 +470,8 @@ size_t get_statusbar_page_start(size_t start_col, size_t column); void reinit_statusbar_x(void); void update_the_statusbar(void); int do_prompt(bool allow_tabs, bool allow_files, - int menu, const char *curranswer, filestruct **history_list, - void (*refresh_func)(void), const char *msg, ...); + int menu, const char *curranswer, filestruct **history_list, + void (*refresh_func)(void), const char *msg, ...); int do_yesno_prompt(bool all, const char *msg); /* Most functions in rcfile.c. */ @@ -488,7 +488,7 @@ void do_rcfiles(void); void not_found_msg(const char *str); void search_replace_abort(void); int findnextstr(const char *needle, bool whole_word_only, int modus, - size_t *match_len, bool skipone, const filestruct *begin, size_t begin_x); + size_t *match_len, bool skipone, const filestruct *begin, size_t begin_x); void do_search(void); void do_search_forward(void); void do_search_backward(void); @@ -499,11 +499,11 @@ void do_findnext(void); void do_research(void); void go_looking(void); ssize_t do_replace_loop(const char *needle, bool whole_word_only, - const filestruct *real_current, size_t *real_current_x); + const filestruct *real_current, size_t *real_current_x); void do_replace(void); void goto_line_posx(ssize_t line, size_t pos_x); void do_gotolinecolumn(ssize_t line, ssize_t column, bool use_answer, - bool interactive); + bool interactive); void do_gotolinecolumn_void(void); #ifndef NANO_TINY void do_find_bracket(void); @@ -592,7 +592,7 @@ const char *fixbounds(const char *r); bool is_separate_word(size_t position, size_t length, const char *buf); #endif const char *strstrwrapper(const char *haystack, const char *needle, - const char *start); + const char *start); void nperror(const char *s); void *nmalloc(size_t howmuch); void *nrealloc(void *ptr, size_t howmuch); @@ -610,7 +610,7 @@ void remove_magicline(void); #endif #ifndef NANO_TINY void mark_order(const filestruct **top, size_t *top_x, - const filestruct **bot, size_t *bot_x, bool *right_side_up); + const filestruct **bot, size_t *bot_x, bool *right_side_up); void get_range(const filestruct **top, const filestruct **bot); #endif size_t get_totsize(const filestruct *begin, const filestruct *end); @@ -654,7 +654,7 @@ void bottombars(int menu); void post_one_key(const char *keystroke, const char *tag, int width); void place_the_cursor(void); void edit_draw(filestruct *fileptr, const char *converted, - int line, size_t from_col); + int line, size_t from_col); int update_line(filestruct *fileptr, size_t index); #ifndef NANO_TINY int update_softwrapped_line(filestruct *fileptr); @@ -666,7 +666,7 @@ bool less_than_a_screenful(size_t was_lineno, size_t was_leftedge); void edit_scroll(bool direction, int nrows); #ifndef NANO_TINY size_t get_softwrap_breakpoint(const char *text, size_t leftedge, - bool *end_of_line); + bool *end_of_line); size_t get_chunk_and_edge(size_t column, filestruct *line, size_t *leftedge); size_t chunk_for(size_t column, filestruct *line); size_t leftedge_for(size_t column, filestruct *line); diff --git a/src/rcfile.c b/src/rcfile.c index d0b9ca87..eec65440 100644 --- a/src/rcfile.c +++ b/src/rcfile.c @@ -35,124 +35,124 @@ #endif static const rcoption rcopts[] = { - {"boldtext", BOLD_TEXT}, + {"boldtext", BOLD_TEXT}, #ifdef ENABLE_LINENUMBERS - {"linenumbers", LINE_NUMBERS}, + {"linenumbers", LINE_NUMBERS}, #endif #ifdef ENABLE_JUSTIFY - {"brackets", 0}, + {"brackets", 0}, #endif - {"const", CONSTANT_SHOW}, /* deprecated form, remove in 2018 */ - {"constantshow", CONSTANT_SHOW}, + {"const", CONSTANT_SHOW}, /* deprecated form, remove in 2018 */ + {"constantshow", CONSTANT_SHOW}, #ifdef ENABLED_WRAPORJUSTIFY - {"fill", 0}, + {"fill", 0}, #endif #ifdef ENABLE_HISTORIES - {"historylog", HISTORYLOG}, + {"historylog", HISTORYLOG}, #endif - {"morespace", MORE_SPACE}, + {"morespace", MORE_SPACE}, #ifdef ENABLE_MOUSE - {"mouse", USE_MOUSE}, + {"mouse", USE_MOUSE}, #endif #ifdef ENABLE_MULTIBUFFER - {"multibuffer", MULTIBUFFER}, + {"multibuffer", MULTIBUFFER}, #endif - {"nohelp", NO_HELP}, - {"nonewlines", NO_NEWLINES}, - {"nopauses", NO_PAUSES}, + {"nohelp", NO_HELP}, + {"nonewlines", NO_NEWLINES}, + {"nopauses", NO_PAUSES}, #ifdef ENABLE_WRAPPING - {"nowrap", NO_WRAP}, + {"nowrap", NO_WRAP}, #endif #ifdef ENABLE_OPERATINGDIR - {"operatingdir", 0}, + {"operatingdir", 0}, #endif #ifdef ENABLE_HISTORIES - {"poslog", POS_HISTORY}, /* deprecated form, remove in 2018 */ - {"positionlog", POS_HISTORY}, + {"poslog", POS_HISTORY}, /* deprecated form, remove in 2018 */ + {"positionlog", POS_HISTORY}, #endif - {"preserve", PRESERVE}, + {"preserve", PRESERVE}, #ifdef ENABLE_JUSTIFY - {"punct", 0}, - {"quotestr", 0}, + {"punct", 0}, + {"quotestr", 0}, #endif - {"quickblank", QUICK_BLANK}, - {"rebinddelete", REBIND_DELETE}, - {"rebindkeypad", REBIND_KEYPAD}, - {"regexp", USE_REGEXP}, + {"quickblank", QUICK_BLANK}, + {"rebinddelete", REBIND_DELETE}, + {"rebindkeypad", REBIND_KEYPAD}, + {"regexp", USE_REGEXP}, #ifdef ENABLE_SPELLER - {"speller", 0}, + {"speller", 0}, #endif - {"suspend", SUSPEND}, - {"tabsize", 0}, - {"tempfile", TEMP_FILE}, - {"view", VIEW_MODE}, + {"suspend", SUSPEND}, + {"tabsize", 0}, + {"tempfile", TEMP_FILE}, + {"view", VIEW_MODE}, #ifndef NANO_TINY - {"allow_insecure_backup", INSECURE_BACKUP}, - {"atblanks", AT_BLANKS}, - {"autoindent", AUTOINDENT}, - {"backup", BACKUP_FILE}, - {"backupdir", 0}, - {"backwards", BACKWARDS_SEARCH}, - {"casesensitive", CASE_SENSITIVE}, - {"cut", CUT_FROM_CURSOR}, /* deprecated form, remove in 2020 */ - {"cutfromcursor", CUT_FROM_CURSOR}, - {"justifytrim", TRIM_BLANKS}, /* deprecated form, remove in 2020 */ - {"locking", LOCKING}, - {"matchbrackets", 0}, - {"noconvert", NO_CONVERT}, - {"quiet", QUIET}, - {"showcursor", SHOW_CURSOR}, - {"smarthome", SMART_HOME}, - {"smooth", SMOOTH_SCROLL}, - {"softwrap", SOFTWRAP}, - {"tabstospaces", TABS_TO_SPACES}, - {"trimblanks", TRIM_BLANKS}, - {"unix", MAKE_IT_UNIX}, - {"whitespace", 0}, - {"wordbounds", WORD_BOUNDS}, - {"wordchars", 0}, + {"allow_insecure_backup", INSECURE_BACKUP}, + {"atblanks", AT_BLANKS}, + {"autoindent", AUTOINDENT}, + {"backup", BACKUP_FILE}, + {"backupdir", 0}, + {"backwards", BACKWARDS_SEARCH}, + {"casesensitive", CASE_SENSITIVE}, + {"cut", CUT_FROM_CURSOR}, /* deprecated form, remove in 2020 */ + {"cutfromcursor", CUT_FROM_CURSOR}, + {"justifytrim", TRIM_BLANKS}, /* deprecated form, remove in 2020 */ + {"locking", LOCKING}, + {"matchbrackets", 0}, + {"noconvert", NO_CONVERT}, + {"quiet", QUIET}, + {"showcursor", SHOW_CURSOR}, + {"smarthome", SMART_HOME}, + {"smooth", SMOOTH_SCROLL}, + {"softwrap", SOFTWRAP}, + {"tabstospaces", TABS_TO_SPACES}, + {"trimblanks", TRIM_BLANKS}, + {"unix", MAKE_IT_UNIX}, + {"whitespace", 0}, + {"wordbounds", WORD_BOUNDS}, + {"wordchars", 0}, #endif #ifdef ENABLE_COLOR - {"titlecolor", 0}, - {"numbercolor", 0}, - {"selectedcolor", 0}, - {"statuscolor", 0}, - {"keycolor", 0}, - {"functioncolor", 0}, + {"titlecolor", 0}, + {"numbercolor", 0}, + {"selectedcolor", 0}, + {"statuscolor", 0}, + {"keycolor", 0}, + {"functioncolor", 0}, #endif - {NULL, 0} + {NULL, 0} }; static size_t lineno = 0; - /* The line number of the last encountered error. */ + /* The line number of the last encountered error. */ static char *nanorc = NULL; - /* The path to the rcfile we're parsing. */ + /* The path to the rcfile we're parsing. */ #ifdef ENABLE_COLOR static bool opensyntax = FALSE; - /* Whether we're allowed to add to the last syntax. When a file ends, - * or when a new syntax command is seen, this bool becomes FALSE. */ + /* Whether we're allowed to add to the last syntax. When a file ends, + * or when a new syntax command is seen, this bool becomes FALSE. */ static syntaxtype *live_syntax; - /* The syntax that is currently being parsed. */ + /* The syntax that is currently being parsed. */ static colortype *lastcolor = NULL; - /* The end of the color list for the current syntax. */ + /* The end of the color list for the current syntax. */ #endif /* Report an error in an rcfile, printing it to stderr. */ void rcfile_error(const char *msg, ...) { - va_list ap; + va_list ap; - if (rcfile_with_errors == NULL) - rcfile_with_errors = strdup(nanorc); + if (rcfile_with_errors == NULL) + rcfile_with_errors = strdup(nanorc); - if (lineno > 0) - fprintf(stderr, _("Error in %s on line %zu: "), nanorc, lineno); + if (lineno > 0) + fprintf(stderr, _("Error in %s on line %zu: "), nanorc, lineno); - va_start(ap, msg); - vfprintf(stderr, _(msg), ap); - va_end(ap); + va_start(ap, msg); + vfprintf(stderr, _(msg), ap); + va_end(ap); - fprintf(stderr, "\n"); + fprintf(stderr, "\n"); } #endif /* ENABLE_NANORC */ @@ -162,19 +162,19 @@ void rcfile_error(const char *msg, ...) * returned pointer will point to '\0' if we hit the end of the line. */ char *parse_next_word(char *ptr) { - while (!isblank((unsigned char)*ptr) && *ptr != '\0') - ptr++; + while (!isblank((unsigned char)*ptr) && *ptr != '\0') + ptr++; + + if (*ptr == '\0') + return ptr; + + /* Null-terminate and advance ptr. */ + *ptr++ = '\0'; + + while (isblank((unsigned char)*ptr)) + ptr++; - if (*ptr == '\0') return ptr; - - /* Null-terminate and advance ptr. */ - *ptr++ = '\0'; - - while (isblank((unsigned char)*ptr)) - ptr++; - - return ptr; } #endif /* ENABLE_NANORC || ENABLE_HISTORIES */ @@ -185,34 +185,34 @@ char *parse_next_word(char *ptr) * arguments can contain "'s too. */ char *parse_argument(char *ptr) { - const char *ptr_save = ptr; - char *last_quote = NULL; + const char *ptr_save = ptr; + char *last_quote = NULL; - assert(ptr != NULL); + assert(ptr != NULL); - if (*ptr != '"') - return parse_next_word(ptr); + if (*ptr != '"') + return parse_next_word(ptr); - do { - ptr++; - if (*ptr == '"') - last_quote = ptr; - } while (*ptr != '\0'); + do { + ptr++; + if (*ptr == '"') + last_quote = ptr; + } while (*ptr != '\0'); - if (last_quote == NULL) { - if (*ptr == '\0') - ptr = NULL; - else - *ptr++ = '\0'; - rcfile_error(N_("Argument '%s' has an unterminated \""), ptr_save); - } else { - *last_quote = '\0'; - ptr = last_quote + 1; - } - if (ptr != NULL) - while (isblank((unsigned char)*ptr)) - ptr++; - return ptr; + if (last_quote == NULL) { + if (*ptr == '\0') + ptr = NULL; + else + *ptr++ = '\0'; + rcfile_error(N_("Argument '%s' has an unterminated \""), ptr_save); + } else { + *last_quote = '\0'; + ptr = last_quote + 1; + } + if (ptr != NULL) + while (isblank((unsigned char)*ptr)) + ptr++; + return ptr; } #ifdef ENABLE_COLOR @@ -220,123 +220,123 @@ char *parse_argument(char *ptr) * null-terminate it, and return a pointer to the /next/ word. */ char *parse_next_regex(char *ptr) { - assert(ptr != NULL); + assert(ptr != NULL); - /* Continue until the end of line, or until a " followed by a - * blank character or the end of line. */ - while (*ptr != '\0' && (*ptr != '"' || - (*(ptr + 1) != '\0' && !isblank((unsigned char)ptr[1])))) - ptr++; + /* Continue until the end of line, or until a " followed by a + * blank character or the end of line. */ + while (*ptr != '\0' && (*ptr != '"' || + (*(ptr + 1) != '\0' && !isblank((unsigned char)ptr[1])))) + ptr++; - assert(*ptr == '"' || *ptr == '\0'); + assert(*ptr == '"' || *ptr == '\0'); - if (*ptr == '\0') { - rcfile_error( - N_("Regex strings must begin and end with a \" character")); - return NULL; - } + if (*ptr == '\0') { + rcfile_error( + N_("Regex strings must begin and end with a \" character")); + return NULL; + } - /* Null-terminate and advance ptr. */ - *ptr++ = '\0'; + /* Null-terminate and advance ptr. */ + *ptr++ = '\0'; - while (isblank((unsigned char)*ptr)) - ptr++; + while (isblank((unsigned char)*ptr)) + ptr++; - return ptr; + return ptr; } /* Compile the regular expression regex to see if it's valid. Return * TRUE if it is, and FALSE otherwise. */ bool nregcomp(const char *regex, int compile_flags) { - regex_t preg; - const char *r = fixbounds(regex); - int rc = regcomp(&preg, r, compile_flags); + regex_t preg; + const char *r = fixbounds(regex); + int rc = regcomp(&preg, r, compile_flags); - if (rc != 0) { - size_t len = regerror(rc, &preg, NULL, 0); - char *str = charalloc(len); + if (rc != 0) { + size_t len = regerror(rc, &preg, NULL, 0); + char *str = charalloc(len); - regerror(rc, &preg, str, len); - rcfile_error(N_("Bad regex \"%s\": %s"), r, str); - free(str); - } + regerror(rc, &preg, str, len); + rcfile_error(N_("Bad regex \"%s\": %s"), r, str); + free(str); + } - regfree(&preg); - return (rc == 0); + regfree(&preg); + return (rc == 0); } /* Parse the next syntax name and its possible extension regexes from the * line at ptr, and add it to the global linked list of color syntaxes. */ void parse_syntax(char *ptr) { - char *nameptr; - /* A pointer to what should be the name of the syntax. */ + char *nameptr; + /* A pointer to what should be the name of the syntax. */ - opensyntax = FALSE; + opensyntax = FALSE; - assert(ptr != NULL); + assert(ptr != NULL); - /* Check that the syntax name is not empty. */ - if (*ptr == '\0' || (*ptr == '"' && - (*(ptr + 1) == '\0' || *(ptr + 1) == '"'))) { - rcfile_error(N_("Missing syntax name")); - return; - } + /* Check that the syntax name is not empty. */ + if (*ptr == '\0' || (*ptr == '"' && + (*(ptr + 1) == '\0' || *(ptr + 1) == '"'))) { + rcfile_error(N_("Missing syntax name")); + return; + } - nameptr = ++ptr; - ptr = parse_next_word(ptr); + nameptr = ++ptr; + ptr = parse_next_word(ptr); - /* Check that the name starts and ends with a double quote. */ - if (*(nameptr - 1) != '\x22' || nameptr[strlen(nameptr) - 1] != '\x22') { - rcfile_error(N_("A syntax name must be quoted")); - return; - } + /* Check that the name starts and ends with a double quote. */ + if (*(nameptr - 1) != '\x22' || nameptr[strlen(nameptr) - 1] != '\x22') { + rcfile_error(N_("A syntax name must be quoted")); + return; + } - /* Strip the end quote. */ - nameptr[strlen(nameptr) - 1] = '\0'; + /* Strip the end quote. */ + nameptr[strlen(nameptr) - 1] = '\0'; - /* Redefining the "none" syntax is not allowed. */ - if (strcmp(nameptr, "none") == 0) { - rcfile_error(N_("The \"none\" syntax is reserved")); - return; - } + /* Redefining the "none" syntax is not allowed. */ + if (strcmp(nameptr, "none") == 0) { + rcfile_error(N_("The \"none\" syntax is reserved")); + return; + } - /* Initialize a new syntax struct. */ - live_syntax = (syntaxtype *)nmalloc(sizeof(syntaxtype)); - live_syntax->name = mallocstrcpy(NULL, nameptr); - live_syntax->extensions = NULL; - live_syntax->headers = NULL; - live_syntax->magics = NULL; - live_syntax->linter = NULL; - live_syntax->formatter = NULL; + /* Initialize a new syntax struct. */ + live_syntax = (syntaxtype *)nmalloc(sizeof(syntaxtype)); + live_syntax->name = mallocstrcpy(NULL, nameptr); + live_syntax->extensions = NULL; + live_syntax->headers = NULL; + live_syntax->magics = NULL; + live_syntax->linter = NULL; + live_syntax->formatter = NULL; #ifdef ENABLE_COMMENT - live_syntax->comment = mallocstrcpy(NULL, GENERAL_COMMENT_CHARACTER); + live_syntax->comment = mallocstrcpy(NULL, GENERAL_COMMENT_CHARACTER); #endif - live_syntax->color = NULL; - lastcolor = NULL; - live_syntax->nmultis = 0; + live_syntax->color = NULL; + lastcolor = NULL; + live_syntax->nmultis = 0; - /* Hook the new syntax in at the top of the list. */ - live_syntax->next = syntaxes; - syntaxes = live_syntax; + /* Hook the new syntax in at the top of the list. */ + live_syntax->next = syntaxes; + syntaxes = live_syntax; - opensyntax = TRUE; + opensyntax = TRUE; #ifdef DEBUG - fprintf(stderr, "Starting a new syntax type: \"%s\"\n", nameptr); + fprintf(stderr, "Starting a new syntax type: \"%s\"\n", nameptr); #endif - /* The default syntax should have no associated extensions. */ - if (strcmp(live_syntax->name, "default") == 0 && *ptr != '\0') { - rcfile_error( - N_("The \"default\" syntax does not accept extensions")); - return; - } + /* The default syntax should have no associated extensions. */ + if (strcmp(live_syntax->name, "default") == 0 && *ptr != '\0') { + rcfile_error( + N_("The \"default\" syntax does not accept extensions")); + return; + } - /* If there seem to be extension regexes, pick them up. */ - if (*ptr != '\0') - grab_and_store("extension", ptr, &live_syntax->extensions); + /* If there seem to be extension regexes, pick them up. */ + if (*ptr != '\0') + grab_and_store("extension", ptr, &live_syntax->extensions); } #endif /* ENABLE_COLOR */ @@ -345,277 +345,277 @@ void parse_syntax(char *ptr) * all menus. */ bool is_universal(void (*func)(void)) { - if (func == do_left || func == do_right || - func == do_home || func == do_end || + if (func == do_left || func == do_right || + func == do_home || func == do_end || #ifndef NANO_TINY - func == do_prev_word_void || func == do_next_word_void || + func == do_prev_word_void || func == do_next_word_void || #endif - func == do_delete || func == do_backspace || - func == do_cut_text_void || func == do_uncut_text || - func == do_tab || func == do_enter || func == do_verbatim_input) - return TRUE; - else - return FALSE; + func == do_delete || func == do_backspace || + func == do_cut_text_void || func == do_uncut_text || + func == do_tab || func == do_enter || func == do_verbatim_input) + return TRUE; + else + return FALSE; } /* Bind or unbind a key combo, to or from a function. */ void parse_binding(char *ptr, bool dobind) { - char *keyptr = NULL, *keycopy = NULL, *funcptr = NULL, *menuptr = NULL; - sc *s, *newsc = NULL; - int menu; + char *keyptr = NULL, *keycopy = NULL, *funcptr = NULL, *menuptr = NULL; + sc *s, *newsc = NULL; + int menu; - assert(ptr != NULL); + assert(ptr != NULL); #ifdef DEBUG - fprintf(stderr, "Starting the rebinding code...\n"); + fprintf(stderr, "Starting the rebinding code...\n"); #endif - if (*ptr == '\0') { - rcfile_error(N_("Missing key name")); - return; - } - - keyptr = ptr; - ptr = parse_next_word(ptr); - keycopy = mallocstrcpy(NULL, keyptr); - - if (strlen(keycopy) < 2) { - rcfile_error(N_("Key name is too short")); - goto free_things; - } - - /* Uppercase only the first two or three characters of the key name. */ - keycopy[0] = toupper((unsigned char)keycopy[0]); - keycopy[1] = toupper((unsigned char)keycopy[1]); - if (keycopy[0] == 'M' && keycopy[1] == '-') { - if (strlen(keycopy) > 2) - keycopy[2] = toupper((unsigned char)keycopy[2]); - else { - rcfile_error(N_("Key name is too short")); - goto free_things; + if (*ptr == '\0') { + rcfile_error(N_("Missing key name")); + return; } - } - /* 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((unsigned char)keycopy[1]); - else if (keycopy[0] != '^' && keycopy[0] != 'M' && keycopy[0] != 'F') { - rcfile_error(N_("Key name must begin with \"^\", \"M\", or \"F\"")); - goto free_things; - } else if (keycode_from_string(keycopy) < 0) { - rcfile_error(N_("Key name %s is invalid"), keycopy); - goto free_things; - } + keyptr = ptr; + ptr = parse_next_word(ptr); + keycopy = mallocstrcpy(NULL, keyptr); - if (dobind) { - funcptr = ptr; + if (strlen(keycopy) < 2) { + rcfile_error(N_("Key name is too short")); + goto free_things; + } + + /* Uppercase only the first two or three characters of the key name. */ + keycopy[0] = toupper((unsigned char)keycopy[0]); + keycopy[1] = toupper((unsigned char)keycopy[1]); + if (keycopy[0] == 'M' && keycopy[1] == '-') { + if (strlen(keycopy) > 2) + keycopy[2] = toupper((unsigned char)keycopy[2]); + else { + rcfile_error(N_("Key name is too short")); + goto free_things; + } + } + + /* 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((unsigned char)keycopy[1]); + else if (keycopy[0] != '^' && keycopy[0] != 'M' && keycopy[0] != 'F') { + rcfile_error(N_("Key name must begin with \"^\", \"M\", or \"F\"")); + goto free_things; + } else if (keycode_from_string(keycopy) < 0) { + rcfile_error(N_("Key name %s is invalid"), keycopy); + goto free_things; + } + + if (dobind) { + funcptr = ptr; + ptr = parse_next_word(ptr); + + if (funcptr[0] == '\0') { + rcfile_error(N_("Must specify a function to bind the key to")); + goto free_things; + } + } + + menuptr = ptr; ptr = parse_next_word(ptr); - if (funcptr[0] == '\0') { - rcfile_error(N_("Must specify a function to bind the key to")); - goto free_things; + if (menuptr[0] == '\0') { + /* TRANSLATORS: Do not translate the word "all". */ + rcfile_error(N_("Must specify a menu (or \"all\") in which to bind/unbind the key")); + goto free_things; } - } - menuptr = ptr; - ptr = parse_next_word(ptr); - - if (menuptr[0] == '\0') { - /* TRANSLATORS: Do not translate the word "all". */ - rcfile_error(N_("Must specify a menu (or \"all\") in which to bind/unbind the key")); - goto free_things; - } - - if (dobind) { - newsc = strtosc(funcptr); - if (newsc == NULL) { - rcfile_error(N_("Cannot map name \"%s\" to a function"), funcptr); - goto free_things; + if (dobind) { + newsc = strtosc(funcptr); + if (newsc == NULL) { + rcfile_error(N_("Cannot map name \"%s\" to a function"), funcptr); + goto free_things; + } } - } - menu = strtomenu(menuptr); - if (menu < 1) { - rcfile_error(N_("Cannot map name \"%s\" to a menu"), menuptr); - goto free_things; - } + menu = strtomenu(menuptr); + if (menu < 1) { + rcfile_error(N_("Cannot map name \"%s\" to a menu"), menuptr); + goto free_things; + } - if (dobind) { - subnfunc *f; - int mask = 0; + if (dobind) { + subnfunc *f; + int mask = 0; - /* Tally up the menus where the function exists. */ - for (f = allfuncs; f != NULL; f = f->next) - if (f->scfunc == newsc->scfunc) - mask = mask | f->menus; + /* Tally up the menus where the function exists. */ + for (f = allfuncs; f != NULL; f = f->next) + if (f->scfunc == newsc->scfunc) + mask = mask | f->menus; #ifndef NANO_TINY - /* Handle the special case of the toggles. */ - if (newsc->scfunc == do_toggle_void) - mask = MMAIN; + /* Handle the special case of the toggles. */ + if (newsc->scfunc == do_toggle_void) + mask = MMAIN; #endif - /* Now limit the given menu to those where the function exists. */ - if (is_universal(newsc->scfunc)) - menu = menu & MMOST; - else - menu = menu & mask; + /* Now limit the given menu to those where the function exists. */ + if (is_universal(newsc->scfunc)) + menu = menu & MMOST; + else + menu = menu & mask; - if (!menu) { - rcfile_error(N_("Function '%s' does not exist in menu '%s'"), funcptr, menuptr); - goto free_things; + if (!menu) { + rcfile_error(N_("Function '%s' does not exist in menu '%s'"), funcptr, menuptr); + goto free_things; + } + + newsc->menus = menu; + assign_keyinfo(newsc, keycopy, 0); + + /* Do not allow rebinding a frequent escape-sequence starter: Esc [. */ + if (newsc->meta && newsc->keycode == 91) { + rcfile_error(N_("Sorry, keystroke \"%s\" may not be rebound"), newsc->keystr); + goto free_things; + } } - newsc->menus = menu; - assign_keyinfo(newsc, keycopy, 0); - - /* Do not allow rebinding a frequent escape-sequence starter: Esc [. */ - if (newsc->meta && newsc->keycode == 91) { - rcfile_error(N_("Sorry, keystroke \"%s\" may not be rebound"), newsc->keystr); - goto free_things; + /* Now find and delete any existing same shortcut in the menu(s). */ + for (s = sclist; s != NULL; s = s->next) { + if ((s->menus & menu) && !strcmp(s->keystr, keycopy)) + s->menus &= ~menu; } - } - /* Now find and delete any existing same shortcut in the menu(s). */ - for (s = sclist; s != NULL; s = s->next) { - if ((s->menus & menu) && !strcmp(s->keystr, keycopy)) - s->menus &= ~menu; - } - - if (dobind) { + if (dobind) { #ifndef NANO_TINY - /* If this is a toggle, copy its sequence number. */ - if (newsc->scfunc == do_toggle_void) { - for (s = sclist; s != NULL; s = s->next) - if (s->scfunc == do_toggle_void && s->toggle == newsc->toggle) - newsc->ordinal = s->ordinal; - } else - newsc->ordinal = 0; + /* If this is a toggle, copy its sequence number. */ + if (newsc->scfunc == do_toggle_void) { + for (s = sclist; s != NULL; s = s->next) + if (s->scfunc == do_toggle_void && s->toggle == newsc->toggle) + newsc->ordinal = s->ordinal; + } else + newsc->ordinal = 0; #endif - /* Add the new shortcut at the start of the list. */ - newsc->next = sclist; - sclist = newsc; - return; - } + /* Add the new shortcut at the start of the list. */ + newsc->next = sclist; + sclist = newsc; + return; + } free_things: - free(newsc); - free(keycopy); + free(newsc); + free(keycopy); } /* Verify that the given file exists, is not a folder nor a device. */ bool is_good_file(char *file) { - struct stat rcinfo; + struct stat rcinfo; - /* First check that the file exists and is readable. */ - if (access(file, R_OK) != 0) - return FALSE; + /* First check that the file exists and is readable. */ + if (access(file, R_OK) != 0) + return FALSE; - /* If the thing exists, it may not be a directory nor a device. */ - if (stat(file, &rcinfo) != -1 && (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"), file); - return FALSE; - } else - return TRUE; + /* If the thing exists, it may not be a directory nor a device. */ + if (stat(file, &rcinfo) != -1 && (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"), file); + return FALSE; + } else + return TRUE; } #ifdef ENABLE_COLOR /* Read and parse one included syntax file. */ static void parse_one_include(char *file) { - FILE *rcstream; + FILE *rcstream; - /* Don't open directories, character files, or block files. */ - if (!is_good_file(file)) - return; + /* Don't open directories, character files, or block files. */ + if (!is_good_file(file)) + return; - /* Open the included syntax file. */ - rcstream = fopen(file, "rb"); + /* Open the included syntax file. */ + rcstream = fopen(file, "rb"); - if (rcstream == NULL) { - rcfile_error(_("Error reading %s: %s"), file, strerror(errno)); - return; - } + if (rcstream == NULL) { + rcfile_error(_("Error reading %s: %s"), file, strerror(errno)); + return; + } - /* Use the name and line number position of the included syntax file - * while parsing it, so we can know where any errors in it are. */ - nanorc = file; - lineno = 0; + /* Use the name and line number position of the included syntax file + * while parsing it, so we can know where any errors in it are. */ + nanorc = file; + lineno = 0; #ifdef DEBUG - fprintf(stderr, "Parsing file \"%s\"\n", file); + fprintf(stderr, "Parsing file \"%s\"\n", file); #endif - parse_rcfile(rcstream, TRUE); + parse_rcfile(rcstream, TRUE); } /* Expand globs in the passed name, and parse the resultant files. */ void parse_includes(char *ptr) { - char *option, *nanorc_save = nanorc, *expanded; - size_t lineno_save = lineno, i; - glob_t files; + char *option, *nanorc_save = nanorc, *expanded; + size_t lineno_save = lineno, i; + glob_t files; - option = ptr; - if (*option == '"') - option++; - ptr = parse_argument(ptr); + option = ptr; + if (*option == '"') + option++; + ptr = parse_argument(ptr); - /* Expand tildes first, then the globs. */ - expanded = real_dir_from_tilde(option); + /* 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_one_include(files.gl_pathv[i]); - } else - rcfile_error(_("Error expanding %s: %s"), option, strerror(errno)); + if (glob(expanded, GLOB_ERR|GLOB_NOSORT, NULL, &files) == 0) { + for (i = 0; i < files.gl_pathc; ++i) + parse_one_include(files.gl_pathv[i]); + } else + rcfile_error(_("Error expanding %s: %s"), option, strerror(errno)); - globfree(&files); - free(expanded); + globfree(&files); + free(expanded); - /* We're done with the included file(s). Restore the original - * filename and line number position. */ - nanorc = nanorc_save; - lineno = lineno_save; + /* We're done with the included file(s). 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, * and set bright to TRUE if that color is bright. */ short color_to_short(const char *colorname, bool *bright) { - if (strncasecmp(colorname, "bright", 6) == 0) { - *bright = TRUE; - colorname += 6; - } + if (strncasecmp(colorname, "bright", 6) == 0) { + *bright = TRUE; + colorname += 6; + } - if (strcasecmp(colorname, "green") == 0) - return COLOR_GREEN; - else if (strcasecmp(colorname, "red") == 0) - return COLOR_RED; - else if (strcasecmp(colorname, "blue") == 0) - return COLOR_BLUE; - else if (strcasecmp(colorname, "white") == 0) - return COLOR_WHITE; - else if (strcasecmp(colorname, "yellow") == 0) - return COLOR_YELLOW; - else if (strcasecmp(colorname, "cyan") == 0) - return COLOR_CYAN; - else if (strcasecmp(colorname, "magenta") == 0) - return COLOR_MAGENTA; - else if (strcasecmp(colorname, "black") == 0) - return COLOR_BLACK; + if (strcasecmp(colorname, "green") == 0) + return COLOR_GREEN; + else if (strcasecmp(colorname, "red") == 0) + return COLOR_RED; + else if (strcasecmp(colorname, "blue") == 0) + return COLOR_BLUE; + else if (strcasecmp(colorname, "white") == 0) + return COLOR_WHITE; + else if (strcasecmp(colorname, "yellow") == 0) + return COLOR_YELLOW; + else if (strcasecmp(colorname, "cyan") == 0) + return COLOR_CYAN; + else if (strcasecmp(colorname, "magenta") == 0) + return COLOR_MAGENTA; + else if (strcasecmp(colorname, "black") == 0) + return COLOR_BLACK; - rcfile_error(N_("Color \"%s\" not understood.\n" - "Valid colors are \"green\", \"red\", \"blue\",\n" - "\"white\", \"yellow\", \"cyan\", \"magenta\" and\n" - "\"black\", with the optional prefix \"bright\"\n" - "for foreground colors."), colorname); - return -1; + rcfile_error(N_("Color \"%s\" not understood.\n" + "Valid colors are \"green\", \"red\", \"blue\",\n" + "\"white\", \"yellow\", \"cyan\", \"magenta\" and\n" + "\"black\", with the optional prefix \"bright\"\n" + "for foreground colors."), colorname); + return -1; } /* Parse the color string in the line at ptr, and add it to the current @@ -623,253 +623,253 @@ short color_to_short(const char *colorname, bool *bright) * to use, excluding or including REG_ICASE for case (in)sensitivity. */ void parse_colors(char *ptr, int rex_flags) { - short fg, bg; - bool bright = FALSE; - char *item; + short fg, bg; + bool bright = FALSE; + char *item; - if (!opensyntax) { - rcfile_error( - N_("A '%s' command requires a preceding 'syntax' command"), - "color"); - return; - } - - if (*ptr == '\0') { - rcfile_error(N_("Missing color name")); - return; - } - - item = ptr; - ptr = parse_next_word(ptr); - if (!parse_color_names(item, &fg, &bg, &bright)) - return; - - if (*ptr == '\0') { - rcfile_error(N_("Missing regex string after '%s' command"), "color"); - return; - } - - /* Now for the fun part. Start adding regexes to individual strings - * in the colorstrings array, woo! */ - while (ptr != NULL && *ptr != '\0') { - colortype *newcolor = NULL; - /* The container for a color plus its regexes. */ - bool goodstart; - /* Whether the start expression was valid. */ - bool expectend = FALSE; - /* Whether to expect an end= line. */ - - if (strncasecmp(ptr, "start=", 6) == 0) { - ptr += 6; - expectend = TRUE; + if (!opensyntax) { + rcfile_error( + N_("A '%s' command requires a preceding 'syntax' command"), + "color"); + return; } - if (*ptr != '"') { - rcfile_error( - N_("Regex strings must begin and end with a \" character")); - ptr = parse_next_regex(ptr); - continue; + if (*ptr == '\0') { + rcfile_error(N_("Missing color name")); + return; } - item = ++ptr; - ptr = parse_next_regex(ptr); - if (ptr == NULL) - break; + item = ptr; + ptr = parse_next_word(ptr); + if (!parse_color_names(item, &fg, &bg, &bright)) + return; - if (*item == '\0') { - rcfile_error(N_("Empty regex string")); - goodstart = FALSE; - } else - goodstart = nregcomp(item, rex_flags); - - /* If the starting regex is valid, initialize a new color struct, - * and hook it in at the tail of the linked list. */ - if (goodstart) { - newcolor = (colortype *)nmalloc(sizeof(colortype)); - - newcolor->fg = fg; - newcolor->bg = bg; - newcolor->bright = bright; - newcolor->rex_flags = rex_flags; - - newcolor->start_regex = mallocstrcpy(NULL, item); - newcolor->start = NULL; - - newcolor->end_regex = NULL; - newcolor->end = NULL; - - newcolor->next = NULL; - - if (lastcolor == NULL) - live_syntax->color = newcolor; - else - lastcolor->next = newcolor; - - lastcolor = newcolor; + if (*ptr == '\0') { + rcfile_error(N_("Missing regex string after '%s' command"), "color"); + return; } - if (!expectend) - continue; + /* Now for the fun part. Start adding regexes to individual strings + * in the colorstrings array, woo! */ + while (ptr != NULL && *ptr != '\0') { + colortype *newcolor = NULL; + /* The container for a color plus its regexes. */ + bool goodstart; + /* Whether the start expression was valid. */ + bool expectend = FALSE; + /* Whether to expect an end= line. */ - if (ptr == NULL || strncasecmp(ptr, "end=", 4) != 0) { - rcfile_error(N_("\"start=\" requires a corresponding \"end=\"")); - return; + if (strncasecmp(ptr, "start=", 6) == 0) { + ptr += 6; + expectend = TRUE; + } + + if (*ptr != '"') { + rcfile_error( + N_("Regex strings must begin and end with a \" character")); + ptr = parse_next_regex(ptr); + continue; + } + + item = ++ptr; + ptr = parse_next_regex(ptr); + if (ptr == NULL) + break; + + if (*item == '\0') { + rcfile_error(N_("Empty regex string")); + goodstart = FALSE; + } else + goodstart = nregcomp(item, rex_flags); + + /* If the starting regex is valid, initialize a new color struct, + * and hook it in at the tail of the linked list. */ + if (goodstart) { + newcolor = (colortype *)nmalloc(sizeof(colortype)); + + newcolor->fg = fg; + newcolor->bg = bg; + newcolor->bright = bright; + newcolor->rex_flags = rex_flags; + + newcolor->start_regex = mallocstrcpy(NULL, item); + newcolor->start = NULL; + + newcolor->end_regex = NULL; + newcolor->end = NULL; + + newcolor->next = NULL; + + if (lastcolor == NULL) + live_syntax->color = newcolor; + else + lastcolor->next = newcolor; + + lastcolor = newcolor; + } + + if (!expectend) + continue; + + if (ptr == NULL || strncasecmp(ptr, "end=", 4) != 0) { + rcfile_error(N_("\"start=\" requires a corresponding \"end=\"")); + return; + } + + ptr += 4; + if (*ptr != '"') { + rcfile_error(N_("Regex strings must begin and end with a \" character")); + continue; + } + + item = ++ptr; + ptr = parse_next_regex(ptr); + if (ptr == NULL) + break; + + if (*item == '\0') { + rcfile_error(N_("Empty regex string")); + continue; + } + + /* If the start regex was invalid, skip past the end regex + * to stay in sync. */ + if (!goodstart) + continue; + + /* If it's valid, save the ending regex string. */ + if (nregcomp(item, rex_flags)) + newcolor->end_regex = mallocstrcpy(NULL, item); + + /* Lame way to skip another static counter. */ + newcolor->id = live_syntax->nmultis; + live_syntax->nmultis++; } - - ptr += 4; - if (*ptr != '"') { - rcfile_error(N_("Regex strings must begin and end with a \" character")); - continue; - } - - item = ++ptr; - ptr = parse_next_regex(ptr); - if (ptr == NULL) - break; - - if (*item == '\0') { - rcfile_error(N_("Empty regex string")); - continue; - } - - /* If the start regex was invalid, skip past the end regex - * to stay in sync. */ - if (!goodstart) - continue; - - /* If it's valid, save the ending regex string. */ - if (nregcomp(item, rex_flags)) - newcolor->end_regex = mallocstrcpy(NULL, item); - - /* Lame way to skip another static counter. */ - newcolor->id = live_syntax->nmultis; - live_syntax->nmultis++; - } } /* Parse the color name, or pair of color names, in combostr. */ bool parse_color_names(char *combostr, short *fg, short *bg, bool *bright) { - char *comma = strchr(combostr, ','); + char *comma = strchr(combostr, ','); - if (comma != NULL) { - *bg = color_to_short(comma + 1, bright); - if (*bright) { - rcfile_error(N_("A background color cannot be bright")); - return FALSE; - } - *comma = '\0'; - } else - *bg = -1; + if (comma != NULL) { + *bg = color_to_short(comma + 1, bright); + if (*bright) { + rcfile_error(N_("A background color cannot be bright")); + return FALSE; + } + *comma = '\0'; + } else + *bg = -1; - if (comma != combostr) { - *fg = color_to_short(combostr, bright); + if (comma != combostr) { + *fg = color_to_short(combostr, bright); - /* If the specified foreground color is bad, ignore the regexes. */ - if (*fg == -1) - return FALSE; - } else - *fg = -1; + /* If the specified foreground color is bad, ignore the regexes. */ + if (*fg == -1) + return FALSE; + } else + *fg = -1; - return TRUE; + return TRUE; } /* Read regex strings enclosed in double quotes from the line pointed at * by ptr, and store them quoteless in the passed storage place. */ void grab_and_store(const char *kind, char *ptr, regexlisttype **storage) { - regexlisttype *lastthing; + regexlisttype *lastthing; - if (!opensyntax) { - rcfile_error( - N_("A '%s' command requires a preceding 'syntax' command"), kind); - return; - } - - /* The default syntax doesn't take any file matching stuff. */ - if (strcmp(live_syntax->name, "default") == 0 && *ptr != '\0') { - rcfile_error( - N_("The \"default\" syntax does not accept '%s' regexes"), kind); - return; - } - - if (*ptr == '\0') { - rcfile_error(N_("Missing regex string after '%s' command"), kind); - return; - } - - lastthing = *storage; - - /* If there was an earlier command, go to the last of those regexes. */ - while (lastthing != NULL && lastthing->next != NULL) - lastthing = lastthing->next; - - /* Now gather any valid regexes and add them to the linked list. */ - while (*ptr != '\0') { - const char *regexstring; - regexlisttype *newthing; - - if (*ptr != '"') { - rcfile_error( - N_("Regex strings must begin and end with a \" character")); - return; + if (!opensyntax) { + rcfile_error( + N_("A '%s' command requires a preceding 'syntax' command"), kind); + return; } - regexstring = ++ptr; - ptr = parse_next_regex(ptr); - if (ptr == NULL) - return; + /* The default syntax doesn't take any file matching stuff. */ + if (strcmp(live_syntax->name, "default") == 0 && *ptr != '\0') { + rcfile_error( + N_("The \"default\" syntax does not accept '%s' regexes"), kind); + return; + } - /* If the regex string is malformed, skip it. */ - if (!nregcomp(regexstring, NANO_REG_EXTENDED | REG_NOSUB)) - continue; + if (*ptr == '\0') { + rcfile_error(N_("Missing regex string after '%s' command"), kind); + return; + } - /* Copy the regex into a struct, and hook this in at the end. */ - newthing = (regexlisttype *)nmalloc(sizeof(regexlisttype)); - newthing->full_regex = mallocstrcpy(NULL, regexstring); - newthing->next = NULL; + lastthing = *storage; - if (lastthing == NULL) - *storage = newthing; - else - lastthing->next = newthing; + /* If there was an earlier command, go to the last of those regexes. */ + while (lastthing != NULL && lastthing->next != NULL) + lastthing = lastthing->next; - lastthing = newthing; - } + /* Now gather any valid regexes and add them to the linked list. */ + while (*ptr != '\0') { + const char *regexstring; + regexlisttype *newthing; + + if (*ptr != '"') { + rcfile_error( + N_("Regex strings must begin and end with a \" character")); + return; + } + + regexstring = ++ptr; + ptr = parse_next_regex(ptr); + if (ptr == NULL) + return; + + /* If the regex string is malformed, skip it. */ + if (!nregcomp(regexstring, NANO_REG_EXTENDED | REG_NOSUB)) + continue; + + /* Copy the regex into a struct, and hook this in at the end. */ + newthing = (regexlisttype *)nmalloc(sizeof(regexlisttype)); + newthing->full_regex = mallocstrcpy(NULL, regexstring); + newthing->next = NULL; + + if (lastthing == NULL) + *storage = newthing; + else + lastthing->next = newthing; + + lastthing = newthing; + } } /* Gather and store the string after a comment/linter/formatter command. */ void pick_up_name(const char *kind, char *ptr, char **storage) { - assert(ptr != NULL); + assert(ptr != NULL); - if (!opensyntax) { - rcfile_error( - N_("A '%s' command requires a preceding 'syntax' command"), kind); - return; - } - - if (*ptr == '\0') { - rcfile_error(N_("Missing argument after '%s'"), kind); - return; - } - - /* If the argument starts with a quote, find the terminating quote. */ - if (*ptr == '"') { - char *look = ++ptr; - - look += strlen(ptr); - - while (*look != '"') { - if (--look < ptr) { - rcfile_error(N_("Argument of '%s' lacks closing \""), kind); + if (!opensyntax) { + rcfile_error( + N_("A '%s' command requires a preceding 'syntax' command"), kind); return; - } } - *look = '\0'; - } - *storage = mallocstrcpy(*storage, ptr); + if (*ptr == '\0') { + rcfile_error(N_("Missing argument after '%s'"), kind); + return; + } + + /* If the argument starts with a quote, find the terminating quote. */ + if (*ptr == '"') { + char *look = ++ptr; + + look += strlen(ptr); + + while (*look != '"') { + if (--look < ptr) { + rcfile_error(N_("Argument of '%s' lacks closing \""), kind); + return; + } + } + *look = '\0'; + } + + *storage = mallocstrcpy(*storage, ptr); } #endif /* ENABLE_COLOR */ @@ -877,27 +877,27 @@ void pick_up_name(const char *kind, char *ptr, char **storage) * function that we consider 'vital' (such as "Exit"). */ static void check_vitals_mapped(void) { - subnfunc *f; - int v; + subnfunc *f; + int v; #define VITALS 5 - void (*vitals[VITALS])(void) = { do_exit, do_exit, do_cancel, do_cancel, do_cancel }; - int inmenus[VITALS] = { MMAIN, MHELP, MWHEREIS, MREPLACE, MGOTOLINE }; + void (*vitals[VITALS])(void) = { do_exit, do_exit, do_cancel, do_cancel, do_cancel }; + int inmenus[VITALS] = { MMAIN, MHELP, MWHEREIS, MREPLACE, MGOTOLINE }; - for (v = 0; v < VITALS; v++) { - for (f = allfuncs; f != NULL; f = f->next) { - if (f->scfunc == vitals[v] && f->menus & inmenus[v]) { - const sc *s = first_sc_for(inmenus[v], f->scfunc); - if (!s) { - 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); + for (v = 0; v < VITALS; v++) { + for (f = allfuncs; f != NULL; f = f->next) { + if (f->scfunc == vitals[v] && f->menus & inmenus[v]) { + const sc *s = first_sc_for(inmenus[v], f->scfunc); + if (!s) { + 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; + } } - break; - } } - } } /* Parse the rcfile, once it has been opened successfully at rcstream, @@ -905,362 +905,362 @@ static void check_vitals_mapped(void) * to contain only color syntax commands. */ void parse_rcfile(FILE *rcstream, bool syntax_only) { - char *buf = NULL; - ssize_t len; - size_t n = 0; + char *buf = NULL; + ssize_t len; + size_t n = 0; - while ((len = getline(&buf, &n, rcstream)) > 0) { - char *ptr, *keyword, *option; - int set = 0; - size_t i; + while ((len = getline(&buf, &n, rcstream)) > 0) { + char *ptr, *keyword, *option; + int set = 0; + size_t i; - /* Ignore the newline. */ - if (buf[len - 1] == '\n') - buf[len - 1] = '\0'; + /* Ignore the newline. */ + if (buf[len - 1] == '\n') + buf[len - 1] = '\0'; - lineno++; - ptr = buf; - while (isblank((unsigned char)*ptr)) - ptr++; + lineno++; + ptr = buf; + while (isblank((unsigned char)*ptr)) + ptr++; - /* If we have a blank line or a comment, skip to the next - * line. */ - if (*ptr == '\0' || *ptr == '#') - continue; + /* If we have a blank line or a comment, skip to the next + * line. */ + if (*ptr == '\0' || *ptr == '#') + continue; - /* Otherwise, skip to the next space. */ - keyword = ptr; - ptr = parse_next_word(ptr); + /* Otherwise, skip to the next space. */ + keyword = ptr; + ptr = parse_next_word(ptr); #ifdef ENABLE_COLOR - /* Handle extending first... */ - if (strcasecmp(keyword, "extendsyntax") == 0) { - syntaxtype *sint; - char *syntaxname = ptr; + /* Handle extending first... */ + if (strcasecmp(keyword, "extendsyntax") == 0) { + syntaxtype *sint; + char *syntaxname = ptr; - ptr = parse_next_word(ptr); + ptr = parse_next_word(ptr); - for (sint = syntaxes; sint != NULL; sint = sint->next) - if (!strcmp(sint->name, syntaxname)) - break; + for (sint = syntaxes; sint != NULL; sint = sint->next) + if (!strcmp(sint->name, syntaxname)) + break; - if (sint == NULL) { - rcfile_error(N_("Could not find syntax \"%s\" to extend"), - syntaxname); - opensyntax = FALSE; - continue; - } + if (sint == NULL) { + rcfile_error(N_("Could not find syntax \"%s\" to extend"), + syntaxname); + opensyntax = FALSE; + continue; + } - live_syntax = sint; - opensyntax = TRUE; + live_syntax = sint; + opensyntax = TRUE; - /* Refind the tail of the color list for this syntax. */ - lastcolor = sint->color; - if (lastcolor != NULL) - while (lastcolor->next != NULL) - lastcolor = lastcolor->next; + /* Refind the tail of the color list for this syntax. */ + lastcolor = sint->color; + if (lastcolor != NULL) + while (lastcolor->next != NULL) + lastcolor = lastcolor->next; - keyword = ptr; - ptr = parse_next_word(ptr); - } + keyword = ptr; + ptr = parse_next_word(ptr); + } - /* Try to parse the keyword. */ - if (strcasecmp(keyword, "syntax") == 0) { - if (opensyntax && lastcolor == NULL) - rcfile_error(N_("Syntax \"%s\" has no color commands"), - live_syntax->name); - parse_syntax(ptr); - } - else if (strcasecmp(keyword, "header") == 0) - grab_and_store("header", ptr, &live_syntax->headers); - else if (strcasecmp(keyword, "magic") == 0) + /* Try to parse the keyword. */ + if (strcasecmp(keyword, "syntax") == 0) { + if (opensyntax && lastcolor == NULL) + rcfile_error(N_("Syntax \"%s\" has no color commands"), + live_syntax->name); + parse_syntax(ptr); + } + else if (strcasecmp(keyword, "header") == 0) + grab_and_store("header", ptr, &live_syntax->headers); + else if (strcasecmp(keyword, "magic") == 0) #ifdef HAVE_LIBMAGIC - grab_and_store("magic", ptr, &live_syntax->magics); + grab_and_store("magic", ptr, &live_syntax->magics); #else - ; + ; #endif - else if (strcasecmp(keyword, "comment") == 0) + else if (strcasecmp(keyword, "comment") == 0) #ifdef ENABLE_COMMENT - pick_up_name("comment", ptr, &live_syntax->comment); + pick_up_name("comment", ptr, &live_syntax->comment); #else - ; + ; #endif - else if (strcasecmp(keyword, "color") == 0) - parse_colors(ptr, NANO_REG_EXTENDED); - else if (strcasecmp(keyword, "icolor") == 0) - parse_colors(ptr, NANO_REG_EXTENDED | REG_ICASE); - else if (strcasecmp(keyword, "linter") == 0) - pick_up_name("linter", ptr, &live_syntax->linter); - else if (strcasecmp(keyword, "formatter") == 0) + else if (strcasecmp(keyword, "color") == 0) + parse_colors(ptr, NANO_REG_EXTENDED); + else if (strcasecmp(keyword, "icolor") == 0) + parse_colors(ptr, NANO_REG_EXTENDED | REG_ICASE); + else if (strcasecmp(keyword, "linter") == 0) + pick_up_name("linter", ptr, &live_syntax->linter); + else if (strcasecmp(keyword, "formatter") == 0) #ifdef ENABLE_SPELLER - pick_up_name("formatter", ptr, &live_syntax->formatter); + pick_up_name("formatter", ptr, &live_syntax->formatter); #else - ; + ; #endif - else if (syntax_only) - rcfile_error(N_("Command \"%s\" not allowed in included file"), - keyword); - else if (strcasecmp(keyword, "include") == 0) - parse_includes(ptr); - else + else if (syntax_only) + rcfile_error(N_("Command \"%s\" not allowed in included file"), + keyword); + else if (strcasecmp(keyword, "include") == 0) + parse_includes(ptr); + else #endif /* ENABLE_COLOR */ - if (strcasecmp(keyword, "set") == 0) - set = 1; - else if (strcasecmp(keyword, "unset") == 0) - set = -1; - else if (strcasecmp(keyword, "bind") == 0) - parse_binding(ptr, TRUE); - else if (strcasecmp(keyword, "unbind") == 0) - parse_binding(ptr, FALSE); - else - rcfile_error(N_("Command \"%s\" not understood"), keyword); + if (strcasecmp(keyword, "set") == 0) + set = 1; + else if (strcasecmp(keyword, "unset") == 0) + set = -1; + else if (strcasecmp(keyword, "bind") == 0) + parse_binding(ptr, TRUE); + else if (strcasecmp(keyword, "unbind") == 0) + parse_binding(ptr, FALSE); + else + rcfile_error(N_("Command \"%s\" not understood"), keyword); #ifdef ENABLE_COLOR - /* If a syntax was extended, it stops at the end of the command. */ - if (live_syntax != syntaxes) - opensyntax = FALSE; + /* If a syntax was extended, it stops at the end of the command. */ + if (live_syntax != syntaxes) + opensyntax = FALSE; #endif - if (set == 0) - continue; + if (set == 0) + continue; - if (*ptr == '\0') { - rcfile_error(N_("Missing option")); - continue; - } + if (*ptr == '\0') { + rcfile_error(N_("Missing option")); + continue; + } - option = ptr; - ptr = parse_next_word(ptr); + option = ptr; + ptr = parse_next_word(ptr); - /* Find the just read name among the existing options. */ - for (i = 0; rcopts[i].name != NULL; i++) { - if (strcasecmp(option, rcopts[i].name) == 0) - break; - } + /* Find the just read name among the existing options. */ + for (i = 0; rcopts[i].name != NULL; i++) { + if (strcasecmp(option, rcopts[i].name) == 0) + break; + } - if (rcopts[i].name == NULL) { - rcfile_error(N_("Unknown option \"%s\""), option); - continue; - } + if (rcopts[i].name == NULL) { + rcfile_error(N_("Unknown option \"%s\""), option); + continue; + } #ifdef DEBUG - fprintf(stderr, " Option name = \"%s\"\n", rcopts[i].name); - fprintf(stderr, " Flag = %ld\n", rcopts[i].flag); + fprintf(stderr, " Option name = \"%s\"\n", rcopts[i].name); + fprintf(stderr, " Flag = %ld\n", rcopts[i].flag); #endif - /* First handle unsetting. */ - if (set == -1) { - if (rcopts[i].flag != 0) - UNSET(rcopts[i].flag); - else - rcfile_error(N_("Cannot unset option \"%s\""), rcopts[i].name); - continue; - } + /* First handle unsetting. */ + if (set == -1) { + if (rcopts[i].flag != 0) + UNSET(rcopts[i].flag); + else + rcfile_error(N_("Cannot unset option \"%s\""), rcopts[i].name); + continue; + } - /* If the option has a flag, it doesn't take an argument. */ - if (rcopts[i].flag != 0) { - SET(rcopts[i].flag); - continue; - } + /* If the option has a flag, it doesn't take an argument. */ + if (rcopts[i].flag != 0) { + SET(rcopts[i].flag); + continue; + } - /* The option doesn't have a flag, so it takes an argument. */ - if (*ptr == '\0') { - rcfile_error(N_("Option \"%s\" requires an argument"), - rcopts[i].name); - continue; - } + /* The option doesn't have a flag, so it takes an argument. */ + if (*ptr == '\0') { + rcfile_error(N_("Option \"%s\" requires an argument"), + rcopts[i].name); + continue; + } - option = ptr; - if (*option == '"') - option++; - ptr = parse_argument(ptr); + option = ptr; + if (*option == '"') + option++; + ptr = parse_argument(ptr); - option = mallocstrcpy(NULL, option); + option = mallocstrcpy(NULL, option); #ifdef DEBUG - fprintf(stderr, " Option argument = \"%s\"\n", option); + fprintf(stderr, " Option argument = \"%s\"\n", option); #endif - /* Make sure the option argument is a valid multibyte string. */ - if (!is_valid_mbstring(option)) { - rcfile_error(N_("Argument is not a valid multibyte string")); - continue; - } + /* Make sure the option argument is a valid multibyte string. */ + if (!is_valid_mbstring(option)) { + rcfile_error(N_("Argument is not a valid multibyte string")); + continue; + } #ifdef ENABLE_COLOR - if (strcasecmp(rcopts[i].name, "titlecolor") == 0) - specified_color_combo[TITLE_BAR] = option; - else if (strcasecmp(rcopts[i].name, "numbercolor") == 0) - specified_color_combo[LINE_NUMBER] = option; - else if (strcasecmp(rcopts[i].name, "selectedcolor") == 0) - specified_color_combo[SELECTED_TEXT] = 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 + if (strcasecmp(rcopts[i].name, "titlecolor") == 0) + specified_color_combo[TITLE_BAR] = option; + else if (strcasecmp(rcopts[i].name, "numbercolor") == 0) + specified_color_combo[LINE_NUMBER] = option; + else if (strcasecmp(rcopts[i].name, "selectedcolor") == 0) + specified_color_combo[SELECTED_TEXT] = 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 #ifdef ENABLE_OPERATINGDIR - if (strcasecmp(rcopts[i].name, "operatingdir") == 0) - operating_dir = option; - else + if (strcasecmp(rcopts[i].name, "operatingdir") == 0) + operating_dir = option; + else #endif #ifdef ENABLED_WRAPORJUSTIFY - if (strcasecmp(rcopts[i].name, "fill") == 0) { - if (!parse_num(option, &wrap_at)) { - rcfile_error(N_("Requested fill size \"%s\" is invalid"), - option); - wrap_at = -CHARS_FROM_EOL; - } else - UNSET(NO_WRAP); - free(option); - } else + if (strcasecmp(rcopts[i].name, "fill") == 0) { + if (!parse_num(option, &wrap_at)) { + rcfile_error(N_("Requested fill size \"%s\" is invalid"), + option); + wrap_at = -CHARS_FROM_EOL; + } else + UNSET(NO_WRAP); + free(option); + } else #endif #ifndef NANO_TINY - if (strcasecmp(rcopts[i].name, "matchbrackets") == 0) { - matchbrackets = option; - if (has_blank_mbchars(matchbrackets)) { - rcfile_error(N_("Non-blank characters required")); - free(matchbrackets); - matchbrackets = NULL; - } - } else if (strcasecmp(rcopts[i].name, "whitespace") == 0) { - whitespace = option; - if (mbstrlen(whitespace) != 2 || strlenpt(whitespace) != 2) { - rcfile_error(N_("Two single-column characters required")); - free(whitespace); - whitespace = NULL; - } else { - whitespace_len[0] = parse_mbchar(whitespace, NULL, NULL); - whitespace_len[1] = parse_mbchar(whitespace + - whitespace_len[0], NULL, NULL); - } - } else + if (strcasecmp(rcopts[i].name, "matchbrackets") == 0) { + matchbrackets = option; + if (has_blank_mbchars(matchbrackets)) { + rcfile_error(N_("Non-blank characters required")); + free(matchbrackets); + matchbrackets = NULL; + } + } else if (strcasecmp(rcopts[i].name, "whitespace") == 0) { + whitespace = option; + if (mbstrlen(whitespace) != 2 || strlenpt(whitespace) != 2) { + rcfile_error(N_("Two single-column characters required")); + free(whitespace); + whitespace = NULL; + } else { + whitespace_len[0] = parse_mbchar(whitespace, NULL, NULL); + whitespace_len[1] = parse_mbchar(whitespace + + whitespace_len[0], NULL, NULL); + } + } else #endif #ifdef ENABLE_JUSTIFY - if (strcasecmp(rcopts[i].name, "punct") == 0) { - punct = option; - if (has_blank_mbchars(punct)) { - rcfile_error(N_("Non-blank characters required")); - free(punct); - punct = NULL; - } - } else if (strcasecmp(rcopts[i].name, "brackets") == 0) { - brackets = option; - if (has_blank_mbchars(brackets)) { - rcfile_error(N_("Non-blank characters required")); - free(brackets); - brackets = NULL; - } - } else if (strcasecmp(rcopts[i].name, "quotestr") == 0) - quotestr = option; - else + if (strcasecmp(rcopts[i].name, "punct") == 0) { + punct = option; + if (has_blank_mbchars(punct)) { + rcfile_error(N_("Non-blank characters required")); + free(punct); + punct = NULL; + } + } else if (strcasecmp(rcopts[i].name, "brackets") == 0) { + brackets = option; + if (has_blank_mbchars(brackets)) { + rcfile_error(N_("Non-blank characters required")); + free(brackets); + brackets = NULL; + } + } else if (strcasecmp(rcopts[i].name, "quotestr") == 0) + quotestr = option; + else #endif #ifndef NANO_TINY - if (strcasecmp(rcopts[i].name, "backupdir") == 0) - backup_dir = option; - else - if (strcasecmp(rcopts[i].name, "wordchars") == 0) - word_chars = option; - else + if (strcasecmp(rcopts[i].name, "backupdir") == 0) + backup_dir = option; + else + if (strcasecmp(rcopts[i].name, "wordchars") == 0) + word_chars = option; + else #endif #ifdef ENABLE_SPELLER - if (strcasecmp(rcopts[i].name, "speller") == 0) - alt_speller = option; - else + if (strcasecmp(rcopts[i].name, "speller") == 0) + alt_speller = option; + else #endif - if (strcasecmp(rcopts[i].name, "tabsize") == 0) { - if (!parse_num(option, &tabsize) || tabsize <= 0) { - rcfile_error(N_("Requested tab size \"%s\" is invalid"), - option); - tabsize = -1; - } - free(option); - } else - assert(FALSE); - } + if (strcasecmp(rcopts[i].name, "tabsize") == 0) { + if (!parse_num(option, &tabsize) || tabsize <= 0) { + rcfile_error(N_("Requested tab size \"%s\" is invalid"), + option); + tabsize = -1; + } + free(option); + } else + assert(FALSE); + } #ifdef ENABLE_COLOR - if (opensyntax && lastcolor == NULL) - rcfile_error(N_("Syntax \"%s\" has no color commands"), - live_syntax->name); + if (opensyntax && lastcolor == NULL) + rcfile_error(N_("Syntax \"%s\" has no color commands"), + live_syntax->name); - opensyntax = FALSE; + opensyntax = FALSE; #endif - free(buf); - fclose(rcstream); - lineno = 0; + free(buf); + fclose(rcstream); + lineno = 0; - return; + return; } /* Read and interpret one of the two nanorc files. */ void parse_one_nanorc(void) { - FILE *rcstream; + FILE *rcstream; - /* Don't try to open directories nor devices. */ - if (!is_good_file(nanorc)) - return; + /* Don't try to open directories nor devices. */ + if (!is_good_file(nanorc)) + return; #ifdef DEBUG - fprintf(stderr, "Going to parse file \"%s\"\n", nanorc); + fprintf(stderr, "Going to parse file \"%s\"\n", nanorc); #endif - rcstream = fopen(nanorc, "rb"); + rcstream = fopen(nanorc, "rb"); - /* If opening the file succeeded, parse it. Otherwise, only - * complain if the file actually exists. */ - if (rcstream != NULL) - parse_rcfile(rcstream, FALSE); - else if (errno != ENOENT) - rcfile_error(N_("Error reading %s: %s"), nanorc, strerror(errno)); + /* If opening the file succeeded, parse it. Otherwise, only + * complain if the file actually exists. */ + if (rcstream != NULL) + parse_rcfile(rcstream, FALSE); + else if (errno != ENOENT) + rcfile_error(N_("Error reading %s: %s"), nanorc, strerror(errno)); } bool have_nanorc(const char *path, char *name) { - if (path == NULL) - return FALSE; + if (path == NULL) + return FALSE; - free(nanorc); - nanorc = concatenate(path, name); + free(nanorc); + nanorc = concatenate(path, name); - return is_good_file(nanorc); + return is_good_file(nanorc); } /* First read the system-wide rcfile, then the user's rcfile. */ void do_rcfiles(void) { - const char *xdgconfdir; + const char *xdgconfdir; - nanorc = mallocstrcpy(nanorc, SYSCONFDIR "/nanorc"); + nanorc = mallocstrcpy(nanorc, SYSCONFDIR "/nanorc"); - /* Process the system-wide nanorc. */ - parse_one_nanorc(); + /* Process the system-wide nanorc. */ + parse_one_nanorc(); - /* When configured with --disable-wrapping-as-root, turn wrapping off - * for root, so that only root's .nanorc or --fill can turn it on. */ + /* When configured with --disable-wrapping-as-root, turn wrapping off + * for root, so that only root's .nanorc or --fill can turn it on. */ #ifdef DISABLE_ROOTWRAPPING - if (geteuid() == NANO_ROOT_UID) - SET(NO_WRAP); + if (geteuid() == NANO_ROOT_UID) + SET(NO_WRAP); #endif - get_homedir(); - xdgconfdir = getenv("XDG_CONFIG_HOME"); + get_homedir(); + xdgconfdir = getenv("XDG_CONFIG_HOME"); - /* Now try the to find a nanorc file in the user's home directory - * or in the XDG configuration directories. */ - if (have_nanorc(homedir, "/." RCFILE_NAME)) - parse_one_nanorc(); - else if (have_nanorc(xdgconfdir, "/nano/" RCFILE_NAME)) - parse_one_nanorc(); - else if (have_nanorc(homedir, "/.config/nano/" RCFILE_NAME)) - parse_one_nanorc(); - else if (homedir == NULL && xdgconfdir == NULL) - rcfile_error(N_("I can't find my home directory! Wah!")); + /* Now try the to find a nanorc file in the user's home directory + * or in the XDG configuration directories. */ + if (have_nanorc(homedir, "/." RCFILE_NAME)) + parse_one_nanorc(); + else if (have_nanorc(xdgconfdir, "/nano/" RCFILE_NAME)) + parse_one_nanorc(); + else if (have_nanorc(homedir, "/.config/nano/" RCFILE_NAME)) + parse_one_nanorc(); + else if (homedir == NULL && xdgconfdir == NULL) + rcfile_error(N_("I can't find my home directory! Wah!")); - check_vitals_mapped(); + check_vitals_mapped(); - free(nanorc); + free(nanorc); } #endif /* ENABLE_NANORC */ diff --git a/src/search.c b/src/search.c index a6ea882b..d268cd59 100644 --- a/src/search.c +++ b/src/search.c @@ -27,53 +27,53 @@ #endif static bool came_full_circle = FALSE; - /* Have we reached the starting line again while searching? */ + /* Have we reached the starting line again while searching? */ static bool regexp_compiled = FALSE; - /* Have we compiled any regular expressions? */ + /* Have we compiled any regular expressions? */ /* Compile the given regular expression and store it in search_regexp. * Return TRUE if the expression is valid, and FALSE otherwise. */ bool regexp_init(const char *regexp) { - int value = regcomp(&search_regexp, fixbounds(regexp), - NANO_REG_EXTENDED | (ISSET(CASE_SENSITIVE) ? 0 : REG_ICASE)); + int value = regcomp(&search_regexp, fixbounds(regexp), + NANO_REG_EXTENDED | (ISSET(CASE_SENSITIVE) ? 0 : REG_ICASE)); - /* If regex compilation failed, show the error message. */ - if (value != 0) { - size_t len = regerror(value, &search_regexp, NULL, 0); - char *str = charalloc(len); + /* If regex compilation failed, show the error message. */ + if (value != 0) { + size_t len = regerror(value, &search_regexp, NULL, 0); + char *str = charalloc(len); - regerror(value, &search_regexp, str, len); - statusline(ALERT, _("Bad regex \"%s\": %s"), regexp, str); - free(str); + regerror(value, &search_regexp, str, len); + statusline(ALERT, _("Bad regex \"%s\": %s"), regexp, str); + free(str); - return FALSE; - } + return FALSE; + } - regexp_compiled = TRUE; + regexp_compiled = TRUE; - return TRUE; + return TRUE; } /* Decompile the compiled regular expression we used in the last * search, if any. */ void regexp_cleanup(void) { - if (regexp_compiled) { - regexp_compiled = FALSE; - regfree(&search_regexp); - } + if (regexp_compiled) { + regexp_compiled = FALSE; + regfree(&search_regexp); + } } /* Report on the status bar that the given string was not found. */ void not_found_msg(const char *str) { - char *disp = display_string(str, 0, (COLS / 2) + 1, FALSE); - size_t numchars = actual_x(disp, strnlenpt(disp, COLS / 2)); + char *disp = display_string(str, 0, (COLS / 2) + 1, FALSE); + size_t numchars = actual_x(disp, strnlenpt(disp, COLS / 2)); - statusline(HUSH, _("\"%.*s%s\" not found"), numchars, disp, - (disp[numchars] == '\0') ? "" : "..."); - free(disp); + statusline(HUSH, _("\"%.*s%s\" not found"), numchars, disp, + (disp[numchars] == '\0') ? "" : "..."); + free(disp); } /* Abort the current search or replace. Clean up by displaying the main @@ -83,10 +83,10 @@ void not_found_msg(const char *str) void search_replace_abort(void) { #ifndef NANO_TINY - if (openfile->mark) - refresh_needed = TRUE; + if (openfile->mark) + refresh_needed = TRUE; #endif - regexp_cleanup(); + regexp_cleanup(); } /* Set up the system variables for a search or replace. If use_answer @@ -100,102 +100,102 @@ void search_replace_abort(void) * from do_search(). */ int search_init(bool replacing, bool use_answer) { - int i = 0; - char *buf; - static char *backupstring = NULL; - /* The search string we'll be using. */ - functionptrtype func; + int i = 0; + char *buf; + static char *backupstring = NULL; + /* The search string we'll be using. */ + functionptrtype func; - /* If use_answer is TRUE, set backupstring to answer and get out. */ - if (use_answer) { - backupstring = mallocstrcpy(backupstring, answer); - return 0; - } - - /* We display the search prompt below. If the user types a partial - * search string and then Replace or a toggle, we will return to - * do_search() or do_replace() and be called again. In that case, - * we should put the same search string back up. */ - - if (*last_search != '\0') { - char *disp = display_string(last_search, 0, COLS / 3, FALSE); - - buf = charalloc(strlen(disp) + 7); - /* We use (COLS / 3) here because we need to see more on the line. */ - sprintf(buf, " [%s%s]", disp, - (strlenpt(last_search) > COLS / 3) ? "..." : ""); - free(disp); - } else - buf = mallocstrcpy(NULL, ""); - - /* This is now one simple call. It just does a lot. */ - i = do_prompt(FALSE, FALSE, - inhelp ? MFINDINHELP : (replacing ? MREPLACE : MWHEREIS), - backupstring, &search_history, - /* TRANSLATORS: This is the main search prompt. */ - edit_refresh, "%s%s%s%s%s%s", _("Search"), - /* TRANSLATORS: The next three modify the search prompt. */ - ISSET(CASE_SENSITIVE) ? _(" [Case Sensitive]") : "", - ISSET(USE_REGEXP) ? _(" [Regexp]") : "", - ISSET(BACKWARDS_SEARCH) ? _(" [Backwards]") : "", replacing ? -#ifndef NANO_TINY - /* TRANSLATORS: The next two modify the search prompt. */ - openfile->mark ? _(" (to replace) in selection") : -#endif - _(" (to replace)") : "", buf); - - /* Release buf now that we don't need it anymore. */ - free(buf); - - free(backupstring); - backupstring = NULL; - - /* If the search was cancelled, or we have a blank answer and - * nothing was searched for yet during this session, get out. */ - if (i == -1 || (i == -2 && *last_search == '\0')) { - statusbar(_("Cancelled")); - return -1; - } - - /* If Enter was pressed, see what we got. */ - if (i == 0 || i == -2) { - /* If an answer was given, remember it. */ - if (*answer != '\0') { - last_search = mallocstrcpy(last_search, answer); -#ifdef ENABLE_HISTORIES - update_history(&search_history, answer); -#endif + /* If use_answer is TRUE, set backupstring to answer and get out. */ + if (use_answer) { + backupstring = mallocstrcpy(backupstring, answer); + return 0; } - if (ISSET(USE_REGEXP) && !regexp_init(last_search)) - return -1; - else - return 0; /* We have a valid string or regex. */ - } - func = func_from_key(&i); + /* We display the search prompt below. If the user types a partial + * search string and then Replace or a toggle, we will return to + * do_search() or do_replace() and be called again. In that case, + * we should put the same search string back up. */ - if (func == case_sens_void) { - TOGGLE(CASE_SENSITIVE); - backupstring = mallocstrcpy(backupstring, answer); - return 1; - } else if (func == backwards_void) { - TOGGLE(BACKWARDS_SEARCH); - backupstring = mallocstrcpy(backupstring, answer); - return 1; - } else if (func == regexp_void) { - TOGGLE(USE_REGEXP); - backupstring = mallocstrcpy(backupstring, answer); - return 1; - } else if (func == flip_replace) { - backupstring = mallocstrcpy(backupstring, answer); - return -2; /* Call the opposite search function. */ - } else if (func == do_gotolinecolumn_void) { - do_gotolinecolumn(openfile->current->lineno, - openfile->placewewant + 1, TRUE, TRUE); - return 3; - } + if (*last_search != '\0') { + char *disp = display_string(last_search, 0, COLS / 3, FALSE); - return -1; + buf = charalloc(strlen(disp) + 7); + /* We use (COLS / 3) here because we need to see more on the line. */ + sprintf(buf, " [%s%s]", disp, + (strlenpt(last_search) > COLS / 3) ? "..." : ""); + free(disp); + } else + buf = mallocstrcpy(NULL, ""); + + /* This is now one simple call. It just does a lot. */ + i = do_prompt(FALSE, FALSE, + inhelp ? MFINDINHELP : (replacing ? MREPLACE : MWHEREIS), + backupstring, &search_history, + /* TRANSLATORS: This is the main search prompt. */ + edit_refresh, "%s%s%s%s%s%s", _("Search"), + /* TRANSLATORS: The next three modify the search prompt. */ + ISSET(CASE_SENSITIVE) ? _(" [Case Sensitive]") : "", + ISSET(USE_REGEXP) ? _(" [Regexp]") : "", + ISSET(BACKWARDS_SEARCH) ? _(" [Backwards]") : "", replacing ? +#ifndef NANO_TINY + /* TRANSLATORS: The next two modify the search prompt. */ + openfile->mark ? _(" (to replace) in selection") : +#endif + _(" (to replace)") : "", buf); + + /* Release buf now that we don't need it anymore. */ + free(buf); + + free(backupstring); + backupstring = NULL; + + /* If the search was cancelled, or we have a blank answer and + * nothing was searched for yet during this session, get out. */ + if (i == -1 || (i == -2 && *last_search == '\0')) { + statusbar(_("Cancelled")); + return -1; + } + + /* If Enter was pressed, see what we got. */ + if (i == 0 || i == -2) { + /* If an answer was given, remember it. */ + if (*answer != '\0') { + last_search = mallocstrcpy(last_search, answer); +#ifdef ENABLE_HISTORIES + update_history(&search_history, answer); +#endif + } + if (ISSET(USE_REGEXP) && !regexp_init(last_search)) + return -1; + else + return 0; /* We have a valid string or regex. */ + } + + func = func_from_key(&i); + + if (func == case_sens_void) { + TOGGLE(CASE_SENSITIVE); + backupstring = mallocstrcpy(backupstring, answer); + return 1; + } else if (func == backwards_void) { + TOGGLE(BACKWARDS_SEARCH); + backupstring = mallocstrcpy(backupstring, answer); + return 1; + } else if (func == regexp_void) { + TOGGLE(USE_REGEXP); + backupstring = mallocstrcpy(backupstring, answer); + return 1; + } else if (func == flip_replace) { + backupstring = mallocstrcpy(backupstring, answer); + return -2; /* Call the opposite search function. */ + } else if (func == do_gotolinecolumn_void) { + do_gotolinecolumn(openfile->current->lineno, + openfile->placewewant + 1, TRUE, TRUE); + return 3; + } + + return -1; } /* Look for needle, starting at (current, current_x). begin is the line @@ -203,200 +203,200 @@ int search_init(bool replacing, bool use_answer) * found something, 0 when nothing, and -2 on cancel. When match_len is * not NULL, set it to the length of the found string, if any. */ int findnextstr(const char *needle, bool whole_word_only, int modus, - size_t *match_len, bool skipone, const filestruct *begin, size_t begin_x) + size_t *match_len, bool skipone, const filestruct *begin, size_t begin_x) { - size_t found_len = strlen(needle); - /* The length of a match -- will be recomputed for a regex. */ - int feedback = 0; - /* When bigger than zero, show and wipe the "Searching..." message. */ - filestruct *line = openfile->current; - /* The line that we will search through now. */ - const char *from = line->data + openfile->current_x; - /* The point in the line from where we start searching. */ - const char *found = NULL; - /* A pointer to the location of the match, if any. */ - size_t found_x; - /* The x coordinate of a found occurrence. */ - time_t lastkbcheck = time(NULL); - /* The time we last looked at the keyboard. */ + size_t found_len = strlen(needle); + /* The length of a match -- will be recomputed for a regex. */ + int feedback = 0; + /* When bigger than zero, show and wipe the "Searching..." message. */ + filestruct *line = openfile->current; + /* The line that we will search through now. */ + const char *from = line->data + openfile->current_x; + /* The point in the line from where we start searching. */ + const char *found = NULL; + /* A pointer to the location of the match, if any. */ + size_t found_x; + /* The x coordinate of a found occurrence. */ + time_t lastkbcheck = time(NULL); + /* The time we last looked at the keyboard. */ - /* Set non-blocking input so that we can just peek for a Cancel. */ - disable_waiting(); + /* Set non-blocking input so that we can just peek for a Cancel. */ + disable_waiting(); - if (begin == NULL) - came_full_circle = FALSE; + if (begin == NULL) + came_full_circle = FALSE; - /* Start searching through the lines, looking for the needle. */ - while (TRUE) { - /* Glance at the keyboard once every second. */ - if (time(NULL) - lastkbcheck > 0) { - int input = parse_kbinput(edit); + /* Start searching through the lines, looking for the needle. */ + while (TRUE) { + /* Glance at the keyboard once every second. */ + if (time(NULL) - lastkbcheck > 0) { + int input = parse_kbinput(edit); - lastkbcheck = time(NULL); + lastkbcheck = time(NULL); - /* Consume all waiting keystrokes until a Cancel. */ - while (input) { - if (func_from_key(&input) == do_cancel) { - statusbar(_("Cancelled")); - enable_waiting(); - return -2; + /* Consume all waiting keystrokes until a Cancel. */ + while (input) { + if (func_from_key(&input) == do_cancel) { + statusbar(_("Cancelled")); + enable_waiting(); + return -2; + } + input = parse_kbinput(NULL); + } + + if (++feedback > 0) + /* TRANSLATORS: This is shown when searching takes + * more than half a second. */ + statusbar(_("Searching...")); } - input = parse_kbinput(NULL); - } - if (++feedback > 0) - /* TRANSLATORS: This is shown when searching takes - * more than half a second. */ - statusbar(_("Searching...")); - } + /* Search for the needle in the current line. */ + if (!skipone) + found = strstrwrapper(line->data, needle, from); - /* Search for the needle in the current line. */ - if (!skipone) - found = strstrwrapper(line->data, needle, from); + /* Ignore the initial match at the starting position: continue + * searching from the next character, or invalidate the match. */ + if (skipone || (!whole_word_only && !came_full_circle && + found == begin->data + begin_x)) { + skipone = FALSE; + if (ISSET(BACKWARDS_SEARCH) && from != line->data) { + from = line->data + move_mbleft(line->data, from - line->data); + continue; + } else if (!ISSET(BACKWARDS_SEARCH) && *from != '\0') { + from += move_mbright(from, 0); + continue; + } + found = NULL; + } - /* Ignore the initial match at the starting position: continue - * searching from the next character, or invalidate the match. */ - if (skipone || (!whole_word_only && !came_full_circle && - found == begin->data + begin_x)) { - skipone = FALSE; - if (ISSET(BACKWARDS_SEARCH) && from != line->data) { - from = line->data + move_mbleft(line->data, from - line->data); - continue; - } else if (!ISSET(BACKWARDS_SEARCH) && *from != '\0') { - from += move_mbright(from, 0); - continue; - } - found = NULL; - } - - if (found != NULL) { - /* When doing a regex search, compute the length of the match. */ - if (ISSET(USE_REGEXP)) - found_len = regmatches[0].rm_eo - regmatches[0].rm_so; + if (found != NULL) { + /* When doing a regex search, compute the length of the match. */ + if (ISSET(USE_REGEXP)) + found_len = regmatches[0].rm_eo - regmatches[0].rm_so; #ifdef ENABLE_SPELLER - /* When we're spell checking, a match should be a separate word; - * if it's not, continue looking in the rest of the line. */ - if (whole_word_only && !is_separate_word(found - line->data, - found_len, line->data)) { - from = found + move_mbright(found, 0); - continue; - } + /* When we're spell checking, a match should be a separate word; + * if it's not, continue looking in the rest of the line. */ + if (whole_word_only && !is_separate_word(found - line->data, + found_len, line->data)) { + from = found + move_mbright(found, 0); + continue; + } #endif - /* The match is valid. */ - break; + /* The match is valid. */ + break; + } + + /* If we're back at the beginning, then there is no needle. */ + if (came_full_circle) { + enable_waiting(); + return 0; + } + + /* Move to the previous or next line in the file. */ + if (ISSET(BACKWARDS_SEARCH)) + line = line->prev; + else + line = line->next; + + /* If we've reached the start or end of the buffer, wrap around; + * but stop when spell-checking or replacing in a region. */ + if (line == NULL) { + if (whole_word_only || modus == INREGION) { + enable_waiting(); + return 0; + } + + if (ISSET(BACKWARDS_SEARCH)) + line = openfile->filebot; + else + line = openfile->fileage; + + if (modus == JUSTFIND) { + statusbar(_("Search Wrapped")); + /* Delay the "Searching..." message for at least two seconds. */ + feedback = -2; + } + } + + /* If we've reached the original starting line, take note. */ + if (line == begin) + came_full_circle = TRUE; + + /* Set the starting x to the start or end of the line. */ + from = line->data; + if (ISSET(BACKWARDS_SEARCH)) + from += strlen(line->data); } - /* If we're back at the beginning, then there is no needle. */ - if (came_full_circle) { - enable_waiting(); - return 0; - } + found_x = found - line->data; - /* Move to the previous or next line in the file. */ - if (ISSET(BACKWARDS_SEARCH)) - line = line->prev; - else - line = line->next; + enable_waiting(); - /* If we've reached the start or end of the buffer, wrap around; - * but stop when spell-checking or replacing in a region. */ - if (line == NULL) { - if (whole_word_only || modus == INREGION) { - enable_waiting(); + /* Ensure that the found occurrence is not beyond the starting x. */ + if (came_full_circle && ((!ISSET(BACKWARDS_SEARCH) && found_x > begin_x) || + (ISSET(BACKWARDS_SEARCH) && found_x < begin_x))) return 0; - } - if (ISSET(BACKWARDS_SEARCH)) - line = openfile->filebot; - else - line = openfile->fileage; + /* Set the current position to point at what we found. */ + openfile->current = line; + openfile->current_x = found_x; - if (modus == JUSTFIND) { - statusbar(_("Search Wrapped")); - /* Delay the "Searching..." message for at least two seconds. */ - feedback = -2; - } + /* When requested, pass back the length of the match. */ + if (match_len != NULL) + *match_len = found_len; + + /* Wipe the "Searching..." message and unset the suppression flag. */ + if (feedback > 0) { + wipe_statusbar(); + suppress_cursorpos = FALSE; } - /* If we've reached the original starting line, take note. */ - if (line == begin) - came_full_circle = TRUE; - - /* Set the starting x to the start or end of the line. */ - from = line->data; - if (ISSET(BACKWARDS_SEARCH)) - from += strlen(line->data); - } - - found_x = found - line->data; - - enable_waiting(); - - /* Ensure that the found occurrence is not beyond the starting x. */ - if (came_full_circle && ((!ISSET(BACKWARDS_SEARCH) && found_x > begin_x) || - (ISSET(BACKWARDS_SEARCH) && found_x < begin_x))) - return 0; - - /* Set the current position to point at what we found. */ - openfile->current = line; - openfile->current_x = found_x; - - /* When requested, pass back the length of the match. */ - if (match_len != NULL) - *match_len = found_len; - - /* Wipe the "Searching..." message and unset the suppression flag. */ - if (feedback > 0) { - wipe_statusbar(); - suppress_cursorpos = FALSE; - } - - return 1; + return 1; } /* Ask what to search for and then go looking for it. */ void do_search(void) { - int i = search_init(FALSE, FALSE); + int i = search_init(FALSE, FALSE); - if (i == -1) /* Cancelled, or some other exit reason. */ - search_replace_abort(); - else if (i == -2) /* Do a replace instead. */ - do_replace(); - else if (i == 1) /* Toggled something. */ - do_search(); + if (i == -1) /* Cancelled, or some other exit reason. */ + search_replace_abort(); + else if (i == -2) /* Do a replace instead. */ + do_replace(); + else if (i == 1) /* Toggled something. */ + do_search(); - if (i == 0) - go_looking(); + if (i == 0) + go_looking(); } /* Search forward for a string. */ void do_search_forward(void) { - UNSET(BACKWARDS_SEARCH); - do_search(); + UNSET(BACKWARDS_SEARCH); + do_search(); } /* Search backwards for a string. */ void do_search_backward(void) { - SET(BACKWARDS_SEARCH); - do_search(); + SET(BACKWARDS_SEARCH); + do_search(); } #ifndef NANO_TINY /* Search in the backward direction for the next occurrence. */ void do_findprevious(void) { - SET(BACKWARDS_SEARCH); - do_research(); + SET(BACKWARDS_SEARCH); + do_research(); } /* Search in the forward direction for the next occurrence. */ void do_findnext(void) { - UNSET(BACKWARDS_SEARCH); - do_research(); + UNSET(BACKWARDS_SEARCH); + do_research(); } #endif /* !NANO_TINY */ @@ -404,55 +404,55 @@ void do_findnext(void) void do_research(void) { #ifdef ENABLE_HISTORIES - /* If nothing was searched for yet during this run of nano, but - * there is a search history, take the most recent item. */ - if (*last_search == '\0' && searchbot->prev != NULL) - last_search = mallocstrcpy(last_search, searchbot->prev->data); + /* If nothing was searched for yet during this run of nano, but + * there is a search history, take the most recent item. */ + if (*last_search == '\0' && searchbot->prev != NULL) + last_search = mallocstrcpy(last_search, searchbot->prev->data); #endif - if (*last_search == '\0') { - statusbar(_("No current search pattern")); - return; - } + if (*last_search == '\0') { + statusbar(_("No current search pattern")); + return; + } - if (ISSET(USE_REGEXP) && !regexp_init(last_search)) - return; + if (ISSET(USE_REGEXP) && !regexp_init(last_search)) + return; - /* Use the search-menu key bindings, to allow cancelling. */ - currmenu = MWHEREIS; + /* Use the search-menu key bindings, to allow cancelling. */ + currmenu = MWHEREIS; - go_looking(); + go_looking(); } /* Search for the global string 'last_search'. Inform the user when * the string occurs only once. */ void go_looking(void) { - filestruct *was_current = openfile->current; - size_t was_current_x = openfile->current_x; + filestruct *was_current = openfile->current; + size_t was_current_x = openfile->current_x; #ifdef DEBUG - clock_t start = clock(); + clock_t start = clock(); #endif - came_full_circle = FALSE; + came_full_circle = FALSE; - didfind = findnextstr(last_search, FALSE, JUSTFIND, NULL, FALSE, - openfile->current, openfile->current_x); + didfind = findnextstr(last_search, FALSE, JUSTFIND, NULL, FALSE, + openfile->current, openfile->current_x); - /* If we found something, and we're back at the exact same spot - * where we started searching, then this is the only occurrence. */ - if (didfind == 1 && openfile->current == was_current && - openfile->current_x == was_current_x) - statusbar(_("This is the only occurrence")); - else if (didfind == 0) - not_found_msg(last_search); + /* If we found something, and we're back at the exact same spot + * where we started searching, then this is the only occurrence. */ + if (didfind == 1 && openfile->current == was_current && + openfile->current_x == was_current_x) + statusbar(_("This is the only occurrence")); + else if (didfind == 0) + not_found_msg(last_search); #ifdef DEBUG - statusline(HUSH, "Took: %.2f", (double)(clock() - start) / CLOCKS_PER_SEC); + statusline(HUSH, "Took: %.2f", (double)(clock() - start) / CLOCKS_PER_SEC); #endif - edit_redraw(was_current, CENTERING); - search_replace_abort(); + edit_redraw(was_current, CENTERING); + search_replace_abort(); } /* Calculate the size of the replacement text, taking possible @@ -460,78 +460,78 @@ void go_looking(void) * text in the passed string only when create is TRUE. */ int replace_regexp(char *string, bool create) { - const char *c = answer; - size_t replacement_size = 0; + const char *c = answer; + size_t replacement_size = 0; - /* Iterate through the replacement text to handle subexpression - * replacement using \1, \2, \3, etc. */ - while (*c != '\0') { - int num = (*(c + 1) - '0'); + /* Iterate through the replacement text to handle subexpression + * replacement using \1, \2, \3, etc. */ + while (*c != '\0') { + int num = (*(c + 1) - '0'); - if (*c != '\\' || num < 1 || num > 9 || num > search_regexp.re_nsub) { - if (create) - *string++ = *c; - c++; - replacement_size++; - } else { - size_t i = regmatches[num].rm_eo - regmatches[num].rm_so; + if (*c != '\\' || num < 1 || num > 9 || num > search_regexp.re_nsub) { + if (create) + *string++ = *c; + c++; + replacement_size++; + } else { + size_t i = regmatches[num].rm_eo - regmatches[num].rm_so; - /* Skip over the replacement expression. */ - c += 2; + /* Skip over the replacement expression. */ + c += 2; - /* But add the length of the subexpression to new_size. */ - replacement_size += i; + /* But add the length of the subexpression to new_size. */ + replacement_size += i; - /* And if create is TRUE, append the result of the - * subexpression match to the new line. */ - if (create) { - strncpy(string, openfile->current->data + - regmatches[num].rm_so, i); - string += i; - } + /* And if create is TRUE, append the result of the + * subexpression match to the new line. */ + if (create) { + strncpy(string, openfile->current->data + + regmatches[num].rm_so, i); + string += i; + } + } } - } - if (create) - *string = '\0'; + if (create) + *string = '\0'; - return replacement_size; + return replacement_size; } /* Return a copy of the current line with one needle replaced. */ char *replace_line(const char *needle) { - char *copy; - size_t match_len; - size_t new_line_size = strlen(openfile->current->data) + 1; + char *copy; + size_t match_len; + size_t new_line_size = strlen(openfile->current->data) + 1; - /* First adjust the size of the new line for the change. */ - if (ISSET(USE_REGEXP)) { - match_len = regmatches[0].rm_eo - regmatches[0].rm_so; - new_line_size += replace_regexp(NULL, FALSE) - match_len; - } else { - match_len = strlen(needle); - new_line_size += strlen(answer) - match_len; - } + /* First adjust the size of the new line for the change. */ + if (ISSET(USE_REGEXP)) { + match_len = regmatches[0].rm_eo - regmatches[0].rm_so; + new_line_size += replace_regexp(NULL, FALSE) - match_len; + } else { + match_len = strlen(needle); + new_line_size += strlen(answer) - match_len; + } - /* Create the buffer. */ - copy = charalloc(new_line_size); + /* Create the buffer. */ + copy = charalloc(new_line_size); - /* Copy the head of the original line. */ - strncpy(copy, openfile->current->data, openfile->current_x); + /* Copy the head of the original line. */ + strncpy(copy, openfile->current->data, openfile->current_x); - /* Add the replacement text. */ - if (ISSET(USE_REGEXP)) - replace_regexp(copy + openfile->current_x, TRUE); - else - strcpy(copy + openfile->current_x, answer); + /* Add the replacement text. */ + if (ISSET(USE_REGEXP)) + replace_regexp(copy + openfile->current_x, TRUE); + else + strcpy(copy + openfile->current_x, answer); - assert(openfile->current_x + match_len <= strlen(openfile->current->data)); + assert(openfile->current_x + match_len <= strlen(openfile->current->data)); - /* Copy the tail of the original line. */ - strcat(copy, openfile->current->data + openfile->current_x + match_len); + /* Copy the tail of the original line. */ + strcat(copy, openfile->current->data + openfile->current_x + match_len); - return copy; + return copy; } /* Step through each occurrence of the search string and prompt the user @@ -541,368 +541,368 @@ char *replace_line(const char *needle) * is replaced by a shorter word. Return -1 if needle isn't found, -2 if * the seeking is aborted, else the number of replacements performed. */ ssize_t do_replace_loop(const char *needle, bool whole_word_only, - const filestruct *real_current, size_t *real_current_x) + const filestruct *real_current, size_t *real_current_x) { - ssize_t numreplaced = -1; - size_t match_len; - bool replaceall = FALSE; - bool skipone = FALSE; - int modus = REPLACING; + ssize_t numreplaced = -1; + size_t match_len; + bool replaceall = FALSE; + bool skipone = FALSE; + int modus = REPLACING; #ifndef NANO_TINY - filestruct *was_mark = openfile->mark; - filestruct *top, *bot; - size_t top_x, bot_x; - bool right_side_up = FALSE; - /* TRUE if (mark_begin, mark_begin_x) is the top of the mark, - * FALSE if (current, current_x) is. */ + filestruct *was_mark = openfile->mark; + filestruct *top, *bot; + size_t top_x, bot_x; + bool right_side_up = FALSE; + /* TRUE if (mark_begin, mark_begin_x) is the top of the mark, + * FALSE if (current, current_x) is. */ - /* If the mark is on, frame the region, and turn the mark off. */ - if (openfile->mark) { - mark_order((const filestruct **)&top, &top_x, - (const filestruct **)&bot, &bot_x, &right_side_up); - openfile->mark = NULL; - modus = INREGION; + /* If the mark is on, frame the region, and turn the mark off. */ + if (openfile->mark) { + mark_order((const filestruct **)&top, &top_x, + (const filestruct **)&bot, &bot_x, &right_side_up); + openfile->mark = NULL; + modus = INREGION; - /* Start either at the top or the bottom of the marked region. */ - if (!ISSET(BACKWARDS_SEARCH)) { - openfile->current = top; - openfile->current_x = top_x; - } else { - openfile->current = bot; - openfile->current_x = bot_x; + /* Start either at the top or the bottom of the marked region. */ + if (!ISSET(BACKWARDS_SEARCH)) { + openfile->current = top; + openfile->current_x = top_x; + } else { + openfile->current = bot; + openfile->current_x = bot_x; + } } - } #endif /* !NANO_TINY */ - came_full_circle = FALSE; + came_full_circle = FALSE; - while (TRUE) { - int i = 0; - int result = findnextstr(needle, whole_word_only, modus, - &match_len, skipone, real_current, *real_current_x); + while (TRUE) { + int i = 0; + int result = findnextstr(needle, whole_word_only, modus, + &match_len, skipone, real_current, *real_current_x); - /* If nothing more was found, or the user aborted, stop looping. */ - if (result < 1) { - if (result < 0) - numreplaced = -2; /* It's a Cancel instead of Not found. */ - break; - } + /* If nothing more was found, or the user aborted, stop looping. */ + if (result < 1) { + if (result < 0) + numreplaced = -2; /* It's a Cancel instead of Not found. */ + break; + } #ifndef NANO_TINY - /* An occurrence outside of the marked region means we're done. */ - if (was_mark && (openfile->current->lineno > bot->lineno || - openfile->current->lineno < top->lineno || - (openfile->current == bot && - openfile->current_x + match_len > bot_x) || - (openfile->current == top && - openfile->current_x < top_x))) - break; + /* An occurrence outside of the marked region means we're done. */ + if (was_mark && (openfile->current->lineno > bot->lineno || + openfile->current->lineno < top->lineno || + (openfile->current == bot && + openfile->current_x + match_len > bot_x) || + (openfile->current == top && + openfile->current_x < top_x))) + break; #endif - /* Indicate that we found the search string. */ + /* Indicate that we found the search string. */ + if (numreplaced == -1) + numreplaced = 0; + + if (!replaceall) { + size_t from_col = xplustabs(); + size_t to_col = strnlenpt(openfile->current->data, + openfile->current_x + match_len); + + /* Refresh the edit window, scrolling it if necessary. */ + edit_refresh(); + + spotlight(TRUE, from_col, to_col); + + /* TRANSLATORS: This is a prompt. */ + i = do_yesno_prompt(TRUE, _("Replace this instance?")); + + spotlight(FALSE, from_col, to_col); + + if (i == -1) /* The replacing was cancelled. */ + break; + else if (i == 2) + replaceall = TRUE; + + /* When "No" or moving backwards, the search routine should + * first move one character further before continuing. */ + skipone = (i == 0 || ISSET(BACKWARDS_SEARCH)); + } + + if (i == 1 || replaceall) { /* Yes, replace it. */ + char *copy; + size_t length_change; + +#ifndef NANO_TINY + add_undo(REPLACE); +#endif + copy = replace_line(needle); + + length_change = strlen(copy) - strlen(openfile->current->data); + +#ifndef NANO_TINY + /* If the mark was on and it was located after the cursor, + * then adjust its x position for any text length changes. */ + if (was_mark && !right_side_up) { + if (openfile->current == was_mark && + openfile->mark_x > openfile->current_x) { + if (openfile->mark_x < openfile->current_x + match_len) + openfile->mark_x = openfile->current_x; + else + openfile->mark_x += length_change; + bot_x = openfile->mark_x; + } + } + + /* If the mark was not on or it was before the cursor, then + * adjust the cursor's x position for any text length changes. */ + if (!was_mark || right_side_up) { +#endif + if (openfile->current == real_current && + openfile->current_x < *real_current_x) { + if (*real_current_x < openfile->current_x + match_len) + *real_current_x = openfile->current_x + match_len; + *real_current_x += length_change; +#ifndef NANO_TINY + bot_x = *real_current_x; + } +#endif + } + + /* Don't find the same zero-length or BOL match again. */ + if (match_len == 0 || (*needle == '^' && ISSET(USE_REGEXP))) + skipone = TRUE; + + /* When moving forward, put the cursor just after the replacement + * text, so that searching will continue there. */ + if (!ISSET(BACKWARDS_SEARCH)) + openfile->current_x += match_len + length_change; + + /* Update the file size, and put the changed line into place. */ + openfile->totsize += mbstrlen(copy) - mbstrlen(openfile->current->data); + free(openfile->current->data); + openfile->current->data = copy; + + if (!replaceall) { +#ifdef ENABLE_COLOR + /* When doing syntax coloring, the replacement might require + * a change of colors, so refresh the whole edit window. */ + if (openfile->colorstrings != NULL && !ISSET(NO_COLOR_SYNTAX)) + edit_refresh(); + else +#endif + update_line(openfile->current, openfile->current_x); + } + + set_modified(); + as_an_at = TRUE; + numreplaced++; + } + } + if (numreplaced == -1) - numreplaced = 0; - - if (!replaceall) { - size_t from_col = xplustabs(); - size_t to_col = strnlenpt(openfile->current->data, - openfile->current_x + match_len); - - /* Refresh the edit window, scrolling it if necessary. */ - edit_refresh(); - - spotlight(TRUE, from_col, to_col); - - /* TRANSLATORS: This is a prompt. */ - i = do_yesno_prompt(TRUE, _("Replace this instance?")); - - spotlight(FALSE, from_col, to_col); - - if (i == -1) /* The replacing was cancelled. */ - break; - else if (i == 2) - replaceall = TRUE; - - /* When "No" or moving backwards, the search routine should - * first move one character further before continuing. */ - skipone = (i == 0 || ISSET(BACKWARDS_SEARCH)); - } - - if (i == 1 || replaceall) { /* Yes, replace it. */ - char *copy; - size_t length_change; - -#ifndef NANO_TINY - add_undo(REPLACE); -#endif - copy = replace_line(needle); - - length_change = strlen(copy) - strlen(openfile->current->data); - -#ifndef NANO_TINY - /* If the mark was on and it was located after the cursor, - * then adjust its x position for any text length changes. */ - if (was_mark && !right_side_up) { - if (openfile->current == was_mark && - openfile->mark_x > openfile->current_x) { - if (openfile->mark_x < openfile->current_x + match_len) - openfile->mark_x = openfile->current_x; - else - openfile->mark_x += length_change; - bot_x = openfile->mark_x; - } - } - - /* If the mark was not on or it was before the cursor, then - * adjust the cursor's x position for any text length changes. */ - if (!was_mark || right_side_up) { -#endif - if (openfile->current == real_current && - openfile->current_x < *real_current_x) { - if (*real_current_x < openfile->current_x + match_len) - *real_current_x = openfile->current_x + match_len; - *real_current_x += length_change; -#ifndef NANO_TINY - bot_x = *real_current_x; - } -#endif - } - - /* Don't find the same zero-length or BOL match again. */ - if (match_len == 0 || (*needle == '^' && ISSET(USE_REGEXP))) - skipone = TRUE; - - /* When moving forward, put the cursor just after the replacement - * text, so that searching will continue there. */ - if (!ISSET(BACKWARDS_SEARCH)) - openfile->current_x += match_len + length_change; - - /* Update the file size, and put the changed line into place. */ - openfile->totsize += mbstrlen(copy) - mbstrlen(openfile->current->data); - free(openfile->current->data); - openfile->current->data = copy; - - if (!replaceall) { + not_found_msg(needle); #ifdef ENABLE_COLOR - /* When doing syntax coloring, the replacement might require - * a change of colors, so refresh the whole edit window. */ - if (openfile->colorstrings != NULL && !ISSET(NO_COLOR_SYNTAX)) - edit_refresh(); - else -#endif - update_line(openfile->current, openfile->current_x); - } - - set_modified(); - as_an_at = TRUE; - numreplaced++; - } - } - - if (numreplaced == -1) - not_found_msg(needle); -#ifdef ENABLE_COLOR - else if (numreplaced > 0) - refresh_needed = TRUE; + else if (numreplaced > 0) + refresh_needed = TRUE; #endif #ifndef NANO_TINY - openfile->mark = was_mark; + openfile->mark = was_mark; #endif - /* If "automatic newline" is enabled, and text has been added to the - * magicline, make a new magicline. */ - if (!ISSET(NO_NEWLINES) && openfile->filebot->data[0] != '\0') - new_magicline(); + /* If "automatic newline" is enabled, and text has been added to the + * magicline, make a new magicline. */ + if (!ISSET(NO_NEWLINES) && openfile->filebot->data[0] != '\0') + new_magicline(); - return numreplaced; + return numreplaced; } /* Replace a string. */ void do_replace(void) { - filestruct *edittop_save, *begin; - size_t firstcolumn_save, begin_x; - ssize_t numreplaced; - int i; + filestruct *edittop_save, *begin; + size_t firstcolumn_save, begin_x; + ssize_t numreplaced; + int i; - if (ISSET(VIEW_MODE)) { - print_view_warning(); - return; - } + if (ISSET(VIEW_MODE)) { + print_view_warning(); + return; + } - i = search_init(TRUE, FALSE); + i = search_init(TRUE, FALSE); - if (i == -1) /* Cancelled, or some other exit reason. */ - search_replace_abort(); - else if (i == -2) /* Do a search instead. */ - do_search(); - else if (i == 1) /* Toggled something. */ - do_replace(); + if (i == -1) /* Cancelled, or some other exit reason. */ + search_replace_abort(); + else if (i == -2) /* Do a search instead. */ + do_search(); + else if (i == 1) /* Toggled something. */ + do_replace(); - if (i != 0) - return; + if (i != 0) + return; - i = do_prompt(FALSE, FALSE, MREPLACEWITH, NULL, &replace_history, - /* TRANSLATORS: This is a prompt. */ - edit_refresh, _("Replace with")); + i = do_prompt(FALSE, FALSE, MREPLACEWITH, NULL, &replace_history, + /* TRANSLATORS: This is a prompt. */ + edit_refresh, _("Replace with")); #ifdef ENABLE_HISTORIES - /* If the replace string is not "", add it to the replace history list. */ - if (i == 0) - update_history(&replace_history, answer); + /* If the replace string is not "", add it to the replace history list. */ + if (i == 0) + update_history(&replace_history, answer); #endif - /* When cancelled, or when a function was run, get out. */ - if (i == -1 || i > 0) { - if (i == -1) - statusbar(_("Cancelled")); + /* When cancelled, or when a function was run, get out. */ + if (i == -1 || i > 0) { + if (i == -1) + statusbar(_("Cancelled")); + search_replace_abort(); + return; + } + + /* Save where we are. */ + edittop_save = openfile->edittop; + firstcolumn_save = openfile->firstcolumn; + begin = openfile->current; + begin_x = openfile->current_x; + + numreplaced = do_replace_loop(last_search, FALSE, begin, &begin_x); + + /* Restore where we were. */ + openfile->edittop = edittop_save; + openfile->firstcolumn = firstcolumn_save; + openfile->current = begin; + openfile->current_x = begin_x; + refresh_needed = TRUE; + + if (numreplaced >= 0) + statusline(HUSH, P_("Replaced %zd occurrence", + "Replaced %zd occurrences", numreplaced), numreplaced); + search_replace_abort(); - return; - } - - /* Save where we are. */ - edittop_save = openfile->edittop; - firstcolumn_save = openfile->firstcolumn; - begin = openfile->current; - begin_x = openfile->current_x; - - numreplaced = do_replace_loop(last_search, FALSE, begin, &begin_x); - - /* Restore where we were. */ - openfile->edittop = edittop_save; - openfile->firstcolumn = firstcolumn_save; - openfile->current = begin; - openfile->current_x = begin_x; - refresh_needed = TRUE; - - if (numreplaced >= 0) - statusline(HUSH, P_("Replaced %zd occurrence", - "Replaced %zd occurrences", numreplaced), numreplaced); - - 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; line > 1 && - openfile->current != openfile->filebot; line--) - openfile->current = openfile->current->next; + for (openfile->current = openfile->fileage; line > 1 && + openfile->current != openfile->filebot; line--) + openfile->current = openfile->current->next; - openfile->current_x = pos_x; - openfile->placewewant = xplustabs(); + openfile->current_x = pos_x; + openfile->placewewant = xplustabs(); - refresh_needed = TRUE; + refresh_needed = TRUE; } /* Go to the specified line and column, or ask for them if interactive * is TRUE. In the latter case also update the screen afterwards. * Note that both the line and column number should be one-based. */ void do_gotolinecolumn(ssize_t line, ssize_t column, bool use_answer, - bool interactive) + bool interactive) { - if (interactive) { - functionptrtype func; + if (interactive) { + functionptrtype func; - /* Ask for the line and column. */ - int i = do_prompt(FALSE, FALSE, MGOTOLINE, - use_answer ? answer : NULL, NULL, - /* TRANSLATORS: This is a prompt. */ - edit_refresh, _("Enter line number, column number")); + /* Ask for the line and column. */ + int i = do_prompt(FALSE, FALSE, MGOTOLINE, + use_answer ? answer : NULL, NULL, + /* TRANSLATORS: This is a prompt. */ + edit_refresh, _("Enter line number, column number")); - /* If the user cancelled or gave a blank answer, get out. */ - if (i < 0) { - statusbar(_("Cancelled")); - return; + /* If the user cancelled or gave a blank answer, get out. */ + if (i < 0) { + statusbar(_("Cancelled")); + return; + } + + func = func_from_key(&i); + + if (func == gototext_void) { + /* Retain what the user typed so far and switch to searching. */ + search_init(TRUE, TRUE); + do_search(); + } + + /* If a function was executed, we're done here. */ + if (i > 0) + return; + + /* Try to extract one or two numbers from the user's response. */ + if (!parse_line_column(answer, &line, &column)) { + statusline(ALERT, _("Invalid line or column number")); + return; + } + } else { + if (line == 0) + line = openfile->current->lineno; + + if (column == 0) + column = openfile->placewewant + 1; } - func = func_from_key(&i); + /* Take a negative line number to mean: from the end of the file. */ + if (line < 0) + line = openfile->filebot->lineno + line + 1; + if (line < 1) + line = 1; - if (func == gototext_void) { - /* Retain what the user typed so far and switch to searching. */ - search_init(TRUE, TRUE); - do_search(); - } + /* Iterate to the requested line. */ + for (openfile->current = openfile->fileage; line > 1 && + openfile->current != openfile->filebot; line--) + openfile->current = openfile->current->next; - /* If a function was executed, we're done here. */ - if (i > 0) - return; + /* Take a negative column number to mean: from the end of the line. */ + if (column < 0) + column = strlenpt(openfile->current->data) + column + 2; + if (column < 1) + column = 1; - /* Try to extract one or two numbers from the user's response. */ - if (!parse_line_column(answer, &line, &column)) { - statusline(ALERT, _("Invalid line or column number")); - return; - } - } else { - if (line == 0) - line = openfile->current->lineno; - - if (column == 0) - column = openfile->placewewant + 1; - } - - /* Take a negative line number to mean: from the end of the file. */ - if (line < 0) - line = openfile->filebot->lineno + line + 1; - if (line < 1) - line = 1; - - /* Iterate to the requested line. */ - for (openfile->current = openfile->fileage; line > 1 && - openfile->current != openfile->filebot; line--) - openfile->current = openfile->current->next; - - /* Take a negative column number to mean: from the end of the line. */ - if (column < 0) - column = strlenpt(openfile->current->data) + column + 2; - if (column < 1) - column = 1; - - /* Set the x position that corresponds to the requested column. */ - openfile->current_x = actual_x(openfile->current->data, column - 1); - openfile->placewewant = column - 1; + /* Set the x position that corresponds to the requested column. */ + openfile->current_x = actual_x(openfile->current->data, column - 1); + openfile->placewewant = column - 1; #ifndef NANO_TINY - if (ISSET(SOFTWRAP) && openfile->placewewant / editwincols > - strlenpt(openfile->current->data) / editwincols) - openfile->placewewant = strlenpt(openfile->current->data); + if (ISSET(SOFTWRAP) && openfile->placewewant / editwincols > + strlenpt(openfile->current->data) / editwincols) + openfile->placewewant = strlenpt(openfile->current->data); #endif - /* When the position was manually given, center the target line. */ - if (interactive) { - adjust_viewport(CENTERING); - refresh_needed = TRUE; - } else { - int rows_from_tail; + /* When the position was manually given, center the target line. */ + if (interactive) { + adjust_viewport(CENTERING); + refresh_needed = TRUE; + } else { + int rows_from_tail; #ifndef NANO_TINY - if (ISSET(SOFTWRAP)) { - filestruct *line = openfile->current; - size_t leftedge = leftedge_for(xplustabs(), openfile->current); + if (ISSET(SOFTWRAP)) { + filestruct *line = openfile->current; + size_t leftedge = leftedge_for(xplustabs(), openfile->current); - rows_from_tail = (editwinrows / 2) - - go_forward_chunks(editwinrows / 2, &line, &leftedge); - } else + rows_from_tail = (editwinrows / 2) - + go_forward_chunks(editwinrows / 2, &line, &leftedge); + } else #endif - rows_from_tail = openfile->filebot->lineno - - openfile->current->lineno; + rows_from_tail = openfile->filebot->lineno - + openfile->current->lineno; - /* If the target line is close to the tail of the file, put the last - * line or chunk on the bottom line of the screen; otherwise, just - * center the target line. */ - if (rows_from_tail < editwinrows / 2 && ISSET(SMOOTH_SCROLL)) { - openfile->current_y = editwinrows - 1 - rows_from_tail; - adjust_viewport(STATIONARY); - } else - adjust_viewport(CENTERING); - } + /* If the target line is close to the tail of the file, put the last + * line or chunk on the bottom line of the screen; otherwise, just + * center the target line. */ + if (rows_from_tail < editwinrows / 2 && ISSET(SMOOTH_SCROLL)) { + openfile->current_y = editwinrows - 1 - rows_from_tail; + adjust_viewport(STATIONARY); + } else + adjust_viewport(CENTERING); + } } /* Go to the specified line and column, asking for them beforehand. */ void do_gotolinecolumn_void(void) { - do_gotolinecolumn(openfile->current->lineno, - openfile->placewewant + 1, FALSE, TRUE); + do_gotolinecolumn(openfile->current->lineno, + openfile->placewewant + 1, FALSE, TRUE); } #ifndef NANO_TINY @@ -912,158 +912,158 @@ void do_gotolinecolumn_void(void) * we found a match, and FALSE otherwise. */ bool find_bracket_match(bool reverse, const char *bracket_set) { - filestruct *fileptr = openfile->current; - const char *rev_start = NULL, *found = NULL; + filestruct *fileptr = openfile->current; + const char *rev_start = NULL, *found = NULL; - assert(mbstrlen(bracket_set) == 2); - - /* rev_start might end up 1 character before the start or after the - * end of the line. This won't be a problem because we'll skip over - * it below in that case, and rev_start will be properly set when - * the search continues on the previous or next line. */ - if (reverse) - rev_start = fileptr->data + (openfile->current_x - 1); - else - rev_start = fileptr->data + (openfile->current_x + 1); - - /* Look for either of the two characters in bracket_set. rev_start - * can be 1 character before the start or after the end of the line. - * In either case, just act as though no match is found. */ - while (TRUE) { - if ((rev_start > fileptr->data && *(rev_start - 1) == '\0') || - rev_start < fileptr->data) - found = NULL; - else if (reverse) - found = mbrevstrpbrk(fileptr->data, bracket_set, rev_start); - else - found = mbstrpbrk(rev_start, bracket_set); - - if (found) - break; + assert(mbstrlen(bracket_set) == 2); + /* rev_start might end up 1 character before the start or after the + * end of the line. This won't be a problem because we'll skip over + * it below in that case, and rev_start will be properly set when + * the search continues on the previous or next line. */ if (reverse) - fileptr = fileptr->prev; + rev_start = fileptr->data + (openfile->current_x - 1); else - fileptr = fileptr->next; + rev_start = fileptr->data + (openfile->current_x + 1); - /* If we've reached the start or end of the buffer, get out. */ - if (fileptr == NULL) - return FALSE; + /* Look for either of the two characters in bracket_set. rev_start + * can be 1 character before the start or after the end of the line. + * In either case, just act as though no match is found. */ + while (TRUE) { + if ((rev_start > fileptr->data && *(rev_start - 1) == '\0') || + rev_start < fileptr->data) + found = NULL; + else if (reverse) + found = mbrevstrpbrk(fileptr->data, bracket_set, rev_start); + else + found = mbstrpbrk(rev_start, bracket_set); - rev_start = fileptr->data; - if (reverse) - rev_start += strlen(fileptr->data); - } + if (found) + break; - /* Set the current position to the found matching bracket. */ - openfile->current = fileptr; - openfile->current_x = found - fileptr->data; + if (reverse) + fileptr = fileptr->prev; + else + fileptr = fileptr->next; - return TRUE; + /* If we've reached the start or end of the buffer, get out. */ + if (fileptr == NULL) + return FALSE; + + rev_start = fileptr->data; + if (reverse) + rev_start += strlen(fileptr->data); + } + + /* Set the current position to the found matching bracket. */ + openfile->current = fileptr; + openfile->current_x = found - fileptr->data; + + return TRUE; } /* Search for a match to the bracket at the current cursor position, if * there is one. */ void do_find_bracket(void) { - filestruct *current_save; - size_t current_x_save; - const char *ch; - /* The location in matchbrackets of the bracket at the current - * cursor position. */ - int ch_len; - /* The length of ch in bytes. */ - const char *wanted_ch; - /* The location in matchbrackets of the bracket complementing - * the bracket at the current cursor position. */ - int wanted_ch_len; - /* The length of wanted_ch in bytes. */ - char bracket_set[MAXCHARLEN * 2 + 1]; - /* The pair of characters in ch and wanted_ch. */ - size_t i; - /* Generic loop variable. */ - size_t matchhalf; - /* The number of single-byte characters in one half of - * matchbrackets. */ - size_t mbmatchhalf; - /* The number of multibyte characters in one half of - * matchbrackets. */ - size_t count = 1; - /* The initial bracket count. */ - bool reverse; - /* The direction we search. */ + filestruct *current_save; + size_t current_x_save; + const char *ch; + /* The location in matchbrackets of the bracket at the current + * cursor position. */ + int ch_len; + /* The length of ch in bytes. */ + const char *wanted_ch; + /* The location in matchbrackets of the bracket complementing + * the bracket at the current cursor position. */ + int wanted_ch_len; + /* The length of wanted_ch in bytes. */ + char bracket_set[MAXCHARLEN * 2 + 1]; + /* The pair of characters in ch and wanted_ch. */ + size_t i; + /* Generic loop variable. */ + size_t matchhalf; + /* The number of single-byte characters in one half of + * matchbrackets. */ + size_t mbmatchhalf; + /* The number of multibyte characters in one half of + * matchbrackets. */ + size_t count = 1; + /* The initial bracket count. */ + bool reverse; + /* The direction we search. */ - assert(mbstrlen(matchbrackets) % 2 == 0); + assert(mbstrlen(matchbrackets) % 2 == 0); - ch = openfile->current->data + openfile->current_x; + ch = openfile->current->data + openfile->current_x; - if ((ch = mbstrchr(matchbrackets, ch)) == NULL) { - statusbar(_("Not a bracket")); - return; - } - - /* Save where we are. */ - current_save = openfile->current; - current_x_save = openfile->current_x; - - /* If we're on an opening bracket, which must be in the first half - * of matchbrackets, we want to search forwards for a closing - * bracket. If we're on a closing bracket, which must be in the - * second half of matchbrackets, we want to search backwards for an - * opening bracket. */ - matchhalf = 0; - mbmatchhalf = mbstrlen(matchbrackets) / 2; - - for (i = 0; i < mbmatchhalf; i++) - matchhalf += parse_mbchar(matchbrackets + matchhalf, NULL, NULL); - - reverse = ((ch - matchbrackets) >= matchhalf); - - /* If we're on an opening bracket, set wanted_ch to the character - * that's matchhalf characters after ch. If we're on a closing - * bracket, set wanted_ch to the character that's matchhalf - * characters before ch. */ - wanted_ch = ch; - - while (mbmatchhalf > 0) { - if (reverse) - wanted_ch = matchbrackets + move_mbleft(matchbrackets, - wanted_ch - matchbrackets); - else - wanted_ch += move_mbright(wanted_ch, 0); - - mbmatchhalf--; - } - - ch_len = parse_mbchar(ch, NULL, NULL); - wanted_ch_len = parse_mbchar(wanted_ch, NULL, NULL); - - /* Fill bracket_set in with the values of ch and wanted_ch. */ - strncpy(bracket_set, ch, ch_len); - strncpy(bracket_set + ch_len, wanted_ch, wanted_ch_len); - bracket_set[ch_len + wanted_ch_len] = '\0'; - - while (TRUE) { - if (find_bracket_match(reverse, bracket_set)) { - /* If we found an identical bracket, increment count. If we - * found a complementary bracket, decrement it. */ - count += (strncmp(openfile->current->data + openfile->current_x, - ch, ch_len) == 0) ? 1 : -1; - - /* If count is zero, we've found a matching bracket. Update - * the screen and get out. */ - if (count == 0) { - edit_redraw(current_save, FLOWING); - break; - } - } else { - /* We didn't find either an opening or closing bracket. - * Indicate this, restore where we were, and get out. */ - statusbar(_("No matching bracket")); - openfile->current = current_save; - openfile->current_x = current_x_save; - break; + if ((ch = mbstrchr(matchbrackets, ch)) == NULL) { + statusbar(_("Not a bracket")); + return; + } + + /* Save where we are. */ + current_save = openfile->current; + current_x_save = openfile->current_x; + + /* If we're on an opening bracket, which must be in the first half + * of matchbrackets, we want to search forwards for a closing + * bracket. If we're on a closing bracket, which must be in the + * second half of matchbrackets, we want to search backwards for an + * opening bracket. */ + matchhalf = 0; + mbmatchhalf = mbstrlen(matchbrackets) / 2; + + for (i = 0; i < mbmatchhalf; i++) + matchhalf += parse_mbchar(matchbrackets + matchhalf, NULL, NULL); + + reverse = ((ch - matchbrackets) >= matchhalf); + + /* If we're on an opening bracket, set wanted_ch to the character + * that's matchhalf characters after ch. If we're on a closing + * bracket, set wanted_ch to the character that's matchhalf + * characters before ch. */ + wanted_ch = ch; + + while (mbmatchhalf > 0) { + if (reverse) + wanted_ch = matchbrackets + move_mbleft(matchbrackets, + wanted_ch - matchbrackets); + else + wanted_ch += move_mbright(wanted_ch, 0); + + mbmatchhalf--; + } + + ch_len = parse_mbchar(ch, NULL, NULL); + wanted_ch_len = parse_mbchar(wanted_ch, NULL, NULL); + + /* Fill bracket_set in with the values of ch and wanted_ch. */ + strncpy(bracket_set, ch, ch_len); + strncpy(bracket_set + ch_len, wanted_ch, wanted_ch_len); + bracket_set[ch_len + wanted_ch_len] = '\0'; + + while (TRUE) { + if (find_bracket_match(reverse, bracket_set)) { + /* If we found an identical bracket, increment count. If we + * found a complementary bracket, decrement it. */ + count += (strncmp(openfile->current->data + openfile->current_x, + ch, ch_len) == 0) ? 1 : -1; + + /* If count is zero, we've found a matching bracket. Update + * the screen and get out. */ + if (count == 0) { + edit_redraw(current_save, FLOWING); + break; + } + } else { + /* We didn't find either an opening or closing bracket. + * Indicate this, restore where we were, and get out. */ + statusbar(_("No matching bracket")); + openfile->current = current_save; + openfile->current_x = current_x_save; + break; + } } - } } #endif /* !NANO_TINY */ diff --git a/src/text.c b/src/text.c index 7852f0e2..ac45c6b2 100644 --- a/src/text.c +++ b/src/text.c @@ -32,41 +32,41 @@ #ifndef NANO_TINY static pid_t pid = -1; - /* The PID of the forked process in execute_command(), for use - * with the cancel_command() signal handler. */ + /* The PID of the forked process in execute_command(), for use + * with the cancel_command() signal handler. */ #endif #ifdef ENABLE_WRAPPING static bool prepend_wrap = FALSE; - /* Should we prepend wrapped text to the next line? */ + /* Should we prepend wrapped text to the next line? */ #endif #ifdef ENABLE_JUSTIFY static filestruct *jusbuffer = NULL; - /* The buffer where we store unjustified text. */ + /* The buffer where we store unjustified text. */ static filestruct *jusbottom = NULL; - /* A pointer to the end of the buffer with unjustified text. */ + /* A pointer to the end of the buffer with unjustified text. */ #endif #ifdef ENABLE_WORDCOMPLETION static int pletion_x = 0; - /* The x position in pletion_line of the last found completion. */ + /* The x position in pletion_line of the last found completion. */ static completion_word *list_of_completions; - /* A linked list of the completions that have been attempted. */ + /* A linked list of the completions that have been attempted. */ #endif #ifndef NANO_TINY /* Toggle the mark. */ void do_mark(void) { - if (!openfile->mark) { - openfile->mark = openfile->current; - openfile->mark_x = openfile->current_x; - statusbar(_("Mark Set")); - openfile->kind_of_mark = HARDMARK; - } else { - openfile->mark = NULL; - statusbar(_("Mark Unset")); - refresh_needed = TRUE; - } + if (!openfile->mark) { + openfile->mark = openfile->current; + openfile->mark_x = openfile->current_x; + statusbar(_("Mark Set")); + openfile->kind_of_mark = HARDMARK; + } else { + openfile->mark = NULL; + statusbar(_("Mark Unset")); + refresh_needed = TRUE; + } } #endif /* !NANO_TINY */ @@ -74,11 +74,11 @@ void do_mark(void) /* Return an error message containing the given name. */ char *invocation_error(const char *name) { - char *message, *invoke_error = _("Error invoking \"%s\""); + char *message, *invoke_error = _("Error invoking \"%s\""); - message = charalloc(strlen(invoke_error) + strlen(name) + 1); - sprintf(message, invoke_error, name); - return message; + message = charalloc(strlen(invoke_error) + strlen(name) + 1); + sprintf(message, invoke_error, name); + return message; } #endif @@ -86,108 +86,108 @@ char *invocation_error(const char *name) void do_deletion(undo_type action) { #ifndef NANO_TINY - size_t old_amount = 0; + size_t old_amount = 0; #endif - openfile->placewewant = xplustabs(); + openfile->placewewant = xplustabs(); - if (openfile->current->data[openfile->current_x] != '\0') { - /* We're in the middle of a line: delete the current character. */ - int char_len = parse_mbchar(openfile->current->data + - openfile->current_x, NULL, NULL); - size_t line_len = strlen(openfile->current->data + - openfile->current_x); + if (openfile->current->data[openfile->current_x] != '\0') { + /* We're in the middle of a line: delete the current character. */ + int char_len = parse_mbchar(openfile->current->data + + openfile->current_x, NULL, NULL); + size_t line_len = strlen(openfile->current->data + + openfile->current_x); #ifndef NANO_TINY - update_undo(action); + update_undo(action); - if (ISSET(SOFTWRAP)) - old_amount = number_of_chunks_in(openfile->current); + if (ISSET(SOFTWRAP)) + old_amount = number_of_chunks_in(openfile->current); #endif - /* Move the remainder of the line "in", over the current character. */ - charmove(&openfile->current->data[openfile->current_x], - &openfile->current->data[openfile->current_x + char_len], - line_len - char_len + 1); + /* Move the remainder of the line "in", over the current character. */ + charmove(&openfile->current->data[openfile->current_x], + &openfile->current->data[openfile->current_x + char_len], + line_len - char_len + 1); #ifndef NANO_TINY - /* Adjust the mark if it is after the cursor on the current line. */ - if (openfile->mark == openfile->current && - openfile->mark_x > openfile->current_x) - openfile->mark_x -= char_len; + /* Adjust the mark if it is after the cursor on the current line. */ + if (openfile->mark == openfile->current && + openfile->mark_x > openfile->current_x) + openfile->mark_x -= char_len; #endif - /* Adjust the file size. */ - openfile->totsize--; - } else if (openfile->current != openfile->filebot) { - /* We're at the end of a line and not at the end of the file: join - * this line with the next. */ - filestruct *joining = openfile->current->next; + /* Adjust the file size. */ + openfile->totsize--; + } else if (openfile->current != openfile->filebot) { + /* We're at the end of a line and not at the end of the file: join + * this line with the next. */ + filestruct *joining = openfile->current->next; - /* If there is a magic line, and we're before it: don't eat it. */ - if (joining == openfile->filebot && openfile->current_x != 0 && - !ISSET(NO_NEWLINES)) { + /* If there is a magic line, and we're before it: don't eat it. */ + if (joining == openfile->filebot && openfile->current_x != 0 && + !ISSET(NO_NEWLINES)) { #ifndef NANO_TINY - if (action == BACK) - add_undo(BACK); + if (action == BACK) + add_undo(BACK); #endif - return; - } + return; + } #ifndef NANO_TINY - add_undo(action); + add_undo(action); #endif - /* Add the contents of the next line to those of the current one. */ - openfile->current->data = charealloc(openfile->current->data, - strlen(openfile->current->data) + strlen(joining->data) + 1); - strcat(openfile->current->data, joining->data); + /* Add the contents of the next line to those of the current one. */ + openfile->current->data = charealloc(openfile->current->data, + strlen(openfile->current->data) + strlen(joining->data) + 1); + strcat(openfile->current->data, joining->data); - /* Adjust the file size. */ - openfile->totsize--; + /* Adjust the file size. */ + openfile->totsize--; #ifndef NANO_TINY - /* Remember the new file size for a possible redo. */ - openfile->current_undo->newsize = openfile->totsize; + /* Remember the new file size for a possible redo. */ + openfile->current_undo->newsize = openfile->totsize; - /* Adjust the mark if it was on the line that was "eaten". */ - if (openfile->mark == joining) { - openfile->mark = openfile->current; - openfile->mark_x += openfile->current_x; - } + /* Adjust the mark if it was on the line that was "eaten". */ + if (openfile->mark == joining) { + openfile->mark = openfile->current; + openfile->mark_x += openfile->current_x; + } #endif - unlink_node(joining); - renumber(openfile->current); + unlink_node(joining); + renumber(openfile->current); - /* Two lines were joined, so we need to refresh the screen. */ - refresh_needed = TRUE; - } else - /* We're at the end-of-file: nothing to do. */ - return; + /* Two lines were joined, so we need to refresh the screen. */ + refresh_needed = TRUE; + } else + /* We're at the end-of-file: nothing to do. */ + return; #ifndef NANO_TINY - /* If the number of screen rows that a softwrapped line occupies - * has changed, we need a full refresh. */ - if (ISSET(SOFTWRAP) && refresh_needed == FALSE && - number_of_chunks_in(openfile->current) != old_amount) - refresh_needed = TRUE; + /* If the number of screen rows that a softwrapped line occupies + * has changed, we need a full refresh. */ + if (ISSET(SOFTWRAP) && refresh_needed == FALSE && + number_of_chunks_in(openfile->current) != old_amount) + refresh_needed = TRUE; #endif - set_modified(); + set_modified(); } /* Delete the character under the cursor. */ void do_delete(void) { - do_deletion(DEL); + do_deletion(DEL); } /* Backspace over one character. That is, move the cursor left one * character, and then delete the character under the cursor. */ void do_backspace(void) { - if (openfile->current != openfile->fileage || openfile->current_x > 0) { - do_left(); - do_deletion(BACK); - } + if (openfile->current != openfile->fileage || openfile->current_x > 0) { + do_left(); + do_deletion(BACK); + } } #ifndef NANO_TINY @@ -195,49 +195,49 @@ void do_backspace(void) * the right, or to the left when backward is true. */ void do_cutword(bool backward) { - /* Remember the current cursor position. */ - filestruct *is_current = openfile->current; - size_t is_current_x = openfile->current_x; + /* Remember the current cursor position. */ + filestruct *is_current = openfile->current; + size_t is_current_x = openfile->current_x; - /* Remember where the cutbuffer is and then make it seem blank. */ - filestruct *is_cutbuffer = cutbuffer; - filestruct *is_cutbottom = cutbottom; - cutbuffer = NULL; - cutbottom = NULL; + /* Remember where the cutbuffer is and then make it seem blank. */ + filestruct *is_cutbuffer = cutbuffer; + filestruct *is_cutbottom = cutbottom; + cutbuffer = NULL; + cutbottom = NULL; - /* Move the cursor to a word start, to the left or to the right. */ - if (backward) - do_prev_word(ISSET(WORD_BOUNDS), FALSE); - else - do_next_word(ISSET(WORD_BOUNDS), FALSE); + /* Move the cursor to a word start, to the left or to the right. */ + if (backward) + do_prev_word(ISSET(WORD_BOUNDS), FALSE); + else + do_next_word(ISSET(WORD_BOUNDS), FALSE); - /* Set the mark at the start of that word. */ - openfile->mark = openfile->current; - openfile->mark_x = openfile->current_x; + /* Set the mark at the start of that word. */ + openfile->mark = openfile->current; + openfile->mark_x = openfile->current_x; - /* Put the cursor back where it was, so an undo will put it there too. */ - openfile->current = is_current; - openfile->current_x = is_current_x; + /* Put the cursor back where it was, so an undo will put it there too. */ + openfile->current = is_current; + openfile->current_x = is_current_x; - /* Now kill the marked region and a word is gone. */ - do_cut_text_void(); + /* Now kill the marked region and a word is gone. */ + do_cut_text_void(); - /* Discard the cut word and restore the cutbuffer. */ - free_filestruct(cutbuffer); - cutbuffer = is_cutbuffer; - cutbottom = is_cutbottom; + /* Discard the cut word and restore the cutbuffer. */ + free_filestruct(cutbuffer); + cutbuffer = is_cutbuffer; + cutbottom = is_cutbottom; } /* Delete a word leftward. */ void do_cut_prev_word(void) { - do_cutword(TRUE); + do_cutword(TRUE); } /* Delete a word rightward. */ void do_cut_next_word(void) { - do_cutword(FALSE); + do_cutword(FALSE); } #endif /* !NANO_TINY */ @@ -246,46 +246,46 @@ void do_cut_next_word(void) void do_tab(void) { #ifndef NANO_TINY - if (ISSET(TABS_TO_SPACES)) { - char *spaces = charalloc(tabsize + 1); - size_t length = tabsize - (xplustabs() % tabsize); + if (ISSET(TABS_TO_SPACES)) { + char *spaces = charalloc(tabsize + 1); + size_t length = tabsize - (xplustabs() % tabsize); - charset(spaces, ' ', length); - spaces[length] = '\0'; + charset(spaces, ' ', length); + spaces[length] = '\0'; - do_output(spaces, length, TRUE); + do_output(spaces, length, TRUE); - free(spaces); - } else + free(spaces); + } else #endif - do_output((char *)"\t", 1, TRUE); + do_output((char *)"\t", 1, TRUE); } #ifndef NANO_TINY /* Add an indent to the given line. */ void indent_a_line(filestruct *line, char *indentation) { - size_t length = strlen(line->data); - size_t indent_len = strlen(indentation); + size_t length = strlen(line->data); + size_t indent_len = strlen(indentation); - /* If the indent is empty, don't change the line. */ - if (indent_len == 0) - return; + /* If the indent is empty, don't change the line. */ + if (indent_len == 0) + return; - /* Add the fabricated indentation to the beginning of the line. */ - line->data = charealloc(line->data, length + indent_len + 1); - charmove(line->data + indent_len, line->data, length + 1); - strncpy(line->data, indentation, indent_len); + /* Add the fabricated indentation to the beginning of the line. */ + line->data = charealloc(line->data, length + indent_len + 1); + charmove(line->data + indent_len, line->data, length + 1); + strncpy(line->data, indentation, indent_len); - openfile->totsize += indent_len; + openfile->totsize += indent_len; - /* Compensate for the change in the current line. */ - if (line == openfile->mark && openfile->mark_x > 0) - openfile->mark_x += indent_len; - if (line == openfile->current && openfile->current_x > 0) { - openfile->current_x += indent_len; - openfile->placewewant = xplustabs(); - } + /* Compensate for the change in the current line. */ + if (line == openfile->mark && openfile->mark_x > 0) + openfile->mark_x += indent_len; + if (line == openfile->current && openfile->current_x > 0) { + openfile->current_x += indent_len; + openfile->placewewant = xplustabs(); + } } /* Indent the current line (or the marked lines) by tabsize columns. @@ -293,247 +293,247 @@ void indent_a_line(filestruct *line, char *indentation) * depending on whether --tabstospaces is in effect. */ void do_indent(void) { - char *indentation; - filestruct *top, *bot, *line; + char *indentation; + filestruct *top, *bot, *line; - /* Use either all the marked lines or just the current line. */ - get_range((const filestruct **)&top, (const filestruct **)&bot); + /* Use either all the marked lines or just the current line. */ + get_range((const filestruct **)&top, (const filestruct **)&bot); - /* Skip any leading empty lines. */ - while (top != bot->next && top->data[0] == '\0') - top = top->next; + /* Skip any leading empty lines. */ + while (top != bot->next && top->data[0] == '\0') + top = top->next; - /* If all lines are empty, there is nothing to do. */ - if (top == bot->next) - return; + /* If all lines are empty, there is nothing to do. */ + if (top == bot->next) + return; - indentation = charalloc(tabsize + 1); + indentation = charalloc(tabsize + 1); - /* Set the indentation to either a bunch of spaces or a single tab. */ - if (ISSET(TABS_TO_SPACES)) { - charset(indentation, ' ', tabsize); - indentation[tabsize] = '\0'; - } else { - indentation[0] = '\t'; - indentation[1] = '\0'; - } + /* Set the indentation to either a bunch of spaces or a single tab. */ + if (ISSET(TABS_TO_SPACES)) { + charset(indentation, ' ', tabsize); + indentation[tabsize] = '\0'; + } else { + indentation[0] = '\t'; + indentation[1] = '\0'; + } - add_undo(INDENT); + add_undo(INDENT); - /* Go through each of the lines, but skip empty ones. */ - for (line = top; line != bot->next; line = line->next) { - char *real_indent = (line->data[0] == '\0') ? "" : indentation; + /* Go through each of the lines, but skip empty ones. */ + for (line = top; line != bot->next; line = line->next) { + char *real_indent = (line->data[0] == '\0') ? "" : indentation; - /* Indent a line, add undo data, and save the original indent. */ - indent_a_line(line, real_indent); - update_multiline_undo(line->lineno, real_indent); - } + /* Indent a line, add undo data, and save the original indent. */ + indent_a_line(line, real_indent); + update_multiline_undo(line->lineno, real_indent); + } - free(indentation); + free(indentation); - set_modified(); - refresh_needed = TRUE; - shift_held = TRUE; + set_modified(); + refresh_needed = TRUE; + shift_held = TRUE; } /* Return the number of bytes of whitespace at the start of the given text, * but at most a tab's worth. */ size_t length_of_white(const char *text) { - size_t bytes_of_white = 0; + size_t bytes_of_white = 0; - while (TRUE) { - if (*text == '\t') - return ++bytes_of_white; + while (TRUE) { + if (*text == '\t') + return ++bytes_of_white; - if (*text != ' ') - return bytes_of_white; + if (*text != ' ') + return bytes_of_white; - if (++bytes_of_white == tabsize) - return tabsize; + if (++bytes_of_white == tabsize) + return tabsize; - text++; - } + text++; + } } /* Adjust the positions of mark and cursor when they are on the given line. */ void compensate_leftward(filestruct *line, size_t leftshift) { - if (line == openfile->mark) { - if (openfile->mark_x < leftshift) - openfile->mark_x = 0; - else - openfile->mark_x -= leftshift; - } + if (line == openfile->mark) { + if (openfile->mark_x < leftshift) + openfile->mark_x = 0; + else + openfile->mark_x -= leftshift; + } - if (line == openfile->current) { - if (openfile->current_x < leftshift) - openfile->current_x = 0; - else - openfile->current_x -= leftshift; - openfile->placewewant = xplustabs(); - } + if (line == openfile->current) { + if (openfile->current_x < leftshift) + openfile->current_x = 0; + else + openfile->current_x -= leftshift; + openfile->placewewant = xplustabs(); + } } /* Remove an indent from the given line. */ void unindent_a_line(filestruct *line, size_t indent_len) { - size_t length = strlen(line->data); + size_t length = strlen(line->data); - /* If the indent is empty, don't change the line. */ - if (indent_len == 0) - return; + /* If the indent is empty, don't change the line. */ + if (indent_len == 0) + return; - /* Remove the first tab's worth of whitespace from this line. */ - charmove(line->data, line->data + indent_len, length - indent_len + 1); + /* Remove the first tab's worth of whitespace from this line. */ + charmove(line->data, line->data + indent_len, length - indent_len + 1); - openfile->totsize -= indent_len; + openfile->totsize -= indent_len; - /* Adjust the positions of mark and cursor, when they are affected. */ - compensate_leftward(line, indent_len); + /* Adjust the positions of mark and cursor, when they are affected. */ + compensate_leftward(line, indent_len); } /* Unindent the current line (or the marked lines) by tabsize columns. * The removed indent can be a mixture of spaces plus at most one tab. */ void do_unindent(void) { - filestruct *top, *bot, *line; + filestruct *top, *bot, *line; - /* Use either all the marked lines or just the current line. */ - get_range((const filestruct **)&top, (const filestruct **)&bot); + /* Use either all the marked lines or just the current line. */ + get_range((const filestruct **)&top, (const filestruct **)&bot); - /* Skip any leading lines that cannot be unindented. */ - while (top != bot->next && length_of_white(top->data) == 0) - top = top->next; + /* Skip any leading lines that cannot be unindented. */ + while (top != bot->next && length_of_white(top->data) == 0) + top = top->next; - /* If none of the lines can be unindented, there is nothing to do. */ - if (top == bot->next) - return; + /* If none of the lines can be unindented, there is nothing to do. */ + if (top == bot->next) + return; - add_undo(UNINDENT); + add_undo(UNINDENT); - /* Go through each of the lines and remove their leading indent. */ - for (line = top; line != bot->next; line = line->next) { - size_t indent_len = length_of_white(line->data); - char *indentation = mallocstrncpy(NULL, line->data, indent_len + 1); + /* Go through each of the lines and remove their leading indent. */ + for (line = top; line != bot->next; line = line->next) { + size_t indent_len = length_of_white(line->data); + char *indentation = mallocstrncpy(NULL, line->data, indent_len + 1); - indentation[indent_len] = '\0'; + indentation[indent_len] = '\0'; - /* Unindent a line, add undo data, and save the original indent. */ - unindent_a_line(line, indent_len); - update_multiline_undo(line->lineno, indentation); + /* Unindent a line, add undo data, and save the original indent. */ + unindent_a_line(line, indent_len); + update_multiline_undo(line->lineno, indentation); - free(indentation); - } + free(indentation); + } - set_modified(); - refresh_needed = TRUE; - shift_held = TRUE; + set_modified(); + refresh_needed = TRUE; + shift_held = TRUE; } /* Perform an undo or redo for an indent or unindent action. */ void handle_indent_action(undo *u, bool undoing, bool add_indent) { - undo_group *group = u->grouping; + undo_group *group = u->grouping; - /* When redoing, reposition the cursor and let the indenter adjust it. */ - if (!undoing) - goto_line_posx(u->lineno, u->begin); + /* When redoing, reposition the cursor and let the indenter adjust it. */ + if (!undoing) + goto_line_posx(u->lineno, u->begin); - while (group) { - filestruct *line = fsfromline(group->top_line); + while (group) { + filestruct *line = fsfromline(group->top_line); - /* For each line in the group, add or remove the individual indent. */ - while (line && line->lineno <= group->bottom_line) { - char *blanks = group->indentations[line->lineno - group->top_line]; + /* For each line in the group, add or remove the individual indent. */ + while (line && line->lineno <= group->bottom_line) { + char *blanks = group->indentations[line->lineno - group->top_line]; - if (undoing ^ add_indent) - indent_a_line(line, blanks); - else - unindent_a_line(line, strlen(blanks)); + if (undoing ^ add_indent) + indent_a_line(line, blanks); + else + unindent_a_line(line, strlen(blanks)); - line = line->next; + line = line->next; + } + + group = group->next; } - group = group->next; - } + /* When undoing, reposition the cursor to the recorded location. */ + if (undoing) + goto_line_posx(u->lineno, u->begin); - /* When undoing, reposition the cursor to the recorded location. */ - if (undoing) - goto_line_posx(u->lineno, u->begin); - - refresh_needed = TRUE; + refresh_needed = TRUE; } #endif /* !NANO_TINY */ /* Test whether the string is empty or consists of only blanks. */ bool white_string(const char *s) { - while (*s != '\0' && (is_blank_mbchar(s) || *s == '\r')) - s += move_mbright(s, 0); + while (*s != '\0' && (is_blank_mbchar(s) || *s == '\r')) + s += move_mbright(s, 0); - return !*s; + return !*s; } #ifdef ENABLE_COMMENT /* Comment or uncomment the current line or the marked lines. */ void do_comment(void) { - const char *comment_seq = GENERAL_COMMENT_CHARACTER; - undo_type action = UNCOMMENT; - filestruct *top, *bot, *line; - bool empty, all_empty = TRUE; + const char *comment_seq = GENERAL_COMMENT_CHARACTER; + undo_type action = UNCOMMENT; + filestruct *top, *bot, *line; + bool empty, all_empty = TRUE; #ifdef ENABLE_COLOR - if (openfile->syntax) - comment_seq = openfile->syntax->comment; + if (openfile->syntax) + comment_seq = openfile->syntax->comment; - if (*comment_seq == '\0') { - statusbar(_("Commenting is not supported for this file type")); - return; - } + if (*comment_seq == '\0') { + statusbar(_("Commenting is not supported for this file type")); + return; + } #endif - /* Determine which lines to work on. */ - get_range((const filestruct **)&top, (const filestruct **)&bot); + /* Determine which lines to work on. */ + get_range((const filestruct **)&top, (const filestruct **)&bot); - /* If only the magic line is selected, don't do anything. */ - if (top == bot && bot == openfile->filebot && !ISSET(NO_NEWLINES)) { - statusbar(_("Cannot comment past end of file")); - return; - } - - /* Figure out whether to comment or uncomment the selected line or lines. */ - for (line = top; line != bot->next; line = line->next) { - empty = white_string(line->data); - - /* If this line is not blank and not commented, we comment all. */ - if (!empty && !comment_line(PREFLIGHT, line, comment_seq)) { - action = COMMENT; - break; + /* If only the magic line is selected, don't do anything. */ + if (top == bot && bot == openfile->filebot && !ISSET(NO_NEWLINES)) { + statusbar(_("Cannot comment past end of file")); + return; } - all_empty = all_empty && empty; - } - /* If all selected lines are blank, we comment them. */ - action = all_empty ? COMMENT : action; + /* Figure out whether to comment or uncomment the selected line or lines. */ + for (line = top; line != bot->next; line = line->next) { + empty = white_string(line->data); - add_undo(action); + /* If this line is not blank and not commented, we comment all. */ + if (!empty && !comment_line(PREFLIGHT, line, comment_seq)) { + action = COMMENT; + break; + } + all_empty = all_empty && empty; + } - /* Store the comment sequence used for the operation, because it could - * change when the file name changes; we need to know what it was. */ - openfile->current_undo->strdata = mallocstrcpy(NULL, comment_seq); + /* If all selected lines are blank, we comment them. */ + action = all_empty ? COMMENT : action; - /* Process the selected line or lines. */ - for (line = top; line != bot->next; line = line->next) { - /* Comment/uncomment a line, and add undo data when line changed. */ - if (comment_line(action, line, comment_seq)) - update_multiline_undo(line->lineno, ""); - } + add_undo(action); - set_modified(); - refresh_needed = TRUE; - shift_held = TRUE; + /* Store the comment sequence used for the operation, because it could + * change when the file name changes; we need to know what it was. */ + openfile->current_undo->strdata = mallocstrcpy(NULL, comment_seq); + + /* Process the selected line or lines. */ + for (line = top; line != bot->next; line = line->next) { + /* Comment/uncomment a line, and add undo data when line changed. */ + if (comment_line(action, line, comment_seq)) + update_multiline_undo(line->lineno, ""); + } + + set_modified(); + refresh_needed = TRUE; + shift_held = TRUE; } /* Test whether the given line can be uncommented, or add or remove a comment, @@ -541,89 +541,89 @@ void do_comment(void) * anything was added or removed; FALSE otherwise. */ bool comment_line(undo_type action, filestruct *line, const char *comment_seq) { - size_t comment_seq_len = strlen(comment_seq); - const char *post_seq = strchr(comment_seq, '|'); - /* The postfix, if this is a bracketing type comment sequence. */ - size_t pre_len = post_seq ? post_seq++ - comment_seq : comment_seq_len; - /* Length of prefix. */ - size_t post_len = post_seq ? comment_seq_len - pre_len - 1 : 0; - /* Length of postfix. */ - size_t line_len = strlen(line->data); + size_t comment_seq_len = strlen(comment_seq); + const char *post_seq = strchr(comment_seq, '|'); + /* The postfix, if this is a bracketing type comment sequence. */ + size_t pre_len = post_seq ? post_seq++ - comment_seq : comment_seq_len; + /* Length of prefix. */ + size_t post_len = post_seq ? comment_seq_len - pre_len - 1 : 0; + /* Length of postfix. */ + size_t line_len = strlen(line->data); - if (!ISSET(NO_NEWLINES) && line == openfile->filebot) - return FALSE; + if (!ISSET(NO_NEWLINES) && line == openfile->filebot) + return FALSE; - if (action == COMMENT) { - /* Make room for the comment sequence(s), move the text right and - * copy them in. */ - line->data = charealloc(line->data, line_len + pre_len + post_len + 1); - charmove(line->data + pre_len, line->data, line_len + 1); - charmove(line->data, comment_seq, pre_len); - if (post_len > 0) - charmove(line->data + pre_len + line_len, post_seq, post_len + 1); + if (action == COMMENT) { + /* Make room for the comment sequence(s), move the text right and + * copy them in. */ + line->data = charealloc(line->data, line_len + pre_len + post_len + 1); + charmove(line->data + pre_len, line->data, line_len + 1); + charmove(line->data, comment_seq, pre_len); + if (post_len > 0) + charmove(line->data + pre_len + line_len, post_seq, post_len + 1); - openfile->totsize += pre_len + post_len; + openfile->totsize += pre_len + post_len; - /* If needed, adjust the position of the mark and of the cursor. */ - if (line == openfile->mark && openfile->mark_x > 0) - openfile->mark_x += pre_len; - if (line == openfile->current && openfile->current_x > 0) { - openfile->current_x += pre_len; - openfile->placewewant = xplustabs(); + /* If needed, adjust the position of the mark and of the cursor. */ + if (line == openfile->mark && openfile->mark_x > 0) + openfile->mark_x += pre_len; + if (line == openfile->current && openfile->current_x > 0) { + openfile->current_x += pre_len; + openfile->placewewant = xplustabs(); + } + + return TRUE; } - return TRUE; - } + /* If the line is commented, report it as uncommentable, or uncomment it. */ + if (strncmp(line->data, comment_seq, pre_len) == 0 && (post_len == 0 || + strcmp(line->data + line_len - post_len, post_seq) == 0)) { - /* If the line is commented, report it as uncommentable, or uncomment it. */ - if (strncmp(line->data, comment_seq, pre_len) == 0 && (post_len == 0 || - strcmp(line->data + line_len - post_len, post_seq) == 0)) { + if (action == PREFLIGHT) + return TRUE; - if (action == PREFLIGHT) - return TRUE; + /* Erase the comment prefix by moving the non-comment part. */ + charmove(line->data, line->data + pre_len, line_len - pre_len); + /* Truncate the postfix if there was one. */ + line->data[line_len - pre_len - post_len] = '\0'; - /* Erase the comment prefix by moving the non-comment part. */ - charmove(line->data, line->data + pre_len, line_len - pre_len); - /* Truncate the postfix if there was one. */ - line->data[line_len - pre_len - post_len] = '\0'; + openfile->totsize -= pre_len + post_len; - openfile->totsize -= pre_len + post_len; + /* Adjust the positions of mark and cursor, when needed. */ + compensate_leftward(line, pre_len); - /* Adjust the positions of mark and cursor, when needed. */ - compensate_leftward(line, pre_len); + return TRUE; + } - return TRUE; - } - - return FALSE; + return FALSE; } /* Perform an undo or redo for a comment or uncomment action. */ void handle_comment_action(undo *u, bool undoing, bool add_comment) { - undo_group *group = u->grouping; + undo_group *group = u->grouping; - /* When redoing, reposition the cursor and let the commenter adjust it. */ - if (!undoing) - goto_line_posx(u->lineno, u->begin); + /* When redoing, reposition the cursor and let the commenter adjust it. */ + if (!undoing) + goto_line_posx(u->lineno, u->begin); - while (group) { - filestruct *f = fsfromline(group->top_line); + while (group) { + filestruct *f = fsfromline(group->top_line); - while (f && f->lineno <= group->bottom_line) { - comment_line(undoing ^ add_comment ? - COMMENT : UNCOMMENT, f, u->strdata); - f = f->next; + while (f && f->lineno <= group->bottom_line) { + comment_line(undoing ^ add_comment ? + COMMENT : UNCOMMENT, f, u->strdata); + f = f->next; + } + + group = group->next; } - group = group->next; - } + /* When undoing, reposition the cursor to the recorded location. */ + if (undoing) + goto_line_posx(u->lineno, u->begin); - /* When undoing, reposition the cursor to the recorded location. */ - if (undoing) - goto_line_posx(u->lineno, u->begin); - - refresh_needed = TRUE; + refresh_needed = TRUE; } #endif /* ENABLE_COMMENT */ @@ -634,442 +634,442 @@ void handle_comment_action(undo *u, bool undoing, bool add_comment) /* Undo a cut, or redo an uncut. */ void undo_cut(undo *u) { - /* If we cut the magicline, we may as well not crash. :/ */ - if (!u->cutbuffer) - return; + /* If we cut the magicline, we may as well not crash. :/ */ + if (!u->cutbuffer) + return; - /* Get to where we need to uncut from. */ - if (u->xflags == WAS_WHOLE_LINE) - goto_line_posx(u->mark_begin_lineno, 0); - else - goto_line_posx(u->mark_begin_lineno, u->mark_begin_x); + /* Get to where we need to uncut from. */ + if (u->xflags == WAS_WHOLE_LINE) + goto_line_posx(u->mark_begin_lineno, 0); + else + goto_line_posx(u->mark_begin_lineno, u->mark_begin_x); - copy_from_buffer(u->cutbuffer); + copy_from_buffer(u->cutbuffer); - if (u->xflags != WAS_MARKED_FORWARD && u->type != PASTE) - goto_line_posx(u->mark_begin_lineno, u->mark_begin_x); + if (u->xflags != WAS_MARKED_FORWARD && u->type != PASTE) + goto_line_posx(u->mark_begin_lineno, u->mark_begin_x); } /* Redo a cut, or undo an uncut. */ void redo_cut(undo *u) { - filestruct *oldcutbuffer = cutbuffer, *oldcutbottom = cutbottom; + filestruct *oldcutbuffer = cutbuffer, *oldcutbottom = cutbottom; - /* If we cut the magicline, we may as well not crash. :/ */ - if (!u->cutbuffer) - return; + /* If we cut the magicline, we may as well not crash. :/ */ + if (!u->cutbuffer) + return; - cutbuffer = NULL; - cutbottom = NULL; + cutbuffer = NULL; + cutbottom = NULL; - goto_line_posx(u->lineno, u->begin); + goto_line_posx(u->lineno, u->begin); - openfile->mark = fsfromline(u->mark_begin_lineno); - openfile->mark_x = (u->xflags == WAS_WHOLE_LINE) ? 0 : u->mark_begin_x; + openfile->mark = fsfromline(u->mark_begin_lineno); + openfile->mark_x = (u->xflags == WAS_WHOLE_LINE) ? 0 : u->mark_begin_x; - do_cut_text(FALSE, FALSE); + do_cut_text(FALSE, FALSE); - free_filestruct(cutbuffer); - cutbuffer = oldcutbuffer; - cutbottom = oldcutbottom; + free_filestruct(cutbuffer); + cutbuffer = oldcutbuffer; + cutbottom = oldcutbottom; } /* Undo the last thing(s) we did. */ void do_undo(void) { - undo *u = openfile->current_undo; - filestruct *f, *t = NULL; - filestruct *oldcutbuffer, *oldcutbottom; - char *data, *undidmsg = NULL; - size_t from_x, to_x; + undo *u = openfile->current_undo; + filestruct *f, *t = NULL; + filestruct *oldcutbuffer, *oldcutbottom; + char *data, *undidmsg = NULL; + size_t from_x, to_x; - if (!u) { - statusbar(_("Nothing in undo buffer!")); - return; - } + if (!u) { + statusbar(_("Nothing in undo buffer!")); + return; + } - f = fsfromline(u->mark_begin_lineno); - if (!f) - return; + f = fsfromline(u->mark_begin_lineno); + if (!f) + return; #ifdef DEBUG - fprintf(stderr, " >> Undoing a type %d...\n", u->type); - fprintf(stderr, " >> Data we're about to undo = \"%s\"\n", f->data); + fprintf(stderr, " >> Undoing a type %d...\n", u->type); + fprintf(stderr, " >> Data we're about to undo = \"%s\"\n", f->data); #endif - openfile->current_x = u->begin; - switch (u->type) { - case ADD: - /* TRANSLATORS: The next twelve strings describe actions - * that are undone or redone. It are all nouns, not verbs. */ - undidmsg = _("text add"); - if (u->xflags == WAS_FINAL_LINE && !ISSET(NO_NEWLINES)) - remove_magicline(); - data = charalloc(strlen(f->data) - strlen(u->strdata) + 1); - strncpy(data, f->data, u->begin); - strcpy(&data[u->begin], &f->data[u->begin + strlen(u->strdata)]); - free(f->data); - f->data = data; - goto_line_posx(u->lineno, u->begin); - break; - case BACK: - case DEL: - undidmsg = _("text delete"); - data = charalloc(strlen(f->data) + strlen(u->strdata) + 1); - strncpy(data, f->data, u->begin); - strcpy(&data[u->begin], u->strdata); - strcpy(&data[u->begin + strlen(u->strdata)], &f->data[u->begin]); - free(f->data); - f->data = data; - goto_line_posx(u->mark_begin_lineno, u->mark_begin_x); - break; + openfile->current_x = u->begin; + switch (u->type) { + case ADD: + /* TRANSLATORS: The next twelve strings describe actions + * that are undone or redone. It are all nouns, not verbs. */ + undidmsg = _("text add"); + if (u->xflags == WAS_FINAL_LINE && !ISSET(NO_NEWLINES)) + remove_magicline(); + data = charalloc(strlen(f->data) - strlen(u->strdata) + 1); + strncpy(data, f->data, u->begin); + strcpy(&data[u->begin], &f->data[u->begin + strlen(u->strdata)]); + free(f->data); + f->data = data; + goto_line_posx(u->lineno, u->begin); + break; + case BACK: + case DEL: + undidmsg = _("text delete"); + data = charalloc(strlen(f->data) + strlen(u->strdata) + 1); + strncpy(data, f->data, u->begin); + strcpy(&data[u->begin], u->strdata); + strcpy(&data[u->begin + strlen(u->strdata)], &f->data[u->begin]); + free(f->data); + f->data = data; + goto_line_posx(u->mark_begin_lineno, u->mark_begin_x); + break; #ifdef ENABLE_WRAPPING - case SPLIT_END: - goto_line_posx(u->lineno, u->begin); + case SPLIT_END: + goto_line_posx(u->lineno, u->begin); + openfile->current_undo = openfile->current_undo->next; + openfile->last_action = OTHER; + while (openfile->current_undo->type != SPLIT_BEGIN) + do_undo(); + u = openfile->current_undo; + f = openfile->current; + case SPLIT_BEGIN: + undidmsg = _("text add"); + break; +#endif + case JOIN: + undidmsg = _("line join"); + /* When the join was done by a Backspace at the tail of the file, + * and the nonewlines flag isn't set, do not re-add a newline that + * wasn't actually deleted; just position the cursor. */ + if (u->xflags == WAS_FINAL_BACKSPACE && !ISSET(NO_NEWLINES)) { + goto_line_posx(openfile->filebot->lineno, 0); + break; + } + t = make_new_node(f); + t->data = mallocstrcpy(NULL, u->strdata); + data = mallocstrncpy(NULL, f->data, u->mark_begin_x + 1); + data[u->mark_begin_x] = '\0'; + free(f->data); + f->data = data; + splice_node(f, t); + goto_line_posx(u->lineno, u->begin); + break; + case CUT_TO_EOF: + case CUT: + undidmsg = _("text cut"); + undo_cut(u); + f = fsfromline(u->lineno); + break; + case PASTE: + undidmsg = _("text uncut"); + undo_paste(u); + f = fsfromline(u->mark_begin_lineno); + break; + case ENTER: + if (f->next == NULL) { + statusline(ALERT, "Missing break line -- please report a bug"); + break; + } + undidmsg = _("line break"); + from_x = (u->begin == 0) ? 0 : u->mark_begin_x; + to_x = (u->begin == 0) ? u->mark_begin_x : u->begin; + f->data = charealloc(f->data, strlen(f->data) + + strlen(&u->strdata[from_x]) + 1); + strcat(f->data, &u->strdata[from_x]); + unlink_node(f->next); + goto_line_posx(u->lineno, to_x); + break; + case INDENT: + handle_indent_action(u, TRUE, TRUE); + undidmsg = _("indent"); + break; + case UNINDENT: + handle_indent_action(u, TRUE, FALSE); + undidmsg = _("unindent"); + break; +#ifdef ENABLE_COMMENT + case COMMENT: + handle_comment_action(u, TRUE, TRUE); + undidmsg = _("comment"); + break; + case UNCOMMENT: + handle_comment_action(u, TRUE, FALSE); + undidmsg = _("uncomment"); + break; +#endif + case INSERT: + undidmsg = _("text insert"); + oldcutbuffer = cutbuffer; + oldcutbottom = cutbottom; + cutbuffer = NULL; + cutbottom = NULL; + openfile->mark = fsfromline(u->mark_begin_lineno); + openfile->mark_x = u->mark_begin_x; + goto_line_posx(u->lineno, u->begin); + cut_marked(NULL); + free_filestruct(u->cutbuffer); + u->cutbuffer = cutbuffer; + u->cutbottom = cutbottom; + cutbuffer = oldcutbuffer; + cutbottom = oldcutbottom; + 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: + statusline(ALERT, "Wrong undo type -- please report a bug"); + break; + } + + if (undidmsg && !pletion_line) + statusline(HUSH, _("Undid action (%s)"), undidmsg); + + renumber(f); + openfile->current_undo = openfile->current_undo->next; openfile->last_action = OTHER; - while (openfile->current_undo->type != SPLIT_BEGIN) - do_undo(); - u = openfile->current_undo; - f = openfile->current; - case SPLIT_BEGIN: - undidmsg = _("text add"); - break; -#endif - case JOIN: - undidmsg = _("line join"); - /* When the join was done by a Backspace at the tail of the file, - * and the nonewlines flag isn't set, do not re-add a newline that - * wasn't actually deleted; just position the cursor. */ - if (u->xflags == WAS_FINAL_BACKSPACE && !ISSET(NO_NEWLINES)) { - goto_line_posx(openfile->filebot->lineno, 0); - break; - } - t = make_new_node(f); - t->data = mallocstrcpy(NULL, u->strdata); - data = mallocstrncpy(NULL, f->data, u->mark_begin_x + 1); - data[u->mark_begin_x] = '\0'; - free(f->data); - f->data = data; - splice_node(f, t); - goto_line_posx(u->lineno, u->begin); - break; - case CUT_TO_EOF: - case CUT: - undidmsg = _("text cut"); - undo_cut(u); - f = fsfromline(u->lineno); - break; - case PASTE: - undidmsg = _("text uncut"); - undo_paste(u); - f = fsfromline(u->mark_begin_lineno); - break; - case ENTER: - if (f->next == NULL) { - statusline(ALERT, "Missing break line -- please report a bug"); - break; - } - undidmsg = _("line break"); - from_x = (u->begin == 0) ? 0 : u->mark_begin_x; - to_x = (u->begin == 0) ? u->mark_begin_x : u->begin; - f->data = charealloc(f->data, strlen(f->data) + - strlen(&u->strdata[from_x]) + 1); - strcat(f->data, &u->strdata[from_x]); - unlink_node(f->next); - goto_line_posx(u->lineno, to_x); - break; - case INDENT: - handle_indent_action(u, TRUE, TRUE); - undidmsg = _("indent"); - break; - case UNINDENT: - handle_indent_action(u, TRUE, FALSE); - undidmsg = _("unindent"); - break; -#ifdef ENABLE_COMMENT - case COMMENT: - handle_comment_action(u, TRUE, TRUE); - undidmsg = _("comment"); - break; - case UNCOMMENT: - handle_comment_action(u, TRUE, FALSE); - undidmsg = _("uncomment"); - break; -#endif - case INSERT: - undidmsg = _("text insert"); - oldcutbuffer = cutbuffer; - oldcutbottom = cutbottom; - cutbuffer = NULL; - cutbottom = NULL; - openfile->mark = fsfromline(u->mark_begin_lineno); - openfile->mark_x = u->mark_begin_x; - goto_line_posx(u->lineno, u->begin); - cut_marked(NULL); - free_filestruct(u->cutbuffer); - u->cutbuffer = cutbuffer; - u->cutbottom = cutbottom; - cutbuffer = oldcutbuffer; - cutbottom = oldcutbottom; - 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: - statusline(ALERT, "Wrong undo type -- please report a bug"); - break; - } + openfile->mark = NULL; + openfile->placewewant = xplustabs(); - if (undidmsg && !pletion_line) - statusline(HUSH, _("Undid action (%s)"), undidmsg); + openfile->totsize = u->wassize; - renumber(f); - - openfile->current_undo = openfile->current_undo->next; - openfile->last_action = OTHER; - openfile->mark = NULL; - openfile->placewewant = xplustabs(); - - openfile->totsize = u->wassize; - - /* When at the point where the file was last saved, unset "Modified". */ - if (openfile->current_undo == openfile->last_saved) { - openfile->modified = FALSE; - titlebar(NULL); - } else - set_modified(); + /* When at the point where the file was last saved, unset "Modified". */ + if (openfile->current_undo == openfile->last_saved) { + openfile->modified = FALSE; + titlebar(NULL); + } else + set_modified(); } /* Redo the last thing(s) we undid. */ void do_redo(void) { - filestruct *f, *shoveline; - char *data, *redidmsg = NULL; - undo *u = openfile->undotop; + filestruct *f, *shoveline; + char *data, *redidmsg = NULL; + undo *u = openfile->undotop; - if (u == NULL || u == openfile->current_undo) { - statusbar(_("Nothing to re-do!")); - return; - } + if (u == NULL || u == openfile->current_undo) { + statusbar(_("Nothing to re-do!")); + return; + } - /* Get the previous undo item. */ - while (u != NULL && u->next != openfile->current_undo) - u = u->next; + /* Get the previous undo item. */ + while (u != NULL && u->next != openfile->current_undo) + u = u->next; - if (u->next != openfile->current_undo) { - statusline(ALERT, "Bad undo stack -- please report a bug"); - return; - } + if (u->next != openfile->current_undo) { + statusline(ALERT, "Bad undo stack -- please report a bug"); + return; + } - f = fsfromline(u->mark_begin_lineno); - if (!f) - return; + f = fsfromline(u->mark_begin_lineno); + if (!f) + return; #ifdef DEBUG - fprintf(stderr, " >> Redo running for type %d\n", u->type); - fprintf(stderr, " >> Data we're about to redo = \"%s\"\n", f->data); + fprintf(stderr, " >> Redo running for type %d\n", u->type); + fprintf(stderr, " >> Data we're about to redo = \"%s\"\n", f->data); #endif - switch (u->type) { - case ADD: - redidmsg = _("text add"); - if (u->xflags == WAS_FINAL_LINE && !ISSET(NO_NEWLINES)) - new_magicline(); - data = charalloc(strlen(f->data) + strlen(u->strdata) + 1); - strncpy(data, f->data, u->begin); - strcpy(&data[u->begin], u->strdata); - strcpy(&data[u->begin + strlen(u->strdata)], &f->data[u->begin]); - free(f->data); - f->data = data; - goto_line_posx(u->mark_begin_lineno, u->mark_begin_x); - break; - case BACK: - case DEL: - redidmsg = _("text delete"); - data = charalloc(strlen(f->data) + strlen(u->strdata) + 1); - strncpy(data, f->data, u->begin); - strcpy(&data[u->begin], &f->data[u->begin + strlen(u->strdata)]); - free(f->data); - f->data = data; - goto_line_posx(u->lineno, u->begin); - break; - case ENTER: - redidmsg = _("line break"); - shoveline = make_new_node(f); - shoveline->data = mallocstrcpy(NULL, u->strdata); - data = mallocstrncpy(NULL, f->data, u->begin + 1); - data[u->begin] = '\0'; - free(f->data); - f->data = data; - splice_node(f, shoveline); - renumber(shoveline); - goto_line_posx(u->lineno + 1, u->mark_begin_x); - break; + switch (u->type) { + case ADD: + redidmsg = _("text add"); + if (u->xflags == WAS_FINAL_LINE && !ISSET(NO_NEWLINES)) + new_magicline(); + data = charalloc(strlen(f->data) + strlen(u->strdata) + 1); + strncpy(data, f->data, u->begin); + strcpy(&data[u->begin], u->strdata); + strcpy(&data[u->begin + strlen(u->strdata)], &f->data[u->begin]); + free(f->data); + f->data = data; + goto_line_posx(u->mark_begin_lineno, u->mark_begin_x); + break; + case BACK: + case DEL: + redidmsg = _("text delete"); + data = charalloc(strlen(f->data) + strlen(u->strdata) + 1); + strncpy(data, f->data, u->begin); + strcpy(&data[u->begin], &f->data[u->begin + strlen(u->strdata)]); + free(f->data); + f->data = data; + goto_line_posx(u->lineno, u->begin); + break; + case ENTER: + redidmsg = _("line break"); + shoveline = make_new_node(f); + shoveline->data = mallocstrcpy(NULL, u->strdata); + data = mallocstrncpy(NULL, f->data, u->begin + 1); + data[u->begin] = '\0'; + free(f->data); + f->data = data; + splice_node(f, shoveline); + renumber(shoveline); + goto_line_posx(u->lineno + 1, u->mark_begin_x); + break; #ifdef ENABLE_WRAPPING - case SPLIT_BEGIN: - goto_line_posx(u->lineno, u->begin); + case SPLIT_BEGIN: + goto_line_posx(u->lineno, u->begin); + openfile->current_undo = u; + openfile->last_action = OTHER; + while (openfile->current_undo->type != SPLIT_END) + do_redo(); + u = openfile->current_undo; + goto_line_posx(u->lineno, u->begin); + case SPLIT_END: + redidmsg = _("text add"); + break; +#endif + case JOIN: + if (f->next == NULL) { + statusline(ALERT, "Missing join line -- please report a bug"); + break; + } + redidmsg = _("line join"); + /* When the join was done by a Backspace at the tail of the file, + * and the nonewlines flag isn't set, do not join anything, as + * nothing was actually deleted; just position the cursor. */ + if (u->xflags == WAS_FINAL_BACKSPACE && !ISSET(NO_NEWLINES)) { + goto_line_posx(u->mark_begin_lineno, u->mark_begin_x); + break; + } + f->data = charealloc(f->data, strlen(f->data) + strlen(u->strdata) + 1); + strcat(f->data, u->strdata); + unlink_node(f->next); + renumber(f); + goto_line_posx(u->mark_begin_lineno, u->mark_begin_x); + break; + case CUT_TO_EOF: + case CUT: + redidmsg = _("text cut"); + redo_cut(u); + break; + case PASTE: + redidmsg = _("text uncut"); + redo_paste(u); + break; + case REPLACE: + redidmsg = _("text replace"); + data = u->strdata; + u->strdata = f->data; + f->data = data; + goto_line_posx(u->lineno, u->begin); + break; + case INSERT: + redidmsg = _("text insert"); + goto_line_posx(u->lineno, u->begin); + copy_from_buffer(u->cutbuffer); + free_filestruct(u->cutbuffer); + u->cutbuffer = NULL; + break; + case INDENT: + handle_indent_action(u, FALSE, TRUE); + redidmsg = _("indent"); + break; + case UNINDENT: + handle_indent_action(u, FALSE, FALSE); + redidmsg = _("unindent"); + break; +#ifdef ENABLE_COMMENT + case COMMENT: + handle_comment_action(u, FALSE, TRUE); + redidmsg = _("comment"); + break; + case UNCOMMENT: + handle_comment_action(u, FALSE, FALSE); + redidmsg = _("uncomment"); + break; +#endif + default: + statusline(ALERT, "Wrong redo type -- please report a bug"); + break; + } + + if (redidmsg) + statusline(HUSH, _("Redid action (%s)"), redidmsg); + openfile->current_undo = u; openfile->last_action = OTHER; - while (openfile->current_undo->type != SPLIT_END) - do_redo(); - u = openfile->current_undo; - goto_line_posx(u->lineno, u->begin); - case SPLIT_END: - redidmsg = _("text add"); - break; -#endif - case JOIN: - if (f->next == NULL) { - statusline(ALERT, "Missing join line -- please report a bug"); - break; - } - redidmsg = _("line join"); - /* When the join was done by a Backspace at the tail of the file, - * and the nonewlines flag isn't set, do not join anything, as - * nothing was actually deleted; just position the cursor. */ - if (u->xflags == WAS_FINAL_BACKSPACE && !ISSET(NO_NEWLINES)) { - goto_line_posx(u->mark_begin_lineno, u->mark_begin_x); - break; - } - f->data = charealloc(f->data, strlen(f->data) + strlen(u->strdata) + 1); - strcat(f->data, u->strdata); - unlink_node(f->next); - renumber(f); - goto_line_posx(u->mark_begin_lineno, u->mark_begin_x); - break; - case CUT_TO_EOF: - case CUT: - redidmsg = _("text cut"); - redo_cut(u); - break; - case PASTE: - redidmsg = _("text uncut"); - redo_paste(u); - break; - case REPLACE: - redidmsg = _("text replace"); - data = u->strdata; - u->strdata = f->data; - f->data = data; - goto_line_posx(u->lineno, u->begin); - break; - case INSERT: - redidmsg = _("text insert"); - goto_line_posx(u->lineno, u->begin); - copy_from_buffer(u->cutbuffer); - free_filestruct(u->cutbuffer); - u->cutbuffer = NULL; - break; - case INDENT: - handle_indent_action(u, FALSE, TRUE); - redidmsg = _("indent"); - break; - case UNINDENT: - handle_indent_action(u, FALSE, FALSE); - redidmsg = _("unindent"); - break; -#ifdef ENABLE_COMMENT - case COMMENT: - handle_comment_action(u, FALSE, TRUE); - redidmsg = _("comment"); - break; - case UNCOMMENT: - handle_comment_action(u, FALSE, FALSE); - redidmsg = _("uncomment"); - break; -#endif - default: - statusline(ALERT, "Wrong redo type -- please report a bug"); - break; - } + openfile->mark = NULL; + openfile->placewewant = xplustabs(); - if (redidmsg) - statusline(HUSH, _("Redid action (%s)"), redidmsg); + openfile->totsize = u->newsize; - openfile->current_undo = u; - openfile->last_action = OTHER; - openfile->mark = NULL; - openfile->placewewant = xplustabs(); - - openfile->totsize = u->newsize; - - /* When at the point where the file was last saved, unset "Modified". */ - if (openfile->current_undo == openfile->last_saved) { - openfile->modified = FALSE; - titlebar(NULL); - } else - set_modified(); + /* When at the point where the file was last saved, unset "Modified". */ + if (openfile->current_undo == openfile->last_saved) { + openfile->modified = FALSE; + titlebar(NULL); + } else + set_modified(); } #endif /* !NANO_TINY */ /* Break the current line at the cursor position. */ void do_enter(void) { - filestruct *newnode = make_new_node(openfile->current); - size_t extra = 0; + filestruct *newnode = make_new_node(openfile->current); + size_t extra = 0; #ifndef NANO_TINY - bool allblanks = FALSE; + bool allblanks = FALSE; - if (ISSET(AUTOINDENT)) { - extra = indent_length(openfile->current->data); + if (ISSET(AUTOINDENT)) { + extra = indent_length(openfile->current->data); - /* If we are breaking the line in the indentation, limit the new - * indentation to the current x position. */ - if (extra > openfile->current_x) - extra = openfile->current_x; - else if (extra == openfile->current_x) - allblanks = TRUE; - } + /* If we are breaking the line in the indentation, limit the new + * indentation to the current x position. */ + if (extra > openfile->current_x) + extra = openfile->current_x; + else if (extra == openfile->current_x) + allblanks = TRUE; + } #endif - newnode->data = charalloc(strlen(openfile->current->data + - openfile->current_x) + extra + 1); - strcpy(&newnode->data[extra], openfile->current->data + - openfile->current_x); + newnode->data = charalloc(strlen(openfile->current->data + + openfile->current_x) + extra + 1); + strcpy(&newnode->data[extra], openfile->current->data + + openfile->current_x); #ifndef NANO_TINY - if (ISSET(AUTOINDENT)) { - /* Copy the whitespace from the current line to the new one. */ - strncpy(newnode->data, openfile->current->data, extra); - /* If there were only blanks before the cursor, trim them. */ - if (allblanks) - openfile->current_x = 0; - else - openfile->totsize += extra; - } + if (ISSET(AUTOINDENT)) { + /* Copy the whitespace from the current line to the new one. */ + strncpy(newnode->data, openfile->current->data, extra); + /* If there were only blanks before the cursor, trim them. */ + if (allblanks) + openfile->current_x = 0; + else + openfile->totsize += extra; + } #endif - null_at(&openfile->current->data, openfile->current_x); + null_at(&openfile->current->data, openfile->current_x); #ifndef NANO_TINY - add_undo(ENTER); + add_undo(ENTER); - /* Adjust the mark if it was on the current line after the cursor. */ - if (openfile->mark == openfile->current && - openfile->mark_x > openfile->current_x) { - openfile->mark = newnode; - openfile->mark_x += extra - openfile->current_x; - } + /* Adjust the mark if it was on the current line after the cursor. */ + if (openfile->mark == openfile->current && + openfile->mark_x > openfile->current_x) { + openfile->mark = newnode; + openfile->mark_x += extra - openfile->current_x; + } #endif - splice_node(openfile->current, newnode); - renumber(newnode); + splice_node(openfile->current, newnode); + renumber(newnode); - openfile->current = newnode; - openfile->current_x = extra; - openfile->placewewant = xplustabs(); + openfile->current = newnode; + openfile->current_x = extra; + openfile->placewewant = xplustabs(); - openfile->totsize++; - set_modified(); + openfile->totsize++; + set_modified(); #ifndef NANO_TINY - update_undo(ENTER); + update_undo(ENTER); #endif - refresh_needed = TRUE; + refresh_needed = TRUE; } #ifndef NANO_TINY @@ -1077,260 +1077,260 @@ void do_enter(void) * execute_command(). */ RETSIGTYPE cancel_command(int signal) { - if (kill(pid, SIGKILL) == -1) - nperror("kill"); + if (kill(pid, SIGKILL) == -1) + nperror("kill"); } /* Execute command in a shell. Return TRUE on success. */ bool execute_command(const char *command) { - int fd[2]; - FILE *f; - const char *shellenv; - struct sigaction oldaction, newaction; - /* Original and temporary handlers for SIGINT. */ - bool sig_failed = FALSE; - /* Did sigaction() fail without changing the signal handlers? */ + int fd[2]; + FILE *f; + const char *shellenv; + struct sigaction oldaction, newaction; + /* Original and temporary handlers for SIGINT. */ + bool sig_failed = FALSE; + /* Did sigaction() fail without changing the signal handlers? */ - /* Make our pipes. */ - if (pipe(fd) == -1) { - 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. */ - shellenv = getenv("SHELL"); - if (shellenv == NULL) - shellenv = (char *) "/bin/sh"; - - /* Fork a child. */ - if ((pid = fork()) == 0) { - close(fd[0]); - dup2(fd[1], fileno(stdout)); - dup2(fd[1], fileno(stderr)); - - /* If execl() returns at all, there was an error. */ - execl(shellenv, tail(shellenv), "-c", command, NULL); - exit(0); - } - - /* Continue as parent. */ - close(fd[1]); - - if (pid == -1) { - close(fd[0]); - statusbar(_("Could not fork")); - return FALSE; - } - - /* Before we start reading the forked command's output, we 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_signals(); - - if (sigaction(SIGINT, NULL, &newaction) == -1) { - sig_failed = TRUE; - nperror("sigaction"); - } else { - newaction.sa_handler = cancel_command; - if (sigaction(SIGINT, &newaction, &oldaction) == -1) { - sig_failed = TRUE; - nperror("sigaction"); + /* Make our pipes. */ + if (pipe(fd) == -1) { + statusbar(_("Could not create pipe")); + return FALSE; } - } - /* Note that now oldaction is the previous SIGINT signal handler, - * to be restored later. */ + /* 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"; - f = fdopen(fd[0], "rb"); - if (f == NULL) - nperror("fdopen"); + /* Fork a child. */ + if ((pid = fork()) == 0) { + close(fd[0]); + dup2(fd[1], fileno(stdout)); + dup2(fd[1], fileno(stderr)); - read_file(f, 0, "stdin", TRUE, FALSE); + /* If execl() returns at all, there was an error. */ + execl(shellenv, tail(shellenv), "-c", command, NULL); + exit(0); + } - if (wait(NULL) == -1) - nperror("wait"); + /* Continue as parent. */ + close(fd[1]); - if (!sig_failed && sigaction(SIGINT, &oldaction, NULL) == -1) - nperror("sigaction"); + if (pid == -1) { + close(fd[0]); + statusbar(_("Could not fork")); + return FALSE; + } - /* Restore the terminal to its previous state. In the process, - * disable interpretation of the special control keys so that we can - * use Ctrl-C for other things. */ - terminal_init(); + /* Before we start reading the forked command's output, we set + * things up so that Ctrl-C will cancel the new process. */ - return TRUE; + /* Enable interpretation of the special control keys so that we get + * SIGINT when Ctrl-C is pressed. */ + enable_signals(); + + if (sigaction(SIGINT, NULL, &newaction) == -1) { + sig_failed = TRUE; + nperror("sigaction"); + } else { + newaction.sa_handler = cancel_command; + if (sigaction(SIGINT, &newaction, &oldaction) == -1) { + sig_failed = TRUE; + nperror("sigaction"); + } + } + + /* Note that now oldaction is the previous SIGINT signal handler, + * to be restored later. */ + + f = fdopen(fd[0], "rb"); + if (f == NULL) + nperror("fdopen"); + + read_file(f, 0, "stdin", TRUE, FALSE); + + if (wait(NULL) == -1) + nperror("wait"); + + if (!sig_failed && sigaction(SIGINT, &oldaction, NULL) == -1) + nperror("sigaction"); + + /* Restore the terminal to its previous state. In the process, + * disable interpretation of the special control keys so that we can + * use Ctrl-C for other things. */ + terminal_init(); + + return TRUE; } /* Discard undo items that are newer than the given one, or all if NULL. * When keep is TRUE, do not touch the last_saved pointer. */ void discard_until(const undo *thisitem, openfilestruct *thefile, bool keep) { - undo *dropit = thefile->undotop; - undo_group *group; + undo *dropit = thefile->undotop; + undo_group *group; - while (dropit != NULL && dropit != thisitem) { - thefile->undotop = dropit->next; - free(dropit->strdata); - free_filestruct(dropit->cutbuffer); - group = dropit->grouping; - while (group != NULL) { - undo_group *next = group->next; - free_chararray(group->indentations, - group->bottom_line - group->top_line); - free(group); - group = next; + while (dropit != NULL && dropit != thisitem) { + thefile->undotop = dropit->next; + free(dropit->strdata); + free_filestruct(dropit->cutbuffer); + group = dropit->grouping; + while (group != NULL) { + undo_group *next = group->next; + free_chararray(group->indentations, + group->bottom_line - group->top_line); + free(group); + group = next; + } + dropit = thefile->undotop; } - dropit = thefile->undotop; - } - /* Adjust the pointer to the top of the undo stack. */ - thefile->current_undo = (undo *)thisitem; + /* Adjust the pointer to the top of the undo stack. */ + thefile->current_undo = (undo *)thisitem; - /* Prevent a chain of editing actions from continuing. */ - thefile->last_action = OTHER; + /* Prevent a chain of editing actions from continuing. */ + thefile->last_action = OTHER; - /* When requested, record that the undo stack was chopped, and - * that thus there is no point at which the file was last saved. */ - if (!keep) - thefile->last_saved = (undo *)0xbeeb; + /* When requested, record that the undo stack was chopped, and + * that thus there is no point at which the file was last saved. */ + if (!keep) + thefile->last_saved = (undo *)0xbeeb; } /* Add a new undo struct to the top of the current pile. */ void add_undo(undo_type action) { - undo *u = openfile->current_undo; - /* The thing we did previously. */ + undo *u = openfile->current_undo; + /* The thing we did previously. */ - /* When doing contiguous adds or contiguous cuts -- which means: with - * no cursor movement in between -- don't add a new undo item. */ - if (u && u->mark_begin_lineno == openfile->current->lineno && action == openfile->last_action && - ((action == ADD && u->type == ADD && u->mark_begin_x == openfile->current_x) || - (action == CUT && u->type == CUT && u->xflags < MARK_WAS_SET && keeping_cutbuffer()))) - return; + /* When doing contiguous adds or contiguous cuts -- which means: with + * no cursor movement in between -- don't add a new undo item. */ + if (u && u->mark_begin_lineno == openfile->current->lineno && action == openfile->last_action && + ((action == ADD && u->type == ADD && u->mark_begin_x == openfile->current_x) || + (action == CUT && u->type == CUT && u->xflags < MARK_WAS_SET && keeping_cutbuffer()))) + return; - /* Blow away newer undo items if we add somewhere in the middle. */ - discard_until(u, openfile, TRUE); + /* Blow away newer undo items if we add somewhere in the middle. */ + discard_until(u, openfile, TRUE); #ifdef DEBUG - fprintf(stderr, " >> Adding an undo...\n"); + fprintf(stderr, " >> Adding an undo...\n"); #endif - /* Allocate and initialize a new undo type. */ - u = (undo *) nmalloc(sizeof(undo)); - u->type = action; + /* Allocate and initialize a new undo type. */ + u = (undo *) nmalloc(sizeof(undo)); + u->type = action; #ifdef ENABLE_WRAPPING - if (u->type == SPLIT_BEGIN) { - /* Some action, most likely an ADD, was performed that invoked - * do_wrap(). Rearrange the undo order so that this previous - * action is after the SPLIT_BEGIN undo. */ - u->next = openfile->undotop->next; - openfile->undotop->next = u; - } else + if (u->type == SPLIT_BEGIN) { + /* Some action, most likely an ADD, was performed that invoked + * do_wrap(). Rearrange the undo order so that this previous + * action is after the SPLIT_BEGIN undo. */ + u->next = openfile->undotop->next; + openfile->undotop->next = u; + } else #endif - { - u->next = openfile->undotop; - openfile->undotop = u; - openfile->current_undo = u; - } - u->strdata = NULL; - u->cutbuffer = NULL; - u->cutbottom = NULL; - u->lineno = openfile->current->lineno; - u->begin = openfile->current_x; - u->mark_begin_lineno = openfile->current->lineno; - u->mark_begin_x = openfile->current_x; - u->wassize = openfile->totsize; - u->xflags = 0; - u->grouping = NULL; + { + u->next = openfile->undotop; + openfile->undotop = u; + openfile->current_undo = u; + } + u->strdata = NULL; + u->cutbuffer = NULL; + u->cutbottom = NULL; + u->lineno = openfile->current->lineno; + u->begin = openfile->current_x; + u->mark_begin_lineno = openfile->current->lineno; + u->mark_begin_x = openfile->current_x; + u->wassize = openfile->totsize; + u->xflags = 0; + u->grouping = NULL; - switch (u->type) { - /* We need to start copying data into the undo buffer - * or we won't be able to restore it later. */ - case ADD: - /* If a new magic line will be added, an undo should remove it. */ - if (openfile->current == openfile->filebot) - u->xflags = WAS_FINAL_LINE; - u->wassize--; - break; - case BACK: - /* If the next line is the magic line, don't ever undo this - * backspace, as it won't actually have deleted anything. */ - if (openfile->current->next == openfile->filebot && - openfile->current->data[0] != '\0') - u->xflags = WAS_FINAL_BACKSPACE; - case DEL: - if (openfile->current->data[openfile->current_x] != '\0') { - char *char_buf = charalloc(MAXCHARLEN + 1); - int char_len = parse_mbchar(&openfile->current->data[u->begin], - char_buf, NULL); - char_buf[char_len] = '\0'; - u->strdata = char_buf; - if (u->type == BACK) - u->mark_begin_x += char_len; - break; - } - /* Else purposely fall into the line-joining code. */ - case JOIN: - if (openfile->current->next) { - if (u->type == BACK) { - u->lineno = openfile->current->next->lineno; - u->begin = 0; - } - u->strdata = mallocstrcpy(NULL, openfile->current->next->data); - } - action = u->type = JOIN; - break; + switch (u->type) { + /* We need to start copying data into the undo buffer + * or we won't be able to restore it later. */ + case ADD: + /* If a new magic line will be added, an undo should remove it. */ + if (openfile->current == openfile->filebot) + u->xflags = WAS_FINAL_LINE; + u->wassize--; + break; + case BACK: + /* If the next line is the magic line, don't ever undo this + * backspace, as it won't actually have deleted anything. */ + if (openfile->current->next == openfile->filebot && + openfile->current->data[0] != '\0') + u->xflags = WAS_FINAL_BACKSPACE; + case DEL: + if (openfile->current->data[openfile->current_x] != '\0') { + char *char_buf = charalloc(MAXCHARLEN + 1); + int char_len = parse_mbchar(&openfile->current->data[u->begin], + char_buf, NULL); + char_buf[char_len] = '\0'; + u->strdata = char_buf; + if (u->type == BACK) + u->mark_begin_x += char_len; + break; + } + /* Else purposely fall into the line-joining code. */ + case JOIN: + if (openfile->current->next) { + if (u->type == BACK) { + u->lineno = openfile->current->next->lineno; + u->begin = 0; + } + u->strdata = mallocstrcpy(NULL, openfile->current->next->data); + } + action = u->type = JOIN; + break; #ifdef ENABLE_WRAPPING - case SPLIT_BEGIN: - action = openfile->undotop->type; - break; - case SPLIT_END: - break; + case SPLIT_BEGIN: + action = openfile->undotop->type; + break; + case SPLIT_END: + break; #endif - case INSERT: - break; - case REPLACE: - u->strdata = mallocstrcpy(NULL, openfile->current->data); - break; - case CUT_TO_EOF: - cutbuffer_reset(); - break; - case CUT: - cutbuffer_reset(); - if (openfile->mark) { - u->mark_begin_lineno = openfile->mark->lineno; - u->mark_begin_x = openfile->mark_x; - u->xflags = MARK_WAS_SET; - } else if (!ISSET(CUT_FROM_CURSOR)) { - /* The entire line is being cut regardless of the cursor position. */ - u->begin = 0; - u->xflags = WAS_WHOLE_LINE; - } - break; - case PASTE: - u->cutbuffer = copy_filestruct(cutbuffer); - u->lineno += cutbottom->lineno - cutbuffer->lineno; - break; - case ENTER: - break; - case INDENT: - case UNINDENT: - break; + case INSERT: + break; + case REPLACE: + u->strdata = mallocstrcpy(NULL, openfile->current->data); + break; + case CUT_TO_EOF: + cutbuffer_reset(); + break; + case CUT: + cutbuffer_reset(); + if (openfile->mark) { + u->mark_begin_lineno = openfile->mark->lineno; + u->mark_begin_x = openfile->mark_x; + u->xflags = MARK_WAS_SET; + } else if (!ISSET(CUT_FROM_CURSOR)) { + /* The entire line is being cut regardless of the cursor position. */ + u->begin = 0; + u->xflags = WAS_WHOLE_LINE; + } + break; + case PASTE: + u->cutbuffer = copy_filestruct(cutbuffer); + u->lineno += cutbottom->lineno - cutbuffer->lineno; + break; + case ENTER: + break; + case INDENT: + case UNINDENT: + break; #ifdef ENABLE_COMMENT - case COMMENT: - case UNCOMMENT: - break; + case COMMENT: + case UNCOMMENT: + break; #endif - default: - statusline(ALERT, "Wrong undo adding type -- please report a bug"); - break; - } + default: + statusline(ALERT, "Wrong undo adding type -- please report a bug"); + break; + } - openfile->last_action = action; + openfile->last_action = action; } /* Update a multiline undo item. This should be called once for each line @@ -1338,34 +1338,34 @@ void add_undo(undo_type action) * is saved separately for each line in the undo item. */ void update_multiline_undo(ssize_t lineno, char *indentation) { - undo *u = openfile->current_undo; + undo *u = openfile->current_undo; - /* If there already is a group and the current line is contiguous with it, - * extend the group; otherwise, create a new group. */ - if (u->grouping && u->grouping->bottom_line + 1 == lineno) { - size_t number_of_lines; + /* If there already is a group and the current line is contiguous with it, + * extend the group; otherwise, create a new group. */ + if (u->grouping && u->grouping->bottom_line + 1 == lineno) { + size_t number_of_lines; - u->grouping->bottom_line++; + u->grouping->bottom_line++; - number_of_lines = u->grouping->bottom_line - u->grouping->top_line + 1; - u->grouping->indentations = (char **)nrealloc(u->grouping->indentations, - number_of_lines * sizeof(char *)); - u->grouping->indentations[number_of_lines - 1] = mallocstrcpy(NULL, - indentation); - } else { - undo_group *born = (undo_group *)nmalloc(sizeof(undo_group)); + number_of_lines = u->grouping->bottom_line - u->grouping->top_line + 1; + u->grouping->indentations = (char **)nrealloc(u->grouping->indentations, + number_of_lines * sizeof(char *)); + u->grouping->indentations[number_of_lines - 1] = mallocstrcpy(NULL, + indentation); + } else { + undo_group *born = (undo_group *)nmalloc(sizeof(undo_group)); - born->next = u->grouping; - u->grouping = born; - born->top_line = lineno; - born->bottom_line = lineno; + born->next = u->grouping; + u->grouping = born; + born->top_line = lineno; + born->bottom_line = lineno; - u->grouping->indentations = (char **)nmalloc(sizeof(char *)); - u->grouping->indentations[0] = mallocstrcpy(NULL, indentation); - } + u->grouping->indentations = (char **)nmalloc(sizeof(char *)); + u->grouping->indentations[0] = mallocstrcpy(NULL, indentation); + } - /* Store the file size after the change, to be used when redoing. */ - u->newsize = openfile->totsize; + /* Store the file size after the change, to be used when redoing. */ + u->newsize = openfile->totsize; } /* Update an undo item, or determine whether a new one is really needed @@ -1374,133 +1374,133 @@ void update_multiline_undo(ssize_t lineno, char *indentation) * so it should be axed if needed. */ void update_undo(undo_type action) { - undo *u; + undo *u; #ifdef DEBUG fprintf(stderr, " >> Updating... action = %d, openfile->last_action = %d, openfile->current->lineno = %ld", - action, openfile->last_action, (long)openfile->current->lineno); - if (openfile->current_undo) - fprintf(stderr, ", openfile->current_undo->lineno = %ld\n", (long)openfile->current_undo->lineno); - else - fprintf(stderr, "\n"); + action, openfile->last_action, (long)openfile->current->lineno); + if (openfile->current_undo) + fprintf(stderr, ", openfile->current_undo->lineno = %ld\n", (long)openfile->current_undo->lineno); + else + fprintf(stderr, "\n"); #endif - /* Change to an add if we're not using the same undo struct - * that we should be using. */ - if (action != openfile->last_action || - (action != ENTER && action != CUT && action != INSERT && - openfile->current->lineno != openfile->current_undo->lineno)) { - add_undo(action); - return; - } - - u = openfile->undotop; - - u->newsize = openfile->totsize; - - switch (u->type) { - case ADD: { -#ifdef DEBUG - fprintf(stderr, " >> openfile->current->data = \"%s\", current_x = %lu, u->begin = %lu\n", - openfile->current->data, (unsigned long)openfile->current_x, (unsigned long)u->begin); -#endif - char *char_buf = charalloc(MAXCHARLEN); - int char_len = parse_mbchar(&openfile->current->data[u->mark_begin_x], char_buf, NULL); - u->strdata = addstrings(u->strdata, u->strdata ? strlen(u->strdata) : 0, char_buf, char_len); -#ifdef DEBUG - fprintf(stderr, " >> current undo data is \"%s\"\n", u->strdata); -#endif - u->mark_begin_lineno = openfile->current->lineno; - u->mark_begin_x = openfile->current_x; - break; - } - case BACK: - case DEL: { - char *char_buf = charalloc(MAXCHARLEN); - int char_len = parse_mbchar(&openfile->current->data[openfile->current_x], char_buf, NULL); - if (openfile->current_x == u->begin) { - /* They deleted more: add removed character after earlier stuff. */ - u->strdata = addstrings(u->strdata, strlen(u->strdata), char_buf, char_len); - u->mark_begin_x = openfile->current_x; - } else if (openfile->current_x == u->begin - char_len) { - /* They backspaced further: add removed character before earlier. */ - u->strdata = addstrings(char_buf, char_len, u->strdata, strlen(u->strdata)); - u->begin = openfile->current_x; - } else { - /* They deleted *elsewhere* on the line: start a new undo item. */ - free(char_buf); - add_undo(u->type); - return; + /* Change to an add if we're not using the same undo struct + * that we should be using. */ + if (action != openfile->last_action || + (action != ENTER && action != CUT && action != INSERT && + openfile->current->lineno != openfile->current_undo->lineno)) { + add_undo(action); + return; } + + u = openfile->undotop; + + u->newsize = openfile->totsize; + + switch (u->type) { + case ADD: { #ifdef DEBUG - fprintf(stderr, " >> current undo data is \"%s\"\nu->begin = %lu\n", u->strdata, (unsigned long)u->begin); + fprintf(stderr, " >> openfile->current->data = \"%s\", current_x = %lu, u->begin = %lu\n", + openfile->current->data, (unsigned long)openfile->current_x, (unsigned long)u->begin); #endif - break; - } - case CUT_TO_EOF: - case CUT: - if (!cutbuffer) - break; - free_filestruct(u->cutbuffer); - u->cutbuffer = copy_filestruct(cutbuffer); - if (u->xflags == MARK_WAS_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) { - ssize_t line = u->lineno; - size_t x_loc = u->begin; - - u->begin = u->mark_begin_x; - u->mark_begin_x = x_loc; - - u->lineno = u->mark_begin_lineno; - u->mark_begin_lineno = line; - } else - u->xflags = WAS_MARKED_FORWARD; - } else { - /* Compute the end of the cut for the undo, using our copy. */ - u->cutbottom = u->cutbuffer; - while (u->cutbottom->next != NULL) - u->cutbottom = u->cutbottom->next; - u->lineno = u->mark_begin_lineno + u->cutbottom->lineno - - u->cutbuffer->lineno; - if (ISSET(CUT_FROM_CURSOR) || u->type == CUT_TO_EOF) { - u->begin = strlen(u->cutbottom->data); - if (u->lineno == u->mark_begin_lineno) - u->begin += u->mark_begin_x; - } else if (openfile->current == openfile->filebot && - ISSET(NO_NEWLINES)) - u->begin = strlen(u->cutbottom->data); + char *char_buf = charalloc(MAXCHARLEN); + int char_len = parse_mbchar(&openfile->current->data[u->mark_begin_x], char_buf, NULL); + u->strdata = addstrings(u->strdata, u->strdata ? strlen(u->strdata) : 0, char_buf, char_len); +#ifdef DEBUG + fprintf(stderr, " >> current undo data is \"%s\"\n", u->strdata); +#endif + u->mark_begin_lineno = openfile->current->lineno; + u->mark_begin_x = openfile->current_x; + break; } - break; - case REPLACE: - case PASTE: - u->begin = openfile->current_x; - u->lineno = openfile->current->lineno; - break; - case INSERT: - u->mark_begin_lineno = openfile->current->lineno; - u->mark_begin_x = openfile->current_x; - break; - case ENTER: - u->strdata = mallocstrcpy(NULL, openfile->current->data); - u->mark_begin_x = openfile->current_x; - break; + case BACK: + case DEL: { + char *char_buf = charalloc(MAXCHARLEN); + int char_len = parse_mbchar(&openfile->current->data[openfile->current_x], char_buf, NULL); + if (openfile->current_x == u->begin) { + /* They deleted more: add removed character after earlier stuff. */ + u->strdata = addstrings(u->strdata, strlen(u->strdata), char_buf, char_len); + u->mark_begin_x = openfile->current_x; + } else if (openfile->current_x == u->begin - char_len) { + /* They backspaced further: add removed character before earlier. */ + u->strdata = addstrings(char_buf, char_len, u->strdata, strlen(u->strdata)); + u->begin = openfile->current_x; + } else { + /* They deleted *elsewhere* on the line: start a new undo item. */ + free(char_buf); + add_undo(u->type); + return; + } +#ifdef DEBUG + fprintf(stderr, " >> current undo data is \"%s\"\nu->begin = %lu\n", u->strdata, (unsigned long)u->begin); +#endif + break; + } + case CUT_TO_EOF: + case CUT: + if (!cutbuffer) + break; + free_filestruct(u->cutbuffer); + u->cutbuffer = copy_filestruct(cutbuffer); + if (u->xflags == MARK_WAS_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) { + ssize_t line = u->lineno; + size_t x_loc = u->begin; + + u->begin = u->mark_begin_x; + u->mark_begin_x = x_loc; + + u->lineno = u->mark_begin_lineno; + u->mark_begin_lineno = line; + } else + u->xflags = WAS_MARKED_FORWARD; + } else { + /* Compute the end of the cut for the undo, using our copy. */ + u->cutbottom = u->cutbuffer; + while (u->cutbottom->next != NULL) + u->cutbottom = u->cutbottom->next; + u->lineno = u->mark_begin_lineno + u->cutbottom->lineno - + u->cutbuffer->lineno; + if (ISSET(CUT_FROM_CURSOR) || u->type == CUT_TO_EOF) { + u->begin = strlen(u->cutbottom->data); + if (u->lineno == u->mark_begin_lineno) + u->begin += u->mark_begin_x; + } else if (openfile->current == openfile->filebot && + ISSET(NO_NEWLINES)) + u->begin = strlen(u->cutbottom->data); + } + break; + case REPLACE: + case PASTE: + u->begin = openfile->current_x; + u->lineno = openfile->current->lineno; + break; + case INSERT: + u->mark_begin_lineno = openfile->current->lineno; + u->mark_begin_x = openfile->current_x; + break; + case ENTER: + u->strdata = mallocstrcpy(NULL, openfile->current->data); + u->mark_begin_x = openfile->current_x; + break; #ifdef ENABLE_WRAPPING - case SPLIT_BEGIN: - case SPLIT_END: + case SPLIT_BEGIN: + case SPLIT_END: #endif - case JOIN: - /* These cases are handled by the earlier check for a new line and action. */ - break; - default: - statusline(ALERT, "Wrong undo update type -- please report a bug"); - break; - } + case JOIN: + /* These cases are handled by the earlier check for a new line and action. */ + break; + default: + statusline(ALERT, "Wrong undo update type -- please report a bug"); + break; + } #ifdef DEBUG - fprintf(stderr, " >> Done in update_undo (type was %d)\n", action); + fprintf(stderr, " >> Done in update_undo (type was %d)\n", action); #endif } #endif /* !NANO_TINY */ @@ -1510,142 +1510,142 @@ fprintf(stderr, " >> Updating... action = %d, openfile->last_action = %d, openf * something other than type text. */ void wrap_reset(void) { - prepend_wrap = FALSE; + prepend_wrap = FALSE; } /* Try wrapping the given line. Return TRUE if wrapped, FALSE otherwise. */ bool do_wrap(filestruct *line) { - size_t line_len = strlen(line->data); - /* The length of the line we wrap. */ - ssize_t wrap_loc; - /* The index of line->data where we wrap. */ - const char *remainder; - /* The text after the wrap point. */ - size_t rest_length; - /* The length of the remainder. */ + size_t line_len = strlen(line->data); + /* The length of the line we wrap. */ + ssize_t wrap_loc; + /* The index of line->data where we wrap. */ + const char *remainder; + /* The text after the wrap point. */ + size_t rest_length; + /* The length of the remainder. */ - size_t old_x = openfile->current_x; - filestruct * old_line = openfile->current; + size_t old_x = openfile->current_x; + filestruct * old_line = openfile->current; - /* There are three steps. First, we decide where to wrap. Then, we - * create the new wrap line. Finally, we clean up. */ + /* There are three steps. First, we decide where to wrap. Then, we + * create the new wrap line. Finally, we clean up. */ - /* Step 1, finding where to wrap. We are going to add a new line - * after a blank character. In this step, we call break_line() to - * get the location of the last blank we can break the line at, and - * set wrap_loc to the location of the character after it, so that - * the blank is preserved at the end of the line. - * - * If there is no legal wrap point, or we reach the last character - * of the line while trying to find one, we should return without - * wrapping. Note that if autoindent is turned on, we don't break - * at the end of it! */ + /* Step 1, finding where to wrap. We are going to add a new line + * after a blank character. In this step, we call break_line() to + * get the location of the last blank we can break the line at, and + * set wrap_loc to the location of the character after it, so that + * the blank is preserved at the end of the line. + * + * If there is no legal wrap point, or we reach the last character + * of the line while trying to find one, we should return without + * wrapping. Note that if autoindent is turned on, we don't break + * at the end of it! */ - /* Find the last blank where we can break the line. */ - wrap_loc = break_line(line->data, fill, FALSE); + /* Find the last blank where we can break the line. */ + wrap_loc = break_line(line->data, fill, FALSE); - /* If we couldn't break the line, or we've reached the end of it, we - * don't wrap. */ - if (wrap_loc == -1 || line->data[wrap_loc] == '\0') - return FALSE; + /* If we couldn't break the line, or we've reached the end of it, we + * don't wrap. */ + if (wrap_loc == -1 || line->data[wrap_loc] == '\0') + return FALSE; - /* Otherwise, move forward to the character just after the blank. */ - wrap_loc += move_mbright(line->data + wrap_loc, 0); + /* Otherwise, move forward to the character just after the blank. */ + wrap_loc += move_mbright(line->data + wrap_loc, 0); - /* If we've reached the end of the line, we don't wrap. */ - if (line->data[wrap_loc] == '\0') - return FALSE; + /* If we've reached the end of the line, we don't wrap. */ + if (line->data[wrap_loc] == '\0') + return FALSE; #ifndef NANO_TINY - /* If autoindent is turned on, and we're on the character just after - * the indentation, we don't wrap. */ - if (ISSET(AUTOINDENT) && wrap_loc == indent_length(line->data)) - return FALSE; + /* If autoindent is turned on, and we're on the character just after + * the indentation, we don't wrap. */ + if (ISSET(AUTOINDENT) && wrap_loc == indent_length(line->data)) + return FALSE; - add_undo(SPLIT_BEGIN); + add_undo(SPLIT_BEGIN); #endif - openfile->current = line; + openfile->current = line; - /* Step 2, making the new wrap line. It will consist of indentation - * followed by the text after the wrap point, optionally followed by - * a space (if the text after the wrap point doesn't end in a blank) - * and the text of the next line, if they can fit without wrapping, - * the next line exists, and the prepend_wrap flag is set. */ + /* Step 2, making the new wrap line. It will consist of indentation + * followed by the text after the wrap point, optionally followed by + * a space (if the text after the wrap point doesn't end in a blank) + * and the text of the next line, if they can fit without wrapping, + * the next line exists, and the prepend_wrap flag is set. */ - /* The remainder is the text that will be wrapped to the next line. */ - remainder = line->data + wrap_loc; - rest_length = line_len - wrap_loc; + /* The remainder is the text that will be wrapped to the next line. */ + remainder = line->data + wrap_loc; + rest_length = line_len - wrap_loc; - /* We prepend the wrapped text to the next line, if the prepend_wrap - * flag is set, there is a next line, and prepending would not make - * the line too long. */ - if (prepend_wrap && line != openfile->filebot) { - const char *tail = remainder + move_mbleft(remainder, rest_length); + /* We prepend the wrapped text to the next line, if the prepend_wrap + * flag is set, there is a next line, and prepending would not make + * the line too long. */ + if (prepend_wrap && line != openfile->filebot) { + const char *tail = remainder + move_mbleft(remainder, rest_length); - /* Go to the end of the line. */ - openfile->current_x = line_len; + /* Go to the end of the line. */ + openfile->current_x = line_len; - /* If the remainder doesn't end in a blank, add a space. */ - if (!is_blank_mbchar(tail)) { + /* If the remainder doesn't end in a blank, add a space. */ + if (!is_blank_mbchar(tail)) { #ifndef NANO_TINY - add_undo(ADD); + add_undo(ADD); #endif - line->data = charealloc(line->data, line_len + 2); - line->data[line_len] = ' '; - line->data[line_len + 1] = '\0'; - remainder = line->data + wrap_loc; - rest_length++; - openfile->totsize++; - openfile->current_x++; + line->data = charealloc(line->data, line_len + 2); + line->data[line_len] = ' '; + line->data[line_len + 1] = '\0'; + remainder = line->data + wrap_loc; + rest_length++; + openfile->totsize++; + openfile->current_x++; #ifndef NANO_TINY - update_undo(ADD); + update_undo(ADD); #endif + } + + if (rest_length + strlen(line->next->data) <= fill) { + /* Delete the LF to join the two lines. */ + do_delete(); + /* Delete any leading blanks from the joined-on line. */ + while (is_blank_mbchar(&line->data[openfile->current_x])) + do_delete(); + } } - if (rest_length + strlen(line->next->data) <= fill) { - /* Delete the LF to join the two lines. */ - do_delete(); - /* Delete any leading blanks from the joined-on line. */ - while (is_blank_mbchar(&line->data[openfile->current_x])) - do_delete(); + /* Go to the wrap location. */ + openfile->current_x = wrap_loc; + + /* When requested, snip trailing blanks off the wrapped line. */ + if (ISSET(TRIM_BLANKS)) { + size_t cur_x = move_mbleft(line->data, wrap_loc); + + while (is_blank_mbchar(line->data + cur_x)) { + openfile->current_x = cur_x; + do_delete(); + cur_x = move_mbleft(line->data, cur_x); + } } - } - /* Go to the wrap location. */ - openfile->current_x = wrap_loc; + /* Now split the line. */ + do_enter(); - /* When requested, snip trailing blanks off the wrapped line. */ - if (ISSET(TRIM_BLANKS)) { - size_t cur_x = move_mbleft(line->data, wrap_loc); - - while (is_blank_mbchar(line->data + cur_x)) { - openfile->current_x = cur_x; - do_delete(); - cur_x = move_mbleft(line->data, cur_x); + if (old_x < wrap_loc) { + openfile->current_x = old_x; + openfile->current = old_line; + prepend_wrap = TRUE; + } else { + openfile->current_x += (old_x - wrap_loc); + prepend_wrap = FALSE; } - } - /* Now split the line. */ - do_enter(); - - if (old_x < wrap_loc) { - openfile->current_x = old_x; - openfile->current = old_line; - prepend_wrap = TRUE; - } else { - openfile->current_x += (old_x - wrap_loc); - prepend_wrap = FALSE; - } - - openfile->placewewant = xplustabs(); + openfile->placewewant = xplustabs(); #ifndef NANO_TINY - add_undo(SPLIT_END); + add_undo(SPLIT_END); #endif - return TRUE; + return TRUE; } #endif /* ENABLE_WRAPPING */ @@ -1657,69 +1657,69 @@ bool do_wrap(filestruct *line) * blank, as does a '\n' if snap_at_nl is TRUE. */ ssize_t break_line(const char *line, ssize_t goal, bool snap_at_nl) { - ssize_t lastblank = -1; - /* The index of the last blank we found. */ - ssize_t index = 0; - /* The index of the character we are looking at. */ - size_t column = 0; - /* The column position that corresponds with index. */ - int char_len = 0; - /* The length of the current character, in bytes. */ + ssize_t lastblank = -1; + /* The index of the last blank we found. */ + ssize_t index = 0; + /* The index of the character we are looking at. */ + size_t column = 0; + /* The column position that corresponds with index. */ + int char_len = 0; + /* The length of the current character, in bytes. */ - /* Find the last blank that does not overshoot the target column. */ - while (*line != '\0' && column <= goal) { - if (is_blank_mbchar(line) || (snap_at_nl && *line == '\n')) { - lastblank = index; + /* Find the last blank that does not overshoot the target column. */ + while (*line != '\0' && column <= goal) { + if (is_blank_mbchar(line) || (snap_at_nl && *line == '\n')) { + lastblank = index; - if (*line == '\n') - break; + if (*line == '\n') + break; + } + + char_len = parse_mbchar(line, NULL, &column); + line += char_len; + index += char_len; } - char_len = parse_mbchar(line, NULL, &column); - line += char_len; - index += char_len; - } - - /* If the whole line displays shorter than goal, we're done. */ - if (column <= goal) - return index; + /* If the whole line displays shorter than goal, we're done. */ + if (column <= goal) + return index; #ifdef ENABLE_HELP - /* If we're wrapping a help text and no blank was found, or was - * found only as the first character, force a line break. */ - if (snap_at_nl && lastblank < 1) - return (index - char_len); + /* If we're wrapping a help text and no blank was found, or was + * found only as the first character, force a line break. */ + if (snap_at_nl && lastblank < 1) + return (index - char_len); #endif - /* If no blank was found within the goal width, seek one after it. */ - if (lastblank < 0) { - while (*line != '\0') { - if (is_blank_mbchar(line)) - lastblank = index; - else if (lastblank > 0) - return lastblank; + /* If no blank was found within the goal width, seek one after it. */ + if (lastblank < 0) { + while (*line != '\0') { + if (is_blank_mbchar(line)) + lastblank = index; + else if (lastblank > 0) + return lastblank; - char_len = parse_mbchar(line, NULL, NULL); - line += char_len; - index += char_len; + char_len = parse_mbchar(line, NULL, NULL); + line += char_len; + index += char_len; + } + + return -1; } - return -1; - } - - /* Move the pointer back to the last blank, and then step beyond it. */ - line = line - index + lastblank; - char_len = parse_mbchar(line, NULL, NULL); - line += char_len; - - /* Skip any consecutive blanks after the last blank. */ - while (*line != '\0' && is_blank_mbchar(line)) { - lastblank += char_len; + /* Move the pointer back to the last blank, and then step beyond it. */ + line = line - index + lastblank; char_len = parse_mbchar(line, NULL, NULL); line += char_len; - } - return lastblank; + /* Skip any consecutive blanks after the last blank. */ + while (*line != '\0' && is_blank_mbchar(line)) { + lastblank += char_len; + char_len = parse_mbchar(line, NULL, NULL); + line += char_len; + } + + return lastblank; } #endif /* ENABLE_HELP || ENABLED_WRAPORJUSTIFY */ @@ -1728,21 +1728,21 @@ ssize_t break_line(const char *line, ssize_t goal, bool snap_at_nl) * and the non-whitespace of the line. */ size_t indent_length(const char *line) { - size_t len = 0; - char onechar[MAXCHARLEN]; - int charlen; + size_t len = 0; + char onechar[MAXCHARLEN]; + int charlen; - while (*line != '\0') { - charlen = parse_mbchar(line, onechar, NULL); + while (*line != '\0') { + charlen = parse_mbchar(line, onechar, NULL); - if (!is_blank_mbchar(onechar)) - break; + if (!is_blank_mbchar(onechar)) + break; - line += charlen; - len += charlen; - } + line += charlen; + len += charlen; + } - return len; + return len; } #endif /* !NANO_TINY || ENABLE_JUSTIFY */ @@ -1759,135 +1759,135 @@ size_t indent_length(const char *line) * character at paragraph[skip + 1] must not be blank. */ void justify_format(filestruct *paragraph, size_t skip) { - char *end, *new_end, *new_paragraph_data; - size_t shift = 0; + char *end, *new_end, *new_paragraph_data; + size_t shift = 0; #ifndef NANO_TINY - size_t mark_shift = 0; + size_t mark_shift = 0; #endif - end = paragraph->data + skip; - new_paragraph_data = charalloc(strlen(paragraph->data) + 1); - strncpy(new_paragraph_data, paragraph->data, skip); - new_end = new_paragraph_data + skip; + end = paragraph->data + skip; + new_paragraph_data = charalloc(strlen(paragraph->data) + 1); + strncpy(new_paragraph_data, paragraph->data, skip); + new_end = new_paragraph_data + skip; - while (*end != '\0') { - int end_len; + while (*end != '\0') { + int end_len; - /* If this character is blank, change it to a space if - * necessary, and skip over all blanks after it. */ - if (is_blank_mbchar(end)) { - end_len = parse_mbchar(end, NULL, NULL); + /* If this character is blank, change it to a space if + * necessary, and skip over all blanks after it. */ + if (is_blank_mbchar(end)) { + end_len = parse_mbchar(end, NULL, NULL); - *new_end = ' '; - new_end++; - end += end_len; + *new_end = ' '; + new_end++; + end += end_len; - while (*end != '\0' && is_blank_mbchar(end)) { - end_len = parse_mbchar(end, NULL, NULL); + while (*end != '\0' && is_blank_mbchar(end)) { + end_len = parse_mbchar(end, NULL, NULL); - end += end_len; - shift += end_len; + end += end_len; + shift += end_len; #ifndef NANO_TINY - /* Keep track of the change in the current line. */ - if (openfile->mark == paragraph && - openfile->mark_x >= end - paragraph->data) - mark_shift += end_len; + /* Keep track of the change in the current line. */ + if (openfile->mark == paragraph && + openfile->mark_x >= end - paragraph->data) + mark_shift += end_len; #endif - } - /* If this character is punctuation optionally followed by a - * bracket and then followed by blanks, change no more than two - * of the blanks to spaces if necessary, and skip over all - * blanks after them. */ - } else if (mbstrchr(punct, end) != NULL) { - end_len = parse_mbchar(end, NULL, NULL); + } + /* If this character is punctuation optionally followed by a + * bracket and then followed by blanks, change no more than two + * of the blanks to spaces if necessary, and skip over all + * blanks after them. */ + } else if (mbstrchr(punct, end) != NULL) { + end_len = parse_mbchar(end, NULL, NULL); - while (end_len > 0) { - *new_end = *end; - new_end++; - end++; - end_len--; - } + while (end_len > 0) { + *new_end = *end; + new_end++; + end++; + end_len--; + } - if (*end != '\0' && mbstrchr(brackets, end) != NULL) { - end_len = parse_mbchar(end, NULL, NULL); + if (*end != '\0' && mbstrchr(brackets, end) != NULL) { + end_len = parse_mbchar(end, NULL, NULL); - while (end_len > 0) { - *new_end = *end; - new_end++; - end++; - end_len--; + while (end_len > 0) { + *new_end = *end; + new_end++; + end++; + end_len--; + } + } + + if (*end != '\0' && is_blank_mbchar(end)) { + end_len = parse_mbchar(end, NULL, NULL); + + *new_end = ' '; + new_end++; + end += end_len; + } + + if (*end != '\0' && is_blank_mbchar(end)) { + end_len = parse_mbchar(end, NULL, NULL); + + *new_end = ' '; + new_end++; + end += end_len; + } + + while (*end != '\0' && is_blank_mbchar(end)) { + end_len = parse_mbchar(end, NULL, NULL); + + end += end_len; + shift += end_len; + +#ifndef NANO_TINY + /* Keep track of the change in the current line. */ + if (openfile->mark == paragraph && + openfile->mark_x >= end - paragraph->data) + mark_shift += end_len; +#endif + } + /* If this character is neither blank nor punctuation, leave it + * unchanged. */ + } else { + end_len = parse_mbchar(end, NULL, NULL); + + while (end_len > 0) { + *new_end = *end; + new_end++; + end++; + end_len--; + } } - } + } - if (*end != '\0' && is_blank_mbchar(end)) { - end_len = parse_mbchar(end, NULL, NULL); + *new_end = *end; - *new_end = ' '; - new_end++; - end += end_len; - } + /* If there are spaces at the end of the line, remove them. */ + while (new_end > new_paragraph_data + skip && *(new_end - 1) == ' ') { + new_end--; + shift++; + } - if (*end != '\0' && is_blank_mbchar(end)) { - end_len = parse_mbchar(end, NULL, NULL); - - *new_end = ' '; - new_end++; - end += end_len; - } - - while (*end != '\0' && is_blank_mbchar(end)) { - end_len = parse_mbchar(end, NULL, NULL); - - end += end_len; - shift += end_len; + if (shift > 0) { + openfile->totsize -= shift; + null_at(&new_paragraph_data, new_end - new_paragraph_data); + free(paragraph->data); + paragraph->data = new_paragraph_data; #ifndef NANO_TINY - /* Keep track of the change in the current line. */ - if (openfile->mark == paragraph && - openfile->mark_x >= end - paragraph->data) - mark_shift += end_len; + /* Adjust the mark coordinates to compensate for the change in + * the current line. */ + if (openfile->mark == paragraph) { + openfile->mark_x -= mark_shift; + if (openfile->mark_x > new_end - new_paragraph_data) + openfile->mark_x = new_end - new_paragraph_data; + } #endif - } - /* If this character is neither blank nor punctuation, leave it - * unchanged. */ - } else { - end_len = parse_mbchar(end, NULL, NULL); - - while (end_len > 0) { - *new_end = *end; - new_end++; - end++; - end_len--; - } - } - } - - *new_end = *end; - - /* If there are spaces at the end of the line, remove them. */ - while (new_end > new_paragraph_data + skip && *(new_end - 1) == ' ') { - new_end--; - shift++; - } - - if (shift > 0) { - openfile->totsize -= shift; - null_at(&new_paragraph_data, new_end - new_paragraph_data); - free(paragraph->data); - paragraph->data = new_paragraph_data; - -#ifndef NANO_TINY - /* Adjust the mark coordinates to compensate for the change in - * the current line. */ - if (openfile->mark == paragraph) { - openfile->mark_x -= mark_shift; - if (openfile->mark_x > new_end - new_paragraph_data) - openfile->mark_x = new_end - new_paragraph_data; - } -#endif - } else - free(new_paragraph_data); + } else + free(new_paragraph_data); } /* The "quote part" of a line is the largest initial substring matching @@ -1895,14 +1895,14 @@ void justify_format(filestruct *paragraph, size_t skip) * of the given line. */ size_t quote_length(const char *line) { - regmatch_t matches; - int rc = regexec("ereg, line, 1, &matches, 0); + regmatch_t matches; + int rc = regexec("ereg, line, 1, &matches, 0); - if (rc == REG_NOMATCH || matches.rm_so == (regoff_t)-1) - return 0; - /* matches.rm_so should be 0, since the quote string should start - * with the caret ^. */ - return matches.rm_eo; + if (rc == REG_NOMATCH || matches.rm_so == (regoff_t)-1) + return 0; + /* matches.rm_so should be 0, since the quote string should start + * with the caret ^. */ + return matches.rm_eo; } /* a_line and b_line are lines of text. The quotation part of a_line is @@ -1910,16 +1910,16 @@ size_t quote_length(const char *line) * b_line is the same. */ bool quotes_match(const char *a_line, size_t a_quote, const char *b_line) { - return (a_quote == quote_length(b_line) && - strncmp(a_line, b_line, a_quote) == 0); + return (a_quote == quote_length(b_line) && + strncmp(a_line, b_line, a_quote) == 0); } /* We assume a_line and b_line have no quote part. Then, we return * whether b_line could follow a_line in a paragraph. */ bool indents_match(const char *a_line, size_t a_indent, const char - *b_line, size_t b_indent) + *b_line, size_t b_indent) { - return (b_indent <= a_indent && strncmp(a_line, b_line, b_indent) == 0); + return (b_indent <= a_indent && strncmp(a_line, b_line, b_indent) == 0); } /* Is foo the beginning of a paragraph? @@ -1947,50 +1947,50 @@ bool indents_match(const char *a_line, size_t a_indent, const char * autoindent is turned on. */ bool begpar(const filestruct *const foo) { - size_t quote_len, indent_len, temp_id_len; + size_t quote_len, indent_len, temp_id_len; + + if (foo == NULL) + return FALSE; + + /* Case 1). */ + if (foo == openfile->fileage) + return TRUE; + + quote_len = quote_length(foo->data); + indent_len = indent_length(foo->data + quote_len); + + /* Not part of a paragraph. */ + if (foo->data[quote_len + indent_len] == '\0') + return FALSE; + + /* Case 3). */ + if (!quotes_match(foo->data, quote_len, foo->prev->data)) + return TRUE; + + temp_id_len = indent_length(foo->prev->data + quote_len); + + /* Case 2) or 5) or 4). */ + if (foo->prev->data[quote_len + temp_id_len] == '\0' || + (quote_len == 0 && indent_len > 0 && !ISSET(AUTOINDENT)) || + !indents_match(foo->prev->data + quote_len, temp_id_len, + foo->data + quote_len, indent_len)) + return TRUE; - if (foo == NULL) return FALSE; - - /* Case 1). */ - if (foo == openfile->fileage) - return TRUE; - - quote_len = quote_length(foo->data); - indent_len = indent_length(foo->data + quote_len); - - /* Not part of a paragraph. */ - if (foo->data[quote_len + indent_len] == '\0') - return FALSE; - - /* Case 3). */ - if (!quotes_match(foo->data, quote_len, foo->prev->data)) - return TRUE; - - temp_id_len = indent_length(foo->prev->data + quote_len); - - /* Case 2) or 5) or 4). */ - if (foo->prev->data[quote_len + temp_id_len] == '\0' || - (quote_len == 0 && indent_len > 0 && !ISSET(AUTOINDENT)) || - !indents_match(foo->prev->data + quote_len, temp_id_len, - foo->data + quote_len, indent_len)) - return TRUE; - - return FALSE; } /* Is foo inside a paragraph? */ bool inpar(const filestruct *const foo) { - size_t quote_len; + size_t quote_len; - if (foo == NULL) - return FALSE; + if (foo == NULL) + return FALSE; - quote_len = quote_length(foo->data); + quote_len = quote_length(foo->data); - return (foo->data[quote_len + indent_length(foo->data + - quote_len)] != '\0'); + return (foo->data[quote_len + indent_length(foo->data + + quote_len)] != '\0'); } /* Move the next par_len lines, starting with first_line, into the @@ -1999,68 +1999,68 @@ bool inpar(const filestruct *const foo) * first_line. */ void backup_lines(filestruct *first_line, size_t par_len) { - filestruct *top = first_line; - /* The top of the paragraph we're backing up. */ - filestruct *bot = first_line; - /* The bottom of the paragraph we're backing up. */ - size_t i; - size_t current_x_save = openfile->current_x; - ssize_t fl_lineno_save = first_line->lineno; - ssize_t edittop_lineno_save = openfile->edittop->lineno; - ssize_t current_lineno_save = openfile->current->lineno; + filestruct *top = first_line; + /* The top of the paragraph we're backing up. */ + filestruct *bot = first_line; + /* The bottom of the paragraph we're backing up. */ + size_t i; + size_t current_x_save = openfile->current_x; + ssize_t fl_lineno_save = first_line->lineno; + ssize_t edittop_lineno_save = openfile->edittop->lineno; + ssize_t current_lineno_save = openfile->current->lineno; #ifndef NANO_TINY - bool mark_is_set = (openfile->mark != NULL); - ssize_t was_mark_lineno = (mark_is_set ? openfile->mark->lineno : 0); - size_t was_mark_x = openfile->mark_x; + bool mark_is_set = (openfile->mark != NULL); + ssize_t was_mark_lineno = (mark_is_set ? openfile->mark->lineno : 0); + size_t was_mark_x = openfile->mark_x; #endif - /* Move bot down par_len lines to the line after the last line of - * the paragraph, if there is one. */ - for (i = par_len; i > 0 && bot != openfile->filebot; i--) - bot = bot->next; + /* Move bot down par_len lines to the line after the last line of + * the paragraph, if there is one. */ + for (i = par_len; i > 0 && bot != openfile->filebot; i--) + bot = bot->next; - /* Move the paragraph from the current buffer to the justify buffer. */ - extract_buffer(&jusbuffer, &jusbottom, top, 0, bot, - (i == 1 && bot == openfile->filebot) ? strlen(bot->data) : 0); + /* Move the paragraph from the current buffer to the justify buffer. */ + extract_buffer(&jusbuffer, &jusbottom, top, 0, bot, + (i == 1 && bot == openfile->filebot) ? strlen(bot->data) : 0); - /* Copy the paragraph back to the current buffer. */ - copy_from_buffer(jusbuffer); + /* Copy the paragraph back to the current buffer. */ + copy_from_buffer(jusbuffer); - /* Move upward from the last line of the paragraph to the first - * line, putting first_line, edittop, current, and mark_begin at the - * same lines in the copied paragraph that they had in the original - * paragraph. */ - if (openfile->current != openfile->fileage) { - top = openfile->current->prev; + /* Move upward from the last line of the paragraph to the first + * line, putting first_line, edittop, current, and mark_begin at the + * same lines in the copied paragraph that they had in the original + * paragraph. */ + if (openfile->current != openfile->fileage) { + top = openfile->current->prev; #ifndef NANO_TINY - if (mark_is_set && openfile->current->lineno == was_mark_lineno) { - openfile->mark = openfile->current; - openfile->mark_x = was_mark_x; + if (mark_is_set && openfile->current->lineno == was_mark_lineno) { + openfile->mark = openfile->current; + openfile->mark_x = was_mark_x; + } +#endif + } else + top = openfile->current; + for (i = par_len; i > 0 && top != NULL; i--) { + if (top->lineno == fl_lineno_save) + first_line = top; + if (top->lineno == edittop_lineno_save) + openfile->edittop = top; + if (top->lineno == current_lineno_save) + openfile->current = top; +#ifndef NANO_TINY + if (mark_is_set && top->lineno == was_mark_lineno) { + openfile->mark = top; + openfile->mark_x = was_mark_x; + } +#endif + top = top->prev; } -#endif - } else - top = openfile->current; - for (i = par_len; i > 0 && top != NULL; i--) { - if (top->lineno == fl_lineno_save) - first_line = top; - if (top->lineno == edittop_lineno_save) - openfile->edittop = top; - if (top->lineno == current_lineno_save) - openfile->current = top; -#ifndef NANO_TINY - if (mark_is_set && top->lineno == was_mark_lineno) { - openfile->mark = top; - openfile->mark_x = was_mark_x; - } -#endif - top = top->prev; - } - /* Put current_x at the same place in the copied paragraph that it - * had in the original paragraph. */ - openfile->current_x = current_x_save; + /* Put current_x at the same place in the copied paragraph that it + * had in the original paragraph. */ + openfile->current_x = current_x_save; - set_modified(); + set_modified(); } /* Find the beginning of the current paragraph if we're in one, or the @@ -2073,452 +2073,452 @@ void backup_lines(filestruct *first_line, size_t par_len) * beginning of a paragraph. */ bool find_paragraph(size_t *const quote, size_t *const par) { - size_t quote_len; - /* Length of the initial quotation of the paragraph we search - * for. */ - size_t par_len; - /* Number of lines in the paragraph we search for. */ - filestruct *current_save; - /* The line at the beginning of the paragraph we search for. */ + size_t quote_len; + /* Length of the initial quotation of the paragraph we search + * for. */ + size_t par_len; + /* Number of lines in the paragraph we search for. */ + filestruct *current_save; + /* The line at the beginning of the paragraph we search for. */ - if (quoterc != 0) { - statusline(ALERT, _("Bad quote string %s: %s"), quotestr, quoteerr); - return FALSE; - } - - /* If we're at the end of the last line of the file, it means that - * there aren't any paragraphs left, so get out. */ - if (openfile->current == openfile->filebot && openfile->current_x == - strlen(openfile->filebot->data)) - return FALSE; - - /* If the current line isn't in a paragraph, move forward to the - * last line of the next paragraph, if any. */ - if (!inpar(openfile->current)) { - do_para_end(FALSE); - - /* If we end up past the beginning of the line, it means that - * we're at the end of the last line of the file, and the line - * isn't blank, in which case the last line of the file is the - * last line of the next paragraph. - * - * Otherwise, if we end up on a line that's in a paragraph, it - * means that we're on the line after the last line of the next - * paragraph, in which case we should move back to the last line - * of the next paragraph. */ - if (openfile->current_x == 0) { - if (!inpar(openfile->current->prev)) + if (quoterc != 0) { + statusline(ALERT, _("Bad quote string %s: %s"), quotestr, quoteerr); return FALSE; - if (openfile->current != openfile->fileage) - openfile->current = openfile->current->prev; } - } - /* If the current line isn't the first line of the paragraph, move - * back to the first line of the paragraph. */ - if (!begpar(openfile->current)) - do_para_begin(FALSE); + /* If we're at the end of the last line of the file, it means that + * there aren't any paragraphs left, so get out. */ + if (openfile->current == openfile->filebot && openfile->current_x == + strlen(openfile->filebot->data)) + return FALSE; - /* Now current is the first line of the paragraph. Set quote_len to - * the quotation length of that line, and set par_len to the number - * of lines in this paragraph. */ - quote_len = quote_length(openfile->current->data); - current_save = openfile->current; - do_para_end(FALSE); - par_len = openfile->current->lineno - current_save->lineno; + /* If the current line isn't in a paragraph, move forward to the + * last line of the next paragraph, if any. */ + if (!inpar(openfile->current)) { + do_para_end(FALSE); - /* If we end up past the beginning of the line, it means that we're at - * the end of the last line of the file, and the line isn't blank, in - * which case the last line of the file is part of the paragraph. */ - if (openfile->current_x > 0) - par_len++; - openfile->current = current_save; + /* If we end up past the beginning of the line, it means that + * we're at the end of the last line of the file, and the line + * isn't blank, in which case the last line of the file is the + * last line of the next paragraph. + * + * Otherwise, if we end up on a line that's in a paragraph, it + * means that we're on the line after the last line of the next + * paragraph, in which case we should move back to the last line + * of the next paragraph. */ + if (openfile->current_x == 0) { + if (!inpar(openfile->current->prev)) + return FALSE; + if (openfile->current != openfile->fileage) + openfile->current = openfile->current->prev; + } + } - /* Save the values of quote_len and par_len. */ - *quote = quote_len; - *par = par_len; + /* If the current line isn't the first line of the paragraph, move + * back to the first line of the paragraph. */ + if (!begpar(openfile->current)) + do_para_begin(FALSE); - return TRUE; + /* Now current is the first line of the paragraph. Set quote_len to + * the quotation length of that line, and set par_len to the number + * of lines in this paragraph. */ + quote_len = quote_length(openfile->current->data); + current_save = openfile->current; + do_para_end(FALSE); + par_len = openfile->current->lineno - current_save->lineno; + + /* If we end up past the beginning of the line, it means that we're at + * the end of the last line of the file, and the line isn't blank, in + * which case the last line of the file is part of the paragraph. */ + if (openfile->current_x > 0) + par_len++; + openfile->current = current_save; + + /* Save the values of quote_len and par_len. */ + *quote = quote_len; + *par = par_len; + + return TRUE; } /* If full_justify is TRUE, justify the entire file. Otherwise, justify * the current paragraph. */ void do_justify(bool full_justify) { - filestruct *first_par_line = NULL; - /* Will be the first line of the justified paragraph(s), if any. - * For restoring after unjustify. */ - filestruct *last_par_line = NULL; - /* Will be the line after the last line of the justified - * paragraph(s), if any. Also for restoring after unjustify. */ - bool filebot_inpar = FALSE; - /* Whether the text at filebot is part of the current paragraph. */ - int kbinput; - /* The first keystroke after a justification. */ - functionptrtype func; - /* The function associated with that keystroke. */ + filestruct *first_par_line = NULL; + /* Will be the first line of the justified paragraph(s), if any. + * For restoring after unjustify. */ + filestruct *last_par_line = NULL; + /* Will be the line after the last line of the justified + * paragraph(s), if any. Also for restoring after unjustify. */ + bool filebot_inpar = FALSE; + /* Whether the text at filebot is part of the current paragraph. */ + int kbinput; + /* The first keystroke after a justification. */ + functionptrtype func; + /* The function associated with that keystroke. */ - /* We save these variables to be restored if the user unjustifies. */ - filestruct *edittop_save = openfile->edittop; - size_t firstcolumn_save = openfile->firstcolumn; - filestruct *current_save = openfile->current; - size_t current_x_save = openfile->current_x; + /* We save these variables to be restored if the user unjustifies. */ + filestruct *edittop_save = openfile->edittop; + size_t firstcolumn_save = openfile->firstcolumn; + filestruct *current_save = openfile->current; + size_t current_x_save = openfile->current_x; #ifndef NANO_TINY - filestruct *was_mark = openfile->mark; - size_t was_mark_x = openfile->mark_x; + filestruct *was_mark = openfile->mark; + size_t was_mark_x = openfile->mark_x; #endif - bool modified_save = openfile->modified; + bool modified_save = openfile->modified; - /* Move to the beginning of the current line, so that justifying at - * the end of the last line of the file, if that line isn't blank, - * will work the first time through. */ - openfile->current_x = 0; + /* Move to the beginning of the current line, so that justifying at + * the end of the last line of the file, if that line isn't blank, + * will work the first time through. */ + openfile->current_x = 0; - /* If we're justifying the entire file, start at the beginning. */ - if (full_justify) - openfile->current = openfile->fileage; + /* If we're justifying the entire file, start at the beginning. */ + if (full_justify) + openfile->current = openfile->fileage; - while (TRUE) { - size_t i; - /* Generic loop variable. */ - filestruct *curr_first_par_line; - /* The first line of the current paragraph. */ - size_t quote_len; - /* Length of the initial quotation of the current paragraph. */ - size_t indent_len; - /* Length of the initial indentation of the current paragraph. */ - size_t par_len; - /* Number of lines in the current paragraph. */ - ssize_t break_pos; - /* Where we will break lines. */ - char *indent_string; - /* The first indentation that doesn't match the initial - * indentation of the current paragraph. This is put at the - * beginning of every line broken off the first justified - * line of the paragraph. Note that this works because a - * paragraph can only contain two indentations at most: the - * initial one, and a different one starting on a line after - * the first. See the comment at begpar() for more about - * when a line is part of a paragraph. */ + while (TRUE) { + size_t i; + /* Generic loop variable. */ + filestruct *curr_first_par_line; + /* The first line of the current paragraph. */ + size_t quote_len; + /* Length of the initial quotation of the current paragraph. */ + size_t indent_len; + /* Length of the initial indentation of the current paragraph. */ + size_t par_len; + /* Number of lines in the current paragraph. */ + ssize_t break_pos; + /* Where we will break lines. */ + char *indent_string; + /* The first indentation that doesn't match the initial + * indentation of the current paragraph. This is put at the + * beginning of every line broken off the first justified + * line of the paragraph. Note that this works because a + * paragraph can only contain two indentations at most: the + * initial one, and a different one starting on a line after + * the first. See the comment at begpar() for more about + * when a line is part of a paragraph. */ - /* Find the first line of the paragraph to be justified. That - * is the start of this paragraph if we're in one, or the start - * of the next otherwise. Save the quote length and paragraph - * length (number of lines). Don't refresh the screen yet, - * since we'll do that after we justify. - * - * If the search failed, we do one of two things. If we're - * justifying the whole file, and we've found at least one - * paragraph, it means that we should justify all the way to the - * last line of the file, so set the last line of the text to be - * justified to the last line of the file and break out of the - * loop. Otherwise, it means that there are no paragraph(s) to - * justify, so refresh the screen and get out. */ - if (!find_paragraph("e_len, &par_len)) { - if (full_justify && first_par_line != NULL) { - last_par_line = openfile->filebot; - break; - } else { - refresh_needed = TRUE; - return; - } - } + /* Find the first line of the paragraph to be justified. That + * is the start of this paragraph if we're in one, or the start + * of the next otherwise. Save the quote length and paragraph + * length (number of lines). Don't refresh the screen yet, + * since we'll do that after we justify. + * + * If the search failed, we do one of two things. If we're + * justifying the whole file, and we've found at least one + * paragraph, it means that we should justify all the way to the + * last line of the file, so set the last line of the text to be + * justified to the last line of the file and break out of the + * loop. Otherwise, it means that there are no paragraph(s) to + * justify, so refresh the screen and get out. */ + if (!find_paragraph("e_len, &par_len)) { + if (full_justify && first_par_line != NULL) { + last_par_line = openfile->filebot; + break; + } else { + refresh_needed = TRUE; + return; + } + } - /* par_len will be one greater than the number of lines between - * current and filebot if filebot is the last line in the - * paragraph. Set filebot_inpar to TRUE if this is the case. */ - filebot_inpar = (openfile->current->lineno + par_len == - openfile->filebot->lineno + 1); + /* par_len will be one greater than the number of lines between + * current and filebot if filebot is the last line in the + * paragraph. Set filebot_inpar to TRUE if this is the case. */ + filebot_inpar = (openfile->current->lineno + par_len == + openfile->filebot->lineno + 1); - /* If we haven't already done it, move the original paragraph(s) - * to the justify buffer, splice a copy of the original - * paragraph(s) into the file in the same place, and set - * first_par_line to the first line of the copy. */ - if (first_par_line == NULL) { - backup_lines(openfile->current, full_justify ? - openfile->filebot->lineno - openfile->current->lineno + - ((openfile->filebot->data[0] != '\0') ? 1 : 0) : par_len); - first_par_line = openfile->current; - } + /* If we haven't already done it, move the original paragraph(s) + * to the justify buffer, splice a copy of the original + * paragraph(s) into the file in the same place, and set + * first_par_line to the first line of the copy. */ + if (first_par_line == NULL) { + backup_lines(openfile->current, full_justify ? + openfile->filebot->lineno - openfile->current->lineno + + ((openfile->filebot->data[0] != '\0') ? 1 : 0) : par_len); + first_par_line = openfile->current; + } - /* Set curr_first_par_line to the first line of the current - * paragraph. */ - curr_first_par_line = openfile->current; + /* Set curr_first_par_line to the first line of the current + * paragraph. */ + curr_first_par_line = openfile->current; - /* Initialize indent_string to a blank string. */ - indent_string = mallocstrcpy(NULL, ""); + /* Initialize indent_string to a blank string. */ + indent_string = mallocstrcpy(NULL, ""); - /* Find the first indentation in the paragraph that doesn't - * match the indentation of the first line, and save it in - * indent_string. If all the indentations are the same, save - * the indentation of the first line in indent_string. */ - { - const filestruct *indent_line = openfile->current; - bool past_first_line = FALSE; + /* Find the first indentation in the paragraph that doesn't + * match the indentation of the first line, and save it in + * indent_string. If all the indentations are the same, save + * the indentation of the first line in indent_string. */ + { + const filestruct *indent_line = openfile->current; + bool past_first_line = FALSE; - for (i = 0; i < par_len; i++) { - indent_len = quote_len + - indent_length(indent_line->data + quote_len); + for (i = 0; i < par_len; i++) { + indent_len = quote_len + + indent_length(indent_line->data + quote_len); - if (indent_len != strlen(indent_string)) { - indent_string = mallocstrncpy(indent_string, - indent_line->data, indent_len + 1); - indent_string[indent_len] = '\0'; + if (indent_len != strlen(indent_string)) { + indent_string = mallocstrncpy(indent_string, + indent_line->data, indent_len + 1); + indent_string[indent_len] = '\0'; - if (past_first_line) + if (past_first_line) + break; + } + + if (indent_line == openfile->current) + past_first_line = TRUE; + + indent_line = indent_line->next; + } + } + + /* Now tack all the lines of the paragraph together, skipping + * the quoting and indentation on all lines after the first. */ + for (i = 0; i < par_len - 1; i++) { + filestruct *next_line = openfile->current->next; + size_t line_len = strlen(openfile->current->data); + size_t next_line_len = strlen(openfile->current->next->data); + + indent_len = quote_len + + indent_length(openfile->current->next->data + quote_len); + + next_line_len -= indent_len; + openfile->totsize -= indent_len; + + /* We're just about to tack the next line onto this one. If + * this line isn't empty, make sure it ends in a space. */ + if (line_len > 0 && openfile->current->data[line_len - 1] != ' ') { + line_len++; + openfile->current->data = + charealloc(openfile->current->data, line_len + 1); + openfile->current->data[line_len - 1] = ' '; + openfile->current->data[line_len] = '\0'; + openfile->totsize++; + } + + openfile->current->data = charealloc(openfile->current->data, + line_len + next_line_len + 1); + strcat(openfile->current->data, next_line->data + indent_len); + +#ifndef NANO_TINY + /* If needed, adjust the coordinates of the mark. */ + if (openfile->mark == next_line) { + openfile->mark = openfile->current; + openfile->mark_x += line_len - indent_len; + } +#endif + /* Don't destroy edittop! */ + if (next_line == openfile->edittop) + openfile->edittop = openfile->current; + + unlink_node(next_line); + + /* If we've removed the next line, we need to go through + * this line again. */ + i--; + + openfile->totsize--; + par_len--; + } + + /* Call justify_format() on the paragraph, which will remove excess + * spaces from it and change all blank characters to spaces. */ + justify_format(openfile->current, quote_len + + indent_length(openfile->current->data + quote_len)); + + while (par_len > 0 && strlenpt(openfile->current->data) > fill) { + size_t line_len = strlen(openfile->current->data); + + indent_len = strlen(indent_string); + + /* If this line is too long, try to wrap it to the next line + * to make it short enough. */ + break_pos = break_line(openfile->current->data + indent_len, + fill - strnlenpt(openfile->current->data, indent_len), FALSE); + + /* We can't break the line, or don't need to, so get out. */ + if (break_pos == -1 || break_pos + indent_len == line_len) + break; + + /* Move forward to the character after the indentation and + * just after the space. */ + break_pos += indent_len + 1; + + /* If this paragraph is non-quoted, and autoindent isn't + * turned on, set the indentation length to zero so that the + * indentation is treated as part of the line. */ + if (quote_len == 0 && !ISSET(AUTOINDENT)) + indent_len = 0; + + /* Insert a new line after the current one. */ + splice_node(openfile->current, make_new_node(openfile->current)); + + /* Copy the text after where we're going to break the + * current line to the next line. */ + openfile->current->next->data = charalloc(indent_len + 1 + + line_len - break_pos); + strncpy(openfile->current->next->data, indent_string, + indent_len); + strcpy(openfile->current->next->data + indent_len, + openfile->current->data + break_pos); + + openfile->totsize += indent_len + 1; + par_len++; + +#ifndef NANO_TINY + /* Adjust the mark coordinates to compensate for the change + * in the current line. */ + if (openfile->mark == openfile->current && + openfile->mark_x > break_pos) { + openfile->mark = openfile->current->next; + openfile->mark_x -= break_pos - indent_len; + } +#endif + /* When requested, snip all trailing blanks. */ + if (ISSET(TRIM_BLANKS)) { + while (break_pos > 0 && + is_blank_mbchar(&openfile->current->data[break_pos - 1])) { + break_pos--; + openfile->totsize--; + } + } + + /* Break the current line. */ + null_at(&openfile->current->data, break_pos); + + /* Go to the next line. */ + openfile->current = openfile->current->next; + par_len--; + } + + free(indent_string); + + /* Go to the next line, if possible. If there is no next line, + * move to the end of the current line. */ + if (openfile->current != openfile->filebot) + openfile->current = openfile->current->next; + else + openfile->current_x = strlen(openfile->current->data); + + /* Renumber the now-justified paragraph, since both refreshing the + * edit window and finding a paragraph need correct line numbers. */ + renumber(curr_first_par_line); + + /* We've just finished justifying the paragraph. If we're not + * justifying the entire file, break out of the loop. + * Otherwise, continue the loop so that we justify all the + * paragraphs in the file. */ + if (!full_justify) break; + } + + /* We are now done justifying the paragraph or the file, so clean + * up. totsize has been maintained above. If we actually justified + * something, set last_par_line to the new end of the paragraph. */ + if (first_par_line != NULL) + last_par_line = openfile->current; + + /* Let a justification cancel a soft mark. */ + if (openfile->mark && openfile->kind_of_mark == SOFTMARK) + openfile->mark = NULL; + + edit_refresh(); + + /* Show "Unjustify" in the help lines. */ + 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. */ +#ifndef NANO_TINY + do { +#endif + statusbar(_("Can now UnJustify!")); + place_the_cursor(); + kbinput = do_input(FALSE); +#ifndef NANO_TINY + } while (kbinput == KEY_WINCH); +#endif + + /* Unset the suppression flag after showing the Unjustify message. */ + suppress_cursorpos = FALSE; + + func = func_from_key(&kbinput); + + if (func == do_uncut_text +#ifndef NANO_TINY + || func == do_undo +#endif + ) { + /* If we actually justified something, then splice the preserved + * unjustified text back into the file, */ + if (first_par_line != NULL) { + filestruct *trash = NULL, *dummy = NULL; + + /* Throw away the justified paragraph, and replace it with + * the preserved unjustified text. */ + extract_buffer(&trash, &dummy, first_par_line, 0, last_par_line, + filebot_inpar ? strlen(last_par_line->data) : 0); + free_filestruct(trash); + ingraft_buffer(jusbuffer); + + /* Restore the old position and the mark. */ + openfile->edittop = edittop_save; + openfile->firstcolumn = firstcolumn_save; + openfile->current = current_save; + openfile->current_x = current_x_save; +#ifndef NANO_TINY + if (openfile->mark) { + openfile->mark = was_mark; + openfile->mark_x = was_mark_x; + } +#endif + openfile->modified = modified_save; + if (!openfile->modified) + titlebar(NULL); + + refresh_needed = TRUE; } + } else { + /* Put the keystroke back into the queue. */ + unget_kbinput(kbinput, meta_key); - if (indent_line == openfile->current) - past_first_line = TRUE; + /* Set the desired screen column (always zero, except at EOF). */ + openfile->placewewant = xplustabs(); - indent_line = indent_line->next; - } +#ifndef NANO_TINY + /* Throw away the entire undo stack, to prevent a crash when + * the user tries to undo something in the justified text. */ + discard_until(NULL, openfile, FALSE); +#endif + /* Blow away the unjustified text. */ + free_filestruct(jusbuffer); } - /* Now tack all the lines of the paragraph together, skipping - * the quoting and indentation on all lines after the first. */ - for (i = 0; i < par_len - 1; i++) { - filestruct *next_line = openfile->current->next; - size_t line_len = strlen(openfile->current->data); - size_t next_line_len = strlen(openfile->current->next->data); + /* Mark the buffer for unjustified text as empty. */ + jusbuffer = NULL; - indent_len = quote_len + - indent_length(openfile->current->next->data + quote_len); + wipe_statusbar(); - next_line_len -= indent_len; - openfile->totsize -= indent_len; - - /* We're just about to tack the next line onto this one. If - * this line isn't empty, make sure it ends in a space. */ - if (line_len > 0 && openfile->current->data[line_len - 1] != ' ') { - line_len++; - openfile->current->data = - charealloc(openfile->current->data, line_len + 1); - openfile->current->data[line_len - 1] = ' '; - openfile->current->data[line_len] = '\0'; - openfile->totsize++; - } - - openfile->current->data = charealloc(openfile->current->data, - line_len + next_line_len + 1); - strcat(openfile->current->data, next_line->data + indent_len); - -#ifndef NANO_TINY - /* If needed, adjust the coordinates of the mark. */ - if (openfile->mark == next_line) { - openfile->mark = openfile->current; - openfile->mark_x += line_len - indent_len; - } -#endif - /* Don't destroy edittop! */ - if (next_line == openfile->edittop) - openfile->edittop = openfile->current; - - unlink_node(next_line); - - /* If we've removed the next line, we need to go through - * this line again. */ - i--; - - openfile->totsize--; - par_len--; - } - - /* Call justify_format() on the paragraph, which will remove excess - * spaces from it and change all blank characters to spaces. */ - justify_format(openfile->current, quote_len + - indent_length(openfile->current->data + quote_len)); - - while (par_len > 0 && strlenpt(openfile->current->data) > fill) { - size_t line_len = strlen(openfile->current->data); - - indent_len = strlen(indent_string); - - /* If this line is too long, try to wrap it to the next line - * to make it short enough. */ - break_pos = break_line(openfile->current->data + indent_len, - fill - strnlenpt(openfile->current->data, indent_len), FALSE); - - /* We can't break the line, or don't need to, so get out. */ - if (break_pos == -1 || break_pos + indent_len == line_len) - break; - - /* Move forward to the character after the indentation and - * just after the space. */ - break_pos += indent_len + 1; - - /* If this paragraph is non-quoted, and autoindent isn't - * turned on, set the indentation length to zero so that the - * indentation is treated as part of the line. */ - if (quote_len == 0 && !ISSET(AUTOINDENT)) - indent_len = 0; - - /* Insert a new line after the current one. */ - splice_node(openfile->current, make_new_node(openfile->current)); - - /* Copy the text after where we're going to break the - * current line to the next line. */ - openfile->current->next->data = charalloc(indent_len + 1 + - line_len - break_pos); - strncpy(openfile->current->next->data, indent_string, - indent_len); - strcpy(openfile->current->next->data + indent_len, - openfile->current->data + break_pos); - - openfile->totsize += indent_len + 1; - par_len++; - -#ifndef NANO_TINY - /* Adjust the mark coordinates to compensate for the change - * in the current line. */ - if (openfile->mark == openfile->current && - openfile->mark_x > break_pos) { - openfile->mark = openfile->current->next; - openfile->mark_x -= break_pos - indent_len; - } -#endif - /* When requested, snip all trailing blanks. */ - if (ISSET(TRIM_BLANKS)) { - while (break_pos > 0 && - is_blank_mbchar(&openfile->current->data[break_pos - 1])) { - break_pos--; - openfile->totsize--; - } - } - - /* Break the current line. */ - null_at(&openfile->current->data, break_pos); - - /* Go to the next line. */ - openfile->current = openfile->current->next; - par_len--; - } - - free(indent_string); - - /* Go to the next line, if possible. If there is no next line, - * move to the end of the current line. */ - if (openfile->current != openfile->filebot) - openfile->current = openfile->current->next; - else - openfile->current_x = strlen(openfile->current->data); - - /* Renumber the now-justified paragraph, since both refreshing the - * edit window and finding a paragraph need correct line numbers. */ - renumber(curr_first_par_line); - - /* We've just finished justifying the paragraph. If we're not - * justifying the entire file, break out of the loop. - * Otherwise, continue the loop so that we justify all the - * paragraphs in the file. */ - if (!full_justify) - break; - } - - /* We are now done justifying the paragraph or the file, so clean - * up. totsize has been maintained above. If we actually justified - * something, set last_par_line to the new end of the paragraph. */ - if (first_par_line != NULL) - last_par_line = openfile->current; - - /* Let a justification cancel a soft mark. */ - if (openfile->mark && openfile->kind_of_mark == SOFTMARK) - openfile->mark = NULL; - - edit_refresh(); - - /* Show "Unjustify" in the help lines. */ - 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. */ -#ifndef NANO_TINY - do { -#endif - statusbar(_("Can now UnJustify!")); - place_the_cursor(); - kbinput = do_input(FALSE); -#ifndef NANO_TINY - } while (kbinput == KEY_WINCH); -#endif - - /* Unset the suppression flag after showing the Unjustify message. */ - suppress_cursorpos = FALSE; - - func = func_from_key(&kbinput); - - if (func == do_uncut_text -#ifndef NANO_TINY - || func == do_undo -#endif - ) { - /* If we actually justified something, then splice the preserved - * unjustified text back into the file, */ - if (first_par_line != NULL) { - filestruct *trash = NULL, *dummy = NULL; - - /* Throw away the justified paragraph, and replace it with - * the preserved unjustified text. */ - extract_buffer(&trash, &dummy, first_par_line, 0, last_par_line, - filebot_inpar ? strlen(last_par_line->data) : 0); - free_filestruct(trash); - ingraft_buffer(jusbuffer); - - /* Restore the old position and the mark. */ - openfile->edittop = edittop_save; - openfile->firstcolumn = firstcolumn_save; - openfile->current = current_save; - openfile->current_x = current_x_save; -#ifndef NANO_TINY - if (openfile->mark) { - openfile->mark = was_mark; - openfile->mark_x = was_mark_x; - } -#endif - openfile->modified = modified_save; - if (!openfile->modified) - titlebar(NULL); - - refresh_needed = TRUE; - } - } else { - /* Put the keystroke back into the queue. */ - unget_kbinput(kbinput, meta_key); - - /* Set the desired screen column (always zero, except at EOF). */ - openfile->placewewant = xplustabs(); - -#ifndef NANO_TINY - /* Throw away the entire undo stack, to prevent a crash when - * the user tries to undo something in the justified text. */ - discard_until(NULL, openfile, FALSE); -#endif - /* Blow away the unjustified text. */ - free_filestruct(jusbuffer); - } - - /* Mark the buffer for unjustified text as empty. */ - jusbuffer = NULL; - - wipe_statusbar(); - - /* Show "Uncut" again in the help lines, and force their redrawing. */ - uncutfunc->desc = uncut_tag; - currmenu = MMOST; + /* Show "Uncut" again in the help lines, and force their redrawing. */ + uncutfunc->desc = uncut_tag; + currmenu = MMOST; } /* Justify the current paragraph. */ void do_justify_void(void) { - do_justify(FALSE); + do_justify(FALSE); } /* Justify the entire file. */ void do_full_justify(void) { - do_justify(TRUE); + do_justify(TRUE); } #endif /* ENABLE_JUSTIFY */ @@ -2527,129 +2527,129 @@ void do_full_justify(void) * return FALSE if the user cancels. */ bool do_int_spell_fix(const char *word) { - char *save_search; - size_t firstcolumn_save = openfile->firstcolumn; - size_t current_x_save = openfile->current_x; - filestruct *edittop_save = openfile->edittop; - filestruct *current_save = openfile->current; - /* Save where we are. */ - bool proceed = FALSE; - /* The return value of this function. */ - bool result; - /* The return value of searching for a misspelled word. */ - unsigned stash[sizeof(flags) / sizeof(flags[0])]; - /* A storage place for the current flag settings. */ + char *save_search; + size_t firstcolumn_save = openfile->firstcolumn; + size_t current_x_save = openfile->current_x; + filestruct *edittop_save = openfile->edittop; + filestruct *current_save = openfile->current; + /* Save where we are. */ + bool proceed = FALSE; + /* The return value of this function. */ + bool result; + /* The return value of searching for a misspelled word. */ + unsigned stash[sizeof(flags) / sizeof(flags[0])]; + /* A storage place for the current flag settings. */ #ifndef NANO_TINY - bool right_side_up = FALSE; - /* TRUE if (mark_begin, mark_begin_x) is the top of the mark, - * FALSE if (current, current_x) is. */ - filestruct *top, *bot; - size_t top_x, bot_x; + bool right_side_up = FALSE; + /* TRUE if (mark_begin, mark_begin_x) is the top of the mark, + * FALSE if (current, current_x) is. */ + filestruct *top, *bot; + size_t top_x, bot_x; #endif - /* Save the settings of the global flags. */ - memcpy(stash, flags, sizeof(flags)); + /* Save the settings of the global flags. */ + memcpy(stash, flags, sizeof(flags)); - /* Do the spell checking case sensitive, forward, and without regexes. */ - SET(CASE_SENSITIVE); - UNSET(BACKWARDS_SEARCH); - UNSET(USE_REGEXP); + /* Do the spell checking case sensitive, forward, and without regexes. */ + SET(CASE_SENSITIVE); + UNSET(BACKWARDS_SEARCH); + UNSET(USE_REGEXP); - /* Save the current search string, then set it to the misspelled word. */ - save_search = last_search; - last_search = mallocstrcpy(NULL, word); + /* Save the current search string, then set it to the misspelled word. */ + save_search = last_search; + last_search = mallocstrcpy(NULL, word); #ifndef NANO_TINY - /* If the mark is on, start at the beginning of the marked region. */ - if (openfile->mark) { - mark_order((const filestruct **)&top, &top_x, - (const filestruct **)&bot, &bot_x, &right_side_up); - /* If the region is marked normally, swap the end points, so that - * (current, current_x) (where searching starts) is at the top. */ - if (right_side_up) { - openfile->current = top; - openfile->current_x = top_x; - openfile->mark = bot; - openfile->mark_x = bot_x; + /* If the mark is on, start at the beginning of the marked region. */ + if (openfile->mark) { + mark_order((const filestruct **)&top, &top_x, + (const filestruct **)&bot, &bot_x, &right_side_up); + /* If the region is marked normally, swap the end points, so that + * (current, current_x) (where searching starts) is at the top. */ + if (right_side_up) { + openfile->current = top; + openfile->current_x = top_x; + openfile->mark = bot; + openfile->mark_x = bot_x; + } + } else +#endif + /* Otherwise, start from the top of the file. */ + { + openfile->current = openfile->fileage; + openfile->current_x = 0; } - } else -#endif - /* Otherwise, start from the top of the file. */ - { - openfile->current = openfile->fileage; - openfile->current_x = 0; - } - /* Find the first whole occurrence of word. */ - result = findnextstr(word, TRUE, INREGION, NULL, FALSE, NULL, 0); + /* Find the first whole occurrence of word. */ + result = findnextstr(word, TRUE, INREGION, NULL, FALSE, NULL, 0); - /* If the word isn't found, alert the user; if it is, allow correction. */ - if (result == 0) { - statusline(ALERT, _("Unfindable word: %s"), word); - lastmessage = HUSH; - proceed = TRUE; - napms(2800); - } else if (result == 1) { - size_t from_col = xplustabs(); - size_t to_col = from_col + strlenpt(word); + /* If the word isn't found, alert the user; if it is, allow correction. */ + if (result == 0) { + statusline(ALERT, _("Unfindable word: %s"), word); + lastmessage = HUSH; + proceed = TRUE; + napms(2800); + } else if (result == 1) { + size_t from_col = xplustabs(); + size_t to_col = from_col + strlenpt(word); #ifndef NANO_TINY - filestruct *saved_mark = openfile->mark; - openfile->mark = NULL; + filestruct *saved_mark = openfile->mark; + openfile->mark = NULL; #endif - edit_refresh(); + edit_refresh(); #ifndef NANO_TINY - openfile->mark = saved_mark; + openfile->mark = saved_mark; #endif - spotlight(TRUE, from_col, to_col); + spotlight(TRUE, from_col, to_col); - /* Let the user supply a correctly spelled alternative. */ - proceed = (do_prompt(FALSE, FALSE, MSPELL, word, NULL, - edit_refresh, _("Edit a replacement")) != -1); + /* Let the user supply a correctly spelled alternative. */ + proceed = (do_prompt(FALSE, FALSE, MSPELL, word, NULL, + edit_refresh, _("Edit a replacement")) != -1); - spotlight(FALSE, from_col, to_col); + spotlight(FALSE, from_col, to_col); - /* If a replacement was given, go through all occurrences. */ - if (proceed && strcmp(word, answer) != 0) { - do_replace_loop(word, TRUE, current_save, ¤t_x_save); + /* If a replacement was given, go through all occurrences. */ + if (proceed && strcmp(word, answer) != 0) { + do_replace_loop(word, TRUE, current_save, ¤t_x_save); - /* TRANSLATORS: Shown after fixing misspellings in one word. */ - statusbar(_("Next word...")); - napms(400); + /* TRANSLATORS: Shown after fixing misspellings in one word. */ + statusbar(_("Next word...")); + napms(400); + } } - } #ifndef NANO_TINY - if (openfile->mark) { - /* Restore the (compensated) end points of the marked region. */ - if (right_side_up) { - openfile->current = openfile->mark; - openfile->current_x = openfile->mark_x; - openfile->mark = top; - openfile->mark_x = top_x; - } else { - openfile->current = top; - openfile->current_x = top_x; - } - } else + if (openfile->mark) { + /* Restore the (compensated) end points of the marked region. */ + if (right_side_up) { + openfile->current = openfile->mark; + openfile->current_x = openfile->mark_x; + openfile->mark = top; + openfile->mark_x = top_x; + } else { + openfile->current = top; + openfile->current_x = top_x; + } + } else #endif - { - /* Restore the (compensated) cursor position. */ - openfile->current = current_save; - openfile->current_x = current_x_save; - } + { + /* Restore the (compensated) cursor position. */ + openfile->current = current_save; + openfile->current_x = current_x_save; + } - /* Restore the string that was last searched for. */ - free(last_search); - last_search = save_search; + /* Restore the string that was last searched for. */ + free(last_search); + last_search = save_search; - /* Restore the viewport to where it was. */ - openfile->edittop = edittop_save; - openfile->firstcolumn = firstcolumn_save; + /* Restore the viewport to where it was. */ + openfile->edittop = edittop_save; + openfile->firstcolumn = firstcolumn_save; - /* Restore the settings of the global flags. */ - memcpy(flags, stash, sizeof(flags)); + /* Restore the settings of the global flags. */ + memcpy(flags, stash, sizeof(flags)); - return proceed; + return proceed; } /* Internal (integrated) spell checking using the spell program, @@ -2657,357 +2657,357 @@ bool do_int_spell_fix(const char *word) * termination, and the error string otherwise. */ const char *do_int_speller(const char *tempfile_name) { - char *read_buff, *read_buff_ptr, *read_buff_word; - size_t pipe_buff_size, read_buff_size, read_buff_read, bytesread; - int spell_fd[2], sort_fd[2], uniq_fd[2], tempfile_fd = -1; - pid_t pid_spell, pid_sort, pid_uniq; - int spell_status, sort_status, uniq_status; + char *read_buff, *read_buff_ptr, *read_buff_word; + size_t pipe_buff_size, read_buff_size, read_buff_read, bytesread; + int spell_fd[2], sort_fd[2], uniq_fd[2], tempfile_fd = -1; + pid_t pid_spell, pid_sort, pid_uniq; + int spell_status, sort_status, uniq_status; - /* Create all three pipes up front. */ - if (pipe(spell_fd) == -1 || pipe(sort_fd) == -1 || pipe(uniq_fd) == -1) - return _("Could not create pipe"); + /* Create all three pipes up front. */ + if (pipe(spell_fd) == -1 || pipe(sort_fd) == -1 || pipe(uniq_fd) == -1) + return _("Could not create pipe"); - statusbar(_("Creating misspelled word list, please wait...")); + statusbar(_("Creating misspelled word list, please wait...")); - /* A new process to run spell in. */ - if ((pid_spell = fork()) == 0) { - /* Child continues (i.e. future spell process). */ - close(spell_fd[0]); + /* A new process to run spell in. */ + if ((pid_spell = fork()) == 0) { + /* Child continues (i.e. future spell process). */ + close(spell_fd[0]); - /* Replace the standard input with the temp file. */ - if ((tempfile_fd = open(tempfile_name, O_RDONLY)) == -1) - goto close_pipes_and_exit; + /* Replace the standard input with the temp file. */ + if ((tempfile_fd = open(tempfile_name, O_RDONLY)) == -1) + goto close_pipes_and_exit; - if (dup2(tempfile_fd, STDIN_FILENO) != STDIN_FILENO) - goto close_pipes_and_exit; + if (dup2(tempfile_fd, STDIN_FILENO) != STDIN_FILENO) + goto close_pipes_and_exit; - close(tempfile_fd); + close(tempfile_fd); - /* Send spell's standard output to the pipe. */ - if (dup2(spell_fd[1], STDOUT_FILENO) != STDOUT_FILENO) - goto close_pipes_and_exit; + /* Send spell's standard output to the pipe. */ + if (dup2(spell_fd[1], STDOUT_FILENO) != STDOUT_FILENO) + goto close_pipes_and_exit; + close(spell_fd[1]); + + /* Start the spell program; we are using $PATH. */ + execlp("spell", "spell", NULL); + + /* This should not be reached if spell is found. */ + exit(1); + } + + /* Parent continues here. */ close(spell_fd[1]); - /* Start the spell program; we are using $PATH. */ - execlp("spell", "spell", NULL); + /* A new process to run sort in. */ + if ((pid_sort = fork()) == 0) { + /* Child continues (i.e. future sort process). Replace the + * standard input with the standard output of the old pipe. */ + if (dup2(spell_fd[0], STDIN_FILENO) != STDIN_FILENO) + goto close_pipes_and_exit; - /* This should not be reached if spell is found. */ - exit(1); - } + close(spell_fd[0]); - /* Parent continues here. */ - close(spell_fd[1]); + /* Send sort's standard output to the new pipe. */ + if (dup2(sort_fd[1], STDOUT_FILENO) != STDOUT_FILENO) + goto close_pipes_and_exit; - /* A new process to run sort in. */ - if ((pid_sort = fork()) == 0) { - /* Child continues (i.e. future sort process). Replace the - * standard input with the standard output of the old pipe. */ - if (dup2(spell_fd[0], STDIN_FILENO) != STDIN_FILENO) - goto close_pipes_and_exit; + close(sort_fd[1]); + + /* Start the sort program. Use -f to ignore case. */ + execlp("sort", "sort", "-f", NULL); + + /* This should not be reached if sort is found. */ + exit(1); + } close(spell_fd[0]); - - /* Send sort's standard output to the new pipe. */ - if (dup2(sort_fd[1], STDOUT_FILENO) != STDOUT_FILENO) - goto close_pipes_and_exit; - close(sort_fd[1]); - /* Start the sort program. Use -f to ignore case. */ - execlp("sort", "sort", "-f", NULL); + /* A new process to run uniq in. */ + if ((pid_uniq = fork()) == 0) { + /* Child continues (i.e. future uniq process). Replace the + * standard input with the standard output of the old pipe. */ + if (dup2(sort_fd[0], STDIN_FILENO) != STDIN_FILENO) + goto close_pipes_and_exit; - /* This should not be reached if sort is found. */ - exit(1); - } + close(sort_fd[0]); - close(spell_fd[0]); - close(sort_fd[1]); + /* Send uniq's standard output to the new pipe. */ + if (dup2(uniq_fd[1], STDOUT_FILENO) != STDOUT_FILENO) + goto close_pipes_and_exit; - /* A new process to run uniq in. */ - if ((pid_uniq = fork()) == 0) { - /* Child continues (i.e. future uniq process). Replace the - * standard input with the standard output of the old pipe. */ - if (dup2(sort_fd[0], STDIN_FILENO) != STDIN_FILENO) - goto close_pipes_and_exit; + close(uniq_fd[1]); + + /* Start the uniq program; we are using PATH. */ + execlp("uniq", "uniq", NULL); + + /* This should not be reached if uniq is found. */ + exit(1); + } close(sort_fd[0]); - - /* Send uniq's standard output to the new pipe. */ - if (dup2(uniq_fd[1], STDOUT_FILENO) != STDOUT_FILENO) - goto close_pipes_and_exit; - close(uniq_fd[1]); - /* Start the uniq program; we are using PATH. */ - execlp("uniq", "uniq", NULL); - - /* This should not be reached if uniq is found. */ - exit(1); - } - - close(sort_fd[0]); - close(uniq_fd[1]); - - /* The child process was not forked successfully. */ - if (pid_spell < 0 || pid_sort < 0 || pid_uniq < 0) { - close(uniq_fd[0]); - return _("Could not fork"); - } - - /* Get the system pipe buffer size. */ - if ((pipe_buff_size = fpathconf(uniq_fd[0], _PC_PIPE_BUF)) < 1) { - close(uniq_fd[0]); - return _("Could not get size of pipe buffer"); - } - - /* 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(uniq_fd[0], read_buff_ptr, pipe_buff_size)) > 0) { - 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(uniq_fd[0]); - - /* Process the spelling errors. */ - 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) { - if (!do_int_spell_fix(read_buff_word)) { - read_buff_word = read_buff_ptr; - break; - } - } - read_buff_word = read_buff_ptr + 1; + /* The child process was not forked successfully. */ + if (pid_spell < 0 || pid_sort < 0 || pid_uniq < 0) { + close(uniq_fd[0]); + return _("Could not fork"); } - read_buff_ptr++; - } - /* Special case: the last word doesn't end with '\r' or '\n'. */ - if (read_buff_word != read_buff_ptr) - do_int_spell_fix(read_buff_word); + /* Get the system pipe buffer size. */ + if ((pipe_buff_size = fpathconf(uniq_fd[0], _PC_PIPE_BUF)) < 1) { + close(uniq_fd[0]); + return _("Could not get size of pipe buffer"); + } - free(read_buff); - search_replace_abort(); - refresh_needed = TRUE; + /* 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); - /* Process the end of the three processes. */ - waitpid(pid_spell, &spell_status, 0); - waitpid(pid_sort, &sort_status, 0); - waitpid(pid_uniq, &uniq_status, 0); + while ((bytesread = read(uniq_fd[0], read_buff_ptr, pipe_buff_size)) > 0) { + 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; + } - if (WIFEXITED(spell_status) == 0 || WEXITSTATUS(spell_status)) - return _("Error invoking \"spell\""); + *read_buff_ptr = '\0'; + close(uniq_fd[0]); - if (WIFEXITED(sort_status) == 0 || WEXITSTATUS(sort_status)) - return _("Error invoking \"sort -f\""); + /* Process the spelling errors. */ + read_buff_word = read_buff_ptr = read_buff; - if (WIFEXITED(uniq_status) == 0 || WEXITSTATUS(uniq_status)) - return _("Error invoking \"uniq\""); + 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) { + if (!do_int_spell_fix(read_buff_word)) { + read_buff_word = read_buff_ptr; + break; + } + } + read_buff_word = read_buff_ptr + 1; + } + read_buff_ptr++; + } - /* When all went okay. */ - return NULL; + /* Special case: the last word doesn't end with '\r' or '\n'. */ + if (read_buff_word != read_buff_ptr) + do_int_spell_fix(read_buff_word); + + free(read_buff); + search_replace_abort(); + refresh_needed = TRUE; + + /* Process the end of the three processes. */ + waitpid(pid_spell, &spell_status, 0); + waitpid(pid_sort, &sort_status, 0); + waitpid(pid_uniq, &uniq_status, 0); + + if (WIFEXITED(spell_status) == 0 || WEXITSTATUS(spell_status)) + return _("Error invoking \"spell\""); + + if (WIFEXITED(sort_status) == 0 || WEXITSTATUS(sort_status)) + return _("Error invoking \"sort -f\""); + + if (WIFEXITED(uniq_status) == 0 || WEXITSTATUS(uniq_status)) + return _("Error invoking \"uniq\""); + + /* When all went okay. */ + return NULL; close_pipes_and_exit: - /* Don't leak any handles. */ - close(tempfile_fd); - close(spell_fd[0]); - close(spell_fd[1]); - close(sort_fd[0]); - close(sort_fd[1]); - close(uniq_fd[0]); - close(uniq_fd[1]); - exit(1); + /* Don't leak any handles. */ + close(tempfile_fd); + close(spell_fd[0]); + close(spell_fd[1]); + close(sort_fd[0]); + close(sort_fd[1]); + close(uniq_fd[0]); + close(uniq_fd[1]); + exit(1); } /* External (alternate) spell checking. Return NULL for normal * termination, and the error string otherwise. */ const char *do_alt_speller(char *tempfile_name) { - int alt_spell_status; - size_t current_x_save = openfile->current_x; - size_t pww_save = openfile->placewewant; - ssize_t lineno_save = openfile->current->lineno; - bool was_at_eol = (openfile->current->data[openfile->current_x] == '\0'); - struct stat spellfileinfo; - time_t timestamp; - pid_t pid_spell; - char *ptr; - static int arglen = 3; - static char **spellargs = NULL; + int alt_spell_status; + size_t current_x_save = openfile->current_x; + size_t pww_save = openfile->placewewant; + ssize_t lineno_save = openfile->current->lineno; + bool was_at_eol = (openfile->current->data[openfile->current_x] == '\0'); + struct stat spellfileinfo; + time_t timestamp; + pid_t pid_spell; + char *ptr; + static int arglen = 3; + static char **spellargs = NULL; - /* Get the timestamp and the size of the temporary file. */ - stat(tempfile_name, &spellfileinfo); - timestamp = spellfileinfo.st_mtime; + /* Get the timestamp and the size of the temporary file. */ + stat(tempfile_name, &spellfileinfo); + timestamp = spellfileinfo.st_mtime; - /* If the number of bytes to check is zero, get out. */ - if (spellfileinfo.st_size == 0) - return NULL; + /* If the number of bytes to check is zero, get out. */ + if (spellfileinfo.st_size == 0) + return NULL; - /* Exit from curses mode. */ - endwin(); + /* Exit from curses mode. */ + endwin(); - /* Set up the argument list to pass to execvp(). */ - if (spellargs == NULL) { - spellargs = (char **)nmalloc(arglen * sizeof(char *)); + /* Set up the argument list to pass to execvp(). */ + if (spellargs == NULL) { + spellargs = (char **)nmalloc(arglen * sizeof(char *)); - spellargs[0] = strtok(alt_speller, " "); - while ((ptr = strtok(NULL, " ")) != NULL) { - arglen++; - spellargs = (char **)nrealloc(spellargs, arglen * - sizeof(char *)); - spellargs[arglen - 3] = ptr; + spellargs[0] = strtok(alt_speller, " "); + while ((ptr = strtok(NULL, " ")) != NULL) { + arglen++; + spellargs = (char **)nrealloc(spellargs, arglen * + sizeof(char *)); + spellargs[arglen - 3] = ptr; + } + spellargs[arglen - 1] = NULL; } - spellargs[arglen - 1] = NULL; - } - spellargs[arglen - 2] = tempfile_name; + spellargs[arglen - 2] = tempfile_name; - /* Fork a child process and run the alternate spell program in it. */ - if ((pid_spell = fork()) == 0) { - execvp(spellargs[0], spellargs); + /* Fork a child process and run the alternate spell program in it. */ + if ((pid_spell = fork()) == 0) { + execvp(spellargs[0], spellargs); - /* Terminate the child process if no alternate speller is found. */ - exit(1); - } else if (pid_spell < 0) - return _("Could not fork"); + /* Terminate the child process if no alternate speller is found. */ + exit(1); + } else if (pid_spell < 0) + return _("Could not fork"); #ifndef NANO_TINY - /* Block SIGWINCHes so the spell checker doesn't get any. */ - allow_sigwinch(FALSE); + /* Block SIGWINCHes so the spell checker doesn't get any. */ + allow_sigwinch(FALSE); #endif - /* Wait for the alternate spell checker to finish. */ - wait(&alt_spell_status); + /* Wait for the alternate spell checker to finish. */ + wait(&alt_spell_status); - /* Reenter curses mode. */ - doupdate(); + /* Reenter curses mode. */ + doupdate(); - /* Restore the terminal to its previous state. */ - terminal_init(); + /* Restore the terminal to its previous state. */ + terminal_init(); - if (!WIFEXITED(alt_spell_status) || WEXITSTATUS(alt_spell_status) != 0) - return invocation_error(alt_speller); + if (!WIFEXITED(alt_spell_status) || WEXITSTATUS(alt_spell_status) != 0) + return invocation_error(alt_speller); #ifndef NANO_TINY - /* Replace the marked text (or the entire text) of the current buffer - * with the spell-checked text. */ - if (openfile->mark) { - filestruct *top, *bot; - size_t top_x, bot_x; - bool right_side_up; - ssize_t was_mark_lineno = openfile->mark->lineno; + /* Replace the marked text (or the entire text) of the current buffer + * with the spell-checked text. */ + if (openfile->mark) { + filestruct *top, *bot; + size_t top_x, bot_x; + bool right_side_up; + ssize_t was_mark_lineno = openfile->mark->lineno; - mark_order((const filestruct **)&top, &top_x, - (const filestruct **)&bot, &bot_x, &right_side_up); - openfile->mark = NULL; + mark_order((const filestruct **)&top, &top_x, + (const filestruct **)&bot, &bot_x, &right_side_up); + openfile->mark = NULL; - replace_marked_buffer(tempfile_name, top, top_x, bot, bot_x); + replace_marked_buffer(tempfile_name, top, top_x, bot, bot_x); - /* Adjust the end point of the marked region for any change in - * length of the region's last line. */ - if (right_side_up) - current_x_save = openfile->current_x; - else - openfile->mark_x = openfile->current_x; + /* Adjust the end point of the marked region for any change in + * length of the region's last line. */ + if (right_side_up) + current_x_save = openfile->current_x; + else + openfile->mark_x = openfile->current_x; - /* Restore the mark. */ - openfile->mark = fsfromline(was_mark_lineno); - } else + /* Restore the mark. */ + openfile->mark = fsfromline(was_mark_lineno); + } else #endif - replace_buffer(tempfile_name); + replace_buffer(tempfile_name); - /* Go back to the old position. */ - goto_line_posx(lineno_save, current_x_save); - if (was_at_eol || openfile->current_x > strlen(openfile->current->data)) - openfile->current_x = strlen(openfile->current->data); - openfile->placewewant = pww_save; - adjust_viewport(STATIONARY); + /* Go back to the old position. */ + goto_line_posx(lineno_save, current_x_save); + if (was_at_eol || openfile->current_x > strlen(openfile->current->data)) + openfile->current_x = strlen(openfile->current->data); + openfile->placewewant = pww_save; + adjust_viewport(STATIONARY); - /* Stat the temporary file again, and mark the buffer as modified only - * if this file was changed since it was written. */ - stat(tempfile_name, &spellfileinfo); - if (spellfileinfo.st_mtime != timestamp) { - set_modified(); + /* Stat the temporary file again, and mark the buffer as modified only + * if this file was changed since it was written. */ + stat(tempfile_name, &spellfileinfo); + if (spellfileinfo.st_mtime != timestamp) { + set_modified(); #ifndef NANO_TINY - /* Flush the undo stack, to avoid making a mess when the user - * tries to undo things in spell-corrected lines. */ - discard_until(NULL, openfile, FALSE); + /* Flush the undo stack, to avoid making a mess when the user + * tries to undo things in spell-corrected lines. */ + discard_until(NULL, openfile, FALSE); #endif - } + } #ifndef NANO_TINY - /* Unblock SIGWINCHes again. */ - allow_sigwinch(TRUE); + /* Unblock SIGWINCHes again. */ + allow_sigwinch(TRUE); #endif - return NULL; + return NULL; } /* Spell check the current file. If an alternate spell checker is * specified, use it. Otherwise, use the internal spell checker. */ void do_spell(void) { - bool status; - FILE *temp_file; - char *temp; - const char *spell_msg; + bool status; + FILE *temp_file; + char *temp; + const char *spell_msg; - if (ISSET(RESTRICTED)) { - show_restricted_warning(); - return; - } + if (ISSET(RESTRICTED)) { + show_restricted_warning(); + return; + } - temp = safe_tempfile(&temp_file); + temp = safe_tempfile(&temp_file); - if (temp == NULL) { - statusline(ALERT, _("Error writing temp file: %s"), strerror(errno)); - return; - } + if (temp == NULL) { + statusline(ALERT, _("Error writing temp file: %s"), strerror(errno)); + return; + } #ifndef NANO_TINY - if (openfile->mark) - status = write_marked_file(temp, temp_file, TRUE, OVERWRITE); - else -#endif - status = write_file(temp, temp_file, TRUE, OVERWRITE, TRUE); - - if (!status) { - statusline(ALERT, _("Error writing temp file: %s"), strerror(errno)); - free(temp); - return; - } - - blank_bottombars(); - statusbar(_("Invoking spell checker, please wait")); - - spell_msg = (alt_speller != NULL) ? do_alt_speller(temp) : - do_int_speller(temp); - unlink(temp); - free(temp); - - /* If the spell-checker printed any error messages onscreen, make - * sure that they're cleared off. */ - total_refresh(); - - if (spell_msg != NULL) { - if (errno == 0) - /* Don't display an error message of "Success". */ - statusline(ALERT, _("Spell checking failed: %s"), spell_msg); + if (openfile->mark) + status = write_marked_file(temp, temp_file, TRUE, OVERWRITE); else - statusline(ALERT, _("Spell checking failed: %s: %s"), spell_msg, - strerror(errno)); - } else - statusbar(_("Finished checking spelling")); +#endif + status = write_file(temp, temp_file, TRUE, OVERWRITE, TRUE); + + if (!status) { + statusline(ALERT, _("Error writing temp file: %s"), strerror(errno)); + free(temp); + return; + } + + blank_bottombars(); + statusbar(_("Invoking spell checker, please wait")); + + spell_msg = (alt_speller != NULL) ? do_alt_speller(temp) : + do_int_speller(temp); + unlink(temp); + free(temp); + + /* If the spell-checker printed any error messages onscreen, make + * sure that they're cleared off. */ + total_refresh(); + + if (spell_msg != NULL) { + if (errno == 0) + /* Don't display an error message of "Success". */ + statusline(ALERT, _("Spell checking failed: %s"), spell_msg); + else + statusline(ALERT, _("Spell checking failed: %s: %s"), spell_msg, + strerror(errno)); + } else + statusbar(_("Finished checking spelling")); } #endif /* ENABLE_SPELLER */ @@ -3016,323 +3016,323 @@ void do_spell(void) * termination, and the error string otherwise. */ void do_linter(void) { - char *read_buff, *read_buff_ptr, *read_buff_word, *ptr, *lintcopy; - size_t pipe_buff_size, read_buff_size, read_buff_read, bytesread; - size_t parsesuccess = 0; - int lint_status, lint_fd[2]; - pid_t pid_lint; - static int arglen = 3; - static char **lintargs = NULL; - lintstruct *lints = NULL, *tmplint = NULL, *curlint = NULL; + char *read_buff, *read_buff_ptr, *read_buff_word, *ptr, *lintcopy; + size_t pipe_buff_size, read_buff_size, read_buff_read, bytesread; + size_t parsesuccess = 0; + int lint_status, lint_fd[2]; + pid_t pid_lint; + static int arglen = 3; + static char **lintargs = NULL; + lintstruct *lints = NULL, *tmplint = NULL, *curlint = NULL; - if (ISSET(RESTRICTED)) { - show_restricted_warning(); - return; - } - - if (!openfile->syntax || !openfile->syntax->linter) { - statusbar(_("No linter defined for this type of file!")); - return; - } - - openfile->mark = NULL; - edit_refresh(); - - if (openfile->modified) { - int i = do_yesno_prompt(FALSE, _("Save modified buffer before linting?")); - - if (i == -1) { - statusbar(_("Cancelled")); - return; - } else if (i == 1 && (do_writeout(FALSE, FALSE) != 1)) - return; - } - - lintcopy = mallocstrcpy(NULL, openfile->syntax->linter); - /* Create a pipe up front. */ - if (pipe(lint_fd) == -1) { - statusbar(_("Could not create pipe")); - return; - } - - blank_bottombars(); - statusbar(_("Invoking linter, please wait")); - - /* Set up an argument list to pass to 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; + if (ISSET(RESTRICTED)) { + show_restricted_warning(); + return; } - lintargs[arglen - 1] = NULL; - } - lintargs[arglen - 2] = openfile->filename; - /* Start a new process to run the linter in. */ - if ((pid_lint = fork()) == 0) { + if (!openfile->syntax || !openfile->syntax->linter) { + statusbar(_("No linter defined for this type of file!")); + return; + } - /* Child continues here (i.e. the future linting process). */ - close(lint_fd[0]); + openfile->mark = NULL; + edit_refresh(); - /* Send the linter's standard output + err to the pipe. */ - if (dup2(lint_fd[1], STDOUT_FILENO) != STDOUT_FILENO) - exit(9); - if (dup2(lint_fd[1], STDERR_FILENO) != STDERR_FILENO) - exit(9); + if (openfile->modified) { + int i = do_yesno_prompt(FALSE, _("Save modified buffer before linting?")); + if (i == -1) { + statusbar(_("Cancelled")); + return; + } else if (i == 1 && (do_writeout(FALSE, FALSE) != 1)) + return; + } + + lintcopy = mallocstrcpy(NULL, openfile->syntax->linter); + /* Create a pipe up front. */ + if (pipe(lint_fd) == -1) { + statusbar(_("Could not create pipe")); + return; + } + + blank_bottombars(); + statusbar(_("Invoking linter, please wait")); + + /* Set up an argument list to pass to 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; + + /* Start a new process to run the linter in. */ + if ((pid_lint = fork()) == 0) { + + /* Child continues here (i.e. the future linting process). */ + close(lint_fd[0]); + + /* Send the linter's standard output + err to the pipe. */ + if (dup2(lint_fd[1], STDOUT_FILENO) != STDOUT_FILENO) + exit(9); + if (dup2(lint_fd[1], STDERR_FILENO) != STDERR_FILENO) + exit(9); + + close(lint_fd[1]); + + /* Start the linter program; we are using $PATH. */ + execvp(lintargs[0], lintargs); + + /* This is only reached when the linter is not found. */ + exit(9); + } + + /* Parent continues here. */ close(lint_fd[1]); - /* Start the linter program; we are using $PATH. */ - execvp(lintargs[0], lintargs); - - /* This is only reached when the linter is not found. */ - exit(9); - } - - /* Parent continues here. */ - close(lint_fd[1]); - - /* If the child process was not forked successfully... */ - if (pid_lint < 0) { - close(lint_fd[0]); - statusbar(_("Could not fork")); - 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")); - return; - } - - /* Read in the returned syntax 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) { - 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]); - - /* Process the linter 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 handle the following formats: - * - * filenameorcategory:line:column:message (e.g. splint) - * filenameorcategory:line,column:message (e.g. pylint) - * filenameorcategory:line:message (e.g. pyflakes) - */ - if (strstr(message, ": ") != NULL) { - filename = strtok(read_buff_word, ":"); - 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, NULL, 10); - /* Check if the middle field is in comma format. */ - if (tmpcolno <= 0) { - strtok(linestr, ","); - if ((tmplinecol = strtok(NULL, ",")) != NULL) - tmpcolno = strtol(tmplinecol, NULL, 10); - else - tmpcolno = 1; - } - - /* 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; + /* If the child process was not forked successfully... */ + if (pid_lint < 0) { + close(lint_fd[0]); + statusbar(_("Could not fork")); + return; } - read_buff_ptr++; - } - /* Process the end of the linting process. */ - waitpid(pid_lint, &lint_status, 0); + /* 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")); + return; + } - if (!WIFEXITED(lint_status) || WEXITSTATUS(lint_status) > 2) { - statusbar(invocation_error(openfile->syntax->linter)); - return; - } + /* Read in the returned syntax errors. */ + read_buff_read = 0; + read_buff_size = pipe_buff_size + 1; + read_buff = read_buff_ptr = charalloc(read_buff_size); - free(read_buff); + while ((bytesread = read(lint_fd[0], read_buff_ptr, pipe_buff_size)) > 0) { + 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; + } - if (parsesuccess == 0) { - statusline(HUSH, _("Got 0 parsable lines from command: %s"), - openfile->syntax->linter); - return; - } + *read_buff_ptr = '\0'; + close(lint_fd[0]); - bottombars(MLINTER); - tmplint = NULL; - curlint = lints; + /* Process the linter output. */ + read_buff_word = read_buff_ptr = read_buff; - while (TRUE) { - int kbinput; - functionptrtype func; + 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); - if (tmplint != curlint) { -#ifndef NANO_TINY - struct stat lintfileinfo; + /* At the moment we handle the following formats: + * + * filenameorcategory:line:column:message (e.g. splint) + * filenameorcategory:line,column:message (e.g. pylint) + * filenameorcategory:line:message (e.g. pyflakes) + */ + if (strstr(message, ": ") != NULL) { + filename = strtok(read_buff_word, ":"); + if ((linestr = strtok(NULL, ":")) != NULL) { + if ((maybecol = strtok(NULL, ":")) != NULL) { + ssize_t tmplineno = 0, tmpcolno = 0; + char *tmplinecol; - 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; + tmplineno = strtol(linestr, NULL, 10); + if (tmplineno <= 0) { + read_buff_ptr++; + free(message); + continue; + } - 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 = mallocstrcpy(NULL, curlint->filename); - lintstruct *restlint = NULL; + tmpcolno = strtol(maybecol, NULL, 10); + /* Check if the middle field is in comma format. */ + if (tmpcolno <= 0) { + strtok(linestr, ","); + if ((tmplinecol = strtok(NULL, ",")) != NULL) + tmpcolno = strtol(tmplinecol, NULL, 10); + else + tmpcolno = 1; + } - while (curlint != NULL) { - if (strcmp(curlint->filename, dontwantfile) == 0) { - if (curlint == lints) - lints = curlint->next; - else - curlint->prev->next = curlint->next; - if (curlint->next != NULL) - curlint->next->prev = curlint->prev; - tmplint = curlint; - curlint = curlint->next; - free(tmplint->msg); - free(tmplint->filename); - free(tmplint); - } else { - if (restlint == NULL) - restlint = curlint; - curlint = curlint->next; - } - } + /* 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 (restlint == NULL) { - statusbar(_("No more errors in unopened files, cancelling")); - napms(2400); - break; - } else { - curlint = restlint; - goto new_lint_loop; - } - - free(dontwantfile); + if (lints == NULL) + lints = curlint; + } + } + } else + free(message); } - } else - openfile = tmpof; + read_buff_word = read_buff_ptr + 1; } - } -#endif /* !NANO_TINY */ - goto_line_posx(curlint->lineno, curlint->colno - 1); - titlebar(NULL); - adjust_viewport(CENTERING); - edit_refresh(); - statusbar(curlint->msg); - bottombars(MLINTER); + read_buff_ptr++; } - /* Place the cursor to indicate the affected line. */ - place_the_cursor(); - wnoutrefresh(edit); + /* Process the end of the linting process. */ + waitpid(pid_lint, &lint_status, 0); - kbinput = get_kbinput(bottomwin, VISIBLE); + if (!WIFEXITED(lint_status) || WEXITSTATUS(lint_status) > 2) { + statusbar(invocation_error(openfile->syntax->linter)); + return; + } + + free(read_buff); + + if (parsesuccess == 0) { + statusline(HUSH, _("Got 0 parsable lines from command: %s"), + openfile->syntax->linter); + return; + } + + bottombars(MLINTER); + tmplint = NULL; + curlint = lints; + + while (TRUE) { + int kbinput; + functionptrtype func; + + 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 = mallocstrcpy(NULL, curlint->filename); + lintstruct *restlint = NULL; + + while (curlint != NULL) { + if (strcmp(curlint->filename, dontwantfile) == 0) { + if (curlint == lints) + lints = curlint->next; + else + curlint->prev->next = curlint->next; + if (curlint->next != NULL) + curlint->next->prev = curlint->prev; + tmplint = curlint; + curlint = curlint->next; + free(tmplint->msg); + free(tmplint->filename); + free(tmplint); + } else { + if (restlint == NULL) + restlint = curlint; + curlint = curlint->next; + } + } + + if (restlint == NULL) { + statusbar(_("No more errors in unopened files, cancelling")); + napms(2400); + break; + } else { + curlint = restlint; + goto new_lint_loop; + } + + free(dontwantfile); + } + } else + openfile = tmpof; + } + } +#endif /* !NANO_TINY */ + goto_line_posx(curlint->lineno, curlint->colno - 1); + titlebar(NULL); + adjust_viewport(CENTERING); + edit_refresh(); + statusbar(curlint->msg); + bottombars(MLINTER); + } + + /* Place the cursor to indicate the affected line. */ + place_the_cursor(); + wnoutrefresh(edit); + + kbinput = get_kbinput(bottomwin, VISIBLE); #ifndef NANO_TINY - if (kbinput == KEY_WINCH) - continue; + if (kbinput == KEY_WINCH) + continue; #endif - func = func_from_key(&kbinput); - tmplint = curlint; + func = func_from_key(&kbinput); + tmplint = curlint; - if (func == do_cancel) - break; - else if (func == do_help_void) { - tmplint = NULL; - do_help_void(); - } else if (func == do_page_down) { - if (curlint->next != NULL) - curlint = curlint->next; - else - statusbar(_("At last message")); - } else if (func == do_page_up) { - if (curlint->prev != NULL) - curlint = curlint->prev; - else - statusbar(_("At first message")); + if (func == do_cancel) + break; + else if (func == do_help_void) { + tmplint = NULL; + do_help_void(); + } else if (func == do_page_down) { + if (curlint->next != NULL) + curlint = curlint->next; + else + statusbar(_("At last message")); + } else if (func == do_page_up) { + if (curlint->prev != NULL) + curlint = curlint->prev; + else + statusbar(_("At first message")); + } } - } - wipe_statusbar(); + wipe_statusbar(); #ifndef NANO_TINY free_lints_and_return: #endif - for (curlint = lints; curlint != NULL;) { - tmplint = curlint; - curlint = curlint->next; - free(tmplint->msg); - free(tmplint->filename); - free(tmplint); - } + for (curlint = lints; curlint != NULL;) { + tmplint = curlint; + curlint = curlint->next; + free(tmplint->msg); + free(tmplint->filename); + free(tmplint); + } } #ifdef ENABLE_SPELLER @@ -3341,123 +3341,123 @@ void do_linter(void) * pass it on the command line. */ void do_formatter(void) { - bool status; - FILE *temp_file; - int format_status; - ssize_t lineno_save = openfile->current->lineno; - size_t current_x_save = openfile->current_x; - size_t pww_save = openfile->placewewant; - bool was_at_eol = (openfile->current->data[openfile->current_x] == '\0'); - pid_t pid_format; - static int arglen = 3; - static char **formatargs = NULL; - char *temp, *ptr, *finalstatus = NULL; + bool status; + FILE *temp_file; + int format_status; + ssize_t lineno_save = openfile->current->lineno; + size_t current_x_save = openfile->current_x; + size_t pww_save = openfile->placewewant; + bool was_at_eol = (openfile->current->data[openfile->current_x] == '\0'); + pid_t pid_format; + static int arglen = 3; + static char **formatargs = NULL; + char *temp, *ptr, *finalstatus = NULL; - if (openfile->totsize == 0) { - statusbar(_("Finished")); - return; - } + if (openfile->totsize == 0) { + statusbar(_("Finished")); + return; + } - temp = safe_tempfile(&temp_file); + temp = safe_tempfile(&temp_file); - if (temp == NULL) { - statusline(ALERT, _("Error writing temp file: %s"), strerror(errno)); - return; - } + if (temp == NULL) { + statusline(ALERT, _("Error writing temp file: %s"), strerror(errno)); + return; + } #ifndef NANO_TINY - /* We're not supporting partial formatting, oi vey. */ - openfile->mark = NULL; + /* We're not supporting partial formatting, oi vey. */ + openfile->mark = NULL; #endif - status = write_file(temp, temp_file, TRUE, OVERWRITE, TRUE); + status = write_file(temp, temp_file, TRUE, OVERWRITE, TRUE); - if (!status) { - statusline(ALERT, _("Error writing temp file: %s"), strerror(errno)); - free(temp); - return; - } - - blank_bottombars(); - statusbar(_("Invoking formatter, please wait")); - - /* Set up an argument list to pass to execvp(). */ - if (formatargs == NULL) { - formatargs = (char **)nmalloc(arglen * sizeof(char *)); - - formatargs[0] = strtok(openfile->syntax->formatter, " "); - while ((ptr = strtok(NULL, " ")) != NULL) { - arglen++; - formatargs = (char **)nrealloc(formatargs, arglen * sizeof(char *)); - formatargs[arglen - 3] = ptr; + if (!status) { + statusline(ALERT, _("Error writing temp file: %s"), strerror(errno)); + free(temp); + return; } - formatargs[arglen - 1] = NULL; - } - formatargs[arglen - 2] = temp; - /* Start a new process for the formatter. */ - if ((pid_format = fork()) == 0) { - /* Start the formatting program; we are using $PATH. */ - execvp(formatargs[0], formatargs); + blank_bottombars(); + statusbar(_("Invoking formatter, please wait")); - /* Should not be reached, if the formatter is found! */ - exit(1); - } + /* Set up an argument list to pass to execvp(). */ + if (formatargs == NULL) { + formatargs = (char **)nmalloc(arglen * sizeof(char *)); + + formatargs[0] = strtok(openfile->syntax->formatter, " "); + while ((ptr = strtok(NULL, " ")) != NULL) { + arglen++; + formatargs = (char **)nrealloc(formatargs, arglen * sizeof(char *)); + formatargs[arglen - 3] = ptr; + } + formatargs[arglen - 1] = NULL; + } + formatargs[arglen - 2] = temp; + + /* Start a new process for the formatter. */ + if ((pid_format = fork()) == 0) { + /* Start the formatting program; we are using $PATH. */ + execvp(formatargs[0], formatargs); + + /* Should not be reached, if the formatter is found! */ + exit(1); + } + + /* If we couldn't fork, get out. */ + if (pid_format < 0) { + statusbar(_("Could not fork")); + unlink(temp); + free(temp); + return; + } + +#ifndef NANO_TINY + /* Block SIGWINCHes so the formatter doesn't get any. */ + allow_sigwinch(FALSE); +#endif + + /* Wait for the formatter to finish. */ + wait(&format_status); + + if (!WIFEXITED(format_status) || WEXITSTATUS(format_status) != 0) + finalstatus = invocation_error(openfile->syntax->formatter); + else { + /* Replace the text of the current buffer with the formatted text. */ + replace_buffer(temp); + + /* Restore the cursor position. */ + goto_line_posx(lineno_save, current_x_save); + if (was_at_eol || openfile->current_x > strlen(openfile->current->data)) + openfile->current_x = strlen(openfile->current->data); + openfile->placewewant = pww_save; + adjust_viewport(STATIONARY); + + set_modified(); + +#ifndef NANO_TINY + /* Flush the undo stack, to avoid a mess or crash when + * the user tries to undo things in reformatted lines. */ + discard_until(NULL, openfile, FALSE); +#endif + finalstatus = _("Finished formatting"); + } - /* If we couldn't fork, get out. */ - if (pid_format < 0) { - statusbar(_("Could not fork")); unlink(temp); free(temp); - return; - } #ifndef NANO_TINY - /* Block SIGWINCHes so the formatter doesn't get any. */ - allow_sigwinch(FALSE); + /* Unblock SIGWINCHes again. */ + allow_sigwinch(TRUE); #endif - /* Wait for the formatter to finish. */ - wait(&format_status); + statusbar(finalstatus); - if (!WIFEXITED(format_status) || WEXITSTATUS(format_status) != 0) - finalstatus = invocation_error(openfile->syntax->formatter); - else { - /* Replace the text of the current buffer with the formatted text. */ - replace_buffer(temp); + /* If there were error messages, allow the user some time to read them. */ + if (WIFEXITED(format_status) && WEXITSTATUS(format_status) == 2) + sleep(4); - /* Restore the cursor position. */ - goto_line_posx(lineno_save, current_x_save); - if (was_at_eol || openfile->current_x > strlen(openfile->current->data)) - openfile->current_x = strlen(openfile->current->data); - openfile->placewewant = pww_save; - adjust_viewport(STATIONARY); - - set_modified(); - -#ifndef NANO_TINY - /* Flush the undo stack, to avoid a mess or crash when - * the user tries to undo things in reformatted lines. */ - discard_until(NULL, openfile, FALSE); -#endif - finalstatus = _("Finished formatting"); - } - - unlink(temp); - free(temp); - -#ifndef NANO_TINY - /* Unblock SIGWINCHes again. */ - allow_sigwinch(TRUE); -#endif - - statusbar(finalstatus); - - /* If there were error messages, allow the user some time to read them. */ - if (WIFEXITED(format_status) && WEXITSTATUS(format_status) == 2) - sleep(4); - - /* If there were any messages, clear them off. */ - total_refresh(); + /* If there were any messages, clear them off. */ + total_refresh(); } #endif /* ENABLE_SPELLER */ #endif /* ENABLE_COLOR */ @@ -3467,123 +3467,123 @@ void do_formatter(void) * multibyte characters instead of single-byte characters. */ void do_wordlinechar_count(void) { - size_t words = 0, chars = 0; - ssize_t nlines = 0; - size_t current_x_save = openfile->current_x; - size_t pww_save = openfile->placewewant; - filestruct *current_save = openfile->current; - filestruct *was_mark = openfile->mark; - filestruct *top, *bot; - size_t top_x, bot_x; + size_t words = 0, chars = 0; + ssize_t nlines = 0; + size_t current_x_save = openfile->current_x; + size_t pww_save = openfile->placewewant; + filestruct *current_save = openfile->current; + filestruct *was_mark = openfile->mark; + filestruct *top, *bot; + size_t top_x, bot_x; - /* If the mark is on, partition the buffer so that it - * contains only the marked text, and turn the mark off. */ - if (was_mark) { - mark_order((const filestruct **)&top, &top_x, - (const filestruct **)&bot, &bot_x, NULL); - filepart = partition_filestruct(top, top_x, bot, bot_x); - openfile->mark = NULL; - } + /* If the mark is on, partition the buffer so that it + * contains only the marked text, and turn the mark off. */ + if (was_mark) { + mark_order((const filestruct **)&top, &top_x, + (const filestruct **)&bot, &bot_x, NULL); + filepart = partition_filestruct(top, top_x, bot, bot_x); + openfile->mark = NULL; + } - /* Start at the top of the file. */ - openfile->current = openfile->fileage; - openfile->current_x = 0; - openfile->placewewant = 0; + /* Start at the top of the file. */ + openfile->current = openfile->fileage; + openfile->current_x = 0; + openfile->placewewant = 0; - /* Keep moving to the next word (counting punctuation characters as - * part of a word, as "wc -w" does), without updating the screen, - * until we reach the end of the file, incrementing the total word - * count whenever we're on a word just before moving. */ - while (openfile->current != openfile->filebot || - openfile->current->data[openfile->current_x] != '\0') { - if (do_next_word(TRUE, FALSE)) - words++; - } + /* Keep moving to the next word (counting punctuation characters as + * part of a word, as "wc -w" does), without updating the screen, + * until we reach the end of the file, incrementing the total word + * count whenever we're on a word just before moving. */ + while (openfile->current != openfile->filebot || + openfile->current->data[openfile->current_x] != '\0') { + if (do_next_word(TRUE, FALSE)) + words++; + } - /* Get the total line and character counts, as "wc -l" and "wc -c" - * do, but get the latter in multibyte characters. */ - if (was_mark) { - nlines = openfile->filebot->lineno - openfile->fileage->lineno + 1; - chars = get_totsize(openfile->fileage, openfile->filebot); + /* Get the total line and character counts, as "wc -l" and "wc -c" + * do, but get the latter in multibyte characters. */ + if (was_mark) { + nlines = openfile->filebot->lineno - openfile->fileage->lineno + 1; + chars = get_totsize(openfile->fileage, openfile->filebot); - /* Unpartition the buffer so that it contains all the text - * again, and turn the mark back on. */ - unpartition_filestruct(&filepart); - openfile->mark = was_mark; - } else { - nlines = openfile->filebot->lineno; - chars = openfile->totsize; - } + /* Unpartition the buffer so that it contains all the text + * again, and turn the mark back on. */ + unpartition_filestruct(&filepart); + openfile->mark = was_mark; + } else { + nlines = openfile->filebot->lineno; + chars = openfile->totsize; + } - /* Restore where we were. */ - openfile->current = current_save; - openfile->current_x = current_x_save; - openfile->placewewant = pww_save; + /* Restore where we were. */ + openfile->current = current_save; + openfile->current_x = current_x_save; + openfile->placewewant = pww_save; - /* Display the total word, line, and character counts on the statusbar. */ - statusline(HUSH, _("%sWords: %zu Lines: %zd Chars: %zu"), was_mark ? - _("In Selection: ") : "", words, nlines, chars); + /* Display the total word, line, and character counts on the statusbar. */ + statusline(HUSH, _("%sWords: %zu Lines: %zd Chars: %zu"), was_mark ? + _("In Selection: ") : "", words, nlines, chars); } #endif /* !NANO_TINY */ /* Get verbatim input. */ void do_verbatim_input(void) { - int *kbinput; - size_t kbinput_len, i; - char *output; + int *kbinput; + size_t kbinput_len, i; + char *output; - /* TRANSLATORS: This is displayed when the next keystroke will be - * inserted verbatim. */ - statusbar(_("Verbatim Input")); - place_the_cursor(); + /* TRANSLATORS: This is displayed when the next keystroke will be + * inserted verbatim. */ + statusbar(_("Verbatim Input")); + place_the_cursor(); - /* Read in all the verbatim characters. */ - kbinput = get_verbatim_kbinput(edit, &kbinput_len); + /* Read in all the verbatim characters. */ + kbinput = get_verbatim_kbinput(edit, &kbinput_len); - /* Unsuppress cursor-position display or blank the statusbar. */ - if (ISSET(CONSTANT_SHOW)) - suppress_cursorpos = FALSE; - else - wipe_statusbar(); + /* Unsuppress cursor-position display or blank the statusbar. */ + if (ISSET(CONSTANT_SHOW)) + suppress_cursorpos = FALSE; + else + wipe_statusbar(); - /* Display all the verbatim characters at once, not filtering out - * control characters. */ - output = charalloc(kbinput_len + 1); + /* Display all the verbatim characters at once, not filtering out + * control characters. */ + output = charalloc(kbinput_len + 1); - for (i = 0; i < kbinput_len; i++) - output[i] = (char)kbinput[i]; - output[i] = '\0'; + for (i = 0; i < kbinput_len; i++) + output[i] = (char)kbinput[i]; + output[i] = '\0'; - free(kbinput); + free(kbinput); - do_output(output, kbinput_len, TRUE); + do_output(output, kbinput_len, TRUE); - free(output); + free(output); } #ifdef ENABLE_WORDCOMPLETION /* Copy the found completion candidate. */ char *copy_completion(char *check_line, int start) { - char *word; - int position = start, len_of_word = 0, index = 0; + char *word; + int position = start, len_of_word = 0, index = 0; - /* Find the length of the word by travelling to its end. */ - while (is_word_mbchar(&check_line[position], FALSE)) { - int next = move_mbright(check_line, position); - len_of_word += next - position; - position = next; - } + /* Find the length of the word by travelling to its end. */ + while (is_word_mbchar(&check_line[position], FALSE)) { + int next = move_mbright(check_line, position); + len_of_word += next - position; + position = next; + } - word = charalloc(len_of_word + 1); + word = charalloc(len_of_word + 1); - /* Simply copy the word. */ - while (index < len_of_word) - word[index++] = check_line[start++]; + /* Simply copy the word. */ + while (index < len_of_word) + word[index++] = check_line[start++]; - word[index] = '\0'; - return word; + word[index] = '\0'; + return word; } /* Look at the fragment the user has typed, then search the current buffer for @@ -3592,147 +3592,147 @@ char *copy_completion(char *check_line, int start) * possible completion. */ void complete_a_word(void) { - char *shard, *completion = NULL; - int start_of_shard, shard_length = 0; - int i = 0, j = 0; - completion_word *some_word; + char *shard, *completion = NULL; + int start_of_shard, shard_length = 0; + int i = 0, j = 0; + completion_word *some_word; #ifdef ENABLE_WRAPPING - bool was_set_wrapping = !ISSET(NO_WRAP); + bool was_set_wrapping = !ISSET(NO_WRAP); #endif - /* If this is a fresh completion attempt... */ - if (pletion_line == NULL) { - /* Clear the list of words of a previous completion run. */ - while (list_of_completions != NULL) { - completion_word *dropit = list_of_completions; - list_of_completions = list_of_completions->next; - free(dropit->word); - free(dropit); + /* If this is a fresh completion attempt... */ + if (pletion_line == NULL) { + /* Clear the list of words of a previous completion run. */ + while (list_of_completions != NULL) { + completion_word *dropit = list_of_completions; + list_of_completions = list_of_completions->next; + free(dropit->word); + free(dropit); + } + + /* Prevent a completion from being merged with typed text. */ + openfile->last_action = OTHER; + + /* Initialize the starting point for searching. */ + pletion_line = openfile->fileage; + pletion_x = 0; + + /* Wipe the "No further matches" message. */ + wipe_statusbar(); + } else { + /* Remove the attempted completion from the buffer. */ + do_undo(); } - /* Prevent a completion from being merged with typed text. */ - openfile->last_action = OTHER; + /* Find the start of the fragment that the user typed. */ + start_of_shard = openfile->current_x; + while (start_of_shard > 0) { + int step_left = move_mbleft(openfile->current->data, start_of_shard); - /* Initialize the starting point for searching. */ - pletion_line = openfile->fileage; - pletion_x = 0; - - /* Wipe the "No further matches" message. */ - wipe_statusbar(); - } else { - /* Remove the attempted completion from the buffer. */ - do_undo(); - } - - /* Find the start of the fragment that the user typed. */ - start_of_shard = openfile->current_x; - while (start_of_shard > 0) { - int step_left = move_mbleft(openfile->current->data, start_of_shard); - - if (!is_word_mbchar(&openfile->current->data[step_left], FALSE)) - break; - start_of_shard = step_left; - } - - /* If there is no word fragment before the cursor, do nothing. */ - if (start_of_shard == openfile->current_x) { - pletion_line = NULL; - return; - } - - shard = charalloc(openfile->current_x - start_of_shard + 1); - - /* Copy the fragment that has to be searched for. */ - while (start_of_shard < openfile->current_x) - shard[shard_length++] = openfile->current->data[start_of_shard++]; - shard[shard_length] = '\0'; - - /* Run through all of the lines in the buffer, looking for shard. */ - while (pletion_line != NULL) { - int threshold = strlen(pletion_line->data) - shard_length - 1; - /* The point where we can stop searching for shard. */ - - /* Traverse the whole line, looking for shard. */ - for (i = pletion_x; i < threshold; i++) { - /* If the first byte doesn't match, run on. */ - if (pletion_line->data[i] != shard[0]) - continue; - - /* Compare the rest of the bytes in shard. */ - for (j = 1; j < shard_length; j++) - if (pletion_line->data[i + j] != shard[j]) - break; - - /* If not all of the bytes matched, continue searching. */ - if (j < shard_length) - continue; - - /* If the found match is not /longer/ than shard, skip it. */ - if (!is_word_mbchar(&pletion_line->data[i + j], FALSE)) - continue; - - /* If the match is not a separate word, skip it. */ - if (i > 0 && is_word_mbchar(&pletion_line->data[ - move_mbleft(pletion_line->data, i)], FALSE)) - continue; - - /* If this match is the shard itself, ignore it. */ - if (pletion_line == openfile->current && - i == openfile->current_x - shard_length) - continue; - - completion = copy_completion(pletion_line->data, i); - - /* Look among earlier attempted completions for a duplicate. */ - some_word = list_of_completions; - while (some_word && strcmp(some_word->word, completion) != 0) - some_word = some_word->next; - - /* If we've already tried this word, skip it. */ - if (some_word != NULL) { - free(completion); - continue; - } - - /* Add the found word to the list of completions. */ - some_word = (completion_word *)nmalloc(sizeof(completion_word)); - some_word->word = completion; - some_word->next = list_of_completions; - list_of_completions = some_word; - -#ifdef ENABLE_WRAPPING - /* Temporarily disable wrapping so only one undo item is added. */ - SET(NO_WRAP); -#endif - /* Inject the completion into the buffer. */ - do_output(&completion[shard_length], - strlen(completion) - shard_length, FALSE); -#ifdef ENABLE_WRAPPING - /* If needed, reenable wrapping and wrap the current line. */ - if (was_set_wrapping) { - UNSET(NO_WRAP); - do_wrap(openfile->current); - } -#endif - /* Set the position for a possible next search attempt. */ - pletion_x = ++i; - - free(shard); - return; + if (!is_word_mbchar(&openfile->current->data[step_left], FALSE)) + break; + start_of_shard = step_left; } - pletion_line = pletion_line->next; - pletion_x = 0; - } + /* If there is no word fragment before the cursor, do nothing. */ + if (start_of_shard == openfile->current_x) { + pletion_line = NULL; + return; + } - /* The search has reached the end of the file. */ - if (list_of_completions != NULL) { - statusline(ALERT, _("No further matches")); - refresh_needed = TRUE; - } else - /* TRANSLATORS: Shown when there are zero possible completions. */ - statusline(ALERT, _("No matches")); + shard = charalloc(openfile->current_x - start_of_shard + 1); - free(shard); + /* Copy the fragment that has to be searched for. */ + while (start_of_shard < openfile->current_x) + shard[shard_length++] = openfile->current->data[start_of_shard++]; + shard[shard_length] = '\0'; + + /* Run through all of the lines in the buffer, looking for shard. */ + while (pletion_line != NULL) { + int threshold = strlen(pletion_line->data) - shard_length - 1; + /* The point where we can stop searching for shard. */ + + /* Traverse the whole line, looking for shard. */ + for (i = pletion_x; i < threshold; i++) { + /* If the first byte doesn't match, run on. */ + if (pletion_line->data[i] != shard[0]) + continue; + + /* Compare the rest of the bytes in shard. */ + for (j = 1; j < shard_length; j++) + if (pletion_line->data[i + j] != shard[j]) + break; + + /* If not all of the bytes matched, continue searching. */ + if (j < shard_length) + continue; + + /* If the found match is not /longer/ than shard, skip it. */ + if (!is_word_mbchar(&pletion_line->data[i + j], FALSE)) + continue; + + /* If the match is not a separate word, skip it. */ + if (i > 0 && is_word_mbchar(&pletion_line->data[ + move_mbleft(pletion_line->data, i)], FALSE)) + continue; + + /* If this match is the shard itself, ignore it. */ + if (pletion_line == openfile->current && + i == openfile->current_x - shard_length) + continue; + + completion = copy_completion(pletion_line->data, i); + + /* Look among earlier attempted completions for a duplicate. */ + some_word = list_of_completions; + while (some_word && strcmp(some_word->word, completion) != 0) + some_word = some_word->next; + + /* If we've already tried this word, skip it. */ + if (some_word != NULL) { + free(completion); + continue; + } + + /* Add the found word to the list of completions. */ + some_word = (completion_word *)nmalloc(sizeof(completion_word)); + some_word->word = completion; + some_word->next = list_of_completions; + list_of_completions = some_word; + +#ifdef ENABLE_WRAPPING + /* Temporarily disable wrapping so only one undo item is added. */ + SET(NO_WRAP); +#endif + /* Inject the completion into the buffer. */ + do_output(&completion[shard_length], + strlen(completion) - shard_length, FALSE); +#ifdef ENABLE_WRAPPING + /* If needed, reenable wrapping and wrap the current line. */ + if (was_set_wrapping) { + UNSET(NO_WRAP); + do_wrap(openfile->current); + } +#endif + /* Set the position for a possible next search attempt. */ + pletion_x = ++i; + + free(shard); + return; + } + + pletion_line = pletion_line->next; + pletion_x = 0; + } + + /* The search has reached the end of the file. */ + if (list_of_completions != NULL) { + statusline(ALERT, _("No further matches")); + refresh_needed = TRUE; + } else + /* TRANSLATORS: Shown when there are zero possible completions. */ + statusline(ALERT, _("No matches")); + + free(shard); } #endif /* ENABLE_WORDCOMPLETION */ diff --git a/src/utils.c b/src/utils.c index 4ae36f4f..f6cd3b83 100644 --- a/src/utils.c +++ b/src/utils.c @@ -32,79 +32,79 @@ * we fall back on the home directory of the effective user ID. */ void get_homedir(void) { - if (homedir == NULL) { - const char *homenv = getenv("HOME"); + if (homedir == NULL) { + const char *homenv = getenv("HOME"); #ifdef HAVE_PWD_H - /* When HOME isn't set, or when we're root, get the home directory - * from the password file instead. */ - if (homenv == NULL || geteuid() == 0) { - const struct passwd *userage = getpwuid(geteuid()); + /* When HOME isn't set, or when we're root, get the home directory + * from the password file instead. */ + if (homenv == NULL || geteuid() == 0) { + const struct passwd *userage = getpwuid(geteuid()); - if (userage != NULL) - homenv = userage->pw_dir; - } + if (userage != NULL) + homenv = userage->pw_dir; + } #endif - /* Only set homedir if some home directory could be determined, - * otherwise keep homedir NULL. */ - if (homenv != NULL && strcmp(homenv, "") != 0) - homedir = mallocstrcpy(NULL, homenv); - } + /* Only set homedir if some home directory could be determined, + * otherwise keep homedir NULL. */ + if (homenv != NULL && strcmp(homenv, "") != 0) + homedir = mallocstrcpy(NULL, homenv); + } } /* Return the filename part of the given path. */ const char *tail(const char *path) { - const char *slash = strrchr(path, '/'); + const char *slash = strrchr(path, '/'); - if (slash == NULL) - return path; - else - return ++slash; + if (slash == NULL) + return path; + else + return ++slash; } /* Return a copy of the two given strings, welded together. */ char *concatenate(const char *path, const char *name) { - size_t pathlen = strlen(path); - char *joined = charalloc(pathlen + strlen(name) + 1); + size_t pathlen = strlen(path); + char *joined = charalloc(pathlen + strlen(name) + 1); - strcpy(joined, path); - strcpy(joined + pathlen, name); + strcpy(joined, path); + strcpy(joined + pathlen, name); - return joined; + return joined; } #ifdef ENABLE_LINENUMBERS /* Return the number of digits that the given integer n takes up. */ int digits(ssize_t n) { - if (n < 100000) { - if (n < 1000) { - if (n < 100) - return 2; - else - return 3; + if (n < 100000) { + if (n < 1000) { + if (n < 100) + return 2; + else + return 3; + } else { + if (n < 10000) + return 4; + else + return 5; + } } else { - if (n < 10000) - return 4; - else - return 5; + if (n < 10000000) { + if (n < 1000000) + return 6; + else + return 7; + } else { + if (n < 100000000) + return 8; + else + return 9; + } } - } else { - if (n < 10000000) { - if (n < 1000000) - return 6; - else - return 7; - } else { - if (n < 100000000) - return 8; - else - return 9; - } - } } #endif @@ -112,98 +112,98 @@ int digits(ssize_t n) * and return TRUE; otherwise, return FALSE. */ bool parse_num(const char *str, ssize_t *result) { - char *first_error; - ssize_t value; + char *first_error; + ssize_t value; - /* The manual page for strtol() says this is required. */ - errno = 0; + /* The manual page for strtol() says this is required. */ + errno = 0; - value = (ssize_t)strtol(str, &first_error, 10); + value = (ssize_t)strtol(str, &first_error, 10); - if (errno == ERANGE || *str == '\0' || *first_error != '\0') - return FALSE; + if (errno == ERANGE || *str == '\0' || *first_error != '\0') + return FALSE; - *result = value; + *result = value; - return TRUE; + return TRUE; } /* Read two numbers, separated by a comma, from str, and store them in * *line and *column. Return FALSE on error, and TRUE otherwise. */ bool parse_line_column(const char *str, ssize_t *line, ssize_t *column) { - bool retval; - char *firstpart; - const char *comma; + bool retval; + char *firstpart; + const char *comma; - while (*str == ' ') - str++; + while (*str == ' ') + str++; - comma = strpbrk(str, "m,. /;"); + comma = strpbrk(str, "m,. /;"); - if (comma == NULL) - return parse_num(str, line); + if (comma == NULL) + return parse_num(str, line); - retval = parse_num(comma + 1, column); + retval = parse_num(comma + 1, column); + + if (comma == str) + return retval; + + firstpart = mallocstrcpy(NULL, str); + firstpart[comma - str] = '\0'; + + retval = parse_num(firstpart, line) && retval; + + free(firstpart); - if (comma == str) return retval; - - firstpart = mallocstrcpy(NULL, str); - firstpart[comma - str] = '\0'; - - retval = parse_num(firstpart, line) && retval; - - free(firstpart); - - return retval; } /* Reduce the memory allocation of a string to what is needed. */ void snuggly_fit(char **str) { - if (*str != NULL) - *str = charealloc(*str, strlen(*str) + 1); + if (*str != NULL) + *str = charealloc(*str, strlen(*str) + 1); } /* Null a string at a certain index and align it. */ void null_at(char **data, size_t index) { - *data = charealloc(*data, index + 1); - (*data)[index] = '\0'; + *data = charealloc(*data, index + 1); + (*data)[index] = '\0'; } /* For non-null-terminated lines. A line, by definition, shouldn't * normally have newlines in it, so encode its nulls as newlines. */ void unsunder(char *str, size_t true_len) { - for (; true_len > 0; true_len--, str++) { - if (*str == '\0') - *str = '\n'; - } + for (; true_len > 0; true_len--, str++) { + if (*str == '\0') + *str = '\n'; + } } /* For non-null-terminated lines. A line, by definition, shouldn't * normally have newlines in it, so decode its newlines as nulls. */ void sunder(char *str) { - for (; *str != '\0'; str++) { - if (*str == '\n') - *str = '\0'; - } + for (; *str != '\0'; str++) { + if (*str == '\n') + *str = '\0'; + } } #if !defined(ENABLE_TINY) || defined(ENABLE_TABCOMP) || defined(ENABLE_BROWSER) /* Free the memory of the given array, which should contain len elements. */ void free_chararray(char **array, size_t len) { - if (array == NULL) - return; + if (array == NULL) + return; - while (len > 0) - free(array[--len]); + while (len > 0) + free(array[--len]); - free(array); + free(array); } #endif @@ -212,30 +212,30 @@ void free_chararray(char **array, size_t len) const char *fixbounds(const char *r) { #ifndef GNU_WORDBOUNDS - int i, j = 0; - char *r2 = charalloc(strlen(r) * 5); - char *r3; + int i, j = 0; + char *r2 = charalloc(strlen(r) * 5); + char *r3; - for (i = 0; i < strlen(r); i++) { - if (r[i] != '\0' && r[i] == '\\' && (r[i + 1] == '>' || r[i + 1] == '<')) { - strcpy(&r2[j], "[[:"); - r2[j + 3] = r[i + 1]; - strcpy(&r2[j + 4], ":]]"); - i++; - j += 6; - } else - r2[j] = r[i]; - j++; - } + for (i = 0; i < strlen(r); i++) { + if (r[i] != '\0' && r[i] == '\\' && (r[i + 1] == '>' || r[i + 1] == '<')) { + strcpy(&r2[j], "[[:"); + r2[j + 3] = r[i + 1]; + strcpy(&r2[j + 4], ":]]"); + i++; + j += 6; + } else + r2[j] = r[i]; + j++; + } - r2[j] = '\0'; - r3 = mallocstrcpy(NULL, r2); - free(r2); + r2[j] = '\0'; + r3 = mallocstrcpy(NULL, r2); + free(r2); - return (const char *) r3; + return (const char *) r3; #endif /* !GNU_WORDBOUNDS */ - return r; + return r; } #ifdef ENABLE_SPELLER @@ -243,18 +243,18 @@ const char *fixbounds(const char *r) * a separate word? That is: is it not part of a longer word?*/ bool is_separate_word(size_t position, size_t length, const char *buf) { - char before[MAXCHARLEN], after[MAXCHARLEN]; - size_t word_end = position + length; + char before[MAXCHARLEN], after[MAXCHARLEN]; + size_t word_end = position + length; - /* Get the characters before and after the word, if any. */ - parse_mbchar(buf + move_mbleft(buf, position), before, NULL); - parse_mbchar(buf + word_end, after, NULL); + /* Get the characters before and after the word, if any. */ + parse_mbchar(buf + move_mbleft(buf, position), before, NULL); + parse_mbchar(buf + word_end, after, NULL); - /* If the word starts at the beginning of the line OR the character before - * the word isn't a letter, and if the word ends at the end of the line OR - * the character after the word isn't a letter, we have a whole word. */ - return ((position == 0 || !is_alpha_mbchar(before)) && - (buf[word_end] == '\0' || !is_alpha_mbchar(after))); + /* If the word starts at the beginning of the line OR the character before + * the word isn't a letter, and if the word ends at the end of the line OR + * the character after the word isn't a letter, we have a whole word. */ + return ((position == 0 || !is_alpha_mbchar(before)) && + (buf[word_end] == '\0' || !is_alpha_mbchar(after))); } #endif /* ENABLE_SPELLER */ @@ -264,76 +264,76 @@ bool is_separate_word(size_t position, size_t length, const char *buf) * than start. If we are doing a regexp search, and we find a match, we fill * in the global variable regmatches with at most 9 subexpression matches. */ const char *strstrwrapper(const char *haystack, const char *needle, - const char *start) + const char *start) { - if (*needle == '\0') { + if (*needle == '\0') { #ifndef NANO_TINY - statusline(ALERT, "Searching for nothing -- please report a bug"); + statusline(ALERT, "Searching for nothing -- please report a bug"); #endif - return (char *)start; - } - - if (ISSET(USE_REGEXP)) { - if (ISSET(BACKWARDS_SEARCH)) { - size_t last_find, ceiling, far_end; - size_t floor = 0, next_rung = 0; - /* The start of the search range, and the next start. */ - - if (regexec(&search_regexp, haystack, 1, regmatches, 0) != 0) - return NULL; - - far_end = strlen(haystack); - ceiling = start - haystack; - last_find = regmatches[0].rm_so; - - /* A result beyond the search range also means: no match. */ - if (last_find > ceiling) - return NULL; - - /* Move the start-of-range forward until there is no more match; - * then the last match found is the first match backwards. */ - while (regmatches[0].rm_so <= ceiling) { - floor = next_rung; - last_find = regmatches[0].rm_so; - /* If this is the last possible match, don't try to advance. */ - if (last_find == ceiling) - break; - next_rung = move_mbright(haystack, last_find); - regmatches[0].rm_so = next_rung; - regmatches[0].rm_eo = far_end; - if (regexec(&search_regexp, haystack, 1, regmatches, - REG_STARTEND) != 0) - break; - } - - /* Find the last match again, to get possible submatches. */ - regmatches[0].rm_so = floor; - regmatches[0].rm_eo = far_end; - if (regexec(&search_regexp, haystack, 10, regmatches, - REG_STARTEND) != 0) - return NULL; - - return haystack + regmatches[0].rm_so; + return (char *)start; } - /* Do a forward regex search from the starting point. */ - regmatches[0].rm_so = start - haystack; - regmatches[0].rm_eo = strlen(haystack); - if (regexec(&search_regexp, haystack, 10, regmatches, - REG_STARTEND) != 0) - return NULL; - else - return haystack + regmatches[0].rm_so; - } - if (ISSET(CASE_SENSITIVE)) { - if (ISSET(BACKWARDS_SEARCH)) - return revstrstr(haystack, needle, start); - else - return strstr(start, needle); - } else if (ISSET(BACKWARDS_SEARCH)) - return mbrevstrcasestr(haystack, needle, start); + if (ISSET(USE_REGEXP)) { + if (ISSET(BACKWARDS_SEARCH)) { + size_t last_find, ceiling, far_end; + size_t floor = 0, next_rung = 0; + /* The start of the search range, and the next start. */ - return mbstrcasestr(start, needle); + if (regexec(&search_regexp, haystack, 1, regmatches, 0) != 0) + return NULL; + + far_end = strlen(haystack); + ceiling = start - haystack; + last_find = regmatches[0].rm_so; + + /* A result beyond the search range also means: no match. */ + if (last_find > ceiling) + return NULL; + + /* Move the start-of-range forward until there is no more match; + * then the last match found is the first match backwards. */ + while (regmatches[0].rm_so <= ceiling) { + floor = next_rung; + last_find = regmatches[0].rm_so; + /* If this is the last possible match, don't try to advance. */ + if (last_find == ceiling) + break; + next_rung = move_mbright(haystack, last_find); + regmatches[0].rm_so = next_rung; + regmatches[0].rm_eo = far_end; + if (regexec(&search_regexp, haystack, 1, regmatches, + REG_STARTEND) != 0) + break; + } + + /* Find the last match again, to get possible submatches. */ + regmatches[0].rm_so = floor; + regmatches[0].rm_eo = far_end; + if (regexec(&search_regexp, haystack, 10, regmatches, + REG_STARTEND) != 0) + return NULL; + + return haystack + regmatches[0].rm_so; + } + + /* Do a forward regex search from the starting point. */ + regmatches[0].rm_so = start - haystack; + regmatches[0].rm_eo = strlen(haystack); + if (regexec(&search_regexp, haystack, 10, regmatches, + REG_STARTEND) != 0) + return NULL; + else + return haystack + regmatches[0].rm_so; + } + if (ISSET(CASE_SENSITIVE)) { + if (ISSET(BACKWARDS_SEARCH)) + return revstrstr(haystack, needle, start); + else + return strstr(start, needle); + } else if (ISSET(BACKWARDS_SEARCH)) + return mbrevstrcasestr(haystack, needle, start); + + return mbstrcasestr(start, needle); } /* This is a wrapper for the perror() function. The wrapper temporarily @@ -342,63 +342,63 @@ const char *strstrwrapper(const char *haystack, const char *needle, * nperror() causes the window to flicker once. */ void nperror(const char *s) { - endwin(); - perror(s); - doupdate(); + endwin(); + perror(s); + doupdate(); } /* This is a wrapper for the malloc() function that properly handles * things when we run out of memory. */ void *nmalloc(size_t howmuch) { - void *r = malloc(howmuch); + void *r = malloc(howmuch); - if (r == NULL && howmuch != 0) - die(_("nano is out of memory!")); + if (r == NULL && howmuch != 0) + die(_("nano is out of memory!")); - return r; + return r; } /* This is a wrapper for the realloc() function that properly handles * things when we run out of memory. */ void *nrealloc(void *ptr, size_t howmuch) { - void *r = realloc(ptr, howmuch); + void *r = realloc(ptr, howmuch); - if (r == NULL && howmuch != 0) - die(_("nano is out of memory!")); + if (r == NULL && howmuch != 0) + die(_("nano is out of memory!")); - return r; + return r; } /* Allocate and copy the first n characters of the given src string, after * freeing the destination. Usage: "dest = mallocstrncpy(dest, src, n);". */ char *mallocstrncpy(char *dest, const char *src, size_t n) { - if (src == NULL) - src = ""; + if (src == NULL) + src = ""; - if (src != dest) - free(dest); + if (src != dest) + free(dest); - dest = charalloc(n); - strncpy(dest, src, n); + dest = charalloc(n); + strncpy(dest, src, n); - return dest; + return dest; } /* Free the dest string and return a malloc'ed copy of src. Should be used as: * "dest = mallocstrcpy(dest, src);". */ char *mallocstrcpy(char *dest, const char *src) { - return mallocstrncpy(dest, src, (src == NULL) ? 1 : strlen(src) + 1); + return mallocstrncpy(dest, src, (src == NULL) ? 1 : strlen(src) + 1); } /* Free the string at dest and return the string at src. */ char *free_and_assign(char *dest, char *src) { - free(dest); - return src; + free(dest); + return src; } /* When not in softwrap mode, nano scrolls horizontally within a line in @@ -408,83 +408,83 @@ char *free_and_assign(char *dest, char *src) * get_page_start(column) < COLS). */ size_t get_page_start(size_t column) { - if (column < editwincols - 1 || ISSET(SOFTWRAP) || column == 0) - return 0; - else if (editwincols > 8) - return column - 7 - (column - 7) % (editwincols - 8); - else - return column - (editwincols - 2); + if (column < editwincols - 1 || ISSET(SOFTWRAP) || column == 0) + return 0; + else if (editwincols > 8) + return column - 7 - (column - 7) % (editwincols - 8); + else + return column - (editwincols - 2); } /* Return the placewewant associated with current_x, i.e. the zero-based * column position of the cursor. */ size_t xplustabs(void) { - return strnlenpt(openfile->current->data, openfile->current_x); + return strnlenpt(openfile->current->data, openfile->current_x); } /* Return the index in text of the character that (when displayed) will * not overshoot the given column. */ size_t actual_x(const char *text, size_t column) { - const char *start = text; - /* From where we start walking through the text. */ - size_t width = 0; - /* The current accumulated span, in columns. */ + const char *start = text; + /* From where we start walking through the text. */ + size_t width = 0; + /* The current accumulated span, in columns. */ - while (*text != '\0') { - int charlen = parse_mbchar(text, NULL, &width); + while (*text != '\0') { + int charlen = parse_mbchar(text, NULL, &width); - if (width > column) - break; + if (width > column) + break; - text += charlen; - } + text += charlen; + } - return (text - start); + return (text - start); } /* A strnlen() with tabs and multicolumn characters factored in: * how many columns wide are the first maxlen bytes of text? */ size_t strnlenpt(const char *text, size_t maxlen) { - size_t width = 0; - /* The screen display width to text[maxlen]. */ + size_t width = 0; + /* The screen display width to text[maxlen]. */ - if (maxlen == 0) - return 0; + if (maxlen == 0) + return 0; - while (*text != '\0') { - int charlen = parse_mbchar(text, NULL, &width); + while (*text != '\0') { + int charlen = parse_mbchar(text, NULL, &width); - if (maxlen <= charlen) - break; + if (maxlen <= charlen) + break; - maxlen -= charlen; - text += charlen; - } + maxlen -= charlen; + text += charlen; + } - return width; + return width; } /* Return the number of columns that the given text occupies. */ size_t strlenpt(const char *text) { - size_t span = 0; + size_t span = 0; - while (*text != '\0') - text += parse_mbchar(text, NULL, &span); + while (*text != '\0') + text += parse_mbchar(text, NULL, &span); - return span; + return span; } /* Append a new magicline to the end of the buffer. */ void new_magicline(void) { - openfile->filebot->next = make_new_node(openfile->filebot); - openfile->filebot->next->data = mallocstrcpy(NULL, ""); - openfile->filebot = openfile->filebot->next; - openfile->totsize++; + openfile->filebot->next = make_new_node(openfile->filebot); + openfile->filebot->next->data = mallocstrcpy(NULL, ""); + openfile->filebot = openfile->filebot->next; + openfile->totsize++; } #if !defined(NANO_TINY) || defined(ENABLE_HELP) @@ -492,13 +492,13 @@ void new_magicline(void) * it isn't the only line in the file. */ void remove_magicline(void) { - if (openfile->filebot->data[0] == '\0' && - openfile->filebot != openfile->fileage) { - openfile->filebot = openfile->filebot->prev; - free_filestruct(openfile->filebot->next); - openfile->filebot->next = NULL; - openfile->totsize--; - } + if (openfile->filebot->data[0] == '\0' && + openfile->filebot != openfile->fileage) { + openfile->filebot = openfile->filebot->prev; + free_filestruct(openfile->filebot->next); + openfile->filebot->next = NULL; + openfile->totsize--; + } } #endif @@ -507,25 +507,25 @@ void remove_magicline(void) * the marked region. If right_side_up isn't NULL, set it to TRUE when the * mark is at the top of the marked region, and to FALSE otherwise. */ void mark_order(const filestruct **top, size_t *top_x, - const filestruct **bot, size_t *bot_x, bool *right_side_up) + const filestruct **bot, size_t *bot_x, bool *right_side_up) { - if ((openfile->current->lineno == openfile->mark->lineno && - openfile->current_x > openfile->mark_x) || - openfile->current->lineno > openfile->mark->lineno) { - *top = openfile->mark; - *top_x = openfile->mark_x; - *bot = openfile->current; - *bot_x = openfile->current_x; - if (right_side_up != NULL) - *right_side_up = TRUE; - } else { - *bot = openfile->mark; - *bot_x = openfile->mark_x; - *top = openfile->current; - *top_x = openfile->current_x; - if (right_side_up != NULL) - *right_side_up = FALSE; - } + if ((openfile->current->lineno == openfile->mark->lineno && + openfile->current_x > openfile->mark_x) || + openfile->current->lineno > openfile->mark->lineno) { + *top = openfile->mark; + *top_x = openfile->mark_x; + *bot = openfile->current; + *bot_x = openfile->current_x; + if (right_side_up != NULL) + *right_side_up = TRUE; + } else { + *bot = openfile->mark; + *bot_x = openfile->mark_x; + *top = openfile->current; + *top_x = openfile->current_x; + if (right_side_up != NULL) + *right_side_up = FALSE; + } } /* Get the set of lines to work on -- either just the current line, or the @@ -533,74 +533,74 @@ void mark_order(const filestruct **top, size_t *top_x, * at the start of the last line of the region, exclude that line. */ void get_range(const filestruct **top, const filestruct **bot) { - if (!openfile->mark) { - *top = openfile->current; - *bot = openfile->current; - } else { - size_t top_x, bot_x; + if (!openfile->mark) { + *top = openfile->current; + *bot = openfile->current; + } else { + size_t top_x, bot_x; - mark_order(top, &top_x, bot, &bot_x, NULL); + mark_order(top, &top_x, bot, &bot_x, NULL); - if (bot_x == 0 && *bot != *top && !also_the_last) - *bot = (*bot)->prev; - else - also_the_last = TRUE; - } + if (bot_x == 0 && *bot != *top && !also_the_last) + *bot = (*bot)->prev; + else + also_the_last = TRUE; + } } /* Given a line number, return a pointer to the corresponding struct. */ filestruct *fsfromline(ssize_t lineno) { - filestruct *f = openfile->current; + filestruct *f = openfile->current; - if (lineno <= openfile->current->lineno) - while (f->lineno != lineno && f->prev != NULL) - f = f->prev; - else - while (f->lineno != lineno && f->next != NULL) - f = f->next; + if (lineno <= openfile->current->lineno) + while (f->lineno != lineno && f->prev != NULL) + f = f->prev; + else + while (f->lineno != lineno && f->next != NULL) + f = f->next; - if (f->lineno != lineno) { - statusline(ALERT, "Gone undo line -- please report a bug"); - return NULL; - } + if (f->lineno != lineno) { + statusline(ALERT, "Gone undo line -- please report a bug"); + return NULL; + } - return f; + return f; } #endif /* !NANO_TINY */ /* Count the number of characters from begin to end, and return it. */ size_t get_totsize(const filestruct *begin, const filestruct *end) { - const filestruct *line; - size_t totsize = 0; + const filestruct *line; + size_t totsize = 0; - /* Sum the number of characters (plus a newline) in each line. */ - for (line = begin; line != end->next; line = line->next) - totsize += mbstrlen(line->data) + 1; + /* Sum the number of characters (plus a newline) in each line. */ + for (line = begin; line != end->next; line = line->next) + totsize += mbstrlen(line->data) + 1; - /* The last line of a file doesn't have a newline -- otherwise it - * wouldn't be the last line -- so subtract 1 when at EOF. */ - if (line == NULL) - totsize--; + /* The last line of a file doesn't have a newline -- otherwise it + * wouldn't be the last line -- so subtract 1 when at EOF. */ + if (line == NULL) + totsize--; - return totsize; + return totsize; } #ifdef DEBUG /* Dump the given buffer to stderr. */ void dump_filestruct(const filestruct *inptr) { - if (inptr == openfile->fileage) - fprintf(stderr, "Dumping file buffer to stderr...\n"); - else if (inptr == cutbuffer) - fprintf(stderr, "Dumping cutbuffer to stderr...\n"); - else - fprintf(stderr, "Dumping a buffer to stderr...\n"); + if (inptr == openfile->fileage) + fprintf(stderr, "Dumping file buffer to stderr...\n"); + else if (inptr == cutbuffer) + fprintf(stderr, "Dumping cutbuffer to stderr...\n"); + else + fprintf(stderr, "Dumping a buffer to stderr...\n"); - while (inptr != NULL) { - fprintf(stderr, "(%zd) %s\n", inptr->lineno, inptr->data); - inptr = inptr->next; - } + while (inptr != NULL) { + fprintf(stderr, "(%zd) %s\n", inptr->lineno, inptr->data); + inptr = inptr->next; + } } #endif /* DEBUG */ diff --git a/src/winio.c b/src/winio.c index 61c81196..aecb020f 100644 --- a/src/winio.c +++ b/src/winio.c @@ -35,83 +35,83 @@ #endif static int *key_buffer = NULL; - /* The keystroke buffer, containing all the keystrokes we - * haven't handled yet at a given point. */ + /* The keystroke buffer, containing all the keystrokes we + * haven't handled yet at a given point. */ static size_t key_buffer_len = 0; - /* The length of the keystroke buffer. */ + /* The length of the keystroke buffer. */ static bool solitary = FALSE; - /* Whether an Esc arrived by itself -- not as leader of a sequence. */ + /* Whether an Esc arrived by itself -- not as leader of a sequence. */ static bool waiting_mode = TRUE; - /* Whether getting a character will wait for a key to be pressed. */ + /* Whether getting a character will wait for a key to be pressed. */ static int statusblank = 0; - /* The number of keystrokes left before we blank the statusbar. */ + /* The number of keystrokes left before we blank the statusbar. */ #ifdef USING_OLD_NCURSES static bool seen_wide = FALSE; - /* Whether we've seen a multicolumn character in the current line. */ + /* Whether we've seen a multicolumn character in the current line. */ #endif static bool reveal_cursor = FALSE; - /* Whether the cursor should be shown when waiting for input. */ + /* Whether the cursor should be shown when waiting for input. */ #ifndef NANO_TINY static bool recording = FALSE; - /* Whether we are in the process of recording a macro. */ + /* Whether we are in the process of recording a macro. */ static int *macro_buffer = NULL; - /* A buffer where the recorded key codes are stored. */ + /* A buffer where the recorded key codes are stored. */ static size_t macro_length = 0; - /* The current length of the macro. */ + /* The current length of the macro. */ /* Add the given code to the macro buffer. */ void add_to_macrobuffer(int code) { - macro_length++; - macro_buffer = (int*)nrealloc(macro_buffer, macro_length * sizeof(int)); - macro_buffer[macro_length - 1] = code; + macro_length++; + macro_buffer = (int*)nrealloc(macro_buffer, macro_length * sizeof(int)); + macro_buffer[macro_length - 1] = code; } /* Remove the last key code plus any trailing Esc codes from macro buffer. */ void snip_last_keystroke(void) { - macro_length--; - while (macro_length > 0 && macro_buffer[macro_length - 1] == '\x1b') macro_length--; + while (macro_length > 0 && macro_buffer[macro_length - 1] == '\x1b') + macro_length--; } /* Start or stop the recording of keystrokes. */ void record_macro(void) { - recording = !recording; + recording = !recording; - if (recording) { - macro_length = 0; - statusbar(_("Recording a macro...")); - } else { - snip_last_keystroke(); - statusbar(_("Stopped recording")); - } + if (recording) { + macro_length = 0; + statusbar(_("Recording a macro...")); + } else { + snip_last_keystroke(); + statusbar(_("Stopped recording")); + } } /* Copy the stored sequence of codes into the regular key buffer, * so they will be "executed" again. */ void run_macro(void) { - size_t i; + size_t i; - if (recording) { - statusbar(_("Cannot run macro while recording")); - snip_last_keystroke(); - return; - } + if (recording) { + statusbar(_("Cannot run macro while recording")); + snip_last_keystroke(); + return; + } - if (macro_length == 0) { - statusbar(_("Macro is empty")); - return; - } + if (macro_length == 0) { + statusbar(_("Macro is empty")); + return; + } - free(key_buffer); - key_buffer = (int *)nmalloc(macro_length * sizeof(int)); - key_buffer_len = macro_length; + free(key_buffer); + key_buffer = (int *)nmalloc(macro_length * sizeof(int)); + key_buffer_len = macro_length; - for (i = 0; i < macro_length; i++) - key_buffer[i] = macro_buffer[i]; + for (i = 0; i < macro_length; i++) + key_buffer[i] = macro_buffer[i]; } #endif /* !NANO_TINY */ @@ -171,133 +171,133 @@ void run_macro(void) * in the keystroke buffer. */ void get_key_buffer(WINDOW *win) { - int input = ERR; - size_t errcount = 0; + int input = ERR; + size_t errcount = 0; - /* If the keystroke buffer isn't empty, get out. */ - if (key_buffer != NULL) - return; + /* If the keystroke buffer isn't empty, get out. */ + if (key_buffer != NULL) + return; - /* Before reading the first keycode, display any pending screen updates. */ - doupdate(); - - if (reveal_cursor) { - curs_set(1); -#ifdef USE_SLANG + /* Before reading the first keycode, display any pending screen updates. */ doupdate(); -#endif - } - /* Read in the first keycode using whatever mode we're in. */ - while (input == ERR) { - input = wgetch(win); - -#ifndef NANO_TINY - if (the_window_resized) { - regenerate_screen(); - input = KEY_WINCH; - } + if (reveal_cursor) { + curs_set(1); +#ifdef USE_SLANG + doupdate(); #endif - if (input == ERR && !waiting_mode) { - curs_set(0); - return; } - /* If we've failed to get a keycode MAX_BUF_SIZE times in a row, - * assume our input source is gone and die gracefully. We could - * check if errno is set to EIO ("Input/output error") and die in - * that case, but it's not always set properly. Argh. */ - if (input == ERR && ++errcount == MAX_BUF_SIZE) - die(_("Too many errors from stdin")); - } - - curs_set(0); - - /* Initiate the keystroke buffer, and save the keycode in it. */ - key_buffer_len++; - key_buffer = (int *)nmalloc(sizeof(int)); - key_buffer[0] = input; + /* Read in the first keycode using whatever mode we're in. */ + while (input == ERR) { + input = wgetch(win); #ifndef NANO_TINY - /* If we got a SIGWINCH, get out as the win argument is no longer valid. */ - if (input == KEY_WINCH) - return; + if (the_window_resized) { + regenerate_screen(); + input = KEY_WINCH; + } #endif + if (input == ERR && !waiting_mode) { + curs_set(0); + return; + } - /* Read in the remaining characters using non-blocking input. */ - nodelay(win, TRUE); + /* If we've failed to get a keycode MAX_BUF_SIZE times in a row, + * assume our input source is gone and die gracefully. We could + * check if errno is set to EIO ("Input/output error") and die in + * that case, but it's not always set properly. Argh. */ + if (input == ERR && ++errcount == MAX_BUF_SIZE) + die(_("Too many errors from stdin")); + } - while (TRUE) { -#ifndef NANO_TINY - if (recording) - add_to_macrobuffer(input); -#endif - input = wgetch(win); + curs_set(0); - /* If there aren't any more characters, stop reading. */ - if (input == ERR) - break; - - /* Extend the keystroke buffer, and save the keycode at its end. */ + /* Initiate the keystroke buffer, and save the keycode in it. */ key_buffer_len++; - key_buffer = (int *)nrealloc(key_buffer, key_buffer_len * sizeof(int)); - key_buffer[key_buffer_len - 1] = input; - } + key_buffer = (int *)nmalloc(sizeof(int)); + key_buffer[0] = input; - /* Restore waiting mode if it was on. */ - if (waiting_mode) - nodelay(win, FALSE); +#ifndef NANO_TINY + /* If we got a SIGWINCH, get out as the win argument is no longer valid. */ + if (input == KEY_WINCH) + return; +#endif + + /* Read in the remaining characters using non-blocking input. */ + nodelay(win, TRUE); + + while (TRUE) { +#ifndef NANO_TINY + if (recording) + add_to_macrobuffer(input); +#endif + input = wgetch(win); + + /* If there aren't any more characters, stop reading. */ + if (input == ERR) + break; + + /* Extend the keystroke buffer, and save the keycode at its end. */ + key_buffer_len++; + key_buffer = (int *)nrealloc(key_buffer, key_buffer_len * sizeof(int)); + key_buffer[key_buffer_len - 1] = input; + } + + /* Restore waiting mode if it was on. */ + if (waiting_mode) + nodelay(win, FALSE); #ifdef DEBUG - fprintf(stderr, "\nSequence of hex codes:"); - for (size_t i = 0; i < key_buffer_len; i++) - fprintf(stderr, " %3x", key_buffer[i]); - fprintf(stderr, "\n"); + fprintf(stderr, "\nSequence of hex codes:"); + for (size_t i = 0; i < key_buffer_len; i++) + fprintf(stderr, " %3x", key_buffer[i]); + fprintf(stderr, "\n"); #endif } /* Return the length of the keystroke buffer. */ size_t get_key_buffer_len(void) { - return key_buffer_len; + return key_buffer_len; } /* Add the keycodes in input to the keystroke buffer. */ void unget_input(int *input, size_t input_len) { - /* If input is empty, get out. */ - if (input_len == 0) - return; + /* If input is empty, get out. */ + if (input_len == 0) + return; - /* If adding input would put the keystroke buffer beyond maximum capacity, - * only add enough of input to put it at maximum capacity. */ - if (key_buffer_len + input_len < key_buffer_len) - input_len = (size_t)-1 - key_buffer_len; + /* If adding input would put the keystroke buffer beyond maximum capacity, + * only add enough of input to put it at maximum capacity. */ + if (key_buffer_len + input_len < key_buffer_len) + input_len = (size_t)-1 - key_buffer_len; - /* Extend the keystroke buffer to make room for the extra keycodes. */ - key_buffer_len += input_len; - key_buffer = (int *)nrealloc(key_buffer, key_buffer_len * sizeof(int)); + /* Extend the keystroke buffer to make room for the extra keycodes. */ + key_buffer_len += input_len; + key_buffer = (int *)nrealloc(key_buffer, key_buffer_len * sizeof(int)); - /* If the keystroke buffer wasn't empty before, move its beginning - * forward far enough so that we can add input to its beginning. */ - if (key_buffer_len > input_len) - memmove(key_buffer + input_len, key_buffer, - (key_buffer_len - input_len) * sizeof(int)); + /* If the keystroke buffer wasn't empty before, move its beginning + * forward far enough so that we can add input to its beginning. */ + if (key_buffer_len > input_len) + memmove(key_buffer + input_len, key_buffer, + (key_buffer_len - input_len) * sizeof(int)); - /* Copy input to the beginning of the keystroke buffer. */ - memcpy(key_buffer, input, input_len * sizeof(int)); + /* Copy input to the beginning of the keystroke buffer. */ + memcpy(key_buffer, input, input_len * sizeof(int)); } /* Put the character given in kbinput back into the input stream. If it * is a Meta key, also insert an Escape character in front of it. */ void unget_kbinput(int kbinput, bool metakey) { - unget_input(&kbinput, 1); - - if (metakey) { - kbinput = ESC_CODE; unget_input(&kbinput, 1); - } + + if (metakey) { + kbinput = ESC_CODE; + unget_input(&kbinput, 1); + } } /* Try to read input_len codes from the keystroke buffer. If the @@ -306,54 +306,54 @@ void unget_kbinput(int kbinput, bool metakey) * anything else. If the keystroke buffer is (still) empty, return NULL. */ int *get_input(WINDOW *win, size_t input_len) { - int *input; + int *input; - if (key_buffer_len == 0 && win != NULL) - get_key_buffer(win); + if (key_buffer_len == 0 && win != NULL) + get_key_buffer(win); - if (key_buffer_len == 0) - return NULL; + if (key_buffer_len == 0) + return NULL; - /* Limit the request to the number of available codes in the buffer. */ - if (input_len > key_buffer_len) - input_len = key_buffer_len; + /* Limit the request to the number of available codes in the buffer. */ + if (input_len > key_buffer_len) + input_len = key_buffer_len; - /* Copy input_len codes from the head of the keystroke buffer. */ - input = (int *)nmalloc(input_len * sizeof(int)); - memcpy(input, key_buffer, input_len * sizeof(int)); - key_buffer_len -= input_len; + /* Copy input_len codes from the head of the keystroke buffer. */ + input = (int *)nmalloc(input_len * sizeof(int)); + memcpy(input, key_buffer, input_len * sizeof(int)); + key_buffer_len -= input_len; - /* If the keystroke buffer is now empty, mark it as such. */ - if (key_buffer_len == 0) { - free(key_buffer); - key_buffer = NULL; - } else { - /* Trim from the buffer the codes that were copied. */ - memmove(key_buffer, key_buffer + input_len, key_buffer_len * - sizeof(int)); - key_buffer = (int *)nrealloc(key_buffer, key_buffer_len * - sizeof(int)); - } + /* If the keystroke buffer is now empty, mark it as such. */ + if (key_buffer_len == 0) { + free(key_buffer); + key_buffer = NULL; + } else { + /* Trim from the buffer the codes that were copied. */ + memmove(key_buffer, key_buffer + input_len, key_buffer_len * + sizeof(int)); + key_buffer = (int *)nrealloc(key_buffer, key_buffer_len * + sizeof(int)); + } - return input; + return input; } /* Read in a single keystroke, ignoring any that are invalid. */ int get_kbinput(WINDOW *win, bool showcursor) { - int kbinput = ERR; + int kbinput = ERR; - reveal_cursor = showcursor; + reveal_cursor = showcursor; - /* Extract one keystroke from the input stream. */ - while (kbinput == ERR) - kbinput = parse_kbinput(win); + /* Extract one keystroke from the input stream. */ + while (kbinput == ERR) + kbinput = parse_kbinput(win); - /* If we read from the edit window, blank the statusbar if needed. */ - if (win == edit) - check_statusblank(); + /* If we read from the edit window, blank the statusbar if needed. */ + if (win == edit) + check_statusblank(); - return kbinput; + return kbinput; } /* Extract a single keystroke from the input stream. Translate escape @@ -364,428 +364,428 @@ int get_kbinput(WINDOW *win, bool showcursor) * the function keys (F1-F16), and the numeric keypad with NumLock off. */ int parse_kbinput(WINDOW *win) { - static int escapes = 0, byte_digits = 0; - static bool double_esc = FALSE; - int *kbinput, keycode, retval = ERR; + static int escapes = 0, byte_digits = 0; + static bool double_esc = FALSE; + int *kbinput, keycode, retval = ERR; - meta_key = FALSE; - shift_held = FALSE; + meta_key = FALSE; + shift_held = FALSE; - /* Read in a character. */ - kbinput = get_input(win, 1); - - if (kbinput == NULL && !waiting_mode) - return 0; - - while (kbinput == NULL) + /* Read in a character. */ kbinput = get_input(win, 1); - keycode = *kbinput; - free(kbinput); + if (kbinput == NULL && !waiting_mode) + return 0; + + while (kbinput == NULL) + kbinput = get_input(win, 1); + + keycode = *kbinput; + free(kbinput); #ifdef DEBUG - fprintf(stderr, "before parsing: keycode = %d, escapes = %d, byte_digits = %d\n", - keycode, escapes, byte_digits); + fprintf(stderr, "before parsing: keycode = %d, escapes = %d, byte_digits = %d\n", + keycode, escapes, byte_digits); #endif - if (keycode == ERR) - return ERR; + if (keycode == ERR) + return ERR; - if (keycode == ESC_CODE) { - /* Increment the escape counter, but trim an overabundance. */ - escapes++; - if (escapes > 3) - escapes = 1; - /* Take note when an Esc arrived by itself. */ - solitary = (escapes == 1 && key_buffer_len == 0); - return ERR; - } + if (keycode == ESC_CODE) { + /* Increment the escape counter, but trim an overabundance. */ + escapes++; + if (escapes > 3) + escapes = 1; + /* Take note when an Esc arrived by itself. */ + solitary = (escapes == 1 && key_buffer_len == 0); + return ERR; + } - switch (escapes) { - case 0: - /* One non-escape: normal input mode. */ - retval = keycode; - break; - case 1: - if (keycode >= 0x80) - retval = keycode; - else if ((keycode != 'O' && keycode != 'o' && keycode != '[') || - key_buffer_len == 0 || *key_buffer == ESC_CODE) { - /* One escape followed by a single non-escape: - * meta key sequence mode. */ - if (!solitary || (keycode >= 0x20 && keycode < 0x7F)) - meta_key = TRUE; - retval = tolower(keycode); - } else - /* One escape followed by a non-escape, and there - * are more codes waiting: escape sequence mode. */ - retval = parse_escape_sequence(win, keycode); - escapes = 0; - break; - case 2: - if (double_esc) { - /* An "ESC ESC [ X" sequence from Option+arrow, or - * an "ESC ESC [ x" sequence from Shift+Alt+arrow. */ - switch (keycode) { - case 'A': - retval = KEY_HOME; - break; - case 'B': - retval = KEY_END; - break; - case 'C': - retval = CONTROL_RIGHT; - break; - case 'D': - retval = CONTROL_LEFT; - break; -#ifndef NANO_TINY - case 'a': - retval = shiftaltup; - break; - case 'b': - retval = shiftaltdown; - break; - case 'c': - retval = shiftaltright; - break; - case 'd': - retval = shiftaltleft; - break; -#endif - } - double_esc = FALSE; - escapes = 0; - } else if (key_buffer_len == 0) { - if (('0' <= keycode && keycode <= '2' && - byte_digits == 0) || ('0' <= keycode && - keycode <= '9' && byte_digits > 0)) { - /* Two escapes followed by one or more decimal - * digits, and there aren't any other codes - * waiting: byte sequence mode. If the range - * of the byte sequence is limited to 2XX (the - * first digit is between '0' and '2' and the - * others between '0' and '9', interpret it. */ - int byte; - - byte_digits++; - byte = get_byte_kbinput(keycode); - - /* If the decimal byte value is complete, convert it and - * put the obtained byte(s) back into the input buffer. */ - if (byte != ERR) { - char *byte_mb; - int byte_mb_len, *seq, i; - - /* Convert the decimal code to one or two bytes. */ - byte_mb = make_mbchar((long)byte, &byte_mb_len); - - seq = (int *)nmalloc(byte_mb_len * sizeof(int)); - - for (i = 0; i < byte_mb_len; i++) - seq[i] = (unsigned char)byte_mb[i]; - - /* Insert the byte(s) into the input buffer. */ - unget_input(seq, byte_mb_len); - - free(byte_mb); - free(seq); - - byte_digits = 0; - escapes = 0; - } - } else { - if (byte_digits == 0) - /* Two escapes followed by a non-decimal - * digit (or a decimal digit that would - * create a byte sequence greater than 2XX) - * and there aren't any other codes waiting: - * control character sequence mode. */ - retval = get_control_kbinput(keycode); - else { - /* An invalid digit in the middle of a byte - * sequence: reset the byte sequence counter - * and save the code we got as the result. */ - byte_digits = 0; + switch (escapes) { + case 0: + /* One non-escape: normal input mode. */ retval = keycode; - } - escapes = 0; - } - } else if (keycode == '[' && key_buffer_len > 0 && - (('A' <= *key_buffer && *key_buffer <= 'D') || - ('a' <= *key_buffer && *key_buffer <= 'd'))) { - /* An iTerm2/Eterm/rxvt sequence: ^[ ^[ [ X. */ - double_esc = TRUE; - } else { - /* Two escapes followed by a non-escape, and there are more - * codes waiting: combined meta and escape sequence mode. */ - retval = parse_escape_sequence(win, keycode); - meta_key = TRUE; - escapes = 0; - } - break; - case 3: - if (key_buffer_len == 0) - /* Three escapes followed by a non-escape, and no - * other codes are waiting: normal input mode. */ - retval = keycode; - else - /* Three escapes followed by a non-escape, and more - * codes are waiting: combined control character and - * escape sequence mode. First interpret the escape - * sequence, then the result as a control sequence. */ - retval = get_control_kbinput( - parse_escape_sequence(win, keycode)); - escapes = 0; - break; - } - - if (retval == ERR) - return ERR; - - if (retval == controlleft) - return CONTROL_LEFT; - else if (retval == controlright) - return CONTROL_RIGHT; - else if (retval == controlup) - return CONTROL_UP; - else if (retval == controldown) - return CONTROL_DOWN; - else if (retval == controlhome) - return CONTROL_HOME; - else if (retval == controlend) - return CONTROL_END; + break; + case 1: + if (keycode >= 0x80) + retval = keycode; + else if ((keycode != 'O' && keycode != 'o' && keycode != '[') || + key_buffer_len == 0 || *key_buffer == ESC_CODE) { + /* One escape followed by a single non-escape: + * meta key sequence mode. */ + if (!solitary || (keycode >= 0x20 && keycode < 0x7F)) + meta_key = TRUE; + retval = tolower(keycode); + } else + /* One escape followed by a non-escape, and there + * are more codes waiting: escape sequence mode. */ + retval = parse_escape_sequence(win, keycode); + escapes = 0; + break; + case 2: + if (double_esc) { + /* An "ESC ESC [ X" sequence from Option+arrow, or + * an "ESC ESC [ x" sequence from Shift+Alt+arrow. */ + switch (keycode) { + case 'A': + retval = KEY_HOME; + break; + case 'B': + retval = KEY_END; + break; + case 'C': + retval = CONTROL_RIGHT; + break; + case 'D': + retval = CONTROL_LEFT; + break; #ifndef NANO_TINY - else if (retval == shiftcontrolleft) { - shift_held = TRUE; - return CONTROL_LEFT; - } else if (retval == shiftcontrolright) { - shift_held = TRUE; - return CONTROL_RIGHT; - } else if (retval == shiftcontrolup) { - shift_held = TRUE; - return CONTROL_UP; - } else if (retval == shiftcontroldown) { - shift_held = TRUE; - return CONTROL_DOWN; - } else if (retval == shiftcontrolhome) { - shift_held = TRUE; - return CONTROL_HOME; - } else if (retval == shiftcontrolend) { - shift_held = TRUE; - return CONTROL_END; - } else if (retval == altleft) - return ALT_LEFT; - else if (retval == altright) - return ALT_RIGHT; - else if (retval == altup) - return ALT_UP; - else if (retval == altdown) - return ALT_DOWN; - else if (retval == shiftaltleft) { - shift_held = TRUE; - return KEY_HOME; - } else if (retval == shiftaltright) { - shift_held = TRUE; - return KEY_END; - } else if (retval == shiftaltup) { - shift_held = TRUE; - return KEY_PPAGE; - } else if (retval == shiftaltdown) { - shift_held = TRUE; - return KEY_NPAGE; - } + case 'a': + retval = shiftaltup; + break; + case 'b': + retval = shiftaltdown; + break; + case 'c': + retval = shiftaltright; + break; + case 'd': + retval = shiftaltleft; + break; +#endif + } + double_esc = FALSE; + escapes = 0; + } else if (key_buffer_len == 0) { + if (('0' <= keycode && keycode <= '2' && + byte_digits == 0) || ('0' <= keycode && + keycode <= '9' && byte_digits > 0)) { + /* Two escapes followed by one or more decimal + * digits, and there aren't any other codes + * waiting: byte sequence mode. If the range + * of the byte sequence is limited to 2XX (the + * first digit is between '0' and '2' and the + * others between '0' and '9', interpret it. */ + int byte; + + byte_digits++; + byte = get_byte_kbinput(keycode); + + /* If the decimal byte value is complete, convert it and + * put the obtained byte(s) back into the input buffer. */ + if (byte != ERR) { + char *byte_mb; + int byte_mb_len, *seq, i; + + /* Convert the decimal code to one or two bytes. */ + byte_mb = make_mbchar((long)byte, &byte_mb_len); + + seq = (int *)nmalloc(byte_mb_len * sizeof(int)); + + for (i = 0; i < byte_mb_len; i++) + seq[i] = (unsigned char)byte_mb[i]; + + /* Insert the byte(s) into the input buffer. */ + unget_input(seq, byte_mb_len); + + free(byte_mb); + free(seq); + + byte_digits = 0; + escapes = 0; + } + } else { + if (byte_digits == 0) + /* Two escapes followed by a non-decimal + * digit (or a decimal digit that would + * create a byte sequence greater than 2XX) + * and there aren't any other codes waiting: + * control character sequence mode. */ + retval = get_control_kbinput(keycode); + else { + /* An invalid digit in the middle of a byte + * sequence: reset the byte sequence counter + * and save the code we got as the result. */ + byte_digits = 0; + retval = keycode; + } + escapes = 0; + } + } else if (keycode == '[' && key_buffer_len > 0 && + (('A' <= *key_buffer && *key_buffer <= 'D') || + ('a' <= *key_buffer && *key_buffer <= 'd'))) { + /* An iTerm2/Eterm/rxvt sequence: ^[ ^[ [ X. */ + double_esc = TRUE; + } else { + /* Two escapes followed by a non-escape, and there are more + * codes waiting: combined meta and escape sequence mode. */ + retval = parse_escape_sequence(win, keycode); + meta_key = TRUE; + escapes = 0; + } + break; + case 3: + if (key_buffer_len == 0) + /* Three escapes followed by a non-escape, and no + * other codes are waiting: normal input mode. */ + retval = keycode; + else + /* Three escapes followed by a non-escape, and more + * codes are waiting: combined control character and + * escape sequence mode. First interpret the escape + * sequence, then the result as a control sequence. */ + retval = get_control_kbinput( + parse_escape_sequence(win, keycode)); + escapes = 0; + break; + } + + if (retval == ERR) + return ERR; + + if (retval == controlleft) + return CONTROL_LEFT; + else if (retval == controlright) + return CONTROL_RIGHT; + else if (retval == controlup) + return CONTROL_UP; + else if (retval == controldown) + return CONTROL_DOWN; + else if (retval == controlhome) + return CONTROL_HOME; + else if (retval == controlend) + return CONTROL_END; +#ifndef NANO_TINY + else if (retval == shiftcontrolleft) { + shift_held = TRUE; + return CONTROL_LEFT; + } else if (retval == shiftcontrolright) { + shift_held = TRUE; + return CONTROL_RIGHT; + } else if (retval == shiftcontrolup) { + shift_held = TRUE; + return CONTROL_UP; + } else if (retval == shiftcontroldown) { + shift_held = TRUE; + return CONTROL_DOWN; + } else if (retval == shiftcontrolhome) { + shift_held = TRUE; + return CONTROL_HOME; + } else if (retval == shiftcontrolend) { + shift_held = TRUE; + return CONTROL_END; + } else if (retval == altleft) + return ALT_LEFT; + else if (retval == altright) + return ALT_RIGHT; + else if (retval == altup) + return ALT_UP; + else if (retval == altdown) + return ALT_DOWN; + else if (retval == shiftaltleft) { + shift_held = TRUE; + return KEY_HOME; + } else if (retval == shiftaltright) { + shift_held = TRUE; + return KEY_END; + } else if (retval == shiftaltup) { + shift_held = TRUE; + return KEY_PPAGE; + } else if (retval == shiftaltdown) { + shift_held = TRUE; + return KEY_NPAGE; + } #endif #ifdef __linux__ - /* When not running under X, check for the bare arrow keys whether - * Shift/Ctrl/Alt are being held together with them. */ - unsigned char modifiers = 6; + /* When not running under X, check for the bare arrow keys whether + * Shift/Ctrl/Alt are being held together with them. */ + unsigned char modifiers = 6; - if (console && ioctl(0, TIOCLINUX, &modifiers) >= 0) { + if (console && ioctl(0, TIOCLINUX, &modifiers) >= 0) { #ifndef NANO_TINY - /* Is Shift being held? */ - if (modifiers & 0x01) { - /* A shifted is a back tab. */ - if (retval == TAB_CODE) - return SHIFT_TAB; - shift_held = TRUE; - } + /* Is Shift being held? */ + if (modifiers & 0x01) { + /* A shifted is a back tab. */ + if (retval == TAB_CODE) + return SHIFT_TAB; + shift_held = TRUE; + } #endif - /* Is Ctrl being held? */ - if (modifiers & 0x04) { - if (retval == KEY_UP) - return CONTROL_UP; - else if (retval == KEY_DOWN) - return CONTROL_DOWN; - else if (retval == KEY_LEFT) - return CONTROL_LEFT; - else if (retval == KEY_RIGHT) - return CONTROL_RIGHT; - else if (retval == KEY_HOME) - return CONTROL_HOME; - else if (retval == KEY_END) - return CONTROL_END; - } + /* Is Ctrl being held? */ + if (modifiers & 0x04) { + if (retval == KEY_UP) + return CONTROL_UP; + else if (retval == KEY_DOWN) + return CONTROL_DOWN; + else if (retval == KEY_LEFT) + return CONTROL_LEFT; + else if (retval == KEY_RIGHT) + return CONTROL_RIGHT; + else if (retval == KEY_HOME) + return CONTROL_HOME; + else if (retval == KEY_END) + return CONTROL_END; + } #ifndef NANO_TINY - /* Are both Shift and Alt being held? */ - if ((modifiers & 0x09) == 0x09) { - if (retval == KEY_UP) - return KEY_PPAGE; - else if (retval == KEY_DOWN) - return KEY_NPAGE; - else if (retval == KEY_LEFT) - return KEY_HOME; - else if (retval == KEY_RIGHT) - return KEY_END; - } + /* Are both Shift and Alt being held? */ + if ((modifiers & 0x09) == 0x09) { + if (retval == KEY_UP) + return KEY_PPAGE; + else if (retval == KEY_DOWN) + return KEY_NPAGE; + else if (retval == KEY_LEFT) + return KEY_HOME; + else if (retval == KEY_RIGHT) + return KEY_END; + } #endif - } + } #endif /* __linux__ */ #ifndef NANO_TINY - /* When is pressed while the mark is on, do an indent. */ - if (retval == TAB_CODE && openfile->mark && currmenu == MMAIN) { - const sc *command = first_sc_for(MMAIN, do_indent); + /* When is pressed while the mark is on, do an indent. */ + if (retval == TAB_CODE && openfile->mark && currmenu == MMAIN) { + const sc *command = first_sc_for(MMAIN, do_indent); - meta_key = command->meta; - return command->keycode; - } + meta_key = command->meta; + return command->keycode; + } #endif - switch (retval) { + switch (retval) { #ifdef KEY_SLEFT - /* Slang doesn't support KEY_SLEFT. */ - case KEY_SLEFT: - shift_held = TRUE; - return KEY_LEFT; + /* Slang doesn't support KEY_SLEFT. */ + case KEY_SLEFT: + shift_held = TRUE; + return KEY_LEFT; #endif #ifdef KEY_SRIGHT - /* Slang doesn't support KEY_SRIGHT. */ - case KEY_SRIGHT: - shift_held = TRUE; - return KEY_RIGHT; + /* Slang doesn't support KEY_SRIGHT. */ + case KEY_SRIGHT: + shift_held = TRUE; + return KEY_RIGHT; #endif #ifdef KEY_SR #ifdef KEY_SUP - /* ncurses and Slang don't support KEY_SUP. */ - case KEY_SUP: + /* ncurses and Slang don't support KEY_SUP. */ + case KEY_SUP: #endif - case KEY_SR: /* Scroll backward, on Xfce4-terminal. */ - shift_held = TRUE; - return KEY_UP; + case KEY_SR: /* Scroll backward, on Xfce4-terminal. */ + shift_held = TRUE; + return KEY_UP; #endif #ifdef KEY_SF #ifdef KEY_SDOWN - /* ncurses and Slang don't support KEY_SDOWN. */ - case KEY_SDOWN: + /* ncurses and Slang don't support KEY_SDOWN. */ + case KEY_SDOWN: #endif - case KEY_SF: /* Scroll forward, on Xfce4-terminal. */ - shift_held = TRUE; - return KEY_DOWN; + case KEY_SF: /* Scroll forward, on Xfce4-terminal. */ + shift_held = TRUE; + return KEY_DOWN; #endif #ifdef KEY_SHOME - /* HP-UX 10-11 and Slang don't support KEY_SHOME. */ - case KEY_SHOME: + /* HP-UX 10-11 and Slang don't support KEY_SHOME. */ + case KEY_SHOME: #endif - case SHIFT_HOME: - shift_held = TRUE; - case KEY_A1: /* Home (7) on keypad with NumLock off. */ - return KEY_HOME; + case SHIFT_HOME: + shift_held = TRUE; + case KEY_A1: /* Home (7) on keypad with NumLock off. */ + return KEY_HOME; #ifdef KEY_SEND - /* HP-UX 10-11 and Slang don't support KEY_SEND. */ - case KEY_SEND: + /* HP-UX 10-11 and Slang don't support KEY_SEND. */ + case KEY_SEND: #endif - case SHIFT_END: - shift_held = TRUE; - case KEY_C1: /* End (1) on keypad with NumLock off. */ - return KEY_END; + case SHIFT_END: + shift_held = TRUE; + case KEY_C1: /* End (1) on keypad with NumLock off. */ + return KEY_END; #ifndef NANO_TINY #ifdef KEY_SPREVIOUS - case KEY_SPREVIOUS: + case KEY_SPREVIOUS: #endif - case SHIFT_PAGEUP: /* Fake key, from Shift+Alt+Up. */ - shift_held = TRUE; + case SHIFT_PAGEUP: /* Fake key, from Shift+Alt+Up. */ + shift_held = TRUE; #endif - case KEY_A3: /* PageUp (9) on keypad with NumLock off. */ - return KEY_PPAGE; + case KEY_A3: /* PageUp (9) on keypad with NumLock off. */ + return KEY_PPAGE; #ifndef NANO_TINY #ifdef KEY_SNEXT - case KEY_SNEXT: + case KEY_SNEXT: #endif - case SHIFT_PAGEDOWN: /* Fake key, from Shift+Alt+Down. */ - shift_held = TRUE; + case SHIFT_PAGEDOWN: /* Fake key, from Shift+Alt+Down. */ + shift_held = TRUE; #endif - case KEY_C3: /* PageDown (3) on keypad with NumLock off. */ - return KEY_NPAGE; + case KEY_C3: /* PageDown (3) on keypad with NumLock off. */ + return KEY_NPAGE; #ifdef KEY_SDC - /* Slang doesn't support KEY_SDC. */ - case KEY_SDC: + /* Slang doesn't support KEY_SDC. */ + case KEY_SDC: #endif - case DEL_CODE: - if (ISSET(REBIND_DELETE)) - return the_code_for(do_delete, KEY_DC); - else - return KEY_BACKSPACE; + case DEL_CODE: + if (ISSET(REBIND_DELETE)) + return the_code_for(do_delete, KEY_DC); + else + return KEY_BACKSPACE; #ifdef KEY_SIC - /* Slang doesn't support KEY_SIC. */ - case KEY_SIC: - return the_code_for(do_insertfile_void, KEY_IC); + /* Slang doesn't support KEY_SIC. */ + case KEY_SIC: + return the_code_for(do_insertfile_void, KEY_IC); #endif #ifdef KEY_SBEG - /* Slang doesn't support KEY_SBEG. */ - case KEY_SBEG: + /* Slang doesn't support KEY_SBEG. */ + case KEY_SBEG: #endif #ifdef KEY_BEG - /* Slang doesn't support KEY_BEG. */ - case KEY_BEG: + /* Slang doesn't support KEY_BEG. */ + case KEY_BEG: #endif - case KEY_B2: /* Center (5) on keypad with NumLock off. */ - return ERR; + case KEY_B2: /* Center (5) on keypad with NumLock off. */ + return ERR; #ifdef KEY_CANCEL #ifdef KEY_SCANCEL - /* Slang doesn't support KEY_SCANCEL. */ - case KEY_SCANCEL: + /* Slang doesn't support KEY_SCANCEL. */ + case KEY_SCANCEL: #endif - /* Slang doesn't support KEY_CANCEL. */ - case KEY_CANCEL: - return the_code_for(do_cancel, 0x03); + /* Slang doesn't support KEY_CANCEL. */ + case KEY_CANCEL: + return the_code_for(do_cancel, 0x03); #endif #ifdef KEY_SUSPEND #ifdef KEY_SSUSPEND - /* Slang doesn't support KEY_SSUSPEND. */ - case KEY_SSUSPEND: + /* Slang doesn't support KEY_SSUSPEND. */ + case KEY_SSUSPEND: #endif - /* Slang doesn't support KEY_SUSPEND. */ - case KEY_SUSPEND: - return the_code_for(do_suspend_void, KEY_SUSPEND); + /* Slang doesn't support KEY_SUSPEND. */ + case KEY_SUSPEND: + return the_code_for(do_suspend_void, KEY_SUSPEND); #endif #ifdef KEY_BTAB - /* Slang doesn't support KEY_BTAB. */ - case KEY_BTAB: - return SHIFT_TAB; + /* Slang doesn't support KEY_BTAB. */ + case KEY_BTAB: + return SHIFT_TAB; #endif #ifdef PDCURSES - case KEY_SHIFT_L: - case KEY_SHIFT_R: - case KEY_CONTROL_L: - case KEY_CONTROL_R: - case KEY_ALT_L: - case KEY_ALT_R: - return ERR; + case KEY_SHIFT_L: + case KEY_SHIFT_R: + case KEY_CONTROL_L: + case KEY_CONTROL_R: + case KEY_ALT_L: + case KEY_ALT_R: + return ERR; #endif #ifdef KEY_RESIZE - /* Slang and SunOS 5.7-5.9 don't support KEY_RESIZE. */ - case KEY_RESIZE: + /* Slang and SunOS 5.7-5.9 don't support KEY_RESIZE. */ + case KEY_RESIZE: #endif #if defined(USE_SLANG) && defined(ENABLE_UTF8) - case KEY_BAD: + case KEY_BAD: #endif - case KEY_FLUSH: - return ERR; - } + case KEY_FLUSH: + return ERR; + } - return retval; + return retval; } /* Translate escape sequences, most of which correspond to extended @@ -794,470 +794,470 @@ int parse_kbinput(WINDOW *win) * Assume that Escape has already been read in. */ int convert_sequence(const int *seq, size_t seq_len) { - if (seq_len > 1) { - switch (seq[0]) { - case 'O': - switch (seq[1]) { - case '1': - if (seq_len > 4 && seq[2] == ';') { + if (seq_len > 1) { + switch (seq[0]) { + case 'O': + switch (seq[1]) { + case '1': + if (seq_len > 4 && seq[2] == ';') { - switch (seq[3]) { - case '2': - switch (seq[4]) { - case 'A': /* Esc O 1 ; 2 A == Shift-Up on Terminal. */ - case 'B': /* Esc O 1 ; 2 B == Shift-Down on Terminal. */ - case 'C': /* Esc O 1 ; 2 C == Shift-Right on Terminal. */ - case 'D': /* Esc O 1 ; 2 D == Shift-Left on Terminal. */ - shift_held = TRUE; - return arrow_from_abcd(seq[4]); - case 'P': /* Esc O 1 ; 2 P == F13 on Terminal. */ - return KEY_F(13); - case 'Q': /* Esc O 1 ; 2 Q == F14 on Terminal. */ - return KEY_F(14); - case 'R': /* Esc O 1 ; 2 R == F15 on Terminal. */ - return KEY_F(15); - case 'S': /* Esc O 1 ; 2 S == F16 on Terminal. */ - return KEY_F(16); + switch (seq[3]) { + case '2': + switch (seq[4]) { + case 'A': /* Esc O 1 ; 2 A == Shift-Up on Terminal. */ + case 'B': /* Esc O 1 ; 2 B == Shift-Down on Terminal. */ + case 'C': /* Esc O 1 ; 2 C == Shift-Right on Terminal. */ + case 'D': /* Esc O 1 ; 2 D == Shift-Left on Terminal. */ + shift_held = TRUE; + return arrow_from_abcd(seq[4]); + case 'P': /* Esc O 1 ; 2 P == F13 on Terminal. */ + return KEY_F(13); + case 'Q': /* Esc O 1 ; 2 Q == F14 on Terminal. */ + return KEY_F(14); + case 'R': /* Esc O 1 ; 2 R == F15 on Terminal. */ + return KEY_F(15); + case 'S': /* Esc O 1 ; 2 S == F16 on Terminal. */ + return KEY_F(16); + } + break; + case '5': + switch (seq[4]) { + case 'A': /* Esc O 1 ; 5 A == Ctrl-Up on Terminal. */ + return CONTROL_UP; + case 'B': /* Esc O 1 ; 5 B == Ctrl-Down on Terminal. */ + return CONTROL_DOWN; + case 'C': /* Esc O 1 ; 5 C == Ctrl-Right on Terminal. */ + return CONTROL_RIGHT; + case 'D': /* Esc O 1 ; 5 D == Ctrl-Left on Terminal. */ + return CONTROL_LEFT; + } + break; } - break; - case '5': - switch (seq[4]) { - case 'A': /* Esc O 1 ; 5 A == Ctrl-Up on Terminal. */ - return CONTROL_UP; - case 'B': /* Esc O 1 ; 5 B == Ctrl-Down on Terminal. */ - return CONTROL_DOWN; - case 'C': /* Esc O 1 ; 5 C == Ctrl-Right on Terminal. */ - return CONTROL_RIGHT; - case 'D': /* Esc O 1 ; 5 D == Ctrl-Left on Terminal. */ - return CONTROL_LEFT; + + } + break; + case '2': + if (seq_len >= 3) { + switch (seq[2]) { + case 'P': /* Esc O 2 P == F13 on xterm. */ + return KEY_F(13); + case 'Q': /* Esc O 2 Q == F14 on xterm. */ + return KEY_F(14); + case 'R': /* Esc O 2 R == F15 on xterm. */ + return KEY_F(15); + case 'S': /* Esc O 2 S == F16 on xterm. */ + return KEY_F(16); + } + } + break; + case '5': + if (seq_len >= 3) { + switch (seq[2]) { + case 'A': /* Esc O 5 A == Ctrl-Up on Haiku. */ + return CONTROL_UP; + case 'B': /* Esc O 5 B == Ctrl-Down on Haiku. */ + return CONTROL_DOWN; + case 'C': /* Esc O 5 C == Ctrl-Right on Haiku. */ + return CONTROL_RIGHT; + case 'D': /* Esc O 5 D == Ctrl-Left on Haiku. */ + return CONTROL_LEFT; + } + } + case 'A': /* Esc O A == Up on VT100/VT320/xterm. */ + case 'B': /* Esc O B == Down on VT100/VT320/xterm. */ + case 'C': /* Esc O C == Right on VT100/VT320/xterm. */ + case 'D': /* Esc O D == Left on VT100/VT320/xterm. */ + return arrow_from_abcd(seq[1]); + case 'E': /* Esc O E == Center (5) on numeric keypad + * with NumLock off on xterm. */ + return KEY_B2; + case 'F': /* Esc O F == End on xterm/Terminal. */ + return KEY_END; + case 'H': /* Esc O H == Home on xterm/Terminal. */ + return KEY_HOME; + case 'M': /* Esc O M == Enter on numeric keypad with + * NumLock off on VT100/VT220/VT320/xterm/ + * rxvt/Eterm. */ + return KEY_ENTER; + case 'P': /* Esc O P == F1 on VT100/VT220/VT320/Mach console. */ + return KEY_F(1); + case 'Q': /* Esc O Q == F2 on VT100/VT220/VT320/Mach console. */ + return KEY_F(2); + case 'R': /* Esc O R == F3 on VT100/VT220/VT320/Mach console. */ + return KEY_F(3); + case 'S': /* Esc O S == F4 on VT100/VT220/VT320/Mach console. */ + return KEY_F(4); + case 'T': /* Esc O T == F5 on Mach console. */ + return KEY_F(5); + case 'U': /* Esc O U == F6 on Mach console. */ + return KEY_F(6); + case 'V': /* Esc O V == F7 on Mach console. */ + return KEY_F(7); + case 'W': /* Esc O W == F8 on Mach console. */ + return KEY_F(8); + case 'X': /* Esc O X == F9 on Mach console. */ + return KEY_F(9); + case 'Y': /* Esc O Y == F10 on Mach console. */ + return KEY_F(10); + case 'a': /* Esc O a == Ctrl-Up on rxvt. */ + return CONTROL_UP; + case 'b': /* Esc O b == Ctrl-Down on rxvt. */ + return CONTROL_DOWN; + case 'c': /* Esc O c == Ctrl-Right on rxvt. */ + return CONTROL_RIGHT; + case 'd': /* Esc O d == Ctrl-Left on rxvt. */ + return CONTROL_LEFT; + case 'j': /* Esc O j == '*' on numeric keypad with + * NumLock off on VT100/VT220/VT320/xterm/ + * rxvt/Eterm/Terminal. */ + return '*'; + case 'k': /* Esc O k == '+' on the same. */ + return '+'; + case 'l': /* Esc O l == ',' on the same. */ + return ','; + case 'm': /* Esc O m == '-' on the same. */ + return '-'; + case 'n': /* Esc O n == Delete (.) on the same. */ + return KEY_DC; + case 'o': /* Esc O o == '/' on the same. */ + return '/'; + case 'p': /* Esc O p == Insert (0) on numeric keypad + * with NumLock off on VT100/VT220/VT320/ + * rxvt/Eterm/Terminal. */ + return KEY_IC; + case 'q': /* Esc O q == End (1) on the same. */ + return KEY_END; + case 'r': /* Esc O r == Down (2) on the same. */ + return KEY_DOWN; + case 's': /* Esc O s == PageDown (3) on the same. */ + return KEY_NPAGE; + case 't': /* Esc O t == Left (4) on the same. */ + return KEY_LEFT; + case 'u': /* Esc O u == Center (5) on numeric keypad + * with NumLock off on VT100/VT220/VT320/ + * rxvt/Eterm. */ + return KEY_B2; + case 'v': /* Esc O v == Right (6) on numeric keypad + * with NumLock off on VT100/VT220/VT320/ + * rxvt/Eterm/Terminal. */ + return KEY_RIGHT; + case 'w': /* Esc O w == Home (7) on the same. */ + return KEY_HOME; + case 'x': /* Esc O x == Up (8) on the same. */ + return KEY_UP; + case 'y': /* Esc O y == PageUp (9) on the same. */ + return KEY_PPAGE; + } + break; + case 'o': + switch (seq[1]) { + case 'a': /* Esc o a == Ctrl-Up on Eterm. */ + return CONTROL_UP; + case 'b': /* Esc o b == Ctrl-Down on Eterm. */ + return CONTROL_DOWN; + case 'c': /* Esc o c == Ctrl-Right on Eterm. */ + return CONTROL_RIGHT; + case 'd': /* Esc o d == Ctrl-Left on Eterm. */ + return CONTROL_LEFT; + } + break; + case '[': + switch (seq[1]) { + case '1': + if (seq_len > 3 && seq[3] == '~') { + switch (seq[2]) { + case '1': /* Esc [ 1 1 ~ == F1 on rxvt/Eterm. */ + return KEY_F(1); + case '2': /* Esc [ 1 2 ~ == F2 on rxvt/Eterm. */ + return KEY_F(2); + case '3': /* Esc [ 1 3 ~ == F3 on rxvt/Eterm. */ + return KEY_F(3); + case '4': /* Esc [ 1 4 ~ == F4 on rxvt/Eterm. */ + return KEY_F(4); + case '5': /* Esc [ 1 5 ~ == F5 on xterm/rxvt/Eterm. */ + return KEY_F(5); + case '7': /* Esc [ 1 7 ~ == F6 on VT220/VT320/ + * Linux console/xterm/rxvt/Eterm. */ + return KEY_F(6); + case '8': /* Esc [ 1 8 ~ == F7 on the same. */ + return KEY_F(7); + case '9': /* Esc [ 1 9 ~ == F8 on the same. */ + return KEY_F(8); + } + } else if (seq_len > 4 && seq[2] == ';') { + + switch (seq[3]) { + case '2': + switch (seq[4]) { + case 'A': /* Esc [ 1 ; 2 A == Shift-Up on xterm. */ + case 'B': /* Esc [ 1 ; 2 B == Shift-Down on xterm. */ + case 'C': /* Esc [ 1 ; 2 C == Shift-Right on xterm. */ + case 'D': /* Esc [ 1 ; 2 D == Shift-Left on xterm. */ + shift_held = TRUE; + return arrow_from_abcd(seq[4]); + } + break; +#ifndef NANO_TINY + case '9': /* To accomodate iTerm2 in "xterm mode". */ + case '3': + switch (seq[4]) { + case 'A': /* Esc [ 1 ; 3 A == Alt-Up on xterm. */ + return ALT_UP; + case 'B': /* Esc [ 1 ; 3 B == Alt-Down on xterm. */ + return ALT_DOWN; + case 'C': /* Esc [ 1 ; 3 C == Alt-Right on xterm. */ + return ALT_RIGHT; + case 'D': /* Esc [ 1 ; 3 D == Alt-Left on xterm. */ + return ALT_LEFT; + } + break; + case '4': + /* When the arrow keys are held together with Shift+Meta, + * act as if they are Home/End/PgUp/PgDown with Shift. */ + switch (seq[4]) { + case 'A': /* Esc [ 1 ; 4 A == Shift-Alt-Up on xterm. */ + return SHIFT_PAGEUP; + case 'B': /* Esc [ 1 ; 4 B == Shift-Alt-Down on xterm. */ + return SHIFT_PAGEDOWN; + case 'C': /* Esc [ 1 ; 4 C == Shift-Alt-Right on xterm. */ + return SHIFT_END; + case 'D': /* Esc [ 1 ; 4 D == Shift-Alt-Left on xterm. */ + return SHIFT_HOME; + } + break; +#endif + case '5': + switch (seq[4]) { + case 'A': /* Esc [ 1 ; 5 A == Ctrl-Up on xterm. */ + return CONTROL_UP; + case 'B': /* Esc [ 1 ; 5 B == Ctrl-Down on xterm. */ + return CONTROL_DOWN; + case 'C': /* Esc [ 1 ; 5 C == Ctrl-Right on xterm. */ + return CONTROL_RIGHT; + case 'D': /* Esc [ 1 ; 5 D == Ctrl-Left on xterm. */ + return CONTROL_LEFT; + case 'F': /* Esc [ 1 ; 5 F == Ctrl-End on xterm. */ + return CONTROL_END; + case 'H': /* Esc [ 1 ; 5 H == Ctrl-Home on xterm. */ + return CONTROL_HOME; + } + break; +#ifndef NANO_TINY + case '6': + switch (seq[4]) { + case 'A': /* Esc [ 1 ; 6 A == Shift-Ctrl-Up on xterm. */ + return shiftcontrolup; + case 'B': /* Esc [ 1 ; 6 B == Shift-Ctrl-Down on xterm. */ + return shiftcontroldown; + case 'C': /* Esc [ 1 ; 6 C == Shift-Ctrl-Right on xterm. */ + return shiftcontrolright; + case 'D': /* Esc [ 1 ; 6 D == Shift-Ctrl-Left on xterm. */ + return shiftcontrolleft; + case 'F': /* Esc [ 1 ; 6 F == Shift-Ctrl-End on xterm. */ + return shiftcontrolend; + case 'H': /* Esc [ 1 ; 6 H == Shift-Ctrl-Home on xterm. */ + return shiftcontrolhome; + } + break; +#endif + } + + } else if (seq_len > 2 && seq[2] == '~') + /* Esc [ 1 ~ == Home on VT320/Linux console. */ + return KEY_HOME; + break; + case '2': + if (seq_len > 3 && seq[3] == '~') { + switch (seq[2]) { + case '0': /* Esc [ 2 0 ~ == F9 on VT220/VT320/ + * Linux console/xterm/rxvt/Eterm. */ + return KEY_F(9); + case '1': /* Esc [ 2 1 ~ == F10 on the same. */ + return KEY_F(10); + case '3': /* Esc [ 2 3 ~ == F11 on the same. */ + return KEY_F(11); + case '4': /* Esc [ 2 4 ~ == F12 on the same. */ + return KEY_F(12); + case '5': /* Esc [ 2 5 ~ == F13 on VT220/VT320/ + * Linux console/rxvt/Eterm. */ + return KEY_F(13); + case '6': /* Esc [ 2 6 ~ == F14 on the same. */ + return KEY_F(14); + case '8': /* Esc [ 2 8 ~ == F15 on the same. */ + return KEY_F(15); + case '9': /* Esc [ 2 9 ~ == F16 on the same. */ + return KEY_F(16); + } + } else if (seq_len > 2 && seq[2] == '~') + /* Esc [ 2 ~ == Insert on VT220/VT320/ + * Linux console/xterm/Terminal. */ + return KEY_IC; + break; + case '3': /* Esc [ 3 ~ == Delete on VT220/VT320/ + * Linux console/xterm/Terminal. */ + if (seq_len > 2 && seq[2] == '~') + return KEY_DC; + break; + case '4': /* Esc [ 4 ~ == End on VT220/VT320/ + * Linux console/xterm. */ + if (seq_len > 2 && seq[2] == '~') + return KEY_END; + break; + case '5': /* Esc [ 5 ~ == PageUp on VT220/VT320/ + * Linux console/xterm/Terminal; + * Esc [ 5 ^ == PageUp on Eterm. */ + if (seq_len > 2 && (seq[2] == '~' || seq[2] == '^')) + return KEY_PPAGE; + break; + case '6': /* Esc [ 6 ~ == PageDown on VT220/VT320/ + * Linux console/xterm/Terminal; + * Esc [ 6 ^ == PageDown on Eterm. */ + if (seq_len > 2 && (seq[2] == '~' || seq[2] == '^')) + return KEY_NPAGE; + break; + case '7': /* Esc [ 7 ~ == Home on Eterm/rxvt; + * Esc [ 7 $ == Shift-Home on Eterm/rxvt; + * Esc [ 7 ^ == Control-Home on Eterm/rxvt; + * Esc [ 7 @ == Shift-Control-Home on same. */ + if (seq_len > 2 && seq[2] == '~') + return KEY_HOME; + else if (seq_len > 2 && seq[2] == '$') + return SHIFT_HOME; + else if (seq_len > 2 && seq[2] == '^') + return CONTROL_HOME; +#ifndef NANO_TINY + else if (seq_len > 2 && seq[2] == '@') + return shiftcontrolhome; +#endif + break; + case '8': /* Esc [ 8 ~ == End on Eterm/rxvt; + * Esc [ 8 $ == Shift-End on Eterm/rxvt; + * Esc [ 8 ^ == Control-End on Eterm/rxvt; + * Esc [ 8 @ == Shift-Control-End on same. */ + if (seq_len > 2 && seq[2] == '~') + return KEY_END; + else if (seq_len > 2 && seq[2] == '$') + return SHIFT_END; + else if (seq_len > 2 && seq[2] == '^') + return CONTROL_END; +#ifndef NANO_TINY + else if (seq_len > 2 && seq[2] == '@') + return shiftcontrolend; +#endif + break; + case '9': /* Esc [ 9 == Delete on Mach console. */ + return KEY_DC; + case '@': /* Esc [ @ == Insert on Mach console. */ + return KEY_IC; + case 'A': /* Esc [ A == Up on ANSI/VT220/Linux console/rxvt/ + * FreeBSD console/Mach console/Eterm/Terminal. */ + case 'B': /* Esc [ B == Down on the same. */ + case 'C': /* Esc [ C == Right on the same. */ + case 'D': /* Esc [ D == Left on the same. */ + return arrow_from_abcd(seq[1]); + case 'E': /* Esc [ E == Center (5) on numeric keypad with + * NumLock off on FreeBSD console/Terminal. */ + return KEY_B2; + case 'F': /* Esc [ F == End on FreeBSD console/Eterm. */ + return KEY_END; + case 'G': /* Esc [ G == PageDown on FreeBSD console. */ + return KEY_NPAGE; + case 'H': /* Esc [ H == Home on ANSI/VT220/FreeBSD + * console/Mach console/Eterm. */ + return KEY_HOME; + case 'I': /* Esc [ I == PageUp on FreeBSD console. */ + return KEY_PPAGE; + case 'L': /* Esc [ L == Insert on ANSI/FreeBSD console. */ + return KEY_IC; + case 'M': /* Esc [ M == F1 on FreeBSD console. */ + return KEY_F(1); + case 'N': /* Esc [ N == F2 on FreeBSD console. */ + return KEY_F(2); + case 'O': + if (seq_len > 2) { + switch (seq[2]) { + case 'P': /* Esc [ O P == F1 on xterm. */ + return KEY_F(1); + case 'Q': /* Esc [ O Q == F2 on xterm. */ + return KEY_F(2); + case 'R': /* Esc [ O R == F3 on xterm. */ + return KEY_F(3); + case 'S': /* Esc [ O S == F4 on xterm. */ + return KEY_F(4); + } + } else + /* Esc [ O == F3 on FreeBSD console. */ + return KEY_F(3); + break; + case 'P': /* Esc [ P == F4 on FreeBSD console. */ + return KEY_F(4); + case 'Q': /* Esc [ Q == F5 on FreeBSD console. */ + return KEY_F(5); + case 'R': /* Esc [ R == F6 on FreeBSD console. */ + return KEY_F(6); + case 'S': /* Esc [ S == F7 on FreeBSD console. */ + return KEY_F(7); + case 'T': /* Esc [ T == F8 on FreeBSD console. */ + return KEY_F(8); + case 'U': /* Esc [ U == PageDown on Mach console. */ + return KEY_NPAGE; + case 'V': /* Esc [ V == PageUp on Mach console. */ + return KEY_PPAGE; + case 'W': /* Esc [ W == F11 on FreeBSD console. */ + return KEY_F(11); + case 'X': /* Esc [ X == F12 on FreeBSD console. */ + return KEY_F(12); + case 'Y': /* Esc [ Y == End on Mach console. */ + return KEY_END; + case 'Z': /* Esc [ Z == Shift-Tab on ANSI/Linux console/ + * FreeBSD console/xterm/rxvt/Terminal. */ + return SHIFT_TAB; + case 'a': /* Esc [ a == Shift-Up on rxvt/Eterm. */ + case 'b': /* Esc [ b == Shift-Down on rxvt/Eterm. */ + case 'c': /* Esc [ c == Shift-Right on rxvt/Eterm. */ + case 'd': /* Esc [ d == Shift-Left on rxvt/Eterm. */ + shift_held = TRUE; + return arrow_from_abcd(seq[1]); + case '[': + if (seq_len > 2 ) { + switch (seq[2]) { + case 'A': /* Esc [ [ A == F1 on Linux console. */ + return KEY_F(1); + case 'B': /* Esc [ [ B == F2 on Linux console. */ + return KEY_F(2); + case 'C': /* Esc [ [ C == F3 on Linux console. */ + return KEY_F(3); + case 'D': /* Esc [ [ D == F4 on Linux console. */ + return KEY_F(4); + case 'E': /* Esc [ [ E == F5 on Linux console. */ + return KEY_F(5); + } + } + break; + } + break; } - break; } - } - break; - case '2': - if (seq_len >= 3) { - switch (seq[2]) { - case 'P': /* Esc O 2 P == F13 on xterm. */ - return KEY_F(13); - case 'Q': /* Esc O 2 Q == F14 on xterm. */ - return KEY_F(14); - case 'R': /* Esc O 2 R == F15 on xterm. */ - return KEY_F(15); - case 'S': /* Esc O 2 S == F16 on xterm. */ - return KEY_F(16); - } - } - break; - case '5': - if (seq_len >= 3) { - switch (seq[2]) { - case 'A': /* Esc O 5 A == Ctrl-Up on Haiku. */ - return CONTROL_UP; - case 'B': /* Esc O 5 B == Ctrl-Down on Haiku. */ - return CONTROL_DOWN; - case 'C': /* Esc O 5 C == Ctrl-Right on Haiku. */ - return CONTROL_RIGHT; - case 'D': /* Esc O 5 D == Ctrl-Left on Haiku. */ - return CONTROL_LEFT; - } - } - case 'A': /* Esc O A == Up on VT100/VT320/xterm. */ - case 'B': /* Esc O B == Down on VT100/VT320/xterm. */ - case 'C': /* Esc O C == Right on VT100/VT320/xterm. */ - case 'D': /* Esc O D == Left on VT100/VT320/xterm. */ - return arrow_from_abcd(seq[1]); - case 'E': /* Esc O E == Center (5) on numeric keypad - * with NumLock off on xterm. */ - return KEY_B2; - case 'F': /* Esc O F == End on xterm/Terminal. */ - return KEY_END; - case 'H': /* Esc O H == Home on xterm/Terminal. */ - return KEY_HOME; - case 'M': /* Esc O M == Enter on numeric keypad with - * NumLock off on VT100/VT220/VT320/xterm/ - * rxvt/Eterm. */ - return KEY_ENTER; - case 'P': /* Esc O P == F1 on VT100/VT220/VT320/Mach console. */ - return KEY_F(1); - case 'Q': /* Esc O Q == F2 on VT100/VT220/VT320/Mach console. */ - return KEY_F(2); - case 'R': /* Esc O R == F3 on VT100/VT220/VT320/Mach console. */ - return KEY_F(3); - case 'S': /* Esc O S == F4 on VT100/VT220/VT320/Mach console. */ - return KEY_F(4); - case 'T': /* Esc O T == F5 on Mach console. */ - return KEY_F(5); - case 'U': /* Esc O U == F6 on Mach console. */ - return KEY_F(6); - case 'V': /* Esc O V == F7 on Mach console. */ - return KEY_F(7); - case 'W': /* Esc O W == F8 on Mach console. */ - return KEY_F(8); - case 'X': /* Esc O X == F9 on Mach console. */ - return KEY_F(9); - case 'Y': /* Esc O Y == F10 on Mach console. */ - return KEY_F(10); - case 'a': /* Esc O a == Ctrl-Up on rxvt. */ - return CONTROL_UP; - case 'b': /* Esc O b == Ctrl-Down on rxvt. */ - return CONTROL_DOWN; - case 'c': /* Esc O c == Ctrl-Right on rxvt. */ - return CONTROL_RIGHT; - case 'd': /* Esc O d == Ctrl-Left on rxvt. */ - return CONTROL_LEFT; - case 'j': /* Esc O j == '*' on numeric keypad with - * NumLock off on VT100/VT220/VT320/xterm/ - * rxvt/Eterm/Terminal. */ - return '*'; - case 'k': /* Esc O k == '+' on the same. */ - return '+'; - case 'l': /* Esc O l == ',' on the same. */ - return ','; - case 'm': /* Esc O m == '-' on the same. */ - return '-'; - case 'n': /* Esc O n == Delete (.) on the same. */ - return KEY_DC; - case 'o': /* Esc O o == '/' on the same. */ - return '/'; - case 'p': /* Esc O p == Insert (0) on numeric keypad - * with NumLock off on VT100/VT220/VT320/ - * rxvt/Eterm/Terminal. */ - return KEY_IC; - case 'q': /* Esc O q == End (1) on the same. */ - return KEY_END; - case 'r': /* Esc O r == Down (2) on the same. */ - return KEY_DOWN; - case 's': /* Esc O s == PageDown (3) on the same. */ - return KEY_NPAGE; - case 't': /* Esc O t == Left (4) on the same. */ - return KEY_LEFT; - case 'u': /* Esc O u == Center (5) on numeric keypad - * with NumLock off on VT100/VT220/VT320/ - * rxvt/Eterm. */ - return KEY_B2; - case 'v': /* Esc O v == Right (6) on numeric keypad - * with NumLock off on VT100/VT220/VT320/ - * rxvt/Eterm/Terminal. */ - return KEY_RIGHT; - case 'w': /* Esc O w == Home (7) on the same. */ - return KEY_HOME; - case 'x': /* Esc O x == Up (8) on the same. */ - return KEY_UP; - case 'y': /* Esc O y == PageUp (9) on the same. */ - return KEY_PPAGE; - } - break; - case 'o': - switch (seq[1]) { - case 'a': /* Esc o a == Ctrl-Up on Eterm. */ - return CONTROL_UP; - case 'b': /* Esc o b == Ctrl-Down on Eterm. */ - return CONTROL_DOWN; - case 'c': /* Esc o c == Ctrl-Right on Eterm. */ - return CONTROL_RIGHT; - case 'd': /* Esc o d == Ctrl-Left on Eterm. */ - return CONTROL_LEFT; - } - break; - case '[': - switch (seq[1]) { - case '1': - if (seq_len > 3 && seq[3] == '~') { - switch (seq[2]) { - case '1': /* Esc [ 1 1 ~ == F1 on rxvt/Eterm. */ - return KEY_F(1); - case '2': /* Esc [ 1 2 ~ == F2 on rxvt/Eterm. */ - return KEY_F(2); - case '3': /* Esc [ 1 3 ~ == F3 on rxvt/Eterm. */ - return KEY_F(3); - case '4': /* Esc [ 1 4 ~ == F4 on rxvt/Eterm. */ - return KEY_F(4); - case '5': /* Esc [ 1 5 ~ == F5 on xterm/rxvt/Eterm. */ - return KEY_F(5); - case '7': /* Esc [ 1 7 ~ == F6 on VT220/VT320/ - * Linux console/xterm/rxvt/Eterm. */ - return KEY_F(6); - case '8': /* Esc [ 1 8 ~ == F7 on the same. */ - return KEY_F(7); - case '9': /* Esc [ 1 9 ~ == F8 on the same. */ - return KEY_F(8); - } - } else if (seq_len > 4 && seq[2] == ';') { - - switch (seq[3]) { - case '2': - switch (seq[4]) { - case 'A': /* Esc [ 1 ; 2 A == Shift-Up on xterm. */ - case 'B': /* Esc [ 1 ; 2 B == Shift-Down on xterm. */ - case 'C': /* Esc [ 1 ; 2 C == Shift-Right on xterm. */ - case 'D': /* Esc [ 1 ; 2 D == Shift-Left on xterm. */ - shift_held = TRUE; - return arrow_from_abcd(seq[4]); - } - break; -#ifndef NANO_TINY - case '9': /* To accomodate iTerm2 in "xterm mode". */ - case '3': - switch (seq[4]) { - case 'A': /* Esc [ 1 ; 3 A == Alt-Up on xterm. */ - return ALT_UP; - case 'B': /* Esc [ 1 ; 3 B == Alt-Down on xterm. */ - return ALT_DOWN; - case 'C': /* Esc [ 1 ; 3 C == Alt-Right on xterm. */ - return ALT_RIGHT; - case 'D': /* Esc [ 1 ; 3 D == Alt-Left on xterm. */ - return ALT_LEFT; - } - break; - case '4': - /* When the arrow keys are held together with Shift+Meta, - * act as if they are Home/End/PgUp/PgDown with Shift. */ - switch (seq[4]) { - case 'A': /* Esc [ 1 ; 4 A == Shift-Alt-Up on xterm. */ - return SHIFT_PAGEUP; - case 'B': /* Esc [ 1 ; 4 B == Shift-Alt-Down on xterm. */ - return SHIFT_PAGEDOWN; - case 'C': /* Esc [ 1 ; 4 C == Shift-Alt-Right on xterm. */ - return SHIFT_END; - case 'D': /* Esc [ 1 ; 4 D == Shift-Alt-Left on xterm. */ - return SHIFT_HOME; - } - break; -#endif - case '5': - switch (seq[4]) { - case 'A': /* Esc [ 1 ; 5 A == Ctrl-Up on xterm. */ - return CONTROL_UP; - case 'B': /* Esc [ 1 ; 5 B == Ctrl-Down on xterm. */ - return CONTROL_DOWN; - case 'C': /* Esc [ 1 ; 5 C == Ctrl-Right on xterm. */ - return CONTROL_RIGHT; - case 'D': /* Esc [ 1 ; 5 D == Ctrl-Left on xterm. */ - return CONTROL_LEFT; - case 'F': /* Esc [ 1 ; 5 F == Ctrl-End on xterm. */ - return CONTROL_END; - case 'H': /* Esc [ 1 ; 5 H == Ctrl-Home on xterm. */ - return CONTROL_HOME; - } - break; -#ifndef NANO_TINY - case '6': - switch (seq[4]) { - case 'A': /* Esc [ 1 ; 6 A == Shift-Ctrl-Up on xterm. */ - return shiftcontrolup; - case 'B': /* Esc [ 1 ; 6 B == Shift-Ctrl-Down on xterm. */ - return shiftcontroldown; - case 'C': /* Esc [ 1 ; 6 C == Shift-Ctrl-Right on xterm. */ - return shiftcontrolright; - case 'D': /* Esc [ 1 ; 6 D == Shift-Ctrl-Left on xterm. */ - return shiftcontrolleft; - case 'F': /* Esc [ 1 ; 6 F == Shift-Ctrl-End on xterm. */ - return shiftcontrolend; - case 'H': /* Esc [ 1 ; 6 H == Shift-Ctrl-Home on xterm. */ - return shiftcontrolhome; - } - break; -#endif - } - - } else if (seq_len > 2 && seq[2] == '~') - /* Esc [ 1 ~ == Home on VT320/Linux console. */ - return KEY_HOME; - break; - case '2': - if (seq_len > 3 && seq[3] == '~') { - switch (seq[2]) { - case '0': /* Esc [ 2 0 ~ == F9 on VT220/VT320/ - * Linux console/xterm/rxvt/Eterm. */ - return KEY_F(9); - case '1': /* Esc [ 2 1 ~ == F10 on the same. */ - return KEY_F(10); - case '3': /* Esc [ 2 3 ~ == F11 on the same. */ - return KEY_F(11); - case '4': /* Esc [ 2 4 ~ == F12 on the same. */ - return KEY_F(12); - case '5': /* Esc [ 2 5 ~ == F13 on VT220/VT320/ - * Linux console/rxvt/Eterm. */ - return KEY_F(13); - case '6': /* Esc [ 2 6 ~ == F14 on the same. */ - return KEY_F(14); - case '8': /* Esc [ 2 8 ~ == F15 on the same. */ - return KEY_F(15); - case '9': /* Esc [ 2 9 ~ == F16 on the same. */ - return KEY_F(16); - } - } else if (seq_len > 2 && seq[2] == '~') - /* Esc [ 2 ~ == Insert on VT220/VT320/ - * Linux console/xterm/Terminal. */ - return KEY_IC; - break; - case '3': /* Esc [ 3 ~ == Delete on VT220/VT320/ - * Linux console/xterm/Terminal. */ - if (seq_len > 2 && seq[2] == '~') - return KEY_DC; - break; - case '4': /* Esc [ 4 ~ == End on VT220/VT320/ - * Linux console/xterm. */ - if (seq_len > 2 && seq[2] == '~') - return KEY_END; - break; - case '5': /* Esc [ 5 ~ == PageUp on VT220/VT320/ - * Linux console/xterm/Terminal; - * Esc [ 5 ^ == PageUp on Eterm. */ - if (seq_len > 2 && (seq[2] == '~' || seq[2] == '^')) - return KEY_PPAGE; - break; - case '6': /* Esc [ 6 ~ == PageDown on VT220/VT320/ - * Linux console/xterm/Terminal; - * Esc [ 6 ^ == PageDown on Eterm. */ - if (seq_len > 2 && (seq[2] == '~' || seq[2] == '^')) - return KEY_NPAGE; - break; - case '7': /* Esc [ 7 ~ == Home on Eterm/rxvt; - * Esc [ 7 $ == Shift-Home on Eterm/rxvt; - * Esc [ 7 ^ == Control-Home on Eterm/rxvt; - * Esc [ 7 @ == Shift-Control-Home on same. */ - if (seq_len > 2 && seq[2] == '~') - return KEY_HOME; - else if (seq_len > 2 && seq[2] == '$') - return SHIFT_HOME; - else if (seq_len > 2 && seq[2] == '^') - return CONTROL_HOME; -#ifndef NANO_TINY - else if (seq_len > 2 && seq[2] == '@') - return shiftcontrolhome; -#endif - break; - case '8': /* Esc [ 8 ~ == End on Eterm/rxvt; - * Esc [ 8 $ == Shift-End on Eterm/rxvt; - * Esc [ 8 ^ == Control-End on Eterm/rxvt; - * Esc [ 8 @ == Shift-Control-End on same. */ - if (seq_len > 2 && seq[2] == '~') - return KEY_END; - else if (seq_len > 2 && seq[2] == '$') - return SHIFT_END; - else if (seq_len > 2 && seq[2] == '^') - return CONTROL_END; -#ifndef NANO_TINY - else if (seq_len > 2 && seq[2] == '@') - return shiftcontrolend; -#endif - break; - case '9': /* Esc [ 9 == Delete on Mach console. */ - return KEY_DC; - case '@': /* Esc [ @ == Insert on Mach console. */ - return KEY_IC; - case 'A': /* Esc [ A == Up on ANSI/VT220/Linux console/rxvt/ - * FreeBSD console/Mach console/Eterm/Terminal. */ - case 'B': /* Esc [ B == Down on the same. */ - case 'C': /* Esc [ C == Right on the same. */ - case 'D': /* Esc [ D == Left on the same. */ - return arrow_from_abcd(seq[1]); - case 'E': /* Esc [ E == Center (5) on numeric keypad with - * NumLock off on FreeBSD console/Terminal. */ - return KEY_B2; - case 'F': /* Esc [ F == End on FreeBSD console/Eterm. */ - return KEY_END; - case 'G': /* Esc [ G == PageDown on FreeBSD console. */ - return KEY_NPAGE; - case 'H': /* Esc [ H == Home on ANSI/VT220/FreeBSD - * console/Mach console/Eterm. */ - return KEY_HOME; - case 'I': /* Esc [ I == PageUp on FreeBSD console. */ - return KEY_PPAGE; - case 'L': /* Esc [ L == Insert on ANSI/FreeBSD console. */ - return KEY_IC; - case 'M': /* Esc [ M == F1 on FreeBSD console. */ - return KEY_F(1); - case 'N': /* Esc [ N == F2 on FreeBSD console. */ - return KEY_F(2); - case 'O': - if (seq_len > 2) { - switch (seq[2]) { - case 'P': /* Esc [ O P == F1 on xterm. */ - return KEY_F(1); - case 'Q': /* Esc [ O Q == F2 on xterm. */ - return KEY_F(2); - case 'R': /* Esc [ O R == F3 on xterm. */ - return KEY_F(3); - case 'S': /* Esc [ O S == F4 on xterm. */ - return KEY_F(4); - } - } else - /* Esc [ O == F3 on FreeBSD console. */ - return KEY_F(3); - break; - case 'P': /* Esc [ P == F4 on FreeBSD console. */ - return KEY_F(4); - case 'Q': /* Esc [ Q == F5 on FreeBSD console. */ - return KEY_F(5); - case 'R': /* Esc [ R == F6 on FreeBSD console. */ - return KEY_F(6); - case 'S': /* Esc [ S == F7 on FreeBSD console. */ - return KEY_F(7); - case 'T': /* Esc [ T == F8 on FreeBSD console. */ - return KEY_F(8); - case 'U': /* Esc [ U == PageDown on Mach console. */ - return KEY_NPAGE; - case 'V': /* Esc [ V == PageUp on Mach console. */ - return KEY_PPAGE; - case 'W': /* Esc [ W == F11 on FreeBSD console. */ - return KEY_F(11); - case 'X': /* Esc [ X == F12 on FreeBSD console. */ - return KEY_F(12); - case 'Y': /* Esc [ Y == End on Mach console. */ - return KEY_END; - case 'Z': /* Esc [ Z == Shift-Tab on ANSI/Linux console/ - * FreeBSD console/xterm/rxvt/Terminal. */ - return SHIFT_TAB; - case 'a': /* Esc [ a == Shift-Up on rxvt/Eterm. */ - case 'b': /* Esc [ b == Shift-Down on rxvt/Eterm. */ - case 'c': /* Esc [ c == Shift-Right on rxvt/Eterm. */ - case 'd': /* Esc [ d == Shift-Left on rxvt/Eterm. */ - shift_held = TRUE; - return arrow_from_abcd(seq[1]); - case '[': - if (seq_len > 2 ) { - switch (seq[2]) { - case 'A': /* Esc [ [ A == F1 on Linux console. */ - return KEY_F(1); - case 'B': /* Esc [ [ B == F2 on Linux console. */ - return KEY_F(2); - case 'C': /* Esc [ [ C == F3 on Linux console. */ - return KEY_F(3); - case 'D': /* Esc [ [ D == F4 on Linux console. */ - return KEY_F(4); - case 'E': /* Esc [ [ E == F5 on Linux console. */ - return KEY_F(5); - } - } - break; - } - break; - } - } - - return ERR; + return ERR; } /* Return the equivalent arrow-key value for the first four letters * in the alphabet, common to many escape sequences. */ int arrow_from_abcd(int kbinput) { - switch (tolower(kbinput)) { - case 'a': - return KEY_UP; - case 'b': - return KEY_DOWN; - case 'c': - return KEY_RIGHT; - case 'd': - return KEY_LEFT; - default: - return ERR; - } + switch (tolower(kbinput)) { + case 'a': + return KEY_UP; + case 'b': + return KEY_DOWN; + case 'c': + return KEY_RIGHT; + case 'd': + return KEY_LEFT; + default: + return ERR; + } } /* Interpret the escape sequence in the keystroke buffer, the first @@ -1265,102 +1265,102 @@ int arrow_from_abcd(int kbinput) * isn't empty, and that the initial escape has already been read in. */ int parse_escape_sequence(WINDOW *win, int kbinput) { - int retval, *sequence, length; + int retval, *sequence, length; - /* Put back the non-escape character, get the complete escape - * sequence, translate the sequence into its corresponding key - * value, and save that as the result. */ - unget_input(&kbinput, 1); - length = key_buffer_len; - sequence = get_input(NULL, length); - retval = convert_sequence(sequence, length); - free(sequence); + /* Put back the non-escape character, get the complete escape + * sequence, translate the sequence into its corresponding key + * value, and save that as the result. */ + unget_input(&kbinput, 1); + length = key_buffer_len; + sequence = get_input(NULL, length); + retval = convert_sequence(sequence, length); + free(sequence); - /* If we got an unrecognized escape sequence, notify the user. */ - if (retval == ERR && win == edit) { - /* TRANSLATORS: This refers to a sequence of escape codes - * (from the keyboard) that nano does not recogize. */ - statusline(ALERT, _("Unknown sequence")); - suppress_cursorpos = FALSE; - lastmessage = HUSH; - if (currmenu == MMAIN) { - place_the_cursor(); - curs_set(1); + /* If we got an unrecognized escape sequence, notify the user. */ + if (retval == ERR && win == edit) { + /* TRANSLATORS: This refers to a sequence of escape codes + * (from the keyboard) that nano does not recogize. */ + statusline(ALERT, _("Unknown sequence")); + suppress_cursorpos = FALSE; + lastmessage = HUSH; + if (currmenu == MMAIN) { + place_the_cursor(); + curs_set(1); + } } - } - return retval; + return retval; } /* Translate a byte sequence: turn a three-digit decimal number (from * 000 to 255) into its corresponding byte value. */ int get_byte_kbinput(int kbinput) { - static int byte_digits = 0, byte = 0; - int retval = ERR; + static int byte_digits = 0, byte = 0; + int retval = ERR; - /* Increment the byte digit counter. */ - byte_digits++; + /* Increment the byte digit counter. */ + byte_digits++; - switch (byte_digits) { - case 1: - /* First digit: This must be from zero to two. Put it in - * the 100's position of the byte sequence holder. */ - if ('0' <= kbinput && kbinput <= '2') - byte = (kbinput - '0') * 100; - else - /* This isn't the start of a byte sequence. Return this - * character as the result. */ - retval = kbinput; - break; - case 2: - /* Second digit: This must be from zero to five if the first - * was two, and may be any decimal value if the first was - * zero or one. Put it in the 10's position of the byte - * sequence holder. */ - if (('0' <= kbinput && kbinput <= '5') || (byte < 200 && - '6' <= kbinput && kbinput <= '9')) - byte += (kbinput - '0') * 10; - else - /* This isn't the second digit of a byte sequence. - * Return this character as the result. */ - retval = kbinput; - break; - case 3: - /* Third digit: This must be from zero to five if the first - * 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'; - /* The byte sequence is complete. */ - retval = byte; - } else - /* This isn't the third digit of a byte sequence. - * Return this character as the result. */ - retval = kbinput; - break; - default: - /* If there are more than three digits, return this - * character as the result. (Maybe we should produce an - * error instead?) */ - retval = kbinput; - break; - } + switch (byte_digits) { + case 1: + /* First digit: This must be from zero to two. Put it in + * the 100's position of the byte sequence holder. */ + if ('0' <= kbinput && kbinput <= '2') + byte = (kbinput - '0') * 100; + else + /* This isn't the start of a byte sequence. Return this + * character as the result. */ + retval = kbinput; + break; + case 2: + /* Second digit: This must be from zero to five if the first + * was two, and may be any decimal value if the first was + * zero or one. Put it in the 10's position of the byte + * sequence holder. */ + if (('0' <= kbinput && kbinput <= '5') || (byte < 200 && + '6' <= kbinput && kbinput <= '9')) + byte += (kbinput - '0') * 10; + else + /* This isn't the second digit of a byte sequence. + * Return this character as the result. */ + retval = kbinput; + break; + case 3: + /* Third digit: This must be from zero to five if the first + * 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'; + /* The byte sequence is complete. */ + retval = byte; + } else + /* This isn't the third digit of a byte sequence. + * Return this character as the result. */ + retval = kbinput; + break; + default: + /* If there are more than three digits, return this + * character as the result. (Maybe we should produce an + * error instead?) */ + retval = kbinput; + break; + } - /* If we have a result, reset the byte digit counter and the byte - * sequence holder. */ - if (retval != ERR) { - byte_digits = 0; - byte = 0; - } + /* If we have a result, reset the byte digit counter and the byte + * sequence holder. */ + if (retval != ERR) { + byte_digits = 0; + byte = 0; + } #ifdef DEBUG - fprintf(stderr, "get_byte_kbinput(): kbinput = %d, byte_digits = %d, byte = %d, retval = %d\n", kbinput, byte_digits, byte, retval); + fprintf(stderr, "get_byte_kbinput(): kbinput = %d, byte_digits = %d, byte = %d, retval = %d\n", kbinput, byte_digits, byte, retval); #endif - return retval; + return retval; } #ifdef ENABLE_UTF8 @@ -1368,15 +1368,15 @@ int get_byte_kbinput(int kbinput) * by factor and add the result to uni, and return ERR to signify okay. */ long add_unicode_digit(int kbinput, long factor, long *uni) { - if ('0' <= kbinput && kbinput <= '9') - *uni += (kbinput - '0') * factor; - else if ('a' <= tolower(kbinput) && tolower(kbinput) <= 'f') - *uni += (tolower(kbinput) - 'a' + 10) * factor; - else - /* The character isn't hexadecimal; give it as the result. */ - return (long)kbinput; + if ('0' <= kbinput && kbinput <= '9') + *uni += (kbinput - '0') * factor; + else if ('a' <= tolower(kbinput) && tolower(kbinput) <= 'f') + *uni += (tolower(kbinput) - 'a' + 10) * factor; + else + /* The character isn't hexadecimal; give it as the result. */ + return (long)kbinput; - return ERR; + return ERR; } /* Translate a Unicode sequence: turn a six-digit hexadecimal number @@ -1384,68 +1384,68 @@ long add_unicode_digit(int kbinput, long factor, long *uni) * multibyte value. */ long get_unicode_kbinput(WINDOW *win, int kbinput) { - static int uni_digits = 0; - static long uni = 0; - long retval = ERR; + static int uni_digits = 0; + static long uni = 0; + long retval = ERR; - /* Increment the Unicode digit counter. */ - uni_digits++; + /* Increment the Unicode digit counter. */ + uni_digits++; - switch (uni_digits) { - case 1: - /* The first digit must be zero or one. Put it in the - * 0x100000's position of the Unicode sequence holder. - * Otherwise, return the character itself as the result. */ - if (kbinput == '0' || kbinput == '1') - uni = (kbinput - '0') * 0x100000; - else - retval = kbinput; - break; - case 2: - /* The second digit must be zero if the first was one, but - * may be any hexadecimal value if the first was zero. */ - if (kbinput == '0' || uni == 0) - retval = add_unicode_digit(kbinput, 0x10000, &uni); - else - retval = kbinput; - break; - case 3: - /* Later digits may be any hexadecimal value. */ - retval = add_unicode_digit(kbinput, 0x1000, &uni); - break; - case 4: - retval = add_unicode_digit(kbinput, 0x100, &uni); - break; - case 5: - retval = add_unicode_digit(kbinput, 0x10, &uni); - break; - case 6: - retval = add_unicode_digit(kbinput, 0x1, &uni); - /* If also the sixth digit was a valid hexadecimal value, then - * the Unicode sequence is complete, so return it. */ - if (retval == ERR) - retval = uni; - break; - } + switch (uni_digits) { + case 1: + /* The first digit must be zero or one. Put it in the + * 0x100000's position of the Unicode sequence holder. + * Otherwise, return the character itself as the result. */ + if (kbinput == '0' || kbinput == '1') + uni = (kbinput - '0') * 0x100000; + else + retval = kbinput; + break; + case 2: + /* The second digit must be zero if the first was one, but + * may be any hexadecimal value if the first was zero. */ + if (kbinput == '0' || uni == 0) + retval = add_unicode_digit(kbinput, 0x10000, &uni); + else + retval = kbinput; + break; + case 3: + /* Later digits may be any hexadecimal value. */ + retval = add_unicode_digit(kbinput, 0x1000, &uni); + break; + case 4: + retval = add_unicode_digit(kbinput, 0x100, &uni); + break; + case 5: + retval = add_unicode_digit(kbinput, 0x10, &uni); + break; + case 6: + retval = add_unicode_digit(kbinput, 0x1, &uni); + /* If also the sixth digit was a valid hexadecimal value, then + * the Unicode sequence is complete, so return it. */ + if (retval == ERR) + retval = uni; + break; + } - /* Show feedback only when editing, not when at a prompt. */ - if (retval == ERR && win == edit) { - char partial[7] = "......"; + /* Show feedback only when editing, not when at a prompt. */ + if (retval == ERR && win == edit) { + char partial[7] = "......"; - /* Construct the partial result, right-padding it with dots. */ - snprintf(partial, uni_digits + 1, "%06lX", uni); - partial[uni_digits] = '.'; + /* Construct the partial result, right-padding it with dots. */ + snprintf(partial, uni_digits + 1, "%06lX", uni); + partial[uni_digits] = '.'; - /* TRANSLATORS: This is shown while a six-digit hexadecimal - * Unicode character code (%s) is being typed in. */ - statusline(HUSH, _("Unicode Input: %s"), partial); - } + /* TRANSLATORS: This is shown while a six-digit hexadecimal + * Unicode character code (%s) is being typed in. */ + statusline(HUSH, _("Unicode Input: %s"), partial); + } - /* If we have an end result, reset the Unicode digit counter. */ - if (retval != ERR) - uni_digits = 0; + /* If we have an end result, reset the Unicode digit counter. */ + if (retval != ERR) + uni_digits = 0; - return retval; + return retval; } #endif /* ENABLE_UTF8 */ @@ -1453,72 +1453,72 @@ long get_unicode_kbinput(WINDOW *win, int kbinput) * character into its corresponding control character. */ int get_control_kbinput(int kbinput) { - int retval; + int retval; - /* Ctrl-Space (Ctrl-2, Ctrl-@, Ctrl-`) */ - if (kbinput == ' ' || kbinput == '2') - retval = 0; - /* Ctrl-/ (Ctrl-7, Ctrl-_) */ - else if (kbinput == '/') - retval = 31; - /* Ctrl-3 (Ctrl-[, Esc) to Ctrl-7 (Ctrl-/, Ctrl-_) */ - else if ('3' <= kbinput && kbinput <= '7') - retval = kbinput - 24; - /* Ctrl-8 (Ctrl-?) */ - else if (kbinput == '8' || kbinput == '?') - retval = DEL_CODE; - /* Ctrl-@ (Ctrl-Space, Ctrl-2, Ctrl-`) to Ctrl-_ (Ctrl-/, Ctrl-7) */ - else if ('@' <= kbinput && kbinput <= '_') - retval = kbinput - '@'; - /* Ctrl-` (Ctrl-2, Ctrl-Space, Ctrl-@) to Ctrl-~ (Ctrl-6, Ctrl-^) */ - else if ('`' <= kbinput && kbinput <= '~') - retval = kbinput - '`'; - else - retval = kbinput; + /* Ctrl-Space (Ctrl-2, Ctrl-@, Ctrl-`) */ + if (kbinput == ' ' || kbinput == '2') + retval = 0; + /* Ctrl-/ (Ctrl-7, Ctrl-_) */ + else if (kbinput == '/') + retval = 31; + /* Ctrl-3 (Ctrl-[, Esc) to Ctrl-7 (Ctrl-/, Ctrl-_) */ + else if ('3' <= kbinput && kbinput <= '7') + retval = kbinput - 24; + /* Ctrl-8 (Ctrl-?) */ + else if (kbinput == '8' || kbinput == '?') + retval = DEL_CODE; + /* Ctrl-@ (Ctrl-Space, Ctrl-2, Ctrl-`) to Ctrl-_ (Ctrl-/, Ctrl-7) */ + else if ('@' <= kbinput && kbinput <= '_') + retval = kbinput - '@'; + /* Ctrl-` (Ctrl-2, Ctrl-Space, Ctrl-@) to Ctrl-~ (Ctrl-6, Ctrl-^) */ + else if ('`' <= kbinput && kbinput <= '~') + retval = kbinput - '`'; + else + retval = kbinput; #ifdef DEBUG - fprintf(stderr, "get_control_kbinput(): kbinput = %d, retval = %d\n", kbinput, retval); + fprintf(stderr, "get_control_kbinput(): kbinput = %d, retval = %d\n", kbinput, retval); #endif - return retval; + return retval; } /* Read in a stream of characters verbatim, and return the length of the * string in kbinput_len. Assume nodelay(win) is FALSE. */ int *get_verbatim_kbinput(WINDOW *win, size_t *kbinput_len) { - int *retval; + int *retval; - /* Turn off flow control characters if necessary so that we can type - * them in verbatim, and turn the keypad off if necessary so that we - * don't get extended keypad values. */ - if (ISSET(PRESERVE)) - disable_flow_control(); - if (!ISSET(REBIND_KEYPAD)) - keypad(win, FALSE); + /* Turn off flow control characters if necessary so that we can type + * them in verbatim, and turn the keypad off if necessary so that we + * don't get extended keypad values. */ + if (ISSET(PRESERVE)) + disable_flow_control(); + if (!ISSET(REBIND_KEYPAD)) + keypad(win, FALSE); - /* Read in one keycode, or one or two escapes. */ - retval = parse_verbatim_kbinput(win, kbinput_len); + /* Read in one keycode, or one or two escapes. */ + retval = parse_verbatim_kbinput(win, kbinput_len); - /* If the code is invalid in the current mode, discard it. */ - if (retval != NULL && ((*retval == '\n' && as_an_at) || - (*retval == '\0' && !as_an_at))) { - *kbinput_len = 0; - beep(); - } + /* If the code is invalid in the current mode, discard it. */ + if (retval != NULL && ((*retval == '\n' && as_an_at) || + (*retval == '\0' && !as_an_at))) { + *kbinput_len = 0; + beep(); + } - /* Turn flow control characters back on if necessary and turn the - * keypad back on if necessary now that we're done. */ - if (ISSET(PRESERVE)) - enable_flow_control(); - /* Use the global window pointers, because a resize may have freed - * the data that the win parameter points to. */ - if (!ISSET(REBIND_KEYPAD)) { - keypad(edit, TRUE); - keypad(bottomwin, TRUE); - } + /* Turn flow control characters back on if necessary and turn the + * keypad back on if necessary now that we're done. */ + if (ISSET(PRESERVE)) + enable_flow_control(); + /* Use the global window pointers, because a resize may have freed + * the data that the win parameter points to. */ + if (!ISSET(REBIND_KEYPAD)) { + keypad(edit, TRUE); + keypad(bottomwin, TRUE); + } - return retval; + return retval; } /* Read in one control character (or an iTerm/Eterm/rxvt double Escape), @@ -1527,72 +1527,72 @@ int *get_verbatim_kbinput(WINDOW *win, size_t *kbinput_len) * multibyte sequence), or 2 (for an iTerm/Eterm/rxvt double Escape). */ int *parse_verbatim_kbinput(WINDOW *win, size_t *count) { - int *kbinput; + int *kbinput; - reveal_cursor = TRUE; + reveal_cursor = TRUE; - /* Read in the first code. */ - while ((kbinput = get_input(win, 1)) == NULL) - ; + /* Read in the first code. */ + while ((kbinput = get_input(win, 1)) == NULL) + ; #ifndef NANO_TINY - /* When the window was resized, abort and return nothing. */ - if (*kbinput == KEY_WINCH) { - free(kbinput); - *count = 0; - return NULL; - } + /* When the window was resized, abort and return nothing. */ + if (*kbinput == KEY_WINCH) { + free(kbinput); + *count = 0; + return NULL; + } #endif - *count = 1; + *count = 1; #ifdef ENABLE_UTF8 - if (using_utf8()) { - /* Check whether the first code is a valid starter digit: 0 or 1. */ - long unicode = get_unicode_kbinput(win, *kbinput); + if (using_utf8()) { + /* Check whether the first code is a valid starter digit: 0 or 1. */ + long unicode = get_unicode_kbinput(win, *kbinput); - /* If the first code isn't the digit 0 nor 1, put it back. */ - if (unicode != ERR) - unget_input(kbinput, 1); - /* Otherwise, continue reading in digits until we have a complete - * Unicode value, and put back the corresponding byte(s). */ - else { - char *multibyte; - int onebyte, i; + /* If the first code isn't the digit 0 nor 1, put it back. */ + if (unicode != ERR) + unget_input(kbinput, 1); + /* Otherwise, continue reading in digits until we have a complete + * Unicode value, and put back the corresponding byte(s). */ + else { + char *multibyte; + int onebyte, i; - reveal_cursor = FALSE; + reveal_cursor = FALSE; - while (unicode == ERR) { - free(kbinput); - while ((kbinput = get_input(win, 1)) == NULL) - ; - unicode = get_unicode_kbinput(win, *kbinput); - } + while (unicode == ERR) { + free(kbinput); + while ((kbinput = get_input(win, 1)) == NULL) + ; + unicode = get_unicode_kbinput(win, *kbinput); + } - /* Convert the Unicode value to a multibyte sequence. */ - multibyte = make_mbchar(unicode, (int *)count); + /* Convert the Unicode value to a multibyte sequence. */ + multibyte = make_mbchar(unicode, (int *)count); - /* Insert the multibyte sequence into the input buffer. */ - for (i = *count; i > 0 ; i--) { - onebyte = (unsigned char)multibyte[i - 1]; - unget_input(&onebyte, 1); - } + /* Insert the multibyte sequence into the input buffer. */ + for (i = *count; i > 0 ; i--) { + onebyte = (unsigned char)multibyte[i - 1]; + unget_input(&onebyte, 1); + } - free(multibyte); - } - } else + free(multibyte); + } + } else #endif /* ENABLE_UTF8 */ - /* Put back the first code. */ - unget_input(kbinput, 1); + /* Put back the first code. */ + unget_input(kbinput, 1); - free(kbinput); + free(kbinput); - /* If this is an iTerm/Eterm/rxvt double escape, take both Escapes. */ - if (key_buffer_len > 3 && *key_buffer == ESC_CODE && - key_buffer[1] == ESC_CODE && key_buffer[2] == '[') - *count = 2; + /* If this is an iTerm/Eterm/rxvt double escape, take both Escapes. */ + if (key_buffer_len > 3 && *key_buffer == ESC_CODE && + key_buffer[1] == ESC_CODE && key_buffer[2] == '[') + *count = 2; - return get_input(NULL, *count); + return get_input(NULL, *count); } #ifdef ENABLE_MOUSE @@ -1612,135 +1612,135 @@ int *parse_verbatim_kbinput(WINDOW *win, size_t *count) * read in. */ int get_mouseinput(int *mouse_x, int *mouse_y, bool allow_shortcuts) { - MEVENT mevent; - bool in_bottomwin; - subnfunc *f; + MEVENT mevent; + bool in_bottomwin; + subnfunc *f; - *mouse_x = -1; - *mouse_y = -1; + *mouse_x = -1; + *mouse_y = -1; - /* First, get the actual mouse event. */ - if (getmouse(&mevent) == ERR) - return -1; + /* First, get the actual mouse event. */ + if (getmouse(&mevent) == ERR) + return -1; - /* Save the screen coordinates where the mouse event took place. */ - *mouse_x = mevent.x - margin; - *mouse_y = mevent.y; + /* Save the screen coordinates where the mouse event took place. */ + *mouse_x = mevent.x - margin; + *mouse_y = mevent.y; - in_bottomwin = wenclose(bottomwin, *mouse_y, *mouse_x); + in_bottomwin = wenclose(bottomwin, *mouse_y, *mouse_x); - /* Handle releases/clicks of the first mouse button. */ - if (mevent.bstate & (BUTTON1_RELEASED | BUTTON1_CLICKED)) { - /* If we're allowing shortcuts, the current shortcut list is - * being displayed on the last two lines of the screen, and the - * first mouse button was released on/clicked inside it, we need - * to figure out which shortcut was released on/clicked and put - * back the equivalent keystroke(s) for it. */ - if (allow_shortcuts && !ISSET(NO_HELP) && in_bottomwin) { - int i; - /* The width of all the shortcuts, except for the last - * two, in the shortcut list in bottomwin. */ - int j; - /* The calculated index number of the clicked item. */ - size_t number; - /* The number of available shortcuts in the current menu. */ + /* Handle releases/clicks of the first mouse button. */ + if (mevent.bstate & (BUTTON1_RELEASED | BUTTON1_CLICKED)) { + /* If we're allowing shortcuts, the current shortcut list is + * being displayed on the last two lines of the screen, and the + * first mouse button was released on/clicked inside it, we need + * to figure out which shortcut was released on/clicked and put + * back the equivalent keystroke(s) for it. */ + if (allow_shortcuts && !ISSET(NO_HELP) && in_bottomwin) { + int i; + /* The width of all the shortcuts, except for the last + * two, in the shortcut list in bottomwin. */ + int j; + /* The calculated index number of the clicked item. */ + size_t number; + /* The number of available shortcuts in the current menu. */ - /* Translate the mouse event coordinates so that they're - * relative to bottomwin. */ - wmouse_trafo(bottomwin, mouse_y, mouse_x, FALSE); + /* Translate the mouse event coordinates so that they're + * relative to bottomwin. */ + wmouse_trafo(bottomwin, mouse_y, mouse_x, FALSE); - /* Handle releases/clicks of the first mouse button on the - * statusbar elsewhere. */ - if (*mouse_y == 0) { - /* Restore the untranslated mouse event coordinates, so - * that they're relative to the entire screen again. */ - *mouse_x = mevent.x - margin; - *mouse_y = mevent.y; + /* Handle releases/clicks of the first mouse button on the + * statusbar elsewhere. */ + if (*mouse_y == 0) { + /* Restore the untranslated mouse event coordinates, so + * that they're relative to the entire screen again. */ + *mouse_x = mevent.x - margin; + *mouse_y = mevent.y; - return 0; - } + return 0; + } - /* Determine how many shortcuts are being shown. */ - number = length_of_list(currmenu); + /* Determine how many shortcuts are being shown. */ + number = length_of_list(currmenu); - if (number > MAIN_VISIBLE) - number = MAIN_VISIBLE; + if (number > MAIN_VISIBLE) + number = MAIN_VISIBLE; - /* Calculate the width of all of the shortcuts in the list - * except for the last two, which are longer by (COLS % i) - * columns so as to not waste space. */ - if (number < 2) - i = COLS / (MAIN_VISIBLE / 2); - else - i = COLS / ((number / 2) + (number % 2)); + /* Calculate the width of all of the shortcuts in the list + * except for the last two, which are longer by (COLS % i) + * columns so as to not waste space. */ + if (number < 2) + i = COLS / (MAIN_VISIBLE / 2); + else + i = COLS / ((number / 2) + (number % 2)); - /* Calculate the one-based index in the shortcut list. */ - j = (*mouse_x / i) * 2 + *mouse_y; + /* Calculate the one-based index in the shortcut list. */ + j = (*mouse_x / i) * 2 + *mouse_y; - /* Adjust the index if we hit the last two wider ones. */ - if ((j > number) && (*mouse_x % i < COLS % i)) - j -= 2; + /* Adjust the index if we hit the last two wider ones. */ + if ((j > number) && (*mouse_x % i < COLS % i)) + j -= 2; - /* Ignore releases/clicks of the first mouse button beyond - * the last shortcut. */ - if (j > number) - return 2; + /* Ignore releases/clicks of the first mouse button beyond + * the last shortcut. */ + if (j > number) + return 2; - /* 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; - if (first_sc_for(currmenu, f->scfunc) == NULL) - continue; - /* Tick off an actually shown shortcut. */ - j -= 1; - if (j == 0) - break; - } + /* 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; + if (first_sc_for(currmenu, f->scfunc) == NULL) + continue; + /* Tick off an actually shown shortcut. */ + j -= 1; + if (j == 0) + break; + } - /* And put the corresponding key into the keyboard buffer. */ - if (f != NULL) { - const sc *s = first_sc_for(currmenu, f->scfunc); - unget_kbinput(s->keycode, s->meta); - } - return 1; - } else - /* Handle releases/clicks of the first mouse button that - * aren't on the current shortcut list elsewhere. */ - return 0; - } + /* And put the corresponding key into the keyboard buffer. */ + if (f != NULL) { + const sc *s = first_sc_for(currmenu, f->scfunc); + unget_kbinput(s->keycode, s->meta); + } + return 1; + } else + /* Handle releases/clicks of the first mouse button that + * aren't on the current shortcut list elsewhere. */ + return 0; + } #if NCURSES_MOUSE_VERSION >= 2 - /* Handle presses of the fourth mouse button (upward rolls of the - * mouse wheel) and presses of the fifth mouse button (downward - * rolls of the mouse wheel) . */ - else if (mevent.bstate & (BUTTON4_PRESSED | BUTTON5_PRESSED)) { - bool in_edit = wenclose(edit, *mouse_y, *mouse_x); + /* Handle presses of the fourth mouse button (upward rolls of the + * mouse wheel) and presses of the fifth mouse button (downward + * rolls of the mouse wheel) . */ + else if (mevent.bstate & (BUTTON4_PRESSED | BUTTON5_PRESSED)) { + bool in_edit = wenclose(edit, *mouse_y, *mouse_x); - if (in_bottomwin) - /* Translate the mouse event coordinates so that they're - * relative to bottomwin. */ - wmouse_trafo(bottomwin, mouse_y, mouse_x, FALSE); + if (in_bottomwin) + /* Translate the mouse event coordinates so that they're + * relative to bottomwin. */ + wmouse_trafo(bottomwin, mouse_y, mouse_x, FALSE); - if (in_edit || (in_bottomwin && *mouse_y == 0)) { - int i; + if (in_edit || (in_bottomwin && *mouse_y == 0)) { + int i; - /* One roll of the mouse wheel should move three lines. */ - for (i = 0; i < 3; i++) - unget_kbinput((mevent.bstate & BUTTON4_PRESSED) ? - KEY_UP : KEY_DOWN, FALSE); + /* One roll of the mouse wheel should move three lines. */ + for (i = 0; i < 3; i++) + unget_kbinput((mevent.bstate & BUTTON4_PRESSED) ? + KEY_UP : KEY_DOWN, FALSE); - return 1; - } else - /* Ignore presses of the fourth mouse button and presses of - * the fifth mouse buttons that aren't on the edit window or - * the statusbar. */ - return 2; - } + return 1; + } else + /* Ignore presses of the fourth mouse button and presses of + * the fifth mouse buttons that aren't on the edit window or + * the statusbar. */ + return 2; + } #endif - /* Ignore all other mouse events. */ - return 2; + /* Ignore all other mouse events. */ + return 2; } #endif /* ENABLE_MOUSE */ @@ -1750,81 +1750,81 @@ int get_mouseinput(int *mouse_x, int *mouse_y, bool allow_shortcuts) * the given sequence. */ const sc *get_shortcut(int *kbinput) { - sc *s; + sc *s; #ifdef DEBUG - fprintf(stderr, "after parsing: kbinput = %d, meta_key = %s -- ", - *kbinput, meta_key ? "TRUE" : "FALSE"); + fprintf(stderr, "after parsing: kbinput = %d, meta_key = %s -- ", + *kbinput, meta_key ? "TRUE" : "FALSE"); #endif - /* Plain characters cannot be shortcuts, so just skip those. */ - if (!meta_key && (*kbinput & 0x7F) >= 0x20 && *kbinput <= 0xFF) - return NULL; + /* Plain characters cannot be shortcuts, so just skip those. */ + if (!meta_key && (*kbinput & 0x7F) >= 0x20 && *kbinput <= 0xFF) + return NULL; - for (s = sclist; s != NULL; s = s->next) { - if ((s->menus & currmenu) && *kbinput == s->keycode && - meta_key == s->meta) { + for (s = sclist; s != NULL; s = s->next) { + if ((s->menus & currmenu) && *kbinput == s->keycode && + meta_key == s->meta) { #ifdef DEBUG - fprintf (stderr, "matched seq '%s' (menu is %x from %x)\n", - s->keystr, currmenu, s->menus); + fprintf (stderr, "matched seq '%s' (menu is %x from %x)\n", + s->keystr, currmenu, s->menus); #endif - return s; + return s; + } } - } #ifdef DEBUG - fprintf (stderr, "matched nothing\n"); + fprintf (stderr, "matched nothing\n"); #endif - return NULL; + return NULL; } /* Move to (x, y) in win, and display a line of n spaces with the * current attributes. */ void blank_row(WINDOW *win, int y, int x, int n) { - wmove(win, y, x); + wmove(win, y, x); - for (; n > 0; n--) - waddch(win, ' '); + for (; n > 0; n--) + waddch(win, ' '); } /* Blank the first line of the top portion of the window. */ void blank_titlebar(void) { - blank_row(topwin, 0, 0, COLS); + blank_row(topwin, 0, 0, COLS); } /* Blank all the lines of the middle portion of the window, i.e. the * edit window. */ void blank_edit(void) { - int row; + int row; - for (row = 0; row < editwinrows; row++) - blank_row(edit, row, 0, COLS); + for (row = 0; row < editwinrows; row++) + blank_row(edit, row, 0, COLS); } /* Blank the first line of the bottom portion of the window. */ void blank_statusbar(void) { - blank_row(bottomwin, 0, 0, COLS); + blank_row(bottomwin, 0, 0, COLS); } /* Wipe the status bar clean and include this in the next screen update. */ void wipe_statusbar(void) { - blank_row(bottomwin, 0, 0, COLS); - wnoutrefresh(bottomwin); + blank_row(bottomwin, 0, 0, COLS); + wnoutrefresh(bottomwin); } /* If the NO_HELP flag isn't set, blank the last two lines of the bottom * portion of the window. */ void blank_bottombars(void) { - if (!ISSET(NO_HELP) && LINES > 4) { - blank_row(bottomwin, 1, 0, COLS); - blank_row(bottomwin, 2, 0, COLS); - } + if (!ISSET(NO_HELP) && LINES > 4) { + blank_row(bottomwin, 1, 0, COLS); + blank_row(bottomwin, 2, 0, COLS); + } } /* Check if the number of keystrokes needed to blank the statusbar has @@ -1832,21 +1832,21 @@ void blank_bottombars(void) * position display is on and we are in the editing screen. */ void check_statusblank(void) { - if (statusblank == 0) - return; + if (statusblank == 0) + return; - statusblank--; + statusblank--; - /* When editing and 'constantshow' is active, skip the blanking. */ - if (currmenu == MMAIN && ISSET(CONSTANT_SHOW)) - return; + /* When editing and 'constantshow' is active, skip the blanking. */ + if (currmenu == MMAIN && ISSET(CONSTANT_SHOW)) + return; - if (statusblank == 0) - wipe_statusbar(); + if (statusblank == 0) + wipe_statusbar(); - /* If the subwindows overlap, make sure to show the edit window now. */ - if (LINES == 1) - edit_refresh(); + /* If the subwindows overlap, make sure to show the edit window now. */ + if (LINES == 1) + edit_refresh(); } /* Convert buf into a string that can be displayed on screen. The caller @@ -1857,155 +1857,155 @@ void check_statusblank(void) * "$" at the beginning or end of the line if it's too long. */ char *display_string(const char *buf, size_t column, size_t span, bool isdata) { - size_t start_index = actual_x(buf, column); - /* The index of the first character that the caller wishes to show. */ - size_t start_col = strnlenpt(buf, start_index); - /* The actual column where that first character starts. */ - char *converted; - /* The expanded string we will return. */ - size_t index = 0; - /* Current position in converted. */ - size_t beyond = column + span; - /* The column number just beyond the last shown character. */ + size_t start_index = actual_x(buf, column); + /* The index of the first character that the caller wishes to show. */ + size_t start_col = strnlenpt(buf, start_index); + /* The actual column where that first character starts. */ + char *converted; + /* The expanded string we will return. */ + size_t index = 0; + /* Current position in converted. */ + size_t beyond = column + span; + /* The column number just beyond the last shown character. */ #ifdef USING_OLD_NCURSES - seen_wide = FALSE; + seen_wide = FALSE; #endif - buf += start_index; + buf += start_index; - /* Allocate enough space for converting the relevant part of the line. */ - converted = charalloc(strlen(buf) * (MAXCHARLEN + tabsize) + 1); + /* Allocate enough space for converting the relevant part of the line. */ + converted = charalloc(strlen(buf) * (MAXCHARLEN + tabsize) + 1); - /* If the first character starts before the left edge, or would be - * overwritten by a "$" token, then show placeholders instead. */ - if (*buf != '\0' && *buf != '\t' && (start_col < column || - (start_col > 0 && isdata && !ISSET(SOFTWRAP)))) { - if (is_cntrl_mbchar(buf)) { - if (start_col < column) { - converted[index++] = control_mbrep(buf, isdata); - column++; - buf += parse_mbchar(buf, NULL, NULL); - } - } + /* If the first character starts before the left edge, or would be + * overwritten by a "$" token, then show placeholders instead. */ + if (*buf != '\0' && *buf != '\t' && (start_col < column || + (start_col > 0 && isdata && !ISSET(SOFTWRAP)))) { + if (is_cntrl_mbchar(buf)) { + if (start_col < column) { + converted[index++] = control_mbrep(buf, isdata); + column++; + buf += parse_mbchar(buf, NULL, NULL); + } + } #ifdef ENABLE_UTF8 - else if (mbwidth(buf) == 2) { - if (start_col == column) { - converted[index++] = ' '; - column++; - } + else if (mbwidth(buf) == 2) { + if (start_col == column) { + converted[index++] = ' '; + column++; + } - /* Display the right half of a two-column character as '<'. */ - converted[index++] = '<'; - column++; - buf += parse_mbchar(buf, NULL, NULL); - } + /* Display the right half of a two-column character as '<'. */ + converted[index++] = '<'; + column++; + buf += parse_mbchar(buf, NULL, NULL); + } #endif - } + } - while (*buf != '\0' && (column < beyond || mbwidth(buf) == 0)) { - int charlength, charwidth = 1; + while (*buf != '\0' && (column < beyond || mbwidth(buf) == 0)) { + int charlength, charwidth = 1; - if (*buf == ' ') { - /* Show a space as a visible character, or as a space. */ + if (*buf == ' ') { + /* Show a space as a visible character, or as a space. */ #ifndef NANO_TINY - if (ISSET(WHITESPACE_DISPLAY)) { - int i = whitespace_len[0]; + if (ISSET(WHITESPACE_DISPLAY)) { + int i = whitespace_len[0]; - while (i < whitespace_len[0] + whitespace_len[1]) - converted[index++] = whitespace[i++]; - } else + while (i < whitespace_len[0] + whitespace_len[1]) + converted[index++] = whitespace[i++]; + } else #endif - converted[index++] = ' '; - column++; - buf++; - continue; - } else if (*buf == '\t') { - /* Show a tab as a visible character, or as as a space. */ + converted[index++] = ' '; + column++; + buf++; + continue; + } else if (*buf == '\t') { + /* Show a tab as a visible character, or as as a space. */ #ifndef NANO_TINY - if (ISSET(WHITESPACE_DISPLAY) && (index > 0 || !isdata || - !ISSET(SOFTWRAP) || column % tabsize == 0 || - column == start_col)) { - int i = 0; + if (ISSET(WHITESPACE_DISPLAY) && (index > 0 || !isdata || + !ISSET(SOFTWRAP) || column % tabsize == 0 || + column == start_col)) { + int i = 0; - while (i < whitespace_len[0]) - converted[index++] = whitespace[i++]; - } else + while (i < whitespace_len[0]) + converted[index++] = whitespace[i++]; + } else #endif - converted[index++] = ' '; - column++; - /* Fill the tab up with the required number of spaces. */ - while (column % tabsize != 0 && column < beyond) { - converted[index++] = ' '; - column++; - } - buf++; - continue; - } + converted[index++] = ' '; + column++; + /* Fill the tab up with the required number of spaces. */ + while (column % tabsize != 0 && column < beyond) { + converted[index++] = ' '; + column++; + } + buf++; + continue; + } - charlength = length_of_char(buf, &charwidth); + charlength = length_of_char(buf, &charwidth); - /* If buf contains a control character, represent it. */ - if (is_cntrl_mbchar(buf)) { - converted[index++] = '^'; - converted[index++] = control_mbrep(buf, isdata); - column += 2; - buf += charlength; - continue; - } + /* If buf contains a control character, represent it. */ + if (is_cntrl_mbchar(buf)) { + converted[index++] = '^'; + converted[index++] = control_mbrep(buf, isdata); + column += 2; + buf += charlength; + continue; + } - /* If buf contains a valid non-control character, simply copy it. */ - if (charlength > 0) { - for (; charlength > 0; charlength--) - converted[index++] = *(buf++); + /* If buf contains a valid non-control character, simply copy it. */ + if (charlength > 0) { + for (; charlength > 0; charlength--) + converted[index++] = *(buf++); - column += charwidth; + column += charwidth; #ifdef USING_OLD_NCURSES - if (charwidth > 1) - seen_wide = TRUE; + if (charwidth > 1) + seen_wide = TRUE; #endif - continue; + continue; + } + + /* Represent an invalid sequence with the Replacement Character. */ + converted[index++] = '\xEF'; + converted[index++] = '\xBF'; + converted[index++] = '\xBD'; + column++; + buf++; + + /* For invalid codepoints, skip extra bytes. */ + if (charlength < -1) + buf += charlength + 7; } - /* Represent an invalid sequence with the Replacement Character. */ - converted[index++] = '\xEF'; - converted[index++] = '\xBF'; - converted[index++] = '\xBD'; - column++; - buf++; - - /* For invalid codepoints, skip extra bytes. */ - if (charlength < -1) - buf += charlength + 7; - } - - /* If there is more text than can be shown, make room for the $ or >. */ - if (*buf != '\0' && (column > beyond || (isdata && !ISSET(SOFTWRAP)))) { - index = move_mbleft(converted, index); + /* If there is more text than can be shown, make room for the $ or >. */ + if (*buf != '\0' && (column > beyond || (isdata && !ISSET(SOFTWRAP)))) { + index = move_mbleft(converted, index); #ifdef ENABLE_UTF8 - /* Display the left half of a two-column character as '>'. */ - if (mbwidth(converted + index) == 2) - converted[index++] = '>'; + /* Display the left half of a two-column character as '>'. */ + if (mbwidth(converted + index) == 2) + converted[index++] = '>'; #endif - } + } - /* Null-terminate the converted string. */ - converted[index] = '\0'; + /* Null-terminate the converted string. */ + converted[index] = '\0'; - return converted; + return converted; } /* Determine the sequence number of the given buffer in the circular list. */ int buffer_number(openfilestruct *buffer) { - int count = 1; + int count = 1; - while (buffer != firstfile) { - buffer = buffer->prev; - count++; - } + while (buffer != firstfile) { + buffer = buffer->prev; + count++; + } - return count; + return count; } /* If path is NULL, we're in normal editing mode, so display the current @@ -2015,144 +2015,144 @@ int buffer_number(openfilestruct *buffer) * directory or the title of help text, that is: whatever is in path. */ void titlebar(const char *path) { - size_t verlen, prefixlen, pathlen, statelen; - /* The width of the different titlebar elements, in columns. */ - size_t pluglen = 0; - /* The width that "Modified" would take up. */ - size_t offset = 0; - /* The position at which the center part of the titlebar starts. */ - const char *upperleft = ""; - /* What is shown in the top left corner. */ - const char *prefix = ""; - /* What is shown before the path -- "DIR:" or nothing. */ - const char *state = ""; - /* The state of the current buffer -- "Modified", "View", or "". */ - char *caption; - /* The presentable form of the pathname. */ - char *indicator = NULL; - /* The buffer sequence number plus buffer count. */ + size_t verlen, prefixlen, pathlen, statelen; + /* The width of the different titlebar elements, in columns. */ + size_t pluglen = 0; + /* The width that "Modified" would take up. */ + size_t offset = 0; + /* The position at which the center part of the titlebar starts. */ + const char *upperleft = ""; + /* What is shown in the top left corner. */ + const char *prefix = ""; + /* What is shown before the path -- "DIR:" or nothing. */ + const char *state = ""; + /* The state of the current buffer -- "Modified", "View", or "". */ + char *caption; + /* The presentable form of the pathname. */ + char *indicator = NULL; + /* The buffer sequence number plus buffer count. */ - /* If the screen is too small, there is no titlebar. */ - if (topwin == NULL) - return; + /* If the screen is too small, there is no titlebar. */ + if (topwin == NULL) + return; - wattron(topwin, interface_color_pair[TITLE_BAR]); + wattron(topwin, interface_color_pair[TITLE_BAR]); - blank_titlebar(); - as_an_at = FALSE; + blank_titlebar(); + as_an_at = FALSE; - /* Do as Pico: if there is not enough width available for all items, - * first sacrifice the version string, then eat up the side spaces, - * then sacrifice the prefix, and only then start dottifying. */ + /* Do as Pico: if there is not enough width available for all items, + * first sacrifice the version string, then eat up the side spaces, + * then sacrifice the prefix, and only then start dottifying. */ - /* Figure out the path, prefix and state strings. */ + /* Figure out the path, prefix and state strings. */ #ifdef ENABLE_BROWSER - if (!inhelp && path != NULL) - prefix = _("DIR:"); - else -#endif - if (!inhelp) { - /* If there are/were multiple buffers, show which out of how many. */ - if (more_than_one) { - indicator = charalloc(24); - sprintf(indicator, "[%i/%i]", buffer_number(openfile), - buffer_number(firstfile->prev)); - upperleft = indicator; - } else - upperleft = BRANDING; - - if (openfile->filename[0] == '\0') - path = _("New Buffer"); + if (!inhelp && path != NULL) + prefix = _("DIR:"); else - path = openfile->filename; +#endif + if (!inhelp) { + /* If there are/were multiple buffers, show which out of how many. */ + if (more_than_one) { + indicator = charalloc(24); + sprintf(indicator, "[%i/%i]", buffer_number(openfile), + buffer_number(firstfile->prev)); + upperleft = indicator; + } else + upperleft = BRANDING; - if (openfile->modified) - state = _("Modified"); - else if (ISSET(VIEW_MODE)) - state = _("View"); + if (openfile->filename[0] == '\0') + path = _("New Buffer"); + else + path = openfile->filename; - pluglen = strlenpt(_("Modified")) + 1; - } + if (openfile->modified) + state = _("Modified"); + else if (ISSET(VIEW_MODE)) + state = _("View"); - /* Determine the widths of the four elements, including their padding. */ - verlen = strlenpt(upperleft) + 3; - prefixlen = strlenpt(prefix); - if (prefixlen > 0) - prefixlen++; - pathlen = strlenpt(path); - statelen = strlenpt(state) + 2; - if (statelen > 2) { - pathlen++; - pluglen = 0; - } - - /* Only print the version message when there is room for it. */ - if (verlen + prefixlen + pathlen + pluglen + statelen <= COLS) - mvwaddstr(topwin, 0, 2, upperleft); - else { - verlen = 2; - /* If things don't fit yet, give up the placeholder. */ - if (verlen + prefixlen + pathlen + pluglen + statelen > COLS) - pluglen = 0; - /* If things still don't fit, give up the side spaces. */ - if (verlen + prefixlen + pathlen + pluglen + statelen > COLS) { - verlen = 0; - statelen -= 2; + pluglen = strlenpt(_("Modified")) + 1; } - } - free(indicator); - - /* If we have side spaces left, center the path name. */ - if (verlen > 0) - offset = verlen + (COLS - (verlen + pluglen + statelen) - - (prefixlen + pathlen)) / 2; - - /* Only print the prefix when there is room for it. */ - if (verlen + prefixlen + pathlen + pluglen + statelen <= COLS) { - mvwaddstr(topwin, 0, offset, prefix); + /* Determine the widths of the four elements, including their padding. */ + verlen = strlenpt(upperleft) + 3; + prefixlen = strlenpt(prefix); if (prefixlen > 0) - waddstr(topwin, " "); - } else - wmove(topwin, 0, offset); + prefixlen++; + pathlen = strlenpt(path); + statelen = strlenpt(state) + 2; + if (statelen > 2) { + pathlen++; + pluglen = 0; + } - /* Print the full path if there's room; otherwise, dottify it. */ - if (pathlen + pluglen + statelen <= COLS) { - caption = display_string(path, 0, pathlen, FALSE); - waddstr(topwin, caption); - free(caption); - } else if (5 + statelen <= COLS) { - waddstr(topwin, "..."); - caption = display_string(path, 3 + pathlen - COLS + statelen, - COLS - statelen, FALSE); - waddstr(topwin, caption); - free(caption); - } + /* Only print the version message when there is room for it. */ + if (verlen + prefixlen + pathlen + pluglen + statelen <= COLS) + mvwaddstr(topwin, 0, 2, upperleft); + else { + verlen = 2; + /* If things don't fit yet, give up the placeholder. */ + if (verlen + prefixlen + pathlen + pluglen + statelen > COLS) + pluglen = 0; + /* If things still don't fit, give up the side spaces. */ + if (verlen + prefixlen + pathlen + pluglen + statelen > COLS) { + verlen = 0; + statelen -= 2; + } + } - /* Right-align the state if there's room; otherwise, trim it. */ - if (statelen > 0 && statelen <= COLS) - mvwaddstr(topwin, 0, COLS - statelen, state); - else if (statelen > 0) - mvwaddnstr(topwin, 0, 0, state, actual_x(state, COLS)); + free(indicator); - wattroff(topwin, interface_color_pair[TITLE_BAR]); + /* If we have side spaces left, center the path name. */ + if (verlen > 0) + offset = verlen + (COLS - (verlen + pluglen + statelen) - + (prefixlen + pathlen)) / 2; - wrefresh(topwin); + /* Only print the prefix when there is room for it. */ + if (verlen + prefixlen + pathlen + pluglen + statelen <= COLS) { + mvwaddstr(topwin, 0, offset, prefix); + if (prefixlen > 0) + waddstr(topwin, " "); + } else + wmove(topwin, 0, offset); + + /* Print the full path if there's room; otherwise, dottify it. */ + if (pathlen + pluglen + statelen <= COLS) { + caption = display_string(path, 0, pathlen, FALSE); + waddstr(topwin, caption); + free(caption); + } else if (5 + statelen <= COLS) { + waddstr(topwin, "..."); + caption = display_string(path, 3 + pathlen - COLS + statelen, + COLS - statelen, FALSE); + waddstr(topwin, caption); + free(caption); + } + + /* Right-align the state if there's room; otherwise, trim it. */ + if (statelen > 0 && statelen <= COLS) + mvwaddstr(topwin, 0, COLS - statelen, state); + else if (statelen > 0) + mvwaddnstr(topwin, 0, 0, state, actual_x(state, COLS)); + + wattroff(topwin, interface_color_pair[TITLE_BAR]); + + wrefresh(topwin); } /* Display a normal message on the statusbar, quietly. */ void statusbar(const char *msg) { - statusline(HUSH, msg); + statusline(HUSH, msg); } /* Warn the user on the statusbar and pause for a moment, so that the * message can be noticed and read. */ void warn_and_shortly_pause(const char *msg) { - statusbar(msg); - beep(); - napms(1800); + statusbar(msg); + beep(); + napms(1800); } /* Display a message on the statusbar, and set suppress_cursorpos to @@ -2160,142 +2160,142 @@ void warn_and_shortly_pause(const char *msg) * constant cursor position display is on. */ void statusline(message_type importance, const char *msg, ...) { - va_list ap; - static int alerts = 0; - char *compound, *message; - size_t start_col; - bool bracketed; + va_list ap; + static int alerts = 0; + char *compound, *message; + size_t start_col; + bool bracketed; #ifndef NANO_TINY - bool old_whitespace = ISSET(WHITESPACE_DISPLAY); + bool old_whitespace = ISSET(WHITESPACE_DISPLAY); - UNSET(WHITESPACE_DISPLAY); + UNSET(WHITESPACE_DISPLAY); #endif - va_start(ap, msg); + va_start(ap, msg); - /* Curses mode is turned off. If we use wmove() now, it will muck - * up the terminal settings. So we just use vfprintf(). */ - if (isendwin()) { - vfprintf(stderr, msg, ap); + /* Curses mode is turned off. If we use wmove() now, it will muck + * up the terminal settings. So we just use vfprintf(). */ + if (isendwin()) { + vfprintf(stderr, msg, ap); + va_end(ap); + return; + } + + /* If there already was an alert message, ignore lesser ones. */ + if ((lastmessage == ALERT && importance != ALERT) || + (lastmessage == MILD && importance == HUSH)) + return; + + /* If the ALERT status has been reset, reset the counter. */ + if (lastmessage == HUSH) + alerts = 0; + + /* Shortly pause after each of the first three alert messages, + * to give the user time to read them. */ + if (lastmessage == ALERT && alerts < 4 && !ISSET(NO_PAUSES)) + napms(1200); + + if (importance == ALERT) { + if (++alerts > 3 && !ISSET(NO_PAUSES)) + msg = _("Further warnings were suppressed"); + else if (alerts < 4) + beep(); + } + + lastmessage = importance; + + blank_statusbar(); + + /* Construct the message out of all the arguments. */ + compound = charalloc(MAXCHARLEN * (COLS + 1)); + vsnprintf(compound, MAXCHARLEN * (COLS + 1), msg, ap); va_end(ap); - return; - } + message = display_string(compound, 0, COLS, FALSE); + free(compound); - /* If there already was an alert message, ignore lesser ones. */ - if ((lastmessage == ALERT && importance != ALERT) || - (lastmessage == MILD && importance == HUSH)) - return; + start_col = (COLS - strlenpt(message)) / 2; + bracketed = (start_col > 1); - /* If the ALERT status has been reset, reset the counter. */ - if (lastmessage == HUSH) - alerts = 0; + wmove(bottomwin, 0, (bracketed ? start_col - 2 : start_col)); + wattron(bottomwin, interface_color_pair[STATUS_BAR]); + if (bracketed) + waddstr(bottomwin, "[ "); + waddstr(bottomwin, message); + free(message); + if (bracketed) + waddstr(bottomwin, " ]"); + wattroff(bottomwin, interface_color_pair[STATUS_BAR]); - /* Shortly pause after each of the first three alert messages, - * to give the user time to read them. */ - if (lastmessage == ALERT && alerts < 4 && !ISSET(NO_PAUSES)) - napms(1200); + /* Defeat a VTE/Konsole bug, where the cursor can go off-limits. */ + if (ISSET(CONSTANT_SHOW) && ISSET(NO_HELP)) + wmove(bottomwin, 0, 0); - if (importance == ALERT) { - if (++alerts > 3 && !ISSET(NO_PAUSES)) - msg = _("Further warnings were suppressed"); - else if (alerts < 4) - beep(); - } + /* Push the message to the screen straightaway. */ + wrefresh(bottomwin); - lastmessage = importance; - - blank_statusbar(); - - /* Construct the message out of all the arguments. */ - compound = charalloc(MAXCHARLEN * (COLS + 1)); - vsnprintf(compound, MAXCHARLEN * (COLS + 1), msg, ap); - va_end(ap); - message = display_string(compound, 0, COLS, FALSE); - free(compound); - - start_col = (COLS - strlenpt(message)) / 2; - bracketed = (start_col > 1); - - wmove(bottomwin, 0, (bracketed ? start_col - 2 : start_col)); - wattron(bottomwin, interface_color_pair[STATUS_BAR]); - if (bracketed) - waddstr(bottomwin, "[ "); - waddstr(bottomwin, message); - free(message); - if (bracketed) - waddstr(bottomwin, " ]"); - wattroff(bottomwin, interface_color_pair[STATUS_BAR]); - - /* Defeat a VTE/Konsole bug, where the cursor can go off-limits. */ - if (ISSET(CONSTANT_SHOW) && ISSET(NO_HELP)) - wmove(bottomwin, 0, 0); - - /* Push the message to the screen straightaway. */ - wrefresh(bottomwin); - - suppress_cursorpos = TRUE; + suppress_cursorpos = TRUE; #ifndef NANO_TINY - if (old_whitespace) - SET(WHITESPACE_DISPLAY); + if (old_whitespace) + SET(WHITESPACE_DISPLAY); #endif - /* If doing quick blanking, blank the statusbar after just one keystroke. - * Otherwise, blank it after twenty-six keystrokes, as Pico does. */ - if (ISSET(QUICK_BLANK)) - statusblank = 1; - else - statusblank = 26; + /* If doing quick blanking, blank the statusbar after just one keystroke. + * Otherwise, blank it after twenty-six keystrokes, as Pico does. */ + if (ISSET(QUICK_BLANK)) + statusblank = 1; + else + statusblank = 26; } /* Display the shortcut list corresponding to menu on the last two rows * of the bottom portion of the window. */ void bottombars(int menu) { - size_t number, itemwidth, i; - subnfunc *f; - const sc *s; + size_t number, itemwidth, i; + subnfunc *f; + const sc *s; - /* Set the global variable to the given menu. */ - currmenu = menu; + /* Set the global variable to the given menu. */ + currmenu = menu; - if (ISSET(NO_HELP) || LINES < 5) - return; + if (ISSET(NO_HELP) || LINES < 5) + return; - /* Determine how many shortcuts there are to show. */ - number = length_of_list(menu); + /* Determine how many shortcuts there are to show. */ + number = length_of_list(menu); - if (number > MAIN_VISIBLE) - number = MAIN_VISIBLE; + if (number > MAIN_VISIBLE) + number = MAIN_VISIBLE; - /* Compute the width of each keyname-plus-explanation pair. */ - itemwidth = COLS / ((number / 2) + (number % 2)); + /* Compute the width of each keyname-plus-explanation pair. */ + itemwidth = COLS / ((number / 2) + (number % 2)); - /* If there is no room, don't print anything. */ - if (itemwidth == 0) - return; + /* If there is no room, don't print anything. */ + if (itemwidth == 0) + return; - blank_bottombars(); + blank_bottombars(); - /* Display the first number of shortcuts in the given menu that - * have a key combination assigned to them. */ - for (f = allfuncs, i = 0; i < number && f != NULL; f = f->next) { - if ((f->menus & menu) == 0) - continue; + /* Display the first number of shortcuts in the given menu that + * have a key combination assigned to them. */ + for (f = allfuncs, i = 0; i < number && f != NULL; f = f->next) { + if ((f->menus & menu) == 0) + continue; - s = first_sc_for(menu, f->scfunc); - if (s == NULL) - continue; + s = first_sc_for(menu, f->scfunc); + if (s == NULL) + continue; - wmove(bottomwin, 1 + i % 2, (i / 2) * itemwidth); + wmove(bottomwin, 1 + i % 2, (i / 2) * itemwidth); - post_one_key(s->keystr, _(f->desc), itemwidth + (COLS % itemwidth)); - i++; - } + post_one_key(s->keystr, _(f->desc), itemwidth + (COLS % itemwidth)); + i++; + } - /* Defeat a VTE bug by homing the cursor and forcing a screen update. */ - wmove(bottomwin, 0, 0); - wrefresh(bottomwin); + /* Defeat a VTE bug by homing the cursor and forcing a screen update. */ + wmove(bottomwin, 0, 0); + wrefresh(bottomwin); } /* Write a key's representation plus a minute description of its function @@ -2303,55 +2303,55 @@ void bottombars(int menu) * Key plus tag may occupy at most width columns. */ void post_one_key(const char *keystroke, const char *tag, int width) { - wattron(bottomwin, interface_color_pair[KEY_COMBO]); - waddnstr(bottomwin, keystroke, actual_x(keystroke, width)); - wattroff(bottomwin, interface_color_pair[KEY_COMBO]); + wattron(bottomwin, interface_color_pair[KEY_COMBO]); + waddnstr(bottomwin, keystroke, actual_x(keystroke, width)); + wattroff(bottomwin, interface_color_pair[KEY_COMBO]); - /* If the remaning space is too small, skip the description. */ - width -= strlenpt(keystroke); - if (width < 2) - return; + /* If the remaning space is too small, skip the description. */ + width -= strlenpt(keystroke); + if (width < 2) + return; - waddch(bottomwin, ' '); - wattron(bottomwin, interface_color_pair[FUNCTION_TAG]); - waddnstr(bottomwin, tag, actual_x(tag, width - 1)); - wattroff(bottomwin, interface_color_pair[FUNCTION_TAG]); + waddch(bottomwin, ' '); + wattron(bottomwin, interface_color_pair[FUNCTION_TAG]); + waddnstr(bottomwin, tag, actual_x(tag, width - 1)); + wattroff(bottomwin, interface_color_pair[FUNCTION_TAG]); } /* Redetermine current_y from the position of current relative to edittop, * and put the cursor in the edit window at (current_y, "current_x"). */ void place_the_cursor(void) { - ssize_t row = 0; - size_t col, xpt = xplustabs(); + ssize_t row = 0; + size_t col, xpt = xplustabs(); #ifndef NANO_TINY - if (ISSET(SOFTWRAP)) { - filestruct *line = openfile->edittop; - size_t leftedge; + if (ISSET(SOFTWRAP)) { + filestruct *line = openfile->edittop; + size_t leftedge; - row -= chunk_for(openfile->firstcolumn, openfile->edittop); + row -= chunk_for(openfile->firstcolumn, openfile->edittop); - /* Calculate how many rows the lines from edittop to current use. */ - while (line != NULL && line != openfile->current) { - row += number_of_chunks_in(line) + 1; - line = line->next; + /* Calculate how many rows the lines from edittop to current use. */ + while (line != NULL && line != openfile->current) { + row += number_of_chunks_in(line) + 1; + line = line->next; + } + + /* Add the number of wraps in the current line before the cursor. */ + row += get_chunk_and_edge(xpt, openfile->current, &leftedge); + col = xpt - leftedge; + } else +#endif + { + row = openfile->current->lineno - openfile->edittop->lineno; + col = xpt - get_page_start(xpt); } - /* Add the number of wraps in the current line before the cursor. */ - row += get_chunk_and_edge(xpt, openfile->current, &leftedge); - col = xpt - leftedge; - } else -#endif - { - row = openfile->current->lineno - openfile->edittop->lineno; - col = xpt - get_page_start(xpt); - } + if (row < editwinrows) + wmove(edit, row, margin + col); - if (row < editwinrows) - wmove(edit, row, margin + col); - - openfile->current_y = row; + openfile->current_y = row; } /* edit_draw() takes care of the job of actually painting a line into @@ -2363,343 +2363,343 @@ void place_the_cursor(void) * corresponds to character number actual_x(fileptr->data, from_col) of the * line. */ void edit_draw(filestruct *fileptr, const char *converted, - int row, size_t from_col) + int row, size_t from_col) { #if !defined(NANO_TINY) || defined(ENABLE_COLOR) - size_t from_x = actual_x(fileptr->data, from_col); - /* The position in fileptr->data of the leftmost character - * that displays at least partially on the window. */ - size_t till_x = actual_x(fileptr->data, from_col + editwincols - 1) + 1; - /* The position in fileptr->data of the first character that is - * completely off the window to the right. Note that till_x - * might be beyond the null terminator of the string. */ + size_t from_x = actual_x(fileptr->data, from_col); + /* The position in fileptr->data of the leftmost character + * that displays at least partially on the window. */ + size_t till_x = actual_x(fileptr->data, from_col + editwincols - 1) + 1; + /* The position in fileptr->data of the first character that is + * completely off the window to the right. Note that till_x + * might be beyond the null terminator of the string. */ #endif #ifdef ENABLE_LINENUMBERS - /* If line numbering is switched on, put a line number in front of - * the text -- but only for the parts that are not softwrapped. */ - if (margin > 0) { - wattron(edit, interface_color_pair[LINE_NUMBER]); + /* If line numbering is switched on, put a line number in front of + * the text -- but only for the parts that are not softwrapped. */ + if (margin > 0) { + wattron(edit, interface_color_pair[LINE_NUMBER]); #ifndef NANO_TINY - if (ISSET(SOFTWRAP) && from_col != 0) - mvwprintw(edit, row, 0, "%*s", margin - 1, " "); - else + if (ISSET(SOFTWRAP) && from_col != 0) + mvwprintw(edit, row, 0, "%*s", margin - 1, " "); + else #endif - mvwprintw(edit, row, 0, "%*zd", margin - 1, fileptr->lineno); - wattroff(edit, interface_color_pair[LINE_NUMBER]); - } + mvwprintw(edit, row, 0, "%*zd", margin - 1, fileptr->lineno); + wattroff(edit, interface_color_pair[LINE_NUMBER]); + } #endif - /* First simply write the converted line -- afterward we'll add colors - * and the marking highlight on just the pieces that need it. */ - mvwaddstr(edit, row, margin, converted); + /* First simply write the converted line -- afterward we'll add colors + * and the marking highlight on just the pieces that need it. */ + mvwaddstr(edit, row, margin, converted); #ifdef USING_OLD_NCURSES - /* 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. */ - if (seen_wide) - wredrawln(edit, row, 1); + /* 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. */ + if (seen_wide) + wredrawln(edit, row, 1); #endif #ifdef ENABLE_COLOR - /* If color syntaxes are available and turned on, apply them. */ - if (openfile->colorstrings != NULL && !ISSET(NO_COLOR_SYNTAX)) { - const colortype *varnish = openfile->colorstrings; + /* If color syntaxes are available and turned on, apply them. */ + if (openfile->colorstrings != NULL && !ISSET(NO_COLOR_SYNTAX)) { + const colortype *varnish = openfile->colorstrings; - /* If there are multiline regexes, make sure there is a cache. */ - if (openfile->syntax->nmultis > 0) - alloc_multidata_if_needed(fileptr); + /* If there are multiline regexes, make sure there is a cache. */ + if (openfile->syntax->nmultis > 0) + alloc_multidata_if_needed(fileptr); - /* Iterate through all the coloring regexes. */ - for (; varnish != NULL; varnish = varnish->next) { - size_t index = 0; - /* Where in the line we currently begin looking for a match. */ - int start_col; - /* The starting column of a piece to paint. Zero-based. */ - int paintlen = 0; - /* The number of characters to paint. */ - const char *thetext; - /* The place in converted from where painting starts. */ - regmatch_t match; - /* The match positions of a single-line regex. */ - const filestruct *start_line = fileptr->prev; - /* The first line before fileptr that matches 'start'. */ - const filestruct *end_line = fileptr; - /* The line that matches 'end'. */ - regmatch_t startmatch, endmatch; - /* The match positions of the start and end regexes. */ + /* Iterate through all the coloring regexes. */ + for (; varnish != NULL; varnish = varnish->next) { + size_t index = 0; + /* Where in the line we currently begin looking for a match. */ + int start_col; + /* The starting column of a piece to paint. Zero-based. */ + int paintlen = 0; + /* The number of characters to paint. */ + const char *thetext; + /* The place in converted from where painting starts. */ + regmatch_t match; + /* The match positions of a single-line regex. */ + const filestruct *start_line = fileptr->prev; + /* The first line before fileptr that matches 'start'. */ + const filestruct *end_line = fileptr; + /* The line that matches 'end'. */ + regmatch_t startmatch, endmatch; + /* The match positions of the start and end regexes. */ - /* Two notes about regexec(). A return value of zero means - * that there is a match. Also, rm_eo is the first - * non-matching character after the match. */ + /* Two notes about regexec(). A return value of zero means + * that there is a match. Also, rm_eo is the first + * non-matching character after the match. */ - wattron(edit, varnish->attributes); + wattron(edit, varnish->attributes); - /* First case: varnish is a single-line expression. */ - if (varnish->end == NULL) { - /* We increment index by rm_eo, to move past the end of the - * last match. Even though two matches may overlap, we - * want to ignore them, so that we can highlight e.g. C - * strings correctly. */ - while (index < till_x) { - /* Note the fifth parameter to regexec(). It says - * not to match the beginning-of-line character - * unless index is zero. If regexec() returns - * REG_NOMATCH, there are no more matches in the - * line. */ - if (regexec(varnish->start, &fileptr->data[index], 1, - &match, (index == 0) ? 0 : REG_NOTBOL) != 0) - break; + /* First case: varnish is a single-line expression. */ + if (varnish->end == NULL) { + /* We increment index by rm_eo, to move past the end of the + * last match. Even though two matches may overlap, we + * want to ignore them, so that we can highlight e.g. C + * strings correctly. */ + while (index < till_x) { + /* Note the fifth parameter to regexec(). It says + * not to match the beginning-of-line character + * unless index is zero. If regexec() returns + * REG_NOMATCH, there are no more matches in the + * line. */ + if (regexec(varnish->start, &fileptr->data[index], 1, + &match, (index == 0) ? 0 : REG_NOTBOL) != 0) + break; - /* If the match is of length zero, skip it. */ - if (match.rm_so == match.rm_eo) { - index = move_mbright(fileptr->data, - index + match.rm_eo); - continue; - } + /* If the match is of length zero, skip it. */ + if (match.rm_so == match.rm_eo) { + index = move_mbright(fileptr->data, + index + match.rm_eo); + continue; + } - /* Translate the match to the beginning of the line. */ - match.rm_so += index; - match.rm_eo += index; - index = match.rm_eo; + /* Translate the match to the beginning of the line. */ + match.rm_so += index; + match.rm_eo += index; + index = match.rm_eo; - /* If the matching part is not visible, skip it. */ - if (match.rm_eo <= from_x || match.rm_so >= till_x) - continue; + /* If the matching part is not visible, skip it. */ + if (match.rm_eo <= from_x || match.rm_so >= till_x) + continue; - start_col = (match.rm_so <= from_x) ? - 0 : strnlenpt(fileptr->data, - match.rm_so) - from_col; + start_col = (match.rm_so <= from_x) ? + 0 : strnlenpt(fileptr->data, + match.rm_so) - from_col; - thetext = converted + actual_x(converted, start_col); + thetext = converted + actual_x(converted, start_col); - paintlen = actual_x(thetext, strnlenpt(fileptr->data, - match.rm_eo) - from_col - start_col); + paintlen = actual_x(thetext, strnlenpt(fileptr->data, + match.rm_eo) - from_col - start_col); - mvwaddnstr(edit, row, margin + start_col, - thetext, paintlen); - } - goto tail_of_loop; - } + mvwaddnstr(edit, row, margin + start_col, + thetext, paintlen); + } + goto tail_of_loop; + } - /* Second case: varnish is a multiline expression. */ + /* Second case: varnish is a multiline expression. */ - /* Assume nothing gets painted until proven otherwise below. */ - fileptr->multidata[varnish->id] = CNONE; + /* Assume nothing gets painted until proven otherwise below. */ + fileptr->multidata[varnish->id] = CNONE; - /* First check the multidata of the preceding line -- it tells - * us about the situation so far, and thus what to do here. */ - if (start_line != NULL && start_line->multidata != NULL) { - if (start_line->multidata[varnish->id] == CWHOLELINE || - start_line->multidata[varnish->id] == CENDAFTER || - start_line->multidata[varnish->id] == CWOULDBE) - goto seek_an_end; - if (start_line->multidata[varnish->id] == CNONE || - start_line->multidata[varnish->id] == CBEGINBEFORE || - start_line->multidata[varnish->id] == CSTARTENDHERE) - goto step_two; - } + /* First check the multidata of the preceding line -- it tells + * us about the situation so far, and thus what to do here. */ + if (start_line != NULL && start_line->multidata != NULL) { + if (start_line->multidata[varnish->id] == CWHOLELINE || + start_line->multidata[varnish->id] == CENDAFTER || + start_line->multidata[varnish->id] == CWOULDBE) + goto seek_an_end; + if (start_line->multidata[varnish->id] == CNONE || + start_line->multidata[varnish->id] == CBEGINBEFORE || + start_line->multidata[varnish->id] == CSTARTENDHERE) + goto step_two; + } - /* The preceding line has no precalculated multidata. So, do - * some backtracking to find out what to paint. */ + /* The preceding line has no precalculated multidata. So, do + * some backtracking to find out what to paint. */ - /* First step: see if there is a line before current that - * matches 'start' and is not complemented by an 'end'. */ - while (start_line != NULL && regexec(varnish->start, - start_line->data, 1, &startmatch, 0) == REG_NOMATCH) { - /* There is no start on this line; but if there is an end, - * there is no need to look for starts on earlier lines. */ - if (regexec(varnish->end, start_line->data, 0, NULL, 0) == 0) - goto step_two; - start_line = start_line->prev; - } + /* First step: see if there is a line before current that + * matches 'start' and is not complemented by an 'end'. */ + while (start_line != NULL && regexec(varnish->start, + start_line->data, 1, &startmatch, 0) == REG_NOMATCH) { + /* There is no start on this line; but if there is an end, + * there is no need to look for starts on earlier lines. */ + if (regexec(varnish->end, start_line->data, 0, NULL, 0) == 0) + goto step_two; + start_line = start_line->prev; + } - /* If no start was found, skip to the next step. */ - if (start_line == NULL) - goto step_two; + /* If no start was found, skip to the next step. */ + if (start_line == NULL) + goto step_two; - /* If a found start has been qualified as an end earlier, - * believe it and skip to the next step. */ - if (start_line->multidata != NULL && - (start_line->multidata[varnish->id] == CBEGINBEFORE || - start_line->multidata[varnish->id] == CSTARTENDHERE)) - goto step_two; + /* If a found start has been qualified as an end earlier, + * believe it and skip to the next step. */ + if (start_line->multidata != NULL && + (start_line->multidata[varnish->id] == CBEGINBEFORE || + start_line->multidata[varnish->id] == CSTARTENDHERE)) + goto step_two; - /* Is there an uncomplemented start on the found line? */ - while (TRUE) { - /* Begin searching for an end after the start match. */ - index += startmatch.rm_eo; - /* If there is no end after this last start, good. */ - if (regexec(varnish->end, start_line->data + index, 1, &endmatch, - (index == 0) ? 0 : REG_NOTBOL) == REG_NOMATCH) - break; - /* Begin searching for a new start after the end match. */ - index += endmatch.rm_eo; - /* If both start and end match are mere anchors, advance. */ - if (startmatch.rm_so == startmatch.rm_eo && - endmatch.rm_so == endmatch.rm_eo) { - if (start_line->data[index] == '\0') - break; - index = move_mbright(start_line->data, index); - } - /* If there is no later start on this line, next step. */ - if (regexec(varnish->start, start_line->data + index, - 1, &startmatch, REG_NOTBOL) == REG_NOMATCH) - goto step_two; - } - /* Indeed, there is a start without an end on that line. */ + /* Is there an uncomplemented start on the found line? */ + while (TRUE) { + /* Begin searching for an end after the start match. */ + index += startmatch.rm_eo; + /* If there is no end after this last start, good. */ + if (regexec(varnish->end, start_line->data + index, 1, &endmatch, + (index == 0) ? 0 : REG_NOTBOL) == REG_NOMATCH) + break; + /* Begin searching for a new start after the end match. */ + index += endmatch.rm_eo; + /* If both start and end match are mere anchors, advance. */ + if (startmatch.rm_so == startmatch.rm_eo && + endmatch.rm_so == endmatch.rm_eo) { + if (start_line->data[index] == '\0') + break; + index = move_mbright(start_line->data, index); + } + /* If there is no later start on this line, next step. */ + if (regexec(varnish->start, start_line->data + index, + 1, &startmatch, REG_NOTBOL) == REG_NOMATCH) + goto step_two; + } + /* Indeed, there is a start without an end on that line. */ seek_an_end: - /* We've already checked that there is no end between the start - * and the current line. But is there an end after the start - * at all? We don't paint unterminated starts. */ - while (end_line != NULL && regexec(varnish->end, end_line->data, - 1, &endmatch, 0) == REG_NOMATCH) - end_line = end_line->next; + /* We've already checked that there is no end between the start + * and the current line. But is there an end after the start + * at all? We don't paint unterminated starts. */ + while (end_line != NULL && regexec(varnish->end, end_line->data, + 1, &endmatch, 0) == REG_NOMATCH) + end_line = end_line->next; - /* If there is no end, there is nothing to paint. */ - if (end_line == NULL) { - fileptr->multidata[varnish->id] = CWOULDBE; - goto tail_of_loop; - } + /* If there is no end, there is nothing to paint. */ + if (end_line == NULL) { + fileptr->multidata[varnish->id] = CWOULDBE; + goto tail_of_loop; + } - /* If the end is on a later line, paint whole line, and be done. */ - if (end_line != fileptr) { - mvwaddnstr(edit, row, margin, converted, -1); - fileptr->multidata[varnish->id] = CWHOLELINE; - goto tail_of_loop; - } + /* If the end is on a later line, paint whole line, and be done. */ + if (end_line != fileptr) { + mvwaddnstr(edit, row, margin, converted, -1); + fileptr->multidata[varnish->id] = CWHOLELINE; + goto tail_of_loop; + } - /* Only if it is visible, paint the part to be coloured. */ - if (endmatch.rm_eo > from_x) { - paintlen = actual_x(converted, strnlenpt(fileptr->data, - endmatch.rm_eo) - from_col); - mvwaddnstr(edit, row, margin, converted, paintlen); - } - fileptr->multidata[varnish->id] = CBEGINBEFORE; + /* Only if it is visible, paint the part to be coloured. */ + if (endmatch.rm_eo > from_x) { + paintlen = actual_x(converted, strnlenpt(fileptr->data, + endmatch.rm_eo) - from_col); + mvwaddnstr(edit, row, margin, converted, paintlen); + } + fileptr->multidata[varnish->id] = CBEGINBEFORE; step_two: - /* Second step: look for starts on this line, but begin - * looking only after an end match, if there is one. */ - index = (paintlen == 0) ? 0 : endmatch.rm_eo; + /* Second step: look for starts on this line, but begin + * looking only after an end match, if there is one. */ + index = (paintlen == 0) ? 0 : endmatch.rm_eo; - while (regexec(varnish->start, fileptr->data + index, - 1, &startmatch, (index == 0) ? - 0 : REG_NOTBOL) == 0) { - /* Translate the match to be relative to the - * beginning of the line. */ - startmatch.rm_so += index; - startmatch.rm_eo += index; + while (regexec(varnish->start, fileptr->data + index, + 1, &startmatch, (index == 0) ? + 0 : REG_NOTBOL) == 0) { + /* Translate the match to be relative to the + * beginning of the line. */ + startmatch.rm_so += index; + startmatch.rm_eo += index; - start_col = (startmatch.rm_so <= from_x) ? - 0 : strnlenpt(fileptr->data, - startmatch.rm_so) - from_col; + start_col = (startmatch.rm_so <= from_x) ? + 0 : strnlenpt(fileptr->data, + startmatch.rm_so) - from_col; - thetext = converted + actual_x(converted, start_col); + thetext = converted + actual_x(converted, start_col); - if (regexec(varnish->end, fileptr->data + startmatch.rm_eo, - 1, &endmatch, (startmatch.rm_eo == 0) ? - 0 : REG_NOTBOL) == 0) { - /* Translate the end match to be relative to - * the beginning of the line. */ - endmatch.rm_so += startmatch.rm_eo; - endmatch.rm_eo += startmatch.rm_eo; - /* Only paint the match if it is visible on screen and - * it is more than zero characters long. */ - if (endmatch.rm_eo > from_x && - endmatch.rm_eo > startmatch.rm_so) { - paintlen = actual_x(thetext, strnlenpt(fileptr->data, - endmatch.rm_eo) - from_col - start_col); + if (regexec(varnish->end, fileptr->data + startmatch.rm_eo, + 1, &endmatch, (startmatch.rm_eo == 0) ? + 0 : REG_NOTBOL) == 0) { + /* Translate the end match to be relative to + * the beginning of the line. */ + endmatch.rm_so += startmatch.rm_eo; + endmatch.rm_eo += startmatch.rm_eo; + /* Only paint the match if it is visible on screen and + * it is more than zero characters long. */ + if (endmatch.rm_eo > from_x && + endmatch.rm_eo > startmatch.rm_so) { + paintlen = actual_x(thetext, strnlenpt(fileptr->data, + endmatch.rm_eo) - from_col - start_col); - mvwaddnstr(edit, row, margin + start_col, - thetext, paintlen); + mvwaddnstr(edit, row, margin + start_col, + thetext, paintlen); - fileptr->multidata[varnish->id] = CSTARTENDHERE; - } - index = endmatch.rm_eo; - /* If both start and end match are anchors, advance. */ - if (startmatch.rm_so == startmatch.rm_eo && - endmatch.rm_so == endmatch.rm_eo) { - if (fileptr->data[index] == '\0') - break; - index = move_mbright(fileptr->data, index); - } - continue; - } + fileptr->multidata[varnish->id] = CSTARTENDHERE; + } + index = endmatch.rm_eo; + /* If both start and end match are anchors, advance. */ + if (startmatch.rm_so == startmatch.rm_eo && + endmatch.rm_so == endmatch.rm_eo) { + if (fileptr->data[index] == '\0') + break; + index = move_mbright(fileptr->data, index); + } + continue; + } - /* There is no end on this line. But maybe on later lines? */ - end_line = fileptr->next; + /* There is no end on this line. But maybe on later lines? */ + end_line = fileptr->next; - while (end_line != NULL && regexec(varnish->end, end_line->data, - 0, NULL, 0) == REG_NOMATCH) - end_line = end_line->next; + while (end_line != NULL && regexec(varnish->end, end_line->data, + 0, NULL, 0) == REG_NOMATCH) + end_line = end_line->next; - /* If there is no end, we're done with this regex. */ - if (end_line == NULL) { - fileptr->multidata[varnish->id] = CWOULDBE; - break; - } + /* If there is no end, we're done with this regex. */ + if (end_line == NULL) { + fileptr->multidata[varnish->id] = CWOULDBE; + break; + } - /* Paint the rest of the line, and we're done. */ - mvwaddnstr(edit, row, margin + start_col, thetext, -1); - fileptr->multidata[varnish->id] = CENDAFTER; - break; - } + /* Paint the rest of the line, and we're done. */ + mvwaddnstr(edit, row, margin + start_col, thetext, -1); + fileptr->multidata[varnish->id] = CENDAFTER; + break; + } tail_of_loop: - wattroff(edit, varnish->attributes); + wattroff(edit, varnish->attributes); + } } - } #endif /* ENABLE_COLOR */ #ifndef NANO_TINY - /* If the mark is on, and fileptr is at least partially selected, we - * need to paint it. */ - if (openfile->mark && - (fileptr->lineno <= openfile->mark->lineno || - fileptr->lineno <= openfile->current->lineno) && - (fileptr->lineno >= openfile->mark->lineno || - fileptr->lineno >= openfile->current->lineno)) { - const filestruct *top, *bot; - /* The lines where the marked region begins and ends. */ - size_t top_x, bot_x; - /* The x positions where the marked region begins and ends. */ - int start_col; - /* The column where painting starts. Zero-based. */ - const char *thetext; - /* The place in converted from where painting starts. */ - int paintlen = -1; - /* The number of characters to paint. Negative means "all". */ + /* If the mark is on, and fileptr is at least partially selected, we + * need to paint it. */ + if (openfile->mark && + (fileptr->lineno <= openfile->mark->lineno || + fileptr->lineno <= openfile->current->lineno) && + (fileptr->lineno >= openfile->mark->lineno || + fileptr->lineno >= openfile->current->lineno)) { + const filestruct *top, *bot; + /* The lines where the marked region begins and ends. */ + size_t top_x, bot_x; + /* The x positions where the marked region begins and ends. */ + int start_col; + /* The column where painting starts. Zero-based. */ + const char *thetext; + /* The place in converted from where painting starts. */ + int paintlen = -1; + /* The number of characters to paint. Negative means "all". */ - mark_order(&top, &top_x, &bot, &bot_x, NULL); + mark_order(&top, &top_x, &bot, &bot_x, NULL); - if (top->lineno < fileptr->lineno || top_x < from_x) - top_x = from_x; - if (bot->lineno > fileptr->lineno || bot_x > till_x) - bot_x = till_x; + if (top->lineno < fileptr->lineno || top_x < from_x) + top_x = from_x; + if (bot->lineno > fileptr->lineno || bot_x > till_x) + bot_x = till_x; - /* Only paint if the marked part of the line is on this page. */ - if (top_x < till_x && bot_x > from_x) { - /* Compute on which screen column to start painting. */ - start_col = strnlenpt(fileptr->data, top_x) - from_col; + /* Only paint if the marked part of the line is on this page. */ + if (top_x < till_x && bot_x > from_x) { + /* Compute on which screen column to start painting. */ + start_col = strnlenpt(fileptr->data, top_x) - from_col; - if (start_col < 0) - start_col = 0; + if (start_col < 0) + start_col = 0; - thetext = converted + actual_x(converted, start_col); + thetext = converted + actual_x(converted, start_col); - /* If the end of the mark is onscreen, compute how many - * characters to paint. Otherwise, just paint all. */ - if (bot_x < till_x) { - size_t end_col = strnlenpt(fileptr->data, bot_x) - from_col; - paintlen = actual_x(thetext, end_col - start_col); - } + /* If the end of the mark is onscreen, compute how many + * characters to paint. Otherwise, just paint all. */ + if (bot_x < till_x) { + size_t end_col = strnlenpt(fileptr->data, bot_x) - from_col; + paintlen = actual_x(thetext, end_col - start_col); + } - wattron(edit, interface_color_pair[SELECTED_TEXT]); - mvwaddnstr(edit, row, margin + start_col, thetext, paintlen); - wattroff(edit, interface_color_pair[SELECTED_TEXT]); + wattron(edit, interface_color_pair[SELECTED_TEXT]); + mvwaddnstr(edit, row, margin + start_col, thetext, paintlen); + wattroff(edit, interface_color_pair[SELECTED_TEXT]); + } } - } #endif /* !NANO_TINY */ } @@ -2711,49 +2711,49 @@ void edit_draw(filestruct *fileptr, const char *converted, * consumed (when softwrapping). */ int update_line(filestruct *fileptr, size_t index) { - int row = 0; - /* The row in the edit window we will be updating. */ - char *converted; - /* The data of the line with tabs and control characters expanded. */ - size_t from_col = 0; - /* From which column a horizontally scrolled line is displayed. */ + int row = 0; + /* The row in the edit window we will be updating. */ + char *converted; + /* The data of the line with tabs and control characters expanded. */ + size_t from_col = 0; + /* From which column a horizontally scrolled line is displayed. */ #ifndef NANO_TINY - if (ISSET(SOFTWRAP)) - return update_softwrapped_line(fileptr); + if (ISSET(SOFTWRAP)) + return update_softwrapped_line(fileptr); #endif - row = fileptr->lineno - openfile->edittop->lineno; + row = fileptr->lineno - openfile->edittop->lineno; - /* If the line is offscreen, don't even try to display it. */ - if (row < 0 || row >= editwinrows) { + /* If the line is offscreen, don't even try to display it. */ + if (row < 0 || row >= editwinrows) { #ifndef NANO_TINY - statusline(ALERT, "Badness: tried to display a line on row %i" - " -- please report a bug", row); + statusline(ALERT, "Badness: tried to display a line on row %i" + " -- please report a bug", row); #endif - return 0; - } + return 0; + } - /* First, blank out the row. */ - blank_row(edit, row, 0, COLS); + /* First, blank out the row. */ + blank_row(edit, row, 0, COLS); - /* Next, find out from which column to start displaying the line. */ - from_col = get_page_start(strnlenpt(fileptr->data, index)); + /* Next, find out from which column to start displaying the line. */ + from_col = get_page_start(strnlenpt(fileptr->data, index)); - /* Expand the line, replacing tabs with spaces, and control - * characters with their displayed forms. */ - converted = display_string(fileptr->data, from_col, editwincols, TRUE); + /* Expand the line, replacing tabs with spaces, and control + * characters with their displayed forms. */ + converted = display_string(fileptr->data, from_col, editwincols, TRUE); - /* Draw the line. */ - edit_draw(fileptr, converted, row, from_col); - free(converted); + /* Draw the line. */ + edit_draw(fileptr, converted, row, from_col); + free(converted); - if (from_col > 0) - mvwaddch(edit, row, margin, '$'); - if (strlenpt(fileptr->data) > from_col + editwincols) - mvwaddch(edit, row, COLS - 1, '$'); + if (from_col > 0) + mvwaddch(edit, row, margin, '$'); + if (strlenpt(fileptr->data) > from_col + editwincols) + mvwaddch(edit, row, COLS - 1, '$'); - return 1; + return 1; } #ifndef NANO_TINY @@ -2762,64 +2762,64 @@ int update_line(filestruct *fileptr, size_t index) * Return the number of additional rows consumed. */ int update_softwrapped_line(filestruct *fileptr) { - int row = 0; - /* The row in the edit window we will write to. */ - filestruct *line = openfile->edittop; - /* An iterator needed to find the relevant row. */ - int starting_row; - /* The first row in the edit window that gets updated. */ - size_t from_col = 0; - /* The starting column of the current chunk. */ - size_t to_col = 0; - /* To which column a line is displayed. */ - char *converted; - /* The data of the chunk with tabs and control characters expanded. */ + int row = 0; + /* The row in the edit window we will write to. */ + filestruct *line = openfile->edittop; + /* An iterator needed to find the relevant row. */ + int starting_row; + /* The first row in the edit window that gets updated. */ + size_t from_col = 0; + /* The starting column of the current chunk. */ + size_t to_col = 0; + /* To which column a line is displayed. */ + char *converted; + /* The data of the chunk with tabs and control characters expanded. */ - if (fileptr == openfile->edittop) - from_col = openfile->firstcolumn; - else - row -= chunk_for(openfile->firstcolumn, openfile->edittop); + if (fileptr == openfile->edittop) + from_col = openfile->firstcolumn; + else + row -= chunk_for(openfile->firstcolumn, openfile->edittop); - /* Find out on which screen row the target line should be shown. */ - while (line != fileptr && line != NULL) { - row += number_of_chunks_in(line) + 1; - line = line->next; - } + /* Find out on which screen row the target line should be shown. */ + while (line != fileptr && line != NULL) { + row += number_of_chunks_in(line) + 1; + line = line->next; + } - /* If the first chunk is offscreen, don't even try to display it. */ - if (row < 0 || row >= editwinrows) { - statusline(ALERT, "Badness: tried to display a chunk on row %i" - " -- please report a bug", row); - return 0; - } + /* If the first chunk is offscreen, don't even try to display it. */ + if (row < 0 || row >= editwinrows) { + statusline(ALERT, "Badness: tried to display a chunk on row %i" + " -- please report a bug", row); + return 0; + } - starting_row = row; + starting_row = row; - while (row < editwinrows) { - bool end_of_line = FALSE; + while (row < editwinrows) { + bool end_of_line = FALSE; - to_col = get_softwrap_breakpoint(fileptr->data, from_col, &end_of_line); + to_col = get_softwrap_breakpoint(fileptr->data, from_col, &end_of_line); - blank_row(edit, row, 0, COLS); + blank_row(edit, row, 0, COLS); - /* Convert the chunk to its displayable form and draw it. */ - converted = display_string(fileptr->data, from_col, to_col - from_col, TRUE); - edit_draw(fileptr, converted, row++, from_col); - free(converted); + /* Convert the chunk to its displayable form and draw it. */ + converted = display_string(fileptr->data, from_col, to_col - from_col, TRUE); + edit_draw(fileptr, converted, row++, from_col); + free(converted); - if (end_of_line) - break; + if (end_of_line) + break; - /* If the line is softwrapped before its last column, add a ">" just - * after its softwrap breakpoint, unless we're softwrapping at blanks - * and not in the middle of a word. */ - if (!ISSET(AT_BLANKS) && to_col - from_col < editwincols) - mvwaddch(edit, row - 1, to_col - from_col, '>'); + /* If the line is softwrapped before its last column, add a ">" just + * after its softwrap breakpoint, unless we're softwrapping at blanks + * and not in the middle of a word. */ + if (!ISSET(AT_BLANKS) && to_col - from_col < editwincols) + mvwaddch(edit, row - 1, to_col - from_col, '>'); - from_col = to_col; - } + from_col = to_col; + } - return (row - starting_row); + return (row - starting_row); } #endif @@ -2829,11 +2829,11 @@ int update_softwrapped_line(filestruct *fileptr) bool line_needs_update(const size_t old_column, const size_t new_column) { #ifndef NANO_TINY - if (openfile->mark) - return TRUE; - else + if (openfile->mark) + return TRUE; + else #endif - return (get_page_start(old_column) != get_page_start(new_column)); + return (get_page_start(old_column) != get_page_start(new_column)); } /* Try to move up nrows softwrapped chunks from the given line and the @@ -2842,35 +2842,35 @@ bool line_needs_update(const size_t old_column, const size_t new_column) * couldn't move up, which will be zero if we completely succeeded. */ int go_back_chunks(int nrows, filestruct **line, size_t *leftedge) { - int i; + int i; #ifndef NANO_TINY - if (ISSET(SOFTWRAP)) { - /* Recede through the requested number of chunks. */ - for (i = nrows; i > 0; i--) { - size_t chunk = chunk_for(*leftedge, *line); + if (ISSET(SOFTWRAP)) { + /* Recede through the requested number of chunks. */ + for (i = nrows; i > 0; i--) { + size_t chunk = chunk_for(*leftedge, *line); - *leftedge = 0; + *leftedge = 0; - if (chunk >= i) - return go_forward_chunks(chunk - i, line, leftedge); + if (chunk >= i) + return go_forward_chunks(chunk - i, line, leftedge); - if (*line == openfile->fileage) - break; + if (*line == openfile->fileage) + break; - i -= chunk; - *line = (*line)->prev; - *leftedge = HIGHEST_POSITIVE; - } + i -= chunk; + *line = (*line)->prev; + *leftedge = HIGHEST_POSITIVE; + } - if (*leftedge == HIGHEST_POSITIVE) - *leftedge = leftedge_for(*leftedge, *line); - } else + if (*leftedge == HIGHEST_POSITIVE) + *leftedge = leftedge_for(*leftedge, *line); + } else #endif - for (i = nrows; i > 0 && (*line)->prev != NULL; i--) - *line = (*line)->prev; + for (i = nrows; i > 0 && (*line)->prev != NULL; i--) + *line = (*line)->prev; - return i; + return i; } /* Try to move down nrows softwrapped chunks from the given line and the @@ -2879,38 +2879,38 @@ int go_back_chunks(int nrows, filestruct **line, size_t *leftedge) * couldn't move down, which will be zero if we completely succeeded. */ int go_forward_chunks(int nrows, filestruct **line, size_t *leftedge) { - int i; + int i; #ifndef NANO_TINY - if (ISSET(SOFTWRAP)) { - size_t current_leftedge = *leftedge; + if (ISSET(SOFTWRAP)) { + size_t current_leftedge = *leftedge; - /* Advance through the requested number of chunks. */ - for (i = nrows; i > 0; i--) { - bool end_of_line = FALSE; + /* Advance through the requested number of chunks. */ + for (i = nrows; i > 0; i--) { + bool end_of_line = FALSE; - current_leftedge = get_softwrap_breakpoint((*line)->data, - current_leftedge, &end_of_line); + current_leftedge = get_softwrap_breakpoint((*line)->data, + current_leftedge, &end_of_line); - if (!end_of_line) - continue; + if (!end_of_line) + continue; - if (*line == openfile->filebot) - break; + if (*line == openfile->filebot) + break; - *line = (*line)->next; - current_leftedge = 0; - } + *line = (*line)->next; + current_leftedge = 0; + } - /* Only change leftedge when we actually could move. */ - if (i < nrows) - *leftedge = current_leftedge; - } else + /* Only change leftedge when we actually could move. */ + if (i < nrows) + *leftedge = current_leftedge; + } else #endif - for (i = nrows; i > 0 && (*line)->next != NULL; i--) - *line = (*line)->next; + for (i = nrows; i > 0 && (*line)->next != NULL; i--) + *line = (*line)->next; - return i; + return i; } /* Return TRUE if there are fewer than a screen's worth of lines between @@ -2919,90 +2919,90 @@ int go_forward_chunks(int nrows, filestruct **line, size_t *leftedge) bool less_than_a_screenful(size_t was_lineno, size_t was_leftedge) { #ifndef NANO_TINY - if (ISSET(SOFTWRAP)) { - filestruct *line = openfile->current; - size_t leftedge = leftedge_for(xplustabs(), openfile->current); - int rows_left = go_back_chunks(editwinrows - 1, &line, &leftedge); + if (ISSET(SOFTWRAP)) { + filestruct *line = openfile->current; + size_t leftedge = leftedge_for(xplustabs(), openfile->current); + int rows_left = go_back_chunks(editwinrows - 1, &line, &leftedge); - return (rows_left > 0 || line->lineno < was_lineno || - (line->lineno == was_lineno && leftedge <= was_leftedge)); - } else + return (rows_left > 0 || line->lineno < was_lineno || + (line->lineno == was_lineno && leftedge <= was_leftedge)); + } else #endif - return (openfile->current->lineno - was_lineno < editwinrows); + return (openfile->current->lineno - was_lineno < editwinrows); } /* Scroll the edit window in the given direction and the given number of rows, * and draw new lines on the blank lines left after the scrolling. */ void edit_scroll(bool direction, int nrows) { - filestruct *line; - size_t leftedge; + filestruct *line; + size_t leftedge; - /* Part 1: nrows is the number of rows we're going to scroll the text of - * the edit window. */ + /* Part 1: nrows is the number of rows we're going to scroll the text of + * the edit window. */ - /* Move the top line of the edit window the requested number of rows up or - * down, and reduce the number of rows with the amount we couldn't move. */ - if (direction == BACKWARD) - nrows -= go_back_chunks(nrows, &openfile->edittop, &openfile->firstcolumn); - else - nrows -= go_forward_chunks(nrows, &openfile->edittop, &openfile->firstcolumn); + /* Move the top line of the edit window the requested number of rows up or + * down, and reduce the number of rows with the amount we couldn't move. */ + if (direction == BACKWARD) + nrows -= go_back_chunks(nrows, &openfile->edittop, &openfile->firstcolumn); + else + nrows -= go_forward_chunks(nrows, &openfile->edittop, &openfile->firstcolumn); - /* Don't bother scrolling zero rows, nor more than the window can hold. */ - if (nrows == 0) { + /* Don't bother scrolling zero rows, nor more than the window can hold. */ + if (nrows == 0) { #ifndef NANO_TINY - statusline(ALERT, "Underscrolling -- please report a bug"); + statusline(ALERT, "Underscrolling -- please report a bug"); #endif - return; - } - if (nrows >= editwinrows) { + return; + } + if (nrows >= editwinrows) { #ifndef NANO_TINY - if (editwinrows > 1) - statusline(ALERT, "Overscrolling -- please report a bug"); + if (editwinrows > 1) + statusline(ALERT, "Overscrolling -- please report a bug"); #endif - refresh_needed = TRUE; - return; - } + refresh_needed = TRUE; + return; + } - /* Scroll the text of the edit window a number of rows up or down. */ - scrollok(edit, TRUE); - wscrl(edit, (direction == BACKWARD) ? -nrows : nrows); - scrollok(edit, FALSE); + /* Scroll the text of the edit window a number of rows up or down. */ + scrollok(edit, TRUE); + wscrl(edit, (direction == BACKWARD) ? -nrows : nrows); + scrollok(edit, FALSE); - /* Part 2: nrows is now the number of rows in the scrolled region of the - * edit window that we need to draw. */ + /* Part 2: nrows is now the number of rows in the scrolled region of the + * edit window that we need to draw. */ - /* If we're not on the first "page" (when not softwrapping), or the mark - * is on, the row next to the scrolled region needs to be redrawn too. */ - if (line_needs_update(openfile->placewewant, 0) && nrows < editwinrows) - nrows++; + /* If we're not on the first "page" (when not softwrapping), or the mark + * is on, the row next to the scrolled region needs to be redrawn too. */ + if (line_needs_update(openfile->placewewant, 0) && nrows < editwinrows) + nrows++; - /* If we scrolled backward, start on the first line of the blank region. */ - line = openfile->edittop; - leftedge = openfile->firstcolumn; + /* If we scrolled backward, start on the first line of the blank region. */ + line = openfile->edittop; + leftedge = openfile->firstcolumn; - /* If we scrolled forward, move down to the start of the blank region. */ - if (direction == FORWARD) - go_forward_chunks(editwinrows - nrows, &line, &leftedge); + /* If we scrolled forward, move down to the start of the blank region. */ + if (direction == FORWARD) + go_forward_chunks(editwinrows - nrows, &line, &leftedge); #ifndef NANO_TINY - if (ISSET(SOFTWRAP)) { - /* Compensate for the earlier chunks of a softwrapped line. */ - nrows += chunk_for(leftedge, line); + if (ISSET(SOFTWRAP)) { + /* Compensate for the earlier chunks of a softwrapped line. */ + nrows += chunk_for(leftedge, line); - /* Don't compensate for the chunks that are offscreen. */ - if (line == openfile->edittop) - nrows -= chunk_for(openfile->firstcolumn, line); - } + /* Don't compensate for the chunks that are offscreen. */ + if (line == openfile->edittop) + nrows -= chunk_for(openfile->firstcolumn, line); + } #endif - /* Draw new content on the blank rows inside the scrolled region - * (and on the bordering row too when it was deemed necessary). */ - while (nrows > 0 && line != NULL) { - nrows -= update_line(line, (line == openfile->current) ? - openfile->current_x : 0); - line = line->next; - } + /* Draw new content on the blank rows inside the scrolled region + * (and on the bordering row too when it was deemed necessary). */ + while (nrows > 0 && line != NULL) { + nrows -= update_line(line, (line == openfile->current) ? + openfile->current_x : 0); + line = line->next; + } } #ifndef NANO_TINY @@ -3011,57 +3011,57 @@ void edit_scroll(bool direction, int nrows) * end_of_line to TRUE if we reach the end of the line while searching the * text. Assume leftedge is the leftmost column of a softwrapped chunk. */ size_t get_softwrap_breakpoint(const char *text, size_t leftedge, - bool *end_of_line) + bool *end_of_line) { - size_t goal_column = leftedge + editwincols; - /* The place at or before which text must be broken. */ - size_t breaking_col = goal_column; - /* The column where text can be broken, when there's no better. */ - size_t column = 0; - /* Current column position in text. */ - size_t last_blank_col = 0; - /* The column position of the last seen whitespace character. */ - const char *farthest_blank = NULL; - /* A pointer to the last seen whitespace character in text. */ + size_t goal_column = leftedge + editwincols; + /* The place at or before which text must be broken. */ + size_t breaking_col = goal_column; + /* The column where text can be broken, when there's no better. */ + size_t column = 0; + /* Current column position in text. */ + size_t last_blank_col = 0; + /* The column position of the last seen whitespace character. */ + const char *farthest_blank = NULL; + /* A pointer to the last seen whitespace character in text. */ - /* First find the place in text where the current chunk starts. */ - while (*text != '\0' && column < leftedge) - text += parse_mbchar(text, NULL, &column); + /* First find the place in text where the current chunk starts. */ + while (*text != '\0' && column < leftedge) + text += parse_mbchar(text, NULL, &column); - /* Now find the place in text where this chunk should end. */ - while (*text != '\0' && column <= goal_column) { - /* When breaking at blanks, do it *before* the target column. */ - if (ISSET(AT_BLANKS) && is_blank_mbchar(text) && column < goal_column) { - farthest_blank = text; - last_blank_col = column; + /* Now find the place in text where this chunk should end. */ + while (*text != '\0' && column <= goal_column) { + /* When breaking at blanks, do it *before* the target column. */ + if (ISSET(AT_BLANKS) && is_blank_mbchar(text) && column < goal_column) { + farthest_blank = text; + last_blank_col = column; + } + + breaking_col = (*text == '\t' ? goal_column : column); + text += parse_mbchar(text, NULL, &column); } - breaking_col = (*text == '\t' ? goal_column : column); - text += parse_mbchar(text, NULL, &column); - } + /* If we didn't overshoot the limit, we've found a breaking point; + * and we've reached EOL if we didn't even *reach* the limit. */ + if (column <= goal_column) { + *end_of_line = (column < goal_column); + return column; + } - /* If we didn't overshoot the limit, we've found a breaking point; - * and we've reached EOL if we didn't even *reach* the limit. */ - if (column <= goal_column) { - *end_of_line = (column < goal_column); - return column; - } + /* If we're softwrapping at blanks and we found at least one blank, break + * after that blank -- if it doesn't overshoot the screen's edge. */ + if (farthest_blank != NULL) { + parse_mbchar(farthest_blank, NULL, &last_blank_col); - /* If we're softwrapping at blanks and we found at least one blank, break - * after that blank -- if it doesn't overshoot the screen's edge. */ - if (farthest_blank != NULL) { - parse_mbchar(farthest_blank, NULL, &last_blank_col); + if (last_blank_col <= goal_column) + return last_blank_col; - if (last_blank_col <= goal_column) - return last_blank_col; + /* If it's a tab that overshoots, break at the screen's edge. */ + if (*farthest_blank == '\t') + breaking_col = goal_column; + } - /* If it's a tab that overshoots, break at the screen's edge. */ - if (*farthest_blank == '\t') - breaking_col = goal_column; - } - - /* Otherwise, break at the last character that doesn't overshoot. */ - return (editwincols > 1) ? breaking_col : column - 1; + /* Otherwise, break at the last character that doesn't overshoot. */ + return (editwincols > 1) ? breaking_col : column - 1; } /* Get the row of the softwrapped chunk of the given line that column is on, @@ -3069,53 +3069,53 @@ size_t get_softwrap_breakpoint(const char *text, size_t leftedge, * NULL, return the leftmost column of the chunk in it. */ size_t get_chunk_and_edge(size_t column, filestruct *line, size_t *leftedge) { - size_t current_chunk = 0, start_col = 0, end_col; - bool end_of_line = FALSE; + size_t current_chunk = 0, start_col = 0, end_col; + bool end_of_line = FALSE; - while (TRUE) { - end_col = get_softwrap_breakpoint(line->data, start_col, &end_of_line); + while (TRUE) { + end_col = get_softwrap_breakpoint(line->data, start_col, &end_of_line); - /* We reached the end of the line and/or found column, so get out. */ - if (end_of_line || (column >= start_col && column < end_col)) { - if (leftedge != NULL) - *leftedge = start_col; - return current_chunk; + /* We reached the end of the line and/or found column, so get out. */ + if (end_of_line || (column >= start_col && column < end_col)) { + if (leftedge != NULL) + *leftedge = start_col; + return current_chunk; + } + + current_chunk++; + start_col = end_col; } - - current_chunk++; - start_col = end_col; - } } /* Return the row of the softwrapped chunk of the given line that column is on, * relative to the first row (zero-based). */ size_t chunk_for(size_t column, filestruct *line) { - if (ISSET(SOFTWRAP)) - return get_chunk_and_edge(column, line, NULL); - else - return 0; + if (ISSET(SOFTWRAP)) + return get_chunk_and_edge(column, line, NULL); + else + return 0; } /* Return the leftmost column of the softwrapped chunk of the given line that * column is on. */ size_t leftedge_for(size_t column, filestruct *line) { - size_t leftedge; + size_t leftedge; - if (!ISSET(SOFTWRAP)) - return 0; + if (!ISSET(SOFTWRAP)) + return 0; - get_chunk_and_edge(column, line, &leftedge); + get_chunk_and_edge(column, line, &leftedge); - return leftedge; + return leftedge; } /* Return the row of the last softwrapped chunk of the given line, relative to * the first row (zero-based). */ size_t number_of_chunks_in(filestruct *line) { - return chunk_for((size_t)-1, line); + return chunk_for((size_t)-1, line); } /* Ensure that firstcolumn is at the starting column of the softwrapped chunk @@ -3123,11 +3123,11 @@ size_t number_of_chunks_in(filestruct *line) * has changed, because then the width of softwrapped chunks has changed. */ void ensure_firstcolumn_is_aligned(void) { - openfile->firstcolumn = leftedge_for(openfile->firstcolumn, - openfile->edittop); + openfile->firstcolumn = leftedge_for(openfile->firstcolumn, + openfile->edittop); - /* If smooth scrolling is on, make sure the viewport doesn't center. */ - focusing = FALSE; + /* If smooth scrolling is on, make sure the viewport doesn't center. */ + focusing = FALSE; } #endif /* !NANO_TINY */ @@ -3138,23 +3138,23 @@ void ensure_firstcolumn_is_aligned(void) size_t actual_last_column(size_t leftedge, size_t column) { #ifndef NANO_TINY - if (ISSET(SOFTWRAP)) { - bool last_chunk; - size_t end_col = get_softwrap_breakpoint(openfile->current->data, - leftedge, &last_chunk) - leftedge; + if (ISSET(SOFTWRAP)) { + bool last_chunk; + size_t end_col = get_softwrap_breakpoint(openfile->current->data, + leftedge, &last_chunk) - leftedge; - /* If we're not on the last chunk, we're one column past the end of - * the row. Shifting back one column might put us in the middle of - * a multi-column character, but actual_x() will fix that later. */ - if (!last_chunk) - end_col--; + /* If we're not on the last chunk, we're one column past the end of + * the row. Shifting back one column might put us in the middle of + * a multi-column character, but actual_x() will fix that later. */ + if (!last_chunk) + end_col--; - if (column > end_col) - column = end_col; - } + if (column > end_col) + column = end_col; + } #endif - return leftedge + column; + return leftedge + column; } /* Return TRUE if current[current_x] is above the top of the screen, and FALSE @@ -3162,15 +3162,15 @@ size_t actual_last_column(size_t leftedge, size_t column) bool current_is_above_screen(void) { #ifndef NANO_TINY - if (ISSET(SOFTWRAP)) - /* The cursor is above screen when current[current_x] is before edittop - * at column firstcolumn. */ - return (openfile->current->lineno < openfile->edittop->lineno || - (openfile->current->lineno == openfile->edittop->lineno && - xplustabs() < openfile->firstcolumn)); - else + if (ISSET(SOFTWRAP)) + /* The cursor is above screen when current[current_x] is before edittop + * at column firstcolumn. */ + return (openfile->current->lineno < openfile->edittop->lineno || + (openfile->current->lineno == openfile->edittop->lineno && + xplustabs() < openfile->firstcolumn)); + else #endif - return (openfile->current->lineno < openfile->edittop->lineno); + return (openfile->current->lineno < openfile->edittop->lineno); } /* Return TRUE if current[current_x] is below the bottom of the screen, and @@ -3178,105 +3178,105 @@ bool current_is_above_screen(void) bool current_is_below_screen(void) { #ifndef NANO_TINY - if (ISSET(SOFTWRAP)) { - filestruct *line = openfile->edittop; - size_t leftedge = openfile->firstcolumn; + if (ISSET(SOFTWRAP)) { + filestruct *line = openfile->edittop; + size_t leftedge = openfile->firstcolumn; - /* If current[current_x] is more than a screen's worth of lines after - * edittop at column firstcolumn, it's below the screen. */ - return (go_forward_chunks(editwinrows - 1, &line, &leftedge) == 0 && - (line->lineno < openfile->current->lineno || - (line->lineno == openfile->current->lineno && - leftedge < leftedge_for(xplustabs(), - openfile->current)))); - } else + /* If current[current_x] is more than a screen's worth of lines after + * edittop at column firstcolumn, it's below the screen. */ + return (go_forward_chunks(editwinrows - 1, &line, &leftedge) == 0 && + (line->lineno < openfile->current->lineno || + (line->lineno == openfile->current->lineno && + leftedge < leftedge_for(xplustabs(), + openfile->current)))); + } else #endif - return (openfile->current->lineno >= - openfile->edittop->lineno + editwinrows); + return (openfile->current->lineno >= + openfile->edittop->lineno + editwinrows); } /* Return TRUE if current[current_x] is offscreen relative to edittop, and * FALSE otherwise. */ bool current_is_offscreen(void) { - return (current_is_above_screen() || current_is_below_screen()); + return (current_is_above_screen() || current_is_below_screen()); } /* Update any lines between old_current and current that need to be * updated. Use this if we've moved without changing any text. */ void edit_redraw(filestruct *old_current, update_type manner) { - size_t was_pww = openfile->placewewant; + size_t was_pww = openfile->placewewant; - openfile->placewewant = xplustabs(); + openfile->placewewant = xplustabs(); - /* If the current line is offscreen, scroll until it's onscreen. */ - if (current_is_offscreen()) { - adjust_viewport(ISSET(SMOOTH_SCROLL) ? manner : CENTERING); - refresh_needed = TRUE; - return; - } + /* If the current line is offscreen, scroll until it's onscreen. */ + if (current_is_offscreen()) { + adjust_viewport(ISSET(SMOOTH_SCROLL) ? manner : CENTERING); + refresh_needed = TRUE; + return; + } #ifndef NANO_TINY - /* If the mark is on, update all lines between old_current and current. */ - if (openfile->mark) { - filestruct *line = old_current; + /* If the mark is on, update all lines between old_current and current. */ + if (openfile->mark) { + filestruct *line = old_current; - while (line != openfile->current) { - update_line(line, 0); + while (line != openfile->current) { + update_line(line, 0); - line = (line->lineno > openfile->current->lineno) ? - line->prev : line->next; - } - } else + line = (line->lineno > openfile->current->lineno) ? + line->prev : line->next; + } + } else #endif - /* Otherwise, update old_current only if it differs from current - * and was horizontally scrolled. */ - if (old_current != openfile->current && get_page_start(was_pww) > 0) - update_line(old_current, 0); + /* Otherwise, update old_current only if it differs from current + * and was horizontally scrolled. */ + if (old_current != openfile->current && get_page_start(was_pww) > 0) + update_line(old_current, 0); - /* Update current if the mark is on or it has changed "page", or if it - * differs from old_current and needs to be horizontally scrolled. */ - if (line_needs_update(was_pww, openfile->placewewant) || - (old_current != openfile->current && - get_page_start(openfile->placewewant) > 0)) - update_line(openfile->current, openfile->current_x); + /* Update current if the mark is on or it has changed "page", or if it + * differs from old_current and needs to be horizontally scrolled. */ + if (line_needs_update(was_pww, openfile->placewewant) || + (old_current != openfile->current && + get_page_start(openfile->placewewant) > 0)) + update_line(openfile->current, openfile->current_x); } /* Refresh the screen without changing the position of lines. Use this * if we've moved and changed text. */ void edit_refresh(void) { - filestruct *line; - int row = 0; + filestruct *line; + int row = 0; #ifdef ENABLE_COLOR - /* When needed, initialize the colors for the current syntax. */ - if (!have_palette) - color_init(); + /* When needed, initialize the colors for the current syntax. */ + if (!have_palette) + color_init(); #endif - /* If the current line is out of view, get it back on screen. */ - if (current_is_offscreen()) - adjust_viewport((focusing || !ISSET(SMOOTH_SCROLL)) ? CENTERING : FLOWING); + /* If the current line is out of view, get it back on screen. */ + if (current_is_offscreen()) + adjust_viewport((focusing || !ISSET(SMOOTH_SCROLL)) ? CENTERING : FLOWING); - line = openfile->edittop; + line = openfile->edittop; - while (row < editwinrows && line != NULL) { - if (line == openfile->current) - row += update_line(line, openfile->current_x); - else - row += update_line(line, 0); - line = line->next; - } + while (row < editwinrows && line != NULL) { + if (line == openfile->current) + row += update_line(line, openfile->current_x); + else + row += update_line(line, 0); + line = line->next; + } - while (row < editwinrows) - blank_row(edit, row++, 0, COLS); + while (row < editwinrows) + blank_row(edit, row++, 0, COLS); - place_the_cursor(); - wnoutrefresh(edit); + place_the_cursor(); + wnoutrefresh(edit); - refresh_needed = FALSE; + refresh_needed = FALSE; } /* Move edittop so that current is on the screen. manner says how: @@ -3286,35 +3286,35 @@ void edit_refresh(void) * current into view. */ void adjust_viewport(update_type manner) { - int goal = 0; + int goal = 0; - if (manner == STATIONARY) - goal = openfile->current_y; - else if (manner == CENTERING) - goal = editwinrows / 2; - else if (!current_is_above_screen()) - goal = editwinrows - 1; + if (manner == STATIONARY) + goal = openfile->current_y; + else if (manner == CENTERING) + goal = editwinrows / 2; + else if (!current_is_above_screen()) + goal = editwinrows - 1; - openfile->edittop = openfile->current; + openfile->edittop = openfile->current; #ifndef NANO_TINY - if (ISSET(SOFTWRAP)) - openfile->firstcolumn = leftedge_for(xplustabs(), openfile->current); + if (ISSET(SOFTWRAP)) + openfile->firstcolumn = leftedge_for(xplustabs(), openfile->current); #endif - /* Move edittop back goal rows, starting at current[current_x]. */ - go_back_chunks(goal, &openfile->edittop, &openfile->firstcolumn); + /* Move edittop back goal rows, starting at current[current_x]. */ + go_back_chunks(goal, &openfile->edittop, &openfile->firstcolumn); } /* Unconditionally redraw the entire screen. */ void total_redraw(void) { #ifdef USE_SLANG - /* Slang curses emulation brain damage, part 4: Slang doesn't define - * curscr. */ - SLsmg_touch_screen(); - SLsmg_refresh(); + /* Slang curses emulation brain damage, part 4: Slang doesn't define + * curscr. */ + SLsmg_touch_screen(); + SLsmg_refresh(); #else - wrefresh(curscr); + wrefresh(curscr); #endif } @@ -3322,17 +3322,17 @@ void total_redraw(void) * the edit window (when not in the file browser), and the bottom bars. */ void total_refresh(void) { - total_redraw(); - if (currmenu != MBROWSER && currmenu != MWHEREISFILE && currmenu != MGOTODIR) - titlebar(title); + total_redraw(); + if (currmenu != MBROWSER && currmenu != MWHEREISFILE && currmenu != MGOTODIR) + titlebar(title); #ifdef ENABLE_HELP - if (inhelp) - wrap_the_help_text(TRUE); - else + if (inhelp) + wrap_the_help_text(TRUE); + else #endif - if (currmenu != MBROWSER && currmenu != MWHEREISFILE && currmenu != MGOTODIR) - edit_refresh(); - bottombars(currmenu); + if (currmenu != MBROWSER && currmenu != MWHEREISFILE && currmenu != MGOTODIR) + edit_refresh(); + bottombars(currmenu); } /* Display the main shortcut list on the last two rows of the bottom @@ -3340,14 +3340,14 @@ void total_refresh(void) void display_main_list(void) { #ifdef ENABLE_COLOR - if (openfile->syntax && - (openfile->syntax->formatter || openfile->syntax->linter)) - set_lint_or_format_shortcuts(); - else - set_spell_shortcuts(); + if (openfile->syntax && + (openfile->syntax->formatter || openfile->syntax->linter)) + set_lint_or_format_shortcuts(); + else + set_spell_shortcuts(); #endif - bottombars(MMAIN); + bottombars(MMAIN); } /* Show info about the current cursor position on the statusbar. @@ -3355,108 +3355,108 @@ void display_main_list(void) * suppress_cursorpos is FALSE. In any case, reset the latter. */ void do_cursorpos(bool force) { - char saved_byte; - size_t sum, cur_xpt = xplustabs() + 1; - size_t cur_lenpt = strlenpt(openfile->current->data) + 1; - int linepct, colpct, charpct; + char saved_byte; + size_t sum, cur_xpt = xplustabs() + 1; + size_t cur_lenpt = strlenpt(openfile->current->data) + 1; + int linepct, colpct, charpct; - /* If the showing needs to be suppressed, don't suppress it next time. */ - if (suppress_cursorpos && !force) { + /* If the showing needs to be suppressed, don't suppress it next time. */ + if (suppress_cursorpos && !force) { + suppress_cursorpos = FALSE; + return; + } + + /* Determine the size of the file up to the cursor. */ + saved_byte = openfile->current->data[openfile->current_x]; + openfile->current->data[openfile->current_x] = '\0'; + + sum = get_totsize(openfile->fileage, openfile->current); + + openfile->current->data[openfile->current_x] = saved_byte; + + /* When not at EOF, subtract 1 for an overcounted newline. */ + if (openfile->current != openfile->filebot) + sum--; + + /* Display the current cursor position on the statusbar. */ + linepct = 100 * openfile->current->lineno / openfile->filebot->lineno; + colpct = 100 * cur_xpt / cur_lenpt; + charpct = (openfile->totsize == 0) ? 0 : 100 * sum / openfile->totsize; + + statusline(HUSH, + _("line %zd/%zd (%d%%), col %zu/%zu (%d%%), char %zu/%zu (%d%%)"), + openfile->current->lineno, openfile->filebot->lineno, linepct, + cur_xpt, cur_lenpt, colpct, sum, openfile->totsize, charpct); + + /* Displaying the cursor position should not suppress it next time. */ suppress_cursorpos = FALSE; - return; - } - - /* Determine the size of the file up to the cursor. */ - saved_byte = openfile->current->data[openfile->current_x]; - openfile->current->data[openfile->current_x] = '\0'; - - sum = get_totsize(openfile->fileage, openfile->current); - - openfile->current->data[openfile->current_x] = saved_byte; - - /* When not at EOF, subtract 1 for an overcounted newline. */ - if (openfile->current != openfile->filebot) - sum--; - - /* Display the current cursor position on the statusbar. */ - linepct = 100 * openfile->current->lineno / openfile->filebot->lineno; - colpct = 100 * cur_xpt / cur_lenpt; - charpct = (openfile->totsize == 0) ? 0 : 100 * sum / openfile->totsize; - - statusline(HUSH, - _("line %zd/%zd (%d%%), col %zu/%zu (%d%%), char %zu/%zu (%d%%)"), - openfile->current->lineno, openfile->filebot->lineno, linepct, - cur_xpt, cur_lenpt, colpct, sum, openfile->totsize, charpct); - - /* Displaying the cursor position should not suppress it next time. */ - suppress_cursorpos = FALSE; } /* Unconditionally display the current cursor position. */ void do_cursorpos_void(void) { - do_cursorpos(TRUE); + do_cursorpos(TRUE); } void disable_waiting(void) { - waiting_mode = FALSE; - nodelay(edit, TRUE); + waiting_mode = FALSE; + nodelay(edit, TRUE); } void enable_waiting(void) { - waiting_mode = TRUE; - nodelay(edit, FALSE); + waiting_mode = TRUE; + nodelay(edit, FALSE); } /* Highlight the text between from_col and to_col when active is TRUE. * Remove the highlight when active is FALSE. */ void spotlight(bool active, size_t from_col, size_t to_col) { - char *word; - size_t word_span, room; + char *word; + size_t word_span, room; - place_the_cursor(); + place_the_cursor(); #ifndef NANO_TINY - if (ISSET(SOFTWRAP)) { - spotlight_softwrapped(active, from_col, to_col); - return; - } + if (ISSET(SOFTWRAP)) { + spotlight_softwrapped(active, from_col, to_col); + return; + } #endif - /* This is so we can show zero-length matches. */ - if (to_col == from_col) { - word = mallocstrcpy(NULL, " "); - to_col++; - } else - word = display_string(openfile->current->data, from_col, - to_col - from_col, FALSE); + /* This is so we can show zero-length matches. */ + if (to_col == from_col) { + word = mallocstrcpy(NULL, " "); + to_col++; + } else + word = display_string(openfile->current->data, from_col, + to_col - from_col, FALSE); - word_span = strlenpt(word); + word_span = strlenpt(word); - /* Compute the number of columns that are available for the word. */ - room = editwincols + get_page_start(from_col) - from_col; + /* Compute the number of columns that are available for the word. */ + room = editwincols + get_page_start(from_col) - from_col; - /* If the word is partially offscreen, reserve space for the "$". */ - if (word_span > room) - room--; + /* If the word is partially offscreen, reserve space for the "$". */ + if (word_span > room) + room--; - if (active) - wattron(edit, interface_color_pair[SELECTED_TEXT]); + if (active) + wattron(edit, interface_color_pair[SELECTED_TEXT]); - waddnstr(edit, word, actual_x(word, room)); + waddnstr(edit, word, actual_x(word, room)); - if (word_span > room) - waddch(edit, '$'); + if (word_span > room) + waddch(edit, '$'); - if (active) - wattroff(edit, interface_color_pair[SELECTED_TEXT]); + if (active) + wattroff(edit, interface_color_pair[SELECTED_TEXT]); - free(word); + free(word); - wnoutrefresh(edit); + wnoutrefresh(edit); } #ifndef NANO_TINY @@ -3465,51 +3465,51 @@ void spotlight(bool active, size_t from_col, size_t to_col) * line breaks, since they're not actually part of the spotlighted text. */ void spotlight_softwrapped(bool active, size_t from_col, size_t to_col) { - ssize_t row = openfile->current_y; - size_t leftedge = leftedge_for(from_col, openfile->current); - size_t break_col; - bool end_of_line = FALSE; - char *word; + ssize_t row = openfile->current_y; + size_t leftedge = leftedge_for(from_col, openfile->current); + size_t break_col; + bool end_of_line = FALSE; + char *word; - while (row < editwinrows) { - break_col = get_softwrap_breakpoint(openfile->current->data, - leftedge, &end_of_line); + while (row < editwinrows) { + break_col = get_softwrap_breakpoint(openfile->current->data, + leftedge, &end_of_line); - /* Stop after the end of the word, by pretending the end of the word is - * the end of the line. */ - if (break_col >= to_col) { - end_of_line = TRUE; - break_col = to_col; + /* Stop after the end of the word, by pretending the end of the word is + * the end of the line. */ + if (break_col >= to_col) { + end_of_line = TRUE; + break_col = to_col; + } + + /* This is so we can show zero-length matches. */ + if (break_col == from_col) { + word = mallocstrcpy(NULL, " "); + break_col++; + } else + word = display_string(openfile->current->data, from_col, + break_col - from_col, FALSE); + + if (active) + wattron(edit, interface_color_pair[SELECTED_TEXT]); + + waddnstr(edit, word, actual_x(word, break_col)); + + if (active) + wattroff(edit, interface_color_pair[SELECTED_TEXT]); + + free(word); + + if (end_of_line) + break; + + wmove(edit, ++row, 0); + + leftedge = break_col; + from_col = break_col; } - /* This is so we can show zero-length matches. */ - if (break_col == from_col) { - word = mallocstrcpy(NULL, " "); - break_col++; - } else - word = display_string(openfile->current->data, from_col, - break_col - from_col, FALSE); - - if (active) - wattron(edit, interface_color_pair[SELECTED_TEXT]); - - waddnstr(edit, word, actual_x(word, break_col)); - - if (active) - wattroff(edit, interface_color_pair[SELECTED_TEXT]); - - free(word); - - if (end_of_line) - break; - - wmove(edit, ++row, 0); - - leftedge = break_col; - from_col = break_col; - } - - wnoutrefresh(edit); + wnoutrefresh(edit); } #endif @@ -3521,145 +3521,145 @@ void spotlight_softwrapped(bool active, size_t from_col, size_t to_col) * are FALSE. */ void do_credits(void) { - bool old_more_space = ISSET(MORE_SPACE); - bool old_no_help = ISSET(NO_HELP); - int kbinput = ERR, crpos = 0, xlpos = 0; - const char *credits[CREDIT_LEN] = { - NULL, /* "The nano text editor" */ - NULL, /* "version" */ - VERSION, - "", - NULL, /* "Brought to you by:" */ - "Chris Allegretta", - "Jordi Mallach", - "Adam Rogoyski", - "Rob Siemborski", - "Rocco Corsi", - "David Lawrence Ramsey", - "David Benbennick", - "Mark Majeres", - "Mike Frysinger", - "Benno Schulenberg", - "Ken Tyler", - "Sven Guckes", - "Bill Soudan", - "Christian Weisgerber", - "Erik Andersen", - "Big Gaute", - "Joshua Jensen", - "Ryan Krebs", - "Albert Chin", - "", - NULL, /* "Special thanks to:" */ - "Monique, Brielle & Joseph", - "Plattsburgh State University", - "Benet Laboratories", - "Amy Allegretta", - "Linda Young", - "Jeremy Robichaud", - "Richard Kolb II", - NULL, /* "The Free Software Foundation" */ - "Linus Torvalds", - NULL, /* "the many translators and the TP" */ - NULL, /* "For ncurses:" */ - "Thomas Dickey", - "Pavel Curtis", - "Zeyd Ben-Halim", - "Eric S. Raymond", - NULL, /* "and anyone else we forgot..." */ - NULL, /* "Thank you for using nano!" */ - "", - "", - "", - "", - "(C) 2017", - "Free Software Foundation, Inc.", - "", - "", - "", - "", - "https://nano-editor.org/" - }; + bool old_more_space = ISSET(MORE_SPACE); + bool old_no_help = ISSET(NO_HELP); + int kbinput = ERR, crpos = 0, xlpos = 0; + const char *credits[CREDIT_LEN] = { + NULL, /* "The nano text editor" */ + NULL, /* "version" */ + VERSION, + "", + NULL, /* "Brought to you by:" */ + "Chris Allegretta", + "Jordi Mallach", + "Adam Rogoyski", + "Rob Siemborski", + "Rocco Corsi", + "David Lawrence Ramsey", + "David Benbennick", + "Mark Majeres", + "Mike Frysinger", + "Benno Schulenberg", + "Ken Tyler", + "Sven Guckes", + "Bill Soudan", + "Christian Weisgerber", + "Erik Andersen", + "Big Gaute", + "Joshua Jensen", + "Ryan Krebs", + "Albert Chin", + "", + NULL, /* "Special thanks to:" */ + "Monique, Brielle & Joseph", + "Plattsburgh State University", + "Benet Laboratories", + "Amy Allegretta", + "Linda Young", + "Jeremy Robichaud", + "Richard Kolb II", + NULL, /* "The Free Software Foundation" */ + "Linus Torvalds", + NULL, /* "the many translators and the TP" */ + NULL, /* "For ncurses:" */ + "Thomas Dickey", + "Pavel Curtis", + "Zeyd Ben-Halim", + "Eric S. Raymond", + NULL, /* "and anyone else we forgot..." */ + NULL, /* "Thank you for using nano!" */ + "", + "", + "", + "", + "(C) 2017", + "Free Software Foundation, Inc.", + "", + "", + "", + "", + "https://nano-editor.org/" + }; - const char *xlcredits[XLCREDIT_LEN] = { - N_("The nano text editor"), - N_("version"), - N_("Brought to you by:"), - N_("Special thanks to:"), - N_("The Free Software Foundation"), - N_("the many translators and the TP"), - N_("For ncurses:"), - N_("and anyone else we forgot..."), - N_("Thank you for using nano!") - }; + const char *xlcredits[XLCREDIT_LEN] = { + N_("The nano text editor"), + N_("version"), + N_("Brought to you by:"), + N_("Special thanks to:"), + N_("The Free Software Foundation"), + N_("the many translators and the TP"), + N_("For ncurses:"), + N_("and anyone else we forgot..."), + N_("Thank you for using nano!") + }; - if (!old_more_space || !old_no_help) { - SET(MORE_SPACE); - SET(NO_HELP); - window_init(); - } - - nodelay(edit, TRUE); - - blank_titlebar(); - blank_edit(); - blank_statusbar(); - - wrefresh(topwin); - wrefresh(edit); - wrefresh(bottomwin); - napms(700); - - for (crpos = 0; crpos < CREDIT_LEN + editwinrows / 2; crpos++) { - if ((kbinput = wgetch(edit)) != ERR) - break; - - if (crpos < CREDIT_LEN) { - const char *what; - size_t start_col; - - if (credits[crpos] == NULL) - what = _(xlcredits[xlpos++]); - else - what = credits[crpos]; - - start_col = COLS / 2 - strlenpt(what) / 2 - 1; - mvwaddstr(edit, editwinrows - 1 - (editwinrows % 2), - start_col, what); + if (!old_more_space || !old_no_help) { + SET(MORE_SPACE); + SET(NO_HELP); + window_init(); } - wrefresh(edit); + nodelay(edit, TRUE); - if ((kbinput = wgetch(edit)) != ERR) - break; + blank_titlebar(); + blank_edit(); + blank_statusbar(); + + wrefresh(topwin); + wrefresh(edit); + wrefresh(bottomwin); napms(700); - scrollok(edit, TRUE); - wscrl(edit, 1); - scrollok(edit, FALSE); - wrefresh(edit); + for (crpos = 0; crpos < CREDIT_LEN + editwinrows / 2; crpos++) { + if ((kbinput = wgetch(edit)) != ERR) + break; - if ((kbinput = wgetch(edit)) != ERR) - break; - napms(700); + if (crpos < CREDIT_LEN) { + const char *what; + size_t start_col; - scrollok(edit, TRUE); - wscrl(edit, 1); - scrollok(edit, FALSE); - wrefresh(edit); - } + if (credits[crpos] == NULL) + what = _(xlcredits[xlpos++]); + else + what = credits[crpos]; - if (kbinput != ERR) - ungetch(kbinput); + start_col = COLS / 2 - strlenpt(what) / 2 - 1; + mvwaddstr(edit, editwinrows - 1 - (editwinrows % 2), + start_col, what); + } - if (!old_more_space) - UNSET(MORE_SPACE); - if (!old_no_help) - UNSET(NO_HELP); - window_init(); + wrefresh(edit); - nodelay(edit, FALSE); + if ((kbinput = wgetch(edit)) != ERR) + break; + napms(700); - total_refresh(); + scrollok(edit, TRUE); + wscrl(edit, 1); + scrollok(edit, FALSE); + wrefresh(edit); + + if ((kbinput = wgetch(edit)) != ERR) + break; + napms(700); + + scrollok(edit, TRUE); + wscrl(edit, 1); + scrollok(edit, FALSE); + wrefresh(edit); + } + + if (kbinput != ERR) + ungetch(kbinput); + + if (!old_more_space) + UNSET(MORE_SPACE); + if (!old_no_help) + UNSET(NO_HELP); + window_init(); + + nodelay(edit, FALSE); + + total_refresh(); } #endif /* ENABLE_EXTRA */