This commit is contained in:
Apple 2016-02-18 22:50:21 +01:00 committed by Lubos Dolezel
commit ca5fd02bb5
25 changed files with 23354 additions and 0 deletions

233
config.h Normal file
View File

@ -0,0 +1,233 @@
/* config.h. Generated from config.h.in by configure. */
/* config.h.in. Generated from configure.ac by autoheader. */
/* Define this to enable debug messages and assert warnings. */
/* #undef DEBUG */
/* Define this to disable the built-in file browser. */
/* #undef DISABLE_BROWSER */
/* Define this to disable the help text display. */
/* #undef DISABLE_HELP */
/* Define this to disable the justify routines. */
/* #undef DISABLE_JUSTIFY */
/* Define this to disable the mouse support. */
/* #undef DISABLE_MOUSE */
/* Define this to disable the setting of the operating directory (chroot of
sorts). */
/* #undef DISABLE_OPERATINGDIR */
/* Define this to disable text wrapping as root by default. */
/* #undef DISABLE_ROOTWRAPPING */
/* Define this to disable the spell checker functions. */
/* #undef DISABLE_SPELLER */
/* Define to disable the tab completion functions for files and search
strings. */
/* #undef DISABLE_TABCOMP */
/* Define this to disable all text wrapping. */
/* #undef DISABLE_WRAPPING */
/* Define this to have syntax highlighting, requires regex.h and ENABLE_NANORC
too! */
#define ENABLE_COLOR 1
/* Define this to enable multiple file buffers. */
#define ENABLE_MULTIBUFFER 1
/* Define this to use .nanorc files. */
#define ENABLE_NANORC 1
/* Define to 1 if translation of program messages to the user's native
language is requested. */
/* #undef ENABLE_NLS */
/* Define this if your system has sufficient UTF-8 support (a wide curses
library, iswalnum(), iswpunct(), iswblank() or iswspace(), mblen(),
mbstowcs(), mbtowc(), wctomb(), and wcwidth()). */
#define ENABLE_UTF8 1
/* Define to 1 if you have the <curses.h> header file. */
/* #undef HAVE_CURSES_H */
/* Define if the GNU dcgettext() function is already present or preinstalled.
*/
/* #undef HAVE_DCGETTEXT */
/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
/* #undef HAVE_DOPRNT */
/* Define to 1 if you have the `getdelim' function. */
/* #undef HAVE_GETDELIM */
/* Define to 1 if you have the `getline' function. */
/* #undef HAVE_GETLINE */
/* Define to 1 if you have the <getopt.h> header file. */
#define HAVE_GETOPT_H 1
/* Define to 1 if you have the `getopt_long' function. */
#define HAVE_GETOPT_LONG 1
/* Define if the GNU gettext() function is already present or preinstalled. */
/* #undef HAVE_GETTEXT */
/* Define if you have the iconv() function. */
#define HAVE_ICONV 1
/* Define to 1 if you have the <inttypes.h> header file. */
#define HAVE_INTTYPES_H 1
/* Define to 1 if you have the `isblank' function. */
#define HAVE_ISBLANK 1
/* Define to 1 if you have the `iswalnum' function. */
#define HAVE_ISWALNUM 1
/* Define to 1 if you have the `iswblank' function. */
#define HAVE_ISWBLANK 1
/* Define to 1 if you have the `iswpunct' function. */
#define HAVE_ISWPUNCT 1
/* Define to 1 if you have the `iswspace' function. */
#define HAVE_ISWSPACE 1
/* Define to 1 if you have the <libintl.h> header file. */
/* #undef HAVE_LIBINTL_H */
/* Define to 1 if you have the <limits.h> header file. */
#define HAVE_LIMITS_H 1
/* Define to 1 if you have the `mblen' function. */
#define HAVE_MBLEN 1
/* Define to 1 if you have the `mbstowcs' function. */
#define HAVE_MBSTOWCS 1
/* Define to 1 if you have the `mbtowc' function. */
#define HAVE_MBTOWC 1
/* Define to 1 if you have the <memory.h> header file. */
#define HAVE_MEMORY_H 1
/* Define to 1 if you have the <ncurses.h> header file. */
#define HAVE_NCURSES_H 1
/* Define to 1 if you have the <regex.h> header file. */
#define HAVE_REGEX_H 1
/* Define to 1 if you have the <stdint.h> header file. */
#define HAVE_STDINT_H 1
/* Define to 1 if you have the <stdlib.h> header file. */
#define HAVE_STDLIB_H 1
/* Define to 1 if you have the `strcasecmp' function. */
#define HAVE_STRCASECMP 1
/* Define to 1 if you have the `strcasestr' function. */
#define HAVE_STRCASESTR 1
/* Define to 1 if you have the <strings.h> header file. */
#define HAVE_STRINGS_H 1
/* Define to 1 if you have the <string.h> header file. */
#define HAVE_STRING_H 1
/* Define to 1 if you have the `strncasecmp' function. */
#define HAVE_STRNCASECMP 1
/* Define to 1 if you have the `strnlen' function. */
/* #undef HAVE_STRNLEN */
/* Define to 1 if you have the <sys/param.h> header file. */
#define HAVE_SYS_PARAM_H 1
/* Define to 1 if you have the <sys/stat.h> header file. */
#define HAVE_SYS_STAT_H 1
/* Define to 1 if you have the <sys/types.h> header file. */
#define HAVE_SYS_TYPES_H 1
/* Define to 1 if you have the <unistd.h> header file. */
#define HAVE_UNISTD_H 1
/* Define this if your curses library has the use_default_colors() command. */
#define HAVE_USE_DEFAULT_COLORS 1
/* Define to 1 if you have the `vprintf' function. */
#define HAVE_VPRINTF 1
/* Define to 1 if you have the `vsnprintf' function. */
#define HAVE_VSNPRINTF 1
/* Define to 1 if you have the <wchar.h> header file. */
#define HAVE_WCHAR_H 1
/* Define to 1 if you have the `wctomb' function. */
#define HAVE_WCTOMB 1
/* Define to 1 if you have the <wctype.h> header file. */
#define HAVE_WCTYPE_H 1
/* Define to 1 if you have the `wcwidth' function. */
#define HAVE_WCWIDTH 1
/* Define this to enable extra stuff. */
#define NANO_EXTRA 1
/* Define this to make the nano executable as small as possible. */
/* #undef NANO_TINY */
/* Shut up assert warnings :-) */
#define NDEBUG 1
/* Name of package */
#define PACKAGE "nano"
/* Define to the address where bug reports for this package should be sent. */
#define PACKAGE_BUGREPORT "nano-devel@gnu.org"
/* Define to the full name of this package. */
#define PACKAGE_NAME "GNU nano"
/* Define to the full name and version of this package. */
#define PACKAGE_STRING "GNU nano 2.0.6"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "nano"
/* Define to the version of this package. */
#define PACKAGE_VERSION "2.0.6"
/* Where data are placed to. */
#define PKGDATADIR "/usr/share/nano"
/* Define as the return type of signal handlers (`int' or `void'). */
#define RETSIGTYPE void
/* Define to 1 if you have the ANSI C header files. */
#define STDC_HEADERS 1
/* Define to use the slang wrappers for curses instead of native curses. */
/* #undef USE_SLANG */
/* Version number of package */
#define VERSION "2.0.6"
/* Number of bits in a file offset, on hosts where this is settable. */
/* #undef _FILE_OFFSET_BITS */
/* Enable GNU extensions on systems that have them. */
#ifndef _GNU_SOURCE
# define _GNU_SOURCE 1
#endif
/* Define for large files, on AIX-style hosts. */
/* #undef _LARGE_FILES */

340
doc/COPYING Normal file
View File

@ -0,0 +1,340 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

234
doc/nano.1 Normal file
View File

@ -0,0 +1,234 @@
.\" Hey, EMACS: -*- nroff -*-
.\" nano.1 is Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005,
.\" 2006 by Chris Allegretta <chrisa@asty.org>
.\"
.\" This is free documentation, see the latest version of the GNU
.\" General Public License for copying conditions. There is NO
.\" warranty.
.\"
.\" $Id: nano.1,v 1.50 2006/10/28 19:21:12 dolorous Exp $
.TH NANO 1 "version 2.0.0" "October 28, 2006"
.\" Please adjust this date whenever revising the manpage.
.\"
.SH NAME
nano \- Nano's ANOther editor, an enhanced free Pico clone
.SH SYNOPSIS
.B nano
.I [OPTIONS]\ [[\+LINE,COLUMN]\ FILE]...
.br
.SH DESCRIPTION
This manual page briefly documents the \fBnano\fP command.
.PP
.\" TeX users may be more comfortable with the \fB<whatever>\fP and
.\" \fI<whatever>\fP escape sequences to invoke bold face and italics,
.\" respectively.
\fBnano\fP is a small, free and friendly editor which aims to replace
Pico, the default editor included in the non-free Pine package. Rather
than just copying Pico's look and feel, \fBnano\fP also implements some
missing (or disabled by default) features in Pico, such as "search and
replace" and "go to line and column number".
.SH OPTIONS
.TP
.B \+\fILINE\fP,\fICOLUMN\fP
Places cursor at line number \fILINE\fP and column number \fICOLUMN\fP
(at least one of which must be specified) on startup, instead of the
default of line 1, column 1.
.TP
.B \-?
Same as \fB-h (\-\-help)\fP.
.TP
.B \-A (\-\-smarthome)
Make the Home key smarter. When Home is pressed anywhere but at the
very beginning of non-whitespace characters on a line, the cursor will
jump to that beginning (either forwards or backwards). If the cursor is
already at that position, it will jump to the true beginning of the
line.
.TP
.B \-B (\-\-backup)
When saving a file, back up the previous version of it to the current
filename suffixed with a ~.
.TP
.B \-C \fIdir\fP (\-\-backupdir=\fIdir\fP)
Set the directory where \fBnano\fP puts unique backup files if file
backups are enabled.
.TP
.B \-D (\-\-boldtext)
Use bold text instead of reverse video text.
.TP
.B \-E (\-\-tabstospaces)
Convert typed tabs to spaces.
.TP
.B \-F (\-\-multibuffer)
Enable multiple file buffers, if available.
.TP
.B \-H (\-\-historylog)
Log search and replace strings to \fI~/.nano_history\fP, so they can be
retrieved in later sessions, if nanorc support is available.
.TP
.B \-I (\-\-ignorercfiles)
Don't look at \fISYSCONFDIR/nanorc\fP or \fI~/.nanorc\fP, if nanorc
support is available.
.TP
.B \-K (\-\-rebindkeypad)
Interpret the numeric keypad keys so that they all work properly. You
should only need to use this option if they don't, as mouse support
won't work properly with this option enabled.
.TP
.B \-L (\-\-nonewlines)
Don't add newlines to the ends of files.
.TP
.B \-N (\-\-noconvert)
Disable automatic conversion of files from DOS/Mac format.
.TP
.B \-O (\-\-morespace)
Use the blank line below the titlebar as extra editing space.
.TP
.B \-Q \fIstr\fP (\-\-quotestr=\fIstr\fP)
Set the quoting string for justifying. The default is
"\fI^([\ \\t]*[#:>\\|}])+\fP" if extended regular expression support is
available, or "\fI>\ \fP" otherwise. Note that \fI\\t\fP stands for a
Tab.
.TP
.B \-R (\-\-restricted)
Restricted mode: don't read or write to any file not specified on the
command line; read any nanorc files; allow suspending; allow a file
to be appended to, prepended to, or saved under a different name if it
already has one; or use backup files or spell checking. Also accessible
by invoking \fBnano\fP with any name beginning with 'r' (e.g. "rnano").
.TP
.B \-S (\-\-smooth)
Enable smooth scrolling. Text will scroll line-by-line, instead of the
usual chunk-by-chunk behavior.
.TP
.B \-T \fIcols\fP (\-\-tabsize=\fIcols\fP)
Set the size (width) of a tab to \fIcols\fP columns. The value of
\fIcols\fP must be greater than 0. The default value is 8.
.TP
.B \-U (\-\-quickblank)
Do quick statusbar blanking. Statusbar messages will disappear after 1
keystroke instead of 25. Note that \fB-c\fP overrides this.
.TP
.B \-V (\-\-version)
Show the current version number and exit.
.TP
.B \-W (\-\-wordbounds)
Detect word boundaries more accurately by treating punctuation
characters as part of a word.
.TP
.B \-Y \fIstr\fP (\-\-syntax=\fIstr\fP)
Specify a specific syntax highlighting from the \fInanorc\fP to use, if
available.
.TP
.B \-c (\-\-const)
Constantly show the cursor position. Note that this overrides \fB-U\fP.
.TP
.B \-d (\-\-rebinddelete)
Interpret the Delete key differently so that both Backspace and Delete
work properly. You should only need to use this option if Backspace
acts like Delete on your system.
.TP
.B \-h (\-\-help)
Show a summary of command line options and exit.
.TP
.B \-i (\-\-autoindent)
Indent new lines to the previous line's indentation. Useful when
editing source code.
.TP
.B \-k (\-\-cut)
Enable cut from cursor to end of line.
.TP
.B \-l (\-\-nofollow)
If the file being edited is a symbolic link, replace the link with
a new file instead of following it. Good for editing files in
\fI/tmp\fP, perhaps?
.TP
.B \-m (\-\-mouse)
Enable mouse support, if available for your system. When enabled, mouse
clicks can be used to place the cursor, set the mark (with a double
click), and execute shortcuts. The mouse will work in the X Window
System, and on the console when gpm is running.
.TP
.B \-o \fIdir\fP (\-\-operatingdir=\fIdir\fP)
Set operating directory. Makes \fBnano\fP set up something similar to a
chroot.
.TP
.B \-p (\-\-preserve)
Preserve the XON and XOFF sequences (^Q and ^S) so they will be caught
by the terminal.
.TP
.B \-r \fIcols\fP (\-\-fill=\fIcols\fP)
Wrap lines at column \fIcols\fP. If this value is 0 or less, wrapping
will occur at the width of the screen less \fIcols\fP columns, allowing
the wrap point to vary along with the width of the screen if the screen
is resized. The default value is -8.
.TP
.B \-s \fIprog\fP (\-\-speller=\fIprog\fP)
Enable alternative spell checker command.
.TP
.B \-t (\-\-tempfile)
Always save changed buffer without prompting. Same as Pico's \fB-t\fP
option.
.TP
.B \-v (\-\-view)
View file (read only) mode.
.TP
.B \-w (\-\-nowrap)
Disable wrapping of long lines.
.TP
.B \-x (\-\-nohelp)
Disable help screen at bottom of editor.
.TP
.B \-z (\-\-suspend)
Enable suspend ability.
.TP
.B \-a, \-b, \-e, \-f, \-g, \-j
Ignored, for compatibility with Pico.
.SH INITIALIZATION FILE
\fBnano\fP will read initialization files in the following order:
\fISYSCONFDIR/nanorc\fP, then \fI~/.nanorc\fP. Please see
\fBnanorc(5)\fP and the example file \fBnanorc.sample\fP, both of which
should be provided with \fBnano\fP.
.SH NOTES
If no alternative spell checker command is specified on the command
line or in one of the nanorc files, \fBnano\fP will check the
\fBSPELL\fP environment variable for one.
In some cases \fBnano\fP will try to dump the buffer into an emergency
file. This will happen mainly if \fBnano\fP receives a SIGHUP or
SIGTERM or runs out of memory. It will write the buffer into a file
named \fInano.save\fP if the buffer didn't have a name already, or will
add a ".save" suffix to the current filename. If an emergency file with
that name already exists in the current directory, it will add ".save"
plus a number (e.g. ".save.1") to the current filename in order to make
it unique. In multibuffer mode, \fBnano\fP will write all the open
buffers to their respective emergency files.
.SH BUGS
Please send any comments or bug reports to \fBnano@nano-editor.org\fP.
The \fBnano\fP mailing list is available from \fBnano-devel@gnu.org\fP.
To subscribe, email to \fBnano-devel-request@gnu.org\fP with a subject
of "subscribe".
.SH HOMEPAGE
http://www.nano-editor.org/
.SH SEE ALSO
.PD 0
.TP
\fBnanorc\fP(5)
.PP
\fI/usr/share/doc/nano/\fP (or equivalent on your system)
.SH AUTHOR
Chris Allegretta <chrisa@asty.org>, et al (see \fIAUTHORS\fP and
\fITHANKS\fP for details). This manual page was originally written by
Jordi Mallach <jordi@gnu.org>, for the Debian system (but may be used by
others).

259
doc/nanorc.5 Normal file
View File

@ -0,0 +1,259 @@
.\" Hey, EMACS: -*- nroff -*-
.\" nanorc.5 is Copyright (C) 2003, 2004, 2005, 2006 by the Free
.\" Software Foundation, Inc.
.\"
.\" This is free documentation, see the latest version of the GNU
.\" General Public License for copying conditions. There is NO
.\" warranty.
.\"
.\" $Id: nanorc.5,v 1.53 2006/10/28 19:21:12 dolorous Exp $
.TH NANORC 5 "version 2.0.0" "October 28, 2006"
.\" Please adjust this date whenever revising the manpage.
.\"
.SH NAME
nanorc \- GNU nano's rcfile
.SH DESCRIPTION
This manual page briefly documents GNU \fBnano\fP's rcfile.
.PP
\fBnano\fP is a small, free and friendly editor which aims to replace
Pico, the default editor included in the non-free Pine package. Rather
than just copying Pico's look and feel, \fBnano\fP also implements some
missing (or disabled by default) features in Pico, such as "search and
replace" and "go to line and column number".
.PP
The \fInanorc\fP file contains the default settings for \fBnano\fP. It
should not be in DOS or Mac format. During startup, \fBnano\fP will
first read its system-wide settings from \fISYSCONFDIR/nanorc\fP, and
then user-specific settings from \fI~/.nanorc\fP.
.SH OPTIONS
The configuration file accepts a series of \fBset\fP and \fBunset\fP
commands, which can be used to configure nano on startup without using
the command line options. Additionally, the \fBsyntax\fP, \fBcolor\fP,
and \fBicolor\fP keywords are used to define syntax highlighting rules
for different text patterns. \fBnano\fP will read one command per line.
Options in nanorc files take precedence over nano's defaults, and
command line options override nanorc settings. Also, options are unset
by default, except for those that take arguments.
Quotes inside string parameters don't have to be escaped with
backslashes. The last double quote in the string will be treated as its
end. For example, for the \fBbrackets\fP option, "\fI"')>]}\fP" will
match \fI"\fP, \fI'\fP, \fI)\fP, \fI>\fP, \fI]\fP, and \fI}\fP.
The supported commands and arguments are:
.TP 3
.B set/unset autoindent
Use auto-indentation.
.TP
.B set/unset backup
Create backup files in \fIfilename~\fP.
.TP
.B set backupdir "\fIdirectory\fP"
Set the directory where \fBnano\fP puts unique backup files if file
backups are enabled.
.TP
.B set/unset backwards
Do backwards searches by default.
.TP
.B set/unset boldtext
Use bold text instead of reverse video text.
.TP
.B set brackets "\fIstring\fP"
Set the characters treated as closing brackets when justifying
paragraphs. They cannot contain blank characters. Only closing
punctuation, optionally followed by closing brackets, can end sentences.
The default value is "\fI"')>]}\fP".
.TP
.B set/unset casesensitive
Do case sensitive searches by default.
.TP
.B set/unset const
Constantly display the cursor position in the status bar.
.TP
.B set/unset cut
Use cut to end of line by default.
.TP
.B set fill \fIn\fP
Wrap lines at column number \fIn\fP. If \fIn\fP is 0 or less, the
maximum line length will be the screen width less \fIn\fP columns. The
default value is -8.
.TP
.B set/unset historylog
Enable \fI~/.nano_history\fP for saving and reading search/replace
strings.
.TP
.B set matchbrackets "\fIstring\fP"
Set the opening and closing brackets that can be found by bracket
searches. They cannot contain blank characters. The former set must
come before the latter set, and both must be in the same order. The
default value is "\fI(<[{)>]}\fP".
.TP
.B set/unset morespace
Use the blank line below the titlebar as extra editing space.
.TP
.B set/unset mouse
Enable mouse support, if available for your system. When enabled, mouse
clicks can be used to place the cursor, set the mark (with a double
click), and execute shortcuts. The mouse will work in the X Window
System, and on the console when gpm is running.
.TP
.B set/unset multibuffer
Allow inserting files into their own buffers.
.TP
.B set/unset noconvert
Don't convert files from DOS/Mac format.
.TP
.B set/unset nofollow
Don't follow symlinks when writing files.
.TP
.B set/unset nohelp
Don't display the help lists at the bottom of the screen.
.TP
.B set/unset nonewlines
Don't add newlines to the ends of files.
.TP
.B set/unset nowrap
Don't wrap text at all.
.TP
.B set operatingdir "\fIdirectory\fP"
\fBnano\fP will only read and write files inside \fIdirectory\fP and its
subdirectories. Also, the current directory is changed to here, so
files are inserted from this diractory. By default, the operating
directory feature is turned off.
.TP
.B set/unset preserve
Preserve the XON and XOFF keys (^Q and ^S).
.TP
.B set punct "\fIstring\fP"
Set the characters treated as closing punctuation when justifying
paragraphs. They cannot contain blank characters. Only closing
punctuation, optionally followed by closing brackets, can end sentences.
The default value is "\fI!.?\fP".
.TP
.B set/unset quickblank
Do quick statusbar blanking. Statusbar messages will disappear after 1
keystroke instead of 25.
.TP
.B set quotestr "\fIstring\fP"
The email-quote string, used to justify email-quoted paragraphs. This
is an extended regular expression if your system supports them,
otherwise a literal string. The default value is
"\fI^([\ \\t]*[#:>\\|}])+\fP" if you have extended regular expression
support, or "\fI>\ \fP" otherwise. Note that '\\t' stands for a literal
Tab character.
.TP
.B set/unset rebinddelete
Interpret the Delete key differently so that both Backspace and Delete
work properly. You should only need to use this option if Backspace
acts like Delete on your system.
.TP
.B set/unset rebindkeypad
Interpret the numeric keypad keys so that they all work properly. You
should only need to use this option if they don't, as mouse support
won't work properly with this option enabled.
.TP
.B set/unset regexp
Do extended regular expression searches by default.
.TP
.B set/unset smarthome
Make the Home key smarter. When Home is pressed anywhere but at the
very beginning of non-whitespace characters on a line, the cursor will
jump to that beginning (either forwards or backwards). If the cursor is
already at that position, it will jump to the true beginning of the
line.
.TP
.B set/unset smooth
Use smooth scrolling by default.
.TP
.B set speller "\fIspellprog\fP"
Use spelling checker \fIspellprog\fP instead of the built-in one, which
calls \fIspell\fP.
.TP
.B set/unset suspend
Allow \fBnano\fP to be suspended.
.TP
.B set tabsize \fIn\fP
Use a tab size of \fIn\fP columns. The value of \fIn\fP must be greater
than 0. The default value is 8.
.TP
.B set/unset tabstospaces
Convert typed tabs to spaces.
.TP
.B set/unset tempfile
Save automatically on exit, don't prompt.
.TP
.B set/unset view
Disallow file modification.
.TP
.B set whitespace "\fIstring\fP"
Set the two characters used to display the first characters of tabs and
spaces. They must be single-column characters.
.TP
.B set/unset wordbounds
Detect word boundaries more accurately by treating punctuation
characters as parts of words.
.TP
.B syntax "\fIstr\fP" ["\fIfileregex\fP" ... ]
Defines a syntax named \fIstr\fP which can be activated via the
-Y/--syntax command line option, or will be automatically activated if
the current filename matches the extended regular expression
\fIfileregex\fP. All following \fBcolor\fP and \fBicolor\fP statements
will apply to \fIsyntax\fP until a new syntax is defined.
The \fInone\fP syntax is reserved; specifying it on the command line is
the same as not having a syntax at all. The \fIdefault\fP syntax is
special: it takes no \fIfileregex\fP, and applies to files that don't
match any other syntax's \fIfileregex\fP.
.TP
.B color \fIfgcolor\fP,\fIbgcolor\fP "\fIregex\fP" ...
For the currently defined syntax, display all expressions matching
the extended regular expression \fIregex\fP with foreground color
\fIfgcolor\fP and background color \fIbgcolor\fP, at least one of which
must be specified. Legal colors for foreground and background color
are: white, black, red, blue, green, yellow, magenta, and cyan. You may
use the prefix "bright" to force a stronger color highlight for the
foreground. If your terminal supports transparency, not specifying a
\fIbgcolor\fP tells \fBnano\fP to attempt to use a transparent
background.
.TP
.B icolor \fIfgcolor\fP,\fIbgcolor\fP "\fIregex\fP" ...
Same as above, except that the expression matching is case insensitive.
.TP
.B color \fIfgcolor\fP,\fIbgcolor\fP start="\fIsr\fP" end="\fIer\fP"
Display expressions which start with the extended regular expression
\fIsr\fP and end with the extended regular expression \fIer\fP with
foreground color \fIfgcolor\fP and background color \fIbgcolor\fP,
at least one of which must be specified. This allows syntax
highlighting to span multiple lines. Note that all subsequent instances
of \fIsr\fP after an initial \fIsr\fP is found will be highlighted until
the first instance of \fIer\fP.
.TP
.B icolor \fIfgcolor\fP,\fIbgcolor\fP start="\fIsr\fP" end="\fIer\fP"
Same as above, except that the expression matching is case insensitive.
.TP
.B include "\fIsyntaxfile\fP"
Read in self-contained color syntaxes from \fIsyntaxfile\fP. Note that
\fIsyntaxfile\fP can only contain \fBsyntax\fP, \fBcolor\fP, and
\fBicolor\fP commands.
.SH FILES
.TP
.I SYSCONFDIR/nanorc
System-wide configuration file
.TP
.I ~/.nanorc
Per-user configuration file
.SH SEE ALSO
.PD 0
.TP
\fBnano\fP(1)
.PP
\fI/usr/share/doc/nano/examples/nanorc.sample\fP (or equivalent on your
system)
.SH AUTHOR
Chris Allegretta <chrisa@asty.org>, et al (see \fIAUTHORS\fP and
\fITHANKS\fP for details). This manual page was originally written by
Jordi Mallach <jordi@gnu.org>, for the Debian system (but may be used by
others).

