root/src/file_history.c

/* [previous][next][first][last][top][bottom][index][help]  */

DEFINITIONS

This source file includes following definitions.
  1. file_history_list_read
  2. file_history_list_write
  3. file_history_create_item
  4. file_history_release_item
  5. file_history_free_item
  6. show_file_history

   1 /*
   2    Load and show history of edited and viewed files
   3 
   4    Copyright (C) 2019
   5    Free Software Foundation, Inc.
   6 
   7    Written by:
   8    Andrew Borodin <aborodin@vmail.ru>, 2019.
   9 
  10    This file is part of the Midnight Commander.
  11 
  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.
  16 
  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.
  21 
  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/>.
  24  */
  25 
  26 #include <config.h>
  27 
  28 #include <stdio.h>              /* file functions */
  29 
  30 #include "lib/global.h"
  31 
  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 */
  36 
  37 #include "file_history.h"
  38 
  39 /*** global variables ****************************************************************************/
  40 
  41 /*** file scope macro definitions ****************************************************************/
  42 
  43 #define TMP_SUFFIX ".tmp"
  44 
  45 /*** file scope type declarations ****************************************************************/
  46 
  47 typedef struct file_history_data_t
  48 {
  49     char *file_name;
  50     char *file_pos;
  51 } file_history_data_t;
  52 
  53 /*** file scope variables ************************************************************************/
  54 
  55 /* --------------------------------------------------------------------------------------------- */
  56 /*** file scope functions ************************************************************************/
  57 /* --------------------------------------------------------------------------------------------- */
  58 
  59 static GList *
  60 file_history_list_read (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
  61 {
  62     char *fn;
  63     FILE *f;
  64     char buf[MC_MAXPATHLEN + 100];
  65     GList *file_list = NULL;
  66 
  67     /* open file with positions */
  68     fn = mc_config_get_full_path (MC_FILEPOS_FILE);
  69     if (fn == NULL)
  70         return NULL;
  71 
  72     f = fopen (fn, "r");
  73     g_free (fn);
  74     if (f == NULL)
  75         return NULL;
  76 
  77     while (fgets (buf, sizeof (buf), f) != NULL)
  78     {
  79         char *s;
  80         file_history_data_t *fhd;
  81         size_t len;
  82 
  83         s = strrchr (buf, ' ');
  84         /* FIXME: saved file position info is present in filepos file */
  85         fhd = g_new (file_history_data_t, 1);
  86         fhd->file_name = g_strndup (buf, s - buf);
  87         len = strlen (s + 1);
  88         fhd->file_pos = g_strndup (s + 1, len - 1);     /* ignore '\n' */
  89         file_list = g_list_prepend (file_list, fhd);
  90     }
  91 
  92     fclose (f);
  93 
  94     return file_list;
  95 }
  96 
  97 /* --------------------------------------------------------------------------------------------- */
  98 
  99 static void
 100 file_history_list_write (const GList * file_list)
     /* [previous][next][first][last][top][bottom][index][help]  */
 101 {
 102     char *fn;
 103     FILE *f;
 104     gboolean write_error = FALSE;
 105 
 106     fn = mc_config_get_full_path (MC_FILEPOS_FILE);
 107     if (fn == NULL)
 108         return;
 109 
 110     mc_util_make_backup_if_possible (fn, TMP_SUFFIX);
 111 
 112     f = fopen (fn, "w");
 113     if (f != NULL)
 114     {
 115         GString *s;
 116 
 117         s = g_string_sized_new (128);
 118 
 119         for (; file_list != NULL && !write_error; file_list = g_list_next (file_list))
 120         {
 121             file_history_data_t *fhd = (file_history_data_t *) file_list->data;
 122 
 123             g_string_append (s, fhd->file_name);
 124             if (fhd->file_pos != NULL)
 125             {
 126                 g_string_append_c (s, ' ');
 127                 g_string_append (s, fhd->file_pos);
 128             }
 129 
 130             write_error = (fprintf (f, "%s\n", s->str) < 0);
 131             g_string_truncate (s, 0);
 132         }
 133 
 134         g_string_free (s, TRUE);
 135 
 136         fclose (f);
 137     }
 138 
 139     if (write_error)
 140         mc_util_restore_from_backup_if_possible (fn, TMP_SUFFIX);
 141     else
 142         mc_util_unlink_backup_if_possible (fn, TMP_SUFFIX);
 143 
 144     g_free (fn);
 145 }
 146 
 147 /* --------------------------------------------------------------------------------------------- */
 148 
 149 static void
 150 file_history_create_item (history_descriptor_t * hd, void *data)
     /* [previous][next][first][last][top][bottom][index][help]  */
 151 {
 152     file_history_data_t *fhd = (file_history_data_t *) data;
 153     size_t width;
 154 
 155     width = str_term_width1 (fhd->file_name);
 156     hd->max_width = MAX (width, hd->max_width);
 157 
 158     listbox_add_item (hd->listbox, LISTBOX_APPEND_AT_END, 0, fhd->file_name, fhd->file_pos, TRUE);
 159     /* fhd->file_pos is not copied, NULLize it to prevent double free */
 160     fhd->file_pos = NULL;
 161 }
 162 
 163 /* --------------------------------------------------------------------------------------------- */
 164 
 165 static void *
 166 file_history_release_item (history_descriptor_t * hd, WLEntry * le)
     /* [previous][next][first][last][top][bottom][index][help]  */
 167 {
 168     file_history_data_t *fhd;
 169 
 170     (void) hd;
 171 
 172     fhd = g_new (file_history_data_t, 1);
 173     fhd->file_name = le->text;
 174     le->text = NULL;
 175     fhd->file_pos = (char *) le->data;
 176     le->data = NULL;
 177 
 178     return fhd;
 179 }
 180 
 181 /* --------------------------------------------------------------------------------------------- */
 182 
 183 static void
 184 file_history_free_item (void *data)
     /* [previous][next][first][last][top][bottom][index][help]  */
 185 {
 186     file_history_data_t *fhd = (file_history_data_t *) data;
 187 
 188     g_free (fhd->file_name);
 189     g_free (fhd->file_pos);
 190     g_free (fhd);
 191 }
 192 
 193 /* --------------------------------------------------------------------------------------------- */
 194 /*** public functions ****************************************************************************/
 195 /* --------------------------------------------------------------------------------------------- */
 196 
 197 /**
 198  * Show file history and return the selected file
 199  *
 200  * @param w widget used for positioning of history window
 201  * @param action to do with file (edit, view, etc)
 202  *
 203  * @return name of selected file, A newly allocated string.
 204  */
 205 char *
 206 show_file_history (const Widget * w, int *action)
     /* [previous][next][first][last][top][bottom][index][help]  */
 207 {
 208     GList *file_list;
 209     size_t len;
 210     history_descriptor_t hd;
 211 
 212     file_list = file_history_list_read ();
 213     if (file_list == NULL)
 214         return NULL;
 215 
 216     len = g_list_length (file_list);
 217 
 218     file_list = g_list_last (file_list);
 219 
 220     history_descriptor_init (&hd, w->y, w->x, file_list, 0);
 221     /* redefine list-specific functions */
 222     hd.create = file_history_create_item;
 223     hd.release = file_history_release_item;
 224     hd.free = file_history_free_item;
 225 
 226     history_show (&hd);
 227 
 228     hd.list = g_list_first (hd.list);
 229 
 230     /* Has history cleaned up or not? */
 231     if (len != g_list_length (hd.list))
 232         file_history_list_write (hd.list);
 233 
 234     g_list_free_full (hd.list, (GDestroyNotify) file_history_free_item);
 235 
 236     *action = hd.action;
 237 
 238     return hd.text;
 239 }
 240 
 241 /* --------------------------------------------------------------------------------------------- */

/* [previous][next][first][last][top][bottom][index][help]  */