diff src/history_list.c @ 902:c414002a1f27

Move history_list_*() functions to separate files: history_list.c and history_list.h.
author zas_
date Sun, 20 Jul 2008 14:56:32 +0000
parents
children 4fe8f9656107
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/history_list.c	Sun Jul 20 14:56:32 2008 +0000
@@ -0,0 +1,351 @@
+/*
+ * Geeqie
+ * Copyright (C) 2008 The Geeqie Team
+ *
+ * Authors: John Ellis, Vladimir Nadvornik, Laurent Monin
+ *
+ *
+ * This software is released under the GNU General Public License (GNU GPL).
+ * Please read the included file COPYING for more information.
+ * This software comes with no warranty of any kind, use at your own risk!
+ */
+
+#include "main.h"
+#include "history_list.h"
+
+#include "secure_save.h"
+#include "ui_fileops.h"
+
+/*
+ *-----------------------------------------------------------------------------
+ * history lists
+ *-----------------------------------------------------------------------------
+ */
+
+#define HISTORY_DEFAULT_KEY_COUNT 16
+
+
+typedef struct _HistoryData HistoryData;
+struct _HistoryData
+{
+	gchar *key;
+	GList *list;
+};
+
+static GList *history_list = NULL;
+
+
+static gchar *quoted_from_text(const gchar *text)
+{
+	const gchar *ptr;
+	gint c = 0;
+	gint l = strlen(text);
+
+	if (l == 0) return NULL;
+
+	while (c < l && text[c] !='"') c++;
+	if (text[c] == '"')
+		{
+		gint e;
+		c++;
+		ptr = text + c;
+		e = c;
+		while (e < l && text[e] !='"') e++;
+		if (text[e] == '"')
+			{
+			if (e - c > 0)
+				{
+				return g_strndup(ptr, e - c);
+				}
+			}
+		}
+	return NULL;
+}
+
+gint history_list_load(const gchar *path)
+{
+	FILE *f;
+	gchar *key = NULL;
+	gchar s_buf[1024];
+	gchar *pathl;
+
+	pathl = path_from_utf8(path);
+	f = fopen(pathl, "r");
+	g_free(pathl);
+	if (!f) return FALSE;
+
+	/* first line must start with History comment */
+	if (!fgets(s_buf, sizeof(s_buf), f) ||
+	    strncmp(s_buf, "#History", 8) != 0)
+		{
+		fclose(f);
+		return FALSE;
+		}
+
+	while (fgets(s_buf, sizeof(s_buf), f))
+		{
+		if (s_buf[0]=='#') continue;
+		if (s_buf[0]=='[')
+			{
+			gint c;
+			gchar *ptr;
+
+			ptr = s_buf + 1;
+			c = 0;
+			while (ptr[c] != ']' && ptr[c] != '\n' && ptr[c] != '\0') c++;
+
+			g_free(key);
+			key = g_strndup(ptr, c);
+			}
+		else
+			{
+			gchar *value;
+
+			value = quoted_from_text(s_buf);
+			if (value && key)
+				{
+				history_list_add_to_key(key, value, 0);
+				}
+			g_free(value);
+			}
+		}
+
+	fclose(f);
+
+	g_free(key);
+
+	return TRUE;
+}
+
+gint history_list_save(const gchar *path)
+{
+	SecureSaveInfo *ssi;
+	GList *list;
+	gchar *pathl;
+
+	pathl = path_from_utf8(path);
+	ssi = secure_open(pathl);
+	g_free(pathl);
+	if (!ssi)
+		{
+		log_printf(_("Unable to write history lists to: %s\n"), path);
+		return FALSE;
+		}
+
+	secure_fprintf(ssi, "#History lists\n\n");
+
+	list = g_list_last(history_list);
+	while (list && secsave_errno == SS_ERR_NONE)
+		{
+		HistoryData *hd;
+		GList *work;
+
+		hd = list->data;
+		list = list->prev;
+
+		secure_fprintf(ssi, "[%s]\n", hd->key);
+
+		/* save them inverted (oldest to newest)
+		 * so that when reading they are added correctly
+		 */
+		work = g_list_last(hd->list);
+		while (work && secsave_errno == SS_ERR_NONE)
+			{
+			secure_fprintf(ssi, "\"%s\"\n", (gchar *)work->data);
+			work = work->prev;
+			}
+		secure_fputc(ssi, '\n');
+		}
+
+	secure_fprintf(ssi, "#end\n");
+
+	return (secure_close(ssi) == 0);
+}
+
+static void history_list_free(HistoryData *hd)
+{
+	GList *work;
+
+	if (!hd) return;
+
+	work = hd->list;
+	while (work)
+		{
+		g_free(work->data);
+		work = work->next;
+		}
+
+	g_free(hd->key);
+	g_free(hd);
+}
+
+static HistoryData *history_list_find_by_key(const gchar* key)
+{
+	GList *work = history_list;
+
+	if (!key) return NULL;
+
+	while (work)
+		{
+		HistoryData *hd = work->data;
+		if (strcmp(hd->key, key) == 0) return hd;
+		work = work->next;
+		}
+	return NULL;
+}
+
+const gchar *history_list_find_last_path_by_key(const gchar* key)
+{
+	HistoryData *hd;
+
+	hd = history_list_find_by_key(key);
+	if (!hd || !hd->list) return NULL;
+
+	return hd->list->data;
+}
+
+void history_list_free_key(const gchar *key)
+{
+	HistoryData *hd;
+	hd = history_list_find_by_key(key);
+	if (!hd) return;
+
+	history_list = g_list_remove(history_list, hd);
+	history_list_free(hd);
+}
+
+void history_list_add_to_key(const gchar *key, const gchar *path, gint max)
+{
+	HistoryData *hd;
+	GList *work;
+
+	if (!key || !path) return;
+
+	hd = history_list_find_by_key(key);
+	if (!hd)
+		{
+		hd = g_new(HistoryData, 1);
+		hd->key = g_strdup(key);
+		hd->list = NULL;
+		history_list = g_list_prepend(history_list, hd);
+		}
+
+	/* if already in the list, simply move it to the top */
+	work = hd->list;
+	while (work)
+		{
+		gchar *buf = work->data;
+
+		if (strcmp(buf, path) == 0)
+			{
+			/* if not first, move it */
+			if (work != hd->list)
+				{
+				hd->list = g_list_remove(hd->list, buf);
+				hd->list = g_list_prepend(hd->list, buf);
+				}
+			return;
+			}
+		work = work->next;
+		}
+
+	hd->list = g_list_prepend(hd->list, g_strdup(path));
+
+	if (max == -1) max = HISTORY_DEFAULT_KEY_COUNT;
+	if (max > 0)
+		{
+		gint len = 0;
+		GList *work = hd->list;
+		GList *last = NULL;
+
+		while (work)
+			{
+			len++;
+			last = work;
+			work = work->next;
+			}
+
+		work = last;
+		while (work && len > max)
+			{
+			GList *node = work;
+			work = work->prev;
+
+			g_free(node->data);
+			hd->list = g_list_delete_link(hd->list, node);
+			len--;
+			}
+		}
+}
+
+void history_list_item_change(const gchar *key, const gchar *oldpath, const gchar *newpath)
+{
+	HistoryData *hd;
+	GList *work;
+
+	if (!oldpath) return;
+	hd = history_list_find_by_key(key);
+	if (!hd) return;
+
+	work = hd->list;
+	while (work)
+		{
+		gchar *buf = work->data;
+		if (strcmp(buf, oldpath) == 0)
+			{
+			if (newpath)
+				{
+				work->data = g_strdup(newpath);
+				}
+			else
+				{
+				hd->list = g_list_remove(hd->list, buf);
+				}
+			g_free(buf);
+			return;
+			}
+		work = work->next;
+		}
+}
+
+void history_list_item_move(const gchar *key, const gchar *path, gint direction)
+{
+	HistoryData *hd;
+	GList *work;
+	gint p = 0;
+
+	if (!path) return;
+	hd = history_list_find_by_key(key);
+	if (!hd) return;
+
+	work = hd->list;
+	while (work)
+		{
+		gchar *buf = work->data;
+		if (strcmp(buf, path) == 0)
+			{
+			p += direction;
+			if (p < 0) return;
+			hd->list = g_list_remove(hd->list, buf);
+			hd->list = g_list_insert(hd->list, buf, p);
+			return;
+			}
+		work = work->next;
+		p++;
+		}
+}
+
+void history_list_item_remove(const gchar *key, const gchar *path)
+{
+	history_list_item_change(key, path, NULL);
+}
+
+GList *history_list_get_by_key(const gchar *key)
+{
+	HistoryData *hd;
+
+	hd = history_list_find_by_key(key);
+	if (!hd) return NULL;
+
+	return hd->list;
+}