Compare commits
76 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
084dda3837 | ||
|
|
30f367e0db | ||
|
|
5965e80a38 | ||
|
|
a794c3318b | ||
|
|
d04b0c123e | ||
|
|
21cd953e85 | ||
|
|
058b9da9b9 | ||
|
|
38a10a62d0 | ||
|
|
091e8faf6d | ||
|
|
d8ea89f6a6 | ||
|
|
1f48ed0412 | ||
|
|
b18bcbbe9f | ||
|
|
920730f1aa | ||
|
|
9506b51101 | ||
|
|
918d0e71ab | ||
|
|
484a199175 | ||
|
|
17429d7f38 | ||
|
|
87206c0607 | ||
|
|
b574f73e60 | ||
|
|
eac90c3eff | ||
|
|
440a128d25 | ||
|
|
4f2b01c7e5 | ||
|
|
12073001c2 | ||
|
|
4c20135749 | ||
|
|
f9ebf038e0 | ||
|
|
62ebd93579 | ||
|
|
a10fdc3fb1 | ||
|
|
8581e702d6 | ||
|
|
bdbd5ff0e7 | ||
|
|
f769465284 | ||
|
|
1b5b52d2e4 | ||
|
|
ab62d28817 | ||
|
|
8e0a7ec20d | ||
|
|
23d66949e1 | ||
|
|
184bb11fd9 | ||
|
|
a70db34fc9 | ||
|
|
fbde1b2d71 | ||
|
|
c22fef18e4 | ||
|
|
ee5b250b66 | ||
|
|
fb85c05594 | ||
|
|
25b1114e03 | ||
|
|
4b8a387529 | ||
|
|
df41114e0e | ||
|
|
dc3618a127 | ||
|
|
31fe0753e3 | ||
|
|
7ad5afb935 | ||
|
|
e1b0f2b275 | ||
|
|
0e0fb452a3 | ||
|
|
f66432e999 | ||
|
|
08e9d30fa2 | ||
|
|
d2270e514b | ||
|
|
031305c205 | ||
|
|
e2843ede7e | ||
|
|
09958ebdff | ||
|
|
53fc9a66a6 | ||
|
|
a95c6c5fe8 | ||
|
|
bcd187d7d6 | ||
|
|
03783a7d1b | ||
|
|
f2fb8c01f4 | ||
|
|
ddb8e95d39 | ||
|
|
fbac4505ce | ||
|
|
eb937f81fa | ||
|
|
5144162a2d | ||
|
|
b4411b4f28 | ||
|
|
29f7654ab1 | ||
|
|
66fd6a5ab1 | ||
|
|
c30d3d8010 | ||
|
|
0c40f87b55 | ||
|
|
4761e00852 | ||
|
|
0133d5cba8 | ||
|
|
9066a96dde | ||
|
|
6abb551fdd | ||
|
|
97bdf13b59 | ||
|
|
dae88f8dc7 | ||
|
|
64d1711a24 | ||
|
|
b9638cb7cc |
93
ChangeLog
93
ChangeLog
@@ -1,3 +1,96 @@
|
||||
Changes between v2.9.1 and v2.9.2:
|
||||
----------------------------------
|
||||
|
||||
Benjamin Mintz (1):
|
||||
syntax: python: add 'async', 'await', and 'nonlocal' as keywords
|
||||
|
||||
Benno Schulenberg (62):
|
||||
bump version numbers and add a news item for the 2.9.2 release
|
||||
display: ensure that cursor is visible when compiled with --with-slang
|
||||
docs: mention that the source code is best viewed with a tab size of 4
|
||||
docs: say thanks to some fairly recent translators, and rename one
|
||||
gnulib: pull in the fix for the missing stat include
|
||||
gnulib: update to its current upstream state
|
||||
help: show that "Tab" will indent, just like "Sh-Tab" will unindent
|
||||
help: swap the order of the Complete and Comment functions
|
||||
indenting: don't exclude last line of region when region is empty
|
||||
indenting: keep affecting last line of marked region if it was at first
|
||||
input: allow using <Tab> and <Shift+Tab> to (un)indent selected region
|
||||
input: make <Ctrl+Shift+Arrow> work also when using --rebindkeypad
|
||||
input: optimize a bit for non-shortcut keys, as they are most frequent
|
||||
options: rename 'justifytrim' to 'trimblanks', because it has morphed
|
||||
prompt: blank the bar when a "continue?" is answered with No or ^C
|
||||
syntaxes: remove redundant word-boundary markers
|
||||
syntax: javascript: add some comments, and color explicit numbers too
|
||||
syntax: javascript: add some keywords, and sort them more logically
|
||||
syntax: javascript: color strings differently from major keywords
|
||||
syntax: javascript: require that a comment is preceded by whitespace
|
||||
syntax: lua: condense some regexes, tweak comments, reorder things
|
||||
syntax: nanorc: don't color parts of valid strings as if invalid
|
||||
syntax: python: color also the special values 'False', 'None', 'True'
|
||||
text: allow unindenting when not all lines are indented
|
||||
text: keep cursor at left edge when it IS there when indenting/commenting
|
||||
text: let a Shift-selection persist when indenting and commenting
|
||||
text: let indenting/commenting skip the last line if its x is zero
|
||||
text: set and reset the Modified state correctly when undoing/redoing
|
||||
tweaks: add a separate function that actually wipes the status bar
|
||||
tweaks: avoid incrementing a variable that won't be used again later
|
||||
tweaks: condense or rewrap a bunch of repetitious comments
|
||||
tweaks: condense, reword, and rewrap a bunch of comments
|
||||
tweaks: condense some debugging code, and rewrap a line
|
||||
tweaks: convert the indentation of the NEWS file too
|
||||
tweaks: convert the indentation to use only tabs
|
||||
tweaks: drop some old debugging code plus a superfluous comment
|
||||
tweaks: elide two parameters from the get_region() function
|
||||
tweaks: elide two variables that are used just once
|
||||
tweaks: factor out a piece of common code
|
||||
tweaks: fix some whitespace errors, and convert alignment tabs to spaces
|
||||
tweaks: fold some regexes into one another, for conciseness
|
||||
tweaks: frob four comments, and rewrap two lines
|
||||
tweaks: invert the logic of a variable, and rename it
|
||||
tweaks: limit the resetting of "Modified" to writing a full buffer
|
||||
tweaks: move some frequently-used keystrokes to the top of the list
|
||||
tweaks: remove a redundant call of renumber()
|
||||
tweaks: remove a superfluous condition
|
||||
tweaks: remove a superfluous placing of a terminating nul byte
|
||||
tweaks: remove some unneeded parentheses, and shorten two function calls
|
||||
tweaks: remove two irrelevant conditions
|
||||
tweaks: rename three variables, for more contrast and variety
|
||||
tweaks: reshuffle a bit of common code, moving it to an existing function
|
||||
tweaks: reshuffle another bit of code, for conciseness
|
||||
tweaks: rewrap some lines and some comments, and trim two others
|
||||
tweaks: slightly rename four functions, for aptness and variety
|
||||
tweaks: strip some debugging stuff, and condense a bit of code
|
||||
tweaks: trim another placing of a terminating nul byte
|
||||
tweaks: use for git the more faithful "less -x1,5" suggested by Brand
|
||||
tweaks: use spaces for alignment also in the THANKS file
|
||||
wrapping: delete trailing blanks upon hardwrapping, when requested
|
||||
wrapping: keep prepending to the same next line as long as possible
|
||||
wrapping: we're still on the same line if the next line has not changed
|
||||
|
||||
David Lawrence Ramsey (3):
|
||||
input: support backtab when Slang and/or --rebindkeypad is used
|
||||
tweaks: use printf's z modifier for (s)size_t, instead of casting
|
||||
undo: when adding text adds a magicline, an undo should remove both
|
||||
|
||||
Liu Hao (1):
|
||||
syntax: c: increase the color contrast of reminders like FIXME
|
||||
|
||||
Michael Francis (1):
|
||||
syntax: php: function and variable names can contain uppercase and digits
|
||||
|
||||
Mike Frysinger (1):
|
||||
syntax: javascript: add newer keywords and string syntax
|
||||
|
||||
Tom Levy (6):
|
||||
syntax: go: fix word boundary before dot in number literal
|
||||
syntax: go: sign of exponent in number literal is optional
|
||||
syntax: lua: add new and missing standard library functions
|
||||
syntax: lua: correct the word boundaries on standard library functions
|
||||
syntax: lua: require at least one digit for hexadecimal numbers
|
||||
syntax: lua: support fractional part and exponent for decimal and hex
|
||||
|
||||
|
||||
Changes between v2.9.0 and v2.9.1:
|
||||
----------------------------------
|
||||
|
||||
|
||||
@@ -2,6 +2,8 @@ Improvements in GNU nano
|
||||
========================
|
||||
|
||||
Since 2.9.0:
|
||||
- <Tab> and <Shift+Tab> can be used to indent/unindent a marked region.
|
||||
- Can snip trailing whitespace while typing, with 'set trimblanks'.
|
||||
- The ability to record and replay a series of keystrokes (a macro).
|
||||
- Assigned functions to ^S (save file) and ^Q (start backward search).
|
||||
- Indenting and unindenting have been integrated into the undo system.
|
||||
|
||||
@@ -107,3 +107,10 @@ the license that covers nano. Then create a patch (or patches):
|
||||
|
||||
Send that patch (or patches) to <nano-devel@gnu.org>, as an attachment
|
||||
or with git send-email.
|
||||
|
||||
To keep most lines of nano's source code within a width of 80 characters,
|
||||
a tab size of four should be used. So in your nanorc file you may want
|
||||
to include 'set tabsize 4', or you could use -T4 on the command line.
|
||||
To make git display things as intended, you can do:
|
||||
|
||||
$ git config --local core.pager "less -x1,5"
|
||||
|
||||
168
THANKS
168
THANKS
@@ -4,90 +4,94 @@ If we missed you here, let us know!
|
||||
|
||||
Translations:
|
||||
============
|
||||
Sharuzzaman Ahmat Raslan <sharuzzaman@excite.com> Malay
|
||||
Josef Andersson <josef.andersson@fripost.org> Swedish
|
||||
Laurentiu Buzdugan <buzdugan@voyager.net> Romanian
|
||||
Mario Blättermann <mario.blaettermann@gmail.com> German
|
||||
Ricardo Cárdenes Medina <ricardo@conisys.com> Spanish
|
||||
Antonio Ceballos <aceballos@gmail.com> Spanish
|
||||
Wei-Lun CHAO <chaoweilun@pcmail.com.tw> Chinese (traditional)
|
||||
Yuri Chornoivan <yurchor@ukr.net> Ukrainian
|
||||
Marco Colombo <magicdice@inwind.it> Italian
|
||||
Mihai Cristescu <mihai.cristescu@archlinux.info> Romanian
|
||||
Yavor Doganov <yavor@doganov.org> Bulgarian
|
||||
Karl Eichwalder <keichwa@gmx.net> German
|
||||
A. Murat EREN <meren@comu.edu.tr> Turkish
|
||||
Rafael Ferreira <rafael.f.f1@gmail.com> Brazilian Portuguese
|
||||
Doruk Fisek <dfisek@fisek.com.tr> Turkish
|
||||
Pavel Fric <pavelfric@seznam.cz> Czech
|
||||
Jorge González <aloriel@gmail.com> Spanish
|
||||
Sharuzzaman Ahmat Raslan <sharuzzaman@excite.com> Malay
|
||||
Josef Andersson <josef.andersson@fripost.org> Swedish
|
||||
Laurentiu Buzdugan <buzdugan@voyager.net> Romanian
|
||||
Mario Blättermann <mario.blaettermann@gmail.com> German
|
||||
Ricardo Cárdenes Medina <ricardo@conisys.com> Spanish
|
||||
Antonio Ceballos <aceballos@gmail.com> Spanish
|
||||
Wei-Lun CHAO <chaoweilun@pcmail.com.tw> Chinese (traditional)
|
||||
Yuri Chornoivan <yurchor@ukr.net> Ukrainian
|
||||
Marco Colombo <magicdice@inwind.it> Italian
|
||||
Mihai Cristescu <mihai.cristescu@archlinux.info> Romanian
|
||||
Yavor Doganov <yavor@doganov.org> Bulgarian
|
||||
Karl Eichwalder <keichwa@gmx.net> German
|
||||
A. Murat EREN <meren@comu.edu.tr> Turkish
|
||||
Doruk Fisek <dfisek@fisek.com.tr> Turkish
|
||||
Rafael Fontenelle <rffontenelle@gmail.com> Brazilian Portuguese
|
||||
Pavel Fric <pavelfric@seznam.cz> Czech
|
||||
Jorge González <aloriel@gmail.com> Spanish
|
||||
Jean-Philippe Guérard <jean-philippe.guerard@laposte.net> French
|
||||
Geir Helland <pjallabais@users.sourceforge.net> Norwegian Bokmål
|
||||
Tedi Heriyanto <tedi_h@gmx.net> Indonesian
|
||||
Václav Haisman <V.Haisman@sh.cvut.cz> Czech
|
||||
Kjetil Torgrim Homme <kjetilho@linpro.no> Norwegian Nynorsk
|
||||
Szabolcs Horvath <horvaths@janus.gimsz.sulinet.hu> Hungarian
|
||||
Jorma Karvonen <karvonen.jorma@gmail.com> Finnish
|
||||
Gabor Kelemen <kelemeng@gnome.hu> Hungarian
|
||||
Kalle Kivimaa <kalle.kivimaa@iki.fi> Finnish
|
||||
Eivind Kjørstad <ekj@vestdata.no> Norwegian Nynorsk
|
||||
Florian König <floki@bigfoot.com> German
|
||||
Klemen Košir <klemen913@gmail.com> Slovenian
|
||||
Wojciech Kotwica <wkotwica@post.pl> Polish
|
||||
Ask Hjorth Larsen <asklarsen@gmail.com> Danish
|
||||
Clement Laforet <clem_laf@wanadoo.fr> French
|
||||
LI Daobing <lidaobing@gmail.com> Chinese (simplified)
|
||||
Jordi Mallach <jordi@gnu.org> Catalan
|
||||
João Victor Duarte Martins <jvdm@sdf.lonestar.org> Brazilian Portuguese
|
||||
Pavel Maryanov <acid@jack.kiev.ua> Russian
|
||||
Daniele Medri <madrid@linux.it> Italian
|
||||
Gergely Nagy <algernon@debian.org> Hungarian
|
||||
Kalle Olavi Niemitalo <kon@iki.fi> Finnish
|
||||
Мирослав Николић <miroslavnikolic@rocketmail.com> Serbian
|
||||
Claudio Neves <cneves@nextis.com> Brazilian Portuguese
|
||||
Daniel Nylander <po@danielnylander.se> Swedish
|
||||
Mikel Olasagasti <hey_neken@mundurat.net> Basque
|
||||
Michael Piefel <piefel@informatik.hu-berlin.de> German
|
||||
Sergey Poznyakoff <gray@gnu.org> Polish
|
||||
Božidar Putanec <bozidarp@yahoo.com> Croatian
|
||||
Trần Ngọc Quân <vnwildman@gmail.com> Vietnamese
|
||||
Sergey A. Ribalchenko <fisher@obu.ck.ua> Ukrainian and Russian
|
||||
Michel Robitaille <robitail@IRO.UMontreal.CA> French
|
||||
Christian Rose <menthos@menthos.com> Swedish
|
||||
Dimitriy Ryazantcev <DJm00n@mail.ru> Russian
|
||||
Stig E Sandø <stig@ii.uib.no> Norwegian Bokmål
|
||||
Kevin Patrick Scannell <kscanne@gmail.com> Irish
|
||||
Benno Schulenberg <benno@vertaalt.nl> Dutch and Esperanto
|
||||
Danilo Segan <dsegan@gmx.net> Serbian
|
||||
Clytie Siddall <clytie@riverland.net.au> Vietnamese
|
||||
Keld Simonsen <keld@dkuug.dk> Danish
|
||||
Guus Sliepen <guus@nl.linux.org> Dutch
|
||||
Cezary Sliwa <sliwa@cft.edu.pl> Polish
|
||||
Johnny A. Solbu <johnny@solbu.net> Norwegian Bokmål
|
||||
Pierre Tane <tanep@bigfoot.com> French
|
||||
Yasuaki Taniguchi <yasuakit@gmail.com> Japanese
|
||||
Jacobo Tarrío <jtarrio@trasno.net> Galician
|
||||
Francisco Javier Tsao Santín <tsao@members.fsf.org> Galician
|
||||
Miquel Vidal <miquel@sindominio.net> Catalan
|
||||
Phan Vinh Thinh <teppi82@gmail.com> Vietnamese
|
||||
Pauli Virtanen <pauli.virtanen@saunalahti.fi> Finnish
|
||||
Aron Xu <happyaron.xu@gmail.com> Chinese (simplified)
|
||||
Peio Ziarsolo <peio@sindominio.net> Basque
|
||||
Anton Zinoviev <zinoviev@debian.org> Bulgarian
|
||||
Geir Helland <pjallabais@users.sourceforge.net> Norwegian Bokmål
|
||||
Tedi Heriyanto <tedi_h@gmx.net> Indonesian
|
||||
Václav Haisman <V.Haisman@sh.cvut.cz> Czech
|
||||
Takeshi Hamasaki <hmatrjp@users.sourceforge.jp> Japanese
|
||||
Kjetil Torgrim Homme <kjetilho@linpro.no> Norwegian Nynorsk
|
||||
Szabolcs Horvath <horvaths@janus.gimsz.sulinet.hu> Hungarian
|
||||
Jorma Karvonen <karvonen.jorma@gmail.com> Finnish
|
||||
Mehmet Kececi <mkececi@mehmetkececi.com> Turkish
|
||||
Gabor Kelemen <kelemeng@gnome.hu> Hungarian
|
||||
Kalle Kivimaa <kalle.kivimaa@iki.fi> Finnish
|
||||
Eivind Kjørstad <ekj@vestdata.no> Norwegian Nynorsk
|
||||
Florian König <floki@bigfoot.com> German
|
||||
Klemen Košir <klemen913@gmail.com> Slovenian
|
||||
Wojciech Kotwica <wkotwica@post.pl> Polish
|
||||
Ask Hjorth Larsen <asklarsen@gmail.com> Danish
|
||||
Clement Laforet <clem_laf@wanadoo.fr> French
|
||||
LI Daobing <lidaobing@gmail.com> Chinese (simplified)
|
||||
Jordi Mallach <jordi@gnu.org> Catalan
|
||||
João Victor Duarte Martins <jvdm@sdf.lonestar.org> Brazilian Portuguese
|
||||
Pavel Maryanov <acid@jack.kiev.ua> Russian
|
||||
Daniele Medri <madrid@linux.it> Italian
|
||||
Gergely Nagy <algernon@debian.org> Hungarian
|
||||
Kalle Olavi Niemitalo <kon@iki.fi> Finnish
|
||||
Мирослав Николић <miroslavnikolic@rocketmail.com> Serbian
|
||||
Claudio Neves <cneves@nextis.com> Brazilian Portuguese
|
||||
Lauri Nurmi <lanurmi@iki.fi> Finnish
|
||||
Daniel Nylander <po@danielnylander.se> Swedish
|
||||
Mikel Olasagasti <hey_neken@mundurat.net> Basque
|
||||
Michael Piefel <piefel@informatik.hu-berlin.de> German
|
||||
Sergey Poznyakoff <gray@gnu.org> Polish
|
||||
Božidar Putanec <bozidarp@yahoo.com> Croatian
|
||||
Trần Ngọc Quân <vnwildman@gmail.com> Vietnamese
|
||||
Sergey A. Ribalchenko <fisher@obu.ck.ua> Ukrainian and Russian
|
||||
Michel Robitaille <robitail@IRO.UMontreal.CA> French
|
||||
Christian Rose <menthos@menthos.com> Swedish
|
||||
Dimitriy Ryazantcev <DJm00n@mail.ru> Russian
|
||||
Stig E Sandø <stig@ii.uib.no> Norwegian Bokmål
|
||||
Kevin Patrick Scannell <kscanne@gmail.com> Irish
|
||||
Benno Schulenberg <benno@vertaalt.nl> Dutch and Esperanto
|
||||
Danilo Segan <dsegan@gmx.net> Serbian
|
||||
Clytie Siddall <clytie@riverland.net.au> Vietnamese
|
||||
Keld Simonsen <keld@dkuug.dk> Danish
|
||||
Guus Sliepen <guus@nl.linux.org> Dutch
|
||||
Cezary Sliwa <sliwa@cft.edu.pl> Polish
|
||||
Johnny A. Solbu <johnny@solbu.net> Norwegian Bokmål
|
||||
Pierre Tane <tanep@bigfoot.com> French
|
||||
Yasuaki Taniguchi <yasuakit@gmail.com> Japanese
|
||||
Jacobo Tarrío <jtarrio@trasno.net> Galician
|
||||
Francisco Javier Tsao Santín <tsao@members.fsf.org> Galician
|
||||
Balázs Úr <urbalazs@gmail.com> Hungarian
|
||||
Miquel Vidal <miquel@sindominio.net> Catalan
|
||||
Phan Vinh Thinh <teppi82@gmail.com> Vietnamese
|
||||
Pauli Virtanen <pauli.virtanen@saunalahti.fi> Finnish
|
||||
Aron Xu <happyaron.xu@gmail.com> Chinese (simplified)
|
||||
Peio Ziarsolo <peio@sindominio.net> Basque
|
||||
Anton Zinoviev <zinoviev@debian.org> Bulgarian
|
||||
|
||||
|
||||
Other stuff:
|
||||
===========
|
||||
Ben Armstrong <synrg@sanctuary.nslug.ns.ca> Negative -r value idea, code
|
||||
Thomas Dickey <dickey@herndon4.his.com> Curses help and advice
|
||||
Sven Guckes <guckes@math.fu-berlin.de> Advice and advocacy
|
||||
Thijs Kinkhorst <thijs@kinkhorst.com> rnano.1 manpage
|
||||
Jim Knoble <jmknoble@pobox.com> Pico compat for browser
|
||||
Ryan Krebs <fluffy@highwire.stanford.edu> Many bug fixes and testing
|
||||
Roy Lanek <lanek@ranahminang.net> Advice and advocacy
|
||||
Chuck Mead <csm@MoonGroup.com> Feedback and RPM stuff
|
||||
Mike Melanson <melanson@pcisys.net> Bugs
|
||||
Neil Parks <nparks@acsmail.com> Bug reports and fixes
|
||||
Jeremy Robichaud <robicj@yahoo.com> Beta tester
|
||||
Bill Soudan <wes0472@rit.edu> Regex code, etc
|
||||
Ken Tyler <kent@werple.net.au> Search fixes and more
|
||||
Ben Armstrong <synrg@sanctuary.nslug.ns.ca> Negative -r value idea, code
|
||||
Thomas Dickey <dickey@herndon4.his.com> Curses help and advice
|
||||
Sven Guckes <guckes@math.fu-berlin.de> Advice and advocacy
|
||||
Thijs Kinkhorst <thijs@kinkhorst.com> rnano.1 manpage
|
||||
Jim Knoble <jmknoble@pobox.com> Pico compat for browser
|
||||
Ryan Krebs <fluffy@highwire.stanford.edu> Many bug fixes and testing
|
||||
Roy Lanek <lanek@ranahminang.net> Advice and advocacy
|
||||
Chuck Mead <csm@MoonGroup.com> Feedback and RPM stuff
|
||||
Mike Melanson <melanson@pcisys.net> Bug reports
|
||||
Neil Parks <nparks@acsmail.com> Bug reports and fixes
|
||||
Jeremy Robichaud <robicj@yahoo.com> Beta tester
|
||||
Bill Soudan <wes0472@rit.edu> Regex code, etc
|
||||
Ken Tyler <kent@werple.net.au> Search fixes and more
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# Generate configure & friends for GIT users.
|
||||
|
||||
gnulib_url="git://git.sv.gnu.org/gnulib.git"
|
||||
gnulib_hash="b9d0b50f6cd122a1748e1e5b79ecca7a0fef214e"
|
||||
gnulib_hash="44100f563482fe469a33abecda5797da04fc3c61"
|
||||
|
||||
modules="
|
||||
futimens
|
||||
|
||||
744
configure.ac
744
configure.ac
File diff suppressed because it is too large
Load Diff
@@ -83,7 +83,7 @@
|
||||
<h2><a name="1.3"></a>1.3. Why the name change from TIP?</h2>
|
||||
<blockquote><p>On January 10, 2000, TIP was officially renamed to nano because of a namespace conflict with another program called 'tip'. The original 'tip' program "establishes a full duplex terminal connection to a remote host", and was included with many older Unix systems (and newer ones like Solaris). The conflict was not noticed at first because there is no 'tip' utility included with most GNU/Linux distributions (where nano was developed).</p></blockquote>
|
||||
<h2><a name="1.4"></a>1.4. What is the current version of nano?</h2>
|
||||
<blockquote><p>The current version of nano <i>should</i> be <b>2.9.1</b>. Of course, you should always check the <a href="https://nano-editor.org/">nano homepage</a> to see what the latest and greatest version is.</p></blockquote>
|
||||
<blockquote><p>The current version of nano <i>should</i> be <b>2.9.2</b>. Of course, you should always check the <a href="https://nano-editor.org/">nano homepage</a> to see what the latest and greatest version is.</p></blockquote>
|
||||
<h2><a name="1.5"></a>1.5. I want to read the man page without having to download the program!</h2>
|
||||
<blockquote><p>Jeez, demanding, aren't we? Okay, look <a href="https://nano-editor.org/dist/latest/nano.1.html">here</a>.</p></blockquote>
|
||||
<hr width="100%">
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
.\" Documentation License along with this program. If not, see
|
||||
.\" <http://www.gnu.org/licenses/>.
|
||||
.\"
|
||||
.TH NANO 1 "version 2.9.1" "November 2017"
|
||||
.TH NANO 1 "version 2.9.2" "January 2018"
|
||||
|
||||
.SH NAME
|
||||
nano \- Nano's ANOther editor, an enhanced free Pico clone
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
|
||||
@smallbook
|
||||
@set EDITION 0.5
|
||||
@set VERSION 2.9.1
|
||||
@set UPDATED November 2017
|
||||
@set VERSION 2.9.2
|
||||
@set UPDATED January 2018
|
||||
|
||||
@dircategory Editors
|
||||
@direntry
|
||||
@@ -23,7 +23,7 @@
|
||||
@titlepage
|
||||
@title GNU @command{nano}
|
||||
@subtitle a small and friendly text editor
|
||||
@subtitle version 2.9.1
|
||||
@subtitle version 2.9.2
|
||||
|
||||
@author Chris Allegretta
|
||||
@page
|
||||
@@ -63,7 +63,7 @@ e-mail: @email{chrisa@@asty.org}@*
|
||||
@node Top
|
||||
@top
|
||||
|
||||
This manual documents the GNU @command{nano} editor, version 2.9.1.
|
||||
This manual documents the GNU @command{nano} editor, version 2.9.2.
|
||||
|
||||
@menu
|
||||
* Introduction::
|
||||
@@ -753,9 +753,6 @@ And either @var{fgcolor} or ,@var{bgcolor} may be left out.
|
||||
Save the last hundred search strings and replacement strings and
|
||||
executed commands, so they can be easily reused in later sessions.
|
||||
|
||||
@item set justifytrim
|
||||
When justifying text, trailing whitespace will automatically be removed.
|
||||
|
||||
@item set keycolor @var{fgcolor},@var{bgcolor}
|
||||
Use this color combination for the shortcut key combos
|
||||
in the two help lines at the bottom of the screen.
|
||||
@@ -899,6 +896,10 @@ Save automatically on exit, don't prompt.
|
||||
Use this color combination for the title bar.
|
||||
@xref{@code{set functioncolor}} for valid color names.
|
||||
|
||||
@item set trimblanks
|
||||
Remove trailing whitespace from wrapped lines when automatic
|
||||
hard-wrapping occurs or when text is justified.
|
||||
|
||||
@item set unix
|
||||
Save a file by default in Unix format. This overrides nano's
|
||||
default behavior of saving a file in the format that it had.
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
.\" Documentation License along with this program. If not, see
|
||||
.\" <http://www.gnu.org/licenses/>.
|
||||
.\"
|
||||
.TH NANORC 5 "version 2.9.1" "November 2017"
|
||||
.TH NANORC 5 "version 2.9.2" "January 2018"
|
||||
|
||||
.SH NAME
|
||||
nanorc \- GNU nano's configuration file
|
||||
@@ -118,9 +118,6 @@ See \fBset titlecolor\fR for more details.
|
||||
Save the last hundred search strings and replacement strings and
|
||||
executed commands, so they can be easily reused in later sessions.
|
||||
.TP
|
||||
.B set justifytrim
|
||||
When justifying text, trailing whitespace will automatically be removed.
|
||||
.TP
|
||||
.B set keycolor \fIfgcolor\fR,\fIbgcolor\fR
|
||||
Specify the color combination to use for the shortcut key combos
|
||||
in the two help lines at the bottom of the screen.
|
||||
@@ -269,6 +266,10 @@ Valid names for the foreground and background colors are:
|
||||
The name of the foreground color may be prefixed with \fBbright\fR.
|
||||
And either "\fIfgcolor\fR" or ",\fIbgcolor\fR" may be left out.
|
||||
.TP
|
||||
.B set trimblanks
|
||||
Remove trailing whitespace from wrapped lines when automatic
|
||||
hard-wrapping occurs or when text is justified.
|
||||
.TP
|
||||
.B set unix
|
||||
Save a file by default in Unix format. This overrides nano's
|
||||
default behavior of saving a file in the format that it had.
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
.\" Documentation License along with this program. If not, see
|
||||
.\" <http://www.gnu.org/licenses/>.
|
||||
.\"
|
||||
.TH RNANO 1 "version 2.9.1" "November 2017"
|
||||
.TH RNANO 1 "version 2.9.2" "January 2018"
|
||||
|
||||
.SH NAME
|
||||
rnano \- a restricted nano
|
||||
|
||||
@@ -57,9 +57,6 @@
|
||||
## Remember the used search/replace strings for the next session.
|
||||
# set historylog
|
||||
|
||||
## Make the justify command kill whitespace at the end of lines.
|
||||
# set justifytrim
|
||||
|
||||
## Display line numbers to the left of the text.
|
||||
# set linenumbers
|
||||
|
||||
@@ -175,6 +172,9 @@
|
||||
## Save automatically on exit; don't prompt.
|
||||
# set tempfile
|
||||
|
||||
## Snip whitespace at the end of lines when justifying or hard-wrapping.
|
||||
# set trimblanks
|
||||
|
||||
## Disallow file modification. Why would you want this in an rcfile? ;)
|
||||
# set view
|
||||
|
||||
|
||||
826
po/nano.pot
826
po/nano.pot
File diff suppressed because it is too large
Load Diff
831
po/pt_BR.po
831
po/pt_BR.po
File diff suppressed because it is too large
Load Diff
820
po/zh_CN.po
820
po/zh_CN.po
File diff suppressed because it is too large
Load Diff
820
po/zh_TW.po
820
po/zh_TW.po
File diff suppressed because it is too large
Load Diff
1140
src/browser.c
1140
src/browser.c
File diff suppressed because it is too large
Load Diff
762
src/chars.c
762
src/chars.c
File diff suppressed because it is too large
Load Diff
576
src/color.c
576
src/color.c
@@ -33,7 +33,7 @@
|
||||
/* For early versions of ncurses-6.0, use an additional A_PROTECT attribute
|
||||
* for all colors, in order to work around an ncurses miscoloring bug. */
|
||||
#if defined(NCURSES_VERSION_MAJOR) && (NCURSES_VERSION_MAJOR == 6) && \
|
||||
(NCURSES_VERSION_MINOR == 0) && (NCURSES_VERSION_PATCH < 20151017)
|
||||
(NCURSES_VERSION_MINOR == 0) && (NCURSES_VERSION_PATCH < 20151017)
|
||||
#define A_BANDAID A_PROTECT
|
||||
#else
|
||||
#define A_BANDAID A_NORMAL
|
||||
@@ -43,394 +43,394 @@
|
||||
* for the colors in each syntax. */
|
||||
void set_colorpairs(void)
|
||||
{
|
||||
const syntaxtype *sint;
|
||||
bool using_defaults = FALSE;
|
||||
short foreground, background;
|
||||
size_t i;
|
||||
const syntaxtype *sint;
|
||||
bool using_defaults = FALSE;
|
||||
short foreground, background;
|
||||
size_t i;
|
||||
|
||||
/* Tell ncurses to enable colors. */
|
||||
start_color();
|
||||
/* Tell ncurses to enable colors. */
|
||||
start_color();
|
||||
|
||||
#ifdef HAVE_USE_DEFAULT_COLORS
|
||||
/* Allow using the default colors, if available. */
|
||||
using_defaults = (use_default_colors() != ERR);
|
||||
/* Allow using the default colors, if available. */
|
||||
using_defaults = (use_default_colors() != ERR);
|
||||
#endif
|
||||
|
||||
/* Initialize the color pairs for nano's interface elements. */
|
||||
for (i = 0; i < NUMBER_OF_ELEMENTS; i++) {
|
||||
bool bright = FALSE;
|
||||
/* Initialize the color pairs for nano's interface elements. */
|
||||
for (i = 0; i < NUMBER_OF_ELEMENTS; i++) {
|
||||
bool bright = FALSE;
|
||||
|
||||
if (specified_color_combo[i] != NULL &&
|
||||
parse_color_names(specified_color_combo[i],
|
||||
&foreground, &background, &bright)) {
|
||||
if (foreground == -1 && !using_defaults)
|
||||
foreground = COLOR_WHITE;
|
||||
if (background == -1 && !using_defaults)
|
||||
background = COLOR_BLACK;
|
||||
init_pair(i + 1, foreground, background);
|
||||
interface_color_pair[i] = COLOR_PAIR(i + 1) | A_BANDAID |
|
||||
(bright ? A_BOLD : A_NORMAL);
|
||||
} else {
|
||||
if (i != FUNCTION_TAG)
|
||||
interface_color_pair[i] = hilite_attribute;
|
||||
else
|
||||
interface_color_pair[i] = A_NORMAL;
|
||||
if (specified_color_combo[i] != NULL &&
|
||||
parse_color_names(specified_color_combo[i],
|
||||
&foreground, &background, &bright)) {
|
||||
if (foreground == -1 && !using_defaults)
|
||||
foreground = COLOR_WHITE;
|
||||
if (background == -1 && !using_defaults)
|
||||
background = COLOR_BLACK;
|
||||
init_pair(i + 1, foreground, background);
|
||||
interface_color_pair[i] = COLOR_PAIR(i + 1) | A_BANDAID |
|
||||
(bright ? A_BOLD : A_NORMAL);
|
||||
} else {
|
||||
if (i != FUNCTION_TAG)
|
||||
interface_color_pair[i] = hilite_attribute;
|
||||
else
|
||||
interface_color_pair[i] = A_NORMAL;
|
||||
}
|
||||
|
||||
free(specified_color_combo[i]);
|
||||
specified_color_combo[i] = NULL;
|
||||
}
|
||||
|
||||
free(specified_color_combo[i]);
|
||||
specified_color_combo[i] = NULL;
|
||||
}
|
||||
/* For each syntax, go through its list of colors and assign each
|
||||
* its pair number, giving identical color pairs the same number. */
|
||||
for (sint = syntaxes; sint != NULL; sint = sint->next) {
|
||||
colortype *ink;
|
||||
int new_number = NUMBER_OF_ELEMENTS + 1;
|
||||
|
||||
/* For each syntax, go through its list of colors and assign each
|
||||
* its pair number, giving identical color pairs the same number. */
|
||||
for (sint = syntaxes; sint != NULL; sint = sint->next) {
|
||||
colortype *ink;
|
||||
int new_number = NUMBER_OF_ELEMENTS + 1;
|
||||
for (ink = sint->color; ink != NULL; ink = ink->next) {
|
||||
const colortype *beforenow = sint->color;
|
||||
|
||||
for (ink = sint->color; ink != NULL; ink = ink->next) {
|
||||
const colortype *beforenow = sint->color;
|
||||
while (beforenow != ink && (beforenow->fg != ink->fg ||
|
||||
beforenow->bg != ink->bg ||
|
||||
beforenow->bright != ink->bright))
|
||||
beforenow = beforenow->next;
|
||||
|
||||
while (beforenow != ink && (beforenow->fg != ink->fg ||
|
||||
beforenow->bg != ink->bg ||
|
||||
beforenow->bright != ink->bright))
|
||||
beforenow = beforenow->next;
|
||||
if (beforenow != ink)
|
||||
ink->pairnum = beforenow->pairnum;
|
||||
else
|
||||
ink->pairnum = new_number++;
|
||||
|
||||
if (beforenow != ink)
|
||||
ink->pairnum = beforenow->pairnum;
|
||||
else
|
||||
ink->pairnum = new_number++;
|
||||
|
||||
ink->attributes = COLOR_PAIR(ink->pairnum) | A_BANDAID |
|
||||
(ink->bright ? A_BOLD : A_NORMAL);
|
||||
ink->attributes = COLOR_PAIR(ink->pairnum) | A_BANDAID |
|
||||
(ink->bright ? A_BOLD : A_NORMAL);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Initialize the color information. */
|
||||
void color_init(void)
|
||||
{
|
||||
const colortype *ink;
|
||||
bool using_defaults = FALSE;
|
||||
short foreground, background;
|
||||
const colortype *ink;
|
||||
bool using_defaults = FALSE;
|
||||
short foreground, background;
|
||||
|
||||
/* If the terminal is not capable of colors, forget it. */
|
||||
if (!has_colors())
|
||||
return;
|
||||
/* If the terminal is not capable of colors, forget it. */
|
||||
if (!has_colors())
|
||||
return;
|
||||
|
||||
#ifdef HAVE_USE_DEFAULT_COLORS
|
||||
/* Allow using the default colors, if available. */
|
||||
using_defaults = (use_default_colors() != ERR);
|
||||
/* Allow using the default colors, if available. */
|
||||
using_defaults = (use_default_colors() != ERR);
|
||||
#endif
|
||||
|
||||
/* For each coloring expression, initialize the color pair. */
|
||||
for (ink = openfile->colorstrings; ink != NULL; ink = ink->next) {
|
||||
foreground = ink->fg;
|
||||
background = ink->bg;
|
||||
/* For each coloring expression, initialize the color pair. */
|
||||
for (ink = openfile->colorstrings; ink != NULL; ink = ink->next) {
|
||||
foreground = ink->fg;
|
||||
background = ink->bg;
|
||||
|
||||
if (foreground == -1 && !using_defaults)
|
||||
foreground = COLOR_WHITE;
|
||||
if (foreground == -1 && !using_defaults)
|
||||
foreground = COLOR_WHITE;
|
||||
|
||||
if (background == -1 && !using_defaults)
|
||||
background = COLOR_BLACK;
|
||||
if (background == -1 && !using_defaults)
|
||||
background = COLOR_BLACK;
|
||||
|
||||
init_pair(ink->pairnum, foreground, background);
|
||||
}
|
||||
init_pair(ink->pairnum, foreground, background);
|
||||
}
|
||||
|
||||
have_palette = TRUE;
|
||||
have_palette = TRUE;
|
||||
}
|
||||
|
||||
/* Try to match the given shibboleth string with one of the regexes in
|
||||
* the list starting at head. Return TRUE upon success. */
|
||||
bool found_in_list(regexlisttype *head, const char *shibboleth)
|
||||
{
|
||||
regexlisttype *item;
|
||||
regex_t rgx;
|
||||
regexlisttype *item;
|
||||
regex_t rgx;
|
||||
|
||||
for (item = head; item != NULL; item = item->next) {
|
||||
regcomp(&rgx, fixbounds(item->full_regex), NANO_REG_EXTENDED);
|
||||
for (item = head; item != NULL; item = item->next) {
|
||||
regcomp(&rgx, fixbounds(item->full_regex), NANO_REG_EXTENDED);
|
||||
|
||||
if (regexec(&rgx, shibboleth, 0, NULL, 0) == 0) {
|
||||
regfree(&rgx);
|
||||
return TRUE;
|
||||
if (regexec(&rgx, shibboleth, 0, NULL, 0) == 0) {
|
||||
regfree(&rgx);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
regfree(&rgx);
|
||||
}
|
||||
|
||||
regfree(&rgx);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Update the color information based on the current filename and content. */
|
||||
void color_update(void)
|
||||
{
|
||||
syntaxtype *sint = NULL;
|
||||
colortype *ink;
|
||||
syntaxtype *sint = NULL;
|
||||
colortype *ink;
|
||||
|
||||
/* If the rcfiles were not read, or contained no syntaxes, get out. */
|
||||
if (syntaxes == NULL)
|
||||
return;
|
||||
/* If the rcfiles were not read, or contained no syntaxes, get out. */
|
||||
if (syntaxes == NULL)
|
||||
return;
|
||||
|
||||
/* If we specified a syntax-override string, use it. */
|
||||
if (syntaxstr != NULL) {
|
||||
/* An override of "none" is like having no syntax at all. */
|
||||
if (strcmp(syntaxstr, "none") == 0)
|
||||
return;
|
||||
/* If we specified a syntax-override string, use it. */
|
||||
if (syntaxstr != NULL) {
|
||||
/* An override of "none" is like having no syntax at all. */
|
||||
if (strcmp(syntaxstr, "none") == 0)
|
||||
return;
|
||||
|
||||
for (sint = syntaxes; sint != NULL; sint = sint->next) {
|
||||
if (strcmp(sint->name, syntaxstr) == 0)
|
||||
break;
|
||||
for (sint = syntaxes; sint != NULL; sint = sint->next) {
|
||||
if (strcmp(sint->name, syntaxstr) == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (sint == NULL && !inhelp)
|
||||
statusline(ALERT, _("Unknown syntax name: %s"), syntaxstr);
|
||||
}
|
||||
|
||||
if (sint == NULL && !inhelp)
|
||||
statusline(ALERT, _("Unknown syntax name: %s"), syntaxstr);
|
||||
}
|
||||
/* If no syntax-override string was specified, or it didn't match,
|
||||
* try finding a syntax based on the filename (extension). */
|
||||
if (sint == NULL && !inhelp) {
|
||||
char *reserved = charalloc(PATH_MAX + 1);
|
||||
char *currentdir = getcwd(reserved, PATH_MAX + 1);
|
||||
char *joinednames = charalloc(PATH_MAX + 1);
|
||||
char *fullname = NULL;
|
||||
|
||||
/* If no syntax-override string was specified, or it didn't match,
|
||||
* try finding a syntax based on the filename (extension). */
|
||||
if (sint == NULL && !inhelp) {
|
||||
char *reserved = charalloc(PATH_MAX + 1);
|
||||
char *currentdir = getcwd(reserved, PATH_MAX + 1);
|
||||
char *joinednames = charalloc(PATH_MAX + 1);
|
||||
char *fullname = NULL;
|
||||
if (currentdir == NULL)
|
||||
free(reserved);
|
||||
else {
|
||||
/* Concatenate the current working directory with the
|
||||
* specified filename, and canonicalize the result. */
|
||||
sprintf(joinednames, "%s/%s", currentdir, openfile->filename);
|
||||
fullname = get_full_path(joinednames);
|
||||
free(currentdir);
|
||||
}
|
||||
|
||||
if (currentdir == NULL)
|
||||
free(reserved);
|
||||
else {
|
||||
/* Concatenate the current working directory with the
|
||||
* specified filename, and canonicalize the result. */
|
||||
sprintf(joinednames, "%s/%s", currentdir, openfile->filename);
|
||||
fullname = get_full_path(joinednames);
|
||||
free(currentdir);
|
||||
if (fullname == NULL)
|
||||
fullname = mallocstrcpy(fullname, openfile->filename);
|
||||
|
||||
for (sint = syntaxes; sint != NULL; sint = sint->next) {
|
||||
if (found_in_list(sint->extensions, fullname))
|
||||
break;
|
||||
}
|
||||
|
||||
free(joinednames);
|
||||
free(fullname);
|
||||
}
|
||||
|
||||
if (fullname == NULL)
|
||||
fullname = mallocstrcpy(fullname, openfile->filename);
|
||||
|
||||
for (sint = syntaxes; sint != NULL; sint = sint->next) {
|
||||
if (found_in_list(sint->extensions, fullname))
|
||||
break;
|
||||
/* If the filename didn't match anything, try the first line. */
|
||||
if (sint == NULL && !inhelp) {
|
||||
for (sint = syntaxes; sint != NULL; sint = sint->next) {
|
||||
if (found_in_list(sint->headers, openfile->fileage->data))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
free(joinednames);
|
||||
free(fullname);
|
||||
}
|
||||
|
||||
/* If the filename didn't match anything, try the first line. */
|
||||
if (sint == NULL && !inhelp) {
|
||||
for (sint = syntaxes; sint != NULL; sint = sint->next) {
|
||||
if (found_in_list(sint->headers, openfile->fileage->data))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBMAGIC
|
||||
/* If we still don't have an answer, try using magic. */
|
||||
if (sint == NULL && !inhelp) {
|
||||
struct stat fileinfo;
|
||||
magic_t cookie = NULL;
|
||||
const char *magicstring = NULL;
|
||||
/* If we still don't have an answer, try using magic. */
|
||||
if (sint == NULL && !inhelp) {
|
||||
struct stat fileinfo;
|
||||
magic_t cookie = NULL;
|
||||
const char *magicstring = NULL;
|
||||
|
||||
if (stat(openfile->filename, &fileinfo) == 0) {
|
||||
/* Open the magic database and get a diagnosis of the file. */
|
||||
cookie = magic_open(MAGIC_SYMLINK |
|
||||
if (stat(openfile->filename, &fileinfo) == 0) {
|
||||
/* Open the magic database and get a diagnosis of the file. */
|
||||
cookie = magic_open(MAGIC_SYMLINK |
|
||||
#ifdef DEBUG
|
||||
MAGIC_DEBUG | MAGIC_CHECK |
|
||||
MAGIC_DEBUG | MAGIC_CHECK |
|
||||
#endif
|
||||
MAGIC_ERROR);
|
||||
if (cookie == NULL || magic_load(cookie, NULL) < 0)
|
||||
statusline(ALERT, _("magic_load() failed: %s"), strerror(errno));
|
||||
else {
|
||||
magicstring = magic_file(cookie, openfile->filename);
|
||||
if (magicstring == NULL)
|
||||
statusline(ALERT, _("magic_file(%s) failed: %s"),
|
||||
openfile->filename, magic_error(cookie));
|
||||
}
|
||||
}
|
||||
MAGIC_ERROR);
|
||||
if (cookie == NULL || magic_load(cookie, NULL) < 0)
|
||||
statusline(ALERT, _("magic_load() failed: %s"), strerror(errno));
|
||||
else {
|
||||
magicstring = magic_file(cookie, openfile->filename);
|
||||
if (magicstring == NULL)
|
||||
statusline(ALERT, _("magic_file(%s) failed: %s"),
|
||||
openfile->filename, magic_error(cookie));
|
||||
}
|
||||
}
|
||||
|
||||
/* Now try and find a syntax that matches the magic string. */
|
||||
if (magicstring != NULL) {
|
||||
for (sint = syntaxes; sint != NULL; sint = sint->next) {
|
||||
if (found_in_list(sint->magics, magicstring))
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Now try and find a syntax that matches the magic string. */
|
||||
if (magicstring != NULL) {
|
||||
for (sint = syntaxes; sint != NULL; sint = sint->next) {
|
||||
if (found_in_list(sint->magics, magicstring))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (stat(openfile->filename, &fileinfo) == 0)
|
||||
magic_close(cookie);
|
||||
}
|
||||
if (stat(openfile->filename, &fileinfo) == 0)
|
||||
magic_close(cookie);
|
||||
}
|
||||
#endif /* HAVE_LIBMAGIC */
|
||||
|
||||
/* If nothing at all matched, see if there is a default syntax. */
|
||||
if (sint == NULL && !inhelp) {
|
||||
for (sint = syntaxes; sint != NULL; sint = sint->next) {
|
||||
if (strcmp(sint->name, "default") == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
openfile->syntax = sint;
|
||||
openfile->colorstrings = (sint == NULL ? NULL : sint->color);
|
||||
|
||||
/* If a syntax was found, compile its specified regexes (which have
|
||||
* already been checked for validity when they were read in). */
|
||||
for (ink = openfile->colorstrings; ink != NULL; ink = ink->next) {
|
||||
if (ink->start == NULL) {
|
||||
ink->start = (regex_t *)nmalloc(sizeof(regex_t));
|
||||
regcomp(ink->start, fixbounds(ink->start_regex), ink->rex_flags);
|
||||
/* If nothing at all matched, see if there is a default syntax. */
|
||||
if (sint == NULL && !inhelp) {
|
||||
for (sint = syntaxes; sint != NULL; sint = sint->next) {
|
||||
if (strcmp(sint->name, "default") == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ink->end_regex != NULL && ink->end == NULL) {
|
||||
ink->end = (regex_t *)nmalloc(sizeof(regex_t));
|
||||
regcomp(ink->end, fixbounds(ink->end_regex), ink->rex_flags);
|
||||
openfile->syntax = sint;
|
||||
openfile->colorstrings = (sint == NULL ? NULL : sint->color);
|
||||
|
||||
/* If a syntax was found, compile its specified regexes (which have
|
||||
* already been checked for validity when they were read in). */
|
||||
for (ink = openfile->colorstrings; ink != NULL; ink = ink->next) {
|
||||
if (ink->start == NULL) {
|
||||
ink->start = (regex_t *)nmalloc(sizeof(regex_t));
|
||||
regcomp(ink->start, fixbounds(ink->start_regex), ink->rex_flags);
|
||||
}
|
||||
|
||||
if (ink->end_regex != NULL && ink->end == NULL) {
|
||||
ink->end = (regex_t *)nmalloc(sizeof(regex_t));
|
||||
regcomp(ink->end, fixbounds(ink->end_regex), ink->rex_flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Determine whether the matches of multiline regexes are still the same,
|
||||
* and if not, schedule a screen refresh, so things will be repainted. */
|
||||
void check_the_multis(filestruct *line)
|
||||
{
|
||||
const colortype *ink;
|
||||
bool astart, anend;
|
||||
regmatch_t startmatch, endmatch;
|
||||
const colortype *ink;
|
||||
bool astart, anend;
|
||||
regmatch_t startmatch, endmatch;
|
||||
|
||||
/* If there is no syntax or no multiline regex, there is nothing to do. */
|
||||
if (openfile->syntax == NULL || openfile->syntax->nmultis == 0)
|
||||
return;
|
||||
/* If there is no syntax or no multiline regex, there is nothing to do. */
|
||||
if (openfile->syntax == NULL || openfile->syntax->nmultis == 0)
|
||||
return;
|
||||
|
||||
for (ink = openfile->colorstrings; ink != NULL; ink = ink->next) {
|
||||
/* If it's not a multiline regex, skip. */
|
||||
if (ink->end == NULL)
|
||||
continue;
|
||||
for (ink = openfile->colorstrings; ink != NULL; ink = ink->next) {
|
||||
/* If it's not a multiline regex, skip. */
|
||||
if (ink->end == NULL)
|
||||
continue;
|
||||
|
||||
alloc_multidata_if_needed(line);
|
||||
alloc_multidata_if_needed(line);
|
||||
|
||||
astart = (regexec(ink->start, line->data, 1, &startmatch, 0) == 0);
|
||||
anend = (regexec(ink->end, line->data, 1, &endmatch, 0) == 0);
|
||||
astart = (regexec(ink->start, line->data, 1, &startmatch, 0) == 0);
|
||||
anend = (regexec(ink->end, line->data, 1, &endmatch, 0) == 0);
|
||||
|
||||
/* Check whether the multidata still matches the current situation. */
|
||||
if (line->multidata[ink->id] == CNONE ||
|
||||
line->multidata[ink->id] == CWHOLELINE) {
|
||||
if (!astart && !anend)
|
||||
continue;
|
||||
} else if (line->multidata[ink->id] == CSTARTENDHERE) {
|
||||
if (astart && anend && startmatch.rm_so < endmatch.rm_so)
|
||||
continue;
|
||||
} else if (line->multidata[ink->id] == CBEGINBEFORE) {
|
||||
if (!astart && anend)
|
||||
continue;
|
||||
} else if (line->multidata[ink->id] == CENDAFTER) {
|
||||
if (astart && !anend)
|
||||
continue;
|
||||
/* Check whether the multidata still matches the current situation. */
|
||||
if (line->multidata[ink->id] == CNONE ||
|
||||
line->multidata[ink->id] == CWHOLELINE) {
|
||||
if (!astart && !anend)
|
||||
continue;
|
||||
} else if (line->multidata[ink->id] == CSTARTENDHERE) {
|
||||
if (astart && anend && startmatch.rm_so < endmatch.rm_so)
|
||||
continue;
|
||||
} else if (line->multidata[ink->id] == CBEGINBEFORE) {
|
||||
if (!astart && anend)
|
||||
continue;
|
||||
} else if (line->multidata[ink->id] == CENDAFTER) {
|
||||
if (astart && !anend)
|
||||
continue;
|
||||
}
|
||||
|
||||
/* There is a mismatch, so something changed: repaint. */
|
||||
refresh_needed = TRUE;
|
||||
return;
|
||||
}
|
||||
|
||||
/* There is a mismatch, so something changed: repaint. */
|
||||
refresh_needed = TRUE;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Allocate (for one line) the cache space for multiline color regexes. */
|
||||
void alloc_multidata_if_needed(filestruct *fileptr)
|
||||
{
|
||||
int i;
|
||||
int i;
|
||||
|
||||
if (fileptr->multidata == NULL) {
|
||||
fileptr->multidata = (short *)nmalloc(openfile->syntax->nmultis * sizeof(short));
|
||||
if (fileptr->multidata == NULL) {
|
||||
fileptr->multidata = (short *)nmalloc(openfile->syntax->nmultis * sizeof(short));
|
||||
|
||||
for (i = 0; i < openfile->syntax->nmultis; i++)
|
||||
fileptr->multidata[i] = -1;
|
||||
}
|
||||
for (i = 0; i < openfile->syntax->nmultis; i++)
|
||||
fileptr->multidata[i] = -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Precalculate the multi-line start and end regex info so we can
|
||||
* speed up rendering (with any hope at all...). */
|
||||
void precalc_multicolorinfo(void)
|
||||
{
|
||||
const colortype *ink;
|
||||
regmatch_t startmatch, endmatch;
|
||||
filestruct *line, *tailline;
|
||||
const colortype *ink;
|
||||
regmatch_t startmatch, endmatch;
|
||||
filestruct *line, *tailline;
|
||||
|
||||
if (openfile->colorstrings == NULL || ISSET(NO_COLOR_SYNTAX))
|
||||
return;
|
||||
if (openfile->colorstrings == NULL || ISSET(NO_COLOR_SYNTAX))
|
||||
return;
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "Precalculating the multiline color info...\n");
|
||||
fprintf(stderr, "Precalculating the multiline color info...\n");
|
||||
#endif
|
||||
|
||||
for (ink = openfile->colorstrings; ink != NULL; ink = ink->next) {
|
||||
/* If this is not a multi-line regex, skip it. */
|
||||
if (ink->end == NULL)
|
||||
continue;
|
||||
for (ink = openfile->colorstrings; ink != NULL; ink = ink->next) {
|
||||
/* If this is not a multi-line regex, skip it. */
|
||||
if (ink->end == NULL)
|
||||
continue;
|
||||
|
||||
for (line = openfile->fileage; line != NULL; line = line->next) {
|
||||
int index = 0;
|
||||
for (line = openfile->fileage; line != NULL; line = line->next) {
|
||||
int index = 0;
|
||||
|
||||
alloc_multidata_if_needed(line);
|
||||
/* Assume nothing applies until proven otherwise below. */
|
||||
line->multidata[ink->id] = CNONE;
|
||||
alloc_multidata_if_needed(line);
|
||||
/* Assume nothing applies until proven otherwise below. */
|
||||
line->multidata[ink->id] = CNONE;
|
||||
|
||||
/* For an unpaired start match, mark all remaining lines. */
|
||||
if (line->prev && line->prev->multidata[ink->id] == CWOULDBE) {
|
||||
line->multidata[ink->id] = CWOULDBE;
|
||||
continue;
|
||||
}
|
||||
/* For an unpaired start match, mark all remaining lines. */
|
||||
if (line->prev && line->prev->multidata[ink->id] == CWOULDBE) {
|
||||
line->multidata[ink->id] = CWOULDBE;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* When the line contains a start match, look for an end, and if
|
||||
* found, mark all the lines that are affected. */
|
||||
while (regexec(ink->start, line->data + index, 1,
|
||||
&startmatch, (index == 0) ? 0 : REG_NOTBOL) == 0) {
|
||||
/* Begin looking for an end match after the start match. */
|
||||
index += startmatch.rm_eo;
|
||||
/* When the line contains a start match, look for an end, and if
|
||||
* found, mark all the lines that are affected. */
|
||||
while (regexec(ink->start, line->data + index, 1,
|
||||
&startmatch, (index == 0) ? 0 : REG_NOTBOL) == 0) {
|
||||
/* Begin looking for an end match after the start match. */
|
||||
index += startmatch.rm_eo;
|
||||
|
||||
/* If there is an end match on this line, mark the line, but
|
||||
* continue looking for other starts after it. */
|
||||
if (regexec(ink->end, line->data + index, 1,
|
||||
&endmatch, (index == 0) ? 0 : REG_NOTBOL) == 0) {
|
||||
line->multidata[ink->id] = CSTARTENDHERE;
|
||||
index += endmatch.rm_eo;
|
||||
/* If both start and end are mere anchors, step ahead. */
|
||||
if (startmatch.rm_so == startmatch.rm_eo &&
|
||||
endmatch.rm_so == endmatch.rm_eo) {
|
||||
/* When at end-of-line, we're done. */
|
||||
if (line->data[index] == '\0')
|
||||
break;
|
||||
index = move_mbright(line->data, index);
|
||||
}
|
||||
continue;
|
||||
/* If there is an end match on this line, mark the line, but
|
||||
* continue looking for other starts after it. */
|
||||
if (regexec(ink->end, line->data + index, 1,
|
||||
&endmatch, (index == 0) ? 0 : REG_NOTBOL) == 0) {
|
||||
line->multidata[ink->id] = CSTARTENDHERE;
|
||||
index += endmatch.rm_eo;
|
||||
/* If both start and end are mere anchors, step ahead. */
|
||||
if (startmatch.rm_so == startmatch.rm_eo &&
|
||||
endmatch.rm_so == endmatch.rm_eo) {
|
||||
/* When at end-of-line, we're done. */
|
||||
if (line->data[index] == '\0')
|
||||
break;
|
||||
index = move_mbright(line->data, index);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Look for an end match on later lines. */
|
||||
tailline = line->next;
|
||||
|
||||
while (tailline != NULL) {
|
||||
if (regexec(ink->end, tailline->data, 1, &endmatch, 0) == 0)
|
||||
break;
|
||||
tailline = tailline->next;
|
||||
}
|
||||
|
||||
if (tailline == NULL) {
|
||||
line->multidata[ink->id] = CWOULDBE;
|
||||
break;
|
||||
}
|
||||
|
||||
/* We found it, we found it, la la la la la. Mark all
|
||||
* the lines in between and the end properly. */
|
||||
line->multidata[ink->id] = CENDAFTER;
|
||||
|
||||
for (line = line->next; line != tailline; line = line->next) {
|
||||
alloc_multidata_if_needed(line);
|
||||
line->multidata[ink->id] = CWHOLELINE;
|
||||
}
|
||||
|
||||
alloc_multidata_if_needed(tailline);
|
||||
tailline->multidata[ink->id] = CBEGINBEFORE;
|
||||
|
||||
/* Begin looking for a new start after the end match. */
|
||||
index = endmatch.rm_eo;
|
||||
}
|
||||
}
|
||||
|
||||
/* Look for an end match on later lines. */
|
||||
tailline = line->next;
|
||||
|
||||
while (tailline != NULL) {
|
||||
if (regexec(ink->end, tailline->data, 1, &endmatch, 0) == 0)
|
||||
break;
|
||||
tailline = tailline->next;
|
||||
}
|
||||
|
||||
if (tailline == NULL) {
|
||||
line->multidata[ink->id] = CWOULDBE;
|
||||
break;
|
||||
}
|
||||
|
||||
/* We found it, we found it, la la la la la. Mark all
|
||||
* the lines in between and the end properly. */
|
||||
line->multidata[ink->id] = CENDAFTER;
|
||||
|
||||
for (line = line->next; line != tailline; line = line->next) {
|
||||
alloc_multidata_if_needed(line);
|
||||
line->multidata[ink->id] = CWHOLELINE;
|
||||
}
|
||||
|
||||
alloc_multidata_if_needed(tailline);
|
||||
tailline->multidata[ink->id] = CBEGINBEFORE;
|
||||
|
||||
/* Begin looking for a new start after the end match. */
|
||||
index = endmatch.rm_eo;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* ENABLE_COLOR */
|
||||
|
||||
296
src/cut.c
296
src/cut.c
@@ -25,18 +25,18 @@
|
||||
#include <string.h>
|
||||
|
||||
static bool keep_cutbuffer = FALSE;
|
||||
/* Should we keep the contents of the cutbuffer? */
|
||||
/* Should we keep the contents of the cutbuffer? */
|
||||
|
||||
/* Indicate that we should no longer keep the contents of the cutbuffer. */
|
||||
void cutbuffer_reset(void)
|
||||
{
|
||||
keep_cutbuffer = FALSE;
|
||||
keep_cutbuffer = FALSE;
|
||||
}
|
||||
|
||||
/* Return the status of cutbuffer preservation. */
|
||||
inline bool keeping_cutbuffer(void)
|
||||
{
|
||||
return keep_cutbuffer;
|
||||
return keep_cutbuffer;
|
||||
}
|
||||
|
||||
/* If we aren't on the last line of the file, move all the text of the
|
||||
@@ -46,13 +46,13 @@ inline bool keeping_cutbuffer(void)
|
||||
* current line. */
|
||||
void cut_line(void)
|
||||
{
|
||||
if (openfile->current != openfile->filebot)
|
||||
extract_buffer(&cutbuffer, &cutbottom, openfile->current, 0,
|
||||
openfile->current->next, 0);
|
||||
else
|
||||
extract_buffer(&cutbuffer, &cutbottom, openfile->current, 0,
|
||||
openfile->current, strlen(openfile->current->data));
|
||||
openfile->placewewant = 0;
|
||||
if (openfile->current != openfile->filebot)
|
||||
extract_buffer(&cutbuffer, &cutbottom, openfile->current, 0,
|
||||
openfile->current->next, 0);
|
||||
else
|
||||
extract_buffer(&cutbuffer, &cutbottom, openfile->current, 0,
|
||||
openfile->current, strlen(openfile->current->data));
|
||||
openfile->placewewant = 0;
|
||||
}
|
||||
|
||||
#ifndef NANO_TINY
|
||||
@@ -60,14 +60,14 @@ void cut_line(void)
|
||||
* current place we want to where the text used to start. */
|
||||
void cut_marked(bool *right_side_up)
|
||||
{
|
||||
filestruct *top, *bot;
|
||||
size_t top_x, bot_x;
|
||||
filestruct *top, *bot;
|
||||
size_t top_x, bot_x;
|
||||
|
||||
mark_order((const filestruct **)&top, &top_x,
|
||||
(const filestruct **)&bot, &bot_x, right_side_up);
|
||||
mark_order((const filestruct **)&top, &top_x,
|
||||
(const filestruct **)&bot, &bot_x, right_side_up);
|
||||
|
||||
extract_buffer(&cutbuffer, &cutbottom, top, top_x, bot, bot_x);
|
||||
openfile->placewewant = xplustabs();
|
||||
extract_buffer(&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
|
||||
@@ -78,32 +78,32 @@ void cut_marked(bool *right_side_up)
|
||||
* newline used to be. */
|
||||
void cut_to_eol(void)
|
||||
{
|
||||
size_t data_len = strlen(openfile->current->data);
|
||||
size_t data_len = strlen(openfile->current->data);
|
||||
|
||||
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. */
|
||||
extract_buffer(&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. */
|
||||
extract_buffer(&cutbuffer, &cutbottom, openfile->current,
|
||||
openfile->current_x, openfile->current->next, 0);
|
||||
openfile->placewewant = xplustabs();
|
||||
}
|
||||
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. */
|
||||
extract_buffer(&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. */
|
||||
extract_buffer(&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)
|
||||
{
|
||||
extract_buffer(&cutbuffer, &cutbottom,
|
||||
openfile->current, openfile->current_x,
|
||||
openfile->filebot, strlen(openfile->filebot->data));
|
||||
extract_buffer(&cutbuffer, &cutbottom,
|
||||
openfile->current, openfile->current_x,
|
||||
openfile->filebot, strlen(openfile->filebot->data));
|
||||
}
|
||||
#endif /* !NANO_TINY */
|
||||
|
||||
@@ -114,86 +114,86 @@ void cut_to_eof(void)
|
||||
void do_cut_text(bool copy_text, bool cut_till_eof)
|
||||
{
|
||||
#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);
|
||||
bool right_side_up = TRUE;
|
||||
/* There *is* no region, *or* it is marked forward. */
|
||||
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);
|
||||
bool right_side_up = TRUE;
|
||||
/* There *is* no region, *or* it is marked forward. */
|
||||
#endif
|
||||
size_t was_totsize = openfile->totsize;
|
||||
size_t was_totsize = openfile->totsize;
|
||||
|
||||
/* If a chain of cuts was broken, empty the cutbuffer. */
|
||||
if (!keep_cutbuffer) {
|
||||
free_filestruct(cutbuffer);
|
||||
cutbuffer = NULL;
|
||||
/* Indicate that future cuts should add to the cutbuffer. */
|
||||
keep_cutbuffer = TRUE;
|
||||
}
|
||||
/* If a chain of cuts was broken, empty the cutbuffer. */
|
||||
if (!keep_cutbuffer) {
|
||||
free_filestruct(cutbuffer);
|
||||
cutbuffer = NULL;
|
||||
/* Indicate that future cuts should add to the cutbuffer. */
|
||||
keep_cutbuffer = TRUE;
|
||||
}
|
||||
|
||||
#ifndef NANO_TINY
|
||||
if (copy_text) {
|
||||
/* If the cutbuffer isn't empty, remember where it currently ends. */
|
||||
if (cutbuffer != NULL) {
|
||||
cb_save = cutbottom;
|
||||
cb_save_len = strlen(cutbottom->data);
|
||||
if (copy_text) {
|
||||
/* If the cutbuffer isn't empty, remember where it currently ends. */
|
||||
if (cutbuffer != NULL) {
|
||||
cb_save = cutbottom;
|
||||
cb_save_len = strlen(cutbottom->data);
|
||||
}
|
||||
/* Don't add a magicline when moving text to the cutbuffer. */
|
||||
SET(NO_NEWLINES);
|
||||
}
|
||||
/* Don't add a magicline when moving text to the cutbuffer. */
|
||||
SET(NO_NEWLINES);
|
||||
}
|
||||
|
||||
if (cut_till_eof) {
|
||||
/* Move all text up to the end of the file into the cutbuffer. */
|
||||
cut_to_eof();
|
||||
} else if (openfile->mark) {
|
||||
/* Move the marked text to the cutbuffer, and turn the mark off. */
|
||||
cut_marked(&right_side_up);
|
||||
openfile->mark = NULL;
|
||||
} else if (ISSET(CUT_FROM_CURSOR))
|
||||
/* Move all text up to the end of the line into the cutbuffer. */
|
||||
cut_to_eol();
|
||||
else
|
||||
if (cut_till_eof) {
|
||||
/* Move all text up to the end of the file into the cutbuffer. */
|
||||
cut_to_eof();
|
||||
} else if (openfile->mark) {
|
||||
/* Move the marked text to the cutbuffer, and turn the mark off. */
|
||||
cut_marked(&right_side_up);
|
||||
openfile->mark = NULL;
|
||||
} else if (ISSET(CUT_FROM_CURSOR))
|
||||
/* 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();
|
||||
/* Move the entire line into the cutbuffer. */
|
||||
cut_line();
|
||||
|
||||
#ifndef NANO_TINY
|
||||
if (copy_text) {
|
||||
/* Copy the text that is in the cutbuffer (starting at its saved end,
|
||||
* if there is one) back into the current buffer. This effectively
|
||||
* uncuts the text we just cut. */
|
||||
if (cutbuffer != NULL) {
|
||||
if (cb_save != NULL) {
|
||||
cb_save->data += cb_save_len;
|
||||
copy_from_buffer(cb_save);
|
||||
cb_save->data -= cb_save_len;
|
||||
} else
|
||||
copy_from_buffer(cutbuffer);
|
||||
if (copy_text) {
|
||||
/* Copy the text that is in the cutbuffer (starting at its saved end,
|
||||
* if there is one) back into the current buffer. This effectively
|
||||
* uncuts the text we just cut. */
|
||||
if (cutbuffer != NULL) {
|
||||
if (cb_save != NULL) {
|
||||
cb_save->data += cb_save_len;
|
||||
copy_from_buffer(cb_save);
|
||||
cb_save->data -= cb_save_len;
|
||||
} else
|
||||
copy_from_buffer(cutbuffer);
|
||||
|
||||
/* If the copied region was marked forward, put the new desired
|
||||
* x position at its end; otherwise, leave it at its beginning. */
|
||||
if (right_side_up)
|
||||
openfile->placewewant = xplustabs();
|
||||
}
|
||||
/* Restore the magicline behavior now that we're done fiddling. */
|
||||
if (!old_no_newlines)
|
||||
UNSET(NO_NEWLINES);
|
||||
} else
|
||||
/* If the copied region was marked forward, put the new desired
|
||||
* x position at its end; otherwise, leave it at its beginning. */
|
||||
if (right_side_up)
|
||||
openfile->placewewant = xplustabs();
|
||||
}
|
||||
/* Restore the magicline behavior now that we're done fiddling. */
|
||||
if (!old_no_newlines)
|
||||
UNSET(NO_NEWLINES);
|
||||
} else
|
||||
#endif /* !NANO_TINY */
|
||||
/* Only set the modification flag if actually something was cut. */
|
||||
if (openfile->totsize != was_totsize)
|
||||
set_modified();
|
||||
/* Only set the modification flag if actually something was cut. */
|
||||
if (openfile->totsize != was_totsize)
|
||||
set_modified();
|
||||
|
||||
refresh_needed = TRUE;
|
||||
refresh_needed = TRUE;
|
||||
|
||||
#ifdef ENABLE_COLOR
|
||||
check_the_multis(openfile->current);
|
||||
check_the_multis(openfile->current);
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
dump_filestruct(cutbuffer);
|
||||
dump_filestruct(cutbuffer);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -201,11 +201,11 @@ void do_cut_text(bool copy_text, bool cut_till_eof)
|
||||
void do_cut_text_void(void)
|
||||
{
|
||||
#ifndef NANO_TINY
|
||||
add_undo(CUT);
|
||||
add_undo(CUT);
|
||||
#endif
|
||||
do_cut_text(FALSE, FALSE);
|
||||
do_cut_text(FALSE, FALSE);
|
||||
#ifndef NANO_TINY
|
||||
update_undo(CUT);
|
||||
update_undo(CUT);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -215,85 +215,79 @@ void do_cut_text_void(void)
|
||||
* was moved, blow away previous contents of the cutbuffer. */
|
||||
void do_copy_text(void)
|
||||
{
|
||||
static struct filestruct *next_contiguous_line = NULL;
|
||||
bool mark_is_set = (openfile->mark != NULL);
|
||||
static struct filestruct *next_contiguous_line = NULL;
|
||||
bool mark_is_set = (openfile->mark != NULL);
|
||||
|
||||
/* Remember the current viewport and cursor position. */
|
||||
ssize_t is_edittop_lineno = openfile->edittop->lineno;
|
||||
size_t is_firstcolumn = openfile->firstcolumn;
|
||||
ssize_t is_current_lineno = openfile->current->lineno;
|
||||
size_t is_current_x = openfile->current_x;
|
||||
/* Remember the current viewport and cursor position. */
|
||||
ssize_t is_edittop_lineno = openfile->edittop->lineno;
|
||||
size_t is_firstcolumn = openfile->firstcolumn;
|
||||
ssize_t is_current_lineno = openfile->current->lineno;
|
||||
size_t is_current_x = openfile->current_x;
|
||||
|
||||
if (mark_is_set || openfile->current != next_contiguous_line)
|
||||
cutbuffer_reset();
|
||||
if (mark_is_set || openfile->current != next_contiguous_line)
|
||||
cutbuffer_reset();
|
||||
|
||||
do_cut_text(TRUE, FALSE);
|
||||
do_cut_text(TRUE, FALSE);
|
||||
|
||||
/* If the mark was set, blow away the cutbuffer on the next copy. */
|
||||
next_contiguous_line = (mark_is_set ? NULL : openfile->current);
|
||||
/* If the mark was set, blow away the cutbuffer on the next copy. */
|
||||
next_contiguous_line = (mark_is_set ? NULL : openfile->current);
|
||||
|
||||
/* If the mark was set, restore the viewport and cursor position. */
|
||||
if (mark_is_set) {
|
||||
openfile->edittop = fsfromline(is_edittop_lineno);
|
||||
openfile->firstcolumn = is_firstcolumn;
|
||||
openfile->current = fsfromline(is_current_lineno);
|
||||
openfile->current_x = is_current_x;
|
||||
}
|
||||
/* If the mark was set, restore the viewport and cursor position. */
|
||||
if (mark_is_set) {
|
||||
openfile->edittop = fsfromline(is_edittop_lineno);
|
||||
openfile->firstcolumn = is_firstcolumn;
|
||||
openfile->current = fsfromline(is_current_lineno);
|
||||
openfile->current_x = is_current_x;
|
||||
}
|
||||
}
|
||||
|
||||
/* Cut from the current cursor position to the end of the file. */
|
||||
void do_cut_till_eof(void)
|
||||
{
|
||||
add_undo(CUT_TO_EOF);
|
||||
do_cut_text(FALSE, TRUE);
|
||||
update_undo(CUT_TO_EOF);
|
||||
add_undo(CUT_TO_EOF);
|
||||
do_cut_text(FALSE, TRUE);
|
||||
update_undo(CUT_TO_EOF);
|
||||
}
|
||||
#endif /* !NANO_TINY */
|
||||
|
||||
/* Copy text from the cutbuffer into the current buffer. */
|
||||
void do_uncut_text(void)
|
||||
{
|
||||
ssize_t was_lineno = openfile->current->lineno;
|
||||
/* The line number where we started the paste. */
|
||||
size_t was_leftedge = 0;
|
||||
/* The leftedge where we started the paste. */
|
||||
ssize_t was_lineno = openfile->current->lineno;
|
||||
/* The line number where we started the paste. */
|
||||
size_t was_leftedge = 0;
|
||||
/* The leftedge where we started the paste. */
|
||||
|
||||
/* If the cutbuffer is empty, there is nothing to do. */
|
||||
if (cutbuffer == NULL)
|
||||
return;
|
||||
/* If the cutbuffer is empty, there is nothing to do. */
|
||||
if (cutbuffer == NULL)
|
||||
return;
|
||||
|
||||
#ifndef NANO_TINY
|
||||
add_undo(PASTE);
|
||||
add_undo(PASTE);
|
||||
|
||||
if (ISSET(SOFTWRAP))
|
||||
was_leftedge = leftedge_for(xplustabs(), openfile->current);
|
||||
if (ISSET(SOFTWRAP))
|
||||
was_leftedge = leftedge_for(xplustabs(), openfile->current);
|
||||
#endif
|
||||
|
||||
/* Add a copy of the text in the cutbuffer to the current buffer
|
||||
* at the current cursor position. */
|
||||
copy_from_buffer(cutbuffer);
|
||||
/* Add a copy of the text in the cutbuffer to the current buffer
|
||||
* at the current cursor position. */
|
||||
copy_from_buffer(cutbuffer);
|
||||
|
||||
#ifndef NANO_TINY
|
||||
update_undo(PASTE);
|
||||
update_undo(PASTE);
|
||||
#endif
|
||||
|
||||
/* If we pasted less than a screenful, don't center the cursor. */
|
||||
if (less_than_a_screenful(was_lineno, was_leftedge))
|
||||
focusing = FALSE;
|
||||
/* If we pasted less than a screenful, don't center the cursor. */
|
||||
if (less_than_a_screenful(was_lineno, was_leftedge))
|
||||
focusing = FALSE;
|
||||
|
||||
/* Set the desired x position to where the pasted text ends. */
|
||||
openfile->placewewant = xplustabs();
|
||||
/* Set the desired x position to where the pasted text ends. */
|
||||
openfile->placewewant = xplustabs();
|
||||
|
||||
/* Mark the file as modified. */
|
||||
set_modified();
|
||||
|
||||
refresh_needed = TRUE;
|
||||
set_modified();
|
||||
refresh_needed = TRUE;
|
||||
|
||||
#ifdef ENABLE_COLOR
|
||||
check_the_multis(openfile->current);
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
dump_filestruct_reverse();
|
||||
check_the_multis(openfile->current);
|
||||
#endif
|
||||
}
|
||||
|
||||
3778
src/files.c
3778
src/files.c
File diff suppressed because it is too large
Load Diff
2350
src/global.c
2350
src/global.c
File diff suppressed because it is too large
Load Diff
946
src/help.c
946
src/help.c
File diff suppressed because it is too large
Load Diff
798
src/history.c
798
src/history.c
@@ -35,146 +35,146 @@
|
||||
#endif
|
||||
|
||||
static bool history_changed = FALSE;
|
||||
/* Whether any of the history lists has changed. */
|
||||
/* Whether any of the history lists has changed. */
|
||||
static struct stat stat_of_positions_file;
|
||||
/* The last-obtained stat information of the positions file. */
|
||||
/* The last-obtained stat information of the positions file. */
|
||||
static char *poshistname = NULL;
|
||||
/* The name of the positions-history file. */
|
||||
/* The name of the positions-history file. */
|
||||
|
||||
/* Initialize the lists of historical search and replace strings
|
||||
* and the list of historical executed commands. */
|
||||
void history_init(void)
|
||||
{
|
||||
search_history = make_new_node(NULL);
|
||||
search_history->data = mallocstrcpy(NULL, "");
|
||||
searchtop = search_history;
|
||||
searchbot = search_history;
|
||||
search_history = make_new_node(NULL);
|
||||
search_history->data = mallocstrcpy(NULL, "");
|
||||
searchtop = search_history;
|
||||
searchbot = search_history;
|
||||
|
||||
replace_history = make_new_node(NULL);
|
||||
replace_history->data = mallocstrcpy(NULL, "");
|
||||
replacetop = replace_history;
|
||||
replacebot = replace_history;
|
||||
replace_history = make_new_node(NULL);
|
||||
replace_history->data = mallocstrcpy(NULL, "");
|
||||
replacetop = replace_history;
|
||||
replacebot = replace_history;
|
||||
|
||||
execute_history = make_new_node(NULL);
|
||||
execute_history->data = mallocstrcpy(NULL, "");
|
||||
executetop = execute_history;
|
||||
executebot = execute_history;
|
||||
execute_history = make_new_node(NULL);
|
||||
execute_history->data = mallocstrcpy(NULL, "");
|
||||
executetop = execute_history;
|
||||
executebot = execute_history;
|
||||
}
|
||||
|
||||
/* Set the current position in the given history list to the bottom. */
|
||||
void history_reset(const filestruct *list)
|
||||
{
|
||||
if (list == search_history)
|
||||
search_history = searchbot;
|
||||
else if (list == replace_history)
|
||||
replace_history = replacebot;
|
||||
else if (list == execute_history)
|
||||
execute_history = executebot;
|
||||
if (list == search_history)
|
||||
search_history = searchbot;
|
||||
else if (list == replace_history)
|
||||
replace_history = replacebot;
|
||||
else if (list == execute_history)
|
||||
execute_history = executebot;
|
||||
}
|
||||
|
||||
/* Return from the history list that starts at start and ends at end
|
||||
* the first node that contains the first len characters of the given
|
||||
* text, or NULL if there is no such node. */
|
||||
filestruct *find_history(const filestruct *start, const filestruct *end,
|
||||
const char *text, size_t len)
|
||||
const char *text, size_t len)
|
||||
{
|
||||
const filestruct *item;
|
||||
const filestruct *item;
|
||||
|
||||
for (item = start; item != end->prev && item != NULL; item = item->prev) {
|
||||
if (strncmp(item->data, text, len) == 0)
|
||||
return (filestruct *)item;
|
||||
}
|
||||
for (item = start; item != end->prev && item != NULL; item = item->prev) {
|
||||
if (strncmp(item->data, text, len) == 0)
|
||||
return (filestruct *)item;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Update a history list (the one in which item is the current position)
|
||||
* with a fresh string text. That is: add text, or move it to the end. */
|
||||
void update_history(filestruct **item, const char *text)
|
||||
{
|
||||
filestruct **htop = NULL, **hbot = NULL, *thesame;
|
||||
filestruct **htop = NULL, **hbot = NULL, *thesame;
|
||||
|
||||
if (*item == search_history) {
|
||||
htop = &searchtop;
|
||||
hbot = &searchbot;
|
||||
} else if (*item == replace_history) {
|
||||
htop = &replacetop;
|
||||
hbot = &replacebot;
|
||||
} else if (*item == execute_history) {
|
||||
htop = &executetop;
|
||||
hbot = &executebot;
|
||||
}
|
||||
if (*item == search_history) {
|
||||
htop = &searchtop;
|
||||
hbot = &searchbot;
|
||||
} else if (*item == replace_history) {
|
||||
htop = &replacetop;
|
||||
hbot = &replacebot;
|
||||
} else if (*item == execute_history) {
|
||||
htop = &executetop;
|
||||
hbot = &executebot;
|
||||
}
|
||||
|
||||
/* See if the string is already in the history. */
|
||||
thesame = find_history(*hbot, *htop, text, HIGHEST_POSITIVE);
|
||||
/* See if the string is already in the history. */
|
||||
thesame = find_history(*hbot, *htop, text, HIGHEST_POSITIVE);
|
||||
|
||||
/* If an identical string was found, delete that item. */
|
||||
if (thesame != NULL) {
|
||||
filestruct *after = thesame->next;
|
||||
/* If an identical string was found, delete that item. */
|
||||
if (thesame != NULL) {
|
||||
filestruct *after = thesame->next;
|
||||
|
||||
/* If the string is at the head of the list, move the head. */
|
||||
if (thesame == *htop)
|
||||
*htop = after;
|
||||
/* If the string is at the head of the list, move the head. */
|
||||
if (thesame == *htop)
|
||||
*htop = after;
|
||||
|
||||
unlink_node(thesame);
|
||||
renumber(after);
|
||||
}
|
||||
unlink_node(thesame);
|
||||
renumber(after);
|
||||
}
|
||||
|
||||
/* If the history is full, delete the oldest item (the one at the
|
||||
* head of the list), to make room for a new item at the end. */
|
||||
if ((*hbot)->lineno == MAX_SEARCH_HISTORY + 1) {
|
||||
filestruct *oldest = *htop;
|
||||
/* If the history is full, delete the oldest item (the one at the
|
||||
* head of the list), to make room for a new item at the end. */
|
||||
if ((*hbot)->lineno == MAX_SEARCH_HISTORY + 1) {
|
||||
filestruct *oldest = *htop;
|
||||
|
||||
*htop = (*htop)->next;
|
||||
unlink_node(oldest);
|
||||
renumber(*htop);
|
||||
}
|
||||
*htop = (*htop)->next;
|
||||
unlink_node(oldest);
|
||||
renumber(*htop);
|
||||
}
|
||||
|
||||
/* Store the fresh string in the last item, then create a new item. */
|
||||
(*hbot)->data = mallocstrcpy((*hbot)->data, text);
|
||||
splice_node(*hbot, make_new_node(*hbot));
|
||||
*hbot = (*hbot)->next;
|
||||
(*hbot)->data = mallocstrcpy(NULL, "");
|
||||
/* Store the fresh string in the last item, then create a new item. */
|
||||
(*hbot)->data = mallocstrcpy((*hbot)->data, text);
|
||||
splice_node(*hbot, make_new_node(*hbot));
|
||||
*hbot = (*hbot)->next;
|
||||
(*hbot)->data = mallocstrcpy(NULL, "");
|
||||
|
||||
/* Indicate that the history needs to be saved on exit. */
|
||||
history_changed = TRUE;
|
||||
/* Indicate that the history needs to be saved on exit. */
|
||||
history_changed = TRUE;
|
||||
|
||||
/* Set the current position in the list to the bottom. */
|
||||
*item = *hbot;
|
||||
/* Set the current position in the list to the bottom. */
|
||||
*item = *hbot;
|
||||
}
|
||||
|
||||
/* Move h to the string in the history list just before it, and return
|
||||
* that string. If there isn't one, don't move h and return NULL. */
|
||||
char *get_history_older(filestruct **h)
|
||||
{
|
||||
if ((*h)->prev == NULL)
|
||||
return NULL;
|
||||
if ((*h)->prev == NULL)
|
||||
return NULL;
|
||||
|
||||
*h = (*h)->prev;
|
||||
*h = (*h)->prev;
|
||||
|
||||
return (*h)->data;
|
||||
return (*h)->data;
|
||||
}
|
||||
|
||||
/* Move h to the string in the history list just after it, and return
|
||||
* that string. If there isn't one, don't move h and return NULL. */
|
||||
char *get_history_newer(filestruct **h)
|
||||
{
|
||||
if ((*h)->next == NULL)
|
||||
return NULL;
|
||||
if ((*h)->next == NULL)
|
||||
return NULL;
|
||||
|
||||
*h = (*h)->next;
|
||||
*h = (*h)->next;
|
||||
|
||||
return (*h)->data;
|
||||
return (*h)->data;
|
||||
}
|
||||
|
||||
/* More placeholders. */
|
||||
void get_history_newer_void(void)
|
||||
{
|
||||
;
|
||||
;
|
||||
}
|
||||
void get_history_older_void(void)
|
||||
{
|
||||
;
|
||||
;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_TABCOMP
|
||||
@@ -184,408 +184,408 @@ void get_history_older_void(void)
|
||||
* s. */
|
||||
char *get_history_completion(filestruct **h, char *s, size_t len)
|
||||
{
|
||||
if (len > 0) {
|
||||
filestruct *htop = NULL, *hbot = NULL, *p;
|
||||
if (len > 0) {
|
||||
filestruct *htop = NULL, *hbot = NULL, *p;
|
||||
|
||||
if (*h == search_history) {
|
||||
htop = searchtop;
|
||||
hbot = searchbot;
|
||||
} else if (*h == replace_history) {
|
||||
htop = replacetop;
|
||||
hbot = replacebot;
|
||||
} else if (*h == execute_history) {
|
||||
htop = executetop;
|
||||
hbot = executebot;
|
||||
if (*h == search_history) {
|
||||
htop = searchtop;
|
||||
hbot = searchbot;
|
||||
} else if (*h == replace_history) {
|
||||
htop = replacetop;
|
||||
hbot = replacebot;
|
||||
} else if (*h == execute_history) {
|
||||
htop = executetop;
|
||||
hbot = executebot;
|
||||
}
|
||||
|
||||
/* Search the history list from the current position to the top
|
||||
* for a match of len characters. Skip over an exact match. */
|
||||
p = find_history((*h)->prev, htop, s, len);
|
||||
|
||||
while (p != NULL && strcmp(p->data, s) == 0)
|
||||
p = find_history(p->prev, htop, s, len);
|
||||
|
||||
if (p != NULL) {
|
||||
*h = p;
|
||||
return mallocstrcpy(s, (*h)->data);
|
||||
}
|
||||
|
||||
/* Search the history list from the bottom to the current position
|
||||
* for a match of len characters. Skip over an exact match. */
|
||||
p = find_history(hbot, *h, s, len);
|
||||
|
||||
while (p != NULL && strcmp(p->data, s) == 0)
|
||||
p = find_history(p->prev, *h, s, len);
|
||||
|
||||
if (p != NULL) {
|
||||
*h = p;
|
||||
return mallocstrcpy(s, (*h)->data);
|
||||
}
|
||||
}
|
||||
|
||||
/* Search the history list from the current position to the top
|
||||
* for a match of len characters. Skip over an exact match. */
|
||||
p = find_history((*h)->prev, htop, s, len);
|
||||
|
||||
while (p != NULL && strcmp(p->data, s) == 0)
|
||||
p = find_history(p->prev, htop, s, len);
|
||||
|
||||
if (p != NULL) {
|
||||
*h = p;
|
||||
return mallocstrcpy(s, (*h)->data);
|
||||
}
|
||||
|
||||
/* Search the history list from the bottom to the current position
|
||||
* for a match of len characters. Skip over an exact match. */
|
||||
p = find_history(hbot, *h, s, len);
|
||||
|
||||
while (p != NULL && strcmp(p->data, s) == 0)
|
||||
p = find_history(p->prev, *h, s, len);
|
||||
|
||||
if (p != NULL) {
|
||||
*h = p;
|
||||
return mallocstrcpy(s, (*h)->data);
|
||||
}
|
||||
}
|
||||
|
||||
/* If we're here, we didn't find a match, we didn't find an inexact
|
||||
* match, or len is 0. Return s. */
|
||||
return (char *)s;
|
||||
/* If we're here, we didn't find a match, we didn't find an inexact
|
||||
* match, or len is 0. Return s. */
|
||||
return (char *)s;
|
||||
}
|
||||
#endif /* ENSABLE_TABCOMP */
|
||||
|
||||
void history_error(const char *msg, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, msg);
|
||||
vfprintf(stderr, _(msg), ap);
|
||||
va_end(ap);
|
||||
va_start(ap, msg);
|
||||
vfprintf(stderr, _(msg), ap);
|
||||
va_end(ap);
|
||||
|
||||
fprintf(stderr, _("\nPress Enter to continue\n"));
|
||||
while (getchar() != '\n')
|
||||
;
|
||||
fprintf(stderr, _("\nPress Enter to continue\n"));
|
||||
while (getchar() != '\n')
|
||||
;
|
||||
}
|
||||
|
||||
/* Check whether we have or could make a directory for history files. */
|
||||
bool have_statedir(void)
|
||||
{
|
||||
struct stat dirstat;
|
||||
const char *xdgdatadir;
|
||||
struct stat dirstat;
|
||||
const char *xdgdatadir;
|
||||
|
||||
get_homedir();
|
||||
get_homedir();
|
||||
|
||||
if (homedir != NULL) {
|
||||
statedir = concatenate(homedir, "/.nano/");
|
||||
if (homedir != NULL) {
|
||||
statedir = concatenate(homedir, "/.nano/");
|
||||
|
||||
if (stat(statedir, &dirstat) == 0 && S_ISDIR(dirstat.st_mode)) {
|
||||
poshistname = concatenate(statedir, POSITION_HISTORY);
|
||||
return TRUE;
|
||||
if (stat(statedir, &dirstat) == 0 && S_ISDIR(dirstat.st_mode)) {
|
||||
poshistname = concatenate(statedir, POSITION_HISTORY);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free(statedir);
|
||||
xdgdatadir = getenv("XDG_DATA_HOME");
|
||||
free(statedir);
|
||||
xdgdatadir = getenv("XDG_DATA_HOME");
|
||||
|
||||
if (homedir == NULL && xdgdatadir == NULL)
|
||||
return FALSE;
|
||||
if (homedir == NULL && xdgdatadir == NULL)
|
||||
return FALSE;
|
||||
|
||||
if (xdgdatadir != NULL)
|
||||
statedir = concatenate(xdgdatadir, "/nano/");
|
||||
else
|
||||
statedir = concatenate(homedir, "/.local/share/nano/");
|
||||
if (xdgdatadir != NULL)
|
||||
statedir = concatenate(xdgdatadir, "/nano/");
|
||||
else
|
||||
statedir = concatenate(homedir, "/.local/share/nano/");
|
||||
|
||||
if (stat(statedir, &dirstat) == -1) {
|
||||
if (xdgdatadir == NULL) {
|
||||
char *statepath = concatenate(homedir, "/.local");
|
||||
mkdir(statepath, S_IRWXU | S_IRWXG | S_IRWXO);
|
||||
free(statepath);
|
||||
statepath = concatenate(homedir, "/.local/share");
|
||||
mkdir(statepath, S_IRWXU);
|
||||
free(statepath);
|
||||
if (stat(statedir, &dirstat) == -1) {
|
||||
if (xdgdatadir == NULL) {
|
||||
char *statepath = concatenate(homedir, "/.local");
|
||||
mkdir(statepath, S_IRWXU | S_IRWXG | S_IRWXO);
|
||||
free(statepath);
|
||||
statepath = concatenate(homedir, "/.local/share");
|
||||
mkdir(statepath, S_IRWXU);
|
||||
free(statepath);
|
||||
}
|
||||
if (mkdir(statedir, S_IRWXU) == -1) {
|
||||
history_error(N_("Unable to create directory %s: %s\n"
|
||||
"It is required for saving/loading "
|
||||
"search history or cursor positions.\n"),
|
||||
statedir, strerror(errno));
|
||||
return FALSE;
|
||||
}
|
||||
} else if (!S_ISDIR(dirstat.st_mode)) {
|
||||
history_error(N_("Path %s is not a directory and needs to be.\n"
|
||||
"Nano will be unable to load or save "
|
||||
"search history or cursor positions.\n"),
|
||||
statedir);
|
||||
return FALSE;
|
||||
}
|
||||
if (mkdir(statedir, S_IRWXU) == -1) {
|
||||
history_error(N_("Unable to create directory %s: %s\n"
|
||||
"It is required for saving/loading "
|
||||
"search history or cursor positions.\n"),
|
||||
statedir, strerror(errno));
|
||||
return FALSE;
|
||||
}
|
||||
} else if (!S_ISDIR(dirstat.st_mode)) {
|
||||
history_error(N_("Path %s is not a directory and needs to be.\n"
|
||||
"Nano will be unable to load or save "
|
||||
"search history or cursor positions.\n"),
|
||||
statedir);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
poshistname = concatenate(statedir, POSITION_HISTORY);
|
||||
return TRUE;
|
||||
poshistname = concatenate(statedir, POSITION_HISTORY);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Load the histories for Search and Replace and Execute Command. */
|
||||
void load_history(void)
|
||||
{
|
||||
char *histname = concatenate(statedir, SEARCH_HISTORY);
|
||||
FILE *hisfile = fopen(histname, "rb");
|
||||
char *histname = concatenate(statedir, SEARCH_HISTORY);
|
||||
FILE *hisfile = fopen(histname, "rb");
|
||||
|
||||
if (hisfile == NULL) {
|
||||
if (errno != ENOENT) {
|
||||
/* When reading failed, don't save history when we quit. */
|
||||
UNSET(HISTORYLOG);
|
||||
history_error(N_("Error reading %s: %s"), histname,
|
||||
strerror(errno));
|
||||
}
|
||||
} else {
|
||||
/* Load the three history lists -- first search, then replace,
|
||||
* then execute -- from oldest entry to newest. Between two
|
||||
* lists there is an empty line. */
|
||||
filestruct **history = &search_history;
|
||||
char *line = NULL;
|
||||
size_t buf_len = 0;
|
||||
ssize_t read;
|
||||
if (hisfile == NULL) {
|
||||
if (errno != ENOENT) {
|
||||
/* When reading failed, don't save history when we quit. */
|
||||
UNSET(HISTORYLOG);
|
||||
history_error(N_("Error reading %s: %s"), histname,
|
||||
strerror(errno));
|
||||
}
|
||||
} else {
|
||||
/* Load the three history lists -- first search, then replace,
|
||||
* then execute -- from oldest entry to newest. Between two
|
||||
* lists there is an empty line. */
|
||||
filestruct **history = &search_history;
|
||||
char *line = NULL;
|
||||
size_t buf_len = 0;
|
||||
ssize_t read;
|
||||
|
||||
while ((read = getline(&line, &buf_len, hisfile)) > 0) {
|
||||
line[--read] = '\0';
|
||||
if (read > 0) {
|
||||
/* Encode any embedded NUL as 0x0A. */
|
||||
unsunder(line, read);
|
||||
update_history(history, line);
|
||||
} else if (history == &search_history)
|
||||
history = &replace_history;
|
||||
else
|
||||
history = &execute_history;
|
||||
while ((read = getline(&line, &buf_len, hisfile)) > 0) {
|
||||
line[--read] = '\0';
|
||||
if (read > 0) {
|
||||
/* Encode any embedded NUL as 0x0A. */
|
||||
unsunder(line, read);
|
||||
update_history(history, line);
|
||||
} else if (history == &search_history)
|
||||
history = &replace_history;
|
||||
else
|
||||
history = &execute_history;
|
||||
}
|
||||
|
||||
fclose(hisfile);
|
||||
free(line);
|
||||
}
|
||||
|
||||
fclose(hisfile);
|
||||
free(line);
|
||||
}
|
||||
/* After reading them in, set the status of the lists to "unchanged". */
|
||||
history_changed = FALSE;
|
||||
|
||||
/* After reading them in, set the status of the lists to "unchanged". */
|
||||
history_changed = FALSE;
|
||||
|
||||
free(histname);
|
||||
free(histname);
|
||||
}
|
||||
|
||||
/* Write the lines of a history list, starting at head, from oldest to newest,
|
||||
* to the given file. Return TRUE if writing succeeded, and FALSE otherwise. */
|
||||
bool write_list(const filestruct *head, FILE *hisfile)
|
||||
{
|
||||
const filestruct *item;
|
||||
const filestruct *item;
|
||||
|
||||
for (item = head; item != NULL; item = item->next) {
|
||||
size_t length = strlen(item->data);
|
||||
for (item = head; item != NULL; item = item->next) {
|
||||
size_t length = strlen(item->data);
|
||||
|
||||
/* Decode 0x0A bytes as embedded NULs. */
|
||||
sunder(item->data);
|
||||
/* Decode 0x0A bytes as embedded NULs. */
|
||||
sunder(item->data);
|
||||
|
||||
if (fwrite(item->data, sizeof(char), length, hisfile) < length)
|
||||
return FALSE;
|
||||
if (putc('\n', hisfile) == EOF)
|
||||
return FALSE;
|
||||
}
|
||||
if (fwrite(item->data, sizeof(char), length, hisfile) < length)
|
||||
return FALSE;
|
||||
if (putc('\n', hisfile) == EOF)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Save the histories for Search and Replace and Execute Command. */
|
||||
void save_history(void)
|
||||
{
|
||||
char *histname;
|
||||
FILE *hisfile;
|
||||
char *histname;
|
||||
FILE *hisfile;
|
||||
|
||||
/* If the histories are unchanged, don't bother saving them. */
|
||||
if (!history_changed)
|
||||
return;
|
||||
/* If the histories are unchanged, don't bother saving them. */
|
||||
if (!history_changed)
|
||||
return;
|
||||
|
||||
histname = concatenate(statedir, SEARCH_HISTORY);
|
||||
hisfile = fopen(histname, "wb");
|
||||
histname = concatenate(statedir, SEARCH_HISTORY);
|
||||
hisfile = fopen(histname, "wb");
|
||||
|
||||
if (hisfile == NULL)
|
||||
fprintf(stderr, _("Error writing %s: %s\n"), histname,
|
||||
strerror(errno));
|
||||
else {
|
||||
/* Don't allow others to read or write the history file. */
|
||||
chmod(histname, S_IRUSR | S_IWUSR);
|
||||
if (hisfile == NULL)
|
||||
fprintf(stderr, _("Error writing %s: %s\n"), histname,
|
||||
strerror(errno));
|
||||
else {
|
||||
/* Don't allow others to read or write the history file. */
|
||||
chmod(histname, S_IRUSR | S_IWUSR);
|
||||
|
||||
if (!write_list(searchtop, hisfile) ||
|
||||
!write_list(replacetop, hisfile) ||
|
||||
!write_list(executetop, hisfile))
|
||||
fprintf(stderr, _("Error writing %s: %s\n"), histname,
|
||||
strerror(errno));
|
||||
if (!write_list(searchtop, hisfile) ||
|
||||
!write_list(replacetop, hisfile) ||
|
||||
!write_list(executetop, hisfile))
|
||||
fprintf(stderr, _("Error writing %s: %s\n"), histname,
|
||||
strerror(errno));
|
||||
|
||||
fclose(hisfile);
|
||||
}
|
||||
fclose(hisfile);
|
||||
}
|
||||
|
||||
free(histname);
|
||||
free(histname);
|
||||
}
|
||||
|
||||
/* Load the recorded cursor positions for files that were edited. */
|
||||
void load_poshistory(void)
|
||||
{
|
||||
FILE *hisfile = fopen(poshistname, "rb");
|
||||
FILE *hisfile = fopen(poshistname, "rb");
|
||||
|
||||
if (hisfile == NULL) {
|
||||
if (errno != ENOENT) {
|
||||
/* When reading failed, don't save history when we quit. */
|
||||
UNSET(POS_HISTORY);
|
||||
history_error(N_("Error reading %s: %s"), poshistname, strerror(errno));
|
||||
if (hisfile == NULL) {
|
||||
if (errno != ENOENT) {
|
||||
/* When reading failed, don't save history when we quit. */
|
||||
UNSET(POS_HISTORY);
|
||||
history_error(N_("Error reading %s: %s"), poshistname, strerror(errno));
|
||||
}
|
||||
} else {
|
||||
char *line = NULL, *lineptr, *xptr;
|
||||
size_t buf_len = 0;
|
||||
ssize_t read, count = 0;
|
||||
poshiststruct *record_ptr = NULL, *newrecord;
|
||||
|
||||
/* Read and parse each line, and store the extracted data. */
|
||||
while ((read = getline(&line, &buf_len, hisfile)) > 5) {
|
||||
/* Decode nulls as embedded newlines. */
|
||||
unsunder(line, read);
|
||||
|
||||
/* Find where the x index and line number are in the line. */
|
||||
xptr = revstrstr(line, " ", line + read - 3);
|
||||
if (xptr == NULL)
|
||||
continue;
|
||||
lineptr = revstrstr(line, " ", xptr - 2);
|
||||
if (lineptr == NULL)
|
||||
continue;
|
||||
|
||||
/* Now separate the three elements of the line. */
|
||||
*(xptr++) = '\0';
|
||||
*(lineptr++) = '\0';
|
||||
|
||||
/* Create a new position record. */
|
||||
newrecord = (poshiststruct *)nmalloc(sizeof(poshiststruct));
|
||||
newrecord->filename = mallocstrcpy(NULL, line);
|
||||
newrecord->lineno = atoi(lineptr);
|
||||
newrecord->xno = atoi(xptr);
|
||||
newrecord->next = NULL;
|
||||
|
||||
/* Add the record to the list. */
|
||||
if (position_history == NULL)
|
||||
position_history = newrecord;
|
||||
else
|
||||
record_ptr->next = newrecord;
|
||||
|
||||
record_ptr = newrecord;
|
||||
|
||||
/* Impose a limit, so the file will not grow indefinitely. */
|
||||
if (++count > 200) {
|
||||
poshiststruct *drop_record = position_history;
|
||||
|
||||
position_history = position_history->next;
|
||||
|
||||
free(drop_record->filename);
|
||||
free(drop_record);
|
||||
}
|
||||
}
|
||||
fclose(hisfile);
|
||||
free(line);
|
||||
|
||||
stat(poshistname, &stat_of_positions_file);
|
||||
}
|
||||
} else {
|
||||
char *line = NULL, *lineptr, *xptr;
|
||||
size_t buf_len = 0;
|
||||
ssize_t read, count = 0;
|
||||
poshiststruct *record_ptr = NULL, *newrecord;
|
||||
|
||||
/* Read and parse each line, and store the extracted data. */
|
||||
while ((read = getline(&line, &buf_len, hisfile)) > 5) {
|
||||
/* Decode nulls as embedded newlines. */
|
||||
unsunder(line, read);
|
||||
|
||||
/* Find where the x index and line number are in the line. */
|
||||
xptr = revstrstr(line, " ", line + read - 3);
|
||||
if (xptr == NULL)
|
||||
continue;
|
||||
lineptr = revstrstr(line, " ", xptr - 2);
|
||||
if (lineptr == NULL)
|
||||
continue;
|
||||
|
||||
/* Now separate the three elements of the line. */
|
||||
*(xptr++) = '\0';
|
||||
*(lineptr++) = '\0';
|
||||
|
||||
/* Create a new position record. */
|
||||
newrecord = (poshiststruct *)nmalloc(sizeof(poshiststruct));
|
||||
newrecord->filename = mallocstrcpy(NULL, line);
|
||||
newrecord->lineno = atoi(lineptr);
|
||||
newrecord->xno = atoi(xptr);
|
||||
newrecord->next = NULL;
|
||||
|
||||
/* Add the record to the list. */
|
||||
if (position_history == NULL)
|
||||
position_history = newrecord;
|
||||
else
|
||||
record_ptr->next = newrecord;
|
||||
|
||||
record_ptr = newrecord;
|
||||
|
||||
/* Impose a limit, so the file will not grow indefinitely. */
|
||||
if (++count > 200) {
|
||||
poshiststruct *drop_record = position_history;
|
||||
|
||||
position_history = position_history->next;
|
||||
|
||||
free(drop_record->filename);
|
||||
free(drop_record);
|
||||
}
|
||||
}
|
||||
fclose(hisfile);
|
||||
free(line);
|
||||
|
||||
stat(poshistname, &stat_of_positions_file);
|
||||
}
|
||||
}
|
||||
|
||||
/* Save the recorded cursor positions for files that were edited. */
|
||||
void save_poshistory(void)
|
||||
{
|
||||
poshiststruct *posptr;
|
||||
FILE *hisfile = fopen(poshistname, "wb");
|
||||
poshiststruct *posptr;
|
||||
FILE *hisfile = fopen(poshistname, "wb");
|
||||
|
||||
if (hisfile == NULL)
|
||||
fprintf(stderr, _("Error writing %s: %s\n"), poshistname, strerror(errno));
|
||||
else {
|
||||
/* Don't allow others to read or write the history file. */
|
||||
chmod(poshistname, S_IRUSR | S_IWUSR);
|
||||
if (hisfile == NULL)
|
||||
fprintf(stderr, _("Error writing %s: %s\n"), poshistname, strerror(errno));
|
||||
else {
|
||||
/* Don't allow others to read or write the history file. */
|
||||
chmod(poshistname, S_IRUSR | S_IWUSR);
|
||||
|
||||
for (posptr = position_history; posptr != NULL; posptr = posptr->next) {
|
||||
char *path_and_place;
|
||||
size_t length;
|
||||
for (posptr = position_history; posptr != NULL; posptr = posptr->next) {
|
||||
char *path_and_place;
|
||||
size_t length;
|
||||
|
||||
/* Assume 20 decimal positions each for line and column number,
|
||||
* plus two spaces, plus the line feed, plus the null byte. */
|
||||
path_and_place = charalloc(strlen(posptr->filename) + 44);
|
||||
sprintf(path_and_place, "%s %zd %zd\n",
|
||||
posptr->filename, posptr->lineno, posptr->xno);
|
||||
length = strlen(path_and_place);
|
||||
/* Assume 20 decimal positions each for line and column number,
|
||||
* plus two spaces, plus the line feed, plus the null byte. */
|
||||
path_and_place = charalloc(strlen(posptr->filename) + 44);
|
||||
sprintf(path_and_place, "%s %zd %zd\n",
|
||||
posptr->filename, posptr->lineno, posptr->xno);
|
||||
length = strlen(path_and_place);
|
||||
|
||||
/* Encode newlines in filenames as nulls. */
|
||||
sunder(path_and_place);
|
||||
/* Restore the terminating newline. */
|
||||
path_and_place[length - 1] = '\n';
|
||||
/* Encode newlines in filenames as nulls. */
|
||||
sunder(path_and_place);
|
||||
/* Restore the terminating newline. */
|
||||
path_and_place[length - 1] = '\n';
|
||||
|
||||
if (fwrite(path_and_place, sizeof(char), length, hisfile) < length)
|
||||
fprintf(stderr, _("Error writing %s: %s\n"),
|
||||
poshistname, strerror(errno));
|
||||
free(path_and_place);
|
||||
if (fwrite(path_and_place, sizeof(char), length, hisfile) < length)
|
||||
fprintf(stderr, _("Error writing %s: %s\n"),
|
||||
poshistname, strerror(errno));
|
||||
free(path_and_place);
|
||||
}
|
||||
fclose(hisfile);
|
||||
|
||||
stat(poshistname, &stat_of_positions_file);
|
||||
}
|
||||
fclose(hisfile);
|
||||
|
||||
stat(poshistname, &stat_of_positions_file);
|
||||
}
|
||||
}
|
||||
|
||||
/* Reload the position history file if it has been modified since last load. */
|
||||
void reload_positions_if_needed(void)
|
||||
{
|
||||
struct stat newstat;
|
||||
struct stat newstat;
|
||||
|
||||
stat(poshistname, &newstat);
|
||||
stat(poshistname, &newstat);
|
||||
|
||||
if (newstat.st_mtime != stat_of_positions_file.st_mtime) {
|
||||
poshiststruct *ptr, *nextone;
|
||||
if (newstat.st_mtime != stat_of_positions_file.st_mtime) {
|
||||
poshiststruct *ptr, *nextone;
|
||||
|
||||
for (ptr = position_history; ptr != NULL; ptr = nextone) {
|
||||
nextone = ptr->next;
|
||||
free(ptr->filename);
|
||||
free(ptr);
|
||||
for (ptr = position_history; ptr != NULL; ptr = nextone) {
|
||||
nextone = ptr->next;
|
||||
free(ptr->filename);
|
||||
free(ptr);
|
||||
}
|
||||
position_history = NULL;
|
||||
|
||||
load_poshistory();
|
||||
}
|
||||
position_history = NULL;
|
||||
|
||||
load_poshistory();
|
||||
}
|
||||
}
|
||||
|
||||
/* Update the recorded last file positions, given a filename, a line
|
||||
* and a column. If no entry is found, add a new one at the end. */
|
||||
void update_poshistory(char *filename, ssize_t lineno, ssize_t xpos)
|
||||
{
|
||||
poshiststruct *posptr, *theone, *posprev = NULL;
|
||||
char *fullpath = get_full_path(filename);
|
||||
poshiststruct *posptr, *theone, *posprev = NULL;
|
||||
char *fullpath = get_full_path(filename);
|
||||
|
||||
if (fullpath == NULL || fullpath[strlen(fullpath) - 1] == '/' || inhelp) {
|
||||
free(fullpath);
|
||||
return;
|
||||
}
|
||||
|
||||
reload_positions_if_needed();
|
||||
|
||||
/* Look for a matching filename in the list. */
|
||||
for (posptr = position_history; posptr != NULL; posptr = posptr->next) {
|
||||
if (!strcmp(posptr->filename, fullpath))
|
||||
break;
|
||||
posprev = posptr;
|
||||
}
|
||||
|
||||
/* Don't record files that have the default cursor position. */
|
||||
if (lineno == 1 && xpos == 1) {
|
||||
if (posptr != NULL) {
|
||||
if (posprev == NULL)
|
||||
position_history = posptr->next;
|
||||
else
|
||||
posprev->next = posptr->next;
|
||||
free(posptr->filename);
|
||||
free(posptr);
|
||||
save_poshistory();
|
||||
if (fullpath == NULL || fullpath[strlen(fullpath) - 1] == '/' || inhelp) {
|
||||
free(fullpath);
|
||||
return;
|
||||
}
|
||||
|
||||
reload_positions_if_needed();
|
||||
|
||||
/* Look for a matching filename in the list. */
|
||||
for (posptr = position_history; posptr != NULL; posptr = posptr->next) {
|
||||
if (!strcmp(posptr->filename, fullpath))
|
||||
break;
|
||||
posprev = posptr;
|
||||
}
|
||||
|
||||
/* Don't record files that have the default cursor position. */
|
||||
if (lineno == 1 && xpos == 1) {
|
||||
if (posptr != NULL) {
|
||||
if (posprev == NULL)
|
||||
position_history = posptr->next;
|
||||
else
|
||||
posprev->next = posptr->next;
|
||||
free(posptr->filename);
|
||||
free(posptr);
|
||||
save_poshistory();
|
||||
}
|
||||
free(fullpath);
|
||||
return;
|
||||
}
|
||||
|
||||
theone = posptr;
|
||||
|
||||
/* If we didn't find it, make a new node; otherwise, if we're
|
||||
* not at the end, move the matching one to the end. */
|
||||
if (theone == NULL) {
|
||||
theone = (poshiststruct *)nmalloc(sizeof(poshiststruct));
|
||||
theone->filename = mallocstrcpy(NULL, fullpath);
|
||||
if (position_history == NULL)
|
||||
position_history = theone;
|
||||
else
|
||||
posprev->next = theone;
|
||||
} else if (posptr->next != NULL) {
|
||||
if (posprev == NULL)
|
||||
position_history = posptr->next;
|
||||
else
|
||||
posprev->next = posptr->next;
|
||||
while (posptr->next != NULL)
|
||||
posptr = posptr->next;
|
||||
posptr->next = theone;
|
||||
}
|
||||
|
||||
/* Store the last cursor position. */
|
||||
theone->lineno = lineno;
|
||||
theone->xno = xpos;
|
||||
theone->next = NULL;
|
||||
|
||||
free(fullpath);
|
||||
return;
|
||||
}
|
||||
|
||||
theone = posptr;
|
||||
|
||||
/* If we didn't find it, make a new node; otherwise, if we're
|
||||
* not at the end, move the matching one to the end. */
|
||||
if (theone == NULL) {
|
||||
theone = (poshiststruct *)nmalloc(sizeof(poshiststruct));
|
||||
theone->filename = mallocstrcpy(NULL, fullpath);
|
||||
if (position_history == NULL)
|
||||
position_history = theone;
|
||||
else
|
||||
posprev->next = theone;
|
||||
} else if (posptr->next != NULL) {
|
||||
if (posprev == NULL)
|
||||
position_history = posptr->next;
|
||||
else
|
||||
posprev->next = posptr->next;
|
||||
while (posptr->next != NULL)
|
||||
posptr = posptr->next;
|
||||
posptr->next = theone;
|
||||
}
|
||||
|
||||
/* Store the last cursor position. */
|
||||
theone->lineno = lineno;
|
||||
theone->xno = xpos;
|
||||
theone->next = NULL;
|
||||
|
||||
free(fullpath);
|
||||
|
||||
save_poshistory();
|
||||
save_poshistory();
|
||||
}
|
||||
|
||||
/* Check whether the given file matches an existing entry in the recorded
|
||||
@@ -593,24 +593,24 @@ void update_poshistory(char *filename, ssize_t lineno, ssize_t xpos)
|
||||
* set line and column to the retrieved values. */
|
||||
bool has_old_position(const char *file, ssize_t *line, ssize_t *column)
|
||||
{
|
||||
poshiststruct *posptr = position_history;
|
||||
char *fullpath = get_full_path(file);
|
||||
poshiststruct *posptr = position_history;
|
||||
char *fullpath = get_full_path(file);
|
||||
|
||||
if (fullpath == NULL)
|
||||
return FALSE;
|
||||
if (fullpath == NULL)
|
||||
return FALSE;
|
||||
|
||||
reload_positions_if_needed();
|
||||
reload_positions_if_needed();
|
||||
|
||||
while (posptr != NULL && strcmp(posptr->filename, fullpath) != 0)
|
||||
posptr = posptr->next;
|
||||
while (posptr != NULL && strcmp(posptr->filename, fullpath) != 0)
|
||||
posptr = posptr->next;
|
||||
|
||||
free(fullpath);
|
||||
free(fullpath);
|
||||
|
||||
if (posptr == NULL)
|
||||
return FALSE;
|
||||
if (posptr == NULL)
|
||||
return FALSE;
|
||||
|
||||
*line = posptr->lineno;
|
||||
*column = posptr->xno;
|
||||
return TRUE;
|
||||
*line = posptr->lineno;
|
||||
*column = posptr->xno;
|
||||
return TRUE;
|
||||
}
|
||||
#endif /* ENABLE_HISTORIES */
|
||||
|
||||
668
src/move.c
668
src/move.c
@@ -24,44 +24,44 @@
|
||||
#include <string.h>
|
||||
|
||||
/* Move to the first line of the file. */
|
||||
void do_first_line(void)
|
||||
void to_first_line(void)
|
||||
{
|
||||
openfile->current = openfile->fileage;
|
||||
openfile->current_x = 0;
|
||||
openfile->placewewant = 0;
|
||||
openfile->current = openfile->fileage;
|
||||
openfile->current_x = 0;
|
||||
openfile->placewewant = 0;
|
||||
|
||||
refresh_needed = TRUE;
|
||||
refresh_needed = TRUE;
|
||||
}
|
||||
|
||||
/* Move to the last line of the file. */
|
||||
void do_last_line(void)
|
||||
void to_last_line(void)
|
||||
{
|
||||
openfile->current = openfile->filebot;
|
||||
openfile->current_x = strlen(openfile->filebot->data);
|
||||
openfile->placewewant = xplustabs();
|
||||
openfile->current = openfile->filebot;
|
||||
openfile->current_x = strlen(openfile->filebot->data);
|
||||
openfile->placewewant = xplustabs();
|
||||
|
||||
/* Set the last line of the screen as the target for the cursor. */
|
||||
openfile->current_y = editwinrows - 1;
|
||||
/* Set the last line of the screen as the target for the cursor. */
|
||||
openfile->current_y = editwinrows - 1;
|
||||
|
||||
refresh_needed = TRUE;
|
||||
focusing = FALSE;
|
||||
refresh_needed = TRUE;
|
||||
focusing = FALSE;
|
||||
}
|
||||
|
||||
/* Determine the actual current chunk and the target column. */
|
||||
void get_edge_and_target(size_t *leftedge, size_t *target_column)
|
||||
{
|
||||
#ifndef NANO_TINY
|
||||
if (ISSET(SOFTWRAP)) {
|
||||
size_t shim = editwincols * (1 + (tabsize / editwincols));
|
||||
if (ISSET(SOFTWRAP)) {
|
||||
size_t shim = editwincols * (1 + (tabsize / editwincols));
|
||||
|
||||
*leftedge = leftedge_for(xplustabs(), openfile->current);
|
||||
*target_column = (openfile->placewewant + shim - *leftedge) % editwincols;
|
||||
} else
|
||||
*leftedge = leftedge_for(xplustabs(), openfile->current);
|
||||
*target_column = (openfile->placewewant + shim - *leftedge) % editwincols;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
*leftedge = 0;
|
||||
*target_column = openfile->placewewant;
|
||||
}
|
||||
{
|
||||
*leftedge = 0;
|
||||
*target_column = openfile->placewewant;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return the index in line->data that corresponds to the given column on the
|
||||
@@ -69,104 +69,104 @@ void get_edge_and_target(size_t *leftedge, size_t *target_column)
|
||||
* on a tab, prevent the cursor from falling back a row when moving forward,
|
||||
* or from skipping a row when moving backward, by incrementing the index. */
|
||||
size_t proper_x(filestruct *line, size_t *leftedge, bool forward,
|
||||
size_t column, bool *shifted)
|
||||
size_t column, bool *shifted)
|
||||
{
|
||||
size_t index = actual_x(line->data, column);
|
||||
size_t index = actual_x(line->data, column);
|
||||
|
||||
#ifndef NANO_TINY
|
||||
if (ISSET(SOFTWRAP) && line->data[index] == '\t' &&
|
||||
((forward && strnlenpt(line->data, index) < *leftedge) ||
|
||||
(!forward && column / tabsize == (*leftedge - 1) / tabsize &&
|
||||
column / tabsize < (*leftedge + editwincols - 1) / tabsize))) {
|
||||
index++;
|
||||
if (ISSET(SOFTWRAP) && line->data[index] == '\t' &&
|
||||
((forward && strnlenpt(line->data, index) < *leftedge) ||
|
||||
(!forward && column / tabsize == (*leftedge - 1) / tabsize &&
|
||||
column / tabsize < (*leftedge + editwincols - 1) / tabsize))) {
|
||||
index++;
|
||||
|
||||
if (shifted != NULL)
|
||||
*shifted = TRUE;
|
||||
}
|
||||
if (shifted != NULL)
|
||||
*shifted = TRUE;
|
||||
}
|
||||
|
||||
if (ISSET(SOFTWRAP))
|
||||
*leftedge = leftedge_for(strnlenpt(line->data, index), line);
|
||||
if (ISSET(SOFTWRAP))
|
||||
*leftedge = leftedge_for(strnlenpt(line->data, index), line);
|
||||
#endif
|
||||
|
||||
return index;
|
||||
return index;
|
||||
}
|
||||
|
||||
/* Adjust the values for current_x and placewewant in case we have landed in
|
||||
* the middle of a tab that crosses a row boundary. */
|
||||
void set_proper_index_and_pww(size_t *leftedge, size_t target, bool forward)
|
||||
{
|
||||
bool shifted = FALSE;
|
||||
size_t was_edge = *leftedge;
|
||||
bool shifted = FALSE;
|
||||
size_t was_edge = *leftedge;
|
||||
|
||||
openfile->current_x = proper_x(openfile->current, leftedge, forward,
|
||||
actual_last_column(*leftedge, target), &shifted);
|
||||
|
||||
/* If the index was incremented, try going to the target column. */
|
||||
if (shifted || *leftedge < was_edge)
|
||||
openfile->current_x = proper_x(openfile->current, leftedge, forward,
|
||||
actual_last_column(*leftedge, target), &shifted);
|
||||
actual_last_column(*leftedge, target), &shifted);
|
||||
|
||||
openfile->placewewant = *leftedge + target;
|
||||
/* If the index was incremented, try going to the target column. */
|
||||
if (shifted || *leftedge < was_edge)
|
||||
openfile->current_x = proper_x(openfile->current, leftedge, forward,
|
||||
actual_last_column(*leftedge, target), &shifted);
|
||||
|
||||
openfile->placewewant = *leftedge + target;
|
||||
}
|
||||
|
||||
/* Move up nearly one screenful. */
|
||||
void do_page_up(void)
|
||||
{
|
||||
int mustmove = (editwinrows < 3) ? 1 : editwinrows - 2;
|
||||
size_t leftedge, target_column;
|
||||
int mustmove = (editwinrows < 3) ? 1 : editwinrows - 2;
|
||||
size_t leftedge, target_column;
|
||||
|
||||
/* 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. */
|
||||
if (!ISSET(SMOOTH_SCROLL)) {
|
||||
openfile->current = openfile->edittop;
|
||||
leftedge = openfile->firstcolumn;
|
||||
openfile->current_y = 0;
|
||||
target_column = 0;
|
||||
} else
|
||||
get_edge_and_target(&leftedge, &target_column);
|
||||
/* 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. */
|
||||
if (!ISSET(SMOOTH_SCROLL)) {
|
||||
openfile->current = openfile->edittop;
|
||||
leftedge = openfile->firstcolumn;
|
||||
openfile->current_y = 0;
|
||||
target_column = 0;
|
||||
} else
|
||||
get_edge_and_target(&leftedge, &target_column);
|
||||
|
||||
/* Move up the required number of lines or chunks. If we can't, we're
|
||||
* at the top of the file, so put the cursor there and get out. */
|
||||
if (go_back_chunks(mustmove, &openfile->current, &leftedge) > 0) {
|
||||
do_first_line();
|
||||
return;
|
||||
}
|
||||
/* Move up the required number of lines or chunks. If we can't, we're
|
||||
* at the top of the file, so put the cursor there and get out. */
|
||||
if (go_back_chunks(mustmove, &openfile->current, &leftedge) > 0) {
|
||||
to_first_line();
|
||||
return;
|
||||
}
|
||||
|
||||
set_proper_index_and_pww(&leftedge, target_column, FALSE);
|
||||
set_proper_index_and_pww(&leftedge, target_column, FALSE);
|
||||
|
||||
/* Move the viewport so that the cursor stays immobile, if possible. */
|
||||
adjust_viewport(STATIONARY);
|
||||
refresh_needed = TRUE;
|
||||
/* Move the viewport so that the cursor stays immobile, if possible. */
|
||||
adjust_viewport(STATIONARY);
|
||||
refresh_needed = TRUE;
|
||||
}
|
||||
|
||||
/* Move down nearly one screenful. */
|
||||
void do_page_down(void)
|
||||
{
|
||||
int mustmove = (editwinrows < 3) ? 1 : editwinrows - 2;
|
||||
size_t leftedge, target_column;
|
||||
int mustmove = (editwinrows < 3) ? 1 : editwinrows - 2;
|
||||
size_t leftedge, target_column;
|
||||
|
||||
/* 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. */
|
||||
if (!ISSET(SMOOTH_SCROLL)) {
|
||||
openfile->current = openfile->edittop;
|
||||
leftedge = openfile->firstcolumn;
|
||||
openfile->current_y = 0;
|
||||
target_column = 0;
|
||||
} else
|
||||
get_edge_and_target(&leftedge, &target_column);
|
||||
/* 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. */
|
||||
if (!ISSET(SMOOTH_SCROLL)) {
|
||||
openfile->current = openfile->edittop;
|
||||
leftedge = openfile->firstcolumn;
|
||||
openfile->current_y = 0;
|
||||
target_column = 0;
|
||||
} else
|
||||
get_edge_and_target(&leftedge, &target_column);
|
||||
|
||||
/* Move down the required number of lines or chunks. If we can't, we're
|
||||
* at the bottom of the file, so put the cursor there and get out. */
|
||||
if (go_forward_chunks(mustmove, &openfile->current, &leftedge) > 0) {
|
||||
do_last_line();
|
||||
return;
|
||||
}
|
||||
/* Move down the required number of lines or chunks. If we can't, we're
|
||||
* at the bottom of the file, so put the cursor there and get out. */
|
||||
if (go_forward_chunks(mustmove, &openfile->current, &leftedge) > 0) {
|
||||
to_last_line();
|
||||
return;
|
||||
}
|
||||
|
||||
set_proper_index_and_pww(&leftedge, target_column, TRUE);
|
||||
set_proper_index_and_pww(&leftedge, target_column, TRUE);
|
||||
|
||||
/* Move the viewport so that the cursor stays immobile, if possible. */
|
||||
adjust_viewport(STATIONARY);
|
||||
refresh_needed = TRUE;
|
||||
/* Move the viewport so that the cursor stays immobile, if possible. */
|
||||
adjust_viewport(STATIONARY);
|
||||
refresh_needed = TRUE;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_JUSTIFY
|
||||
@@ -174,18 +174,18 @@ void do_page_down(void)
|
||||
* current line. If update_screen is TRUE, update the screen afterwards. */
|
||||
void do_para_begin(bool update_screen)
|
||||
{
|
||||
filestruct *was_current = openfile->current;
|
||||
filestruct *was_current = openfile->current;
|
||||
|
||||
if (openfile->current != openfile->fileage)
|
||||
openfile->current = openfile->current->prev;
|
||||
if (openfile->current != openfile->fileage)
|
||||
openfile->current = openfile->current->prev;
|
||||
|
||||
while (!begpar(openfile->current))
|
||||
openfile->current = openfile->current->prev;
|
||||
while (!begpar(openfile->current))
|
||||
openfile->current = openfile->current->prev;
|
||||
|
||||
openfile->current_x = 0;
|
||||
openfile->current_x = 0;
|
||||
|
||||
if (update_screen)
|
||||
edit_redraw(was_current, CENTERING);
|
||||
if (update_screen)
|
||||
edit_redraw(was_current, CENTERING);
|
||||
}
|
||||
|
||||
/* Move down to the beginning of the last line of the current paragraph.
|
||||
@@ -196,122 +196,122 @@ void do_para_begin(bool update_screen)
|
||||
* paragraph or isn't in a paragraph. */
|
||||
void do_para_end(bool update_screen)
|
||||
{
|
||||
filestruct *was_current = openfile->current;
|
||||
filestruct *was_current = openfile->current;
|
||||
|
||||
while (openfile->current != openfile->filebot &&
|
||||
!inpar(openfile->current))
|
||||
openfile->current = openfile->current->next;
|
||||
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;
|
||||
}
|
||||
while (openfile->current != openfile->filebot &&
|
||||
inpar(openfile->current->next) &&
|
||||
!begpar(openfile->current->next)) {
|
||||
openfile->current = openfile->current->next;
|
||||
}
|
||||
|
||||
if (openfile->current != openfile->filebot) {
|
||||
openfile->current = openfile->current->next;
|
||||
openfile->current_x = 0;
|
||||
} else
|
||||
openfile->current_x = strlen(openfile->current->data);
|
||||
if (openfile->current != openfile->filebot) {
|
||||
openfile->current = openfile->current->next;
|
||||
openfile->current_x = 0;
|
||||
} else
|
||||
openfile->current_x = strlen(openfile->current->data);
|
||||
|
||||
if (update_screen)
|
||||
edit_redraw(was_current, CENTERING);
|
||||
if (update_screen)
|
||||
edit_redraw(was_current, CENTERING);
|
||||
}
|
||||
|
||||
/* Move up to first start of a paragraph before the current line. */
|
||||
void do_para_begin_void(void)
|
||||
{
|
||||
do_para_begin(TRUE);
|
||||
do_para_begin(TRUE);
|
||||
}
|
||||
|
||||
/* Move down to just after the first end of a paragraph. */
|
||||
void do_para_end_void(void)
|
||||
{
|
||||
do_para_end(TRUE);
|
||||
do_para_end(TRUE);
|
||||
}
|
||||
#endif /* ENABLE_JUSTIFY */
|
||||
|
||||
/* Move to the preceding block of text. */
|
||||
void do_prev_block(void)
|
||||
{
|
||||
filestruct *was_current = openfile->current;
|
||||
bool is_text = FALSE, seen_text = FALSE;
|
||||
filestruct *was_current = openfile->current;
|
||||
bool is_text = FALSE, seen_text = FALSE;
|
||||
|
||||
/* Skip backward until first blank line after some nonblank line(s). */
|
||||
while (openfile->current->prev != NULL && (!seen_text || is_text)) {
|
||||
openfile->current = openfile->current->prev;
|
||||
is_text = !white_string(openfile->current->data);
|
||||
seen_text = seen_text || is_text;
|
||||
}
|
||||
/* Skip backward until first blank line after some nonblank line(s). */
|
||||
while (openfile->current->prev != NULL && (!seen_text || is_text)) {
|
||||
openfile->current = openfile->current->prev;
|
||||
is_text = !white_string(openfile->current->data);
|
||||
seen_text = seen_text || is_text;
|
||||
}
|
||||
|
||||
/* Step forward one line again if this one is blank. */
|
||||
if (openfile->current->next != NULL &&
|
||||
white_string(openfile->current->data))
|
||||
openfile->current = openfile->current->next;
|
||||
/* Step forward one line again if this one is blank. */
|
||||
if (openfile->current->next != NULL &&
|
||||
white_string(openfile->current->data))
|
||||
openfile->current = openfile->current->next;
|
||||
|
||||
openfile->current_x = 0;
|
||||
edit_redraw(was_current, CENTERING);
|
||||
openfile->current_x = 0;
|
||||
edit_redraw(was_current, CENTERING);
|
||||
}
|
||||
|
||||
/* Move to the next block of text. */
|
||||
void do_next_block(void)
|
||||
{
|
||||
filestruct *was_current = openfile->current;
|
||||
bool is_white = white_string(openfile->current->data);
|
||||
bool seen_white = is_white;
|
||||
filestruct *was_current = openfile->current;
|
||||
bool is_white = white_string(openfile->current->data);
|
||||
bool seen_white = is_white;
|
||||
|
||||
/* Skip forward until first nonblank line after some blank line(s). */
|
||||
while (openfile->current->next != NULL && (!seen_white || is_white)) {
|
||||
openfile->current = openfile->current->next;
|
||||
is_white = white_string(openfile->current->data);
|
||||
seen_white = seen_white || is_white;
|
||||
}
|
||||
/* Skip forward until first nonblank line after some blank line(s). */
|
||||
while (openfile->current->next != NULL && (!seen_white || is_white)) {
|
||||
openfile->current = openfile->current->next;
|
||||
is_white = white_string(openfile->current->data);
|
||||
seen_white = seen_white || is_white;
|
||||
}
|
||||
|
||||
openfile->current_x = 0;
|
||||
edit_redraw(was_current, CENTERING);
|
||||
openfile->current_x = 0;
|
||||
edit_redraw(was_current, CENTERING);
|
||||
}
|
||||
|
||||
/* Move to the previous word. If allow_punct is TRUE, treat punctuation
|
||||
* as part of a word. When requested, update the screen afterwards. */
|
||||
void do_prev_word(bool allow_punct, bool update_screen)
|
||||
{
|
||||
filestruct *was_current = openfile->current;
|
||||
bool seen_a_word = FALSE, step_forward = FALSE;
|
||||
filestruct *was_current = openfile->current;
|
||||
bool seen_a_word = FALSE, step_forward = FALSE;
|
||||
|
||||
/* Move backward until we pass over the start of a word. */
|
||||
while (TRUE) {
|
||||
/* If at the head of a line, move to the end of the preceding one. */
|
||||
if (openfile->current_x == 0) {
|
||||
if (openfile->current->prev == NULL)
|
||||
break;
|
||||
openfile->current = openfile->current->prev;
|
||||
openfile->current_x = strlen(openfile->current->data);
|
||||
/* Move backward until we pass over the start of a word. */
|
||||
while (TRUE) {
|
||||
/* If at the head of a line, move to the end of the preceding one. */
|
||||
if (openfile->current_x == 0) {
|
||||
if (openfile->current->prev == NULL)
|
||||
break;
|
||||
openfile->current = openfile->current->prev;
|
||||
openfile->current_x = strlen(openfile->current->data);
|
||||
}
|
||||
|
||||
/* Step back one character. */
|
||||
openfile->current_x = move_mbleft(openfile->current->data,
|
||||
openfile->current_x);
|
||||
|
||||
if (is_word_mbchar(openfile->current->data + openfile->current_x,
|
||||
allow_punct)) {
|
||||
seen_a_word = TRUE;
|
||||
/* If at the head of a line now, this surely is a word start. */
|
||||
if (openfile->current_x == 0)
|
||||
break;
|
||||
} else if (seen_a_word) {
|
||||
/* This is space now: we've overshot the start of the word. */
|
||||
step_forward = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Step back one character. */
|
||||
openfile->current_x = move_mbleft(openfile->current->data,
|
||||
openfile->current_x);
|
||||
if (step_forward)
|
||||
/* Move one character forward again to sit on the start of the word. */
|
||||
openfile->current_x = move_mbright(openfile->current->data,
|
||||
openfile->current_x);
|
||||
|
||||
if (is_word_mbchar(openfile->current->data + openfile->current_x,
|
||||
allow_punct)) {
|
||||
seen_a_word = TRUE;
|
||||
/* If at the head of a line now, this surely is a word start. */
|
||||
if (openfile->current_x == 0)
|
||||
break;
|
||||
} else if (seen_a_word) {
|
||||
/* This is space now: we've overshot the start of the word. */
|
||||
step_forward = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (step_forward)
|
||||
/* Move one character forward again to sit on the start of the word. */
|
||||
openfile->current_x = move_mbright(openfile->current->data,
|
||||
openfile->current_x);
|
||||
|
||||
if (update_screen)
|
||||
edit_redraw(was_current, FLOWING);
|
||||
if (update_screen)
|
||||
edit_redraw(was_current, FLOWING);
|
||||
}
|
||||
|
||||
/* Move to the next word. If allow_punct is TRUE, treat punctuation
|
||||
@@ -319,55 +319,55 @@ void do_prev_word(bool allow_punct, bool update_screen)
|
||||
* Return TRUE if we started on a word, and FALSE otherwise. */
|
||||
bool do_next_word(bool allow_punct, bool update_screen)
|
||||
{
|
||||
filestruct *was_current = openfile->current;
|
||||
bool started_on_word = is_word_mbchar(openfile->current->data +
|
||||
openfile->current_x, allow_punct);
|
||||
bool seen_space = !started_on_word;
|
||||
filestruct *was_current = openfile->current;
|
||||
bool started_on_word = is_word_mbchar(openfile->current->data +
|
||||
openfile->current_x, allow_punct);
|
||||
bool seen_space = !started_on_word;
|
||||
|
||||
/* Move forward until we reach the start of a word. */
|
||||
while (TRUE) {
|
||||
/* If at the end of a line, move to the beginning of the next one. */
|
||||
if (openfile->current->data[openfile->current_x] == '\0') {
|
||||
/* When at end of file, stop. */
|
||||
if (openfile->current->next == NULL)
|
||||
break;
|
||||
openfile->current = openfile->current->next;
|
||||
openfile->current_x = 0;
|
||||
seen_space = TRUE;
|
||||
} else {
|
||||
/* Step forward one character. */
|
||||
openfile->current_x = move_mbright(openfile->current->data,
|
||||
openfile->current_x);
|
||||
/* Move forward until we reach the start of a word. */
|
||||
while (TRUE) {
|
||||
/* If at the end of a line, move to the beginning of the next one. */
|
||||
if (openfile->current->data[openfile->current_x] == '\0') {
|
||||
/* When at end of file, stop. */
|
||||
if (openfile->current->next == NULL)
|
||||
break;
|
||||
openfile->current = openfile->current->next;
|
||||
openfile->current_x = 0;
|
||||
seen_space = TRUE;
|
||||
} else {
|
||||
/* Step forward one character. */
|
||||
openfile->current_x = move_mbright(openfile->current->data,
|
||||
openfile->current_x);
|
||||
}
|
||||
|
||||
/* If this is not a word character, then it's a separator; else
|
||||
* if we've already seen a separator, then it's a word start. */
|
||||
if (!is_word_mbchar(openfile->current->data + openfile->current_x,
|
||||
allow_punct))
|
||||
seen_space = TRUE;
|
||||
else if (seen_space)
|
||||
break;
|
||||
}
|
||||
|
||||
/* If this is not a word character, then it's a separator; else
|
||||
* if we've already seen a separator, then it's a word start. */
|
||||
if (!is_word_mbchar(openfile->current->data + openfile->current_x,
|
||||
allow_punct))
|
||||
seen_space = TRUE;
|
||||
else if (seen_space)
|
||||
break;
|
||||
}
|
||||
if (update_screen)
|
||||
edit_redraw(was_current, FLOWING);
|
||||
|
||||
if (update_screen)
|
||||
edit_redraw(was_current, FLOWING);
|
||||
|
||||
/* Return whether we started on a word. */
|
||||
return started_on_word;
|
||||
/* 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);
|
||||
do_prev_word(ISSET(WORD_BOUNDS), TRUE);
|
||||
}
|
||||
|
||||
/* 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);
|
||||
do_next_word(ISSET(WORD_BOUNDS), TRUE);
|
||||
}
|
||||
|
||||
/* Move to the beginning of the current line (or softwrapped chunk).
|
||||
@@ -375,59 +375,59 @@ void do_next_word_void(void)
|
||||
* of the full line when already at the start of a chunk. */
|
||||
void do_home(void)
|
||||
{
|
||||
filestruct *was_current = openfile->current;
|
||||
size_t was_column = xplustabs();
|
||||
bool moved_off_chunk = TRUE;
|
||||
filestruct *was_current = openfile->current;
|
||||
size_t was_column = xplustabs();
|
||||
bool moved_off_chunk = TRUE;
|
||||
#ifndef NANO_TINY
|
||||
bool moved = FALSE;
|
||||
size_t leftedge = 0, leftedge_x = 0;
|
||||
bool moved = FALSE;
|
||||
size_t leftedge = 0, leftedge_x = 0;
|
||||
|
||||
if (ISSET(SOFTWRAP)) {
|
||||
leftedge = leftedge_for(was_column, openfile->current);
|
||||
leftedge_x = proper_x(openfile->current, &leftedge, FALSE, leftedge,
|
||||
NULL);
|
||||
}
|
||||
|
||||
if (ISSET(SMART_HOME)) {
|
||||
size_t indent_x = indent_length(openfile->current->data);
|
||||
|
||||
if (openfile->current->data[indent_x] != '\0') {
|
||||
/* If we're exactly on the indent, move fully home. Otherwise,
|
||||
* when not softwrapping or not after the first nonblank chunk,
|
||||
* move to the first nonblank character. */
|
||||
if (openfile->current_x == indent_x) {
|
||||
openfile->current_x = 0;
|
||||
moved = TRUE;
|
||||
} else if (!ISSET(SOFTWRAP) || leftedge_x <= indent_x) {
|
||||
openfile->current_x = indent_x;
|
||||
moved = TRUE;
|
||||
}
|
||||
if (ISSET(SOFTWRAP)) {
|
||||
leftedge = leftedge_for(was_column, openfile->current);
|
||||
leftedge_x = proper_x(openfile->current, &leftedge, FALSE, leftedge,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
if (!moved && ISSET(SOFTWRAP)) {
|
||||
/* If already at the left edge of the screen, move fully home.
|
||||
* Otherwise, move to the left edge. */
|
||||
if (openfile->current_x == leftedge_x)
|
||||
openfile->current_x = 0;
|
||||
else {
|
||||
openfile->current_x = leftedge_x;
|
||||
openfile->placewewant = leftedge;
|
||||
moved_off_chunk = FALSE;
|
||||
if (ISSET(SMART_HOME)) {
|
||||
size_t indent_x = indent_length(openfile->current->data);
|
||||
|
||||
if (openfile->current->data[indent_x] != '\0') {
|
||||
/* If we're exactly on the indent, move fully home. Otherwise,
|
||||
* when not softwrapping or not after the first nonblank chunk,
|
||||
* move to the first nonblank character. */
|
||||
if (openfile->current_x == indent_x) {
|
||||
openfile->current_x = 0;
|
||||
moved = TRUE;
|
||||
} else if (!ISSET(SOFTWRAP) || leftedge_x <= indent_x) {
|
||||
openfile->current_x = indent_x;
|
||||
moved = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (!moved)
|
||||
|
||||
if (!moved && ISSET(SOFTWRAP)) {
|
||||
/* If already at the left edge of the screen, move fully home.
|
||||
* Otherwise, move to the left edge. */
|
||||
if (openfile->current_x == leftedge_x)
|
||||
openfile->current_x = 0;
|
||||
else {
|
||||
openfile->current_x = leftedge_x;
|
||||
openfile->placewewant = leftedge;
|
||||
moved_off_chunk = FALSE;
|
||||
}
|
||||
} else if (!moved)
|
||||
#endif
|
||||
openfile->current_x = 0;
|
||||
openfile->current_x = 0;
|
||||
|
||||
if (moved_off_chunk)
|
||||
openfile->placewewant = xplustabs();
|
||||
if (moved_off_chunk)
|
||||
openfile->placewewant = xplustabs();
|
||||
|
||||
/* If we changed chunk, we might be offscreen. Otherwise,
|
||||
* update current if the mark is on or we changed "page". */
|
||||
if (ISSET(SOFTWRAP) && moved_off_chunk)
|
||||
edit_redraw(was_current, FLOWING);
|
||||
else if (line_needs_update(was_column, openfile->placewewant))
|
||||
update_line(openfile->current, openfile->current_x);
|
||||
/* If we changed chunk, we might be offscreen. Otherwise,
|
||||
* update current if the mark is on or we changed "page". */
|
||||
if (ISSET(SOFTWRAP) && moved_off_chunk)
|
||||
edit_redraw(was_current, FLOWING);
|
||||
else if (line_needs_update(was_column, openfile->placewewant))
|
||||
update_line(openfile->current, openfile->current_x);
|
||||
}
|
||||
|
||||
/* Move to the end of the current line (or softwrapped chunk).
|
||||
@@ -435,159 +435,159 @@ void do_home(void)
|
||||
* end of the full line. */
|
||||
void do_end(void)
|
||||
{
|
||||
filestruct *was_current = openfile->current;
|
||||
size_t was_column = xplustabs();
|
||||
size_t line_len = strlen(openfile->current->data);
|
||||
bool moved_off_chunk = TRUE;
|
||||
filestruct *was_current = openfile->current;
|
||||
size_t was_column = xplustabs();
|
||||
size_t line_len = strlen(openfile->current->data);
|
||||
bool moved_off_chunk = TRUE;
|
||||
|
||||
#ifndef NANO_TINY
|
||||
if (ISSET(SOFTWRAP)) {
|
||||
bool last_chunk = FALSE;
|
||||
size_t leftedge = leftedge_for(was_column, openfile->current);
|
||||
size_t rightedge = get_softwrap_breakpoint(openfile->current->data,
|
||||
leftedge, &last_chunk);
|
||||
size_t rightedge_x;
|
||||
if (ISSET(SOFTWRAP)) {
|
||||
bool last_chunk = FALSE;
|
||||
size_t leftedge = leftedge_for(was_column, openfile->current);
|
||||
size_t rightedge = get_softwrap_breakpoint(openfile->current->data,
|
||||
leftedge, &last_chunk);
|
||||
size_t rightedge_x;
|
||||
|
||||
/* If we're on the last chunk, we're already at the end of the line.
|
||||
* Otherwise, we're one column past the end of the line. Shifting
|
||||
* backwards one column might put us in the middle of a multi-column
|
||||
* character, but actual_x() will fix that. */
|
||||
if (!last_chunk)
|
||||
rightedge--;
|
||||
/* If we're on the last chunk, we're already at the end of the line.
|
||||
* Otherwise, we're one column past the end of the line. Shifting
|
||||
* backwards one column might put us in the middle of a multi-column
|
||||
* character, but actual_x() will fix that. */
|
||||
if (!last_chunk)
|
||||
rightedge--;
|
||||
|
||||
rightedge_x = actual_x(openfile->current->data, rightedge);
|
||||
rightedge_x = actual_x(openfile->current->data, rightedge);
|
||||
|
||||
/* If already at the right edge of the screen, move fully to
|
||||
* the end of the line. Otherwise, move to the right edge. */
|
||||
if (openfile->current_x == rightedge_x)
|
||||
openfile->current_x = line_len;
|
||||
else {
|
||||
openfile->current_x = rightedge_x;
|
||||
openfile->placewewant = rightedge;
|
||||
moved_off_chunk = FALSE;
|
||||
}
|
||||
} else
|
||||
/* If already at the right edge of the screen, move fully to
|
||||
* the end of the line. Otherwise, move to the right edge. */
|
||||
if (openfile->current_x == rightedge_x)
|
||||
openfile->current_x = line_len;
|
||||
else {
|
||||
openfile->current_x = rightedge_x;
|
||||
openfile->placewewant = rightedge;
|
||||
moved_off_chunk = FALSE;
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
openfile->current_x = line_len;
|
||||
openfile->current_x = line_len;
|
||||
|
||||
if (moved_off_chunk)
|
||||
openfile->placewewant = xplustabs();
|
||||
if (moved_off_chunk)
|
||||
openfile->placewewant = xplustabs();
|
||||
|
||||
/* If we changed chunk, we might be offscreen. Otherwise,
|
||||
* update current if the mark is on or we changed "page". */
|
||||
if (ISSET(SOFTWRAP) && moved_off_chunk)
|
||||
edit_redraw(was_current, FLOWING);
|
||||
else if (line_needs_update(was_column, openfile->placewewant))
|
||||
update_line(openfile->current, openfile->current_x);
|
||||
/* If we changed chunk, we might be offscreen. Otherwise,
|
||||
* update current if the mark is on or we changed "page". */
|
||||
if (ISSET(SOFTWRAP) && moved_off_chunk)
|
||||
edit_redraw(was_current, FLOWING);
|
||||
else if (line_needs_update(was_column, openfile->placewewant))
|
||||
update_line(openfile->current, openfile->current_x);
|
||||
}
|
||||
|
||||
/* Move the cursor to the preceding line or chunk. If scroll_only is TRUE,
|
||||
* also scroll the screen one row, so the cursor stays in the same spot. */
|
||||
void do_up(bool scroll_only)
|
||||
{
|
||||
filestruct *was_current = openfile->current;
|
||||
size_t leftedge, target_column;
|
||||
filestruct *was_current = openfile->current;
|
||||
size_t leftedge, target_column;
|
||||
|
||||
/* When just scrolling and the top of the file is onscreen, get out. */
|
||||
if (scroll_only && openfile->edittop == openfile->fileage &&
|
||||
openfile->firstcolumn == 0)
|
||||
return;
|
||||
/* When just scrolling and the top of the file is onscreen, get out. */
|
||||
if (scroll_only && openfile->edittop == openfile->fileage &&
|
||||
openfile->firstcolumn == 0)
|
||||
return;
|
||||
|
||||
get_edge_and_target(&leftedge, &target_column);
|
||||
get_edge_and_target(&leftedge, &target_column);
|
||||
|
||||
/* If we can't move up one line or chunk, we're at top of file. */
|
||||
if (go_back_chunks(1, &openfile->current, &leftedge) > 0)
|
||||
return;
|
||||
/* If we can't move up one line or chunk, we're at top of file. */
|
||||
if (go_back_chunks(1, &openfile->current, &leftedge) > 0)
|
||||
return;
|
||||
|
||||
set_proper_index_and_pww(&leftedge, target_column, FALSE);
|
||||
set_proper_index_and_pww(&leftedge, target_column, FALSE);
|
||||
|
||||
if (scroll_only)
|
||||
edit_scroll(BACKWARD, 1);
|
||||
if (scroll_only)
|
||||
edit_scroll(BACKWARD, 1);
|
||||
|
||||
edit_redraw(was_current, FLOWING);
|
||||
edit_redraw(was_current, FLOWING);
|
||||
|
||||
/* <Up> should not change placewewant, so restore it. */
|
||||
openfile->placewewant = leftedge + target_column;
|
||||
/* <Up> should not change placewewant, so restore it. */
|
||||
openfile->placewewant = leftedge + target_column;
|
||||
}
|
||||
|
||||
/* Move the cursor to next line or chunk. If scroll_only is TRUE, also
|
||||
* scroll the screen one row, so the cursor stays in the same spot. */
|
||||
void do_down(bool scroll_only)
|
||||
{
|
||||
filestruct *was_current = openfile->current;
|
||||
size_t leftedge, target_column;
|
||||
filestruct *was_current = openfile->current;
|
||||
size_t leftedge, target_column;
|
||||
|
||||
get_edge_and_target(&leftedge, &target_column);
|
||||
get_edge_and_target(&leftedge, &target_column);
|
||||
|
||||
/* If we can't move down one line or chunk, we're at bottom of file. */
|
||||
if (go_forward_chunks(1, &openfile->current, &leftedge) > 0)
|
||||
return;
|
||||
/* If we can't move down one line or chunk, we're at bottom of file. */
|
||||
if (go_forward_chunks(1, &openfile->current, &leftedge) > 0)
|
||||
return;
|
||||
|
||||
set_proper_index_and_pww(&leftedge, target_column, TRUE);
|
||||
set_proper_index_and_pww(&leftedge, target_column, TRUE);
|
||||
|
||||
if (scroll_only)
|
||||
edit_scroll(FORWARD, 1);
|
||||
if (scroll_only)
|
||||
edit_scroll(FORWARD, 1);
|
||||
|
||||
edit_redraw(was_current, FLOWING);
|
||||
edit_redraw(was_current, FLOWING);
|
||||
|
||||
/* <Down> should not change placewewant, so restore it. */
|
||||
openfile->placewewant = leftedge + target_column;
|
||||
/* <Down> should not change placewewant, so restore it. */
|
||||
openfile->placewewant = leftedge + target_column;
|
||||
}
|
||||
|
||||
/* Move up one line or chunk. */
|
||||
void do_up_void(void)
|
||||
{
|
||||
do_up(FALSE);
|
||||
do_up(FALSE);
|
||||
}
|
||||
|
||||
/* Move down one line or chunk. */
|
||||
void do_down_void(void)
|
||||
{
|
||||
do_down(FALSE);
|
||||
do_down(FALSE);
|
||||
}
|
||||
|
||||
#ifndef NANO_TINY
|
||||
/* Scroll up one line or chunk without scrolling the cursor. */
|
||||
void do_scroll_up(void)
|
||||
{
|
||||
do_up(TRUE);
|
||||
do_up(TRUE);
|
||||
}
|
||||
|
||||
/* Scroll down one line or chunk without scrolling the cursor. */
|
||||
void do_scroll_down(void)
|
||||
{
|
||||
do_down(TRUE);
|
||||
do_down(TRUE);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Move left one character. */
|
||||
void do_left(void)
|
||||
{
|
||||
filestruct *was_current = openfile->current;
|
||||
filestruct *was_current = openfile->current;
|
||||
|
||||
if (openfile->current_x > 0)
|
||||
openfile->current_x = move_mbleft(openfile->current->data,
|
||||
openfile->current_x);
|
||||
else if (openfile->current != openfile->fileage) {
|
||||
openfile->current = openfile->current->prev;
|
||||
openfile->current_x = strlen(openfile->current->data);
|
||||
}
|
||||
if (openfile->current_x > 0)
|
||||
openfile->current_x = move_mbleft(openfile->current->data,
|
||||
openfile->current_x);
|
||||
else if (openfile->current != openfile->fileage) {
|
||||
openfile->current = openfile->current->prev;
|
||||
openfile->current_x = strlen(openfile->current->data);
|
||||
}
|
||||
|
||||
edit_redraw(was_current, FLOWING);
|
||||
edit_redraw(was_current, FLOWING);
|
||||
}
|
||||
|
||||
/* Move right one character. */
|
||||
void do_right(void)
|
||||
{
|
||||
filestruct *was_current = openfile->current;
|
||||
filestruct *was_current = openfile->current;
|
||||
|
||||
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) {
|
||||
openfile->current = openfile->current->next;
|
||||
openfile->current_x = 0;
|
||||
}
|
||||
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) {
|
||||
openfile->current = openfile->current->next;
|
||||
openfile->current_x = 0;
|
||||
}
|
||||
|
||||
edit_redraw(was_current, FLOWING);
|
||||
edit_redraw(was_current, FLOWING);
|
||||
}
|
||||
|
||||
3265
src/nano.c
3265
src/nano.c
File diff suppressed because it is too large
Load Diff
625
src/nano.h
625
src/nano.h
@@ -111,7 +111,7 @@
|
||||
#endif
|
||||
#define gettext_noop(string) (string)
|
||||
#define N_(string) gettext_noop(string)
|
||||
/* Mark a string that will be sent to gettext() later. */
|
||||
/* Mark a string that will be sent to gettext() later. */
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
@@ -144,416 +144,415 @@
|
||||
|
||||
/* Enumeration types. */
|
||||
typedef enum {
|
||||
NIX_FILE, DOS_FILE, MAC_FILE
|
||||
NIX_FILE, DOS_FILE, MAC_FILE
|
||||
} file_format;
|
||||
|
||||
typedef enum {
|
||||
HUSH, MILD, ALERT
|
||||
HUSH, MILD, ALERT
|
||||
} message_type;
|
||||
|
||||
typedef enum {
|
||||
OVERWRITE, APPEND, PREPEND
|
||||
OVERWRITE, APPEND, PREPEND
|
||||
} kind_of_writing_type;
|
||||
|
||||
typedef enum {
|
||||
SOFTMARK, HARDMARK
|
||||
SOFTMARK, HARDMARK
|
||||
} mark_type;
|
||||
|
||||
typedef enum {
|
||||
CENTERING, FLOWING, STATIONARY
|
||||
CENTERING, FLOWING, STATIONARY
|
||||
} update_type;
|
||||
|
||||
typedef enum {
|
||||
ADD, DEL, BACK, CUT, CUT_TO_EOF, REPLACE,
|
||||
ADD, DEL, BACK, CUT, CUT_TO_EOF, REPLACE,
|
||||
#ifdef ENABLE_WRAPPING
|
||||
SPLIT_BEGIN, SPLIT_END,
|
||||
SPLIT_BEGIN, SPLIT_END,
|
||||
#endif
|
||||
INDENT, UNINDENT,
|
||||
INDENT, UNINDENT,
|
||||
#ifdef ENABLE_COMMENT
|
||||
COMMENT, UNCOMMENT, PREFLIGHT,
|
||||
COMMENT, UNCOMMENT, PREFLIGHT,
|
||||
#endif
|
||||
JOIN, PASTE, INSERT, ENTER, OTHER
|
||||
JOIN, PASTE, INSERT, ENTER, OTHER
|
||||
} undo_type;
|
||||
|
||||
/* Structure types. */
|
||||
#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? */
|
||||
int pairnum;
|
||||
/* The color pair number used for this foreground color and
|
||||
* background color. */
|
||||
int attributes;
|
||||
/* Pair number and brightness composed into ready-to-use attributes. */
|
||||
int rex_flags;
|
||||
/* The regex compilation flags (with or without REG_ICASE). */
|
||||
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. */
|
||||
int id;
|
||||
/* Basic id for assigning to lines later. */
|
||||
short fg;
|
||||
/* This syntax's foreground color. */
|
||||
short bg;
|
||||
/* This syntax's background color. */
|
||||
bool bright;
|
||||
/* Is this color A_BOLD? */
|
||||
int pairnum;
|
||||
/* The color pair number used for this foreground color and
|
||||
* background color. */
|
||||
int attributes;
|
||||
/* Pair number and brightness composed into ready-to-use attributes. */
|
||||
int rex_flags;
|
||||
/* The regex compilation flags (with or without REG_ICASE). */
|
||||
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. */
|
||||
int id;
|
||||
/* Basic id for assigning to lines later. */
|
||||
} colortype;
|
||||
|
||||
typedef struct regexlisttype {
|
||||
char *full_regex;
|
||||
/* A regex string to match things that imply a certain syntax. */
|
||||
struct regexlisttype *next;
|
||||
/* The next regex. */
|
||||
char *full_regex;
|
||||
/* A regex string to match things that imply a certain syntax. */
|
||||
struct regexlisttype *next;
|
||||
/* The next regex. */
|
||||
} regexlisttype;
|
||||
|
||||
typedef struct syntaxtype {
|
||||
char *name;
|
||||
/* The name of this syntax. */
|
||||
regexlisttype *extensions;
|
||||
/* The list of extensions that this syntax applies to. */
|
||||
regexlisttype *headers;
|
||||
/* The list of headerlines that this syntax applies to. */
|
||||
regexlisttype *magics;
|
||||
/* The list of libmagic results that this syntax applies to. */
|
||||
char *linter;
|
||||
/* The command with which to lint this type of file. */
|
||||
char *formatter;
|
||||
/* The formatting command (for programming languages mainly). */
|
||||
char *name;
|
||||
/* The name of this syntax. */
|
||||
regexlisttype *extensions;
|
||||
/* The list of extensions that this syntax applies to. */
|
||||
regexlisttype *headers;
|
||||
/* The list of headerlines that this syntax applies to. */
|
||||
regexlisttype *magics;
|
||||
/* The list of libmagic results that this syntax applies to. */
|
||||
char *linter;
|
||||
/* The command with which to lint this type of file. */
|
||||
char *formatter;
|
||||
/* The formatting command (for programming languages mainly). */
|
||||
#ifdef ENABLE_COMMENT
|
||||
char *comment;
|
||||
/* The line comment prefix (and postfix) for this type of file. */
|
||||
char *comment;
|
||||
/* The line comment prefix (and postfix) for this type of file. */
|
||||
#endif
|
||||
colortype *color;
|
||||
/* The colors and their regexes used in this syntax. */
|
||||
int nmultis;
|
||||
/* How many multiline regex strings this syntax has. */
|
||||
struct syntaxtype *next;
|
||||
/* Next syntax. */
|
||||
colortype *color;
|
||||
/* The colors and their regexes used in this syntax. */
|
||||
int nmultis;
|
||||
/* How many multiline regex strings this syntax has. */
|
||||
struct syntaxtype *next;
|
||||
/* Next syntax. */
|
||||
} syntaxtype;
|
||||
|
||||
typedef struct lintstruct {
|
||||
ssize_t lineno;
|
||||
/* Line number of the error. */
|
||||
ssize_t colno;
|
||||
/* Column # of the error. */
|
||||
char *msg;
|
||||
/* Error message text. */
|
||||
char *filename;
|
||||
/* Filename. */
|
||||
struct lintstruct *next;
|
||||
/* Next error. */
|
||||
struct lintstruct *prev;
|
||||
/* Previous error. */
|
||||
ssize_t lineno;
|
||||
/* Line number of the error. */
|
||||
ssize_t colno;
|
||||
/* Column # of the error. */
|
||||
char *msg;
|
||||
/* Error message text. */
|
||||
char *filename;
|
||||
/* Filename. */
|
||||
struct lintstruct *next;
|
||||
/* Next error. */
|
||||
struct lintstruct *prev;
|
||||
/* Previous error. */
|
||||
} lintstruct;
|
||||
|
||||
/* Flags that indicate how a multiline regex applies to a line. */
|
||||
#define CNONE (1<<1)
|
||||
/* Yay, regex doesn't apply to this line at all! */
|
||||
#define CBEGINBEFORE (1<<2)
|
||||
/* Regex starts on an earlier line, ends on this one. */
|
||||
#define CENDAFTER (1<<3)
|
||||
/* Regex starts on this line and ends on a later one. */
|
||||
#define CWHOLELINE (1<<4)
|
||||
/* Whole line engulfed by the regex, start < me, end > me. */
|
||||
#define CSTARTENDHERE (1<<5)
|
||||
/* Regex starts and ends within this line. */
|
||||
#define CWOULDBE (1<<6)
|
||||
/* An unpaired start match on or before this line. */
|
||||
#define CNONE (1<<1)
|
||||
/* Yay, regex doesn't apply to this line at all! */
|
||||
#define CBEGINBEFORE (1<<2)
|
||||
/* Regex starts on an earlier line, ends on this one. */
|
||||
#define CENDAFTER (1<<3)
|
||||
/* Regex starts on this line and ends on a later one. */
|
||||
#define CWHOLELINE (1<<4)
|
||||
/* Whole line engulfed by the regex, start < me, end > me. */
|
||||
#define CSTARTENDHERE (1<<5)
|
||||
/* Regex starts and ends within this line. */
|
||||
#define CWOULDBE (1<<6)
|
||||
/* An unpaired start match on or before this line. */
|
||||
#endif /* ENABLE_COLOR */
|
||||
|
||||
/* More 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. */
|
||||
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. */
|
||||
#ifdef ENABLE_COLOR
|
||||
short *multidata;
|
||||
/* Array of which multi-line regexes apply to this line. */
|
||||
short *multidata;
|
||||
/* Array of which multi-line regexes apply to this line. */
|
||||
#endif
|
||||
} 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. */
|
||||
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;
|
||||
|
||||
#ifndef NANO_TINY
|
||||
typedef struct undo_group {
|
||||
ssize_t top_line;
|
||||
/* First line of group. */
|
||||
ssize_t bottom_line;
|
||||
/* Last line of group. */
|
||||
char **indentations;
|
||||
/* String data used to restore the affected lines; one per line. */
|
||||
struct undo_group *next;
|
||||
ssize_t top_line;
|
||||
/* First line of group. */
|
||||
ssize_t bottom_line;
|
||||
/* Last line of group. */
|
||||
char **indentations;
|
||||
/* String data used to restore the affected lines; one per line. */
|
||||
struct undo_group *next;
|
||||
} undo_group;
|
||||
|
||||
typedef struct undo {
|
||||
ssize_t lineno;
|
||||
undo_type type;
|
||||
/* What type of undo this was. */
|
||||
size_t begin;
|
||||
/* Where did this action begin or end. */
|
||||
char *strdata;
|
||||
/* String type data we will use for copying the affected line back. */
|
||||
size_t wassize;
|
||||
/* The file size before the action. */
|
||||
size_t newsize;
|
||||
/* The file size after the action. */
|
||||
int xflags;
|
||||
/* Some flag data we need. */
|
||||
undo_group *grouping;
|
||||
/* Undo info specific to groups of lines. */
|
||||
ssize_t lineno;
|
||||
undo_type type;
|
||||
/* What type of undo this was. */
|
||||
size_t begin;
|
||||
/* Where did this action begin or end. */
|
||||
char *strdata;
|
||||
/* String type data we will use for copying the affected line back. */
|
||||
size_t wassize;
|
||||
/* The file size before the action. */
|
||||
size_t newsize;
|
||||
/* The file size after the action. */
|
||||
int xflags;
|
||||
/* Some flag data we need. */
|
||||
undo_group *grouping;
|
||||
/* Undo info specific to groups of lines. */
|
||||
|
||||
/* Cut-specific stuff we need. */
|
||||
filestruct *cutbuffer;
|
||||
/* Copy of the cutbuffer. */
|
||||
filestruct *cutbottom;
|
||||
/* Copy of cutbottom. */
|
||||
ssize_t mark_begin_lineno;
|
||||
/* Mostly the line number of the current line; sometimes something else. */
|
||||
size_t mark_begin_x;
|
||||
/* The x position corresponding to the above line number. */
|
||||
struct undo *next;
|
||||
/* A pointer to the undo item of the preceding action. */
|
||||
/* Cut-specific stuff we need. */
|
||||
filestruct *cutbuffer;
|
||||
/* Copy of the cutbuffer. */
|
||||
filestruct *cutbottom;
|
||||
/* Copy of cutbottom. */
|
||||
ssize_t mark_begin_lineno;
|
||||
/* Mostly the line number of the current line; sometimes something else. */
|
||||
size_t mark_begin_x;
|
||||
/* The x position corresponding to the above line number. */
|
||||
struct undo *next;
|
||||
/* A pointer to the undo item of the preceding action. */
|
||||
} undo;
|
||||
#endif /* !NANO_TINY */
|
||||
|
||||
#ifdef ENABLE_HISTORIES
|
||||
typedef struct poshiststruct {
|
||||
char *filename;
|
||||
/* The file. */
|
||||
ssize_t lineno;
|
||||
/* Line number we left off on. */
|
||||
ssize_t xno;
|
||||
/* x position in the file we left off on. */
|
||||
struct poshiststruct *next;
|
||||
char *filename;
|
||||
/* The file. */
|
||||
ssize_t lineno;
|
||||
/* Line number we left off on. */
|
||||
ssize_t xno;
|
||||
/* x position in the file we left off on. */
|
||||
struct poshiststruct *next;
|
||||
} poshiststruct;
|
||||
#endif
|
||||
|
||||
typedef struct openfilestruct {
|
||||
char *filename;
|
||||
/* The file's name. */
|
||||
filestruct *fileage;
|
||||
/* The file's first line. */
|
||||
filestruct *filebot;
|
||||
/* The file's last line. */
|
||||
filestruct *edittop;
|
||||
/* The current top of the edit window for this file. */
|
||||
filestruct *current;
|
||||
/* The current line for this file. */
|
||||
size_t totsize;
|
||||
/* The file's total number of characters. */
|
||||
size_t firstcolumn;
|
||||
/* The starting column of the top line of the edit window.
|
||||
* When not in softwrap mode, it's always zero. */
|
||||
size_t current_x;
|
||||
/* The file's x-coordinate position. */
|
||||
size_t placewewant;
|
||||
/* The file's x position we would like. */
|
||||
ssize_t current_y;
|
||||
/* The file's y-coordinate position. */
|
||||
bool modified;
|
||||
/* Whether the file has been modified. */
|
||||
struct stat *current_stat;
|
||||
/* The file's current stat information. */
|
||||
char *filename;
|
||||
/* The file's name. */
|
||||
filestruct *fileage;
|
||||
/* The file's first line. */
|
||||
filestruct *filebot;
|
||||
/* The file's last line. */
|
||||
filestruct *edittop;
|
||||
/* The current top of the edit window for this file. */
|
||||
filestruct *current;
|
||||
/* The current line for this file. */
|
||||
size_t totsize;
|
||||
/* The file's total number of characters. */
|
||||
size_t firstcolumn;
|
||||
/* The starting column of the top line of the edit window.
|
||||
* When not in softwrap mode, it's always zero. */
|
||||
size_t current_x;
|
||||
/* The file's x-coordinate position. */
|
||||
size_t placewewant;
|
||||
/* The file's x position we would like. */
|
||||
ssize_t current_y;
|
||||
/* The file's y-coordinate position. */
|
||||
bool modified;
|
||||
/* Whether the file has been modified. */
|
||||
struct stat *current_stat;
|
||||
/* The file's current stat information. */
|
||||
#ifndef NANO_TINY
|
||||
filestruct *mark;
|
||||
/* The line in the file where the mark is set; NULL if not set. */
|
||||
size_t mark_x;
|
||||
/* The mark's x position in the above line. */
|
||||
mark_type kind_of_mark;
|
||||
/* Whether it is a soft (with Shift) or a hard mark. */
|
||||
file_format fmt;
|
||||
/* The file's format -- Unix or DOS or Mac or mixed. */
|
||||
undo *undotop;
|
||||
/* The top of the undo list. */
|
||||
undo *current_undo;
|
||||
/* The current (i.e. next) level of undo. */
|
||||
undo_type last_action;
|
||||
/* The type of the last action the user performed. */
|
||||
bool pristine;
|
||||
/* Whether the undo stack still contains the first edit -- it won't
|
||||
* when a justification or spell check discarded the undo stack. */
|
||||
char *lock_filename;
|
||||
/* The path of the lockfile, if we created one. */
|
||||
filestruct *mark;
|
||||
/* The line in the file where the mark is set; NULL if not set. */
|
||||
size_t mark_x;
|
||||
/* The mark's x position in the above line. */
|
||||
mark_type kind_of_mark;
|
||||
/* Whether it is a soft (with Shift) or a hard mark. */
|
||||
file_format fmt;
|
||||
/* The file's format -- Unix or DOS or Mac or mixed. */
|
||||
undo *undotop;
|
||||
/* The top of the undo list. */
|
||||
undo *current_undo;
|
||||
/* The current (i.e. next) level of undo. */
|
||||
undo *last_saved;
|
||||
/* The undo item at which the file was last saved. */
|
||||
undo_type last_action;
|
||||
/* The type of the last action the user performed. */
|
||||
char *lock_filename;
|
||||
/* The path of the lockfile, if we created one. */
|
||||
#endif
|
||||
#ifdef ENABLE_COLOR
|
||||
syntaxtype *syntax;
|
||||
/* The syntax struct for this file, if any. */
|
||||
colortype *colorstrings;
|
||||
/* The file's associated colors. */
|
||||
syntaxtype *syntax;
|
||||
/* The syntax struct for this file, if any. */
|
||||
colortype *colorstrings;
|
||||
/* The file's associated colors. */
|
||||
#endif
|
||||
struct openfilestruct *next;
|
||||
/* The next open file, if any. */
|
||||
struct openfilestruct *prev;
|
||||
/* The preceding open file, if any. */
|
||||
struct openfilestruct *next;
|
||||
/* The next open file, if any. */
|
||||
struct openfilestruct *prev;
|
||||
/* The preceding open file, if any. */
|
||||
} openfilestruct;
|
||||
|
||||
#ifdef ENABLE_NANORC
|
||||
typedef struct rcoption {
|
||||
const char *name;
|
||||
/* The name of the rcfile option. */
|
||||
long flag;
|
||||
/* The flag associated with it, if any. */
|
||||
const char *name;
|
||||
/* The name of the rcfile option. */
|
||||
long flag;
|
||||
/* The flag associated with it, if any. */
|
||||
} rcoption;
|
||||
#endif
|
||||
|
||||
typedef struct sc {
|
||||
const char *keystr;
|
||||
/* The string that describes a keystroke, like "^C" or "M-R". */
|
||||
bool meta;
|
||||
/* Whether this is a Meta keystroke. */
|
||||
int keycode;
|
||||
/* The integer that, together with meta, identifies the keystroke. */
|
||||
int menus;
|
||||
/* Which menus this applies to. */
|
||||
void (*scfunc)(void);
|
||||
/* The function we're going to run. */
|
||||
const char *keystr;
|
||||
/* The string that describes a keystroke, like "^C" or "M-R". */
|
||||
bool meta;
|
||||
/* Whether this is a Meta keystroke. */
|
||||
int keycode;
|
||||
/* The integer that, together with meta, identifies the keystroke. */
|
||||
int menus;
|
||||
/* Which menus this applies to. */
|
||||
void (*scfunc)(void);
|
||||
/* The function we're going to run. */
|
||||
#ifndef NANO_TINY
|
||||
int toggle;
|
||||
/* If a toggle, what we're toggling. */
|
||||
int ordinal;
|
||||
/* The how-manieth toggle this is, in order to be able to
|
||||
* keep them in sequence. */
|
||||
int toggle;
|
||||
/* If a toggle, what we're toggling. */
|
||||
int ordinal;
|
||||
/* The how-manieth toggle this is, in order to be able to
|
||||
* keep them in sequence. */
|
||||
#endif
|
||||
struct sc *next;
|
||||
/* Next in the list. */
|
||||
struct sc *next;
|
||||
/* Next in the list. */
|
||||
} sc;
|
||||
|
||||
typedef struct subnfunc {
|
||||
void (*scfunc)(void);
|
||||
/* The actual function to call. */
|
||||
int menus;
|
||||
/* In what menus this function applies. */
|
||||
const char *desc;
|
||||
/* The function's short description, for example "Where Is". */
|
||||
void (*scfunc)(void);
|
||||
/* The actual function to call. */
|
||||
int menus;
|
||||
/* In what menus this function applies. */
|
||||
const char *desc;
|
||||
/* The function's short description, for example "Where Is". */
|
||||
#ifdef ENABLE_HELP
|
||||
const char *help;
|
||||
/* The help-screen text for this function. */
|
||||
bool blank_after;
|
||||
/* Whether there should be a blank line after the help text
|
||||
* for this function. */
|
||||
const char *help;
|
||||
/* The help-screen text for this function. */
|
||||
bool blank_after;
|
||||
/* Whether there should be a blank line after the help text
|
||||
* for this function. */
|
||||
#endif
|
||||
bool viewok;
|
||||
/* Is this function allowed when in view mode? */
|
||||
long toggle;
|
||||
/* If this is a toggle, which toggle to affect. */
|
||||
struct subnfunc *next;
|
||||
/* Next item in the list. */
|
||||
bool viewok;
|
||||
/* Is this function allowed when in view mode? */
|
||||
long toggle;
|
||||
/* If this is a toggle, which toggle to affect. */
|
||||
struct subnfunc *next;
|
||||
/* Next item in the list. */
|
||||
} subnfunc;
|
||||
|
||||
#ifdef ENABLE_WORDCOMPLETION
|
||||
typedef struct completion_word {
|
||||
char *word;
|
||||
struct completion_word *next;
|
||||
char *word;
|
||||
struct completion_word *next;
|
||||
} completion_word;
|
||||
#endif
|
||||
|
||||
/* The elements of the interface that can be colored differently. */
|
||||
enum
|
||||
{
|
||||
TITLE_BAR = 0,
|
||||
LINE_NUMBER,
|
||||
SELECTED_TEXT,
|
||||
STATUS_BAR,
|
||||
KEY_COMBO,
|
||||
FUNCTION_TAG,
|
||||
NUMBER_OF_ELEMENTS
|
||||
TITLE_BAR = 0,
|
||||
LINE_NUMBER,
|
||||
SELECTED_TEXT,
|
||||
STATUS_BAR,
|
||||
KEY_COMBO,
|
||||
FUNCTION_TAG,
|
||||
NUMBER_OF_ELEMENTS
|
||||
};
|
||||
|
||||
/* Enumeration used in the flags array. See the definition of FLAGMASK. */
|
||||
enum
|
||||
{
|
||||
DONTUSE,
|
||||
CASE_SENSITIVE,
|
||||
CONSTANT_SHOW,
|
||||
NO_HELP,
|
||||
SUSPEND,
|
||||
NO_WRAP,
|
||||
AUTOINDENT,
|
||||
VIEW_MODE,
|
||||
USE_MOUSE,
|
||||
USE_REGEXP,
|
||||
TEMP_FILE,
|
||||
CUT_FROM_CURSOR,
|
||||
BACKWARDS_SEARCH,
|
||||
MULTIBUFFER,
|
||||
SMOOTH_SCROLL,
|
||||
REBIND_DELETE,
|
||||
REBIND_KEYPAD,
|
||||
NO_CONVERT,
|
||||
BACKUP_FILE,
|
||||
INSECURE_BACKUP,
|
||||
NO_COLOR_SYNTAX,
|
||||
PRESERVE,
|
||||
HISTORYLOG,
|
||||
RESTRICTED,
|
||||
SMART_HOME,
|
||||
WHITESPACE_DISPLAY,
|
||||
MORE_SPACE,
|
||||
TABS_TO_SPACES,
|
||||
QUICK_BLANK,
|
||||
WORD_BOUNDS,
|
||||
NO_NEWLINES,
|
||||
BOLD_TEXT,
|
||||
QUIET,
|
||||
SOFTWRAP,
|
||||
POS_HISTORY,
|
||||
LOCKING,
|
||||
NOREAD_MODE,
|
||||
MAKE_IT_UNIX,
|
||||
JUSTIFY_TRIM,
|
||||
SHOW_CURSOR,
|
||||
LINE_NUMBERS,
|
||||
NO_PAUSES,
|
||||
AT_BLANKS
|
||||
DONTUSE,
|
||||
CASE_SENSITIVE,
|
||||
CONSTANT_SHOW,
|
||||
NO_HELP,
|
||||
SUSPEND,
|
||||
NO_WRAP,
|
||||
AUTOINDENT,
|
||||
VIEW_MODE,
|
||||
USE_MOUSE,
|
||||
USE_REGEXP,
|
||||
TEMP_FILE,
|
||||
CUT_FROM_CURSOR,
|
||||
BACKWARDS_SEARCH,
|
||||
MULTIBUFFER,
|
||||
SMOOTH_SCROLL,
|
||||
REBIND_DELETE,
|
||||
REBIND_KEYPAD,
|
||||
NO_CONVERT,
|
||||
BACKUP_FILE,
|
||||
INSECURE_BACKUP,
|
||||
NO_COLOR_SYNTAX,
|
||||
PRESERVE,
|
||||
HISTORYLOG,
|
||||
RESTRICTED,
|
||||
SMART_HOME,
|
||||
WHITESPACE_DISPLAY,
|
||||
MORE_SPACE,
|
||||
TABS_TO_SPACES,
|
||||
QUICK_BLANK,
|
||||
WORD_BOUNDS,
|
||||
NO_NEWLINES,
|
||||
BOLD_TEXT,
|
||||
QUIET,
|
||||
SOFTWRAP,
|
||||
POS_HISTORY,
|
||||
LOCKING,
|
||||
NOREAD_MODE,
|
||||
MAKE_IT_UNIX,
|
||||
TRIM_BLANKS,
|
||||
SHOW_CURSOR,
|
||||
LINE_NUMBERS,
|
||||
NO_PAUSES,
|
||||
AT_BLANKS
|
||||
};
|
||||
|
||||
/* Flags for the menus in which a given function should be present. */
|
||||
#define MMAIN (1<<0)
|
||||
#define MWHEREIS (1<<1)
|
||||
#define MREPLACE (1<<2)
|
||||
#define MREPLACEWITH (1<<3)
|
||||
#define MGOTOLINE (1<<4)
|
||||
#define MWRITEFILE (1<<5)
|
||||
#define MINSERTFILE (1<<6)
|
||||
#define MEXTCMD (1<<7)
|
||||
#define MHELP (1<<8)
|
||||
#define MSPELL (1<<9)
|
||||
#define MBROWSER (1<<10)
|
||||
#define MWHEREISFILE (1<<11)
|
||||
#define MGOTODIR (1<<12)
|
||||
#define MYESNO (1<<13)
|
||||
#define MLINTER (1<<14)
|
||||
#define MFINDINHELP (1<<15)
|
||||
#define MMAIN (1<<0)
|
||||
#define MWHEREIS (1<<1)
|
||||
#define MREPLACE (1<<2)
|
||||
#define MREPLACEWITH (1<<3)
|
||||
#define MGOTOLINE (1<<4)
|
||||
#define MWRITEFILE (1<<5)
|
||||
#define MINSERTFILE (1<<6)
|
||||
#define MEXTCMD (1<<7)
|
||||
#define MHELP (1<<8)
|
||||
#define MSPELL (1<<9)
|
||||
#define MBROWSER (1<<10)
|
||||
#define MWHEREISFILE (1<<11)
|
||||
#define MGOTODIR (1<<12)
|
||||
#define MYESNO (1<<13)
|
||||
#define MLINTER (1<<14)
|
||||
#define MFINDINHELP (1<<15)
|
||||
/* This is an abbreviation for all menus except Help and YesNo. */
|
||||
#define MMOST (MMAIN|MWHEREIS|MREPLACE|MREPLACEWITH|MGOTOLINE|MWRITEFILE|MINSERTFILE|\
|
||||
MEXTCMD|MBROWSER|MWHEREISFILE|MGOTODIR|MFINDINHELP|MSPELL|MLINTER)
|
||||
MEXTCMD|MBROWSER|MWHEREISFILE|MGOTODIR|MFINDINHELP|MSPELL|MLINTER)
|
||||
#ifndef NANO_TINY
|
||||
#define MSOME MMOST
|
||||
#else
|
||||
@@ -590,6 +589,7 @@ enum
|
||||
#define SHIFT_END 0x456
|
||||
#define SHIFT_PAGEUP 0x457
|
||||
#define SHIFT_PAGEDOWN 0x458
|
||||
#define SHIFT_TAB 0x45F
|
||||
|
||||
#ifdef USE_SLANG
|
||||
#ifdef ENABLE_UTF8
|
||||
@@ -605,11 +605,12 @@ enum
|
||||
#define KEY_WINCH -2
|
||||
|
||||
/* Some extra flags for the undo function. */
|
||||
#define WAS_FINAL_BACKSPACE (1<<1)
|
||||
#define WAS_WHOLE_LINE (1<<2)
|
||||
#define WAS_FINAL_BACKSPACE (1<<1)
|
||||
#define WAS_WHOLE_LINE (1<<2)
|
||||
#define WAS_FINAL_LINE (1<<3)
|
||||
/* The flags for the mark need to be the highest. */
|
||||
#define MARK_WAS_SET (1<<3)
|
||||
#define WAS_MARKED_FORWARD (1<<4)
|
||||
#define MARK_WAS_SET (1<<4)
|
||||
#define WAS_MARKED_FORWARD (1<<5)
|
||||
#endif /* !NANO_TINY */
|
||||
|
||||
/* The maximum number of entries displayed in the main shortcut list. */
|
||||
|
||||
987
src/prompt.c
987
src/prompt.c
File diff suppressed because it is too large
Load Diff
58
src/proto.h
58
src/proto.h
@@ -54,6 +54,8 @@ extern char *title;
|
||||
|
||||
extern bool more_than_one;
|
||||
|
||||
extern bool also_the_last;
|
||||
|
||||
extern int didfind;
|
||||
|
||||
extern int controlleft;
|
||||
@@ -189,8 +191,8 @@ void browser_refresh(void);
|
||||
void browser_select_dirname(const char *needle);
|
||||
void do_filesearch(void);
|
||||
void do_fileresearch(bool forwards);
|
||||
void do_first_file(void);
|
||||
void do_last_file(void);
|
||||
void to_first_file(void);
|
||||
void to_last_file(void);
|
||||
char *strip_last_component(const char *path);
|
||||
#endif
|
||||
|
||||
@@ -216,10 +218,8 @@ size_t move_mbright(const char *buf, size_t pos);
|
||||
int mbstrcasecmp(const char *s1, const char *s2);
|
||||
int mbstrncasecmp(const char *s1, const char *s2, size_t n);
|
||||
char *mbstrcasestr(const char *haystack, const char *needle);
|
||||
char *revstrstr(const char *haystack, const char *needle,
|
||||
const char *index);
|
||||
char *mbrevstrcasestr(const char *haystack, const char *needle,
|
||||
const char *index);
|
||||
char *revstrstr(const char *haystack, const char *needle, const char *index);
|
||||
char *mbrevstrcasestr(const char *haystack, const char *needle, const char *index);
|
||||
size_t mbstrlen(const char *s);
|
||||
size_t mbstrnlen(const char *s, size_t maxlen);
|
||||
#if !defined(NANO_TINY) || defined(ENABLE_JUSTIFY)
|
||||
@@ -266,12 +266,13 @@ void do_uncut_text(void);
|
||||
|
||||
/* Most functions in files.c. */
|
||||
void initialize_buffer_text(void);
|
||||
void set_modified(void);
|
||||
bool open_buffer(const char *filename, bool undoable);
|
||||
#ifdef ENABLE_SPELLER
|
||||
void replace_buffer(const char *filename);
|
||||
#ifndef NANO_TINY
|
||||
void replace_marked_buffer(const char *filename, filestruct *top, size_t top_x,
|
||||
filestruct *bot, size_t bot_x);
|
||||
filestruct *bot, size_t bot_x);
|
||||
#endif
|
||||
#endif
|
||||
void prepare_for_display(void);
|
||||
@@ -281,7 +282,7 @@ void switch_to_next_buffer(void);
|
||||
bool close_buffer(void);
|
||||
#endif
|
||||
void read_file(FILE *f, int fd, const char *filename, bool undoable,
|
||||
bool checkwritable);
|
||||
bool checkwritable);
|
||||
int open_file(const char *filename, bool newfie, bool quiet, FILE **f);
|
||||
char *get_next_filename(const char *name, const char *suffix);
|
||||
void do_insertfile_void(void);
|
||||
@@ -298,10 +299,10 @@ int write_lockfile(const char *lockfilename, const char *origfilename, bool modi
|
||||
#endif
|
||||
int copy_file(FILE *inn, FILE *out, bool close_out);
|
||||
bool write_file(const char *name, FILE *f_open, bool tmp,
|
||||
kind_of_writing_type method, bool nonamechange);
|
||||
kind_of_writing_type method, bool fullbuffer);
|
||||
#ifndef NANO_TINY
|
||||
bool write_marked_file(const char *name, FILE *f_open, bool tmp,
|
||||
kind_of_writing_type method);
|
||||
kind_of_writing_type method);
|
||||
#endif
|
||||
int do_writeout(bool exiting, bool withprompt);
|
||||
void do_writeout_void(void);
|
||||
@@ -312,7 +313,7 @@ int diralphasort(const void *va, const void *vb);
|
||||
#endif
|
||||
#ifdef ENABLE_TABCOMP
|
||||
char *input_tab(char *buf, bool allow_files, size_t *place,
|
||||
bool *lastwastab, void (*refresh_func)(void), bool *listed);
|
||||
bool *lastwastab, void (*refresh_func)(void), bool *listed);
|
||||
#endif
|
||||
|
||||
/* Some functions in global.c. */
|
||||
@@ -367,8 +368,8 @@ bool has_old_position(const char *file, ssize_t *line, ssize_t *column);
|
||||
#endif
|
||||
|
||||
/* Most functions in move.c. */
|
||||
void do_first_line(void);
|
||||
void do_last_line(void);
|
||||
void to_first_line(void);
|
||||
void to_last_line(void);
|
||||
void do_page_up(void);
|
||||
void do_page_down(void);
|
||||
#ifdef ENABLE_JUSTIFY
|
||||
@@ -405,10 +406,10 @@ 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);
|
||||
filestruct *bot, size_t bot_x);
|
||||
void unpartition_filestruct(partition **p);
|
||||
void extract_buffer(filestruct **file_top, filestruct **file_bot,
|
||||
filestruct *top, size_t top_x, filestruct *bot, size_t bot_x);
|
||||
filestruct *top, size_t top_x, filestruct *bot, size_t bot_x);
|
||||
void ingraft_buffer(filestruct *somebuffer);
|
||||
void copy_from_buffer(filestruct *somebuffer);
|
||||
openfilestruct *make_new_opennode(void);
|
||||
@@ -450,8 +451,7 @@ void do_output(char *output, size_t output_len, bool allow_cntrls);
|
||||
#ifdef ENABLE_MOUSE
|
||||
int do_statusbar_mouse(void);
|
||||
#endif
|
||||
void do_statusbar_output(int *the_input, size_t input_len,
|
||||
bool filtering);
|
||||
void do_statusbar_output(int *the_input, size_t input_len, bool filtering);
|
||||
void do_statusbar_home(void);
|
||||
void do_statusbar_end(void);
|
||||
void do_statusbar_left(void);
|
||||
@@ -470,8 +470,8 @@ size_t get_statusbar_page_start(size_t start_col, size_t column);
|
||||
void reinit_statusbar_x(void);
|
||||
void update_the_statusbar(void);
|
||||
int do_prompt(bool allow_tabs, bool allow_files,
|
||||
int menu, const char *curranswer, filestruct **history_list,
|
||||
void (*refresh_func)(void), const char *msg, ...);
|
||||
int menu, const char *curranswer, filestruct **history_list,
|
||||
void (*refresh_func)(void), const char *msg, ...);
|
||||
int do_yesno_prompt(bool all, const char *msg);
|
||||
|
||||
/* Most functions in rcfile.c. */
|
||||
@@ -488,7 +488,7 @@ void do_rcfiles(void);
|
||||
void not_found_msg(const char *str);
|
||||
void search_replace_abort(void);
|
||||
int findnextstr(const char *needle, bool whole_word_only, int modus,
|
||||
size_t *match_len, bool skipone, const filestruct *begin, size_t begin_x);
|
||||
size_t *match_len, bool skipone, const filestruct *begin, size_t begin_x);
|
||||
void do_search(void);
|
||||
void do_search_forward(void);
|
||||
void do_search_backward(void);
|
||||
@@ -499,11 +499,11 @@ void do_findnext(void);
|
||||
void do_research(void);
|
||||
void go_looking(void);
|
||||
ssize_t do_replace_loop(const char *needle, bool whole_word_only,
|
||||
const filestruct *real_current, size_t *real_current_x);
|
||||
const filestruct *real_current, size_t *real_current_x);
|
||||
void do_replace(void);
|
||||
void goto_line_posx(ssize_t line, size_t pos_x);
|
||||
void do_gotolinecolumn(ssize_t line, ssize_t column, bool use_answer,
|
||||
bool interactive);
|
||||
bool interactive);
|
||||
void do_gotolinecolumn_void(void);
|
||||
#ifndef NANO_TINY
|
||||
void do_find_bracket(void);
|
||||
@@ -592,7 +592,7 @@ const char *fixbounds(const char *r);
|
||||
bool is_separate_word(size_t position, size_t length, const char *buf);
|
||||
#endif
|
||||
const char *strstrwrapper(const char *haystack, const char *needle,
|
||||
const char *start);
|
||||
const char *start);
|
||||
void nperror(const char *s);
|
||||
void *nmalloc(size_t howmuch);
|
||||
void *nrealloc(void *ptr, size_t howmuch);
|
||||
@@ -609,8 +609,9 @@ void new_magicline(void);
|
||||
void remove_magicline(void);
|
||||
#endif
|
||||
#ifndef NANO_TINY
|
||||
void mark_order(const filestruct **top, size_t *top_x, const filestruct
|
||||
**bot, size_t *bot_x, bool *right_side_up);
|
||||
void mark_order(const filestruct **top, size_t *top_x,
|
||||
const filestruct **bot, size_t *bot_x, bool *right_side_up);
|
||||
void get_range(const filestruct **top, const filestruct **bot);
|
||||
#endif
|
||||
size_t get_totsize(const filestruct *begin, const filestruct *end);
|
||||
#ifndef NANO_TINY
|
||||
@@ -618,7 +619,6 @@ filestruct *fsfromline(ssize_t lineno);
|
||||
#endif
|
||||
#ifdef DEBUG
|
||||
void dump_filestruct(const filestruct *inptr);
|
||||
void dump_filestruct_reverse(void);
|
||||
#endif
|
||||
|
||||
/* Most functions in winio.c. */
|
||||
@@ -642,11 +642,11 @@ const sc *get_shortcut(int *kbinput);
|
||||
void blank_row(WINDOW *win, int y, int x, int n);
|
||||
void blank_edit(void);
|
||||
void blank_statusbar(void);
|
||||
void wipe_statusbar(void);
|
||||
void blank_bottombars(void);
|
||||
void check_statusblank(void);
|
||||
char *display_string(const char *buf, size_t column, size_t span, bool isdata);
|
||||
void titlebar(const char *path);
|
||||
extern void set_modified(void);
|
||||
void statusbar(const char *msg);
|
||||
void warn_and_shortly_pause(const char *msg);
|
||||
void statusline(message_type importance, const char *msg, ...);
|
||||
@@ -654,7 +654,7 @@ void bottombars(int menu);
|
||||
void post_one_key(const char *keystroke, const char *tag, int width);
|
||||
void place_the_cursor(void);
|
||||
void edit_draw(filestruct *fileptr, const char *converted,
|
||||
int line, size_t from_col);
|
||||
int line, size_t from_col);
|
||||
int update_line(filestruct *fileptr, size_t index);
|
||||
#ifndef NANO_TINY
|
||||
int update_softwrapped_line(filestruct *fileptr);
|
||||
@@ -666,7 +666,7 @@ bool less_than_a_screenful(size_t was_lineno, size_t was_leftedge);
|
||||
void edit_scroll(bool direction, int nrows);
|
||||
#ifndef NANO_TINY
|
||||
size_t get_softwrap_breakpoint(const char *text, size_t leftedge,
|
||||
bool *end_of_line);
|
||||
bool *end_of_line);
|
||||
size_t get_chunk_and_edge(size_t column, filestruct *line, size_t *leftedge);
|
||||
size_t chunk_for(size_t column, filestruct *line);
|
||||
size_t leftedge_for(size_t column, filestruct *line);
|
||||
|
||||
1743
src/rcfile.c
1743
src/rcfile.c
File diff suppressed because it is too large
Load Diff
1543
src/search.c
1543
src/search.c
File diff suppressed because it is too large
Load Diff
5685
src/text.c
5685
src/text.c
File diff suppressed because it is too large
Load Diff
653
src/utils.c
653
src/utils.c
@@ -32,79 +32,79 @@
|
||||
* 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 (homedir == NULL) {
|
||||
const char *homenv = getenv("HOME");
|
||||
|
||||
#ifdef HAVE_PWD_H
|
||||
/* When HOME isn't set, or when we're root, get the home directory
|
||||
* from the password file instead. */
|
||||
if (homenv == NULL || geteuid() == 0) {
|
||||
const struct passwd *userage = getpwuid(geteuid());
|
||||
/* When HOME isn't set, or when we're root, get the home directory
|
||||
* from the password file instead. */
|
||||
if (homenv == NULL || geteuid() == 0) {
|
||||
const struct passwd *userage = getpwuid(geteuid());
|
||||
|
||||
if (userage != NULL)
|
||||
homenv = userage->pw_dir;
|
||||
}
|
||||
if (userage != NULL)
|
||||
homenv = userage->pw_dir;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Only set homedir if some home directory could be determined,
|
||||
* otherwise keep homedir NULL. */
|
||||
if (homenv != NULL && strcmp(homenv, "") != 0)
|
||||
homedir = mallocstrcpy(NULL, homenv);
|
||||
}
|
||||
/* Only set homedir if some home directory could be determined,
|
||||
* otherwise keep homedir NULL. */
|
||||
if (homenv != NULL && strcmp(homenv, "") != 0)
|
||||
homedir = mallocstrcpy(NULL, homenv);
|
||||
}
|
||||
}
|
||||
|
||||
/* Return the filename part of the given path. */
|
||||
const char *tail(const char *path)
|
||||
{
|
||||
const char *slash = strrchr(path, '/');
|
||||
const char *slash = strrchr(path, '/');
|
||||
|
||||
if (slash == NULL)
|
||||
return path;
|
||||
else
|
||||
return ++slash;
|
||||
if (slash == NULL)
|
||||
return path;
|
||||
else
|
||||
return ++slash;
|
||||
}
|
||||
|
||||
/* Return a copy of the two given strings, welded together. */
|
||||
char *concatenate(const char *path, const char *name)
|
||||
{
|
||||
size_t pathlen = strlen(path);
|
||||
char *joined = charalloc(pathlen + strlen(name) + 1);
|
||||
size_t pathlen = strlen(path);
|
||||
char *joined = charalloc(pathlen + strlen(name) + 1);
|
||||
|
||||
strcpy(joined, path);
|
||||
strcpy(joined + pathlen, name);
|
||||
strcpy(joined, path);
|
||||
strcpy(joined + pathlen, name);
|
||||
|
||||
return joined;
|
||||
return joined;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_LINENUMBERS
|
||||
/* Return the number of digits that the given integer n takes up. */
|
||||
int digits(ssize_t n)
|
||||
{
|
||||
if (n < 100000) {
|
||||
if (n < 1000) {
|
||||
if (n < 100)
|
||||
return 2;
|
||||
else
|
||||
return 3;
|
||||
if (n < 100000) {
|
||||
if (n < 1000) {
|
||||
if (n < 100)
|
||||
return 2;
|
||||
else
|
||||
return 3;
|
||||
} else {
|
||||
if (n < 10000)
|
||||
return 4;
|
||||
else
|
||||
return 5;
|
||||
}
|
||||
} else {
|
||||
if (n < 10000)
|
||||
return 4;
|
||||
else
|
||||
return 5;
|
||||
if (n < 10000000) {
|
||||
if (n < 1000000)
|
||||
return 6;
|
||||
else
|
||||
return 7;
|
||||
} else {
|
||||
if (n < 100000000)
|
||||
return 8;
|
||||
else
|
||||
return 9;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (n < 10000000) {
|
||||
if (n < 1000000)
|
||||
return 6;
|
||||
else
|
||||
return 7;
|
||||
} else {
|
||||
if (n < 100000000)
|
||||
return 8;
|
||||
else
|
||||
return 9;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -112,98 +112,98 @@ int digits(ssize_t n)
|
||||
* and return TRUE; otherwise, return FALSE. */
|
||||
bool parse_num(const char *str, ssize_t *result)
|
||||
{
|
||||
char *first_error;
|
||||
ssize_t value;
|
||||
char *first_error;
|
||||
ssize_t value;
|
||||
|
||||
/* The manual page for strtol() says this is required. */
|
||||
errno = 0;
|
||||
/* The manual page for strtol() says this is required. */
|
||||
errno = 0;
|
||||
|
||||
value = (ssize_t)strtol(str, &first_error, 10);
|
||||
value = (ssize_t)strtol(str, &first_error, 10);
|
||||
|
||||
if (errno == ERANGE || *str == '\0' || *first_error != '\0')
|
||||
return FALSE;
|
||||
if (errno == ERANGE || *str == '\0' || *first_error != '\0')
|
||||
return FALSE;
|
||||
|
||||
*result = value;
|
||||
*result = value;
|
||||
|
||||
return TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Read two numbers, separated by a comma, from str, and store them in
|
||||
* *line and *column. Return FALSE on error, and TRUE otherwise. */
|
||||
bool parse_line_column(const char *str, ssize_t *line, ssize_t *column)
|
||||
{
|
||||
bool retval;
|
||||
char *firstpart;
|
||||
const char *comma;
|
||||
bool retval;
|
||||
char *firstpart;
|
||||
const char *comma;
|
||||
|
||||
while (*str == ' ')
|
||||
str++;
|
||||
while (*str == ' ')
|
||||
str++;
|
||||
|
||||
comma = strpbrk(str, "m,. /;");
|
||||
comma = strpbrk(str, "m,. /;");
|
||||
|
||||
if (comma == NULL)
|
||||
return parse_num(str, line);
|
||||
if (comma == NULL)
|
||||
return parse_num(str, line);
|
||||
|
||||
retval = parse_num(comma + 1, column);
|
||||
retval = parse_num(comma + 1, column);
|
||||
|
||||
if (comma == str)
|
||||
return retval;
|
||||
|
||||
firstpart = mallocstrcpy(NULL, str);
|
||||
firstpart[comma - str] = '\0';
|
||||
|
||||
retval = parse_num(firstpart, line) && retval;
|
||||
|
||||
free(firstpart);
|
||||
|
||||
if (comma == str)
|
||||
return retval;
|
||||
|
||||
firstpart = mallocstrcpy(NULL, str);
|
||||
firstpart[comma - str] = '\0';
|
||||
|
||||
retval = parse_num(firstpart, line) && retval;
|
||||
|
||||
free(firstpart);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* Reduce the memory allocation of a string to what is needed. */
|
||||
void snuggly_fit(char **str)
|
||||
{
|
||||
if (*str != NULL)
|
||||
*str = charealloc(*str, strlen(*str) + 1);
|
||||
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)
|
||||
{
|
||||
*data = charealloc(*data, index + 1);
|
||||
(*data)[index] = '\0';
|
||||
*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)
|
||||
{
|
||||
for (; true_len > 0; true_len--, str++) {
|
||||
if (*str == '\0')
|
||||
*str = '\n';
|
||||
}
|
||||
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)
|
||||
{
|
||||
for (; *str != '\0'; str++) {
|
||||
if (*str == '\n')
|
||||
*str = '\0';
|
||||
}
|
||||
for (; *str != '\0'; str++) {
|
||||
if (*str == '\n')
|
||||
*str = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(ENABLE_TINY) || defined(ENABLE_TABCOMP) || defined(ENABLE_BROWSER)
|
||||
/* Free the memory of the given array, which should contain len elements. */
|
||||
void free_chararray(char **array, size_t len)
|
||||
{
|
||||
if (array == NULL)
|
||||
return;
|
||||
if (array == NULL)
|
||||
return;
|
||||
|
||||
while (len > 0)
|
||||
free(array[--len]);
|
||||
while (len > 0)
|
||||
free(array[--len]);
|
||||
|
||||
free(array);
|
||||
free(array);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -212,30 +212,30 @@ void free_chararray(char **array, size_t len)
|
||||
const char *fixbounds(const char *r)
|
||||
{
|
||||
#ifndef GNU_WORDBOUNDS
|
||||
int i, j = 0;
|
||||
char *r2 = charalloc(strlen(r) * 5);
|
||||
char *r3;
|
||||
int i, j = 0;
|
||||
char *r2 = charalloc(strlen(r) * 5);
|
||||
char *r3;
|
||||
|
||||
for (i = 0; i < strlen(r); i++) {
|
||||
if (r[i] != '\0' && r[i] == '\\' && (r[i + 1] == '>' || r[i + 1] == '<')) {
|
||||
strcpy(&r2[j], "[[:");
|
||||
r2[j + 3] = r[i + 1];
|
||||
strcpy(&r2[j + 4], ":]]");
|
||||
i++;
|
||||
j += 6;
|
||||
} else
|
||||
r2[j] = r[i];
|
||||
j++;
|
||||
}
|
||||
for (i = 0; i < strlen(r); i++) {
|
||||
if (r[i] != '\0' && r[i] == '\\' && (r[i + 1] == '>' || r[i + 1] == '<')) {
|
||||
strcpy(&r2[j], "[[:");
|
||||
r2[j + 3] = r[i + 1];
|
||||
strcpy(&r2[j + 4], ":]]");
|
||||
i++;
|
||||
j += 6;
|
||||
} else
|
||||
r2[j] = r[i];
|
||||
j++;
|
||||
}
|
||||
|
||||
r2[j] = '\0';
|
||||
r3 = mallocstrcpy(NULL, r2);
|
||||
free(r2);
|
||||
r2[j] = '\0';
|
||||
r3 = mallocstrcpy(NULL, r2);
|
||||
free(r2);
|
||||
|
||||
return (const char *) r3;
|
||||
return (const char *) r3;
|
||||
#endif /* !GNU_WORDBOUNDS */
|
||||
|
||||
return r;
|
||||
return r;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_SPELLER
|
||||
@@ -243,18 +243,18 @@ const char *fixbounds(const char *r)
|
||||
* a separate word? That is: is it not part of a longer word?*/
|
||||
bool is_separate_word(size_t position, size_t length, const char *buf)
|
||||
{
|
||||
char before[MAXCHARLEN], after[MAXCHARLEN];
|
||||
size_t word_end = position + length;
|
||||
char before[MAXCHARLEN], after[MAXCHARLEN];
|
||||
size_t word_end = position + length;
|
||||
|
||||
/* Get the characters before and after the word, if any. */
|
||||
parse_mbchar(buf + move_mbleft(buf, position), before, NULL);
|
||||
parse_mbchar(buf + word_end, after, NULL);
|
||||
/* Get the characters before and after the word, if any. */
|
||||
parse_mbchar(buf + move_mbleft(buf, position), before, NULL);
|
||||
parse_mbchar(buf + word_end, after, NULL);
|
||||
|
||||
/* If the word starts at the beginning of the line OR the character before
|
||||
* the word isn't a letter, and if the word ends at the end of the line OR
|
||||
* the character after the word isn't a letter, we have a whole word. */
|
||||
return ((position == 0 || !is_alpha_mbchar(before)) &&
|
||||
(buf[word_end] == '\0' || !is_alpha_mbchar(after)));
|
||||
/* If the word starts at the beginning of the line OR the character before
|
||||
* the word isn't a letter, and if the word ends at the end of the line OR
|
||||
* the character after the word isn't a letter, we have a whole word. */
|
||||
return ((position == 0 || !is_alpha_mbchar(before)) &&
|
||||
(buf[word_end] == '\0' || !is_alpha_mbchar(after)));
|
||||
}
|
||||
#endif /* ENABLE_SPELLER */
|
||||
|
||||
@@ -264,76 +264,76 @@ bool is_separate_word(size_t position, size_t length, const char *buf)
|
||||
* than start. If we are doing a regexp search, and we find a match, we fill
|
||||
* in the global variable regmatches with at most 9 subexpression matches. */
|
||||
const char *strstrwrapper(const char *haystack, const char *needle,
|
||||
const char *start)
|
||||
const char *start)
|
||||
{
|
||||
if (*needle == '\0') {
|
||||
if (*needle == '\0') {
|
||||
#ifndef NANO_TINY
|
||||
statusline(ALERT, "Searching for nothing -- please report a bug");
|
||||
statusline(ALERT, "Searching for nothing -- please report a bug");
|
||||
#endif
|
||||
return (char *)start;
|
||||
}
|
||||
|
||||
if (ISSET(USE_REGEXP)) {
|
||||
if (ISSET(BACKWARDS_SEARCH)) {
|
||||
size_t last_find, ceiling, far_end;
|
||||
size_t floor = 0, next_rung = 0;
|
||||
/* The start of the search range, and the next start. */
|
||||
|
||||
if (regexec(&search_regexp, haystack, 1, regmatches, 0) != 0)
|
||||
return NULL;
|
||||
|
||||
far_end = strlen(haystack);
|
||||
ceiling = start - haystack;
|
||||
last_find = regmatches[0].rm_so;
|
||||
|
||||
/* A result beyond the search range also means: no match. */
|
||||
if (last_find > ceiling)
|
||||
return NULL;
|
||||
|
||||
/* Move the start-of-range forward until there is no more match;
|
||||
* then the last match found is the first match backwards. */
|
||||
while (regmatches[0].rm_so <= ceiling) {
|
||||
floor = next_rung;
|
||||
last_find = regmatches[0].rm_so;
|
||||
/* If this is the last possible match, don't try to advance. */
|
||||
if (last_find == ceiling)
|
||||
break;
|
||||
next_rung = move_mbright(haystack, last_find);
|
||||
regmatches[0].rm_so = next_rung;
|
||||
regmatches[0].rm_eo = far_end;
|
||||
if (regexec(&search_regexp, haystack, 1, regmatches,
|
||||
REG_STARTEND) != 0)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Find the last match again, to get possible submatches. */
|
||||
regmatches[0].rm_so = floor;
|
||||
regmatches[0].rm_eo = far_end;
|
||||
if (regexec(&search_regexp, haystack, 10, regmatches,
|
||||
REG_STARTEND) != 0)
|
||||
return NULL;
|
||||
|
||||
return haystack + regmatches[0].rm_so;
|
||||
return (char *)start;
|
||||
}
|
||||
|
||||
/* Do a forward regex search from the starting point. */
|
||||
regmatches[0].rm_so = start - haystack;
|
||||
regmatches[0].rm_eo = strlen(haystack);
|
||||
if (regexec(&search_regexp, haystack, 10, regmatches,
|
||||
REG_STARTEND) != 0)
|
||||
return NULL;
|
||||
else
|
||||
return haystack + regmatches[0].rm_so;
|
||||
}
|
||||
if (ISSET(CASE_SENSITIVE)) {
|
||||
if (ISSET(BACKWARDS_SEARCH))
|
||||
return revstrstr(haystack, needle, start);
|
||||
else
|
||||
return strstr(start, needle);
|
||||
} else if (ISSET(BACKWARDS_SEARCH))
|
||||
return mbrevstrcasestr(haystack, needle, start);
|
||||
if (ISSET(USE_REGEXP)) {
|
||||
if (ISSET(BACKWARDS_SEARCH)) {
|
||||
size_t last_find, ceiling, far_end;
|
||||
size_t floor = 0, next_rung = 0;
|
||||
/* The start of the search range, and the next start. */
|
||||
|
||||
return mbstrcasestr(start, needle);
|
||||
if (regexec(&search_regexp, haystack, 1, regmatches, 0) != 0)
|
||||
return NULL;
|
||||
|
||||
far_end = strlen(haystack);
|
||||
ceiling = start - haystack;
|
||||
last_find = regmatches[0].rm_so;
|
||||
|
||||
/* A result beyond the search range also means: no match. */
|
||||
if (last_find > ceiling)
|
||||
return NULL;
|
||||
|
||||
/* Move the start-of-range forward until there is no more match;
|
||||
* then the last match found is the first match backwards. */
|
||||
while (regmatches[0].rm_so <= ceiling) {
|
||||
floor = next_rung;
|
||||
last_find = regmatches[0].rm_so;
|
||||
/* If this is the last possible match, don't try to advance. */
|
||||
if (last_find == ceiling)
|
||||
break;
|
||||
next_rung = move_mbright(haystack, last_find);
|
||||
regmatches[0].rm_so = next_rung;
|
||||
regmatches[0].rm_eo = far_end;
|
||||
if (regexec(&search_regexp, haystack, 1, regmatches,
|
||||
REG_STARTEND) != 0)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Find the last match again, to get possible submatches. */
|
||||
regmatches[0].rm_so = floor;
|
||||
regmatches[0].rm_eo = far_end;
|
||||
if (regexec(&search_regexp, haystack, 10, regmatches,
|
||||
REG_STARTEND) != 0)
|
||||
return NULL;
|
||||
|
||||
return haystack + regmatches[0].rm_so;
|
||||
}
|
||||
|
||||
/* Do a forward regex search from the starting point. */
|
||||
regmatches[0].rm_so = start - haystack;
|
||||
regmatches[0].rm_eo = strlen(haystack);
|
||||
if (regexec(&search_regexp, haystack, 10, regmatches,
|
||||
REG_STARTEND) != 0)
|
||||
return NULL;
|
||||
else
|
||||
return haystack + regmatches[0].rm_so;
|
||||
}
|
||||
if (ISSET(CASE_SENSITIVE)) {
|
||||
if (ISSET(BACKWARDS_SEARCH))
|
||||
return revstrstr(haystack, needle, start);
|
||||
else
|
||||
return strstr(start, needle);
|
||||
} else if (ISSET(BACKWARDS_SEARCH))
|
||||
return mbrevstrcasestr(haystack, needle, start);
|
||||
|
||||
return mbstrcasestr(start, needle);
|
||||
}
|
||||
|
||||
/* This is a wrapper for the perror() function. The wrapper temporarily
|
||||
@@ -342,64 +342,63 @@ const char *strstrwrapper(const char *haystack, const char *needle,
|
||||
* nperror() causes the window to flicker once. */
|
||||
void nperror(const char *s)
|
||||
{
|
||||
endwin();
|
||||
perror(s);
|
||||
doupdate();
|
||||
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... */
|
||||
* things when we run out of memory. */
|
||||
void *nmalloc(size_t howmuch)
|
||||
{
|
||||
void *r = malloc(howmuch);
|
||||
void *r = malloc(howmuch);
|
||||
|
||||
if (r == NULL && howmuch != 0)
|
||||
die(_("nano is out of memory!"));
|
||||
if (r == NULL && howmuch != 0)
|
||||
die(_("nano is out of memory!"));
|
||||
|
||||
return r;
|
||||
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);
|
||||
void *r = realloc(ptr, howmuch);
|
||||
|
||||
if (r == NULL && howmuch != 0)
|
||||
die(_("nano is out of memory!"));
|
||||
if (r == NULL && howmuch != 0)
|
||||
die(_("nano is out of memory!"));
|
||||
|
||||
return r;
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Allocate and copy the first n characters of the given src string, after
|
||||
* freeing the destination. Usage: "dest = mallocstrncpy(dest, src, n);". */
|
||||
char *mallocstrncpy(char *dest, const char *src, size_t n)
|
||||
{
|
||||
if (src == NULL)
|
||||
src = "";
|
||||
if (src == NULL)
|
||||
src = "";
|
||||
|
||||
if (src != dest)
|
||||
free(dest);
|
||||
if (src != dest)
|
||||
free(dest);
|
||||
|
||||
dest = charalloc(n);
|
||||
strncpy(dest, src, n);
|
||||
dest = charalloc(n);
|
||||
strncpy(dest, src, n);
|
||||
|
||||
return dest;
|
||||
return dest;
|
||||
}
|
||||
|
||||
/* Free the dest string and return a malloc'ed copy of src. 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);
|
||||
return mallocstrncpy(dest, src, (src == NULL) ? 1 : strlen(src) + 1);
|
||||
}
|
||||
|
||||
/* Free the string at dest and return the string at src. */
|
||||
char *free_and_assign(char *dest, char *src)
|
||||
{
|
||||
free(dest);
|
||||
return src;
|
||||
free(dest);
|
||||
return src;
|
||||
}
|
||||
|
||||
/* When not in softwrap mode, nano scrolls horizontally within a line in
|
||||
@@ -409,193 +408,199 @@ char *free_and_assign(char *dest, char *src)
|
||||
* get_page_start(column) < COLS). */
|
||||
size_t get_page_start(size_t column)
|
||||
{
|
||||
if (column < editwincols - 1 || ISSET(SOFTWRAP) || column == 0)
|
||||
return 0;
|
||||
else if (editwincols > 8)
|
||||
return column - 7 - (column - 7) % (editwincols - 8);
|
||||
else
|
||||
return column - (editwincols - 2);
|
||||
if (column < editwincols - 1 || ISSET(SOFTWRAP) || column == 0)
|
||||
return 0;
|
||||
else if (editwincols > 8)
|
||||
return column - 7 - (column - 7) % (editwincols - 8);
|
||||
else
|
||||
return column - (editwincols - 2);
|
||||
}
|
||||
|
||||
/* Return the placewewant associated with current_x, i.e. the zero-based
|
||||
* column position of the cursor. */
|
||||
size_t xplustabs(void)
|
||||
{
|
||||
return strnlenpt(openfile->current->data, openfile->current_x);
|
||||
return strnlenpt(openfile->current->data, openfile->current_x);
|
||||
}
|
||||
|
||||
/* Return the index in text of the character that (when displayed) will
|
||||
* not overshoot the given column. */
|
||||
size_t actual_x(const char *text, size_t column)
|
||||
{
|
||||
const char *start = text;
|
||||
/* From where we start walking through the text. */
|
||||
size_t width = 0;
|
||||
/* The current accumulated span, in columns. */
|
||||
const char *start = text;
|
||||
/* From where we start walking through the text. */
|
||||
size_t width = 0;
|
||||
/* The current accumulated span, in columns. */
|
||||
|
||||
while (*text != '\0') {
|
||||
int charlen = parse_mbchar(text, NULL, &width);
|
||||
while (*text != '\0') {
|
||||
int charlen = parse_mbchar(text, NULL, &width);
|
||||
|
||||
if (width > column)
|
||||
break;
|
||||
if (width > column)
|
||||
break;
|
||||
|
||||
text += charlen;
|
||||
}
|
||||
text += charlen;
|
||||
}
|
||||
|
||||
return (text - start);
|
||||
return (text - start);
|
||||
}
|
||||
|
||||
/* A strnlen() with tabs and multicolumn characters factored in:
|
||||
* how many columns wide are the first maxlen bytes of text? */
|
||||
size_t strnlenpt(const char *text, size_t maxlen)
|
||||
{
|
||||
size_t width = 0;
|
||||
/* The screen display width to text[maxlen]. */
|
||||
size_t width = 0;
|
||||
/* The screen display width to text[maxlen]. */
|
||||
|
||||
if (maxlen == 0)
|
||||
return 0;
|
||||
if (maxlen == 0)
|
||||
return 0;
|
||||
|
||||
while (*text != '\0') {
|
||||
int charlen = parse_mbchar(text, NULL, &width);
|
||||
while (*text != '\0') {
|
||||
int charlen = parse_mbchar(text, NULL, &width);
|
||||
|
||||
if (maxlen <= charlen)
|
||||
break;
|
||||
if (maxlen <= charlen)
|
||||
break;
|
||||
|
||||
maxlen -= charlen;
|
||||
text += charlen;
|
||||
}
|
||||
maxlen -= charlen;
|
||||
text += charlen;
|
||||
}
|
||||
|
||||
return width;
|
||||
return width;
|
||||
}
|
||||
|
||||
/* Return the number of columns that the given text occupies. */
|
||||
size_t strlenpt(const char *text)
|
||||
{
|
||||
size_t span = 0;
|
||||
size_t span = 0;
|
||||
|
||||
while (*text != '\0')
|
||||
text += parse_mbchar(text, NULL, &span);
|
||||
while (*text != '\0')
|
||||
text += parse_mbchar(text, NULL, &span);
|
||||
|
||||
return span;
|
||||
return span;
|
||||
}
|
||||
|
||||
/* Append a new magicline to filebot. */
|
||||
/* Append a new magicline to the end of the buffer. */
|
||||
void new_magicline(void)
|
||||
{
|
||||
openfile->filebot->next = make_new_node(openfile->filebot);
|
||||
openfile->filebot->next->data = mallocstrcpy(NULL, "");
|
||||
openfile->filebot = openfile->filebot->next;
|
||||
openfile->totsize++;
|
||||
openfile->filebot->next = make_new_node(openfile->filebot);
|
||||
openfile->filebot->next->data = mallocstrcpy(NULL, "");
|
||||
openfile->filebot = openfile->filebot->next;
|
||||
openfile->totsize++;
|
||||
}
|
||||
|
||||
#if !defined(NANO_TINY) || defined(ENABLE_HELP)
|
||||
/* 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. */
|
||||
/* Remove the magicline from the end of the buffer, if there is one and
|
||||
* it isn't the only line in the file. */
|
||||
void remove_magicline(void)
|
||||
{
|
||||
if (openfile->filebot->data[0] == '\0' &&
|
||||
openfile->filebot != openfile->fileage) {
|
||||
openfile->filebot = openfile->filebot->prev;
|
||||
free_filestruct(openfile->filebot->next);
|
||||
openfile->filebot->next = NULL;
|
||||
openfile->totsize--;
|
||||
}
|
||||
if (openfile->filebot->data[0] == '\0' &&
|
||||
openfile->filebot != openfile->fileage) {
|
||||
openfile->filebot = openfile->filebot->prev;
|
||||
free_filestruct(openfile->filebot->next);
|
||||
openfile->filebot->next = NULL;
|
||||
openfile->totsize--;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef NANO_TINY
|
||||
/* 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)
|
||||
/* Set (top, top_x) and (bot, bot_x) to the start and end "coordinates" of
|
||||
* the marked region. If right_side_up isn't NULL, set it to TRUE when the
|
||||
* mark is at the top of the marked region, and to FALSE otherwise. */
|
||||
void mark_order(const filestruct **top, size_t *top_x,
|
||||
const filestruct **bot, size_t *bot_x, bool *right_side_up)
|
||||
{
|
||||
if ((openfile->current->lineno == openfile->mark->lineno &&
|
||||
openfile->current_x > openfile->mark_x) ||
|
||||
openfile->current->lineno > openfile->mark->lineno) {
|
||||
*top = openfile->mark;
|
||||
*top_x = openfile->mark_x;
|
||||
*bot = openfile->current;
|
||||
*bot_x = openfile->current_x;
|
||||
if (right_side_up != NULL)
|
||||
*right_side_up = TRUE;
|
||||
} else {
|
||||
*bot = openfile->mark;
|
||||
*bot_x = openfile->mark_x;
|
||||
*top = openfile->current;
|
||||
*top_x = openfile->current_x;
|
||||
if (right_side_up != NULL)
|
||||
*right_side_up = FALSE;
|
||||
}
|
||||
if ((openfile->current->lineno == openfile->mark->lineno &&
|
||||
openfile->current_x > openfile->mark_x) ||
|
||||
openfile->current->lineno > openfile->mark->lineno) {
|
||||
*top = openfile->mark;
|
||||
*top_x = openfile->mark_x;
|
||||
*bot = openfile->current;
|
||||
*bot_x = openfile->current_x;
|
||||
if (right_side_up != NULL)
|
||||
*right_side_up = TRUE;
|
||||
} else {
|
||||
*bot = openfile->mark;
|
||||
*bot_x = openfile->mark_x;
|
||||
*top = openfile->current;
|
||||
*top_x = openfile->current_x;
|
||||
if (right_side_up != NULL)
|
||||
*right_side_up = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the set of lines to work on -- either just the current line, or the
|
||||
* first to last lines of the marked region. When the cursor (or mark) is
|
||||
* at the start of the last line of the region, exclude that line. */
|
||||
void get_range(const filestruct **top, const filestruct **bot)
|
||||
{
|
||||
if (!openfile->mark) {
|
||||
*top = openfile->current;
|
||||
*bot = openfile->current;
|
||||
} else {
|
||||
size_t top_x, bot_x;
|
||||
|
||||
mark_order(top, &top_x, bot, &bot_x, NULL);
|
||||
|
||||
if (bot_x == 0 && *bot != *top && !also_the_last)
|
||||
*bot = (*bot)->prev;
|
||||
else
|
||||
also_the_last = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Given a line number, return a pointer to the corresponding struct. */
|
||||
filestruct *fsfromline(ssize_t lineno)
|
||||
{
|
||||
filestruct *f = openfile->current;
|
||||
filestruct *f = openfile->current;
|
||||
|
||||
if (lineno <= openfile->current->lineno)
|
||||
while (f->lineno != lineno && f->prev != NULL)
|
||||
f = f->prev;
|
||||
else
|
||||
while (f->lineno != lineno && f->next != NULL)
|
||||
f = f->next;
|
||||
if (lineno <= openfile->current->lineno)
|
||||
while (f->lineno != lineno && f->prev != NULL)
|
||||
f = f->prev;
|
||||
else
|
||||
while (f->lineno != lineno && f->next != NULL)
|
||||
f = f->next;
|
||||
|
||||
if (f->lineno != lineno) {
|
||||
statusline(ALERT, "Gone undo line -- please report a bug");
|
||||
return NULL;
|
||||
}
|
||||
if (f->lineno != lineno) {
|
||||
statusline(ALERT, "Gone undo line -- please report a bug");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return f;
|
||||
return f;
|
||||
}
|
||||
#endif /* !NANO_TINY */
|
||||
|
||||
/* Count the number of characters from begin to end, and return it. */
|
||||
size_t get_totsize(const filestruct *begin, const filestruct *end)
|
||||
{
|
||||
const filestruct *line;
|
||||
size_t totsize = 0;
|
||||
const filestruct *line;
|
||||
size_t totsize = 0;
|
||||
|
||||
/* Sum the number of characters (plus a newline) in each line. */
|
||||
for (line = begin; line != end->next; line = line->next)
|
||||
totsize += mbstrlen(line->data) + 1;
|
||||
/* Sum the number of characters (plus a newline) in each line. */
|
||||
for (line = begin; line != end->next; line = line->next)
|
||||
totsize += mbstrlen(line->data) + 1;
|
||||
|
||||
/* The last line of a file doesn't have a newline -- otherwise it
|
||||
* wouldn't be the last line -- so subtract 1 when at EOF. */
|
||||
if (line == NULL)
|
||||
totsize--;
|
||||
/* The last line of a file doesn't have a newline -- otherwise it
|
||||
* wouldn't be the last line -- so subtract 1 when at EOF. */
|
||||
if (line == NULL)
|
||||
totsize--;
|
||||
|
||||
return totsize;
|
||||
return totsize;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
/* Dump the given buffer 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");
|
||||
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, "(%zd) %s\n", inptr->lineno, inptr->data);
|
||||
inptr = inptr->next;
|
||||
}
|
||||
}
|
||||
|
||||
/* Dump the current buffer to stderr in reverse. */
|
||||
void dump_filestruct_reverse(void)
|
||||
{
|
||||
const filestruct *fileptr = openfile->filebot;
|
||||
|
||||
while (fileptr != NULL) {
|
||||
fprintf(stderr, "(%zd) %s\n", fileptr->lineno, fileptr->data);
|
||||
fileptr = fileptr->prev;
|
||||
}
|
||||
while (inptr != NULL) {
|
||||
fprintf(stderr, "(%zd) %s\n", inptr->lineno, inptr->data);
|
||||
inptr = inptr->next;
|
||||
}
|
||||
}
|
||||
#endif /* DEBUG */
|
||||
|
||||
5259
src/winio.c
5259
src/winio.c
File diff suppressed because it is too large
Load Diff
@@ -33,7 +33,7 @@ color brightblue "//.*"
|
||||
color brightblue start="/\*" end="\*/"
|
||||
|
||||
# Reminders.
|
||||
color ,yellow "\<(FIXME|TODO|XXX)\>"
|
||||
color brightwhite,yellow "\<(FIXME|TODO|XXX)\>"
|
||||
|
||||
# Trailing whitespace.
|
||||
color ,green "[[:space:]]+$"
|
||||
|
||||
@@ -6,11 +6,11 @@ comment "#"
|
||||
icolor green "^[[:space:]]*[A-Z0-9_]+"
|
||||
icolor brightyellow "^[[:space:]]*(include|include_directories|include_external_msproject)\>"
|
||||
|
||||
icolor brightgreen "^[[:space:]]*\<((else|end)?if|else|(end)?while|(end)?foreach|break)\>"
|
||||
color brightgreen "\<(NOT|COMMAND|POLICY|TARGET|EXISTS|IS_(DIRECTORY|ABSOLUTE)|DEFINED)\>[[:space:]]"
|
||||
color brightgreen "[[:space:]]\<(OR|AND|IS_NEWER_THAN|MATCHES|(STR|VERSION_)?(LESS|GREATER|EQUAL))\>[[:space:]]"
|
||||
icolor brightgreen "^[[:space:]]*((else|end)?if|else|(end)?while|(end)?foreach|break)\>"
|
||||
color brightgreen "\<(NOT|COMMAND|POLICY|TARGET|EXISTS|IS_(DIRECTORY|ABSOLUTE)|DEFINED)[[:space:]]"
|
||||
color brightgreen "[[:space:]](OR|AND|IS_NEWER_THAN|MATCHES|(STR|VERSION_)?(LESS|GREATER|EQUAL))[[:space:]]"
|
||||
|
||||
icolor brightred "^[[:space:]]*\<((end)?(function|macro)|return)"
|
||||
icolor brightred "^[[:space:]]*((end)?(function|macro)|return)"
|
||||
|
||||
icolor cyan start="\$(\{|ENV\{)" end="\}"
|
||||
color magenta "\<(APPLE|UNIX|WIN32|CYGWIN|BORLAND|MINGW|MSVC(_IDE|60|71|80|90)?)\>"
|
||||
|
||||
@@ -24,7 +24,7 @@ color red "\<EBUILD_PHASE(_FUNC)?\>"
|
||||
color red "\<QA_((TEXTRELS|EXECSTACK|WX_LOAD)(_[a-zA-Z_0-9]+)?|DT_HASH|PRESTRIPPED)\>"
|
||||
color red "\<(PATCHES|(HTML_)?DOCS)\>" "\<WANT_(AUTO(CONF|MAKE)|LIBTOOL)\>" "\<AT_M4DIR\>"
|
||||
## Portage commands:
|
||||
color magenta "\<(use(_(with|enable|if_iuse)|x)?|in_iuse)\> [!a-zA-Z0-9_+ -]*" "inherit.*"
|
||||
color magenta "\<(use(_(with|enable|if_iuse)|x)?|in_iuse) [!a-zA-Z0-9_+ -]*" "inherit.*"
|
||||
color brightblue "\<e(begin|end|conf|install|make|qmake4|ant|(qa)?warn|infon?|error|log|patch(_user)?|new(group|user))\>"
|
||||
color brightblue "\<e(pause|beep|mktemp|(cvs|svn)_clean|punt_cxx)\>" "\<e(aclocal|auto(reconf|header|conf|make)|libtoolize)\>"
|
||||
color brightblue "\<e(stack|shopts|umask)_(push|pop)\>" "\<version_is_at_least\>"
|
||||
|
||||
@@ -24,13 +24,9 @@ color brightcyan "\<(package|import)\>"
|
||||
color brightcyan "//[[:space:]]*\+build[[:space:]]+(([a-zA-Z_0-9]+[[:space:]]*)+,[[:space:]]*)*[a-zA-Z_0-9]+"
|
||||
|
||||
# Literals.
|
||||
color red "\<[0-9]+\.[0-9]*([Ee][+-][0-9]+)?i?\>"
|
||||
color red "\<[0-9]+[Ee][+-][0-9]+i?\>"
|
||||
color red "\<\.[0-9]+([Ee][+-][0-9]+)?i?\>"
|
||||
color red "\<[0-9]+i\>"
|
||||
color red "\<[1-9][0-9]*\>"
|
||||
color red "\<0[0-7]*\>"
|
||||
icolor red "\<0x[0-9a-f]+\>"
|
||||
color red "\<[0-9]+(\.[0-9]*)?([Ee][+-]?[0-9]+)?i?\>"
|
||||
color red "\B\.[0-9]+([Ee][+-]?[0-9]+)?i?\>"
|
||||
color red "\<(0[0-7]*|[1-9][0-9]*|0[xX][0-9a-fA-F]+)\>"
|
||||
|
||||
# Strings and characters; slightly fuzzy.
|
||||
color red "\<(true|false|nil|iota|_)\>"
|
||||
|
||||
@@ -1,19 +1,23 @@
|
||||
## Here is an example for Javascript.
|
||||
## Syntax highlighting for Javascript.
|
||||
|
||||
syntax "javascript" "\.js$"
|
||||
comment "//"
|
||||
|
||||
color brightred "\<[A-Z_][0-9A-Z_]+\>"
|
||||
color green "\<(const|function|let|this|typeof|var|void)\>"
|
||||
color brightyellow "\<(for|if|while|with|do|else|case|default|switch)\>"
|
||||
color brightyellow "\<(export|try|throw|catch|new|delete)\>"
|
||||
color magenta "\<(continue|break|return|yield)\>"
|
||||
color brightmagenta "'([^'\]|(\\["'abfnrtv\\]))'" "'\\(([0-3]?[0-7]{1,2}))'" "'\\x[0-9A-Fa-f]{1,2}'"
|
||||
# Declarational stuff.
|
||||
color green "\<(async|class|const|extends|function|let|this|typeof|var|void)\>"
|
||||
# Flow control and special keywords.
|
||||
color brightyellow "\<(do|while|if|else|switch|case|default|for|each|in|of|with)\>"
|
||||
color brightyellow "\<(await|export|import|throw|try|catch|finally|new|delete)\>"
|
||||
# "Exit" points.
|
||||
color magenta "\<(break|continue|return|yield)\>"
|
||||
|
||||
# Octal/decimal and hexadecimal numbers.
|
||||
color cyan "\<[0-9]+\>" "\<0x[0-9A-Fa-f]+\>"
|
||||
|
||||
# Strings.
|
||||
color brightyellow "<[^= ]*>" ""(\\.|[^"])*"" "'(\\.|[^'])*'"
|
||||
color brightmagenta ""(\\.|[^"])*"" "'(\\.|[^'])*'" "`(\\.|[^`])*`"
|
||||
# Comments.
|
||||
color brightblue "//.*"
|
||||
color brightblue "(^|[[:space:]])//.*"
|
||||
color brightblue start="/\*" end="\*/"
|
||||
|
||||
# Trailing whitespace.
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
## Syntax highlighting for Lua.
|
||||
#
|
||||
## Author: Matthew Wild <mwild1 (at) gmail.com>
|
||||
## Original author: Matthew Wild <mwild1 (at) gmail.com>
|
||||
## License: GPL 3 or later
|
||||
## Version: 2011-05-05
|
||||
|
||||
syntax "lua" "\.lua$"
|
||||
magic "Lua script"
|
||||
@@ -17,48 +16,42 @@ color brightyellow ":|\*|/|%|\+|-|\^|>|>=|<|<=|~=|=|\.\.|\<(not|and|or)\>"
|
||||
color brightblue "\<(do|end|while|repeat|until|if|elseif|then|else|for|in|function|local|return|break)\>"
|
||||
|
||||
# Keywords
|
||||
color brightyellow "\<(io|math|os|string|table|coroutine|debug)\>\."
|
||||
color brightyellow "\<(_G|_VERSION|assert|collectgarbage|dofile|error|getfenv|getmetatable|ipairs|load|loadfile|module|next|pairs|pcall|print|rawequal|rawget|rawset|require|select|setfenv|setmetatable|tonumber|tostring|type|unpack|xpcall)\s*\("
|
||||
color brightyellow "\<(_G|_VERSION|assert|collectgarbage|dofile|error|getfenv|getmetatable|ipairs|load|loadfile|module|next|pairs|pcall|print|rawequal|rawget|rawlen|rawset|require|select|setfenv|setmetatable|tonumber|tostring|type|unpack|xpcall)\s*\("
|
||||
|
||||
# Standard library
|
||||
color brightyellow "io\.\<(close|flush|input|lines|open|output|popen|read|tmpfile|type|write|stdin|stdout|stderr)\>"
|
||||
color brightyellow "math\.\<(abs|acos|asin|atan2|atan|ceil|cosh|cos|deg|exp|floor|fmod|frexp|huge|ldexp|log10|log)\>"
|
||||
color brightyellow "math\.\<(max|min|mod|modf|pi|pow|rad|random|randomseed|sinh|tan)\>"
|
||||
color brightyellow "os\.\<(clock|date|difftime|execute|exit|getenv|remove|rename|setlocale|time|tmpname)\>"
|
||||
color brightyellow "package\.\<(cpath|loaded|loadlib|path|preload|seeall)\>"
|
||||
color brightyellow "string\.\<(byte|char|dump|find|format|gmatch|gsub|len|lower|match|rep|reverse|sub|upper)\>"
|
||||
color brightyellow "table\.\<(concat|insert|maxn|remove|sort)\>"
|
||||
color brightyellow "coroutine\.\<(create|resume|running|status|wrap|yield)\>"
|
||||
color brightyellow "debug\.\<(debug|getfenv|gethook|getinfo|getlocal|getmetatable|getregistry|getupvalue)\>"
|
||||
color brightyellow "debug\.\<(setfenv|sethook|setlocal|setmetatable|setupvalue|traceback)\>"
|
||||
color brightyellow "\<coroutine\.(create|isyieldable|resume|running|status|wrap|yield)\>"
|
||||
color brightyellow "\<debug\.(debug|(get|set)(fenv|hook|info|local|metatable|(up|user)value)|getregistry|traceback|upvalue(id|join))\>"
|
||||
color brightyellow "\<io\.(close|flush|input|lines|output|p?open|read|tmpfile|type|write|std(in|out|err))\>"
|
||||
color brightyellow "\<math\.(abs|acos|asin|atan2?|ceil|cosh?|deg|exp|floor|fmod|frexp|huge|ldexp|log10|log)\>"
|
||||
color brightyellow "\<math\.((max|min)(integer)?|modf?|pi|pow|rad|random(seed)?|sinh?|sqrt|tan|tointeger|type|ult)\>"
|
||||
color brightyellow "\<os\.(clock|date|difftime|execute|exit|getenv|remove|rename|setlocale|time|tmpname)\>"
|
||||
color brightyellow "\<package\.(config|cpath|loaded|loadlib|path|preload|searchers|searchpath|seeall)\>"
|
||||
color brightyellow "\<string\.(byte|char|dump|find|format|gmatch|gsub|len|lower|match|pack|packsize|rep|reverse|sub|unpack|upper)\>"
|
||||
color brightyellow "\<table\.(concat|insert|maxn|move|pack|remove|sort|unpack)\>"
|
||||
color brightyellow "\<utf8\.(char|charpattern|codepoint|codes|len|offset)\>"
|
||||
|
||||
# File handle methods
|
||||
color brightyellow "\:\<(close|flush|lines|read|seek|setvbuf|write)\>"
|
||||
|
||||
# false, nil, true
|
||||
color brightmagenta "\<(false|nil|true)\>"
|
||||
color brightyellow ":(close|flush|lines|read|seek|setvbuf|write)\>"
|
||||
|
||||
# External files
|
||||
color brightgreen "\<(dofile|require)\>"
|
||||
|
||||
# Numbers
|
||||
color red "\<([0-9]+)\>"
|
||||
# Special words
|
||||
color brightmagenta "\<(false|nil|true)\>"
|
||||
|
||||
# Symbols
|
||||
color brightmagenta "(\(|\)|\[|\]|\{|\})"
|
||||
# Decimal and hexadecimal numbers
|
||||
color red "\<[0-9]+(\.[0-9]*)?([Ee][+-]?[0-9]+)?\>"
|
||||
icolor red "\<0x[0-9a-f]+(\.[0-9a-f]*)?(p[+-]?[0-9]+)?\>"
|
||||
|
||||
# Brackets
|
||||
color brightmagenta "\(|\)|\[|\]|\{|\}"
|
||||
|
||||
# Shebang
|
||||
color brightcyan "^#!.*"
|
||||
color brightcyan "^#!.*"
|
||||
|
||||
# Simple comments
|
||||
color green "\-\-.*$"
|
||||
|
||||
# Multiline comments
|
||||
color green start="\-\-\[\[" end="\]\]"
|
||||
# Simple comments and multiline comments
|
||||
color green "--.*"
|
||||
color green start="--\[\[" end="\]\]"
|
||||
|
||||
# Strings
|
||||
color red "\"(\\.|[^\\\"])*\"|'(\\.|[^\\'])*'"
|
||||
##color red start="\[\[" end="\]\]"
|
||||
|
||||
# Hex literals
|
||||
color red "0x[0-9a-fA-F]*"
|
||||
color red ""(\\.|[^"\])*"|'(\\.|[^'\])*'"
|
||||
|
||||
@@ -7,7 +7,7 @@ comment "#"
|
||||
icolor brightred "^[[:space:]]*((un)?(bind|set)|include|syntax|header|magic|comment|linter|formatter|i?color|extendsyntax).*$"
|
||||
|
||||
# Keywords
|
||||
icolor brightgreen "^[[:space:]]*(set|unset)[[:space:]]+(allow_insecure_backup|atblanks|autoindent|backup|backwards|boldtext|casesensitive|constantshow|cutfromcursor|fill[[:space:]]+-?[[:digit:]]+|historylog|justifytrim|linenumbers|locking|morespace|mouse|multibuffer|noconvert|nohelp|nopauses|nonewlines|nowrap|positionlog|preserve|quickblank|quiet|rebinddelete|rebindkeypad|regexp|showcursor|smarthome|smooth|softwrap|suspend|tabsize[[:space:]]+[1-9][0-9]*|tabstospaces|tempfile|unix|view|wordbounds)\>"
|
||||
icolor brightgreen "^[[:space:]]*(set|unset)[[:space:]]+(allow_insecure_backup|atblanks|autoindent|backup|backwards|boldtext|casesensitive|constantshow|cutfromcursor|fill[[:space:]]+-?[[:digit:]]+|historylog|linenumbers|locking|morespace|mouse|multibuffer|noconvert|nohelp|nopauses|nonewlines|nowrap|positionlog|preserve|quickblank|quiet|rebinddelete|rebindkeypad|regexp|showcursor|smarthome|smooth|softwrap|suspend|tabsize[[:space:]]+[1-9][0-9]*|tabstospaces|tempfile|trimblanks|unix|view|wordbounds)\>"
|
||||
icolor yellow "^[[:space:]]*set[[:space:]]+((function|key|number|selected|status|title)color)[[:space:]]+(bright)?(white|black|red|blue|green|yellow|magenta|cyan)?(,(white|black|red|blue|green|yellow|magenta|cyan))?\>"
|
||||
icolor brightgreen "^[[:space:]]*set[[:space:]]+(backupdir|brackets|functioncolor|keycolor|matchbrackets|numbercolor|operatingdir|punct|quotestr|selectedcolor|speller|statuscolor|titlecolor|whitespace|wordchars)[[:space:]]+"
|
||||
icolor brightgreen "^[[:space:]]*bind[[:space:]]+((\^([[:alpha:]]|[]0-9\^_]|Space)|M-([[:alpha:]]|[]!"#$%&'()*+,./0-9:;<=>?@\^_`{|}~-]|Space))|F([1-9]|1[0-6])|Ins|Del)[[:space:]]+[[:alpha:]]+[[:space:]]+(all|main|search|replace(with)?|gotoline|writeout|insert|ext(ernal)?cmd|help|spell|linter|browser|whereisfile|gotodir)([[:space:]]+#|[[:space:]]*$)"
|
||||
@@ -16,12 +16,13 @@ icolor brightgreen "^[[:space:]]*extendsyntax[[:space:]]+[[:alpha:]]+[[:space:]]
|
||||
icolor brightgreen "^[[:space:]]*(linter|formatter)[[:space:]]+[[:alpha:]]+"
|
||||
icolor green "^[[:space:]]*((un)?(bind|set)|include|syntax|header|magic|comment|linter|formatter|extendsyntax)\>"
|
||||
|
||||
# Strings
|
||||
color brightmagenta "".+"([[:space:]]|$)"
|
||||
|
||||
# Colors
|
||||
icolor yellow "^[[:space:]]*i?color[[:space:]]*(bright)?(white|black|red|blue|green|yellow|magenta|cyan)?(,(white|black|red|blue|green|yellow|magenta|cyan))?\>"
|
||||
icolor magenta "^[[:space:]]*i?color\>" "\<(start|end)="
|
||||
|
||||
# Strings
|
||||
color brightmagenta ""(\\.|[^"])*""
|
||||
# Comments
|
||||
color brightblue "(^|[[:space:]]+)#.*$"
|
||||
color cyan "^[[:space:]]*##.*$"
|
||||
|
||||
@@ -12,7 +12,7 @@ color green "\<(class|namespace|template|public|protected|private|typename|this|
|
||||
color brightgreen "\<(for|if|while|do|else|case|default|switch)\>"
|
||||
color brightgreen "\<(try|throw|catch|operator|new|delete)\>"
|
||||
color brightgreen "\<(goto|continue|break|return)\>"
|
||||
color brightgreen "@\<(en(code|d)|i(mplementation|nterface)|selector)\>"
|
||||
color brightgreen "@(encode|end|implementation|interface)|selector)\>"
|
||||
|
||||
# GCC builtins.
|
||||
color cyan "__attribute__[[:space:]]*\(\([^)]*\)\)" "__(aligned|asm|builtin|hidden|inline|packed|restrict|section|typeof|weak)__"
|
||||
|
||||
@@ -8,18 +8,18 @@ comment "//"
|
||||
color brightgreen "(<\?(php)?|\?>)"
|
||||
|
||||
# Function names.
|
||||
color white "\<[a-z_]*\("
|
||||
color white "\<[A-Za-z_][A-Za-z_0-9]*\("
|
||||
# Variable names.
|
||||
color cyan "\$[a-z_]+"
|
||||
color cyan "\$[A-Za-z_][A-Za-z_0-9]*"
|
||||
|
||||
# Types.
|
||||
color green "\<(array|bool|callable|const|float|global|int|object|string|var)\>"
|
||||
|
||||
# Directives and structure.
|
||||
color brightyellow "\<(abstract|as|class|clone|(end)?declare|extends|function|implements|include(_once)?|inst(ance|ead)of|interface|namespace|new|private|protected|public|require(_once)?|static|trait|use|yield)\>"
|
||||
color brightyellow "\<(case|catch|default|do|echo|else(if)?|end(for(each)?|if|switch|while)|final(ly)?|for(each)?|if|print|switch|throw|try|while)\>"
|
||||
color brightcyan "\<(abstract|as|class|clone|(end)?declare|extends|function|implements|include(_once)?|inst(ance|ead)of|interface|namespace|new|private|protected|public|require(_once)?|static|trait|use|yield)\>"
|
||||
color brightcyan "\<(case|catch|default|do|echo|else(if)?|end(for(each)?|if|switch|while)|final(ly)?|for(each)?|if|print|switch|throw|try|while)\>"
|
||||
# Operators.
|
||||
color brightyellow "\<(and|or|xor)\>"
|
||||
color brightcyan "\<(and|or|xor)\>"
|
||||
|
||||
# Control flow.
|
||||
color magenta "\<(break|continue|goto|return)\>"
|
||||
|
||||
@@ -11,7 +11,7 @@ color brightred "^\"X-Bugs:.*\"$"
|
||||
color brightmagenta "\<(Project\-Id\-Version|Report\-Msgid\-Bugs\-To|Last\-Translator|Language(\-Team)?|X-Bugs|X-Generator|Plural\-Forms)\>"
|
||||
color cyan "\<(POT\-Creation\-Date|PO\-Revision\-Date|MIME\-Version|Content\-Type|Content\-Transfer\-Encoding)\>"
|
||||
# Encodings and numbers.
|
||||
color yellow "\<(UTF|ISO|Windows|Mac|IBM)\>\-[0-9]"
|
||||
color yellow "\<(UTF|ISO|Windows|Mac|IBM)-[0-9]+"
|
||||
color yellow "[0-9]|pre[0-9]|[0-9]bit"
|
||||
# Msgids.
|
||||
color brightblue "^(msgid|msgid_plural|msgstr)\>"
|
||||
@@ -24,6 +24,6 @@ color brightmagenta "%([1-9]\$)?[a-z]*"
|
||||
color yellow "\""
|
||||
color cyan "\\n"
|
||||
# Reminders.
|
||||
color ,yellow "(FIXME|TODO|XXX)"
|
||||
color brightwhite,yellow "(FIXME|TODO|XXX)"
|
||||
# Obsolete strings.
|
||||
color red "#~.*$"
|
||||
|
||||
@@ -7,9 +7,7 @@ color brightcyan "^[[:space:]]*#[[:space:]]*(declare)"
|
||||
color brightyellow "\<(sphere|cylinder|translate|matrix|rotate|scale)\>"
|
||||
color brightyellow "\<(orthographic|location|up|right|direction|clipped_by)\>"
|
||||
color brightyellow "\<(fog_type|fog_offset|fog_alt|rgb|distance|transform)\>"
|
||||
color brightred "^\<(texture)\>"
|
||||
color brightred "\<(light_source|background)\>"
|
||||
color brightred "\<(fog|object|camera)\>"
|
||||
color brightred "\<(background|camera|fog|light_source|object|texture)\>"
|
||||
color green "(\{|\}|\(|\)|\;|\]|\[|`|\\|\$|<|>|!|=|&|\|)"
|
||||
color brightmagenta "\<(union|group|subgroup)\>"
|
||||
|
||||
|
||||
@@ -9,8 +9,10 @@ comment "#"
|
||||
# Function definitions.
|
||||
icolor brightblue "def [0-9A-Z_]+"
|
||||
# Keywords.
|
||||
color brightcyan "\<(and|as|assert|break|class|continue|def|del|elif|else|except|exec|finally|for|from)\>"
|
||||
color brightcyan "\<(global|if|import|in|is|lambda|not|or|pass|print|raise|return|try|while|with|yield)\>"
|
||||
color brightcyan "\<(and|as|assert|async|await|break|class|continue)\>"
|
||||
color brightcyan "\<(def|del|elif|else|except|exec|finally|for|from)\>"
|
||||
color brightcyan "\<(global|if|import|in|is|lambda|nonlocal|not|or)\>"
|
||||
color brightcyan "\<(pass|print|raise|return|try|while|with|yield)\>"
|
||||
|
||||
# Single-quoted strings.
|
||||
color brightgreen "'([^'\]|\\.)+'"
|
||||
@@ -21,8 +23,11 @@ color brightred "(^|[[:blank:]])#.*$"
|
||||
color brightgreen start="'''([^'),]|$)" end="(^|[^(\])'''"
|
||||
color brightgreen start="\"\"\"([^"),]|$)" end="(^|[^(\])\"\"\""
|
||||
|
||||
# Special values.
|
||||
color brightmagenta "\<(False|None|True)\>"
|
||||
|
||||
# Reminders.
|
||||
color ,yellow "(FIXME|TODO|XXX)"
|
||||
color brightwhite,yellow "(FIXME|TODO|XXX)"
|
||||
|
||||
# Trailing whitespace.
|
||||
color ,green "[[:space:]]+$"
|
||||
|
||||
Reference in New Issue
Block a user