overhaul the cutting and uncutting routines and the justify-related

routines to back up and restore unjustified text to use the partitioning
code, as it greatly simplifies how they work; also back up and restore
unjustified text in its own buffer instead of the cutbuffer, and add a
few minor bug fixes to the overhauled routines


git-svn-id: svn://svn.savannah.gnu.org/nano/trunk/nano@2124 35c25a1d-7b9e-4130-9fde-d3aeb78583b8
master
David Lawrence Ramsey 2004-11-23 04:08:28 +00:00
parent b5a7a5a2d6
commit 93c8405bfa
8 changed files with 446 additions and 511 deletions

View File

@ -1,7 +1,40 @@
CVS code -
- General:
- Overhaul the cutting and uncutting routines to use the
partitioning code, as it greatly simplifies how they work.
New functions move_to_filestruct(), copy_from_filestruct(),
cut_line(), cut_marked(), and cut_to_eol(); changes to
add_to_cutbuffer(), do_cut_text(), do_uncut_text(), etc.;
removal of functions get_cutbottom(), add_to_cutbuffer(), and
cut_marked_segment(). (DLR)
- Overhaul the justify-related routines to back up and restore
unjustified text to use the partitioning code, as it greatly
simplifies how they work, and to store such text in its own
buffer rather than the cutbuffer. Changes to backup_lines(),
do_justify(), etc. (DLR)
- cut.c:
do_uncut_text()
- No longer duplicate Pico's adding an extra magicline to the
file if uncutting leaves the cursor on the current one, as
it's actually a bug. (DLR)
- global.c:
thanks_for_all_the_fish()
- Free the justify buffer if it isn't empty. (DLR)
- nano.c:
handle_sigwinch()
- If the justify buffer isn't empty, blow it away and don't
display "UnJustify" in the shortcut list anymore. (DLR)
do_wrap()
- Make wrap_loc and word_back ssize_t's, to match fill. (DLR)
do_justify()
- For consistency, preserve placewewant if we didn't unjustify
instead of setting it to 0. (DLR)
- winio.c:
get_edit_input()
- Remove parameter allow_funcs, as it was only needed as a
workaround for when justified text was stored in the cutbuffer
and the cut shortcut was hit at the "Can now UnJustify!"
prompt. (DLR)
GNU nano 1.3.5 - 2004.11.22
- General:

467
src/cut.c
View File