86
doc/rnano.1 Normal file
View File

@ -0,0 +1,86 @@
.\" Hey, EMACS: -*- nroff -*-
.\" rnano.1 is Copyright (C) 2005, 2006 by Thijs Kinkhorst
.\" <thijs@kinkhorst.com>; skeleton based on nano-tiny.1 by Jordi
.\" Mallach <jordi@gnu.org>.
.\"
.\" This is free documentation, see the latest version of the GNU
.\" General Public License for copying conditions. There is NO
.\" warranty.
.\"
.\" $Id: rnano.1,v 1.15 2006/11/10 02:47:11 dolorous Exp $
.TH RNANO 1 "version 2.0.0" "October 28, 2006"
.\" Please adjust this date whenever revising the manpage.
.\"
.SH NAME
rnano \- Restricted mode for Nano's ANOther editor, an enhanced free
Pico clone
.SH SYNOPSIS
.B rnano
.I [OPTIONS]\ [[\+LINE,COLUMN]\ FILE]...
.br
.SH DESCRIPTION
This manual page briefly documents the \fBrnano\fP command.
.PP
.\" TeX users may be more comfortable with the \fB<whatever>\fP and
.\" \fI<whatever>\fP escape sequences to invoke bold face and italics,
.\" respectively.
\fBnano\fP is a small, free and friendly editor which aims to replace
Pico, the default editor included in the non-free Pine package. Rather
than just copying Pico's look and feel, \fBnano\fP also implements some
missing (or disabled by default) features in Pico, such as "search and
replace" and "go to line and column number".
.PP
\fBrnano\fP is a restricted version of \fBnano\fP, which only edits
specific files and doesn't allow the user access to the filesystem or a
command shell.
.PP
In restricted mode, \fBnano\fP will \fInot\fP:
.IP \[bu] 2
read or write to any file not specified on the command line;
.IP \[bu]
read any nanorc files;
.IP \[bu]
allow suspending;
.IP \[bu]
allow a file to be appended to, prepended to, or saved under a different
name;
.IP \[bu]
use backup files or spell checking.
.SH OPTIONS
.TP
.B \+\fILINE\fP,\fICOLUMN\fP
Places cursor at line number \fILINE\fP and column number \fICOLUMN\fP
(at least one of which must be specified) on startup, instead of the
default of line 1, column 1.
.TP
.B \-?
Same as \fB-h (\-\-help)\fP.
.TP
.B \-h (\-\-help)
Show a summary of command line options and exit.
.TP
.B \-V (\-\-version)
Show the current version number and exit.
.PP
See the \fBnano\fP(1) manpage for the complete documentation of
\fBnano\fP.
.SH BUGS
Please send any comments or bug reports to \fBnano@nano-editor.org\fP.
The \fBnano\fP mailing list is available from \fBnano-devel@gnu.org\fP.
To subscribe, email to \fBnano-devel-request@gnu.org\fP with a subject
of "subscribe".
.SH HOMEPAGE
http://www.nano-editor.org/
.SH AUTHOR
Chris Allegretta <chrisa@asty.org>, et al (see AUTHORS for details).
This manual page was originally written by Thijs Kinkhorst
<thijs@kinkhorst.com>, for the Debian system (but may be used by
others).

28
nano.plist Normal file
View File

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>OpenSourceProject</key>
<string>nano</string>
<key>OpenSourceVersion</key>
<string>2.0.6</string>
<key>OpenSourceWebsiteURL</key>
<string>http://www.nano-editor.org/</string>
<key>OpenSourceURL</key>
<string>http://www.nano-editor.org/dist/v2.0/nano-2.0.6.tar.gz</string>
<key>OpenSourceSHA1</key>
<string>00102580404cdb1c8594e5f6193000d5acac2249</string>
<key>OpenSourceImportDate</key>
<string>2007-11-01</string>
<key>OpenSourceModifications</key>
<array>
<string>7477012</string>
<string>12988489</string>
<string>16401178</string>
</array>
<key>OpenSourceLicense</key>
<string>GPL</string>
<key>OpenSourceLicenseFile</key>
<string>nano.txt</string>
</dict>
</plist>

View File

