gtkfilesel.c
来自「gtk是linux一款强大的夸平台的图形化开发工具」· C语言 代码 · 共 2,416 行 · 第 1/5 页
C
2,416 行
if (fs->history_pulldown) { gtk_file_selection_update_history_menu (fs, cmpl_reference_position (cmpl_state)); } }}static voidgtk_file_selection_abort (GtkFileSelection *fs){ gchar err_buf[256]; sprintf (err_buf, _("Directory unreadable: %s"), cmpl_strerror (cmpl_errno)); /* BEEP gdk_beep(); */ if (fs->selection_entry) gtk_label_set_text (GTK_LABEL (fs->selection_text), err_buf);}/**********************************************************************//* External Interface *//**********************************************************************//* The four completion state selectors */static gchar*cmpl_updated_text (CompletionState* cmpl_state){ return cmpl_state->updated_text;}static gintcmpl_updated_dir (CompletionState* cmpl_state){ return cmpl_state->re_complete;}static gchar*cmpl_reference_position (CompletionState* cmpl_state){ return cmpl_state->reference_dir->fullname;}static gintcmpl_last_valid_char (CompletionState* cmpl_state){ return cmpl_state->last_valid_char;}static gchar*cmpl_completion_fullname (gchar* text, CompletionState* cmpl_state){ static char nothing[2] = ""; if (!cmpl_state_okay (cmpl_state)) { return nothing; } else if (text[0] == '/') { strcpy (cmpl_state->updated_text, text); } else if (text[0] == '~') { CompletionDir* dir; char* slash; dir = open_user_dir (text, cmpl_state); if (!dir) { /* spencer says just return ~something, so * for now just do it. */ strcpy (cmpl_state->updated_text, text); } else { strcpy (cmpl_state->updated_text, dir->fullname); slash = strchr (text, '/'); if (slash) strcat (cmpl_state->updated_text, slash); } } else { strcpy (cmpl_state->updated_text, cmpl_state->reference_dir->fullname); if (strcmp (cmpl_state->reference_dir->fullname, "/") != 0) strcat (cmpl_state->updated_text, "/"); strcat (cmpl_state->updated_text, text); } return cmpl_state->updated_text;}/* The three completion selectors */static gchar*cmpl_this_completion (PossibleCompletion* pc){ return pc->text;}static gintcmpl_is_directory (PossibleCompletion* pc){ return pc->is_directory;}static gintcmpl_is_a_completion (PossibleCompletion* pc){ return pc->is_a_completion;}/**********************************************************************//* Construction, deletion *//**********************************************************************/static CompletionState*cmpl_init_state (void){ gchar getcwd_buf[2*MAXPATHLEN]; CompletionState *new_state; new_state = g_new (CompletionState, 1); /* We don't use getcwd() on SUNOS, because, it does a popen("pwd") * and, if that wasn't bad enough, hangs in doing so. */#if defined(sun) && !defined(__SVR4) if (!getwd (getcwd_buf))#else if (!getcwd (getcwd_buf, MAXPATHLEN))#endif { /* Oh joy, we can't get the current directory. Um..., we should have * a root directory, right? Right? (Probably not portable to non-Unix) */ strcpy (getcwd_buf, "/"); }tryagain: new_state->reference_dir = NULL; new_state->completion_dir = NULL; new_state->active_completion_dir = NULL; new_state->directory_storage = NULL; new_state->directory_sent_storage = NULL; new_state->last_valid_char = 0; new_state->updated_text = g_new (gchar, MAXPATHLEN); new_state->updated_text_alloc = MAXPATHLEN; new_state->the_completion.text = g_new (gchar, MAXPATHLEN); new_state->the_completion.text_alloc = MAXPATHLEN; new_state->user_dir_name_buffer = NULL; new_state->user_directories = NULL; new_state->reference_dir = open_dir (getcwd_buf, new_state); if (!new_state->reference_dir) { /* Directories changing from underneath us, grumble */ strcpy (getcwd_buf, "/"); goto tryagain; } return new_state;}static voidcmpl_free_dir_list(GList* dp0){ GList *dp = dp0; while (dp) { free_dir (dp->data); dp = dp->next; } g_list_free(dp0);}static voidcmpl_free_dir_sent_list(GList* dp0){ GList *dp = dp0; while (dp) { free_dir_sent (dp->data); dp = dp->next; } g_list_free(dp0);}static voidcmpl_free_state (CompletionState* cmpl_state){ cmpl_free_dir_list (cmpl_state->directory_storage); cmpl_free_dir_sent_list (cmpl_state->directory_sent_storage); if (cmpl_state->user_dir_name_buffer) g_free (cmpl_state->user_dir_name_buffer); if (cmpl_state->user_directories) g_free (cmpl_state->user_directories); if (cmpl_state->the_completion.text) g_free (cmpl_state->the_completion.text); if (cmpl_state->updated_text) g_free (cmpl_state->updated_text); g_free (cmpl_state);}static voidfree_dir(CompletionDir* dir){ g_free(dir->fullname); g_free(dir);}static voidfree_dir_sent(CompletionDirSent* sent){ g_free(sent->name_buffer); g_free(sent->entries); g_free(sent);}static voidprune_memory_usage(CompletionState *cmpl_state){ GList* cdsl = cmpl_state->directory_sent_storage; GList* cdl = cmpl_state->directory_storage; GList* cdl0 = cdl; gint len = 0; for(; cdsl && len < CMPL_DIRECTORY_CACHE_SIZE; len += 1) cdsl = cdsl->next; if (cdsl) { cmpl_free_dir_sent_list(cdsl->next); cdsl->next = NULL; } cmpl_state->directory_storage = NULL; while (cdl) { if (cdl->data == cmpl_state->reference_dir) cmpl_state->directory_storage = g_list_prepend(NULL, cdl->data); else free_dir (cdl->data); cdl = cdl->next; } g_list_free(cdl0);}/**********************************************************************//* The main entrances. *//**********************************************************************/static PossibleCompletion*cmpl_completion_matches (gchar* text_to_complete, gchar** remaining_text, CompletionState* cmpl_state){ gchar* first_slash; PossibleCompletion *poss; prune_memory_usage(cmpl_state); g_assert (text_to_complete != NULL); cmpl_state->user_completion_index = -1; cmpl_state->last_completion_text = text_to_complete; cmpl_state->the_completion.text[0] = 0; cmpl_state->last_valid_char = 0; cmpl_state->updated_text_len = -1; cmpl_state->updated_text[0] = 0; cmpl_state->re_complete = FALSE; first_slash = strchr (text_to_complete, '/'); if (text_to_complete[0] == '~' && !first_slash) { /* Text starts with ~ and there is no slash, show all the * home directory completions. */ poss = attempt_homedir_completion (text_to_complete, cmpl_state); update_cmpl(poss, cmpl_state); return poss; } cmpl_state->reference_dir = open_ref_dir (text_to_complete, remaining_text, cmpl_state); if(!cmpl_state->reference_dir) return NULL; cmpl_state->completion_dir = find_completion_dir (*remaining_text, remaining_text, cmpl_state); cmpl_state->last_valid_char = *remaining_text - text_to_complete; if(!cmpl_state->completion_dir) return NULL; cmpl_state->completion_dir->cmpl_index = -1; cmpl_state->completion_dir->cmpl_parent = NULL; cmpl_state->completion_dir->cmpl_text = *remaining_text; cmpl_state->active_completion_dir = cmpl_state->completion_dir; cmpl_state->reference_dir = cmpl_state->completion_dir; poss = attempt_file_completion(cmpl_state); update_cmpl(poss, cmpl_state); return poss;}static PossibleCompletion*cmpl_next_completion (CompletionState* cmpl_state){ PossibleCompletion* poss = NULL; cmpl_state->the_completion.text[0] = 0; if(cmpl_state->user_completion_index >= 0) poss = attempt_homedir_completion(cmpl_state->last_completion_text, cmpl_state); else poss = attempt_file_completion(cmpl_state); update_cmpl(poss, cmpl_state); return poss;}/**********************************************************************//* Directory Operations *//**********************************************************************//* Open the directory where completion will begin from, if possible. */static CompletionDir*open_ref_dir(gchar* text_to_complete, gchar** remaining_text, CompletionState* cmpl_state){ gchar* first_slash; CompletionDir *new_dir; first_slash = strchr(text_to_complete, '/'); if (text_to_complete[0] == '/' || !cmpl_state->reference_dir) { new_dir = open_dir("/", cmpl_state); if(new_dir) *remaining_text = text_to_complete + 1; } else if (text_to_complete[0] == '~') { new_dir = open_user_dir(text_to_complete, cmpl_state); if(new_dir) { if(first_slash) *remaining_text = first_slash + 1; else *remaining_text = text_to_complete + strlen(text_to_complete); } else { return NULL; } } else { *remaining_text = text_to_complete; new_dir = open_dir(cmpl_state->reference_dir->fullname, cmpl_state); } if(new_dir) { new_dir->cmpl_index = -1; new_dir->cmpl_parent = NULL; } return new_dir;}/* open a directory by user name */static CompletionDir*open_user_dir(gchar* text_to_complete, CompletionState *cmpl_state){ gchar *first_slash; gint cmp_len; g_assert(text_to_complete && text_to_complete[0] == '~'); first_slash = strchr(text_to_complete, '/'); if (first_slash) cmp_len = first_slash - text_to_complete - 1; else cmp_len = strlen(text_to_complete + 1); if(!cmp_len) { /* ~/ */ gchar *homedir = g_get_home_dir (); if (homedir) return open_dir(homedir, cmpl_state); else return NULL; } else { /* ~user/ */ char* copy = g_new(char, cmp_len + 1); struct passwd *pwd; strncpy(copy, text_to_complete + 1, cmp_len); copy[cmp_len] = 0; pwd = getpwnam(copy); g_free(copy); if (!pwd) { cmpl_errno = errno; return NULL; } return open_dir(pwd->pw_dir, cmpl_state); }}/* open a directory relative the the current relative directory */static CompletionDir*open_relative_dir(gchar* dir_name, CompletionDir* dir, CompletionState *cmpl_state){ gchar path_buf[2*MAXPATHLEN]; if(dir->fullname_len + strlen(dir_name) + 2 >= MAXPATHLEN) { cmpl_errno = CMPL_ERRNO_TOO_LONG; return NULL; } strcpy(path_buf, dir->fullname); if(dir->fullname_len > 1) { path_buf[dir->fullname_len] = '/'; strcpy(path_buf + dir->fullname_len + 1, dir_name); } else { strcpy(path_buf + dir->fullname_len, dir_name); } return open_dir(path_buf, cmpl_state);}/* after the cache lookup fails, really open a new directory */static CompletionDirSent*open_new_dir(gchar* dir_name, struct stat* sbuf, gboolean stat_subdirs){ CompletionDirSent* sent; DIR* directory; gchar *buffer_ptr; struct dirent *dirent_ptr; gint buffer_size = 0; gint entry_count = 0; gint i;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?