add folding.c

This commit is contained in:
rexy712 2023-04-01 12:35:48 -07:00
parent e13b24e0ce
commit cb1507bdd4

138
src/folding.c Normal file
View File

@ -0,0 +1,138 @@
/**************************************************************************
* folding.c -- This file is part of GNU nano. *
* *
* Copyright (C) 2022 rexy712 *
* *
* GNU nano is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published *
* by the Free Software Foundation, either version 3 of the License, *
* or (at your option) any later version. *
* *
* GNU nano is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty *
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see http://www.gnu.org/licenses/. *
* *
**************************************************************************/
#include "prototypes.h"
#include <ctype.h>
/* isspace */
#ifdef ENABLE_FOLDING
/* Remove a folded segment from the given line until end of segment */
void unfold_folded_segment_from(linestruct *line)
{
if (line != NULL)
refresh_needed = TRUE;
for(;line != NULL && line->folded;line = line->next)
line->folded = FALSE;
}
/* Remove a folded segment containing the given line */
void unfold_folded_segment(linestruct *line)
{
unfold_folded_segment_from(get_start_of_folded_segment(line));
}
/* Get the first member of the folded segment */
linestruct *get_start_of_folded_segment(linestruct *line)
{
if (!line->folded)
return line;
while (line->prev != NULL && line->prev->folded)
line = line->prev;
return line;
}
/* Get the last member of the folded segment */
linestruct *get_end_of_folded_segment(linestruct *line)
{
if (!line->folded)
return line;
while (line->next != NULL && line->next->folded)
line = line->next;
return line;
}
/* Get the span length of a folded_segment */
int get_folded_segment_length(linestruct *line)
{
int i = 1;
if (!line->folded)
return 0;
line = get_start_of_folded_segment(line);
for (;line->next != NULL && line->next->folded;line = line->next)
++i;
return i;
}
/* Remove any folded_segments within the range [top, bottom].
* Returns true if any segments are removed. */
bool do_unfold_segment(linestruct *line)
{
/* Attempt to find a bracketed region first.
* If not, top is unmodified. */
if (!line->folded) {
linestruct *bot;
find_bracketed_region(openfile->current, &line, &bot);
}
if (line->folded) {
unfold_folded_segment(line);
move_cursor_to_proper_column();
return TRUE;
}
return FALSE;
}
/* Fold the currently selected lines unless the current selection
* already contains a folded_segment. In that case, remove any
* segments that are selected. */
void do_fold_segment(void)
{
linestruct *top, *bot;
get_range(&top, &bot);
if (top == bot) {
/* First try to unfold if this line/bracketed region is folded */
if (do_unfold_segment(top))
return;
/* When not selecting multiple lines, try to find bounding
* brackets to act as top and bot. */
if (!find_bracketed_region(openfile->current, &top, &bot)) {
statusline(AHEM, _("No valid region found for automatic fold"));
return;
}
}
for (linestruct* line = top;line != bot->next;line = line->next)
line->folded = TRUE;
if (top->lineno < openfile->edittop->lineno &&
bot->lineno > openfile->edittop->lineno)
openfile->edittop = top;
/* Place the cursor at the start of the fold segment.
* Anywhere else within the segment is invalid. */
if (openfile->current->folded)
openfile->current = get_start_of_folded_segment(top);
openfile->mark = NULL;
refresh_needed = TRUE;
}
#endif /* ENABLE_FOLDING */