Clean up a slew of warnings from gcc -Wall - mostly unused variables.
[gwave-svn.git] / src / wavelist.c
blob91cf7e96c3fe16940c184199e03e7e542f260eb2
1 /*
2 * wavelist.c - part of gwave
3 * routines to handle the scrolling list of potentialy-displayable waveforms,
4 * and other stuff related to loading of data files.
6 * Copyright (C) 1998, 1999 Stephen G. Tell
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public
19 * License along with this software; if not, write to the Free
20 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #include <ctype.h>
25 #include <math.h>
26 #include <setjmp.h>
27 #include <stdarg.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <unistd.h>
32 #include <errno.h>
33 #include <sys/time.h>
35 #include <gtk/gtk.h>
36 #include <guile-gnome-gobject/gobject.h>
38 #include <config.h>
39 #include <scwm_guile.h>
40 #include <gwave.h>
42 #define WAVELIST_IMPLEMENTATION
43 #include <wavelist.h>
44 #include <wavewin.h>
45 #include <measurebtn.h>
46 #include <dnd.h>
48 GList *wdata_list = NULL;
49 static char file_tag_chars[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
50 static const int n_file_tags = sizeof(file_tag_chars)/sizeof(char);
51 static int next_file_tagno = 0;
53 void gwfile_add_wv_to_list(gpointer d /*WaveVar* */,
54 gpointer p /*GWDataFile */);
56 void wavelist_button_click(GtkWidget *widget,
57 GdkEventButton *event, gpointer data);
59 XSCM_HOOK(new_wavefile_hook,"new-wavefile-hook", 1, (SCM DF),
60 "This hook is invoked when a new waveform file is successfully loaded."
61 "It is called with the new GWDataFile, DF, as its only argument.");
63 XSCM_HOOK(new_wavelist_hook,"new-wavelist-hook", 1, (SCM DF),
64 "This hook is invoked when the variable list window for a"
65 "GWDataFile is created. The GWDataFile object, DF, is passed as an"
66 "argument. Note that variable-list windows can be created and"
67 "destroyed many times during the life of a GWDataFile. One of the principle"
68 "uses of this hook is creating the menus such for the variable-list window.");
71 * Load a waveform file, adding it to the list of files from which
72 * variables can be chosen to add to the display.
74 GWDataFile *
75 load_wave_file(char *fname, char *ftype)
77 GWDataFile *wdata;
79 wdata = g_new0(GWDataFile, 1);
80 wdata->wf = wf_read(fname, ftype);
82 if(wdata->wf == NULL) {
83 g_free(wdata);
84 return NULL;
86 wdata->wf->udata = wdata;
88 /* give the file a short (fow now, 1-character) "tag" to identify it
89 * in the menu and variable labels.
91 wdata->ftag = g_new(char, 2);
92 wdata->ftag[0] = file_tag_chars[next_file_tagno];
93 wdata->ftag[1] = '\0';
94 next_file_tagno = (next_file_tagno + 1) % n_file_tags;
95 wdata->ndv = wdata->wf->wf_ndv;
96 wdata->wvhl = NULL; /* empty GSList of WaveVarH* */
98 wdata_list = g_list_append(wdata_list, wdata);
99 wdata->outstanding_smob = 1;
100 SGT_NEWCELL_SMOB(wdata->smob, GWDataFile, wdata);
101 call1_hooks(new_wavefile_hook, wdata->smob);
103 if(wtable->window)
104 cmd_show_wave_list(NULL, wdata);
106 return wdata;
109 SCM_DEFINE(load_wavefile_x, "load-wavefile!", 1, 1, 0, (SCM file, SCM filetype),
110 "Load waveform data from FILE into memory, and make it available for"
111 "display. If FILETYPE is specified, it indicates the format of the file"
112 "and which wavefile reader to use, otherwise the format is inferred"
113 "from the filename and file contents. Returns a GWDataFile object"
114 "which can be used to refer to the loaded data.")
115 #define FUNC_NAME s_load_wavefile_x
117 char *fname, *ftype;
118 GWDataFile *df;
120 VALIDATE_ARG_STR_NEWCOPY(1, file, fname);
121 VALIDATE_ARG_STR_NEWCOPY_USE_NULL(2, filetype, ftype);
122 df = load_wave_file(fname, ftype);
123 g_free(fname);
124 if(ftype)
125 g_free(ftype);
126 if(df)
127 return df->smob;
128 else
129 return SCM_BOOL_F;
131 #undef FUNC_NAME
134 * Delete a wave file.
135 * callback from menu: wavelist->file->delete
137 void
138 delete_wave_file(GtkWidget *w, GWDataFile *wdata)
140 GSList *list;
141 /* remove references from displayed waves */
142 remove_wfile_waves(wdata);
144 /* remove per-file GUI stuff */
145 if(wdata->wlist_win && GTK_WIDGET_VISIBLE(wdata->wlist_win))
146 gtk_widget_destroy(wdata->wlist_win);
148 /* invalidate WaveVar pointers in handles.
149 * Can't free WaveVar because un-GCed smobs may point to them
151 for(list = wdata->wvhl; list; list = list->next) {
152 WaveVarH *wvh = (WaveVarH *)list->data;
153 wvh->wv = NULL;
156 /* now nuke the data */
157 wf_free(wdata->wf);
158 wdata->wf = NULL;
159 wdata_list = g_list_remove(wdata_list, wdata);
161 if(wdata->outstanding_smob) {
162 if(v_flag)
163 fprintf(stderr, "defering free of GWDataFile\n");
164 } else {
165 if(v_flag)
166 fprintf(stderr, "free GWDataFile 0x%x\n", wdata);
167 g_free(wdata);
171 SCM_DEFINE(datafile_delete_x, "wavefile-delete!", 1, 0, 0,
172 (SCM obj),
173 "Delete from memory the waveform data from OBJ.")
174 #define FUNC_NAME s_datafile_delete_x
176 GWDataFile *wdata;
177 VALIDATE_ARG_GWDataFile_COPY(1, obj, wdata);
179 if(wdata->wf)
180 delete_wave_file(NULL, wdata);
181 return SCM_UNSPECIFIED;
183 #undef FUNC_NAME
186 * command or callback from menu: wavelist->file->reload
188 void
189 reload_wave_file(GtkWidget *w, GWDataFile *wdata)
191 WaveFile *new_wf;
192 WaveFile *old_wf;
194 /* FIXME:sgt: get file type from old file, if it was specified
195 * when loading it originaly
197 new_wf = wf_read(wdata->wf->wf_filename, NULL);
198 if(new_wf == NULL) {
199 fprintf(stderr, "reload_wave_file: failed to read %s\n", wdata->wf->wf_filename);
200 /* FIXME:sgt put up error message in window */
201 return;
203 old_wf = wdata->wf;
204 wdata->wf = new_wf;
205 wdata->wf->udata = wdata;
206 /* printf("reload_wave_file(%s) old=%lx new=%lx\n",
207 wdata->wf->wf_filename, old_wf, new_wf); */
209 update_wfile_waves(wdata);
211 /* remove old buttons from list, and add new ones */
212 if(wdata->wlist_win && GTK_WIDGET_VISIBLE(wdata->wlist_win)) {
213 gtk_container_foreach(GTK_CONTAINER(wdata->wlist_box),
214 (GtkCallback) gtk_widget_destroy, NULL);
215 wf_foreach_wavevar(wdata->wf, gwfile_add_wv_to_list, (gpointer)wdata);
218 wf_free(old_wf);
219 mbtn_update_all();
222 void
223 reload_wave_file_w(gpointer p, gpointer d)
225 GWDataFile *wdata = (GWDataFile *)p;
226 reload_wave_file(NULL, wdata);
230 * Reload all files.
231 * plan: replace this with update_all_wave_files(), which checks
232 * file dates/sizes and only reloads those that need it.
234 void
235 reload_all_wave_files(GtkWidget *w)
237 g_list_foreach(wdata_list, reload_wave_file_w, NULL);
240 SCM_DEFINE(reload_all_files_x, "reload-all-files!", 0, 0, 0, (),
241 "Reload all files")
242 #define FUNC_NAME s_reload_all_files_x
244 g_list_foreach(wdata_list, reload_wave_file_w, NULL);
245 return SCM_UNSPECIFIED;
247 #undef FUNC_NAME
249 SCM_DEFINE(datafile_reload_x, "wavefile-reload!", 1, 0, 0,
250 (SCM obj),
251 "Reread the data file for OBJ. Useful for updating the display"
252 " after simulation has been rerun.")
253 #define FUNC_NAME s_datafile_reload_x
255 GWDataFile *wdata;
256 VALIDATE_ARG_GWDataFile_COPY(1, obj, wdata);
258 if(wdata->wf)
259 reload_wave_file(NULL, wdata);
260 return SCM_UNSPECIFIED;
262 #undef FUNC_NAME
265 * Callback for use with wv_foreach_wavevar:
267 * Add a button for each variable in the file to the win_wlist box for it.
268 * Arrange for the buttons to be drag-and-drop sources for placing the
269 * variables into wavepanels.
271 * formerly add_variables_to_list(GWDataFile *wdata)
273 void
274 gwfile_add_wv_to_list(gpointer d, gpointer p)
276 WaveVar *wv = (WaveVar *)d;
277 GWDataFile *wdata = (GWDataFile *)p;
278 GtkWidget *button;
280 if(wv_is_multisweep(wv)) {
281 char lab[4096];
282 sprintf(lab, "%s @ %s=%g", wv->wv_name,
283 wv->wtable->name, wv->wtable->swval);
284 button = gtk_button_new_with_label(lab);
285 } else {
286 button = gtk_button_new_with_label(wv->wv_name);
289 gtk_box_pack_start (GTK_BOX (wdata->wlist_box), button, FALSE, FALSE, 0);
290 gtk_widget_show (button);
292 if(GTK_IS_TOOLTIPS(wtable->ttips))
293 gtk_tooltips_set_tip(GTK_TOOLTIPS(wtable->ttips), button,
294 "Wavefile Variable.\nDrag-and-Drop to a WavePanel.", "");
296 dnd_setup_source(GTK_WINDOW(wdata->wlist_win), button, wv);
298 gtk_signal_connect (GTK_OBJECT(button), "button-press-event",
299 GTK_SIGNAL_FUNC(wavelist_button_click),
300 (gpointer) wv);
304 * Show the variable-list window for a waveform data file.
305 * If the window already exists, simply raise it to the top.
307 void
308 cmd_show_wave_list(GtkWidget *w, GWDataFile *wdata)
310 GtkWidget *box1;
311 GtkWidget *scrolled_window;
312 GtkWidget *label;
314 if(!wdata) {
315 fprintf(stderr, "cmd_show_wave_list: wdata is NULL");
316 return;
319 if(!wdata->wlist_win) {
320 char buf[256];
322 wdata->wlist_win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
323 gtk_widget_set_name(wdata->wlist_win, "data list window");
324 sprintf(buf, "gwave: %.64s", wdata->wf->wf_filename);
325 gtk_window_set_title(GTK_WINDOW(wdata->wlist_win), buf);
326 gtk_widget_set_usize(wdata->wlist_win, 150, 300);
327 { /* suggest that the window manager try to put the wavelist
328 * window somewhere to the left of the main window.
329 * This nonsense really belongs in a smarter window manager,
330 * but users are demanding somthing.
332 static int diddle=0;
333 int x, y;
334 x = 200+175;
335 y = 200;
336 if(wtable
337 && wtable->window && wtable->window->window) {
338 gdk_window_get_position(wtable->window->window,
339 &x, &y);
340 y += diddle * 25;
341 x -= diddle * 20;
342 diddle = (diddle + 1) % 4;
344 gtk_widget_set_uposition(wdata->wlist_win, x-175, y);
346 gtk_signal_connect (GTK_OBJECT (wdata->wlist_win), "destroy",
347 GTK_SIGNAL_FUNC(gtk_widget_destroyed),
348 &(wdata->wlist_win));
350 box1 = gtk_vbox_new(FALSE, 0);
351 gtk_container_add(GTK_CONTAINER(wdata->wlist_win), box1);
352 gtk_widget_show(box1);
353 wdata->wlist_menubar = gtk_menu_bar_new();
354 gtk_widget_show(wdata->wlist_menubar);
355 gtk_box_pack_start (GTK_BOX (box1), wdata->wlist_menubar, FALSE, FALSE, 0);
357 if(strlen(wdata->wf->wf_filename) > 16) {
358 char *cp = strrchr(wdata->wf->wf_filename, '/');
359 if(cp)
360 sprintf(buf, "%s: .../%.64s", wdata->ftag, cp+1);
361 else
362 sprintf(buf, "%s: .../%.64s", wdata->ftag, wdata->wf->wf_filename);
363 } else {
364 sprintf(buf, "%s: %.64s", wdata->ftag, wdata->wf->wf_filename);
366 label = gtk_label_new(buf);
367 gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT);
368 gtk_widget_show(label);
369 gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);
373 scrolled_window = gtk_scrolled_window_new (NULL, NULL);
374 gtk_container_border_width (GTK_CONTAINER (scrolled_window), 10);
375 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
376 GTK_POLICY_AUTOMATIC,
377 GTK_POLICY_ALWAYS);
378 GTK_WIDGET_UNSET_FLAGS (GTK_SCROLLED_WINDOW (scrolled_window)->vscrollbar, GTK_CAN_FOCUS);
379 gtk_box_pack_start(GTK_BOX (box1), scrolled_window,
380 TRUE, TRUE, 0);
381 gtk_widget_show (scrolled_window);
383 wdata->wlist_box = gtk_vbox_new (FALSE, 0);
384 gtk_container_border_width (GTK_CONTAINER (wdata->wlist_box), 10);
385 gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolled_window),
386 wdata->wlist_box);
387 gtk_container_set_focus_vadjustment(
388 GTK_CONTAINER (wdata->wlist_box),
389 gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(scrolled_window)));
390 gtk_widget_show (wdata->wlist_box);
392 dnd_init(wdata->wlist_win);
393 wf_foreach_wavevar(wdata->wf, gwfile_add_wv_to_list, (gpointer)wdata);
395 call1_hooks(new_wavelist_hook, wdata->smob);
397 gtk_widget_show(wdata->wlist_win);
398 } else {
399 gdk_window_raise(wdata->wlist_win->window);
404 * Called for all button presses on wavelist button.
405 * If it is a doubleclick, add variable to the "current" wavepanel immediately.
407 void
408 wavelist_button_click(GtkWidget *widget,
409 GdkEventButton *bevent,
410 gpointer data)
412 WaveVar *dv = (WaveVar *)data;
413 if(bevent->type == GDK_2BUTTON_PRESS) {
414 /* printf("doubleclicked %s %s\n", dv->wfile->ss->filename,
415 dv->sv->name); */
416 add_var_to_panel(NULL, dv);
420 SCM_DEFINE(wavefile_show_listwin_x, "wavefile-show-listwin!", 1, 0, 0,
421 (SCM obj),
422 "Displays the scrolling list of the variables in OBJ, from which they"
423 "can be dragged into a waveform display panel.")
424 #define FUNC_NAME s_wavefile_show_listwin_x
426 GWDataFile *wdata;
427 VALIDATE_ARG_GWDataFile_COPY(1, obj, wdata);
429 if(v_flag)
430 fprintf(stderr, "%s wdata=0x%x\n", FUNC_NAME, wdata);
431 if(wdata->wf)
432 cmd_show_wave_list(NULL, wdata);
433 return SCM_UNSPECIFIED;
436 #undef FUNC_NAME
438 /* maybe I should just expose the GTkWindow itself, and destroy from guile */
439 SCM_DEFINE(wavefile_remove_listwin_x, "wavefile-remove-listwin!", 1, 0, 0,
440 (SCM obj),
441 "Removes the variable-list window for OBJ")
442 #define FUNC_NAME s_wavefile_remove_listwin_x
444 GWDataFile *wdata;
445 VALIDATE_ARG_GWDataFile_COPY(1, obj, wdata);
447 if(wdata->wf && wdata->wlist_win)
448 gtk_widget_destroy(wdata->wlist_win);
449 return SCM_UNSPECIFIED;
452 #undef FUNC_NAME
454 /* Primitives for accessing GWDataFile info from scheme */
456 SCM_DEFINE(wavefile_file_name, "wavefile-file-name", 1, 0, 0,
457 (SCM obj),
458 "Returns the filename from which the GWDataFile OBJ was loaded."
459 "If OBJ is invalid because the datafile has been deleted,"
460 "#f is returned.")
461 #define FUNC_NAME s_wavefile_file_name
463 GWDataFile *wdata;
464 VALIDATE_ARG_GWDataFile_COPY(1, obj, wdata);
466 if(wdata->wf)
467 return scm_makfrom0str(wdata->wf->wf_filename);
468 else
469 return SCM_BOOL_F;
472 #undef FUNC_NAME
474 SCM_DEFINE(wavefile_nsweeps, "wavefile-nsweeps", 1, 0, 0,
475 (SCM df),
476 "Returns the number of sweeps for which data is present in GWDataFile DF.")
477 #define FUNC_NAME s_wavefile_nsweeps
479 GWDataFile *wdata;
480 VALIDATE_ARG_GWDataFile_COPY(1, df, wdata);
482 return scm_long2num(wdata->wf->wf_ntables);
484 #undef FUNC_NAME
486 SCM_DEFINE(wavefile_sweeps, "wavefile-sweeps", 1, 0, 0,
487 (SCM df),
488 "Returns a list of sweeps contained in GWDataFile DF. Each element of the list is a pair, of the form (sweepname . sweepvalue)")
489 #define FUNC_NAME s_wavefile_nsweeps
491 GWDataFile *wdata;
492 SCM result = SCM_EOL;
493 SCM p;
494 WvTable *wt;
495 WaveFile *wf;
496 int i;
497 VALIDATE_ARG_GWDataFile_COPY(1, df, wdata);
499 if(!wdata->wf)
500 return result;
502 wf = wdata->wf;
503 for(i = 0; i < wf->wf_ntables; i++) {
504 wt = wf_wtable(wf, i);
505 p = scm_cons(scm_makfrom0str(wt->name), scm_make_real(wt->swval));
506 result = scm_cons(p, result);
508 return scm_reverse(result);
510 #undef FUNC_NAME
512 SCM_DEFINE(wavefile_tag, "wavefile-tag", 1, 0, 0,
513 (SCM obj),
514 "Returns the short identifying tag for the GWDataFile OBJ.")
515 #define FUNC_NAME s_wavefile_tag
517 GWDataFile *wdata;
518 VALIDATE_ARG_GWDataFile_COPY(1, obj, wdata);
520 return scm_makfrom0str(wdata->ftag);
522 #undef FUNC_NAME
524 SCM_DEFINE(wavefile_set_tag_x, "wavefile-set-tag!", 2, 0, 0,
525 (SCM obj, SCM str),
526 "Set the short identifying tag for the GWDataFile OBJ to STR.")
527 #define FUNC_NAME s_wavefile_set_tag_x
529 GWDataFile *wdata;
530 char *s;
531 VALIDATE_ARG_GWDataFile_COPY(1, obj, wdata);
532 VALIDATE_ARG_STR_NEWCOPY(1, str, s);
533 g_free(wdata->ftag);
534 wdata->ftag = s;
535 return SCM_UNSPECIFIED;
536 /* BUG: any visiblewave button labels and wavelist menu entries
537 * won't be affected by the change in ftag */
539 #undef FUNC_NAME
541 SCM_DEFINE(wavefile_listwin_menubar, "wavefile-listwin-menubar", 1, 0, 0,
542 (SCM obj),
543 "Returns the GTK Menubar for the variable-list window of the"
544 " * GWDataFile OBJ, or #f if the window doesn't exist.")
545 #define FUNC_NAME s_wavefile_listwin_menubar
547 GWDataFile *wdata;
548 VALIDATE_ARG_GWDataFile_COPY(1, obj, wdata);
550 if(wdata->wlist_win && wdata->wlist_menubar)
551 return scm_c_gtype_instance_to_scm(GTK_OBJECT(wdata->wlist_menubar));
552 else
553 return SCM_BOOL_F;
555 #undef FUNC_NAME
558 wavefile_to_scm(void *vp)
560 GWDataFile *wdata = (GWDataFile *)vp;
561 return wdata->smob;
565 glist2scm(GList *list, SCM (*toscm)(void*))
567 SCM result = SCM_EOL;
568 while(list) {
569 result = scm_cons(toscm(list->data), result);
570 list = list->next;
572 return result;
575 SCM_DEFINE(wavefile_list, "wavefile-list", 0, 0, 0, (),
576 "Returns a list containing all waveform data files")
577 #define FUNC_NAME s_wavefile_list
579 return glist2scm(wdata_list, wavefile_to_scm);
581 #undef FUNC_NAME
584 SCM_DEFINE(wavefile_all_variables, "wavefile-all-variables", 1, 0, 0, (SCM df),
585 "Returns a list of WaveVars, composed of all variables in the GWDataFile DF.")
586 #define FUNC_NAME s_wavefile_all_variables
588 GWDataFile *wdata;
589 SCM result = SCM_EOL;
590 SCM wvsmob;
592 WaveFile *wf;
593 WvTable *wt;
594 int i, j;
595 VALIDATE_ARG_GWDataFile_COPY(1, df, wdata);
597 if(!wdata->wf)
598 return result;
600 wf = wdata->wf;
601 for(i = 0; i < wf->wf_ntables; i++) {
602 wt = wf_wtable(wf, i);
603 for(j = 0; j < wf->wf_ndv; j++) {
604 WaveVar *wv;
605 WaveVarH *wvh;
606 wv = &wt->dv[j];
607 if(!wv->udata) {
608 wvh = g_new0(WaveVarH, 1);
609 wvh->wv = wv;
610 wvh->df = wdata;
611 wv->udata = wvh;
612 wdata->wvhl = g_slist_prepend(wdata->wvhl, wvh);
613 SGT_NEWCELL_SMOB(wvsmob, WaveVar, wvh);
614 wvh->smob = wvsmob;
615 } else {
616 wvh = (WaveVarH *)wv->udata;
617 wvsmob = wvh->smob;
619 result = scm_cons(wvsmob, result);
622 return scm_reverse(result);
624 #undef FUNC_NAME
627 SCM_DEFINE(wavefile_variable, "wavefile-variable", 3, 0, 0,
628 (SCM df, SCM vname, SCM swindex),
629 "Returns a WaveVar representing the variable named VNAME in sweep/table/segment SWINDEX in the GWDataFile DF. Return #f if there is no variable named VNAME")
630 #define FUNC_NAME s_wavefile_variable
632 GWDataFile *wdata;
633 SCM result = SCM_BOOL_F;
634 char *s;
635 int swp;
636 VALIDATE_ARG_GWDataFile_COPY(1, df, wdata);
637 VALIDATE_ARG_STR_NEWCOPY(2, vname, s);
638 VALIDATE_ARG_INT_MIN_COPY(3, swindex, 0, swp);
640 if(wdata->wf && swp < wdata->wf->wf_ntables) {
641 WaveVar *wv = wf_find_variable(wdata->wf, s, swp);
642 if(wv) {
643 WaveVarH *wvh;
644 if(!wv->udata) {
645 wvh = g_new0(WaveVarH, 1);
646 wvh->wv = wv;
647 wvh->df = wdata;
648 wv->udata = wvh;
649 wdata->wvhl = g_slist_prepend(wdata->wvhl, wvh);
650 SGT_NEWCELL_SMOB(result, WaveVar, wvh);
651 wvh->smob = result;
652 } else {
653 wvh = (WaveVarH *)wv->udata;
654 result = wvh->smob;
658 g_free(s);
659 return result;
661 #undef FUNC_NAME
663 SCM_DEFINE(variable_signame, "variable-signame", 1, 0, 0,
664 (SCM var),
665 "Return the signal name for the variable VAR.")
666 #define FUNC_NAME s_variable_signame
668 WaveVar *wv;
669 VALIDATE_ARG_VisibleWaveOrWaveVar_COPY(1,var,wv);
671 if(wv)
672 return scm_makfrom0str(wv->sv->name);
673 else
674 return SCM_BOOL_F;
676 #undef FUNC_NAME
679 SCM_DEFINE(variable_sweepname, "variable-sweepname", 1, 0, 0,
680 (SCM var),
681 "Return the sweep name or table name for the variable VAR.")
682 #define FUNC_NAME s_variable_sweepname
684 WaveVar *wv;
685 VALIDATE_ARG_VisibleWaveOrWaveVar_COPY(1,var,wv);
687 if(wv)
688 return scm_makfrom0str(wv->wtable->name);
689 else
690 return SCM_BOOL_F;
692 #undef FUNC_NAME
695 SCM_DEFINE(variable_sweepindex, "variable-sweepindex", 1, 0, 0,
696 (SCM var),
697 "Return the sweep table index for the variable VAR. Sweeps/tables are numbered starting with 0. ")
698 #define FUNC_NAME s_variable_sweepindex
700 WaveVar *wv;
701 VALIDATE_ARG_VisibleWaveOrWaveVar_COPY(1,var,wv);
703 if(wv)
704 return scm_long2num(wv->wtable->swindex);
705 else
706 return SCM_BOOL_F;
708 #undef FUNC_NAME
711 SCM_DEFINE(variable_wavefile, "variable-wavefile", 1, 0, 0,
712 (SCM var),
713 "Return the WaveFile that the variable VAR is contained in.")
714 // Really, the GWDataFile smob.
715 #define FUNC_NAME s_variable_wavefile
717 WaveVar *wv;
718 VALIDATE_ARG_VisibleWaveOrWaveVar_COPY(1,var,wv);
720 if(wv) {
721 GWDataFile *df = wvar_gwdatafile(wv);
722 df->outstanding_smob = 1;
723 return df->smob;
724 } else
725 return SCM_BOOL_F;
727 #undef FUNC_NAME
729 SCM_DEFINE(export_variables, "export-variables", 2, 2, 0,
730 (SCM varlist, SCM port, SCM from, SCM to),
731 "Write the data for all variables in VARLIST to PORT in tabular ascii form"
732 "If FROM and TO are specified, writes only data points for which the"
733 "independent variable is between FROM and TO includsive."
734 "All variables in VARLIST must share the same independent variable")
735 #define FUNC_NAME s_export_variables
737 SCM l, v;
738 WaveVar *wv;
739 WaveVar *iv = NULL;
740 double from_val, to_val;
741 int starti, endi, i;
742 double x,y;
743 char buf[128];
744 SCM_ASYNC_TICK;
745 /* validate varlist and count elements */
746 for (l = varlist; SCM_NNULLP(l); l = SCM_CDR (l)) {
747 v = SCM_CAR(l);
748 VALIDATE_ARG_VisibleWaveOrWaveVar_COPY(1,v,wv);
749 if(!wv) {
750 scm_misc_error(FUNC_NAME, "invalid WaveVar ~s", SCM_LIST1(v));
752 if(iv == NULL)
753 iv = wv->wv_iv;
754 else if(iv != wv->wv_iv) {
755 scm_misc_error(FUNC_NAME, "All WaveVars in VARLIST must relate to the same independent variable", SCM_UNDEFINED);
758 VALIDATE_ARG_DBL_COPY_USE_DEF(3,from,from_val, iv->wds[0].min);
759 VALIDATE_ARG_DBL_COPY_USE_DEF(4,to,to_val, iv->wds[0].max);
761 if(from_val > to_val)
762 return SCM_UNSPECIFIED;
763 starti = wf_find_point(iv, from_val);
764 endi = wf_find_point(iv, to_val);
766 for(i = starti; i <= endi; i++) {
767 x = wds_get_point(&iv->wds[0], i);
768 sprintf(buf, "%g", x);
769 scm_puts(buf, port);
770 for (l = varlist; SCM_NNULLP(l); l = SCM_CDR (l)) {
771 v = SCM_CAR(l);
772 VALIDATE_ARG_VisibleWaveOrWaveVar_COPY(1,v,wv);
773 g_assert(wv); /* should have been checked above */
774 y = wds_get_point(&wv->wds[0], i);
775 sprintf(buf, " %g", y);
776 scm_puts(buf, port);
778 scm_puts("\n", port);
781 return SCM_UNSPECIFIED;
783 #undef FUNC_NAME
786 * On the C side we never free WaveVars without freeing the whole
787 * WaveFile structure. When guile GC's one, we invalidate the pointer
788 * in the handle, and then check to see if we can dump the whole
789 * structure.
790 * Methinks we need a more formal reference-counting scheme instead of
791 * all this ad-hockery.
793 int wavefile_try_free(GWDataFile *wdata)
795 int n;
796 if(wdata->outstanding_smob)
797 return 0;
798 if(wdata->wf)
799 return 0;
800 if(wdata->wvhl) /* nonempty list means outstanding handles remain */
801 return 0;
803 if(gwave_debug)
804 printf("free GWDataFile 0x%x during gc\n", wdata);
805 n = wdata->ndv;
806 g_free(wdata);
807 return sizeof(GWDataFile);
810 /* standard SMOB functions for GWDataFile: free, mark, print, GWDataFile? */
811 scm_sizet
812 free_GWDataFile(SCM obj)
814 GWDataFile *wdata =GWDataFile(obj);
815 wdata->outstanding_smob = 0;
816 return wavefile_try_free(wdata);
819 static void mark_GWDataFile_wvh(void *p, void *d)
821 WaveVarH *wvh = (WaveVarH *)p;
822 if(wvh->wv)
823 scm_gc_mark(wvh->smob);
827 mark_GWDataFile(SCM obj)
829 GWDataFile *wdata = GWDataFile(obj);
830 g_slist_foreach(wdata->wvhl, mark_GWDataFile_wvh, NULL);
832 return SCM_BOOL_F;
835 int
836 print_GWDataFile(SCM obj, SCM port, scm_print_state *ARG_IGNORE(pstate))
838 scm_puts("#<GWDataFile ", port);
839 if(GWDataFile(obj)->wf)
840 scm_puts(GWDataFile(obj)->wf->wf_filename, port);
841 else
842 scm_puts("invalid", port);
843 scm_putc('>', port);
844 return 1;
847 SCM_DEFINE(GWDataFile_p, "GWDataFile?", 1, 0, 0,
848 (SCM obj),
849 "Returns #t if OBJ is a gwave data file object, otherwise #f.")
850 #define FUNC_NAME s_GWDataFile_p
852 return SCM_BOOL_FromBool(GWDataFile_P(obj));
854 #undef FUNC_NAME
856 /* standard SMOB functions for WaveVar: free, mark, print, WaveVar? */
858 scm_sizet
859 free_WaveVar(SCM obj)
861 WaveVarH *wvh = WaveVarH(obj);
862 GWDataFile *df;
863 scm_sizet fsize;
864 df = wvh->df;
866 if(gwave_debug)
867 printf("free_WaveVar(wvh=%lx wv=%lx)\n", wvh, wvh->wv);
868 df->wvhl = g_slist_remove(df->wvhl, wvh);
869 fsize = wavefile_try_free(wvh->df);
870 wvh->wv = NULL;
871 wvh->df = NULL;
872 g_free(wvh);
874 return fsize + sizeof(WaveVarH);
878 mark_WaveVar(SCM obj)
880 return SCM_BOOL_F;
883 int
884 print_WaveVar(SCM obj, SCM port, scm_print_state *ARG_IGNORE(pstate))
886 WaveVarH *wvh = WaveVarH(obj);
887 char buf[128];
889 scm_puts("#<WaveVar ", port);
890 if(wvh->wv) {
891 scm_puts(wvh->df->wf->wf_filename, port);
892 scm_puts(",", port);
893 sprintf(buf, "%d", wvh->wv->wtable->swindex);
894 scm_puts(buf,port);
895 scm_puts(",", port);
896 scm_puts(wvh->wv->sv->name, port);
897 scm_puts(",", port);
898 scm_intprint((long)wvh->wv, 16, port);
899 } else
900 scm_puts("invalid", port);
902 scm_putc('>', port);
903 return 1;
906 SCM_DEFINE(WaveVar_p, "WaveVar?", 1, 0, 0,
907 (SCM obj),
908 "Returns #t if OBJ is a wave-file variable object, otherwise #f.")
909 #define FUNC_NAME s_WaveVar_p
911 return SCM_BOOL_FromBool(WaveVarH_P(obj));
913 #undef FUNC_NAME
915 /* guile initialization */
917 MAKE_SMOBFUNS(GWDataFile);
918 MAKE_SMOBFUNS(WaveVar);
920 void init_wavelist()
922 REGISTER_SCWMSMOBFUNS(GWDataFile);
923 REGISTER_SCWMSMOBFUNS(WaveVar);
925 #ifndef SCM_MAGIC_SNARF_INITS
926 #include "wavelist.x"
927 #endif