Manual pages: mcmcdiffmceditmcview

root/lib/mcconfig/history.c

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

DEFINITIONS

This source file includes following definitions.
  1. mc_config_history_get
  2. mc_config_history_get_recent_item
  3. mc_config_history_load
  4. mc_config_history_save

   1 /*
   2    Configure module for the Midnight Commander
   3 
   4    Copyright (C) 1994-2025
   5    Free Software Foundation, Inc.
   6 
   7    Authors:
   8    Radek Doulik, 1994, 1995
   9    Miguel de Icaza, 1994, 1995
  10    Jakub Jelinek, 1995
  11    Andrej Borsenkow, 1996
  12    Norbert Warmuth, 1997
  13    Andrew Borodin <aborodin@vmail.ru>, 2009-2023
  14 
  15    This file is part of the Midnight Commander.
  16 
  17    The Midnight Commander is free software: you can redistribute it
  18    and/or modify it under the terms of the GNU General Public License as
  19    published by the Free Software Foundation, either version 3 of the License,
  20    or (at your option) any later version.
  21 
  22    The Midnight Commander is distributed in the hope that it will be useful,
  23    but WITHOUT ANY WARRANTY; without even the implied warranty of
  24    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  25    GNU General Public License for more details.
  26 
  27    You should have received a copy of the GNU General Public License
  28    along with this program.  If not, see <https://www.gnu.org/licenses/>.
  29  */
  30 
  31 /** \file history.c
  32  *  \brief Source: save and load history
  33  */
  34 
  35 #include <config.h>
  36 
  37 #include <stdlib.h>
  38 #include <sys/types.h>
  39 
  40 #include "lib/global.h"
  41 
  42 #include "lib/fileloc.h"  // MC_HISTORY_FILE
  43 #include "lib/strutil.h"
  44 #include "lib/util.h"  // list_append_unique
  45 
  46 #include "lib/mcconfig.h"
  47 
  48 /*** global variables ****************************************************************************/
  49 
  50 /* how much history items are used */
  51 int num_history_items_recorded = 60;
  52 
  53 /*** file scope macro definitions ****************************************************************/
  54 
  55 /*** file scope type declarations ****************************************************************/
  56 
  57 /*** file scope variables ************************************************************************/
  58 
  59 /* --------------------------------------------------------------------------------------------- */
  60 /*** file scope functions ************************************************************************/
  61 /* --------------------------------------------------------------------------------------------- */
  62 
  63 /* --------------------------------------------------------------------------------------------- */
  64 /*** public functions ****************************************************************************/
  65 /* --------------------------------------------------------------------------------------------- */
  66 
  67 /**
  68  * Load the history from the ${XDG_DATA_HOME}/mc/history file.
  69  * It is called with the widgets history name and returns the GList list.
  70  */
  71 
  72 GList *
  73 mc_config_history_get (const char *name)
     /* [previous][next][first][last][top][bottom][index][help]  */
  74 {
  75     GList *hist = NULL;
  76     char *profile;
  77     mc_config_t *cfg;
  78 
  79     if (num_history_items_recorded == 0)  // this is how to disable
  80         return NULL;
  81     if (name == NULL || *name == '\0')
  82         return NULL;
  83 
  84     profile = mc_config_get_full_path (MC_HISTORY_FILE);
  85     cfg = mc_config_init (profile, TRUE);
  86 
  87     hist = mc_config_history_load (cfg, name);
  88 
  89     mc_config_deinit (cfg);
  90     g_free (profile);
  91 
  92     return hist;
  93 }
  94 
  95 /* --------------------------------------------------------------------------------------------- */
  96 
  97 /**
  98  * Get the recent item of a history from the ${XDG_DATA_HOME}/mc/history file.
  99  *
 100  * TODO: get rid of load the entire history to get the only top item.
 101  */
 102 
 103 char *
 104 mc_config_history_get_recent_item (const char *name)
     /* [previous][next][first][last][top][bottom][index][help]  */
 105 {
 106     GList *history;
 107     char *item = NULL;
 108 
 109     history = mc_config_history_get (name);
 110     if (history != NULL)
 111     {
 112         // FIXME: can history->data be NULL?
 113         item = (char *) history->data;
 114         history->data = NULL;
 115         history = g_list_first (history);
 116         g_list_free_full (history, g_free);
 117     }
 118 
 119     return item;
 120 }
 121 
 122 /* --------------------------------------------------------------------------------------------- */
 123 
 124 /**
 125  * Load history from the mc_config
 126  */
 127 GList *
 128 mc_config_history_load (mc_config_t *cfg, const char *name)
     /* [previous][next][first][last][top][bottom][index][help]  */
 129 {
 130     size_t i;
 131     GList *hist = NULL;
 132     char **keys;
 133     size_t keys_num = 0;
 134     GIConv conv = INVALID_CONV;
 135     GString *buffer;
 136 
 137     if (name == NULL || *name == '\0')
 138         return NULL;
 139 
 140     // get number of keys
 141     keys = mc_config_get_keys (cfg, name, &keys_num);
 142     g_strfreev (keys);
 143 
 144     /* create charset conversion handler to convert strings
 145        from utf-8 to system codepage */
 146     if (!mc_global.utf8_display)
 147         conv = str_crt_conv_from ("UTF-8");
 148 
 149     buffer = g_string_sized_new (64);
 150 
 151     for (i = 0; i < keys_num; i++)
 152     {
 153         char key[BUF_TINY];
 154         char *this_entry;
 155 
 156         g_snprintf (key, sizeof (key), "%lu", (unsigned long) i);
 157         this_entry = mc_config_get_string_raw (cfg, name, key, "");
 158 
 159         if (this_entry == NULL)
 160             continue;
 161 
 162         if (conv == INVALID_CONV)
 163             hist = list_append_unique (hist, this_entry);
 164         else
 165         {
 166             g_string_set_size (buffer, 0);
 167             if (str_convert (conv, this_entry, buffer) == ESTR_FAILURE)
 168                 hist = list_append_unique (hist, this_entry);
 169             else
 170             {
 171                 hist = list_append_unique (hist, g_strndup (buffer->str, buffer->len));
 172                 g_free (this_entry);
 173             }
 174         }
 175     }
 176 
 177     g_string_free (buffer, TRUE);
 178     if (conv != INVALID_CONV)
 179         str_close_conv (conv);
 180 
 181     // return pointer to the last entry in the list
 182     return g_list_last (hist);
 183 }
 184 
 185 /* --------------------------------------------------------------------------------------------- */
 186 
 187 /**
 188  * Save history to the mc_config, but don't save config to file
 189  *
 190  * @param cfg mc_config_t object where history is stored in
 191  * @param name history name
 192  * @param h history. If NULL, then the @name group will be removed from @cfg
 193  */
 194 void
 195 mc_config_history_save (mc_config_t *cfg, const char *name, GList *h)
     /* [previous][next][first][last][top][bottom][index][help]  */
 196 {
 197     GIConv conv = INVALID_CONV;
 198     GString *buffer;
 199     int i;
 200 
 201     if (name == NULL || *name == '\0')
 202         return;
 203 
 204     mc_config_del_group (cfg, name);
 205 
 206     if (h == NULL)
 207         return;
 208 
 209     // go to end of list
 210     h = g_list_last (h);
 211 
 212     // go back 60 places
 213     for (i = 0; (i < num_history_items_recorded - 1) && (h->prev != NULL); i++)
 214         h = g_list_previous (h);
 215 
 216     /* create charset conversion handler to convert strings
 217        from system codepage to UTF-8 */
 218     if (!mc_global.utf8_display)
 219         conv = str_crt_conv_to ("UTF-8");
 220 
 221     buffer = g_string_sized_new (64);
 222 
 223     // dump history into profile
 224     for (i = 0; h != NULL; h = g_list_next (h))
 225     {
 226         char key[BUF_TINY];
 227         char *text = (char *) h->data;
 228 
 229         // We shouldn't have null entries, but let's be sure
 230         if (text == NULL)
 231             continue;
 232 
 233         g_snprintf (key, sizeof (key), "%d", i++);
 234 
 235         if (conv == INVALID_CONV)
 236             mc_config_set_string_raw (cfg, name, key, text);
 237         else
 238         {
 239             g_string_set_size (buffer, 0);
 240             if (str_convert (conv, text, buffer) == ESTR_FAILURE)
 241                 mc_config_set_string_raw (cfg, name, key, text);
 242             else
 243                 mc_config_set_string_raw (cfg, name, key, buffer->str);
 244         }
 245     }
 246 
 247     g_string_free (buffer, TRUE);
 248     if (conv != INVALID_CONV)
 249         str_close_conv (conv);
 250 }
 251 
 252 /* --------------------------------------------------------------------------------------------- */

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