[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