1 /*-- ggobi-API.c --*/
2 /*
3  * ggobi
4  * Copyright (C) AT&T, Duncan Temple Lang, Dianne Cook 1999-2005
5  *
6  * ggobi is free software; you may use, redistribute, and/or modify it
7  * under the terms of the Eclipse Public License, which is distributed
8  * with the source code and displayed on the ggobi web site,
9  * www.ggobi.org.  For more information, contact the authors:
10  *
11  *   Deborah F. Swayne   dfs@research.att.com
12  *   Di Cook             dicook@iastate.edu
13  *   Duncan Temple Lang  duncan@wald.ucdavis.edu
14  *   Andreas Buja        andreas.buja@wharton.upenn.edu
15 */
16 
17 #include <math.h>
18 #include <string.h>
19 #include <stdlib.h>
20 #include <gtk/gtk.h>
21 
22 #include "GGobiAPI.h"
23 
24 #include "ggobi.h"
25 #include "ggobi-data.h"
26 #include "types.h"
27 #include "vars.h"
28 #include "externs.h"
29 #include "display.h"
30 #include "plugin.h"
31 
32 extern const gchar *const GlyphNames[];
33 
34 void warning (const char *msg);
35 
36 #ifdef __cplusplus
37 extern "C"
38 {
39 #endif
40   void GGOBI (displays_release) (ggobid * gg);
41   void GGOBI (display_release) (displayd * display, ggobid * gg);
42   void GGOBI (splot_release) (splotd * sp, displayd * display, ggobid * gg);
43   void GGOBI (data_release) (GGobiData *, ggobid * gg);
44   void GGOBI (vartable_free) (GGobiData *, ggobid * gg);
45   void GGOBI (vardatum_free) (vartabled * var, ggobid * gg);
46 #ifdef __cplusplus
47 }
48 #endif
49 
GGOBI(getFileName)50 const gchar *GGOBI (getFileName) (ggobid * gg)
51 {
52   return (gg->input->fileName);
53 }
54 
GGOBI(setFileName)55 const gchar *GGOBI (setFileName) (const gchar * fileName, DataMode data_mode,
56                                   ggobid * gg)
57 {
58   const gchar *old = g_strdup (GGOBI (getFileName) (gg));
59   fileset_read_init (fileName, NULL, NULL, gg);
60   display_menu_build (gg);
61   return (old);
62 }
63 
64 
GGOBI(getDataMode)65 DataMode GGOBI (getDataMode) (ggobid * gg)
66 {
67   return (gg->input->mode);
68 }
69 
GGOBI(setDataMode)70 DataMode GGOBI (setDataMode) (DataMode newMode, ggobid * gg)
71 {
72   DataMode old = gg->input->mode;
73   sessionOptions->data_mode = newMode;
74   gg->input->mode = newMode;
75   return (old);
76 }
77 
78 /**
79  Caller should now free the return value, but not the elements of the
80  array.
81  This is computed dynamically by querying each of the input plugins
82  for its collection of mode names.
83 */
GGOBI(getDataModeNames)84 const gchar **GGOBI (getDataModeNames) (int *n)
85 {
86   int ctr = 0, num, k, i;
87   GList *plugins;
88   const gchar **ans;
89   GGobiPluginInfo *plugin;
90 
91   plugins = sessionOptions->info->inputPlugins;
92   num = g_list_length (plugins);
93   for (i = 0; i < num; i++) {
94     plugin = g_list_nth_data (plugins, i);
95     ctr += plugin->info.i->numModeNames;
96   }
97 
98   ans = (const gchar **) g_malloc (sizeof (gchar *) * ctr);
99   ctr = 0;
100   for (i = 0; i < num; i++) {
101     plugin = g_list_nth_data (plugins, i);
102     for (k = 0; k < plugin->info.i->numModeNames; k++) {
103       ans[ctr++] = plugin->info.i->modeNames[k];
104     }
105   }
106 
107   if (n)
108     *n = ctr;
109 
110   return (ans);
111 }
112 
113 
GGOBI(getVariableNames)114 gchar **GGOBI (getVariableNames) (gint transformed, GGobiData * d,
115                                   ggobid * gg)
116 {
117   gchar **names;
118   gint nc = d->ncols, j;
119 
120   names = (gchar **) g_malloc (sizeof (gchar *) * nc);
121 
122   for (j = 0; j < nc; j++) {
123     names[j] = transformed ? ggobi_data_get_transformed_col_name(d, j) : ggobi_data_get_col_name(d, j);
124   }
125 
126   return (names);
127 }
128 
129 
130 void
GGOBI(setVariableName)131 GGOBI (setVariableName) (gint j, gchar * name, gboolean transformed,
132                          GGobiData * d, ggobid * gg)
133 {
134 
135   if (transformed)
136     ggobi_data_set_transformed_col_name(d, j, name);
137   else
138     ggobi_data_set_col_name(d, j, name);
139 
140 }
141 
142 
143 /*
144   Closes the specified display
145  */
GGOBI(destroyCurrentDisplay)146 void GGOBI (destroyCurrentDisplay) (ggobid * gg)
147 {
148   display_free (gg->current_display, false, gg);
149 }
150 
151 
152 MissingValue_p GGobiMissingValue;
153 
154 MissingValue_p
GGobi_setMissingValueIdentifier(MissingValue_p f)155 GGobi_setMissingValueIdentifier (MissingValue_p f)
156 {
157   MissingValue_p old = GGobiMissingValue;
158   GGobiMissingValue = f;
159   return (old);
160 }
161 
162 
163 static const gchar *const DefaultRowNames = NULL;
164 
165 const gchar *const *
getDefaultRowNamesPtr()166 getDefaultRowNamesPtr ()
167 {
168   return ((const gchar * const *) &DefaultRowNames);
169 }
170 
171 void
setRowNames(GGobiData * d,gchar ** rownames)172 setRowNames (GGobiData * d, gchar ** rownames)
173 {
174   int i;
175   gchar *lbl;
176   for (i = 0; i < d->nrows; i++) {
177     lbl = (rownames != (gchar **) & DefaultRowNames
178            && rownames != (gchar **) NULL
179            && rownames[i] !=
180            (gchar *) NULL) ? g_strdup (rownames[i]) : g_strdup_printf ("%d",
181                                                                        i + 1);
182     g_array_append_val (d->rowlab, lbl);
183   }
184 }
185 
186 /*
187   An initial attempt to allow new data to be introduced
188   to the Ggobi session, replacing the existing contents.
189 
190   There are still a few details remaining regarding the scaling
191   on the axes, etc. (See ruler_ranges_set in scatterplot.c)
192   The reverse pipeline data has not been established correctly
193   and the computation is incorrect.
194   Specifically, the routine splot_screen_to_tform() is not
195 
196 
197   When this works, we will take the calls for the different stages
198   and put them in separate routines.
199  */
200 /*-- need two of these now, one to replace and one to append --*/
201 void
GGOBI(setData)202 GGOBI (setData) (gdouble * values, gchar ** rownames, gchar ** colnames,
203                  gint nr, gint nc, GGobiData * d, gboolean cleanup,
204                  ggobid * gg, gchar ** ids, gboolean duplicate,
205                  InputDescription * desc)
206 {
207   gint i, j;
208   gchar *lbl;
209   gchar *varname;
210 
211   if (cleanup) {
212     /* Release all the displays associated with this datad
213        and then release all the GUI components and memory
214        for this datad.
215 
216        This may need some reworking in order to release
217        exactly the right things, no more and no less.
218      */
219     GGOBI (displays_release) (gg);
220     varpanel_clear (d, gg);
221     GGOBI (data_release) (d, gg);
222     /* ?? */
223     gtk_ui_manager_remove_ui (gg->main_menu_manager, gg->mode_merge_id);
224     /*submenu_destroy (gg->pmode_item);
225        submenu_destroy (gg->imode_item); */
226   }
227 
228   d->input = desc;
229   if (d->name == NULL)
230     d->name = g_strdup (desc->fileName);
231   if (gg->input == NULL)
232     gg->input = desc;
233 
234   d->ncols = nc;
235   d->nrows = nr;
236 
237   vectori_init_null (&d->rows_in_plot);
238   d->nrows_in_plot = d->nrows;  /*-- for now --*/
239 
240   arrayf_alloc (&d->raw, nr, nc);
241 
242   if (ids) {
243     datad_record_ids_set (d, ids, duplicate);
244   }
245 
246   rowlabels_alloc (d);
247 
248   vartable_alloc (d);
249   vartable_init (d);
250 
251   br_glyph_ids_alloc (d);
252   br_glyph_ids_init (d);
253 
254   br_color_ids_alloc (d);
255   br_color_ids_init (d);
256 
257   br_hidden_alloc (d);
258   br_hidden_init (d);
259 
260   if (values && d->vartable) {
261     /* the person who created the datad is taking care of populating it. */
262     for (j = 0; j < nc; j++) {
263       varname = (colnames != NULL && colnames[j] != NULL) ? colnames[j] : NULL;
264       ggobi_data_set_col_name(d, j, varname);
265 
266       for (i = 0; i < nr; i++) {
267         if (j == 0) {
268           lbl = (rownames != NULL && rownames[i] != NULL) ?
269             g_strdup (rownames[i]) : g_strdup_printf ("%d", i + 1);
270           g_array_append_val (d->rowlab, lbl);
271           /* g_free (lbl); */
272         }
273 
274         if (values)
275           ggobi_data_set_raw_value(d, i, j, values[i + j * nr]);
276       }
277     }
278   }
279 
280   if (rownames && d->rowlab->len == 0)
281     setRowNames (d, rownames);
282 
283 
284   /* Now recompute and display the top plot. */
285   if (nc > 0 && datad_init (d, gg, cleanup) != NULL) {
286     /* Have to patch up the displays list since we removed
287        every entry and that makes for meaningless entries.
288 
289        IS THIS TRUE? Only if cleanup was specified!
290        This looks very dangerous. Should use g_list_remove();
291      */
292     gg->displays->next = NULL;
293   }
294   display_menu_build (gg);
295 }
296 
297 
298 /* These are all for freeing the currently held data. */
GGOBI(displays_release)299 void GGOBI (displays_release) (ggobid * gg)
300 {
301   GList *dlist;
302   displayd *display;
303 
304   /* We have to be careful here as we are removing all the elements
305      of the singly-linked list. When we remove the last one,
306      the ->next value of the dlist becomes non-NULL. Hence
307      we are getting garbage. Accordingly, we count down from the total
308      number to remove using num and when this is 0, we exit.
309      This should leave the slist allocated, but empty.
310 
311      We have to patch the list up afterwards.
312    */
313   gint num = g_list_length (gg->displays);
314 
315   for (dlist = gg->displays; dlist != NULL; dlist = dlist->next, num--) {
316     if (num == 0)
317       break;
318     display = (displayd *) dlist->data;
319     /*  display_release(display, gg); */
320     display_free (display, true, gg);
321   }
322 }
323 
GGOBI(display_release)324 void GGOBI (display_release) (displayd * display, ggobid * gg)
325 {
326   display_free (display, true, gg);
327 }
328 
329 
GGOBI(splot_release)330 void GGOBI (splot_release) (splotd * sp, displayd * display, ggobid * gg)
331 {
332   splot_free (sp, display, gg);
333 }
334 
335 /* Not in the API for the moment. A "protected" routine. */
GGOBI(data_release)336 void GGOBI (data_release) (GGobiData * d, ggobid * gg)
337 {
338   void vartable_free (GGobiData * d);
339 
340   if (d == NULL)
341     return;
342   if (d->rowlab) {
343     rowlabels_free (d);
344     d->rowlab = NULL;
345   }
346 
347   vartable_free (d);
348 }
349 
350 
351 /**XX*/
GGOBI(getViewTypes)352 const gchar *const *GGOBI (getViewTypes) (int *n)
353 {
354   *n = NDISPLAYTYPES;
355   return (ViewTypes);
356 }
357 
GGOBI(getViewTypeIndices)358 const gint *GGOBI (getViewTypeIndices) (gint * n)
359 {
360   extern const gint ViewTypeIndices[];
361   *n = NDISPLAYTYPES;
362   return (ViewTypeIndices);
363 }
364 
365 
GGOBI(newScatterplot)366 displayd *GGOBI (newScatterplot) (gint ix, gint iy, gboolean use_window,
367                                   GGobiData * d, ggobid * gg)
368 {
369   displayd *display = NULL;
370   gint vars[2];
371 
372   vars[0] = ix;
373   vars[1] = iy;
374   display = scatterplot_new_with_vars (use_window, false, 2, vars, d, gg);
375 #ifdef FORCE_ADD_DISPLAY
376   display_add (display, gg);
377 #endif
378 
379 
380   return (display);
381 }
382 
GGOBI(newScatmat)383 displayd *GGOBI (newScatmat) (gint * rows, gint * columns, gint nr, gint nc,
384                               gboolean use_window, GGobiData * d, ggobid * gg)
385 {
386   displayd *display;
387 
388   display = scatmat_new (NULL, use_window, false, nr, rows, nc, columns, d, gg);
389 #ifdef FORCE_ADD_DISPLAY
390   display_add (display, gg);    /*XX  the caller should add this display. */
391 #endif
392 
393   return (display);
394 }
395 
GGOBI(newParCoords)396 displayd *GGOBI (newParCoords) (gint * vars, gint numVars, gboolean use_window,
397                                 GGobiData * d, ggobid * gg)
398 {
399   displayd *display = NULL;
400 
401   display = parcoords_new (display, use_window, false, numVars, vars, d, gg);
402 #ifdef FORCE_ADD_DISPLAY
403   display_add (display, gg);    /*XX  the caller should add this display. */
404 #endif
405 
406 
407   return (display);
408 }
409 
GGOBI(newTimeSeries)410 displayd *GGOBI (newTimeSeries) (gint * yvars, gint numVars, gboolean use_window,
411                                  GGobiData * d, ggobid * gg)
412 {
413   displayd *display = NULL;
414 
415   display = tsplot_new (display, use_window, false, numVars, yvars, d, gg);
416 #ifdef FORCE_ADD_DISPLAY
417   display_add (display, gg);    /*XX  the caller should add this display. */
418 #endif
419 
420   return (display);
421 }
422 
GGOBI(createPlot)423 displayd *GGOBI (createPlot) (int type, char **varnames)
424 {
425   displayd *display = NULL;
426   /*
427      display_new(type);
428    */
429   return (display);
430 }
431 
432 
GGOBI(getCurrentDisplayType)433 const gchar *GGOBI (getCurrentDisplayType) (ggobid * gg)
434 {
435 /*XX */
436   return (GGOBI (getViewTypeName) (gg->current_display));
437 }
438 
GGOBI(getViewTypeName)439 const gchar *GGOBI (getViewTypeName) (displayd * dpy)
440 {
441   gchar *val;
442 
443   if (!GGOBI_IS_EXTENDED_DISPLAY (dpy))
444     return (NULL);
445 
446 /*
447  or use gtk_type_name(GTK_OBJECT_TYPE(dpy))
448  */
449   val = GGOBI_EXTENDED_DISPLAY_GET_CLASS (dpy)->treeLabel;
450 
451   return (val);
452 }
453 
454 
455 /*
456   Pointer to the raw data managed by GGobi.
457   Don't touch this.
458  */
GGOBI(getRawData)459 const gfloat **GGOBI (getRawData) (GGobiData * d, ggobid * gg)
460 {
461   return ((const gfloat **) d->raw.vals);
462 }
463 
464 /*
465   Pointer to the second transformation of the data managed by GGobi.
466   Don't touch this.
467  */
GGOBI(getTFormData)468 const gfloat **GGOBI (getTFormData) (GGobiData * d, ggobid * gg)
469 {
470   return ((const gfloat **) d->tform.vals);
471 }
472 
473 
474 /*
475   Returns a reference to the labels used to identify
476   the observations.
477   Do not change this as it is not a copy.
478  */
GGOBI(getCaseNames)479 const gchar **GGOBI (getCaseNames) (GGobiData * d, ggobid * gg)
480 {
481   gchar **rowlab = (gchar **) g_malloc (sizeof (gchar *) * d->nrows);
482   gint i;
483   for (i = 0; i < d->nrows; i++)
484     rowlab[i] = (gchar *) g_array_index (d->rowlab, gchar *, i);
485 
486   return ((const gchar **) rowlab);
487 }
488 
489 /*
490  This does not copy the label, so it is assumed
491  that the caller has already allocated the space
492  using the appropriate GTK memory model.
493  If it is apparent that this is being called from
494  contexts that use a very different memory model (e.g. S/R),
495  we can change the behaviour to copy this.
496 
497  Similarly, this can be modified to return the previous
498  value, but the caller will have to free that pointer.
499  */
500 void
GGOBI(setCaseName)501 GGOBI (setCaseName) (gint index, const gchar * label, GGobiData * d,
502                      ggobid * gg)
503 {
504   gchar *old;
505   if (index < 0 || index >= d->nrows) {
506     warning ("Index is out of range of observations in setCaseName");
507     return;
508   }
509 
510   old = g_array_index (d->rowlab, gchar *, index);
511   g_free (old);
512 
513   g_array_insert_val (d->rowlab, index, label);
514 }
515 
516 
517 void
warning(const gchar * msg)518 warning (const gchar * msg)
519 {
520   fprintf (stderr, "%s\n", msg);
521   fflush (stderr);
522 }
523 
524 
525 /*-------------------------------------------------------------------------*/
526 /*     setting and getting point glyph types and sizes                     */
527 /*-------------------------------------------------------------------------*/
528 
GGOBI(getGlyphTypes)529 gint *GGOBI (getGlyphTypes) (int *n)
530 {
531   static gint *glyphIds = NULL;
532   *n = UNKNOWN_GLYPH - 1;       /* -1 since we start at 1 */
533 
534   if (glyphIds == NULL) {
535     gint i;
536     glyphIds = (gint *) g_malloc (*n * sizeof (gint));
537     for (i = 0; i < *n; i++) {
538       glyphIds[i] = mapGlyphName (GlyphNames[i]);
539     }
540   }
541 
542   return (glyphIds);
543 }
544 
GGOBI(getGlyphTypeNames)545 const gchar *const *GGOBI (getGlyphTypeNames) (gint * n)
546 {
547   *n = UNKNOWN_GLYPH - 1;       /* -1 since we start at 1; starting at 0 now */
548   return ((const gchar * const *) GlyphNames);
549 }
550 
551 
GGOBI(getGlyphTypeName)552 gchar const *GGOBI (getGlyphTypeName) (gint type)
553 {
554   gchar const *ans;
555   ans = GlyphNames[type];
556 
557   return (ans);
558 }
559 
560 
GGOBI(getCaseGlyphTypes)561 gint *GGOBI (getCaseGlyphTypes) (gint * ids, gint n, GGobiData * d,
562                                  ggobid * gg)
563 {
564   gint i;
565   gint *ans = (gint *) g_malloc (n * sizeof (gint));
566 
567   for (i = 0; i < n; i++)
568     ans[i] = GGOBI (getCaseGlyphType) (ids[i], d, gg);
569 
570   return (ids);
571 }
572 
GGOBI(getCaseGlyphType)573 gint GGOBI (getCaseGlyphType) (gint id, GGobiData * d, ggobid * gg)
574 {
575   gint index = d->rows_in_plot.els[id];
576   return (d->glyph_now.els[index].type);
577 }
578 
GGOBI(getCaseGlyphSizes)579 gint *GGOBI (getCaseGlyphSizes) (gint * ids, gint n, GGobiData * d,
580                                  ggobid * gg)
581 {
582   gint i;
583   gint *ans = (gint *) g_malloc (n * sizeof (gint));
584 
585   for (i = 0; i < n; i++)
586     ans[i] = GGOBI (getCaseGlyphSize) (ids[i], d, gg);
587 
588   return (ids);
589 }
590 
GGOBI(getCaseGlyphSize)591 gint GGOBI (getCaseGlyphSize) (gint id, GGobiData * d, ggobid * gg)
592 {
593   gint index = d->rows_in_plot.els[id];
594 
595   return (d->glyph_now.els[index].size);
596 }
597 
598 void
GGOBI(setCaseGlyph)599 GGOBI (setCaseGlyph) (gint index, gint type, gint size, GGobiData * d,
600                       ggobid * gg)
601 {
602   if (type > -1) {
603     if (type >= NGLYPHTYPES)
604       g_printerr ("Illegal glyph type: %d\n", type);
605     else
606       d->glyph.els[index].type = d->glyph_now.els[index].type = type;
607   }
608 
609   if (size > -1) {
610     if (size >= NGLYPHSIZES)
611       g_printerr ("Illegal glyph size: %d\n", size);
612     else
613       d->glyph.els[index].size = d->glyph_now.els[index].size = size;
614   }
615 }
616 
617 void
GGOBI(setCaseGlyphs)618 GGOBI (setCaseGlyphs) (gint * ids, gint n, gint type, gint size,
619                        GGobiData * d, ggobid * gg)
620 {
621   gint i, doit = 1;
622   /*
623    * Make sure glyphs are legal before assigning.  (It's safe to
624    * ignore values of -1, because those are likely to be deliberately
625    * set by the calling routine as an indication to do nothing.)
626    * Do the check here to avoid generating large numbers of
627    * error messages.
628    */
629   if (type >= NGLYPHTYPES) {
630     g_printerr ("Illegal glyph type: %d\n", type);
631     doit = 0;
632   }
633   if (size >= NGLYPHSIZES) {
634     g_printerr ("Illegal glyph size: %d\n", size);
635     doit = 0;
636   }
637 
638   if (doit)
639     for (i = 0; i < n; i++)
640       GGOBI (setCaseGlyph) (ids[i], type, size, d, gg);
641 }
642 
643 /*-------------------------------------------------------------------------*/
644 /*               setting and getting point colors                          */
645 /*-------------------------------------------------------------------------*/
646 
647 void
GGOBI(setCaseColor)648 GGOBI (setCaseColor) (gint pt, gint colorIndex, GGobiData * d, ggobid * gg)
649 {
650   colorschemed *scheme = gg->activeColorScheme;
651 
652   /*-- temporary fix --*/
653   if (colorIndex < 0 || colorIndex > scheme->n - 1)
654     colorIndex = 0;
655   d->color.els[pt] = d->color_now.els[pt] = colorIndex;
656 }
657 
658 void
GGOBI(setCaseColors)659 GGOBI (setCaseColors) (gint * pts, gint howMany, gint colorIndex,
660                        GGobiData * d, ggobid * gg)
661 {
662   gint i;
663   for (i = 0; i < howMany; i++)
664     d->color.els[pts[i]] = d->color_now.els[pts[i]] = colorIndex;
665 }
666 
667 
GGOBI(getCaseColor)668 gint GGOBI (getCaseColor) (gint pt, GGobiData * d, ggobid * gg)
669 {
670   return (d->color_now.els[pt]);
671 }
672 
GGOBI(getCaseColors)673 gint *GGOBI (getCaseColors) (gint * pts, gint howMany, GGobiData * d,
674                              ggobid * gg)
675 {
676   gint i;
677   gint *ans = (gint *) g_malloc (howMany * sizeof (gint));
678 
679   for (i = 0; i < howMany; i++)
680     ans[i] = GGOBI (getCaseColor) (pts[i], d, gg);
681 
682   return (ans);
683 }
684 
685 /*-------------------------------------------------------------------------*/
686 /*        setting and getting the point hidden state                       */
687 /*-------------------------------------------------------------------------*/
688 
689 void
GGOBI(setCaseHidden)690 GGOBI (setCaseHidden) (gint pt, gboolean hidden_p, GGobiData * d, ggobid * gg)
691 {
692   d->hidden.els[pt] = d->hidden_now.els[pt] = hidden_p;
693   /*-- don't replot --*/
694 }
695 
696 void
GGOBI(setCaseHiddens)697 GGOBI (setCaseHiddens) (gint * pts, gint howMany, gboolean hidden_p,
698                         GGobiData * d, ggobid * gg)
699 {
700   gint i;
701   for (i = 0; i < howMany; i++)
702     GGOBI (setCaseHidden) (pts[i], hidden_p, d, gg);
703   displays_plot (NULL, FULL, gg);
704 }
705 
GGOBI(getCaseHidden)706 gboolean GGOBI (getCaseHidden) (gint pt, GGobiData * d, ggobid * gg)
707 {
708   return (d->hidden_now.els[pt]);
709 }
710 
GGOBI(getCaseHiddens)711 gboolean *GGOBI (getCaseHiddens) (gint * pts, gint howMany, GGobiData * d,
712                                   ggobid * gg)
713 {
714   gint i;
715   gboolean *ans = (gboolean *) g_malloc (howMany * sizeof (gboolean));
716 
717   for (i = 0; i < howMany; i++)
718     ans[i] = GGOBI (getCaseHidden) (pts[i], d, gg);
719 
720   return (ans);
721 }
722 
723 /*-------------------------------------------------------------------------*/
724 /*        setting and getting edges                                        */
725 /*-------------------------------------------------------------------------*/
726 
GGOBI(getShowLines)727 gboolean GGOBI (getShowLines) ()
728 {
729   return (GGOBI (getDefaultDisplayOptions) ()->edges_undirected_show_p);
730 }
731 
732 /* uh.. this takes a boolean value but always shows lines... what's up */
GGOBI(setShowLines)733 gboolean GGOBI (setShowLines) (displayd * dsp, gboolean val)
734 {
735   GtkAction *action;
736   gboolean old = GGOBI (getShowLines) ();
737   /*GGOBI(getDefaultDisplayOptions)()->edges_undirected_show_p = val; */
738   dsp->options.edges_undirected_show_p = true;
739 
740   action = gtk_ui_manager_get_action (dsp->menu_manager,
741                                       "/menubar/Edges/ShowUndirectedEdges");
742   if (action)
743     gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), true);
744 
745   return (old);
746 }
747 
748 /* setShowAxes  will require this code:
749 
750 {
751   GtkWidget *topmenu, *menu, *item;
752   topmenu = widget_find_by_name (dspnew->menubar, "DISPLAY:options_topmenu");
753   if (topmenu) {
754     menu = GTK_MENU_ITEM(topmenu)->submenu;
755     if (menu) {
756       item = widget_find_by_name (menu, "DISPLAY:show_axes");
757       if (item) {
758         gtk_check_menu_item_set_active ((GtkCheckMenuItem *) item, false);
759       }
760     }
761   }
762 }
763 
764 
765 */
766 
GGOBI(getDefaultDisplayOptions)767 DisplayOptions *GGOBI (getDefaultDisplayOptions) ()
768 {
769   return (&DefaultDisplayOptions);
770 }
771 
772 
GGOBI(getDisplay)773 displayd *GGOBI (getDisplay) (gint which, ggobid * gg)
774 {
775   displayd *display = NULL;
776 
777   if (which < g_list_length (gg->displays))
778     display = (displayd *) g_list_nth_data (gg->displays, which);
779 
780   return (display);
781 }
782 
GGOBI(getDisplayOptions)783 DisplayOptions *GGOBI (getDisplayOptions) (int displayNum, ggobid * gg)
784 {
785   DisplayOptions *options = NULL;
786   if (displayNum < 0)
787     options = GGOBI (getDefaultDisplayOptions) ();
788   else {
789     displayd *display;
790     display = GGOBI (getDisplay) (displayNum, gg);
791     if (display)
792       options = &(display->options);
793   }
794 
795   return (options);
796 }
797 
798 
GGOBI(getCurrentDisplay)799 displayd *GGOBI (getCurrentDisplay) (ggobid * gg)
800 {
801   return (gg->current_display);
802 }
803 
GGOBI(getCurrentDisplayIndex)804 gint GGOBI (getCurrentDisplayIndex) (ggobid * gg)
805 {
806   return (g_list_index (gg->displays, gg->current_display));
807 }
808 
GGOBI(getCurrentPlotIndex)809 gint GGOBI (getCurrentPlotIndex) (ggobid * gg)
810 {
811   int val = -1;
812   displayd *d;
813   if (gg->current_splot) {
814     d = GGOBI (getCurrentDisplay) (gg);
815     val = g_list_index (d->splots, gg->current_splot);
816   }
817 
818   return (val);
819 }
820 
GGOBI(setCurrentDisplay)821 displayd *GGOBI (setCurrentDisplay) (int which, ggobid * gg)
822 {
823   displayd *d;
824 
825   d = GGOBI (getDisplay) (which, gg);
826 
827   if (d != NULL)
828     display_set_current (d, gg);
829 
830   return (d);
831 }
832 
833 
GGOBI(getPlot)834 splotd *GGOBI (getPlot) (displayd * display, int which)
835 {
836   splotd *sp = (splotd *) g_list_nth_data (display->splots, which);
837   return (sp);
838 }
839 
840 
GGOBI(getNumGGobis)841 gint GGOBI (getNumGGobis) ()
842 {
843   extern gint num_ggobis;
844   return (num_ggobis);
845 }
846 
847 /*
848   Whether to destory the window or not.  If this is being called from an
849   event handler in response to the window being destroyed, we would get
850   a circularity. However, when called programmatically from within the
851   process (or from e.g. R) we need to force it to be closed.
852  */
GGOBI(close)853 gboolean GGOBI (close) (ggobid * gg, gboolean closeWindow)
854 {
855   gboolean val = true;
856 
857   if (gg->close_pending)
858     return (false);
859 
860   gg->close_pending = true;
861 
862   /* close plugin instances */
863   closePlugins (gg);
864 
865   procs_activate (off, gg->pmode, gg->current_display, gg);
866 
867   display_free_all (gg);
868 
869   if (closeWindow && gg->main_window)
870     gtk_widget_destroy (gg->main_window);
871 
872   if (gg->display_tree.window)
873     gtk_widget_destroy (gg->display_tree.window);
874   if (gg->vartable_ui.window)
875     gtk_widget_destroy (gg->vartable_ui.window);
876 
877   if (gg->color_ui.symbol_window)
878     gtk_widget_destroy (gg->color_ui.symbol_window);
879 
880   if (gg->wvis.window)
881     gtk_widget_destroy (gg->wvis.window);
882   if (gg->svis.window)
883     gtk_widget_destroy (gg->svis.window);
884 
885   gg->close_pending = false;
886   /* Now fix up the list of ggobi's */
887   val = ggobi_remove (gg) != -1;
888 
889   if (GGobi_getNumGGobis () == 0 && sessionOptions->info->quitWithNoGGobi &&
890       gtk_main_level () > 0) {
891     gtk_main_quit ();
892   }
893 
894   return (val);
895 }
896 
897 #ifdef EXPLICIT_IDENTIFY_HANDLER
GGOBI(setIdentifyHandler)898 void GGOBI (setIdentifyHandler) (IdentifyProc proc, void *data, ggobid * gg)
899 {
900   gg->identify_handler.handler = proc;
901   gg->identify_handler.user_data = data;
902 }
903 #endif
904 
GGOBI(getBrushSize)905 void GGOBI (getBrushSize) (gint * w, gint * h, ggobid * gg)
906 {
907   splotd *sp = gg->current_splot;
908 
909   *w = ABS (sp->brush_pos.x1 - sp->brush_pos.x2);
910   *h = ABS (sp->brush_pos.y1 - sp->brush_pos.y2);
911 }
912 
GGOBI(getBrushLocation)913 void GGOBI (getBrushLocation) (gint * x, gint * y, ggobid * gg)
914 {
915   splotd *sp = gg->current_splot;
916 
917   *x = MIN (sp->brush_pos.x1, sp->brush_pos.x2);
918   *y = MIN (sp->brush_pos.y1, sp->brush_pos.y2);
919 }
920 
921 void
redraw(splotd * sp,ggobid * gg)922 redraw (splotd * sp, ggobid * gg)
923 {
924   brush_once (true, sp, gg);
925   display_plot (sp->displayptr, FULL, gg);
926 }
927 
928 
GGOBI(setBrushSize)929 void GGOBI (setBrushSize) (int w, int h, ggobid * gg)
930 {
931   splotd *sp = gg->current_splot;
932   displayd *display = sp->displayptr;
933 
934   sp->brush_pos.x1 = MIN (sp->brush_pos.x1, sp->brush_pos.x2);
935   sp->brush_pos.y1 = MIN (sp->brush_pos.y1, sp->brush_pos.y2);
936 
937   sp->brush_pos.x2 = sp->brush_pos.x1 + w;
938   sp->brush_pos.y2 = sp->brush_pos.y1 + h;
939 
940   brush_once (true, sp, gg);
941   redraw (sp, gg);
942   display_plot (display, FULL, gg);
943 }
944 
945 
GGOBI(setBrushLocation)946 void GGOBI (setBrushLocation) (gint x, gint y, ggobid * gg)
947 {
948   gint wd, ht;
949   splotd *sp = gg->current_splot;
950 
951   GGOBI (getBrushSize) (&wd, &ht, gg);
952 
953   sp->brush_pos.x1 = x;
954   sp->brush_pos.y1 = y;
955   sp->brush_pos.x2 = x + wd;
956   sp->brush_pos.y2 = y + ht;
957 
958   brush_once (true, sp, gg);
959 
960   redraw (sp, gg);
961 }
962 
GGOBI(setBrushGlyph)963 gboolean GGOBI (setBrushGlyph) (gint type, gint size, ggobid * gg)
964 {
965   if (type > -1)
966     gg->glyph_id.type = type;
967   if (size > -1)
968     gg->glyph_id.size = size;
969 
970   return (true);                /* Should be true iff there is a change. */
971 }
972 
GGOBI(getBrushGlyph)973 void GGOBI (getBrushGlyph) (gint * type, gint * size, ggobid * gg)
974 {
975   *type = gg->glyph_id.type;
976   *size = gg->glyph_id.size;
977 }
978 
979 
980 /*
981   Returns the dimensions of the specified
982   splot in pixels which can then be used for
983   specifying.
984  */
GGOBI(getPlotPixelSize)985 void GGOBI (getPlotPixelSize) (gint * w, gint * h, splotd * sp)
986 {
987   /* Temp */
988   *w = -1;
989   *h = -1;
990 }
991 
992 
GGOBI(getSPlot)993 splotd *GGOBI (getSPlot) (gint which, displayd * display)
994 {
995   splotd *sp = (splotd *) g_list_nth_data (display->splots, which);
996   return (sp);
997 }
998 
GGOBI(setPMode)999 gint GGOBI (setPMode) (const gchar * name, ggobid * gg)
1000 {
1001   ProjectionMode old = pmode_get (gg->current_display, gg);
1002   ProjectionMode newMode = (ProjectionMode) GGOBI (getPModeId) (name);
1003   if (newMode != NULL_PMODE)
1004     GGOBI (full_viewmode_set) (newMode, DEFAULT_IMODE, gg);
1005   return (old);
1006 }
1007 
GGOBI(getPModeId)1008 gint GGOBI (getPModeId) (const gchar * name)
1009 {
1010   gint n, i;
1011   const gchar *const *names = GGOBI (getPModeNames) (&n);
1012 
1013   for (i = 0; i < n; i++) {
1014     if (strcmp (names[i], name) == 0)
1015       return (i);
1016   }
1017 
1018   return (-1);
1019 }
1020 
GGOBI(getPModeName)1021 const gchar *GGOBI (getPModeName) (int which)
1022 {
1023   int n;
1024   const gchar *const *names;
1025 
1026   names = GGOBI (getPModeNames) (&n);
1027   return (names[which]);
1028 }
1029 
GGOBI(getPModeScreenName)1030 const gchar *GGOBI (getPModeScreenName) (int which, displayd * display)
1031 {
1032   if (which == EXTENDED_DISPLAY_PMODE) {
1033     gchar *name;
1034     GGOBI_EXTENDED_DISPLAY_GET_CLASS (display)->imode_control_box (display,
1035                                                                    &name,
1036                                                                    display->
1037                                                                    ggobi);
1038     return name;
1039   }
1040   return (GGOBI (getPModeName) (which));
1041 }
1042 
GGOBI(setIMode)1043 gint GGOBI (setIMode) (const gchar * name, ggobid * gg)
1044 {
1045   InteractionMode old = imode_get (gg);
1046   InteractionMode newMode = (InteractionMode) GGOBI (getIModeId) (name);
1047   if (newMode != NULL_PMODE)
1048     GGOBI (full_viewmode_set) (NULL_PMODE, newMode, gg);
1049   return (old);
1050 }
1051 
GGOBI(getIModeId)1052 gint GGOBI (getIModeId) (const gchar * name)
1053 {
1054   gint n, i;
1055   const gchar *const *names = GGOBI (getIModeNames) (&n);
1056 
1057   for (i = 0; i < n; i++) {
1058     if (strcmp (names[i], name) == 0)
1059       return (i);
1060   }
1061 
1062   return (-1);
1063 }
1064 
GGOBI(getIModeName)1065 const gchar *GGOBI (getIModeName) (int which)
1066 {
1067   int n;
1068   const gchar *const *names;
1069 
1070   names = GGOBI (getIModeNames) (&n);
1071   return (names[which]);
1072 }
1073 
GGOBI(getIModeScreenName)1074 const gchar *GGOBI (getIModeScreenName) (int which, displayd * display)
1075 {
1076   if (which == DEFAULT_IMODE)
1077     return (GGOBI (getPModeScreenName) (display->cpanel.pmode, display));
1078   return (GGOBI (getIModeName) (which));
1079 }
1080 
GGOBI(getPModeKey)1081 const gchar *GGOBI (getPModeKey) (int which)
1082 {
1083   int n;
1084   const gchar *const *keys = GGOBI (getPModeKeys) (&n);
1085   return (keys[which]);
1086 }
1087 
1088 /*
1089 gint
1090 GGOBI(getModeId)(const gchar *name)
1091 {
1092   gint n, i;
1093   const gchar *const *names = GGOBI(getOpModeNames)(&n);
1094 
1095   for(i = 0; i < n; i++) {
1096     if(strcmp(names[i],name) == 0)
1097       return(i);
1098   }
1099 
1100   return(-1);
1101 }
1102 
1103 const gchar *
1104 GGOBI(getModeName)(int which)
1105 {
1106   int n;
1107   const gchar *const *names = GGOBI(getOpModeNames)(&n);
1108   return(names[which]);
1109 }
1110 */
1111 
GGOBI(setBrushColor)1112 gint GGOBI (setBrushColor) (gint cid, ggobid * gg)
1113 {
1114   gint old = gg->color_id;
1115   if (cid > -1 && cid < gg->activeColorScheme->n)
1116     gg->color_id = cid;
1117 
1118   return (old);
1119 }
1120 
GGOBI(getBrushColor)1121 gint GGOBI (getBrushColor) (ggobid * gg)
1122 {
1123   return (gg->color_id);
1124 }
1125 
GGOBI(getColorName)1126 const gchar *GGOBI (getColorName) (gint cid, ggobid * gg, gboolean inDefault)
1127 {
1128   if (cid >= 0 && cid < gg->activeColorScheme->n) {
1129     return ((gchar *) g_array_index (gg->activeColorScheme->colorNames,
1130                                      gchar *, cid));
1131   }
1132 
1133   return (NULL);
1134 }
1135 
1136 
1137 static gint
addVariableInternal(gdouble * vals,gint num,gchar * name,gchar ** levels,gint * values,gint * counts,gint numLevels,gboolean update,GGobiData * d,ggobid * gg)1138 addVariableInternal (gdouble * vals, gint num, gchar * name,
1139                      gchar ** levels, gint * values, gint * counts,
1140                      gint numLevels, gboolean update, GGobiData * d,
1141                      ggobid * gg)
1142 {
1143   /*if (d->ncols < 1) {
1144      gchar ** rnames = (gchar **) &DefaultRowNames;
1145      GGOBI(setData)(NULL, rnames, &name, num, d->ncols, d, false, gg, NULL, false, d->input);
1146      datad_init(d, gg, false);
1147      } */
1148 
1149   if (num > d->nrows && d->ncols > 0) {
1150     num = d->nrows;
1151     g_warning ("Variable length (%d) exceeds the number of dataset rows (%d)",
1152                num, d->nrows);
1153   }
1154   newvar_add_with_values (vals, num, name,
1155                           numLevels > 0 ? categorical : real,
1156                           numLevels, levels, values, counts, d);
1157 
1158   if (update)
1159     gdk_flush ();
1160 
1161   return (d->ncols - 1);
1162 }
1163 
1164 /*-- this is really addRealVariable --*/
1165 gint
GGOBI(addVariable)1166 GGOBI (addVariable) (gdouble * vals, gint num, gchar * name,
1167                      gboolean update, GGobiData * d, ggobid * gg)
1168 {
1169   return (addVariableInternal
1170           (vals, num, name, NULL, NULL, NULL, 0, update, d, gg));
1171 }
1172 
1173 /*
1174 It's hard to get the sequence right of adding a variable, updating its
1175 data, updating the variable table structure, setting the variable's type,
1176 emitting an event saying that a variable has been added, and updating the
1177 GUI.   ....  This works for now, but the code is not pretty.  We're making
1178 only very limted use of the event we emit.    dfs  2/7
1179 */
1180 gint
GGOBI(addCategoricalVariable)1181 GGOBI (addCategoricalVariable) (gdouble * vals, gint num, gchar * name,
1182                                 gchar ** levels, gint * values, gint * counts,
1183                                 gint numLevels, gboolean update,
1184                                 GGobiData * d, ggobid * gg)
1185 {
1186 
1187   return (addVariableInternal
1188           (vals, num, name, levels, values, counts, numLevels, update, d,
1189            gg));
1190 }
1191 
1192 
1193 /*
1194   The idea of the update argument is that we can defer recomputing
1195   the statistics for all the variables and then the transformations.
1196   This is useful when we know we will be adding more variables before
1197   redisplaying.
1198   For example,
1199     for(i = 0; i < n; i++)
1200       GGOBI(setVariableValues)(i, values[i], gg->nrows, i == n-1, gg);
1201   causes the update to be done only for the last variable.
1202  */
1203 gboolean
GGOBI(setVariableValues)1204 GGOBI (setVariableValues) (gint whichVar, gdouble * vals, gint num,
1205                            gboolean update, GGobiData * d, ggobid * gg)
1206 {
1207   gint i;
1208   for (i = 0; i < num; i++) {
1209     d->raw.vals[i][whichVar] = d->tform.vals[i][whichVar] = vals[i];
1210   }
1211 
1212   if (update) {
1213     GGOBI (update_data) (d, gg);
1214   }
1215 
1216   return (true);
1217 }
1218 
GGOBI(update_data)1219 void GGOBI (update_data) (GGobiData * d, ggobid * gg)
1220 {
1221   limits_set (d, true, true, gg->lims_use_visible);
1222   vartable_limits_set (d);
1223   vartable_stats_set (d);
1224 
1225   tform_to_world (d, gg);
1226 }
1227 
GGOBI(removeVariable)1228 gint GGOBI (removeVariable) (gchar * name, GGobiData * d, ggobid * gg)
1229 {
1230   gint which = GGOBI (getVariableIndex) (name, d, gg);
1231   if (which > -1 && which < d->ncols)
1232     return (GGOBI (removeVariableByIndex) (which, d, gg));
1233 
1234   return (-1);
1235 }
1236 
GGOBI(removeVariableByIndex)1237 gint GGOBI (removeVariableByIndex) (gint which, GGobiData * d, ggobid * gg)
1238 {
1239   gint i, j;
1240   for (i = 0; i < d->nrows; i++) {
1241     for (j = which + 1; j < d->ncols; j++) {
1242 /*XXX Fill in */
1243     }
1244   }
1245 
1246   d->ncols--;
1247 
1248   return (-1);
1249 }
1250 
1251 
GGOBI(getVariableIndex)1252 gint GGOBI (getVariableIndex) (const gchar * name, GGobiData * d, ggobid * gg)
1253 {
1254   gint j;
1255 
1256   for (j = 0; j < d->ncols; j++) {
1257     if (strcmp (ggobi_data_get_col_name(d, j), name) == 0)
1258       return (j);
1259   }
1260 
1261   return (-1);
1262 }
1263 
1264 void
GGOBI(setPlotRange)1265 GGOBI (setPlotRange) (double *x, double *y, int plotNum, displayd * display,
1266                       gboolean pixels, ggobid * gg)
1267 {
1268   splotd *sp;
1269 
1270   sp = GGOBI (getPlot) (display, plotNum);
1271 
1272   if (pixels) {
1273 
1274   }
1275   else {
1276 
1277     splot_zoom (sp, *x, *y);
1278   }
1279 
1280   /*
1281      fcoords tfmin, tfmax;
1282      tfmin.x = x[0];
1283      tfmin.y = y[0];
1284      tfmax.x = x[1];
1285      tfmax.y = y[1];
1286 
1287      if (GTK_WIDGET_VISIBLE (display->hrule)) {
1288      if (((gfloat) GTK_RULER (display->hrule)->lower != tfmin.x) ||
1289      ((gfloat) GTK_RULER (display->hrule)->upper != tfmax.x))
1290      {
1291      GTK_RULER_set_range (GTK_RULER (display->hrule),
1292      (gdouble) tfmin.x, (gdouble) tfmax.x);
1293      }
1294      }
1295 
1296      if (GTK_WIDGET_VISIBLE (display->vrule)) {
1297      if (((gfloat) GTK_RULER (display->vrule)->upper != tfmin.y) ||
1298      ((gfloat) GTK_RULER (display->vrule)->lower != tfmax.y))
1299      {
1300      GTK_RULER_set_range (GTK_RULER (display->vrule),
1301      (gdouble) tfmax.y, (gdouble) tfmin.y);
1302      }
1303      }
1304    */
1305 }
1306 
1307 
1308 /*
1309   This handles the raising and lowering or the iconifying or
1310   de-iconifying of one or more windows.  If which is negative,
1311   the operation applies to all the displays with the ggobid
1312   instance.  Otherwise, the operation applies just to the
1313   display indexed by which.
1314 
1315   The two logical arguments indicate whether to raise/lower
1316   or iconify/deiconify.  Within these two operation types, the
1317   up argument indicates whether to raise or lower, an iconify
1318   or deiconify.
1319  */
1320 gboolean
GGOBI(raiseWindow)1321 GGOBI (raiseWindow) (int which, gboolean raiseOrIcon, gboolean up,
1322                      ggobid * gg)
1323 {
1324   windowDisplayd *display;
1325   gboolean ok = false;
1326   int start, end, i;
1327 
1328   if (which < 0) {
1329     start = 0;
1330     end = g_list_length (gg->displays);
1331   }
1332   else {
1333     end = which + 1;
1334     start = which;
1335   }
1336 
1337   for (i = start; i < end; i++) {
1338     display = (windowDisplayd *) g_list_nth_data (gg->displays, i);
1339     if (GGOBI_IS_WINDOW_DISPLAY (display) == false)
1340       continue;
1341     if (raiseOrIcon) {
1342       if (up)
1343         gdk_window_raise (display->window->window);
1344       else
1345         gdk_window_lower (display->window->window);
1346     }
1347     else {
1348       if (up)
1349         gtk_widget_hide_all (display->window);
1350       else
1351         gtk_widget_show_all (display->window);
1352 
1353     }
1354   }
1355 
1356   ok = true;
1357 
1358 
1359   gdk_flush ();
1360   return (ok);
1361 }
1362 
GGOBI(getDescription)1363 gchar *GGOBI (getDescription) (ggobid * gg)
1364 {
1365   if (!gg->input)
1366     return (NULL);
1367 
1368   return (g_strdup (gg->input->fileName));
1369 }
1370 
1371 /*
1372   Finds the index of the dataset named `name'
1373   in the specified ggobid object.
1374  */
GGOBI(datasetIndex)1375 int GGOBI (datasetIndex) (const char *name, const ggobid * const gg)
1376 {
1377   GGobiData *d;
1378   int ctr = 0;
1379   GSList *tmp = gg->d;
1380 
1381   while (tmp) {
1382     d = (GGobiData *) tmp->data;
1383     if (strcmp (name, d->name) == 0)
1384       return (ctr);
1385     ctr++;
1386     tmp = tmp->next;
1387   }
1388 
1389   return (-1);
1390 }
1391 
1392 /*
1393   Returns the names of the different datasets
1394   maintained in the specified ggobid object.
1395  */
GGOBI(getDatasetNames)1396 gchar **GGOBI (getDatasetNames) (gint * n, ggobid * gg)
1397 {
1398   gint i;
1399   GGobiData *d;
1400   gchar **names;
1401   GSList *tmp = gg->d;
1402   *n = g_slist_length (gg->d);
1403   names = (gchar **) g_malloc (sizeof (gchar *) * (*n));
1404   for (i = 0; i < *n; i++) {
1405     d = (GGobiData *) tmp->data;
1406     names[i] = g_strdup (d->name);
1407     tmp = tmp->next;
1408   }
1409 
1410   return (names);
1411 }
1412 
1413 /*
1414  Added to the API and to avoid breaking code (e.g. in RSggobi)
1415  we add it here with a new name GGOBI(ggobi_get).
1416 */
GGOBI(ggobi_get)1417 ggobid *GGOBI (ggobi_get) (gint which)
1418 {
1419   return (ggobi_get (which));
1420 }
1421 
GGOBI(ncols)1422 gint GGOBI (ncols) (GGobiData * data)
1423 {
1424   return (data->ncols);
1425 }
1426 
GGOBI(nrecords)1427 gint GGOBI (nrecords) (GGobiData * data)
1428 {
1429   return (data->nrows);
1430 }
1431 
1432 
1433 /*
1434  This is the routine one uses to register a handler for key press events
1435  for the numbered keys, i.e. 0, 1, ..., 9
1436  One can specify null values for each of these to remove the handler and have
1437  these events discarded.
1438 
1439  See notes/NumberedKeys.*, splot.c and ggobi.h also for more details
1440  */
GGOBI(registerNumberedKeyEventHandler)1441 KeyEventHandler *GGOBI (registerNumberedKeyEventHandler) (KeyEventHandlerFunc
1442                                                           routine,
1443                                                           void *userData,
1444                                                           char *description,
1445                                                           ReleaseData *
1446                                                           releaseData,
1447                                                           ggobid * gg,
1448                                                           ProgrammingLanguage
1449                                                           lang)
1450 {
1451   KeyEventHandler *old = gg->NumberedKeyEventHandler;
1452   KeyEventHandler *newValue;
1453   if (routine == NULL)
1454     newValue = NULL;
1455   else {
1456     newValue = g_malloc (1 * sizeof (KeyEventHandler));
1457     newValue->handlerRoutine = routine;
1458     newValue->userData = userData;
1459     newValue->description = g_strdup (description);
1460     newValue->language = lang;
1461     newValue->releaseData = releaseData;
1462   }
1463 
1464   gg->NumberedKeyEventHandler = newValue;
1465 
1466   return (old);
1467 }
1468 
GGOBI(removeNumberedKeyEventHandler)1469 KeyEventHandler *GGOBI (removeNumberedKeyEventHandler) (ggobid * gg)
1470 {
1471   return (GGOBI
1472           (registerNumberedKeyEventHandler (NULL, NULL, NULL, NULL, gg, C)));
1473 }
1474 
1475 
1476 #include "config.h"
1477 static const gchar *version_date = GGOBI_RELEASE_DATE;
1478 static const int GgobiVersionNumbers[] =
1479   { MAJOR_VERSION, MINOR_VERSION, MICRO_VERSION };
1480 static const gchar *version_string = PACKAGE_VERSION;
1481 
GGOBI(getVersionDate)1482 const char *GGOBI (getVersionDate) ()
1483 {
1484   return (version_date);
1485 }
1486 
GGOBI(getVersionString)1487 const char *GGOBI (getVersionString) ()
1488 {
1489   return (version_string);
1490 }
1491 
GGOBI(getVersionNumbers)1492 const int *GGOBI (getVersionNumbers) ()
1493 {
1494   return (GgobiVersionNumbers);
1495 }
1496 
1497 
GGOBI(data_get)1498 GGobiData *GGOBI (data_get) (gint which, const ggobid * const gg)
1499 {
1500   GGobiData *data = NULL;
1501 
1502   if (gg->d != NULL)
1503     data = g_slist_nth_data (gg->d, which);
1504 
1505   return (data);
1506 }
1507 
GGOBI(data_get_by_name)1508 GGobiData *GGOBI (data_get_by_name) (const gchar * const name,
1509                                      const ggobid * const gg)
1510 {
1511   gint which;
1512   GGobiData *data = NULL;
1513 
1514   which = GGOBI (datasetIndex) (name, gg);
1515   if (which > -1) {
1516     data = GGOBI (data_get) (which, gg);
1517   }
1518 
1519   return (NULL);
1520 }
1521 
1522 void
GGobi_setSessionOptions(GGobiOptions * opts)1523 GGobi_setSessionOptions (GGobiOptions * opts)
1524 {
1525   sessionOptions = opts;
1526 }
1527 
1528 const gchar *
GGobi_getLevelName(vartabled * vt,double value)1529 GGobi_getLevelName (vartabled * vt, double value)
1530 {
1531   int which = 0;
1532   for (which = 0; which < vt->nlevels; which++) {
1533     if (vt->level_values[which] == (int) value)
1534       return (vt->level_names[which]);
1535   }
1536 
1537   return (NULL);
1538 }
1539 
1540 
1541 void
GGobi_setDataName(const char * const name,GGobiData * d)1542 GGobi_setDataName (const char *const name, GGobiData * d)
1543 {
1544   if (d->name)
1545     g_free ((gchar *) d->name);
1546 
1547   d->name = g_strdup (name);
1548   /* Update the different labels. */
1549 }
1550 
1551 
1552 /* sets the tour projection matrix, F */
1553 gboolean
GGOBI(setTour2DProjectionMatrix)1554 GGOBI (setTour2DProjectionMatrix) (gdouble * Fvalues, gint ncols, gint ndim,
1555                                    gboolean vals_scaled, ggobid * gg)
1556 {
1557   ProjectionMode vm = pmode_get (gg->current_display, gg);
1558   displayd *dsp = gg->current_display;
1559   cpaneld *cpanel = &dsp->cpanel;
1560   GGobiData *d = dsp->d;
1561   gboolean candoit = true;
1562   gint i, j;
1563 
1564   if ((ncols != d->ncols) || ndim != 2)
1565     candoit = false;
1566 
1567   if (candoit) {
1568     /* Set the scatterplot display mode to be tour2d */
1569     if (vm != TOUR2D) {
1570       /* Needs to be filled in */
1571     }
1572 
1573     /* Pause the tour */
1574     if (!cpanel->t2d.paused)
1575       tour2d_pause (cpanel, true, dsp, gg);
1576 
1577     /* Set the projection vector F */
1578     for (i = 0; i < ndim; i++)
1579       for (j = 0; j < ncols; j++)
1580         dsp->t2d.F.vals[i][j] = Fvalues[i + j * 2];
1581 
1582     /* If the values are scaled, then we need to multiply
1583        them by the tform data, else we multiply them by the
1584        world data */
1585     if (vals_scaled) {
1586       /* Needs to be filled in */
1587     }
1588     else {
1589       display_tailpipe (dsp, FULL, gg);
1590       varcircles_refresh (d, gg);
1591     }
1592   }
1593 
1594   return (candoit);
1595 }
1596 
GGOBI(getTour2DProjectionMatrix)1597 const gdouble **GGOBI (getTour2DProjectionMatrix) (gint ncols, gint ndim,
1598                                                    gboolean vals_scaled,
1599                                                    ggobid * gg)
1600 {
1601   displayd *dsp = gg->current_display;
1602   GGobiData *d = dsp->d;
1603   gdouble **Fvals;
1604   gint i, j;
1605 
1606   ncols = d->ncols;
1607   ndim = 2;
1608 
1609   Fvals = (gdouble **) g_malloc (sizeof (gdouble *) * ncols);
1610 
1611   if (vals_scaled) {
1612     /* run the F values through the reverse pipeline */
1613   }
1614   else {
1615     for (i = 0; i < ndim; i++)
1616       for (j = 0; j < ncols; j++)
1617         Fvals[i][j] = dsp->t2d.F.vals[i][j];
1618   }
1619 
1620   return ((const gdouble **) Fvals);
1621 }
1622 
1623 
1624 guint
getGGobiSignal(GGobiSignalType which)1625 getGGobiSignal (GGobiSignalType which)
1626 {
1627   /*
1628      XXX  assert(which > -1 && which < MAX_GGOBI_SIGNALS);
1629    */
1630   return (GGobiSignals[which]);
1631 }
1632 
1633 
GGOBI(getExtendedDisplayTypes)1634 GSList *GGOBI (getExtendedDisplayTypes) ()
1635 {
1636   return (ExtendedDisplayTypes);
1637 }
1638