@ -32,12 +32,6 @@
static bool keep_cutbuffer = FALSE;
/* Should we keep the contents of the cutbuffer? */
static cut_type marked_cut = CUT_LINE;
/* What type of cut is in the cutbuffer? */
#ifndef NANO_SMALL
static bool concatenate_cut = FALSE;
/* Should we add this cut string to the end of the last one? */
#endif
static filestruct *cutbottom = NULL;
/* Pointer to end of cutbuffer. */
@ -46,444 +40,133 @@ void cutbuffer_reset(void)
keep_cutbuffer = FALSE;
}
filestruct *get_cutbottom(void)
/* If we're not on the magicline, move all the text of the current line,
* plus the newline at the end, to the cutbuffer. */
void cut_line(void)
{
return cutbottom;
}
void add_to_cutbuffer(filestruct *inptr, bool allow_concat)
{
#ifdef DEBUG
fprintf(stderr, "add_to_cutbuffer(): inptr->data = %s\n", inptr->data);
#endif
if (cutbuffer == NULL)
cutbuffer = inptr;
#ifndef NANO_SMALL
else if (allow_concat && concatenate_cut) {
/* If allow_concat is TRUE and we're concatenating, tack the
* text in inptr onto the text in cutbottom. */
cutbottom->data = charealloc(cutbottom->data,
strlen(cutbottom->data) + strlen(inptr->data) + 1);
strcat(cutbottom->data, inptr->data);
return;
}
#endif
else {
cutbottom->next = inptr;
inptr->prev = cutbottom;
}
cutbottom = inptr;
cutbottom->next = NULL;
if (current->next != NULL)
move_to_filestruct(&cutbuffer, &cutbottom, current, 0,
current->next, 0);
}
#ifndef NANO_SMALL
/* Cut a marked segment instead of a whole line.
*
* The first cut character is top->data[top_x]. Unless top == bot, the
* last cut line has length bot_x. That is, if bot_x > 0 then we cut to
* bot->data[bot_x - 1].
*
* We maintain totsize, totlines, filebot, the magicline, and line
* numbers. Also, we set current and current_x so the cursor will be on
* the first character after what was cut. We do not do any screen
* updates.
*
* Note cutbuffer might not be NULL if cut to end is used. */
void cut_marked_segment(void)
/* Move all currently marked text to the cutbuffer, and set the current
* place we want to where the text used to start. */
void cut_marked(void)
{
filestruct *top;
filestruct *bot;
filestruct *tmp;
size_t top_x;
size_t bot_x;
size_t newsize;
filestruct *top, *bot;
size_t top_x, bot_x;
/* If the mark doesn't cover any text, get out. */
if (current == mark_beginbuf && current_x == mark_beginx)
return;
assert(current != NULL && mark_beginbuf != NULL);
/* Set up the top and bottom lines and coordinates of the marked
* text. */
mark_order((const filestruct **)&top, &top_x,
(const filestruct **)&bot, &bot_x, NULL);
(const filestruct **)&bot, &bot_x, NULL);
/* Make the first cut line manually. Move the cut part of the top
* line into tmp, and set newsize to that partial line's length. */
tmp = copy_node(top);
newsize = (top == bot ? bot_x - top_x : strlen(top->data + top_x));
charmove(tmp->data, tmp->data + top_x, newsize);
null_at(&tmp->data, newsize);
/* Add the contents of tmp to the cutbuffer. Note that cutbuffer
* might be non-NULL if we have cut to end enabled. */
if (cutbuffer == NULL) {
cutbuffer = tmp;
cutbottom = tmp;
} else {
if (concatenate_cut) {
/* If we're concatenating, tack the text in the first line
* of tmp onto the text in the bottom of the cutbuffer, and
* move tmp one line down to where its next line begins. */
cutbottom->data = charealloc(cutbottom->data,
strlen(cutbottom->data) + strlen(tmp->data) + 1);
strcat(cutbottom->data, tmp->data);
tmp = tmp->next;
}
/* Put tmp on the line after the bottom of the cutbuffer. */
cutbottom->next = tmp;
if (!concatenate_cut) {
/* Tf we're not concatenating, attach tmp to the bottom of
* the cutbuffer, and then move the bottom of the cutbuffer
* one line down to where tmp is. */
tmp->prev = cutbottom;
cutbottom = tmp;
}
}
/* 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) {
/* 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
dump_buffer(cutbuffer);
#endif
return;
}
/* Update totsize to account for the cut part of the last line. */
totsize -= bot_x + 1;
/* Here, the top remainder line might get longer (if the bottom
* remainder line is added to the end of it), so we realloc() it
* first. */
top->data = charealloc(top->data, newsize);
charmove(top->data + top_x, bot->data + bot_x, newsize - top_x);
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. */
null_at(&bot->data, bot_x);
/* Move the rest of the cut text (other than the cut part of the top
* line) from the buffer to the end of the cutbuffer, and fix the
* edit buffer to account for the cut text. */
top->next = bot->next;
cutbottom = bot;
cutbottom->next = NULL;
if (top->next != NULL)
top->next->prev = top;
renumber(top);
current = top;
/* 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
dump_buffer(cutbuffer);
#endif
move_to_filestruct(&cutbuffer, &cutbottom, top, top_x, bot, bot_x);
placewewant = xplustabs();
}
#endif
/* If we're not at the end of the current line, move all the text from
* the current cursor position to the end of the current line,
* not counting the newline at the end, to the cutbuffer. If we are,
* and we're not on the magicline, move the newline at the end to the
* cutbuffer, and set the current place we want to where the newline
* used to be. */
void cut_to_eol(void)
{
size_t data_len = strlen(current->data);
assert(current_x <= data_len);
if (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, to the cutbuffer. */
move_to_filestruct(&cutbuffer, &cutbottom, current, current_x,
current, data_len);
else if (current->next != NULL) {
/* If we're at the end of the line, and the next line isn't the
* magicline, move all the text from the current position up to
* the beginning of the next line, i.e, the newline at the
* end, to the cutbuffer. */
move_to_filestruct(&cutbuffer, &cutbottom, current, current_x,
current->next, 0);
placewewant = xplustabs();
}
}
/* Move text from the current filestruct into the cutbuffer. */
void do_cut_text(void)
{
filestruct *fileptr;
assert(current != NULL && current->data != NULL);
check_statusblank();
/* If keep_cutbuffer is FALSE, blow away the text in the
* cutbuffer. */
if (!keep_cutbuffer) {
free_filestruct(cutbuffer);
cutbuffer = NULL;
marked_cut = CUT_LINE;
#ifndef NANO_SMALL
concatenate_cut = FALSE;
#endif
#ifdef DEBUG
fprintf(stderr, "Blew away cutbuffer =)\n");
#endif
}
/* You can't cut the magicline except with the mark. But trying
* does clear the cutbuffer if keep_cutbuffer is FALSE. */
if (current == filebot
#ifndef NANO_SMALL
&& !ISSET(MARK_ISSET)
#endif
)
return;
/* Set keep_cutbuffer to TRUE, so that the text we're going to move
* into the cutbuffer will be added to the text already in the
* cutbuffer instead of replacing it. */
keep_cutbuffer = TRUE;
#ifndef NANO_SMALL
if (ISSET(CUT_TO_END) && !ISSET(MARK_ISSET)) {
assert(current_x <= strlen(current->data));
if (current->data[current_x] == '\0') {
/* If the line is empty and we didn't just cut a non-blank
* line, create a dummy blank line and add it to the
* cutbuffer. */
if (marked_cut != CUT_MARKED && current->next != filebot) {
filestruct *junk = make_new_node(current);
junk->data = mallocstrcpy(NULL, "");
add_to_cutbuffer(junk, TRUE);
#ifdef DEBUG
dump_buffer(cutbuffer);
#endif
}
do_delete();
marked_cut = CUT_TO_EOL;
return;
} else {
SET(MARK_ISSET);
mark_beginx = strlen(current->data);
mark_beginbuf = current;
}
}
if (ISSET(MARK_ISSET)) {
cut_marked_segment();
placewewant = xplustabs();
/* If the mark is on, move the marked text to the cutbuffer and
* turn the mark off. */
cut_marked();
UNSET(MARK_ISSET);
} else
#endif
if (ISSET(CUT_TO_END))
/* Otherwise, if the CUT_TO_END flag is set, move all text up to
* the end of the line into the cutbuffer. */
cut_to_eol();
else
/* Otherwise, move the entire line into the cutbuffer. */
cut_line();
marked_cut = CUT_MARKED;
concatenate_cut = TRUE;
edit_refresh();
set_modified();
edit_refresh();
set_modified();
return;
}
#endif /* !NANO_SMALL */
totlines--;
totsize -= strlen(current->data) + 1;
fileptr = current;
current = current->next;
current->prev = fileptr->prev;
add_to_cutbuffer(fileptr, TRUE);
#ifdef DEBUG
dump_buffer(cutbuffer);
#endif
if (fileptr == fileage)
fileage = current;
else
current->prev->next = current;
if (fileptr == edittop)
edittop = current;
renumber(current);
current_x = 0;
edit_refresh();
set_modified();
marked_cut = CUT_LINE;
#ifndef NANO_SMALL
concatenate_cut = FALSE;
#endif
}
/* Copy text from the cutbuffer into the current filestruct. */
void do_uncut_text(void)
{
filestruct *tmp = current;
filestruct *newbuf = NULL;
filestruct *newend = NULL;
assert(current != NULL && current->data != NULL);
#ifndef DISABLE_WRAPPING
wrap_reset();
#endif
check_statusblank();
if (cutbuffer == NULL || current == NULL)
return; /* AIEEEEEEEEEEEE */
/* 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
* beginning of the line, set placewewant to 0. Pico does both of
* these. */
if (marked_cut == CUT_LINE) {
if (current_x > 0)
marked_cut = CUT_TO_EOL;
else
placewewant = 0;
}
/* If we're going to uncut on the magicline, always make a new
* magicline in advance, as Pico does. */
if (current->next == NULL)
new_magicline();
if (marked_cut == CUT_LINE || cutbuffer->next != NULL) {
newbuf = copy_filestruct(cutbuffer);
for (newend = newbuf; newend->next != NULL && newend != NULL;
newend = newend->next)
totlines++;
}
/* Hook newbuf in at current. */
if (marked_cut != CUT_LINE) {
filestruct *hold = current;
/* If there's only one line in the cutbuffer... */
if (cutbuffer->next == NULL) {
size_t buf_len = strlen(cutbuffer->data);
size_t cur_len = strlen(current->data);
current->data = charealloc(current->data, cur_len +
buf_len + 1);
charmove(current->data + current_x + buf_len,
current->data + current_x, cur_len - current_x + 1);
strncpy(current->data + current_x, cutbuffer->data,
buf_len);
/* Use strncpy() to not copy the null terminator. */
current_x += buf_len;
totsize += buf_len;
placewewant = xplustabs();
} else { /* Yuck -- no kidding! */
char *tmpstr, *tmpstr2;
tmp = current->next;
/* New beginning. */
tmpstr = charalloc(current_x + strlen(newbuf->data) + 1);
strncpy(tmpstr, current->data, current_x);
strcpy(&tmpstr[current_x], newbuf->data);
totsize += strlen(newbuf->data) + strlen(newend->data) + 1;
/* New end. */
tmpstr2 = charalloc(strlen(newend->data) +
strlen(&current->data[current_x]) + 1);
strcpy(tmpstr2, newend->data);
strcat(tmpstr2, &current->data[current_x]);
free(current->data);
current->data = tmpstr;
current->next = newbuf->next;
newbuf->next->prev = current;
delete_node(newbuf);
current_x = strlen(newend->data);
placewewant = xplustabs();
free(newend->data);
newend->data = tmpstr2;
newend->next = tmp;
/* If tmp isn't NULL, we're in the middle: update the
* prev pointer. If it IS NULL, we're at the end; update
* the filebot pointer. */
if (tmp != NULL)
tmp->prev = newend;
else {
filebot = newend;
new_magicline();
}
/* Recalculate current_y and totsize. */
for (tmp = current->next; tmp != newend; tmp = tmp->next) {
current_y++;
totsize += strlen(tmp->data) + 1;
}
current = newend;
}
/* If we're doing a cut to end, 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. */
if (marked_cut == CUT_TO_EOL) {
tmp = make_new_node(current);
tmp->data = mallocstrcpy(NULL, current->data + current_x);
splice_node(current, tmp, current->next);
null_at(&current->data, current_x);
current = current->next;
current_x = 0;
placewewant = 0;
/* Extra line added; update stuff. */
totlines++;
totsize++;
}
/* Renumber from BEFORE where we pasted ;) */
renumber(hold);
#ifdef DEBUG
dump_buffer(fileage);
dump_buffer(cutbuffer);
#endif
set_modified();
edit_refresh();
/* If the cutbuffer is empty, get out. */
if (cutbuffer == NULL)
return;
}
if (current != fileage) {
tmp = current->prev;
tmp->next = newbuf;
newbuf->prev = tmp;
} else
fileage = newbuf;
/* Add a copy of the text in the cutbuffer to the current filestruct
* at the current cursor position. */
copy_from_filestruct(cutbuffer, cutbottom);
totlines++; /* Unmarked uncuts don't split lines. */
/* Set the current place we want to where the text from the
* cutbuffer ends. */
placewewant = xplustabs();
/* This is so uncutting at the top of the buffer will work => */
if (current_y == 0)
edittop = newbuf;
/* Connect the end of the buffer to the filestruct. */
newend->next = current;
current->prev = newend;
/* Recalculate current_y and totsize. */
for (tmp = newbuf; tmp != current; tmp = tmp->next) {
current_y++;
totsize += strlen(tmp->data) + 1;
}
renumber(newbuf);
edit_refresh();
set_modified();
#ifdef DEBUG
dump_buffer_reverse();
#endif
set_modified();
}