@ -0,0 +1,328 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 45;
objects = {
/* Begin PBXBuildFile section */
FDF793C70F992EA80016724F /* browser.c in Sources */ = {isa = PBXBuildFile; fileRef = FDF793A70F992E100016724F /* browser.c */; };
FDF793C80F992EA80016724F /* chars.c in Sources */ = {isa = PBXBuildFile; fileRef = FDF793A80F992E100016724F /* chars.c */; };
FDF793C90F992EA80016724F /* color.c in Sources */ = {isa = PBXBuildFile; fileRef = FDF793A90F992E100016724F /* color.c */; };
FDF793CA0F992EA80016724F /* cut.c in Sources */ = {isa = PBXBuildFile; fileRef = FDF793AA0F992E100016724F /* cut.c */; };
FDF793CB0F992EA80016724F /* files.c in Sources */ = {isa = PBXBuildFile; fileRef = FDF793AB0F992E100016724F /* files.c */; };
FDF793CC0F992EA80016724F /* global.c in Sources */ = {isa = PBXBuildFile; fileRef = FDF793AC0F992E100016724F /* global.c */; };
FDF793CD0F992EA80016724F /* help.c in Sources */ = {isa = PBXBuildFile; fileRef = FDF793AD0F992E100016724F /* help.c */; };
FDF793CE0F992EA80016724F /* move.c in Sources */ = {isa = PBXBuildFile; fileRef = FDF793AE0F992E100016724F /* move.c */; };
FDF793CF0F992EA80016724F /* nano.c in Sources */ = {isa = PBXBuildFile; fileRef = FDF793AF0F992E100016724F /* nano.c */; };
FDF793D00F992EA80016724F /* prompt.c in Sources */ = {isa = PBXBuildFile; fileRef = FDF793B10F992E110016724F /* prompt.c */; };
FDF793D10F992EA80016724F /* rcfile.c in Sources */ = {isa = PBXBuildFile; fileRef = FDF793B30F992E110016724F /* rcfile.c */; };
FDF793D20F992EA80016724F /* search.c in Sources */ = {isa = PBXBuildFile; fileRef = FDF793B40F992E110016724F /* search.c */; };
FDF793D30F992EA80016724F /* text.c in Sources */ = {isa = PBXBuildFile; fileRef = FDF793B50F992E110016724F /* text.c */; };
FDF793D40F992EA80016724F /* utils.c in Sources */ = {isa = PBXBuildFile; fileRef = FDF793B60F992E110016724F /* utils.c */; };
FDF793D50F992EA80016724F /* winio.c in Sources */ = {isa = PBXBuildFile; fileRef = FDF793B70F992E110016724F /* winio.c */; };
FDF794260F9931E60016724F /* libncurses.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = FDF794250F9931E60016724F /* libncurses.dylib */; };
FDF794460F9933940016724F /* nano.1 in Install man1 (1) */ = {isa = PBXBuildFile; fileRef = FDF793F60F992FAA0016724F /* nano.1 */; };
FDF794480F9933B40016724F /* nanorc.5 in Install man5 (1) */ = {isa = PBXBuildFile; fileRef = FDF793F70F992FAA0016724F /* nanorc.5 */; };
FDF7944C0F9934000016724F /* nanorc in Install etc */ = {isa = PBXBuildFile; fileRef = FDF793FC0F992FF80016724F /* nanorc */; };
FDF7944F0F99343D0016724F /* COPYING in Install OpenSourceLicenses */ = {isa = PBXBuildFile; fileRef = FDF793FB0F992FF80016724F /* COPYING */; };
FDF794500F9934430016724F /* nano.plist in Install OpenSourceVersions */ = {isa = PBXBuildFile; fileRef = FDF793E40F992F070016724F /* nano.plist */; };
/* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */
FDF794610F99344A0016724F /* Install man1 (1) */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 8;
dstPath = /usr/share/man/man1;
dstSubfolderSpec = 0;
files = (
FDF794460F9933940016724F /* nano.1 in Install man1 (1) */,
);
name = "Install man1 (1)";
runOnlyForDeploymentPostprocessing = 1;
};
FDF794620F99344A0016724F /* Install man5 (1) */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 8;
dstPath = /usr/share/man/man5;
dstSubfolderSpec = 0;
files = (
FDF794480F9933B40016724F /* nanorc.5 in Install man5 (1) */,
);
name = "Install man5 (1)";
runOnlyForDeploymentPostprocessing = 1;
};
FDF794640F99344A0016724F /* Install etc */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 8;
dstPath = /private/etc;
dstSubfolderSpec = 0;
files = (
FDF7944C0F9934000016724F /* nanorc in Install etc */,
);
name = "Install etc";
runOnlyForDeploymentPostprocessing = 1;
};
FDF794650F99344A0016724F /* Install OpenSourceVersions */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 8;
dstPath = /usr/local/OpenSourceVersions;
dstSubfolderSpec = 0;
files = (
FDF794500F9934430016724F /* nano.plist in Install OpenSourceVersions */,
);
name = "Install OpenSourceVersions";
runOnlyForDeploymentPostprocessing = 1;
};
FDF794660F99344A0016724F /* Install OpenSourceLicenses */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 8;
dstPath = /usr/local/OpenSourceLicenses;
dstSubfolderSpec = 0;
files = (
FDF7944F0F99343D0016724F /* COPYING in Install OpenSourceLicenses */,
);
name = "Install OpenSourceLicenses";
runOnlyForDeploymentPostprocessing = 1;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
FDF793A70F992E100016724F /* browser.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = browser.c; path = src/browser.c; sourceTree = "<group>"; };
FDF793A80F992E100016724F /* chars.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = chars.c; path = src/chars.c; sourceTree = "<group>"; };
FDF793A90F992E100016724F /* color.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = color.c; path = src/color.c; sourceTree = "<group>"; };
FDF793AA0F992E100016724F /* cut.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = cut.c; path = src/cut.c; sourceTree = "<group>"; };
FDF793AB0F992E100016724F /* files.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = files.c; path = src/files.c; sourceTree = "<group>"; };
FDF793AC0F992E100016724F /* global.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = global.c; path = src/global.c; sourceTree = "<group>"; };
FDF793AD0F992E100016724F /* help.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = help.c; path = src/help.c; sourceTree = "<group>"; };
FDF793AE0F992E100016724F /* move.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = move.c; path = src/move.c; sourceTree = "<group>"; };
FDF793AF0F992E100016724F /* nano.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = nano.c; path = src/nano.c; sourceTree = "<group>"; };
FDF793B00F992E100016724F /* nano.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = nano.h; path = src/nano.h; sourceTree = "<group>"; };
FDF793B10F992E110016724F /* prompt.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = prompt.c; path = src/prompt.c; sourceTree = "<group>"; };
FDF793B20F992E110016724F /* proto.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = proto.h; path = src/proto.h; sourceTree = "<group>"; };
FDF793B30F992E110016724F /* rcfile.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = rcfile.c; path = src/rcfile.c; sourceTree = "<group>"; };
FDF793B40F992E110016724F /* search.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = search.c; path = src/search.c; sourceTree = "<group>"; };
FDF793B50F992E110016724F /* text.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = text.c; path = src/text.c; sourceTree = "<group>"; };
FDF793B60F992E110016724F /* utils.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = utils.c; path = src/utils.c; sourceTree = "<group>"; };
FDF793B70F992E110016724F /* winio.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = winio.c; path = src/winio.c; sourceTree = "<group>"; };
FDF793C10F992E950016724F /* nano */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = nano; sourceTree = BUILT_PRODUCTS_DIR; };
FDF793E20F992F070016724F /* config.h */ = {isa = PBXFileReference; comments = "This file was generated by running:\n\n./configure --prefix=/usr --sysconfdir=/etc --enable-all\n\nNote that ENABLE_UTF8 was forced on, as the standard configure script does correctly detect the ncurses in Mac OS X."; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = config.h; sourceTree = "<group>"; };
FDF793E40F992F070016724F /* nano.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist; path = nano.plist; sourceTree = "<group>"; };
FDF793F60F992FAA0016724F /* nano.1 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.man; name = nano.1; path = doc/nano.1; sourceTree = "<group>"; };
FDF793F70F992FAA0016724F /* nanorc.5 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = nanorc.5; path = doc/nanorc.5; sourceTree = "<group>"; };
FDF793F80F992FAA0016724F /* rnano.1 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.man; name = rnano.1; path = doc/rnano.1; sourceTree = "<group>"; };
FDF793FB0F992FF80016724F /* COPYING */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = COPYING; path = doc/COPYING; sourceTree = "<group>"; };
FDF793FC0F992FF80016724F /* nanorc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = nanorc; sourceTree = "<group>"; };
FDF794250F9931E60016724F /* libncurses.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libncurses.dylib; path = /usr/lib/libncurses.dylib; sourceTree = "<absolute>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
FDF793BF0F992E950016724F /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
FDF794260F9931E60016724F /* libncurses.dylib in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
FDF793970F992DAB0016724F = {
isa = PBXGroup;
children = (
FDF793E20F992F070016724F /* config.h */,
FDF793E40F992F070016724F /* nano.plist */,
FDF793E60F992F3D0016724F /* doc */,
FDF793A40F992DBE0016724F /* src */,
FDF793C20F992E950016724F /* Products */,
FDF794250F9931E60016724F /* libncurses.dylib */,
);
sourceTree = "<group>";
};
FDF793A40F992DBE0016724F /* src */ = {
isa = PBXGroup;
children = (
FDF793B00F992E100016724F /* nano.h */,
FDF793B20F992E110016724F /* proto.h */,
FDF793A70F992E100016724F /* browser.c */,
FDF793A80F992E100016724F /* chars.c */,
FDF793A90F992E100016724F /* color.c */,
FDF793AA0F992E100016724F /* cut.c */,
FDF793AB0F992E100016724F /* files.c */,
FDF793AC0F992E100016724F /* global.c */,
FDF793AD0F992E100016724F /* help.c */,
FDF793AE0F992E100016724F /* move.c */,
FDF793AF0F992E100016724F /* nano.c */,
FDF793B10F992E110016724F /* prompt.c */,
FDF793B30F992E110016724F /* rcfile.c */,
FDF793B40F992E110016724F /* search.c */,
FDF793B50F992E110016724F /* text.c */,
FDF793B60F992E110016724F /* utils.c */,
FDF793B70F992E110016724F /* winio.c */,
);
name = src;
sourceTree = "<group>";
};
FDF793C20F992E950016724F /* Products */ = {
isa = PBXGroup;
children = (
FDF793C10F992E950016724F /* nano */,
);
name = Products;
sourceTree = "<group>";
};
FDF793E60F992F3D0016724F /* doc */ = {
isa = PBXGroup;
children = (
FDF793FB0F992FF80016724F /* COPYING */,
FDF793FC0F992FF80016724F /* nanorc */,
FDF793F70F992FAA0016724F /* nanorc.5 */,
FDF793F60F992FAA0016724F /* nano.1 */,
FDF793F80F992FAA0016724F /* rnano.1 */,
);
name = doc;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
FDF793C00F992E950016724F /* nano */ = {
isa = PBXNativeTarget;
buildConfigurationList = FDF793C60F992E960016724F /* Build configuration list for PBXNativeTarget "nano" */;
buildPhases = (
FDF793BE0F992E950016724F /* Sources */,
FDF793BF0F992E950016724F /* Frameworks */,
FDF794610F99344A0016724F /* Install man1 (1) */,
FDF794620F99344A0016724F /* Install man5 (1) */,
FDF794640F99344A0016724F /* Install etc */,
FDF794650F99344A0016724F /* Install OpenSourceVersions */,
FDF794660F99344A0016724F /* Install OpenSourceLicenses */,
FDF794700F9935650016724F /* Rename COPYING, Link pico */,
);
buildRules = (
);
dependencies = (
);
name = nano;
productName = nano;
productReference = FDF793C10F992E950016724F /* nano */;
productType = "com.apple.product-type.tool";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
FDF793990F992DAB0016724F /* Project object */ = {
isa = PBXProject;
buildConfigurationList = FDF7939C0F992DAB0016724F /* Build configuration list for PBXProject "nano" */;
compatibilityVersion = "Xcode 2.4";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
);
mainGroup = FDF793970F992DAB0016724F;
productRefGroup = FDF793C20F992E950016724F /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
FDF793C00F992E950016724F /* nano */,
);
};
/* End PBXProject section */
/* Begin PBXShellScriptBuildPhase section */
FDF794700F9935650016724F /* Rename COPYING, Link pico */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 8;
files = (
);
inputPaths = (
);
name = "Rename COPYING, Link pico";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 1;
shellPath = /bin/sh;
shellScript = "mv ${DSTROOT}/usr/local/OpenSourceLicenses/COPYING ${DSTROOT}/usr/local/OpenSourceLicenses/nano.txt\nln -s nano ${DSTROOT}/usr/bin/pico\nln -s nano.1 ${DSTROOT}/usr/share/man/man1/pico.1";
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
FDF793BE0F992E950016724F /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
FDF793C70F992EA80016724F /* browser.c in Sources */,
FDF793C80F992EA80016724F /* chars.c in Sources */,
FDF793C90F992EA80016724F /* color.c in Sources */,
FDF793CA0F992EA80016724F /* cut.c in Sources */,
FDF793CB0F992EA80016724F /* files.c in Sources */,
FDF793CC0F992EA80016724F /* global.c in Sources */,
FDF793CD0F992EA80016724F /* help.c in Sources */,
FDF793CE0F992EA80016724F /* move.c in Sources */,
FDF793CF0F992EA80016724F /* nano.c in Sources */,
FDF793D00F992EA80016724F /* prompt.c in Sources */,
FDF793D10F992EA80016724F /* rcfile.c in Sources */,
FDF793D20F992EA80016724F /* search.c in Sources */,
FDF793D30F992EA80016724F /* text.c in Sources */,
FDF793D40F992EA80016724F /* utils.c in Sources */,
FDF793D50F992EA80016724F /* winio.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin XCBuildConfiguration section */
FDF7939B0F992DAB0016724F /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CODE_SIGN_IDENTITY = "-";
CURRENT_PROJECT_VERSION = "$(RC_ProjectSourceVersion)";
DEAD_CODE_STRIPPING = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
PREBINDING = NO;
VERSIONING_SYSTEM = "apple-generic";
ZERO_LINK = NO;
};
name = Release;
};
FDF793C50F992E960016724F /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
GCC_PREPROCESSOR_DEFINITIONS = (
"$(GCC_PREPROCESSOR_DEFINITIONS_QUOTED_FOR_TARGET_1)",
HAVE_CONFIG_H,
);
GCC_PREPROCESSOR_DEFINITIONS_QUOTED_FOR_TARGET_1 = "SYSCONFDIR=\\\"/etc\\\"";
HEADER_SEARCH_PATHS = "$(SRCROOT)";
INSTALL_PATH = /usr/bin;
PRODUCT_NAME = nano;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
FDF7939C0F992DAB0016724F /* Build configuration list for PBXProject "nano" */ = {
isa = XCConfigurationList;
buildConfigurations = (
FDF7939B0F992DAB0016724F /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
FDF793C60F992E960016724F /* Build configuration list for PBXNativeTarget "nano" */ = {
isa = XCConfigurationList;
buildConfigurations = (
FDF793C50F992E960016724F /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = FDF793990F992DAB0016724F /* Project object */;
}

1
nanorc Normal file
View File

@ -0,0 +1 @@
set nowrap

1087
src/browser.c Normal file

File diff suppressed because it is too large Load Diff

1028
src/chars.c Normal file

File diff suppressed because it is too large Load Diff

203
src/color.c Normal file
View File

@ -0,0 +1,203 @@
/* $Id: color.c,v 1.42 2007/01/01 05:15:32 dolorous Exp $ */
/**************************************************************************
* color.c *
* *
* Copyright (C) 2001, 2002, 2003, 2004 Chris Allegretta *
* Copyright (C) 2005, 2006, 2007 David Lawrence Ramsey *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2, or (at your option) *
* any later version. *
* *
* This program is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software *
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA *
* 02110-1301, USA. *
* *
**************************************************************************/
#include "proto.h"
#include <stdio.h>
#include <string.h>
#ifdef ENABLE_COLOR
/* For each syntax list entry, go through the list of colors and assign
* the color pairs. */
void set_colorpairs(void)
{
const syntaxtype *this_syntax = syntaxes;
for (; this_syntax != NULL; this_syntax = this_syntax->next) {
colortype *this_color = this_syntax->color;
int color_pair = 1;
for (; this_color != NULL; this_color = this_color->next) {
const colortype *beforenow = this_syntax->color;
for (; beforenow != this_color &&
(beforenow->fg != this_color->fg ||
beforenow->bg != this_color->bg ||
beforenow->bright != this_color->bright);
beforenow = beforenow->next)
;
if (beforenow != this_color)
this_color->pairnum = beforenow->pairnum;
else {
this_color->pairnum = color_pair;
color_pair++;
}
}
}
}
/* Initialize the color information. */
void color_init(void)
{
assert(openfile != NULL);
if (has_colors()) {
const colortype *tmpcolor;
#ifdef HAVE_USE_DEFAULT_COLORS
bool defok;
#endif
start_color();
#ifdef HAVE_USE_DEFAULT_COLORS
/* Use the default colors, if available. */
defok = (use_default_colors() != ERR);
#endif
for (tmpcolor = openfile->colorstrings; tmpcolor != NULL;
tmpcolor = tmpcolor->next) {
short foreground = tmpcolor->fg, background = tmpcolor->bg;
if (foreground == -1) {
#ifdef HAVE_USE_DEFAULT_COLORS
if (!defok)
#endif
foreground = COLOR_WHITE;
}
if (background == -1) {
#ifdef HAVE_USE_DEFAULT_COLORS
if (!defok)
#endif
background = COLOR_BLACK;
}
init_pair(tmpcolor->pairnum, foreground, background);
#ifdef DEBUG
fprintf(stderr, "init_pair(): fg = %hd, bg = %hd\n", tmpcolor->fg, tmpcolor->bg);
#endif
}
}
}
/* Update the color information based on the current filename. */
void color_update(void)
{
const syntaxtype *tmpsyntax;
colortype *tmpcolor, *defcolor = NULL;
assert(openfile != NULL);
openfile->colorstrings = NULL;
/* If we specified a syntax override string, use it. */
if (syntaxstr != NULL) {
/* If the syntax override is "none", it's the same as not having
* a syntax at all, so get out. */
if (strcmp(syntaxstr, "none") == 0)
return;
for (tmpsyntax = syntaxes; tmpsyntax != NULL;
tmpsyntax = tmpsyntax->next) {
if (strcmp(tmpsyntax->desc, syntaxstr) == 0)
openfile->colorstrings = tmpsyntax->color;
if (openfile->colorstrings != NULL)
break;
}
}
/* If we didn't specify a syntax override string, or if we did and
* there was no syntax by that name, get the syntax based on the
* file extension. */
if (openfile->colorstrings == NULL) {
for (tmpsyntax = syntaxes; tmpsyntax != NULL;
tmpsyntax = tmpsyntax->next) {
exttype *e;
/* If this is the default syntax, it has no associated
* extensions, which we've checked for elsewhere. Skip over
* it here, but keep track of its color regexes. */
if (strcmp(tmpsyntax->desc, "default") == 0) {
defcolor = tmpsyntax->color;
continue;
}
for (e = tmpsyntax->extensions; e != NULL; e = e->next) {
bool not_compiled = (e->ext == NULL);
/* e->ext_regex has already been checked for validity
* elsewhere. Compile its specified regex if we haven't
* already. */
if (not_compiled) {
e->ext = (regex_t *)nmalloc(sizeof(regex_t));
regcomp(e->ext, e->ext_regex, REG_EXTENDED);
}
/* Set colorstrings if we matched the extension
* regex. */
if (regexec(e->ext, openfile->filename, 0, NULL,
0) == 0)
openfile->colorstrings = tmpsyntax->color;
if (openfile->colorstrings != NULL)
break;
/* Decompile e->ext_regex's specified regex if we aren't
* going to use it. */
if (not_compiled) {
regfree(e->ext);
free(e->ext);
e->ext = NULL;
}
}
}
}
/* If we didn't get a syntax based on the file extension, and we
* have a default syntax, use it. */
if (openfile->colorstrings == NULL && defcolor != NULL)
openfile->colorstrings = defcolor;
for (tmpcolor = openfile->colorstrings; tmpcolor != NULL;
tmpcolor = tmpcolor->next) {
/* tmpcolor->start_regex and tmpcolor->end_regex have already
* been checked for validity elsewhere. Compile their specified
* regexes if we haven't already. */
if (tmpcolor->start == NULL) {
tmpcolor->start = (regex_t *)nmalloc(sizeof(regex_t));
regcomp(tmpcolor->start, tmpcolor->start_regex,
REG_EXTENDED | (tmpcolor->icase ? REG_ICASE : 0));
}
if (tmpcolor->end_regex != NULL && tmpcolor->end == NULL) {
tmpcolor->end = (regex_t *)nmalloc(sizeof(regex_t));
regcomp(tmpcolor->end, tmpcolor->end_regex,
REG_EXTENDED | (tmpcolor->icase ? REG_ICASE : 0));
}
}
}
#endif /* ENABLE_COLOR */

272
src/cut.c Normal file
View File

@ -0,0 +1,272 @@
/* $Id: cut.c,v 1.61 2007/01/01 05:15:32 dolorous Exp $ */
/**************************************************************************
* cut.c *
* *
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 Chris Allegretta *
* Copyright (C) 2005, 2006, 2007 David Lawrence Ramsey *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2, or (at your option) *
* any later version. *
* *
* This program is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software *
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA *
* 02110-1301, USA. *
* *
**************************************************************************/
#include "proto.h"
#include <string.h>
#include <stdio.h>
static bool keep_cutbuffer = FALSE;
/* Should we keep the contents of the cutbuffer? */
static filestruct *cutbottom = NULL;
/* Pointer to the end of the cutbuffer. */
/* Indicate that we should no longer keep the contents of the
* cutbuffer. */
void cutbuffer_reset(void)
{
keep_cutbuffer = FALSE;
}
/* If we aren't on the last line of the file, move all the text of the
* current line, plus the newline at the end, into the cutbuffer. If we
* are, move all of the text of the current line into the cutbuffer. In
* both cases, set the current place we want to the beginning of the
* current line. */
void cut_line(void)
{
if (openfile->current != openfile->filebot)
move_to_filestruct(&cutbuffer, &cutbottom, openfile->current, 0,
openfile->current->next, 0);
else
move_to_filestruct(&cutbuffer, &cutbottom, openfile->current, 0,
openfile->current, strlen(openfile->current->data));
openfile->placewewant = 0;
}
#ifndef NANO_TINY
/* Move all currently marked text into the cutbuffer, and set the
* current place we want to where the text used to start. */
void cut_marked(void)
{
filestruct *top, *bot;
size_t top_x, bot_x;
mark_order((const filestruct **)&top, &top_x,
(const filestruct **)&bot, &bot_x, NULL);
move_to_filestruct(&cutbuffer, &cutbottom, top, top_x, bot, bot_x);
openfile->placewewant = xplustabs();
}
/* If we aren't at the end of the current line, move all the text from
* the current cursor position to the end of the current line, not
* counting the newline at the end, into the cutbuffer. If we are, and
* we're not on the last line of the file, move the newline at the end
* into the cutbuffer, and set the current place we want to where the
* newline used to be. */
void cut_to_eol(void)
{
size_t data_len = strlen(openfile->current->data);
assert(openfile->current_x <= data_len);
if (openfile->current_x < data_len)
/* If we're not at the end of the line, move all the text from
* the current position up to it, not counting the newline at
* the end, into the cutbuffer. */
move_to_filestruct(&cutbuffer, &cutbottom, openfile->current,
openfile->current_x, openfile->current, data_len);
else if (openfile->current != openfile->filebot) {
/* If we're at the end of the line, and it isn't the last line
* of the file, move all the text from the current position up
* to the beginning of the next line, i.e. the newline at the
* end, into the cutbuffer. */
move_to_filestruct(&cutbuffer, &cutbottom, openfile->current,
openfile->current_x, openfile->current->next, 0);
openfile->placewewant = xplustabs();
}
}
/* Move all the text from the current cursor position to the end of the
* file into the cutbuffer. */
void cut_to_eof(void)
{
move_to_filestruct(&cutbuffer, &cutbottom, openfile->current,
openfile->current_x, openfile->filebot,
strlen(openfile->filebot->data));
}
#endif /* !NANO_TINY */
/* Move text from the current filestruct into the cutbuffer. If
* copy_text is TRUE, copy the text back into the filestruct afterward.
* If cut_till_end is TRUE, move all text from the current cursor
* position to the end of the file into the cutbuffer. */
void do_cut_text(
#ifndef NANO_TINY
bool copy_text, bool cut_till_end
#else
void
#endif
)
{
#ifndef NANO_TINY
filestruct *cb_save = NULL;
/* The current end of the cutbuffer, before we add text to
* it. */
size_t cb_save_len = 0;
/* The length of the string at the current end of the cutbuffer,
* before we add text to it. */
bool old_no_newlines = ISSET(NO_NEWLINES);
#endif
assert(openfile->current != NULL && openfile->current->data != NULL);
/* If keep_cutbuffer is FALSE and the cutbuffer isn't empty, blow
* away the text in the cutbuffer. */
if (!keep_cutbuffer && cutbuffer != NULL) {
free_filestruct(cutbuffer);
cutbuffer = NULL;
#ifdef DEBUG
fprintf(stderr, "Blew away cutbuffer =)\n");
#endif
}
#ifndef NANO_TINY
if (copy_text) {
if (cutbuffer != NULL) {
/* If the cutbuffer isn't empty, save where it currently
* ends. This is where we'll add the new text. */
cb_save = cutbottom;
cb_save_len = strlen(cutbottom->data);
}
/* Set NO_NEWLINES to TRUE, so that we don't disturb the last
* line of the file when moving text to the cutbuffer. */
SET(NO_NEWLINES);
}
#endif
/* Set keep_cutbuffer to TRUE, so that the text we're going to move
* into the cutbuffer will be added to the text already in the
* cutbuffer instead of replacing it. */
keep_cutbuffer = TRUE;
#ifndef NANO_TINY
if (cut_till_end) {
/* If cut_till_end is TRUE, move all text up to the end of the
* file into the cutbuffer. */
cut_to_eof();
} else if (openfile->mark_set) {
/* If the mark is on, move the marked text to the cutbuffer, and
* turn the mark off. */
cut_marked();
openfile->mark_set = FALSE;
} else if (ISSET(CUT_TO_END))
/* If the CUT_TO_END flag is set, move all text up to the end of
* the line into the cutbuffer. */
cut_to_eol();
else
#endif
/* Move the entire line into the cutbuffer. */
cut_line();
#ifndef NANO_TINY
if (copy_text) {
/* Copy the text in the cutbuffer, starting at its saved end if
* there is one, back into the filestruct. This effectively
* uncuts the text we just cut without marking the file as
* modified. */
if (cutbuffer != NULL) {
if (cb_save != NULL) {
cb_save->data += cb_save_len;
copy_from_filestruct(cb_save, cutbottom);
cb_save->data -= cb_save_len;
} else
copy_from_filestruct(cutbuffer, cutbottom);
/* Set the current place we want to where the text from the
* cutbuffer ends. */
openfile->placewewant = xplustabs();
}
/* Set NO_NEWLINES back to what it was before, since we're done
* disturbing the text. */
if (!old_no_newlines)
UNSET(NO_NEWLINES);
} else
#endif
/* Leave the text in the cutbuffer, and mark the file as
* modified. */
set_modified();
/* Update the screen. */
edit_refresh();
#ifdef DEBUG
dump_filestruct(cutbuffer);
#endif
}
/* Move text from the current filestruct into the cutbuffer. */
void do_cut_text_void(void)
{
do_cut_text(
#ifndef NANO_TINY
FALSE, FALSE
#endif
);
}
#ifndef NANO_TINY
/* Move text from the current filestruct into the cutbuffer, and copy it
* back into the filestruct afterward. */
void do_copy_text(void)
{
do_cut_text(TRUE, FALSE);
}
/* Cut from the current cursor position to the end of the file. */
void do_cut_till_end(void)
{
do_cut_text(FALSE, TRUE);
}
#endif /* !NANO_TINY */
/* Copy text from the cutbuffer into the current filestruct. */
void do_uncut_text(void)
{
assert(openfile->current != NULL && openfile->current->data != NULL);
/* If the cutbuffer is empty, get out. */
if (cutbuffer == NULL)
return;
/* Add a copy of the text in the cutbuffer to the current filestruct
* at the current cursor position. */
copy_from_filestruct(cutbuffer, cutbottom);
/* Set the current place we want to where the text from the
* cutbuffer ends. */
openfile->placewewant = xplustabs();
/* Mark the file as modified. */
set_modified();
/* Update the screen. */
edit_refresh();
#ifdef DEBUG
dump_filestruct_reverse();
#endif
}

2556
src/files.c Normal file

File diff suppressed because it is too large Load Diff

1508
src/global.c Normal file

File diff suppressed because it is too large Load Diff

621
src/help.c Normal file
View File

@ -0,0 +1,621 @@
/* $Id: help.c,v 1.58.2.1 2007/04/19 03:15:04 dolorous Exp $ */
/**************************************************************************
* help.c *
* *
* Copyright (C) 2000, 2001, 2002, 2003, 2004 Chris Allegretta *
* Copyright (C) 2005, 2006, 2007 David Lawrence Ramsey *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2, or (at your option) *
* any later version. *
* *
* This program is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software *
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA *
* 02110-1301, USA. *
* *
**************************************************************************/
#include "proto.h"
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#ifndef DISABLE_HELP
static char *help_text = NULL;
/* The text displayed in the help window. */
/* Our main help browser function. refresh_func is the function we will
* call to refresh the edit window. */
void do_help(void (*refresh_func)(void))
{
int kbinput = ERR;
bool meta_key, func_key, old_no_help = ISSET(NO_HELP);
bool abort = FALSE;
/* Whether we should abort the help browser. */
size_t line = 0;
/* The line number in help_text of the first displayed help
* line. This variable is zero-based. */
size_t last_line = 0;
/* The line number in help_text of the last help line. This
* variable is zero-based. */
#ifndef DISABLE_MOUSE
const shortcut *oldshortcut = currshortcut;
/* The current shortcut list. */
#endif
const char *ptr;
/* The current line of the help text. */
size_t old_line = (size_t)-1;
/* The line we were on before the current line. */
curs_set(0);
blank_edit();
wattroff(bottomwin, reverse_attr);
blank_statusbar();
/* Set help_text as the string to display. */
help_init();
assert(help_text != NULL);
#ifndef DISABLE_MOUSE
/* Set currshortcut to allow clicking on the help screen's shortcut
* list, after help_init() is called. */
currshortcut = help_list;
#endif
if (ISSET(NO_HELP)) {
/* Make sure that the help screen's shortcut list will actually
* be displayed. */
UNSET(NO_HELP);
window_init();
}
bottombars(help_list);
wnoutrefresh(bottomwin);
/* Get the last line of the help text. */
ptr = help_text;
for (; *ptr != '\0'; last_line++) {
ptr += help_line_len(ptr);
if (*ptr == '\n')
ptr++;
}
if (last_line > 0)
last_line--;
while (!abort) {
size_t i;
/* Display the help text if we don't have a key, or if the help
* text has moved. */
if (kbinput == ERR || line != old_line) {
blank_edit();
ptr = help_text;
/* Calculate where in the text we should be, based on the
* page. */
for (i = 0; i < line; i++) {
ptr += help_line_len(ptr);
if (*ptr == '\n')
ptr++;
}
for (i = 0; i < editwinrows && *ptr != '\0'; i++) {
size_t j = help_line_len(ptr);
mvwaddnstr(edit, i, 0, ptr, j);
ptr += j;
if (*ptr == '\n')
ptr++;
}
}
wnoutrefresh(edit);
old_line = line;
kbinput = get_kbinput(edit, &meta_key, &func_key);
parse_help_input(&kbinput, &meta_key, &func_key);
switch (kbinput) {
#ifndef DISABLE_MOUSE
case KEY_MOUSE:
{
int mouse_x, mouse_y;
get_mouseinput(&mouse_x, &mouse_y, TRUE);
}
break;
#endif
/* Redraw the screen. */
case NANO_REFRESH_KEY:
total_redraw();
break;
case NANO_PREVPAGE_KEY:
if (line > editwinrows - 2)
line -= editwinrows - 2;
else
line = 0;
break;
case NANO_NEXTPAGE_KEY:
if (line + (editwinrows - 1) < last_line)
line += editwinrows - 2;
break;
case NANO_PREVLINE_KEY:
if (line > 0)
line--;
break;
case NANO_NEXTLINE_KEY:
if (line + (editwinrows - 1) < last_line)
line++;
break;
case NANO_FIRSTLINE_METAKEY:
if (meta_key)
line = 0;
break;
case NANO_LASTLINE_METAKEY:
if (meta_key) {
if (line + (editwinrows - 1) < last_line)
line = last_line - (editwinrows - 1);
}
break;
/* Abort the help browser. */
case NANO_EXIT_KEY:
abort = TRUE;
break;
}
}
#ifndef DISABLE_MOUSE
currshortcut = oldshortcut;
#endif
if (old_no_help) {
blank_bottombars();
wnoutrefresh(bottomwin);
SET(NO_HELP);
window_init();
} else
bottombars(currshortcut);
curs_set(1);
refresh_func();
/* The help_init() at the beginning allocated help_text. Since
* help_text has now been written to the screen, we don't need it
* anymore. */
free(help_text);
help_text = NULL;
}
/* Start the help browser for the edit window. */
void do_help_void(void)
{
do_help(&edit_refresh);
}
#ifndef DISABLE_BROWSER
/* Start the help browser for the file browser. */
void do_browser_help(void)
{
do_help(&browser_refresh);
}
#endif
/* This function allocates help_text, and stores the help string in it.
* help_text should be NULL initially. */
void help_init(void)
{
size_t allocsize = 0; /* Space needed for help_text. */
const char *htx[3]; /* Untranslated help message. We break
* it up into three chunks in case the
* full string is too long for the
* compiler to handle. */
char *ptr;
const shortcut *s;
#ifndef NANO_TINY
const toggle *t;
#ifdef ENABLE_NANORC
bool old_whitespace = ISSET(WHITESPACE_DISPLAY);
UNSET(WHITESPACE_DISPLAY);
#endif
#endif
/* First, set up the initial help text for the current function. */
if (currshortcut == whereis_list || currshortcut == replace_list ||
currshortcut == replace_list_2) {
htx[0] = N_("Search Command Help Text\n\n "
"Enter the words or characters you would like to "
"search for, and then press Enter. If there is a "
"match for the text you entered, the screen will be "
"updated to the location of the nearest match for the "
"search string.\n\n The previous search string will be "
"shown in brackets after the search prompt. Hitting "
"Enter without entering any text will perform the "
"previous search. ");
htx[1] = N_("If you have selected text with the mark and then "
"search to replace, only matches in the selected text "
"will be replaced.\n\n The following function keys are "
"available in Search mode:\n\n");
htx[2] = NULL;
} else if (currshortcut == gotoline_list) {
htx[0] = N_("Go To Line Help Text\n\n "
"Enter the line number that you wish to go to and hit "
"Enter. If there are fewer lines of text than the "
"number you entered, you will be brought to the last "
"line of the file.\n\n The following function keys are "
"available in Go To Line mode:\n\n");
htx[1] = NULL;
htx[2] = NULL;
} else if (currshortcut == insertfile_list) {
htx[0] = N_("Insert File Help Text\n\n "
"Type in the name of a file to be inserted into the "
"current file buffer at the current cursor "
"location.\n\n If you have compiled nano with multiple "
"file buffer support, and enable multiple file buffers "
"with the -F or --multibuffer command line flags, the "
"Meta-F toggle, or a nanorc file, inserting a file "
"will cause it to be loaded into a separate buffer "
"(use Meta-< and > to switch between file buffers). ");
htx[1] = N_("If you need another blank buffer, do not enter "
"any filename, or type in a nonexistent filename at "
"the prompt and press Enter.\n\n The following "
"function keys are available in Insert File mode:\n\n");
htx[2] = NULL;
} else if (currshortcut == writefile_list) {
htx[0] = N_("Write File Help Text\n\n "
"Type the name that you wish to save the current file "
"as and press Enter to save the file.\n\n If you have "
"selected text with the mark, you will be prompted to "
"save only the selected portion to a separate file. To "
"reduce the chance of overwriting the current file with "
"just a portion of it, the current filename is not the "
"default in this mode.\n\n The following function keys "
"are available in Write File mode:\n\n");
htx[1] = NULL;
htx[2] = NULL;
}
#ifndef DISABLE_BROWSER
else if (currshortcut == browser_list) {
htx[0] = N_("File Browser Help Text\n\n "
"The file browser is used to visually browse the "
"directory structure to select a file for reading "
"or writing. You may use the arrow keys or Page Up/"
"Down to browse through the files, and S or Enter to "
"choose the selected file or enter the selected "
"directory. To move up one level, select the "
"directory called \"..\" at the top of the file "
"list.\n\n The following function keys are available "
"in the file browser:\n\n");
htx[1] = NULL;
htx[2] = NULL;
} else if (currshortcut == whereis_file_list) {
htx[0] = N_("Browser Search Command Help Text\n\n "
"Enter the words or characters you would like to "
"search for, and then press Enter. If there is a "
"match for the text you entered, the screen will be "
"updated to the location of the nearest match for the "
"search string.\n\n The previous search string will be "
"shown in brackets after the search prompt. Hitting "
"Enter without entering any text will perform the "
"previous search.\n\n");
htx[1] = N_(" The following function keys are available in "
"Browser Search mode:\n\n");
htx[2] = NULL;
} else if (currshortcut == gotodir_list) {
htx[0] = N_("Browser Go To Directory Help Text\n\n "
"Enter the name of the directory you would like to "
"browse to.\n\n If tab completion has not been "
"disabled, you can use the Tab key to (attempt to) "
"automatically complete the directory name.\n\n The "
"following function keys are available in Browser Go "
"To Directory mode:\n\n");
htx[1] = NULL;
htx[2] = NULL;
}
#endif /* !DISABLE_BROWSER */
#ifndef DISABLE_SPELLER
else if (currshortcut == spell_list) {
htx[0] = N_("Spell Check Help Text\n\n "
"The spell checker checks the spelling of all text in "
"the current file. When an unknown word is "
"encountered, it is highlighted and a replacement can "
"be edited. It will then prompt to replace every "
"instance of the given misspelled word in the current "
"file, or, if you have selected text with the mark, in "
"the selected text.\n\n The following function keys "
"are available in Spell Check mode:\n\n");
htx[1] = NULL;
htx[2] = NULL;
}
#endif /* !DISABLE_SPELLER */
#ifndef NANO_TINY
else if (currshortcut == extcmd_list) {
htx[0] = N_("Execute Command Help Text\n\n "
"This mode allows you to insert the output of a "
"command run by the shell into the current buffer (or "
"a new buffer in multiple file buffer mode). If you "
"need another blank buffer, do not enter any "
"command.\n\n The following function keys are "
"available in Execute Command mode:\n\n");
htx[1] = NULL;
htx[2] = NULL;
}
#endif /* !NANO_TINY */
else {
/* Default to the main help list. */
htx[0] = N_("Main nano help text\n\n "
"The nano editor is designed to emulate the "
"functionality and ease-of-use of the UW Pico text "
"editor. There are four main sections of the editor. "
"The top line shows the program version, the current "
"filename being edited, and whether or not the file "
"has been modified. Next is the main editor window "
"showing the file being edited. The status line is "
"the third line from the bottom and shows important "
"messages. ");
htx[1] = N_("The bottom two lines show the most commonly used "
"shortcuts in the editor.\n\n The notation for "
"shortcuts is as follows: Control-key sequences are "
"notated with a caret (^) symbol and can be entered "
"either by using the Control (Ctrl) key or pressing "
"the Escape (Esc) key twice. Escape-key sequences are "
"notated with the Meta (M-) symbol and can be entered "
"using either the Esc, Alt, or Meta key depending on "
"your keyboard setup. ");
htx[2] = N_("Also, pressing Esc twice and then typing a "
"three-digit decimal number from 000 to 255 will enter "
"the character with the corresponding value. The "
"following keystrokes are available in the main editor "
"window. Alternative keys are shown in "
"parentheses:\n\n");
}
htx[0] = _(htx[0]);
if (htx[1] != NULL)
htx[1] = _(htx[1]);
if (htx[2] != NULL)
htx[2] = _(htx[2]);
allocsize += strlen(htx[0]);
if (htx[1] != NULL)
allocsize += strlen(htx[1]);
if (htx[2] != NULL)
allocsize += strlen(htx[2]);
/* Count the shortcut help text. Each entry has up to three keys,
* which fill 24 columns, plus translated text, plus one or two
* \n's. */
for (s = currshortcut; s != NULL; s = s->next)
allocsize += (24 * mb_cur_max()) + strlen(s->help) + 2;
#ifndef NANO_TINY
/* If we're on the main list, we also count the toggle help text.
* Each entry has "M-%c\t\t\t", which fills 24 columns, plus a
* space, plus translated text, plus one or two '\n's. */
if (currshortcut == main_list) {
size_t endis_len = strlen(_("enable/disable"));
for (t = toggles; t != NULL; t = t->next)
allocsize += strlen(t->desc) + endis_len + 9;
}
#endif
/* help_text has been freed and set to NULL unless the user resized
* while in the help screen. */
if (help_text != NULL)
free(help_text);
/* Allocate space for the help text. */
help_text = charalloc(allocsize + 1);
/* Now add the text we want. */
strcpy(help_text, htx[0]);
if (htx[1] != NULL)
strcat(help_text, htx[1]);
if (htx[2] != NULL)
strcat(help_text, htx[2]);
ptr = help_text + strlen(help_text);
/* Now add our shortcut info. Assume that each shortcut has, at the
* very least, an equivalent control key, an equivalent primary meta
* key sequence, or both. Also assume that the meta key values are
* not control characters. We can display a maximum of three
* shortcut entries. */
for (s = currshortcut; s != NULL; s = s->next) {
int entries = 0;
/* Control key. */
if (s->ctrlval != NANO_NO_KEY) {
entries++;
/* Yucky sentinel values that we can't handle a better
* way. */
if (s->ctrlval == NANO_CONTROL_SPACE) {
char *space_ptr = display_string(_("Space"), 0, 14,
FALSE);
if (s->funcval == NANO_NO_KEY && (s->metaval ==
NANO_NO_KEY || s->miscval == NANO_NO_KEY)) {
/* If we're here, we have at least two entries worth
* of blank space. If this entry takes up more than
* one entry's worth of space, use two to display
* it. */
if (mbstrlen(space_ptr) > 6)
entries++;
} else
/* Otherwise, truncate it so that it takes up only
* one entry's worth of space. */
space_ptr[6] = '\0';
ptr += sprintf(ptr, "^%s", space_ptr);
free(space_ptr);
} else if (s->ctrlval == NANO_CONTROL_8)
ptr += sprintf(ptr, "^?");
/* Normal values. */
else
ptr += sprintf(ptr, "^%c", s->ctrlval + 64);
*(ptr++) = '\t';
}
/* Function key. */
if (s->funcval != NANO_NO_KEY) {
entries++;
/* If this is the first entry, put it in the middle. */
if (entries == 1) {
entries++;
*(ptr++) = '\t';
}
ptr += sprintf(ptr, "(F%d)", s->funcval - KEY_F0);
*(ptr++) = '\t';
}
/* Primary meta key sequence. If it's the first entry, don't
* put parentheses around it. */
if (s->metaval != NANO_NO_KEY) {
entries++;
/* If this is the last entry, put it at the end. */
if (entries == 2 && s->miscval == NANO_NO_KEY) {
entries++;
*(ptr++) = '\t';
}
/* Yucky sentinel values that we can't handle a better
* way. */
if (s->metaval == NANO_META_SPACE && entries == 1) {
char *space_ptr = display_string(_("Space"), 0, 13,
FALSE);
/* If we're here, we have at least two entries worth of
* blank space. If this entry takes up more than one
* entry's worth of space, use two to display it. */
if (mbstrlen(space_ptr) > 5)
entries++;
ptr += sprintf(ptr, "M-%s", space_ptr);
free(space_ptr);
} else
/* Normal values. */
ptr += sprintf(ptr, (entries == 1) ? "M-%c" : "(M-%c)",
toupper(s->metaval));
*(ptr++) = '\t';
}
/* Miscellaneous meta key sequence. */
if (entries < 3 && s->miscval != NANO_NO_KEY) {
entries++;
/* If this is the last entry, put it at the end. */
if (entries == 2) {
entries++;
*(ptr++) = '\t';
}
ptr += sprintf(ptr, "(M-%c)", toupper(s->miscval));
*(ptr++) = '\t';
}
/* If this entry isn't blank, make sure all the help text starts
* at the same place. */
if (s->ctrlval != NANO_NO_KEY || s->funcval != NANO_NO_KEY ||
s->metaval != NANO_NO_KEY || s->miscval !=
NANO_NO_KEY) {
while (entries < 3) {
entries++;
*(ptr++) = '\t';
}
}
/* The shortcut's help text. */
ptr += sprintf(ptr, "%s\n", s->help);
if (s->blank_after)
ptr += sprintf(ptr, "\n");
}
#ifndef NANO_TINY
/* And the toggles... */
if (currshortcut == main_list) {
for (t = toggles; t != NULL; t = t->next) {
ptr += sprintf(ptr, "M-%c\t\t\t%s %s\n",
toupper(t->val), t->desc, _("enable/disable"));
if (t->blank_after)
ptr += sprintf(ptr, "\n");
}
}
#ifdef ENABLE_NANORC
if (old_whitespace)
SET(WHITESPACE_DISPLAY);
#endif
#endif
/* If all went well, we didn't overwrite the allocated space for
* help_text. */
assert(strlen(help_text) <= allocsize + 1);
}
/* Determine the shortcut key corresponding to the values of kbinput
* (the key itself), meta_key (whether the key is a meta sequence), and
* func_key (whether the key is a function key), if any. In the
* process, convert certain non-shortcut keys into their corresponding
* shortcut keys. */
void parse_help_input(int *kbinput, bool *meta_key, bool *func_key)
{
get_shortcut(help_list, kbinput, meta_key, func_key);
if (!*meta_key) {
switch (*kbinput) {
/* For consistency with the file browser. */
case ' ':
*kbinput = NANO_NEXTPAGE_KEY;
break;
case '-':
*kbinput = NANO_PREVPAGE_KEY;
break;
/* Cancel is equivalent to Exit here. */
case NANO_CANCEL_KEY:
case 'E':
case 'e':
*kbinput = NANO_EXIT_KEY;
break;
}
}
}
/* Calculate the next line of help_text, starting at ptr. */
size_t help_line_len(const char *ptr)
{
int help_cols = (COLS > 24) ? COLS - 1 : 24;
/* Try to break the line at (COLS - 1) columns if we have more than
* 24 columns, and at 24 columns otherwise. */
ssize_t wrap_loc = break_line(ptr, help_cols, TRUE);
size_t retval = (wrap_loc < 0) ? 0 : wrap_loc;
size_t retval_save = retval;
/* Get the length of the entire line up to a null or a newline. */
while (*(ptr + retval) != '\0' && *(ptr + retval) != '\n')
retval += move_mbright(ptr + retval, 0);
/* If the entire line doesn't go more than one column beyond where
* we tried to break it, we should display it as-is. Otherwise, we
* should display it only up to the break. */
if (strnlenpt(ptr, retval) > help_cols + 1)
retval = retval_save;
return retval;
}
#endif /* !DISABLE_HELP */

647
src/move.c Normal file
View File

@ -0,0 +1,647 @@
/* $Id: move.c,v 1.67 2007/01/01 05:15:32 dolorous Exp $ */
/**************************************************************************
* move.c *
* *
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 Chris Allegretta *
* Copyright (C) 2005, 2006, 2007 David Lawrence Ramsey *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2, or (at your option) *
* any later version. *
* *
* This program is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software *
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA *
* 02110-1301, USA. *
* *
**************************************************************************/
#include "proto.h"
#include <string.h>
#include <ctype.h>
/* Move to the first line of the file. */
void do_first_line(void)
{
const filestruct *current_save = openfile->current;
size_t pww_save = openfile->placewewant;
openfile->current = openfile->fileage;
openfile->current_x = 0;
openfile->placewewant = 0;
edit_redraw(current_save, pww_save);
}
/* Move to the last line of the file. */
void do_last_line(void)
{
const filestruct *current_save = openfile->current;
size_t pww_save = openfile->placewewant;
openfile->current = openfile->filebot;
openfile->current_x = strlen(openfile->filebot->data);
openfile->placewewant = xplustabs();
openfile->current_y = editwinrows - 1;
edit_redraw(current_save, pww_save);
}
/* Move up one page. */
void do_page_up(void)
{
int i;
/* If there's less than a page of text left on the screen, put the
* cursor at the beginning of the first line of the file, and then
* update the edit window. */
if (openfile->current->lineno <= editwinrows - 2) {
do_first_line();
return;
}
/* If we're not in smooth scrolling mode, put the cursor at the
* beginning of the top line of the edit window, as Pico does. */
#ifndef NANO_TINY
if (!ISSET(SMOOTH_SCROLL)) {
#endif
openfile->current = openfile->edittop;
openfile->placewewant = 0;
#ifndef NANO_TINY
}
#endif
for (i = editwinrows - 2; i > 0 && openfile->current !=
openfile->fileage; i--)
openfile->current = openfile->current->prev;
openfile->current_x = actual_x(openfile->current->data,
openfile->placewewant);
/* Scroll the edit window up a page. */
edit_scroll(UP_DIR, editwinrows - 2);
}
/* Move down one page. */
void do_page_down(void)
{
int i;
/* If there's less than a page of text left on the screen, put the
* cursor at the beginning of the last line of the file, and then
* update the edit window. */
if (openfile->current->lineno + editwinrows - 2 >=
openfile->filebot->lineno) {
do_last_line();
return;
}
/* If we're not in smooth scrolling mode, put the cursor at the
* beginning of the top line of the edit window, as Pico does. */
#ifndef NANO_TINY
if (!ISSET(SMOOTH_SCROLL)) {
#endif
openfile->current = openfile->edittop;
openfile->placewewant = 0;
#ifndef NANO_TINY
}
#endif
for (i = editwinrows - 2; i > 0 && openfile->current !=
openfile->filebot; i--)
openfile->current = openfile->current->next;
openfile->current_x = actual_x(openfile->current->data,
openfile->placewewant);
/* Scroll the edit window down a page. */
edit_scroll(DOWN_DIR, editwinrows - 2);
}
#ifndef DISABLE_JUSTIFY
/* Move up to the beginning of the last beginning-of-paragraph line
* before the current line. If allow_update is TRUE, update the screen
* afterwards. */
void do_para_begin(bool allow_update)
{
const filestruct *current_save = openfile->current;
const size_t pww_save = openfile->placewewant;
if (openfile->current != openfile->fileage) {
do {
openfile->current = openfile->current->prev;
openfile->current_y--;
} while (!begpar(openfile->current));
}
openfile->current_x = 0;
openfile->placewewant = 0;
if (allow_update)
edit_redraw(current_save, pww_save);
}
/* Move up to the beginning of the last beginning-of-paragraph line
* before the current line, and update the screen afterwards. */
void do_para_begin_void(void)
{
do_para_begin(TRUE);
}
/* Move down to the beginning of the last line of the current paragraph.
* Then move down one line farther if there is such a line, or to the
* end of the current line if not. If allow_update is TRUE, update the
* screen afterwards. A line is the last line of a paragraph if it is
* in a paragraph, and the next line either is the beginning line of a
* paragraph or isn't in a paragraph. */
void do_para_end(bool allow_update)
{
const filestruct *const current_save = openfile->current;
const size_t pww_save = openfile->placewewant;
while (openfile->current != openfile->filebot &&
!inpar(openfile->current))
openfile->current = openfile->current->next;
while (openfile->current != openfile->filebot &&
inpar(openfile->current->next) &&
!begpar(openfile->current->next)) {
openfile->current = openfile->current->next;
openfile->current_y++;
}
if (openfile->current != openfile->filebot) {
openfile->current = openfile->current->next;
openfile->current_x = 0;
openfile->placewewant = 0;
} else {
openfile->current_x = strlen(openfile->current->data);
openfile->placewewant = xplustabs();
}
if (allow_update)
edit_redraw(current_save, pww_save);
}
/* Move down to the beginning of the last line of the current paragraph.
* Then move down one line farther if there is such a line, or to the
* end of the current line if not, and update the screen afterwards. */
void do_para_end_void(void)
{
do_para_end(TRUE);
}
#endif /* !DISABLE_JUSTIFY */
#ifndef NANO_TINY
/* Move to the next word in the file. If allow_punct is TRUE, treat
* punctuation as part of a word. If allow_update is TRUE, update the
* screen afterwards. Return TRUE if we started on a word, and FALSE
* otherwise. */
bool do_next_word(bool allow_punct, bool allow_update)
{
size_t pww_save = openfile->placewewant;
const filestruct *current_save = openfile->current;
char *char_mb;
int char_mb_len;
bool end_line = FALSE, started_on_word = FALSE;
assert(openfile->current != NULL && openfile->current->data != NULL);
char_mb = charalloc(mb_cur_max());
/* Move forward until we find the character after the last letter of
* the current word. */
while (!end_line) {
char_mb_len = parse_mbchar(openfile->current->data +
openfile->current_x, char_mb, NULL);
/* If we've found it, stop moving forward through the current
* line. */
if (!is_word_mbchar(char_mb, allow_punct))
break;
/* If we haven't found it, then we've started on a word, so set
* started_on_word to TRUE. */
started_on_word = TRUE;
if (openfile->current->data[openfile->current_x] == '\0')
end_line = TRUE;
else
openfile->current_x += char_mb_len;
}
/* Move forward until we find the first letter of the next word. */
if (openfile->current->data[openfile->current_x] == '\0')
end_line = TRUE;
else
openfile->current_x += char_mb_len;
for (; openfile->current != NULL;
openfile->current = openfile->current->next) {
while (!end_line) {
char_mb_len = parse_mbchar(openfile->current->data +
openfile->current_x, char_mb, NULL);
/* If we've found it, stop moving forward through the
* current line. */
if (is_word_mbchar(char_mb, allow_punct))
break;
if (openfile->current->data[openfile->current_x] == '\0')
end_line = TRUE;
else
openfile->current_x += char_mb_len;
}
/* If we've found it, stop moving forward to the beginnings of
* subsequent lines. */
if (!end_line)
break;
if (openfile->current != openfile->filebot) {
end_line = FALSE;
openfile->current_x = 0;
}
}
free(char_mb);
/* If we haven't found it, move to the end of the file. */
if (openfile->current == NULL)
openfile->current = openfile->filebot;
openfile->placewewant = xplustabs();
/* If allow_update is TRUE, update the screen. */
if (allow_update)
edit_redraw(current_save, pww_save);
/* Return whether we started on a word. */
return started_on_word;
}
/* Move to the next word in the file, treating punctuation as part of a
* word if the WORD_BOUNDS flag is set, and update the screen
* afterwards. */
void do_next_word_void(void)
{
do_next_word(ISSET(WORD_BOUNDS), TRUE);
}
/* Move to the previous word in the file. If allow_punct is TRUE, treat
* punctuation as part of a word. If allow_update is TRUE, update the
* screen afterwards. Return TRUE if we started on a word, and FALSE
* otherwise. */
bool do_prev_word(bool allow_punct, bool allow_update)
{
size_t pww_save = openfile->placewewant;
const filestruct *current_save = openfile->current;
char *char_mb;
int char_mb_len;
bool begin_line = FALSE, started_on_word = FALSE;
assert(openfile->current != NULL && openfile->current->data != NULL);
char_mb = charalloc(mb_cur_max());
/* Move backward until we find the character before the first letter
* of the current word. */
while (!begin_line) {
char_mb_len = parse_mbchar(openfile->current->data +
openfile->current_x, char_mb, NULL);
/* If we've found it, stop moving backward through the current
* line. */
if (!is_word_mbchar(char_mb, allow_punct))
break;
/* If we haven't found it, then we've started on a word, so set
* started_on_word to TRUE. */
started_on_word = TRUE;
if (openfile->current_x == 0)
begin_line = TRUE;
else
openfile->current_x = move_mbleft(openfile->current->data,
openfile->current_x);
}
/* Move backward until we find the last letter of the previous
* word. */
if (openfile->current_x == 0)
begin_line = TRUE;
else
openfile->current_x = move_mbleft(openfile->current->data,
openfile->current_x);
for (; openfile->current != NULL;
openfile->current = openfile->current->prev) {
while (!begin_line) {
char_mb_len = parse_mbchar(openfile->current->data +
openfile->current_x, char_mb, NULL);
/* If we've found it, stop moving backward through the
* current line. */
if (is_word_mbchar(char_mb, allow_punct))
break;
if (openfile->current_x == 0)
begin_line = TRUE;
else
openfile->current_x =
move_mbleft(openfile->current->data,
openfile->current_x);
}
/* If we've found it, stop moving backward to the ends of
* previous lines. */
if (!begin_line)
break;
if (openfile->current != openfile->fileage) {
begin_line = FALSE;
openfile->current_x = strlen(openfile->current->prev->data);
}
}
/* If we haven't found it, move to the beginning of the file. */
if (openfile->current == NULL)
openfile->current = openfile->fileage;
/* If we've found it, move backward until we find the character
* before the first letter of the previous word. */
else if (!begin_line) {
if (openfile->current_x == 0)
begin_line = TRUE;
else
openfile->current_x = move_mbleft(openfile->current->data,
openfile->current_x);
while (!begin_line) {
char_mb_len = parse_mbchar(openfile->current->data +
openfile->current_x, char_mb, NULL);
/* If we've found it, stop moving backward through the
* current line. */
if (!is_word_mbchar(char_mb, allow_punct))
break;
if (openfile->current_x == 0)
begin_line = TRUE;
else
openfile->current_x =
move_mbleft(openfile->current->data,
openfile->current_x);
}
/* If we've found it, move forward to the first letter of the
* previous word. */
if (!begin_line)
openfile->current_x += char_mb_len;
}
free(char_mb);
openfile->placewewant = xplustabs();
/* If allow_update is TRUE, update the screen. */
if (allow_update)
edit_redraw(current_save, pww_save);
/* Return whether we started on a word. */
return started_on_word;
}
/* Move to the previous word in the file, treating punctuation as part
* of a word if the WORD_BOUNDS flag is set, and update the screen
* afterwards. */
void do_prev_word_void(void)
{
do_prev_word(ISSET(WORD_BOUNDS), TRUE);
}
#endif /* !NANO_TINY */
/* Move to the beginning of the current line. If the SMART_HOME flag is
* set, move to the first non-whitespace character of the current line
* if we aren't already there, or to the beginning of the current line
* if we are. */
void do_home(void)
{
size_t pww_save = openfile->placewewant;
#ifndef NANO_TINY
if (ISSET(SMART_HOME)) {
size_t current_x_save = openfile->current_x;
openfile->current_x = indent_length(openfile->current->data);
if (openfile->current_x == current_x_save ||
openfile->current->data[openfile->current_x] == '\0')
openfile->current_x = 0;
openfile->placewewant = xplustabs();
} else {
#endif
openfile->current_x = 0;
openfile->placewewant = 0;
#ifndef NANO_TINY
}
#endif
if (need_horizontal_update(pww_save))
update_line(openfile->current, openfile->current_x);
}
/* Move to the end of the current line. */
void do_end(void)
{
size_t pww_save = openfile->placewewant;
openfile->current_x = strlen(openfile->current->data);
openfile->placewewant = xplustabs();
if (need_horizontal_update(pww_save))
update_line(openfile->current, openfile->current_x);
}
/* If scroll_only is FALSE, move up one line. If scroll_only is TRUE,
* scroll up one line without scrolling the cursor. */
void do_up(
#ifndef NANO_TINY
bool scroll_only
#else
void
#endif
)
{
/* If we're at the top of the file, or if scroll_only is TRUE and
* the top of the file is onscreen, get out. */
if (openfile->current == openfile->fileage
#ifndef NANO_TINY
|| (scroll_only && openfile->edittop == openfile->fileage)
#endif
)
return;
assert(openfile->current_y == openfile->current->lineno - openfile->edittop->lineno);
/* Move the current line of the edit window up. */
openfile->current = openfile->current->prev;
openfile->current_x = actual_x(openfile->current->data,
openfile->placewewant);
/* If scroll_only is FALSE and if we're on the first line of the
* edit window, scroll the edit window up one line if we're in
* smooth scrolling mode, or up half a page if we're not. If
* scroll_only is TRUE, scroll the edit window up one line
* unconditionally. */
if (openfile->current_y == 0
#ifndef NANO_TINY
|| scroll_only
#endif
)
edit_scroll(UP_DIR,
#ifndef NANO_TINY
(ISSET(SMOOTH_SCROLL) || scroll_only) ? 1 :
#endif
editwinrows / 2);
/* If we're below the first line of the edit window, update the
* line we were on before and the line we're on now. The former
* needs to be redrawn if we're not on the first page, and the
* latter needs to be drawn unconditionally. */
if (openfile->current_y > 0) {
if (need_vertical_update(0))
update_line(openfile->current->next, 0);
update_line(openfile->current, openfile->current_x);
}
}
/* Move up one line. */
void do_up_void(void)
{
do_up(
#ifndef NANO_TINY
FALSE
#endif
);
}
#ifndef NANO_TINY
/* Scroll up one line without scrolling the cursor. */
void do_scroll_up(void)
{
do_up(TRUE);
}
#endif
/* If scroll_only is FALSE, move down one line. If scroll_only is TRUE,
* scroll down one line without scrolling the cursor. */
void do_down(
#ifndef NANO_TINY
bool scroll_only
#else
void
#endif
)
{
/* If we're at the bottom of the file, get out. */
if (openfile->current == openfile->filebot)
return;
assert(openfile->current_y == openfile->current->lineno - openfile->edittop->lineno);
/* Move the current line of the edit window down. */
openfile->current = openfile->current->next;
openfile->current_x = actual_x(openfile->current->data,
openfile->placewewant);
/* If scroll_only is FALSE and if we're on the first line of the
* edit window, scroll the edit window down one line if we're in
* smooth scrolling mode, or down half a page if we're not. If
* scroll_only is TRUE, scroll the edit window down one line
* unconditionally. */
if (openfile->current_y == editwinrows - 1
#ifndef NANO_TINY
|| scroll_only
#endif
)
edit_scroll(DOWN_DIR,
#ifndef NANO_TINY
(ISSET(SMOOTH_SCROLL) || scroll_only) ? 1 :
#endif
editwinrows / 2);
/* If we're above the last line of the edit window, update the line
* we were on before and the line we're on now. The former needs to
* be redrawn if we're not on the first page, and the latter needs
* to be drawn unconditionally. */
if (openfile->current_y < editwinrows - 1) {
if (need_vertical_update(0))
update_line(openfile->current->prev, 0);
update_line(openfile->current, openfile->current_x);
}
}
/* Move down one line. */
void do_down_void(void)
{
do_down(
#ifndef NANO_TINY
FALSE
#endif
);
}
#ifndef NANO_TINY
/* Scroll down one line without scrolling the cursor. */
void do_scroll_down(void)
{
do_down(TRUE);
}
#endif
/* Move left one character. */
void do_left(void)
{
size_t pww_save = openfile->placewewant;
if (openfile->current_x > 0)
openfile->current_x = move_mbleft(openfile->current->data,
openfile->current_x);
else if (openfile->current != openfile->fileage) {
do_up_void();
openfile->current_x = strlen(openfile->current->data);
}
openfile->placewewant = xplustabs();
if (need_horizontal_update(pww_save))
update_line(openfile->current, openfile->current_x);
}
/* Move right one character. */
void do_right(void)
{
size_t pww_save = openfile->placewewant;
assert(openfile->current_x <= strlen(openfile->current->data));
if (openfile->current->data[openfile->current_x] != '\0')
openfile->current_x = move_mbright(openfile->current->data,
openfile->current_x);
else if (openfile->current != openfile->filebot) {
do_down_void();
openfile->current_x = 0;
}
openfile->placewewant = xplustabs();
if (need_horizontal_update(pww_save))
update_line(openfile->current, openfile->current_x);
}

2264
src/nano.c Normal file

File diff suppressed because it is too large Load Diff

631
src/nano.h Normal file
View File

@ -0,0 +1,631 @@
/* $Id: nano.h,v 1.188 2007/01/01 05:15:32 dolorous Exp $ */
/**************************************************************************
* nano.h *
* *
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 Chris Allegretta *
* Copyright (C) 2005, 2006, 2007 David Lawrence Ramsey *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2, or (at your option) *
* any later version. *
* *
* This program is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software *
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA *
* 02110-1301, USA. *
* *
**************************************************************************/
#ifndef NANO_H
#define NANO_H 1
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#ifdef __TANDEM
/* Tandem NonStop Kernel support. */
#include <floss.h>
#define NANO_ROOT_UID 65535
#else
#define NANO_ROOT_UID 0
#endif
#ifdef HAVE_LIMITS_H
#include <limits.h>
#endif
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
/* Macros for flags. */
#define SET(bit) flags |= bit
#define UNSET(bit) flags &= ~bit
#define ISSET(bit) ((flags & bit) != 0)
#define TOGGLE(bit) flags ^= bit
/* Macros for character allocation and more. */
#define charalloc(howmuch) (char *)nmalloc((howmuch) * sizeof(char))
#define charealloc(ptr, howmuch) (char *)nrealloc(ptr, (howmuch) * sizeof(char))
#define charmove(dest, src, n) memmove(dest, src, (n) * sizeof(char))
#define charset(dest, src, n) memset(dest, src, (n) * sizeof(char))
/* Set a default value for PATH_MAX if there isn't one. */
#ifndef PATH_MAX
#define PATH_MAX 4096
#endif
#ifdef USE_SLANG
/* Slang support. */
#include <slcurses.h>
/* Slang curses emulation brain damage, part 3: Slang doesn't define the
* curses equivalents of the Insert or Delete keys. */
#define KEY_DC SL_KEY_DELETE
#define KEY_IC SL_KEY_IC
/* Ncurses support. */
#elif defined(HAVE_NCURSES_H)
#include <ncurses.h>
#else
/* Curses support. */
#include <curses.h>
#endif /* CURSES_H */
#ifdef ENABLE_NLS
/* Native language support. */
#ifdef HAVE_LIBINTL_H
#include <libintl.h>
#endif
#define _(string) gettext(string)
#define P_(singular, plural, number) ngettext(singular, plural, number)
#else
#define _(string) (string)
#define P_(singular, plural, number) (number == 1 ? singular : plural)
#endif
#define gettext_noop(string) (string)
#define N_(string) gettext_noop(string)
/* Mark a string that will be sent to gettext() later. */
#include <stddef.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#ifdef HAVE_REGEX_H
#include <regex.h>
#endif
#ifndef NANO_TINY
#include <setjmp.h>
#endif
#include <assert.h>
/* If no vsnprintf(), use the version from glib 2.x. */
#ifndef HAVE_VSNPRINTF
#include <glib.h>
#define vsnprintf g_vsnprintf
#endif
/* If no isblank(), iswblank(), strcasecmp(), strncasecmp(),
* strcasestr(), strnlen(), getdelim(), or getline(), use the versions
* we have. */
#ifndef HAVE_ISBLANK
#define isblank nisblank
#endif
#ifndef HAVE_ISWBLANK
#define iswblank niswblank
#endif
#ifndef HAVE_STRCASECMP
#define strcasecmp nstrcasecmp
#endif
#ifndef HAVE_STRNCASECMP
#define strncasecmp nstrncasecmp
#endif
#ifndef HAVE_STRCASESTR
#define strcasestr nstrcasestr
#endif
#ifndef HAVE_STRNLEN
#define strnlen nstrnlen
#endif
#ifndef HAVE_GETDELIM
#define getdelim ngetdelim
#endif
#ifndef HAVE_GETLINE
#define getline ngetline
#endif
/* If we aren't using ncurses with mouse support, turn the mouse support
* off, as it's useless then. */
#ifndef NCURSES_MOUSE_VERSION
#define DISABLE_MOUSE 1
#endif
#if defined(DISABLE_WRAPPING) && defined(DISABLE_JUSTIFY)
#define DISABLE_WRAPJUSTIFY 1
#endif
/* Enumeration types. */
typedef enum {
NIX_FILE, DOS_FILE, MAC_FILE
} file_format;
typedef enum {
OVERWRITE, APPEND, PREPEND
} append_type;
typedef enum {
UP_DIR, DOWN_DIR
} scroll_dir;
typedef enum {
CENTER, NONE
} update_type;
/* Structure types. */
typedef struct filestruct {
char *data;
/* The text of this line. */
ssize_t lineno;
/* The number of this line. */
struct filestruct *next;
/* Next node. */
struct filestruct *prev;
/* Previous node. */
} filestruct;
typedef struct partition {
filestruct *fileage;
/* The top line of this portion of the file. */
filestruct *top_prev;
/* The line before the top line of this portion of the file. */
char *top_data;
/* The text before the beginning of the top line of this portion
* of the file. */
filestruct *filebot;
/* The bottom line of this portion of the file. */
filestruct *bot_next;
/* The line after the bottom line of this portion of the
* file. */
char *bot_data;
/* The text after the end of the bottom line of this portion of
* the file. */
} partition;
#ifdef ENABLE_COLOR
typedef struct colortype {
short fg;
/* This syntax's foreground color. */
short bg;
/* This syntax's background color. */
bool bright;
/* Is this color A_BOLD? */
bool icase;
/* Is this regex string case insensitive? */
int pairnum;
/* The color pair number used for this foreground color and
* background color. */
char *start_regex;
/* The start (or all) of the regex string. */
regex_t *start;
/* The compiled start (or all) of the regex string. */
char *end_regex;
/* The end (if any) of the regex string. */
regex_t *end;
/* The compiled end (if any) of the regex string. */
struct colortype *next;
/* Next set of colors. */
} colortype;
typedef struct exttype {
char *ext_regex;
/* The extensions that match this syntax. */
regex_t *ext;
/* The compiled extensions that match this syntax. */
struct exttype *next;
/* Next set of extensions. */
} exttype;
typedef struct syntaxtype {
char *desc;
/* The name of this syntax. */
exttype *extensions;
/* The list of extensions that this syntax applies to. */
colortype *color;
/* The colors used in this syntax. */
struct syntaxtype *next;
/* Next syntax. */
} syntaxtype;
#endif /* ENABLE_COLOR */
typedef struct openfilestruct {
char *filename;
/* The current file's name. */
filestruct *fileage;
/* The current file's first line. */
filestruct *filebot;
/* The current file's last line. */
filestruct *edittop;
/* The current top of the edit window. */
filestruct *current;
/* The current file's current line. */
size_t totsize;
/* The current file's total number of characters. */
size_t current_x;
/* The current file's x-coordinate position. */
size_t placewewant;
/* The current file's place we want. */
ssize_t current_y;
/* The current file's y-coordinate position. */
bool modified;
/* Whether the current file has been modified. */
#ifndef NANO_TINY
bool mark_set;
/* Whether the mark is on in the current file. */
filestruct *mark_begin;
/* The current file's beginning marked line, if any. */
size_t mark_begin_x;
/* The current file's beginning marked line's x-coordinate
* position, if any. */
file_format fmt;
/* The current file's format. */
struct stat *current_stat;
/* The current file's stat. */
#endif
#ifdef ENABLE_COLOR
colortype *colorstrings;
/* The current file's associated colors. */
#endif
struct openfilestruct *next;
/* Next node. */
struct openfilestruct *prev;
/* Previous node. */
} openfilestruct;
typedef struct shortcut {
const char *desc;
/* The function's description, e.g. "Page Up". */
#ifndef DISABLE_HELP
const char *help;
/* The help file entry text for this function. */
bool blank_after;
/* Whether there should be a blank line after the help entry
* text for this function. */
#endif
/* Note: Key values that aren't used should be set to
* NANO_NO_KEY. */
int ctrlval;
/* The special sentinel key or control key we want bound, if
* any. */
int metaval;
/* The meta key we want bound, if any. */
int funcval;
/* The function key we want bound, if any. */
int miscval;
/* The other meta key we want bound, if any. */
bool viewok;
/* Is this function allowed when in view mode? */
void (*func)(void);
/* The function to call when we get this key. */
struct shortcut *next;
/* Next shortcut. */
} shortcut;
#ifndef NANO_TINY
typedef struct toggle {
int val;
/* The sequence to toggle the key. We should only need one. */
const char *desc;
/* The description of the toggle, e.g. "Cut to end"; we'll
* append Enabled or Disabled to it. */
#ifndef DISABLE_HELP
bool blank_after;
/* Whether there should be a blank line after the description of
* the toggle. */
#endif
long flag;
/* Which flag actually gets toggled. */
struct toggle *next;
/* Next toggle. */
} toggle;
#endif
#ifdef ENABLE_NANORC
typedef struct rcoption {
const char *name;
/* The name of the rcfile option. */
long flag;
/* The flag associated with it, if any. */
} rcoption;
#endif
/* Bitwise flags so that we can save space (or, more correctly, not
* waste it). */
#define CASE_SENSITIVE (1<<0)
#define CONST_UPDATE (1<<1)
#define NO_HELP (1<<2)
#define NOFOLLOW_SYMLINKS (1<<3)
#define SUSPEND (1<<4)
#define NO_WRAP (1<<5)
#define AUTOINDENT (1<<6)
#define VIEW_MODE (1<<7)
#define USE_MOUSE (1<<8)
#define USE_REGEXP (1<<9)
#define TEMP_FILE (1<<10)
#define CUT_TO_END (1<<11)
#define BACKWARDS_SEARCH (1<<12)
#define MULTIBUFFER (1<<13)
#define SMOOTH_SCROLL (1<<14)
#define REBIND_DELETE (1<<15)
#define REBIND_KEYPAD (1<<16)
#define NO_CONVERT (1<<17)
#define BACKUP_FILE (1<<18)
#define NO_COLOR_SYNTAX (1<<19)
#define PRESERVE (1<<20)
#define HISTORYLOG (1<<21)
#define RESTRICTED (1<<22)
#define SMART_HOME (1<<23)
#define WHITESPACE_DISPLAY (1<<24)
#define MORE_SPACE (1<<25)
#define TABS_TO_SPACES (1<<26)
#define QUICK_BLANK (1<<27)
#define WORD_BOUNDS (1<<28)
#define NO_NEWLINES (1<<29)
#define BOLD_TEXT (1<<30)
/* Control key sequences. Changing these would be very, very bad. */
#define NANO_CONTROL_SPACE 0
#define NANO_CONTROL_A 1
#define NANO_CONTROL_B 2
#define NANO_CONTROL_C 3
#define NANO_CONTROL_D 4
#define NANO_CONTROL_E 5
#define NANO_CONTROL_F 6
#define NANO_CONTROL_G 7
#define NANO_CONTROL_H 8
#define NANO_CONTROL_I 9
#define NANO_CONTROL_J 10
#define NANO_CONTROL_K 11
#define NANO_CONTROL_L 12
#define NANO_CONTROL_M 13
#define NANO_CONTROL_N 14
#define NANO_CONTROL_O 15
#define NANO_CONTROL_P 16
#define NANO_CONTROL_Q 17
#define NANO_CONTROL_R 18
#define NANO_CONTROL_S 19
#define NANO_CONTROL_T 20
#define NANO_CONTROL_U 21
#define NANO_CONTROL_V 22
#define NANO_CONTROL_W 23
#define NANO_CONTROL_X 24
#define NANO_CONTROL_Y 25
#define NANO_CONTROL_Z 26
#define NANO_CONTROL_3 27
#define NANO_CONTROL_4 28
#define NANO_CONTROL_5 29
#define NANO_CONTROL_6 30
#define NANO_CONTROL_7 31
#define NANO_CONTROL_8 127
/* Meta key sequences. */
#define NANO_META_SPACE ' '
#define NANO_META_LPARENTHESIS '('
#define NANO_META_RPARENTHESIS ')'
#define NANO_META_PLUS '+'
#define NANO_META_COMMA ','
#define NANO_META_MINUS '-'
#define NANO_META_PERIOD '.'
#define NANO_META_SLASH '/'
#define NANO_META_0 '0'
#define NANO_META_6 '6'
#define NANO_META_9 '9'
#define NANO_META_LCARET '<'
#define NANO_META_EQUALS '='
#define NANO_META_RCARET '>'
#define NANO_META_QUESTION '?'
#define NANO_META_BACKSLASH '\\'
#define NANO_META_RBRACKET ']'
#define NANO_META_CARET '^'
#define NANO_META_UNDERSCORE '_'
#define NANO_META_A 'a'
#define NANO_META_B 'b'
#define NANO_META_C 'c'
#define NANO_META_D 'd'
#define NANO_META_E 'e'
#define NANO_META_F 'f'
#define NANO_META_G 'g'
#define NANO_META_H 'h'
#define NANO_META_I 'i'
#define NANO_META_J 'j'
#define NANO_META_K 'k'
#define NANO_META_L 'l'
#define NANO_META_M 'm'
#define NANO_META_N 'n'
#define NANO_META_O 'o'
#define NANO_META_P 'p'
#define NANO_META_Q 'q'
#define NANO_META_R 'r'
#define NANO_META_S 's'
#define NANO_META_T 't'
#define NANO_META_U 'u'
#define NANO_META_V 'v'
#define NANO_META_W 'w'
#define NANO_META_X 'x'
#define NANO_META_Y 'y'
#define NANO_META_Z 'z'
#define NANO_META_LCURLYBRACKET '{'
#define NANO_META_PIPE '|'
#define NANO_META_RCURLYBRACKET '}'
/* Some semi-changeable keybindings; don't play with these unless you're
* sure you know what you're doing. Assume ERR is defined as -1. */
/* No key at all. */
#define NANO_NO_KEY -2
/* Normal keys. */
#define NANO_XON_KEY NANO_CONTROL_Q
#define NANO_XOFF_KEY NANO_CONTROL_S
#define NANO_CANCEL_KEY NANO_CONTROL_C
#define NANO_EXIT_KEY NANO_CONTROL_X
#define NANO_EXIT_FKEY KEY_F(2)
#define NANO_INSERTFILE_KEY NANO_CONTROL_R
#define NANO_INSERTFILE_FKEY KEY_F(5)
#define NANO_TOOTHERINSERT_KEY NANO_CONTROL_X
#define NANO_WRITEOUT_KEY NANO_CONTROL_O
#define NANO_WRITEOUT_FKEY KEY_F(3)
#define NANO_GOTOLINE_KEY NANO_CONTROL_7
#define NANO_GOTOLINE_FKEY KEY_F(13)
#define NANO_GOTOLINE_METAKEY NANO_META_G
#define NANO_GOTODIR_KEY NANO_CONTROL_7
#define NANO_GOTODIR_FKEY KEY_F(13)
#define NANO_GOTODIR_METAKEY NANO_META_G
#define NANO_TOGOTOLINE_KEY NANO_CONTROL_T
#define NANO_HELP_KEY NANO_CONTROL_G
#define NANO_HELP_FKEY KEY_F(1)
#define NANO_WHEREIS_KEY NANO_CONTROL_W
#define NANO_WHEREIS_FKEY KEY_F(6)
#define NANO_WHEREIS_NEXT_KEY NANO_META_W
#define NANO_WHEREIS_NEXT_FKEY KEY_F(16)
#define NANO_TOOTHERWHEREIS_KEY NANO_CONTROL_T
#define NANO_REGEXP_KEY NANO_META_R
#define NANO_REPLACE_KEY NANO_CONTROL_4
#define NANO_REPLACE_FKEY KEY_F(14)
#define NANO_REPLACE_METAKEY NANO_META_R
#define NANO_TOOTHERSEARCH_KEY NANO_CONTROL_R
#define NANO_PREVPAGE_KEY NANO_CONTROL_Y
#define NANO_PREVPAGE_FKEY KEY_F(7)
#define NANO_NEXTPAGE_KEY NANO_CONTROL_V
#define NANO_NEXTPAGE_FKEY KEY_F(8)
#define NANO_CUT_KEY NANO_CONTROL_K
#define NANO_CUT_FKEY KEY_F(9)
#define NANO_COPY_KEY NANO_META_CARET
#define NANO_COPY_METAKEY NANO_META_6
#define NANO_UNCUT_KEY NANO_CONTROL_U
#define NANO_UNCUT_FKEY KEY_F(10)
#define NANO_CURSORPOS_KEY NANO_CONTROL_C
#define NANO_CURSORPOS_FKEY KEY_F(11)
#define NANO_SPELL_KEY NANO_CONTROL_T
#define NANO_SPELL_FKEY KEY_F(12)
#define NANO_FIRSTLINE_KEY NANO_PREVPAGE_KEY
#define NANO_FIRSTLINE_FKEY NANO_PREVPAGE_FKEY
#define NANO_FIRSTLINE_METAKEY NANO_META_BACKSLASH
#define NANO_FIRSTLINE_METAKEY2 NANO_META_PIPE
#define NANO_FIRSTFILE_KEY NANO_FIRSTLINE_KEY
#define NANO_FIRSTFILE_FKEY NANO_FIRSTLINE_FKEY
#define NANO_FIRSTFILE_METAKEY NANO_FIRSTLINE_METAKEY
#define NANO_FIRSTFILE_METAKEY2 NANO_FIRSTLINE_METAKEY2
#define NANO_LASTLINE_KEY NANO_NEXTPAGE_KEY
#define NANO_LASTLINE_FKEY NANO_NEXTPAGE_FKEY
#define NANO_LASTLINE_METAKEY NANO_META_SLASH
#define NANO_LASTLINE_METAKEY2 NANO_META_QUESTION
#define NANO_LASTFILE_KEY NANO_LASTLINE_KEY
#define NANO_LASTFILE_FKEY NANO_LASTLINE_FKEY
#define NANO_LASTFILE_METAKEY NANO_LASTLINE_METAKEY
#define NANO_LASTFILE_METAKEY2 NANO_LASTLINE_METAKEY2
#define NANO_REFRESH_KEY NANO_CONTROL_L
#define NANO_JUSTIFY_KEY NANO_CONTROL_J
#define NANO_JUSTIFY_FKEY KEY_F(4)
#define NANO_UNJUSTIFY_KEY NANO_UNCUT_KEY
#define NANO_UNJUSTIFY_FKEY NANO_UNCUT_FKEY
#define NANO_PREVLINE_KEY NANO_CONTROL_P
#define NANO_NEXTLINE_KEY NANO_CONTROL_N
#define NANO_FORWARD_KEY NANO_CONTROL_F
#define NANO_BACK_KEY NANO_CONTROL_B
#define NANO_MARK_KEY NANO_CONTROL_6
#define NANO_MARK_METAKEY NANO_META_A
#define NANO_MARK_FKEY KEY_F(15)
#define NANO_HOME_KEY NANO_CONTROL_A
#define NANO_END_KEY NANO_CONTROL_E
#define NANO_DELETE_KEY NANO_CONTROL_D
#define NANO_BACKSPACE_KEY NANO_CONTROL_H
#define NANO_TAB_KEY NANO_CONTROL_I
#define NANO_INDENT_KEY NANO_META_RCURLYBRACKET
#define NANO_UNINDENT_KEY NANO_META_LCURLYBRACKET
#define NANO_SUSPEND_KEY NANO_CONTROL_Z
#define NANO_ENTER_KEY NANO_CONTROL_M
#define NANO_TOFILES_KEY NANO_CONTROL_T
#define NANO_APPEND_KEY NANO_META_A
#define NANO_PREPEND_KEY NANO_META_P
#define NANO_PREVFILE_KEY NANO_META_LCARET
#define NANO_PREVFILE_METAKEY NANO_META_COMMA
#define NANO_NEXTFILE_KEY NANO_META_RCARET
#define NANO_NEXTFILE_METAKEY NANO_META_PERIOD
#define NANO_BRACKET_KEY NANO_META_RBRACKET
#define NANO_NEXTWORD_KEY NANO_CONTROL_SPACE
#define NANO_PREVWORD_KEY NANO_META_SPACE
#define NANO_WORDCOUNT_KEY NANO_META_D
#define NANO_SCROLLUP_KEY NANO_META_MINUS
#define NANO_SCROLLDOWN_KEY NANO_META_PLUS
#define NANO_SCROLLUP_METAKEY NANO_META_UNDERSCORE
#define NANO_SCROLLDOWN_METAKEY NANO_META_EQUALS
#define NANO_CUTTILLEND_METAKEY NANO_META_T
#define NANO_PARABEGIN_KEY NANO_CONTROL_W
#define NANO_PARABEGIN_METAKEY NANO_META_LPARENTHESIS
#define NANO_PARABEGIN_METAKEY2 NANO_META_9
#define NANO_PARAEND_KEY NANO_CONTROL_O
#define NANO_PARAEND_METAKEY NANO_META_RPARENTHESIS
#define NANO_PARAEND_METAKEY2 NANO_META_0
#define NANO_FULLJUSTIFY_KEY NANO_CONTROL_U
#define NANO_FULLJUSTIFY_METAKEY NANO_META_J
#define NANO_VERBATIM_KEY NANO_META_V
/* Toggles do not exist if NANO_TINY is defined. */
#ifndef NANO_TINY
/* No toggle at all. */
#define TOGGLE_NO_KEY -2
/* Normal toggles. */
#define TOGGLE_NOHELP_KEY NANO_META_X
#define TOGGLE_CONST_KEY NANO_META_C
#define TOGGLE_MORESPACE_KEY NANO_META_O
#define TOGGLE_SMOOTH_KEY NANO_META_S
#define TOGGLE_WHITESPACE_KEY NANO_META_P
#define TOGGLE_SYNTAX_KEY NANO_META_Y
#define TOGGLE_SMARTHOME_KEY NANO_META_H
#define TOGGLE_AUTOINDENT_KEY NANO_META_I
#define TOGGLE_CUTTOEND_KEY NANO_META_K
#define TOGGLE_WRAP_KEY NANO_META_L
#define TOGGLE_TABSTOSPACES_KEY NANO_META_Q
#define TOGGLE_BACKUP_KEY NANO_META_B
#define TOGGLE_MULTIBUFFER_KEY NANO_META_F
#define TOGGLE_MOUSE_KEY NANO_META_M
#define TOGGLE_NOCONVERT_KEY NANO_META_N
#define TOGGLE_SUSPEND_KEY NANO_META_Z
#define TOGGLE_CASE_KEY NANO_META_C
#define TOGGLE_BACKWARDS_KEY NANO_META_B
#define TOGGLE_DOS_KEY NANO_META_D
#define TOGGLE_MAC_KEY NANO_META_M
#endif /* !NANO_TINY */
#define VIEW TRUE
#define NOVIEW FALSE
/* The maximum number of entries displayed in the main shortcut list. */
#define MAIN_VISIBLE 12
/* The minimum editor window columns and rows required for nano to work
* correctly. */
#define MIN_EDITOR_COLS 4
#define MIN_EDITOR_ROWS 1
/* The default number of characters from the end of the line where
* wrapping occurs. */
#define CHARS_FROM_EOL 8
/* The default width of a tab in spaces. */
#define WIDTH_OF_TAB 8
/* The maximum number of search/replace history strings saved, not
* counting the blank lines at their ends. */
#define MAX_SEARCH_HISTORY 100
/* The maximum number of bytes buffered at one time. */
#define MAX_BUF_SIZE 128
#endif /* !NANO_H */

1385
src/prompt.c Normal file

File diff suppressed because it is too large Load Diff

793
src/proto.h Normal file
View File

@ -0,0 +1,793 @@
/* $Id: proto.h,v 1.372 2007/01/11 21:36:29 dolorous Exp $ */
/**************************************************************************
* proto.h *
* *
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 Chris Allegretta *
* Copyright (C) 2005, 2006, 2007 David Lawrence Ramsey *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2, or (at your option) *
* any later version. *
* *
* This program is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software *
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA *
* 02110-1301, USA. *
* *
**************************************************************************/
#ifndef PROTO_H
#define PROTO_H 1
#include "nano.h"
/* All external variables. See global.c for their descriptions. */
#ifndef NANO_TINY
extern sigjmp_buf jump_buf;
extern bool jump_buf_main;
#endif
#ifndef DISABLE_WRAPJUSTIFY
extern ssize_t fill;
extern ssize_t wrap_at;
#endif
extern char *last_search;
extern char *last_replace;
extern long flags;
extern WINDOW *topwin;
extern WINDOW *edit;
extern WINDOW *bottomwin;
extern int editwinrows;
extern filestruct *cutbuffer;
#ifndef DISABLE_JUSTIFY
extern filestruct *jusbuffer;
#endif
extern partition *filepart;
extern openfilestruct *openfile;
#ifndef NANO_TINY
extern char *matchbrackets;
#endif
#if !defined(NANO_TINY) && defined(ENABLE_NANORC)
extern char *whitespace;
extern int whitespace_len[2];
#endif
#ifndef DISABLE_JUSTIFY
extern char *punct;
extern char *brackets;
extern char *quotestr;
#ifdef HAVE_REGEX_H
extern regex_t quotereg;
extern int quoterc;
extern char *quoteerr;
#else
extern size_t quotelen;
#endif
#endif
extern char *answer;
extern ssize_t tabsize;
#ifndef NANO_TINY
extern char *backup_dir;
#endif
#ifndef DISABLE_OPERATINGDIR
extern char *operating_dir;
extern char *full_operating_dir;
#endif
#ifndef DISABLE_SPELLER
extern char *alt_speller;
#endif
extern shortcut *main_list;
extern shortcut *whereis_list;
extern shortcut *replace_list;
extern shortcut *replace_list_2;
extern shortcut *gotoline_list;
extern shortcut *writefile_list;
extern shortcut *insertfile_list;
#ifndef NANO_TINY
extern shortcut *extcmd_list;
#endif
#ifndef DISABLE_HELP
extern shortcut *help_list;
#endif
#ifndef DISABLE_SPELLER
extern shortcut *spell_list;
#endif
#ifndef DISABLE_BROWSER
extern shortcut *browser_list;
extern shortcut *whereis_file_list;
extern shortcut *gotodir_list;
#endif
#ifdef ENABLE_COLOR
extern syntaxtype *syntaxes;
extern char *syntaxstr;
#endif
extern const shortcut *currshortcut;
#ifndef NANO_TINY
extern toggle *toggles;
#endif
#ifndef NANO_TINY
extern filestruct *search_history;
extern filestruct *searchage;
extern filestruct *searchbot;
extern filestruct *replace_history;
extern filestruct *replaceage;
extern filestruct *replacebot;
#endif
#ifdef HAVE_REGEX_H
extern regex_t search_regexp;
extern regmatch_t regmatches[10];
#endif
extern int reverse_attr;
extern char *homedir;
/* All functions in browser.c. */
#ifndef DISABLE_BROWSER
char *do_browser(char *path, DIR *dir);
char *do_browse_from(const char *inpath);
void browser_init(const char *path, DIR *dir);
void parse_browser_input(int *kbinput, bool *meta_key, bool *func_key);
void browser_refresh(void);
bool browser_select_filename(const char *needle);
int filesearch_init(void);
bool findnextfile(bool no_sameline, size_t begin, const char *needle);
void findnextfile_wrap_reset(void);
void filesearch_abort(void);
void do_filesearch(void);
void do_fileresearch(void);
void do_first_file(void);
void do_last_file(void);
char *striponedir(const char *path);
#endif
/* All functions in chars.c. */
#ifdef ENABLE_UTF8
void utf8_init(void);
bool using_utf8(void);
#endif
#ifndef HAVE_ISBLANK
bool nisblank(int c);
#endif
#if !defined(HAVE_ISWBLANK) && defined(ENABLE_UTF8)
bool niswblank(wchar_t wc);
#endif
bool is_byte(int c);
bool is_alnum_mbchar(const char *c);
bool is_blank_mbchar(const char *c);
bool is_ascii_cntrl_char(int c);
bool is_cntrl_char(int c);
#ifdef ENABLE_UTF8
bool is_cntrl_wchar(wchar_t wc);
#endif
bool is_cntrl_mbchar(const char *c);
bool is_punct_mbchar(const char *c);
bool is_word_mbchar(const char *c, bool allow_punct);
char control_rep(char c);
#ifdef ENABLE_UTF8
wchar_t control_wrep(wchar_t c);
#endif
char *control_mbrep(const char *c, char *crep, int *crep_len);
char *mbrep(const char *c, char *crep, int *crep_len);
int mbwidth(const char *c);
int mb_cur_max(void);
char *make_mbchar(long chr, int *chr_mb_len);
int parse_mbchar(const char *buf, char *chr, size_t *col);
size_t move_mbleft(const char *buf, size_t pos);
size_t move_mbright(const char *buf, size_t pos);
#ifndef HAVE_STRCASECMP
int nstrcasecmp(const char *s1, const char *s2);
#endif
int mbstrcasecmp(const char *s1, const char *s2);
#ifndef HAVE_STRNCASECMP
int nstrncasecmp(const char *s1, const char *s2, size_t n);
#endif
int mbstrncasecmp(const char *s1, const char *s2, size_t n);
#ifndef HAVE_STRCASESTR
const char *nstrcasestr(const char *haystack, const char *needle);
#endif
const char *mbstrcasestr(const char *haystack, const char *needle);
#if !defined(NANO_TINY) || !defined(DISABLE_TABCOMP)
const char *revstrstr(const char *haystack, const char *needle, const
char *rev_start);
#endif
#ifndef NANO_TINY
const char *revstrcasestr(const char *haystack, const char *needle,
const char *rev_start);
const char *mbrevstrcasestr(const char *haystack, const char *needle,
const char *rev_start);
#endif
size_t mbstrlen(const char *s);
#ifndef HAVE_STRNLEN
size_t nstrnlen(const char *s, size_t maxlen);
#endif
size_t mbstrnlen(const char *s, size_t maxlen);
#if !defined(NANO_TINY) || !defined(DISABLE_JUSTIFY)
char *mbstrchr(const char *s, const char *c);
#endif
#ifndef NANO_TINY
char *mbstrpbrk(const char *s, const char *accept);
char *revstrpbrk(const char *s, const char *accept, const char
*rev_start);
char *mbrevstrpbrk(const char *s, const char *accept, const char
*rev_start);
#endif
#if defined(ENABLE_NANORC) && (!defined(NANO_TINY) || !defined(DISABLE_JUSTIFY))
bool has_blank_chars(const char *s);
bool has_blank_mbchars(const char *s);
#endif
#ifdef ENABLE_UTF8
bool is_valid_unicode(wchar_t wc);
#endif
#ifdef ENABLE_NANORC
bool is_valid_mbstring(const char *s);
#endif
/* All functions in color.c. */
#ifdef ENABLE_COLOR
void set_colorpairs(void);
void color_init(void);
void color_update(void);
#endif
/* All functions in cut.c. */
void cutbuffer_reset(void);
void cut_line(void);
#ifndef NANO_TINY
void cut_marked(void);
void cut_to_eol(void);
void cut_to_eof(void);
#endif
void do_cut_text(
#ifndef NANO_TINY
bool copy_text, bool cut_till_end
#else
void
#endif
);
void do_cut_text_void(void);
#ifndef NANO_TINY
void do_copy_text(void);
void do_cut_till_end(void);
#endif
void do_uncut_text(void);
/* All functions in files.c. */
void make_new_buffer(void);
void initialize_buffer(void);
void initialize_buffer_text(void);
void open_buffer(const char *filename);
#ifndef DISABLE_SPELLER
void replace_buffer(const char *filename);
#endif
void display_buffer(void);
#ifdef ENABLE_MULTIBUFFER
void switch_to_prevnext_buffer(bool next);
void switch_to_prev_buffer_void(void);
void switch_to_next_buffer_void(void);
bool close_buffer(void);
#endif
filestruct *read_line(char *buf, filestruct *prevnode, bool
*first_line_ins, size_t buf_len);
void read_file(FILE *f, const char *filename);
int open_file(const char *filename, bool newfie, FILE **f);
char *get_next_filename(const char *name, const char *suffix);
void do_insertfile(
#ifndef NANO_TINY
bool execute
#else
void
#endif
);
void do_insertfile_void(void);
char *get_full_path(const char *origpath);
char *check_writable_directory(const char *path);
char *safe_tempfile(FILE **f);
#ifndef DISABLE_OPERATINGDIR
void init_operating_dir(void);
bool check_operating_dir(const char *currpath, bool allow_tabcomp);
#endif
#ifndef NANO_TINY
void init_backup_dir(void);
#endif
int copy_file(FILE *inn, FILE *out);
bool write_file(const char *name, FILE *f_open, bool tmp, append_type
append, bool nonamechange);
#ifndef NANO_TINY
bool write_marked_file(const char *name, FILE *f_open, bool tmp,
append_type append);
#endif
bool do_writeout(bool exiting);
void do_writeout_void(void);
char *real_dir_from_tilde(const char *buf);
#if !defined(DISABLE_TABCOMP) || !defined(DISABLE_BROWSER)
int diralphasort(const void *va, const void *vb);
void free_chararray(char **array, size_t len);
#endif
#ifndef DISABLE_TABCOMP
bool is_dir(const char *buf);
char **username_tab_completion(const char *buf, size_t *num_matches,
size_t buflen);
char **cwd_tab_completion(const char *buf, bool allow_files, size_t
*num_matches, size_t buflen);
char *input_tab(char *buf, bool allow_files, size_t *place, bool
*lastwastab, void (*refresh_func)(void), bool *list);
#endif
const char *tail(const char *foo);
#if !defined(NANO_TINY) && defined(ENABLE_NANORC)
char *histfilename(void);
void load_history(void);
bool writehist(FILE *hist, filestruct *histhead);
void save_history(void);
#endif
/* All functions in global.c. */
size_t length_of_list(const shortcut *s);
#ifndef NANO_TINY
void toggle_init_one(int val
#ifndef DISABLE_HELP
, const char *desc, bool blank_after
#endif
, long flag);
void toggle_init(void);
#endif
void sc_init_one(shortcut **shortcutage, int ctrlval, const char *desc
#ifndef DISABLE_HELP
, const char *help, bool blank_after
#endif
, int metaval, int funcval, int miscval, bool view, void
(*func)(void));
void shortcut_init(bool unjustify);
void free_shortcutage(shortcut **shortcutage);
#ifdef DEBUG
void thanks_for_all_the_fish(void);
#endif
/* All functions in help.c. */
#ifndef DISABLE_HELP
void do_help(void (*refresh_func)(void));
void do_help_void(void);
#ifndef DISABLE_BROWSER
void do_browser_help(void);
#endif
void help_init(void);
void parse_help_input(int *kbinput, bool *meta_key, bool *func_key);
size_t help_line_len(const char *ptr);
#endif
/* All functions in move.c. */
void do_first_line(void);
void do_last_line(void);
void do_page_up(void);
void do_page_down(void);
#ifndef DISABLE_JUSTIFY
void do_para_begin(bool allow_update);
void do_para_begin_void(void);
void do_para_end(bool allow_update);
void do_para_end_void(void);
#endif
#ifndef NANO_TINY
bool do_next_word(bool allow_punct, bool allow_update);
void do_next_word_void(void);
bool do_prev_word(bool allow_punct, bool allow_update);
void do_prev_word_void(void);
#endif
void do_home(void);
void do_end(void);
void do_up(
#ifndef NANO_TINY
bool scroll_only
#else
void
#endif
);
void do_up_void(void);
#ifndef NANO_TINY
void do_scroll_up(void);
#endif
void do_down(
#ifndef NANO_TINY
bool scroll_only
#else
void
#endif
);
void do_down_void(void);
#ifndef NANO_TINY
void do_scroll_down(void);
#endif
void do_left(void);
void do_right(void);
/* All functions in nano.c. */
filestruct *make_new_node(filestruct *prevnode);
filestruct *copy_node(const filestruct *src);
void splice_node(filestruct *begin, filestruct *newnode, filestruct
*end);
void unlink_node(const filestruct *fileptr);
void delete_node(filestruct *fileptr);
filestruct *copy_filestruct(const filestruct *src);
void free_filestruct(filestruct *src);
void renumber(filestruct *fileptr);
partition *partition_filestruct(filestruct *top, size_t top_x,
filestruct *bot, size_t bot_x);
void unpartition_filestruct(partition **p);
void move_to_filestruct(filestruct **file_top, filestruct **file_bot,
filestruct *top, size_t top_x, filestruct *bot, size_t bot_x);
void copy_from_filestruct(filestruct *file_top, filestruct *file_bot);
openfilestruct *make_new_opennode(void);
void splice_opennode(openfilestruct *begin, openfilestruct *newnode,
openfilestruct *end);
void unlink_opennode(openfilestruct *fileptr);
void delete_opennode(openfilestruct *fileptr);
#ifdef DEBUG
void free_openfilestruct(openfilestruct *src);
#endif
void print_view_warning(void);
void finish(void);
void die(const char *msg, ...);
void die_save_file(const char *die_filename);
void window_init(void);
#ifndef DISABLE_MOUSE
void disable_mouse_support(void);
void enable_mouse_support(void);
void mouse_init(void);
#endif
void print_opt_full(const char *shortflag
#ifdef HAVE_GETOPT_LONG
, const char *longflag
#endif
, const char *desc);
void usage(void);
void version(void);
int no_more_space(void);
int no_help(void);
void nano_disabled_msg(void);
void do_exit(void);
void signal_init(void);
RETSIGTYPE handle_hupterm(int signal);
RETSIGTYPE do_suspend(int signal);
RETSIGTYPE do_continue(int signal);
#ifndef NANO_TINY
RETSIGTYPE handle_sigwinch(int signal);
void allow_pending_sigwinch(bool allow);
#endif
#ifndef NANO_TINY
void do_toggle(const toggle *which);
#endif
void disable_extended_io(void);
void disable_signals(void);
#ifndef NANO_TINY
void enable_signals(void);
#endif
void disable_flow_control(void);
void enable_flow_control(void);
void terminal_init(void);
int do_input(bool *meta_key, bool *func_key, bool *s_or_t, bool
*ran_func, bool *finished, bool allow_funcs);
#ifndef DISABLE_MOUSE
bool do_mouse(void);
#endif
void do_output(char *output, size_t output_len, bool allow_cntrls);
/* All functions in prompt.c. */
int do_statusbar_input(bool *meta_key, bool *func_key, bool *s_or_t,
bool *ran_func, bool *finished, bool allow_funcs, void
(*refresh_func)(void));
#ifndef DISABLE_MOUSE
bool do_statusbar_mouse(void);
#endif
void do_statusbar_output(char *output, size_t output_len, bool
*got_enter, bool allow_cntrls);
void do_statusbar_home(void);
void do_statusbar_end(void);
void do_statusbar_left(void);
void do_statusbar_right(void);
void do_statusbar_backspace(void);
void do_statusbar_delete(void);
void do_statusbar_cut_text(void);
#ifndef NANO_TINY
bool do_statusbar_next_word(bool allow_punct);
bool do_statusbar_prev_word(bool allow_punct);
#endif
void do_statusbar_verbatim_input(bool *got_enter);
#ifndef NANO_TINY
bool find_statusbar_bracket_match(bool reverse, const char
*bracket_set);
void do_statusbar_find_bracket(void);
#endif
size_t statusbar_xplustabs(void);
size_t get_statusbar_page_start(size_t start_col, size_t column);
void reset_statusbar_cursor(void);
void update_statusbar_line(const char *curranswer, size_t index);
bool need_statusbar_horizontal_update(size_t pww_save);
void total_statusbar_refresh(void (*refresh_func)(void));
int get_prompt_string(bool allow_tabs,
#ifndef DISABLE_TABCOMP
bool allow_files,
#endif
const char *curranswer,
#ifndef NANO_TINY
filestruct **history_list,
#endif
void (*refresh_func)(void), const shortcut *s
#ifndef DISABLE_TABCOMP
, bool *list
#endif
);
int do_prompt(bool allow_tabs,
#ifndef DISABLE_TABCOMP
bool allow_files,
#endif
const shortcut *s, const char *curranswer,
#ifndef NANO_TINY
filestruct **history_list,
#endif
void (*refresh_func)(void), const char *msg, ...);
void do_prompt_abort(void);
int do_yesno_prompt(bool all, const char *msg);
/* All functions in rcfile.c. */
#ifdef ENABLE_NANORC
void rcfile_error(const char *msg, ...);
char *parse_next_word(char *ptr);
char *parse_argument(char *ptr);
#ifdef ENABLE_COLOR
char *parse_next_regex(char *ptr);
bool nregcomp(const char *regex, int eflags);
void parse_syntax(char *ptr);
void parse_include(char *ptr);
short color_to_short(const char *colorname, bool *bright);
void parse_colors(char *ptr, bool icase);
#endif
void parse_rcfile(FILE *rcstream
#ifdef ENABLE_COLOR
, bool syntax_only
#endif
);
void do_rcfile(void);
#endif
/* All functions in search.c. */
#ifdef HAVE_REGEX_H
bool regexp_init(const char *regexp);
void regexp_cleanup(void);
#endif
void not_found_msg(const char *str);
void search_replace_abort(void);
void search_init_globals(void);
int search_init(bool replacing, bool use_answer);
bool findnextstr(
#ifndef DISABLE_SPELLER
bool whole_word,
#endif
bool no_sameline, const filestruct *begin, size_t begin_x, const
char *needle, size_t *needle_len);
void findnextstr_wrap_reset(void);
void do_search(void);
#ifndef NANO_TINY
void do_research(void);
#endif
#ifdef HAVE_REGEX_H
int replace_regexp(char *string, bool create);
#endif
char *replace_line(const char *needle);
ssize_t do_replace_loop(
#ifndef DISABLE_SPELLER
bool whole_word,
#endif
bool *canceled, const filestruct *real_current, size_t
*real_current_x, const char *needle);
void do_replace(void);
void do_gotolinecolumn(ssize_t line, ssize_t column, bool use_answer,
bool interactive, bool save_pos, bool allow_update);
void do_gotolinecolumn_void(void);
#ifndef DISABLE_SPELLER
void do_gotopos(ssize_t pos_line, size_t pos_x, ssize_t pos_y, size_t
pos_pww);
#endif
#ifndef NANO_TINY
bool find_bracket_match(bool reverse, const char *bracket_set);
void do_find_bracket(void);
#ifdef ENABLE_NANORC
bool history_has_changed(void);
#endif
void history_init(void);
void history_reset(const filestruct *h);
filestruct *find_history(const filestruct *h_start, const filestruct
*h_end, const char *s, size_t len);
void update_history(filestruct **h, const char *s);
char *get_history_older(filestruct **h);
char *get_history_newer(filestruct **h);
#ifndef DISABLE_TABCOMP
char *get_history_completion(filestruct **h, const char *s, size_t len);
#endif
#endif
/* All functions in text.c. */
#ifndef NANO_TINY
void do_mark(void);
#endif
void do_delete(void);
void do_backspace(void);
void do_tab(void);
#ifndef NANO_TINY
void do_indent(ssize_t cols);
void do_indent_void(void);
void do_unindent(void);
#endif
void do_enter(void);
#ifndef NANO_TINY
RETSIGTYPE cancel_command(int signal);
bool execute_command(const char *command);
#endif
#ifndef DISABLE_WRAPPING
void wrap_reset(void);
bool do_wrap(filestruct *line);
#endif
#if !defined(DISABLE_HELP) || !defined(DISABLE_WRAPJUSTIFY)
ssize_t break_line(const char *line, ssize_t goal
#ifndef DISABLE_HELP
, bool newline
#endif
);
#endif
#if !defined(NANO_TINY) || !defined(DISABLE_JUSTIFY)
size_t indent_length(const char *line);
#endif
#ifndef DISABLE_JUSTIFY
void justify_format(filestruct *paragraph, size_t skip);
size_t quote_length(const char *line);
bool quotes_match(const char *a_line, size_t a_quote, const char
*b_line);
bool indents_match(const char *a_line, size_t a_indent, const char
*b_line, size_t b_indent);
bool begpar(const filestruct *const foo);
bool inpar(const filestruct *const foo);
void backup_lines(filestruct *first_line, size_t par_len);
bool find_paragraph(size_t *const quote, size_t *const par);
void do_justify(bool full_justify);
void do_justify_void(void);
void do_full_justify(void);
#endif
#ifndef DISABLE_SPELLER
bool do_int_spell_fix(const char *word);
const char *do_int_speller(const char *tempfile_name);
const char *do_alt_speller(char *tempfile_name);
void do_spell(void);
#endif
#ifndef NANO_TINY
void do_wordlinechar_count(void);
#endif
void do_verbatim_input(void);
/* All functions in utils.c. */
int digits(size_t n);
void get_homedir(void);
bool parse_num(const char *str, ssize_t *val);
bool parse_line_column(const char *str, ssize_t *line, ssize_t *column);
void align(char **str);
void null_at(char **data, size_t index);
void unsunder(char *str, size_t true_len);
void sunder(char *str);
#if !defined(NANO_TINY) && defined(ENABLE_NANORC)
#ifndef HAVE_GETLINE
ssize_t ngetline(char **lineptr, size_t *n, FILE *stream);
#endif
#ifndef HAVE_GETDELIM
ssize_t ngetdelim(char **lineptr, size_t *n, int delim, FILE *stream);
#endif
#endif
#ifdef HAVE_REGEX_H
bool regexp_bol_or_eol(const regex_t *preg, const char *string);
#endif
#ifndef DISABLE_SPELLER
bool is_whole_word(size_t pos, const char *buf, const char *word);
#endif
const char *strstrwrapper(const char *haystack, const char *needle,
const char *start);
void nperror(const char *s);
void *nmalloc(size_t howmuch);
void *nrealloc(void *ptr, size_t howmuch);
char *mallocstrncpy(char *dest, const char *src, size_t n);
char *mallocstrcpy(char *dest, const char *src);
char *mallocstrassn(char *dest, char *src);
size_t get_page_start(size_t column);
size_t xplustabs(void);
size_t actual_x(const char *s, size_t column);
size_t strnlenpt(const char *s, size_t maxlen);
size_t strlenpt(const char *s);
void new_magicline(void);
#ifndef NANO_TINY
void remove_magicline(void);
void mark_order(const filestruct **top, size_t *top_x, const filestruct
**bot, size_t *bot_x, bool *right_side_up);
#endif
size_t get_totsize(const filestruct *begin, const filestruct *end);
#ifdef DEBUG
void dump_filestruct(const filestruct *inptr);
void dump_filestruct_reverse(void);
#endif
/* All functions in winio.c. */
void get_key_buffer(WINDOW *win);
size_t get_key_buffer_len(void);
void unget_input(int *input, size_t input_len);
void unget_kbinput(int kbinput, bool meta_key, bool func_key);
int *get_input(WINDOW *win, size_t input_len);
int get_kbinput(WINDOW *win, bool *meta_key, bool *func_key);
int parse_kbinput(WINDOW *win, bool *meta_key, bool *func_key);
int get_escape_seq_kbinput(const int *seq, size_t seq_len);
int get_escape_seq_abcd(int kbinput);
int parse_escape_seq_kbinput(WINDOW *win, int kbinput);
int get_byte_kbinput(int kbinput);
#ifdef ENABLE_UTF8
long add_unicode_digit(int kbinput, long factor, long *uni);
long get_unicode_kbinput(int kbinput);
#endif
int get_control_kbinput(int kbinput);
void unparse_kbinput(char *output, size_t output_len);
int *get_verbatim_kbinput(WINDOW *win, size_t *kbinput_len);
int *parse_verbatim_kbinput(WINDOW *win, size_t *kbinput_len);
#ifndef DISABLE_MOUSE
bool get_mouseinput(int *mouse_x, int *mouse_y, bool allow_shortcuts);
#endif
const shortcut *get_shortcut(const shortcut *s_list, int *kbinput, bool
*meta_key, bool *func_key);
#ifndef NANO_TINY
const toggle *get_toggle(int kbinput, bool meta_key);
#endif
void blank_line(WINDOW *win, int y, int x, int n);
void blank_titlebar(void);
void blank_topbar(void);
void blank_edit(void);
void blank_statusbar(void);
void blank_bottombars(void);
void check_statusblank(void);
char *display_string(const char *buf, size_t start_col, size_t len, bool
dollars);
void titlebar(const char *path);
void set_modified(void);
void statusbar(const char *msg, ...);
void bottombars(const shortcut *s);
void onekey(const char *keystroke, const char *desc, size_t len);
void reset_cursor(void);
void edit_draw(const filestruct *fileptr, const char *converted, int
line, size_t start);
void update_line(const filestruct *fileptr, size_t index);
bool need_horizontal_update(size_t pww_save);
bool need_vertical_update(size_t pww_save);
void edit_scroll(scroll_dir direction, ssize_t nlines);
void edit_redraw(const filestruct *old_current, size_t pww_save);
void edit_refresh(void);
void edit_update(update_type location);
void total_redraw(void);
void total_refresh(void);
void display_main_list(void);
void do_cursorpos(bool constant);
void do_cursorpos_void(void);
void do_replace_highlight(bool highlight, const char *word);
#ifdef NANO_EXTRA
void do_credits(void);
#endif
#endif /* !PROTO_H */

932
src/rcfile.c Normal file
View File

@ -0,0 +1,932 @@
/* $Id: rcfile.c,v 1.122.2.1 2007/04/18 18:22:13 dolorous Exp $ */
/**************************************************************************
* rcfile.c *
* *
* Copyright (C) 2001, 2002, 2003, 2004 Chris Allegretta *
* Copyright (C) 2005, 2006, 2007 David Lawrence Ramsey *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2, or (at your option) *
* any later version. *
* *
* This program is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software *
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA *
* 02110-1301, USA. *
* *
**************************************************************************/
#include "proto.h"
#include <stdarg.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <ctype.h>
#ifdef ENABLE_NANORC
static const rcoption rcopts[] = {
{"boldtext", BOLD_TEXT},
#ifndef DISABLE_JUSTIFY
{"brackets", 0},
#endif
{"const", CONST_UPDATE},
#ifndef DISABLE_WRAPJUSTIFY
{"fill", 0},
#endif
#ifndef DISABLE_MOUSE
{"mouse", USE_MOUSE},
#endif
#ifdef ENABLE_MULTIBUFFER
{"multibuffer", MULTIBUFFER},
#endif
{"morespace", MORE_SPACE},
{"nofollow", NOFOLLOW_SYMLINKS},
{"nohelp", NO_HELP},
{"nonewlines", NO_NEWLINES},
#ifndef DISABLE_WRAPPING
{"nowrap", NO_WRAP},
#endif
#ifndef DISABLE_OPERATINGDIR
{"operatingdir", 0},
#endif
{"preserve", PRESERVE},
#ifndef DISABLE_JUSTIFY
{"punct", 0},
{"quotestr", 0},
#endif
{"rebinddelete", REBIND_DELETE},
{"rebindkeypad", REBIND_KEYPAD},
#ifdef HAVE_REGEX_H
{"regexp", USE_REGEXP},
#endif
#ifndef DISABLE_SPELLER
{"speller", 0},
#endif
{"suspend", SUSPEND},
{"tabsize", 0},
{"tempfile", TEMP_FILE},
{"view", VIEW_MODE},
#ifndef NANO_TINY
{"autoindent", AUTOINDENT},
{"backup", BACKUP_FILE},
{"backupdir", 0},
{"backwards", BACKWARDS_SEARCH},
{"casesensitive", CASE_SENSITIVE},
{"cut", CUT_TO_END},
{"historylog", HISTORYLOG},
{"matchbrackets", 0},
{"noconvert", NO_CONVERT},
{"quickblank", QUICK_BLANK},
{"smarthome", SMART_HOME},
{"smooth", SMOOTH_SCROLL},
{"tabstospaces", TABS_TO_SPACES},
{"whitespace", 0},
{"wordbounds", WORD_BOUNDS},
#endif
{NULL, 0}
};
static bool errors = FALSE;
/* Whether we got any errors while parsing an rcfile. */
static size_t lineno = 0;
/* If we did, the line number where the last error occurred. */
static char *nanorc = NULL;
/* The path to the rcfile we're parsing. */
#ifdef ENABLE_COLOR
static syntaxtype *endsyntax = NULL;
/* The end of the list of syntaxes. */
static colortype *endcolor = NULL;
/* The end of the color list for the current syntax. */
#endif
/* We have an error in some part of the rcfile. Print the error message
* on stderr, and then make the user hit Enter to continue starting
* nano. */
void rcfile_error(const char *msg, ...)
{
va_list ap;
fprintf(stderr, "\n");
if (lineno > 0) {
errors = TRUE;
fprintf(stderr, _("Error in %s on line %lu: "), nanorc, (unsigned long)lineno);
}
va_start(ap, msg);
vfprintf(stderr, _(msg), ap);
va_end(ap);
fprintf(stderr, "\n");
}
/* Parse the next word from the string, null-terminate it, and return
* a pointer to the first character after the null terminator. The
* returned pointer will point to '\0' if we hit the end of the line. */
char *parse_next_word(char *ptr)
{
while (!isblank(*ptr) && *ptr != '\0')
ptr++;
if (*ptr == '\0')
return ptr;
/* Null-terminate and advance ptr. */
*ptr++ = '\0';
while (isblank(*ptr))
ptr++;
return ptr;
}
/* Parse an argument, with optional quotes, after a keyword that takes
* one. If the next word starts with a ", we say that it ends with the
* last " of the line. Otherwise, we interpret it as usual, so that the
* arguments can contain "'s too. */
char *parse_argument(char *ptr)
{
const char *ptr_save = ptr;
char *last_quote = NULL;
assert(ptr != NULL);
if (*ptr != '"')
return parse_next_word(ptr);
do {
ptr++;
if (*ptr == '"')
last_quote = ptr;
} while (*ptr != '\0');
if (last_quote == NULL) {
if (*ptr == '\0')
ptr = NULL;
else
*ptr++ = '\0';
rcfile_error(N_("Argument '%s' has an unterminated \""), ptr_save);
} else {
*last_quote = '\0';
ptr = last_quote + 1;
}
if (ptr != NULL)
while (isblank(*ptr))
ptr++;
return ptr;
}
#ifdef ENABLE_COLOR
/* Parse the next regex string from the line at ptr, and return it. */
char *parse_next_regex(char *ptr)
{
assert(ptr != NULL);
/* Continue until the end of the line, or a " followed by a space, a
* blank character, or \0. */
while ((*ptr != '"' || (!isblank(*(ptr + 1)) &&
*(ptr + 1) != '\0')) && *ptr != '\0')
ptr++;
assert(*ptr == '"' || *ptr == '\0');
if (*ptr == '\0') {
rcfile_error(
N_("Regex strings must begin and end with a \" character"));
return NULL;
}
/* Null-terminate and advance ptr. */
*ptr++ = '\0';
while (isblank(*ptr))
ptr++;
return ptr;
}
/* Compile the regular expression regex to see if it's valid. Return
* TRUE if it is, or FALSE otherwise. */
bool nregcomp(const char *regex, int eflags)
{
regex_t preg;
int rc = regcomp(&preg, regex, REG_EXTENDED | eflags);
if (rc != 0) {
size_t len = regerror(rc, &preg, NULL, 0);
char *str = charalloc(len);
regerror(rc, &preg, str, len);
rcfile_error(N_("Bad regex \"%s\": %s"), regex, str);
free(str);
}
regfree(&preg);
return (rc == 0);
}
/* Parse the next syntax string from the line at ptr, and add it to the
* global list of color syntaxes. */
void parse_syntax(char *ptr)
{
const char *fileregptr = NULL, *nameptr = NULL;
syntaxtype *tmpsyntax;
exttype *endext = NULL;
/* The end of the extensions list for this syntax. */
assert(ptr != NULL);
if (*ptr == '\0') {
rcfile_error(N_("Missing syntax name"));
return;
}
if (*ptr != '"') {
rcfile_error(
N_("Regex strings must begin and end with a \" character"));
return;
}
ptr++;
nameptr = ptr;
ptr = parse_next_regex(ptr);
if (ptr == NULL)
return;
/* Search for a duplicate syntax name. If we find one, free it, so
* that we always use the last syntax with a given name. */
for (tmpsyntax = syntaxes; tmpsyntax != NULL;
tmpsyntax = tmpsyntax->next) {
if (strcmp(nameptr, tmpsyntax->desc) == 0) {
syntaxtype *prev_syntax = tmpsyntax;
tmpsyntax = tmpsyntax->next;
free(prev_syntax);
break;
}
}
if (syntaxes == NULL) {
syntaxes = (syntaxtype *)nmalloc(sizeof(syntaxtype));
endsyntax = syntaxes;
} else {
endsyntax->next = (syntaxtype *)nmalloc(sizeof(syntaxtype));
endsyntax = endsyntax->next;
#ifdef DEBUG
fprintf(stderr, "Adding new syntax after first one\n");
#endif
}
endsyntax->desc = mallocstrcpy(NULL, nameptr);
endsyntax->color = NULL;
endcolor = NULL;
endsyntax->extensions = NULL;
endsyntax->next = NULL;
#ifdef DEBUG
fprintf(stderr, "Starting a new syntax type: \"%s\"\n", nameptr);
#endif
/* The "none" syntax is the same as not having a syntax at all, so
* we can't assign any extensions or colors to it. */
if (strcmp(endsyntax->desc, "none") == 0) {
rcfile_error(N_("The \"none\" syntax is reserved"));
return;
}
/* The default syntax should have no associated extensions. */
if (strcmp(endsyntax->desc, "default") == 0 && *ptr != '\0') {
rcfile_error(
N_("The \"default\" syntax must take no extensions"));
return;
}
/* Now load the extensions into their part of the struct. */
while (*ptr != '\0') {
exttype *newext;
/* The new extension structure. */
while (*ptr != '"' && *ptr != '\0')
ptr++;
if (*ptr == '\0')
return;
ptr++;
fileregptr = ptr;
ptr = parse_next_regex(ptr);
if (ptr == NULL)
break;
newext = (exttype *)nmalloc(sizeof(exttype));
/* Save the extension regex if it's valid. */
if (nregcomp(fileregptr, REG_NOSUB)) {
newext->ext_regex = mallocstrcpy(NULL, fileregptr);
newext->ext = NULL;
if (endext == NULL)
endsyntax->extensions = newext;
else
endext->next = newext;
endext = newext;
endext->next = NULL;
} else
free(newext);
}
}
/* Read and parse additional syntax files. */
void parse_include(char *ptr)
{
struct stat rcinfo;
FILE *rcstream;
char *option, *full_option, *nanorc_save = nanorc;
size_t lineno_save = lineno;
option = ptr;
if (*option == '"')
option++;
ptr = parse_argument(ptr);
/* Get the specified file's full path. */
full_option = get_full_path(option);
if (full_option == NULL)
full_option = mallocstrcpy(NULL, option);
/* Don't open directories, character files, or block files. */
if (stat(full_option, &rcinfo) != -1) {
if (S_ISDIR(rcinfo.st_mode) || S_ISCHR(rcinfo.st_mode) ||
S_ISBLK(rcinfo.st_mode)) {
rcfile_error(S_ISDIR(rcinfo.st_mode) ?
_("\"%s\" is a directory") :
_("\"%s\" is a device file"), option);
goto cleanup_include;
}
}
/* Open the new syntax file. */
if ((rcstream = fopen(full_option, "rb")) == NULL) {
rcfile_error(_("Error reading %s: %s"), option,
strerror(errno));
goto cleanup_include;
}
/* Use the name and line number position of the new syntax file
* while parsing it, so we can know where any errors in it are. */
nanorc = full_option;
lineno = 0;
parse_rcfile(rcstream
#ifdef ENABLE_COLOR
, TRUE
#endif
);
/* We're done with the new syntax file. Restore the original
* filename and line number position. */
nanorc = nanorc_save;
lineno = lineno_save;
cleanup_include:
free(full_option);
}
/* Return the short value corresponding to the color named in colorname,
* and set bright to TRUE if that color is bright. */
short color_to_short(const char *colorname, bool *bright)
{
short mcolor = -1;
assert(colorname != NULL && bright != NULL);
if (strncasecmp(colorname, "bright", 6) == 0) {
*bright = TRUE;
colorname += 6;
}
if (strcasecmp(colorname, "green") == 0)
mcolor = COLOR_GREEN;
else if (strcasecmp(colorname, "red") == 0)
mcolor = COLOR_RED;
else if (strcasecmp(colorname, "blue") == 0)
mcolor = COLOR_BLUE;
else if (strcasecmp(colorname, "white") == 0)
mcolor = COLOR_WHITE;
else if (strcasecmp(colorname, "yellow") == 0)
mcolor = COLOR_YELLOW;
else if (strcasecmp(colorname, "cyan") == 0)
mcolor = COLOR_CYAN;
else if (strcasecmp(colorname, "magenta") == 0)
mcolor = COLOR_MAGENTA;
else if (strcasecmp(colorname, "black") == 0)
mcolor = COLOR_BLACK;
else
rcfile_error(N_("Color \"%s\" not understood.\n"
"Valid colors are \"green\", \"red\", \"blue\",\n"
"\"white\", \"yellow\", \"cyan\", \"magenta\" and\n"
"\"black\", with the optional prefix \"bright\"\n"
"for foreground colors."), colorname);
return mcolor;
}
/* Parse the color string in the line at ptr, and add it to the current
* file's associated colors. If icase is TRUE, treat the color string
* as case insensitive. */
void parse_colors(char *ptr, bool icase)
{
short fg, bg;
bool bright = FALSE, no_fgcolor = FALSE;
char *fgstr;
assert(ptr != NULL);
if (syntaxes == NULL) {
rcfile_error(
N_("Cannot add a color command without a syntax command"));
return;
}
if (*ptr == '\0') {
rcfile_error(N_("Missing color name"));
return;
}
fgstr = ptr;
ptr = parse_next_word(ptr);
if (strchr(fgstr, ',') != NULL) {
char *bgcolorname;
strtok(fgstr, ",");
bgcolorname = strtok(NULL, ",");
if (bgcolorname == NULL) {
/* If we have a background color without a foreground color,
* parse it properly. */
bgcolorname = fgstr + 1;
no_fgcolor = TRUE;
}
if (strncasecmp(bgcolorname, "bright", 6) == 0) {
rcfile_error(
N_("Background color \"%s\" cannot be bright"),
bgcolorname);
return;
}
bg = color_to_short(bgcolorname, &bright);
} else
bg = -1;
if (!no_fgcolor) {
fg = color_to_short(fgstr, &bright);
/* Don't try to parse screwed-up foreground colors. */
if (fg == -1)
return;
} else
fg = -1;
if (*ptr == '\0') {
rcfile_error(N_("Missing regex string"));
return;
}
/* Now for the fun part. Start adding regexes to individual strings
* in the colorstrings array, woo! */
while (ptr != NULL && *ptr != '\0') {
colortype *newcolor;
/* The new color structure. */
bool cancelled = FALSE;
/* The start expression was bad. */
bool expectend = FALSE;
/* Do we expect an end= line? */
if (strncasecmp(ptr, "start=", 6) == 0) {
ptr += 6;
expectend = TRUE;
}
if (*ptr != '"') {
rcfile_error(
N_("Regex strings must begin and end with a \" character"));
ptr = parse_next_regex(ptr);
continue;
}
ptr++;
fgstr = ptr;
ptr = parse_next_regex(ptr);
if (ptr == NULL)
break;
newcolor = (colortype *)nmalloc(sizeof(colortype));
/* Save the starting regex string if it's valid, and set up the
* color information. */
if (nregcomp(fgstr, icase ? REG_ICASE : 0)) {
newcolor->fg = fg;
newcolor->bg = bg;
newcolor->bright = bright;
newcolor->icase = icase;
newcolor->start_regex = mallocstrcpy(NULL, fgstr);
newcolor->start = NULL;
newcolor->end_regex = NULL;
newcolor->end = NULL;
newcolor->next = NULL;
if (endcolor == NULL) {
endsyntax->color = newcolor;
#ifdef DEBUG
fprintf(stderr, "Starting a new colorstring for fg %hd, bg %hd\n", fg, bg);
#endif
} else {
#ifdef DEBUG
fprintf(stderr, "Adding new entry for fg %hd, bg %hd\n", fg, bg);
#endif
endcolor->next = newcolor;
}
endcolor = newcolor;
} else {
free(newcolor);
cancelled = TRUE;
}
if (expectend) {
if (ptr == NULL || strncasecmp(ptr, "end=", 4) != 0) {
rcfile_error(
N_("\"start=\" requires a corresponding \"end=\""));
return;
}
ptr += 4;
if (*ptr != '"') {
rcfile_error(
N_("Regex strings must begin and end with a \" character"));
continue;
}
ptr++;
fgstr = ptr;
ptr = parse_next_regex(ptr);
if (ptr == NULL)
break;
/* If the start regex was invalid, skip past the end regex to
* stay in sync. */
if (cancelled)
continue;
/* Save the ending regex string if it's valid. */
newcolor->end_regex = (nregcomp(fgstr, icase ? REG_ICASE :
0)) ? mallocstrcpy(NULL, fgstr) : NULL;
}
}
}
#endif /* ENABLE_COLOR */
/* Parse the rcfile, once it has been opened successfully at rcstream,
* and close it afterwards. If syntax_only is TRUE, only allow the file
* to contain color syntax commands: syntax, color, and icolor. */
void parse_rcfile(FILE *rcstream
#ifdef ENABLE_COLOR
, bool syntax_only
#endif
)
{
char *buf = NULL;
ssize_t len;
size_t n;
while ((len = getline(&buf, &n, rcstream)) > 0) {
char *ptr, *keyword, *option;
int set = 0;
size_t i;
/* Ignore the newline. */
if (buf[len - 1] == '\n')
buf[len - 1] = '\0';
lineno++;
ptr = buf;
while (isblank(*ptr))
ptr++;
/* If we have a blank line or a comment, skip to the next
* line. */
if (*ptr == '\0' || *ptr == '#')
continue;
/* Otherwise, skip to the next space. */
keyword = ptr;
ptr = parse_next_word(ptr);
/* Try to parse the keyword. */
if (strcasecmp(keyword, "set") == 0) {
#ifdef ENABLE_COLOR
if (syntax_only)
rcfile_error(
N_("Command \"%s\" not allowed in included file"),
keyword);
else
#endif
set = 1;
} else if (strcasecmp(keyword, "unset") == 0) {
#ifdef ENABLE_COLOR
if (syntax_only)
rcfile_error(
N_("Command \"%s\" not allowed in included file"),
keyword);
else
#endif
set = -1;
}
#ifdef ENABLE_COLOR
else if (strcasecmp(keyword, "include") == 0) {
if (syntax_only)
rcfile_error(
N_("Command \"%s\" not allowed in included file"),
keyword);
else
parse_include(ptr);
} else if (strcasecmp(keyword, "syntax") == 0) {
if (endsyntax != NULL && endcolor == NULL)
rcfile_error(N_("Syntax \"%s\" has no color commands"),
endsyntax->desc);
parse_syntax(ptr);
} else if (strcasecmp(keyword, "color") == 0)
parse_colors(ptr, FALSE);
else if (strcasecmp(keyword, "icolor") == 0)
parse_colors(ptr, TRUE);
#endif /* ENABLE_COLOR */
else
rcfile_error(N_("Command \"%s\" not understood"), keyword);
if (set == 0)
continue;
if (*ptr == '\0') {
rcfile_error(N_("Missing flag"));
continue;
}
option = ptr;
ptr = parse_next_word(ptr);
for (i = 0; rcopts[i].name != NULL; i++) {
if (strcasecmp(option, rcopts[i].name) == 0) {
#ifdef DEBUG
fprintf(stderr, "parse_rcfile(): name = \"%s\"\n", rcopts[i].name);
#endif
if (set == 1) {
if (rcopts[i].flag != 0)
/* This option has a flag, so it doesn't take an
* argument. */
SET(rcopts[i].flag);
else {
/* This option doesn't have a flag, so it takes
* an argument. */
if (*ptr == '\0') {
rcfile_error(
N_("Option \"%s\" requires an argument"),
rcopts[i].name);
break;
}
option = ptr;
if (*option == '"')
option++;
ptr = parse_argument(ptr);
option = mallocstrcpy(NULL, option);
#ifdef DEBUG
fprintf(stderr, "option = \"%s\"\n", option);
#endif
/* Make sure option is a valid multibyte
* string. */
if (!is_valid_mbstring(option)) {
rcfile_error(
N_("Option is not a valid multibyte string"));
break;
}
#ifndef DISABLE_OPERATINGDIR
if (strcasecmp(rcopts[i].name, "operatingdir") == 0)
operating_dir = option;
else
#endif
#ifndef DISABLE_WRAPJUSTIFY
if (strcasecmp(rcopts[i].name, "fill") == 0) {
if (!parse_num(option, &wrap_at)) {
rcfile_error(
N_("Requested fill size \"%s\" is invalid"),
option);
wrap_at = -CHARS_FROM_EOL;
} else
free(option);
} else
#endif
#ifndef NANO_TINY
if (strcasecmp(rcopts[i].name,
"matchbrackets") == 0) {
matchbrackets = option;
if (has_blank_mbchars(matchbrackets)) {
rcfile_error(
N_("Non-blank characters required"));
free(matchbrackets);
matchbrackets = NULL;
}
} else if (strcasecmp(rcopts[i].name,
"whitespace") == 0) {
whitespace = option;
if (mbstrlen(whitespace) != 2 ||
strlenpt(whitespace) != 2) {
rcfile_error(
N_("Two single-column characters required"));
free(whitespace);
whitespace = NULL;
} else {
whitespace_len[0] =
parse_mbchar(whitespace, NULL,
NULL);
whitespace_len[1] =
parse_mbchar(whitespace +
whitespace_len[0], NULL, NULL);
}
} else
#endif
#ifndef DISABLE_JUSTIFY
if (strcasecmp(rcopts[i].name, "punct") == 0) {
punct = option;
if (has_blank_mbchars(punct)) {
rcfile_error(
N_("Non-blank characters required"));
free(punct);
punct = NULL;
}
} else if (strcasecmp(rcopts[i].name,
"brackets") == 0) {
brackets = option;
if (has_blank_mbchars(brackets)) {
rcfile_error(
N_("Non-blank characters required"));
free(brackets);
brackets = NULL;
}
} else if (strcasecmp(rcopts[i].name,
"quotestr") == 0)
quotestr = option;
else
#endif
#ifndef NANO_TINY
if (strcasecmp(rcopts[i].name,
"backupdir") == 0)
backup_dir = option;
else
#endif
#ifndef DISABLE_SPELLER
if (strcasecmp(rcopts[i].name, "speller") == 0)
alt_speller = option;
else
#endif
if (strcasecmp(rcopts[i].name,
"tabsize") == 0) {
if (!parse_num(option, &tabsize) ||
tabsize <= 0) {
rcfile_error(
N_("Requested tab size \"%s\" is invalid"),
option);
tabsize = -1;
} else
free(option);
} else
assert(FALSE);
}
#ifdef DEBUG
fprintf(stderr, "flag = %ld\n", rcopts[i].flag);
#endif
} else if (rcopts[i].flag != 0)
UNSET(rcopts[i].flag);
else
rcfile_error(N_("Cannot unset flag \"%s\""),
rcopts[i].name);
break;
}
}
if (rcopts[i].name == NULL)
rcfile_error(N_("Unknown flag \"%s\""), option);
}
#ifdef ENABLE_COLOR
if (endsyntax != NULL && endcolor == NULL)
rcfile_error(N_("Syntax \"%s\" has no color commands"),
endsyntax->desc);
#endif
free(buf);
fclose(rcstream);
lineno = 0;
if (errors) {
errors = FALSE;
fprintf(stderr,
_("\nPress Enter to continue starting nano.\n"));
while (getchar() != '\n')
;
}
return;
}
/* The main rcfile function. It tries to open the system-wide rcfile,
* followed by the current user's rcfile. */
void do_rcfile(void)
{
struct stat rcinfo;
FILE *rcstream;
nanorc = mallocstrcpy(nanorc, SYSCONFDIR "/nanorc");
/* Don't open directories, character files, or block files. */
if (stat(nanorc, &rcinfo) != -1) {
if (S_ISDIR(rcinfo.st_mode) || S_ISCHR(rcinfo.st_mode) ||
S_ISBLK(rcinfo.st_mode))
rcfile_error(S_ISDIR(rcinfo.st_mode) ?
_("\"%s\" is a directory") :
_("\"%s\" is a device file"), nanorc);
}
/* Try to open the system-wide nanorc. */
rcstream = fopen(nanorc, "rb");
if (rcstream != NULL)
parse_rcfile(rcstream
#ifdef ENABLE_COLOR
, FALSE
#endif
);
#ifdef DISABLE_ROOTWRAPPING
/* We've already read SYSCONFDIR/nanorc, if it's there. If we're
* root, and --disable-wrapping-as-root is used, turn wrapping off
* now. */
if (geteuid() == NANO_ROOT_UID)
SET(NO_WRAP);
#endif
get_homedir();
if (homedir == NULL)
rcfile_error(N_("I can't find my home directory! Wah!"));
else {
nanorc = charealloc(nanorc, strlen(homedir) + 9);
sprintf(nanorc, "%s/.nanorc", homedir);
/* Don't open directories, character files, or block files. */
if (stat(nanorc, &rcinfo) != -1) {
if (S_ISDIR(rcinfo.st_mode) || S_ISCHR(rcinfo.st_mode) ||
S_ISBLK(rcinfo.st_mode))
rcfile_error(S_ISDIR(rcinfo.st_mode) ?
_("\"%s\" is a directory") :
_("\"%s\" is a device file"), nanorc);
}
/* Try to open the current user's nanorc. */
rcstream = fopen(nanorc, "rb");
if (rcstream == NULL) {
/* Don't complain about the file's not existing. */
if (errno != ENOENT)
rcfile_error(N_("Error reading %s: %s"), nanorc,
strerror(errno));
} else
parse_rcfile(rcstream
#ifdef ENABLE_COLOR
, FALSE
#endif
);
}
free(nanorc);
nanorc = NULL;
#ifdef ENABLE_COLOR
set_colorpairs();
#endif
}
#endif /* ENABLE_NANORC */

1442
src/search.c Normal file

File diff suppressed because it is too large Load Diff

2461
src/text.c Normal file

File diff suppressed because it is too large Load Diff

616
src/utils.c Normal file
View File

@ -0,0 +1,616 @@
/* $Id: utils.c,v 1.124 2007/01/01 05:15:32 dolorous Exp $ */
/**************************************************************************
* utils.c *
* *
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 Chris Allegretta *
* Copyright (C) 2005, 2006, 2007 David Lawrence Ramsey *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2, or (at your option) *
* any later version. *
* *
* This program is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software *
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA *
* 02110-1301, USA. *
* *
**************************************************************************/
#include "proto.h"
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <pwd.h>
#include <ctype.h>
#include <errno.h>
/* Return the number of decimal digits in n. */
int digits(size_t n)
{
int i;
if (n == 0)
i = 1;
else {
for (i = 0; n != 0; n /= 10, i++)
;
}
return i;
}
/* Return the user's home directory. We use $HOME, and if that fails,
* we fall back on the home directory of the effective user ID. */
void get_homedir(void)
{
if (homedir == NULL) {
const char *homenv = getenv("HOME");
if (homenv == NULL) {
const struct passwd *userage = getpwuid(geteuid());
if (userage != NULL)
homenv = userage->pw_dir;
}
homedir = mallocstrcpy(NULL, homenv);
}
}
/* Read a ssize_t from str, and store it in *val (if val is not NULL).
* On error, we return FALSE and don't change *val. Otherwise, we
* return TRUE. */
bool parse_num(const char *str, ssize_t *val)
{
char *first_error;
ssize_t j;
assert(str != NULL);
j = (ssize_t)strtol(str, &first_error, 10);
if (errno == ERANGE || *str == '\0' || *first_error != '\0')
return FALSE;
if (val != NULL)
*val = j;
return TRUE;
}
/* Read two ssize_t's, separated by a comma, from str, and store them in
* *line and *column (if they're not both NULL). Return FALSE on error,
* or TRUE otherwise. */
bool parse_line_column(const char *str, ssize_t *line, ssize_t *column)
{
bool retval = TRUE;
const char *comma;
assert(str != NULL);
comma = strchr(str, ',');
if (comma != NULL && column != NULL) {
if (!parse_num(comma + 1, column))
retval = FALSE;
}
if (line != NULL) {
if (comma != NULL) {
char *str_line = mallocstrncpy(NULL, str, comma - str + 1);
str_line[comma - str] = '\0';
if (str_line[0] != '\0' && !parse_num(str_line, line))
retval = FALSE;
free(str_line);
} else if (!parse_num(str, line))
retval = FALSE;
}
return retval;
}
/* Fix the memory allocation for a string. */
void align(char **str)
{
assert(str != NULL);
if (*str != NULL)
*str = charealloc(*str, strlen(*str) + 1);
}
/* Null a string at a certain index and align it. */
void null_at(char **data, size_t index)
{
assert(data != NULL);
*data = charealloc(*data, index + 1);
(*data)[index] = '\0';
}
/* For non-null-terminated lines. A line, by definition, shouldn't
* normally have newlines in it, so encode its nulls as newlines. */
void unsunder(char *str, size_t true_len)
{
assert(str != NULL);
for (; true_len > 0; true_len--, str++) {
if (*str == '\0')
*str = '\n';
}
}
/* For non-null-terminated lines. A line, by definition, shouldn't
* normally have newlines in it, so decode its newlines as nulls. */
void sunder(char *str)
{
assert(str != NULL);
for (; *str != '\0'; str++) {
if (*str == '\n')
*str = '\0';
}
}
/* These functions, ngetline() (originally getline()) and ngetdelim()
* (originally getdelim()), were adapted from GNU mailutils 0.5
* (mailbox/getline.c). Here is the notice from that file, after
* converting to the GPL via LGPL clause 3, and with the Free Software
* Foundation's address updated:
*
* GNU Mailutils -- a suite of utilities for electronic mail
* Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301, USA. */
#if !defined(NANO_TINY) && defined(ENABLE_NANORC)
#ifndef HAVE_GETLINE
/* This function is equivalent to getline(). */
ssize_t ngetline(char **lineptr, size_t *n, FILE *stream)
{
return getdelim(lineptr, n, '\n', stream);
}
#endif
#ifndef HAVE_GETDELIM
/* This function is equivalent to getdelim(). */
ssize_t ngetdelim(char **lineptr, size_t *n, int delim, FILE *stream)
{
size_t indx = 0;
int c;
/* Sanity checks. */
if (lineptr == NULL || n == NULL || stream == NULL ||
fileno(stream) == -1) {
errno = EINVAL;
return -1;
}
/* Allocate the line the first time. */
if (*lineptr == NULL) {
*lineptr = charalloc(MAX_BUF_SIZE);
*n = MAX_BUF_SIZE;
}
while ((c = getc(stream)) != EOF) {
/* Check if more memory is needed. */
if (indx >= *n) {
*lineptr = charealloc(*lineptr, *n + MAX_BUF_SIZE);
*n += MAX_BUF_SIZE;
}
/* Put the result in the line. */
(*lineptr)[indx++] = (char)c;
/* Bail out. */
if (c == delim)
break;
}
/* Make room for the null character. */
if (indx >= *n) {
*lineptr = charealloc(*lineptr, *n + MAX_BUF_SIZE);
*n += MAX_BUF_SIZE;
}
/* Null-terminate the buffer. */
null_at(lineptr, indx++);
*n = indx;
/* The last line may not have the delimiter. We have to return what
* we got, and the error will be seen on the next iteration. */
return (c == EOF && (indx - 1) == 0) ? -1 : indx - 1;
}
#endif
#endif /* !NANO_TINY && ENABLE_NANORC */
#ifdef HAVE_REGEX_H
/* Do the compiled regex in preg and the regex in string match the
* beginning or end of a line? */
bool regexp_bol_or_eol(const regex_t *preg, const char *string)
{
return (regexec(preg, string, 0, NULL, 0) == 0 &&
regexec(preg, string, 0, NULL, REG_NOTBOL | REG_NOTEOL) ==
REG_NOMATCH);
}
#endif
#ifndef DISABLE_SPELLER
/* Is the word starting at position pos in buf a whole word? */
bool is_whole_word(size_t pos, const char *buf, const char *word)
{
char *p = charalloc(mb_cur_max()), *r = charalloc(mb_cur_max());
size_t word_end = pos + strlen(word);
bool retval;
assert(buf != NULL && pos <= strlen(buf) && word != NULL);
parse_mbchar(buf + move_mbleft(buf, pos), p, NULL);
parse_mbchar(buf + word_end, r, NULL);
/* If we're at the beginning of the line or the character before the
* word isn't a non-punctuation "word" character, and if we're at
* the end of the line or the character after the word isn't a
* non-punctuation "word" character, we have a whole word. */
retval = (pos == 0 || !is_word_mbchar(p, FALSE)) &&
(word_end == strlen(buf) || !is_word_mbchar(r, FALSE));
free(p);
free(r);
return retval;
}
#endif /* !DISABLE_SPELLER */
/* If we are searching backwards, we will find the last match that
* starts no later than start. Otherwise we find the first match
* starting no earlier than start. If we are doing a regexp search, we
* fill in the global variable regmatches with at most 9 subexpression
* matches. Also, all .rm_so elements are relative to the start of the
* whole match, so regmatches[0].rm_so == 0. */
const char *strstrwrapper(const char *haystack, const char *needle,
const char *start)
{
/* start can be 1 character before the start or after the end of the
* line. In either case, we just say no match was found. */
if ((start > haystack && *(start - 1) == '\0') || start < haystack)
return NULL;
assert(haystack != NULL && needle != NULL && start != NULL);
#ifdef HAVE_REGEX_H
if (ISSET(USE_REGEXP)) {
#ifndef NANO_TINY
if (ISSET(BACKWARDS_SEARCH)) {
if (regexec(&search_regexp, haystack, 1, regmatches,
0) == 0 && haystack + regmatches[0].rm_so <= start) {
const char *retval = haystack + regmatches[0].rm_so;
/* Search forward until there are no more matches. */
while (regexec(&search_regexp, retval + 1, 1,
regmatches, REG_NOTBOL) == 0 &&
retval + regmatches[0].rm_so + 1 <= start)
retval += regmatches[0].rm_so + 1;
/* Finally, put the subexpression matches in global
* variable regmatches. The REG_NOTBOL flag doesn't
* matter now. */
regexec(&search_regexp, retval, 10, regmatches, 0);
return retval;
}
} else
#endif /* !NANO_TINY */
if (regexec(&search_regexp, start, 10, regmatches,
(start > haystack) ? REG_NOTBOL : 0) == 0) {
const char *retval = start + regmatches[0].rm_so;
regexec(&search_regexp, retval, 10, regmatches, 0);
return retval;
}
return NULL;
}
#endif /* HAVE_REGEX_H */
#if !defined(NANO_TINY) || !defined(DISABLE_SPELLER)
if (ISSET(CASE_SENSITIVE)) {
#ifndef NANO_TINY
if (ISSET(BACKWARDS_SEARCH))
return revstrstr(haystack, needle, start);
else
#endif
return strstr(start, needle);
}
#endif /* !DISABLE_SPELLER || !NANO_TINY */
#ifndef NANO_TINY
else if (ISSET(BACKWARDS_SEARCH))
return mbrevstrcasestr(haystack, needle, start);
#endif
return mbstrcasestr(start, needle);
}
/* This is a wrapper for the perror() function. The wrapper temporarily
* leaves curses mode, calls perror() (which writes to stderr), and then
* reenters curses mode, updating the screen in the process. Note that
* nperror() causes the window to flicker once. */
void nperror(const char *s)
{
endwin();
perror(s);
doupdate();
}
/* This is a wrapper for the malloc() function that properly handles
* things when we run out of memory. Thanks, BG, many people have been
* asking for this... */
void *nmalloc(size_t howmuch)
{
void *r = malloc(howmuch);
if (r == NULL && howmuch != 0)
die(_("nano is out of memory!"));
return r;
}
/* This is a wrapper for the realloc() function that properly handles
* things when we run out of memory. */
void *nrealloc(void *ptr, size_t howmuch)
{
void *r = realloc(ptr, howmuch);
if (r == NULL && howmuch != 0)
die(_("nano is out of memory!"));
return r;
}
/* Copy the first n characters of one malloc()ed string to another
* pointer. Should be used as: "dest = mallocstrncpy(dest, src,
* n);". */
char *mallocstrncpy(char *dest, const char *src, size_t n)
{
if (src == NULL)
src = "";
if (src != dest)
free(dest);
dest = charalloc(n);
strncpy(dest, src, n);
return dest;
}
/* Copy one malloc()ed string to another pointer. Should be used as:
* "dest = mallocstrcpy(dest, src);". */
char *mallocstrcpy(char *dest, const char *src)
{
return mallocstrncpy(dest, src, (src == NULL) ? 1 :
strlen(src) + 1);
}
/* Free the malloc()ed string at dest and return the malloc()ed string
* at src. Should be used as: "answer = mallocstrassn(answer,
* real_dir_from_tilde(answer));". */
char *mallocstrassn(char *dest, char *src)
{
free(dest);
return src;
}
/* nano scrolls horizontally within a line in chunks. Return the column
* number of the first character displayed in the edit window when the
* cursor is at the given column. Note that (0 <= column -
* get_page_start(column) < COLS). */
size_t get_page_start(size_t column)
{
if (column == 0 || column < COLS - 1)
return 0;
else if (COLS > 8)
return column - 7 - (column - 7) % (COLS - 8);
else
return column - (COLS - 2);
}
/* Return the placewewant associated with current_x, i.e. the zero-based
* column position of the cursor. The value will be no smaller than
* current_x. */
size_t xplustabs(void)
{
return strnlenpt(openfile->current->data, openfile->current_x);
}
/* Return the index in s of the character displayed at the given column,
* i.e. the largest value such that strnlenpt(s, actual_x(s, column)) <=
* column. */
size_t actual_x(const char *s, size_t column)
{
size_t i = 0;
/* The position in s, returned. */
size_t len = 0;
/* The screen display width to s[i]. */
assert(s != NULL);
while (*s != '\0') {
int s_len = parse_mbchar(s, NULL, &len);
if (len > column)
break;
i += s_len;
s += s_len;
}
return i;
}
/* A strnlen() with tabs and multicolumn characters factored in, similar
* to xplustabs(). How many columns wide are the first maxlen characters
* of s? */
size_t strnlenpt(const char *s, size_t maxlen)
{
size_t len = 0;
/* The screen display width to s[i]. */
if (maxlen == 0)
return 0;
assert(s != NULL);
while (*s != '\0') {
int s_len = parse_mbchar(s, NULL, &len);
s += s_len;
if (maxlen <= s_len)
break;
maxlen -= s_len;
}
return len;
}
/* A strlen() with tabs and multicolumn characters factored in, similar
* to xplustabs(). How many columns wide is s? */
size_t strlenpt(const char *s)
{
return strnlenpt(s, (size_t)-1);
}
/* Append a new magicline to filebot. */
void new_magicline(void)
{
openfile->filebot->next = (filestruct *)nmalloc(sizeof(filestruct));
openfile->filebot->next->data = mallocstrcpy(NULL, "");
openfile->filebot->next->prev = openfile->filebot;
openfile->filebot->next->next = NULL;
openfile->filebot->next->lineno = openfile->filebot->lineno + 1;
openfile->filebot = openfile->filebot->next;
openfile->totsize++;
}
#ifndef NANO_TINY
/* Remove the magicline from filebot, if there is one and it isn't the
* only line in the file. Assume that edittop and current are not at
* filebot. */
void remove_magicline(void)
{
if (openfile->filebot->data[0] == '\0' &&
openfile->filebot != openfile->fileage) {
assert(openfile->filebot != openfile->edittop && openfile->filebot != openfile->current);
openfile->filebot = openfile->filebot->prev;
free_filestruct(openfile->filebot->next);
openfile->filebot->next = NULL;
openfile->totsize--;
}
}
/* Set top_x and bot_x to the top and bottom x-coordinates of the mark,
* respectively, based on the locations of top and bot. If
* right_side_up isn't NULL, set it to TRUE If the mark begins with
* (mark_begin, mark_begin_x) and ends with (current, current_x), or
* FALSE otherwise. */
void mark_order(const filestruct **top, size_t *top_x, const filestruct
**bot, size_t *bot_x, bool *right_side_up)
{
assert(top != NULL && top_x != NULL && bot != NULL && bot_x != NULL);
if ((openfile->current->lineno == openfile->mark_begin->lineno &&
openfile->current_x > openfile->mark_begin_x) ||
openfile->current->lineno > openfile->mark_begin->lineno) {
*top = openfile->mark_begin;
*top_x = openfile->mark_begin_x;
*bot = openfile->current;
*bot_x = openfile->current_x;
if (right_side_up != NULL)
*right_side_up = TRUE;
} else {
*bot = openfile->mark_begin;
*bot_x = openfile->mark_begin_x;
*top = openfile->current;
*top_x = openfile->current_x;
if (right_side_up != NULL)
*right_side_up = FALSE;
}
}
#endif
/* Calculate the number of characters between begin and end, and return
* it. */
size_t get_totsize(const filestruct *begin, const filestruct *end)
{
size_t totsize = 0;
const filestruct *f;
/* Go through the lines from begin to end->prev, if we can. */
for (f = begin; f != end && f != NULL; f = f->next) {
/* Count the number of characters on this line. */
totsize += mbstrlen(f->data);
/* Count the newline if we have one. */
if (f->next != NULL)
totsize++;
}
/* Go through the line at end, if we can. */
if (f != NULL) {
/* Count the number of characters on this line. */
totsize += mbstrlen(f->data);
/* Count the newline if we have one. */
if (f->next != NULL)
totsize++;
}
return totsize;
}
#ifdef DEBUG
/* Dump the filestruct inptr to stderr. */
void dump_filestruct(const filestruct *inptr)
{
if (inptr == openfile->fileage)
fprintf(stderr, "Dumping file buffer to stderr...\n");
else if (inptr == cutbuffer)
fprintf(stderr, "Dumping cutbuffer to stderr...\n");
else
fprintf(stderr, "Dumping a buffer to stderr...\n");
while (inptr != NULL) {
fprintf(stderr, "(%ld) %s\n", (long)inptr->lineno, inptr->data);
inptr = inptr->next;
}
}
/* Dump the current buffer's filestruct to stderr in reverse. */
void dump_filestruct_reverse(void)
{
const filestruct *fileptr = openfile->filebot;
while (fileptr != NULL) {
fprintf(stderr, "(%ld) %s\n", (long)fileptr->lineno,
fileptr->data);
fileptr = fileptr->prev;
}
}
#endif /* DEBUG */

3399
src/winio.c Normal file

File diff suppressed because it is too large Load Diff