📄 ui_bookmark.c
字号:
/* * (SLIK) SimpLIstic sKin functions * (C) 2004 John Ellis * * Author: John Ellis * * 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! */#ifdef HAVE_CONFIG_H# include "config.h"#endif#include "intl.h"#include <stdio.h>#include <stdlib.h>#include <string.h>#include <gtk/gtk.h>#include <gdk/gdkkeysyms.h> /* for key values */#include "ui_bookmark.h"#include "ui_fileops.h"#include "ui_menu.h"#include "ui_misc.h"#include "ui_utildlg.h"#include "ui_tabcomp.h"/* *----------------------------------------------------------------------------- * history lists *----------------------------------------------------------------------------- */#define HISTORY_DEFAULT_KEY_COUNT 16typedef 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,1024,f) || strncmp(s_buf, "#History", 8) != 0) { fclose(f); return FALSE; } while (fgets(s_buf,1024,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){ FILE *f; GList *list; gchar *pathl; pathl = path_from_utf8(path); f = fopen(pathl, "w"); g_free(pathl); if (!f) { gchar *buf; buf = g_strdup_printf(_("Unable to write history lists to: %s\n"), path); print_term(buf); g_free(buf); return FALSE; } fprintf(f, "#History lists\n"); fprintf(f, "\n"); list = g_list_last(history_list); while(list) { HistoryData *hd; GList *work; hd = list->data; list = list->prev; fprintf(f, "[%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) { fprintf(f, "\"%s\"\n", (gchar *)work->data); work = work->prev; } fprintf(f, "\n"); } fprintf(f, "#end\n"); fclose(f); return TRUE;}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; work = work->next; if (strcmp(buf, path) == 0) { hd->list = g_list_remove(hd->list, buf); hd->list = g_list_prepend(hd->list, buf); return; } } hd->list = g_list_prepend(hd->list, g_strdup(path)); if (max == -1) max = HISTORY_DEFAULT_KEY_COUNT; if (max > 0) { while(hd->list && g_list_length(hd->list) > max) { GList *work = g_list_last(hd->list); gchar *buf = work->data; hd->list = g_list_remove(hd->list, buf); g_free(buf); } }}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;}/* *----------------------------------------------------------------------------- * bookmarks *----------------------------------------------------------------------------- */#define BOOKMARK_DATA_KEY "bookmarkdata"#define MARKER_PATH "[path]"#define MARKER_ICON "[icon]"typedef struct _BookMarkData BookMarkData;typedef struct _BookButtonData BookButtonData;typedef struct _BookPropData BookPropData;struct _BookMarkData{ GtkWidget *widget; GtkWidget *box; gchar *key; void (*select_func)(const gchar *path, gpointer data); gpointer select_data; gint no_defaults; gint editable; BookButtonData *active_button;};struct _BookButtonData{ GtkWidget *button; GtkWidget *image; GtkWidget *label; gchar *key; gchar *name; gchar *path; gchar *icon; gchar *parent;};struct _BookPropData{ GtkWidget *name_entry; GtkWidget *path_entry; GtkWidget *icon_entry; BookButtonData *bb;};enum { TARGET_URI_LIST, TARGET_X_URL, TARGET_TEXT_PLAIN};static GtkTargetEntry bookmark_drop_types[] = { { "text/uri-list", 0, TARGET_URI_LIST }, { "x-url/http", 0, TARGET_X_URL }, { "_NETSCAPE_URL", 0, TARGET_X_URL }};#define bookmark_drop_types_n 3static GtkTargetEntry bookmark_drag_types[] = { { "text/uri-list", 0, TARGET_URI_LIST }, { "text/plain", 0, TARGET_TEXT_PLAIN }};#define bookmark_drag_types_n 2static GList *bookmark_widget_list = NULL;static GList *bookmark_default_list = NULL;static void bookmark_populate_all(const gchar *key);static BookButtonData *bookmark_from_string(const gchar *text){ BookButtonData *b; const gchar *path_ptr; const gchar *icon_ptr; b = g_new0(BookButtonData, 1); if (!text) { b->name = g_strdup(_("New Bookmark")); b->path = g_strdup(homedir()); b->key = NULL; return b; } b->key = g_strdup(text); path_ptr = strstr(text, MARKER_PATH); icon_ptr = strstr(text, MARKER_ICON); if (path_ptr && icon_ptr && icon_ptr < path_ptr) { printf("warning, bookmark icon must be after path\n"); return NULL; } if (path_ptr) { gint l; l = path_ptr - text; b->name = g_strndup(text, l); path_ptr += strlen(MARKER_PATH); if (icon_ptr) { l = icon_ptr - path_ptr; b->path = g_strndup(path_ptr, l); } else { b->path = g_strdup(path_ptr); } } else { b->name = g_strdup(text); b->path = g_strdup(""); } if (icon_ptr) { icon_ptr += strlen(MARKER_ICON); b->icon = g_strdup(icon_ptr); } return b;}static void bookmark_free(BookButtonData *b){ if (!b) return; g_free(b->name); g_free(b->path);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -