PIPS
directory_menu.c
Go to the documentation of this file.
1 /*
2 
3  $Id: directory_menu.c 23065 2016-03-02 09:05:50Z coelho $
4 
5  Copyright 1989-2016 MINES ParisTech
6 
7  This file is part of PIPS.
8 
9  PIPS is free software: you can redistribute it and/or modify it
10  under the terms of the GNU General Public License as published by
11  the Free Software Foundation, either version 3 of the License, or
12  any later version.
13 
14  PIPS is distributed in the hope that it will be useful, but WITHOUT ANY
15  WARRANTY; without even the implied warranty of MERCHANTABILITY or
16  FITNESS FOR A PARTICULAR PURPOSE.
17 
18  See the GNU General Public License for more details.
19 
20  You should have received a copy of the GNU General Public License
21  along with PIPS. If not, see <http://www.gnu.org/licenses/>.
22 
23 */
24 #ifdef HAVE_CONFIG_H
25  #include "pips_config.h"
26 #endif
27 /* Generate a menu from the current directory to serve as a directory
28  chooser. */
29 
30 #ifndef lint
31 char vcid_directory_menu[] = "$Id: directory_menu.c 23065 2016-03-02 09:05:50Z coelho $";
32 #endif /* lint */
33 
34 /* To have SunOS 5.5 happy about MAXNAMELEN (in SunOS 4, it is already
35  defined in sys/dirent.h): */
36 #include <sys/param.h>
37 #include <sys/stat.h>
38 
39 #if __linux__ || __bsdi__ || __NetBSD__ || __OpenBSD__ || __FreeBSD__
40 /* Posix version: */
41 #define MAXNAMELEN NAME_MAX
42 #else
43 /* To have SunOS4 still working: */
44 #ifndef MAXNAMELEN
45 #define MAXNAMELEN MAXNAMLEN
46 #endif
47 #endif
48 #include "genC.h"
49 #include "misc.h"
50 #include "database.h"
51 #include "linear.h"
52 #include "ri.h"
53 #include "ri-util.h"
54 #include "pipsdbm.h"
55 
56 #undef test_undefined // also defined in glib included from gtk
57 #include <gtk/gtk.h>
58 #include "gpips.h"
59 
60 
61 enum {
63  /* Maximum size of the directory menu of the main frame: */
65 };
66 
67 #if 0
68 /* Note the pedantic way to avoid the warning about unused file_name. :-) */
69 static bool accept_all_file_names(char * file_name __attribute__ ((unused))) {
70  return TRUE;
71 }
72 #endif
73 
74 static GtkWidget * directory_gen_pullright(GtkWidget * widget) {
75  GtkWidget * parent_menu;
76 
77  parent_menu = gtk_widget_get_parent(widget);
78 
79  char directory[MAXNAMELEN + 1];
80  const char * parent_directory;
81 
82  debug(2, "directory_gen_pullright", "widget = %#x (%s), parent = %#x\n",
83  widget, gpips_gtk_menu_item_get_label(GTK_WIDGET(GTK_MENU_ITEM(widget))), parent_menu);
84 
85  /* First get the parent directory name that is the title: */
86  parent_directory = gtk_menu_get_title(GTK_MENU(parent_menu));
87  debug(2, "directory_gen_pullright", " parent_directory = %s\n",
88  parent_directory);
89 
90  /* Build the new directory name: */
91  (void) sprintf(directory, "%s/%s", parent_directory, gpips_gtk_menu_item_get_label(GTK_WIDGET(GTK_MENU_ITEM(widget))));
92 
93  if (gtk_menu_item_get_submenu(GTK_MENU_ITEM(widget)) != NULL) {
94  /* Well, there is already a menu... we've been already here.
95  Free it first: */
96  /* Free the associated directory name: */
97  GtkWidget * submenu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(widget));
98  gtk_menu_item_set_submenu(GTK_MENU_ITEM(widget), NULL);
99  gtk_widget_destroy(submenu);
100  }
101 
102  /* Then initialize it with a new directory menu: */
103 
104  return generate_a_directory_menu(directory);
105 }
106 
107 static void generate_a_directory_menu_notify(GtkWidget * widget, gpointer data) {
108  GtkWidget * parent;
109  const char * parent_path_name;
110  const char * directory_name;
111  char full_directory_name[MAXNAMELEN + 1];
112  directory_name = gpips_gtk_menu_item_get_label(widget);
113  parent = gtk_widget_get_parent(widget);
114  if(parent == NULL || ! GTK_IS_MENU(parent))
115  parent_path_name = "";
116  else
117  parent_path_name = gtk_menu_get_title(GTK_MENU(parent));
118 
119  (void) sprintf(full_directory_name, "%s/%s", parent_path_name,
120  directory_name);
121  (void) end_directory_notify(full_directory_name);
122 }
123 
124 GtkWidget * generate_a_directory_menu(char * directory) {
125  gen_array_t file_list;
126  int file_list_length;
127  int return_code;
128  int i;
129 
130  GtkWidget * menu;
131 
132  menu = gtk_menu_new();
133  gtk_menu_set_title(GTK_MENU(menu), directory);
134 
135 // menu = (Menu) xv_create((int) NULL, MENU,
136 // /* The string is *not* copied in MENU_TITLE_ITEM: */
137 // MENU_TITLE_ITEM, strdup(directory),
138 // /* and furthermore MENU_TITLE_ITEM is write
139 // only, so add the info somewhere else: */
140 // XV_KEY_DATA, MENU_PATH_DATA_HANDLER, strdup(directory),
141 // /* Add its own notifying procedure: */
142 // MENU_NOTIFY_PROC, generate_a_directory_menu_notify, NULL);
143 
144  pips_debug(2, "menu = %p (%s)\n", (void *) menu, directory);
145 
147  GtkWidget * please_close = gtk_menu_item_new_with_label(
148  "* Close the current workspace before changing directory *");
149  gtk_widget_set_sensitive(please_close, FALSE);
150  gtk_menu_append(GTK_MENU(menu), please_close);
151  pips_user_warning("Close the current workspace before changing "
152  "directory.\n");
153  } else {
154  GtkWidget * file_item;
155  /* Get all the files in the directory: */
156  file_list = gen_array_make(0);
157  return_code = safe_list_files_in_directory(file_list, directory, ".*",
159  file_list_length = gen_array_nitems(file_list);
160 
161  if (return_code == -1 || file_list_length == 0) {
162  file_item = gtk_menu_item_new_with_label(
163  "* No file in this directory or cannot be open *");
164  gtk_widget_set_sensitive(file_item, FALSE);
165  gtk_menu_append(GTK_MENU(menu), file_item);
166  } else if (file_list_length > GPIPS_MAX_DIRECTORY_MENU_SIZE) {
167  file_item
168  = gtk_menu_item_new_with_label(
169  "* Too many files. Type directly in the Directory line of the main panel *");
170  gtk_widget_set_sensitive(file_item, FALSE);
171  gtk_menu_append(GTK_MENU(menu), file_item);
172  user_warning("generate_a_directory_menu",
173  "Too many files in the \"%s\" directory.\n", directory);
174  } else
175  /* Generate a corresponding entry for each file: */
176  for (i = 0; i < file_list_length; i++) {
177  string file_name = gen_array_item(file_list, i);
178  /* Skip the "." directory: */
179  if (strcmp(file_name, ".") != 0) {
180  struct stat buf;
181  char complete_file_name[MAXNAMELEN + 1];
182 
183  file_item = gtk_menu_item_new_with_label(file_name);
184  gtk_menu_append(GTK_MENU(menu), file_item);
185 
186  (void) sprintf(complete_file_name, "%s/%s", directory,
187  file_name);
188  if (((stat(complete_file_name, &buf) == 0) && (buf.st_mode
189  & S_IFDIR))) {
190  /* Since a menu item cannot be selected as an item, add an
191  plain item with the same name. Not beautiful
192  hack... :-( */
193  gtk_menu_item_set_submenu(GTK_MENU_ITEM(file_item),
194  directory_gen_pullright(file_item));
195  g_signal_connect(G_OBJECT(file_item), "activate",
196  G_CALLBACK(generate_a_directory_menu_notify), NULL);
197  pips_debug(2, " file_item = %p (%s)\n",
198  (void *) file_item, file_name);
199  } else {
200  gtk_widget_set_sensitive(file_item, FALSE);
201  }
202  /* And disable non-subdirectory entry: */
203  }
204  }
205  gen_array_full_free(file_list);
206  }
207  gtk_widget_show_all(menu);
208  return menu;
209 }
float a2sf[2] __attribute__((aligned(16)))
USER generates a user error (i.e., non fatal) by printing the given MSG according to the FMT.
Definition: 3dnow.h:3
size_t gen_array_nitems(const gen_array_t a)
Definition: array.c:131
void gen_array_full_free(gen_array_t a)
Definition: array.c:77
gen_array_t gen_array_make(size_t size)
declarations...
Definition: array.c:40
void * gen_array_item(const gen_array_t a, size_t i)
Definition: array.c:143
bool directory_exists_p(const char *name)
Definition: file.c:314
int safe_list_files_in_directory(gen_array_t files, string dir, string re, bool(*file_name_predicate)(const char *))
returns a sorted arg list of files matching regular expression re in directory 'dir' and with file_na...
Definition: file.c:250
GtkWidget * generate_a_directory_menu(char *directory)
char vcid_directory_menu[]
Generate a menu from the current directory to serve as a directory chooser.
#define MAXNAMELEN
lint
static void generate_a_directory_menu_notify(GtkWidget *widget, gpointer data)
static GtkWidget * directory_gen_pullright(GtkWidget *widget)
@ GPIPS_MAX_DIRECTORY_MENU_SIZE
Maximum size of the directory menu of the main frame:
@ MENU_PATH_DATA_HANDLER
success end_directory_notify(const char *dir)
Definition: gtk_select.c:103
const char * gpips_gtk_menu_item_get_label(GtkWidget *w)
Definition: gtk_utils.c:43
#define pips_debug
these macros use the GNU extensions that allow variadic macros, including with an empty list.
Definition: misc-local.h:145
#define pips_user_warning
Definition: misc-local.h:146
#define user_warning(fn,...)
Definition: misc-local.h:262
void debug(const int the_expected_debug_level, const char *calling_function_name, const char *a_message_format,...)
ARARGS0.
Definition: debug.c:189
string db_get_current_workspace_name(void)
the function is used to check that there is some current workspace...
Definition: workspace.c:82
static char buf[BSZ]
Definition: split_file.c:157
static string file_name
static bool accept_all_file_names(char *file_name __attribute__((unused)))
Note the pedantic way to avoid the warning about unused file_name.