[xiph-commits] r13756 - trunk/sushivision

xiphmont at svn.xiph.org xiphmont at svn.xiph.org
Tue Sep 4 23:32:40 PDT 2007


Author: xiphmont
Date: 2007-09-04 23:32:39 -0700 (Tue, 04 Sep 2007)
New Revision: 13756

Added:
   trunk/sushivision/tokens.c
Modified:
   trunk/sushivision/Makefile
   trunk/sushivision/dimension.c
   trunk/sushivision/example_fractal.c
   trunk/sushivision/internal.h
   trunk/sushivision/main.c
   trunk/sushivision/objective.c
   trunk/sushivision/panel-1d.c
   trunk/sushivision/panel-1d.h
   trunk/sushivision/panel-2d.c
   trunk/sushivision/panel.c
   trunk/sushivision/scale.c
   trunk/sushivision/sushivision.h
Log:
I'm aware this commit doesn't build; I just want to get current/extensive ongoing API changes into SVN before I lose them by accident.



Modified: trunk/sushivision/Makefile
===================================================================
--- trunk/sushivision/Makefile	2007-09-05 03:25:14 UTC (rev 13755)
+++ trunk/sushivision/Makefile	2007-09-05 06:32:39 UTC (rev 13756)
@@ -26,13 +26,14 @@
 
 SRC       = main.c scale.c plot.c slider.c slice.c spinner.c panel.c panel-1d.c panel-2d.c \
 	panel-xy.c mapping.c dimension.c function.c objective.c undo.c gtksucks.c xml.c \
-	example_fractal.c example_discrete.c example_chirp.c example_spirograph.c
+	tokens.c example_fractal.c example_discrete.c example_chirp.c example_spirograph.c
 INC       = sushivision.h sushimacro.h
 MAN	  =
 EXAMPLES  = sushivision_fractal #sushivision_discrete sushivision_chirp
 EX_OBJ    = example_fractal.o #example_discrete.o example_chirp.o example_spirograph.o
 OBJ       = main.o scale.o plot.o slider.o slice.o spinner.c panel.o panel-1d.o panel-2d.o \
-	panel-xy.o mapping.o dimension.o function.o objective.o undo.o gtksucks.o xml.o
+	panel-xy.o mapping.o dimension.o function.o objective.o undo.o gtksucks.o xml.o \
+	tokens.c
 LIBS      = -lpthread -ldl
 CAIROVER  =  >= 1.4.1
 GTKVER    =  >= 2.10.0

