Initial import of gattrib 20040806
[geda-gaf/whiteaudio.git] / gattrib / src / x_fileselect.c
blob3f0574929f1c25745dcfd4b469fa84d9cdef0c98
1 /* gEDA - GPL Electronic Design Automation
2 * gattrib -- gEDA component and net attribute manipulation using spreadsheet.
3 * Copyright (C) 2003 Stuart D. Brorson.
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
19 /*------------------------------------------------------------------
20 * This file holds fcns used to display the file open/save dialog box.
21 * It was cloned from x_fileselect.c in gschem/src, and then hacked
22 * by SDB for use in gattrib.
23 *------------------------------------------------------------------*/
25 #ifdef HAVE_CONFIG_H
26 #include "config.h"
27 #endif
29 /*------------------------------------------------------------------
30 * Includes required to run graphical widgets.
31 *------------------------------------------------------------------*/
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <gtk/gtk.h>
35 #include <gdk/gdk.h>
36 #include <gdk/gdkkeysyms.h>
38 #include <glib.h>
39 #ifdef HAS_GTK22
40 #include <glib-object.h>
41 #endif
43 #include <sys/types.h>
45 #ifdef HAVE_SYS_PARAM_H
46 #include <sys/param.h>
47 #endif
49 #include <sys/stat.h>
51 #ifdef HAVE_UNISTD_H
52 #include <unistd.h>
53 #endif
55 #ifdef HAVE_DIRENT_H
56 #include <dirent.h>
57 #endif
59 #ifdef HAVE_STRING_H
60 #include <string.h>
61 #endif
65 #ifdef HAS_GTK22
66 #include "gtksheet_2_2.h"
67 #include "gtkitementry_2_2.h"
68 #else
69 #include "gtksheet_1_2.h"
70 #include "gtkitementry_1_2.h"
71 #endif
73 /*------------------------------------------------------------------
74 * Gattrib specific includes
75 *------------------------------------------------------------------*/
76 #include <config.h>
77 #include <libgeda/libgeda.h> /* geda library fcns */
78 #include "../include/struct.h" /* typdef and struct declarations */
79 #include "../include/prototype.h" /* function prototypes */
80 #include "../include/globals.h"
81 #include "../include/x_menu.h"
85 /* ----- x_fileselect stuff begins here ----- */
87 #define DIR_LIST_WIDTH 180
88 #define DIR_LIST_HEIGHT 180
89 #define FILE_LIST_WIDTH 180
90 #define FILE_LIST_HEIGHT 180
92 /* ------------------------------------------------------------- *
93 * This destroys the entire FILEDIALOG structure & frees its memory.
94 * There is another fcn which just closes the window.
95 * ------------------------------------------------------------- */
96 void
97 x_fileselect_destroy_window(GtkWidget * widget, FILEDIALOG * f_current)
100 #if DEBUG
101 printf("In x_fileselect_destroy_window, about to destroy window!\n");
102 #endif
103 x_fileselect_free_list_buffers(f_current);
105 if (f_current->directory) {
106 free(f_current->directory);
107 f_current->directory = NULL;
110 if (f_current->filename) {
111 free(f_current->filename);
112 f_current->filename = NULL;
115 gtk_grab_remove(f_current->xfwindow);
116 f_current->toplevel = NULL;
117 f_current->xfwindow = NULL;
118 free(f_current);
119 /* *window = NULL; */
120 return;
124 /* ------------------------------------------------------------- *
126 * ------------------------------------------------------------- */
128 x_fileselect_keypress(GtkWidget * widget, GdkEventKey * event,
129 FILEDIALOG * f_current)
131 if (strcmp(gdk_keyval_name(event->keyval), "Escape") == 0) {
132 x_fileselect_close(NULL, f_current);
133 return TRUE;
136 return FALSE;
139 /* ------------------------------------------------------------- *
141 * ------------------------------------------------------------- */
142 void x_fileselect_init_list_buffers(FILEDIALOG * f_current)
144 int i;
146 /* Shouldn't we malloc something in here?? */
147 for (i = MAX_FILES; i >= 0; i--) {
148 f_current->file_entries[i] = NULL;
151 for (i = MAX_DIRS; i >= 0; i--) {
152 f_current->directory_entries[i] = NULL;
155 return;
159 /* ------------------------------------------------------------- *
161 * ------------------------------------------------------------- */
162 void x_fileselect_free_list_buffers(FILEDIALOG * f_current)
164 int i;
166 for (i = MAX_FILES; i >= 0; i--) {
167 if (f_current->file_entries[i])
168 free(f_current->file_entries[i]);
170 f_current->file_entries[i] = NULL;
173 for (i = MAX_DIRS; i >= 0; i--) {
174 if (f_current->directory_entries[i])
175 free(f_current->directory_entries[i]);
177 f_current->directory_entries[i] = NULL;
179 return;
184 /*********** File Open/Save As... specific code starts here ***********/
185 /* ------------------------------------------------------------- *
187 * ------------------------------------------------------------- */
188 void x_fileselect_update_dirfile(FILEDIALOG * f_current, char *filename)
190 char *temp = NULL;
192 if (f_current->filename) {
193 free(f_current->filename);
194 f_current->filename = NULL;
197 if (f_current->directory) {
198 free(f_current->directory);
199 f_current->directory = NULL;
202 /* this may cause problems on non POSIX complient systems */
203 temp = getcwd(NULL, 1024);
205 if (filename) {
206 f_current->directory = u_basic_strdup(temp);
207 f_current->filename = u_basic_strdup(filename);
209 free(temp);
210 #ifdef __MINGW32__
211 if (u_basic_has_trailing(f_current->directory, PATH_SEPARATER_CHAR)) {
212 temp = u_basic_strdup_multiple(f_current->directory,
213 f_current->filename, NULL);
214 } else {
215 #endif
216 temp = u_basic_strdup_multiple(f_current->directory,
217 PATH_SEPARATER_STRING,
218 f_current->filename, NULL);
219 #ifdef __MINGW32__
221 #endif
223 gtk_entry_set_text(GTK_ENTRY(f_current->filename_entry), temp);
225 } else {
226 f_current->directory = u_basic_strdup(temp);
228 if (f_current->filename) {
229 free(f_current->filename);
230 f_current->filename = NULL;
233 gtk_entry_set_text(GTK_ENTRY(f_current->filename_entry),
234 f_current->directory);
237 free(temp);
239 #if DEBUG
240 printf("In x_fileselect_update_dirfile, directory: %s\n", f_current->directory);
241 #endif
243 return;
247 /* ------------------------------------------------------------- *
249 * ------------------------------------------------------------- */
250 void
251 x_fileselect_setup_list_buffers(FILEDIALOG * f_current,
252 int num_directories, int num_files)
254 int i;
256 for (i = num_files+1; i >= 0; i--) {
257 if (f_current->file_entries[i]) {
258 free(f_current->file_entries[i]);
260 f_current->file_entries[i] = NULL;
263 for (i = num_directories+1; i >= 0; i--) {
264 if (f_current->directory_entries[i]) {
265 free(f_current->directory_entries[i]);
267 f_current->directory_entries[i] = NULL;
269 return;
273 /* ------------------------------------------------------------- *
275 * ------------------------------------------------------------- */
276 /* returns TRUE if the file should be included (passes the filter) */
277 /* else returns FALSE */
278 int x_fileselect_include_file(char *filename, int filter_type)
280 switch (filter_type) {
281 case (FILEDIALOG_SCH_ONLY):
282 if (strstr(filename, ".sch")) {
283 return (TRUE);
285 break;
287 case (FILEDIALOG_SYM_ONLY):
288 if (strstr(filename, ".sym")) {
289 return (TRUE);
291 break;
293 case (FILEDIALOG_SCH_SYM):
294 if (strstr(filename, ".sch") || strstr(filename, ".sym")) {
295 return (TRUE);
297 break;
299 case (FILEDIALOG_ALL_FILES):
300 return (TRUE);
301 break;
304 return (FALSE);
308 /* ------------------------------------------------------------- *
310 * ------------------------------------------------------------- */
311 void x_fileselect_fill_lists(FILEDIALOG * f_current)
313 DIR *directory;
314 struct dirent *dirent_ptr;
315 int num_files = 0;
316 int num_directories = 0;
317 int file_count = 0;
318 int dir_count = 0;
319 struct stat stat_en;
320 char path_buf[MAXPATHLEN * 2];
321 char *text[2];
322 char *temp;
323 int i;
324 int max_width = 0;
325 int width;
326 int first, last, j, done = 0;
327 #ifdef __MINGW32__
328 int has_trailing = FALSE;
329 #endif
331 directory = opendir(f_current->directory);
332 #ifdef DEBUG
333 printf("In x_fileselect_fill_lists, directory = %s\n", directory);
334 #endif
337 #ifdef __MINGW32__
338 has_trailing = u_basic_has_trailing(f_current->directory,
339 PATH_SEPARATER_CHAR);
340 #endif
342 if (!directory) {
343 fprintf(stderr, "Agg, could not open directory: %s\n",
344 f_current->directory);
345 return;
348 while ((dirent_ptr = readdir(directory)) != NULL) {
349 #ifdef __MINGW32__
350 if (has_trailing) {
351 sprintf(path_buf, "%s%s", f_current->directory, dirent_ptr->d_name);
352 } else {
353 #endif
354 sprintf(path_buf, "%s%c%s", f_current->directory,
355 PATH_SEPARATER_CHAR, dirent_ptr->d_name);
356 #ifdef __MINGW32__
358 #endif
360 if (stat(path_buf, &stat_en) >= 0 && S_ISDIR(stat_en.st_mode)) {
361 /* printf("dir: %s\n", path_buf); */
362 num_directories++;
363 } else {
364 /* printf("file: %s\n", path_buf); */
365 num_files++;
370 if (num_directories > MAX_DIRS) {
371 fprintf(stderr, "Too many directories! Increase MAX_DIRS\n");
372 exit(-1);
375 if (num_files > MAX_FILES) {
376 fprintf(stderr, "Too many files! Increase MAX_FILES\n");
377 exit(-1);
380 x_fileselect_setup_list_buffers(f_current, num_directories, num_files);
382 rewinddir(directory);
384 while ((dirent_ptr = readdir(directory)) != NULL) {
385 #ifdef __MINGW32__
386 if (has_trailing) {
387 sprintf(path_buf, "%s%s", f_current->directory, dirent_ptr->d_name);
388 } else {
389 #endif
390 sprintf(path_buf, "%s%c%s", f_current->directory,
391 PATH_SEPARATER_CHAR, dirent_ptr->d_name);
392 #ifdef __MINGW32__
394 #endif
395 if (stat(path_buf, &stat_en) >= 0 && S_ISDIR(stat_en.st_mode) &&
396 (strcmp(dirent_ptr->d_name, ".") != 0)) {
398 f_current->directory_entries[dir_count] = (char *)
399 malloc(sizeof(char) * (strlen(dirent_ptr->d_name) + 2));
401 sprintf(f_current->directory_entries[dir_count],
402 "%s", dirent_ptr->d_name);
403 dir_count++;
405 } else {
406 if (x_fileselect_include_file(dirent_ptr->d_name,
407 f_current->filter_type)) {
408 f_current->file_entries[file_count] = (char *)
409 malloc(sizeof(char) * (strlen(dirent_ptr->d_name) + 1));
410 strcpy(f_current->file_entries[file_count], dirent_ptr->d_name);
411 file_count++;
416 #if DEBUG
417 printf("In x_fileselect_fill_lists, FILE COUNT: %d\n", file_count);
418 #endif
420 /* lame bubble sort */
421 first = 0;
422 last = file_count;
423 while (!done) {
425 done = 1;
426 for (j = first; j < last - 1; j++) {
427 if (strcmp(f_current->file_entries[j],
428 f_current->file_entries[j + 1]) > 0) {
429 temp = f_current->file_entries[j];
430 f_current->file_entries[j] = f_current->file_entries[j + 1];
431 f_current->file_entries[j + 1] = temp;
432 done = 0;
435 last = last - 1;
439 /* lame bubble sort */
440 done = 0;
441 first = 0;
442 last = dir_count;
443 while (!done) {
444 done = 1;
445 for (j = first; j < last - 1; j++) {
446 if (strcmp(f_current->directory_entries[j],
447 f_current->directory_entries[j + 1]) > 0) {
448 temp = f_current->directory_entries[j];
449 f_current->directory_entries[j] =
450 f_current->directory_entries[j + 1];
451 f_current->directory_entries[j + 1] = temp;
452 done = 0;
455 last = last - 1;
459 gtk_clist_freeze(GTK_CLIST(f_current->dir_list));
460 gtk_clist_clear(GTK_CLIST(f_current->dir_list));
461 gtk_clist_freeze(GTK_CLIST(f_current->file_list));
462 gtk_clist_clear(GTK_CLIST(f_current->file_list));
464 text[0] = NULL;
465 text[1] = NULL;
466 max_width = 0;
467 for (i = 0; i < dir_count; i++) {
468 temp = u_basic_strdup_multiple(f_current->directory_entries[i],
469 PATH_SEPARATER_STRING, NULL);
470 text[0] = temp;
471 gtk_clist_append(GTK_CLIST(f_current->dir_list), text);
473 #ifdef HAS_GTK22
474 width =
475 gdk_string_width(gtk_style_get_font(f_current->dir_list->style),
476 f_current->directory_entries[i]);
477 #else
478 width = gdk_string_width(f_current->dir_list->style->font,
479 f_current->directory_entries[i]);
480 #endif
482 if (width > max_width) {
483 gtk_clist_set_column_width(GTK_CLIST(f_current->dir_list), 0, width);
484 max_width = width;
487 free(temp);
488 #if DEBUG
489 printf("In x_fileselect_fill_lists, directory: %s\n", f_current->directory_entries[i]);
490 #endif
493 max_width = 0;
494 for (i = 0; i < file_count; i++) {
495 text[0] = f_current->file_entries[i];
496 gtk_clist_append(GTK_CLIST(f_current->file_list), text);
498 #ifdef HAS_GTK22
499 width =
500 gdk_string_width(gtk_style_get_font(f_current->dir_list->style),
501 f_current->file_entries[i]);
502 #else
503 width = gdk_string_width(f_current->dir_list->style->font,
504 f_current->file_entries[i]);
505 #endif
507 if (width > max_width) {
508 gtk_clist_set_column_width(GTK_CLIST(f_current->
509 file_list), 0, width);
510 max_width = width;
512 #if DEBUG
513 printf("In x_fileselect_fill_lists, file: %s\n", f_current->file_entries[i]);
514 #endif
517 closedir(directory);
518 gtk_clist_thaw(GTK_CLIST(f_current->file_list));
519 gtk_clist_thaw(GTK_CLIST(f_current->dir_list));
520 f_current->last_search = -1;
521 return;
525 /* ------------------------------------------------------------- *
526 * This is a support fcn for the filter menu
527 * ------------------------------------------------------------- */
528 gint x_fileselect_sch_files(GtkWidget * w, FILEDIALOG * f_current)
530 f_current->filter_type = FILEDIALOG_SCH_ONLY;
531 x_fileselect_fill_lists(f_current);
532 return (0);
537 /* ------------------------------------------------------------- *
538 * This is a support fcn for the filter menu
539 * ------------------------------------------------------------- */
540 gint x_fileselect_all_files(GtkWidget * w, FILEDIALOG * f_current)
542 f_current->filter_type = FILEDIALOG_ALL_FILES;
543 x_fileselect_fill_lists(f_current);
544 return (0);
548 /* ------------------------------------------------------------- *
550 * ------------------------------------------------------------- */
551 /* this is from gtktest.c */
552 static GtkWidget *x_fileselect_filter_menu(FILEDIALOG * f_current)
554 GtkWidget *menu;
555 GtkWidget *menuitem;
556 GSList *group;
557 char *buf;
559 menu = gtk_menu_new();
560 group = NULL;
562 buf = g_strdup_printf("sch - Schematics");
563 menuitem = gtk_radio_menu_item_new_with_label(group, buf);
564 free(buf);
565 group = gtk_radio_menu_item_group(GTK_RADIO_MENU_ITEM(menuitem));
566 gtk_menu_append(GTK_MENU(menu), menuitem);
567 gtk_signal_connect(GTK_OBJECT(menuitem), "activate",
568 (GtkSignalFunc) x_fileselect_sch_files, f_current);
569 gtk_widget_show(menuitem);
571 buf = g_strdup_printf("* - All Files");
572 menuitem = gtk_radio_menu_item_new_with_label(group, buf);
573 free(buf);
574 group = gtk_radio_menu_item_group(GTK_RADIO_MENU_ITEM(menuitem));
575 gtk_menu_append(GTK_MENU(menu), menuitem);
576 gtk_signal_connect(GTK_OBJECT(menuitem), "activate",
577 (GtkSignalFunc) x_fileselect_all_files, f_current);
578 gtk_widget_show(menuitem);
580 switch (f_current->filter_type) {
582 case (FILEDIALOG_SCH_ONLY):
583 gtk_menu_set_active(GTK_MENU(menu), 0);
584 break;
586 case (FILEDIALOG_SYM_ONLY):
587 gtk_menu_set_active(GTK_MENU(menu), 1);
588 break;
590 case (FILEDIALOG_SCH_SYM):
591 gtk_menu_set_active(GTK_MENU(menu), 2);
592 break;
594 case (FILEDIALOG_ALL_FILES):
595 gtk_menu_set_active(GTK_MENU(menu), 3);
596 break;
599 return menu;
605 /* ------------------------------------------------------------- *
606 * This fcn just closes the window and does nothing else.
607 * It is invoked when you click "cancel" during a save
608 * operation.
609 * ------------------------------------------------------------- */
610 void x_fileselect_saveas_close(GtkWidget * w, FILEDIALOG * f_current)
612 gtk_widget_destroy(GTK_WIDGET(f_current->xfwindow));
614 #if 0 /* this isn't relavent anymore */
615 w_current = f_current->toplevel;
617 if (f_current->filesel_type == SAVEAS_QUIT) {
618 exit_dialog(w_current);
621 if (f_current->filesel_type == SAVEAS_OPEN) {
622 x_fileselect_setup(w_current, FILESELECT, SAVEAS_OPEN);
625 if (f_current->filesel_type == SAVEAS_NEW) {
626 w_current->page_current->CHANGED = 0;
627 i_callback_file_new(w_current, 0, NULL);
629 #endif
631 /* do nothing if close is pressed for SAVEAS_CLOSE case */
632 return;
636 /* ------------------------------------------------------------- *
637 * This fcn saves out the files and then closes the fileselect
638 * dialog box. It is invoked when you click "save" during a save
639 * operation.
640 * ------------------------------------------------------------- */
641 void x_fileselect_saveas(GtkWidget * w, FILEDIALOG * f_current)
644 TOPLEVEL *w_current;
645 gchar *string;
646 int len;
648 w_current = f_current->toplevel;
650 string = (gchar *) gtk_entry_get_text(GTK_ENTRY(f_current->filename_entry));
652 if (!string) {
653 return;
656 len = strlen(string);
658 if (string[len - 1] != PATH_SEPARATER_CHAR) {
659 if (w_current->page_current->page_filename) {
660 free(w_current->page_current->page_filename);
663 w_current->page_current->page_filename = u_basic_strdup(string);
665 /* Try to do save by calling f_save . . . . */
666 if (f_save(w_current, string)) {
667 s_log_message("Saved As [%s]\n",
668 w_current->page_current->page_filename);
670 /* Update filename for "saveas" operation */
671 x_fileselect_set_filename(w_current, string);
673 w_current->page_current->CHANGED = 0;
674 } else {
675 s_log_message("Could NOT save [%s]\n",
676 w_current->page_current->page_filename);
679 x_fileselect_close(NULL, f_current);
681 #if 0
682 /* What do these do? */
683 if (f_current->filesel_type == SAVEAS_QUIT) {
684 x_window_close(w_current);
685 } else if (f_current->filesel_type == SAVEAS_OPEN) {
686 i_callback_file_open(w_current, 0, NULL);
687 } else if (f_current->filesel_type == SAVEAS_NEW) {
688 i_callback_file_new(w_current, 0, NULL);
689 } else if (f_current->filesel_type == SAVEAS_CLOSE) {
690 i_callback_page_close(w_current, 0, NULL);
692 #endif
694 /* do nothing if SAVEAS_NONE */
695 } else {
696 s_log_message("Specify a Filename!\n");
698 return;
702 /* ------------------------------------------------------------- *
703 * I think this puts the new filename back into pr_current as part
704 * of a "save as" operation. This was originally i_set_filename
705 * in gschem/src/i_basic.c
706 * ------------------------------------------------------------- */
707 void x_fileselect_set_filename(TOPLEVEL * w_current, const char *string)
709 char trunc_string[41];
710 int len;
711 int i;
713 if (!w_current->filename_label) {
714 return;
717 if (string) {
718 len = strlen(string);
719 w_current->DONT_RESIZE = 1;
721 if (w_current->filename_label) {
722 if (len > 40) {
724 trunc_string[0] = '.';
725 trunc_string[1] = '.';
726 trunc_string[2] = '.';
728 trunc_string[40] = '\0';
729 for (i = 39; i > 2; i--) {
730 if (len >= 0) {
731 trunc_string[i] = string[len];
732 } else {
733 break;
735 len--;
738 gtk_label_set(GTK_LABEL(w_current->filename_label), trunc_string);
740 } else {
742 gtk_label_set(GTK_LABEL(w_current->
743 filename_label), (char *) string);
747 return;
751 /* ------------------------------------------------------------- *
753 * ------------------------------------------------------------- */
754 void x_fileselect_change_dir(FILEDIALOG * f_current, char *new_directory)
756 if (new_directory) {
757 chdir(new_directory);
758 x_fileselect_update_dirfile(f_current, NULL);
759 x_fileselect_fill_lists(f_current);
764 /* ------------------------------------------------------------- *
765 * This is the callback from the fileselect "open" button. It does
766 * the following:
767 * 1. It loops over all filenames returned in the CLIST
768 * 2. For each filenname, it calls s_toplevel_open_file, which
769 * reads in the file & fills out pr_current (which is a gloabal).
770 * If this is a new file, it also calls s_sheet_data_add_master_*_list
771 * to fill out the master lists.
772 * ------------------------------------------------------------- */
773 /* don't use widget, since it can be NULL */
774 void x_fileselect_open_file(GtkWidget *w, FILEDIALOG *f_current)
776 PAGE *p_local;
777 char *string;
778 int len;
779 int return_code = 0;
780 int old_num_rows, old_num_cols; /* There is a better way . . . */
782 char *filename = NULL;
783 GList *files;
784 int row;
786 #ifdef DEBUG
787 printf("We have just entered x_fileselect_open_file.\n");
788 #endif
790 /* get GList of selected files */
791 files = (GTK_CLIST(f_current->file_list))->selection;
792 if (files) {
794 old_num_rows = sheet_head->comp_count;
795 old_num_cols = sheet_head->comp_attrib_count;
797 /* iterate over selected files */
798 for (; files; files = files->next) {
799 row = (int) files->data; /* Why do we need to do cast here? */
800 /* because files->data is a void * */
801 gtk_clist_get_text(GTK_CLIST(f_current->file_list), row, 0,
802 &filename);
804 /* allocate space, then stick full, absolute filename into string */
805 string = malloc(strlen(f_current->directory) + strlen(filename) + 2);
806 if (!string) { /* sanity check . . . */
807 /* free(string); freeing a null pointer is bad. */
808 return;
810 /* string is full name of file. */
811 sprintf(string, "%s/%s", f_current->directory, filename);
813 #if DEBUG
814 printf("In x_fileselect_open_file, opening string = %s\n", string);
815 #endif
817 if (first_page == 1) {
818 if (pr_current->page_current->page_filename) {
819 /* Page structure & first page has already been created in
820 * s_project_create_new. Therefore, just rename the first page
821 * and open the project. */
822 free(pr_current->page_current->page_filename);
824 return_code |= s_toplevel_read_page(string); /* read in first page, or in return code */
825 first_page = 0;
826 } else {
827 return_code |= s_toplevel_read_page(string); /* read in secondary page, or in return code */
829 free(string);
831 /* Now add all items found to the master lists */
832 s_sheet_data_add_master_comp_list_items(pr_current->page_current->object_head);
833 s_sheet_data_add_master_comp_attrib_list_items(pr_current->page_current->object_head);
834 #if 0
835 /* Note that this must be changed. We need to input the entire project
836 * before doing anything with the nets because we need to first
837 * determine where they are all connected! */
838 s_sheet_data_add_master_net_list_items(pr_current->page_current->object_head);
839 s_sheet_data_add_master_net_attrib_list_items(pr_current->page_current->object_head);
840 #endif
842 s_sheet_data_add_master_pin_list_items(pr_current->page_current->object_head);
843 s_sheet_data_add_master_pin_attrib_list_items(pr_current->page_current->object_head);
846 } /* end of loop over files */
848 /* Now update rest of project if we had at least one new file */
849 if (return_code) {
850 /* ---------- Sort the master lists ---------- */
851 s_string_list_sort_master_comp_list();
852 s_string_list_sort_master_comp_attrib_list();
853 #if 0
854 /* Note that this must be changed. We need to input the entire project
855 * before doing anything with the nets because we need to first
856 * determine where they are all connected! */
857 s_string_list_sort_master_net_list();
858 s_string_list_sort_master_net_attrib_list();
859 #endif
861 /* ---------- Now create and load the tables ---------- */
862 sheet_head->component_table = s_table_new(sheet_head->comp_count, sheet_head->comp_attrib_count);
863 sheet_head->net_table = s_table_new(sheet_head->net_count, sheet_head->net_attrib_count);
865 p_local = pr_current->page_head; /* must iterate over all pages in design */
866 while (p_local != NULL) {
867 if (p_local->pid != -1) { /* only traverse pages which are toplevel */
868 if (p_local->object_head && p_local->page_control == 0) {
869 s_table_add_toplevel_comp_items_to_comp_table(p_local->object_head); /* adds all objects from page */
870 #if 0
871 /* Note that this must be changed. We need to input the entire project
872 * before doing anything with the nets because we need to first
873 * determine where they are all connected! */
874 s_table_add_toplevel_net_items_to_net_table(p_local->object_head); /* adds all objects from page */
875 #endif
877 s_table_add_toplevel_pin_items_to_pin_table(p_local->object_head); /* adds all objects from page */
881 p_local = p_local->next; /* iterate to next schematic page */
882 } /* while(p_local != NULL) */
884 #if DEBUG
885 printf("In x_fileselect_open_file -- we have just added more files to the project.\n");
886 #endif
888 /* -------------- update windows --------------- */
889 x_window_add_items(); /* This updates the top level stuff,
890 * and then calls another fcn to update
891 * the GtkSheet itself. */
892 #ifdef DEBUG
893 printf("In x_fileselect_open_file -- we have just returned from x_window_add_items.\n");
894 #endif
895 } else {
896 fprintf(stderr, "Couldn't open any file!.\n");
898 } /* if (files) */
900 /* Now close file dialog window . . . . */
901 gtk_widget_destroy(GTK_WIDGET(f_current->xfwindow));
903 return;
908 /* ------------------------------------------------------------- *
910 * ------------------------------------------------------------- */
911 void
912 x_fileselect_dir_button(GtkWidget * widget, gint row, gint column,
913 GdkEventButton * bevent, FILEDIALOG * f_current)
915 * SDB notes: This fcn is called for almost every event which occurs
916 * to the "open file" widget, except when the actual file is to be
917 * opened. Stuff handled by this fcn are e.g. highlighting the file
918 * selected in the file list, updating the dir/file lists upon change
919 * of directory, etc.
922 char *temp = NULL;
924 gtk_clist_get_text(GTK_CLIST(f_current->dir_list), row, 0, &temp);
926 if (temp) {
927 #if DEBUG
928 printf("In x_fileselect_dir_button, selected: %d _%s_\n", row, temp);
929 #endif
930 if (bevent) {
931 switch (bevent->type) {
932 case (GDK_2BUTTON_PRESS):
933 x_fileselect_change_dir(f_current, temp);
934 break;
936 default:
938 break;
945 /* ------------------------------------------------------------- *
947 * ------------------------------------------------------------- */
948 void
949 x_fileselect_file_button(GtkWidget * widget, gint row, gint column,
950 GdkEventButton * bevent, FILEDIALOG * f_current)
952 * SDB notes: This fcn is apparently called for each event occuring to
953 * the file clist. This fcn determines if the button event captured was to
954 * update the directory/file display or was a doubleclick on a file
955 * in the clist meant to open the file. It then
956 * calls the appropriate handler. Unfortunately, in the event of
957 * selecting multiple files (using ENHANCED mode), bevent is nonnull
958 * only on the first call.
961 char *temp = NULL;
963 /* put name of desired file into temp */
964 gtk_clist_get_text(GTK_CLIST(f_current->file_list), row, 0, &temp);
966 if (temp) {
968 #if DEBUG
969 printf("In x_fileselect_file_button, file selected: %d %s\n", row,
970 temp);
971 if (bevent) {
972 printf("in x_fileselect_file_button, bevent->type = %d\n",
973 bevent->type);
974 } else {
975 printf("In x_fileselect_file_button, bevent = NULL\n");
977 #endif
979 if (bevent) {
980 switch (bevent->type) {
981 case (GDK_2BUTTON_PRESS):
982 x_fileselect_open_file(NULL, f_current);
983 break;
985 default:
986 x_fileselect_update_dirfile(f_current, temp);
987 break;
994 /* ------------------------------------------------------------- *
996 * ------------------------------------------------------------- */
997 void
998 x_fileselect_update_dirfile_saveas(FILEDIALOG * f_current,
999 char *new_filename)
1001 char *temp = NULL;
1002 char *ptr = NULL;
1003 char *filename = NULL;
1004 char *directory = NULL;
1005 int i;
1007 #ifdef DEBUG
1008 printf("In x_fileselect_update_dirfile_saveas, new_filename = [%s]\n", new_filename);
1009 #endif
1011 if (new_filename == NULL) {
1012 return;
1015 if (f_current->filename) {
1016 free(f_current->filename);
1017 f_current->filename = NULL;
1020 if (f_current->directory) {
1021 free(f_current->directory);
1022 f_current->directory = NULL;
1025 #if 0
1026 directory = (char *) malloc(sizeof(char) * (strlen(new_filename) + 1));
1027 filename = (char *) malloc(sizeof(char) * (strlen(new_filename) + 1));
1029 ptr = new_filename;
1030 temp = strrchr(new_filename, PATH_SEPARATER_CHAR);
1031 if (temp) {
1032 /* SDB asks: What is all this stuff for? */
1033 i = 0;
1034 while (ptr != temp && ptr[0] != '\0') {
1035 directory[i] = *ptr;
1036 ptr++;
1037 i++;
1039 directory[i] = '\0';
1040 ptr++; /* skip over last '/' */
1041 i = 0;
1042 while (ptr[0] != '\0') {
1043 filename[i] = *ptr;
1044 ptr++;
1045 i++;
1047 filename[i] = '\0';
1048 } else {
1049 #endif
1050 /* SDB says: This is what generally is run. What is the above stuff for? */
1051 directory = getcwd(NULL, 1024);
1052 filename = u_basic_strdup(new_filename);
1053 #if 0
1055 #endif
1057 #if DEBUG
1058 printf("In x_fileselect_update_dirfile_saveas, directory = %s\n", directory);
1059 printf("In x_fileselect_update_dirfile_saveas, filename = %s\n", filename);
1060 #endif
1062 if (directory) {
1063 f_current->directory = u_basic_strdup(directory);
1064 free(directory);
1067 if (filename) {
1068 f_current->filename = u_basic_strdup(filename);
1069 free(filename);
1071 #ifdef __MINGW32__
1072 if (u_basic_has_trailing(f_current->directory, PATH_SEPARATER_CHAR)) {
1073 temp = u_basic_strdup_multiple(f_current->directory,
1074 f_current->filename, NULL);
1075 } else {
1076 #endif
1077 temp = u_basic_strdup_multiple(f_current->directory,
1078 PATH_SEPARATER_STRING,
1079 f_current->filename, NULL);
1080 #ifdef __MINGW32__
1082 #endif
1083 gtk_entry_set_text(GTK_ENTRY(f_current->filename_entry), temp);
1085 free(temp);
1087 #if DEBUG
1088 printf("In x_fileselect_update_dirfile_saveas, f_current->directory = %s\n", f_current->directory);
1089 printf("In x_fileselect_update_dirfile_saveas, f_current->filename = %s\n", f_current->filename);
1090 #endif
1092 return;
1096 /* ------------------------------------------------------------- *
1097 * This fcn closes the filedialog window, but doesn't kill the
1098 * filedialog object. There is another fcn which will kill
1099 * the whole object.
1100 * ------------------------------------------------------------- */
1101 void x_fileselect_close(GtkWidget * w, FILEDIALOG * f_current)
1103 if(f_current->filter)
1104 gtk_widget_destroy(GTK_WIDGET(f_current->filter));
1106 if(f_current->search_entry)
1107 gtk_widget_destroy(GTK_WIDGET(f_current->search_entry));
1109 if(f_current->search_label)
1110 gtk_widget_destroy(GTK_WIDGET(f_current->search_label));
1112 if(f_current->filename_entry)
1113 gtk_widget_destroy(GTK_WIDGET(f_current->filename_entry));
1115 if(f_current->dir_list)
1116 gtk_widget_destroy(GTK_WIDGET(f_current->dir_list));
1118 if(f_current->file_list)
1119 gtk_widget_destroy(GTK_WIDGET(f_current->file_list));
1121 if(f_current->preview_checkbox)
1122 gtk_widget_destroy(GTK_WIDGET(f_current->preview_checkbox));
1124 if(f_current->component_pulldown)
1125 gtk_widget_destroy(GTK_WIDGET(f_current->component_pulldown));
1127 /* Finally kill main widget */
1128 gtk_widget_destroy(GTK_WIDGET(f_current->xfwindow));
1129 return;
1134 /*********** File Open/Save As... specific code ends here ***********/
1137 /******************************************************************/
1138 /*------------------------------------------------------------------
1139 * This is the main fcn which creates the "open file" dialog box.
1140 * filesel_type can be one of:
1141 *------------------------------------------------------------------*/
1142 void x_fileselect_setup(TOPLEVEL *pr_current, int filesel_type)
1144 GtkWidget *buttonapply = NULL;
1145 GtkWidget *buttonclose = NULL;
1146 GtkWidget *scrolled_win;
1147 GtkWidget *action_area;
1148 GtkWidget *separator;
1149 GtkWidget *optionmenu;
1150 GtkWidget *drawbox;
1151 GtkWidget *label;
1152 GtkWidget *searchbox;
1154 int type = FILESELECT; /* This was a calling arg in gschem */
1155 /* here, I have just made it fixed. */
1157 FILEDIALOG *f_current;
1159 GtkWidget *vbox;
1160 GtkWidget *list_hbox;
1161 char *dir_title[2];
1162 char *file_title[2];
1164 /* Initialize filedialog object. This object holds pointers
1165 * to all information in filedialog window, including pointers
1166 * to several widgets in the window. */
1167 f_current = malloc(sizeof(FILEDIALOG));
1168 /* (pr_current->fileselect)[0] = f_current; */ /* Keep a pointer to the file dialog in TOPLEVEL */
1170 f_current->xfwindow = gtk_window_new(GTK_WINDOW_TOPLEVEL);
1171 f_current->toplevel = pr_current; /* This points back to toplevel for reading in files. */
1172 f_current->type = 0; /* used to be type */
1173 f_current->filesel_type = filesel_type;
1174 f_current->last_search = -1;
1175 f_current->filename = NULL;
1176 f_current->directory = NULL;
1177 f_current->dir_list = NULL;
1178 f_current->file_list = NULL;
1179 x_fileselect_init_list_buffers(f_current); /* initializes the directory and file lists */
1182 /* These widgets are not used in gattrib. I need to make them
1183 * null so that I don't get segfaults when manipulating windows */
1184 f_current->filter = NULL;
1185 f_current->search_entry = NULL;
1186 f_current->search_label = NULL;
1187 f_current->filename_entry = NULL;
1188 f_current->preview = NULL;
1189 f_current->preview_checkbox = NULL;
1190 f_current->component_pulldown = NULL;
1192 #ifdef DEBUG
1193 printf("We have just entered x_fileselect_setup.\n");
1194 #endif
1196 /* ----- Create main top-level window ----- */
1197 gtk_window_position(GTK_WINDOW(f_current->xfwindow),
1198 GTK_WIN_POS_MOUSE);
1200 if (filesel_type == OPEN) {
1201 gtk_window_set_title(GTK_WINDOW(f_current->xfwindow),
1202 "Open...");
1203 } else if (filesel_type == SAVEAS) {
1204 gtk_window_set_title(GTK_WINDOW(f_current->xfwindow),
1205 "Save As...");
1206 } else if (filesel_type == SAVEAS_CLOSE) {
1207 gtk_window_set_title(GTK_WINDOW(f_current->xfwindow),
1208 "Save As...");
1211 gtk_signal_connect(GTK_OBJECT(f_current->xfwindow),
1212 "destroy",
1213 GTK_SIGNAL_FUNC(x_fileselect_destroy_window),
1214 f_current);
1216 gtk_signal_connect(GTK_OBJECT(f_current->xfwindow), "key_press_event",
1217 (GtkSignalFunc) x_fileselect_keypress, f_current);
1219 vbox = gtk_vbox_new(FALSE, 0);
1220 gtk_container_set_border_width(GTK_CONTAINER(f_current->xfwindow), 10);
1221 gtk_container_add(GTK_CONTAINER(f_current->xfwindow), vbox);
1222 gtk_widget_show(vbox);
1224 action_area = gtk_hbutton_box_new();
1225 gtk_button_box_set_layout(GTK_BUTTON_BOX(action_area),
1226 GTK_BUTTONBOX_END);
1227 gtk_button_box_set_spacing(GTK_BUTTON_BOX(action_area), 5);
1228 gtk_box_pack_end(GTK_BOX(vbox), action_area, TRUE, FALSE, 10);
1229 gtk_widget_show(action_area);
1232 /* ----- Create the filter selection area ----- */
1233 f_current->filter_type = FILEDIALOG_SCH_ONLY; /* we only handle schematics in gattrib */
1235 label = gtk_label_new("Filter");
1236 gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
1237 gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
1238 gtk_widget_show(label);
1240 f_current->filter = gtk_option_menu_new();
1241 gtk_option_menu_set_menu(GTK_OPTION_MENU(f_current->filter),
1242 x_fileselect_filter_menu(f_current));
1243 /* gtk_option_menu_set_history(GTK_OPTION_MENU(f_current->filter),
1244 4); */
1245 gtk_box_pack_start(GTK_BOX(vbox), f_current->filter,
1246 FALSE, FALSE, 0);
1247 gtk_widget_show(f_current->filter);
1250 list_hbox = gtk_hbox_new(FALSE, 5);
1251 gtk_box_pack_start(GTK_BOX(vbox), list_hbox, TRUE, TRUE, 0);
1252 gtk_widget_show(list_hbox);
1254 separator = gtk_hseparator_new();
1255 gtk_box_pack_start(GTK_BOX(vbox), separator, FALSE, TRUE, 0);
1256 gtk_widget_show(separator);
1258 drawbox = gtk_hbox_new(FALSE, 0);
1259 gtk_box_pack_start(GTK_BOX(vbox), drawbox, TRUE, FALSE, 5);
1260 gtk_widget_show(drawbox);
1262 searchbox = gtk_vbox_new(FALSE, 0);
1263 gtk_box_pack_end(GTK_BOX(drawbox), searchbox, TRUE, TRUE, 10);
1264 gtk_widget_show(searchbox);
1267 /* ----- Create the "directories"/"libraries" clist widgets ----- */
1268 dir_title[0] = u_basic_strdup("Directories");
1269 dir_title[1] = NULL;
1270 f_current->dir_list = gtk_clist_new_with_titles(1,
1271 (char **) dir_title);
1272 gtk_widget_set_usize(f_current->dir_list,
1273 DIR_LIST_WIDTH, DIR_LIST_HEIGHT);
1274 gtk_signal_connect(GTK_OBJECT(f_current->dir_list),
1275 "select_row", (GtkSignalFunc)
1276 x_fileselect_dir_button, f_current);
1278 gtk_clist_column_titles_passive(GTK_CLIST(f_current->dir_list));
1280 scrolled_win = gtk_scrolled_window_new(NULL, NULL);
1281 gtk_container_add(GTK_CONTAINER(scrolled_win), f_current->dir_list);
1282 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_win),
1283 GTK_POLICY_AUTOMATIC,
1284 GTK_POLICY_ALWAYS);
1285 gtk_container_set_border_width(GTK_CONTAINER(scrolled_win), 5);
1286 gtk_box_pack_start(GTK_BOX(list_hbox), scrolled_win, TRUE, TRUE, 0);
1287 gtk_clist_set_auto_sort(GTK_CLIST(f_current->dir_list), TRUE);
1289 gtk_widget_show(f_current->dir_list);
1290 gtk_widget_show(scrolled_win);
1291 free(dir_title[0]);
1293 /* ----- Create the files clist ----- */
1294 file_title[0] = u_basic_strdup("Files");
1295 file_title[1] = NULL;
1296 f_current->file_list = gtk_clist_new_with_titles(1,
1297 (gchar **)
1298 file_title);
1299 gtk_widget_set_usize(f_current->file_list, FILE_LIST_WIDTH,
1300 FILE_LIST_HEIGHT);
1302 /* Stuff added by SDB to enable opening multiple files at once */
1303 gtk_clist_set_selection_mode(GTK_CLIST(f_current->file_list),
1304 GTK_SELECTION_EXTENDED);
1306 gtk_signal_connect(GTK_OBJECT(f_current->file_list), "select_row",
1307 /* This is file opening callback */
1308 (GtkSignalFunc) x_fileselect_file_button,
1309 f_current);
1311 gtk_clist_column_titles_passive(GTK_CLIST(f_current->file_list));
1313 scrolled_win = gtk_scrolled_window_new(NULL, NULL);
1314 gtk_container_add(GTK_CONTAINER(scrolled_win), f_current->file_list);
1315 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_win),
1316 GTK_POLICY_AUTOMATIC,
1317 GTK_POLICY_ALWAYS);
1318 gtk_container_set_border_width(GTK_CONTAINER(scrolled_win), 5);
1319 gtk_box_pack_start(GTK_BOX(list_hbox), scrolled_win, TRUE, TRUE, 0);
1320 gtk_clist_set_auto_sort(GTK_CLIST(f_current->file_list), TRUE);
1322 gtk_widget_show(f_current->file_list);
1323 gtk_widget_show(scrolled_win);
1324 free(file_title[0]);
1326 /* ----- Create the "Filename" text entry area ----- */
1327 label = gtk_label_new("Filename");
1328 gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
1329 gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 5);
1330 gtk_widget_show(label);
1332 f_current->filename_entry = gtk_entry_new_with_max_length(1024);
1333 gtk_editable_select_region(GTK_EDITABLE(f_current->filename_entry), 0,
1334 -1);
1335 gtk_box_pack_start(GTK_BOX(vbox), f_current->filename_entry, FALSE,
1336 FALSE, 0);
1338 if (filesel_type == OPEN) {
1339 gtk_signal_connect(GTK_OBJECT(f_current->filename_entry),
1340 /* Here we connect the callback to
1341 fileselect_open_file to the filename in
1342 the filename text entry field.. */
1343 "activate",
1344 GTK_SIGNAL_FUNC(x_fileselect_open_file),
1345 f_current);
1346 } else if ((filesel_type == SAVEAS_NONE) ||
1347 (filesel_type == SAVEAS_QUIT) ||
1348 (filesel_type == SAVEAS_OPEN) ||
1349 (filesel_type == SAVEAS_CLOSE) ||
1350 (filesel_type == SAVEAS_NEW)) {
1351 gtk_signal_connect(GTK_OBJECT(f_current->filename_entry),
1352 "activate",
1353 GTK_SIGNAL_FUNC(x_fileselect_saveas),
1354 f_current);
1356 gtk_editable_select_region(GTK_EDITABLE(f_current->filename_entry),
1357 0, -1);
1359 gtk_widget_show(f_current->filename_entry);
1361 /* ----- Here we create the "open"/"save as"/"apply" buttons ----- */
1362 if (filesel_type == OPEN) {
1363 buttonapply = gtk_button_new_with_label("Open");
1364 gtk_signal_connect(GTK_OBJECT(buttonapply),
1365 "clicked",
1366 GTK_SIGNAL_FUNC(x_fileselect_open_file),
1367 f_current); /* Note that f_current points to pr_current
1368 which is important when reading in
1369 files. */
1370 } else if ((filesel_type == SAVEAS_NONE) ||
1371 (filesel_type == SAVEAS_QUIT) ||
1372 (filesel_type == SAVEAS_OPEN) ||
1373 (filesel_type == SAVEAS_CLOSE) ||
1374 (filesel_type == SAVEAS_NEW)) {
1375 buttonapply = gtk_button_new_with_label("SaveAs");
1376 gtk_signal_connect(GTK_OBJECT(buttonapply),
1377 "clicked",
1378 GTK_SIGNAL_FUNC(x_fileselect_saveas), f_current);
1381 GTK_WIDGET_SET_FLAGS(buttonapply, GTK_CAN_DEFAULT);
1382 gtk_box_pack_start(GTK_BOX(action_area), buttonapply, TRUE, TRUE, 0);
1383 /* This makes the "open" button the default */
1384 gtk_widget_grab_default(buttonapply);
1385 gtk_widget_show(buttonapply);
1387 /* ----- Here we create the "cancel"/"close" buttons ----- */
1388 if (filesel_type == OPEN) {
1389 buttonclose = gtk_button_new_with_label("Cancel");
1390 GTK_WIDGET_SET_FLAGS(buttonclose, GTK_CAN_DEFAULT);
1391 gtk_box_pack_start(GTK_BOX(action_area),
1392 buttonclose, TRUE, TRUE, 0);
1393 gtk_signal_connect(GTK_OBJECT(buttonclose),
1394 "clicked",
1395 GTK_SIGNAL_FUNC(x_fileselect_close), f_current);
1396 gtk_widget_show(buttonclose);
1398 x_fileselect_update_dirfile(f_current, NULL);
1399 x_fileselect_fill_lists(f_current);
1400 } else if ((filesel_type == SAVEAS_NONE) ||
1401 (filesel_type == SAVEAS_QUIT) ||
1402 (filesel_type == SAVEAS_OPEN) ||
1403 (filesel_type == SAVEAS_CLOSE) ||
1404 (filesel_type == SAVEAS_NEW)) {
1405 buttonclose = gtk_button_new_with_label("Cancel");
1406 GTK_WIDGET_SET_FLAGS(buttonclose, GTK_CAN_DEFAULT);
1407 gtk_box_pack_start(GTK_BOX(action_area),
1408 buttonclose, TRUE, TRUE, 0);
1409 gtk_signal_connect(GTK_OBJECT(buttonclose),
1410 "clicked",
1411 GTK_SIGNAL_FUNC(x_fileselect_saveas_close),
1412 f_current);
1413 gtk_widget_show(buttonclose);
1415 x_fileselect_update_dirfile_saveas(f_current,
1416 pr_current->page_current->
1417 page_filename);
1419 x_fileselect_fill_lists(f_current);
1422 if (!GTK_WIDGET_VISIBLE(f_current->xfwindow)) {
1423 gtk_widget_show(f_current->xfwindow);
1424 gdk_window_raise(f_current->xfwindow->window);
1426 gtk_grab_add(f_current->xfwindow);
1428 } else {
1429 /* window should already be mapped, otherwise this
1430 * will core */
1431 gdk_window_raise(f_current->xfwindow->window);