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 #include <xview/xview.h>
31 #include <xview/panel.h>
32 /* To have SunOS 5.5 happy about MAXNAMELEN (in SunOS 4, it is already
33  defined in sys/dirent.h): */
34 #include <sys/param.h>
35 #include <sys/stat.h>
36 
37 #ifdef __linux
38 /* Posix version: */
39 #define MAXNAMELEN NAME_MAX
40 #else
41 /* To have SunOS4 still working: */
42 #ifndef MAXNAMELEN
43 #define MAXNAMELEN MAXNAMLEN
44 #endif
45 #endif
46 #include "genC.h"
47 #include "misc.h"
48 #include "database.h"
49 #include "linear.h"
50 #include "ri.h"
51 #include "ri-util.h"
52 #include "pipsdbm.h"
53 #include "wpips.h"
54 
55 
56 enum {MENU_PATH_DATA_HANDLER = 54829,
57 /* Maximum size of the directory menu of the main frame: */
59 };
60 
61 
62 /* Note the pedantic way to avoid the warning about unused file_name. :-) */
63 static bool
65 {
66  return TRUE;
67 }
68 
69 
70 static Menu
71 directory_gen_pullright(Menu_item menu_item,
72  Menu_generate op)
73 {
74  Menu menu;
75 
76  if (op == MENU_DISPLAY) {
77  char directory[MAXNAMELEN + 1];
78  char * parent_directory;
79  Menu parent = xv_get(menu_item, MENU_PARENT);
80 
81  debug(2, "directory_gen_pullright", "menu_item = %#x (%s), parent = %#x\n",
82  menu_item, (char *) xv_get(menu_item, MENU_STRING), parent);
83 
84  /* First get the parent directory name that is the title: */
85  parent_directory = (char *) xv_get(parent,
86  XV_KEY_DATA, MENU_PATH_DATA_HANDLER);
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",
92  parent_directory,
93  (char *) xv_get(menu_item, MENU_STRING));
94 
95  if ((char *)(menu = (Menu) xv_get(menu_item, MENU_PULLRIGHT)) != NULL) {
96  /* Well, there is already a menu... we've been already here.
97  Free it first: */
98  /* Free the associated directory name: */
99  free((char *) xv_get(menu, XV_KEY_DATA, MENU_PATH_DATA_HANDLER));
100  xv_destroy(menu);
101  }
102 
103  /* Then initialize it with a new directory menu: */
104  menu = generate_a_directory_menu(directory);
105  }
106  else
107  /* A Menu-Generating procedure has to return the menu in any case: */
108  menu = (Menu)xv_get(menu_item, MENU_PULLRIGHT);
109 
110  return menu;
111 }
112 
113 
114 static void
115 generate_a_directory_menu_notify(Menu menu, Menu_item menu_item)
116 {
117  char full_directory_name[MAXNAMELEN + 1];
118  char * directory_name = (char *) xv_get(menu_item, MENU_STRING);
119  char * parent_path_name =
120  (char *) xv_get(menu, XV_KEY_DATA, MENU_PATH_DATA_HANDLER);
121 
122  (void) sprintf(full_directory_name, "%s/%s",
123  parent_path_name, directory_name);
124  (void) end_directory_notify(full_directory_name);
125 }
126 
127 
128 Menu
129 generate_a_directory_menu(char * directory)
130 {
131  gen_array_t file_list;
132  int file_list_length;
133  int return_code;
134  int i;
135  Menu menu;
136 
137  menu = (Menu) xv_create(
138  (int) NULL, MENU,
139  /* The string is *not* copied in MENU_TITLE_ITEM: */
140  MENU_TITLE_ITEM, strdup(directory),
141  /* and furthermore MENU_TITLE_ITEM is write
142  only, so add the info somewhere else: */
143  XV_KEY_DATA, MENU_PATH_DATA_HANDLER, strdup(directory),
144  /* Add its own notifying procedure: */
145  MENU_NOTIFY_PROC, generate_a_directory_menu_notify,
146  NULL);
147  pips_debug(2, "menu = %p (%s)\n", (void *) menu, directory);
148 
150  xv_set(menu, MENU_APPEND_ITEM,
151  xv_create(XV_NULL, MENUITEM,
152  MENU_STRING,
153  "* Close the current workspace before "
154  "changing directory *",
155  MENU_RELEASE,
156  MENU_INACTIVE, TRUE,
157  NULL),
158  NULL);
159  pips_user_warning("Close the current workspace before changing "
160  "directory.\n");
161  }
162  else
163  {
164  /* Get all the files in the directory: */
165  file_list = gen_array_make(0);
166  return_code = safe_list_files_in_directory(file_list,
167  directory,
168  ".*", directory_exists_p);
169  file_list_length = gen_array_nitems(file_list);
170 
171  if (return_code == -1 || file_list_length == 0)
172  xv_set(menu, MENU_APPEND_ITEM,
173  xv_create(XV_NULL, MENUITEM,
174  MENU_STRING,
175  "* No file in this directory or cannot be open *",
176  MENU_RELEASE,
177  MENU_INACTIVE, TRUE,
178  NULL),
179  NULL);
180  else if (file_list_length > WPIPS_MAX_DIRECTORY_MENU_SIZE) {
181  xv_set(menu, MENU_APPEND_ITEM,
182  xv_create(XV_NULL, MENUITEM,
183  MENU_STRING,
184  "* Too many files. Type directly in the Directory "
185  "line of the main panel *",
186  MENU_RELEASE,
187  MENU_INACTIVE, TRUE,
188  NULL),
189  NULL);
190  user_warning("generate_a_directory_menu",
191  "Too many files in the \"%s\" directory.\n", directory);
192  }
193  else
194  /* Generate a corresponding entry for each file: */
195  for(i = 0; i < file_list_length; i++)
196  {
197  string file_name = gen_array_item(file_list, i);
198  /* Skip the "." directory: */
199  if (strcmp(file_name, ".") != 0) {
200  struct stat buf;
201  char complete_file_name[MAXNAMELEN + 1];
202 
203  Menu_item menu_item =
204  xv_create(XV_NULL, MENUITEM,
205  MENU_STRING, strdup(file_name),
206  MENU_RELEASE,
207  /* The strdup'ed string will also be
208  freed when the menu is discarded: */
209  MENU_RELEASE_IMAGE,
210  NULL);
211 
212  (void) sprintf(complete_file_name, "%s/%s",
213  directory, file_name);
214  if (((stat(complete_file_name, &buf) == 0)
215  && (buf.st_mode & S_IFDIR))) {
216  /* Since a menu item cannot be selected as an item, add an
217  plain item with the same name. Not beautiful
218  hack... :-( */
219  xv_set(menu,
220  MENU_APPEND_ITEM, menu_item,
221  NULL);
222  /* Now recreate another item that will be the submenu: */
223  menu_item =
224  xv_create(XV_NULL, MENUITEM,
225  MENU_STRING, strdup(file_name),
226  MENU_RELEASE,
227  /* The strdup'ed string will also be
228  freed when the menu is discarded: */
229  MENU_RELEASE_IMAGE,
230  /* Put a right menu on each directory
231  entry: */
232  MENU_GEN_PULLRIGHT, directory_gen_pullright,
233  NULL);
234  pips_debug(2, " menu_item = %p (%s)\n",
235  (void *) menu_item, file_name);
236  }
237  else
238  /* And disable non-subdirectory entry: */
239  xv_set(menu_item, MENU_INACTIVE, TRUE, NULL);
240 
241  xv_set(menu, MENU_APPEND_ITEM, menu_item, NULL);
242  }
243  }
244  gen_array_full_free(file_list);
245  }
246  return menu;
247 }
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
void free(void *)
GtkWidget * generate_a_directory_menu(char *directory)
@ MENU_PATH_DATA_HANDLER
success end_directory_notify(const char *dir)
Definition: gtk_select.c:103
#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
char * strdup()
static char buf[BSZ]
Definition: split_file.c:157
static string file_name
@ WPIPS_MAX_DIRECTORY_MENU_SIZE
Maximum size of the directory menu of the main frame:
#define MAXNAMELEN
Generate a menu from the current directory to serve as a directory chooser.
static Menu directory_gen_pullright(Menu_item menu_item, Menu_generate op)
static bool accept_all_file_names(char *file_name __attribute__((unused)))
Note the pedantic way to avoid the warning about unused file_name.
static void generate_a_directory_menu_notify(Menu menu, Menu_item menu_item)