View File

@ -63,6 +63,9 @@ filestruct *edittop = NULL; /* Pointer to the top of the edit
file struct */
filestruct *filebot = NULL; /* Last node in the file struct */
filestruct *cutbuffer = NULL; /* A place to store cut text */
#ifndef DISABLE_JUSTIFY
filestruct *jusbuffer = NULL; /* A place to store unjustified text */
#endif
partition *filepart = NULL; /* A place to store a portion of the
file struct */
@ -1160,7 +1163,10 @@ void thanks_for_all_the_fish(void)
free(answer);
if (cutbuffer != NULL)
free_filestruct(cutbuffer);
#ifndef DISABLE_JUSTIFY
if (jusbuffer != NULL)
free_filestruct(jusbuffer);
#endif
free_shortcutage(&main_list);
free_shortcutage(&whereis_list);
free_shortcutage(&replace_list);

View File

@ -78,6 +78,11 @@ static int pid; /* The PID of the newly forked process
* it. */
#endif
#ifndef DISABLE_JUSTIFY
static filestruct *jusbottom = NULL;
/* Pointer to end of justify buffer. */
#endif
/* What we do when we're all set to exit. */
void finish(void)
{
@ -714,6 +719,169 @@ void unpartition_filestruct(partition **p)
*p = NULL;
}
/* Move all the text between (top, top_x) and (bot, bot_x) in the
* current filestruct to a filestruct beginning with file_top and ending
* with file_bot. If no text is between (top, top_x) and (bot, bot_x),
* don't do anything. */
void move_to_filestruct(filestruct **file_top, filestruct **file_bot,
filestruct *top, size_t top_x, filestruct *bot, size_t bot_x)
{
filestruct *top_save;
long part_totsize;
bool at_edittop;
#ifndef NANO_SMALL
bool mark_inside = FALSE;
#endif
assert(file_top != NULL && file_bot != NULL && top != NULL && bot != NULL);
/* If (top, top_x)-(bot, bot_x) doesn't cover any text, get out. */
if (top == bot && top_x == bot_x)
return;
/* Partition the filestruct so that it contains only the text from
* (top, top_x) to (bot, bot_x), keep track of whether the top of
* the partition is the top of the edit window, and keep track of
* whether the mark begins inside the partition. */
filepart = partition_filestruct(top, top_x, bot, bot_x);
at_edittop = (fileage == edittop);
#ifndef NANO_SMALL
if (ISSET(MARK_ISSET))
mark_inside = (mark_beginbuf->lineno >= fileage->lineno &&
mark_beginbuf->lineno <= filebot->lineno &&
(mark_beginbuf != fileage || mark_beginx >= top_x) &&
(mark_beginbuf != filebot || mark_beginx <= bot_x));
#endif
/* Get the number of characters in the text, and subtract it from
* totsize. */
get_totals(top, bot, NULL, &part_totsize);
totsize -= part_totsize;
if (*file_top == NULL) {
/* If file_top is empty, just move all the text directly into
* it. This is equivalent to tacking the text in top onto the
* (lack of) text at the end of file_top. */
*file_top = fileage;
*file_bot = filebot;
} else {
/* Otherwise, tack the text in top onto the text at the end of
* file_bot. */
(*file_bot)->data = charealloc((*file_bot)->data,
strlen((*file_bot)->data) + strlen(fileage->data) + 1);
strcat((*file_bot)->data, fileage->data);
/* Attach the line after top to the line after file_bot. Then,
* if there's more than one line after top, move file_bot down
* to bot. */
(*file_bot)->next = fileage->next;
if ((*file_bot)->next != NULL) {
(*file_bot)->next->prev = *file_bot;
*file_bot = filebot;
}
}
/* Since the text has now been saved, remove it from the filestruct.
* If the top of the partition was the top of the edit window, set
* edittop to where the text used to start. If the mark began
* inside the partition, set the beginning of the mark to where the
* text used to start. */
fileage = (filestruct *)nmalloc(sizeof(filestruct));
fileage->data = mallocstrcpy(NULL, "");
filebot = fileage;
if (at_edittop)
edittop = fileage;
#ifndef NANO_SMALL
if (mark_inside) {
mark_beginbuf = fileage;
mark_beginx = top_x;
}
#endif
/* Restore the current line and cursor position. */
current = fileage;
current_x = top_x;
top_save = fileage;
/* Unpartition the filestruct so that it contains all the text
* again, minus the saved text. */
unpartition_filestruct(&filepart);
/* Renumber starting with the beginning line of the old
* partition. */
renumber(top_save);
if (filebot->data[0] != '\0')
new_magicline();
/* Set totlines to the new number of lines in the file. */
totlines = filebot->lineno;
}
/* Copy all the text from the filestruct beginning with file_top and
* ending with file_bot to the current filestruct at the current cursor
* position. */
void copy_from_filestruct(filestruct *file_top, filestruct *file_bot)
{
filestruct *top_save;
int part_totlines;
long part_totsize;
bool at_edittop;
assert(file_top != NULL && file_bot != NULL);
/* Partition the filestruct so that it contains no text, and keep
* track of whether the top of the partition is the top of the edit
* window. */
filepart = partition_filestruct(current, current_x, current,
current_x);
at_edittop = (fileage == edittop);
/* Put the top and bottom of the filestruct at copies of file_top
* and file_bot. */
fileage = copy_filestruct(file_top);
filebot = fileage;
while (filebot->next != NULL)
filebot = filebot->next;
/* Restore the current line and cursor position. */
current = filebot;
current_x = strlen(filebot->data);
if (fileage == filebot)
current_x += strlen(filepart->top_data);
/* Get the number of lines and the number of characters in the saved
* text, and add the latter to totsize. */
get_totals(fileage, filebot, &part_totlines, &part_totsize);
totsize += part_totsize;
/* If the top of the partition was the top of the edit window, set
* edittop to where the saved text now starts, and update the
* current y-coordinate to account for the number of lines it
* has, less one since the first line will be tacked onto the
* current line. */
if (at_edittop)
edittop = fileage;
current_y += part_totlines - 1;
top_save = fileage;
/* Unpartition the filestruct so that it contains all the text
* again, minus the saved text. */
unpartition_filestruct(&filepart);
/* Renumber starting with the beginning line of the old
* partition. */
renumber(top_save);
if (filebot->data[0] != '\0')
new_magicline();
/* Set totlines to the new number of lines in the file. */
totlines = filebot->lineno;
}
void renumber_all(void)
{
filestruct *temp;
@ -2342,39 +2510,69 @@ void do_para_end(void)
edit_redraw(old_current, old_pww);
}
/* Put the next par_len lines, starting with first_line, in the
* cutbuffer, not allowing them to be concatenated. We assume there
* are enough lines after first_line. We leave copies of the lines in
* place, too. We return the new copy of first_line. */
/* Put the next par_len lines, starting with first_line, into the
* justify buffer, leaving copies of those lines in place. Assume there
* are enough lines after first_line. Return the new copy of
* first_line. */
filestruct *backup_lines(filestruct *first_line, size_t par_len, size_t
quote_len)
{
/* We put the original lines, not copies, into the cutbuffer, just
* out of a misguided sense of consistency, so if you uncut, you get
* the actual same paragraph back, not a copy. */
filestruct *alice = first_line;
set_modified();
cutbuffer = NULL;
for (; par_len > 0; par_len--) {
filestruct *bob = copy_node(alice);
if (alice == first_line)
first_line = bob;
if (alice == current)
current = bob;
if (alice == edittop)
edittop = bob;
filestruct *top = first_line;
/* The top of the paragraph we're backing up. */
filestruct *bot = first_line;
/* The bottom of the paragraph we're backing up. */
size_t i;
/* Generic loop variable. */
size_t current_x_save = current_x;
int fl_lineno_save = first_line->lineno;
int edittop_lineno_save = edittop->lineno;
int current_lineno_save = current->lineno;
#ifndef NANO_SMALL
if (alice == mark_beginbuf)
mark_beginbuf = bob;
bool old_mark_set = ISSET(MARK_ISSET);
int mbb_lineno_save = 0;
if (old_mark_set)
mbb_lineno_save = mark_beginbuf->lineno;
#endif
assert(alice != NULL && bob != NULL);
add_to_cutbuffer(alice, FALSE);
splice_node(bob->prev, bob, bob->next);
alice = bob->next;
/* Move bot down par_len lines to the newline after the last line of
* the paragraph. */
for (i = par_len; i > 0; i--)
bot = bot->next;
/* Move the paragraph from the main filestruct to the justify
* buffer. */
move_to_filestruct(&jusbuffer, &jusbottom, top, 0, bot, 0);
/* Copy the paragraph from the justify buffer to the main
* filestruct. */
copy_from_filestruct(jusbuffer, jusbottom);
/* Move upward from the last line of the paragraph to the first
* line, putting first_line, edittop, current, and mark_beginbuf at
* the same lines in the copied paragraph that they had in the
* original paragraph. */
top = current->prev;
for (i = par_len; i > 0; i--) {
if (top->lineno == fl_lineno_save)
first_line = top;
if (top->lineno == edittop_lineno_save)
edittop = top;
if (top->lineno == current_lineno_save)
current = top;
#ifndef NANO_SMALL
if (old_mark_set && top->lineno == mbb_lineno_save)
mark_beginbuf = top;
#endif
top = top->prev;
}
/* Put current_x at the same place in the copied paragraph that it
* had in the original paragraph. */
current_x = current_x_save;
set_modified();
return first_line;
}
@ -2561,13 +2759,10 @@ void do_justify(bool full_justify)
{
filestruct *first_par_line = NULL;
/* Will be the first line of the resulting justified paragraph.
* For restoring after uncut. */
* For restoring after unjustify. */
filestruct *last_par_line;
/* Will be the last line of the result, also for uncut. */
filestruct *cutbuffer_save = cutbuffer;
/* When the paragraph gets modified, all lines from the changed
* one down are stored in the cutbuffer. We back up the
* original to restore it later. */
/* Will be the line containing the newline after the last line
* of the result. Also for restoring after unjustify. */
bool allow_respacing;
/* Whether we should change the spacing at the end of a line
* after justifying it. This should be TRUE whenever we move
@ -2611,10 +2806,7 @@ void do_justify(bool full_justify)
* get out. */
if (do_para_search(&quote_len, &par_len)) {
if (full_justify) {
/* This should be safe in the event of filebot->prev's
* being NULL, since only last_par_line->next is used if
* we eventually unjustify. */
last_par_line = filebot->prev;
last_par_line = filebot;
break;
} else {
edit_refresh();
@ -2641,7 +2833,7 @@ void do_justify(bool full_justify)
quote_len);
/* If we haven't already done it, copy the original
* paragraph to the cutbuffer for unjustification. */
* paragraph to the justify buffer. */
if (first_par_line == NULL)
first_par_line = backup_lines(current, full_justify ?
filebot->lineno - current->lineno : par_len,
@ -2829,7 +3021,7 @@ void do_justify(bool full_justify)
* fileage, and renumber() since edit_refresh() needs the line
* numbers to be right (but only do the last two if we actually
* justified something). */
last_par_line = current->prev;
last_par_line = current;
if (first_par_line != NULL) {
if (first_par_line->prev == NULL)
fileage = first_par_line;
@ -2846,53 +3038,65 @@ void do_justify(bool full_justify)
/* Now get a keystroke and see if it's unjustify; if not, unget the
* keystroke and return. */
kbinput = get_edit_input(&meta_key, &func_key, FALSE);
kbinput = get_edit_input(&meta_key, &func_key);
if (!meta_key && !func_key && kbinput == NANO_UNJUSTIFY_KEY) {
/* Restore the justify we just did (ungrateful user!). */
filestruct *cutbottom = get_cutbottom();
current = current_save;
current_x = current_x_save;
current_y = current_y_save;
edittop = edittop_save;
/* Splice the cutbuffer back into the file, but only if we
/* Splice the justify buffer back into the file, but only if we
* actually justified something. */
if (first_par_line != NULL) {
cutbottom->next = last_par_line->next;
cutbottom->next->prev = cutbottom;
/* The line numbers after the end of the paragraph have been
* changed, so we change them back. */
renumber(cutbottom->next);
if (first_par_line->prev != NULL) {
cutbuffer->prev = first_par_line->prev;
cutbuffer->prev->next = cutbuffer;
} else
fileage = cutbuffer;
filestruct *bot_save;
last_par_line->next = NULL;
free_filestruct(first_par_line);
}
/* Partition the filestruct so that it contains only the
* text of the justified paragraph. */
filepart = partition_filestruct(first_par_line, 0,
last_par_line, 0);
/* Restore global variables from before the justify. */
totsize = totsize_save;
totlines = filebot->lineno;
/* Remove the text of the justified paragraph, and
* put the text in the justify buffer in its place. */
free_filestruct(fileage);
fileage = jusbuffer;
filebot = jusbottom;
bot_save = filebot;
/* Unpartition the filestruct so that it contains all the
* text again. Note that the justified paragraph has been
* replaced with the unjustified paragraph. */
unpartition_filestruct(&filepart);
/* Renumber starting with the ending line of the old
* partition. */
if (bot_save->next != NULL)
renumber(bot_save->next);
/* Restore global variables from before the justify. */
totsize = totsize_save;
totlines = filebot->lineno;
#ifndef NANO_SMALL
mark_beginbuf = mark_beginbuf_save;
mark_beginx = mark_beginx_save;
mark_beginbuf = mark_beginbuf_save;
mark_beginx = mark_beginx_save;
#endif
flags = flags_save;
if (!ISSET(MODIFIED))
titlebar(NULL);
edit_refresh();
flags = flags_save;
/* Clear the justify buffer. */
jusbuffer = NULL;
if (!ISSET(MODIFIED))
titlebar(NULL);
edit_refresh();
}
} else {
placewewant = 0;
unget_kbinput(kbinput, meta_key, func_key);
/* Blow away the justify buffer.*/
free_filestruct(jusbuffer);
jusbuffer = NULL;
}
cutbuffer = cutbuffer_save;
/* Note that now cutbottom is invalid, but that's okay. */
blank_statusbar();
/* Display the shortcut list with UnCut. */
@ -3060,6 +3264,16 @@ void handle_sigwinch(int s)
if (filepart != NULL)
unpartition_filestruct(&filepart);
#ifndef DISABLE_JUSTIFY
/* If the justify buffer isn't empty, blow it away and display the
* shortcut list with UnCut. */
if (jusbuffer != NULL) {
free_filestruct(jusbuffer);
jusbuffer = NULL;
shortcut_init(FALSE);
}
#endif
#ifdef USE_SLANG
/* Slang curses emulation brain damage, part 1: If we just do what
* curses does here, it'll only work properly if the resize made the
@ -3741,7 +3955,7 @@ int main(int argc, char **argv)
currshortcut = main_list;
#endif
kbinput = get_edit_input(&meta_key, &func_key, TRUE);
kbinput = get_edit_input(&meta_key, &func_key);
/* Last gasp, stuff that's not in the main lists. */
if (kbinput != ERR && !is_cntrl_char(kbinput)) {

View File

@ -145,10 +145,6 @@
#endif
/* Enumeration types. */
typedef enum {
CUT_LINE, CUT_MARKED, CUT_TO_EOL
} cut_type;
typedef enum {
NIX_FILE, DOS_FILE, MAC_FILE
} file_format;

View File

@ -86,6 +86,9 @@ extern char *alt_speller;
extern struct stat fileinfo;
extern filestruct *current, *fileage, *edittop, *filebot;
extern filestruct *cutbuffer;
#ifndef DISABLE_JUSTIFY
extern filestruct *jusbuffer;
#endif
extern partition *filepart;
#ifndef NANO_SMALL
extern filestruct *mark_beginbuf;
@ -158,11 +161,11 @@ void update_color(void);
/* Public functions in cut.c. */
void cutbuffer_reset(void);
filestruct *get_cutbottom(void);
void add_to_cutbuffer(filestruct *inptr, bool allow_concat);
void cut_line(void);
#ifndef NANO_SMALL
void cut_marked_segment(void);
void cut_marked(void);
#endif
void cut_to_eol(void);
void do_cut_text(void);
void do_uncut_text(void);
@ -308,6 +311,9 @@ void free_filestruct(filestruct *src);
partition *partition_filestruct(filestruct *top, size_t top_x,
filestruct *bot, size_t bot_x);
void unpartition_filestruct(partition **p);
void move_to_filestruct(filestruct **file_top, filestruct **file_bot,
filestruct *top, size_t top_x, filestruct *bot, size_t bot_x);
void copy_from_filestruct(filestruct *file_top, filestruct *file_bot);
void renumber_all(void);
void renumber(filestruct *fileptr);
void print1opt(const char *shortflag, const char *longflag, const char
@ -504,11 +510,11 @@ char *mallocstrassn(char *dest, char *src);
void new_magicline(void);
#ifndef NANO_SMALL
void remove_magicline(void);
void get_totals(const filestruct *begin, const filestruct *end, int
*lines, long *size);
void mark_order(const filestruct **top, size_t *top_x, const filestruct
**bot, size_t *bot_x, bool *right_side_up);
#endif
void get_totals(const filestruct *begin, const filestruct *end, int
*lines, long *size);
#ifndef DISABLE_TABCOMP
int check_wildcard_match(const char *text, const char *pattern);
#endif
@ -549,7 +555,7 @@ const shortcut *get_shortcut(const shortcut *s_list, int kbinput, bool
#ifndef NANO_SMALL
const toggle *get_toggle(int kbinput, bool meta_key);
#endif
int get_edit_input(bool *meta_key, bool *func_key, bool allow_funcs);
int get_edit_input(bool *meta_key, bool *func_key);
#ifndef DISABLE_MOUSE
bool get_edit_mouse(void);
#endif

View File

@ -456,6 +456,35 @@ void remove_magicline(void)
}
}
/* 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_beginbuf, mark_beginx) and ends with (current, current_x), or
* FALSE otherwise. */
void mark_order(const filestruct **top, size_t *top_x, const filestruct
**bot, size_t *bot_x, bool *right_side_up)
{
assert(top != NULL && top_x != NULL && bot != NULL && bot_x != NULL);
if ((current->lineno == mark_beginbuf->lineno && current_x >
mark_beginx) || current->lineno > mark_beginbuf->lineno) {
*top = mark_beginbuf;
*top_x = mark_beginx;
*bot = current;
*bot_x = current_x;
if (right_side_up != NULL)
*right_side_up = TRUE;
} else {
*bot = mark_beginbuf;
*bot_x = mark_beginx;
*top = current;
*top_x = current_x;
if (right_side_up != NULL)
*right_side_up = FALSE;
}
}
#endif
/* Calculate the number of lines and the number of characters between
* begin and end, and return them in lines and size, respectively. */
void get_totals(const filestruct *begin, const filestruct *end, int
@ -501,35 +530,6 @@ void get_totals(const filestruct *begin, const filestruct *end, int
}
}
/* 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_beginbuf, mark_beginx) and ends with (current, current_x), or
* FALSE otherwise. */
void mark_order(const filestruct **top, size_t *top_x, const filestruct
**bot, size_t *bot_x, bool *right_side_up)
{
assert(top != NULL && top_x != NULL && bot != NULL && bot_x != NULL);
if ((current->lineno == mark_beginbuf->lineno && current_x >
mark_beginx) || current->lineno > mark_beginbuf->lineno) {
*top = mark_beginbuf;
*top_x = mark_beginx;
*bot = current;
*bot_x = current_x;
if (right_side_up != NULL)
*right_side_up = TRUE;
} else {
*bot = mark_beginbuf;
*bot_x = mark_beginx;
*top = current;
*top_x = current_x;
if (right_side_up != NULL)
*right_side_up = FALSE;
}
}
#endif
#ifndef DISABLE_TABCOMP
/*
* Routine to see if a text string is matched by a wildcard pattern.

View File

@ -1491,7 +1491,7 @@ const toggle *get_toggle(int kbinput, bool meta_key)
}
#endif /* !NANO_SMALL */
int get_edit_input(bool *meta_key, bool *func_key, bool allow_funcs)
int get_edit_input(bool *meta_key, bool *func_key)
{
bool keyhandled = FALSE;
int kbinput, retval;
@ -1536,12 +1536,10 @@ int get_edit_input(bool *meta_key, bool *func_key, bool allow_funcs)
if (s->func != do_cut_text)
cutbuffer_reset();
if (s->func != NULL) {
if (allow_funcs) {
if (ISSET(VIEW_MODE) && !s->viewok)
print_view_warning();
else
s->func();
}
if (ISSET(VIEW_MODE) && !s->viewok)
print_view_warning();
else
s->func();
keyhandled = TRUE;
}
}
@ -1555,8 +1553,7 @@ int get_edit_input(bool *meta_key, bool *func_key, bool allow_funcs)
* corresponding flag. */
if (t != NULL) {
cutbuffer_reset();
if (allow_funcs)
do_toggle(t);
do_toggle(t);
keyhandled = TRUE;
}
}
@ -1565,7 +1562,7 @@ int get_edit_input(bool *meta_key, bool *func_key, bool allow_funcs)
/* If we got a shortcut with a corresponding function or a toggle,
* reset meta_key and retval. If we didn't, keep the value of
* meta_key and return the key we got in retval. */
if (allow_funcs && keyhandled) {
if (keyhandled) {
*meta_key = FALSE;
retval = ERR;
} else {