From: Chris Allegretta
3.8. How do I make a .nanorc file that nano will read when I start it?
4.1. Ack! My backspace/delete/enter/double bucky/meta key doesn't seem to work! What can I do?
+4.1. Ack! My backspace/delete/enter/double bucky/meta key doesn't seem to work! What can I do?
4.2. Nano crashes when I type <insert keystroke here>!
4.3. Nano crashes when I resize my window. How can I fix that?
4.4. Why does nano show ^\ in the shortcut list instead of ^J?
@@ -62,13 +62,13 @@1.2. How do I contribute to it?
Your best bet is to send it to the nano email address, nano@nano-editor.org and if it is useful enough it will be included in future versions.
1.3. What is GNU nano?
-+GNU nano is designed to be a free replacement for the Pico text editor, part of the Pine email suite from The University of Washington. It aims to "emulate Pico as closely as possible and perhaps include extra functionality".
GNU nano is designed to be a free replacement for the Pico text editor, part of the Pine email suite from The University of Washington. It aims to "emulate Pico as closely as possible and perhaps include extra functionality".
1.4. What is the history behind nano?
Funny you should ask!
In the beginning...
For years Pine was THE program used to read email on a Unix system. The Pico text editor is the portion of the program one would use to compose his or her mail messages. Many beginners to Unix flocked to Pico and Pine because of their well organized, easy to use interfaces. With the proliferation of GNU/Linux in the mid to late 90's, many University students became intimately familiar with the strengths (and weaknesses) of Pine and Pico.
Then came Debian...
-The Debian GNU/Linux distribution, known for its strict standards in distributing truly "free" software (i.e. software with no restrictions on redistribution), would not include a binary package for Pine or Pico. Many people had a serious dilemma: they loved these programs, but they were not truly free software in the GNU sense of the word.
+The Debian GNU/Linux distribution, known for its strict standards in distributing truly "free" software (i.e. software with no restrictions on redistribution), would not include a binary package for Pine or Pico. Many people had a serious dilemma: they loved these programs, but they were not truly free software in the GNU sense of the word.
The event...
It was in late 1999 when Chris Allegretta (our hero) was yet again complaining to himself about the less-than-perfect license Pico was distributed under, the 1000 makefiles that came with it and how just a few small improvements could make it the Best Editor in the World (TM). Having been a convert from Slackware to Debian, he missed having a simple binary package that included Pine and Pico, and had grown tired of downloading them himself.
Finally something snapped inside and Chris coded and hacked like a madman for many hours straight one weekend to make a (barely usable) Pico clone, at the time called TIP (Tip Isn't Pico). The program could not be invoked without a filename, could not save files, had no help menu, spell checker, and so forth. But over time it improved, and with the help of a few great coders it matured to the (hopefully) stable state it is today.
@@ -84,31 +84,31 @@2.1. FTP and WWW sites that carry nano.
The nano distribution can be downloaded at the following fine web and ftp sites:
2.2. RedHat and derivatives (.rpm) packages.
-
- http://www.nano-editor.org/dist/v1.0/RPMS
-- http://www.ewtoo.org/~astyanax/nano/dist/v1.0/RPMS
+- http://www.nano-editor.org/dist/v1.0/RPMS/
+- http://www.ewtoo.org/~astyanax/nano/dist/v1.0/RPMS/
Additionally, check out the RedHat contribs section at:
-
- http://distro.ibiblio.org/pub/Linux/distributions/redhat/contrib/libc6/i386
-- ftp://distro.ibiblio.org/pub/Linux/distributions/redhat/contrib/libc6/i386
+- http://distro.ibiblio.org/pub/Linux/distributions/redhat/contrib/libc6/i386/
+- ftp://distro.ibiblio.org/pub/Linux/distributions/redhat/contrib/libc6/i386/
2.3. Debian (.deb) packages.
Debian users can check out the current nano packages for:
-You can also have a look at the Package Pool to see all the available binary and source packages.
+You can also have a look at the Package Pool to see all the available binary and source packages.
Note that versions < 0.9.10 are probably not for those wanting to get serious work done, so if you are using Debian 2.2, check that you have updated to 2.2r3, which comes with nano 0.9.23. If you're tracking unstable, you probably have the newest version already.
2.4. By CVS (for the brave).
@@ -191,7 +191,7 @@For the 'bleeding edge' current version of nano, you can use CVS to download the current source code. Note: believe it or not, by downloading code that has not yet stabilized into an official release, there could quite possibly be bugs, in fact the code may not even compile! Anyway, see the nano CVS page for info on anonymous CVS access to the nano source.
5. Internationalization
5.1. There's no translation for my language!
-On June of 2001, GNU nano entered the Free Translation Project and since then, translations should be managed from there.
+On June of 2001, GNU nano entered the Free Translation Project and since then, translations should be managed from there.
If there isn't a translation for your language, you could ask your language team to translate nano, or better still, join your team and do it yourself. Joining a team is easy. You just need to ask the TP coordinator to add you to your team, and send a translation disclaimer to the FSF (this is necessary as nano is an official GNU package, but it does not mean that you transfer the rights of your work to the FSF, it's just so the FSF can legally manage them).
In any case, translating nano is very easy. Just grab the nano.pot file from the latest and greatest nano distribution (it's in the po/ directory) and translate each line into your native language on the msgstr line. When you're done, you should send it to the TP's central po repository.
5.2. I don't like the translation for <x> in my language. How can I fix it?
@@ -199,13 +199,13 @@
6. Advocacy and Licensing
6.1. Why should I use nano instead of Pico?
-+There are many reasons to use nano instead of Pico, a more complete list can be found at the nano homepage.
There are many reasons to use nano instead of Pico, a more complete list can be found at the nano homepage.
6.2. Why should I use Pico instead of nano?
-+Again, check out the nano homepage for a good summary of reasons. It really is a matter of personal preference as to which editor you should use. If you're the type of person who likes using the original version of a program, then Pico is the editor for you. If you're looking for a few more features and a 'better' license as far as adding your own changes (sacrificing mailer integration with Pine), nano is the way to go.
Again, check out the nano homepage for a good summary of reasons. It really is a matter of personal preference as to which editor you should use. If you're the type of person who likes using the original version of a program, then Pico is the editor for you. If you're looking for a few more features and a 'better' license as far as adding your own changes (sacrificing mailer integration with Pine), nano is the way to go.
6.3. What is so bad about the Pine license?
The U of W license for Pine and Pico is not considered truly Free Software according to both the Free Software Foundation and the Debian Free Software Guidelines. The main problem regards the limitations on distributing derived works: according to UW, you can distribute their software, and you can modify it, but you can not do both, i.e. distribute modified binaries.
6.4. Okay, well what mail program should I use then?
-+If you are looking to use a Free Software program similar to Pine and emacs is not your thing, you should definitely take a look at mutt. It is a full-screen, console based mail program that actually has a lot more flexibility than Pine, but has a keymap included in the distribution that allows you to use the same keystrokes as Pine would to send and receive mail. It's also licensed under the GPL.
If you are looking to use a Free Software program similar to Pine and emacs is not your thing, you should definitely take a look at mutt. It is a full-screen, console based mail program that actually has a lot more flexibility than Pine, but has a keymap included in the distribution that allows you to use the same keystrokes as Pine would to send and receive mail. It's also licensed under the GPL.
6.5. Why doesn't UW simply change their license?
You're really not asking the right person here. I (Chris) waited a long time to see if UW would change their license because of the amount of high quality software being released and developed under the GPL without being taken advantage of by malicious corporate entities or other baddies, but no such luck so far.
6.6. What if tomorrow UW changes the license to be truly Free Software?
@@ -213,10 +213,10 @@
7. Miscellaneous
7.1. Nano related mailing lists.
-+There are three mailing lists for nano hosted at Savannah, info-nano, help-nano and nano-devel. Info-nano is a very low traffic list where new versions of nano are announced (surprise!) Help-nano is for getting help with the editor without needing to hear all of the development issues surrounding it. Nano-devel is a normally low, sometimes high traffic list for discussing the present and future development of nano. Here are links to where you can sign up for a given list:
-info-nano - http://mail.gnu.org/mailman/listinfo/info-nano
- help-nano - http://mail.gnu.org/mailman/listinfo/help-nano
- nano-devel - http://mail.gnu.org/mailman/listinfo/nano-develThere are three mailing lists for nano hosted at Savannah, info-nano, help-nano and nano-devel. Info-nano is a very low traffic list where new versions of nano are announced (surprise!) Help-nano is for getting help with the editor without needing to hear all of the development issues surrounding it. Nano-devel is a normally low, sometimes high traffic list for discussing the present and future development of nano. Here are links to where you can sign up for a given list:
+info-nano - http://mail.gnu.org/mailman/listinfo/info-nano/
+ help-nano - http://mail.gnu.org/mailman/listinfo/help-nano/
+ nano-devel - http://mail.gnu.org/mailman/listinfo/nano-devel/7.2. I want to send the development team a big load of cash (or just a thank you).
That's fine. Send it our way! Better yet, fix a bug in the program or implement a cool feature and send us that instead (though cash is fine too).
7.3. How do I submit a patch?
@@ -226,7 +226,8 @@7.5. Can I have CVS write access?
Re-read Section 7.4 and you should know the answer.
8. ChangeLog
-2002/10/25 - Misc. fixes and link updates (DLR).
+2002/12/28 - More misc. fixes (David Benbennick, DLR).
+2002/10/25 - Misc. fixes and link updates (DLR).
2002/09/10 - Another typo fix (DLR).
2002/05/15 - Typo fix (DLR).
2001/12/26 - Misc. fixes (Aaron S. Hawley, DLR).
diff --git a/files.c b/files.c index e37935db..dd3c6481 100644 --- a/files.c +++ b/files.c @@ -33,8 +33,8 @@ #include#include #include -#include #include +#include #include "proto.h" #include "nano.h" @@ -42,7 +42,7 @@ static int fileformat = 0; /* 0 = *nix, 1 = DOS, 2 = Mac */ #endif -/* Load file into edit buffer - takes data from file struct */ +/* Load file into edit buffer - takes data from file struct. */ void load_file(int update) { current = fileage; @@ -56,9 +56,8 @@ void load_file(int update) #ifdef ENABLE_COLOR update_color(); + edit_refresh(); #endif - - wmove(edit, current_y, current_x); } /* What happens when there is no file to open? aiee! */ @@ -95,6 +94,7 @@ void new_file(void) #ifdef ENABLE_COLOR update_color(); + edit_refresh(); #endif } @@ -149,7 +149,7 @@ filestruct *read_line(char *buf, filestruct *prev, int *line1ins, int len) int read_file(FILE *f, const char *filename, int quiet) { int num_lines = 0, len = 0; - char input = '\0'; /* current input character */ + char input = '\0'; /* current input character */ char *buf; long i = 0, bufx = 128; filestruct *fileptr = current, *tmp = NULL; @@ -171,10 +171,10 @@ int read_file(FILE *f, const char *filename, int quiet) } /* For the assertion in read_line(), it must be true that if current is - NULL then so is fileage. */ + * NULL then so is fileage. */ assert(current != NULL || fileage == NULL); - /* Read the entire file into file struct */ + /* Read the entire file into file struct. */ while ((input_int = getc(f)) != EOF) { input = (char)input_int; #ifndef NANO_SMALL @@ -323,7 +323,7 @@ int read_file(FILE *f, const char *filename, int quiet) return 1; } -/* Open the file (and decide if it exists) */ +/* Open the file (and decide if it exists). */ int open_file(const char *filename, int insert, int quiet) { int fd; @@ -340,7 +340,13 @@ int open_file(const char *filename, int insert, int quiet) new_file(); } } else if ((fd = open(filename, O_RDONLY)) == -1) { - if (!quiet) + /* If we're in multibuffer mode, don't be quiet when an error + occurs while opening a file */ + if (!quiet +#ifdef ENABLE_MULTIBUFFER + || ISSET(MULTIBUFFER) +#endif + ) statusbar("%s: %s", strerror(errno), filename); if (!insert) new_file(); @@ -375,9 +381,9 @@ int open_file(const char *filename, int insert, int quiet) } /* 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 "". */ + * 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(const char *name) { int i = 0; @@ -426,21 +432,37 @@ int do_insertfile(int loading_file) if (operating_dir != NULL && strcmp(operating_dir, ".") != 0) #ifdef ENABLE_MULTIBUFFER if (ISSET(MULTIBUFFER)) - i = statusq(1, insertfile_list, inspath, 0, _("File to insert into new buffer [from %s] "), + i = statusq(1, insertfile_list, inspath, +#ifndef NANO_SMALL + 0, +#endif + _("File to insert into new buffer [from %s] "), operating_dir); else #endif - i = statusq(1, insertfile_list, inspath, 0, _("File to insert [from %s] "), + i = statusq(1, insertfile_list, inspath, +#ifndef NANO_SMALL + 0, +#endif + _("File to insert [from %s] "), operating_dir); else #endif #ifdef ENABLE_MULTIBUFFER if (ISSET(MULTIBUFFER)) - i = statusq(1, insertfile_list, inspath, 0, _("File to insert into new buffer [from ./] ")); + i = statusq(1, insertfile_list, inspath, +#ifndef NANO_SMALL + 0, +#endif + _("File to insert into new buffer [from ./] ")); else +#endif /* ENABLE_MULTIBUFFER */ + i = statusq(1, insertfile_list, inspath, +#ifndef NANO_SMALL + 0, #endif - i = statusq(1, insertfile_list, inspath, 0, _("File to insert [from ./] ")); + _("File to insert [from ./] ")); if (i != -1) { inspath = mallocstrcpy(inspath, answer); @@ -448,11 +470,7 @@ int do_insertfile(int loading_file) fprintf(stderr, _("filename is %s\n"), answer); #endif -#ifndef DISABLE_TABCOMP realname = real_dir_from_tilde(answer); -#else - realname = mallocstrcpy(realname, answer); -#endif #ifndef DISABLE_BROWSER if (i == NANO_TOFILES_KEY) { @@ -522,8 +540,20 @@ int do_insertfile(int loading_file) i = open_file(realname, 1, loading_file); #ifdef ENABLE_MULTIBUFFER - if (loading_file) - filename = mallocstrcpy(filename, realname); + if (loading_file) { + /* if there was an error opening the file, free() realname, + free() fileage (which now points to the new buffer we + created to hold the file), reload the buffer we had open + before, and skip the insertion; otherwise, save realname + in filename and continue the insertion */ + if (i == -1) { + free(realname); + free(fileage); + load_open_file(); + goto skip_insert; + } else + filename = mallocstrcpy(filename, realname); + } #endif free(realname); @@ -570,15 +600,15 @@ int do_insertfile(int loading_file) else edit_refresh(); -#ifdef ENABLE_COLOR - update_color(); -#endif - } else { statusbar(_("Cancelled")); i = 0; } +#ifdef ENABLE_MULTIBUFFER + skip_insert: +#endif + free(inspath); inspath = NULL; @@ -801,6 +831,10 @@ int load_open_file(void) UNSET(MARK_ISSET); #endif +#ifdef ENABLE_COLOR + update_color(); +#endif + /* restore full file position: line number, x-coordinate, y- coordinate, place we want */ do_gotopos(open_files->file_lineno, open_files->file_current_x, open_files->file_current_y, open_files->file_placewewant); @@ -809,16 +843,13 @@ int load_open_file(void) clearok(topwin, FALSE); titlebar(NULL); - /* if we're constantly displaying the cursor position, update it (and do so - unconditionally, in the rare case that the character count is the same - but the line count isn't) */ - if (ISSET(CONSTUPDATE)) + /* if we're constantly displaying the cursor position and + DISABLE_CURPOS isn't set, update it (and do so unconditionally, + in the rare case that the character count is the same but the + line count isn't) */ + if (ISSET(CONSTUPDATE) && !ISSET(DISABLE_CURPOS)) do_cursorpos(0); -#ifdef ENABLE_COLOR - update_color(); -#endif - /* now we're done */ return 0; } @@ -1284,7 +1315,7 @@ int check_operating_dir(const char *currpath, int allow_tabcomp) * 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 * print out how many lines we wrote on the statusbar. - * + * * tmp means we are writing a tmp file in a secure fashion. We use * it when spell checking or dumping the file on an error. * @@ -1316,11 +1347,7 @@ int write_file(const char *name, int tmp, int append, int nonamechange) titlebar(NULL); fileptr = fileage; -#ifndef DISABLE_TABCOMP realname = real_dir_from_tilde(name); -#else - realname = mallocstrcpy(realname, name); -#endif #ifndef DISABLE_OPERATINGDIR /* If we're writing a temporary file, we're probably going outside @@ -1420,11 +1447,11 @@ int write_file(const char *name, int tmp, int append, int nonamechange) /* Use O_EXCL if tmp is nonzero. This is now copied from joe, because wiggy says so *shrug*. */ if (append != 0) - fd = open(realname, O_WRONLY | O_CREAT | O_APPEND, (S_IRUSR|S_IWUSR)); + fd = open(realname, O_WRONLY | O_CREAT | O_APPEND, (S_IRUSR | S_IWUSR)); else if (tmp) - fd = open(realname, O_WRONLY | O_CREAT | O_EXCL, (S_IRUSR|S_IWUSR)); + fd = open(realname, O_WRONLY | O_CREAT | O_EXCL, (S_IRUSR | S_IWUSR)); else - fd = open(realname, O_WRONLY | O_CREAT | O_TRUNC, (S_IRUSR|S_IWUSR)); + fd = open(realname, O_WRONLY | O_CREAT | O_TRUNC, (S_IRUSR | S_IWUSR)); /* First, just give up if we couldn't even open the file */ if (fd == -1) { @@ -1608,9 +1635,10 @@ int write_file(const char *name, int tmp, int append, int nonamechange) umask(mask); if (tmp) /* We don't want anyone reading our temporary file! */ - mask = 0600; + mask = S_IRUSR | S_IWUSR; else - mask = 0666 & ~mask; + mask = (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | + S_IWOTH) & ~mask; } else /* Use permissions from file we are overwriting. */ mask = st.st_mode; @@ -1644,8 +1672,13 @@ int write_file(const char *name, int tmp, int append, int nonamechange) mask, realname, strerror(errno)); if (!tmp && append == 0) { - if (!nonamechange) + if (!nonamechange) { filename = mallocstrcpy(filename, realname); +#ifdef ENABLE_COLOR + update_color(); + edit_refresh(); +#endif + } #ifndef NANO_SMALL /* Update originalfilestat to reference the file as it is now. */ @@ -1713,7 +1746,7 @@ int do_writeout(const char *path, int exiting, int append) if (append == 2) i = statusq(1, writefile_list, "", 0, "%s%s%s", _("Prepend Selection to File"), formatstr, backupstr); - else if (append) + else if (append == 1) i = statusq(1, writefile_list, "", 0, "%s%s%s", _("Append Selection to File"), formatstr, backupstr); else @@ -1723,7 +1756,7 @@ int do_writeout(const char *path, int exiting, int append) if (append == 2) i = statusq(1, writefile_list, answer, 0, "%s%s%s", _("File Name to Prepend to"), formatstr, backupstr); - else if (append) + else if (append == 1) i = statusq(1, writefile_list, answer, 0, "%s%s%s", _("File Name to Append to"), formatstr, backupstr); else @@ -1732,13 +1765,13 @@ int do_writeout(const char *path, int exiting, int append) } #else if (append == 2) - i = statusq(1, writefile_list, answer, 0, + i = statusq(1, writefile_list, answer, "%s", _("File Name to Prepend to")); - else if (append) - i = statusq(1, writefile_list, answer, 0, + else if (append == 1) + i = statusq(1, writefile_list, answer, "%s", _("File Name to Append to")); else - i = statusq(1, writefile_list, answer, 0, + i = statusq(1, writefile_list, answer, "%s", _("File Name to Write")); #endif /* !NANO_SMALL */ @@ -1852,8 +1885,6 @@ int do_writeout_void(void) return do_writeout(filename, 0, 0); } -#ifndef DISABLE_TABCOMP - /* Return a malloc()ed string containing the actual directory, used * to convert ~user and ~/ notation... */ char *real_dir_from_tilde(const char *buf) @@ -1896,6 +1927,7 @@ char *real_dir_from_tilde(const char *buf) return dirtmp; } +#ifndef DISABLE_TABCOMP /* Tack a slash onto the string we're completing if it's a directory. We * assume there is room for one more character on the end of buf. The * return value says whether buf is a directory. */ @@ -1920,8 +1952,8 @@ int append_slash_if_dir(char *buf, int *lastwastab, int *place) } /* - * These functions (username_tab_completion, cwd_tab_completion, and - * input_tab) were taken from busybox 0.46 (cmdedit.c). Here is the + * These functions (username_tab_completion(), cwd_tab_completion(), and + * input_tab()) were taken from busybox 0.46 (cmdedit.c). Here is the * notice from that file: * * Termios command line History and Editting, originally @@ -2093,9 +2125,8 @@ char **cwd_tab_completion(char *buf, int *num_matches) return matches; } -/* This function now has an arg which refers to how much the - * statusbar (place) should be advanced, i.e. the new cursor pos. - */ +/* This function now has an arg which refers to how much the statusbar + * (place) should be advanced, i.e. the new cursor pos. */ char *input_tab(char *buf, int place, int *lastwastab, int *newplace, int *list) { /* Do TAB completion */ @@ -2313,7 +2344,6 @@ char *input_tab(char *buf, int place, int *lastwastab, int *newplace, int *list) #endif /* !DISABLE_TABCOMP */ #ifndef DISABLE_BROWSER - /* Return the stat of the file pointed to by path */ struct stat filestat(const char *path) { @@ -2629,7 +2659,7 @@ char *do_browser(const char *inpath) if (!strcmp("..", tail(path))) { /* They want to go up a level, so strip off .. and the - current dir */ + current dir */ striponedir(path); striponedir(path); align(&path); @@ -2650,7 +2680,11 @@ char *do_browser(const char *inpath) case NANO_GOTO_KEY: curs_set(1); - j = statusq(0, gotodir_list, "", 0, _("Goto Directory")); + j = statusq(0, gotodir_list, "", +#ifndef NANO_SMALL + 0, +#endif + _("Goto Directory")); bottombars(browser_list); curs_set(0); diff --git a/global.c b/global.c index 703b710e..89b45772 100644 --- a/global.c +++ b/global.c @@ -27,16 +27,14 @@ #include "proto.h" #include "nano.h" -/* - * Global variables - */ +/* Global variables */ /* wrap_at might be set in rcfile.c or nano.c */ int wrap_at = -CHARS_FROM_EOL;/* Right justified fill value, allows resize */ char *last_search = NULL; /* Last string we searched for */ char *last_replace = NULL; /* Last replacement string */ int search_last_line; /* Is this the last search line? */ -int past_editbuff; /* search lines not displayed */ +int search_offscreen; /* Search lines not displayed */ int flags = 0; /* Our new flag containing many options */ WINDOW *edit; /* The file portion of the editor */ @@ -67,11 +65,8 @@ openfilestruct *open_files = NULL; /* The list of open files */ #endif #ifndef DISABLE_JUSTIFY -#ifdef HAVE_REGEX_H -char *quotestr = "^([ \t]*[|>:}#])+"; -#else -char *quotestr = "> "; /* Quote string */ -#endif +char *quotestr = NULL; /* Quote string. The default value is + set in main(). */ #endif char *answer = NULL; /* Answer str to many questions */ @@ -81,17 +76,20 @@ int placewewant = 0; /* The column we'd like the cursor to jump to when we go to the next or previous line */ -int tabsize = 8; /* Our internal tabsize variable */ +int tabsize = -1; /* Our internal tabsize variable. The + default value 8 is set in main(). */ -char *hblank; /* A horizontal blank line */ +char *hblank = NULL; /* A horizontal blank line */ #ifndef DISABLE_HELP char *help_text; /* The text in the help window */ #endif /* More stuff for the marker select */ +#ifndef NANO_SMALL filestruct *mark_beginbuf; /* the begin marker buffer */ int mark_beginx; /* X value in the string to start */ +#endif #ifndef DISABLE_OPERATINGDIR char *operating_dir = NULL; /* Operating directory, which we can't */ @@ -110,17 +108,18 @@ shortcut *goto_list = NULL; shortcut *gotodir_list = NULL; shortcut *writefile_list = NULL; shortcut *insertfile_list = NULL; +#ifndef DISABLE_HELP shortcut *help_list = NULL; +#endif +#ifndef DISABLE_SPELLER shortcut *spell_list = NULL; - +#endif #ifndef NANO_SMALL shortcut *extcmd_list = NULL; #endif - #ifndef DISABLE_BROWSER shortcut *browser_list = NULL; #endif - #ifdef ENABLE_COLOR const colortype *colorstrings = NULL; syntaxtype *syntaxes = NULL; @@ -232,9 +231,7 @@ void toggle_init(void) #endif /* There is no need to reinitialize the toggles. They can't - change. In fact, reinitializing them causes a segfault in - nano.c:do_toggle() when it is called with the Pico-mode - toggle. */ + change. */ if (toggles != NULL) return; @@ -591,11 +588,9 @@ void shortcut_init(int unjustify) #ifndef NANO_SMALL sc_init_one(&whereis_list, KEY_UP, _("History"), - IFHELP(nano_editstr_msg, 0), 0, 0, VIEW, 0); + IFHELP(nano_editstr_msg, 0), NANO_UP_KEY, 0, VIEW, 0); #endif - - #endif /* !NANO_SMALL */ free_shortcutage(&replace_list); @@ -630,11 +625,8 @@ void shortcut_init(int unjustify) IFHELP(nano_regexp_msg, 0), 0, 0, VIEW, 0); #endif -#ifndef NANO_SMALL sc_init_one(&replace_list, KEY_UP, _("History"), - IFHELP(nano_editstr_msg, 0), 0, 0, VIEW, 0); -#endif - + IFHELP(nano_editstr_msg, 0), NANO_UP_KEY, 0, VIEW, 0); #endif /* !NANO_SMALL */ free_shortcutage(&replace_list_2); @@ -653,7 +645,7 @@ void shortcut_init(int unjustify) #ifndef NANO_SMALL sc_init_one(&replace_list_2, KEY_UP, _("History"), - IFHELP(nano_editstr_msg, 0), 0, 0, VIEW, 0); + IFHELP(nano_editstr_msg, 0), NANO_UP_KEY, 0, VIEW, 0); #endif free_shortcutage(&goto_list); @@ -670,6 +662,7 @@ void shortcut_init(int unjustify) sc_init_one(&goto_list, NANO_LASTLINE_KEY, _("Last Line"), IFHELP(nano_lastline_msg, 0), 0, 0, VIEW, do_last_line); +#ifndef DISABLE_HELP free_shortcutage(&help_list); sc_init_one(&help_list, NANO_PREVPAGE_KEY, _("Prev Page"), @@ -683,6 +676,7 @@ void shortcut_init(int unjustify) sc_init_one(&help_list, NANO_EXIT_KEY, _("Exit"), IFHELP(nano_exit_msg, 0), NANO_EXIT_FKEY, 0, VIEW, do_exit); +#endif free_shortcutage(&writefile_list); @@ -737,6 +731,7 @@ void shortcut_init(int unjustify) #endif #endif +#ifndef DISABLE_SPELLER free_shortcutage(&spell_list); sc_init_one(&spell_list, NANO_HELP_KEY, _("Get Help"), @@ -744,6 +739,7 @@ void shortcut_init(int unjustify) sc_init_one(&spell_list, NANO_CANCEL_KEY, _("Cancel"), IFHELP(nano_cancel_msg, 0), 0, 0, VIEW, 0); +#endif #ifndef NANO_SMALL free_shortcutage(&extcmd_list); @@ -801,6 +797,10 @@ void shortcut_init(int unjustify) /* added by SPK for memory cleanup, gracefully return our malloc()s */ void thanks_for_all_the_fish(void) { +#ifndef DISABLE_JUSTIFY + if (quotestr != NULL) + free(quotestr); +#endif #ifndef DISABLE_OPERATINGDIR if (operating_dir != NULL) free(operating_dir); @@ -826,23 +826,27 @@ void thanks_for_all_the_fish(void) if (answer != NULL) free(answer); if (cutbuffer != NULL) - free_filestruct(cutbuffer); + free_filestruct(cutbuffer); free_shortcutage(&main_list); free_shortcutage(&whereis_list); free_shortcutage(&replace_list); free_shortcutage(&replace_list_2); free_shortcutage(&goto_list); - free_shortcutage(&gotodir_list); free_shortcutage(&writefile_list); free_shortcutage(&insertfile_list); +#ifndef DISABLE_HELP free_shortcutage(&help_list); +#endif +#ifndef DISABLE_SPELLER free_shortcutage(&spell_list); +#endif #ifndef NANO_SMALL free_shortcutage(&extcmd_list); #endif #ifndef DISABLE_BROWSER free_shortcutage(&browser_list); + free_shortcutage(&gotodir_list); #endif #ifndef NANO_SMALL @@ -852,10 +856,7 @@ void thanks_for_all_the_fish(void) #ifdef ENABLE_MULTIBUFFER if (open_files != NULL) { /* We free the memory associated with each open file. */ - while (open_files->prev != NULL) - open_files = open_files->prev; free_openfilestruct(open_files); - } #else if (fileage != NULL) free_filestruct(fileage); @@ -871,15 +872,16 @@ void thanks_for_all_the_fish(void) exttype *bob = syntaxes->extensions; syntaxes->extensions = bob->next; - free(bob->val); + regfree(&bob->val); free(bob); } while (syntaxes->color != NULL) { colortype *bob = syntaxes->color; syntaxes->color = bob->next; - free(bob->start); - free(bob->end); + regfree(&bob->start); + if (bob->end != NULL) + regfree(&bob->end); free(bob); } syntaxes = syntaxes->next; diff --git a/nano.c b/nano.c index ea0486f7..c98c74a3 100644 --- a/nano.c +++ b/nano.c @@ -405,7 +405,8 @@ void help_init(void) else if (s->altval == NANO_ALT_SPACE) { meta_shortcut = 1; ptr += sprintf(ptr, "M-%.5s", _("Space")); - } + } else if (s->val == KEY_UP) + ptr += sprintf(ptr, "%.2s", _("Up")); #endif else if (s->altval > 0) { meta_shortcut = 1; @@ -762,14 +763,13 @@ void nano_disabled_msg(void) void do_preserve_msg(void) { - fprintf(stderr, _("\nThe -p flag now invokes the Pico \"preserve\" flag. The Pico compatibility\n")); - fprintf(stderr, _("flag been removed as nano is now fully Pico compatible. Please see the nano\n")); - fprintf(stderr, _("FAQ for more info on this change...\n\n")); + fprintf(stderr, _("\nThe -p flag now invokes the Pico \"preserve\" flag. The Pico\n")); + fprintf(stderr, _("compatibility flag has been removed as nano is now fully Pico\n")); + fprintf(stderr, _("compatible. Please see the nano FAQ for more info on this change...\n\n")); fprintf(stderr, _("Press return to continue\n")); while (getchar() != '\n'); } - #ifndef NANO_SMALL static int pid; /* This is the PID of the newly forked process * below. It must be global since the signal @@ -1644,7 +1644,11 @@ int do_int_spell_fix(const char *word) do_replace_highlight(TRUE, word); /* allow replace word to be corrected */ - i = statusq(0, spell_list, last_replace, 0, _("Edit a replacement")); + i = statusq(0, spell_list, last_replace, +#ifndef NANO_SMALL + 0, +#endif + _("Edit a replacement")); do_replace_highlight(FALSE, word); @@ -2985,10 +2989,9 @@ int abcd(int input) int main(int argc, char *argv[]) { int optchr; - int kbinput; /* Input from keyboard */ int startline = 0; /* Line to try and start at */ - int keyhandled; /* Have we handled the keystroke yet? */ int modify_control_seq; + int fill_flag_used = 0; /* Was the fill option used? */ const shortcut *s; #ifdef HAVE_GETOPT_LONG int preserveopt = 0; /* Did the cmdline include --preserve? */ @@ -2996,11 +2999,9 @@ int main(int argc, char *argv[]) #ifndef NANO_SMALL const toggle *t; #endif - #ifdef _POSIX_VDISABLE struct termios term; #endif - #ifdef HAVE_GETOPT_LONG int option_index = 0; const struct option long_options[] = { @@ -3064,56 +3065,37 @@ int main(int argc, char *argv[]) textdomain(PACKAGE); #endif -#ifdef ENABLE_NANORC +#ifdef HAVE_GETOPT_LONG { - /* scan through the options and handle -I/--ignorercfiles - first, so that it's handled before we call do_rcfile() and - read the other options; don't use getopt()/getopt_long() - here, because there's no way to reset it properly - afterward. Also check for the --preserve flag, and report - error if people are still using --pico. */ + /* Check for the --preserve flag, and report error if people are + still using --pico. */ int i; for (i = 1; i < argc; i++) { - if (!strcmp(argv[i], "--")) - break; - else if (!strcmp(argv[i], "-I")) - SET(NO_RCFILE); -#ifdef HAVE_GETOPT_LONG - else if (!strcmp(argv[i], "--ignorercfiles")) - SET(NO_RCFILE); - else if (!strcmp(argv[i], "--preserve")) + if (!strcmp(argv[i], "--preserve")) preserveopt = 1; else if (!strcmp(argv[i], "--pico")) do_preserve_msg(); -#endif } } +#endif - if (!ISSET(NO_RCFILE)) - do_rcfile(); -#else -#if defined(DISABLE_ROOTWRAP) && !defined(DISABLE_WRAPPING) +#if !defined(ENABLE_NANORC) && defined(DISABLE_ROOTWRAP) && !defined(DISABLE_WRAPPING) /* if we don't have rcfile support, we're root, and --disable-wrapping-as-root is used, turn wrapping off */ if (geteuid() == 0) SET(NO_WRAP); #endif -#endif /* ENABLE_NANORC */ #ifdef HAVE_GETOPT_LONG while ((optchr = getopt_long(argc, argv, "h?BDFIKMNQ:RST:VY:abcefgijklmo:pr:s:tvwxz", - long_options, &option_index)) != EOF) { + long_options, &option_index)) != -1) { #else while ((optchr = - getopt(argc, argv, "h?BDFIKMNQ:RST:VY:abcefgijklmo:pr:s:tvwxz")) != EOF) { + getopt(argc, argv, "h?BDFIKMNQ:RST:VY:abcefgijklmo:pr:s:tvwxz")) != -1) { #endif switch (optchr) { - case 'h': - case '?': - usage(); - exit(0); case 'a': case 'b': case 'e': @@ -3137,7 +3119,8 @@ int main(int argc, char *argv[]) #endif #ifdef ENABLE_NANORC case 'I': - break; + SET(NO_RCFILE); + break; #endif case 'K': SET(ALT_KEYPAD); @@ -3152,7 +3135,7 @@ int main(int argc, char *argv[]) #endif #ifndef DISABLE_JUSTIFY case 'Q': - quotestr = optarg; + quotestr = mallocstrcpy(quotestr, optarg); break; #endif #ifdef HAVE_REGEX_H @@ -3170,13 +3153,12 @@ int main(int argc, char *argv[]) int i; char *first_error; - /* Using strtol instead of atoi lets us accept 0 while - * checking other errors. */ + /* Using strtol() instead of atoi() lets us accept 0 + * while checking other errors. */ i = (int)strtol(optarg, &first_error, 10); - if (errno == ERANGE || *optarg == '\0' || *first_error != '\0') { + if (errno == ERANGE || *optarg == '\0' || *first_error != '\0') usage(); - exit(1); - } else + else tabsize = i; if (tabsize <= 0) { fprintf(stderr, _("Tab size is too small for nano...\n")); @@ -3229,15 +3211,15 @@ int main(int argc, char *argv[]) int i; char *first_error; - /* Using strtol instead of atoi lets us accept 0 while - * checking other errors. */ + /* Using strtol() instead of atoi() lets us accept 0 + * while checking other errors. */ i = (int)strtol(optarg, &first_error, 10); - if (errno == ERANGE || *optarg == '\0' || *first_error != '\0') { + if (errno == ERANGE || *optarg == '\0' || *first_error != '\0') usage(); - exit(1); - } else + else wrap_at = i; } + fill_flag_used = 1; break; #endif #ifndef DISABLE_SPELLER @@ -3264,20 +3246,95 @@ int main(int argc, char *argv[]) break; default: usage(); - exit(0); } } +/* We've read through the command line options. Now back up the flags + and values that are set, and read the rcfile(s). If the values + haven't changed afterward, restore the backed-up values. */ +#ifdef ENABLE_NANORC + if (!ISSET(NO_RCFILE)) { +#ifndef DISABLE_OPERATINGDIR + char *operating_dir_cpy = operating_dir; +#endif +#ifndef DISABLE_WRAPPING + int wrap_at_cpy = wrap_at; +#endif +#ifndef DISABLE_JUSTIFY + char *quotestr_cpy = quotestr; +#endif +#ifndef DISABLE_SPELLER + char *alt_speller_cpy = alt_speller; +#endif + int tabsize_cpy = tabsize; + long flags_cpy = flags; + + operating_dir = NULL; + quotestr = NULL; + alt_speller = NULL; + + do_rcfile(); + +#ifndef DISABLE_OPERATINGDIR + if (operating_dir_cpy != NULL) { + free(operating_dir); + operating_dir = operating_dir_cpy; + } +#endif +#ifndef DISABLE_WRAPPING + if (fill_flag_used) + wrap_at = wrap_at_cpy; +#endif +#ifndef DISABLE_JUSTIFY + if (quotestr_cpy != NULL) { + free(quotestr); + quotestr = quotestr_cpy; + } +#endif +#ifndef DISABLE_SPELLER + if (alt_speller_cpy != NULL) { + free(alt_speller); + alt_speller = alt_speller_cpy; + } +#endif + if (tabsize_cpy > 0) + tabsize = tabsize_cpy; + flags |= flags_cpy; + } +#if defined(DISABLE_ROOTWRAP) && !defined(DISABLE_WRAPPING) + else if (geteuid() == 0) + SET(NO_WRAP); +#endif +#endif /* ENABLE_NANORC */ + #ifndef DISABLE_OPERATINGDIR - /* Set up the operating directory. This entails chdir()ing there, so - that file reads and writes will be based there. */ + /* Set up the operating directory. This entails chdir()ing there, + so that file reads and writes will be based there. */ init_operating_dir(); #endif +#ifndef DISABLE_JUSTIFY + if (quotestr == NULL) +#ifdef HAVE_REGEX_H + quotestr = mallocstrcpy(NULL, "^([ \t]*[|>:}#])+"); +#else + quotestr = mallocstrcpy(NULL, "> "); +#endif +#endif /* !DISABLE_JUSTIFY */ + if (tabsize == -1) + tabsize = 8; + /* Clear the filename we'll be using */ filename = charalloc(1); filename[0] = '\0'; + /* If there's a +LINE flag, it is the first non-option argument. */ + if (0 < optind && optind < argc && argv[optind][0] == '+') { + startline = atoi(&argv[optind][1]); + optind++; + } + if (0 < optind && optind < argc) + filename = mallocstrcpy(filename, argv[optind]); /* See if there's a non-option in argv (first non-option is the filename, if +LINE is not given) */ @@ -3333,10 +3390,6 @@ int main(int argc, char *argv[]) history_init(); #endif -#ifdef ENABLE_COLOR - do_colorinit(); -#endif /* ENABLE_COLOR */ - #ifdef DEBUG fprintf(stderr, _("Main: bottom win\n")); #endif @@ -3347,32 +3400,41 @@ int main(int argc, char *argv[]) fprintf(stderr, _("Main: open file\n")); #endif - /* Now we check to see if argv[optind] is non-null to determine if - we're dealing with a new file or not, not argc == 1... */ - if (argv[optind] == NULL) - new_file(); - else - open_file(filename, 0, 0); + open_file(filename, 1, 1); +#ifdef ENABLE_MULTIBUFFER + /* If we're using multibuffers and more than one file is specified + on the command line, load them all and switch to the first one + afterward */ + if (ISSET(MULTIBUFFER) && optind + 1 < argc) { + for (optind++; optind < argc; optind++) { + add_open_file(1); + new_file(); + filename = mallocstrcpy(filename, argv[optind]); + open_file(filename, 0, 0); + load_file(0); + } + open_nextfile_void(); + } +#endif titlebar(NULL); if (startline > 0) do_gotoline(startline, 0); - else - edit_update(fileage, CENTER); - /* return here after a sigwinch */ + /* Return here after a sigwinch */ sigsetjmp(jmpbuf, 1); - /* Fix clobber-age */ - kbinput = 0; - keyhandled = 0; + /* This variable should be initialized after the sigsetjmp(), so we + can't do Esc-Esc then quickly resize and muck things up. */ modify_control_seq = 0; edit_refresh(); reset_cursor(); while (1) { + int keyhandled = 0; /* Have we handled the keystroke yet? */ + int kbinput; /* Input from keyboard */ #if !defined(DISABLE_BROWSER) || !defined(DISABLE_HELP) || (!defined(DISABLE_MOUSE) && defined(NCURSES_MOUSE_VERSION)) currshortcut = main_list; @@ -3388,10 +3450,14 @@ int main(int argc, char *argv[]) fprintf(stderr, _("AHA! %c (%d)\n"), kbinput, kbinput); #endif if (kbinput == 27) { /* Grab Alt-key stuff first */ - switch (kbinput = wgetch(edit)) { + kbinput = wgetch(edit); + switch (kbinput) { /* Alt-O, suddenly very important ;) */ case 'O': kbinput = wgetch(edit); + /* Shift or Ctrl + Arrows are Alt-O-[2,5,6]-[A,B,C,D] on some terms */ + if (kbinput == '2' || kbinput == '5' || kbinput == '6') + kbinput = wgetch(edit); if ((kbinput <= 'D' && kbinput >= 'A') || (kbinput <= 'd' && kbinput >= 'a')) kbinput = abcd(kbinput); @@ -3414,7 +3480,8 @@ int main(int argc, char *argv[]) keyhandled = 1; break; case '[': - switch (kbinput = wgetch(edit)) { + kbinput = wgetch(edit); + switch (kbinput) { case '1': /* Alt-[-1-[0-5,7-9] = F1-F8 in X at least */ kbinput = wgetch(edit); if (kbinput >= '1' && kbinput <= '5') { @@ -3453,7 +3520,8 @@ int main(int argc, char *argv[]) wgetch(edit); break; case '~': - goto do_insertkey; + kbinput = NANO_INSERTFILE_KEY; + break; #ifdef DEBUG default: fprintf(stderr, _("I got Alt-[-2-%c! (%d)\n"), @@ -3499,7 +3567,8 @@ int main(int argc, char *argv[]) break; case '@': /* Alt-[-@ = Insert in Hurd Console */ case 'L': /* Alt-[-L = Insert - FreeBSD Console */ - goto do_insertkey; + kbinput = NANO_INSERTFILE_KEY; + break; case '[': /* Alt-[-[-[A-E], F1-F5 in Linux console */ kbinput = wgetch(edit); if (kbinput >= 'A' && kbinput <= 'E') @@ -3530,7 +3599,6 @@ int main(int argc, char *argv[]) break; } break; - #ifdef ENABLE_MULTIBUFFER case NANO_OPENPREV_KEY: case NANO_OPENPREV_ALTKEY: @@ -3546,8 +3614,8 @@ int main(int argc, char *argv[]) default: /* Check for the altkey defs.... */ for (s = main_list; s != NULL; s = s->next) - if (kbinput == s->altval || - kbinput == s->altval - 32) { + if (kbinput == s->altval || (kbinput >= 'A' && + kbinput <= 'Z' && kbinput == s->altval - 32)) { if (ISSET(VIEW_MODE) && !s->viewok) print_view_warning(); else @@ -3558,9 +3626,8 @@ int main(int argc, char *argv[]) #ifndef NANO_SMALL /* And for toggle switches */ for (t = toggles; t != NULL && !keyhandled; t = t->next) - if (kbinput == t->val || - (t->val > 'a' && - kbinput == t->val - 32)) { + if (kbinput == t->val || (t->val >= 'a' && + t->val <= 'z' && kbinput == t->val - 32)) { do_toggle(t); keyhandled = 1; break; @@ -3573,6 +3640,10 @@ int main(int argc, char *argv[]) break; } } + /* Hack, make insert key do something useful, like insert file */ + else if (kbinput == KEY_IC) + kbinput = NANO_INSERTFILE_KEY; + /* If modify_control_seq is set, we received an Alt-Alt sequence before this, so we make this key a control sequence by subtracting 32, 64, or 96, depending on its value. */ @@ -3603,7 +3674,7 @@ int main(int argc, char *argv[]) else s->func(); keyhandled = 1; - /* rarely, the value of s can change after s->func(), + /* 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; @@ -3622,7 +3693,7 @@ int main(int argc, char *argv[]) if (kbinput == 17 || kbinput == 19) keyhandled = 1; - /* Catch ^Z by hand when triggered also + /* Catch ^Z by hand when triggered also 407 == ^Z in Linux console when keypad() is used? */ if (kbinput == 26 || kbinput == 407) { if (ISSET(SUSPEND)) @@ -3630,25 +3701,6 @@ int main(int argc, char *argv[]) keyhandled = 1; } - /* Hack, make insert key do something useful, like insert file */ - if (kbinput == KEY_IC) { - do_insertkey: - -#ifdef ENABLE_MULTIBUFFER - /* do_insertfile_void() contains the logic needed to - handle view mode with the view mode/multibuffer - exception, so use it here */ - do_insertfile_void(); -#else - if (!ISSET(VIEW_MODE)) - do_insertfile_void(); - else - print_view_warning(); -#endif - - keyhandled = 1; - } - /* Last gasp, stuff that's not in the main lists */ if (!keyhandled) switch (kbinput) { @@ -3659,9 +3711,9 @@ int main(int argc, char *argv[]) #endif case 0: /* Erg */ - case -1: /* Stuff that we don't want to do squat */ - case 410: /* Must ignore this, it gets sent when we resize */ case 29: /* Ctrl-] */ + case -1: /* Stuff that we don't want to do squat */ + case 410: /* Must ignore this, it's sent when we resize */ #ifdef PDCURSES case 541: /* ???? */ case 542: /* Control and alt in Windows *shrug* */ @@ -3678,22 +3730,19 @@ int main(int argc, char *argv[]) /* We no longer stop unhandled sequences so that people with odd character sets can type... */ - if (ISSET(VIEW_MODE)) { + if (ISSET(VIEW_MODE)) print_view_warning(); - break; - } - do_char(kbinput); + else + do_char(kbinput); } + if (ISSET(DISABLE_CURPOS)) UNSET(DISABLE_CURPOS); else if (ISSET(CONSTUPDATE)) - do_cursorpos(1); + do_cursorpos(1); reset_cursor(); wrefresh(edit); - keyhandled = 0; } - - getchar(); - finish(0); + assert(0); } diff --git a/nano.h b/nano.h index caea215b..612633d7 100644 --- a/nano.h +++ b/nano.h @@ -32,6 +32,9 @@ #define ISSET(bit) (flags & bit) #define TOGGLE(bit) flags ^= bit +/* Define charalloc as a macro rather than duplicating code */ +#define charalloc(howmuch) (char *)nmalloc((howmuch) * sizeof(char)) + #ifndef NANO_SMALL /* For the backup file copy ... */ # define COPYFILEBLOCKSIZE 1024 @@ -90,13 +93,12 @@ #define KEY_END -1 #endif /* KEY_END */ -/* Snatch these out of the ncurse sdefs, so we can use them in search - history regardless of whethere we're using ncurses or not */ -#ifndef KEY_UP +/* Snatch these out of the ncurses defs, so we can use them in search + history regardless of whether we're using ncurses or not */ +#if !defined(KEY_UP) || !defined(KEY_DOWN) #define KEY_UP 0403 #define KEY_DOWN 0402 -#endif /* KEY_UP */ - +#endif /* !KEY_UP || !KEY_DOWN */ #define VERMSG "GNU nano " VERSION @@ -412,12 +414,16 @@ typedef enum { /* Minimum editor window rows required for nano to work correctly */ #define MIN_EDITOR_ROWS 3 -/* Default number of characters from end-of-line where text wrapping occurs */ +/* Default number of characters from end-of-line where text wrapping + occurs */ #define CHARS_FROM_EOL 8 -/* Minimum fill length (space available for text before wrapping occurs) */ +/* Minimum fill length (space available for text before wrapping + occurs) */ #define MIN_FILL_LENGTH 10 -/* Maximum number of search history strings saved, same value used for replace history */ +/* Maximum number of search history strings saved, same value used for + replace history */ #define MAX_SEARCH_HISTORY 100 + #endif /* !NANO_H */ diff --git a/proto.h b/proto.h index 01278bf1..5f01c148 100644 --- a/proto.h +++ b/proto.h @@ -40,7 +40,7 @@ extern long totsize; extern int temp_opt; extern int wrap_at, flags, tabsize; extern int search_last_line; -extern int past_editbuff; +extern int search_offscreen; extern int currslen; #ifndef DISABLE_JUSTIFY @@ -169,13 +169,13 @@ int check_operating_dir(const char *currpath, int allow_tabcomp); int write_file(const char *name, int tmp, int append, int nonamechange); int do_writeout(const char *path, int exiting, int append); int do_writeout_void(void); -#ifndef DISABLE_TABCOMP char *real_dir_from_tilde(const char *buf); -#endif +#ifndef DISABLE_TABCOMP 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); +#endif #ifndef DISABLE_BROWSER struct stat filestat(const char *path); int diralphasort(const void *va, const void *vb); @@ -350,7 +350,6 @@ void replace_abort(void); 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_replace(void); @@ -391,7 +390,6 @@ const char *strstrwrapper(const char *haystack, const char *needle, const char *rev_start, int line_pos); void nperror(const char *s); 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); diff --git a/rcfile.c b/rcfile.c index d55986ec..4f6faa15 100644 --- a/rcfile.c +++ b/rcfile.c @@ -27,10 +27,10 @@ #include #include #include -#include #include #include #include +#include #include #include "proto.h" #include "nano.h" @@ -67,6 +67,7 @@ const static rcoption rcopts[] = { #ifndef DISABLE_OPERATINGDIR {"operatingdir", 0}, #endif + {"preserve", PRESERVE}, #ifndef DISABLE_JUSTIFY {"quotestr", 0}, #endif @@ -521,8 +522,8 @@ void parse_rcfile(FILE *rcstream) if (!strcasecmp(rcopts[i].name, "fill")) { char *first_error; - /* Using strtol instead of atoi lets us - * accept 0 while checking other + /* Using strtol() instead of atoi() lets + * us accept 0 while checking other * errors. */ j = (int)strtol(option, &first_error, 10); if (errno == ERANGE || *option == '\0' || *first_error != '\0') @@ -608,7 +609,7 @@ void do_rcfile(void) if (userage == NULL) { rcfile_error(_("I can't find my home directory! Wah!")); - SET(NO_RCFILE); /* if no .nanorc, don't try to read .nano_history */ + SET(NO_RCFILE); } else { nanorc = nrealloc(nanorc, strlen(userage->pw_dir) + 9); sprintf(nanorc, "%s/.nanorc", userage->pw_dir); diff --git a/search.c b/search.c index 86a772aa..d0027644 100644 --- a/search.c +++ b/search.c @@ -31,15 +31,6 @@ #include "proto.h" #include "nano.h" -#ifndef NANO_SMALL -#ifdef ENABLE_NANORC -#include -#endif -#endif - -static int past_editbuff; - /* findnextstr() is now searching lines not displayed */ - /* Regular expression helper functions */ #ifdef HAVE_REGEX_H @@ -95,13 +86,12 @@ 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). - - replacing = 1 if we call from do_replace, 0 if called from do_search - func. */ +/* Set up the system variables for a search or replace. Return -1 on + * abort, 0 on success, and 1 on rerun calling program. 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. */ int search_init(int replacing) { int i = 0; @@ -113,8 +103,6 @@ int search_init(int replacing) if (backupstring == NULL) backupstring = mallocstrcpy(backupstring, ""); -/* NEW TEST */ - #ifndef NANO_SMALL search_history.current = (historytype *)&search_history.next; #endif @@ -209,7 +197,7 @@ int search_init(int replacing) #ifndef NANO_SMALL search_history.current = search_history.next; #endif - i = (int)strtol(answer, &buf, 10); /* just testing answer here */ + i = (int)strtol(answer, &buf, 10); /* Just testing answer here */ if (!(errno == ERANGE || *answer == '\0' || *buf != '\0')) do_gotoline(-1, 0); else @@ -230,9 +218,9 @@ int is_whole_word(int curr_pos, const char *datastr, const char *searchword) size_t sln = curr_pos + strlen(searchword); /* start of line or previous character not a letter and end of line - * or next character not a letter */ - return (curr_pos < 1 || !isalpha((int) datastr[curr_pos - 1])) && - (sln == strlen(datastr) || !isalpha((int) datastr[sln])); + or next character not a letter */ + return (curr_pos < 1 || !isalpha((int)datastr[curr_pos - 1])) && + (sln == strlen(datastr) || !isalpha((int)datastr[sln])); } filestruct *findnextstr(int quiet, int bracket_mode, @@ -243,7 +231,7 @@ filestruct *findnextstr(int quiet, int bracket_mode, const char *searchstr, *rev_start = NULL, *found = NULL; int current_x_find = 0; - past_editbuff = 0; + search_offscreen = 0; if (!ISSET(REVERSE_SEARCH)) { /* forward search */ /* Argh, current_x is set to -1 by nano.c:do_int_spell_fix(), and @@ -274,15 +262,15 @@ filestruct *findnextstr(int quiet, int bracket_mode, fileptr = fileptr->next; if (fileptr == editbot) - past_editbuff = 1; + search_offscreen = 1; - /* EOF reached ?, wrap around once */ + /* EOF reached?, wrap around once */ if (fileptr == NULL) { /* don't wrap if looking for bracket match */ if (bracket_mode) return NULL; fileptr = fileage; - past_editbuff = 1; + search_offscreen = 1; if (!quiet) { statusbar(_("Search Wrapped")); SET(DISABLE_CURPOS); @@ -299,7 +287,7 @@ filestruct *findnextstr(int quiet, int bracket_mode, /* We found an instance */ current_x_find = found - fileptr->data; /* Ensure we haven't wrapped around again! */ - if ((search_last_line) && (current_x_find > beginx)) { + if (search_last_line && current_x_find > beginx) { if (!quiet) not_found_msg(needle); return NULL; @@ -308,7 +296,7 @@ filestruct *findnextstr(int quiet, int bracket_mode, #ifndef NANO_SMALL else { /* reverse search */ current_x_find = current_x - 1; - /* Make sure we haven't passed the begining of the string */ + /* Make sure we haven't passed the beginning of the string */ rev_start = &fileptr->data[current_x_find]; searchstr = fileptr->data; @@ -329,14 +317,14 @@ filestruct *findnextstr(int quiet, int bracket_mode, fileptr = fileptr->prev; if (fileptr == edittop->prev) - past_editbuff = 1; + search_offscreen = 1; /* SOF reached?, wrap around once */ /* ? */ if (fileptr == NULL) { if (bracket_mode) return NULL; fileptr = filebot; - past_editbuff = 1; + search_offscreen = 1; if (!quiet) { statusbar(_("Search Wrapped")); SET(DISABLE_CURPOS); @@ -366,7 +354,7 @@ filestruct *findnextstr(int quiet, int bracket_mode, current_x = current_x_find; if (!bracket_mode) { - if (past_editbuff) + if (search_offscreen) edit_update(fileptr, CENTER); else update_line(current, current_x); @@ -403,7 +391,7 @@ int do_search(void) return 1; } - /* If answer is now == "", copy last_search into answer... */ + /* If answer is now "", copy last_search into answer... */ if (answer[0] == '\0') answer = mallocstrcpy(answer, last_search); else @@ -415,10 +403,15 @@ int do_search(void) update_history(&search_history, answer); #endif /* !NANO_SMALL */ +#ifndef NANO_SMALL + /* add this search string to the search history list */ + update_history(&search_history, answer); +#endif /* !NANO_SMALL */ + search_last_line = 0; didfind = findnextstr(FALSE, FALSE, current, current_x, answer); - if ((fileptr == current) && (fileptr_x == current_x) && didfind != NULL) + if (fileptr == current && fileptr_x == current_x && didfind != NULL) statusbar(_("This is the only occurrence")); search_abort(); @@ -438,9 +431,9 @@ void replace_abort(void) #ifdef HAVE_REGEX_H int replace_regexp(char *string, int create_flag) { - /* split personality here - if create_flag is null, just calculate + /* Split personality here - if create_flag is NULL, just calculate * the size of the replacement line (necessary because of - * subexpressions like \1 \2 \3 in the replaced text) */ + * subexpressions like \1 \2 \3 in the replaced text). */ char *c; int new_size = strlen(current->data) + 1; @@ -459,14 +452,14 @@ int replace_regexp(char *string, int create_flag) c++; new_size++; } else { - int num = (int) *(c + 1) - (int) '0'; + int num = (int)(*(c + 1) - '0'); if (num >= 1 && num <= 9) { int i = regmatches[num].rm_so; if (num > search_regexp.re_nsub) { /* Ugh, they specified a subexpression that doesn't - exist. */ + * exist. */ return -1; } @@ -491,7 +484,7 @@ int replace_regexp(char *string, int create_flag) } if (create_flag) - *string = 0; + *string = '\0'; return new_size; } @@ -549,19 +542,13 @@ 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 */ +/* Step through each replace word and prompt user before replacing + * word. Return -1 if the string to replace isn't found at all. + * Otherwise, return the number of replacements made. */ int do_replace_loop(const char *prevanswer, const filestruct *begin, int *beginx, int wholewords, int *i) { - int replaceall = 0, numreplaced = 0; + int replaceall = 0, numreplaced = -1; filestruct *fileptr = NULL; char *copy; @@ -602,6 +589,9 @@ int do_replace_loop(const char *prevanswer, const filestruct *begin, continue; /* If we're here, we've found the search string */ + if (numreplaced == -1) + numreplaced = 0; + if (!replaceall) { curs_set(0); do_replace_highlight(TRUE, prevanswer); @@ -664,10 +654,14 @@ int do_replace_loop(const char *prevanswer, const filestruct *begin, break; } + /* If text has been added to the magicline, make a new magicline. */ + if (filebot->data[0] != '\0') + new_magicline(); + return numreplaced; } -/* Replace a string */ +/* Replace a string. */ int do_replace(void) { int i, numreplaced, beginx; @@ -738,7 +732,13 @@ int do_replace(void) current_x = beginx; renumber_all(); edit_update(current, CENTER); - print_replaced(numreplaced); + + if (numreplaced >= 0) + statusbar(__("Replaced %d occurrence", "Replaced %d occurrences", + numreplaced), numreplaced); + else + not_found_msg(prevanswer); + replace_abort(); return 1; } @@ -752,7 +752,11 @@ void goto_abort(void) int do_gotoline(int line, int save_pos) { if (line <= 0) { /* Ask for it */ - if (statusq(0, goto_list, (line ? answer : ""), 0, _("Enter line number"))) { + if (statusq(0, goto_list, (line ? answer : ""), +#ifndef NANO_SMALL + 0, +#endif + _("Enter line number"))) { statusbar(_("Aborted")); goto_abort(); return 0; @@ -815,7 +819,7 @@ int do_find_bracket(void) char ch_under_cursor, wanted_ch; const char *pos, *brackets = "([{<>}])"; char regexp_pat[] = "[ ]"; - int offset, have_past_editbuff = 0, flagsave, current_x_save, count = 1; + int offset, have_search_offscreen = 0, flagsave, current_x_save, count = 1; filestruct *current_save; ch_under_cursor = current->data[current_x]; @@ -853,12 +857,16 @@ int do_find_bracket(void) while (1) { search_last_line = 0; if (findnextstr(1, 1, current, current_x, regexp_pat) != NULL) { - have_past_editbuff |= past_editbuff; - if (current->data[current_x] == ch_under_cursor) /* found identical bracket */ + have_search_offscreen |= search_offscreen; + + /* found identical bracket */ + if (current->data[current_x] == ch_under_cursor) count++; - else { /* found complementary bracket */ + else { + + /* found complementary bracket */ if (!(--count)) { - if (have_past_editbuff) + if (have_search_offscreen) edit_update(current, CENTER); else update_line(current, current_x); @@ -867,7 +875,9 @@ int do_find_bracket(void) break; } } - } else { /* didn't find either left or right bracket */ + } else { + + /* didn't find either left or right bracket */ statusbar(_("No matching bracket")); current_x = current_x_save; current = current_save; diff --git a/utils.c b/utils.c index ce21b8ce..f20fc0e0 100644 --- a/utils.c +++ b/utils.c @@ -54,8 +54,8 @@ int num_of_digits(int n) /* Fix the memory allocation for a string. */ void align(char **strp) { - assert(strp != NULL); - *strp = nrealloc(*strp, strlen(*strp) + 1); + if (strp != NULL) + *strp = nrealloc(*strp, strlen(*strp) + 1); } /* Null a string at a certain index and align it. */ @@ -199,34 +199,20 @@ void nperror(const char *s) /* Thanks BG, many ppl have been asking for this... */ void *nmalloc(size_t howmuch) { - void *r; + void *r = malloc(howmuch); - /* Panic save? */ - - if ((r = malloc(howmuch)) == NULL) - die(_("nano: malloc: out of memory!")); - - return r; -} - -/* We're going to need this too - Hopefully this will minimize the - * transition cost of moving to the appropriate function. */ -char *charalloc(size_t howmuch) -{ - char *r = (char *)malloc(howmuch * sizeof(char)); - - if (r == NULL) - die(_("nano: malloc: out of memory!")); + if (r == NULL && howmuch != 0) + die(_("nano is out of memory!")); return r; } void *nrealloc(void *ptr, size_t howmuch) { - void *r; + void *r = realloc(ptr, howmuch); - if ((r = realloc(ptr, howmuch)) == NULL) - die(_("nano: realloc: out of memory!")); + if (r == NULL && howmuch != 0) + die(_("nano is out of memory!")); return r; } diff --git a/winio.c b/winio.c index b0b9fb4e..347ba566 100644 --- a/winio.c +++ b/winio.c @@ -161,10 +161,10 @@ void check_statblank(void) } } -/* Repaint the statusbar when getting a character in nanogetstr. buf +/* Repaint the statusbar when getting a character in nanogetstr(). buf * should be no longer than COLS - 4. * - * Note that we must turn on A_REVERSE here, since do_help turns it + * Note that we must turn on A_REVERSE here, since do_help() turns it * off! */ void nanoget_repaint(const char *buf, const char *inputbuf, int x) { @@ -313,13 +313,13 @@ int nanogetstr(int allowtabs, const char *buf, const char *def, case NANO_CONTROL_I: #ifndef NANO_SMALL /* tab history completion */ - if (history_list) { - if ((!complete) || (last_kbinput != NANO_CONTROL_I)) { + if (history_list != NULL) { + if (!complete || last_kbinput != NANO_CONTROL_I) { history_list->current = (historytype *)history_list; history_list->len = strlen(answer); } - if (history_list->len) { + if (history_list->len > 0) { complete = get_history_completion(history_list, answer); xend = strlen(complete); x = xend; @@ -349,18 +349,20 @@ int nanogetstr(int allowtabs, const char *buf, const char *def, x--; break; case KEY_UP: + case NANO_UP_KEY: #ifndef NANO_SMALL if (history_list) { - /* If there's no previous temp holder, or if we already arrowed - back down to it and (possibly edited ir), update the holder */ + /* If there's no previous temp holder, or if we already + arrowed back down to it and (possibly edited it), + update the holder */ if (currentbuf == NULL || (ret2cb == 1 && strcmp(currentbuf, answer))) { currentbuf = mallocstrcpy(currentbuf, answer); ret2cb = 0; } /* get older search from the history list */ - if ((history = get_history_older(history_list))) { + if ((history = get_history_older(history_list)) != NULL) { answer = mallocstrcpy(answer, history); xend = strlen(history); } else { @@ -372,10 +374,11 @@ int nanogetstr(int allowtabs, const char *buf, const char *def, #endif break; case KEY_DOWN: + case NANO_DOWN_KEY: #ifndef NANO_SMALL if (history_list) { /* get newer search from the history list */ - if ((history = get_history_newer(history_list))) { + if ((history = get_history_newer(history_list)) != NULL) { answer = mallocstrcpy(answer, history); xend = strlen(history); @@ -395,7 +398,6 @@ int nanogetstr(int allowtabs, const char *buf, const char *def, break; case KEY_DC: goto do_deletekey; - case 27: switch (kbinput = wgetch(edit)) { case 'O': @@ -432,7 +434,6 @@ int nanogetstr(int allowtabs, const char *buf, const char *def, case '4': case '8': x = xend; - goto skip_tilde; skip_tilde: nodelay(edit, TRUE); kbinput = wgetch(edit); @@ -479,7 +480,7 @@ int nanogetstr(int allowtabs, const char *buf, const char *def, wrefresh(bottomwin); } /* while (kbinput ...) */ - /* In Pico mode, just check for a blank answer here */ + /* Just check for a blank answer here */ if (answer[0] == '\0') return -2; else @@ -1101,15 +1102,14 @@ void edit_refresh(void) nlines++; } /* What the hell are we expecting to update the screen if this - isn't here? Luck?? */ + isn't here? Luck? */ wrefresh(edit); leaveok(edit, FALSE); } } -/* - * Same as above, but touch the window first, so everything is redrawn. - */ +/* Same as above, but touch the window first, so everything is + * redrawn. */ void edit_refresh_clearok(void) { clearok(edit, TRUE);