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 + -
显示快捷键?