Modified: trunk/sushivision/dimension.c
===================================================================
--- trunk/sushivision/dimension.c	2007-09-05 03:25:14 UTC (rev 13755)
+++ trunk/sushivision/dimension.c	2007-09-05 06:32:39 UTC (rev 13756)
@@ -38,7 +38,7 @@
    third the same as the second, but over the absolute range [0 - n)
    such that discrete dimensions will count from 0 in iteration. */
 /* data_w ignored except in the continuous case, where it may be used
-   to generate linked or over/undersampled data scales. */
+   to generate over/undersampled data scales. */
 
 int _sv_dim_scales(sv_dim_t *d,
 		   double lo,
@@ -718,7 +718,7 @@
   if(d->scale)
     sv_scale_free(d->scale); // always a deep copy we own
   
-  d->scale = (sv_scale_t *)sv_scale_copy(scale);
+  d->scale = sv_scale_copy(scale);
 
   // in the runtime version, don't just blindly reset values!
   d->bracket[0]=scale->val_list[0];
@@ -732,20 +732,19 @@
 
 // XXXX need to recompute after
 // XXXX need to add scale cloning to compute to make this safe in callbacks
-int sv_dim_make_scale(char *first, char *second, ...){
+int sv_dim_make_scale(char *format){
   sv_dim_t *d = sv_dim(0);
   sv_scale_t *scale;
-  va_list ap;
   int ret;
 
-  va_start(ap, second);  
   if(!d) return -EINVAL;
-  scale = _sv_scale_new_v(d->name,first,second,ap);
+  scale = sv_scale_new(d->name,format);
   if(!scale)return errno;
-  va_end(ap);
   
-  ret = sv_dim_set_scale(scale);
-  sv_scale_free(scale);
+  d->scale = scale;
+  d->bracket[0]=scale->val_list[0];
+  d->val = 0;
+  d->bracket[1]=scale->val_list[d->scale->vals-1];
   return ret;
 }
 

Modified: trunk/sushivision/example_fractal.c
===================================================================
--- trunk/sushivision/example_fractal.c	2007-09-05 03:25:14 UTC (rev 13755)
+++ trunk/sushivision/example_fractal.c	2007-09-05 06:32:39 UTC (rev 13756)
@@ -57,25 +57,22 @@
   //gtk_init (&argc, &argv);
   //gdk_threads_init ();
 
+  // "name:label(arg,arg,arg...)"
 
   sv_dim_t *d0 = sv_dim_new(0, "Re(c)", 0);
-  sv_dim_make_scale("-2.25","-0.75","0","0.25","0.75","");
+  sv_dim_make_scale("-2.25; -0.75; 0; 0.25; 0.75");
   
   sv_dim_t *d1 = sv_dim_new(1, "Im(c)", 0);
-  sv_dim_make_scale("-2","-1","0","1","2","");
+  sv_dim_make_scale("-2;-1;0;1;2");
 
   sv_dim_t *d2 = sv_dim_new(2, "Re(z0)", 0);
-  sv_dim_make_scale("-2.25","-1","0","1","2.25","");
+  sv_dim_make_scale("-2.25; -1; 0; 1; 2.25");
 
   sv_dim_t *d3 = sv_dim_new(3, "Im(z0)", 0);
-  sv_dim_make_scale("-2.25","-1","0","1","2.25","");
+  sv_dim_make_scale("-2.25; -1; 0; 1; 2.25");
 
   sv_dim_t *d4 = sv_dim_new(4, "Max Iterations", 0);
-  sv_dim_make_scale("100:one hundred",
-		    "1000:one thousand",
-		    "10000:ten thousand",
-		    "100000:one hundred thousand",
-		    "");
+  sv_dim_make_scale("100:one hundred; 1000:one thousand; 10000:ten thousand; 100000:one hundred thousand");
 
   sv_dim_set_picklist();
   sv_dim_set_value(100);
@@ -86,13 +83,13 @@
 			    (sv_func_t *[]){f},
 			    (int []){0},
 			    "Y", 0);
-  sv_obj_make_scale(o0, "0", ".001", ".01", ".1", "1.0", "");
+  sv_obj_make_scale(o0, "0; .001; .01; .1; 1.0");
   
   sv_obj_t *o1 = sv_obj_new(1,"inner",
 			    (sv_func_t *[]){f},
 			    (int []){1},
 			    "Y", 0);
-  sv_obj_make_scale(o1, "0", ".001", ".01", ".1", "1.0", "");
+  sv_obj_make_scale(o1, "0; .001; .01; .1; 1.0");
   
   sv_panel_new_2d(0,"Mandel/Julia Fractal",
 		  (sv_obj_t *[]){o0,o1,NULL},

Modified: trunk/sushivision/internal.h
===================================================================
--- trunk/sushivision/internal.h	2007-09-05 03:25:14 UTC (rev 13755)
+++ trunk/sushivision/internal.h	2007-09-05 06:32:39 UTC (rev 13756)
@@ -29,6 +29,25 @@
 #include <libxml/tree.h>
 #include "sushivision.h"
 
+typedef struct {
+  char *name;
+  char *label;
+
+  int n;
+  char **options;
+  double *values;
+} _sv_token;
+
+typedef struct {
+  int n;
+  _sv_token **list;
+} _sv_tokenlist;
+
+extern void _sv_token_free(_sv_token *t);
+extern void _sv_tokenlist_free(_sv_tokenlist *l);
+extern _sv_token *_sv_tokenize(char *in);
+extern _sv_tokenlist *_sv_tokenlistize(char *in);
+
 // used to glue numeric settings to semantic labels for menus/save files
 typedef struct _sv_propmap _sv_propmap_t;
 struct _sv_propmap {
@@ -180,8 +199,6 @@
 extern int  _sv_panel_save(sv_panel_t *p, xmlNodePtr n);
 extern int  _sv_panel_load(sv_panel_t *p, _sv_panel_undo_t *u, xmlNodePtr n, int warn);
 
-extern void _sv_panel1d_mark_recompute_linked(sv_panel_t *p); 
-extern void _sv_panel1d_update_linked_crosshairs(sv_panel_t *p, int xflag, int yflag); 
 
 extern void _sv_map_set_throttle_time(sv_panel_t *p);
 

Modified: trunk/sushivision/main.c
===================================================================
--- trunk/sushivision/main.c	2007-09-05 03:25:14 UTC (rev 13755)
+++ trunk/sushivision/main.c	2007-09-05 06:32:39 UTC (rev 13756)
@@ -195,7 +195,12 @@
   gtk_main ();
   gdk_threads_leave();
   
-  gtk_main_quit(); // in case there's another mainloop in the main app
+// in case there's another mainloop in the main app
+  gdk_threads_enter();
+  if(!gtk_main_iteration_do(FALSE)) // side effect: returns true if
+				    // there are no main loops active
+    gtk_main_quit();
+  gdk_threads_leave();
 
   return 0;
 }

Modified: trunk/sushivision/objective.c
===================================================================
--- trunk/sushivision/objective.c	2007-09-05 03:25:14 UTC (rev 13755)
+++ trunk/sushivision/objective.c	2007-09-05 06:32:39 UTC (rev 13756)
@@ -199,22 +199,16 @@
 // XXXX need to recompute after
 // XXXX need to add scale cloning to compute to make this safe in callbacks
 int sv_obj_make_scale(sv_obj_t *in,
-		      char *first,
-		      char *second,
-		      ...){
+		      char *format){
 
   sv_obj_t *o = (sv_obj_t *)in; //unwrap
   sv_scale_t *scale;
-  va_list ap;
   int ret;
 
-  va_start(ap, second);  
   if(!o) return -EINVAL;
-  scale = _sv_scale_new_v(o->name,first,second,ap);
+  scale = sv_scale_new(o->name,format);
   if(!scale)return errno;
-  va_end(ap);
 
-  ret = sv_obj_set_scale(o,scale);
-  sv_scale_free(scale);
+  o->scale = scale;
   return ret;
 }

Modified: trunk/sushivision/panel-1d.c
===================================================================
--- trunk/sushivision/panel-1d.c	2007-09-05 03:25:14 UTC (rev 13755)
+++ trunk/sushivision/panel-1d.c	2007-09-05 06:32:39 UTC (rev 13756)
@@ -403,25 +403,6 @@
       }
     }
 
-    // linked? add the linked dimension value to the legend
-    if(p1->link_x || p1->link_y){
-      sv_dim_t *d;
-      int depth=0;
-      if(p1->link_x)
-	d = p1->link_x->private->x_d;
-      else
-	d = p1->link_y->private->y_d;
-      
-      // add each dimension to the legend
-      // display decimal precision relative to display scales
-      
-      snprintf(buffer,320,"%s = %+.*f",
-	       d->name,
-	       depth,
-	       d->val);
-      _sv_plot_legend_add(plot,buffer);
-    }
-
     // one space 
     _sv_plot_legend_add(plot,NULL);
 
