2 Load and show history of edited and viewed files
4 Copyright (C) 2020-2024
5 Free Software Foundation, Inc.
8 Andrew Borodin <aborodin@vmail.ru>, 2019-2022
10 This file is part of the Midnight Commander.
12 The Midnight Commander is free software: you can redistribute it
13 and/or modify it under the terms of the GNU General Public License as
14 published by the Free Software Foundation, either version 3 of the License,
15 or (at your option) any later version.
17 The Midnight Commander is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
28 #include <stdio.h> /* file functions */
30 #include "lib/global.h"
32 #include "lib/fileloc.h" /* MC_FILEPOS_FILE */
33 #include "lib/mcconfig.h" /* mc_config_get_full_path() */
34 #include "lib/strutil.h" /* str_term_width1() */
35 #include "lib/util.h" /* backup functions */
37 #include "file_history.h"
39 /*** global variables ****************************************************************************/
41 /*** file scope macro definitions ****************************************************************/
43 #define TMP_SUFFIX ".tmp"
45 /*** file scope type declarations ****************************************************************/
47 typedef struct file_history_data_t
51 } file_history_data_t
;
53 /*** forward declarations (file scope functions) *************************************************/
55 /*** file scope variables ************************************************************************/
57 /* --------------------------------------------------------------------------------------------- */
58 /*** file scope functions ************************************************************************/
59 /* --------------------------------------------------------------------------------------------- */
62 file_history_list_read (void)
66 char buf
[MC_MAXPATHLEN
+ 100];
67 GList
*file_list
= NULL
;
69 /* open file with positions */
70 fn
= mc_config_get_full_path (MC_FILEPOS_FILE
);
79 while (fgets (buf
, sizeof (buf
), f
) != NULL
)
82 file_history_data_t
*fhd
;
85 s
= strrchr (buf
, ' ');
86 /* FIXME: saved file position info is present in filepos file */
87 fhd
= g_new (file_history_data_t
, 1);
88 fhd
->file_name
= g_strndup (buf
, s
- buf
);
90 fhd
->file_pos
= g_strndup (s
+ 1, len
- 1); /* ignore '\n' */
91 file_list
= g_list_prepend (file_list
, fhd
);
99 /* --------------------------------------------------------------------------------------------- */
102 file_history_list_write (const GList
* file_list
)
106 gboolean write_error
= FALSE
;
108 fn
= mc_config_get_full_path (MC_FILEPOS_FILE
);
112 mc_util_make_backup_if_possible (fn
, TMP_SUFFIX
);
119 s
= g_string_sized_new (128);
121 for (; file_list
!= NULL
&& !write_error
; file_list
= g_list_next (file_list
))
123 file_history_data_t
*fhd
= (file_history_data_t
*) file_list
->data
;
125 g_string_append (s
, fhd
->file_name
);
126 if (fhd
->file_pos
!= NULL
)
128 g_string_append_c (s
, ' ');
129 g_string_append (s
, fhd
->file_pos
);
132 write_error
= (fprintf (f
, "%s\n", s
->str
) < 0);
133 g_string_truncate (s
, 0);
136 g_string_free (s
, TRUE
);
142 mc_util_restore_from_backup_if_possible (fn
, TMP_SUFFIX
);
144 mc_util_unlink_backup_if_possible (fn
, TMP_SUFFIX
);
149 /* --------------------------------------------------------------------------------------------- */
152 file_history_create_item (history_descriptor_t
* hd
, void *data
)
154 file_history_data_t
*fhd
= (file_history_data_t
*) data
;
157 width
= str_term_width1 (fhd
->file_name
);
158 hd
->max_width
= MAX (width
, hd
->max_width
);
160 listbox_add_item (hd
->listbox
, LISTBOX_APPEND_AT_END
, 0, fhd
->file_name
, fhd
->file_pos
, TRUE
);
161 /* fhd->file_pos is not copied, NULLize it to prevent double free */
162 fhd
->file_pos
= NULL
;
165 /* --------------------------------------------------------------------------------------------- */
168 file_history_release_item (history_descriptor_t
* hd
, WLEntry
* le
)
170 file_history_data_t
*fhd
;
174 fhd
= g_new (file_history_data_t
, 1);
175 fhd
->file_name
= le
->text
;
177 fhd
->file_pos
= (char *) le
->data
;
183 /* --------------------------------------------------------------------------------------------- */
186 file_history_free_item (void *data
)
188 file_history_data_t
*fhd
= (file_history_data_t
*) data
;
190 g_free (fhd
->file_name
);
191 g_free (fhd
->file_pos
);
195 /* --------------------------------------------------------------------------------------------- */
196 /*** public functions ****************************************************************************/
197 /* --------------------------------------------------------------------------------------------- */
200 * Show file history and return the selected file
202 * @param w widget used for positioning of history window
203 * @param action to do with file (edit, view, etc)
205 * @return name of selected file, A newly allocated string.
208 show_file_history (const Widget
* w
, int *action
)
212 history_descriptor_t hd
;
214 file_list
= file_history_list_read ();
215 if (file_list
== NULL
)
218 len
= g_list_length (file_list
);
220 file_list
= g_list_last (file_list
);
222 history_descriptor_init (&hd
, w
->rect
.y
, w
->rect
.x
, file_list
, 0);
223 /* redefine list-specific functions */
224 hd
.create
= file_history_create_item
;
225 hd
.release
= file_history_release_item
;
226 hd
.free
= file_history_free_item
;
230 hd
.list
= g_list_first (hd
.list
);
232 /* Has history cleaned up or not? */
233 if (len
!= g_list_length (hd
.list
))
235 hd
.list
= g_list_reverse (hd
.list
);
236 file_history_list_write (hd
.list
);
239 g_list_free_full (hd
.list
, (GDestroyNotify
) file_history_free_item
);
246 /* --------------------------------------------------------------------------------------------- */