RE: Saving file position in mcedit



Hello!

It looks like I'm going to spend the whole weekend on the position saving.  
I have fixed the remaining unapplied code so that it handles files with
spaces properly.  Also, I'm now using vfs_canon() on the filenames, which
takes care of adding the current directory and canonicalizes VFS names.

The necessary fixes in the src directory have been committed - they should
be safe.  The only remaining part is the patch for editwidget.c.

There are still some bugs to be fixed and issues to be decided.

1) The position is saved even if the file is not saved.  I don't know if
it's a bug, maybe not.

2) The column position is saved (or restored - if we are saving the
visible position, not the number of characters) incorrectly if there are
tabs preceding the cursor on the line.  That's clearly a bug, I hope to
fix it soon.

3) I don't like the filename ".mc/EditPos".  All other editor-specific
files are called ".mc/cedit/cooledit.*", so ".mc/cedit/cooledit.pos"  
would be more consistent.  If we are going to use this file in the viewer
some day, then again ".mc/filepos" would be more consistent with
".mc/history" and ".mc/hotlist" and not specific to the editor.

4) I think that all saving and restoring positions should be moved from 
the dialog level to the widget level.  This would allow us e.g. to restore 
positions in the files loaded by "Open file..." in the editor menu and 
save positions on "Save as".  These actions happen inside run_dlg() for 
the editor.

Any comments?

The current patch is attached.

-- 
Regards,
Pavel Roskin
--- editwidget.c
+++ editwidget.c
@@ -36,6 +36,122 @@ int column_highlighting = 0;
 
 static int edit_callback (WEdit *edit, int msg, int par);
 
+/* file where positions are stored */
+#define MC_EDITPOS ".mc/EditPos"
+/* temporary file */
+#define MC_EDITPOS_TMP ".mc/EditPos.tmp"
+/* maximum entries in MC_EDITPOS */
+#define MC_MAX_EDITPOS_ENTRIES 1024
+
+/* Read and restore position the given filename */
+static void
+edit_load_position (WEdit *edit)
+{
+    char *fn;
+    FILE *f;
+    char buf[MC_MAXPATHLEN + 20];
+    int len;
+    char *filename;
+    long line = 1, column = 0;
+
+    if (!edit->filename || !*edit->filename)
+	return;
+
+    filename = vfs_canon (edit->filename);
+    len = strlen (filename);
+
+    /* open file with positions */
+    fn = concat_dir_and_file (home_dir, MC_EDITPOS);
+    f = fopen (fn, "r");
+    g_free (fn);
+    if (!f) {
+	g_free (filename);
+	return;
+    }
+
+    while (fgets (buf, sizeof (buf), f)) {
+	char *p;
+
+	/* check if the filename matches the beginning of string */
+	if (strncmp (buf, filename, len) != 0)
+	    continue;
+
+	/* followed by single space */
+	if (buf[len] != ' ')
+	    continue;
+
+	/* and string without spaces */
+	p = &buf[len + 1];
+	if (strchr (p, ' '))
+	    continue;
+
+	line = atol (p);
+	p = strchr (buf, ';');
+	column = atol (&p[1]);
+    }
+    fclose (f);
+    g_free (filename);
+
+    edit_move_to_line (wedit, line - 1);
+    edit_move_to_column (wedit, column);
+    edit_move_display (wedit, line - (wedit->num_widget_lines / 2));
+}
+
+/* Store filename and position in MC_EDITPOS */
+static void
+edit_save_position (WEdit *edit)
+{
+    char *tmp, *fn;
+    FILE *f, *t;
+    char buf[MC_MAXPATHLEN + 20];
+    long line = edit->curs_line + 1;
+    long column = edit->curs_col;
+    int i = 1;
+    char *filename;
+    int len;
+
+    if (!edit->filename || !*edit->filename)
+	return;
+
+    filename = vfs_canon (edit->filename);
+    len = strlen (filename);
+
+    tmp = concat_dir_and_file (home_dir, MC_EDITPOS_TMP);
+    fn = concat_dir_and_file (home_dir, MC_EDITPOS);
+
+    /* open temporary file */
+    t = fopen (tmp, "w");
+    if (!t) {
+	g_free (tmp);
+	g_free (fn);
+	return;
+    }
+
+    /* put the new record */
+    fprintf (t, "%s %ld;%ld\n", filename, line, column);
+
+    /* copy records from the old file */
+    f = fopen (fn, "r");
+    if (f) {
+	while (fgets (buf, sizeof (buf), f)) {
+	    /* Skip entries for the current filename */
+	    if (strncmp (buf, filename, len) == 0 && buf[len] == ' '
+		&& !strchr (&buf[len + 1], ' '))
+		continue;
+
+	    fprintf (t, "%s", buf);
+	    if (++i > MC_MAX_EDITPOS_ENTRIES)
+		break;
+	}
+	fclose (f);
+    }
+
+    fclose (t);
+    rename (tmp, fn);
+    g_free (tmp);
+    g_free (fn);
+}
+
 static int
 edit_event (WEdit * edit, Gpm_Event * event, int *result)
 {
@@ -151,6 +267,11 @@ edit_dialog_callback (Dlg_head * h, int 
     return default_dlg_callback (h, id, msg);
 }
 
+/*
+ * Start the editor on the file.  If line is 0, try to restore saved
+ * position of start at the beginning.  If the line is not 0, try to
+ * put cursor on that line and show it in the middle of the screen.
+ */
 int
 edit (const char *_file, int line)
 {
@@ -213,14 +334,26 @@ edit (const char *_file, int line)
 	add_widget (edit_dlg, edit_menubar);
 
     add_widget (edit_dlg, edit_bar);
-    edit_move_display (wedit, line - 1);
-    edit_move_to_line (wedit, line - 1);
+
+    /* load saved cursor position */
+    if ((line == 0) && option_save_position) {
+	edit_load_position (wedit);
+    } else {
+	if (line < 0)
+	    line = 1;
+	edit_move_display (wedit, line - 1);
+	edit_move_to_line (wedit, line - 1);
+    }
 
     run_dlg (edit_dlg);
 
     if (!framed)
 	edit_done_menu ();	/* editmenu.c */
 
+    /* save cursor position */
+    if (option_save_position)
+	edit_save_position (wedit);
+
     destroy_dlg (edit_dlg);
 
     return 1;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]