@@ -694,21 +675,8 @@
   int w = plot->w.allocation.width;
   int h = plot->w.allocation.height;
   int dw = w;
-  sv_panel_t *link = (p1->link_x ? p1->link_x : p1->link_y);
-  _sv_panel2d_t *p2 = (link?link->subtype->p2:NULL);
   int i,j;
 
-  if(p1->link_x){
-    dw = p2->x_v.pixels;
-    p->private->x_d = link->private->x_d;
-    p1->x_scale = p2->x_scale;
-  }
-  if(p1->link_y){
-    dw = p2->y_v.pixels;
-    p->private->x_d = link->private->y_d;
-    p1->x_scale = p2->y_scale;
-  }
-
   if(plot && GTK_WIDGET_REALIZED(GTK_WIDGET(plot))){
     if(p1->flip){
       dw = _sv_dim_scales(p->private->x_d, 
@@ -729,52 +697,52 @@
       
     }else{
       dw = _sv_dim_scales(p->private->x_d, 
-				    p->private->x_d->bracket[0],
-				    p->private->x_d->bracket[1],
-				    w,dw * p->private->oversample_n / p->private->oversample_d,
-				    plot->scalespacing,
-				    p->private->x_d->name,
-				    &p1->x,
-				    &p1->x_v,
-				    &p1->x_i);
-
+			  p->private->x_d->bracket[0],
+			  p->private->x_d->bracket[1],
+			  w,dw * p->private->oversample_n / p->private->oversample_d,
+			  plot->scalespacing,
+			  p->private->x_d->name,
+			  &p1->x,
+			  &p1->x_v,
+			  &p1->x_i);
+      
       p1->y = _sv_scalespace_linear(p1->range_bracket[1],
-				p1->range_bracket[0],
-				h,
-				plot->scalespacing,
-				p1->range_scale->legend);
+				    p1->range_bracket[0],
+				    h,
+				    plot->scalespacing,
+				    p1->range_scale->legend);
     }
-
+    
     if(p1->data_size != dw){
       if(p1->data_vec){
-
+	
 	// make new vec
 	int i;
 	for(i=0;i<p->objectives;i++){
 	  double *new_vec = malloc(dw * sizeof(**p1->data_vec));
-
+	  
 	  free(p1->data_vec[i]);
 	  p1->data_vec[i] = new_vec;
 	}
       }
     }
-
+    
     p1->data_size = dw;
-
+    
     if(!p1->data_vec){
       // allocate it
-
+      
       p1->data_vec = calloc(p->objectives,sizeof(*p1->data_vec));
       for(i=0;i<p->objectives;i++)
 	p1->data_vec[i] = malloc(dw*sizeof(**p1->data_vec));
       
     }
-
+    
     // blank it 
     for(i=0;i<p->objectives;i++)
       for(j=0;j<dw;j++)
 	p1->data_vec[i][j]=NAN;
-
+    
     if(p1->panel_w != w || p1->panel_h != h){
       p->private->map_progress_count=0;
       _sv_panel1d_map_redraw(p, NULL);
@@ -792,59 +760,28 @@
   _sv_panel1d_mark_recompute(p);
 }
 
-void _sv_panel1d_mark_recompute_linked(sv_panel_t *p){
-  int i;
-
-  /* look to see if any 1d panels link to passed in panel */
-  for(i=0;i<_sv_panels;i++){
-    sv_panel_t *q = _sv_panel_list[i];
-    if(q != p && q->type == SV_PANEL_1D){
-      _sv_panel1d_t *q1 = q->subtype->p1;
-      if(q1->link_x == p)
-	_sv_panel1d_mark_recompute(q);
-      else{
-	if(q1->link_y == p)
-	  _sv_panel1d_mark_recompute(q);
-      }
-    }
-  }
-}
-
 static void _sv_panel1d_update_crosshair(sv_panel_t *p){
   _sv_panel1d_t *p1 = p->subtype->p1;
-  sv_panel_t *link=p1->link_x;
   _sv_plot_t *plot = PLOT(p->private->graph);
   double x=0;
   int i;
-
+  
   if(!p->private->realized)return;
   
-  if(p1->link_y)link=p1->link_y;
-
-  if(link){
-    for(i=0;i<link->dimensions;i++){
-      sv_dim_t *d = link->dimension_list[i].d;
-      if(d == p->private->x_d)
-	x = link->dimension_list[i].d->val;
-    }
-  }else{
-    for(i=0;i<p->dimensions;i++){
-      sv_dim_t *d = p->dimension_list[i].d;
-      if(d == p->private->x_d)
-	x = p->dimension_list[i].d->val;
-    }
+  for(i=0;i<p->dimensions;i++){
+    sv_dim_t *d = p->dimension_list[i].d;
+    if(d == p->private->x_d)
+      x = p->dimension_list[i].d->val;
   }
-  
+
   if(p1->flip)
     _sv_plot_set_crosshairs(plot,0,x);
   else
     _sv_plot_set_crosshairs(plot,x,0);
   
-  // in independent panels, crosshairs snap to a pixel position; the
+  // crosshairs snap to a pixel position; the
   // cached dimension value should be accurate with respect to the
-  // crosshairs.  in linked panels, the crosshairs snap to a pixel
-  // position in the master panel; that is handled in the master, not
-  // here.
+  // crosshairs. 
   for(i=0;i<p->dimensions;i++){
     sv_dim_t *d = p->dimension_list[i].d;
     _sv_panel1d_t *p1 = p->subtype->p1;
@@ -858,29 +795,6 @@
   _sv_panel_dirty_legend(p);
 }
 
-void _sv_panel1d_update_linked_crosshairs(sv_panel_t *p, int xflag, int yflag){
-  int i;
-
-  /* look to see if any 1d panels link to passed in panel */
-  for(i=0;i<_sv_panels;i++){
-    sv_panel_t *q = _sv_panel_list[i];
-    if(q != p && q->type == SV_PANEL_1D){
-      _sv_panel1d_t *q1 = q->subtype->p1;
-      if(q1->link_x == p){
-	_sv_panel1d_update_crosshair(q);
-	if(yflag)
-	  q->private->request_compute(q);
-      }else{
-	if(q1->link_y == p){
-	  _sv_panel1d_update_crosshair(q);
-	  if(xflag)
-	    q->private->request_compute(q);
-	}
-      }
-    }
-  }
-}
-
 static void _sv_panel1d_center_callback(sv_dim_list_t *dptr){
   sv_dim_t *d = dptr->d;
   sv_panel_t *p = dptr->p;
@@ -924,42 +838,23 @@
 
 static void _sv_panel1d_crosshair_callback(sv_panel_t *p){
   _sv_panel1d_t *p1 = p->subtype->p1;
-  sv_panel_t *link = p1->link_x;
   double x=PLOT(p->private->graph)->selx;
   int i;
 
   if(p1->flip)
     x=PLOT(p->private->graph)->sely;
-  if(p1->link_y)
-    link=p1->link_y;
   
   _sv_panel_dirty_legend(p);
 
-  if(p1->link_x){
-    // make it the master panel's problem.
-    _sv_plot_set_crosshairs_snap(PLOT(link->private->graph),
-			     x,
-			     PLOT(link->private->graph)->sely);
-    link->private->crosshair_action(link);
-  }else if (p1->link_y){
-    // make it the master panel's problem.
-    _sv_plot_set_crosshairs_snap(PLOT(link->private->graph),
-			     PLOT(link->private->graph)->selx,
-			     x);
-    link->private->crosshair_action(link);
-  }else{
-
-    _sv_undo_push();
-    _sv_undo_suspend();
-
-    for(i=0;i<p->dimensions;i++){
-      sv_dim_t *d = p->dimension_list[i].d;
-      if(d == p->private->x_d)
-	_sv_dim_widget_set_thumb(p->private->dim_scales[i],1,x);
-	            
-      p->private->oldbox_active = 0;
-    }
-    _sv_undo_resume();
+  _sv_undo_push();
+  _sv_undo_suspend();
+  
+  for(i=0;i<p->dimensions;i++){
+    sv_dim_t *d = p->dimension_list[i].d;
+    if(d == p->private->x_d)
+      _sv_dim_widget_set_thumb(p->private->dim_scales[i],1,x);
+    
+    p->private->oldbox_active = 0;
   }
 }
 
@@ -1377,7 +1272,7 @@
 		       GTK_FILL,0,5,0);
       
       /* x radio buttons */
-      if(!(d->flags & SV_DIM_NO_X) && !p1->link_x && !p1->link_y){
+      if(!(d->flags & SV_DIM_NO_X)){
 	if(first_x)
 	  p1->dim_xb[i] = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(first_x),"X");
 	else{
@@ -1562,38 +1457,3 @@
   
   return p;
 }
-
-int sv_panel_link_1d (sv_panel_t *p,
-		      sv_panel_t *panel_2d,
-		      unsigned flags){
-
-
-  if(!p){
-    fprintf(stderr,"Cannot link a NULL 1d panel\n");
-    errno = -EINVAL;
-    return errno;
-  }
-
-  if(!panel_2d){
-    fprintf(stderr,"Panel %d (\"%s\"): Attempted to link NULL panel\n",
-	    p->number,p->name);
-    errno = -EINVAL;
-    return errno;
-  }
-
-  if(panel_2d->type != SV_PANEL_2D){
-    fprintf(stderr,"Panel %d (\"%s\"): Can only link to a 2d paenl\n",
-	    p->number,p->name);
-    errno = -EINVAL;
-    return errno;
-  }
-
-  _sv_panel1d_t *p1 = p->subtype->p1;
-
-  if(flags && SV_PANEL_LINK_Y)
-    p1->link_y = (sv_panel_t *)panel_2d;
-  else
-    p1->link_x = (sv_panel_t *)panel_2d;
-
-  return 0;
-}

Modified: trunk/sushivision/panel-1d.h
===================================================================
--- trunk/sushivision/panel-1d.h	2007-09-05 03:25:14 UTC (rev 13755)
+++ trunk/sushivision/panel-1d.h	2007-09-05 06:32:39 UTC (rev 13756)
@@ -21,9 +21,6 @@
 
 typedef struct {
 
-  sv_panel_t *link_x;
-  sv_panel_t *link_y;
-
   GtkWidget *graph_table;
   GtkWidget *obj_table;
   GtkWidget *dim_table;

Modified: trunk/sushivision/panel-2d.c
===================================================================
--- trunk/sushivision/panel-2d.c	2007-09-05 03:25:14 UTC (rev 13755)
+++ trunk/sushivision/panel-2d.c	2007-09-05 06:32:39 UTC (rev 13756)
@@ -1208,7 +1208,6 @@
   _sv_plot_t *plot = PLOT(p->private->graph);
 
   if(plot && GTK_WIDGET_REALIZED(GTK_WIDGET(plot))){
-    _sv_panel1d_mark_recompute_linked(p);   
     _sv_panel_dirty_plot(p);
   }
 }
@@ -1228,7 +1227,6 @@
   }
   
   _sv_plot_set_crosshairs(plot,x,y);
-  _sv_panel1d_update_linked_crosshairs(p,0,0); 
   _sv_panel_dirty_legend(p);
 }
 
@@ -1243,7 +1241,6 @@
   }else{
     // mid slider of an axis dimension changed, move crosshairs
     _sv_panel2d_update_crosshairs(p);
-    _sv_panel1d_update_linked_crosshairs(p,d==p->private->x_d,d==p->private->y_d); 
   }
 }
 

