Ticket #2287 (mcedit: persistent bookmarks)

Save bookmarks of internal edit in filepos

Signed-off-by: Filip Sefrna <fsefrna@gmail.com>

Type accuracy.

Signed-off-by: Ilia Maslakov <il.smind@gmail.com>
This commit is contained in:
Filip Sefrna 2010-07-17 18:21:29 +02:00 committed by Ilia Maslakov
parent 7a53028565
commit a4651d8d2b
9 changed files with 239 additions and 127 deletions

View File

@ -1450,16 +1450,18 @@ mc_mkstemps (char **pname, const char *prefix, const char *suffix)
return -1;
}
#define MAX_SAVED_BOOKMARKS 10
/*
* Read and restore position for the given filename.
* If there is no stored data, return line 1 and col 0.
*/
void
load_file_position (const char *filename, long *line, long *column, off_t * offset)
load_file_position (const char *filename, long *line, long *column, off_t * offset, long **bookmarks)
{
char *fn;
FILE *f;
char buf[MC_MAXPATHLEN + 20];
char buf[MC_MAXPATHLEN + 100];
int len;
/* defaults */
@ -1474,6 +1476,11 @@ load_file_position (const char *filename, long *line, long *column, off_t * offs
if (!f)
return;
/* prepare array for serialized bookmarks */
(*bookmarks) = (long*) g_malloc ((MAX_SAVED_BOOKMARKS + 1) * sizeof(long));
(*bookmarks)[0] = -1;
(*bookmarks)[MAX_SAVED_BOOKMARKS] = -2;
len = strlen (filename);
while (fgets (buf, sizeof (buf), f))
@ -1494,7 +1501,8 @@ load_file_position (const char *filename, long *line, long *column, off_t * offs
if (strchr (p, ' '))
continue;
pos_tokens = g_strsplit_set (p, ";", 3);
pos_tokens = g_strsplit_set (p, ";", 3 + MAX_SAVED_BOOKMARKS);
if (pos_tokens[0] != NULL)
{
*line = strtol (pos_tokens[0], NULL, 10);
@ -1502,7 +1510,20 @@ load_file_position (const char *filename, long *line, long *column, off_t * offs
{
*column = strtol (pos_tokens[1], NULL, 10);
if (pos_tokens[2] != NULL)
{
int i;
*offset = strtoll (pos_tokens[2], NULL, 10);
for (i = 0; i < MAX_SAVED_BOOKMARKS; i++)
{
if (pos_tokens[3 + i] != NULL)
(*bookmarks)[i] = strtol (pos_tokens[3 + i], NULL, 10);
else
{
(*bookmarks)[i] = -1;
break;
}
}
}
else
*offset = 0;
}
@ -1526,19 +1547,18 @@ load_file_position (const char *filename, long *line, long *column, off_t * offs
/* Save position for the given file */
#define TMP_SUFFIX ".tmp"
void
save_file_position (const char *filename, long line, long column, off_t offset)
save_file_position (const char *filename, long line, long column, off_t offset, long *bookmarks)
{
static int filepos_max_saved_entries = 0;
char *fn, *tmp_fn;
FILE *f, *tmp_f;
char buf[MC_MAXPATHLEN + 20];
int i = 1;
char buf[MC_MAXPATHLEN + 100];
int i;
gsize len;
if (filepos_max_saved_entries == 0)
filepos_max_saved_entries =
mc_config_get_int (mc_main_config, CONFIG_APP_SECTION, "filepos_max_saved_entries",
1024);
filepos_max_saved_entries = mc_config_get_int (mc_main_config, CONFIG_APP_SECTION,
"filepos_max_saved_entries", 1024);
fn = g_build_filename (home_dir, MC_USERCONF_DIR, MC_FILEPOS_FILE, NULL);
if (fn == NULL)
@ -1559,13 +1579,23 @@ save_file_position (const char *filename, long line, long column, off_t offset)
goto open_source_error;
/* put the new record */
if (line != 1 || column != 0)
if (line != 1 || column != 0 || bookmarks != NULL)
{
if (fprintf (f, "%s %ld;%ld;%llu\n", filename, line, column, (unsigned long long) offset) <
0)
if (fprintf (f, "%s %ld;%ld;%llu", filename, line, column, (unsigned long long) offset) < 0)
goto write_position_error;
if (bookmarks != NULL)
{
for (i = 0; bookmarks[i] >= 0 && i < MAX_SAVED_BOOKMARKS; i++)
{
if (fprintf (f, ";%ld", bookmarks[i]) < 0)
goto write_position_error;
}
}
if (fprintf (f, "\n") < 0)
goto write_position_error;
}
i = 1;
while (fgets (buf, sizeof (buf), tmp_f))
{
if (buf[len] == ' ' && strncmp (buf, filename, len) == 0 && !strchr (&buf[len + 1], ' '))
@ -1591,6 +1621,8 @@ save_file_position (const char *filename, long line, long column, off_t offset)
open_target_error:
g_free (fn);
early_error:
if (bookmarks != NULL)
g_free(bookmarks);
return;
}

View File

@ -232,9 +232,9 @@ GList *list_append_unique (GList * list, char *text);
/* Position saving and restoring */
/* Load position for the given filename */
void load_file_position (const char *filename, long *line, long *column, off_t * offset);
void load_file_position (const char *filename, long *line, long *column, off_t * offset, long **bookmarks);
/* Save position for the given filename */
void save_file_position (const char *filename, long line, long column, off_t offset);
void save_file_position (const char *filename, long line, long column, off_t offset, long *bookmarks);
/* OS specific defines */

View File

@ -49,89 +49,108 @@
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 struct _book_mark *double_marks (WEdit * edit, struct _book_mark *p)
static struct _book_mark *
double_marks (WEdit * edit, struct _book_mark *p)
{
(void) edit;
if (p->next)
while (p->next->line == p->line)
p = p->next;
while (p->next->line == p->line)
p = p->next;
return p;
}
/* returns the first bookmark on or before this line */
struct _book_mark *book_mark_find (WEdit * edit, int line)
{
struct _book_mark *p;
if (!edit->book_mark) {
/* must have an imaginary top bookmark at line -1 to make things less complicated */
edit->book_mark = g_malloc0 (sizeof (struct _book_mark));
edit->book_mark->line = -1;
return edit->book_mark;
}
for (p = edit->book_mark; p; p = p->next) {
if (p->line > line)
break; /* gone past it going downward */
if (p->line <= line) {
if (p->next) {
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; p = p->prev) {
if (p->next)
if (p->next->line <= line)
break; /* gone past it going upward */
if (p->line <= line) {
if (p->next) {
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 0; /* can't get here */
}
/* returns true if a bookmark exists at this line of color c */
int book_mark_query_color (WEdit * edit, int line, int c)
struct _book_mark *
book_mark_find (WEdit * edit, int line)
{
struct _book_mark *p;
if (!edit->book_mark)
return 0;
for (p = book_mark_find (edit, line); p; p = p->prev) {
if (p->line != line)
return 0;
if (p->c == c)
return 1;
{
/* must have an imaginary top bookmark at line -1 to make things less complicated */
edit->book_mark = g_malloc0 (sizeof (struct _book_mark));
edit->book_mark->line = -1;
return edit->book_mark;
}
for (p = edit->book_mark; p; p = p->next)
{
if (p->line > line)
break; /* gone past it going downward */
if (p->line <= line)
{
if (p->next)
{
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; p = p->prev)
{
if (p->next)
if (p->next->line <= line)
break; /* gone past it going upward */
if (p->line <= line)
{
if (p->next)
{
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 0; /* can't get here */
}
/* returns true if a bookmark exists at this line of color c */
int
book_mark_query_color (WEdit * edit, int line, int c)
{
struct _book_mark *p;
if (!edit->book_mark)
return 0;
for (p = book_mark_find (edit, line); p; p = p->prev)
{
if (p->line != line)
return 0;
if (p->c == c)
return 1;
}
return 0;
}
/* insert a bookmark at this line */
void
book_mark_insert (WEdit *edit, int line, int c)
book_mark_insert (WEdit * edit, int line, int c)
{
struct _book_mark *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) {
edit->force |= REDRAW_LINE;
p->c = c;
}
return;
if (p->line == line)
{
/* already exists, so just change the color */
if (p->c != c)
{
edit->force |= REDRAW_LINE;
p->c = c;
}
return;
}
#endif
edit->force |= REDRAW_LINE;
@ -143,83 +162,129 @@ book_mark_insert (WEdit *edit, int line, int c)
/* insert into list */
q->prev = p;
if (p->next)
p->next->prev = q;
p->next->prev = q;
p->next = q;
}
/* remove a bookmark if there is one at this line matching this color - c of -1 clear all */
/* returns non-zero on not-found */
int book_mark_clear (WEdit * edit, int line, int c)
int
book_mark_clear (WEdit * edit, int line, int c)
{
struct _book_mark *p, *q;
int r = 1;
if (!edit->book_mark)
return r;
for (p = book_mark_find (edit, line); p; p = q) {
q = p->prev;
if (p->line == line && (p->c == c || c == -1)) {
r = 0;
edit->force |= REDRAW_LINE;
edit->book_mark = p->prev;
p->prev->next = p->next;
if (p->next)
p->next->prev = p->prev;
g_free (p);
break;
}
return r;
for (p = book_mark_find (edit, line); p; p = q)
{
q = p->prev;
if (p->line == line && (p->c == c || c == -1))
{
r = 0;
edit->force |= REDRAW_LINE;
edit->book_mark = p->prev;
p->prev->next = p->next;
if (p->next)
p->next->prev = p->prev;
g_free (p);
break;
}
}
/* if there is only our dummy book mark left, clear it for speed */
if (edit->book_mark->line == -1 && !edit->book_mark->next) {
g_free (edit->book_mark);
edit->book_mark = 0;
/* if there is only our dummy book mark left, clear it for speed */
if (edit->book_mark->line == -1 && !edit->book_mark->next)
{
g_free (edit->book_mark);
edit->book_mark = 0;
}
return r;
}
/* clear all bookmarks matching this color, if c is -1 clears all */
void book_mark_flush (WEdit * edit, int c)
void
book_mark_flush (WEdit * edit, int c)
{
struct _book_mark *p, *q;
if (!edit->book_mark)
return;
return;
edit->force |= REDRAW_PAGE;
while (edit->book_mark->prev)
edit->book_mark = edit->book_mark->prev;
for (q = edit->book_mark->next; q; q = p) {
p = q->next;
if (q->c == c || c == -1) {
q->prev->next = q->next;
if (p)
p->prev = q->prev;
g_free (q);
}
edit->book_mark = edit->book_mark->prev;
for (q = edit->book_mark->next; q; q = p)
{
p = q->next;
if (q->c == c || c == -1)
{
q->prev->next = q->next;
if (p)
p->prev = q->prev;
g_free (q);
}
}
if (!edit->book_mark->next) {
g_free (edit->book_mark);
edit->book_mark = 0;
if (!edit->book_mark->next)
{
g_free (edit->book_mark);
edit->book_mark = 0;
}
}
/* shift down bookmarks after this line */
void book_mark_inc (WEdit * edit, int line)
void
book_mark_inc (WEdit * edit, int line)
{
if (edit->book_mark) {
struct _book_mark *p;
p = book_mark_find (edit, line);
for (p = p->next; p; p = p->next) {
p->line++;
}
if (edit->book_mark)
{
struct _book_mark *p;
p = book_mark_find (edit, line);
for (p = p->next; p; p = p->next)
{
p->line++;
}
}
}
/* shift up bookmarks after this line */
void book_mark_dec (WEdit * edit, int line)
void
book_mark_dec (WEdit * edit, int line)
{
if (edit->book_mark) {
struct _book_mark *p;
p = book_mark_find (edit, line);
for (p = p->next; p; p = p->next) {
p->line--;
}
if (edit->book_mark)
{
struct _book_mark *p;
p = book_mark_find (edit, line);
for (p = p->next; p; p = p->next)
{
p->line--;
}
}
}
/* prepare line positions of bookmarks to be saved to file */
void
book_mark_serialize (WEdit * edit, int color)
{
struct _book_mark *p;
long *bookmarks = edit->serialized_bookmarks;
if (edit->book_mark == NULL || bookmarks == NULL)
return;
for (p = book_mark_find (edit, 0); p != NULL && *bookmarks != -2; p = p->next)
{
if (p->c == color && p->line != -1)
{
*bookmarks++ = p->line;
}
}
*bookmarks = -1;
}
/* restore bookmarks from saved line positions */
void
book_mark_restore (WEdit * edit, int color)
{
long *bookmarks = edit->serialized_bookmarks;
if (bookmarks == NULL)
return;
for (; *bookmarks >= 0; bookmarks++)
book_mark_insert (edit, *bookmarks, color);
}

View File

@ -280,6 +280,8 @@ int book_mark_clear (WEdit * edit, int line, int c);
void book_mark_flush (WEdit * edit, int c);
void book_mark_inc (WEdit * edit, int line);
void book_mark_dec (WEdit * edit, int line);
void book_mark_serialize (WEdit * edit, int color);
void book_mark_restore (WEdit * edit, int color);
int line_is_blank (WEdit * edit, long line);
int edit_indent_width (WEdit * edit, long p);

View File

@ -96,6 +96,7 @@ struct WEdit
long line_offsets[N_LINE_CACHES];
struct _book_mark *book_mark;
long *serialized_bookmarks;
/* undo stack and pointers */
unsigned long stack_pointer;

View File

@ -805,6 +805,8 @@ edit_load_file (WEdit * edit)
return 0;
}
#define MAX_SAVED_BOOKMARKS 10
/* Restore saved cursor position in the file */
static void
edit_load_position (WEdit * edit)
@ -817,7 +819,7 @@ edit_load_position (WEdit * edit)
return;
filename = vfs_canon (edit->filename);
load_file_position (filename, &line, &column, &offset);
load_file_position (filename, &line, &column, &offset, &edit->serialized_bookmarks);
g_free (filename);
if (line > 0)
@ -830,6 +832,9 @@ edit_load_position (WEdit * edit)
edit_cursor_move (edit, offset);
line = edit->curs_line;
}
book_mark_restore (edit, BOOK_MARK_COLOR);
edit_move_to_prev_col (edit, edit_bol (edit, edit->curs1));
edit_move_display (edit, line - (edit->num_widget_lines / 2));
}
@ -844,7 +849,12 @@ edit_save_position (WEdit * edit)
return;
filename = vfs_canon (edit->filename);
save_file_position (filename, edit->curs_line + 1, edit->curs_col, edit->curs1);
book_mark_serialize (edit, BOOK_MARK_COLOR);
save_file_position (filename, edit->curs_line + 1, edit->curs_col, edit->curs1, edit->serialized_bookmarks);
edit->serialized_bookmarks = NULL;
g_free (filename);
}

View File

@ -190,6 +190,8 @@ typedef struct mcview_struct
struct mcview_nroff_struct *search_nroff_seq;
int search_numNeedSkipChar;
long *saved_bookmarks;
} mcview_t;
typedef struct mcview_nroff_struct

View File

@ -233,7 +233,7 @@ mcview_done (mcview_t * view)
{
char *canon_fname;
canon_fname = vfs_canon (view->filename);
save_file_position (canon_fname, -1, 0, view->dpy_start);
save_file_position (canon_fname, -1, 0, view->dpy_start, view->saved_bookmarks);
g_free (canon_fname);
}

View File

@ -412,7 +412,7 @@ mcview_load (mcview_t * view, const char *command, const char *file, int start_l
off_t new_offset;
canon_fname = vfs_canon (view->filename);
load_file_position (canon_fname, &line, &col, &new_offset);
load_file_position (canon_fname, &line, &col, &new_offset, &view->saved_bookmarks);
new_offset = min (new_offset, mcview_get_filesize (view));
view->dpy_start = mcview_bol (view, new_offset);
g_free (canon_fname);