/* Editor book mark handling Copyright (C) 2001-2022 Free Software Foundation, Inc. Written by: Paul Sheer, 1996, 1997 This file is part of the Midnight Commander. The Midnight Commander 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. The Midnight Commander 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 . */ /** \file * \brief Source: editor book mark handling * \author Paul Sheer * \date 1996, 1997 */ #include #include #include #include #include #include #include #include #include #include #include "lib/global.h" #include "lib/util.h" /* MAX_SAVED_BOOKMARKS */ #include "editwidget.h" /*** global variables ****************************************************************************/ /*** file scope macro definitions ****************************************************************/ /*** file scope type declarations ****************************************************************/ /*** file scope variables ************************************************************************/ /*** file scope functions ************************************************************************/ /* --------------------------------------------------------------------------------------------- */ /** note, if there is more than one bookmark on a line, then they are appended after each other and the last one is always the one found by book_mark_found() i.e. last in is the one seen */ static edit_book_mark_t * double_marks (WEdit * edit, edit_book_mark_t * p) { (void) edit; if (p->next != NULL) while (p->next->line == p->line) p = p->next; return p; } /* --------------------------------------------------------------------------------------------- */ /** returns the first bookmark on or before this line */ edit_book_mark_t * book_mark_find (WEdit * edit, long line) { edit_book_mark_t *p; if (edit->book_mark == NULL) { /* must have an imaginary top bookmark at line -1 to make things less complicated */ edit->book_mark = g_new0 (edit_book_mark_t, 1); edit->book_mark->line = -1; return edit->book_mark; } for (p = edit->book_mark; p != NULL; p = p->next) { if (p->line > line) break; /* gone past it going downward */ if (p->next != NULL) { if (p->next->line > line) { edit->book_mark = p; return double_marks (edit, p); } } else { edit->book_mark = p; return double_marks (edit, p); } } for (p = edit->book_mark; p != NULL; p = p->prev) { if (p->next != NULL && p->next->line <= line) break; /* gone past it going upward */ if (p->line <= line) { if (p->next != NULL) { if (p->next->line > line) { edit->book_mark = p; return double_marks (edit, p); } } else { edit->book_mark = p; return double_marks (edit, p); } } } return NULL; /* can't get here */ } /* --------------------------------------------------------------------------------------------- */ /*** public functions ****************************************************************************/ /* --------------------------------------------------------------------------------------------- */ /** * Check if bookmark bookmark exists at this line of this color * * @param edit editor object * @param line line where book mark is * @param c color of book mark * @return TRUE if bookmark exists at this line of color c, FALSE otherwise */ gboolean book_mark_query_color (WEdit * edit, long line, int c) { if (edit->book_mark != NULL) { edit_book_mark_t *p; for (p = book_mark_find (edit, line); p != NULL; p = p->prev) { if (p->line != line) return FALSE; if (p->c == c) return TRUE; } } return FALSE; } /* --------------------------------------------------------------------------------------------- */ /** insert a bookmark at this line */ void book_mark_insert (WEdit * edit, long line, int c) { edit_book_mark_t *p, *q; p = book_mark_find (edit, line); #if 0 if (p->line == line) { /* already exists, so just change the color */ if (p->c != c) { p->c = c; edit->force |= REDRAW_LINE; } return; } #endif /* create list entry */ q = g_new (edit_book_mark_t, 1); q->line = line; q->c = c; q->next = p->next; /* insert into list */ q->prev = p; if (p->next != NULL) p->next->prev = q; p->next = q; edit->force |= REDRAW_LINE; } /* --------------------------------------------------------------------------------------------- */ /** * Remove a bookmark if there is one at this line matching this color - c of -1 clear all * * @param edit editor object * @param line line where book mark is * @param c color of book mark or -1 to clear all book marks on this line * @return FALSE if not found, TRUE otherwise */ gboolean book_mark_clear (WEdit * edit, long line, int c) { edit_book_mark_t *p, *q; gboolean r = FALSE; if (edit->book_mark == NULL) return r; for (p = book_mark_find (edit, line); p != NULL; p = q) { q = p->prev; if (p->line == line && (p->c == c || c == -1)) { r = TRUE; edit->book_mark = p->prev; p->prev->next = p->next; if (p->next != NULL) p->next->prev = p->prev; g_free (p); edit->force |= REDRAW_LINE; break; } } /* if there is only our dummy book mark left, clear it for speed */ if (edit->book_mark->line == -1 && edit->book_mark->next == NULL) MC_PTR_FREE (edit->book_mark); return r; } /* --------------------------------------------------------------------------------------------- */ /** clear all bookmarks matching this color, if c is -1 clears all */ void book_mark_flush (WEdit * edit, int c) { edit_book_mark_t *p, *q; if (edit->book_mark == NULL) return; while (edit->book_mark->prev != NULL) edit->book_mark = edit->book_mark->prev; for (q = edit->book_mark->next; q != NULL; q = p) { p = q->next; if (q->c == c || c == -1) { q->prev->next = q->next; if (p != NULL) p->prev = q->prev; g_free (q); } } if (edit->book_mark->next == NULL) MC_PTR_FREE (edit->book_mark); edit->force |= REDRAW_PAGE; } /* --------------------------------------------------------------------------------------------- */ /** shift down bookmarks after this line */ void book_mark_inc (WEdit * edit, long line) { if (edit->book_mark != NULL) { edit_book_mark_t *p; p = book_mark_find (edit, line); for (p = p->next; p != NULL; p = p->next) p->line++; } } /* --------------------------------------------------------------------------------------------- */ /** shift up bookmarks after this line */ void book_mark_dec (WEdit * edit, long line) { if (edit->book_mark != NULL) { edit_book_mark_t *p; p = book_mark_find (edit, line); for (p = p->next; p != NULL; p = p->next) p->line--; } } /* --------------------------------------------------------------------------------------------- */ /** prepare line positions of bookmarks to be saved to file */ void book_mark_serialize (WEdit * edit, int color) { if (edit->serialized_bookmarks != NULL) g_array_set_size (edit->serialized_bookmarks, 0); if (edit->book_mark != NULL) { edit_book_mark_t *p; if (edit->serialized_bookmarks == NULL) edit->serialized_bookmarks = g_array_sized_new (FALSE, FALSE, sizeof (size_t), MAX_SAVED_BOOKMARKS); for (p = book_mark_find (edit, 0); p != NULL; p = p->next) if (p->c == color && p->line >= 0) g_array_append_val (edit->serialized_bookmarks, p->line); } } /* --------------------------------------------------------------------------------------------- */ /** restore bookmarks from saved line positions */ void book_mark_restore (WEdit * edit, int color) { if (edit->serialized_bookmarks != NULL) { size_t i; for (i = 0; i < edit->serialized_bookmarks->len; i++) book_mark_insert (edit, g_array_index (edit->serialized_bookmarks, size_t, i), color); } } /* --------------------------------------------------------------------------------------------- */