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 *------------------------------------------------------------------*/
29 /*------------------------------------------------------------------
30 * Includes required to run graphical widgets.
31 *------------------------------------------------------------------*/
36 #include <gdk/gdkkeysyms.h>
40 #include <glib-object.h>
43 #include <sys/types.h>
45 #ifdef HAVE_SYS_PARAM_H
46 #include <sys/param.h>
66 #include "gtksheet_2_2.h"
67 #include "gtkitementry_2_2.h"
69 #include "gtksheet_1_2.h"
70 #include "gtkitementry_1_2.h"
73 /*------------------------------------------------------------------
74 * Gattrib specific includes
75 *------------------------------------------------------------------*/
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 * ------------------------------------------------------------- */
97 x_fileselect_destroy_window(GtkWidget
* widget
, FILEDIALOG
* f_current
)
101 printf("In x_fileselect_destroy_window, about to destroy window!\n");
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
;
119 /* *window = NULL; */
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
);
139 /* ------------------------------------------------------------- *
141 * ------------------------------------------------------------- */
142 void x_fileselect_init_list_buffers(FILEDIALOG
* f_current
)
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
;
159 /* ------------------------------------------------------------- *
161 * ------------------------------------------------------------- */
162 void x_fileselect_free_list_buffers(FILEDIALOG
* f_current
)
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
;
184 /*********** File Open/Save As... specific code starts here ***********/
185 /* ------------------------------------------------------------- *
187 * ------------------------------------------------------------- */
188 void x_fileselect_update_dirfile(FILEDIALOG
* f_current
, char *filename
)
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);
206 f_current
->directory
= u_basic_strdup(temp
);
207 f_current
->filename
= u_basic_strdup(filename
);
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
);
216 temp
= u_basic_strdup_multiple(f_current
->directory
,
217 PATH_SEPARATER_STRING
,
218 f_current
->filename
, NULL
);
223 gtk_entry_set_text(GTK_ENTRY(f_current
->filename_entry
), temp
);
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
);
240 printf("In x_fileselect_update_dirfile, directory: %s\n", f_current
->directory
);
247 /* ------------------------------------------------------------- *
249 * ------------------------------------------------------------- */
251 x_fileselect_setup_list_buffers(FILEDIALOG
* f_current
,
252 int num_directories
, int num_files
)
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
;
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")) {
287 case (FILEDIALOG_SYM_ONLY
):
288 if (strstr(filename
, ".sym")) {
293 case (FILEDIALOG_SCH_SYM
):
294 if (strstr(filename
, ".sch") || strstr(filename
, ".sym")) {
299 case (FILEDIALOG_ALL_FILES
):
308 /* ------------------------------------------------------------- *
310 * ------------------------------------------------------------- */
311 void x_fileselect_fill_lists(FILEDIALOG
* f_current
)
314 struct dirent
*dirent_ptr
;
316 int num_directories
= 0;
320 char path_buf
[MAXPATHLEN
* 2];
326 int first
, last
, j
, done
= 0;
328 int has_trailing
= FALSE
;
331 directory
= opendir(f_current
->directory
);
333 printf("In x_fileselect_fill_lists, directory = %s\n", directory
);
338 has_trailing
= u_basic_has_trailing(f_current
->directory
,
339 PATH_SEPARATER_CHAR
);
343 fprintf(stderr
, "Agg, could not open directory: %s\n",
344 f_current
->directory
);
348 while ((dirent_ptr
= readdir(directory
)) != NULL
) {
351 sprintf(path_buf
, "%s%s", f_current
->directory
, dirent_ptr
->d_name
);
354 sprintf(path_buf
, "%s%c%s", f_current
->directory
,
355 PATH_SEPARATER_CHAR
, dirent_ptr
->d_name
);
360 if (stat(path_buf
, &stat_en
) >= 0 && S_ISDIR(stat_en
.st_mode
)) {
361 /* printf("dir: %s\n", path_buf); */
364 /* printf("file: %s\n", path_buf); */
370 if (num_directories
> MAX_DIRS
) {
371 fprintf(stderr
, "Too many directories! Increase MAX_DIRS\n");
375 if (num_files
> MAX_FILES
) {
376 fprintf(stderr
, "Too many files! Increase MAX_FILES\n");
380 x_fileselect_setup_list_buffers(f_current
, num_directories
, num_files
);
382 rewinddir(directory
);
384 while ((dirent_ptr
= readdir(directory
)) != NULL
) {
387 sprintf(path_buf
, "%s%s", f_current
->directory
, dirent_ptr
->d_name
);
390 sprintf(path_buf
, "%s%c%s", f_current
->directory
,
391 PATH_SEPARATER_CHAR
, dirent_ptr
->d_name
);
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
);
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
);
417 printf("In x_fileselect_fill_lists, FILE COUNT: %d\n", file_count
);
420 /* lame bubble sort */
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
;
439 /* lame bubble sort */
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
;
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
));
467 for (i
= 0; i
< dir_count
; i
++) {
468 temp
= u_basic_strdup_multiple(f_current
->directory_entries
[i
],
469 PATH_SEPARATER_STRING
, NULL
);
471 gtk_clist_append(GTK_CLIST(f_current
->dir_list
), text
);
475 gdk_string_width(gtk_style_get_font(f_current
->dir_list
->style
),
476 f_current
->directory_entries
[i
]);
478 width
= gdk_string_width(f_current
->dir_list
->style
->font
,
479 f_current
->directory_entries
[i
]);
482 if (width
> max_width
) {
483 gtk_clist_set_column_width(GTK_CLIST(f_current
->dir_list
), 0, width
);
489 printf("In x_fileselect_fill_lists, directory: %s\n", f_current
->directory_entries
[i
]);
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
);
500 gdk_string_width(gtk_style_get_font(f_current
->dir_list
->style
),
501 f_current
->file_entries
[i
]);
503 width
= gdk_string_width(f_current
->dir_list
->style
->font
,
504 f_current
->file_entries
[i
]);
507 if (width
> max_width
) {
508 gtk_clist_set_column_width(GTK_CLIST(f_current
->
509 file_list
), 0, width
);
513 printf("In x_fileselect_fill_lists, file: %s\n", f_current
->file_entries
[i
]);
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;
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
);
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
);
548 /* ------------------------------------------------------------- *
550 * ------------------------------------------------------------- */
551 /* this is from gtktest.c */
552 static GtkWidget
*x_fileselect_filter_menu(FILEDIALOG
* f_current
)
559 menu
= gtk_menu_new();
562 buf
= g_strdup_printf("sch - Schematics");
563 menuitem
= gtk_radio_menu_item_new_with_label(group
, 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
);
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);
586 case (FILEDIALOG_SYM_ONLY
):
587 gtk_menu_set_active(GTK_MENU(menu
), 1);
590 case (FILEDIALOG_SCH_SYM
):
591 gtk_menu_set_active(GTK_MENU(menu
), 2);
594 case (FILEDIALOG_ALL_FILES
):
595 gtk_menu_set_active(GTK_MENU(menu
), 3);
605 /* ------------------------------------------------------------- *
606 * This fcn just closes the window and does nothing else.
607 * It is invoked when you click "cancel" during a save
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
);
631 /* do nothing if close is pressed for SAVEAS_CLOSE case */
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
640 * ------------------------------------------------------------- */
641 void x_fileselect_saveas(GtkWidget
* w
, FILEDIALOG
* f_current
)
648 w_current
= f_current
->toplevel
;
650 string
= (gchar
*) gtk_entry_get_text(GTK_ENTRY(f_current
->filename_entry
));
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;
675 s_log_message("Could NOT save [%s]\n",
676 w_current
->page_current
->page_filename
);
679 x_fileselect_close(NULL
, f_current
);
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
);
694 /* do nothing if SAVEAS_NONE */
696 s_log_message("Specify a Filename!\n");
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];
713 if (!w_current
->filename_label
) {
718 len
= strlen(string
);
719 w_current
->DONT_RESIZE
= 1;
721 if (w_current
->filename_label
) {
724 trunc_string
[0] = '.';
725 trunc_string
[1] = '.';
726 trunc_string
[2] = '.';
728 trunc_string
[40] = '\0';
729 for (i
= 39; i
> 2; i
--) {
731 trunc_string
[i
] = string
[len
];
738 gtk_label_set(GTK_LABEL(w_current
->filename_label
), trunc_string
);
742 gtk_label_set(GTK_LABEL(w_current
->
743 filename_label
), (char *) string
);
751 /* ------------------------------------------------------------- *
753 * ------------------------------------------------------------- */
754 void x_fileselect_change_dir(FILEDIALOG
* f_current
, char *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
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
)
780 int old_num_rows
, old_num_cols
; /* There is a better way . . . */
782 char *filename
= NULL
;
787 printf("We have just entered x_fileselect_open_file.\n");
790 /* get GList of selected files */
791 files
= (GTK_CLIST(f_current
->file_list
))->selection
;
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,
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. */
810 /* string is full name of file. */
811 sprintf(string
, "%s/%s", f_current
->directory
, filename
);
814 printf("In x_fileselect_open_file, opening string = %s\n", string
);
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 */
827 return_code
|= s_toplevel_read_page(string
); /* read in secondary page, or in return code */
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
);
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
);
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 */
850 /* ---------- Sort the master lists ---------- */
851 s_string_list_sort_master_comp_list();
852 s_string_list_sort_master_comp_attrib_list();
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();
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 */
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 */
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) */
885 printf("In x_fileselect_open_file -- we have just added more files to the project.\n");
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. */
893 printf("In x_fileselect_open_file -- we have just returned from x_window_add_items.\n");
896 fprintf(stderr
, "Couldn't open any file!.\n");
900 /* Now close file dialog window . . . . */
901 gtk_widget_destroy(GTK_WIDGET(f_current
->xfwindow
));
908 /* ------------------------------------------------------------- *
910 * ------------------------------------------------------------- */
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
924 gtk_clist_get_text(GTK_CLIST(f_current
->dir_list
), row
, 0, &temp
);
928 printf("In x_fileselect_dir_button, selected: %d _%s_\n", row
, temp
);
931 switch (bevent
->type
) {
932 case (GDK_2BUTTON_PRESS
):
933 x_fileselect_change_dir(f_current
, temp
);
945 /* ------------------------------------------------------------- *
947 * ------------------------------------------------------------- */
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.
963 /* put name of desired file into temp */
964 gtk_clist_get_text(GTK_CLIST(f_current
->file_list
), row
, 0, &temp
);
969 printf("In x_fileselect_file_button, file selected: %d %s\n", row
,
972 printf("in x_fileselect_file_button, bevent->type = %d\n",
975 printf("In x_fileselect_file_button, bevent = NULL\n");
980 switch (bevent
->type
) {
981 case (GDK_2BUTTON_PRESS
):
982 x_fileselect_open_file(NULL
, f_current
);
986 x_fileselect_update_dirfile(f_current
, temp
);
994 /* ------------------------------------------------------------- *
996 * ------------------------------------------------------------- */
998 x_fileselect_update_dirfile_saveas(FILEDIALOG
* f_current
,
1003 char *filename
= NULL
;
1004 char *directory
= NULL
;
1008 printf("In x_fileselect_update_dirfile_saveas, new_filename = [%s]\n", new_filename
);
1011 if (new_filename
== NULL
) {
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
;
1026 directory
= (char *) malloc(sizeof(char) * (strlen(new_filename
) + 1));
1027 filename
= (char *) malloc(sizeof(char) * (strlen(new_filename
) + 1));
1030 temp
= strrchr(new_filename
, PATH_SEPARATER_CHAR
);
1032 /* SDB asks: What is all this stuff for? */
1034 while (ptr
!= temp
&& ptr
[0] != '\0') {
1035 directory
[i
] = *ptr
;
1039 directory
[i
] = '\0';
1040 ptr
++; /* skip over last '/' */
1042 while (ptr
[0] != '\0') {
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
);
1058 printf("In x_fileselect_update_dirfile_saveas, directory = %s\n", directory
);
1059 printf("In x_fileselect_update_dirfile_saveas, filename = %s\n", filename
);
1063 f_current
->directory
= u_basic_strdup(directory
);
1068 f_current
->filename
= u_basic_strdup(filename
);
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
);
1077 temp
= u_basic_strdup_multiple(f_current
->directory
,
1078 PATH_SEPARATER_STRING
,
1079 f_current
->filename
, NULL
);
1083 gtk_entry_set_text(GTK_ENTRY(f_current
->filename_entry
), temp
);
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
);
1096 /* ------------------------------------------------------------- *
1097 * This fcn closes the filedialog window, but doesn't kill the
1098 * filedialog object. There is another fcn which will kill
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
));
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
;
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
;
1160 GtkWidget
*list_hbox
;
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
;
1193 printf("We have just entered x_fileselect_setup.\n");
1196 /* ----- Create main top-level window ----- */
1197 gtk_window_position(GTK_WINDOW(f_current
->xfwindow
),
1200 if (filesel_type
== OPEN
) {
1201 gtk_window_set_title(GTK_WINDOW(f_current
->xfwindow
),
1203 } else if (filesel_type
== SAVEAS
) {
1204 gtk_window_set_title(GTK_WINDOW(f_current
->xfwindow
),
1206 } else if (filesel_type
== SAVEAS_CLOSE
) {
1207 gtk_window_set_title(GTK_WINDOW(f_current
->xfwindow
),
1211 gtk_signal_connect(GTK_OBJECT(f_current
->xfwindow
),
1213 GTK_SIGNAL_FUNC(x_fileselect_destroy_window
),
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
),
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),
1245 gtk_box_pack_start(GTK_BOX(vbox
), f_current
->filter
,
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
,
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
);
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,
1299 gtk_widget_set_usize(f_current
->file_list
, FILE_LIST_WIDTH
,
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
,
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
,
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,
1335 gtk_box_pack_start(GTK_BOX(vbox
), f_current
->filename_entry
, FALSE
,
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.. */
1344 GTK_SIGNAL_FUNC(x_fileselect_open_file
),
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
),
1353 GTK_SIGNAL_FUNC(x_fileselect_saveas
),
1356 gtk_editable_select_region(GTK_EDITABLE(f_current
->filename_entry
),
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
),
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
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
),
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
),
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
),
1411 GTK_SIGNAL_FUNC(x_fileselect_saveas_close
),
1413 gtk_widget_show(buttonclose
);
1415 x_fileselect_update_dirfile_saveas(f_current
,
1416 pr_current
->page_current
->
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
);
1429 /* window should already be mapped, otherwise this
1431 gdk_window_raise(f_current
->xfwindow
->window
);