📄 gntfilesel.c
字号:
#include "gntbutton.h"#include "gntentry.h"#include "gntfilesel.h"#include "gntlabel.h"#include "gntmarshal.h"#include "gntstyle.h"#include "gnttree.h"#include <string.h>#include <sys/types.h>#include <sys/stat.h>#include <unistd.h>#if 0#include <glob.h>#endifenum{ SIG_FILE_SELECTED, SIGS};static GntWindowClass *parent_class = NULL;static guint signals[SIGS] = { 0 };static void (*orig_map)(GntWidget *widget);static voidgnt_file_sel_destroy(GntWidget *widget){ GntFileSel *sel = GNT_FILE_SEL(widget); g_free(sel->current); g_free(sel->suggest); if (sel->tags) { g_list_foreach(sel->tags, (GFunc)g_free, NULL); g_list_free(sel->tags); }}#if !GLIB_CHECK_VERSION(2,8,0)/* ripped from glib/gfileutils.c */static gchar *g_build_path_va (const gchar *separator, gchar **str_array){ GString *result; gint separator_len = strlen (separator); gboolean is_first = TRUE; gboolean have_leading = FALSE; const gchar *single_element = NULL; const gchar *next_element; const gchar *last_trailing = NULL; gint i = 0; result = g_string_new (NULL); next_element = str_array[i++]; while (TRUE) { const gchar *element; const gchar *start; const gchar *end; if (next_element) { element = next_element; next_element = str_array[i++]; } else break; /* Ignore empty elements */ if (!*element) continue; start = element; if (separator_len) { while (start && strncmp (start, separator, separator_len) == 0) start += separator_len; } end = start + strlen (start); if (separator_len) { while (end >= start + separator_len && strncmp (end - separator_len, separator, separator_len) == 0) end -= separator_len; last_trailing = end; while (last_trailing >= element + separator_len && strncmp (last_trailing - separator_len, separator, separator_len) == 0) last_trailing -= separator_len; if (!have_leading) { /* If the leading and trailing separator strings are in the * same element and overlap, the result is exactly that element */ if (last_trailing <= start) single_element = element; g_string_append_len (result, element, start - element); have_leading = TRUE; } else single_element = NULL; } if (end == start) continue; if (!is_first) g_string_append (result, separator); g_string_append_len (result, start, end - start); is_first = FALSE; } if (single_element) { g_string_free (result, TRUE); return g_strdup (single_element); } else { if (last_trailing) g_string_append (result, last_trailing); return g_string_free (result, FALSE); }}static gchar *g_build_pathv (const gchar *separator, gchar **args){ if (!args) return NULL; return g_build_path_va (separator, args);}#endifstatic char *process_path(const char *path){ char **splits = NULL; int i, j; char *str, *ret; splits = g_strsplit(path, G_DIR_SEPARATOR_S, -1); for (i = 0, j = 0; splits[i]; i++) { if (strcmp(splits[i], ".") == 0) { } else if (strcmp(splits[i], "..") == 0) { if (j) j--; } else { if (i != j) { g_free(splits[j]); splits[j] = splits[i]; splits[i] = NULL; } j++; } } g_free(splits[j]); splits[j] = NULL; str = g_build_pathv(G_DIR_SEPARATOR_S, splits); ret = g_strdup_printf(G_DIR_SEPARATOR_S "%s", str); g_free(str); g_strfreev(splits); return ret;}static voidupdate_location(GntFileSel *sel){ char *old; const char *tmp; tmp = sel->suggest ? sel->suggest : (const char*)gnt_tree_get_selection_data(sel->dirsonly ? GNT_TREE(sel->dirs) : GNT_TREE(sel->files)); old = g_strdup_printf("%s%s%s", sel->current, sel->current[1] ? G_DIR_SEPARATOR_S : "", tmp ? tmp : ""); gnt_entry_set_text(GNT_ENTRY(sel->location), old); g_free(old);}static gbooleanis_tagged(GntFileSel *sel, const char *f){ char *ret = g_strdup_printf("%s%s%s", sel->current, sel->current[1] ? G_DIR_SEPARATOR_S : "", f); gboolean find = g_list_find_custom(sel->tags, ret, (GCompareFunc)g_utf8_collate) != NULL; g_free(ret); return find;}GntFile* gnt_file_new_dir(const char *name){ GntFile *file = g_new0(GntFile, 1); file->basename = g_strdup(name); file->type = GNT_FILE_DIR; return file;}GntFile* gnt_file_new(const char *name, unsigned long size){ GntFile *file = g_new0(GntFile, 1); file->basename = g_strdup(name); file->type = GNT_FILE_REGULAR; file->size = size; return file;}static gbooleanlocal_read_fn(const char *path, GList **files, GError **error){ GDir *dir; GntFile *file; const char *str; dir = g_dir_open(path, 0, error); if (dir == NULL || (error && *error)) { return FALSE; } *files = NULL; if (*path != '\0' && strcmp(path, G_DIR_SEPARATOR_S)) { file = gnt_file_new_dir(".."); *files = g_list_prepend(*files, file); } while ((str = g_dir_read_name(dir)) != NULL) { char *fp = g_build_filename(path, str, NULL); struct stat st; if (stat(fp, &st)) { g_printerr("Error stating location %s\n", fp); } else { if (S_ISDIR(st.st_mode)) { file = gnt_file_new_dir(str); } else { file = gnt_file_new(str, (long)st.st_size); } *files = g_list_prepend(*files, file); } g_free(fp); } *files = g_list_reverse(*files); return TRUE;}static voidgnt_file_free(GntFile *file){ g_free(file->fullpath); g_free(file->basename); g_free(file);}static gbooleanlocation_changed(GntFileSel *sel, GError **err){ GList *files, *iter; gboolean success; if (!sel->dirs) return TRUE; gnt_tree_remove_all(GNT_TREE(sel->dirs)); if (sel->files) gnt_tree_remove_all(GNT_TREE(sel->files)); gnt_entry_set_text(GNT_ENTRY(sel->location), NULL); if (sel->current == NULL) { if (GNT_WIDGET_IS_FLAG_SET(GNT_WIDGET(sel), GNT_WIDGET_MAPPED)) gnt_widget_draw(GNT_WIDGET(sel)); return TRUE; } /* XXX:\ * XXX: This is blocking. * XXX:/ */ files = NULL; if (sel->read_fn) success = sel->read_fn(sel->current, &files, err); else success = local_read_fn(sel->current, &files, err); if (!success || *err) { g_printerr("GntFileSel: error opening location %s (%s)\n", sel->current, *err ? (*err)->message : "reason unknown"); return FALSE; } for (iter = files; iter; iter = iter->next) { GntFile *file = iter->data; char *str = file->basename; if (file->type == GNT_FILE_DIR) { gnt_tree_add_row_after(GNT_TREE(sel->dirs), g_strdup(str), gnt_tree_create_row(GNT_TREE(sel->dirs), str), NULL, NULL); if (sel->multiselect && sel->dirsonly && is_tagged(sel, str)) gnt_tree_set_row_flags(GNT_TREE(sel->dirs), (gpointer)str, GNT_TEXT_FLAG_BOLD); } else if (!sel->dirsonly) { char size[128]; snprintf(size, sizeof(size), "%ld", file->size); gnt_tree_add_row_after(GNT_TREE(sel->files), g_strdup(str), gnt_tree_create_row(GNT_TREE(sel->files), str, size, ""), NULL, NULL); if (sel->multiselect && is_tagged(sel, str)) gnt_tree_set_row_flags(GNT_TREE(sel->files), (gpointer)str, GNT_TEXT_FLAG_BOLD); } } g_list_foreach(files, (GFunc)gnt_file_free, NULL); g_list_free(files); if (GNT_WIDGET_IS_FLAG_SET(GNT_WIDGET(sel), GNT_WIDGET_MAPPED)) gnt_widget_draw(GNT_WIDGET(sel)); return TRUE;}static gbooleandir_key_pressed(GntTree *tree, const char *key, GntFileSel *sel){ if (strcmp(key, "\r") == 0) { char *str = g_strdup(gnt_tree_get_selection_data(tree)); char *path, *dir; if (!str) return TRUE; path = g_build_filename(sel->current, str, NULL); dir = g_path_get_basename(sel->current); if (!gnt_file_sel_set_current_location(sel, path)) { gnt_tree_set_selected(tree, str); } else if (strcmp(str, "..") == 0) { gnt_tree_set_selected(tree, dir); } g_free(dir); g_free(str); g_free(path); return TRUE; } return FALSE;}static gbooleanlocation_key_pressed(GntTree *tree, const char *key, GntFileSel *sel){ char *path; char *str;#if 0 int count; glob_t gl; struct stat st; int glob_ret;#endif if (strcmp(key, "\r")) return FALSE; str = (char*)gnt_entry_get_text(GNT_ENTRY(sel->location)); if (*str == G_DIR_SEPARATOR) path = g_strdup(str); else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -