/* file_io.c * * Copyright (C) 2002 Claudio Girardi * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at * your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA, 02111-1307, USA */ /* This is just a quick hack for saving/loading transmission lines data */ /* some of the functions are adapted from gfit and other GPL'ed software */ /* Thanks goes to all the people writing free software ! */ #include #include #include #include #include #include #include #include "file_io.h" #include "transcalc.h" #ifdef HAVE_FNMATCH #include #else #include "fnmatch.h" #endif static gint goto_flag = 0; static gint idle_flag = 0; /* file name filter for file dialog */ static gchar *filter_text = "*.trc"; static GtkWidget *filter_entry = NULL; //extern trans_win *twin; gint trc_file_save (FILE *fp, short file_save_mode) { time_t date; gint i; gchar *tmp_str1 = NULL, *tmp_str2 = NULL; gchar *tmp_str = NULL; /* get current date and time */ time(&date); /* write header */ fprintf(fp, "# This file was automatically generated\n"); fprintf(fp, "# by transcalc "VERSION" on %s", ctime(&date)); fprintf(fp, "#\n"); fprintf(fp, "# It is suggested not to edit this file directly, use transcalc instead\n"); fprintf(fp, "#\n"); fprintf(fp, "\n"); /* write transmission line type */ tmp_str = (gchar *) gtk_entry_get_text (GTK_ENTRY (GTK_COMBO(transtype_combo)->entry)); fprintf(fp, "%s\n", tmp_str); /* write substrate parameters */ for (i = 0; i < NUMSUBPARS; i++) { tmp_str1 = (gchar *) gtk_entry_get_text(GTK_ENTRY (twin->subparam_text[i])); /* if entry has no text write "NULL" on file */ if (tmp_str1[0] == '\0') strcpy(tmp_str1, "NULL"); tmp_str2 = (gchar *) gtk_entry_get_text (GTK_ENTRY (GTK_COMBO (twin->subparam_combo[i])->entry)); fprintf(fp, "%s %s\n", tmp_str1, tmp_str2); } /* write component parameters */ for (i = 0; i < NUMCOMPPARS; i++) { tmp_str1 = (gchar *) gtk_entry_get_text (GTK_ENTRY (twin->component_param_text[i])); /* if entry has no text write "NULL" on file */ if (tmp_str1[0] == '\0') strcpy(tmp_str1, "NULL"); tmp_str2 = (gchar *) gtk_entry_get_text (GTK_ENTRY (GTK_COMBO (twin->component_param_combo[i])->entry)); fprintf(fp, "%s %s\n", tmp_str1, tmp_str2); } /* write physical parameters */ for (i = 0; i < NUMPHYSPARS; i++) { tmp_str1 = (gchar *) gtk_entry_get_text (GTK_ENTRY (twin->physical_param_text[i])); /* if entry has no text write "NULL" on file */ if (tmp_str1[0] == '\0') strcpy(tmp_str1, "NULL"); tmp_str2 = (gchar *) gtk_entry_get_text (GTK_ENTRY (GTK_COMBO (twin->physical_param_combo[i])->entry)); fprintf(fp, "%s %s\n", tmp_str1, tmp_str2); } /* write physical parameters status (fix/fixed) */ for (i = 0; i < 2; i++) { gtk_label_get(GTK_LABEL (GTK_BIN (twin->physical_param_fix[i])->child), &tmp_str); fprintf(fp, "%s %i\n", tmp_str, GTK_WIDGET_IS_SENSITIVE(GTK_WIDGET (twin->physical_param_fix[i]))); } /* write electrical parameters */ for (i = 0; i < NUMELECPARS; i++) { tmp_str1 = (gchar *) gtk_entry_get_text (GTK_ENTRY (twin->electrical_param_text[i])); /* if entry has no text write "NULL" on file */ if (tmp_str1[0] == '\0') strcpy(tmp_str1, "NULL"); tmp_str2 = (gchar *) gtk_entry_get_text (GTK_ENTRY (GTK_COMBO (twin->electrical_param_combo[i])->entry)); fprintf(fp, "%s %s\n", tmp_str1, tmp_str2); } /* write status */ gtk_label_get(GTK_LABEL (twin->status), &tmp_str); fprintf(fp, "%s\n", tmp_str); if (file_save_mode == SAVE_END) { gdk_window_get_size ( GTK_WIDGET (tgui->mainwindow)->window, &main_window_width, &main_window_height); fprintf(fp, "%d %d \n", main_window_width, main_window_height); } fclose(fp); return 0; } /* file_selection_ok_save() - write current transmission line data to file */ static gint file_selection_ok_save (GtkFileSelection *fs, GtkWidget *w) { FILE *fp; gchar *fname, *fname_ext; gchar *ext; /* get file name */ fname = (gchar *) gtk_file_selection_get_filename (fs); /* add file extension if necessary*/ ext = rindex (fname, '.'); if (ext == NULL) { fname_ext = g_strconcat(fname, ".trc", NULL); } else { if (strcmp(ext, ".trc")) fname_ext = g_strconcat(fname, ".trc", NULL); else fname_ext = g_strdup(fname); } fp = fopen(fname_ext, "w"); /* free complete file name string */ g_free(fname_ext); if (!fp) /* problems opening file */ return -1; /* file selection dialog is no longer needed */ gtk_widget_destroy (GTK_WIDGET (fs)); trc_file_save (fp, SAVE_OPER); return 0; } gint trc_file_load (FILE *fp, short load_mode) { gchar tmp_str1[80], tmp_str2[80]; gint i, tmp_int; char buf[256], *ip = NULL, *end = NULL; /* here fgets and scanf are mixed, could be done in a better way... */ do { fgets(buf, 256, fp); ip = &buf[0]; /* skip spaces */ while ((*ip == ' ') || (*ip == '\t')) ip++; } while ((*ip == '#') || (*ip == '\n')); /* don't process empty lines */ /* Get the ending position. */ for (end = ip; *end && *end != '\n'; end++); /* make sure it terminates with '\0' */ *end = '\0'; /* read transmission line type */ gtk_entry_set_text (GTK_ENTRY (GTK_COMBO(transtype_combo)->entry), ip); /* read substrate parameters */ for (i = 0; i < NUMSUBPARS; i++) { fscanf(fp, "%s %s\n", tmp_str1, tmp_str2); /* if "NULL" is read entry will have no text */ if (!strcmp(tmp_str1, "NULL")) tmp_str1[0] = '\0'; gtk_entry_set_text(GTK_ENTRY (twin->subparam_text[i]), tmp_str1); gtk_entry_set_text (GTK_ENTRY (GTK_COMBO (twin->subparam_combo[i])->entry), tmp_str2); } /* read component parameters */ for (i = 0; i < NUMCOMPPARS; i++) { fscanf(fp, "%s %s\n", tmp_str1, tmp_str2); /* if "NULL" is read entry will have no text */ if (!strcmp(tmp_str1, "NULL")) tmp_str1[0] = '\0'; gtk_entry_set_text (GTK_ENTRY (twin->component_param_text[i]), tmp_str1); gtk_entry_set_text (GTK_ENTRY (GTK_COMBO (twin->component_param_combo[i])->entry), tmp_str2); } /* read physical parameters */ for (i = 0; i < NUMPHYSPARS; i++) { fscanf(fp, "%s %s\n", tmp_str1, tmp_str2); /* if "NULL" is read entry will have no text */ if (!strcmp(tmp_str1, "NULL")) tmp_str1[0] = '\0'; gtk_entry_set_text (GTK_ENTRY (twin->physical_param_text[i]), tmp_str1); gtk_entry_set_text (GTK_ENTRY (GTK_COMBO (twin->physical_param_combo[i])->entry), tmp_str2); } /* read physical parameters status (fix/fixed) */ for (i = 0; i < 2; i++) { fscanf(fp, "%s %i\n", tmp_str1, &tmp_int); gtk_label_set_text(GTK_LABEL (GTK_BIN (twin->physical_param_fix[i])->child), tmp_str1); gtk_widget_set_sensitive(GTK_WIDGET (twin->physical_param_fix[i]), tmp_int); } /* read electrical parameters */ for (i = 0; i < NUMELECPARS; i++) { fscanf(fp, "%s %s\n", tmp_str1, tmp_str2); /* if "NULL" is read entry will have no text */ if (!strcmp(tmp_str1, "NULL")) tmp_str1[0] = '\0'; gtk_entry_set_text (GTK_ENTRY (twin->electrical_param_text[i]), tmp_str1); gtk_entry_set_text (GTK_ENTRY (GTK_COMBO (twin->electrical_param_combo[i])->entry), tmp_str2); } /* read status string */ /* get whole line */ fgets(buf, 256, fp); ip = &buf[0]; /* Get the ending position. */ for (end = ip; *end && *end != '\n'; end++); /* make sure it terminates with '\0' */ *end = '\0'; gtk_label_set_text(GTK_LABEL (twin->status), ip); if (load_mode == LOAD_INIT) { fscanf(fp, "%d %d\n", &main_window_width, &main_window_height); } fclose (fp); return 0; } /* file_selection_ok_load() - read transmission line data from file */ static gint file_selection_ok_load (GtkFileSelection *fs, GtkWidget *w) { FILE *fp; gchar *fname; /* get selected file name */ fname = (gchar *) gtk_file_selection_get_filename (fs); /* try to open the file */ fp = fopen(fname, "r"); /* done with fname, destroy the file dialog */ gtk_widget_destroy (GTK_WIDGET (fs)); if (!fp) /* problems opening file */ return -1; trc_file_load (fp, LOAD_OPER); return 0; } /* this function is called when the file selection entry changes */ static void file_selection_update_file_list(GtkWidget * dialog) { GtkFileSelection *fs = NULL; gchar *list_name; guint i = 0; g_return_if_fail(GTK_IS_FILE_SELECTION(dialog)); fs = GTK_FILE_SELECTION(dialog); gtk_idle_remove(idle_flag); idle_flag = 0; if (!filter_text || !strlen(filter_text)) return; /* stop updating the list visuals */ gtk_clist_freeze(GTK_CLIST(fs->file_list)); while (gtk_clist_get_text(GTK_CLIST(fs->file_list), i, 0, &list_name)) { if (fnmatch(filter_text, list_name, 0)) { gtk_clist_remove(GTK_CLIST(fs->file_list), i); continue; } i++; } /* enable updating list visuals */ gtk_clist_thaw(GTK_CLIST(fs->file_list)); } /* if user double-click on a directory update the file list according to the current filter */ static void file_selection_dir_button(GtkWidget * widget, GtkWidget * dialog) { if (idle_flag) { return; } idle_flag = gtk_idle_add((GtkFunction) file_selection_update_file_list, dialog); } /* When file_selection_dialog() is called with a path argument ending with * a file name this function search and higlight this file in the file list, * if present * * Adapted from gtk-app-devel-list, Andreas Tille: tille@physik.uni-halle.de * */ static void file_selection_goto(GtkFileSelection * fs) { const char *pre_file; gchar *list_name; gint i; gtk_idle_remove(goto_flag); goto_flag = 0; g_return_if_fail(GTK_IS_FILE_SELECTION(fs)); pre_file = gtk_entry_get_text(GTK_ENTRY(fs->selection_entry)); if (pre_file) { i = -1; while (gtk_clist_get_text(GTK_CLIST(fs->file_list), ++i, 0, &list_name)) { if (list_name && g_str_equal(list_name, pre_file)) { gtk_clist_select_row(GTK_CLIST(fs->file_list), i, 0); gtk_clist_moveto(GTK_CLIST(fs->file_list), i, 0, 0.5, 0.0); break; } } } } /* when filter entry is changed update the file list according to the current filter */ static gint file_selection_filter_key_press(GtkWidget * widget, GdkEventKey * event, GtkWidget * dialog) { GtkFileSelection *fs = NULL; if (!GTK_IS_FILE_SELECTION(dialog)) return FALSE; fs = GTK_FILE_SELECTION(dialog); if (event->keyval == GDK_KP_Enter) { /* convert keypad enter key to return key (?) */ event->keyval = GDK_Return; } if (event->keyval == GDK_Tab || event->keyval == GDK_Return) { filter_text = (gchar *) gtk_entry_get_text(GTK_ENTRY(widget)); /* this will trigger the file list updating */ gtk_file_selection_set_filename(fs, "./"); } return FALSE; } /* create a file selection dialog with a given window title and given current files path */ static GtkWidget* file_selection_dialog (gchar * title, gchar *path) { static GtkWidget *dialog = NULL; GtkWidget *label = NULL; if (!dialog) { dialog = gtk_file_selection_new (title); gtk_file_selection_hide_fileop_buttons (GTK_FILE_SELECTION (dialog)); gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE); gtk_signal_connect (GTK_OBJECT (dialog), "destroy", GTK_SIGNAL_FUNC(gtk_widget_destroyed), &dialog); label = gtk_label_new("Filter:"); gtk_box_pack_start(GTK_BOX(GTK_FILE_SELECTION (dialog)->action_area), label, FALSE, FALSE, 0); gtk_widget_show(label); filter_entry = gtk_entry_new(); gtk_box_pack_start(GTK_BOX(GTK_FILE_SELECTION (dialog)->action_area), filter_entry, FALSE, FALSE, 0); gtk_entry_set_text(GTK_ENTRY(filter_entry), filter_text); gtk_widget_show(filter_entry); /* when the selection entry changes update the file list */ /* this can be triggered also by double clicking on a directory */ gtk_signal_connect(GTK_OBJECT (GTK_FILE_SELECTION(dialog)->selection_entry), "changed", (GtkSignalFunc) file_selection_dir_button, (gpointer) dialog); gtk_signal_connect(GTK_OBJECT(filter_entry), "key_press_event", (GtkSignalFunc) file_selection_filter_key_press, dialog); /* set current filename (if any); this will also trigger file list update, according to filter_text */ gtk_file_selection_set_filename(GTK_FILE_SELECTION(dialog), path); /* select the current selection entry */ gtk_editable_select_region(GTK_EDITABLE(GTK_FILE_SELECTION(dialog)->selection_entry), 0, -1); goto_flag = gtk_idle_add((GtkFunction) file_selection_goto, (gpointer) dialog); } if (!GTK_WIDGET_VISIBLE (dialog)) gtk_widget_show (dialog); else gtk_widget_destroy (dialog); return dialog; } /* prepare creation of file selection dialoc setting the callbacks and window title */ void file_dialog(gpointer callback_data, guint callback_action, GtkWidget *widget) { GtkWidget *filesel = NULL; switch (callback_action) { case TC_FILE_LOAD : filesel = file_selection_dialog("Load file...", "./"); gtk_signal_connect_object(GTK_OBJECT(GTK_FILE_SELECTION(filesel)->ok_button), "clicked", GTK_SIGNAL_FUNC(file_selection_ok_load), GTK_OBJECT(filesel)); break; case TC_FILE_SAVE : filesel = file_selection_dialog("Save file...", "./"); gtk_signal_connect_object(GTK_OBJECT(GTK_FILE_SELECTION(filesel)->ok_button), "clicked", GTK_SIGNAL_FUNC(file_selection_ok_save), GTK_OBJECT(filesel)); break; default : g_assert_not_reached(); } gtk_signal_connect_object(GTK_OBJECT(GTK_FILE_SELECTION(filesel)->cancel_button), "clicked", (GtkSignalFunc)gtk_widget_destroy, GTK_OBJECT(filesel)); gtk_widget_show (filesel); }