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
Этот коммит содержится в:
родитель
3a6d70dfb6
Коммит
48b06708ff
12
ChangeLog
12
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).
|
||||
|
216
files.c
216
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
|
||||
|
||||
|
3
global.c
3
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;
|
||||
|
3
nano.1
3
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.
|
||||
|
39
nano.c
39
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 "
|
||||
|
1
nano.h
1
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 */
|
||||
|
11
proto.h
11
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
|
||||
|
||||
|
||||
|
15
utils.c
15
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)
|
||||
{
|
||||
|
Загрузка…
Ссылка в новой задаче
Block a user