From cb1507bdd44c7e79fcd96b0c87b53cbd357e30a1 Mon Sep 17 00:00:00 2001 From: rexy712 Date: Sat, 1 Apr 2023 12:35:48 -0700 Subject: [PATCH] add folding.c --- src/folding.c | 138 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 138 insertions(+) create mode 100644 src/folding.c diff --git a/src/folding.c b/src/folding.c new file mode 100644 index 00000000..646d0353 --- /dev/null +++ b/src/folding.c @@ -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 + /* 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 */