Commit 2d7893d0 authored by Chris Allegretta's avatar Chris Allegretta
Browse files

Added multi buffer (load on insert) code. This wont intoduce any bugs ;-)

git-svn-id: svn://svn.savannah.gnu.org/nano/trunk/nano@722 35c25a1d-7b9e-4130-9fde-d3aeb78583b8
No related merge requests found
Showing with 1938 additions and 1073 deletions
+1938 -1073
......@@ -51,6 +51,14 @@ Cvs code -
- New macro TOGGLE which just toggles, no more silly checking
ISSET and then using SET or UNSET when we want a simple toggle
for a flag.
- Added multiple buffer capability (God help us). New configure
option --enable-loadoninsert (-L), changes to do_insertfile(),
do_insertfile_void(), toggle_init(), do_gotoline(), edit_update(),
and write_file(), new functions add_open_file(),
open_file_change_name(), load_open_file(), open_file_dup_search(),
open_file_dup_fix(), open_prevfile(), open_nextfile(),
close_open_file(), get_full_path(), die_save_file(), etc.
(David Lawrence Ramsey).
- Makefile.am:
- Include ABOUT-NLS and the new THANKS files to the distributed list.
- THANKS:
......
......@@ -57,24 +57,27 @@ POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
host_alias = @host_alias@
host_triplet = @host@
BUILD_INCLUDED_LIBINTL = @BUILD_INCLUDED_LIBINTL@
CATALOGS = @CATALOGS@
CATOBJEXT = @CATOBJEXT@
CC = @CC@
CURSES_LIB = @CURSES_LIB@
DATADIRNAME = @DATADIRNAME@
GENCAT = @GENCAT@
GLIBC21 = @GLIBC21@
GLIB_CFLAGS = @GLIB_CFLAGS@
GLIB_CONFIG = @GLIB_CONFIG@
GLIB_LIBS = @GLIB_LIBS@
GMOFILES = @GMOFILES@
GMSGFMT = @GMSGFMT@
GT_NO = @GT_NO@
GT_YES = @GT_YES@
INCLUDE_LOCALE_H = @INCLUDE_LOCALE_H@
INSTOBJEXT = @INSTOBJEXT@
INTLDEPS = @INTLDEPS@
INTLBISON = @INTLBISON@
INTLLIBS = @INTLLIBS@
INTLOBJS = @INTLOBJS@
INTL_LIBTOOL_SUFFIX_PREFIX = @INTL_LIBTOOL_SUFFIX_PREFIX@
LIBICONV = @LIBICONV@
MKINSTALLDIRS = @MKINSTALLDIRS@
MSGFMT = @MSGFMT@
PACKAGE = @PACKAGE@
......@@ -84,7 +87,6 @@ RANLIB = @RANLIB@
USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@
USE_NLS = @USE_NLS@
VERSION = @VERSION@
l = @l@
bin_PROGRAMS = nano
nano_SOURCES = color.c cut.c files.c global.c move.c nano.c nano.h proto.h rcfile.c search.c utils.c winio.c
......
......@@ -54,6 +54,9 @@
/* Define this to disable the mouse functions */
#undef DISABLE_MOUSE
/* Define this to load files upon inserting them, and allow switching between them; this is disabled if NANO_SMALL is defined */
#undef ENABLE_LOADONINSERT
/* Define this to use the .nanorc file */
#undef ENABLE_NANORC
......
This diff is collapsed.
......@@ -31,9 +31,6 @@
/* Define to `long' if <sys/types.h> doesn't define. */
#undef off_t
/* Define if you need to in order for stat and other things to work. */
#undef _POSIX_SOURCE
/* Define as the return type of signal handlers (int or void). */
#undef RETSIGTYPE
......@@ -61,21 +58,6 @@
/* Define this if your curses lib has the _use_keypad flag */
#undef HAVE_USEKEYPAD
/* Define this if you have NLS */
#undef ENABLE_NLS
/* Define this is you have the catgets command */
#undef HAVE_CATGETS
/* Define this is you have GNU gettext */
#undef HAVE_GETTEXT
/* Define this for HAVE_LC_MESSAGES */
#undef HAVE_LC_MESSAGES
/* Define this if you have the stpcpy function (cool) */
#undef HAVE_STPCPY
/* Define this to make the nano executable as small as possible */
#undef NANO_SMALL
......@@ -106,6 +88,9 @@
/* Define this to disable the mouse functions */
#undef DISABLE_MOUSE
/* Define this to load files upon inserting them, and allow switching between them; this is disabled if NANO_SMALL is defined */
#undef ENABLE_LOADONINSERT
/* Define this to use the .nanorc file */
#undef ENABLE_NANORC
......@@ -127,15 +112,36 @@
/* Define if you have the dcgettext function. */
#undef HAVE_DCGETTEXT
/* Define if you have the feof_unlocked function. */
#undef HAVE_FEOF_UNLOCKED
/* Define if you have the fgets_unlocked function. */
#undef HAVE_FGETS_UNLOCKED
/* Define if you have the getcwd function. */
#undef HAVE_GETCWD
/* Define if you have the getegid function. */
#undef HAVE_GETEGID
/* Define if you have the geteuid function. */
#undef HAVE_GETEUID
/* Define if you have the getgid function. */
#undef HAVE_GETGID
/* Define if you have the getopt_long function. */
#undef HAVE_GETOPT_LONG
/* Define if you have the getpagesize function. */
#undef HAVE_GETPAGESIZE
/* Define if you have the getuid function. */
#undef HAVE_GETUID
/* Define if you have the mempcpy function. */
#undef HAVE_MEMPCPY
/* Define if you have the munmap function. */
#undef HAVE_MUNMAP
......@@ -163,6 +169,12 @@
/* Define if you have the strdup function. */
#undef HAVE_STRDUP
/* Define if you have the strtoul function. */
#undef HAVE_STRTOUL
/* Define if you have the tsearch function. */
#undef HAVE_TSEARCH
/* Define if you have the vsnprintf function. */
#undef HAVE_VSNPRINTF
......@@ -196,6 +208,12 @@
/* Define if you have the <regex.h> header file. */
#undef HAVE_REGEX_H
/* Define if you have the <stddef.h> header file. */
#undef HAVE_STDDEF_H
/* Define if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
/* Define if you have the <string.h> header file. */
#undef HAVE_STRING_H
......@@ -211,12 +229,28 @@
/* Define if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
/* Define if you have the i library (-li). */
#undef HAVE_LIBI
/* Name of package */
#undef PACKAGE
/* Version number of package */
#undef VERSION
/* Define if you have the iconv() function. */
#undef HAVE_ICONV
/* Define as const if the declaration of iconv() needs const. */
#undef ICONV_CONST
/* Define if you have <langinfo.h> and nl_langinfo(CODESET). */
#undef HAVE_LANGINFO_CODESET
/* Define if your <locale.h> file defines LC_MESSAGES. */
#undef HAVE_LC_MESSAGES
/* Define to 1 if translation of program messages to the user's native language
is requested. */
#undef ENABLE_NLS
/* Define if the GNU gettext() function is already present or preinstalled. */
#undef HAVE_GETTEXT
This diff is collapsed.
......@@ -33,6 +33,12 @@ AC_ARG_ENABLE(extra,
AC_DEFINE(NANO_EXTRA) extra_support=yes
fi])
AC_ARG_ENABLE(loadoninsert,
[ --enable-loadoninsert Enable use of file loading on insertion, and switching between loaded files; this is disabled if --enable-tiny is used],
[if test x$enableval = xyes && test x$tiny_support != xyes; then
AC_DEFINE(ENABLE_LOADONINSERT) loadoninsert_support=yes
fi])
AC_ARG_ENABLE(nanorc,
[ --enable-nanorc Enable use of .nanorc file],
[if test x$enableval = xyes; then
......
......@@ -47,6 +47,16 @@
void load_file(void)
{
current = fileage;
#ifdef ENABLE_LOADONINSERT
/* add a new entry to the open_files structure, and check for
duplicate entries; if a duplicate entry was found, reload the
currently open file (it may have been changed during duplicate
handling) */
if (add_open_file(0, 1) == 2)
load_open_file();
#endif
wmove(edit, current_y, current_x);
}
......@@ -253,7 +263,7 @@ int open_file(char *filename, int insert, int quiet)
return 1;
}
int do_insertfile(void)
int do_insertfile(int loading_file)
{
int i;
char *realname = NULL;
......@@ -270,7 +280,7 @@ int do_insertfile(void)
if (i != -1) {
#ifdef DEBUG
fprintf(stderr, "filename is %s", answer);
fprintf(stderr, _("filename is %s"), answer);
#endif
#ifndef DISABLE_TABCOMP
......@@ -294,19 +304,57 @@ int do_insertfile(void)
if (tmp != NULL)
realname = mallocstrcpy(realname, tmp);
else
return do_insertfile();
return do_insertfile(loading_file);
}
#endif
#ifdef ENABLE_LOADONINSERT
if (loading_file) {
/* update the current entry in the open_files structure; we
don't need to check for duplicate entries (the conditions
that could create them are taken care of elsewhere) */
add_open_file(1, 0);
free_filestruct(current);
new_file();
UNSET(MODIFIED);
}
#endif
i = open_file(realname, 1, 0);
#ifdef ENABLE_LOADONINSERT
if (loading_file)
filename = mallocstrcpy(filename, realname);
#endif
free(realname);
dump_buffer(fileage);
set_modified();
#ifdef ENABLE_LOADONINSERT
if (loading_file)
load_file();
else
#endif
set_modified();
/* Here we want to rebuild the edit window */
fix_editbot();
#ifdef ENABLE_LOADONINSERT
/* If we've loaded another file, update the titlebar's contents */
if (loading_file) {
clearok(topwin, FALSE);
titlebar(NULL);
/* And re-init the shortcut list */
shortcut_init(0);
}
#endif
/* If we've gone off the bottom, recenter; otherwise, just redraw */
if (current->lineno > editbot->lineno)
edit_update(current, CENTER);
......@@ -324,6 +372,479 @@ int do_insertfile(void)
}
}
int do_insertfile_void(void)
{
int result = 0;
#ifdef ENABLE_LOADONINSERT
result = do_insertfile(ISSET(LOADONINSERT));
#else
result = do_insertfile(0);
#endif
display_main_list();
return result;
}
#ifdef ENABLE_LOADONINSERT
/*
* Add/update an entry to the open_files filestruct. If update is
* zero, a new entry is created; otherwise, the current entry is updated.
* If dup_fix is zero, checking for and handling duplicate entries is not
* done; otherwise, it is. Return 0 on success, 1 on error, or 2 on
* finding a duplicate entry.
*/
int add_open_file(int update, int dup_fix)
{
filestruct *tmp;
if (!current || !filename)
return 1;
/* first, if duplicate checking is allowed, do it */
if (dup_fix) {
/* if duplicates were found and handled, we're done */
if (open_file_dup_fix(update))
return 2;
}
/* if no entries, make the first one */
if (!open_files) {
open_files = make_new_node(NULL);
/* if open_files->file is NULL at the nrealloc() below, we get a
segfault */
open_files->file = open_files;
}
else if (!update) {
/* otherwise, if we're not updating, make a new entry for
open_files and splice it in after the current one */
#ifdef DEBUG
fprintf(stderr, _("filename is %s"), open_files->data);
#endif
tmp = make_new_node(NULL);
splice_node(open_files, tmp, open_files->next);
open_files = open_files->next;
/* if open_files->file is NULL at the nrealloc() below, we get a
segfault */
open_files->file = open_files;
}
/* save current filename */
open_files->data = mallocstrcpy(open_files->data, filename);
/* save the full path location */
open_files->file_path = get_full_path(open_files->data);
/* save current total number of lines */
open_files->file_totlines = totlines;
/* save current total size */
open_files->file_totsize = totsize;
/* save current x-coordinate position */
open_files->file_current_x = current_x;
/* save current y-coordinate position */
open_files->file_current_y = current_y;
/* save current place we want */
open_files->file_placewewant = placewewant;
/* save current line number */
open_files->lineno = current->lineno;
/* save current filestruct */
open_files->file = nrealloc(open_files->file, sizeof(filestruct));
while (current->prev)
current = current->prev;
open_files->file = copy_filestruct(current);
do_gotoline(open_files->lineno, 1);
placewewant = open_files->file_placewewant;
update_line(current, current_x);
/* save current modification status */
open_files->file_modified = ISSET(MODIFIED);
#ifdef DEBUG
fprintf(stderr, _("filename is %s"), open_files->data);
#endif
return 0;
}
/*
* Update only the filename and full path stored in the current entry.
* Return 0 on success or 1 on error.
*/
int open_file_change_name(void)
{
if (!open_files || !filename)
return 1;
/* save current filename */
open_files->data = mallocstrcpy(open_files->data, filename);
/* save the full path location */
open_files->file_path = get_full_path(open_files->data);
return 0;
}
/*
* Read the current entry in the open_files structure and set up the
* currently open file using that entry's information. Return 0 on
* success or 1 on error.
*/
int load_open_file(void)
{
if (!open_files)
return 1;
/* set up the filename, the file buffer, the total number of lines in
the file, and the total file size */
filename = mallocstrcpy(filename, open_files->data);
fileage = copy_filestruct(open_files->file);
current = fileage;
totlines = open_files->file_totlines;
totsize = open_files->file_totsize;
/* since do_gotoline() resets the x-coordinate but not the
y-coordinate, set all coordinates up this way */
current_y = open_files->file_current_y;
do_gotoline(open_files->lineno, 1);
current_x = open_files->file_current_x;
placewewant = open_files->file_placewewant;
update_line(current, current_x);
/* set up modification status and update the titlebar */
if (open_files->file_modified)
SET(MODIFIED);
else
UNSET(MODIFIED);
clearok(topwin, FALSE);
titlebar(NULL);
/* if we're constantly displaying the cursor position, update it */
if (ISSET(CONSTUPDATE))
do_cursorpos();
/* now we're done */
return 0;
}
/*
* Search the open_files structure for an entry with the same value for
* the file_path member as the current entry (i. e. a duplicate entry).
* If one is found, return a pointer to it; otherwise, return NULL.
*
* Note: This should only be called inside open_file_dup_fix().
*/
filestruct *open_file_dup_search(void)
{
filestruct *tmp;
char *path;
if (!open_files || !filename)
return NULL;
tmp = open_files;
path = get_full_path(filename);
/* if there's only one entry, handle it */
if (!tmp->prev && !tmp->next) {
if (!strcmp(tmp->file_path, path))
return tmp;
}
/* otherwise, go to the beginning */
while (tmp->prev)
tmp = tmp->prev;
/* and search the entries one by one */
while (tmp) {
if (!strcmp(tmp->file_path, path)) {
/* if it's not the current entry, we've found a duplicate */
if (tmp != open_files)
return tmp;
}
/* go to the next entry */
tmp = tmp->next;
}
return NULL;
}
/*
* Search for duplicate entries in the open_files structure using
* open_file_dup_search(), and, if one is found, handle it properly.
* Return 0 if no duplicates were found, and 1 otherwise.
*/
int open_file_dup_fix(int update)
{
filestruct *tmp = open_file_dup_search();
if (!tmp)
return 0;
/* if there's only one entry, handle it */
if (!tmp->prev && !tmp->next)
return 1;
/* otherwise, if we're not updating, the user's trying to load a
duplicate; switch to the original instead */
if (!update) {
open_files = tmp;
return 1;
}
/* if we are updating, the filename's been changed via a save; it's
thus more recent than the original, so remove the original */
else {
unlink_node(tmp);
free_filestruct(tmp->file);
free(tmp->file_path);
delete_node(tmp);
}
return 0;
}
/*
* Open the previous entry in the open_files structure. If closing_file
* is zero, update the current entry before switching from it.
* Otherwise, we are about to close that entry, so don't bother doing so.
* Return 0 on success and 1 on error.
*/
int open_prevfile(int closing_file)
{
if (!open_files)
return 1;
/* if we're not about to close the current entry, update it before
doing anything; since we're only switching, we don't need to check
for duplicate entries */
if (!closing_file)
add_open_file(1, 0);
if (!open_files->prev && !open_files->next) {
/* only one file open */
if (!closing_file)
statusbar(_("No more open files"));
return 1;
}
if (open_files->prev) {
open_files = open_files->prev;
#ifdef DEBUG
fprintf(stderr, _("filename is %s"), open_files->data);
#endif
}
else if (open_files->next) {
/* if we're at the beginning, wrap around to the end */
while (open_files->next)
open_files = open_files->next;
#ifdef DEBUG
fprintf(stderr, _("filename is %s"), open_files->data);
#endif
}
load_open_file();
#ifdef DEBUG
dump_buffer(current);
#endif
return 0;
}
/*
* Open the next entry in the open_files structure. If closing_file is
* zero, update the current entry before switching from it. Otherwise, we
* are about to close that entry, so don't bother doing so. Return 0 on
* success and 1 on error.
*/
int open_nextfile(int closing_file)
{
if (!open_files)
return 1;
/* if we're not about to close the current entry, update it before
doing anything; since we're only switching, we don't need to check
for duplicate entries */
if (!closing_file)
add_open_file(1, 0);
if (!open_files->prev && !open_files->next) {
/* only one file open */
if (!closing_file)
statusbar(_("No more open files"));
return 1;
}
if (open_files->next) {
open_files = open_files->next;
#ifdef DEBUG
fprintf(stderr, _("filename is %s"), open_files->data);
#endif
}
else if (open_files->prev) {
/* if we're at the end, wrap around to the beginning */
while (open_files->prev) {
open_files = open_files->prev;
#ifdef DEBUG
fprintf(stderr, _("filename is %s"), open_files->data);
#endif
}
}
load_open_file();
#ifdef DEBUG
dump_buffer(current);
#endif
return 0;
}
/*
* Delete an entry from the open_files filestruct. After deletion of an
* entry, the previous or next entry is opened, whichever is found first.
* Return 0 on success or 1 on error.
*/
int close_open_file(void)
{
filestruct *tmp;
if (!open_files)
return 1;
tmp = open_files;
if (open_prevfile(1)) {
if (open_nextfile(1))
return 1;
}
unlink_node(tmp);
free_filestruct(tmp->file);
free(tmp->file_path);
delete_node(tmp);
shortcut_init(0);
display_main_list();
return 0;
}
/*
* When passed "[relative path][filename]" in origpath, return "[full
* path][filename]" on success, or NULL on error.
*/
char *get_full_path(const char *origpath)
{
char *newpath = NULL, *last_slash, *d_here, *d_there, *d_there_file;
int last_slash_index;
/* first, get the current directory */
#ifdef PATH_MAX
d_here = getcwd(NULL, PATH_MAX + 1);
#else
d_here = getcwd(NULL, 0);
#endif
if (d_here) {
align(&d_here);
/* get the filename (with path included) and save it in both
d_there and d_there_file */
d_there = charalloc(strlen(origpath) + 1);
d_there_file = charalloc(strlen(origpath) + 1);
strcpy(d_there, origpath);
strcpy(d_there_file, origpath);
/* search for the last slash in d_there */
last_slash = strrchr(d_there, '/');
/* if we didn't find one, copy d_here into d_there; all data is
then set up */
if (!last_slash) {
d_there = nrealloc(d_there, strlen(d_here) + 1);
strcpy(d_there, d_here);
}
else {
/* otherwise, remove all non-path elements from d_there */
last_slash_index = strlen(d_there) - strlen(last_slash);
null_at(d_there, last_slash_index);
/* and remove all non-file elements from d_there_file */
last_slash++;
d_there_file = nrealloc(d_there_file, strlen(last_slash) + 1);
strcpy(d_there_file, last_slash);
/* now go to the path specified in d_there */
if (chdir(d_there) != -1) {
/* get the full pathname, and save it back in d_there */
free(d_there);
#ifdef PATH_MAX
d_there = getcwd(NULL, PATH_MAX + 1);
#else
d_there = getcwd(NULL, 0);
#endif
align(&d_there);
}
/* finally, go back to where we were before, d_here (no error
checking is done on this chdir(), because we can do
nothing if it fails) */
chdir(d_here);
}
/* all data is set up; fill in newpath */
/* newpath = d_there + "/" + d_there_file */
newpath = charalloc(strlen(d_there) + strlen(d_there_file) + 2);
strcpy(newpath, d_there);
strcat(newpath, "/");
strcat(newpath, d_there_file);
/* finally, clean up */
free(d_there_file);
free(d_there);
free(d_here);
}
return newpath;
}
#endif
/*
* Write a file out. If tmp is nonzero, we set the umask to 0600,
* we don't set the global variable filename to its name, and don't
......@@ -637,7 +1158,29 @@ int do_writeout(char *path, int exiting, int append)
} else
#endif
i = write_file(answer, 0, append, 0);
#ifdef ENABLE_LOADONINSERT
/* if we're not about to exit, update the current entry in
the open_files structure */
if (!exiting) {
/* first, if the filename was changed during the save,
update the filename and full path stored in the
current entry, and then update the current entry,
checking for duplicate entries */
if (strcmp(open_files->data, filename)) {
open_file_change_name();
add_open_file(1, 1);
}
else {
/* otherwise, just update the current entry without
checking for duplicate entries */
add_open_file(1, 0);
}
}
#endif
display_main_list();
return i;
} else {
......
......@@ -54,6 +54,10 @@ filestruct *editbot = NULL; /* Same for the bottom */
filestruct *filebot = NULL; /* Last node in the file struct */
filestruct *cutbuffer = NULL; /* A place to store cut text */
#ifdef ENABLE_LOADONINSERT
filestruct *open_files = NULL; /* The list of open files */
#endif
char *answer = NULL; /* Answer str to many questions */
int totlines = 0; /* Total number of lines in the file */
int totsize = 0; /* Total number of bytes in the file */
......@@ -126,11 +130,13 @@ void sc_init_one(shortcut * s, int key, char *desc, char *help, int alt,
#ifndef NANO_SMALL
/* Initialize the toggles in the same manner */
void toggle_init_one(toggle * t, int val, char *desc, int flag)
void toggle_init_one(toggle * t, int val, char *desc, int flag,
char override_ch)
{
t->val = val;
t->desc = desc;
t->flag = flag;
t->override_ch = override_ch;
}
#endif
......@@ -141,6 +147,11 @@ void toggle_init(void)
*toggle_nohelp_msg, *toggle_picomode_msg, *toggle_mouse_msg,
*toggle_cuttoend_msg, *toggle_wrap_msg, *toggle_case_msg,
*toggle_backwards_msg;
#ifdef ENABLE_LOADONINSERT
char *toggle_load_msg, *nano_openprev_msg, *nano_opennext_msg;
#endif
#ifdef HAVE_REGEX_H
char *toggle_regexp_msg;
#endif
......@@ -159,29 +170,45 @@ void toggle_init(void)
#endif
toggle_wrap_msg = _("Auto wrap");
#ifdef ENABLE_LOADONINSERT
toggle_load_msg = _("File loading on insertion");
nano_openprev_msg = _("Open previously loaded file");
nano_opennext_msg = _("Open next loaded file");
#endif
toggle_init_one(&toggles[0], TOGGLE_CONST_KEY, toggle_const_msg,
CONSTUPDATE);
CONSTUPDATE, 0);
toggle_init_one(&toggles[1], TOGGLE_AUTOINDENT_KEY,
toggle_autoindent_msg, AUTOINDENT);
toggle_autoindent_msg, AUTOINDENT, 0);
toggle_init_one(&toggles[2], TOGGLE_SUSPEND_KEY, toggle_suspend_msg,
SUSPEND);
SUSPEND, 0);
toggle_init_one(&toggles[3], TOGGLE_NOHELP_KEY, toggle_nohelp_msg,
NO_HELP);
NO_HELP, 0);
toggle_init_one(&toggles[4], TOGGLE_PICOMODE_KEY, toggle_picomode_msg,
PICO_MODE);
PICO_MODE, 0);
toggle_init_one(&toggles[5], TOGGLE_WRAP_KEY, toggle_wrap_msg,
NO_WRAP);
NO_WRAP, 0);
toggle_init_one(&toggles[6], TOGGLE_MOUSE_KEY, toggle_mouse_msg,
USE_MOUSE);
USE_MOUSE, 0);
toggle_init_one(&toggles[7], TOGGLE_CUTTOEND_KEY, toggle_cuttoend_msg,
CUT_TO_END);
CUT_TO_END, 0);
toggle_init_one(&toggles[8], TOGGLE_BACKWARDS_KEY, toggle_backwards_msg,
REVERSE_SEARCH);
REVERSE_SEARCH, 0);
toggle_init_one(&toggles[9], TOGGLE_CASE_KEY, toggle_case_msg,
CASE_SENSITIVE);
CASE_SENSITIVE, 0);
#ifdef ENABLE_LOADONINSERT
toggle_init_one(&toggles[10], TOGGLE_LOAD_KEY, toggle_load_msg,
LOADONINSERT, 0);
toggle_init_one(&toggles[11], NANO_OPENPREV_KEY, nano_openprev_msg,
0, '<');
toggle_init_one(&toggles[12], NANO_OPENNEXT_KEY, nano_opennext_msg,
0, '>');
#endif
#ifdef HAVE_REGEX_H
toggle_init_one(&toggles[10], TOGGLE_REGEXP_KEY, toggle_regexp_msg,
USE_REGEXP);
toggle_init_one(&toggles[TOGGLE_LEN - 1], TOGGLE_REGEXP_KEY,
toggle_regexp_msg, USE_REGEXP, 0);
#endif
#endif
}
......@@ -210,7 +237,13 @@ void shortcut_init(int unjustify)
nano_help_msg = _("Invoke the help menu");
nano_writeout_msg = _("Write the current file to disk");
#ifdef ENABLE_LOADONINSERT
nano_exit_msg = _("Close currently loaded file/Exit from nano");
#else
nano_exit_msg = _("Exit from nano");
#endif
nano_goto_msg = _("Goto a specific line number");
nano_justify_msg = _("Justify the current paragraph");
nano_unjustify_msg = _("Unjustify after a justify");
......@@ -251,7 +284,13 @@ void shortcut_init(int unjustify)
sc_init_one(&main_list[0], NANO_HELP_KEY, _("Get Help"),
nano_help_msg, 0, NANO_HELP_FKEY, 0, VIEW, do_help);
sc_init_one(&main_list[1], NANO_EXIT_KEY, _("Exit"),
#ifdef ENABLE_LOADONINSERT
if (open_files != NULL && (open_files->prev || open_files->next))
sc_init_one(&main_list[1], NANO_EXIT_KEY, _("Close"),
nano_exit_msg, 0, NANO_EXIT_FKEY, 0, VIEW, do_exit);
else
#endif
sc_init_one(&main_list[1], NANO_EXIT_KEY, _("Exit"),
nano_exit_msg, 0, NANO_EXIT_FKEY, 0, VIEW, do_exit);
sc_init_one(&main_list[2], NANO_WRITEOUT_KEY, _("WriteOut"),
......@@ -265,13 +304,13 @@ void shortcut_init(int unjustify)
else
sc_init_one(&main_list[3], NANO_INSERTFILE_KEY, _("Read File"),
nano_insert_msg,
0, NANO_INSERTFILE_FKEY, 0, NOVIEW, do_insertfile);
0, NANO_INSERTFILE_FKEY, 0, NOVIEW, do_insertfile_void);
if (ISSET(PICO_MODE))
sc_init_one(&main_list[4], NANO_INSERTFILE_KEY, _("Read File"),
nano_insert_msg,
0, NANO_INSERTFILE_FKEY, 0, NOVIEW, do_insertfile);
0, NANO_INSERTFILE_FKEY, 0, NOVIEW, do_insertfile_void);
else
sc_init_one(&main_list[4], NANO_REPLACE_KEY, _("Replace"),
nano_replace_msg,
......
......@@ -107,41 +107,76 @@ RETSIGTYPE finish(int sigage)
void die(char *msg, ...)
{
va_list ap;
char *name;
int i;
va_start(ap, msg);
vfprintf(stderr, msg, ap);
va_end(ap);
/* Restore the old term settings */
tcsetattr(0, TCSANOW, &oldterm);
clear();
refresh();
resetty();
endwin();
fprintf(stderr, msg);
/* save the currently loaded file (if modified, its open_files entry
isn't up to date) */
die_save_file(filename);
#ifdef ENABLE_LOADONINSERT
/* then save all of the other loaded files, if any */
if (open_files) {
filestruct *tmp;
tmp = open_files;
while (open_files->prev)
open_files = open_files->prev;
while (open_files->next) {
/* if we already saved the file above (i. e. if it was the
currently loaded file), don't save it again */
if (tmp != open_files) {
fileage = open_files->file;
die_save_file(open_files->data);
}
open_files = open_files->next;
}
}
#endif
exit(1); /* We have a problem: exit w/ errorlevel(1) */
}
void die_save_file(char *die_filename)
{
char *name;
int i;
/* if we can't save we have REAL bad problems,
* but we might as well TRY. */
if (filename[0] == '\0') {
if (die_filename[0] == '\0') {
name = "nano.save";
i = write_file(name, 1, 0, 0);
} else {
char *buf = charalloc(strlen(filename) + 6);
strcpy(buf, filename);
char *buf = charalloc(strlen(die_filename) + 6);
strcpy(buf, die_filename);
strcat(buf, ".save");
i = write_file(buf, 1, 0, 0);
name = buf;
}
/* Restore the old term settings */
tcsetattr(0, TCSANOW, &oldterm);
clear();
refresh();
resetty();
endwin();
fprintf(stderr, msg);
if (i != -1)
fprintf(stderr, _("\nBuffer written to %s\n"), name);
else
fprintf(stderr, _("\nNo %s written (file exists?)\n"), name);
exit(1); /* We have a problem: exit w/ errorlevel(1) */
}
/* Die with an error message that the screen was too small if, well, the
......@@ -225,7 +260,8 @@ void init_help_msg(void)
}
#endif
/* Make a copy of a node to a pointer (space will be malloc()ed) */
/* Make a copy of a node to a pointer (space will be malloc()ed). This
does NOT copy the data members used only by open_files. */
filestruct *copy_node(filestruct * src)
{
filestruct *dst;
......@@ -252,6 +288,8 @@ void unlink_node(filestruct * fileptr)
fileptr->next->prev = fileptr->prev;
}
/* Delete a node from the struct. This does NOT delete the data members
used only by open_files. */
void delete_node(filestruct * fileptr)
{
if (fileptr == NULL)
......@@ -262,7 +300,8 @@ void delete_node(filestruct * fileptr)
free(fileptr);
}
/* Okay, now let's duplicate a whole struct! */
/* Okay, now let's duplicate a whole struct! This does NOT duplicate the
data members used only by open_files. */
filestruct *copy_filestruct(filestruct * src)
{
filestruct *dst, *tmp, *head, *prev;
......@@ -286,6 +325,8 @@ filestruct *copy_filestruct(filestruct * src)
return head;
}
/* Frees a struct. This does NOT free the data members used only by
open_files. */
int free_filestruct(filestruct * src)
{
filestruct *fileptr = src;
......@@ -360,6 +401,13 @@ void usage(void)
#ifdef HAVE_GETOPT_LONG
printf(_("Usage: nano [GNU long option] [option] +LINE <file>\n\n"));
printf(_("Option Long option Meaning\n"));
#ifdef ENABLE_LOADONINSERT
printf
(_
(" -L --loadoninsert Enable file loading on insertion\n"));
#endif
printf(_
(" -T [num] --tabsize=[num] Set width of a tab to num\n"));
#ifdef HAVE_REGEX_H
......@@ -463,6 +511,9 @@ void version(void)
#ifdef NANO_EXTRA
printf(" --enable-extra");
#endif
#ifdef ENABLE_LOADONINSERT
printf(" --enable-loadoninsert");
#endif
#ifdef ENABLE_NANORC
printf(" --enable-nanorc");
#endif
......@@ -503,6 +554,8 @@ void version(void)
}
/* Create a new node. This does NOT initialize the data members used
only by open_files. */
filestruct *make_new_node(filestruct * prevnode)
{
filestruct *newnode;
......@@ -519,7 +572,8 @@ filestruct *make_new_node(filestruct * prevnode)
return newnode;
}
/* Splice a node into an existing filestruct */
/* Splice a node into an existing filestruct. This does NOT set the data
members used only by open_files. */
void splice_node(filestruct * begin, filestruct * newnode,
filestruct * end)
{
......@@ -1459,9 +1513,17 @@ int do_alt_speller(char *file_name)
global_init();
open_file(file_name, 0, 1);
do_gotoline(lineno_cur);
do_gotoline(lineno_cur, 0);
set_modified();
#ifdef ENABLE_LOADONINSERT
/* if we have multiple files open, the spell-checked (current) file
is now stored after the un-spell-checked file in the open_files
structure, so go back to the un-spell-checked file and close it */
open_prevfile(0);
close_open_file();
#endif
return TRUE;
}
#endif
......@@ -1508,8 +1570,18 @@ int do_exit(void)
{
int i;
if (!ISSET(MODIFIED))
finish(0);
if (!ISSET(MODIFIED)) {
#ifdef ENABLE_LOADONINSERT
if (!close_open_file()) {
display_main_list();
return 1;
}
else
#endif
finish(0);
}
if (ISSET(TEMP_OPT)) {
i = 1;
......@@ -1524,11 +1596,30 @@ int do_exit(void)
#endif
if (i == 1) {
if (do_writeout(filename, 1, 0) > 0)
if (do_writeout(filename, 1, 0) > 0) {
#ifdef ENABLE_LOADONINSERT
if (!close_open_file()) {
display_main_list();
return 1;
}
else
#endif
finish(0);
}
} else if (i == 0) {
#ifdef ENABLE_LOADONINSERT
if (!close_open_file()) {
display_main_list();
return 1;
}
else
#endif
finish(0);
} else if (i == 0)
finish(0);
else
} else
statusbar(_("Cancelled"));
display_main_list();
......@@ -2139,12 +2230,21 @@ void help_init(void)
/* And the toggles... */
for (i = 0; i <= TOGGLE_LEN - 1; i++) {
sofar = snprintf(buf, BUFSIZ,
"M-%c ", toggles[i].val - 32);
if (toggles[i].override_ch != 0)
sofar = snprintf(buf, BUFSIZ,
"M-%c ", toggles[i].override_ch);
else
sofar = snprintf(buf, BUFSIZ,
"M-%c ", toggles[i].val - 32);
if (toggles[i].desc != NULL)
snprintf(&buf[sofar], BUFSIZ - sofar, _("%s enable/disable"),
toggles[i].desc);
if (toggles[i].desc != NULL) {
if (toggles[i].flag != 0)
snprintf(&buf[sofar], BUFSIZ - sofar, _("%s enable/disable"),
toggles[i].desc);
else
snprintf(&buf[sofar], BUFSIZ - sofar, _("%s"),
toggles[i].desc);
}
strcat(help_text, buf);
strcat(help_text, "\n");
......@@ -2183,21 +2283,43 @@ void do_toggle(int which)
edit_refresh();
display_main_list();
break;
#ifdef ENABLE_LOADONINSERT
case NANO_OPENPREV_KEY:
open_prevfile(0);
break;
case NANO_OPENNEXT_KEY:
open_nextfile(0);
break;
#endif
}
if (!ISSET(toggles[which].flag)) {
if (toggles[which].val == TOGGLE_NOHELP_KEY ||
toggles[which].val == TOGGLE_WRAP_KEY)
statusbar("%s %s", toggles[which].desc, enabled);
else
statusbar("%s %s", toggles[which].desc, disabled);
} else {
if (toggles[which].val == TOGGLE_NOHELP_KEY ||
toggles[which].val == TOGGLE_WRAP_KEY)
statusbar("%s %s", toggles[which].desc, disabled);
else
statusbar("%s %s", toggles[which].desc, enabled);
#ifdef ENABLE_LOADONINSERT
/* NANO_OPENPREV_KEY and NANO_OPENNEXT_KEY aren't really toggles, so
don't display anything on the statusbar if they're pressed */
if (toggles[which].val != NANO_OPENPREV_KEY &&
toggles[which].val != NANO_OPENNEXT_KEY) {
#endif
if (!ISSET(toggles[which].flag)) {
if (toggles[which].val == TOGGLE_NOHELP_KEY ||
toggles[which].val == TOGGLE_WRAP_KEY)
statusbar("%s %s", toggles[which].desc, enabled);
else
statusbar("%s %s", toggles[which].desc, disabled);
} else {
if (toggles[which].val == TOGGLE_NOHELP_KEY ||
toggles[which].val == TOGGLE_WRAP_KEY)
statusbar("%s %s", toggles[which].desc, disabled);
else
statusbar("%s %s", toggles[which].desc, enabled);
}
#ifdef ENABLE_LOADONINSERT
}
#endif
SET(DISABLE_CURPOS);
#endif
......@@ -2279,6 +2401,11 @@ int main(int argc, char *argv[])
{"pico", 0, 0, 'p'},
{"nofollow", 0, 0, 'l'},
{"tabsize", 1, 0, 'T'},
#ifdef ENABLE_LOADONINSERT
{"loadoninsert", 0, 0, 'L'},
#endif
{0, 0, 0, 0}
};
#endif
......@@ -2299,14 +2426,21 @@ int main(int argc, char *argv[])
#endif /* ENABLE_NANORC */
#ifdef HAVE_GETOPT_LONG
while ((optchr = getopt_long(argc, argv, "?T:RVbcefghijklmpr:s:tvwxz",
while ((optchr = getopt_long(argc, argv, "h?LT:RVbcefgijklmpr:s:tvwxz",
long_options, &option_index)) != EOF) {
#else
while ((optchr =
getopt(argc, argv, "h?T:RVbcefgijklmpr:s:tvwxz")) != EOF) {
getopt(argc, argv, "h?LT:RVbcefgijklmpr:s:tvwxz")) != EOF) {
#endif
switch (optchr) {
#ifdef ENABLE_LOADONINSERT
case 'L':
SET(LOADONINSERT);
break;
#endif
case 'T':
tabsize = atoi(optarg);
if (tabsize <= 0) {
......@@ -2483,7 +2617,7 @@ int main(int argc, char *argv[])
open_file(filename, 0, 0);
if (startline > 0)
do_gotoline(startline);
do_gotoline(startline, 0);
else
edit_update(fileage, CENTER);
......@@ -2583,7 +2717,12 @@ int main(int argc, char *argv[])
break;
case 126: /* Hack, make insert key do something
useful, like insert file */
do_insertfile();
#ifdef ENABLE_LOADONINSERT
do_insertfile(ISSET(LOADONINSERT));
#else
do_insertfile(0);
#endif
keyhandled = 1;
break;
#ifdef DEBUG
......
......@@ -73,6 +73,18 @@ typedef struct filestruct {
char *data;
struct filestruct *next; /* Next node */
struct filestruct *prev; /* Previous node */
#ifdef ENABLE_LOADONINSERT
struct filestruct *file; /* Current file */
int file_current_x; /* Current file's x-coordinate position */
int file_current_y; /* Current file's y-coordinate position */
int file_modified; /* Current file's modification status */
char *file_path; /* Current file's full path location */
int file_placewewant; /* Current file's place we want */
int file_totlines; /* Current file's total number of lines */
int file_totsize; /* Current file's total size */
#endif
long lineno; /* The line number */
} filestruct;
......@@ -93,6 +105,8 @@ typedef struct toggle {
e.g. "Pico Messages"; we'll append Enabled or
Disabled */
int flag; /* What flag actually gets toggled */
char override_ch; /* The character to display on the help screen,
if it isn't NULL */
} toggle;
#ifdef ENABLE_NANORC
......@@ -125,6 +139,7 @@ typedef struct rcoption {
#define CUT_TO_END (1<<17)
#define DISABLE_CURPOS (1<<18)
#define REVERSE_SEARCH (1<<19)
#define LOADONINSERT (1<<20)
/* Control key sequences, changing these would be very very bad */
......@@ -186,6 +201,8 @@ typedef struct rcoption {
#define NANO_ALT_X 'x'
#define NANO_ALT_Y 'y'
#define NANO_ALT_Z 'z'
#define NANO_ALT_LCARAT ','
#define NANO_ALT_RCARAT '.'
/* Some semi-changeable keybindings; don't play with unless you're sure you
know what you're doing */
......@@ -241,6 +258,8 @@ know what you're doing */
#define NANO_FROMSEARCHTOGOTO_KEY NANO_CONTROL_T
#define NANO_TOFILES_KEY NANO_CONTROL_T
#define NANO_APPEND_KEY NANO_ALT_A
#define NANO_OPENPREV_KEY NANO_ALT_LCARAT
#define NANO_OPENNEXT_KEY NANO_ALT_RCARAT
#define TOGGLE_CONST_KEY NANO_ALT_C
#define TOGGLE_AUTOINDENT_KEY NANO_ALT_I
......@@ -253,15 +272,28 @@ know what you're doing */
#define TOGGLE_WRAP_KEY NANO_ALT_W
#define TOGGLE_BACKWARDS_KEY NANO_ALT_B
#define TOGGLE_CASE_KEY NANO_ALT_A
#define TOGGLE_LOAD_KEY NANO_ALT_L
/* Toggle stuff, these static lengths need to go away RSN */
#ifdef HAVE_REGEX_H
#ifdef ENABLE_LOADONINSERT
#define TOGGLE_LEN 14
#else
#define TOGGLE_LEN 11
#endif
#define WHEREIS_LIST_LEN 8
#define REPLACE_LIST_LEN 8
#else
#ifdef ENABLE_LOADONINSERT
#define TOGGLE_LEN 13
#else
#define TOGGLE_LEN 10
#endif
#define WHEREIS_LIST_LEN 7
#define REPLACE_LIST_LEN 7
#endif
......@@ -286,6 +318,7 @@ know what you're doing */
#define VIEW 1
#define NOVIEW 0
#define NONE 3
#define TOP 2
#define CENTER 1
#define BOTTOM 0
......
......@@ -41,3 +41,6 @@
# Allow nano to be suepended with ^Z
# set suspend
# Load files upon inserting them, and allow switching between them
# set loadoninsert
......@@ -50,6 +50,11 @@ extern char *alt_speller;
extern struct stat fileinfo;
extern filestruct *current, *fileage, *edittop, *editbot, *filebot;
extern filestruct *cutbuffer, *mark_beginbuf;
#ifdef ENABLE_LOADONINSERT
extern filestruct *open_files;
#endif
extern shortcut *shortcut_list;
extern shortcut main_list[MAIN_LIST_LEN], whereis_list[WHEREIS_LIST_LEN];
extern shortcut replace_list[REPLACE_LIST_LEN], goto_list[GOTO_LIST_LEN];
......@@ -89,8 +94,14 @@ int do_uncut_text(void);
int no_help(void);
int renumber_all(void);
int open_file(char *filename, int insert, int quiet);
int do_insertfile(int loading_file);
#ifdef ENABLE_LOADONINSERT
int add_open_file(int update, int dup_fix);
#endif
int do_writeout(char *path, int exiting, int append);
int do_gotoline(long defline);
int do_gotoline(long line, int save_pos);
int do_replace_loop(char *prevanswer, filestruct *begin, int *beginx,
int wholewords, int *i);
/* Now in move.c */
......@@ -110,7 +121,7 @@ void check_wrap(filestruct * inptr, char ch);
void dump_buffer(filestruct * inptr);
void align(char **strp);
void edit_refresh(void), edit_refresh_clearok(void);
void edit_update(filestruct * fileptr, int topmidbot);
void edit_update(filestruct * fileptr, int topmidbotnone);
void update_cursor(void);
void delete_node(filestruct * fileptr);
void set_modified(void);
......@@ -136,6 +147,7 @@ void do_early_abort(void);
void *nmalloc(size_t howmuch);
void *nrealloc(void *ptr, size_t howmuch);
void die(char *msg, ...);
void die_save_file(char *die_filename);
void new_file(void);
void new_magicline(void);
void splice_node(filestruct *begin, filestruct *newnode, filestruct *end);
......@@ -150,6 +162,7 @@ void nano_disabled_msg(void);
void window_init(void);
void do_mouse(void);
void print_view_warning(void);
void unlink_node(filestruct * fileptr);
void cut_marked_segment(filestruct * top, int top_x, filestruct * bot,
int bot_x, int destructive);
......@@ -163,7 +176,13 @@ void do_credits(void);
int do_writeout_void(void), do_exit(void), do_gotoline_void(void);
int do_insertfile(void), do_search(void), page_up(void), page_down(void);
int do_insertfile_void(void), do_search(void);
#ifdef ENABLE_LOADONINSERT
int load_open_file(void), close_open_file(void);
#endif
int page_up(void), page_down(void);
int do_cursorpos(void), do_spell(void);
int do_up(void), do_down (void), do_right(void), do_left (void);
int do_home(void), do_end(void), total_refresh(void), do_mark(void);
......@@ -172,8 +191,17 @@ int do_first_line(void), do_last_line(void);
int do_replace(void), do_help(void), do_enter_void(void);
int keypad_on(WINDOW * win, int newval);
#ifdef ENABLE_LOADONINSERT
int open_file_dup_fix(int update);
int open_prevfile(int closing_file), open_nextfile(int closing_file);
#endif
char *charalloc (size_t howmuch);
#ifdef ENABLE_LOADONINSERT
char *get_full_path(const char *origpath);
#endif
#ifndef DISABLE_BROWSER
char *do_browser(char *path);
struct stat filestat(const char *path);
......@@ -195,3 +223,7 @@ filestruct *copy_filestruct(filestruct * src);
filestruct *make_new_node(filestruct * prevnode);
filestruct *findnextstr(int quiet, filestruct * begin,
int beginx, char *needle);
#ifdef ENABLE_LOADONINSERT
filestruct *open_file_dup_search(void);
#endif
......@@ -39,7 +39,7 @@
#define _(string) (string)
#endif
#define NUM_RCOPTS 14
#define NUM_RCOPTS 15
/* Static stuff for the nanorc file */
rcoption rcopts[NUM_RCOPTS] =
{
......@@ -60,7 +60,8 @@ rcoption rcopts[NUM_RCOPTS] =
{"view", VIEW_MODE},
{"nowrap", NO_WRAP},
{"nohelp", NO_HELP},
{"suspend", SUSPEND}};
{"suspend", SUSPEND},
{"loadoninsert", LOADONINSERT}};
/* We have an error in some part of the rcfile; put it on stderr and
make the user hit return to continue starting up nano */
......
......@@ -743,7 +743,7 @@ void goto_abort(void)
display_main_list();
}
int do_gotoline(long line)
int do_gotoline(long line, int save_pos)
{
long i = 1;
......@@ -772,7 +772,13 @@ int do_gotoline(long line)
current = current->next;
current_x = 0;
edit_update(current, CENTER);
/* if save_pos is non-zero, don't change the cursor position when
updating the edit window */
if (save_pos)
edit_update(current, NONE);
else
edit_update(current, CENTER);
goto_abort();
return 1;
......@@ -780,5 +786,5 @@ int do_gotoline(long line)
int do_gotoline_void(void)
{
return do_gotoline(0);
return do_gotoline(0, 0);
}
......@@ -1079,7 +1079,7 @@ void edit_refresh_clearok(void)
* Nice generic routine to update the edit buffer, given a pointer to the
* file struct =)
*/
void edit_update(filestruct * fileptr, int topmidbot)
void edit_update(filestruct * fileptr, int topmidbotnone)
{
int i = 0;
filestruct *temp;
......@@ -1088,8 +1088,11 @@ void edit_update(filestruct * fileptr, int topmidbot)
return;
temp = fileptr;
if (topmidbot == 2);
else if (topmidbot == 0)
if (topmidbotnone == TOP);
else if (topmidbotnone == NONE)
for (i = 0; i <= current_y - 1 && temp->prev != NULL; i++)
temp = temp->prev;
else if (topmidbotnone == BOTTOM)
for (i = 0; i <= editwinrows - 1 && temp->prev != NULL; i++)
temp = temp->prev;
else
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment