Add the basic support structure for the folding.
Adds in some preprocessor directives for easily adding in unfolding support to existing functions that require it. Also adds in some helper functions in 'folding.c' for common tasks which will need performed. And of course add the 'folded' boolean to the linestruct type so we know which lines are currently folded. Signed-off-by: rexy712 <rexy712@protonmail.com>
This commit is contained in:
parent
fdcafb83e3
commit
584571248f
@ -273,6 +273,15 @@
|
||||
#define MSOME MMAIN|MBROWSER
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_FOLDING
|
||||
#define UNFOLD_SEGMENT(line) unfold_folded_segment(line)
|
||||
#else
|
||||
#define UNFOLD_SEGMENT(line)
|
||||
#endif
|
||||
|
||||
#define ALLOW_FOLDED TRUE
|
||||
#define DISALLOW_FOLDED FALSE
|
||||
|
||||
/* Enumeration types. */
|
||||
typedef enum {
|
||||
UNSPECIFIED, NIX_FILE, DOS_FILE, MAC_FILE
|
||||
@ -374,6 +383,12 @@ enum {
|
||||
ZERO
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
FOUND_BRACKET = 0,
|
||||
NOT_FOUND_BRACKET,
|
||||
NOT_A_BRACKET
|
||||
} bracket_search_result;
|
||||
|
||||
/* Structure types. */
|
||||
#ifdef ENABLE_COLOR
|
||||
typedef struct colortype {
|
||||
@ -480,6 +495,10 @@ typedef struct linestruct {
|
||||
bool has_anchor;
|
||||
/* Whether the user has placed an anchor at this line. */
|
||||
#endif
|
||||
#ifdef ENABLE_FOLDING
|
||||
bool folded;
|
||||
/* Whether or not this line is in a fold segment */
|
||||
#endif
|
||||
} linestruct;
|
||||
|
||||
#ifndef NANO_TINY
|
||||
|
||||
129
src/folding.c
Normal file
129
src/folding.c
Normal file
@ -0,0 +1,129 @@
|
||||
/**************************************************************************
|
||||
* folding.c -- This file is part of GNU nano. *
|
||||
* *
|
||||
* Copyright (C) 2023 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"
|
||||
|
||||
#ifdef ENABLE_FOLDING
|
||||
|
||||
/* Unfold a folded segment containing the given line. */
|
||||
void unfold_folded_segment(linestruct *line)
|
||||
{
|
||||
line = get_start_of_folded_segment(line);
|
||||
if (line != NULL)
|
||||
refresh_needed = TRUE;
|
||||
for (; line != NULL && line->folded; line = line->next)
|
||||
line->folded = FALSE;
|
||||
}
|
||||
|
||||
/* Get the first line 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 line 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 number of lines in 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;
|
||||
}
|
||||
|
||||
|
||||
/* Unfolds a folded segment containing line, or if line is not folded
|
||||
* does nothing. Returns true if any segments are unfolded. */
|
||||
bool do_unfold_segment(linestruct *line)
|
||||
{
|
||||
/* Attempt to find a bracketed region first. */
|
||||
if (!line->folded) {
|
||||
linestruct *dummy;
|
||||
find_bracketed_region(openfile->current, &line, &dummy);
|
||||
}
|
||||
|
||||
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
|
||||
* contains any folded lines. 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 */
|
||||
@ -78,6 +78,9 @@ linestruct *make_new_node(linestruct *prevnode)
|
||||
#ifndef NANO_TINY
|
||||
newnode->has_anchor = FALSE;
|
||||
#endif
|
||||
#ifdef ENABLE_FOLDING
|
||||
newnode->folded = FALSE;
|
||||
#endif
|
||||
|
||||
return newnode;
|
||||
}
|
||||
@ -156,6 +159,9 @@ linestruct *copy_node(const linestruct *src)
|
||||
#ifndef NANO_TINY
|
||||
dst->has_anchor = src->has_anchor;
|
||||
#endif
|
||||
#ifdef ENABLE_FOLDING
|
||||
dst->folded = src->folded;
|
||||
#endif
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
@ -579,6 +579,8 @@ linestruct *line_from_number(ssize_t number);
|
||||
#endif
|
||||
|
||||
/* Most functions in winio.c. */
|
||||
linestruct *get_next_visible_line(linestruct *line);
|
||||
linestruct *get_prev_visible_line(linestruct *line);
|
||||
#ifndef NANO_TINY
|
||||
void record_macro(void);
|
||||
void run_macro(void);
|
||||
@ -674,3 +676,12 @@ void flip_newbuffer(void);
|
||||
#endif
|
||||
void discard_buffer(void);
|
||||
void do_cancel(void);
|
||||
|
||||
/* Most functions in folding.c. */
|
||||
#ifdef ENABLE_FOLDING
|
||||
void do_fold_segment(void);
|
||||
void unfold_folded_segment(linestruct *line);
|
||||
linestruct *get_start_of_folded_segment(linestruct* line);
|
||||
linestruct *get_end_of_folded_segment(linestruct* line);
|
||||
int get_folded_segment_length(linestruct *line);
|
||||
#endif
|
||||
|
||||
49
src/winio.c
49
src/winio.c
@ -140,6 +140,55 @@ void run_macro(void)
|
||||
}
|
||||
#endif /* !NANO_TINY */
|
||||
|
||||
/* Return the current offset of target from openfile->edittop */
|
||||
int get_row_from_edittop(linestruct *target)
|
||||
{
|
||||
#ifdef ENABLE_FOLDING
|
||||
linestruct *line = openfile->edittop;
|
||||
int row = 0;
|
||||
while (line != NULL && line != target && row < editwinrows) {
|
||||
line = get_end_of_folded_segment(line);
|
||||
line = line->next;
|
||||
++row;
|
||||
}
|
||||
return row;
|
||||
#else
|
||||
return target->lineno - openfile->edittop->lineno;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Return the next line, taking fold segments into account */
|
||||
linestruct *get_next_visible_line(linestruct *line)
|
||||
{
|
||||
if (!line)
|
||||
return NULL;
|
||||
|
||||
#ifdef ENABLE_FOLDING
|
||||
line = get_end_of_folded_segment(line);
|
||||
if (line == NULL)
|
||||
return NULL;
|
||||
#endif
|
||||
return line->next;
|
||||
}
|
||||
|
||||
/* Return the previous line, taking fold segments into account */
|
||||
linestruct *get_prev_visible_line(linestruct *line)
|
||||
{
|
||||
if (!line)
|
||||
return NULL;
|
||||
|
||||
#ifdef ENABLE_FOLDING
|
||||
if (line->folded) {
|
||||
line = get_start_of_folded_segment(line);
|
||||
return line == NULL ? NULL : line->prev;
|
||||
}
|
||||
if (line->prev != NULL && line->prev->folded)
|
||||
return get_start_of_folded_segment(line->prev);
|
||||
|
||||
#endif
|
||||
return line->prev;
|
||||
}
|
||||
|
||||
/* Allocate the requested space for the keystroke buffer. */
|
||||
void reserve_space_for(size_t newsize)
|
||||
{
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user