commit ad40fdba593614b6fe92373c9e84c90698d27a30
parent f7c6811e36e5fdda1c23a4b210411777546b63e2
Author: David Lawrence Ramsey <pooka109@gmail.com>
Date: Fri, 6 Sep 2002 20:35:28 +0000
DLR: prototype overhaul, etc.
git-svn-id: svn://svn.savannah.gnu.org/nano/trunk/nano@1270 35c25a1d-7b9e-4130-9fde-d3aeb78583b8
Diffstat:
M | ChangeLog | | | 32 | ++++++++++++++++++++++++++++++++ |
M | configure.ac | | | 113 | +++++++++++++++++++++++++++++++++++++------------------------------------------ |
M | files.c | | | 119 | ++++++++++++++++++++++++++++++++++++++++--------------------------------------- |
M | global.c | | | 34 | ++++++++++++++++++---------------- |
M | move.c | | | 102 | ++++++++++++++++++++++++++++++++++++++++---------------------------------------- |
M | nano.c | | | 2657 | ++++++++++++++++++++++++++++++++++++++++--------------------------------------- |
M | nano.h | | | 1 | + |
M | proto.h | | | 327 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------------- |
M | rcfile.c | | | 36 | ++++++++++++++++++------------------ |
M | search.c | | | 80 | ++++++++++++++++++++++++++++++++++++++++--------------------------------------- |
M | utils.c | | | 9 | +++++---- |
M | winio.c | | | 313 | +++++++++++++++++++++++++++++++++++++++---------------------------------------- |
12 files changed, 2001 insertions(+), 1822 deletions(-)
diff --git a/ChangeLog b/ChangeLog
@@ -11,13 +11,27 @@ CVS code -
need to keep the translatable strings, and (b) added a
variable inspath to keep track of what the string was before
toggling. I'm sure there's bugs, have at it.
+ - Make sure all functions have prototypes in proto.h, and swap
+ some functions around to put similar functions closer
+ together (for this, rename clear_bottombars() to
+ blank_bottombars()). (DLR; suggested by David Benbennick)
- configure.ac:
- Added pt_BR to ALL_LINGUAS (Jordi).
- Changed --enable-color warning to be slightly less severe.
+ - Put the configure options in more or less alphabetical order,
+ and remove --enable-undo, since it doesn't do anything. (DLR)
- files.c:
open_file()
- String change: "File "x" is a directory" -> ""x" is a
directory". (Jordi)
+ do_insertfile()
+ - Disallow multibuffer toggling at the "Insert File" prompt if
+ we're in both view and multibuffer mode, so as to keep proper
+ integration between the two, and make sure the toggle
+ actually works all the time otherwise. Also, use
+ NANO_LOAD_KEY as an alias for TOGGLE_LOAD_KEY, so
+ --enable-tiny and --enable-multibuffer can be used together
+ again. (DLR)
open_prevfile_void(), open_nextfile_void()
- Return the return values of open_prevfile() and
open_nextfile(), respectively, instead of (incorrectly)
@@ -29,6 +43,14 @@ CVS code -
- Most likely fixed the check marked with FIXME, so that tab
completion works properly when we're trying to tab-complete a
username and the string already contains data. (DLR)
+- global.c:
+ shortcut_init()
+ - Use NANO_LOAD_KEY as an alias for TOGGLE_LOAD_KEY, so
+ --enable-tiny and --enable-multibuffer can be used together
+ again. (DLR)
+ thanks_for_all_the_fish()
+ - Make sure the reference to help_text is #ifdefed out when
+ --disable-help is used. (DLR)
- move.c:
page_up()
- Fix bug where current is moved up two lines when the up arrow
@@ -42,6 +64,12 @@ CVS code -
off, pressing the down arrow on that last line centers the
cursor without updating the edit window. (Jeff DeFouw)
- nano.c:
+ version()
+ - Put the listed configure options in more or less alphabetical
+ order. (DLR)
+ open_pipe()
+ - If we're in view mode here (in which case we're also in
+ multibuffer mode), don't set the modification flag. (DLR)
do_next_word(), do_prev_word()
- If we're on the last/first line of the file, don't center the
screen; Pico doesn't in the former case. (DLR)
@@ -65,6 +93,10 @@ CVS code -
do_justify()
- Fix cosmetic problems caused when justifying on the
magicline. (David Benbennick)
+ main()
+ - When searching through the main shortcut list looking for a
+ shortcut key, stop searching after finding one; this avoids a
+ rare segfault. (DLR)
- nano.h:
- Change search toggles for case sensitive searching and regexp
searching to M-C and M-R, respectively. (DLR; suggested by
diff --git a/configure.ac b/configure.ac
@@ -29,70 +29,55 @@ if test "$debug_support" != "yes"; then
AC_DEFINE(NDEBUG, 1, [Shut up the assert warnings :-)])
fi
+AC_ARG_ENABLE(extra,
+[ --enable-extra Enable extra (optional) functions, including easter eggs],
+[if test x$enableval = xyes; then
+ AC_DEFINE(NANO_EXTRA, 1, [Define this to enable the extra stuff.]) extra_support=yes
+ AC_DEFINE(ENABLE_MULTIBUFFER, 1, [Define this to enable multiple file buffers.]) multibuffer_support=yes
+ fi])
+
AC_ARG_ENABLE(tiny,
[ --enable-tiny Disable features for the sake of size
(currently disables detailed help and i18n)],
[if test x$enableval = xyes; then
AC_DEFINE(NANO_SMALL, 1, [Define this to make the nano executable as small as possible.]) tiny_support=yes
- AC_DEFINE(DISABLE_TABCOMP, 1, [Define to disable the tab completion code Chris worked so hard on!])
- AC_DEFINE(DISABLE_SPELLER, 1, [Define this to disable the use(full|less) spelling functions.])
+ AC_DEFINE(DISABLE_BROWSER, 1, [Define this to disable the built-in (crappy) file browser.])
AC_DEFINE(DISABLE_HELP, 1, [Define this to disable the ^G help menu.])
AC_DEFINE(DISABLE_JUSTIFY, 1, [Define this to disable the justify routine.])
- AC_DEFINE(DISABLE_BROWSER, 1, [Define this to disable the built-in (crappy) file browser.])
AC_DEFINE(DISABLE_MOUSE, 1, [Define this to disable the mouse functions.])
AC_DEFINE(DISABLE_OPERATINGDIR, 1, [Define this to disable setting of the operating directory (chroot of sorts).])
+ AC_DEFINE(DISABLE_SPELLER, 1, [Define this to disable the use(full|less) spelling functions.])
+ AC_DEFINE(DISABLE_TABCOMP, 1, [Define to disable the tab completion code Chris worked so hard on!])
fi])
-AC_ARG_ENABLE(extra,
-[ --enable-extra Enable extra (optional) functions, including easter eggs],
-[if test x$enableval = xyes; then
- AC_DEFINE(NANO_EXTRA, 1, [Define this to enable the extra stuff.]) extra_support=yes
- AC_DEFINE(ENABLE_MULTIBUFFER, 1, [Define this to enable multiple file buffers.]) multibuffer_support=yes
- AC_DEFINE(ENABLE_UNDO, 1, [Define this to enable undoing... something]) undo_support=yes
- fi])
-
-AC_ARG_ENABLE(undo,
-[ --enable-undo Enable undo support],
-[if test x$enableval = xyes && test x$tiny_support != xyes; then
- AC_DEFINE(ENABLE_UNDO, 1, [Define this to enable undoing... something.]) undo_support=yes
+AC_ARG_ENABLE(browser,
+[ --disable-browser Disable mini file browser],
+ [if test x$enableval != xyes; then
+ AC_DEFINE(DISABLE_BROWSER, 1, [Define this to disable the built-in (crappy) file browser.])
fi])
-AC_ARG_ENABLE(multibuffer,
-[ --enable-multibuffer Enable multiple file buffers],
-[if test x$enableval = xyes; then
- AC_DEFINE(ENABLE_MULTIBUFFER, 1, [Define this to enable multiple file buffers.]) multibuffer_support=yes
+AC_ARG_ENABLE(help,
+[ --disable-help Disable help function (^G)],
+ [if test x$enableval != xyes; then
+ AC_DEFINE(DISABLE_HELP, 1, [Define this to disable the ^G help menu.])
fi])
-AC_ARG_ENABLE(nanorc,
-[ --enable-nanorc Enable use of .nanorc file],
-[if test x$enableval = xyes; then
- AC_DEFINE(ENABLE_NANORC, 1, [Define this to use the .nanorc file.]) nanorc_support=yes
+AC_ARG_ENABLE(justify,
+[ --disable-justify Disable justify/unjustify function],
+ [if test x$enableval != xyes; then
+ AC_DEFINE(DISABLE_JUSTIFY, 1, [Define this to disable the justify routine.])
fi])
-AC_ARG_ENABLE(color,
-[ --enable-color Enable color and syntax highlighting],
-[if test x$enableval = xyes; then
- AC_DEFINE(ENABLE_NANORC, 1, [Define this to use the .nanorc file.]) nanorc_support=yes
- AC_DEFINE(ENABLE_COLOR, 1, [Define this to have syntax highlighting, requires ENABLE_NANORC too!]) color_support=yes
- AC_MSG_WARN([
-
-***********************************************************************
-*** WARNING: Color support is far from perfect, but functional. ***
-*** Be careful with syntax in your .nanorc or nano may malfunction. ***
-***********************************************************************
-])
-fi])
-
-AC_ARG_ENABLE(tabcomp,
-[ --disable-tabcomp Disable tab completion code for a smaller binary],
+AC_ARG_ENABLE(mouse,
+[ --disable-mouse Disable mouse support (and -m flag)],
[if test x$enableval != xyes; then
- AC_DEFINE(DISABLE_TABCOMP, 1, [Define to disable the tab completion code Chris worked so hard on!])
+ AC_DEFINE(DISABLE_MOUSE, 1, [Define this to disable the mouse functions.])
fi])
-AC_ARG_ENABLE(justify,
-[ --disable-justify Disable justify/unjustify function],
+AC_ARG_ENABLE(operatingdir,
+[ --disable-operatingdir Disable setting of operating directory (chroot of sorts)],
[if test x$enableval != xyes; then
- AC_DEFINE(DISABLE_JUSTIFY, 1, [Define this to disable the justify routine.])
+ AC_DEFINE(DISABLE_OPERATINGDIR, 1, [Define this to disable setting of the operating directory (chroot of sorts).])
fi])
AC_ARG_ENABLE(speller,
@@ -101,16 +86,10 @@ AC_ARG_ENABLE(speller,
AC_DEFINE(DISABLE_SPELLER, 1, [Define this to disable the use(full|less) spelling functions.])
fi])
-AC_ARG_ENABLE(help,
-[ --disable-help Disable help function (^G)],
- [if test x$enableval != xyes; then
- AC_DEFINE(DISABLE_HELP, 1, [Define this to disable the ^G help menu.])
- fi])
-
-AC_ARG_ENABLE(browser,
-[ --disable-browser Disable mini file browser],
+AC_ARG_ENABLE(tabcomp,
+[ --disable-tabcomp Disable tab completion code for a smaller binary],
[if test x$enableval != xyes; then
- AC_DEFINE(DISABLE_BROWSER, 1, [Define this to disable the built-in (crappy) file browser.])
+ AC_DEFINE(DISABLE_TABCOMP, 1, [Define to disable the tab completion code Chris worked so hard on!])
fi])
AC_ARG_ENABLE(wrapping,
@@ -119,16 +98,30 @@ AC_ARG_ENABLE(wrapping,
AC_DEFINE(DISABLE_WRAPPING, 1, [Define this to disable any and all text wrapping.])
fi])
-AC_ARG_ENABLE(mouse,
-[ --disable-mouse Disable mouse support (and -m flag)],
- [if test x$enableval != xyes; then
- AC_DEFINE(DISABLE_MOUSE, 1, [Define this to disable the mouse functions.])
+AC_ARG_ENABLE(color,
+[ --enable-color Enable color and syntax highlighting],
+[if test x$enableval = xyes; then
+ AC_DEFINE(ENABLE_NANORC, 1, [Define this to use the .nanorc file.]) nanorc_support=yes
+ AC_DEFINE(ENABLE_COLOR, 1, [Define this to have syntax highlighting, requires ENABLE_NANORC too!]) color_support=yes
+ AC_MSG_WARN([
+
+***********************************************************************
+*** WARNING: Color support is far from perfect, but functional. ***
+*** Be careful with syntax in your .nanorc or nano may malfunction. ***
+***********************************************************************
+])
+fi])
+
+AC_ARG_ENABLE(multibuffer,
+[ --enable-multibuffer Enable multiple file buffers],
+[if test x$enableval = xyes; then
+ AC_DEFINE(ENABLE_MULTIBUFFER, 1, [Define this to enable multiple file buffers.]) multibuffer_support=yes
fi])
-AC_ARG_ENABLE(operatingdir,
-[ --disable-operatingdir Disable setting of operating directory (chroot of sorts)],
- [if test x$enableval != xyes; then
- AC_DEFINE(DISABLE_OPERATINGDIR, 1, [Define this to disable setting of the operating directory (chroot of sorts).])
+AC_ARG_ENABLE(nanorc,
+[ --enable-nanorc Enable use of .nanorc file],
+[if test x$enableval = xyes; then
+ AC_DEFINE(ENABLE_NANORC, 1, [Define this to use the .nanorc file.]) nanorc_support=yes
fi])
AC_MSG_CHECKING([whether to use slang])
diff --git a/files.c b/files.c
@@ -103,7 +103,6 @@ void new_file(void)
#ifdef ENABLE_COLOR
update_color();
#endif
-
}
filestruct *read_line(char *buf, filestruct *prev, int *line1ins, int len)
@@ -453,14 +452,11 @@ int do_insertfile(int loading_file)
i = statusq(1, insertfile_list, inspath, _("File to insert [from ./] "));
if (i != -1) {
-
inspath = mallocstrcpy(inspath, answer);
-
#ifdef DEBUG
fprintf(stderr, _("filename is %s\n"), answer);
#endif
-
#ifndef DISABLE_TABCOMP
realname = real_dir_from_tilde(answer);
#else
@@ -494,9 +490,12 @@ int do_insertfile(int loading_file)
#endif
#ifdef ENABLE_MULTIBUFFER
- if (i == TOGGLE_LOAD_KEY) {
- TOGGLE(MULTIBUFFER);
- return do_insertfile(loading_file);
+ if (i == NANO_LOAD_KEY) {
+ /* don't allow toggling if we're in both view mode and
+ multibuffer mode now */
+ if (!ISSET(VIEW_MODE) || !ISSET(MULTIBUFFER))
+ TOGGLE(MULTIBUFFER);
+ return do_insertfile(ISSET(MULTIBUFFER));
}
#endif
#ifndef NANO_SMALL
@@ -574,8 +573,6 @@ int do_insertfile(int loading_file)
}
#endif
-
-
/* If we've gone off the bottom, recenter; otherwise, just redraw */
if (current->lineno > editbot->lineno)
edit_update(current, CENTER);
@@ -1139,8 +1136,8 @@ char *get_full_path(char *origpath)
* get_full_path()). On error, if the path doesn't reference a
* directory, or if the directory isn't writable, it returns NULL.
*/
-char *check_writable_directory(char *path) {
-
+char *check_writable_directory(char *path)
+{
char *full_path = get_full_path(path);
int writable;
struct stat fileinfo;
@@ -1178,8 +1175,8 @@ char *check_writable_directory(char *path) {
* implementation is to go on generating random filenames regardless of
* it.
*/
-char *safe_tempnam(const char *dirname, const char *filename_prefix) {
-
+char *safe_tempnam(const char *dirname, const char *filename_prefix)
+{
char *buf, *tempdir = NULL, *full_tempdir = NULL;
int filedesc;
@@ -2221,6 +2218,12 @@ char *input_tab(char *buf, int place, int *lastwastab, int *newplace, int *list)
buf = mallocstrcpy(buf, tmp);
matches = username_tab_completion(tmp, &num_matches);
}
+ /* If we're in the middle of the original line, copy the string
+ only up to the cursor position into buf, so tab completion
+ will result in buf's containing only the tab-completed
+ path/filename. */
+ else if (strlen(buf) > strlen(tmp))
+ buf = mallocstrcpy(buf, tmp);
/* Try to match everything in the current working directory that
* matches. */
@@ -2416,51 +2419,6 @@ int diralphasort(const void *va, const void *vb)
}
-/* Initialize the browser code, including the list of files in *path */
-char **browser_init(char *path, int *longest, int *numents)
-{
- DIR *dir;
- struct dirent *next;
- char **filelist = (char **) NULL;
- int i = 0;
-
- dir = opendir(path);
- if (!dir)
- return NULL;
-
- *numents = 0;
- while ((next = readdir(dir)) != NULL) {
- if (!strcmp(next->d_name, "."))
- continue;
- (*numents)++;
- if (strlen(next->d_name) > *longest)
- *longest = strlen(next->d_name);
- }
- rewinddir(dir);
- *longest += 10;
-
- filelist = nmalloc(*numents * sizeof (char *));
-
- while ((next = readdir(dir)) != NULL) {
- if (!strcmp(next->d_name, "."))
- continue;
- filelist[i] = charalloc(strlen(next->d_name) + strlen(path) + 2);
-
- if (!strcmp(path, "/"))
- snprintf(filelist[i], strlen(next->d_name) + strlen(path) + 1,
- "%s%s", path, next->d_name);
- else
- snprintf(filelist[i], strlen(next->d_name) + strlen(path) + 2,
- "%s/%s", path, next->d_name);
- i++;
- }
-
- if (*longest > COLS - 1)
- *longest = COLS - 1;
-
- return filelist;
-}
-
/* Free our malloc()ed memory */
void free_charptrarray(char **array, int len)
{
@@ -2513,6 +2471,51 @@ void striponedir(char *foo)
return;
}
+/* Initialize the browser code, including the list of files in *path */
+char **browser_init(char *path, int *longest, int *numents)
+{
+ DIR *dir;
+ struct dirent *next;
+ char **filelist = (char **) NULL;
+ int i = 0;
+
+ dir = opendir(path);
+ if (!dir)
+ return NULL;
+
+ *numents = 0;
+ while ((next = readdir(dir)) != NULL) {
+ if (!strcmp(next->d_name, "."))
+ continue;
+ (*numents)++;
+ if (strlen(next->d_name) > *longest)
+ *longest = strlen(next->d_name);
+ }
+ rewinddir(dir);
+ *longest += 10;
+
+ filelist = nmalloc(*numents * sizeof (char *));
+
+ while ((next = readdir(dir)) != NULL) {
+ if (!strcmp(next->d_name, "."))
+ continue;
+ filelist[i] = charalloc(strlen(next->d_name) + strlen(path) + 2);
+
+ if (!strcmp(path, "/"))
+ snprintf(filelist[i], strlen(next->d_name) + strlen(path) + 1,
+ "%s%s", path, next->d_name);
+ else
+ snprintf(filelist[i], strlen(next->d_name) + strlen(path) + 2,
+ "%s/%s", path, next->d_name);
+ i++;
+ }
+
+ if (*longest > COLS - 1)
+ *longest = COLS - 1;
+
+ return filelist;
+}
+
/* Our browser function. inpath is the path to start browsing from */
char *do_browser(char *inpath)
{
diff --git a/global.c b/global.c
@@ -217,19 +217,6 @@ void toggle_init_one(int val, const char *desc, int flag)
u->next = NULL;
}
-#ifdef DEBUG
-/* Deallocate all of the toggles. */
-void free_toggles(void)
-{
- while (toggles != NULL) {
- toggle *pt = toggles; /* Think "previous toggle" */
-
- toggles = toggles->next;
- free(pt);
- }
-}
-#endif
-
void toggle_init(void)
{
char *toggle_const_msg, *toggle_autoindent_msg, *toggle_suspend_msg,
@@ -288,6 +275,19 @@ void toggle_init(void)
toggle_init_one(TOGGLE_BACKUP_KEY, toggle_backup_msg, BACKUP_FILE);
toggle_init_one(TOGGLE_SMOOTH_KEY, toggle_smooth_msg, SMOOTHSCROLL);
}
+
+#ifdef DEBUG
+/* Deallocate all of the toggles. */
+void free_toggles(void)
+{
+ while (toggles != NULL) {
+ toggle *pt = toggles; /* Think "previous toggle" */
+
+ toggles = toggles->next;
+ free(pt);
+ }
+}
+#endif
#endif /* !NANO_SMALL */
/* Deallocate the given shortcut. */
@@ -325,8 +325,8 @@ void shortcut_init(int unjustify)
"", *nano_backup_msg = "";
#ifdef ENABLE_MULTIBUFFER
- char *nano_openprev_msg = "", *nano_opennext_msg = "",
- *nano_multibuffer_msg = "";
+ char *nano_openprev_msg = "", *nano_opennext_msg =
+ "", *nano_multibuffer_msg = "";
#endif
#ifdef HAVE_REGEX_H
char *nano_regexp_msg = "", *nano_bracket_msg = "";
@@ -727,7 +727,7 @@ void shortcut_init(int unjustify)
IFHELP(nano_execute_msg, 0), 0, 0, NOVIEW, 0);
#endif
#ifdef ENABLE_MULTIBUFFER
- sc_init_one(&insertfile_list, TOGGLE_LOAD_KEY, _("New Buffer"),
+ sc_init_one(&insertfile_list, NANO_LOAD_KEY, _("New Buffer"),
IFHELP(nano_multibuffer_msg, 0), 0, 0, NOVIEW, 0);
#endif
@@ -811,8 +811,10 @@ void thanks_for_all_the_fish(void)
if (alt_speller != NULL)
free(alt_speller);
#endif
+#ifndef DISABLE_HELP
if (help_text != NULL)
free(help_text);
+#endif
if (filename != NULL)
free(filename);
if (answer != NULL)
diff --git a/move.c b/move.c
@@ -35,43 +35,6 @@
#define _(string) (string)
#endif
-int do_page_down(void)
-{
- wrap_reset();
- current_x = 0;
- placewewant = 0;
-
- if (current == filebot)
- return 0;
-
- /* AHEM, if we only have a screen or less of text, DON'T do an
- edit_update, just move the cursor to editbot! */
- if (edittop == fileage && editbot == filebot && totlines < editwinrows) {
- current = editbot;
- reset_cursor();
- } else if (editbot != filebot || edittop == fileage) {
- current_y = 0;
- current = editbot;
-
- if (current->prev != NULL)
- current = current->prev;
- if (current->prev != NULL)
- current = current->prev;
- edit_update(current, TOP);
- } else {
- while (current != filebot) {
- current = current->next;
- current_y++;
- }
- edit_update(edittop, TOP);
- }
-
- update_cursor();
- UNSET(KEEP_CUTBUFFER);
- check_statblank();
- return 1;
-}
-
int do_home(void)
{
UNSET(KEEP_CUTBUFFER);
@@ -138,6 +101,43 @@ int do_page_up(void)
return 1;
}
+int do_page_down(void)
+{
+ wrap_reset();
+ current_x = 0;
+ placewewant = 0;
+
+ if (current == filebot)
+ return 0;
+
+ /* AHEM, if we only have a screen or less of text, DON'T do an
+ edit_update, just move the cursor to editbot! */
+ if (edittop == fileage && editbot == filebot && totlines < editwinrows) {
+ current = editbot;
+ reset_cursor();
+ } else if (editbot != filebot || edittop == fileage) {
+ current_y = 0;
+ current = editbot;
+
+ if (current->prev != NULL)
+ current = current->prev;
+ if (current->prev != NULL)
+ current = current->prev;
+ edit_update(current, TOP);
+ } else {
+ while (current != filebot) {
+ current = current->next;
+ current_y++;
+ }
+ edit_update(edittop, TOP);
+ }
+
+ update_cursor();
+ UNSET(KEEP_CUTBUFFER);
+ check_statblank();
+ return 1;
+}
+
int do_up(void)
{
wrap_reset();
@@ -197,15 +197,13 @@ int do_down(void) {
return 1;
}
-int do_right(void)
+int do_left(void)
{
- assert(current_x <= strlen(current->data));
-
- if (current->data[current_x] != '\0')
- current_x++;
- else if (current->next) {
- do_down();
- current_x = 0;
+ if (current_x > 0)
+ current_x--;
+ else if (current != fileage) {
+ do_up();
+ current_x = strlen(current->data);
}
placewewant = xplustabs();
update_line(current, current_x);
@@ -214,13 +212,15 @@ int do_right(void)
return 1;
}
-int do_left(void)
+int do_right(void)
{
- if (current_x > 0)
- current_x--;
- else if (current != fileage) {
- do_up();
- current_x = strlen(current->data);
+ assert(current_x <= strlen(current->data));
+
+ if (current->data[current_x] != '\0')
+ current_x++;
+ else if (current->next) {
+ do_down();
+ current_x = 0;
}
placewewant = xplustabs();
update_line(current, current_x);
diff --git a/nano.c b/nano.c
@@ -222,6 +222,258 @@ void global_init(int save_cutbuffer)
hblank[COLS] = '\0';
}
+void window_init(void)
+{
+ if ((editwinrows = LINES - 5 + no_help()) < MIN_EDITOR_ROWS)
+ die_too_small();
+
+ /* Set up the main text window */
+ edit = newwin(editwinrows, COLS, 2, 0);
+
+ /* And the other windows */
+ topwin = newwin(2, COLS, 0, 0);
+ bottomwin = newwin(3 - no_help(), COLS, LINES - 3 + no_help(), 0);
+
+#ifdef PDCURSES
+ /* Oops, I guess we need this again.
+ Moved here so the keypad still works after a Meta-X, for example */
+ keypad(edit, TRUE);
+ keypad(bottomwin, TRUE);
+#endif
+}
+
+void mouse_init(void)
+{
+#ifndef DISABLE_MOUSE
+#ifdef NCURSES_MOUSE_VERSION
+ if (ISSET(USE_MOUSE)) {
+ keypad_on(edit, 1);
+ keypad_on(bottomwin, 1);
+
+ mousemask(BUTTON1_RELEASED, NULL);
+ mouseinterval(50);
+ } else
+ mousemask(0, NULL);
+#endif
+#endif
+}
+
+#ifndef DISABLE_HELP
+/* This function allocates help_text, and stores the help string in it.
+ * help_text should be NULL initially. */
+void help_init(void)
+{
+ size_t allocsize = 1; /* space needed for help_text */
+ char *ptr = NULL;
+#ifndef NANO_SMALL
+ const toggle *t;
+#endif
+ const shortcut *s;
+
+ /* First set up the initial help text for the current function */
+ if (currshortcut == whereis_list || currshortcut == replace_list
+ || currshortcut == replace_list_2)
+ ptr = _("Search Command Help Text\n\n "
+ "Enter the words or characters you would like to search "
+ "for, then hit 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 "
+ "If using Pico Mode via the -p or --pico flags, the "
+ "Meta-P toggle, or a nanorc file, the previous search "
+ "string will be shown in brackets after the Search: prompt. "
+ "Hitting Enter without entering any text will perform the "
+ "previous search. Otherwise, the previous string will be "
+ "placed before the cursor, and can be edited or deleted "
+ "before hitting enter.\n\n The following function keys are "
+ "available in Search mode:\n\n");
+ else if (currshortcut == goto_list)
+ ptr = _("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");
+ else if (currshortcut == insertfile_list)
+ ptr = _("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 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).\n\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");
+ else if (currshortcut == writefile_list)
+ ptr = _("Write File Help Text\n\n "
+ "Type the name that you wish to save the current file "
+ "as and hit Enter to save the file.\n\n If you have "
+ "selected text with Ctrl-^, 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");
+#ifndef DISABLE_BROWSER
+ else if (currshortcut == browser_list)
+ ptr = _("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");
+ else if (currshortcut == gotodir_list)
+ ptr = _("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");
+#endif
+ else if (currshortcut == spell_list)
+ ptr = _("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.\n\n The following other functions are "
+ "available in Spell Check mode:\n\n");
+#ifndef NANO_SMALL
+ else if (currshortcut == extcmd_list)
+ ptr = _("External Command Help Text\n\n "
+ "This menu allows you to insert the output of a command "
+ "run by the shell into the current buffer (or a new "
+ "buffer in multibuffer mode).\n\n The following keys are "
+ "available in this mode:\n\n");
+#endif
+ else /* Default to the main help list */
+ ptr = _(" 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. "
+ "The bottom two lines show the most commonly used shortcuts "
+ "in the editor.\n\n "
+ "The notation for shortcuts is as follows: Control-key "
+ "sequences are notated with a caret (^) symbol and are entered "
+ "with the Control (Ctrl) key. Escape-key sequences are notated "
+ "with the Meta (M) symbol and can be entered using either the "
+ "Esc, Alt or Meta key depending on your keyboard setup. The "
+ "following keystrokes are available in the main editor window. "
+ "Alternative keys are shown in parentheses:\n\n");
+
+ allocsize += strlen(ptr);
+
+ /* The space needed for the shortcut lists, at most COLS characters,
+ * plus '\n'. */
+ allocsize += (COLS + 1) * length_of_list(currshortcut);
+
+#ifndef NANO_SMALL
+ /* If we're on the main list, we also count the toggle help text.
+ * Each line has "M-%c\t\t\t", which fills 24 columns, plus at most
+ * COLS - 24 characters, plus '\n'.*/
+ if (currshortcut == main_list)
+ for (t = toggles; t != NULL; t = t->next)
+ allocsize += COLS - 17;
+#endif /* !NANO_SMALL */
+
+ /* help_text has been freed and set to NULL unless the user resized
+ * while in the help screen. */
+ free(help_text);
+
+ /* Allocate space for the help text */
+ help_text = charalloc(allocsize);
+
+ /* Now add the text we want */
+ strcpy(help_text, ptr);
+ ptr = help_text + strlen(help_text);
+
+ /* Now add our shortcut info */
+ for (s = currshortcut; s != NULL; s = s->next) {
+ /* true if the character in s->altval is shown in first column */
+ int meta_shortcut = 0;
+
+ if (s->val > 0 && s->val < 32)
+ ptr += sprintf(ptr, "^%c", s->val + 64);
+#ifndef NANO_SMALL
+ else if (s->val == NANO_CONTROL_SPACE)
+ ptr += sprintf(ptr, "^%.6s", _("Space"));
+ else if (s->altval == NANO_ALT_SPACE) {
+ meta_shortcut = 1;
+ ptr += sprintf(ptr, "M-%.5s", _("Space"));
+ }
+#endif
+ else if (s->altval > 0) {
+ meta_shortcut = 1;
+ ptr += sprintf(ptr, "M-%c", s->altval -
+ (('A' <= s->altval && s->altval <= 'Z') ||
+ 'a' <= s->altval ? 32 : 0));
+ }
+ /* Hack */
+ else if (s->val >= 'a') {
+ meta_shortcut = 1;
+ ptr += sprintf(ptr, "M-%c", s->val - 32);
+ }
+
+ *(ptr++) = '\t';
+
+ if (s->misc1 > KEY_F0 && s->misc1 <= KEY_F(64))
+ ptr += sprintf(ptr, "(F%d)", s->misc1 - KEY_F0);
+
+ *(ptr++) = '\t';
+
+ if (!meta_shortcut && s->altval > 0)
+ ptr += sprintf(ptr, "(M-%c)", s->altval -
+ (('A' <= s->altval && s->altval <= 'Z') || 'a' <= s->altval
+ ? 32 : 0));
+
+ *(ptr++) = '\t';
+
+ assert(s->help != NULL);
+ ptr += sprintf(ptr, "%.*s\n", COLS - 24, s->help);
+ }
+
+#ifndef NANO_SMALL
+ /* And the toggles... */
+ if (currshortcut == main_list)
+ for (t = toggles; t != NULL; t = t->next) {
+ ptr += sprintf(ptr, "M-%c\t\t\t", t->val - 32);
+ assert(t->desc != NULL);
+ ptr += sprintf(ptr, _("%.*s enable/disable\n"), COLS - 24, t->desc);
+ }
+#endif /* !NANO_SMALL */
+
+ /* If all went well, we didn't overwrite the allocated space for
+ help_text. */
+ assert(strlen(help_text) < allocsize);
+}
+#endif
+
+/* Create a new filestruct node. Note that we specifically do not set
+ * prevnode->next equal to the new line. */
+filestruct *make_new_node(filestruct *prevnode)
+{
+ filestruct *newnode = (filestruct *)nmalloc(sizeof(filestruct));
+
+ newnode->data = NULL;
+ newnode->prev = prevnode;
+ newnode->next = NULL;
+ newnode->lineno = prevnode != NULL ? prevnode->lineno + 1 : 1;
+
+ return newnode;
+}
+
/* Make a copy of a node to a pointer (space will be malloc()ed). */
filestruct *copy_node(const filestruct *src)
{
@@ -238,6 +490,19 @@ filestruct *copy_node(const filestruct *src)
return dst;
}
+/* Splice a node into an existing filestruct. */
+void splice_node(filestruct *begin, filestruct *newnode, filestruct *end)
+{
+ if (newnode != NULL) {
+ newnode->next = end;
+ newnode->prev = begin;
+ }
+ if (begin != NULL)
+ begin->next = newnode;
+ if (end != NULL)
+ end->prev = newnode;
+}
+
/* Unlink a node from the rest of the filestruct. */
void unlink_node(const filestruct *fileptr)
{
@@ -329,7 +594,7 @@ void renumber(filestruct *fileptr)
* strings to translate and takes out the parts that shouldn't be
* translatable (the flag names). */
void print1opt(const char *shortflag, const char *longflag,
- const char *desc)
+ const char *desc)
{
printf(" %s\t", shortflag);
if (strlen(shortflag) < 8)
@@ -430,46 +695,51 @@ void version(void)
(" Email: nano@nano-editor.org Web: http://www.nano-editor.org"));
printf(_("\n Compiled options:"));
+#ifdef DEBUG
+ printf(" --enable-debug");
+#endif
#ifdef NANO_EXTRA
printf(" --enable-extra");
#endif
-#ifdef ENABLE_MULTIBUFFER
- printf(" --enable-multibuffer");
-#endif
-#ifdef ENABLE_NANORC
- printf(" --enable-nanorc");
-#endif
-#ifdef ENABLE_COLOR
- printf(" --enable-color");
-#endif
-
#ifdef NANO_SMALL
printf(" --enable-tiny");
#else
#ifdef DISABLE_BROWSER
printf(" --disable-browser");
#endif
-#ifdef DISABLE_TABCOMP
- printf(" --disable-tabcomp");
+#ifdef DISABLE_HELP
+ printf(" --disable-help");
#endif
#ifdef DISABLE_JUSTIFY
printf(" --disable-justify");
#endif
-#ifdef DISABLE_SPELLER
- printf(" --disable-speller");
-#endif
-#ifdef DISABLE_HELP
- printf(" --disable-help");
-#endif
#ifdef DISABLE_MOUSE
printf(" --disable-mouse");
#endif
#ifdef DISABLE_OPERATINGDIR
printf(" --disable-operatingdir");
#endif
-#endif /* NANO_SMALL */
-#ifdef DISABLE_WRAPPING
- printf(" --disable-wrapping");
+#ifdef DISABLE_SPELLER
+ printf(" --disable-speller");
+#endif
+#ifdef DISABLE_TABCOMP
+ printf(" --disable-tabcomp");
+#endif
+#endif /* NANO_SMALL */
+#ifdef DISABLE_WRAPPING
+ printf(" --disable-wrapping");
+#endif
+#ifdef ENABLE_COLOR
+ printf(" --enable-color");
+#endif
+#ifdef ENABLE_MULTIBUFFER
+ printf(" --enable-multibuffer");
+#endif
+#ifdef ENABLE_NANORC
+ printf(" --enable-nanorc");
+#endif
+#ifdef ENABLE_UNDO
+ printf(" --enable-undo");
#endif
#ifdef USE_SLANG
printf(" --with-slang");
@@ -477,50 +747,11 @@ void version(void)
printf("\n");
}
-/* Create a new filestruct node. Note that we specifically do not set
- * prevnode->next equal to the new line. */
-filestruct *make_new_node(filestruct *prevnode)
-{
- filestruct *newnode = (filestruct *)nmalloc(sizeof(filestruct));
-
- newnode->data = NULL;
- newnode->prev = prevnode;
- newnode->next = NULL;
- newnode->lineno = prevnode != NULL ? prevnode->lineno + 1 : 1;
-
- return newnode;
-}
-
-/* Splice a node into an existing filestruct. */
-void splice_node(filestruct *begin, filestruct *newnode, filestruct *end)
-{
- if (newnode != NULL) {
- newnode->next = end;
- newnode->prev = begin;
- }
- if (begin != NULL)
- begin->next = newnode;
- if (end != NULL)
- end->prev = newnode;
-}
-
-int do_mark(void)
+/* Stuff we do when we abort from programs and want to clean up the
+ * screen. This doesn't do much right now. */
+void do_early_abort(void)
{
-#ifdef NANO_SMALL
- nano_disabled_msg();
-#else
- if (!ISSET(MARK_ISSET)) {
- statusbar(_("Mark Set"));
- SET(MARK_ISSET);
- mark_beginbuf = current;
- mark_beginx = current_x;
- } else {
- statusbar(_("Mark UNset"));
- UNSET(MARK_ISSET);
- edit_refresh();
- }
-#endif
- return 1;
+ blank_statusbar_refresh();
}
int no_help(void)
@@ -535,448 +766,264 @@ void nano_disabled_msg(void)
}
#endif
-/* The user typed a printable character; add it to the edit buffer. */
-void do_char(char ch)
-{
- size_t current_len = strlen(current->data);
-#if !defined(DISABLE_WRAPPING) || defined(ENABLE_COLOR)
- int refresh = 0;
- /* Do we have to run edit_refresh(), or can we get away with
- * update_line()? */
-#endif
-
- /* magic-line: when a character is inserted on the current magic line,
- * it means we need a new one! */
- if (filebot == current && current->data[0] == '\0') {
- new_magicline();
- fix_editbot();
- }
-
- /* more dangerousness fun =) */
- current->data = nrealloc(current->data, current_len + 2);
- assert(current_x <= current_len);
- memmove(¤t->data[current_x + 1],
- ¤t->data[current_x],
- current_len - current_x + 1);
- current->data[current_x] = ch;
- totsize++;
- set_modified();
-
#ifndef NANO_SMALL
- /* note that current_x has not yet been incremented */
- if (current == mark_beginbuf && current_x < mark_beginx)
- mark_beginx++;
-#endif
-
- do_right();
-
-#ifndef DISABLE_WRAPPING
- if (!ISSET(NO_WRAP) && ch != '\t')
- refresh = do_wrap(current);
-#endif
-
-#ifdef ENABLE_COLOR
- refresh = 1;
-#endif
-
-#if !defined(DISABLE_WRAPPING) || defined(ENABLE_COLOR)
- if (refresh)
- edit_refresh();
-#endif
-
- check_statblank();
- UNSET(KEEP_CUTBUFFER);
-}
+static int pid; /* This is the PID of the newly forked process
+ * below. It must be global since the signal
+ * handler needs it. */
-/* Someone hits return *gasp!* */
-int do_enter(void)
+RETSIGTYPE cancel_fork(int signal)
{
- filestruct *newnode;
- char *tmp;
-
- newnode = make_new_node(current);
- assert(current != NULL && current->data != NULL);
- tmp = ¤t->data[current_x];
-
-#ifndef NANO_SMALL
- /* Do auto-indenting, like the neolithic Turbo Pascal editor. */
- if (ISSET(AUTOINDENT)) {
- int extra = 0;
- const char *spc = current->data;
-
- while (*spc == ' ' || *spc == '\t') {
- extra++;
- spc++;
- }
- /* If current_x < extra, then we are breaking the line in the
- * indentation. Autoindenting should add only current_x
- * characters of indentation. */
- if (current_x < extra)
- extra = current_x;
- else
- current_x = extra;
- totsize += extra;
-
- newnode->data = charalloc(strlen(tmp) + extra + 1);
- strncpy(newnode->data, current->data, extra);
- strcpy(&newnode->data[extra], tmp);
- } else
-#endif
- {
- current_x = 0;
- newnode->data = charalloc(strlen(tmp) + 1);
- strcpy(newnode->data, tmp);
- }
- *tmp = '\0';
-
- if (current->next == NULL) {
- filebot = newnode;
- editbot = newnode;
- }
- splice_node(current, newnode, current->next);
-
- totsize++;
- renumber(current);
- current = newnode;
- align(¤t->data);
-
- /* The logic here is as follows:
- * -> If we are at the bottom of the buffer, we want to recenter
- * (read: rebuild) the screen and forcibly move the cursor.
- * -> otherwise, we want simply to redraw the screen and update
- * where we think the cursor is.
- */
- if (current_y == editwinrows - 1) {
- edit_update(current, CENTER);
- reset_cursor();
- } else {
- current_y++;
- edit_refresh();
- update_cursor();
- }
-
- totlines++;
- set_modified();
-
- placewewant = xplustabs();
- return 1;
+ if (kill(pid, SIGKILL)==-1) nperror("kill");
}
-#ifndef NANO_SMALL
-int do_next_word(void)
+int open_pipe(const char *command)
{
- filestruct *old = current;
-
- assert(current != NULL && current->data != NULL);
-
- /* Skip letters in this word first. */
- while (current->data[current_x] != '\0' &&
- isalnum((int)current->data[current_x]))
- current_x++;
-
- for (; current != NULL; current = current->next) {
- while (current->data[current_x] != '\0' &&
- !isalnum((int)current->data[current_x]))
- current_x++;
-
- if (current->data[current_x] != '\0')
- break;
-
- current_x = 0;
- }
- if (current == NULL)
- current = filebot;
+ int fd[2];
+ FILE *f;
+ struct sigaction oldaction, newaction;
+ /* original and temporary handlers for SIGINT */
+#ifdef _POSIX_VDISABLE
+ struct termios term, newterm;
+#endif /* _POSIX_VDISABLE */
+ int cancel_sigs = 0;
+ /* cancel_sigs==1 means that sigaction failed without changing the
+ * signal handlers. cancel_sigs==2 means the signal handler was
+ * changed, but the tcsetattr didn't succeed.
+ * I use this variable since it is important to put things back when
+ * we finish, even if we get errors. */
- placewewant = xplustabs();
+ /* Make our pipes. */
- if (current->lineno >= editbot->lineno) {
- /* If we're on the last line, don't center the screen. */
- if (current->lineno == filebot->lineno)
- edit_refresh();
- else
- edit_update(current, CENTER);
- }
- else {
- /* If we've jumped lines, refresh the old line. We can't just
- use current->prev here, because we may have skipped over some
- blank lines, in which case the previous line is the wrong
- one. */
- if (current != old) {
- update_line(old, 0);
- /* If the mark was set, then the lines between old and
- current have to be updated too. */
- if (ISSET(MARK_ISSET)) {
- while (old->next != current) {
- old = old->next;
- update_line(old, 0);
- }
- }
- }
- update_line(current, current_x);
+ if (pipe(fd) == -1) {
+ statusbar(_("Could not pipe"));
+ return 1;
}
- return 0;
-}
-
-/* The same thing for backwards. */
-int do_prev_word(void)
-{
- filestruct *old = current;
-
- assert(current != NULL);
-
- /* Skip letters in this word first. */
- while (current_x >= 0 && isalnum((int)current->data[current_x]))
- current_x--;
- for (; current != NULL; current = current->prev) {
- while (current_x >= 0 && !isalnum((int)current->data[current_x]))
- current_x--;
+ /* Fork a child. */
- if (current_x >= 0)
- break;
+ 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("/bin/sh","sh","-c",command,0);
+ exit(0);
+ }
- if (current->prev != NULL)
- current_x = strlen(current->prev->data);
+ /* Else continue as parent. */
+
+ close(fd[1]);
+
+ if (pid == -1) {
+ close(fd[0]);
+ statusbar(_("Could not fork"));
+ return 1;
}
- if (current != NULL) {
- while (current_x > 0 && isalnum((int)current->data[current_x - 1]))
- current_x--;
+ /* Before we start reading the forked command's output, we set
+ * things up so that ^C will cancel the new process. */
+ if (sigaction(SIGINT, NULL, &newaction)==-1) {
+ cancel_sigs = 1;
+ nperror("sigaction");
} else {
- current = fileage;
- current_x = 0;
+ newaction.sa_handler = cancel_fork;
+ if (sigaction(SIGINT, &newaction, &oldaction)==-1) {
+ cancel_sigs = 1;
+ nperror("sigaction");
+ }
}
+ /* Note that now oldaction is the previous SIGINT signal handler,
+ * to be restored later. */
- placewewant = xplustabs();
-
- if (current->lineno <= edittop->lineno) {
- /* If we're on the first line, don't center the screen. */
- if (current->lineno == fileage->lineno)
- edit_refresh();
- else
- edit_update(current, CENTER);
+ /* See if the platform supports disabling individual control
+ * characters. */
+#ifdef _POSIX_VDISABLE
+ if (!cancel_sigs && tcgetattr(0, &term) == -1) {
+ cancel_sigs = 2;
+ nperror("tcgetattr");
}
- else {
- /* If we've jumped lines, refresh the old line. We can't just
- use current->prev here, because we may have skipped over some
- blank lines, in which case the previous line is the wrong
- one. */
- if (current != old) {
- update_line(old, 0);
- /* If the mark was set, then the lines between old and
- current have to be updated too. */
- if (ISSET(MARK_ISSET)) {
- while (old->prev != current) {
- old = old->prev;
- update_line(old, 0);
- }
- }
+ if (!cancel_sigs) {
+ newterm = term;
+ /* Grab oldterm's VINTR key :-) */
+ newterm.c_cc[VINTR] = oldterm.c_cc[VINTR];
+ if (tcsetattr(0, TCSANOW, &newterm) == -1) {
+ cancel_sigs = 2;
+ nperror("tcsetattr");
}
- update_line(current, current_x);
}
+#endif /* _POSIX_VDISABLE */
+
+ f = fdopen(fd[0], "rb");
+ if (!f)
+ nperror("fdopen");
+
+ read_file(f, "stdin", 0);
+ /* if multibuffer mode is on, we could be here in view mode; if so,
+ don't set the modification flag */
+ if (!ISSET(VIEW_MODE))
+ set_modified();
+
+ if (wait(NULL) == -1)
+ nperror("wait");
+
+#ifdef _POSIX_VDISABLE
+ if (!cancel_sigs && tcsetattr(0, TCSANOW, &term) == -1)
+ nperror("tcsetattr");
+#endif /* _POSIX_VDISABLE */
+
+ if (cancel_sigs!=1 && sigaction(SIGINT, &oldaction, NULL) == -1)
+ nperror("sigaction");
+
return 0;
}
-#endif /* !NANO_SMALL */
+#endif /* NANO_SMALL */
-#ifndef DISABLE_WRAPPING
-/* We wrap the given line. Precondition: we assume the cursor has been
- * moved forward since the last typed character. Return value:
- * whether we wrapped. */
-int do_wrap(filestruct *inptr)
+#ifndef DISABLE_MOUSE
+#ifdef NCURSES_MOUSE_VERSION
+void do_mouse(void)
{
- size_t len = strlen(inptr->data); /* length of the line we wrap */
- int i = 0; /* generic loop variable */
- int wrap_loc = -1; /* index of inptr->data where we wrap */
- int word_back = -1;
-#ifndef NANO_SMALL
- const char *indentation = NULL;
- /* indentation to prepend to the new line */
- int indent_len = 0; /* strlen(indentation) */
-#endif
- const char *after_break; /* text after the wrap point */
- int after_break_len; /* strlen(after_break) */
- int wrapping = 0; /* do we prepend to the next line? */
- const char *wrap_line = NULL;
- /* the next line, minus indentation */
- int wrap_line_len = 0; /* strlen(wrap_line) */
- char *newline = NULL; /* the line we create */
- int new_line_len = 0; /* eventual length of newline */
+ MEVENT mevent;
+ int currslen;
+ const shortcut *s = currshortcut;
-/* There are three steps. First, we decide where to wrap. Then, we
- * create the new wrap line. Finally, we clean up. */
+ if (getmouse(&mevent) == ERR)
+ return;
-/* Step 1, finding where to wrap. We are going to replace a white-space
- * character with a new-line. In this step, we set wrap_loc as the
- * location of this replacement.
- *
- * Where should we break the line? We need the last "legal wrap point"
- * such that the last word before it ended at or before fill. If there
- * is no such point, we settle for the first legal wrap point.
- *
- * A "legal wrap point" is a white-space character that is not the last
- * typed character and is not followed by white-space.
- *
- * If there is no legal wrap point or we found the last character of the
- * line, we should return without wrapping.
- *
- * Note that the initial indentation does not count as a legal wrap
- * point if we are going to auto-indent!
- *
- * Note that the code below could be optimised, by not calling strnlenpt()
- * so often. */
+ /* If mouse not in edit or bottom window, return */
+ if (wenclose(edit, mevent.y, mevent.x)) {
-#ifndef NANO_SMALL
- if (ISSET(AUTOINDENT))
- i = indent_length(inptr->data);
-#endif
- wrap_line = inptr->data + i;
- for(; i < len; i++, wrap_line++) {
- /* record where the last word ended */
- if (*wrap_line != ' ' && *wrap_line != '\t')
- word_back = i;
- /* if we have found a "legal wrap point" and the current word
- * extends too far, then we stop */
- if (wrap_loc != -1 && strnlenpt(inptr->data, word_back + 1) > fill)
- break;
- /* we record the latest "legal wrap point" */
- if (i != current_x - 1 && word_back != i &&
- wrap_line[1] != ' ' && wrap_line[1] != '\t')
- wrap_loc = i;
- }
- if (wrap_loc < 0 || i == len)
- return 0;
+ /* Don't let people screw with the marker when they're in a
+ * subfunction. */
+ if (currshortcut != main_list)
+ return;
-/* Step 2, making the new wrap line. It will consist of indentation +
- * after_break + " " + wrap_line (although indentation and wrap_line are
- * conditional on flags and #defines). */
+ /* Subtract out size of topwin. Perhaps we need a constant
+ * somewhere? */
+ mevent.y -= 2;
- /* after_break is the text that will be moved to the next line. */
- after_break = inptr->data + wrap_loc + 1;
- after_break_len = len - wrap_loc - 1;
- assert(after_break_len == strlen(after_break));
+ /* Selecting where the cursor is sets the mark. Selecting
+ * beyond the line length with the cursor at the end of the line
+ * sets the mark as well. */
+ if ((mevent.y == current_y) &&
+ ((mevent.x == current_x) || (current_x == strlen(current->data)
+ && (mevent.x >
+ strlen(current->data))))) {
+ if (ISSET(VIEW_MODE)) {
+ print_view_warning();
+ return;
+ }
+ do_mark();
+ } else if (mevent.y > current_y) {
+ while (mevent.y > current_y) {
+ if (current->next != NULL)
+ current = current->next;
+ else
+ break;
+ current_y++;
+ }
+ } else if (mevent.y < current_y) {
+ while (mevent.y < current_y) {
+ if (current->prev != NULL)
+ current = current->prev;
+ else
+ break;
+ current_y--;
+ }
+ }
+ current_x = actual_x(current, mevent.x);
+ placewewant = current_x;
+ update_cursor();
+ edit_refresh();
+ } else if (wenclose(bottomwin, mevent.y, mevent.x) && !ISSET(NO_HELP)) {
+ int i, k;
- /* new_line_len will later be increased by the lengths of indentation
- * and wrap_line. */
- new_line_len = after_break_len;
+ if (currshortcut == main_list)
+ currslen = MAIN_VISIBLE;
+ else
+ currslen = length_of_list(currshortcut);
- /* We prepend the wrapped text to the next line, if the flag is set,
- * and there is a next line, and prepending would not make the line
- * too long. */
- if (ISSET(SAMELINEWRAP) && inptr->next) {
- wrap_line = inptr->next->data;
- wrap_line_len = strlen(wrap_line);
+ if (currslen < 2)
+ k = COLS / 6;
+ else
+ k = COLS / ((currslen + (currslen %2)) / 2);
- /* +1 for the space between after_break and wrap_line */
- if ((new_line_len + 1 + wrap_line_len) <= fill) {
- wrapping = 1;
- new_line_len += (1 + wrap_line_len);
- }
- }
+ /* Determine what shortcut list was clicked */
+ mevent.y -= (editwinrows + 3);
-#ifndef NANO_SMALL
- if (ISSET(AUTOINDENT)) {
- /* indentation comes from the next line if wrapping, else from
- * this line */
- indentation = (wrapping ? wrap_line : inptr->data);
- indent_len = indent_length(indentation);
- if (wrapping)
- /* The wrap_line text should not duplicate indentation. Note
- * in this case we need not increase new_line_len. */
- wrap_line += indent_len;
- else
- new_line_len += indent_len;
- }
-#endif
+ if (mevent.y < 0) /* They clicked on the statusbar */
+ return;
+
+ /* Don't select stuff beyond list length */
+ if (mevent.x / k >= currslen)
+ return;
- /* Now we allocate the new line and copy into it. */
- newline = charalloc(new_line_len + 1); /* +1 for \0 */
- *newline = '\0';
+ for (i = 0; i < (mevent.x / k) * 2 + mevent.y; i++)
+ s = s->next;
-#ifndef NANO_SMALL
- if (ISSET(AUTOINDENT)) {
- strncpy(newline, indentation, indent_len);
- newline[indent_len] = '\0';
+ /* And ungetch that value */
+ ungetch(s->val);
+
+ /* And if it's an alt-key sequence, we should probably send alt
+ too ;-) */
+ if (s->val >= 'a' && s->val <= 'z')
+ ungetch(27);
}
+}
#endif
- strcat(newline, after_break);
- /* We end the old line at wrap_loc. Note this eats the space. */
- null_at(&inptr->data, wrap_loc);
- if (wrapping) {
- /* In this case, totsize does not change. We ate a space in the
- * null_at() above, but we add a space between after_break and
- * wrap_line below. */
- strcat(newline, " ");
- strcat(newline, wrap_line);
- free(inptr->next->data);
- inptr->next->data = newline;
- } else {
- filestruct *temp = (filestruct *)nmalloc(sizeof(filestruct));
-
- /* In this case, the file size changes by -1 for the eaten
- * space, +1 for the new line, and +indent_len for the new
- * indentation. */
-#ifndef NANO_SMALL
- totsize += indent_len;
#endif
- totlines++;
- temp->data = newline;
- temp->prev = inptr;
- temp->next = inptr->next;
- temp->prev->next = temp;
- /* If !temp->next, then temp is the last line of the file, so we
- * must set filebot */
- if (temp->next)
- temp->next->prev = temp;
- else
- filebot = temp;
- }
-/* Step 3, clean up. Here we reposition the cursor and mark, and do some
- * other sundry things. */
+/* The user typed a printable character; add it to the edit buffer. */
+void do_char(char ch)
+{
+ size_t current_len = strlen(current->data);
+#if !defined(DISABLE_WRAPPING) || defined(ENABLE_COLOR)
+ int refresh = 0;
+ /* Do we have to run edit_refresh(), or can we get away with
+ * update_line()? */
+#endif
- /* later wraps of this line will be prepended to the next line. */
- SET(SAMELINEWRAP);
+ /* magic-line: when a character is inserted on the current magic line,
+ * it means we need a new one! */
+ if (filebot == current && current->data[0] == '\0') {
+ new_magicline();
+ fix_editbot();
+ }
- /* Each line knows its line number. We recalculate these if we
- * inserted a new line. */
- if (!wrapping)
- renumber(inptr);
+ /* more dangerousness fun =) */
+ current->data = nrealloc(current->data, current_len + 2);
+ assert(current_x <= current_len);
+ memmove(¤t->data[current_x + 1],
+ ¤t->data[current_x],
+ current_len - current_x + 1);
+ current->data[current_x] = ch;
+ totsize++;
+ set_modified();
- /* If the cursor was after the break point, we must move it. */
- if (current_x > wrap_loc) {
- current = current->next;
- current_x -=
#ifndef NANO_SMALL
- -indent_len +
+ /* note that current_x has not yet been incremented */
+ if (current == mark_beginbuf && current_x < mark_beginx)
+ mark_beginx++;
#endif
- wrap_loc + 1;
- wrap_reset();
- placewewant = xplustabs();
- }
-#ifndef NANO_SMALL
- /* If the mark was on this line after the wrap point, we move it down.
- * If it was on the next line and we wrapped, we must move it
- * right. */
- if (mark_beginbuf == inptr && mark_beginx > wrap_loc) {
- mark_beginbuf = inptr->next;
- mark_beginx -= wrap_loc - indent_len + 1;
- } else if (wrapping && mark_beginbuf == inptr->next)
- mark_beginx += after_break_len;
-#endif /* !NANO_SMALL */
+ do_right();
- /* Place the cursor. */
- reset_cursor();
+#ifndef DISABLE_WRAPPING
+ if (!ISSET(NO_WRAP) && ch != '\t')
+ refresh = do_wrap(current);
+#endif
- return 1;
-}
-#endif /* !DISABLE_WRAPPING */
+#ifdef ENABLE_COLOR
+ refresh = 1;
+#endif
-/* Stuff we do when we abort from programs and want to clean up the
- * screen. This doesn't do much right now. */
-void do_early_abort(void)
-{
- blank_statusbar_refresh();
+#if !defined(DISABLE_WRAPPING) || defined(ENABLE_COLOR)
+ if (refresh)
+ edit_refresh();
+#endif
+
+ check_statblank();
+ UNSET(KEEP_CUTBUFFER);
}
int do_backspace(void)
@@ -1116,841 +1163,774 @@ int do_delete(void)
return 1;
}
-void wrap_reset(void)
+int do_tab(void)
{
- UNSET(SAMELINEWRAP);
+ do_char('\t');
+ return 1;
}
-#ifndef DISABLE_SPELLER
-int do_int_spell_fix(const char *word)
+/* Someone hits return *gasp!* */
+int do_enter(void)
{
- char *save_search;
- char *save_replace;
- filestruct *begin;
- int i = 0, j = 0, beginx, beginx_top, reverse_search_set;
-#ifndef NANO_SMALL
- int mark_set;
-#endif
-
- /* save where we are */
- begin = current;
- beginx = current_x + 1;
+ filestruct *newnode;
+ char *tmp;
- /* Make sure Spell Check goes forward only */
- reverse_search_set = ISSET(REVERSE_SEARCH);
- UNSET(REVERSE_SEARCH);
+ newnode = make_new_node(current);
+ assert(current != NULL && current->data != NULL);
+ tmp = ¤t->data[current_x];
#ifndef NANO_SMALL
- /* Make sure the marking highlight is off during Spell Check */
- mark_set = ISSET(MARK_ISSET);
- UNSET(MARK_ISSET);
-#endif
-
- /* save the current search/replace strings */
- search_init_globals();
- save_search = last_search;
- save_replace = last_replace;
-
- /* set search/replace strings to mis-spelt word */
- last_search = mallocstrcpy(NULL, word);
- last_replace = mallocstrcpy(NULL, word);
-
- /* start from the top of file */
- current = fileage;
- current_x = beginx_top = -1;
-
- search_last_line = FALSE;
-
- edit_update(fileage, TOP);
-
- while (1) {
- /* make sure word is still mis-spelt (i.e. when multi-errors) */
- if (findnextstr(TRUE, FALSE, fileage, beginx_top, word) != NULL) {
-
- /* find whole words only */
- if (!is_whole_word(current_x, current->data, word))
- continue;
-
- do_replace_highlight(TRUE, word);
-
- /* allow replace word to be corrected */
- i = statusq(0, spell_list, last_replace, _("Edit a replacement"));
-
- do_replace_highlight(FALSE, word);
-
- /* start from the start of this line again */
- current = fileage;
- current_x = beginx_top;
-
- search_last_line = FALSE;
+ /* Do auto-indenting, like the neolithic Turbo Pascal editor. */
+ if (ISSET(AUTOINDENT)) {
+ int extra = 0;
+ const char *spc = current->data;
- if (strcmp(word, answer)) {
- j = i;
- do_replace_loop(word, fileage, &beginx_top, TRUE, &j);
- }
+ while (*spc == ' ' || *spc == '\t') {
+ extra++;
+ spc++;
}
- break;
- }
-
- /* restore the search/replace strings */
- free(last_search); last_search=save_search;
- free(last_replace); last_replace=save_replace;
+ /* If current_x < extra, then we are breaking the line in the
+ * indentation. Autoindenting should add only current_x
+ * characters of indentation. */
+ if (current_x < extra)
+ extra = current_x;
+ else
+ current_x = extra;
+ totsize += extra;
- /* restore where we were */
- current = begin;
- current_x = beginx - 1;
+ newnode->data = charalloc(strlen(tmp) + extra + 1);
+ strncpy(newnode->data, current->data, extra);
+ strcpy(&newnode->data[extra], tmp);
+ } else
+#endif
+ {
+ current_x = 0;
+ newnode->data = charalloc(strlen(tmp) + 1);
+ strcpy(newnode->data, tmp);
+ }
+ *tmp = '\0';
- /* restore Search/Replace direction */
- if (reverse_search_set)
- SET(REVERSE_SEARCH);
+ if (current->next == NULL) {
+ filebot = newnode;
+ editbot = newnode;
+ }
+ splice_node(current, newnode, current->next);
-#ifndef NANO_SMALL
- /* restore marking highlight */
- if (mark_set)
- SET(MARK_ISSET);
-#endif
+ totsize++;
+ renumber(current);
+ current = newnode;
+ align(¤t->data);
- edit_update(current, CENTER);
+ /* The logic here is as follows:
+ * -> If we are at the bottom of the buffer, we want to recenter
+ * (read: rebuild) the screen and forcibly move the cursor.
+ * -> otherwise, we want simply to redraw the screen and update
+ * where we think the cursor is.
+ */
+ if (current_y == editwinrows - 1) {
+ edit_update(current, CENTER);
+ reset_cursor();
+ } else {
+ current_y++;
+ edit_refresh();
+ update_cursor();
+ }
- if (i == -1)
- return FALSE;
+ totlines++;
+ set_modified();
- return TRUE;
+ placewewant = xplustabs();
+ return 1;
}
-/* Integrated spell checking using 'spell' program. */
-int do_int_speller(char *tempfile_name)
+#ifndef NANO_SMALL
+int do_next_word(void)
{
- char *read_buff, *read_buff_ptr, *read_buff_word;
- size_t pipe_buff_size, read_buff_size, read_buff_read, bytesread;
- int in_fd[2], tempfile_fd, spell_status;
- pid_t pid_spell;
-
- /* Create a pipe to spell program */
-
- if (pipe(in_fd) == -1)
- return FALSE;
-
- /* A new process to run spell in */
-
- if ((pid_spell = fork()) == 0) {
+ filestruct *old = current;
- /* Child continues, (i.e. future spell process) */
+ assert(current != NULL && current->data != NULL);
- close(in_fd[0]);
+ /* Skip letters in this word first. */
+ while (current->data[current_x] != '\0' &&
+ isalnum((int)current->data[current_x]))
+ current_x++;
- /* replace the standard in with the tempfile */
+ for (; current != NULL; current = current->next) {
+ while (current->data[current_x] != '\0' &&
+ !isalnum((int)current->data[current_x]))
+ current_x++;
- if ((tempfile_fd = open(tempfile_name, O_RDONLY)) == -1) {
- close(in_fd[1]);
- exit(1);
- }
+ if (current->data[current_x] != '\0')
+ break;
- if (dup2(tempfile_fd, STDIN_FILENO) != STDIN_FILENO) {
- close(tempfile_fd);
- close(in_fd[1]);
- exit(1);
- }
- close(tempfile_fd);
+ current_x = 0;
+ }
+ if (current == NULL)
+ current = filebot;
- /* send spell's standard out to the pipe */
+ placewewant = xplustabs();
- if (dup2(in_fd[1], STDOUT_FILENO) != STDOUT_FILENO) {
- close(in_fd[1]);
- exit(1);
+ if (current->lineno >= editbot->lineno) {
+ /* If we're on the last line, don't center the screen. */
+ if (current->lineno == filebot->lineno)
+ edit_refresh();
+ else
+ edit_update(current, CENTER);
+ }
+ else {
+ /* If we've jumped lines, refresh the old line. We can't just
+ use current->prev here, because we may have skipped over some
+ blank lines, in which case the previous line is the wrong
+ one. */
+ if (current != old) {
+ update_line(old, 0);
+ /* If the mark was set, then the lines between old and
+ current have to be updated too. */
+ if (ISSET(MARK_ISSET)) {
+ while (old->next != current) {
+ old = old->next;
+ update_line(old, 0);
+ }
+ }
}
- close(in_fd[1]);
-
- /* Start spell program, we are using the PATH here!?!? */
- execlp("spell", "spell", NULL);
-
- /* Should not be reached, if spell is found!!! */
-
- exit(1);
+ update_line(current, current_x);
}
+ return 0;
+}
- /* Parent continues here */
+/* The same thing for backwards. */
+int do_prev_word(void)
+{
+ filestruct *old = current;
- close(in_fd[1]);
+ assert(current != NULL);
- /* Child process was not forked successfully */
+ /* Skip letters in this word first. */
+ while (current_x >= 0 && isalnum((int)current->data[current_x]))
+ current_x--;
- if (pid_spell < 0) {
- close(in_fd[0]);
- return FALSE;
- }
+ for (; current != NULL; current = current->prev) {
+ while (current_x >= 0 && !isalnum((int)current->data[current_x]))
+ current_x--;
- /* Get system pipe buffer size */
+ if (current_x >= 0)
+ break;
- if ((pipe_buff_size = fpathconf(in_fd[0], _PC_PIPE_BUF)) < 1) {
- close(in_fd[0]);
- return FALSE;
+ if (current->prev != NULL)
+ current_x = strlen(current->prev->data);
}
- /* 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(in_fd[0], read_buff_ptr, pipe_buff_size)) > 0) {
- read_buff_read += bytesread;
- read_buff_size += pipe_buff_size;
- read_buff = read_buff_ptr = nrealloc(read_buff, read_buff_size);
- read_buff_ptr += read_buff_read;
+ if (current != NULL) {
+ while (current_x > 0 && isalnum((int)current->data[current_x - 1]))
+ current_x--;
+ } else {
+ current = fileage;
+ current_x = 0;
}
- *read_buff_ptr = (char) NULL;
- close(in_fd[0]);
-
- /* Process the spelling errors */
-
- read_buff_word = read_buff_ptr = read_buff;
-
- while (*read_buff_ptr) {
+ placewewant = xplustabs();
- if ((*read_buff_ptr == '\n') || (*read_buff_ptr == '\r')) {
- *read_buff_ptr = (char) NULL;
- if (read_buff_word != read_buff_ptr) {
- if (!do_int_spell_fix(read_buff_word)) {
- read_buff_word = read_buff_ptr;
- break;
+ if (current->lineno <= edittop->lineno) {
+ /* If we're on the first line, don't center the screen. */
+ if (current->lineno == fileage->lineno)
+ edit_refresh();
+ else
+ edit_update(current, CENTER);
+ }
+ else {
+ /* If we've jumped lines, refresh the old line. We can't just
+ use current->prev here, because we may have skipped over some
+ blank lines, in which case the previous line is the wrong
+ one. */
+ if (current != old) {
+ update_line(old, 0);
+ /* If the mark was set, then the lines between old and
+ current have to be updated too. */
+ if (ISSET(MARK_ISSET)) {
+ while (old->prev != current) {
+ old = old->prev;
+ update_line(old, 0);
}
}
- read_buff_word = read_buff_ptr + 1;
}
- read_buff_ptr++;
+ update_line(current, current_x);
}
+ return 0;
+}
+#endif /* !NANO_SMALL */
- /* special case where last word doesn't end with \n or \r */
- if (read_buff_word != read_buff_ptr)
- do_int_spell_fix(read_buff_word);
-
- free(read_buff);
- replace_abort();
-
- /* Process end of spell process */
-
- wait(&spell_status);
- if (WIFEXITED(spell_status)) {
- if (WEXITSTATUS(spell_status) != 0)
- return FALSE;
- } else
- return FALSE;
+int do_mark(void)
+{
+#ifdef NANO_SMALL
+ nano_disabled_msg();
+#else
+ if (!ISSET(MARK_ISSET)) {
+ statusbar(_("Mark Set"));
+ SET(MARK_ISSET);
+ mark_beginbuf = current;
+ mark_beginx = current_x;
+ } else {
+ statusbar(_("Mark UNset"));
+ UNSET(MARK_ISSET);
+ edit_refresh();
+ }
+#endif
+ return 1;
+}
- return TRUE;
+void wrap_reset(void)
+{
+ UNSET(SAMELINEWRAP);
}
-/* External spell checking. */
-int do_alt_speller(char *file_name)
+#ifndef DISABLE_WRAPPING
+/* We wrap the given line. Precondition: we assume the cursor has been
+ * moved forward since the last typed character. Return value:
+ * whether we wrapped. */
+int do_wrap(filestruct *inptr)
{
- int alt_spell_status, lineno_cur = current->lineno;
- int x_cur = current_x, y_cur = current_y, pww_cur = placewewant;
- pid_t pid_spell;
- char *ptr;
- static int arglen = 3;
- static char **spellargs = (char **)NULL;
+ size_t len = strlen(inptr->data); /* length of the line we wrap */
+ int i = 0; /* generic loop variable */
+ int wrap_loc = -1; /* index of inptr->data where we wrap */
+ int word_back = -1;
#ifndef NANO_SMALL
- int mark_set = ISSET(MARK_ISSET);
- int mbb_lineno_cur = 0;
- /* We're going to close the current file, and open the output of
- the alternate spell command. The line that mark_beginbuf
- points to will be freed, so we save the line number and restore
- afterwards. */
-
- if (mark_set) {
- mbb_lineno_cur = mark_beginbuf->lineno;
- UNSET(MARK_ISSET);
- }
+ const char *indentation = NULL;
+ /* indentation to prepend to the new line */
+ int indent_len = 0; /* strlen(indentation) */
#endif
+ const char *after_break; /* text after the wrap point */
+ int after_break_len; /* strlen(after_break) */
+ int wrapping = 0; /* do we prepend to the next line? */
+ const char *wrap_line = NULL;
+ /* the next line, minus indentation */
+ int wrap_line_len = 0; /* strlen(wrap_line) */
+ char *newline = NULL; /* the line we create */
+ int new_line_len = 0; /* eventual length of newline */
- endwin();
+/* There are three steps. First, we decide where to wrap. Then, we
+ * create the new wrap line. Finally, we clean up. */
- /* Set up an argument list to pass the execvp function */
- if (spellargs == NULL) {
- spellargs = nmalloc(arglen * sizeof(char *));
+/* Step 1, finding where to wrap. We are going to replace a white-space
+ * character with a new-line. In this step, we set wrap_loc as the
+ * location of this replacement.
+ *
+ * Where should we break the line? We need the last "legal wrap point"
+ * such that the last word before it ended at or before fill. If there
+ * is no such point, we settle for the first legal wrap point.
+ *
+ * A "legal wrap point" is a white-space character that is not the last
+ * typed character and is not followed by white-space.
+ *
+ * If there is no legal wrap point or we found the last character of the
+ * line, we should return without wrapping.
+ *
+ * Note that the initial indentation does not count as a legal wrap
+ * point if we are going to auto-indent!
+ *
+ * Note that the code below could be optimised, by not calling strnlenpt()
+ * so often. */
- spellargs[0] = strtok(alt_speller, " ");
- while ((ptr = strtok(NULL, " ")) != NULL) {
- arglen++;
- spellargs = nrealloc(spellargs, arglen * sizeof(char *));
- spellargs[arglen - 3] = ptr;
- }
- spellargs[arglen - 1] = NULL;
+#ifndef NANO_SMALL
+ if (ISSET(AUTOINDENT))
+ i = indent_length(inptr->data);
+#endif
+ wrap_line = inptr->data + i;
+ for(; i < len; i++, wrap_line++) {
+ /* record where the last word ended */
+ if (*wrap_line != ' ' && *wrap_line != '\t')
+ word_back = i;
+ /* if we have found a "legal wrap point" and the current word
+ * extends too far, then we stop */
+ if (wrap_loc != -1 && strnlenpt(inptr->data, word_back + 1) > fill)
+ break;
+ /* we record the latest "legal wrap point" */
+ if (i != current_x - 1 && word_back != i &&
+ wrap_line[1] != ' ' && wrap_line[1] != '\t')
+ wrap_loc = i;
}
- spellargs[arglen - 2] = file_name;
-
- /* Start a new process for the alternate speller */
- if ((pid_spell = fork()) == 0) {
- /* Start alternate spell program; we are using the PATH here!?!? */
- execvp(spellargs[0], spellargs);
+ if (wrap_loc < 0 || i == len)
+ return 0;
- /* Should not be reached, if alternate speller is found!!! */
- exit(1);
- }
+/* Step 2, making the new wrap line. It will consist of indentation +
+ * after_break + " " + wrap_line (although indentation and wrap_line are
+ * conditional on flags and #defines). */
- /* Could not fork?? */
- if (pid_spell < 0)
- return FALSE;
+ /* after_break is the text that will be moved to the next line. */
+ after_break = inptr->data + wrap_loc + 1;
+ after_break_len = len - wrap_loc - 1;
+ assert(after_break_len == strlen(after_break));
- /* Wait for alternate speller to complete */
+ /* new_line_len will later be increased by the lengths of indentation
+ * and wrap_line. */
+ new_line_len = after_break_len;
- wait(&alt_spell_status);
- if (!WIFEXITED(alt_spell_status) || WEXITSTATUS(alt_spell_status) != 0)
- return FALSE;
+ /* We prepend the wrapped text to the next line, if the flag is set,
+ * and there is a next line, and prepending would not make the line
+ * too long. */
+ if (ISSET(SAMELINEWRAP) && inptr->next) {
+ wrap_line = inptr->next->data;
+ wrap_line_len = strlen(wrap_line);
- refresh();
- free_filestruct(fileage);
- global_init(1);
- open_file(file_name, 0, 1);
+ /* +1 for the space between after_break and wrap_line */
+ if ((new_line_len + 1 + wrap_line_len) <= fill) {
+ wrapping = 1;
+ new_line_len += (1 + wrap_line_len);
+ }
+ }
#ifndef NANO_SMALL
- if (mark_set) {
- do_gotopos(mbb_lineno_cur, mark_beginx, y_cur, 0);
- mark_beginbuf = current;
- mark_beginx = current_x;
- /* In case the line got shorter, assign mark_beginx. */
- SET(MARK_ISSET);
+ if (ISSET(AUTOINDENT)) {
+ /* indentation comes from the next line if wrapping, else from
+ * this line */
+ indentation = (wrapping ? wrap_line : inptr->data);
+ indent_len = indent_length(indentation);
+ if (wrapping)
+ /* The wrap_line text should not duplicate indentation. Note
+ * in this case we need not increase new_line_len. */
+ wrap_line += indent_len;
+ else
+ new_line_len += indent_len;
}
#endif
- /* go back to the old position, mark the file as modified, and make
- sure that the titlebar is refreshed */
- do_gotopos(lineno_cur, x_cur, y_cur, pww_cur);
- set_modified();
- clearok(topwin, FALSE);
- titlebar(NULL);
-
- return TRUE;
-}
-#endif
-
-int do_spell(void)
-{
-#ifdef DISABLE_SPELLER
- nano_disabled_msg();
- return (TRUE);
-#else
- char *temp;
- int spell_res;
-
- if ((temp = safe_tempnam(0, "nano.")) == NULL) {
- statusbar(_("Could not create a temporary filename: %s"),
- strerror(errno));
- return 0;
- }
+ /* Now we allocate the new line and copy into it. */
+ newline = charalloc(new_line_len + 1); /* +1 for \0 */
+ *newline = '\0';
- if (write_file(temp, 1, 0, 0) == -1) {
- statusbar(_("Spell checking failed: unable to write temp file!"));
- free(temp);
- return 0;
+#ifndef NANO_SMALL
+ if (ISSET(AUTOINDENT)) {
+ strncpy(newline, indentation, indent_len);
+ newline[indent_len] = '\0';
}
-
-#ifdef ENABLE_MULTIBUFFER
- /* update the current open_files entry before spell-checking, in case
- any problems occur */
- add_open_file(1);
#endif
+ strcat(newline, after_break);
+ /* We end the old line at wrap_loc. Note this eats the space. */
+ null_at(&inptr->data, wrap_loc);
+ if (wrapping) {
+ /* In this case, totsize does not change. We ate a space in the
+ * null_at() above, but we add a space between after_break and
+ * wrap_line below. */
+ strcat(newline, " ");
+ strcat(newline, wrap_line);
+ free(inptr->next->data);
+ inptr->next->data = newline;
+ } else {
+ filestruct *temp = (filestruct *)nmalloc(sizeof(filestruct));
- if (alt_speller)
- spell_res = do_alt_speller(temp);
- else
- spell_res = do_int_speller(temp);
+ /* In this case, the file size changes by -1 for the eaten
+ * space, +1 for the new line, and +indent_len for the new
+ * indentation. */
+#ifndef NANO_SMALL
+ totsize += indent_len;
+#endif
+ totlines++;
+ temp->data = newline;
+ temp->prev = inptr;
+ temp->next = inptr->next;
+ temp->prev->next = temp;
+ /* If !temp->next, then temp is the last line of the file, so we
+ * must set filebot */
+ if (temp->next)
+ temp->next->prev = temp;
+ else
+ filebot = temp;
+ }
- remove(temp);
+/* Step 3, clean up. Here we reposition the cursor and mark, and do some
+ * other sundry things. */
- if (spell_res)
- statusbar(_("Finished checking spelling"));
- else
- statusbar(_("Spell checking failed"));
+ /* later wraps of this line will be prepended to the next line. */
+ SET(SAMELINEWRAP);
- free(temp);
- return spell_res;
+ /* Each line knows its line number. We recalculate these if we
+ * inserted a new line. */
+ if (!wrapping)
+ renumber(inptr);
+ /* If the cursor was after the break point, we must move it. */
+ if (current_x > wrap_loc) {
+ current = current->next;
+ current_x -=
+#ifndef NANO_SMALL
+ -indent_len +
#endif
-}
+ wrap_loc + 1;
+ wrap_reset();
+ placewewant = xplustabs();
+ }
#ifndef NANO_SMALL
-static int pid; /* This is the PID of the newly forked process
- * below. It must be global since the signal
- * handler needs it. */
+ /* If the mark was on this line after the wrap point, we move it down.
+ * If it was on the next line and we wrapped, we must move it
+ * right. */
+ if (mark_beginbuf == inptr && mark_beginx > wrap_loc) {
+ mark_beginbuf = inptr->next;
+ mark_beginx -= wrap_loc - indent_len + 1;
+ } else if (wrapping && mark_beginbuf == inptr->next)
+ mark_beginx += after_break_len;
+#endif /* !NANO_SMALL */
-RETSIGTYPE cancel_fork(int signal)
-{
- if (kill(pid, SIGKILL)==-1) nperror("kill");
+ /* Place the cursor. */
+ reset_cursor();
+
+ return 1;
}
+#endif /* !DISABLE_WRAPPING */
-int open_pipe(const char *command)
+#ifndef DISABLE_SPELLER
+int do_int_spell_fix(const char *word)
{
- int fd[2];
- FILE *f;
- struct sigaction oldaction, newaction;
- /* original and temporary handlers for SIGINT */
-#ifdef _POSIX_VDISABLE
- struct termios term, newterm;
-#endif /* _POSIX_VDISABLE */
- int cancel_sigs = 0;
- /* cancel_sigs==1 means that sigaction failed without changing the
- * signal handlers. cancel_sigs==2 means the signal handler was
- * changed, but the tcsetattr didn't succeed.
- * I use this variable since it is important to put things back when
- * we finish, even if we get errors. */
-
- /* Make our pipes. */
+ char *save_search;
+ char *save_replace;
+ filestruct *begin;
+ int i = 0, j = 0, beginx, beginx_top, reverse_search_set;
+#ifndef NANO_SMALL
+ int mark_set;
+#endif
- if (pipe(fd) == -1) {
- statusbar(_("Could not pipe"));
- return 1;
- }
+ /* save where we are */
+ begin = current;
+ beginx = current_x + 1;
- /* Fork a child */
+ /* Make sure Spell Check goes forward only */
+ reverse_search_set = ISSET(REVERSE_SEARCH);
+ UNSET(REVERSE_SEARCH);
- 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("/bin/sh","sh","-c",command,0);
- exit(0);
- }
+#ifndef NANO_SMALL
+ /* Make sure the marking highlight is off during Spell Check */
+ mark_set = ISSET(MARK_ISSET);
+ UNSET(MARK_ISSET);
+#endif
- /* Else continue as parent */
+ /* save the current search/replace strings */
+ search_init_globals();
+ save_search = last_search;
+ save_replace = last_replace;
- close(fd[1]);
+ /* set search/replace strings to mis-spelt word */
+ last_search = mallocstrcpy(NULL, word);
+ last_replace = mallocstrcpy(NULL, word);
- if (pid == -1) {
- close(fd[0]);
- statusbar(_("Could not fork"));
- return 1;
- }
+ /* start from the top of file */
+ current = fileage;
+ current_x = beginx_top = -1;
- /* before we start reading the forked command's output, we set
- * things up so that ^C will cancel the new process */
- if (sigaction(SIGINT, NULL, &newaction)==-1) {
- cancel_sigs = 1;
- nperror("sigaction");
- } else {
- newaction.sa_handler = cancel_fork;
- if (sigaction(SIGINT, &newaction, &oldaction)==-1) {
- cancel_sigs = 1;
- nperror("sigaction");
- }
- }
- /* note that now oldaction is the previous SIGINT signal handler, to
- * be restored later */
+ search_last_line = FALSE;
- /* if the platform supports disabling individual control characters */
-#ifdef _POSIX_VDISABLE
- if (!cancel_sigs && tcgetattr(0, &term) == -1) {
- cancel_sigs = 2;
- nperror("tcgetattr");
- }
- if (!cancel_sigs) {
- newterm = term;
- /* Grab oldterm's VINTR key :-) */
- newterm.c_cc[VINTR] = oldterm.c_cc[VINTR];
- if (tcsetattr(0, TCSANOW, &newterm) == -1) {
- cancel_sigs = 2;
- nperror("tcsetattr");
- }
- }
-#endif /* _POSIX_VDISABLE */
+ edit_update(fileage, TOP);
- f = fdopen(fd[0], "rb");
- if (!f)
- nperror("fdopen");
-
- read_file(f, "stdin", 0);
- set_modified();
+ while (1) {
+ /* make sure word is still mis-spelt (i.e. when multi-errors) */
+ if (findnextstr(TRUE, FALSE, fileage, beginx_top, word) != NULL) {
- if (wait(NULL) == -1)
- nperror("wait");
+ /* find whole words only */
+ if (!is_whole_word(current_x, current->data, word))
+ continue;
-#ifdef _POSIX_VDISABLE
- if (!cancel_sigs && tcsetattr(0, TCSANOW, &term) == -1)
- nperror("tcsetattr");
-#endif /* _POSIX_VDISABLE */
+ do_replace_highlight(TRUE, word);
- if (cancel_sigs!=1 && sigaction(SIGINT, &oldaction, NULL) == -1)
- nperror("sigaction");
+ /* allow replace word to be corrected */
+ i = statusq(0, spell_list, last_replace, _("Edit a replacement"));
- return 0;
-}
-#endif /* NANO_SMALL */
+ do_replace_highlight(FALSE, word);
-int do_exit(void)
-{
- int i;
+ /* start from the start of this line again */
+ current = fileage;
+ current_x = beginx_top;
- if (!ISSET(MODIFIED)) {
+ search_last_line = FALSE;
-#ifdef ENABLE_MULTIBUFFER
- if (!close_open_file()) {
- display_main_list();
- return 1;
+ if (strcmp(word, answer)) {
+ j = i;
+ do_replace_loop(word, fileage, &beginx_top, TRUE, &j);
+ }
}
- else
-#endif
- finish(0);
+ break;
}
- if (ISSET(TEMP_OPT)) {
- i = 1;
- } else {
- i = do_yesno(0, 0,
- _
- ("Save modified buffer (ANSWERING \"No\" WILL DESTROY CHANGES) ? "));
- }
+ /* restore the search/replace strings */
+ free(last_search); last_search=save_search;
+ free(last_replace); last_replace=save_replace;
-#ifdef DEBUG
- dump_buffer(fileage);
-#endif
+ /* restore where we were */
+ current = begin;
+ current_x = beginx - 1;
- if (i == 1) {
- if (do_writeout(filename, 1, 0) > 0) {
+ /* restore Search/Replace direction */
+ if (reverse_search_set)
+ SET(REVERSE_SEARCH);
-#ifdef ENABLE_MULTIBUFFER
- if (!close_open_file()) {
- display_main_list();
- return 1;
- }
- else
+#ifndef NANO_SMALL
+ /* restore marking highlight */
+ if (mark_set)
+ SET(MARK_ISSET);
#endif
- finish(0);
- }
- } else if (i == 0) {
-#ifdef ENABLE_MULTIBUFFER
- if (!close_open_file()) {
- display_main_list();
- return 1;
- }
- else
-#endif
- finish(0);
- } else
- statusbar(_("Cancelled"));
+ edit_update(current, CENTER);
- display_main_list();
- return 1;
+ if (i == -1)
+ return FALSE;
+
+ return TRUE;
}
-#ifndef DISABLE_MOUSE
-#ifdef NCURSES_MOUSE_VERSION
-void do_mouse(void)
+/* Integrated spell checking using 'spell' program. */
+int do_int_speller(char *tempfile_name)
{
- MEVENT mevent;
- int currslen;
- const shortcut *s = currshortcut;
+ char *read_buff, *read_buff_ptr, *read_buff_word;
+ size_t pipe_buff_size, read_buff_size, read_buff_read, bytesread;
+ int in_fd[2], tempfile_fd, spell_status;
+ pid_t pid_spell;
- if (getmouse(&mevent) == ERR)
- return;
+ /* Create a pipe to spell program */
- /* If mouse not in edit or bottom window, return */
- if (wenclose(edit, mevent.y, mevent.x)) {
+ if (pipe(in_fd) == -1)
+ return FALSE;
- /* Don't let people screw with the marker when they're in a
- * subfunction. */
- if (currshortcut != main_list)
- return;
+ /* A new process to run spell in */
- /* Subtract out size of topwin. Perhaps we need a constant
- * somewhere? */
- mevent.y -= 2;
+ if ((pid_spell = fork()) == 0) {
- /* Selecting where the cursor is sets the mark. Selecting
- * beyond the line length with the cursor at the end of the line
- * sets the mark as well. */
- if ((mevent.y == current_y) &&
- ((mevent.x == current_x) || (current_x == strlen(current->data)
- && (mevent.x >
- strlen(current->data))))) {
- if (ISSET(VIEW_MODE)) {
- print_view_warning();
- return;
- }
- do_mark();
- } else if (mevent.y > current_y) {
- while (mevent.y > current_y) {
- if (current->next != NULL)
- current = current->next;
- else
- break;
- current_y++;
- }
- } else if (mevent.y < current_y) {
- while (mevent.y < current_y) {
- if (current->prev != NULL)
- current = current->prev;
- else
- break;
- current_y--;
- }
- }
- current_x = actual_x(current, mevent.x);
- placewewant = current_x;
- update_cursor();
- edit_refresh();
- } else if (wenclose(bottomwin, mevent.y, mevent.x) && !ISSET(NO_HELP)) {
- int i, k;
+ /* Child continues, (i.e. future spell process) */
- if (currshortcut == main_list)
- currslen = MAIN_VISIBLE;
- else
- currslen = length_of_list(currshortcut);
+ close(in_fd[0]);
- if (currslen < 2)
- k = COLS / 6;
- else
- k = COLS / ((currslen + (currslen %2)) / 2);
+ /* replace the standard in with the tempfile */
- /* Determine what shortcut list was clicked */
- mevent.y -= (editwinrows + 3);
+ if ((tempfile_fd = open(tempfile_name, O_RDONLY)) == -1) {
+ close(in_fd[1]);
+ exit(1);
+ }
+
+ if (dup2(tempfile_fd, STDIN_FILENO) != STDIN_FILENO) {
+ close(tempfile_fd);
+ close(in_fd[1]);
+ exit(1);
+ }
+ close(tempfile_fd);
- if (mevent.y < 0) /* They clicked on the statusbar */
- return;
+ /* send spell's standard out to the pipe */
- /* Don't select stuff beyond list length */
- if (mevent.x / k >= currslen)
- return;
+ if (dup2(in_fd[1], STDOUT_FILENO) != STDOUT_FILENO) {
+ close(in_fd[1]);
+ exit(1);
+ }
+ close(in_fd[1]);
- for (i = 0; i < (mevent.x / k) * 2 + mevent.y; i++)
- s = s->next;
+ /* Start spell program, we are using the PATH here!?!? */
+ execlp("spell", "spell", NULL);
- /* And ungetch that value */
- ungetch(s->val);
+ /* Should not be reached, if spell is found!!! */
- /* And if it's an alt-key sequence, we should probably send alt
- too ;-) */
- if (s->val >= 'a' && s->val <= 'z')
- ungetch(27);
+ exit(1);
}
-}
-#endif
-#endif
-/* Handler for SIGHUP */
-RETSIGTYPE handle_hup(int signal)
-{
- die(_("Received SIGHUP"));
-}
+ /* Parent continues here */
-/* What do we do when we catch the suspend signal */
-RETSIGTYPE do_suspend(int signal)
-{
- endwin();
- printf("\n\n\n\n\nUse \"fg\" to return to nano\n");
- fflush(stdout);
+ close(in_fd[1]);
- /* Restore the terminal settings for the disabled keys */
- tcsetattr(0, TCSANOW, &oldterm);
+ /* Child process was not forked successfully */
- /* We used to re-enable the default SIG_DFL and raise SIGTSTP, but
- then we could be (and were) interrupted in the middle of the call.
- So we do it the mutt way instead */
- kill(0, SIGSTOP);
-}
+ if (pid_spell < 0) {
+ close(in_fd[0]);
+ return FALSE;
+ }
-/* Restore the suspend handler when we come back into the prog */
-RETSIGTYPE do_cont(int signal)
-{
- /* Now we just update the screen instead of having to reenable the
- SIGTSTP handler. */
+ /* Get system pipe buffer size */
- doupdate();
- /* The Hurd seems to need this, otherwise a ^Y after a ^Z will
- start suspending again. */
- signal_init();
+ if ((pipe_buff_size = fpathconf(in_fd[0], _PC_PIPE_BUF)) < 1) {
+ close(in_fd[0]);
+ return FALSE;
+ }
-#ifndef NANO_SMALL
- /* Perhaps the user resized the window while we slept. */
- handle_sigwinch(0);
-#endif
-}
+ /* Read-in the returned spelling errors */
-#ifndef NANO_SMALL
-void handle_sigwinch(int s)
-{
- const char *tty = ttyname(0);
- int fd;
- int result = 0;
- struct winsize win;
+ read_buff_read = 0;
+ read_buff_size = pipe_buff_size + 1;
+ read_buff = read_buff_ptr = charalloc(read_buff_size);
- if (!tty)
- return;
- fd = open(tty, O_RDWR);
- if (fd == -1)
- return;
- result = ioctl(fd, TIOCGWINSZ, &win);
- close(fd);
- if (result == -1)
- return;
+ while ((bytesread = read(in_fd[0], read_buff_ptr, pipe_buff_size)) > 0) {
+ read_buff_read += bytesread;
+ read_buff_size += pipe_buff_size;
+ read_buff = read_buff_ptr = nrealloc(read_buff, read_buff_size);
+ read_buff_ptr += read_buff_read;
+ }
- /* Could check whether the COLS or LINES changed, and return
- * otherwise. EXCEPT, that COLS and LINES are ncurses global
- * variables, and in some cases ncurses has already updated them.
- * But not in all cases, argh. */
- COLS = win.ws_col;
- LINES = win.ws_row;
- if ((editwinrows = LINES - 5 + no_help()) < MIN_EDITOR_ROWS)
- die_too_small();
+ *read_buff_ptr = (char) NULL;
+ close(in_fd[0]);
-#ifndef DISABLE_WRAPJUSTIFY
- fill = wrap_at;
- if (fill <= 0)
- fill += COLS;
- if (fill < MIN_FILL_LENGTH)
- die_too_small();
-#endif
+ /* Process the spelling errors */
- hblank = nrealloc(hblank, COLS + 1);
- memset(hblank, ' ', COLS);
- hblank[COLS] = '\0';
+ read_buff_word = read_buff_ptr = read_buff;
-#ifdef HAVE_RESIZETERM
- resizeterm(LINES, COLS);
-#ifdef HAVE_WRESIZE
- if (wresize(topwin, 2, COLS) == ERR)
- die(_("Cannot resize top win"));
- if (mvwin(topwin, 0, 0) == ERR)
- die(_("Cannot move top win"));
- if (wresize(edit, editwinrows, COLS) == ERR)
- die(_("Cannot resize edit win"));
- if (mvwin(edit, 2, 0) == ERR)
- die(_("Cannot move edit win"));
- if (wresize(bottomwin, 3 - no_help(), COLS) == ERR)
- die(_("Cannot resize bottom win"));
- if (mvwin(bottomwin, LINES - 3 + no_help(), 0) == ERR)
- die(_("Cannot move bottom win"));
-#endif /* HAVE_WRESIZE */
-#endif /* HAVE_RESIZETERM */
+ while (*read_buff_ptr) {
- fix_editbot();
+ if ((*read_buff_ptr == '\n') || (*read_buff_ptr == '\r')) {
+ *read_buff_ptr = (char) NULL;
+ 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++;
+ }
- if (current_y > editwinrows - 1)
- edit_update(editbot, CENTER);
- erase();
+ /* special case where last word doesn't end with \n or \r */
+ if (read_buff_word != read_buff_ptr)
+ do_int_spell_fix(read_buff_word);
- /* Do these b/c width may have changed... */
- refresh();
- titlebar(NULL);
- edit_refresh();
- display_main_list();
- blank_statusbar();
- total_refresh();
+ free(read_buff);
+ replace_abort();
- /* Turn cursor back on for sure */
- curs_set(1);
+ /* Process end of spell process */
- /* Jump back to main loop */
- siglongjmp(jmpbuf, 1);
+ wait(&spell_status);
+ if (WIFEXITED(spell_status)) {
+ if (WEXITSTATUS(spell_status) != 0)
+ return FALSE;
+ } else
+ return FALSE;
+
+ return TRUE;
}
-#endif
-void signal_init(void)
+/* External spell checking. */
+int do_alt_speller(char *tempfile_name)
{
-#ifdef _POSIX_VDISABLE
- struct termios term;
+ int alt_spell_status, lineno_cur = current->lineno;
+ int x_cur = current_x, y_cur = current_y, pww_cur = placewewant;
+ pid_t pid_spell;
+ char *ptr;
+ static int arglen = 3;
+ static char **spellargs = (char **)NULL;
+#ifndef NANO_SMALL
+ int mark_set = ISSET(MARK_ISSET);
+ int mbb_lineno_cur = 0;
+ /* We're going to close the current file, and open the output of
+ the alternate spell command. The line that mark_beginbuf
+ points to will be freed, so we save the line number and restore
+ afterwards. */
+
+ if (mark_set) {
+ mbb_lineno_cur = mark_beginbuf->lineno;
+ UNSET(MARK_ISSET);
+ }
#endif
- /* Trap SIGINT and SIGQUIT cuz we want them to do useful things. */
- memset(&act, 0, sizeof(struct sigaction));
- act.sa_handler = SIG_IGN;
- sigaction(SIGINT, &act, NULL);
+ endwin();
- /* Trap SIGHUP cuz we want to write the file out. */
- act.sa_handler = handle_hup;
- sigaction(SIGHUP, &act, NULL);
+ /* Set up an argument list to pass the execvp function */
+ if (spellargs == NULL) {
+ spellargs = nmalloc(arglen * sizeof(char *));
-#ifndef NANO_SMALL
- act.sa_handler = handle_sigwinch;
- sigaction(SIGWINCH, &act, NULL);
-#endif
+ spellargs[0] = strtok(alt_speller, " ");
+ while ((ptr = strtok(NULL, " ")) != NULL) {
+ arglen++;
+ spellargs = nrealloc(spellargs, arglen * sizeof(char *));
+ spellargs[arglen - 3] = ptr;
+ }
+ spellargs[arglen - 1] = NULL;
+ }
+ spellargs[arglen - 2] = tempfile_name;
-#ifdef _POSIX_VDISABLE
- tcgetattr(0, &term);
+ /* Start a new process for the alternate speller */
+ if ((pid_spell = fork()) == 0) {
+ /* Start alternate spell program; we are using the PATH here!?!? */
+ execvp(spellargs[0], spellargs);
-#ifdef VDSUSP
- term.c_cc[VDSUSP] = _POSIX_VDISABLE;
-#endif /* VDSUSP */
+ /* Should not be reached, if alternate speller is found!!! */
+ exit(1);
+ }
-#endif /* _POSIX_VDISABLE */
+ /* Could not fork?? */
+ if (pid_spell < 0)
+ return FALSE;
+
+ /* Wait for alternate speller to complete */
+
+ wait(&alt_spell_status);
+ if (!WIFEXITED(alt_spell_status) || WEXITSTATUS(alt_spell_status) != 0)
+ return FALSE;
+
+ refresh();
+ free_filestruct(fileage);
+ global_init(1);
+ open_file(tempfile_name, 0, 1);
+
+#ifndef NANO_SMALL
+ if (mark_set) {
+ do_gotopos(mbb_lineno_cur, mark_beginx, y_cur, 0);
+ mark_beginbuf = current;
+ mark_beginx = current_x;
+ /* In case the line got shorter, assign mark_beginx. */
+ SET(MARK_ISSET);
+ }
+#endif
- if (!ISSET(SUSPEND)) {
+ /* go back to the old position, mark the file as modified, and make
+ sure that the titlebar is refreshed */
+ do_gotopos(lineno_cur, x_cur, y_cur, pww_cur);
+ set_modified();
+ clearok(topwin, FALSE);
+ titlebar(NULL);
-/* Insane! */
-#ifdef _POSIX_VDISABLE
- term.c_cc[VSUSP] = _POSIX_VDISABLE;
-#else
- act.sa_handler = SIG_IGN;
- sigaction(SIGTSTP, &act, NULL);
+ return TRUE;
+}
#endif
- } else {
- /* If we don't do this, it seems other stuff interrupts the
- suspend handler! Try using nano with mutt without this
- line. */
- sigfillset(&act.sa_mask);
+int do_spell(void)
+{
+#ifdef DISABLE_SPELLER
+ nano_disabled_msg();
+ return (TRUE);
+#else
+ char *temp;
+ int spell_res;
- act.sa_handler = do_suspend;
- sigaction(SIGTSTP, &act, NULL);
+ if ((temp = safe_tempnam(0, "nano.")) == NULL) {
+ statusbar(_("Could not create a temporary filename: %s"),
+ strerror(errno));
+ return 0;
+ }
- act.sa_handler = do_cont;
- sigaction(SIGCONT, &act, NULL);
+ if (write_file(temp, 1, 0, 0) == -1) {
+ statusbar(_("Spell checking failed: unable to write temp file!"));
+ free(temp);
+ return 0;
}
-#ifdef _POSIX_VDISABLE
- tcsetattr(0, TCSANOW, &term);
+#ifdef ENABLE_MULTIBUFFER
+ /* update the current open_files entry before spell-checking, in case
+ any problems occur */
+ add_open_file(1);
#endif
-}
-
-void window_init(void)
-{
- if ((editwinrows = LINES - 5 + no_help()) < MIN_EDITOR_ROWS)
- die_too_small();
- /* Set up the main text window */
- edit = newwin(editwinrows, COLS, 2, 0);
+ if (alt_speller)
+ spell_res = do_alt_speller(temp);
+ else
+ spell_res = do_int_speller(temp);
- /* And the other windows */
- topwin = newwin(2, COLS, 0, 0);
- bottomwin = newwin(3 - no_help(), COLS, LINES - 3 + no_help(), 0);
+ remove(temp);
-#ifdef PDCURSES
- /* Oops, I guess we need this again.
- Moved here so the keypad still works after a Meta-X, for example */
- keypad(edit, TRUE);
- keypad(bottomwin, TRUE);
-#endif
-}
+ if (spell_res)
+ statusbar(_("Finished checking spelling"));
+ else
+ statusbar(_("Spell checking failed"));
-void mouse_init(void)
-{
-#ifndef DISABLE_MOUSE
-#ifdef NCURSES_MOUSE_VERSION
- if (ISSET(USE_MOUSE)) {
- keypad_on(edit, 1);
- keypad_on(bottomwin, 1);
+ free(temp);
+ return spell_res;
- mousemask(BUTTON1_RELEASED, NULL);
- mouseinterval(50);
- } else
- mousemask(0, NULL);
-#endif
#endif
}
-int do_tab(void)
-{
- do_char('\t');
- return 1;
-}
-
#if !defined(DISABLE_WRAPPING) && !defined(NANO_SMALL) || !defined(DISABLE_JUSTIFY)
/* The "indentation" of a line is the white-space between the quote part
* and the non-white-space of the line. */
-size_t indent_length(const char *line) {
+size_t indent_length(const char *line)
+{
size_t len = 0;
assert(line != NULL);
@@ -2067,17 +2047,11 @@ size_t quote_length(const char *line)
}
#endif /* !HAVE_REGEX_H */
-#ifdef HAVE_REGEX_H
-# define IFREG(a, b) a, b
-#else
-# define IFREG(a, b) a
-#endif
-
/* a_line and b_line are lines of text. The quotation part of a_line is
* the first a_quote characters. Check that the quotation part of
* b_line is the same. */
int quotes_match(const char *a_line, size_t a_quote,
- IFREG(const char *b_line, const regex_t *qreg))
+ IFREG(const char *b_line, const regex_t *qreg))
{
/* Here is the assumption about a_quote: */
assert(a_quote == quote_length(IFREG(a_line, qreg)));
@@ -2088,7 +2062,7 @@ int quotes_match(const char *a_line, size_t a_quote,
/* We assume a_line and b_line have no quote part. Then, we return whether
* b_line could follow a_line in a paragraph. */
size_t indents_match(const char *a_line, size_t a_indent,
- const char *b_line, size_t b_indent)
+ const char *b_line, size_t b_indent)
{
assert(a_indent == indent_length(a_line));
assert(b_indent == indent_length(b_line));
@@ -2101,7 +2075,7 @@ size_t indents_match(const char *a_line, size_t a_indent,
* copies of the lines in place, too. We return the new copy of
* first_line. */
filestruct *backup_lines(filestruct *first_line, size_t par_len,
- size_t quote_len)
+ size_t quote_len)
{
/* We put the original lines, not copies, into the cut buffer, just
* out of a misguided sense of consistency, so if you un-cut, you
@@ -2515,7 +2489,7 @@ int do_justify(void)
reset_cursor();
/* Now get a keystroke and see if it's unjustify; if not, unget the
- * keystroke and return */
+ * keystroke and return. */
#ifndef DISABLE_MOUSE
#ifdef NCURSES_MOUSE_VERSION
@@ -2585,207 +2559,249 @@ int do_justify(void)
#endif
}
-#ifndef DISABLE_HELP
-/* This function allocates help_text, and stores the help string in it.
- * help_text should be NULL initially. */
-void help_init(void)
+int do_exit(void)
{
- size_t allocsize = 1; /* space needed for help_text */
- char *ptr = NULL;
-#ifndef NANO_SMALL
- const toggle *t;
+ int i;
+
+ if (!ISSET(MODIFIED)) {
+
+#ifdef ENABLE_MULTIBUFFER
+ if (!close_open_file()) {
+ display_main_list();
+ return 1;
+ }
+ else
#endif
- const shortcut *s;
+ finish(0);
+ }
- /* First set up the initial help text for the current function */
- if (currshortcut == whereis_list || currshortcut == replace_list
- || currshortcut == replace_list_2)
- ptr = _("Search Command Help Text\n\n "
- "Enter the words or characters you would like to search "
- "for, then hit 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 "
- "If using Pico Mode via the -p or --pico flags, the "
- "Meta-P toggle, or a nanorc file, the previous search "
- "string will be shown in brackets after the Search: prompt. "
- "Hitting Enter without entering any text will perform the "
- "previous search. Otherwise, the previous string will be "
- "placed before the cursor, and can be edited or deleted "
- "before hitting enter.\n\n The following function keys are "
- "available in Search mode:\n\n");
- else if (currshortcut == goto_list)
- ptr = _("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");
- else if (currshortcut == insertfile_list)
- ptr = _("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 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).\n\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");
- else if (currshortcut == writefile_list)
- ptr = _("Write File Help Text\n\n "
- "Type the name that you wish to save the current file "
- "as and hit Enter to save the file.\n\n If you have "
- "selected text with Ctrl-^, 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");
-#ifndef DISABLE_BROWSER
- else if (currshortcut == browser_list)
- ptr = _("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");
- else if (currshortcut == gotodir_list)
- ptr = _("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");
+ if (ISSET(TEMP_OPT)) {
+ i = 1;
+ } else {
+ i = do_yesno(0, 0,
+ _
+ ("Save modified buffer (ANSWERING \"No\" WILL DESTROY CHANGES) ? "));
+ }
+
+#ifdef DEBUG
+ dump_buffer(fileage);
#endif
- else if (currshortcut == spell_list)
- ptr = _("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.\n\n The following other functions are "
- "available in Spell Check mode:\n\n");
+
+ if (i == 1) {
+ if (do_writeout(filename, 1, 0) > 0) {
+
+#ifdef ENABLE_MULTIBUFFER
+ if (!close_open_file()) {
+ display_main_list();
+ return 1;
+ }
+ else
+#endif
+ finish(0);
+ }
+ } else if (i == 0) {
+
+#ifdef ENABLE_MULTIBUFFER
+ if (!close_open_file()) {
+ display_main_list();
+ return 1;
+ }
+ else
+#endif
+ finish(0);
+ } else
+ statusbar(_("Cancelled"));
+
+ display_main_list();
+ return 1;
+}
+
+void signal_init(void)
+{
+#ifdef _POSIX_VDISABLE
+ struct termios term;
+#endif
+
+ /* Trap SIGINT and SIGQUIT cuz we want them to do useful things. */
+ memset(&act, 0, sizeof(struct sigaction));
+ act.sa_handler = SIG_IGN;
+ sigaction(SIGINT, &act, NULL);
+
+ /* Trap SIGHUP cuz we want to write the file out. */
+ act.sa_handler = handle_hup;
+ sigaction(SIGHUP, &act, NULL);
+
#ifndef NANO_SMALL
- else if (currshortcut == extcmd_list)
- ptr = _("External Command Help Text\n\n "
- "This menu allows you to insert the output of a command "
- "run by the shell into the current buffer (or a new "
- "buffer in multibuffer mode).\n\n The following keys are "
- "available in this mode:\n\n");
+ act.sa_handler = handle_sigwinch;
+ sigaction(SIGWINCH, &act, NULL);
#endif
- else /* Default to the main help list */
- ptr = _(" 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. "
- "The bottom two lines show the most commonly used shortcuts "
- "in the editor.\n\n "
- "The notation for shortcuts is as follows: Control-key "
- "sequences are notated with a caret (^) symbol and are entered "
- "with the Control (Ctrl) key. Escape-key sequences are notated "
- "with the Meta (M) symbol and can be entered using either the "
- "Esc, Alt or Meta key depending on your keyboard setup. The "
- "following keystrokes are available in the main editor window. "
- "Alternative keys are shown in parentheses:\n\n");
- allocsize += strlen(ptr);
+#ifdef _POSIX_VDISABLE
+ tcgetattr(0, &term);
- /* The space needed for the shortcut lists, at most COLS characters,
- * plus '\n'. */
- allocsize += (COLS + 1) * length_of_list(currshortcut);
+#ifdef VDSUSP
+ term.c_cc[VDSUSP] = _POSIX_VDISABLE;
+#endif /* VDSUSP */
-#ifndef NANO_SMALL
- /* If we're on the main list, we also count the toggle help text.
- * Each line has "M-%c\t\t\t", which fills 24 columns, plus at most
- * COLS - 24 characters, plus '\n'.*/
- if (currshortcut == main_list)
- for (t = toggles; t != NULL; t = t->next)
- allocsize += COLS - 17;
-#endif /* !NANO_SMALL */
+#endif /* _POSIX_VDISABLE */
- /* help_text has been freed and set to NULL unless the user resized
- * while in the help screen. */
- free(help_text);
+ if (!ISSET(SUSPEND)) {
- /* Allocate space for the help text */
- help_text = charalloc(allocsize);
+/* Insane! */
+#ifdef _POSIX_VDISABLE
+ term.c_cc[VSUSP] = _POSIX_VDISABLE;
+#else
+ act.sa_handler = SIG_IGN;
+ sigaction(SIGTSTP, &act, NULL);
+#endif
- /* Now add the text we want */
- strcpy(help_text, ptr);
- ptr = help_text + strlen(help_text);
+ } else {
+ /* If we don't do this, it seems other stuff interrupts the
+ suspend handler! Try using nano with mutt without this
+ line. */
+ sigfillset(&act.sa_mask);
- /* Now add our shortcut info */
- for (s = currshortcut; s != NULL; s = s->next) {
- /* true if the character in s->altval is shown in first column */
- int meta_shortcut = 0;
+ act.sa_handler = do_suspend;
+ sigaction(SIGTSTP, &act, NULL);
- if (s->val > 0 && s->val < 32)
- ptr += sprintf(ptr, "^%c", s->val + 64);
-#ifndef NANO_SMALL
- else if (s->val == NANO_CONTROL_SPACE)
- ptr += sprintf(ptr, "^%.6s", _("Space"));
- else if (s->altval == NANO_ALT_SPACE) {
- meta_shortcut = 1;
- ptr += sprintf(ptr, "M-%.5s", _("Space"));
- }
+ act.sa_handler = do_cont;
+ sigaction(SIGCONT, &act, NULL);
+ }
+
+#ifdef _POSIX_VDISABLE
+ tcsetattr(0, TCSANOW, &term);
#endif
- else if (s->altval > 0) {
- meta_shortcut = 1;
- ptr += sprintf(ptr, "M-%c", s->altval -
- (('A' <= s->altval && s->altval <= 'Z') ||
- 'a' <= s->altval ? 32 : 0));
- }
- /* Hack */
- else if (s->val >= 'a') {
- meta_shortcut = 1;
- ptr += sprintf(ptr, "M-%c", s->val - 32);
- }
+}
- *(ptr++) = '\t';
+/* Handler for SIGHUP */
+RETSIGTYPE handle_hup(int signal)
+{
+ die(_("Received SIGHUP"));
+}
- if (s->misc1 > KEY_F0 && s->misc1 <= KEY_F(64))
- ptr += sprintf(ptr, "(F%d)", s->misc1 - KEY_F0);
+/* What do we do when we catch the suspend signal */
+RETSIGTYPE do_suspend(int signal)
+{
+ endwin();
+ printf("\n\n\n\n\nUse \"fg\" to return to nano\n");
+ fflush(stdout);
- *(ptr++) = '\t';
+ /* Restore the terminal settings for the disabled keys */
+ tcsetattr(0, TCSANOW, &oldterm);
- if (!meta_shortcut && s->altval > 0)
- ptr += sprintf(ptr, "(M-%c)", s->altval -
- (('A' <= s->altval && s->altval <= 'Z') || 'a' <= s->altval
- ? 32 : 0));
+ /* We used to re-enable the default SIG_DFL and raise SIGTSTP, but
+ then we could be (and were) interrupted in the middle of the call.
+ So we do it the mutt way instead */
+ kill(0, SIGSTOP);
+}
- *(ptr++) = '\t';
+/* Restore the suspend handler when we come back into the prog */
+RETSIGTYPE do_cont(int signal)
+{
+ /* Now we just update the screen instead of having to reenable the
+ SIGTSTP handler. */
- assert(s->help != NULL);
- ptr += sprintf(ptr, "%.*s\n", COLS - 24, s->help);
- }
+ doupdate();
+ /* The Hurd seems to need this, otherwise a ^Y after a ^Z will
+ start suspending again. */
+ signal_init();
#ifndef NANO_SMALL
- /* And the toggles... */
- if (currshortcut == main_list)
- for (t = toggles; t != NULL; t = t->next) {
- ptr += sprintf(ptr, "M-%c\t\t\t", t->val - 32);
- assert(t->desc != NULL);
- ptr += sprintf(ptr, _("%.*s enable/disable\n"), COLS - 24, t->desc);
- }
+ /* Perhaps the user resized the window while we slept. */
+ handle_sigwinch(0);
+#endif
+}
+
+#ifndef NANO_SMALL
+void handle_sigwinch(int s)
+{
+ const char *tty = ttyname(0);
+ int fd;
+ int result = 0;
+ struct winsize win;
+
+ if (!tty)
+ return;
+ fd = open(tty, O_RDWR);
+ if (fd == -1)
+ return;
+ result = ioctl(fd, TIOCGWINSZ, &win);
+ close(fd);
+ if (result == -1)
+ return;
+
+ /* Could check whether the COLS or LINES changed, and return
+ * otherwise. EXCEPT, that COLS and LINES are ncurses global
+ * variables, and in some cases ncurses has already updated them.
+ * But not in all cases, argh. */
+ COLS = win.ws_col;
+ LINES = win.ws_row;
+ if ((editwinrows = LINES - 5 + no_help()) < MIN_EDITOR_ROWS)
+ die_too_small();
+
+#ifndef DISABLE_WRAPJUSTIFY
+ fill = wrap_at;
+ if (fill <= 0)
+ fill += COLS;
+ if (fill < MIN_FILL_LENGTH)
+ die_too_small();
+#endif
+
+ hblank = nrealloc(hblank, COLS + 1);
+ memset(hblank, ' ', COLS);
+ hblank[COLS] = '\0';
+
+#ifdef HAVE_RESIZETERM
+ resizeterm(LINES, COLS);
+#ifdef HAVE_WRESIZE
+ if (wresize(topwin, 2, COLS) == ERR)
+ die(_("Cannot resize top win"));
+ if (mvwin(topwin, 0, 0) == ERR)
+ die(_("Cannot move top win"));
+ if (wresize(edit, editwinrows, COLS) == ERR)
+ die(_("Cannot resize edit win"));
+ if (mvwin(edit, 2, 0) == ERR)
+ die(_("Cannot move edit win"));
+ if (wresize(bottomwin, 3 - no_help(), COLS) == ERR)
+ die(_("Cannot resize bottom win"));
+ if (mvwin(bottomwin, LINES - 3 + no_help(), 0) == ERR)
+ die(_("Cannot move bottom win"));
+#endif /* HAVE_WRESIZE */
+#endif /* HAVE_RESIZETERM */
+
+ fix_editbot();
+
+ if (current_y > editwinrows - 1)
+ edit_update(editbot, CENTER);
+ erase();
+
+ /* Do these b/c width may have changed... */
+ refresh();
+ titlebar(NULL);
+ edit_refresh();
+ display_main_list();
+ blank_statusbar();
+ total_refresh();
+
+ /* Turn cursor back on for sure */
+ curs_set(1);
+
+ /* Jump back to main loop */
+ siglongjmp(jmpbuf, 1);
+}
#endif /* !NANO_SMALL */
- /* If all went well, we didn't overwrite the allocated space for
- help_text. */
- assert(strlen(help_text) < allocsize);
+/* If the NumLock key has made the keypad go awry, print an error
+ message; hopefully we can address it later. */
+void print_numlock_warning(void)
+{
+ static int didmsg = 0;
+ if (!didmsg) {
+ statusbar(_
+ ("NumLock glitch detected. Keypad will malfunction with NumLock off"));
+ didmsg = 1;
+ }
}
-#endif
#ifndef NANO_SMALL
void do_toggle(const toggle *which)
@@ -2833,18 +2849,6 @@ void do_toggle(const toggle *which)
}
#endif /* !NANO_SMALL */
-/* If the NumLock key has made the keypad go awry, print an error
- message; hopefully we can address it later. */
-void print_numlock_warning(void)
-{
- static int didmsg = 0;
- if (!didmsg) {
- statusbar(_
- ("NumLock glitch detected. Keypad will malfunction with NumLock off"));
- didmsg = 1;
- }
-}
-
/* This function returns the correct keystroke, given the A,B,C or D
input key. This is a common sequence of many terms which send
Esc-O-[A-D] or Esc-[-[A-D]. */
@@ -3460,7 +3464,7 @@ int main(int argc, char *argv[])
/* Look through the main shortcut list to see if we've hit a
shortcut key */
-
+
#if !defined(DISABLE_BROWSER) || !defined(DISABLE_MOUSE) || !defined (DISABLE_HELP)
for (s = currshortcut; s != NULL && !keyhandled; s = s->next) {
#else
@@ -3474,6 +3478,10 @@ int main(int argc, char *argv[])
else
s->func();
keyhandled = 1;
+ /* rarely, the value of s can change after s->func(),
+ leading to problems; get around this by breaking out
+ explicitly once we successfully handle a shortcut */
+ break;
}
}
/* If we're in raw mode or using Alt-Alt-x, we have to catch
@@ -3489,7 +3497,6 @@ int main(int argc, char *argv[])
keyhandled = 1;
}
-
#ifndef USE_SLANG
/* Hack, make insert key do something useful, like insert file */
if (kbinput == KEY_IC) {
diff --git a/nano.h b/nano.h
@@ -326,6 +326,7 @@ know what you're doing */
#define NANO_TOFILES_KEY NANO_CONTROL_T
#define NANO_APPEND_KEY NANO_ALT_A
#define NANO_PREPEND_KEY NANO_ALT_P
+#define NANO_LOAD_KEY NANO_ALT_F
#define NANO_OPENPREV_KEY NANO_ALT_LCARAT
#define NANO_OPENNEXT_KEY NANO_ALT_RCARAT
#define NANO_OPENPREV_ALTKEY NANO_ALT_COMMA
diff --git a/proto.h b/proto.h
@@ -59,13 +59,7 @@ extern char *operating_dir;
extern char *full_operating_dir;
#endif
#ifndef DISABLE_SPELLER
-extern char *alt_speller;
-#endif
-#ifndef DISABLE_TABCOMP
-char *real_dir_from_tilde(char *buf);
-#endif
-#ifndef DISABLE_BROWSER
-char *do_browse_from(char *inpath);
+extern char *alt_speller;
#endif
extern struct stat fileinfo;
@@ -116,23 +110,28 @@ extern toggle *toggles;
/* Public functions in color.c */
#ifdef ENABLE_COLOR
-void set_colorpairs(void);
void do_colorinit(void);
void update_color(void);
#endif /* ENABLE_COLOR */
/* Public functions in cut.c */
-int do_cut_text(void);
-int do_uncut_text(void);
filestruct *get_cutbottom(void);
void add_to_cutbuffer(filestruct *inptr);
void cut_marked_segment(filestruct *top, size_t top_x, filestruct *bot,
size_t bot_x, int destructive);
+int do_cut_text(void);
+int do_uncut_text(void);
/* Public functions in files.c */
+void load_file(int update);
+void new_file(void);
+filestruct *read_line(char *buf, filestruct *prev, int *line1ins, int len);
int write_file(char *name, int tmpfile, int append, int nonamechange);
-int open_file(const char *filename, int insert, int quiet);
int read_file(FILE *f, const char *filename, int quiet);
+int open_file(const char *filename, int insert, int quiet);
+char *get_next_filename(const char *name);
+int do_insertfile(int loading_file);
+int do_insertfile_void(void);
#ifdef ENABLE_MULTIBUFFER
openfilestruct *make_new_opennode(openfilestruct *prevnode);
void splice_opennode(openfilestruct *begin, openfilestruct *newnode, openfilestruct *end);
@@ -140,157 +139,299 @@ void unlink_opennode(const openfilestruct *fileptr);
void delete_opennode(openfilestruct *fileptr);
void free_openfilestruct(openfilestruct *src);
int add_open_file(int update);
-int close_open_file(void);
+int load_open_file(void);
+int open_prevfile(int closing_file);
int open_prevfile_void(void);
+int open_nextfile(int closing_file);
int open_nextfile_void(void);
+int close_open_file(void);
+#endif
+#if !defined(DISABLE_SPELLER) || !defined(DISABLE_OPERATINGDIR)
+char *get_full_path(char *origpath);
+#endif
+#ifndef DISABLE_SPELLER
+char *check_writable_directory(char *path);
+char *safe_tempnam(const char *dirname, const char *filename_prefix);
#endif
#ifndef DISABLE_OPERATINGDIR
int check_operating_dir(char *currpath, int allow_tabcomp);
#endif
+int write_file(char *name, int tmp, int append, int nonamechange);
int do_writeout(char *path, int exiting, int append);
-char *input_tab(char *buf, int place, int *lastwastab, int *newplace, int *list);
-void new_file(void);
int do_writeout_void(void);
-int do_insertfile_void(void);
-char *get_next_filename(const char *name);
-#ifndef DISABLE_SPELLER
-char *safe_tempnam(const char *dirname, const char *filename_prefix);
+#ifndef DISABLE_TABCOMP
+char *real_dir_from_tilde(char *buf);
+#endif
+int append_slash_if_dir(char *buf, int *lastwastab, int *place);
+char **username_tab_completion(char *buf, int *num_matches);
+char **cwd_tab_completion(char *buf, int *num_matches);
+char *input_tab(char *buf, int place, int *lastwastab, int *newplace, int *list);
+#ifndef DISABLE_BROWSER
+struct stat filestat(const char *path);
+int diralphasort(const void *va, const void *vb);
+void free_charptrarray(char **array, int len);
+char *tail(char *foo);
+void striponedir(char *foo);
+char **browser_init(char *path, int *longest, int *numents);
+char *do_browser(char *inpath);
+char *do_browse_from(char *inpath);
#endif
/* Public functions in global.c */
int length_of_list(const shortcut *s);
+void sc_init_one(shortcut **shortcutage, int key, const char *desc,
+#ifndef DISABLE_HELP
+ const char *help,
+#endif
+ int alt, int misc1, int misc2, int view, int (*func) (void));
+#ifndef NANO_SMALL
+void toggle_init_one(int val, const char *desc, int flag);
+void toggle_init(void);
+#ifdef DEBUG
+void free_toggles(void);
+#endif
+#endif
+void free_shortcutage(shortcut **shortcutage);
void shortcut_init(int unjustify);
#ifdef DEBUG
void thanks_for_all_the_fish(void);
#endif
/* Public functions in move.c */
-int do_first_line(void);
-int do_last_line(void);
-size_t xplustabs(void);
-size_t actual_x(const filestruct *fileptr, size_t xplus);
-size_t strnlenpt(const char *buf, size_t size);
-size_t strlenpt(const char *buf);
-void reset_cursor(void);
-void blank_bottombars(void);
-void blank_edit(void);
-void blank_statusbar(void);
-void blank_statusbar_refresh(void);
-void check_statblank(void);
-void titlebar(const char *path);
-void bottombars(const shortcut *s);
-void set_modified(void);
+int do_home(void);
+int do_end(void);
+void page_up(void);
+int do_page_up(void);
+int do_page_down(void);
int do_up(void);
int do_down(void);
int do_left(void);
int do_right(void);
-void page_up(void);
-int do_page_up(void);
-int do_page_down(void);
-int do_home(void);
-int do_end(void);
/* Public functions in nano.c */
-void renumber(filestruct *fileptr);
+RETSIGTYPE finish(int sigage);
+void die(const char *msg, ...);
+void die_save_file(const char *die_filename);
+void die_too_small(void);
+void print_view_warning(void);
+void global_init(int save_cutbuffer);
+void window_init(void);
+void mouse_init(void);
+#ifndef DISABLE_HELP
+void help_init(void);
+#endif
+filestruct *make_new_node(filestruct *prevnode);
+filestruct *copy_node(const filestruct *src);
+void splice_node(filestruct *begin, filestruct *newnode, filestruct *end);
+void unlink_node(const filestruct *fileptr);
+void delete_node(filestruct *fileptr);
+filestruct *copy_filestruct(const filestruct *src);
void free_filestruct(filestruct *src);
-int no_help(void);
void renumber_all(void);
-int open_pipe(const char *command);
-int do_prev_word(void);
-int do_next_word(void);
-void delete_node(filestruct *fileptr);
-void wrap_reset(void);
+void renumber(filestruct *fileptr);
+void print1opt(const char *shortflag, const char *longflag,
+ const char *desc);
+void usage(void);
+void version(void);
void do_early_abort(void);
-void die(const char *msg, ...);
-void splice_node(filestruct *begin, filestruct *newnode, filestruct *end);
+int no_help(void);
+#if defined(DISABLE_JUSTIFY) || defined(DISABLE_SPELLER) || defined(DISABLE_HELP) || defined(NANO_SMALL)
void nano_disabled_msg(void);
-void window_init(void);
+#endif
+#ifndef NANO_SMALL
+RETSIGTYPE cancel_fork(int signal);
+int open_pipe(const char *command);
+#endif
+#ifndef DISABLE_MOUSE
+#ifdef NCURSES_MOUSE_VERSION
void do_mouse(void);
-void print_view_warning(void);
-int do_exit(void);
-int do_spell(void);
-int do_mark(void);
-int do_delete(void);
+#endif
+#endif
+void do_char(char ch);
int do_backspace(void);
+int do_delete(void);
int do_tab(void);
-int do_justify(void);
int do_enter(void);
+int do_next_word(void);
+int do_prev_word(void);
+int do_mark(void);
+void wrap_reset(void);
+#ifndef DISABLE_WRAPPING
int do_wrap(filestruct *inptr);
+#endif
+#ifndef DISABLE_SPELLER
+int do_int_spell_fix(const char *word);
+int do_int_speller(char *tempfile_name);
+int do_alt_speller(char *tempfile_name);
+#endif
+int do_spell(void);
+#if !defined(DISABLE_WRAPPING) && !defined(NANO_SMALL) || !defined(DISABLE_JUSTIFY)
+size_t indent_length(const char *line);
+#endif
+#ifndef DISABLE_JUSTIFY
+int justify_format(int changes_allowed, filestruct *line, size_t skip);
+#ifdef HAVE_REGEX_H
+size_t quote_length(const char *line, const regex_t *qreg);
+#else
+size_t quote_length(const char *line);
+#endif
+#ifdef HAVE_REGEX_H
+# define IFREG(a, b) a, b
+#else
+# define IFREG(a, b) a
+#endif
+int quotes_match(const char *a_line, size_t a_quote,
+ IFREG(const char *b_line, const regex_t *qreg));
+size_t indents_match(const char *a_line, size_t a_indent,
+ const char *b_line, size_t b_indent);
+filestruct *backup_lines(filestruct *first_line, size_t par_len,
+ size_t quote_len);
+int break_line(const char *line, int goal, int force);
+#endif /* !DISABLE_JUSTIFY */
+int do_justify(void);
+int do_exit(void);
void signal_init(void);
+RETSIGTYPE handle_hup(int signal);
+RETSIGTYPE do_suspend(int signal);
+RETSIGTYPE do_cont(int signal);
+#ifndef NANO_SMALL
void handle_sigwinch(int s);
-void die_save_file(const char *die_filename);
-size_t indent_length(const char *line);
-
-filestruct *copy_node(const filestruct *src);
-filestruct *copy_filestruct(const filestruct *src);
-filestruct *make_new_node(filestruct *prevnode);
-#ifndef DISABLE_HELP
-void help_init(void);
#endif
+void print_numlock_warning(void);
+#ifndef NANO_SMALL
+void do_toggle(const toggle *which);
+#endif
+int ABCD(int input);
/* Public functions in rcfile.c */
#ifdef ENABLE_NANORC
+void rcfile_error(const char *msg, ...);
+void rcfile_msg(const char *msg, ...);
+char *parse_next_word(char *ptr);
+char *parse_argument(char *ptr);
+#ifdef ENABLE_COLOR
+int colortoint(const char *colorname, int *bright);
+char *parse_next_regex(char *ptr);
+void parse_syntax(char *ptr);
+void parse_colors(char *ptr);
+#endif /* ENABLE_COLOR */
+void parse_rcfile(FILE *rcstream);
void do_rcfile(void);
-#endif
+#endif /* ENABLE_NANORC */
/* Public functions in search.c */
-int do_gotoline(int line, int save_pos);
+#ifdef HAVE_REGEX_H
+void regexp_init(const char *regexp);
+void regexp_cleanup(void);
+#endif
+void not_found_msg(const char *str);
+void search_abort(void);
+void search_init_globals(void);
+int search_init(int replacing);
int is_whole_word(int curr_pos, const char *datastr, const char *searchword);
+filestruct *findnextstr(int quiet, int bracket_mode,
+ const filestruct *begin, int beginx,
+ const char *needle);
+int do_search(void);
+void replace_abort(void);
+#ifdef HAVE_REGEX_H
+int replace_regexp(char *string, int create_flag);
+#endif
+char *replace_line(void);
+void print_replaced(int num);
int do_replace_loop(const char *prevanswer, const filestruct *begin,
int *beginx, int wholewords, int *i);
-int do_find_bracket(void);
+int do_replace(void);
+void goto_abort(void);
+int do_gotoline(int line, int save_pos);
+int do_gotoline_void(void);
#if defined (ENABLE_MULTIBUFFER) || !defined (DISABLE_SPELLER)
void do_gotopos(int line, int pos_x, int pos_y, int pos_placewewant);
#endif
-void search_init_globals(void);
-void replace_abort(void);
-int do_gotoline_void(void);
-int do_search(void);
-int do_replace(void);
-filestruct *findnextstr(int quiet, int bracket_mode, const filestruct *begin,
- int beginx, const char *needle);
+int do_find_bracket(void);
/* Public functions in utils.c */
-const char *stristr(const char *haystack, const char *needle);
-const char *strstrwrapper(const char *haystack, const char *needle,
- const char *rev_start, int line_pos);
int is_cntrl_char(int c);
int num_of_digits(int n);
-int check_wildcard_match(const char *text, const char *pattern);
void align(char **strp);
void null_at(char **data, size_t index);
void unsunder(char *str, size_t true_len);
void sunder(char *str);
+#ifndef NANO_SMALL
+const char *revstrstr(const char *haystack, const char *needle,
+ const char *rev_start);
+const char *revstristr(const char *haystack, const char *needle,
+ const char *rev_start);
+#endif
+const char *stristr(const char *haystack, const char *needle);
+const char *strstrwrapper(const char *haystack, const char *needle,
+ const char *rev_start, int line_pos);
void nperror(const char *s);
-char *mallocstrcpy(char *dest, const char *src);
void *nmalloc(size_t howmuch);
+char *charalloc(size_t howmuch);
void *nrealloc(void *ptr, size_t howmuch);
+char *mallocstrcpy(char *dest, const char *src);
void new_magicline(void);
-char *charalloc(size_t howmuch);
+#ifndef DISABLE_TABCOMP
+int check_wildcard_match(const char *text, const char *pattern);
+#endif
/* Public functions in winio.c */
-int do_yesno(int all, int leavecursor, const char *msg, ...);
-int statusq(int allowtabs, const shortcut *s, const char *def,
- const char *msg, ...);
-void do_replace_highlight(int highlight_flag, const char *word);
+int do_first_line(void);
+int do_last_line(void);
+int xpt(const filestruct *fileptr, int index);
+size_t xplustabs(void);
+size_t actual_x(const filestruct *fileptr, size_t xplus);
+size_t strnlenpt(const char *buf, size_t size);
+size_t strlenpt(const char *buf);
+void blank_bottombars(void);
+void blank_bottomwin(void);
+void blank_edit(void);
+void blank_statusbar(void);
+void blank_statusbar_refresh(void);
+void check_statblank(void);
+void nanoget_repaint(const char *buf, const char *inputbuf, int x);
+int nanogetstr(int allowtabs, const char *buf, const char *def,
+ const shortcut *s
+#ifndef DISABLE_TABCOMP
+ , int *list
+#endif
+ );
+void set_modified(void);
+void titlebar(const char *path);
+void bottombars(const shortcut *s);
+void onekey(const char *keystroke, const char *desc, int len);
+int get_page_start_virtual(int page);
+int get_page_from_virtual(int virtual);
+int get_page_end_virtual(int page);
+int get_page_start(int column);
+void reset_cursor(void);
+void add_marked_sameline(int begin, int end, filestruct *fileptr, int y,
+ int virt_cur_x, int this_page);
+void edit_add(filestruct *fileptr, int yval, int start, int virt_cur_x,
+ int virt_mark_beginx, int this_page);
+void update_line(filestruct *fileptr, int index);
+void update_cursor(void);
+void center_cursor(void);
void edit_refresh(void);
void edit_refresh_clearok(void);
void edit_update(filestruct *fileptr, topmidbotnone location);
-void update_cursor(void);
+int statusq(int tabs, const shortcut *s, const char *def,
+ const char *msg, ...);
+int do_yesno(int all, int leavecursor, const char *msg, ...);
+int total_refresh(void);
+void display_main_list(void);
+void statusbar(const char *msg, ...);
+int do_cursorpos(int constant);
+int do_cursorpos_void(void);
+int do_help(void);
+int keypad_on(WINDOW *win, int newval);
+void do_replace_highlight(int highlight_flag, const char *word);
+void fix_editbot(void);
#ifdef DEBUG
void dump_buffer(const filestruct *inptr);
void dump_buffer_reverse(void);
#endif
-void update_line(filestruct *fileptr, int index);
-void fix_editbot(void);
-void statusbar(const char *msg, ...);
-void center_cursor(void);
-void display_main_list(void);
#ifdef NANO_EXTRA
void do_credits(void);
#endif
-int do_cursorpos(int constant);
-int do_cursorpos_void(void);
-int total_refresh(void);
-int do_help(void);
-int keypad_on(WINDOW *win, int newval);
diff --git a/rcfile.c b/rcfile.c
@@ -188,24 +188,6 @@ char *parse_argument(char *ptr)
#ifdef ENABLE_COLOR
-char *parse_next_regex(char *ptr)
-{
- while ((*ptr != '"' || (*(ptr + 1) != ' ' && *(ptr + 1) != '\n'))
- && *ptr != '\n' && *ptr != '\0')
- ptr++;
-
- if (*ptr == '\0')
- return NULL;
-
- /* Null terminate and advance ptr */
- *ptr++ = '\0';
-
- while (*ptr == ' ' || *ptr == '\t')
- ptr++;
-
- return ptr;
-}
-
int colortoint(const char *colorname, int *bright)
{
int mcolor = 0;
@@ -245,6 +227,24 @@ int colortoint(const char *colorname, int *bright)
return mcolor;
}
+char *parse_next_regex(char *ptr)
+{
+ while ((*ptr != '"' || (*(ptr + 1) != ' ' && *(ptr + 1) != '\n'))
+ && *ptr != '\n' && *ptr != '\0')
+ ptr++;
+
+ if (*ptr == '\0')
+ return NULL;
+
+ /* Null terminate and advance ptr */
+ *ptr++ = '\0';
+
+ while (*ptr == ' ' || *ptr == '\t')
+ ptr++;
+
+ return ptr;
+}
+
void parse_syntax(char *ptr)
{
syntaxtype *tmpsyntax = NULL;
diff --git a/search.c b/search.c
@@ -53,6 +53,33 @@ void regexp_cleanup(void)
}
#endif
+void not_found_msg(const char *str)
+{
+ if (strlen(str) <= COLS / 2)
+ statusbar(_("\"%s\" not found"), str);
+ else {
+ char *foo = mallocstrcpy(NULL, str);
+
+ foo[COLS / 2] = '\0';
+ statusbar(_("\"%s...\" not found"), foo);
+ free(foo);
+ }
+}
+
+void search_abort(void)
+{
+ UNSET(KEEP_CUTBUFFER);
+ display_main_list();
+ wrefresh(bottomwin);
+ if (ISSET(MARK_ISSET))
+ edit_refresh_clearok();
+
+#ifdef HAVE_REGEX_H
+ if (ISSET(REGEXP_COMPILED))
+ regexp_cleanup();
+#endif
+}
+
void search_init_globals(void)
{
if (last_search == NULL) {
@@ -67,10 +94,11 @@ void search_init_globals(void)
/* Set up the system variables for a search or replace. Returns -1 on
abort, 0 on success, and 1 on rerun calling program
- Return -2 to run opposite program (search -> replace, replace -> search)
+ Return -2 to run opposite program (search -> replace, replace ->
+ search).
- replacing = 1 if we call from do_replace, 0 if called from do_search func.
-*/
+ replacing = 1 if we call from do_replace, 0 if called from do_search
+ func. */
int search_init(int replacing)
{
int i = 0;
@@ -196,19 +224,6 @@ int search_init(int replacing)
return 0;
}
-void not_found_msg(const char *str)
-{
- if (strlen(str) <= COLS / 2)
- statusbar(_("\"%s\" not found"), str);
- else {
- char *foo = mallocstrcpy(NULL, str);
-
- foo[COLS / 2] = '\0';
- statusbar(_("\"%s...\" not found"), foo);
- free(foo);
- }
-}
-
int is_whole_word(int curr_pos, const char *datastr, const char *searchword)
{
size_t sln = curr_pos + strlen(searchword);
@@ -223,7 +238,8 @@ static int past_editbuff;
/* findnextstr() is now searching lines not displayed */
filestruct *findnextstr(int quiet, int bracket_mode,
- const filestruct *begin, int beginx, const char *needle)
+ const filestruct *begin, int beginx,
+ const char *needle)
{
filestruct *fileptr = current;
const char *searchstr, *rev_start = NULL, *found = NULL;
@@ -363,20 +379,6 @@ filestruct *findnextstr(int quiet, int bracket_mode,
return fileptr;
}
-void search_abort(void)
-{
- UNSET(KEEP_CUTBUFFER);
- display_main_list();
- wrefresh(bottomwin);
- if (ISSET(MARK_ISSET))
- edit_refresh_clearok();
-
-#ifdef HAVE_REGEX_H
- if (ISSET(REGEXP_COMPILED))
- regexp_cleanup();
-#endif
-}
-
/* Search for a string. */
int do_search(void)
{
@@ -430,14 +432,6 @@ int do_search(void)
return 1;
}
-void print_replaced(int num)
-{
- if (num > 1)
- statusbar(_("Replaced %d occurrences"), num);
- else if (num == 1)
- statusbar(_("Replaced 1 occurrence"));
-}
-
void replace_abort(void)
{
/* Identical to search_abort, so we'll call it here. If it
@@ -561,6 +555,14 @@ char *replace_line(void)
return copy;
}
+void print_replaced(int num)
+{
+ if (num > 1)
+ statusbar(_("Replaced %d occurrences"), num);
+ else if (num == 1)
+ statusbar(_("Replaced 1 occurrence"));
+}
+
/* step through each replace word and prompt user before replacing word */
int do_replace_loop(const char *prevanswer, const filestruct *begin,
int *beginx, int wholewords, int *i)
diff --git a/utils.c b/utils.c
@@ -97,7 +97,7 @@ void sunder(char *str)
/* None of this is needed if we're using NANO_SMALL! */
#ifndef NANO_SMALL
const char *revstrstr(const char *haystack, const char *needle,
- const char *rev_start)
+ const char *rev_start)
{
for(; rev_start >= haystack ; rev_start--) {
const char *r, *q;
@@ -111,7 +111,7 @@ const char *revstrstr(const char *haystack, const char *needle,
}
const char *revstristr(const char *haystack, const char *needle,
- const char *rev_start)
+ const char *rev_start)
{
for (; rev_start >= haystack; rev_start--) {
const char *r = rev_start, *q = needle;
@@ -147,7 +147,7 @@ const char *stristr(const char *haystack, const char *needle)
}
const char *strstrwrapper(const char *haystack, const char *needle,
- const char *rev_start, int line_pos)
+ const char *rev_start, int line_pos)
{
#ifdef HAVE_REGEX_H
if (ISSET(USE_REGEXP)) {
@@ -195,7 +195,8 @@ const char *strstrwrapper(const char *haystack, const char *needle,
/* This is a wrapper for the perror function. The wrapper takes care of
* ncurses, calls perror (which writes to STDERR), then refreshes the
* screen. Note that nperror causes the window to flicker once. */
-void nperror(const char *s) {
+void nperror(const char *s)
+{
/* leave ncurses mode, go to the terminal */
if (endwin() != ERR) {
perror(s); /* print the error */
diff --git a/winio.c b/winio.c
@@ -155,6 +155,15 @@ void blank_bottombars(void)
}
}
+void blank_bottomwin(void)
+{
+ if (ISSET(NO_HELP))
+ return;
+
+ mvwaddstr(bottomwin, 1, 0, hblank);
+ mvwaddstr(bottomwin, 2, 0, hblank);
+}
+
void blank_edit(void)
{
int i;
@@ -210,11 +219,11 @@ void nanoget_repaint(const char *buf, const char *inputbuf, int x)
/* Get the input from the kb; this should only be called from
* statusq(). */
int nanogetstr(int allowtabs, const char *buf, const char *def,
- const shortcut *s
+ const shortcut *s
#ifndef DISABLE_TABCOMP
- , int *list
+ , int *list
#endif
- )
+ )
{
int kbinput;
int x;
@@ -241,7 +250,8 @@ int nanogetstr(int allowtabs, const char *buf, const char *def,
nanoget_repaint(buf, answer, x);
- /* Make sure any editor screen updates are displayed before getting input */
+ /* Make sure any editor screen updates are displayed before getting
+ input */
wrefresh(edit);
while ((kbinput = wgetch(bottomwin)) != 13) {
@@ -253,7 +263,8 @@ int nanogetstr(int allowtabs, const char *buf, const char *def,
if (kbinput == t->val && kbinput < 32) {
#ifndef DISABLE_HELP
- /* Have to do this here, it would be too late to do it in statusq */
+ /* Have to do this here, it would be too late to do it
+ in statusq() */
if (kbinput == NANO_HELP_KEY || kbinput == NANO_HELP_FKEY) {
do_help();
break;
@@ -435,6 +446,16 @@ int nanogetstr(int allowtabs, const char *buf, const char *def,
return 0;
}
+/* If modified is not already set, set it and update titlebar. */
+void set_modified(void)
+{
+ if (!ISSET(MODIFIED)) {
+ SET(MODIFIED);
+ titlebar(NULL);
+ wrefresh(topwin);
+ }
+}
+
void titlebar(const char *path)
{
int namelen, space;
@@ -483,35 +504,6 @@ void titlebar(const char *path)
reset_cursor();
}
-/* Write a shortcut key to the help area at the bottom of the window.
- * keystroke is e.g. "^G" and desc is e.g. "Get Help".
- * We are careful to write exactly len characters, even if len is
- * very small and keystroke and desc are long. */
-void onekey(const char *keystroke, const char *desc, int len)
-{
- wattron(bottomwin, A_REVERSE);
- waddnstr(bottomwin, keystroke, len);
- wattroff(bottomwin, A_REVERSE);
- len -= strlen(keystroke);
- if (len > 0) {
- waddch(bottomwin, ' ');
- len--;
- waddnstr(bottomwin, desc, len);
- len -= strlen(desc);
- for (; len > 0; len--)
- waddch(bottomwin, ' ');
- }
-}
-
-void clear_bottomwin(void)
-{
- if (ISSET(NO_HELP))
- return;
-
- mvwaddstr(bottomwin, 1, 0, hblank);
- mvwaddstr(bottomwin, 2, 0, hblank);
-}
-
void bottombars(const shortcut *s)
{
int i, j, numcols;
@@ -530,7 +522,7 @@ void bottombars(const shortcut *s)
/* There will be this many columns of shortcuts */
numcols = (slen + (slen % 2)) / 2;
- clear_bottomwin();
+ blank_bottomwin();
for (i = 0; i < numcols; i++) {
for (j = 0; j <= 1; j++) {
@@ -562,20 +554,30 @@ void bottombars(const shortcut *s)
wrefresh(bottomwin);
}
-/* If modified is not already set, set it and update titlebar. */
-void set_modified(void)
+/* Write a shortcut key to the help area at the bottom of the window.
+ * keystroke is e.g. "^G" and desc is e.g. "Get Help".
+ * We are careful to write exactly len characters, even if len is
+ * very small and keystroke and desc are long. */
+void onekey(const char *keystroke, const char *desc, int len)
{
- if (!ISSET(MODIFIED)) {
- SET(MODIFIED);
- titlebar(NULL);
- wrefresh(topwin);
+ wattron(bottomwin, A_REVERSE);
+ waddnstr(bottomwin, keystroke, len);
+ wattroff(bottomwin, A_REVERSE);
+ len -= strlen(keystroke);
+ if (len > 0) {
+ waddch(bottomwin, ' ');
+ len--;
+ waddnstr(bottomwin, desc, len);
+ len -= strlen(desc);
+ for (; len > 0; len--)
+ waddch(bottomwin, ' ');
}
}
-/* And so start the display update routines */
-/* Given a column, this returns the "page" it is on */
-/* "page" in the case of the display columns, means which set of 80 */
-/* characters is viewable (e.g.: page 1 shows from 1 to COLS) */
+/* And so start the display update routines. Given a column, this
+ * returns the "page" it is on. "page", in the case of the display
+ * columns, means which set of 80 characters is viewable (e.g. page 1
+ * shows from 1 to COLS). */
int get_page_from_virtual(int virtual)
{
int page = 2;
@@ -637,12 +639,10 @@ void reset_cursor(void)
}
#ifndef NANO_SMALL
-/* This takes care of the case where there is a mark that covers only */
-/* the current line. */
-
-/* It expects a line with no tab characters (i.e.: the type that edit_add */
-/* deals with */
-void add_marked_sameline(int begin, int end, filestruct * fileptr, int y,
+/* This takes care of the case where there is a mark that covers only
+ * the current line. It expects a line with no tab characters (i.e.
+ * the type that edit_add() deals with. */
+void add_marked_sameline(int begin, int end, filestruct *fileptr, int y,
int virt_cur_x, int this_page)
{
/*
@@ -691,12 +691,10 @@ void add_marked_sameline(int begin, int end, filestruct * fileptr, int y,
}
#endif
-/* edit_add takes care of the job of actually painting a line into the
- * edit window.
- *
- * Called only from update_line. Expects a converted-to-not-have-tabs
- * line */
-void edit_add(filestruct * fileptr, int yval, int start, int virt_cur_x,
+/* edit_add() takes care of the job of actually painting a line into
+ * the edit window. Called only from update_line(). Expects a
+ * converted-to-not-have-tabs line. */
+void edit_add(filestruct *fileptr, int yval, int start, int virt_cur_x,
int virt_mark_beginx, int this_page)
{
@@ -1007,12 +1005,10 @@ void edit_add(filestruct * fileptr, int yval, int start, int virt_cur_x,
/*
* Just update one line in the edit buffer. Basically a wrapper for
- * edit_add
- *
- * index gives us a place in the string to update starting from.
- * Likely args are current_x or 0.
+ * edit_add(). index gives us a place in the string to update starting
+ * from. Likely args are current_x or 0.
*/
-void update_line(filestruct * fileptr, int index)
+void update_line(filestruct *fileptr, int index)
{
filestruct *filetmp;
int line = 0, col = 0;
@@ -1112,6 +1108,28 @@ void update_line(filestruct * fileptr, int index)
free(tmp);
}
+/* This function updates current, based on where current_y is;
+ * reset_cursor() does the opposite. */
+void update_cursor(void)
+{
+ int i = 0;
+
+#ifdef DEBUG
+ fprintf(stderr, _("Moved to (%d, %d) in edit buffer\n"), current_y,
+ current_x);
+#endif
+
+ current = edittop;
+ while (i < current_y && current->next != NULL) {
+ current = current->next;
+ i++;
+ }
+
+#ifdef DEBUG
+ fprintf(stderr, _("current->data = \"%s\"\n"), current->data);
+#endif
+}
+
void center_cursor(void)
{
current_y = editwinrows / 2;
@@ -1194,28 +1212,6 @@ void edit_update(filestruct *fileptr, topmidbotnone location)
edit_refresh();
}
-/* This function updates current, based on where current_y is;
- * reset_cursor() does the opposite. */
-void update_cursor(void)
-{
- int i = 0;
-
-#ifdef DEBUG
- fprintf(stderr, _("Moved to (%d, %d) in edit buffer\n"), current_y,
- current_x);
-#endif
-
- current = edittop;
- while (i < current_y && current->next != NULL) {
- current = current->next;
- i++;
- }
-
-#ifdef DEBUG
- fprintf(stderr, _("current->data = \"%s\"\n"), current->data);
-#endif
-}
-
/*
* Ask a question on the statusbar. Answer will be stored in answer
* global. Returns -1 on aborted enter, -2 on a blank string, and 0
@@ -1278,8 +1274,9 @@ int statusq(int tabs, const shortcut *s, const char *def,
}
/*
- * Ask a simple yes/no question on the statusbar. Returns 1 for Y, 0 for
- * N, 2 for All (if all is non-zero when passed in) and -1 for abort (^C)
+ * Ask a simple yes/no question on the statusbar. Returns 1 for Y, 0
+ * for N, 2 for All (if all is non-zero when passed in) and -1 for
+ * abort (^C).
*/
int do_yesno(int all, int leavecursor, const char *msg, ...)
{
@@ -1303,7 +1300,7 @@ int do_yesno(int all, int leavecursor, const char *msg, ...)
allstr = _("Aa");
/* Write the bottom of the screen */
- clear_bottomwin();
+ blank_bottomwin();
/* Remove gettext call for keybindings until we clear the thing up */
if (!ISSET(NO_HELP)) {
@@ -1412,6 +1409,28 @@ int do_yesno(int all, int leavecursor, const char *msg, ...)
return ok;
}
+int total_refresh(void)
+{
+ clearok(edit, TRUE);
+ clearok(topwin, TRUE);
+ clearok(bottomwin, TRUE);
+ wnoutrefresh(edit);
+ wnoutrefresh(topwin);
+ wnoutrefresh(bottomwin);
+ doupdate();
+ clearok(edit, FALSE);
+ clearok(topwin, FALSE);
+ clearok(bottomwin, FALSE);
+ edit_refresh();
+ titlebar(NULL);
+ return 1;
+}
+
+void display_main_list(void)
+{
+ bottombars(main_list);
+}
+
void statusbar(const char *msg, ...)
{
va_list ap;
@@ -1452,28 +1471,6 @@ void statusbar(const char *msg, ...)
statblank = 25;
}
-void display_main_list(void)
-{
- bottombars(main_list);
-}
-
-int total_refresh(void)
-{
- clearok(edit, TRUE);
- clearok(topwin, TRUE);
- clearok(bottomwin, TRUE);
- wnoutrefresh(edit);
- wnoutrefresh(topwin);
- wnoutrefresh(bottomwin);
- doupdate();
- clearok(edit, FALSE);
- clearok(topwin, FALSE);
- clearok(bottomwin, FALSE);
- edit_refresh();
- titlebar(NULL);
- return 1;
-}
-
int do_cursorpos(int constant)
{
filestruct *fileptr;
@@ -1703,45 +1700,20 @@ int do_help(void)
return 1;
}
-#ifdef DEBUG
-/* Dump the current file structure to stderr */
-void dump_buffer(const filestruct *inptr) {
- if (inptr == 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, "(%d) %s\n", inptr->lineno, inptr->data);
- inptr = inptr->next;
- }
-}
-#endif /* DEBUG */
-
-#ifdef DEBUG
-void dump_buffer_reverse(void) {
- const filestruct *fileptr = filebot;
-
- while (fileptr != NULL) {
- fprintf(stderr, "(%d) %s\n", fileptr->lineno, fileptr->data);
- fileptr = fileptr->prev;
- }
-}
-#endif /* DEBUG */
-
-/* Fix editbot, based on the assumption that edittop is correct */
-void fix_editbot(void)
+int keypad_on(WINDOW * win, int newval)
{
- int i;
-
- editbot = edittop;
- for (i = 0; i < editwinrows && editbot->next != NULL; i++)
- editbot = editbot->next;
+/* This is taken right from aumix. Don't sue me. */
+#ifdef HAVE_USEKEYPAD
+ int old = win->_use_keypad;
+ keypad(win, newval);
+ return old;
+#else
+ keypad(win, newval);
+ return 1;
+#endif /* HAVE_USEKEYPAD */
}
-/* highlight the current word being replaced or spell checked */
+/* Highlight the current word being replaced or spell checked. */
void do_replace_highlight(int highlight_flag, const char *word)
{
char *highlight_word = NULL;
@@ -1786,6 +1758,44 @@ void do_replace_highlight(int highlight_flag, const char *word)
free(highlight_word);
}
+/* Fix editbot, based on the assumption that edittop is correct. */
+void fix_editbot(void)
+{
+ int i;
+
+ editbot = edittop;
+ for (i = 0; i < editwinrows && editbot->next != NULL; i++)
+ editbot = editbot->next;
+}
+
+#ifdef DEBUG
+/* Dump the current file structure to stderr */
+void dump_buffer(const filestruct *inptr) {
+ if (inptr == 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, "(%d) %s\n", inptr->lineno, inptr->data);
+ inptr = inptr->next;
+ }
+}
+#endif /* DEBUG */
+
+#ifdef DEBUG
+void dump_buffer_reverse(void) {
+ const filestruct *fileptr = filebot;
+
+ while (fileptr != NULL) {
+ fprintf(stderr, "(%d) %s\n", fileptr->lineno, fileptr->data);
+ fileptr = fileptr->prev;
+ }
+}
+#endif /* DEBUG */
+
#ifdef NANO_EXTRA
#define CREDIT_LEN 52
#define XLCREDIT_LEN 8
@@ -1904,16 +1914,3 @@ void do_credits(void)
total_refresh();
}
#endif
-
-int keypad_on(WINDOW * win, int newval)
-{
-/* This is taken right from aumix. Don't sue me. */
-#ifdef HAVE_USEKEYPAD
- int old = win->_use_keypad;
- keypad(win, newval);
- return old;
-#else
- keypad(win, newval);
- return 1;
-#endif /* HAVE_USEKEYPAD */
-}