Modified: trunk/sushivision/panel.c
===================================================================
--- trunk/sushivision/panel.c	2007-09-05 03:25:14 UTC (rev 13755)
+++ trunk/sushivision/panel.c	2007-09-05 06:32:39 UTC (rev 13756)
@@ -685,7 +685,7 @@
   return 0;  
 }
 
-/* request a recomputation with full setup (eg, linking, scales,
+/* request a recomputation with full setup (eg, scales,
    etc) */
 void _sv_panel_recompute(sv_panel_t *p){
   gdk_threads_enter ();
@@ -803,10 +803,11 @@
 sv_panel_t * _sv_panel_new(int number,
 			   char *name, 
 			   sv_obj_t **objectives,
-			   sv_dim_t **dimensions,	
+			   char *dimensions,
 			   unsigned flags){
 
   sv_panel_t *p;
+  char **dim_tokens;
   int i;
 
   if(number<0){
@@ -851,18 +852,28 @@
   }
 
   i=0;
-  while(dimensions && dimensions[i])i++;
+  dim_tokens = _sv_tokenize(dimensions,';',1);
+  while(dim_tokens && dim_tokens[i])i++;
   p->dimensions = i;
   p->dimension_list = malloc(i*sizeof(*p->dimension_list));
   for(i=0;i<p->dimensions;i++){
+    sv_dim_t *d = sv_dim(dim_tokensi[i]);
+
+    if(!d){
+      fprintf(stderr,"Panel %d (\"%s\"): Dimension \"%s\" does not exist\n",
+	      number,p->name,dim_tokens[i]);
+      errno = -EINVAL;
+      return NULL;
+    }
+
     if(!dimensions[i]->scale){
-      fprintf(stderr,"Panel %d (\"%s\"): Dimension number %d (\"%s\") has a NULL scale\n",
-	      number,p->name,dimensions[i]->number,dimensions[i]->name);
+      fprintf(stderr,"Panel %d (\"%s\"): Dimension number \"%s\" has a NULL scale\n",
+	      number,p->name,dimensions[i]->name);
       errno = -EINVAL;
       return NULL;
     }
 
-    p->dimension_list[i].d = (sv_dim_t *)dimensions[i];
+    p->dimension_list[i].d = d;
     p->dimension_list[i].p = p;
   }
 

Modified: trunk/sushivision/scale.c
===================================================================
--- trunk/sushivision/scale.c	2007-09-05 03:25:14 UTC (rev 13755)
+++ trunk/sushivision/scale.c	2007-09-05 06:32:39 UTC (rev 13756)
@@ -26,125 +26,11 @@
 #include <fontconfig/fontconfig.h>
 #include <stdio.h>
 #include <limits.h>
+#include <ctype.h>
 #include "sushivision.h"
 #include "scale.h"
 
 /* slider scales */
-static int trailing_zeroes(double A){
-  int count=0;
-  int64_t iA = (A<0 ? floor(-A) : floor(A));;
-  if(iA==0)return 0;
-  while(!(iA%10)){
-    count++;
-    iA/=10;
-  }
-  return count;
-}
-
-/* depth, at a minimum, must capture the difference between consecutive scale values */
-static int del_depth(double A, double B){
-  int depth = 0;
-
-  double del = B-A;
-  if(del<0)del=-del;
-  if(del != 0){
-    if(del<1){
-      float testdel=del;
-      while(testdel<1){
-	depth++;
-	testdel = del * pow(10,depth);
-      }
-    }else{
-      float testdel=del;
-      while(testdel>10){
-	depth--;
-	testdel = del / pow(10,-depth);
-      }
-    }
-  }
-  return depth;
-}
-
-static int abs_depth(double A){
-  int depth = 0;
-
-  if(A<0)A=-A;
-  if(A != 0){
-    if(A<1){
-      /* first ratchet down to find the beginning */
-      while(A * pow(10.,depth) < 1)
-	depth++;
-
-      /* look for trailing zeroes; assume a reasonable max depth */
-      depth+=5;
-
-      A*=pow(10.,depth);
-      int zero0 = trailing_zeroes(A);
-      int zeroN = trailing_zeroes(A-1);
-      int zeroP = trailing_zeroes(A+1);
-
-      if(zero0 >= zeroN && zero0 >= zeroP)
-	depth -= zero0;
-      else if(zeroN >= zero0 && zeroN >= zeroP)
-	depth -= zeroN;
-      else 
-	depth -=zeroP;
-
-    }else
-      // Max at five sig figs, less if trailing zeroes... */
-      depth= 5-trailing_zeroes(A*100000.);
-  }
-
-  return depth;
-}
-
-static char *generate_label(double val,int depth){
-  char *ret;
-  
-  if(depth>0){
-    asprintf(&ret,"%.*f",depth,val);
-  }else{
-    asprintf(&ret,"%ld",(long)val);
-  }
-  return ret;
-}
-
-/* default scale label generation is hard, but fill it in in an ad-hoc
-   fashion.  Add flags to help out later */
-static char **scale_generate_labels(unsigned scalevals, double *scaleval_list){
-  unsigned i;
-  int depth;
-  char **ret;
-
-  // default behavior; display each scale label at a uniform decimal
-  // depth.  Begin by finding the smallest significant figure in any
-  // label.  Since they're being passed in explicitly, they'll be
-  // pre-hinted to the app's desires. Deal with rounding. */
-
-  if(scalevals<2){
-    fprintf(stderr,"Scale requires at least two scale values.");
-    return NULL;
-  }
-
-  depth = del_depth(scaleval_list[0],scaleval_list[1]);
-
-  for(i=2;i<scalevals;i++){
-    int val = del_depth(scaleval_list[i-1],scaleval_list[i]);
-    if(val>depth)depth=val;
-  }
-  
-  for(i=0;i<scalevals;i++){
-    int val = abs_depth(scaleval_list[i]);
-    if(val>depth)depth=val;
-  }
-  
-  ret = calloc(scalevals,sizeof(*ret));
-  for(i=0;i<scalevals;i++)
-    ret[i] = generate_label(scaleval_list[i],depth);
-  
-  return ret;
-}
-
 void sv_scale_free(sv_scale_t *in){
   sv_scale_t *s = (sv_scale_t *)in;
   int i;
@@ -161,45 +47,52 @@
   }
 }
 
-sv_scale_t *_sv_scale_new_v(char *legend, char *first, char *second, va_list ap){
+sv_scale_t *sv_scale_new(char *arg){
   int i=0;
-  sv_scale_t *s = calloc(1, sizeof(*s));
-  va_list ac;
-  char *arg;
-  int count=0;
+  _sv_tokenlist *t= _sv_tokenlistize(format);
 
-  va_copy(ac, ap);
-  arg = va_arg(ac, char *);
-  while(arg && arg[0]){
-    count++;
-    arg = va_arg(ac, char *);
+  // sanity check the tokenization
+  if(!t){
+    fprintf(stderr,"sushivision: Unable to parse scale argument \"%s\".\n",arg);
+    return NULL;
   }
-  va_end(ac);
 
-  s->vals = count+2;
+  if(t->n != 1)
+    fprintf(stderr,"sushivision: Ignoring excess arguments to scale.\n");
+
+  if(
+  
+  sv_scale_t *s = calloc(1, sizeof(*s));
+  s->vals = count;
   s->val_list = calloc(s->vals,sizeof(*s->val_list));
   s->label_list = calloc(s->vals,sizeof(*s->label_list));
 
-  arg=first;
-  while(arg && arg[0]){
-    // an argument is a number and potentially a colon followed by an auxiliary label.
+  arg=format;
+  while(arg && *arg){
     char *buf = strdup(arg);
-    char *pos = strchr(buf,':');
+    char *pos = strchr(buf,';');
+    while(pos && *(pos-1)=='\\')
+      pos = strchr(pos+1,';');
+    if(!pos){
+      arg=NULL;
+    }else{
+      arg+=pos-buf+1;
+      pos[0]=0;
+    }
+
+    // an argument is a number and potentially a colon followed by an auxiliary label.
+    pos = strchr(buf,':');
     if(pos){
-      s->label_list[i] = strdup(pos+1);
+      // we have a colon (label)
+      s->label_list[i] = strdup(trim(pos+1));
       *pos='\0';
-      s->val_list[i]=atof(buf);
-      free(buf);
     }else{
-      s->label_list[i] = buf;
-      s->val_list[i]=atof(buf);
+      // we have only a number
+      s->label_list[i] = strdup(trim(buf));
     }
+    s->val_list[i]=atof_portable(buf);
+    free(buf);
     
-    if(arg==first){
-      arg=second;
-    }else{
-      arg=va_arg(ap, char *);
-    }
     i++;
   }
 
@@ -211,16 +104,6 @@
   return s;
 }
 
-sv_scale_t *sv_scale_new(char *legend, char *first, char *second, ...){
-  va_list ap;
-  sv_scale_t *ret;
-
-  va_start(ap, second);
-  ret = _sv_scale_new_v(legend,first,second,ap);
-  va_end(ap);
-  return ret;
-}
-
 sv_scale_t *sv_scale_copy(sv_scale_t *in){
   sv_scale_t *s = calloc(1, sizeof(*s));
   int i;
@@ -231,7 +114,7 @@
   s->legend = strdup(in->legend);
 
   for(i=0;i<s->vals;i++){
-    s->val_list[i]=in->val_list[i];
+    s->val_list[i] = in->val_list[i];
     s->label_list[i] = strdup(in->label_list[i]);
   }
   return s;

Modified: trunk/sushivision/sushivision.h
===================================================================
--- trunk/sushivision/sushivision.h	2007-09-05 03:25:14 UTC (rev 13755)
+++ trunk/sushivision/sushivision.h	2007-09-05 06:32:39 UTC (rev 13756)
@@ -22,8 +22,6 @@
 #ifndef _SUSHIVISION_
 #define _SUSHIVISION_
 
-#include <stdarg.h>
-
 typedef struct sv_scale sv_scale_t;
 typedef struct sv_panel sv_panel_t;
 typedef struct sv_dim   sv_dim_t;
@@ -62,9 +60,7 @@
 };
 
 sv_scale_t        *sv_scale_new (char *legend,
-				 char *first,
-				 char *second,
-				 ...);
+				 char *format);
 
 sv_scale_t       *sv_scale_copy (sv_scale_t *s);
 
@@ -105,9 +101,7 @@
 
 int            sv_dim_set_scale (sv_scale_t *scale);
 
-int           sv_dim_make_scale (char *first,
-				 char *second,
-				 ...);
+int           sv_dim_make_scale (char *format);
 
 int         sv_dim_set_discrete (long quant_numerator,
 				 long quant_denominator);
@@ -180,9 +174,7 @@
 				 sv_scale_t *scale);
 
 int           sv_obj_make_scale (sv_obj_t *o,
-				 char *first,
-				 char *second,
-				 ...);
+				 char *format);
 
 /* panels ********************************************************/
 
@@ -193,8 +185,6 @@
 			 SV_BG_BLACK, 
 			 SV_BG_CHECKS };
 
-#define SV_PANEL_LINK_X 0x1 
-#define SV_PANEL_LINK_Y 0x2 
 #define SV_PANEL_FLIP 0x4 
 
 typedef struct {
@@ -244,10 +234,6 @@
 				 sv_dim_t **dimensions,
 				 unsigned flags);
 
-int            sv_panel_link_1d (sv_panel_t *p,
-				 sv_panel_t *panel_2d,
-				 unsigned flags);
-
 int sv_panel_callback_recompute (sv_panel_t *p,
 				 int (*callback)(sv_panel_t *p,void *data),
 				 void *data);

Added: trunk/sushivision/tokens.c
===================================================================
--- trunk/sushivision/tokens.c	                        (rev 0)
+++ trunk/sushivision/tokens.c	2007-09-05 06:32:39 UTC (rev 13756)
@@ -0,0 +1,409 @@
+/*
+ *
+ *     sushivision copyright (C) 2006-2007 Monty <monty at xiph.org>
+ *
+ *  sushivision 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, or (at your option)
+ *  any later version.
+ *   
+ *  sushivision 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 sushivision; see the file COPYING.  If not, write to the
+ *  Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * 
+ */
+
+/* you should never write your own parser.  ever. */
+
+#define _GNU_SOURCE
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <math.h>
+#include "internal.h"
+
+void _sv_token_free(_sv_token *t){
+  if(t){
+    if(t->name)free(t->name);
+    if(t->label)free(t->label);
+    if(t->options){
+      int i;
+      for(i=0;i<t->n;i++)
+	if(t->options[i])free(t->options[i]);
+      free(t->options);
+    }
+    if(t->values)free(t->values);
+    free(t);
+  }
+}
+
+void _sv_tokenlist_free(_sv_tokenlist *l){
+  if(l){
+    if(l->list){
+      int i;
+      for(i=0;i<l->n;i++)
+	if(l->list[i])_sv_token_free(l->list[i]);
+      free(l->list);
+    }
+    free(l);
+  }
+}
+
+// don't allow locale conventions to screw up built-in number strings.
+// Sorry, but we're hardcoding decimal points in the float syntax.  This is
+// for built-in arg strings, we can substitute in labels later if
+// anyone's offended.
+static float atof_portable(char *number){
+  int msign=1;
+  int d=0;
+  int f=0;
+  int fe=0;
+  int esign=1;
+  int e=0;
+  int dflag=0;
+  int fflag=0;
+  int eflag=0;
+
+  // trim whitespace
+  while(number && *number && isspace(*number))number++;
+  
+  // overall sign
+  if(number && *number=='-'){
+    msign = -1;
+    number++;
+  }
+  if(number && *number=='+'){
+    number++;
+  }
+
+  // whole integer
+  while(number && *number>='0' && *number<='9'){
+    d = d*10+(*number-48);
+    number++;
+    dflag=1;
+  }
+
+  // seperator
+  if(number && *number=='.'){
+    number++;
+  }
+    
+  // fraction
+  while(number && *number>='0' && *number<='9'){
+    f = f*10+(*number-48);
+    fe--;
+    number++;
+    fflag=1;
+  }
+
+  // exponent seperator
+  if(number && (*number=='e' || *number=='E')){
+    number++;
+
+    //exponent sign
+    if(number && *number=='-'){
+      esign = -1;
+      number++;
+    }
+    if(number && *number=='+'){
+      number++;
+    }
+    while(number && *number>='0' && *number<='9'){
+      e = e*10+(*number-48);
+      number++;
+      eflag=1;
+    }
+    if(*number)return NAN;
+    if(!eflag)return NAN;
+  }
+
+  if(!dflag && !fflag)return NAN;
+  return msign*(d+f*powf(10,fe))*powf(10,e*esign);
+}
+
+static char *trim(char *in){
+  char *end;
+  if(!in)return NULL;
+
+  while(*in && isspace(*in))in++;
+  end=in;
+  while(*end)end++;
+  while(end>in && (*end==0 || isspace(*end)))end--;
+  if(*end)end[1]='\0';
+
+  return in;
+}
+
+static char *unescape(char *a){
+  char *head=a;
+  char *tail=a;
+  int escape=0;
+
+  if(head){
+    while(1){
+      *tail=*head;
+      if(!*head)break;
+    
+      if(*head!='\\' || escape){
+	tail++;
+	escape=0;
+      }else{
+	escape=1;
+      }
+      
+      head++;
+    }
+  }
+
+  return a;
+}
+
+// split at unescaped, unenclosed seperator
+// only parens enclose in our syntax
+static char *split(char *a, char sep){
+  char *arg=a;
+  char *ret=NULL;
+  int escape=0;
+  int level=0;
+
+  while(arg && *arg){
+    if(*arg=='(' && !escape){
+      level++;
+    }
+    if(*arg==')' && !escape){
+      level--;
+      if(level<0){
+	fprintf(stderr,"sushivision: ignoring extraneous paren in \"%s\".\n",
+		a);
+	*arg=' ';
+	level=0;
+      }
+    }
+    if(*arg==sep && !escape && level==0){
+      // we've found our split point
+      ret=arg+1;
+      *arg='\0';
+      return ret;
+    }
+    if(*arg=='\\'){
+      escape=1-escape;
+    }else{
+      escape=0;
+    }
+    arg++;
+  }
+
+  return NULL;
+}
+
+static int splitcount(char *a, char sep){
+  char *arg=a;
+  int escape=0;
+  int level=0;
+  int count=1;
+
+  while(arg && *arg){
+    if(*arg=='(' && !escape){
+      level++;
+    }
+    if(*arg==')' && !escape){
+      level--;
+      if(level<0) level=0;
+    }
+    if(*arg==sep && !escape && level==0)
+      count++;
+    else{
+      if(*arg=='\\'){
+	escape=1-escape;
+      }else{
+	escape=0;
+      }
+    }
+    arg++;
+  }
+
+  return count;
+}
+
+// unwrap contents enclosed by first level of parens
+// only parens enclose in our syntax
+static char *unwrap(char *a){
+  char *arg=a;
+  char *ret=NULL;
+  int escape=0;
+  int level=0;
+
+  while(arg && *arg){
+    if(*arg=='(' && !escape){
+      if(level==0){
+	ret=arg+1;
+	*arg='\0';
+      }
+      level++;
+    }
+    if(*arg==')' && !escape){
+      level--;
+      if(level==0){
+	*arg='\0';
+	return ret;
+      }
+      if(level<0){
+	fprintf(stderr,"sushivision: ignoring extraneous paren in \"%s\".\n",
+		a);
+	*arg=' ';
+	level=0;
+      }
+    }
+    if(*arg=='\\'){
+      escape=1-escape;
+    }else{
+      escape=0;
+    }
+    arg++;
+  }
+
+  if(level!=0){
+    fprintf(stderr,"sushivision: unbalanced paren(s) at \"%s(%s\".\n",
+	    a,ret);
+    return ret;
+  }
+  return NULL;
+}
+
+// name:label(flag,param=val)
+// name:label(val:label, val:label...)
+_sv_token *_sv_tokenize(char *in){
+  if(!in)return NULL;
+  char *a = strdup(in);
+
+  // single arg; ignore anything following a level 0 comma
+  if(split(a,','))
+    fprintf(stderr,"sushivision: ignoring trailing garbage after \"%s\".\n",a);
+  
+  // split name/label/args
+  char *label=split(a,':');
+  if(!label)label=a;
+  char *p=unwrap(label);
+
+  if(*a=='\0')goto done;
+
+  _sv_token *ret=calloc(1,sizeof(*ret));
+  ret->name = strdup(trim(unescape(a)));
+  ret->label = strdup(trim(unescape(label)));
+
+  if(p){
+    int i;
+    ret->n = splitcount(p,',');
+    ret->options = calloc(ret->n,sizeof(*ret->options));
+    ret->values = calloc(ret->n,sizeof(*ret->values));
+    
+    for(i=0;i<ret->n;i++){
+      char *next = split(p,',');
+      if(p){
+	if(*p){
+	  // may have param=val or val:label syntax
+	  if(splitcount(p,':')>1){
+	    
+	    if(splitcount(p,'=')>1){
+	      fprintf(stderr,"sushivision: parameter \"%s\" contains both \":\" and \"=\"; \"=\" ignored.\n",p);
+	    }
+	    char *label = split(p,':');
+	    ret->options[i]=strdup(trim(unescape(label)));
+	    ret->values[i]=atof_portable(trim(unescape(p)));
+	    
+	  }else if(splitcount(p,'=')>1){
+	    
+	    char *val = split(p,'=');
+	    ret->options[i]=strdup(trim(unescape(p)));
+	    ret->values[i]=atof_portable(trim(unescape(val)));
+	    
+	  }else{
+	    ret->options[i]=strdup(trim(unescape(p)));
+	    ret->values[i]=atof_portable(trim(unescape(ret->options[i])));
+	  }
+	}else{
+	  ret->values[i]=NAN;
+	}
+      }
+      p=next;
+    } 
+  }
+ done:
+  free(a);
+  return ret;
+}
+
+_sv_tokenlist *_sv_tokenlistize(char *in){
+  if(!in)return NULL;
+
+  char *l=strdup(in);
+  in=l;
+
+  int i,n = splitcount(l,',');
+  _sv_tokenlist *ret = calloc(1,sizeof(*ret));
+
+  ret->n = n;
+  ret->list = calloc(n,sizeof(*ret->list));
+
+  for(i=0;i<n;i++){
+    char *next = split(l,',');
+    ret->list[i] = _sv_tokenize(l);
+    l=next;
+  }
+  free(in);
+
+  return ret;
+}
+
+#if 0
+
+int main(int argc, char **argv){
+  int i;
+  for(i=1;i<argc;i++){
+    _sv_tokenlist *ret=_sv_tokenlistize(argv[i]);
+    fprintf(stderr,"parsing arglist %d:\n\n",i);
+    if(!ret)
+      fprintf(stderr,"NULL");
+    else{
+      int j;
+      fprintf(stderr,"arguments: %d",ret->n);
+      for(j=0;j<ret->n;j++){
+	fprintf(stderr,"\n\tname=%s, label=%s ",
+		ret->list[j]->name,
+		ret->list[j]->label);
+	if(ret->list[j]->n){
+	  int k;
+	  fprintf(stderr,"(");
+	  for(k=0;k<ret->list[j]->n;k++){
+	    if(k>0)
+	      fprintf(stderr,", ");
+	    if(ret->list[j]->options[k]){
+	      if(*ret->list[j]->options[k]){
+		fprintf(stderr,"%s",ret->list[j]->options[k]);
+	      }else{
+		fprintf(stderr,"\"\"");
+	      }
+	    }else{
+	      fprintf(stderr,"NULL");
+	    }
+	    fprintf(stderr,"=%g",ret->list[j]->values[k]);
+	  }
+	  fprintf(stderr,")");
+	}
+      }
+    }
+    fprintf(stderr,"\n\n");
+    _sv_tokenlist_free(ret);
+  }
+
+  return 0;
+}
+
+#endif



More information about the commits mailing list