diff --git a/lib/util.c b/lib/util.c index 9e83a708e..cb9ce2cfd 100644 --- a/lib/util.c +++ b/lib/util.c @@ -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; } diff --git a/lib/util.h b/lib/util.h index db7afdf15..c88283acb 100644 --- a/lib/util.h +++ b/lib/util.h @@ -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 */ diff --git a/src/editor/bookmark.c b/src/editor/bookmark.c index 0d6f8b03a..56806cfc1 100644 --- a/src/editor/bookmark.c +++ b/src/editor/bookmark.c @@ -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); +} diff --git a/src/editor/edit-impl.h b/src/editor/edit-impl.h index 6ec37ea2e..ebbcdc642 100644 --- a/src/editor/edit-impl.h +++ b/src/editor/edit-impl.h @@ -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); diff --git a/src/editor/edit-widget.h b/src/editor/edit-widget.h index 3d66abe04..79ff2337c 100644 --- a/src/editor/edit-widget.h +++ b/src/editor/edit-widget.h @@ -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; diff --git a/src/editor/edit.c b/src/editor/edit.c index ce617c435..31f3efc02 100644 --- a/src/editor/edit.c +++ b/src/editor/edit.c @@ -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); } diff --git a/src/viewer/internal.h b/src/viewer/internal.h index 2e30522b5..1ff283819 100644 --- a/src/viewer/internal.h +++ b/src/viewer/internal.h @@ -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 diff --git a/src/viewer/lib.c b/src/viewer/lib.c index 271055f15..d6c29c895 100644 --- a/src/viewer/lib.c +++ b/src/viewer/lib.c @@ -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); } diff --git a/src/viewer/mcviewer.c b/src/viewer/mcviewer.c index 5ed7aa737..75fa8c21a 100644 --- a/src/viewer/mcviewer.c +++ b/src/viewer/mcviewer.c @@ -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);