/************************************************************************** * 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 */