⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gtkfilesel.c

📁 gtk是linux一款强大的夸平台的图形化开发工具
💻 C
📖 第 1 页 / 共 5 页
字号:
/* GTK - The GIMP Toolkit * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. *//* * Modified by the GTK+ Team and others 1997-1999.  See the AUTHORS * file for a list of people on the GTK+ Team.  See the ChangeLog * files for a list of changes.  These files are distributed with * GTK+ at ftp://ftp.gtk.org/pub/gtk/.  */#include <stdio.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/param.h>#include <dirent.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <errno.h>#include <pwd.h>#include "fnmatch.h"#include "gdk/gdkkeysyms.h"#include "gtkbutton.h"#include "gtkentry.h"#include "gtkfilesel.h"#include "gtkhbox.h"#include "gtkhbbox.h"#include "gtklabel.h"#include "gtklist.h"#include "gtklistitem.h"#include "gtkmain.h"#include "gtkscrolledwindow.h"#include "gtksignal.h"#include "gtkvbox.h"#include "gtkmenu.h"#include "gtkmenuitem.h"#include "gtkoptionmenu.h"#include "gtkclist.h"#include "gtkdialog.h"#include "gtkintl.h"#define DIR_LIST_WIDTH   180#define DIR_LIST_HEIGHT  180#define FILE_LIST_WIDTH  180#define FILE_LIST_HEIGHT 180/* I've put this here so it doesn't get confused with the  * file completion interface */typedef struct _HistoryCallbackArg HistoryCallbackArg;struct _HistoryCallbackArg{  gchar *directory;  GtkWidget *menu_item;};typedef struct _CompletionState    CompletionState;typedef struct _CompletionDir      CompletionDir;typedef struct _CompletionDirSent  CompletionDirSent;typedef struct _CompletionDirEntry CompletionDirEntry;typedef struct _CompletionUserDir  CompletionUserDir;typedef struct _PossibleCompletion PossibleCompletion;/* Non-external file completion decls and structures *//* A contant telling PRCS how many directories to cache.  Its actually * kept in a list, so the geometry isn't important. */#define CMPL_DIRECTORY_CACHE_SIZE 10/* A constant used to determine whether a substring was an exact * match by first_diff_index() */#define PATTERN_MATCH -1/* The arguments used by all fnmatch() calls below */#define FNMATCH_FLAGS (FNM_PATHNAME | FNM_PERIOD)#define CMPL_ERRNO_TOO_LONG ((1<<16)-1)/* This structure contains all the useful information about a directory * for the purposes of filename completion.  These structures are cached * in the CompletionState struct.  CompletionDir's are reference counted. */struct _CompletionDirSent{  ino_t inode;  time_t mtime;  dev_t device;  gint entry_count;  gchar *name_buffer; /* memory segment containing names of all entries */  struct _CompletionDirEntry *entries;};struct _CompletionDir{  CompletionDirSent *sent;  gchar *fullname;  gint fullname_len;  struct _CompletionDir *cmpl_parent;  gint cmpl_index;  gchar *cmpl_text;};/* This structure contains pairs of directory entry names with a flag saying * whether or not they are a valid directory.  NOTE: This information is used * to provide the caller with information about whether to update its completions * or try to open a file.  Since directories are cached by the directory mtime, * a symlink which points to an invalid file (which will not be a directory), * will not be reevaluated if that file is created, unless the containing * directory is touched.  I consider this case to be worth ignoring (josh). */struct _CompletionDirEntry{  gint is_dir;  gchar *entry_name;};struct _CompletionUserDir{  gchar *login;  gchar *homedir;};struct _PossibleCompletion{  /* accessible fields, all are accessed externally by functions   * declared above   */  gchar *text;  gint is_a_completion;  gint is_directory;  /* Private fields   */  gint text_alloc;};struct _CompletionState{  gint last_valid_char;  gchar *updated_text;  gint updated_text_len;  gint updated_text_alloc;  gint re_complete;  gchar *user_dir_name_buffer;  gint user_directories_len;  gchar *last_completion_text;  gint user_completion_index; /* if >= 0, currently completing ~user */  struct _CompletionDir *completion_dir; /* directory completing from */  struct _CompletionDir *active_completion_dir;  struct _PossibleCompletion the_completion;  struct _CompletionDir *reference_dir; /* initial directory */  GList* directory_storage;  GList* directory_sent_storage;  struct _CompletionUserDir *user_directories;};/* File completion functions which would be external, were they used * outside of this file. */static CompletionState*    cmpl_init_state        (void);static void                cmpl_free_state        (CompletionState *cmpl_state);static gint                cmpl_state_okay        (CompletionState* cmpl_state);static gchar*              cmpl_strerror          (gint);static PossibleCompletion* cmpl_completion_matches(gchar           *text_to_complete,						   gchar          **remaining_text,						   CompletionState *cmpl_state);/* Returns a name for consideration, possibly a completion, this name * will be invalid after the next call to cmpl_next_completion. */static char*               cmpl_this_completion   (PossibleCompletion*);/* True if this completion matches the given text.  Otherwise, this * output can be used to have a list of non-completions. */static gint                cmpl_is_a_completion   (PossibleCompletion*);/* True if the completion is a directory */static gint                cmpl_is_directory      (PossibleCompletion*);/* Obtains the next completion, or NULL */static PossibleCompletion* cmpl_next_completion   (CompletionState*);/* Updating completions: the return value of cmpl_updated_text() will * be text_to_complete completed as much as possible after the most * recent call to cmpl_completion_matches.  For the present * application, this is the suggested replacement for the user's input * string.  You must CALL THIS AFTER ALL cmpl_text_completions have * been received. */static gchar*              cmpl_updated_text       (CompletionState* cmpl_state);/* After updating, to see if the completion was a directory, call * this.  If it was, you should consider re-calling completion_matches. */static gint                cmpl_updated_dir        (CompletionState* cmpl_state);/* Current location: if using file completion, return the current * directory, from which file completion begins.  More specifically, * the cwd concatenated with all exact completions up to the last * directory delimiter('/'). */static gchar*              cmpl_reference_position (CompletionState* cmpl_state);/* backing up: if cmpl_completion_matches returns NULL, you may query * the index of the last completable character into cmpl_updated_text. */static gint                cmpl_last_valid_char    (CompletionState* cmpl_state);/* When the user selects a non-directory, call cmpl_completion_fullname * to get the full name of the selected file. */static gchar*              cmpl_completion_fullname (gchar*, CompletionState* cmpl_state);/* Directory operations. */static CompletionDir* open_ref_dir         (gchar* text_to_complete,					    gchar** remaining_text,					    CompletionState* cmpl_state);static gboolean       check_dir            (gchar *dir_name, 					    struct stat *result, 					    gboolean *stat_subdirs);static CompletionDir* open_dir             (gchar* dir_name,					    CompletionState* cmpl_state);static CompletionDir* open_user_dir        (gchar* text_to_complete,					    CompletionState *cmpl_state);static CompletionDir* open_relative_dir    (gchar* dir_name, CompletionDir* dir,					    CompletionState *cmpl_state);static CompletionDirSent* open_new_dir     (gchar* dir_name, 					    struct stat* sbuf,					    gboolean stat_subdirs);static gint           correct_dir_fullname (CompletionDir* cmpl_dir);static gint           correct_parent       (CompletionDir* cmpl_dir,					    struct stat *sbuf);static gchar*         find_parent_dir_fullname    (gchar* dirname);static CompletionDir* attach_dir           (CompletionDirSent* sent,					    gchar* dir_name,					    CompletionState *cmpl_state);static void           free_dir_sent (CompletionDirSent* sent);static void           free_dir      (CompletionDir  *dir);static void           prune_memory_usage(CompletionState *cmpl_state);/* Completion operations */static PossibleCompletion* attempt_homedir_completion(gchar* text_to_complete,						      CompletionState *cmpl_state);static PossibleCompletion* attempt_file_completion(CompletionState *cmpl_state);static CompletionDir* find_completion_dir(gchar* text_to_complete,					  gchar** remaining_text,					  CompletionState* cmpl_state);static PossibleCompletion* append_completion_text(gchar* text,						  CompletionState* cmpl_state);static gint get_pwdb(CompletionState* cmpl_state);static gint first_diff_index(gchar* pat, gchar* text);static gint compare_user_dir(const void* a, const void* b);static gint compare_cmpl_dir(const void* a, const void* b);static void update_cmpl(PossibleCompletion* poss,			CompletionState* cmpl_state);static void gtk_file_selection_class_init    (GtkFileSelectionClass *klass);static void gtk_file_selection_init          (GtkFileSelection      *filesel);static void gtk_file_selection_destroy       (GtkObject             *object);static gint gtk_file_selection_key_press     (GtkWidget             *widget,					      GdkEventKey           *event,					      gpointer               user_data);static void gtk_file_selection_file_button (GtkWidget *widget,					    gint row, 					    gint column, 					    GdkEventButton *bevent,					    gpointer user_data);static void gtk_file_selection_dir_button (GtkWidget *widget,					   gint row, 					   gint column, 					   GdkEventButton *bevent,					   gpointer data);static void gtk_file_selection_populate      (GtkFileSelection      *fs,					      gchar                 *rel_path,					      gint                   try_complete);static void gtk_file_selection_abort         (GtkFileSelection      *fs);static void gtk_file_selection_update_history_menu (GtkFileSelection       *fs,						    gchar                  *current_dir);static void gtk_file_selection_create_dir (GtkWidget *widget, gpointer data);static void gtk_file_selection_delete_file (GtkWidget *widget, gpointer data);static void gtk_file_selection_rename_file (GtkWidget *widget, gpointer data);static GtkWindowClass *parent_class = NULL;/* Saves errno when something cmpl does fails. */static gint cmpl_errno;GtkTypegtk_file_selection_get_type (void){  static GtkType file_selection_type = 0;  if (!file_selection_type)    {      static const GtkTypeInfo filesel_info =      {	"GtkFileSelection",	sizeof (GtkFileSelection),	sizeof (GtkFileSelectionClass),	(GtkClassInitFunc) gtk_file_selection_class_init,	(GtkObjectInitFunc) gtk_file_selection_init,	/* reserved_1 */ NULL,	/* reserved_2 */ NULL,        (GtkClassInitFunc) NULL,      };      file_selection_type = gtk_type_unique (GTK_TYPE_WINDOW, &filesel_info);    }  return file_selection_type;}static voidgtk_file_selection_class_init (GtkFileSelectionClass *class){  GtkObjectClass *object_class;  object_class = (GtkObjectClass*) class;  parent_class = gtk_type_class (GTK_TYPE_WINDOW);  object_class->destroy = gtk_file_selection_destroy;}static voidgtk_file_selection_init (GtkFileSelection *filesel){  GtkWidget *entry_vbox;  GtkWidget *label;  GtkWidget *list_hbox;  GtkWidget *confirm_area;  GtkWidget *pulldown_hbox;  GtkWidget *scrolled_win;  char *dir_title [2];  char *file_title [2];    filesel->cmpl_state = cmpl_init_state ();  /* The dialog-sized vertical box  */  filesel->main_vbox = gtk_vbox_new (FALSE, 10);  gtk_container_set_border_width (GTK_CONTAINER (filesel), 10);  gtk_container_add (GTK_CONTAINER (filesel), filesel->main_vbox);  gtk_widget_show (filesel->main_vbox);  /* The horizontal box containing create, rename etc. buttons */  filesel->button_area = gtk_hbutton_box_new ();  gtk_button_box_set_layout(GTK_BUTTON_BOX(filesel->button_area), GTK_BUTTONBOX_START);  gtk_button_box_set_spacing(GTK_BUTTON_BOX(filesel->button_area), 0);  gtk_box_pack_start (GTK_BOX (filesel->main_vbox), filesel->button_area, 		      FALSE, FALSE, 0);  gtk_widget_show (filesel->button_area);    gtk_file_selection_show_fileop_buttons(filesel);  /* hbox for pulldown menu */  pulldown_hbox = gtk_hbox_new (TRUE, 5);  gtk_box_pack_start (GTK_BOX (filesel->main_vbox), pulldown_hbox, FALSE, FALSE, 0);  gtk_widget_show (pulldown_hbox);    /* Pulldown menu */  filesel->history_pulldown = gtk_option_menu_new ();  gtk_widget_show (filesel->history_pulldown);  gtk_box_pack_start (GTK_BOX (pulldown_hbox), filesel->history_pulldown, 		      FALSE, FALSE, 0);      /*  The horizontal box containing the directory and file listboxes  */  list_hbox = gtk_hbox_new (FALSE, 5);  gtk_box_pack_start (GTK_BOX (filesel->main_vbox), list_hbox, TRUE, TRUE, 0);  gtk_widget_show (list_hbox);  /* The directories clist */  dir_title[0] = _("Directories");  dir_title[1] = NULL;  filesel->dir_list = gtk_clist_new_with_titles (1, (gchar**) dir_title);  gtk_widget_set_usize (filesel->dir_list, DIR_LIST_WIDTH, DIR_LIST_HEIGHT);  gtk_signal_connect (GTK_OBJECT (filesel->dir_list), "select_row",		      (GtkSignalFunc) gtk_file_selection_dir_button, 		      (gpointer) filesel);  gtk_clist_column_titles_passive (GTK_CLIST (filesel->dir_list));  scrolled_win = gtk_scrolled_window_new (NULL, NULL);  gtk_container_add (GTK_CONTAINER (scrolled_win), filesel->dir_list);  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),				  GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);  gtk_container_set_border_width (GTK_CONTAINER (scrolled_win), 5);  gtk_box_pack_start (GTK_BOX (list_hbox), scrolled_win, TRUE, TRUE, 0);  gtk_widget_show (filesel->dir_list);  gtk_widget_show (scrolled_win);  /* The files clist */  file_title[0] = _("Files");  file_title[1] = NULL;  filesel->file_list = gtk_clist_new_with_titles (1, (gchar**) file_title);  gtk_widget_set_usize (filesel->file_list, FILE_LIST_WIDTH, FILE_LIST_HEIGHT);  gtk_signal_connect (GTK_OBJECT (filesel->file_list), "select_row",		      (GtkSignalFunc) gtk_file_selection_file_button, 		      (gpointer) filesel);  gtk_clist_column_titles_passive (GTK_CLIST (filesel->file_list));  scrolled_win = gtk_scrolled_window_new (NULL, NULL);  gtk_container_add (GTK_CONTAINER (scrolled_win), filesel->file_list);  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),				  GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);  gtk_container_set_border_width (GTK_CONTAINER (scrolled_win), 5);  gtk_box_pack_start (GTK_BOX (list_hbox), scrolled_win, TRUE, TRUE, 0);  gtk_widget_show (filesel->file_list);  gtk_widget_show (scrolled_win);  /* action area for packing buttons into. */  filesel->action_area = gtk_hbox_new (TRUE, 0);  gtk_box_pack_start (GTK_BOX (filesel->main_vbox), filesel->action_area, 		      FALSE, FALSE, 0);  gtk_widget_show (filesel->action_area);    /*  The OK/Cancel button area */  confirm_area = gtk_hbutton_box_new ();  gtk_button_box_set_layout(GTK_BUTTON_BOX(confirm_area), GTK_BUTTONBOX_END);  gtk_button_box_set_spacing(GTK_BUTTON_BOX(confirm_area), 5);  gtk_box_pack_end (GTK_BOX (filesel->main_vbox), confirm_area, FALSE, FALSE, 0);  gtk_widget_show (confirm_area);  /*  The OK button  */  filesel->ok_button = gtk_button_new_with_label (_("OK"));  GTK_WIDGET_SET_FLAGS (filesel->ok_button, GTK_CAN_DEFAULT);  gtk_box_pack_start (GTK_BOX (confirm_area), filesel->ok_button, TRUE, TRUE, 0);  gtk_widget_grab_default (filesel->ok_button);  gtk_widget_show (filesel->ok_button);  /*  The Cancel button  */  filesel->cancel_button = gtk_button_new_with_label (_("Cancel"));  GTK_WIDGET_SET_FLAGS (filesel->cancel_button, GTK_CAN_DEFAULT);  gtk_box_pack_start (GTK_BOX (confirm_area), filesel->cancel_button, TRUE, TRUE, 0);  gtk_widget_show (filesel->cancel_button);  /*  The selection entry widget  */  entry_vbox = gtk_vbox_new (FALSE, 2);  gtk_box_pack_end (GTK_BOX (filesel->main_vbox), entry_vbox, FALSE, FALSE, 0);  gtk_widget_show (entry_vbox);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -