From 48b06708ff284c91703300426df5588c77f78836 Mon Sep 17 00:00:00 2001
From: Chris Allegretta <chrisa@asty.org>
Date: Fri, 22 Feb 2002 04:30:50 +0000
Subject: [PATCH] Multiple unnamed buffers allowed, multiple filename
 extensions on die_save_file(), more DLR fixes

git-svn-id: svn://svn.savannah.gnu.org/nano/trunk/nano@1081 35c25a1d-7b9e-4130-9fde-d3aeb78583b8
---
 ChangeLog |  12 ++-
 files.c   | 216 +++++++++++++++---------------------------------------
 global.c  |   3 +-
 nano.1    |   3 +
 nano.c    |  39 +++++-----
 nano.h    |   1 -
 proto.h   |  11 +--
 utils.c   |  15 ++++
 8 files changed, 116 insertions(+), 184 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 7aac8d75..9a154a8a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -5,20 +5,26 @@ CVS code -
 	  the translation of files from DOS or Mac format (DLR).
 	- New functions wheck_writable_directory() and safe_tempnam()
 	  to get around the tempnam warning. More improvements (DLR)  
-	  Still eeds testing.
+	  Still needs testing.
 	- Added DOS and Mac format options to write file routine.
 	  Changes to shortcut_init() and do_writeout().	
 	- Removed stupid static definitions of toggles and shortcut
 	  lists.  Many changes to shortcut_init(), toggle_init(),
 	  statusq(), nanogetstr(), main(), and many other places.
 	  FIXME: Mouse support broken by this change.
+	- Multibuffer mode now allows multiple empty filenames.  
+	  Changes to add_open_files(), removed open_file_dup_search(),
+	  open_file_dup_fix(), etc (DLR).
+	- New code to handle multiple .save files.  Changes to 
+	  die_save_file(), new function files.c:get_next_filename()
+	  and utils.c:num_of_digits(). (Dwayne Rightler, DLR & Chris)
 - Makefile.am:
 	- Add SYSCONFDIR to DEFS, so we can have an /etc/nanorc.
 	- Change localedir line to 1.0's version.
 - files.c:
   read_byte()
 	- Added check for conrol characters (indicative of a binary 
-	  file), set NO_CONVERT if found.
+	  file), set NO_CONVERT if found (fixes by DLR).
 - global.c:
 	- Move openprev and opennext functions to shortcuts, they really
 	  aren't toggles (DLR).
@@ -28,6 +34,8 @@ CVS code -
 	  for *ptr+1 is not the end of the regex.
   do_rcfile()
 	- Parse rcfile in $SYSCONFDIR as well (Dwayne Rightler).
+- nano.1:
+	- Added Noconvert option to man page (DLR).
 - nano.c:
   help_init()
 	- Added message re: having multiple blank buffers (DLR).
diff --git a/files.c b/files.c
index 12fb009a..af75e57e 100644
--- a/files.c
+++ b/files.c
@@ -54,18 +54,10 @@ void load_file(int quiet)
     current = fileage;
 
 #ifdef ENABLE_MULTIBUFFER
-    /* if quiet is zero, add a new entry to the open_files structure, and
-       do duplicate checking; otherwise, update the current entry and
-       don't do duplicate checking (the latter is needed in the case of
-       the alternate spell checker); if a duplicate entry was found,
-       reload the currently open file (it may have been changed during
-       duplicate handling) */
-    if (quiet != 0)
-	quiet = 1;
-    if (add_open_file(quiet, 1 - quiet) == 2) {
-	load_open_file();
-	statusbar(_("File already loaded"));
-    }
+    /* if quiet is zero, add a new entry to the open_files structure;
+       otherwise, update the current entry (the latter is needed in the
+       case of the alternate spell checker) */
+    add_open_file(quiet);
 #endif
 
     wmove(edit, current_y, current_x);
@@ -89,12 +81,11 @@ void new_file(void)
 
 #ifdef ENABLE_MULTIBUFFER
     /* if there aren't any entries in open_files, create the entry for
-       this new file, and, of course, don't bother checking for
-       duplicates; without this, if nano is started without a filename on
-       the command line, a new file will be created, but it will be given
-       no open_files entry, leading to problems later on */
+       this new file; without this, if nano is started without a filename
+       on the command line, a new file will be created, but it will be
+       given no open_files entry, leading to problems later on */
     if (!open_files) {
-	add_open_file(0, 0);
+	add_open_file(0);
 	/* turn off view mode in this case; this is for consistency
 	   whether multibuffers are compiled in or not */
 	UNSET(VIEW_MODE);
@@ -210,8 +201,9 @@ int read_file(int fd, char *filename, int quiet)
 	    buf[0] = 0;
 	    i = 0;
 #ifndef NANO_SMALL
-	 } else if (!ISSET(NO_CONVERT) && input[0] < 32 
-			&& input[0] != '\r' && input[0] != '\n') 
+	 } else if (!ISSET(NO_CONVERT) && input[0] >= 0 && input[0] <= 31 
+			&& input[0] != '\t' && input[0] != '\r'
+			&& input[0] != '\n') 
 	    /* If the file has binary chars in it, don't stupidly
 		assume it's a DOS or Mac formatted file! */
 	    SET(NO_CONVERT);
@@ -295,9 +287,8 @@ int open_file(char *filename, int insert, int quiet)
     struct stat fileinfo;
 
     if (!strcmp(filename, "") || stat(filename, &fileinfo) == -1) {
-	if (insert) {
-	    if (!quiet)
-		statusbar(_("\"%s\" not found"), filename);
+	if (insert && !quiet) {
+	    statusbar(_("\"%s\" not found"), filename);
 	    return -1;
 	} else {
 	    /* We have a new file */
@@ -332,6 +323,38 @@ int open_file(char *filename, int insert, int quiet)
     return 1;
 }
 
+
+/* This function will return the name of the first available extension
+   of a filename (starting with the filename, then filename.1, etc).
+   Memory is allocated for the return value.  If no writable extension 
+   exists we return "" */
+char *get_next_filename(char *name)
+{
+    int i = 0;
+    char *buf = NULL;
+    struct stat fs;
+
+    buf = charalloc(strlen(name) + num_of_digits(INT_MAX) + 2);
+    strcpy(buf, name);
+
+    while(1) {
+
+	if (stat(buf, &fs) == -1)
+	    break;
+	if (i == INT_MAX)
+	    break;
+
+	i++;
+	strcpy(buf, name);
+	sprintf(&buf[strlen(name)], ".%d", i);
+    }
+
+    if (i == INT_MAX)
+	buf[0] = '\0';
+
+    return buf;
+}
+
 int do_insertfile(int loading_file)
 {
     int i;
@@ -386,10 +409,8 @@ int do_insertfile(int loading_file)
 #ifdef ENABLE_MULTIBUFFER
 	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);
+	    /* update the current entry in the open_files structure */
+	    add_open_file(1);
 
 	    free_filestruct(fileage);
 	    new_file();
@@ -397,7 +418,7 @@ int do_insertfile(int loading_file)
 	}
 #endif
 
-	i = open_file(realname, 1, 0);
+	i = open_file(realname, 1, loading_file);
 
 #ifdef ENABLE_MULTIBUFFER
 	if (loading_file)
@@ -471,25 +492,15 @@ int do_insertfile_void(void)
 /*
  * 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.
+ * Return 0 on success or 1 on error.
  */
-int add_open_file(int update, int dup_fix)
+int add_open_file(int update)
 {
     filestruct *tmp;
 
     if (!fileage || !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);
@@ -520,9 +531,6 @@ int add_open_file(int update, int dup_fix)
     /* 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;
 
@@ -574,9 +582,6 @@ int open_file_change_name(void)
     /* 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;
 }
 
@@ -629,95 +634,6 @@ int load_open_file(void)
     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(int update)
-{
-    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 (!update)
-		/* if we're making a new entry and there's an entry with
-		   the same full path, we've found a duplicate */
-		return tmp;
-	    else {
-
-		/* if we're updating an existing entry and there's an
-		   entry with the same full path that isn't 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(update);
-
-    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.
@@ -730,10 +646,9 @@ int open_prevfile(int closing_file)
 	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 */
+       doing anything */
     if (!closing_file)
-	add_open_file(1, 0);
+	add_open_file(1);
 
     if (!open_files->prev && !open_files->next) {
 
@@ -792,10 +707,9 @@ int open_nextfile(int closing_file)
 	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 */
+       doing anything */
     if (!closing_file)
-	add_open_file(1, 0);
+	add_open_file(1);
 
     if (!open_files->prev && !open_files->next) {
 
@@ -862,7 +776,6 @@ int close_open_file(void)
 
     unlink_node(tmp);
     free_filestruct(tmp->file);
-    free(tmp->file_path);
     delete_node(tmp);
 
     shortcut_init(0);
@@ -871,7 +784,7 @@ int close_open_file(void)
 }
 #endif /* MULTIBUFFER */
 
-#if defined (ENABLE_MULTIBUFFER) || !defined (DISABLE_SPELLER) || !defined (DISABLE_OPERATINGDIR)
+#if !defined (DISABLE_SPELLER) || !defined (DISABLE_OPERATINGDIR)
 /*
  * When passed "[relative path]" or "[relative path][filename]" in
  * origpath, return "[full path]" or "[full path][filename]" on success,
@@ -1020,7 +933,7 @@ char *get_full_path(const char *origpath)
 
     return newpath;
 }
-#endif /* ENABLE_MULTIBUFFER || !DISABLE_SPELLER || !DISABLE_OPERATINGDIR */
+#endif /* !DISABLE_SPELLER || !DISABLE_OPERATINGDIR */
 
 #ifndef DISABLE_SPELLER
 /*
@@ -1602,18 +1515,16 @@ int do_writeout(char *path, int exiting, int append)
 	    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 */
+		   update the filename stored in the current entry, and
+		   then update the current entry */
 		if (strcmp(open_files->data, filename)) {
 		    open_file_change_name();
-		    add_open_file(1, 1);
+		    add_open_file(1);
 		}
 		else {
 
-		    /* otherwise, just update the current entry without
-		       checking for duplicate entries */
-		    add_open_file(1, 0);
+		    /* otherwise, just update the current entry */
+		    add_open_file(1);
 		}
 	    }
 #endif
@@ -2127,7 +2038,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)
 {
@@ -2618,8 +2528,4 @@ char *do_browse_from(char *inpath)
     return do_browser(tmp);
 
 }
-
-
-
 #endif
-
diff --git a/global.c b/global.c
index cb8b08e5..ad26f8e7 100644
--- a/global.c
+++ b/global.c
@@ -35,6 +35,7 @@
 /*
  * Global variables
  */
+
 int flags = 0;			/* Our new flag containing many options */
 WINDOW *edit;			/* The file portion of the editor  */
 WINDOW *topwin;			/* Top line of screen */
@@ -87,7 +88,7 @@ char *alt_speller;		/* Alternative spell command */
 shortcut *main_list = NULL;
 shortcut *whereis_list = NULL;
 shortcut *replace_list = NULL;
-shortcut *replace_list_2; 	/* 2nd half of replace dialog */
+shortcut *replace_list_2 = NULL; 	/* 2nd half of replace dialog */
 shortcut *goto_list = NULL;
 shortcut *gotodir_list = NULL;
 shortcut *writefile_list = NULL;
diff --git a/nano.1 b/nano.1
index 95ae6578..c4b1376c 100644
--- a/nano.1
+++ b/nano.1
@@ -45,6 +45,9 @@ under nano.
 .B \-M (\-\-mac)
 Write file in Mac format.
 .TP
+.B \-N (\-\-noconvert)
+Disable automatic conversion of files from DOS/Mac format.
+.TP
 .B \-R (\-\-regexp)
 Enable regular expression matching for search strings, as well as
 \\n subexpression replacement for replace strings, if available.
diff --git a/nano.c b/nano.c
index eef586aa..84545abb 100644
--- a/nano.c
+++ b/nano.c
@@ -158,27 +158,34 @@ void die(char *msg, ...)
 
 void die_save_file(char *die_filename)
 {
-    char *name;
-    int i;
+    char *name, *ret;
+    int i = -1;
 
     /* if we can't save we have REAL bad problems,
      * but we might as well TRY. */
     if (die_filename[0] == '\0') {
 	name = "nano.save";
-	i = write_file(name, 1, 0, 0);
-    } else {
-
+	ret = get_next_filename(name);
+	if (strcmp(ret, ""))
+	    i = write_file(ret, 1, 0, 0);
+	name = ret;
+    }
+    else {
 	char *buf = charalloc(strlen(die_filename) + 6);
 	strcpy(buf, die_filename);
 	strcat(buf, ".save");
-	i = write_file(buf, 1, 0, 0);
-	name = buf;
+	ret = get_next_filename(buf);
+	if (strcmp(ret, ""))
+	    i = write_file(ret, 1, 0, 0);
+	name = ret;
     }
 
     if (i != -1)
 	fprintf(stderr, _("\nBuffer written to %s\n"), name);
     else
-	fprintf(stderr, _("\nNo %s written (file exists?)\n"), name);
+	fprintf(stderr, _("\nNo %s written (too many backup files?)\n"), name);
+
+    free(ret);
 }
 
 /* Die with an error message that the screen was too small if, well, the
@@ -1744,9 +1751,8 @@ int do_spell(void)
 #ifdef ENABLE_MULTIBUFFER
     /* update the current open_files entry before spell-checking, in case
        any problems occur; the case of there being no open_files entries
-       is handled elsewhere (before we reach this point); no duplicate
-       checking is needed here */
-    add_open_file(1, 0);
+       is handled elsewhere (before we reach this point) */
+    add_open_file(1);
 #endif
 
     if (alt_speller)
@@ -2454,12 +2460,11 @@ void help_init(void)
 		"or --multibuffer command line flags, the Meta-F toggle or "
 		"using 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 In multiple buffer mode, the "
-		"same file cannot be loaded twice, not even a \"New "
-		"Buffer.\" A workaround to load another blank buffer is to "
-		"load a nonexistent filename into a separate buffer.\n\n "
-		"The following function keys are available in Insert File "
-		"mode:\n\n");
+		"between file buffers).\n\n If you need another blank "
+		"buffer, just press Enter at the prompt without typing in a "
+		"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 "
diff --git a/nano.h b/nano.h
index c00cf8f0..697a7039 100644
--- a/nano.h
+++ b/nano.h
@@ -79,7 +79,6 @@ typedef struct filestruct {
     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 */
     long file_totsize;		/* Current file's total size */
diff --git a/proto.h b/proto.h
index fb0b2022..668b9e03 100644
--- a/proto.h
+++ b/proto.h
@@ -104,9 +104,10 @@ int renumber_all(void);
 int open_file(char *filename, int insert, int quiet);
 int do_insertfile(int loading_file);
 int length_of_list(shortcut *s);
+int num_of_digits(int n);
 
 #ifdef ENABLE_MULTIBUFFER
-int add_open_file(int update, int dup_fix);
+int add_open_file(int update);
 #endif
 
 #ifndef DISABLE_OPERATINGDIR
@@ -212,12 +213,12 @@ int do_replace(void), do_help(void), do_enter_void(void);
 int keypad_on(WINDOW * win, int newval);
 
 #ifdef ENABLE_MULTIBUFFER
-int open_file_dup_fix(int update);
 int open_prevfile(int closing_file), open_nextfile(int closing_file);
 int open_prevfile_void(void), open_nextfile_void(void);
 #endif
 
 char *charalloc (size_t howmuch);
+char *get_next_filename(char *name);
 
 #if defined (ENABLE_MULTIBUFFER) || !defined (DISABLE_SPELLER) || !defined (DISABLE_OPERATINGDIR)
 char *get_full_path(const char *origpath);
@@ -250,12 +251,6 @@ filestruct *make_new_node(filestruct * prevnode);
 filestruct *findnextstr(int quiet, int bracket_mode, filestruct * begin,
 			int beginx, char *needle);
 
-#ifdef ENABLE_MULTIBUFFER
-filestruct *open_file_dup_search(int update);
-#endif
-
 #ifndef DISABLE_HELP
 void help_init(void);
 #endif
-
-
diff --git a/utils.c b/utils.c
index 71c8193e..ed1c3068 100644
--- a/utils.c
+++ b/utils.c
@@ -36,6 +36,21 @@
 #define _(string) (string)
 #endif
 
+int num_of_digits(int n)
+{
+    int i = 1;
+
+    if (n < 0)
+	n = 0 - n;
+
+    while (n > 10) {
+	n /= 10;
+	i++;
+    }
+
+    return i;
+}
+
 /* Lower case a string - must be null terminated */
 void lowercase(char *src)
 {
-- 
GitLab