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 */