add DB's overhaul of the cutting code and related file-writing code, his
fixes to check_operating_dir(), and a few minor cleanups and fixes of mine git-svn-id: svn://svn.savannah.gnu.org/nano/trunk/nano@1600 35c25a1d-7b9e-4130-9fde-d3aeb78583b8master
parent
f427694400
commit
8213850df6
22
ChangeLog
22
ChangeLog
|
@ -29,13 +29,26 @@ CVS code -
|
||||||
shortcut display routines to handle them. Also modify the
|
shortcut display routines to handle them. Also modify the
|
||||||
shortcut list code to not treat non-control character values
|
shortcut list code to not treat non-control character values
|
||||||
of val as Meta-sequences, and fix dependencies on that
|
of val as Meta-sequences, and fix dependencies on that
|
||||||
behavior. (DLR)
|
behavior. Also rename several variables: "alt" -> "meta",
|
||||||
|
"altval" -> "metaval". (DLR)
|
||||||
- Hook up the verbatim input functions so that verbatim input
|
- Hook up the verbatim input functions so that verbatim input
|
||||||
can be used in the edit window. New function
|
can be used in the edit window. New function
|
||||||
do_verbatim_input(); changes to do_char(). (DLR) Additional
|
do_verbatim_input(); changes to do_char(). (DLR) Additional
|
||||||
minor tweaks to do_char() by David Benbennick.
|
minor tweaks to do_char() by David Benbennick.
|
||||||
- Clarify the description of the --rebinddelete option. (DLR)
|
- Clarify the description of the --rebinddelete option. (DLR)
|
||||||
|
- cut.c:
|
||||||
|
- Overhaul to increase efficiency and add various cleanups.
|
||||||
|
Changes to add_to_cutbuffer(), cut_marked_segment(), and
|
||||||
|
do_uncut_text(). (David Benbennick)
|
||||||
- files.c:
|
- files.c:
|
||||||
|
check_operating_dir()
|
||||||
|
- Add an assert to ensure that full_operatingdir isn't NULL,
|
||||||
|
a fix for reporting nonexistent (incomplete) directory names
|
||||||
|
as being outside the operating directory when tab completion
|
||||||
|
is being used, and cosmetic cleanups. (David Benbennick)
|
||||||
|
copy_file()
|
||||||
|
- New function containing part of the functionality formerly in
|
||||||
|
do_writeout. (David Benbennick)
|
||||||
do_writeout()
|
do_writeout()
|
||||||
- Prompt the user if we're trying to save an existing file (and
|
- Prompt the user if we're trying to save an existing file (and
|
||||||
not just a selection of it) under a different name. (DLR;
|
not just a selection of it) under a different name. (DLR;
|
||||||
|
@ -56,6 +69,10 @@ CVS code -
|
||||||
- Convert to use the new low-level input functions. (DLR)
|
- Convert to use the new low-level input functions. (DLR)
|
||||||
main()
|
main()
|
||||||
- Remove unused variable option_index. (DLR)
|
- Remove unused variable option_index. (DLR)
|
||||||
|
- Fix omission of NANO_NO_KEY in the shortcut list scanning
|
||||||
|
code. (DLR)
|
||||||
|
- nano.h:
|
||||||
|
- Comment additions and cosmetic tweaks. (DLR)
|
||||||
- search.c:
|
- search.c:
|
||||||
findnextstr(), do_replace_loop()
|
findnextstr(), do_replace_loop()
|
||||||
- Fix potential infinite loops and other misbehavior when doing
|
- Fix potential infinite loops and other misbehavior when doing
|
||||||
|
@ -95,6 +112,9 @@ CVS code -
|
||||||
- Modify to take an extra parameter indicating if we should
|
- Modify to take an extra parameter indicating if we should
|
||||||
ungetch() the key equivalents of shortcuts we click on or not.
|
ungetch() the key equivalents of shortcuts we click on or not.
|
||||||
(DLR)
|
(DLR)
|
||||||
|
nanogetstr()
|
||||||
|
- Properly interpret the Meta key value in misc if we hit it at
|
||||||
|
the statusbar prompt. (DLR)
|
||||||
do_yesno()
|
do_yesno()
|
||||||
- Add a few efficiency/extensibility tweaks. (David Benbennick)
|
- Add a few efficiency/extensibility tweaks. (David Benbennick)
|
||||||
- Convert to use the new low-level input functions, and remove
|
- Convert to use the new low-level input functions, and remove
|
||||||
|
|
317
src/cut.c
317
src/cut.c
|
@ -28,15 +28,17 @@
|
||||||
#include "proto.h"
|
#include "proto.h"
|
||||||
#include "nano.h"
|
#include "nano.h"
|
||||||
|
|
||||||
static int marked_cut; /* Is the cutbuffer from a mark? */
|
static int marked_cut; /* Is the cutbuffer from a mark?
|
||||||
|
* 0 means whole-line cut, 1 means mark,
|
||||||
|
* 2 means cut-from-cursor. */
|
||||||
|
|
||||||
#ifndef NANO_SMALL
|
#ifndef NANO_SMALL
|
||||||
static int concatenate_cut; /* Should we add this cut string to the
|
static int concatenate_cut; /* Should we add this cut string to the
|
||||||
end of the last one? */
|
* end of the last one? */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static filestruct *cutbottom = NULL;
|
static filestruct *cutbottom = NULL;
|
||||||
/* Pointer to end of cutbuffer */
|
/* Pointer to end of cutbuffer. */
|
||||||
|
|
||||||
filestruct *get_cutbottom(void)
|
filestruct *get_cutbottom(void)
|
||||||
{
|
{
|
||||||
|
@ -46,29 +48,27 @@ filestruct *get_cutbottom(void)
|
||||||
void add_to_cutbuffer(filestruct *inptr)
|
void add_to_cutbuffer(filestruct *inptr)
|
||||||
{
|
{
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
fprintf(stderr, "add_to_cutbuffer() called with inptr->data = %s\n",
|
fprintf(stderr, "add_to_cutbuffer(): inptr->data = %s\n", inptr->data);
|
||||||
inptr->data);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (cutbuffer == NULL) {
|
if (cutbuffer == NULL)
|
||||||
cutbuffer = inptr;
|
cutbuffer = inptr;
|
||||||
inptr->prev = NULL;
|
|
||||||
#ifndef NANO_SMALL
|
#ifndef NANO_SMALL
|
||||||
} else if (concatenate_cut && !ISSET(JUSTIFY_MODE)) {
|
else if (concatenate_cut && !ISSET(JUSTIFY_MODE)) {
|
||||||
/* Just tack the text in inptr onto the text in cutbottom,
|
/* Just tack the text in inptr onto the text in cutbottom,
|
||||||
unless we're backing up lines while justifying text. */
|
* unless we're backing up lines while justifying text. */
|
||||||
cutbottom->data = charealloc(cutbottom->data,
|
cutbottom->data = charealloc(cutbottom->data,
|
||||||
strlen(cutbottom->data) + strlen(inptr->data) + 1);
|
strlen(cutbottom->data) + strlen(inptr->data) + 1);
|
||||||
strcat(cutbottom->data, inptr->data);
|
strcat(cutbottom->data, inptr->data);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
} else {
|
else {
|
||||||
cutbottom->next = inptr;
|
cutbottom->next = inptr;
|
||||||
inptr->prev = cutbottom;
|
inptr->prev = cutbottom;
|
||||||
}
|
}
|
||||||
|
|
||||||
inptr->next = NULL;
|
|
||||||
cutbottom = inptr;
|
cutbottom = inptr;
|
||||||
|
cutbottom->next = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef NANO_SMALL
|
#ifndef NANO_SMALL
|
||||||
|
@ -78,112 +78,115 @@ void add_to_cutbuffer(filestruct *inptr)
|
||||||
* last cut line has length bot_x. That is, if bot_x > 0 then we cut to
|
* last cut line has length bot_x. That is, if bot_x > 0 then we cut to
|
||||||
* bot->data[bot_x - 1].
|
* bot->data[bot_x - 1].
|
||||||
*
|
*
|
||||||
* destructive is whether to actually modify the file structure, if not
|
* We maintain totsize, totlines, filebot, the magicline, and line
|
||||||
* then just copy the buffer into cutbuffer and don't pull it from the
|
* numbers. Also, we set current and current_x so the cursor will be on
|
||||||
* file.
|
* the first character after what was cut. We do not do any screen
|
||||||
|
* updates.
|
||||||
*
|
*
|
||||||
* If destructive, then we maintain totsize, totlines, filebot, the
|
* Note cutbuffer might not be NULL if "cut to end" is used. */
|
||||||
* magic line, and line numbers. Also, we set current and current_x so
|
void cut_marked_segment(void)
|
||||||
* the cursor will be on the first character after what was cut. We do
|
|
||||||
* not do any screen updates. */
|
|
||||||
void cut_marked_segment(filestruct *top, size_t top_x, filestruct *bot,
|
|
||||||
size_t bot_x, int destructive)
|
|
||||||
{
|
{
|
||||||
filestruct *tmp, *next;
|
filestruct *top;
|
||||||
|
filestruct *bot;
|
||||||
|
filestruct *tmp;
|
||||||
|
size_t top_x;
|
||||||
|
size_t bot_x;
|
||||||
size_t newsize;
|
size_t newsize;
|
||||||
|
|
||||||
if (top == bot && top_x == bot_x)
|
/* If the mark doesn't cover any text, get out. */
|
||||||
|
if (current == mark_beginbuf && current_x == mark_beginx)
|
||||||
return;
|
return;
|
||||||
assert(top != NULL && bot != NULL);
|
assert(current != NULL && mark_beginbuf != NULL);
|
||||||
|
|
||||||
/* Make top be no later than bot. */
|
/* Set up the top and bottom lines and coordinates of the marked
|
||||||
if (top->lineno > bot->lineno) {
|
* text. */
|
||||||
filestruct *swap = top;
|
mark_order((const filestruct **)&top, &top_x,
|
||||||
int swap2 = top_x;
|
(const filestruct **)&bot, &bot_x);
|
||||||
|
|
||||||
top = bot;
|
/* Make the first cut line manually. Move the cut part of the top
|
||||||
bot = swap;
|
* line into tmp, and set newsize to that partial line's length. */
|
||||||
|
|
||||||
top_x = bot_x;
|
|
||||||
bot_x = swap2;
|
|
||||||
} else if (top == bot && top_x > bot_x) {
|
|
||||||
/* And bot_x can't be an earlier character than top_x. */
|
|
||||||
int swap = top_x;
|
|
||||||
|
|
||||||
top_x = bot_x;
|
|
||||||
bot_x = swap;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Make the first cut line manually. */
|
|
||||||
tmp = copy_node(top);
|
tmp = copy_node(top);
|
||||||
newsize = (top == bot ? bot_x - top_x : strlen(top->data + top_x));
|
newsize = (top == bot ? bot_x - top_x : strlen(top->data + top_x));
|
||||||
charmove(tmp->data, top->data + top_x, newsize);
|
charmove(tmp->data, tmp->data + top_x, newsize);
|
||||||
null_at(&tmp->data, newsize);
|
null_at(&tmp->data, newsize);
|
||||||
add_to_cutbuffer(tmp);
|
|
||||||
|
|
||||||
/* And make the remainder line manually too. */
|
/* Add the contents of tmp to the cutbuffer. Note that cutbuffer
|
||||||
if (destructive) {
|
* might be non-NULL if we have cut to end enabled. */
|
||||||
current_x = top_x;
|
if (cutbuffer == NULL) {
|
||||||
totsize -= newsize;
|
cutbuffer = tmp;
|
||||||
totlines -= bot->lineno - top->lineno;
|
cutbottom = tmp;
|
||||||
|
} else {
|
||||||
newsize = top_x + strlen(bot->data + bot_x) + 1;
|
cutbottom->next = tmp;
|
||||||
if (top == bot) {
|
tmp->prev = cutbottom;
|
||||||
/* In this case, the remainder line is shorter, so we must
|
cutbottom = tmp;
|
||||||
move text from the end forward first. */
|
|
||||||
charmove(top->data + top_x, bot->data + bot_x,
|
|
||||||
newsize - top_x);
|
|
||||||
top->data = charealloc(top->data, newsize);
|
|
||||||
} else {
|
|
||||||
totsize -= bot_x + 1;
|
|
||||||
|
|
||||||
/* Here, the remainder line might get longer, so we
|
|
||||||
realloc() it first. */
|
|
||||||
top->data = charealloc(top->data, newsize);
|
|
||||||
charmove(top->data + top_x, bot->data + bot_x,
|
|
||||||
newsize - top_x);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* And make the top remainder line manually too. Update current_x
|
||||||
|
* and totlines to account for all the cut text, and update totsize
|
||||||
|
* to account for the length of the cut part of the first line. */
|
||||||
|
current_x = top_x;
|
||||||
|
totsize -= newsize;
|
||||||
|
totlines -= bot->lineno - top->lineno;
|
||||||
|
|
||||||
|
/* Now set newsize to be the length of the top remainder line plus
|
||||||
|
* the bottom remainder line, plus one for the null terminator. */
|
||||||
|
newsize = top_x + strlen(bot->data + bot_x) + 1;
|
||||||
|
|
||||||
if (top == bot) {
|
if (top == bot) {
|
||||||
|
/* In this case, we're only cutting one line or part of one
|
||||||
|
* line, so the remainder line is shorter. This means that we
|
||||||
|
* must move text from the end forward first. */
|
||||||
|
charmove(top->data + top_x, bot->data + bot_x, newsize - top_x);
|
||||||
|
top->data = charealloc(top->data, newsize);
|
||||||
|
|
||||||
|
cutbottom->next = NULL;
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
dump_buffer(cutbuffer);
|
dump_buffer(cutbuffer);
|
||||||
#endif
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
tmp = top->next;
|
/* Update totsize to account for the cut part of the last line. */
|
||||||
while (tmp != bot) {
|
totsize -= bot_x + 1;
|
||||||
next = tmp->next;
|
|
||||||
if (!destructive)
|
/* Here, the top remainder line might get longer (if the bottom
|
||||||
tmp = copy_node(tmp);
|
* remainder line is added to the end of it), so we realloc() it
|
||||||
else
|
* first. */
|
||||||
totsize -= strlen(tmp->data) + 1;
|
top->data = charealloc(top->data, newsize);
|
||||||
add_to_cutbuffer(tmp);
|
charmove(top->data + top_x, bot->data + bot_x, newsize - top_x);
|
||||||
tmp = next;
|
|
||||||
}
|
assert(cutbottom != NULL && cutbottom->next != NULL);
|
||||||
|
/* We're cutting multiple lines, so in particular the next line is
|
||||||
|
* cut too. */
|
||||||
|
cutbottom->next->prev = cutbottom;
|
||||||
|
|
||||||
|
/* Update totsize to account for all the complete lines that have
|
||||||
|
* been cut. After this, totsize is fully up to date. */
|
||||||
|
for (tmp = top->next; tmp != bot; tmp = tmp->next)
|
||||||
|
totsize -= strlen(tmp->data) + 1;
|
||||||
|
|
||||||
/* Make the last cut line manually. */
|
/* Make the last cut line manually. */
|
||||||
tmp = copy_node(bot);
|
null_at(&bot->data, bot_x);
|
||||||
null_at(&tmp->data, bot_x);
|
|
||||||
add_to_cutbuffer(tmp);
|
|
||||||
#ifdef DEBUG
|
|
||||||
dump_buffer(cutbuffer);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (destructive) {
|
/* Move the rest of the cut text (other than the cut part of the top
|
||||||
top->next = bot->next;
|
* line) from the buffer to the end of the cutbuffer, and fix the
|
||||||
if (top->next != NULL)
|
* edit buffer to account for the cut text. */
|
||||||
top->next->prev = top;
|
top->next = bot->next;
|
||||||
delete_node(bot);
|
cutbottom = bot;
|
||||||
renumber(top);
|
cutbottom->next = NULL;
|
||||||
current = top;
|
if (top->next != NULL)
|
||||||
if (bot == filebot) {
|
top->next->prev = top;
|
||||||
filebot = top;
|
renumber(top);
|
||||||
assert(bot_x == 0);
|
current = top;
|
||||||
if (top_x > 0)
|
|
||||||
new_magicline();
|
/* If the bottom line of the cut was the magicline, set filebot
|
||||||
}
|
* properly, and add a new magicline if the top remainder line
|
||||||
|
* (which is now the new bottom line) is non-blank. */
|
||||||
|
if (bot == filebot) {
|
||||||
|
filebot = top;
|
||||||
|
assert(bot_x == 0);
|
||||||
|
if (top_x > 0)
|
||||||
|
new_magicline();
|
||||||
}
|
}
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
dump_buffer(cutbuffer);
|
dump_buffer(cutbuffer);
|
||||||
|
@ -194,9 +197,6 @@ void cut_marked_segment(filestruct *top, size_t top_x, filestruct *bot,
|
||||||
int do_cut_text(void)
|
int do_cut_text(void)
|
||||||
{
|
{
|
||||||
filestruct *fileptr;
|
filestruct *fileptr;
|
||||||
#ifndef NANO_SMALL
|
|
||||||
int dontupdate = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
assert(current != NULL && current->data != NULL);
|
assert(current != NULL && current->data != NULL);
|
||||||
|
|
||||||
|
@ -214,8 +214,8 @@ int do_cut_text(void)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* You can't cut the magic line except with the mark. But
|
/* You can't cut the magicline except with the mark. But trying
|
||||||
trying does clear the cutbuffer if KEEP_CUTBUFFER is not set. */
|
* does clear the cutbuffer if KEEP_CUTBUFFER is not set. */
|
||||||
if (current == filebot
|
if (current == filebot
|
||||||
#ifndef NANO_SMALL
|
#ifndef NANO_SMALL
|
||||||
&& !ISSET(MARK_ISSET)
|
&& !ISSET(MARK_ISSET)
|
||||||
|
@ -231,11 +231,12 @@ int do_cut_text(void)
|
||||||
|
|
||||||
if (current->data[current_x] == '\0') {
|
if (current->data[current_x] == '\0') {
|
||||||
/* If the line is empty and we didn't just cut a non-blank
|
/* If the line is empty and we didn't just cut a non-blank
|
||||||
line, create a dummy line and add it to the cutbuffer */
|
* line, create a dummy blank line and add it to the
|
||||||
|
* cutbuffer. */
|
||||||
if (marked_cut != 1 && current->next != filebot) {
|
if (marked_cut != 1 && current->next != filebot) {
|
||||||
filestruct *junk = make_new_node(current);
|
filestruct *junk = make_new_node(current);
|
||||||
|
|
||||||
junk->data = charalloc(1);
|
junk->data = charalloc(1);
|
||||||
junk->data[0] = '\0';
|
junk->data[0] = '\0';
|
||||||
add_to_cutbuffer(junk);
|
add_to_cutbuffer(junk);
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
@ -251,33 +252,22 @@ int do_cut_text(void)
|
||||||
|
|
||||||
mark_beginx = strlen(current->data);
|
mark_beginx = strlen(current->data);
|
||||||
mark_beginbuf = current;
|
mark_beginbuf = current;
|
||||||
dontupdate = 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ISSET(MARK_ISSET)) {
|
if (ISSET(MARK_ISSET)) {
|
||||||
/* Don't do_update() and move the screen position if the marked
|
cut_marked_segment();
|
||||||
area lies entirely within the screen buffer */
|
|
||||||
dontupdate |= current->lineno >= edittop->lineno &&
|
|
||||||
current->lineno <= editbot->lineno &&
|
|
||||||
mark_beginbuf->lineno >= edittop->lineno &&
|
|
||||||
mark_beginbuf->lineno <= editbot->lineno;
|
|
||||||
cut_marked_segment(current, current_x, mark_beginbuf,
|
|
||||||
mark_beginx, 1);
|
|
||||||
|
|
||||||
placewewant = xplustabs();
|
placewewant = xplustabs();
|
||||||
UNSET(MARK_ISSET);
|
UNSET(MARK_ISSET);
|
||||||
|
|
||||||
/* If we just did a marked cut of part of a line, we should add
|
/* If we just did a marked cut of part of a line, we should add
|
||||||
the first line of any cut done immediately afterward to the
|
* the first line of any cut done immediately afterward to the
|
||||||
end of this cut, as Pico does. */
|
* end of this cut, as Pico does. */
|
||||||
if (current == mark_beginbuf && current_x < strlen(current->data))
|
if (current == mark_beginbuf && current_x < strlen(current->data))
|
||||||
concatenate_cut = 1;
|
concatenate_cut = 1;
|
||||||
marked_cut = 1;
|
marked_cut = 1;
|
||||||
if (dontupdate)
|
edit_refresh();
|
||||||
edit_refresh();
|
|
||||||
else
|
|
||||||
edit_update(current, CENTER);
|
|
||||||
set_modified();
|
set_modified();
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -310,29 +300,26 @@ int do_cut_text(void)
|
||||||
#ifndef NANO_SMALL
|
#ifndef NANO_SMALL
|
||||||
concatenate_cut = 0;
|
concatenate_cut = 0;
|
||||||
#endif
|
#endif
|
||||||
placewewant = 0;
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int do_uncut_text(void)
|
int do_uncut_text(void)
|
||||||
{
|
{
|
||||||
filestruct *tmp = current, *fileptr = current;
|
filestruct *tmp = current;
|
||||||
filestruct *newbuf = NULL, *newend = NULL;
|
filestruct *newbuf = NULL;
|
||||||
char *tmpstr, *tmpstr2;
|
filestruct *newend = NULL;
|
||||||
filestruct *hold = current;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
#ifndef DISABLE_WRAPPING
|
#ifndef DISABLE_WRAPPING
|
||||||
wrap_reset();
|
wrap_reset();
|
||||||
#endif
|
#endif
|
||||||
check_statblank();
|
check_statblank();
|
||||||
if (cutbuffer == NULL || fileptr == NULL)
|
if (cutbuffer == NULL || current == NULL)
|
||||||
return 0; /* AIEEEEEEEEEEEE */
|
return 0; /* AIEEEEEEEEEEEE */
|
||||||
|
|
||||||
/* If we're uncutting a previously non-marked block, uncut to end if
|
/* If we're uncutting a previously non-marked block, uncut to end if
|
||||||
we're not at the beginning of the line. If we are at the
|
* we're not at the beginning of the line. If we are at the
|
||||||
beginning of the line, set placewewant to 0. Pico does both of
|
* beginning of the line, set placewewant to 0. Pico does both of
|
||||||
these. */
|
* these. */
|
||||||
if (marked_cut == 0) {
|
if (marked_cut == 0) {
|
||||||
if (current_x != 0)
|
if (current_x != 0)
|
||||||
marked_cut = 2;
|
marked_cut = 2;
|
||||||
|
@ -341,24 +328,22 @@ int do_uncut_text(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we're going to uncut on the magicline, always make a new
|
/* If we're going to uncut on the magicline, always make a new
|
||||||
magicline in advance. */
|
* magicline in advance, as Pico does. */
|
||||||
if (current->next == NULL)
|
if (current->next == NULL)
|
||||||
new_magicline();
|
new_magicline();
|
||||||
|
|
||||||
if (marked_cut == 0 || cutbuffer->next != NULL)
|
if (marked_cut == 0 || cutbuffer->next != NULL) {
|
||||||
{
|
|
||||||
newbuf = copy_filestruct(cutbuffer);
|
newbuf = copy_filestruct(cutbuffer);
|
||||||
for (newend = newbuf; newend->next != NULL && newend != NULL;
|
for (newend = newbuf; newend->next != NULL && newend != NULL;
|
||||||
newend = newend->next)
|
newend = newend->next)
|
||||||
totlines++;
|
totlines++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Hook newbuf into fileptr */
|
/* Hook newbuf in at current. */
|
||||||
if (marked_cut != 0) {
|
if (marked_cut != 0) {
|
||||||
int recenter_me = 0;
|
filestruct *hold = current;
|
||||||
/* Should we eventually use edit_update(CENTER)? */
|
|
||||||
|
|
||||||
/* If there's only one line in the cutbuffer */
|
/* If there's only one line in the cutbuffer... */
|
||||||
if (cutbuffer->next == NULL) {
|
if (cutbuffer->next == NULL) {
|
||||||
size_t buf_len = strlen(cutbuffer->data);
|
size_t buf_len = strlen(cutbuffer->data);
|
||||||
size_t cur_len = strlen(current->data);
|
size_t cur_len = strlen(current->data);
|
||||||
|
@ -367,22 +352,24 @@ int do_uncut_text(void)
|
||||||
charmove(current->data + current_x + buf_len,
|
charmove(current->data + current_x + buf_len,
|
||||||
current->data + current_x, cur_len - current_x + 1);
|
current->data + current_x, cur_len - current_x + 1);
|
||||||
strncpy(current->data + current_x, cutbuffer->data, buf_len);
|
strncpy(current->data + current_x, cutbuffer->data, buf_len);
|
||||||
/* Use strncpy() to not copy the terminal '\0'. */
|
/* Use strncpy() to not copy the null terminator. */
|
||||||
|
|
||||||
current_x += buf_len;
|
current_x += buf_len;
|
||||||
totsize += buf_len;
|
totsize += buf_len;
|
||||||
|
|
||||||
placewewant = xplustabs();
|
placewewant = xplustabs();
|
||||||
update_cursor();
|
} else { /* Yuck -- no kidding! */
|
||||||
} else { /* yuck -- no kidding! */
|
char *tmpstr, *tmpstr2;
|
||||||
|
|
||||||
tmp = current->next;
|
tmp = current->next;
|
||||||
/* New beginning */
|
|
||||||
|
/* New beginning. */
|
||||||
tmpstr = charalloc(current_x + strlen(newbuf->data) + 1);
|
tmpstr = charalloc(current_x + strlen(newbuf->data) + 1);
|
||||||
strncpy(tmpstr, current->data, current_x);
|
strncpy(tmpstr, current->data, current_x);
|
||||||
strcpy(&tmpstr[current_x], newbuf->data);
|
strcpy(&tmpstr[current_x], newbuf->data);
|
||||||
totsize += strlen(newbuf->data) + strlen(newend->data) + 1;
|
totsize += strlen(newbuf->data) + strlen(newend->data) + 1;
|
||||||
|
|
||||||
/* New end */
|
/* New end. */
|
||||||
tmpstr2 = charalloc(strlen(newend->data) +
|
tmpstr2 = charalloc(strlen(newend->data) +
|
||||||
strlen(¤t->data[current_x]) + 1);
|
strlen(¤t->data[current_x]) + 1);
|
||||||
strcpy(tmpstr2, newend->data);
|
strcpy(tmpstr2, newend->data);
|
||||||
|
@ -401,35 +388,28 @@ int do_uncut_text(void)
|
||||||
|
|
||||||
newend->next = tmp;
|
newend->next = tmp;
|
||||||
|
|
||||||
/* If tmp isn't null, we're in the middle: update the
|
/* If tmp isn't NULL, we're in the middle: update the
|
||||||
prev pointer. If it IS null, we're at the end; update
|
* prev pointer. If it IS NULL, we're at the end; update
|
||||||
the filebot pointer */
|
* the filebot pointer. */
|
||||||
|
|
||||||
if (tmp != NULL)
|
if (tmp != NULL)
|
||||||
tmp->prev = newend;
|
tmp->prev = newend;
|
||||||
else {
|
else {
|
||||||
/* Fix the editbot pointer too */
|
|
||||||
if (editbot == filebot)
|
|
||||||
editbot = newend;
|
|
||||||
filebot = newend;
|
filebot = newend;
|
||||||
new_magicline();
|
new_magicline();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now why don't we update the totsize also */
|
/* Now why don't we update the totsize also? */
|
||||||
for (tmp = current->next; tmp != newend; tmp = tmp->next)
|
for (tmp = current->next; tmp != newend; tmp = tmp->next)
|
||||||
totsize += strlen(tmp->data) + 1;
|
totsize += strlen(tmp->data) + 1;
|
||||||
|
|
||||||
current = newend;
|
current = newend;
|
||||||
if (editbot->lineno < newend->lineno)
|
|
||||||
recenter_me = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If marked cut == 2, that means that we're doing a cut to end
|
/* If marked cut == 2, that means that we're doing a cut to end
|
||||||
and we don't want anything else on the line, so we have to
|
* and we don't want anything else on the line, so we have to
|
||||||
screw up all the work we just did and separate the line.
|
* screw up all the work we just did and separate the line.
|
||||||
There must be a better way to do this, but not at 1AM on a
|
* There must be a better way to do this, but not at 1 AM on a
|
||||||
work night. */
|
* work night. */
|
||||||
|
|
||||||
if (marked_cut == 2) {
|
if (marked_cut == 2) {
|
||||||
tmp = make_new_node(current);
|
tmp = make_new_node(current);
|
||||||
tmp->data = mallocstrcpy(NULL, current->data + current_x);
|
tmp->data = mallocstrcpy(NULL, current->data + current_x);
|
||||||
|
@ -439,7 +419,7 @@ int do_uncut_text(void)
|
||||||
current_x = 0;
|
current_x = 0;
|
||||||
placewewant = 0;
|
placewewant = 0;
|
||||||
|
|
||||||
/* Extra line added, update stuff */
|
/* Extra line added; update stuff. */
|
||||||
totlines++;
|
totlines++;
|
||||||
totsize++;
|
totsize++;
|
||||||
}
|
}
|
||||||
|
@ -451,41 +431,32 @@ int do_uncut_text(void)
|
||||||
dump_buffer(cutbuffer);
|
dump_buffer(cutbuffer);
|
||||||
#endif
|
#endif
|
||||||
set_modified();
|
set_modified();
|
||||||
if (recenter_me)
|
edit_refresh();
|
||||||
edit_update(current, CENTER);
|
|
||||||
else
|
|
||||||
edit_refresh();
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fileptr != fileage) {
|
if (current != fileage) {
|
||||||
tmp = fileptr->prev;
|
tmp = current->prev;
|
||||||
tmp->next = newbuf;
|
tmp->next = newbuf;
|
||||||
newbuf->prev = tmp;
|
newbuf->prev = tmp;
|
||||||
} else
|
} else
|
||||||
fileage = newbuf;
|
fileage = newbuf;
|
||||||
totlines++; /* Unmarked uncuts don't split lines */
|
totlines++; /* Unmarked uncuts don't split lines. */
|
||||||
|
|
||||||
/* This is so uncutting at the top of the buffer will work => */
|
/* This is so uncutting at the top of the buffer will work => */
|
||||||
if (current_y == 0)
|
if (current_y == 0)
|
||||||
edittop = newbuf;
|
edittop = newbuf;
|
||||||
|
|
||||||
/* Connect the end of the buffer to the filestruct */
|
/* Connect the end of the buffer to the filestruct. */
|
||||||
newend->next = fileptr;
|
newend->next = current;
|
||||||
fileptr->prev = newend;
|
current->prev = newend;
|
||||||
|
|
||||||
/* Recalculate size *sigh* */
|
/* Recalculate size *sigh* */
|
||||||
for (tmp = newbuf; tmp != fileptr; tmp = tmp->next)
|
for (tmp = newbuf; tmp != current; tmp = tmp->next)
|
||||||
totsize += strlen(tmp->data) + 1;
|
totsize += strlen(tmp->data) + 1;
|
||||||
|
|
||||||
i = editbot->lineno;
|
|
||||||
renumber(newbuf);
|
renumber(newbuf);
|
||||||
/* Center the screen if we've moved beyond the line numbers of both
|
edit_refresh();
|
||||||
the old and new editbots */
|
|
||||||
if (i < newend->lineno && editbot->lineno < newend->lineno)
|
|
||||||
edit_update(fileptr, CENTER);
|
|
||||||
else
|
|
||||||
edit_refresh();
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
dump_buffer_reverse();
|
dump_buffer_reverse();
|
||||||
|
|
593
src/files.c
593
src/files.c
|
@ -522,7 +522,7 @@ int do_insertfile(int loading_file)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef DISABLE_OPERATINGDIR
|
#ifndef DISABLE_OPERATINGDIR
|
||||||
if (i != NANO_EXTCMD_KEY && check_operating_dir(answer, FALSE)) {
|
if (i != NANO_EXTCMD_KEY && check_operating_dir(answer, 0) != 0) {
|
||||||
statusbar(_("Can't insert file from outside of %s"),
|
statusbar(_("Can't insert file from outside of %s"),
|
||||||
operating_dir);
|
operating_dir);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1272,410 +1272,376 @@ void init_operating_dir(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/* Check to see if we're inside the operating directory. Return 0 if we
|
||||||
* Check to see if we're inside the operating directory. Return 0 if we
|
|
||||||
* are, or 1 otherwise. If allow_tabcomp is nonzero, allow incomplete
|
* are, or 1 otherwise. If allow_tabcomp is nonzero, allow incomplete
|
||||||
* names that would be matches for the operating directory, so that tab
|
* names that would be matches for the operating directory, so that tab
|
||||||
* completion will work.
|
* completion will work. */
|
||||||
*/
|
|
||||||
int check_operating_dir(const char *currpath, int allow_tabcomp)
|
int check_operating_dir(const char *currpath, int allow_tabcomp)
|
||||||
{
|
{
|
||||||
/* The char *full_operating_dir is global for mem cleanup, and
|
/* The char *full_operating_dir is global for mem cleanup. It
|
||||||
therefore we only need to get it the first time this function
|
* should have already been initialized by init_operating_dir().
|
||||||
is called; also, a relative operating directory path will
|
* Also, a relative operating directory path will only be handled
|
||||||
only be handled properly if this is done */
|
* properly if this is done. */
|
||||||
|
|
||||||
char *fullpath;
|
char *fullpath;
|
||||||
int retval = 0;
|
int retval = 0;
|
||||||
const char *whereami1, *whereami2 = NULL;
|
const char *whereami1, *whereami2 = NULL;
|
||||||
|
|
||||||
/* if no operating directory is set, don't bother doing anything */
|
/* If no operating directory is set, don't bother doing anything. */
|
||||||
if (operating_dir == NULL)
|
if (operating_dir == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
assert(full_operating_dir != NULL);
|
||||||
|
|
||||||
fullpath = get_full_path(currpath);
|
fullpath = get_full_path(currpath);
|
||||||
|
|
||||||
|
/* fullpath == NULL means some directory in the path doesn't exist
|
||||||
|
* or is unreadable. If allow_tabcomp is zero, then currpath is
|
||||||
|
* what the user typed somewhere. We don't want to report a
|
||||||
|
* non-existent directory as being outside the operating directory,
|
||||||
|
* so we return 0. If allow_tabcomp is nonzero, then currpath
|
||||||
|
* exists, but is not executable. So we say it isn't in the
|
||||||
|
* operating directory. */
|
||||||
if (fullpath == NULL)
|
if (fullpath == NULL)
|
||||||
return 1;
|
return allow_tabcomp;
|
||||||
|
|
||||||
whereami1 = strstr(fullpath, full_operating_dir);
|
whereami1 = strstr(fullpath, full_operating_dir);
|
||||||
if (allow_tabcomp)
|
if (allow_tabcomp)
|
||||||
whereami2 = strstr(full_operating_dir, fullpath);
|
whereami2 = strstr(full_operating_dir, fullpath);
|
||||||
|
|
||||||
/* if both searches failed, we're outside the operating directory */
|
/* If both searches failed, we're outside the operating directory.
|
||||||
/* otherwise */
|
* Otherwise, check the search results; if the full operating
|
||||||
/* check the search results; if the full operating directory path is
|
* directory path is not at the beginning of the full current path
|
||||||
not at the beginning of the full current path (for normal usage)
|
* (for normal usage) and vice versa (for tab completion, if we're
|
||||||
and vice versa (for tab completion, if we're allowing it), we're
|
* allowing it), we're outside the operating directory. */
|
||||||
outside the operating directory */
|
|
||||||
if (whereami1 != fullpath && whereami2 != full_operating_dir)
|
if (whereami1 != fullpath && whereami2 != full_operating_dir)
|
||||||
retval = 1;
|
retval = 1;
|
||||||
free(fullpath);
|
free(fullpath);
|
||||||
/* otherwise, we're still inside it */
|
|
||||||
|
/* Otherwise, we're still inside it. */
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/* Read from inn, write to out. We assume inn is opened for reading,
|
||||||
* Write a file out. If tmp is nonzero, we set the umask to 0600,
|
* and out for writing. We return 0 on success, -1 on read error, -2 on
|
||||||
* we don't set the global variable filename to its name, and don't
|
* write error. */
|
||||||
* print out how many lines we wrote on the statusbar.
|
int copy_file(FILE *inn, FILE *out)
|
||||||
|
{
|
||||||
|
char buf[BUFSIZ];
|
||||||
|
size_t charsread;
|
||||||
|
int retval = 0;
|
||||||
|
|
||||||
|
assert(inn != NULL && out != NULL);
|
||||||
|
do {
|
||||||
|
charsread = fread(buf, sizeof(char), BUFSIZ, inn);
|
||||||
|
if (charsread == 0 && ferror(inn)) {
|
||||||
|
retval = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (fwrite(buf, sizeof(char), charsread, out) < charsread) {
|
||||||
|
retval = -2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while (charsread > 0);
|
||||||
|
if (fclose(inn) == EOF)
|
||||||
|
retval = -1;
|
||||||
|
if (fclose(out) == EOF)
|
||||||
|
retval = -2;
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write a file out. If tmp is nonzero, we set the umask to disallow
|
||||||
|
* anyone else from accessing the file, we don't set the global variable
|
||||||
|
* filename to its name, and we don't print out how many lines we wrote
|
||||||
|
* on the statusbar.
|
||||||
*
|
*
|
||||||
* tmp means we are writing a tmp file in a secure fashion. We use
|
* tmp means we are writing a temporary file in a secure fashion. We
|
||||||
* it when spell checking or dumping the file on an error.
|
* use it when spell checking or dumping the file on an error.
|
||||||
*
|
*
|
||||||
* append == 1 means we are appending instead of overwriting.
|
* append == 1 means we are appending instead of overwriting.
|
||||||
* append == 2 means we are prepending instead of overwriting.
|
* append == 2 means we are prepending instead of overwriting.
|
||||||
*
|
*
|
||||||
* nonamechange means don't change the current filename, it is ignored
|
* nonamechange means don't change the current filename, it is ignored
|
||||||
* if tmp is nonzero or if we're appending/prepending.
|
* if tmp is nonzero or if we're appending/prepending.
|
||||||
*/
|
*
|
||||||
|
* Return -1 on error, 1 on success. */
|
||||||
int write_file(const char *name, int tmp, int append, int nonamechange)
|
int write_file(const char *name, int tmp, int append, int nonamechange)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
/* Instead of returning in this function, you should always
|
/* Instead of returning in this function, you should always
|
||||||
* merely set retval then goto cleanup_and_exit. */
|
* merely set retval and then goto cleanup_and_exit. */
|
||||||
long size;
|
size_t lineswritten = 0;
|
||||||
int lineswritten = 0;
|
const filestruct *fileptr = fileage;
|
||||||
char *buf = NULL;
|
|
||||||
const filestruct *fileptr;
|
|
||||||
FILE *f;
|
|
||||||
int fd;
|
int fd;
|
||||||
int mask = 0, realexists, anyexists;
|
mode_t original_umask = 0;
|
||||||
struct stat st, lst;
|
/* Our umask, from when nano started. */
|
||||||
char *realname = NULL;
|
int realexists;
|
||||||
|
/* The result of stat(). True if the file exists, false
|
||||||
|
* otherwise. If name is a link that points nowhere, realexists
|
||||||
|
* is false. */
|
||||||
|
struct stat st;
|
||||||
|
/* The status fields filled in by stat(). */
|
||||||
|
int anyexists;
|
||||||
|
/* Result of lstat(). Same as realexists unless name is a
|
||||||
|
* link. */
|
||||||
|
struct stat lst;
|
||||||
|
/* The status fields filled in by lstat(). */
|
||||||
|
char *realname;
|
||||||
|
/* name after ~ expansion. */
|
||||||
|
FILE *f;
|
||||||
|
/* The actual file, realname, we are writing to. */
|
||||||
|
char *tempname = NULL;
|
||||||
|
/* The temp file name we write to on prepend. */
|
||||||
|
|
||||||
|
assert(name != NULL);
|
||||||
if (name[0] == '\0') {
|
if (name[0] == '\0') {
|
||||||
statusbar(_("Cancelled"));
|
statusbar(_("Cancelled"));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (!tmp)
|
if (!tmp)
|
||||||
titlebar(NULL);
|
titlebar(NULL);
|
||||||
fileptr = fileage;
|
|
||||||
|
|
||||||
realname = real_dir_from_tilde(name);
|
realname = real_dir_from_tilde(name);
|
||||||
|
|
||||||
#ifndef DISABLE_OPERATINGDIR
|
#ifndef DISABLE_OPERATINGDIR
|
||||||
/* If we're writing a temporary file, we're probably going outside
|
/* If we're writing a temporary file, we're probably going outside
|
||||||
the operating directory, so skip the operating directory test. */
|
* the operating directory, so skip the operating directory test. */
|
||||||
if (!tmp && operating_dir != NULL && check_operating_dir(realname, 0)) {
|
if (!tmp && check_operating_dir(realname, 0) != 0) {
|
||||||
statusbar(_("Can't write outside of %s"), operating_dir);
|
statusbar(_("Can't write outside of %s"), operating_dir);
|
||||||
goto cleanup_and_exit;
|
goto cleanup_and_exit;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
anyexists = lstat(realname, &lst) != -1;
|
||||||
|
/* New case: if the file exists, just give up. */
|
||||||
|
if (tmp && anyexists)
|
||||||
|
goto cleanup_and_exit;
|
||||||
|
/* If NOFOLLOW_SYMLINKS is set, it doesn't make sense to prepend or
|
||||||
|
* append to a symlink. Here we warn about the contradiction. */
|
||||||
|
if (ISSET(NOFOLLOW_SYMLINKS) && anyexists && S_ISLNK(lst.st_mode)) {
|
||||||
|
statusbar(_("Cannot prepend or append to a symlink with --nofollow set."));
|
||||||
|
goto cleanup_and_exit;
|
||||||
|
}
|
||||||
|
|
||||||
/* Save the state of file at the end of the symlink (if there is
|
/* Save the state of file at the end of the symlink (if there is
|
||||||
one). */
|
* one). */
|
||||||
realexists = stat(realname, &st);
|
realexists = stat(realname, &st) != -1;
|
||||||
|
|
||||||
#ifndef NANO_SMALL
|
#ifndef NANO_SMALL
|
||||||
/* We backup only if the backup toggle is set, the file isn't
|
/* We backup only if the backup toggle is set, the file isn't
|
||||||
temporary, and the file already exists. Furthermore, if we aren't
|
* temporary, and the file already exists. Furthermore, if we
|
||||||
appending, prepending, or writing a selection, we backup only if
|
* aren't appending, prepending, or writing a selection, we backup
|
||||||
the file has not been modified by someone else since nano opened
|
* only if the file has not been modified by someone else since nano
|
||||||
it. */
|
* opened it. */
|
||||||
if (ISSET(BACKUP_FILE) && !tmp && realexists == 0 &&
|
if (ISSET(BACKUP_FILE) && !tmp && realexists != 0 &&
|
||||||
(append != 0 || ISSET(MARK_ISSET) ||
|
(append != 0 || ISSET(MARK_ISSET) ||
|
||||||
originalfilestat.st_mtime == st.st_mtime)) {
|
originalfilestat.st_mtime == st.st_mtime)) {
|
||||||
FILE *backup_file;
|
|
||||||
char *backupname = NULL;
|
|
||||||
char backupbuf[COPYFILEBLOCKSIZE];
|
|
||||||
size_t bytesread;
|
|
||||||
struct utimbuf filetime;
|
|
||||||
|
|
||||||
/* save the original file's access and modification times */
|
FILE *backup_file;
|
||||||
|
char *backupname;
|
||||||
|
struct utimbuf filetime;
|
||||||
|
int copy_status;
|
||||||
|
|
||||||
|
/* Save the original file's access and modification times. */
|
||||||
filetime.actime = originalfilestat.st_atime;
|
filetime.actime = originalfilestat.st_atime;
|
||||||
filetime.modtime = originalfilestat.st_mtime;
|
filetime.modtime = originalfilestat.st_mtime;
|
||||||
|
|
||||||
/* open the original file to copy to the backup */
|
/* Open the original file to copy to the backup. */
|
||||||
f = fopen(realname, "rb");
|
f = fopen(realname, "rb");
|
||||||
if (f == NULL) {
|
if (f == NULL) {
|
||||||
statusbar(_("Could not read %s for backup: %s"), realname,
|
statusbar(_("Error reading %s: %s"), realname,
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
return -1;
|
goto cleanup_and_exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
backupname = charalloc(strlen(realname) + 2);
|
backupname = charalloc(strlen(realname) + 2);
|
||||||
sprintf(backupname, "%s~", realname);
|
sprintf(backupname, "%s~", realname);
|
||||||
|
|
||||||
/* get a file descriptor for the destination backup file */
|
/* Open the destination backup file. Before we write to it, we
|
||||||
|
* set its permissions, so no unauthorized person can read it as
|
||||||
|
* we write. */
|
||||||
backup_file = fopen(backupname, "wb");
|
backup_file = fopen(backupname, "wb");
|
||||||
if (backup_file == NULL) {
|
if (backup_file == NULL ||
|
||||||
statusbar(_("Couldn't write backup: %s"), strerror(errno));
|
chmod(backupname, originalfilestat.st_mode) == -1) {
|
||||||
|
statusbar(_("Error writing %s: %s"), backupname, strerror(errno));
|
||||||
free(backupname);
|
free(backupname);
|
||||||
return -1;
|
if (backup_file != NULL)
|
||||||
|
fclose(backup_file);
|
||||||
|
fclose(f);
|
||||||
|
goto cleanup_and_exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
fprintf(stderr, "Backing up %s to %s\n", realname, backupname);
|
fprintf(stderr, "Backing up %s to %s\n", realname, backupname);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* copy the file */
|
/* Copy the file. */
|
||||||
while ((bytesread = fread(backupbuf, sizeof(char),
|
copy_status = copy_file(f, backup_file);
|
||||||
COPYFILEBLOCKSIZE, f)) > 0)
|
/* And set metadata. */
|
||||||
if (fwrite(backupbuf, sizeof(char), bytesread, backup_file) <= 0)
|
if (copy_status != 0 || chown(backupname, originalfilestat.st_uid,
|
||||||
break;
|
originalfilestat.st_gid) == -1 ||
|
||||||
fclose(backup_file);
|
utime(backupname, &filetime) == -1) {
|
||||||
fclose(f);
|
free(backupname);
|
||||||
|
if (copy_status == -1)
|
||||||
if (chmod(backupname, originalfilestat.st_mode) == -1)
|
statusbar(_("Error reading %s: %s"), realname,
|
||||||
statusbar(_("Could not set permissions %o on backup %s: %s"),
|
|
||||||
originalfilestat.st_mode, backupname,
|
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
|
else
|
||||||
if (chown(backupname, originalfilestat.st_uid,
|
statusbar(_("Error writing %s: %s"), backupname,
|
||||||
originalfilestat.st_gid) == -1)
|
strerror(errno));
|
||||||
statusbar(_("Could not set owner %d/group %d on backup %s: %s"),
|
goto cleanup_and_exit;
|
||||||
originalfilestat.st_uid, originalfilestat.st_gid,
|
}
|
||||||
backupname, strerror(errno));
|
|
||||||
|
|
||||||
if (utime(backupname, &filetime) == -1)
|
|
||||||
statusbar(_("Could not set access/modification time on backup %s: %s"),
|
|
||||||
backupname, strerror(errno));
|
|
||||||
|
|
||||||
free(backupname);
|
free(backupname);
|
||||||
}
|
}
|
||||||
#endif
|
#endif /* !NANO_SMALL */
|
||||||
|
|
||||||
/* Stat the link itself for the check... */
|
/* If NOFOLLOW_SYMLINKS and the file is a link, we aren't doing
|
||||||
anyexists = lstat(realname, &lst);
|
* prepend or append. So we delete the link first, and just
|
||||||
|
* overwrite. */
|
||||||
/* New case: if the file exists, just give up */
|
if (ISSET(NOFOLLOW_SYMLINKS) && anyexists && S_ISLNK(lst.st_mode) &&
|
||||||
if (tmp && anyexists != -1)
|
unlink(realname) == -1) {
|
||||||
|
statusbar(_("Error writing %s: %s"), realname, strerror(errno));
|
||||||
goto cleanup_and_exit;
|
goto cleanup_and_exit;
|
||||||
/* NOTE: If you change this statement, you MUST CHANGE the if
|
}
|
||||||
statement below (that says:
|
|
||||||
if (realexists == -1 || tmp || (ISSET(NOFOLLOW_SYMLINKS) &&
|
|
||||||
S_ISLNK(lst.st_mode))) {
|
|
||||||
to reflect whether or not to link/unlink/rename the file */
|
|
||||||
else if (append != 2 && (!ISSET(NOFOLLOW_SYMLINKS) || !S_ISLNK(lst.st_mode)
|
|
||||||
|| tmp)) {
|
|
||||||
/* Use O_EXCL if tmp is nonzero. This is now copied from joe,
|
|
||||||
because wiggy says so *shrug*. */
|
|
||||||
if (append != 0)
|
|
||||||
fd = open(realname, O_WRONLY | O_CREAT | O_APPEND, (S_IRUSR | S_IWUSR));
|
|
||||||
else if (tmp)
|
|
||||||
fd = open(realname, O_WRONLY | O_CREAT | O_EXCL, (S_IRUSR | S_IWUSR));
|
|
||||||
else
|
|
||||||
fd = open(realname, O_WRONLY | O_CREAT | O_TRUNC, (S_IRUSR | S_IWUSR));
|
|
||||||
|
|
||||||
/* First, just give up if we couldn't even open the file */
|
original_umask = umask(0);
|
||||||
if (fd == -1) {
|
umask(original_umask);
|
||||||
if (!tmp && ISSET(TEMP_OPT)) {
|
/* If we create a temp file, we don't let anyone else access it. We
|
||||||
UNSET(TEMP_OPT);
|
* create a temp file if tmp is nonzero or if we prepend. */
|
||||||
retval = do_writeout(filename, 1, 0);
|
if (tmp || append == 2)
|
||||||
} else
|
umask(S_IRWXG | S_IRWXO);
|
||||||
statusbar(_("Could not open file for writing: %s"),
|
|
||||||
strerror(errno));
|
/* If we are prepending, copy the file to a temp file. */
|
||||||
|
if (append == 2) {
|
||||||
|
int fd_source;
|
||||||
|
FILE *f_source = NULL;
|
||||||
|
|
||||||
|
tempname = charalloc(strlen(realname) + 8);
|
||||||
|
strcpy(tempname, realname);
|
||||||
|
strcat(tempname, ".XXXXXX");
|
||||||
|
fd = mkstemp(tempname);
|
||||||
|
f = NULL;
|
||||||
|
if (fd != -1) {
|
||||||
|
f = fdopen(fd, "wb");
|
||||||
|
if (f == NULL)
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
if (f == NULL) {
|
||||||
|
statusbar(_("Error writing %s: %s"), tempname, strerror(errno));
|
||||||
|
unlink(tempname);
|
||||||
goto cleanup_and_exit;
|
goto cleanup_and_exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
fd_source = open(realname, O_RDONLY | O_CREAT);
|
||||||
/* Don't follow symlink. Create new file. */
|
if (fd_source != -1) {
|
||||||
else {
|
f_source = fdopen(fd_source, "rb");
|
||||||
buf = charalloc(strlen(realname) + 8);
|
if (f_source == NULL)
|
||||||
strcpy(buf, realname);
|
close(fd_source);
|
||||||
strcat(buf, ".XXXXXX");
|
}
|
||||||
if ((fd = mkstemp(buf)) == -1) {
|
if (f_source == NULL) {
|
||||||
if (ISSET(TEMP_OPT)) {
|
statusbar(_("Error reading %s: %s"), realname, strerror(errno));
|
||||||
UNSET(TEMP_OPT);
|
fclose(f);
|
||||||
retval = do_writeout(filename, 1, 0);
|
unlink(tempname);
|
||||||
} else
|
goto cleanup_and_exit;
|
||||||
statusbar(_("Could not open file for writing: %s"),
|
}
|
||||||
strerror(errno));
|
|
||||||
|
if (copy_file(f_source, f) != 0) {
|
||||||
|
statusbar(_("Error writing %s: %s"), tempname, strerror(errno));
|
||||||
|
unlink(tempname);
|
||||||
goto cleanup_and_exit;
|
goto cleanup_and_exit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
/* Now open the file in place. Use O_EXCL if tmp is nonzero. This
|
||||||
dump_buffer(fileage);
|
* is now copied from joe, because wiggy says so *shrug*. */
|
||||||
#endif
|
fd = open(realname, O_WRONLY | O_CREAT |
|
||||||
|
(append == 1 ? O_APPEND : (tmp ? O_EXCL : O_TRUNC)),
|
||||||
|
S_IRUSR | S_IWUSR);
|
||||||
|
|
||||||
|
/* Put the umask back to the user's original value. */
|
||||||
|
umask(original_umask);
|
||||||
|
|
||||||
|
/* First, just give up if we couldn't even open the file. */
|
||||||
|
if (fd == -1) {
|
||||||
|
statusbar(_("Error writing %s: %s"), realname, strerror(errno));
|
||||||
|
unlink(tempname);
|
||||||
|
goto cleanup_and_exit;
|
||||||
|
}
|
||||||
|
|
||||||
f = fdopen(fd, append == 1 ? "ab" : "wb");
|
f = fdopen(fd, append == 1 ? "ab" : "wb");
|
||||||
if (f == NULL) {
|
if (f == NULL) {
|
||||||
statusbar(_("Could not open file for writing: %s"), strerror(errno));
|
statusbar(_("Error writing %s: %s"), realname, strerror(errno));
|
||||||
|
close(fd);
|
||||||
goto cleanup_and_exit;
|
goto cleanup_and_exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (fileptr != NULL && fileptr->next != NULL) {
|
/* There might not be a magic line. There won't be when writing out
|
||||||
int data_len;
|
* a selection. */
|
||||||
|
assert(fileage != NULL && filebot != NULL);
|
||||||
|
while (fileptr != filebot) {
|
||||||
|
size_t data_len = strlen(fileptr->data);
|
||||||
|
size_t size;
|
||||||
|
|
||||||
/* Next line is so we discount the "magic line" */
|
/* Newlines to nulls, just before we write to disk. */
|
||||||
if (filebot == fileptr && fileptr->data[0] == '\0')
|
|
||||||
break;
|
|
||||||
|
|
||||||
data_len = strlen(fileptr->data);
|
|
||||||
|
|
||||||
/* newlines to nulls, just before we write to disk */
|
|
||||||
sunder(fileptr->data);
|
sunder(fileptr->data);
|
||||||
|
|
||||||
size = fwrite(fileptr->data, 1, data_len, f);
|
size = fwrite(fileptr->data, sizeof(char), data_len, f);
|
||||||
|
|
||||||
/* nulls to newlines; data_len is the string's real length here */
|
/* Nulls to newlines; data_len is the string's real length. */
|
||||||
unsunder(fileptr->data, data_len);
|
unsunder(fileptr->data, data_len);
|
||||||
|
|
||||||
if (size < data_len) {
|
if (size < data_len) {
|
||||||
statusbar(_("Could not open file for writing: %s"),
|
statusbar(_("Error writing %s: %s"), realname, strerror(errno));
|
||||||
strerror(errno));
|
|
||||||
fclose(f);
|
fclose(f);
|
||||||
goto cleanup_and_exit;
|
goto cleanup_and_exit;
|
||||||
}
|
}
|
||||||
#ifdef DEBUG
|
|
||||||
else
|
|
||||||
fprintf(stderr, "Wrote >%s\n", fileptr->data);
|
|
||||||
#endif
|
|
||||||
#ifndef NANO_SMALL
|
#ifndef NANO_SMALL
|
||||||
if (ISSET(DOS_FILE) || ISSET(MAC_FILE))
|
if (ISSET(DOS_FILE) || ISSET(MAC_FILE))
|
||||||
putc('\r', f);
|
if (putc('\r', f) == EOF) {
|
||||||
|
statusbar(_("Error writing %s: %s"), realname, strerror(errno));
|
||||||
|
fclose(f);
|
||||||
|
goto cleanup_and_exit;
|
||||||
|
}
|
||||||
|
|
||||||
if (!ISSET(MAC_FILE))
|
if (!ISSET(MAC_FILE))
|
||||||
#endif
|
#endif
|
||||||
putc('\n', f);
|
if (putc('\n', f) == EOF) {
|
||||||
|
statusbar(_("Error writing %s: %s"), realname, strerror(errno));
|
||||||
|
fclose(f);
|
||||||
|
goto cleanup_and_exit;
|
||||||
|
}
|
||||||
|
|
||||||
fileptr = fileptr->next;
|
fileptr = fileptr->next;
|
||||||
lineswritten++;
|
lineswritten++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fileptr != NULL) {
|
/* If we're prepending, open the temp file, and append it to f. */
|
||||||
int data_len = strlen(fileptr->data);
|
if (append == 2) {
|
||||||
|
int fd_source;
|
||||||
|
FILE *f_source = NULL;
|
||||||
|
|
||||||
/* newlines to nulls, just before we write to disk */
|
fd_source = open(tempname, O_RDONLY | O_CREAT);
|
||||||
sunder(fileptr->data);
|
if (fd_source != -1) {
|
||||||
|
f_source = fdopen(fd_source, "rb");
|
||||||
size = fwrite(fileptr->data, 1, data_len, f);
|
if (f_source == NULL)
|
||||||
|
close(fd_source);
|
||||||
/* nulls to newlines; data_len is the string's real length here */
|
}
|
||||||
unsunder(fileptr->data, data_len);
|
if (f_source == NULL) {
|
||||||
|
statusbar(_("Error reading %s: %s"), tempname, strerror(errno));
|
||||||
if (size < data_len) {
|
fclose(f);
|
||||||
statusbar(_("Could not open file for writing: %s"),
|
goto cleanup_and_exit;
|
||||||
strerror(errno));
|
|
||||||
goto cleanup_and_exit;
|
|
||||||
} else if (data_len > 0) {
|
|
||||||
#ifndef NANO_SMALL
|
|
||||||
if (ISSET(DOS_FILE) || ISSET(MAC_FILE)) {
|
|
||||||
if (putc('\r', f) == EOF) {
|
|
||||||
statusbar(_("Could not open file for writing: %s"),
|
|
||||||
strerror(errno));
|
|
||||||
fclose(f);
|
|
||||||
goto cleanup_and_exit;
|
|
||||||
}
|
|
||||||
lineswritten++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ISSET(MAC_FILE))
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
if (putc('\n', f) == EOF) {
|
|
||||||
statusbar(_("Could not open file for writing: %s"),
|
|
||||||
strerror(errno));
|
|
||||||
fclose(f);
|
|
||||||
goto cleanup_and_exit;
|
|
||||||
}
|
|
||||||
lineswritten++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (fclose(f) != 0) {
|
if (copy_file(f_source, f) == -1
|
||||||
statusbar(_("Could not close %s: %s"), realname, strerror(errno));
|
|| unlink(tempname) == -1) {
|
||||||
unlink(buf);
|
statusbar(_("Error writing %s: %s"), realname, strerror(errno));
|
||||||
|
goto cleanup_and_exit;
|
||||||
|
}
|
||||||
|
} else if (fclose(f) == EOF) {
|
||||||
|
statusbar(_("Error writing %s: %s"), realname, strerror(errno));
|
||||||
|
unlink(tempname);
|
||||||
goto cleanup_and_exit;
|
goto cleanup_and_exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if we're prepending, open the real file, and append it here */
|
|
||||||
if (append == 2) {
|
|
||||||
int fd_source, fd_dest;
|
|
||||||
FILE *f_source, *f_dest;
|
|
||||||
int prechar;
|
|
||||||
|
|
||||||
if ((fd_dest = open(buf, O_WRONLY | O_APPEND, (S_IRUSR | S_IWUSR))) == -1) {
|
|
||||||
statusbar(_("Could not reopen %s: %s"), buf, strerror(errno));
|
|
||||||
goto cleanup_and_exit;
|
|
||||||
}
|
|
||||||
f_dest = fdopen(fd_dest, "wb");
|
|
||||||
if (f_dest == NULL) {
|
|
||||||
statusbar(_("Could not reopen %s: %s"), buf, strerror(errno));
|
|
||||||
close(fd_dest);
|
|
||||||
goto cleanup_and_exit;
|
|
||||||
}
|
|
||||||
if ((fd_source = open(realname, O_RDONLY | O_CREAT)) == -1) {
|
|
||||||
statusbar(_("Could not open %s for prepend: %s"), realname, strerror(errno));
|
|
||||||
fclose(f_dest);
|
|
||||||
goto cleanup_and_exit;
|
|
||||||
}
|
|
||||||
f_source = fdopen(fd_source, "rb");
|
|
||||||
if (f_source == NULL) {
|
|
||||||
statusbar(_("Could not open %s for prepend: %s"), realname, strerror(errno));
|
|
||||||
fclose(f_dest);
|
|
||||||
close(fd_source);
|
|
||||||
goto cleanup_and_exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Doing this in blocks is an exercise left to some other reader. */
|
|
||||||
while ((prechar = getc(f_source)) != EOF) {
|
|
||||||
if (putc(prechar, f_dest) == EOF) {
|
|
||||||
statusbar(_("Could not open %s for prepend: %s"), realname, strerror(errno));
|
|
||||||
fclose(f_source);
|
|
||||||
fclose(f_dest);
|
|
||||||
goto cleanup_and_exit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ferror(f_source)) {
|
|
||||||
statusbar(_("Could not reopen %s: %s"), buf, strerror(errno));
|
|
||||||
fclose(f_source);
|
|
||||||
fclose(f_dest);
|
|
||||||
goto cleanup_and_exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
fclose(f_source);
|
|
||||||
fclose(f_dest);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (realexists == -1 || tmp ||
|
|
||||||
(ISSET(NOFOLLOW_SYMLINKS) && S_ISLNK(lst.st_mode))) {
|
|
||||||
|
|
||||||
/* Use default umask as file permissions if file is a new file. */
|
|
||||||
mask = umask(0);
|
|
||||||
umask(mask);
|
|
||||||
|
|
||||||
if (tmp) /* We don't want anyone reading our temporary file! */
|
|
||||||
mask = S_IRUSR | S_IWUSR;
|
|
||||||
else
|
|
||||||
mask = (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH |
|
|
||||||
S_IWOTH) & ~mask;
|
|
||||||
} else
|
|
||||||
/* Use permissions from file we are overwriting. */
|
|
||||||
mask = st.st_mode;
|
|
||||||
|
|
||||||
if (append == 2 ||
|
|
||||||
(!tmp && (ISSET(NOFOLLOW_SYMLINKS) && S_ISLNK(lst.st_mode)))) {
|
|
||||||
if (unlink(realname) == -1) {
|
|
||||||
if (errno != ENOENT) {
|
|
||||||
statusbar(_("Could not open %s for writing: %s"),
|
|
||||||
realname, strerror(errno));
|
|
||||||
unlink(buf);
|
|
||||||
goto cleanup_and_exit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (link(buf, realname) != -1)
|
|
||||||
unlink(buf);
|
|
||||||
else if (errno != EPERM) {
|
|
||||||
statusbar(_("Could not open %s for writing: %s"),
|
|
||||||
name, strerror(errno));
|
|
||||||
unlink(buf);
|
|
||||||
goto cleanup_and_exit;
|
|
||||||
} else if (rename(buf, realname) == -1) { /* Try a rename?? */
|
|
||||||
statusbar(_("Could not open %s for writing: %s"),
|
|
||||||
realname, strerror(errno));
|
|
||||||
unlink(buf);
|
|
||||||
goto cleanup_and_exit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (chmod(realname, mask) == -1)
|
|
||||||
statusbar(_("Could not set permissions %o on %s: %s"),
|
|
||||||
mask, realname, strerror(errno));
|
|
||||||
|
|
||||||
if (!tmp && append == 0) {
|
if (!tmp && append == 0) {
|
||||||
if (!nonamechange) {
|
if (!nonamechange) {
|
||||||
filename = mallocstrcpy(filename, realname);
|
filename = mallocstrcpy(filename, realname);
|
||||||
|
@ -1689,8 +1655,8 @@ int write_file(const char *name, int tmp, int append, int nonamechange)
|
||||||
/* Update originalfilestat to reference the file as it is now. */
|
/* Update originalfilestat to reference the file as it is now. */
|
||||||
stat(filename, &originalfilestat);
|
stat(filename, &originalfilestat);
|
||||||
#endif
|
#endif
|
||||||
statusbar(P_("Wrote %d line", "Wrote %d lines", lineswritten),
|
statusbar(P_("Wrote %u line", "Wrote %u lines", lineswritten),
|
||||||
lineswritten);
|
lineswritten);
|
||||||
UNSET(MODIFIED);
|
UNSET(MODIFIED);
|
||||||
titlebar(NULL);
|
titlebar(NULL);
|
||||||
}
|
}
|
||||||
|
@ -1699,7 +1665,7 @@ int write_file(const char *name, int tmp, int append, int nonamechange)
|
||||||
|
|
||||||
cleanup_and_exit:
|
cleanup_and_exit:
|
||||||
free(realname);
|
free(realname);
|
||||||
free(buf);
|
free(tempname);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1850,31 +1816,52 @@ int do_writeout(const char *path, int exiting, int append)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef NANO_SMALL
|
#ifndef NANO_SMALL
|
||||||
/* Here's where we allow the selected text to be written to
|
/* Here's where we allow the selected text to be written to
|
||||||
a separate file. */
|
* a separate file. */
|
||||||
if (ISSET(MARK_ISSET) && !exiting) {
|
if (ISSET(MARK_ISSET) && !exiting) {
|
||||||
filestruct *fileagebak = fileage;
|
filestruct *fileagebak = fileage;
|
||||||
filestruct *filebotbak = filebot;
|
filestruct *filebotbak = filebot;
|
||||||
filestruct *cutback = cutbuffer;
|
|
||||||
int oldmod = ISSET(MODIFIED);
|
int oldmod = ISSET(MODIFIED);
|
||||||
/* write_file() unsets the MODIFIED flag. */
|
/* write_file() unsets the MODIFIED flag. */
|
||||||
|
size_t topx;
|
||||||
|
/* The column of the beginning of the mark. */
|
||||||
|
char origchar;
|
||||||
|
/* We replace the character at the end of the mark with
|
||||||
|
* '\0'. We save the original character, to restore
|
||||||
|
* it. */
|
||||||
|
char *origcharloc;
|
||||||
|
/* The location of the character we nulled. */
|
||||||
|
|
||||||
cutbuffer = NULL;
|
/* Set fileage as the top of the mark, and filebot as the
|
||||||
|
* bottom. */
|
||||||
/* Put the marked text in the cutbuffer without changing
|
if (current->lineno > mark_beginbuf->lineno ||
|
||||||
the open file. */
|
(current->lineno == mark_beginbuf->lineno &&
|
||||||
cut_marked_segment(current, current_x, mark_beginbuf,
|
current_x > mark_beginx)) {
|
||||||
mark_beginx, 0);
|
fileage = mark_beginbuf;
|
||||||
|
topx = mark_beginx;
|
||||||
fileage = cutbuffer;
|
filebot = current;
|
||||||
filebot = get_cutbottom();
|
origcharloc = current->data + current_x;
|
||||||
|
} else {
|
||||||
|
fileage = current;
|
||||||
|
topx = current_x;
|
||||||
|
filebot = mark_beginbuf;
|
||||||
|
origcharloc = mark_beginbuf->data + mark_beginx;
|
||||||
|
}
|
||||||
|
origchar = *origcharloc;
|
||||||
|
*origcharloc = '\0';
|
||||||
|
fileage->data += topx;
|
||||||
|
/* If the line at filebot is blank, treat it as the
|
||||||
|
* magicline and hence the end of the file. Otherwise,
|
||||||
|
* treat the line after filebot as the end of the file. */
|
||||||
|
if (filebot->data[0] != '\0' && filebot->next != NULL)
|
||||||
|
filebot = filebot->next;
|
||||||
i = write_file(answer, 0, append, 1);
|
i = write_file(answer, 0, append, 1);
|
||||||
|
|
||||||
/* Now restore everything */
|
/* Now restore everything. */
|
||||||
free_filestruct(cutbuffer);
|
fileage->data -= topx;
|
||||||
|
*origcharloc = origchar;
|
||||||
fileage = fileagebak;
|
fileage = fileagebak;
|
||||||
filebot = filebotbak;
|
filebot = filebotbak;
|
||||||
cutbuffer = cutback;
|
|
||||||
if (oldmod)
|
if (oldmod)
|
||||||
set_modified();
|
set_modified();
|
||||||
} else
|
} else
|
||||||
|
@ -2110,7 +2097,7 @@ char **cwd_tab_completion(char *buf, int *num_matches)
|
||||||
strcpy(tmp2, dirname);
|
strcpy(tmp2, dirname);
|
||||||
strcat(tmp2, "/");
|
strcat(tmp2, "/");
|
||||||
strcat(tmp2, next->d_name);
|
strcat(tmp2, next->d_name);
|
||||||
if (check_operating_dir(tmp2, 1)) {
|
if (check_operating_dir(tmp2, 1) != 0) {
|
||||||
free(tmp2);
|
free(tmp2);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -2631,7 +2618,7 @@ char *do_browser(const char *inpath)
|
||||||
/* Note: the selected file can be outside the operating
|
/* Note: the selected file can be outside the operating
|
||||||
* directory if it is .. or if it is a symlink to
|
* directory if it is .. or if it is a symlink to
|
||||||
* directory outside the operating directory. */
|
* directory outside the operating directory. */
|
||||||
if (check_operating_dir(filelist[selected], FALSE)) {
|
if (check_operating_dir(filelist[selected], 0) != 0) {
|
||||||
statusbar(_("Can't go outside of %s in restricted mode"), operating_dir);
|
statusbar(_("Can't go outside of %s in restricted mode"), operating_dir);
|
||||||
beep();
|
beep();
|
||||||
break;
|
break;
|
||||||
|
@ -2704,7 +2691,7 @@ char *do_browser(const char *inpath)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef DISABLE_OPERATINGDIR
|
#ifndef DISABLE_OPERATINGDIR
|
||||||
if (check_operating_dir(new_path, FALSE)) {
|
if (check_operating_dir(new_path, 0) != 0) {
|
||||||
statusbar(_("Can't go outside of %s in restricted mode"), operating_dir);
|
statusbar(_("Can't go outside of %s in restricted mode"), operating_dir);
|
||||||
free(new_path);
|
free(new_path);
|
||||||
break;
|
break;
|
||||||
|
@ -2847,7 +2834,7 @@ char *do_browse_from(const char *inpath)
|
||||||
|
|
||||||
#ifndef DISABLE_OPERATINGDIR
|
#ifndef DISABLE_OPERATINGDIR
|
||||||
/* If the resulting path isn't in the operating directory, use that. */
|
/* If the resulting path isn't in the operating directory, use that. */
|
||||||
if (check_operating_dir(path, FALSE))
|
if (check_operating_dir(path, 0) != 0)
|
||||||
path = mallocstrcpy(path, operating_dir);
|
path = mallocstrcpy(path, operating_dir);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -172,7 +172,7 @@ void sc_init_one(shortcut **shortcutage, int key, const char *desc,
|
||||||
#ifndef DISABLE_HELP
|
#ifndef DISABLE_HELP
|
||||||
const char *help,
|
const char *help,
|
||||||
#endif
|
#endif
|
||||||
int alt, int func_key, int misc, int view, int (*func) (void))
|
int meta, int func_key, int misc, int view, int (*func) (void))
|
||||||
{
|
{
|
||||||
shortcut *s;
|
shortcut *s;
|
||||||
|
|
||||||
|
@ -191,7 +191,7 @@ void sc_init_one(shortcut **shortcutage, int key, const char *desc,
|
||||||
#ifndef DISABLE_HELP
|
#ifndef DISABLE_HELP
|
||||||
s->help = help;
|
s->help = help;
|
||||||
#endif
|
#endif
|
||||||
s->altval = alt;
|
s->metaval = meta;
|
||||||
s->func_key = func_key;
|
s->func_key = func_key;
|
||||||
s->misc = misc;
|
s->misc = misc;
|
||||||
s->viewok = view;
|
s->viewok = view;
|
||||||
|
|
18
src/nano.c
18
src/nano.c
|
@ -403,7 +403,7 @@ void help_init(void)
|
||||||
|
|
||||||
/* Now add our shortcut info */
|
/* Now add our shortcut info */
|
||||||
for (s = currshortcut; s != NULL; s = s->next) {
|
for (s = currshortcut; s != NULL; s = s->next) {
|
||||||
/* true if the character in s->altval is shown in first column */
|
/* true if the character in s->metaval is shown in first column */
|
||||||
int meta_shortcut = 0;
|
int meta_shortcut = 0;
|
||||||
|
|
||||||
if (s->val != NANO_NO_KEY) {
|
if (s->val != NANO_NO_KEY) {
|
||||||
|
@ -420,12 +420,12 @@ void help_init(void)
|
||||||
ptr += sprintf(ptr, "^%c", s->val + 64);
|
ptr += sprintf(ptr, "^%c", s->val + 64);
|
||||||
}
|
}
|
||||||
#ifndef NANO_SMALL
|
#ifndef NANO_SMALL
|
||||||
else if (s->altval != NANO_NO_KEY) {
|
else if (s->metaval != NANO_NO_KEY) {
|
||||||
meta_shortcut = 1;
|
meta_shortcut = 1;
|
||||||
if (s->altval == NANO_ALT_SPACE)
|
if (s->metaval == NANO_ALT_SPACE)
|
||||||
ptr += snprintf(ptr, 8, "M-%.5s", _("Space"));
|
ptr += snprintf(ptr, 8, "M-%.5s", _("Space"));
|
||||||
else
|
else
|
||||||
ptr += sprintf(ptr, "M-%c", toupper(s->altval));
|
ptr += sprintf(ptr, "M-%c", toupper(s->metaval));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -436,8 +436,8 @@ void help_init(void)
|
||||||
|
|
||||||
*(ptr++) = '\t';
|
*(ptr++) = '\t';
|
||||||
|
|
||||||
if (!meta_shortcut && s->altval != NANO_NO_KEY)
|
if (!meta_shortcut && s->metaval != NANO_NO_KEY)
|
||||||
ptr += sprintf(ptr, "(M-%c)", toupper(s->altval));
|
ptr += sprintf(ptr, "(M-%c)", toupper(s->metaval));
|
||||||
else if (meta_shortcut && s->misc != NANO_NO_KEY)
|
else if (meta_shortcut && s->misc != NANO_NO_KEY)
|
||||||
ptr += sprintf(ptr, "(M-%c)", toupper(s->misc));
|
ptr += sprintf(ptr, "(M-%c)", toupper(s->misc));
|
||||||
|
|
||||||
|
@ -3516,10 +3516,10 @@ int main(int argc, char *argv[])
|
||||||
fprintf(stderr, "AHA! %c (%d)\n", kbinput, kbinput);
|
fprintf(stderr, "AHA! %c (%d)\n", kbinput, kbinput);
|
||||||
#endif
|
#endif
|
||||||
if (meta == 1) {
|
if (meta == 1) {
|
||||||
/* Check for the altkey and misc defs... */
|
/* Check for the metaval and misc defs... */
|
||||||
for (s = main_list; s != NULL; s = s->next)
|
for (s = main_list; s != NULL; s = s->next)
|
||||||
if ((s->altval > 0 && kbinput == s->altval) ||
|
if ((s->metaval != NANO_NO_KEY && kbinput == s->metaval) ||
|
||||||
(s->misc > 0 && kbinput == s->misc)) {
|
(s->misc != NANO_NO_KEY && kbinput == s->misc)) {
|
||||||
if (ISSET(VIEW_MODE) && !s->viewok)
|
if (ISSET(VIEW_MODE) && !s->viewok)
|
||||||
print_view_warning();
|
print_view_warning();
|
||||||
else {
|
else {
|
||||||
|
|
119
src/nano.h
119
src/nano.h
|
@ -46,13 +46,14 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USE_SLANG
|
#ifdef USE_SLANG
|
||||||
/* Slang support enabled */
|
/* Slang support enabled. Work around Slang's not defining KEY_DC or
|
||||||
|
* KEY_IC. */
|
||||||
#include <slcurses.h>
|
#include <slcurses.h>
|
||||||
#define KEY_DC SL_KEY_DELETE
|
#define KEY_DC SL_KEY_DELETE
|
||||||
#define KEY_IC SL_KEY_IC
|
#define KEY_IC SL_KEY_IC
|
||||||
#elif defined(HAVE_NCURSES_H)
|
#elif defined(HAVE_NCURSES_H)
|
||||||
#include <ncurses.h>
|
#include <ncurses.h>
|
||||||
#else /* Uh oh */
|
#else /* Uh oh. */
|
||||||
#include <curses.h>
|
#include <curses.h>
|
||||||
#endif /* CURSES_H */
|
#endif /* CURSES_H */
|
||||||
|
|
||||||
|
@ -71,16 +72,18 @@
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
|
/* If no snprintf()/vsnprintf(), use the versions from glib. */
|
||||||
#if !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF)
|
#if !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF)
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
# ifndef HAVE_SNPRINTF
|
# ifndef HAVE_SNPRINTF
|
||||||
# define snprintf g_snprintf
|
# define snprintf g_snprintf
|
||||||
# endif
|
# endif
|
||||||
# ifndef HAVE_VSNPRINTF
|
# ifndef HAVE_VSNPRINTF
|
||||||
# define vsnprintf g_vsnprintf
|
# define vsnprintf g_vsnprintf
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* If no strcasecmp()/strncasecmp(), use the versions we have. */
|
||||||
#ifndef HAVE_STRCASECMP
|
#ifndef HAVE_STRCASECMP
|
||||||
#define strcasecmp nstricmp
|
#define strcasecmp nstricmp
|
||||||
#endif
|
#endif
|
||||||
|
@ -90,11 +93,11 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Assume ERR is defined as -1. To avoid duplicate case values when
|
/* Assume ERR is defined as -1. To avoid duplicate case values when
|
||||||
some key definitions are missing, we have to set all of these, and
|
* some key definitions are missing, we have to set all of these, and
|
||||||
all of the special sentinel values below, to different negative
|
* all of the special sentinel values below, to different negative
|
||||||
values other than -1. */
|
* values other than -1. */
|
||||||
|
|
||||||
/* HP-UX 10 & 11 do not seem to support KEY_HOME and KEY_END */
|
/* HP-UX 10 & 11 do not seem to support KEY_HOME and KEY_END. */
|
||||||
#ifndef KEY_HOME
|
#ifndef KEY_HOME
|
||||||
#define KEY_HOME -2
|
#define KEY_HOME -2
|
||||||
#endif
|
#endif
|
||||||
|
@ -103,13 +106,13 @@
|
||||||
#define KEY_END -3
|
#define KEY_END -3
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Slang and SunOS 5.7-5.9 do not seem to support KEY_RESIZE */
|
/* Slang and SunOS 5.7-5.9 do not seem to support KEY_RESIZE. */
|
||||||
#ifndef KEY_RESIZE
|
#ifndef KEY_RESIZE
|
||||||
#define KEY_RESIZE -4
|
#define KEY_RESIZE -4
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Slang does not seem to support KEY_SUSPEND, KEY_SLEFT, or
|
/* Slang does not seem to support KEY_SUSPEND, KEY_SLEFT, or
|
||||||
KEY_SRIGHT */
|
* KEY_SRIGHT. */
|
||||||
#ifndef KEY_SUSPEND
|
#ifndef KEY_SUSPEND
|
||||||
#define KEY_SUSPEND -5
|
#define KEY_SUSPEND -5
|
||||||
#endif
|
#endif
|
||||||
|
@ -124,6 +127,8 @@
|
||||||
|
|
||||||
#define VERMSG "GNU nano " VERSION
|
#define VERMSG "GNU nano " VERSION
|
||||||
|
|
||||||
|
/* If we aren't using ncurses, turn the mouse support off, as it's
|
||||||
|
* ncurses-specific. */
|
||||||
#ifndef NCURSES_MOUSE_VERSION
|
#ifndef NCURSES_MOUSE_VERSION
|
||||||
#define DISABLE_MOUSE 1
|
#define DISABLE_MOUSE 1
|
||||||
#endif
|
#endif
|
||||||
|
@ -132,12 +137,12 @@
|
||||||
#define DISABLE_WRAPJUSTIFY 1
|
#define DISABLE_WRAPJUSTIFY 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Structure types */
|
/* Structure types. */
|
||||||
typedef struct filestruct {
|
typedef struct filestruct {
|
||||||
char *data;
|
char *data;
|
||||||
struct filestruct *next; /* Next node */
|
struct filestruct *next; /* Next node. */
|
||||||
struct filestruct *prev; /* Previous node */
|
struct filestruct *prev; /* Previous node. */
|
||||||
int lineno; /* The line number */
|
int lineno; /* The line number. */
|
||||||
} filestruct;
|
} filestruct;
|
||||||
|
|
||||||
#ifdef ENABLE_MULTIBUFFER
|
#ifdef ENABLE_MULTIBUFFER
|
||||||
|
@ -146,51 +151,56 @@ typedef struct openfilestruct {
|
||||||
#ifndef NANO_SMALL
|
#ifndef NANO_SMALL
|
||||||
struct stat originalfilestat;
|
struct stat originalfilestat;
|
||||||
#endif
|
#endif
|
||||||
struct openfilestruct *next; /* Next node */
|
struct openfilestruct *next; /* Next node. */
|
||||||
struct openfilestruct *prev; /* Previous node */
|
struct openfilestruct *prev; /* Previous node. */
|
||||||
struct filestruct *fileage; /* Current file */
|
struct filestruct *fileage; /* Current file. */
|
||||||
struct filestruct *filebot; /* Current file's last line */
|
struct filestruct *filebot; /* Current file's last line. */
|
||||||
#ifndef NANO_SMALL
|
#ifndef NANO_SMALL
|
||||||
struct filestruct *file_mark_beginbuf;
|
struct filestruct *file_mark_beginbuf;
|
||||||
/* Current file's beginning marked line */
|
/* Current file's beginning marked
|
||||||
int file_mark_beginx; /* Current file's beginning marked line's
|
* line. */
|
||||||
x-coordinate position */
|
int file_mark_beginx; /* Current file's beginning marked
|
||||||
|
* line's x-coordinate position. */
|
||||||
#endif
|
#endif
|
||||||
int file_current_x; /* Current file's x-coordinate position */
|
int file_current_x; /* Current file's x-coordinate
|
||||||
int file_current_y; /* Current file's y-coordinate position */
|
* position. */
|
||||||
|
int file_current_y; /* Current file's y-coordinate
|
||||||
|
* position. */
|
||||||
int file_flags; /* Current file's flags: modification
|
int file_flags; /* Current file's flags: modification
|
||||||
status (and marking status, if
|
* status (and marking status, if
|
||||||
available) */
|
* available). */
|
||||||
int file_placewewant; /* Current file's place we want */
|
int file_placewewant; /* Current file's place we want. */
|
||||||
int file_totlines; /* Current file's total number of lines */
|
int file_totlines; /* Current file's total number of
|
||||||
long file_totsize; /* Current file's total size */
|
* lines. */
|
||||||
int file_lineno; /* Current file's line number */
|
long file_totsize; /* Current file's total size. */
|
||||||
|
int file_lineno; /* Current file's line number. */
|
||||||
} openfilestruct;
|
} openfilestruct;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct shortcut {
|
typedef struct shortcut {
|
||||||
/* Key values that aren't used should be set to NANO_NO_KEY */
|
/* Key values that aren't used should be set to NANO_NO_KEY. */
|
||||||
int val; /* Special sentinel key or control key we want
|
int val; /* Special sentinel key or control key we want
|
||||||
* bound */
|
* bound. */
|
||||||
int altval; /* Alt key we want bound */
|
int metaval; /* Meta key we want bound. */
|
||||||
int func_key; /* Function key we want bound */
|
int func_key; /* Function key we want bound. */
|
||||||
int misc; /* Other Alt key we want bound */
|
int misc; /* Other Meta key we want bound. */
|
||||||
int viewok; /* Is this function legal in view mode? */
|
int viewok; /* Is this function legal in view mode? */
|
||||||
int (*func) (void); /* Function to call when we catch this key */
|
int (*func) (void); /* Function to call when we catch this key. */
|
||||||
const char *desc; /* Description, e.g. "Page Up" */
|
const char *desc; /* Description, e.g. "Page Up". */
|
||||||
#ifndef DISABLE_HELP
|
#ifndef DISABLE_HELP
|
||||||
const char *help; /* Help file entry text */
|
const char *help; /* Help file entry text. */
|
||||||
#endif
|
#endif
|
||||||
struct shortcut *next;
|
struct shortcut *next;
|
||||||
} shortcut;
|
} shortcut;
|
||||||
|
|
||||||
#ifndef NANO_SMALL
|
#ifndef NANO_SMALL
|
||||||
typedef struct toggle {
|
typedef struct toggle {
|
||||||
int val; /* Sequence to toggle the key. Should only need 1 */
|
int val; /* Sequence to toggle the key. Should only need
|
||||||
|
* one. */
|
||||||
const char *desc; /* Description for when toggle is, uh, toggled,
|
const char *desc; /* Description for when toggle is, uh, toggled,
|
||||||
e.g. "Pico Messages"; we'll append Enabled or
|
e.g. "Pico Messages"; we'll append Enabled or
|
||||||
Disabled */
|
Disabled. */
|
||||||
int flag; /* What flag actually gets toggled */
|
int flag; /* What flag actually gets toggled. */
|
||||||
struct toggle *next;
|
struct toggle *next;
|
||||||
} toggle;
|
} toggle;
|
||||||
#endif /* !NANO_SMALL */
|
#endif /* !NANO_SMALL */
|
||||||
|
@ -235,8 +245,10 @@ typedef struct historytype {
|
||||||
char *data;
|
char *data;
|
||||||
} historytype;
|
} historytype;
|
||||||
typedef struct historyheadtype {
|
typedef struct historyheadtype {
|
||||||
struct historytype *next; /* keep *next and *prev members together */
|
struct historytype *next; /* Keep *next and *prev members
|
||||||
struct historytype *prev; /* and in same order as in historytype */
|
* together. */
|
||||||
|
struct historytype *prev; /* And in same order as in
|
||||||
|
* historytype. */
|
||||||
struct historytype *tail;
|
struct historytype *tail;
|
||||||
struct historytype *current;
|
struct historytype *current;
|
||||||
int count;
|
int count;
|
||||||
|
@ -244,8 +256,8 @@ typedef struct historyheadtype {
|
||||||
} historyheadtype;
|
} historyheadtype;
|
||||||
#endif /* !NANO_SMALL */
|
#endif /* !NANO_SMALL */
|
||||||
|
|
||||||
/* Bitwise flags so we can save space (or more correctly, not waste it) */
|
/* Bitwise flags so we can save space (or more correctly, not waste
|
||||||
|
* it). */
|
||||||
#define MODIFIED (1<<0)
|
#define MODIFIED (1<<0)
|
||||||
#define KEEP_CUTBUFFER (1<<1)
|
#define KEEP_CUTBUFFER (1<<1)
|
||||||
#define CASE_SENSITIVE (1<<2)
|
#define CASE_SENSITIVE (1<<2)
|
||||||
|
@ -267,7 +279,7 @@ typedef struct historyheadtype {
|
||||||
#define DOS_FILE (1<<18)
|
#define DOS_FILE (1<<18)
|
||||||
#define MAC_FILE (1<<19)
|
#define MAC_FILE (1<<19)
|
||||||
#define SMOOTHSCROLL (1<<20)
|
#define SMOOTHSCROLL (1<<20)
|
||||||
#define DISABLE_CURPOS (1<<21) /* Damn, we still need it */
|
#define DISABLE_CURPOS (1<<21) /* Damn, we still need it. */
|
||||||
#define REBIND_DELETE (1<<22)
|
#define REBIND_DELETE (1<<22)
|
||||||
#define NO_CONVERT (1<<23)
|
#define NO_CONVERT (1<<23)
|
||||||
#define BACKUP_FILE (1<<24)
|
#define BACKUP_FILE (1<<24)
|
||||||
|
@ -278,8 +290,7 @@ typedef struct historyheadtype {
|
||||||
#define HISTORYLOG (1<<29)
|
#define HISTORYLOG (1<<29)
|
||||||
#define JUSTIFY_MODE (1<<30)
|
#define JUSTIFY_MODE (1<<30)
|
||||||
|
|
||||||
/* Control key sequences, changing these would be very very bad */
|
/* Control key sequences, changing these would be very very bad. */
|
||||||
|
|
||||||
#define NANO_CONTROL_SPACE 0
|
#define NANO_CONTROL_SPACE 0
|
||||||
#define NANO_CONTROL_A 1
|
#define NANO_CONTROL_A 1
|
||||||
#define NANO_CONTROL_B 2
|
#define NANO_CONTROL_B 2
|
||||||
|
@ -347,13 +358,13 @@ typedef struct historyheadtype {
|
||||||
#define NANO_ALT_RBRACKET ']'
|
#define NANO_ALT_RBRACKET ']'
|
||||||
#define NANO_ALT_SPACE ' '
|
#define NANO_ALT_SPACE ' '
|
||||||
|
|
||||||
/* Some semi-changeable keybindings; don't play with unless you're sure
|
/* Some semi-changeable keybindings; don't play with these unless you're
|
||||||
you know what you're doing */
|
* sure you know what you're doing. */
|
||||||
|
|
||||||
/* No key at all. */
|
/* No key at all. */
|
||||||
#define NANO_NO_KEY -8
|
#define NANO_NO_KEY -8
|
||||||
|
|
||||||
/* Special sentinel key. */
|
/* Special sentinel key used for search string history. */
|
||||||
#define NANO_HISTORY_KEY -9
|
#define NANO_HISTORY_KEY -9
|
||||||
|
|
||||||
/* Normal keys. */
|
/* Normal keys. */
|
||||||
|
@ -453,18 +464,18 @@ typedef enum {
|
||||||
TOP, CENTER, NONE
|
TOP, CENTER, NONE
|
||||||
} topmidnone;
|
} topmidnone;
|
||||||
|
|
||||||
/* Minimum editor window rows required for nano to work correctly */
|
/* Minimum editor window rows required for nano to work correctly. */
|
||||||
#define MIN_EDITOR_ROWS 3
|
#define MIN_EDITOR_ROWS 3
|
||||||
|
|
||||||
/* Minimum editor window cols required for nano to work correctly */
|
/* Minimum editor window cols required for nano to work correctly. */
|
||||||
#define MIN_EDITOR_COLS 10
|
#define MIN_EDITOR_COLS 10
|
||||||
|
|
||||||
/* Default number of characters from end-of-line where text wrapping
|
/* Default number of characters from end-of-line where text wrapping
|
||||||
occurs */
|
* occurs. */
|
||||||
#define CHARS_FROM_EOL 8
|
#define CHARS_FROM_EOL 8
|
||||||
|
|
||||||
/* Maximum number of search history strings saved, same value used for
|
/* Maximum number of search history strings saved, same value used for
|
||||||
replace history */
|
* replace history. */
|
||||||
#define MAX_SEARCH_HISTORY 100
|
#define MAX_SEARCH_HISTORY 100
|
||||||
|
|
||||||
#endif /* !NANO_H */
|
#endif /* !NANO_H */
|
||||||
|
|
|
@ -140,8 +140,7 @@ void update_color(void);
|
||||||
/* Public functions in cut.c */
|
/* Public functions in cut.c */
|
||||||
filestruct *get_cutbottom(void);
|
filestruct *get_cutbottom(void);
|
||||||
void add_to_cutbuffer(filestruct *inptr);
|
void add_to_cutbuffer(filestruct *inptr);
|
||||||
void cut_marked_segment(filestruct *top, size_t top_x, filestruct *bot,
|
void cut_marked_segment(void);
|
||||||
size_t bot_x, int destructive);
|
|
||||||
int do_cut_text(void);
|
int do_cut_text(void);
|
||||||
int do_uncut_text(void);
|
int do_uncut_text(void);
|
||||||
|
|
||||||
|
@ -207,7 +206,7 @@ void sc_init_one(shortcut **shortcutage, int key, const char *desc,
|
||||||
#ifndef DISABLE_HELP
|
#ifndef DISABLE_HELP
|
||||||
const char *help,
|
const char *help,
|
||||||
#endif
|
#endif
|
||||||
int alt, int func_key, int misc, int view, int (*func) (void));
|
int meta, int func_key, int misc, int view, int (*func) (void));
|
||||||
#ifndef NANO_SMALL
|
#ifndef NANO_SMALL
|
||||||
void toggle_init_one(int val, const char *desc, int flag);
|
void toggle_init_one(int val, const char *desc, int flag);
|
||||||
void toggle_init(void);
|
void toggle_init(void);
|
||||||
|
|
16
src/winio.c
16
src/winio.c
|
@ -1090,12 +1090,12 @@ int nanogetstr(int allowtabs, const char *buf, const char *def,
|
||||||
fprintf(stderr, "Aha! \'%c\' (%d)\n", kbinput,
|
fprintf(stderr, "Aha! \'%c\' (%d)\n", kbinput,
|
||||||
kbinput);
|
kbinput);
|
||||||
#endif
|
#endif
|
||||||
if (meta == 1 && kbinput == t->altval)
|
if (meta == 1 && (kbinput == t->metaval || kbinput == t->misc))
|
||||||
/* We hit an Alt key. Do like above. We don't
|
/* We hit a Meta key. Do like above. We don't
|
||||||
just ungetch() the letter and let it get
|
* just ungetch() the letter and let it get
|
||||||
caught above cause that screws the
|
* caught above cause that screws the
|
||||||
keypad... */
|
* keypad... */
|
||||||
return t->altval;
|
return kbinput;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_cntrl_char(kbinput))
|
if (is_cntrl_char(kbinput))
|
||||||
|
@ -1223,8 +1223,8 @@ void bottombars(const shortcut *s)
|
||||||
strcpy(keystr, "^?");
|
strcpy(keystr, "^?");
|
||||||
else
|
else
|
||||||
sprintf(keystr, "^%c", s->val + 64);
|
sprintf(keystr, "^%c", s->val + 64);
|
||||||
} else if (s->altval != NANO_NO_KEY)
|
} else if (s->metaval != NANO_NO_KEY)
|
||||||
sprintf(keystr, "M-%c", toupper(s->altval));
|
sprintf(keystr, "M-%c", toupper(s->metaval));
|
||||||
|
|
||||||
onekey(keystr, s->desc, COLS / numcols);
|
onekey(keystr, s->desc, COLS / numcols);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue