Moving files around, starting libtoolization.
authortrelane@digitasaru.net <trelane@digitasaru.net>
Mon, 12 Oct 2009 12:26:14 +0000 (07:26 -0500)
committertrelane@digitasaru.net <trelane@digitasaru.net>
Mon, 12 Oct 2009 12:26:14 +0000 (07:26 -0500)
22 files changed:
Makefile [deleted file]
Makefile.am [new file with mode: 0644]
configure.ac [new file with mode: 0644]
graph.c [deleted file]
graph.h [deleted file]
graphwidget.c [deleted file]
graphwidget.h [deleted file]
matdb-dotcode.c [deleted file]
matdb-dotcode.h [deleted file]
matdb.c [deleted file]
matdb.h [deleted file]
matdb.txt [deleted symlink]
scdataviz.c [deleted file]
src/graph.c [new file with mode: 0644]
src/graph.h [new file with mode: 0644]
src/graphwidget.c [new file with mode: 0644]
src/graphwidget.h [new file with mode: 0644]
src/matdb-dotcode.c [new file with mode: 0644]
src/matdb-dotcode.h [new file with mode: 0644]
src/matdb.c [new file with mode: 0644]
src/matdb.h [new file with mode: 0644]
src/scdataviz.c [new file with mode: 0644]

diff --git a/Makefile b/Makefile
deleted file mode 100644 (file)
index 3922e81..0000000
--- a/Makefile
+++ /dev/null
@@ -1,68 +0,0 @@
-##
-## Makefile
-##  
-## Made by Johnny Q. Hacker
-## Login   <solarionjohnathan>
-##
-## Started on  Thu Jul 17 10:56:05 2008 Johnny Q. Hacker
-## Last update Thu Jul 17 10:56:05 2008 Johnny Q. Hacker
-## 
-##############################
-# Complete this to make it ! #
-##############################
-NAME   = scdataviz             # Name of executable file
-SRC    = $(wildcard *.c)               # List of *.c
-INCL   =               # List of *.h
-################
-# Optional add #
-################
-IPATH   = -I.           # path of include file
-OBJOPT  = -ggdb -g3 -pg -Wall -Wstrict-prototypes -DDEBUG -std=c99 -D_GNU_SOURCE      # option for obj
-EXEOPT  = -ggdb -g3 -pg -Wall -Wstrict-prototypes -std=c99 -D_GNU_SOURCE     # option for exe (-lefence ...)
-LPATH   = -L.           # path for librairies ... 
-
-#####################
-# Macro Definitions #
-#####################
-CC     = gcc
-MAKE   = make
-SHELL  = /bin/sh
-OBJS   = $(SRC:.c=.o) 
-RM     = /bin/rm -f    
-COMP   = gzip -9v
-UNCOMP = gzip -df
-STRIP  = strip
-
-CFLAGS  = $(OBJOPT) $(IPATH) `pkg-config --cflags gtk+-2.0`
-LDFLAGS = $(EXEOPT) $(LPATH) `pkg-config --libs gtk+-2.0`
-
-.SUFFIXES: .h.Z .c.Z .h.gz .c.gz .c.z .h.z 
-
-##############################
-# Basic Compile Instructions #
-##############################
-
-all:   $(NAME)
-$(NAME): $(OBJS) $(SRC) $(INCL)  
-       $(CC) $(OBJS) $(LDFLAGS) -o $(NAME) 
-#      $(STRIP) ./$(NAME) # if you debug ,don't strip ...
-
-depend:
-       gcc $(IPATH) -MM $(SRC) 
-clean:
-       -$(RM) $(NAME) $(OBJS)
-fclean:
-       -$(RM) $(NAME)
-comp: clean
-       $(COMP) $(INCL) $(SRC)
-ucomp: 
-       $(UNCOMP) $(SRC) $(INCL)
-
-.c.Z.c .h.Z.h .c.gz.c .h.gz.h .c.z.c .h.z.h :
-        -$(UNCOMP) $<
-
-.c.o:
-       $(CC) $(CFLAGS) -c $< 
-################
-# Dependencies #
-################
diff --git a/Makefile.am b/Makefile.am
new file mode 100644 (file)
index 0000000..6809a32
--- /dev/null
@@ -0,0 +1,38 @@
+## Makefile.am -- Process this file with automake to produce Makefile.in
+AUTOMAKE_OPTIONS = gnu subdir-objects
+AM_DEFAULT_SOURCE_EXT = .c++
+ACLOCAL_AMFLAGS=-I m4
+AM_YFLAGS=-d
+AM_CFLAGS = $(GLIB_CFLAGS) $(GIO_CFLAGS) 
+AM_CPPFLAGS = $(GLIB_CFLAGS) $(GIO_CFLAGS) 
+
+bin_PROGRAMS = kdotp/kdotp kdotp/makestruct
+lib_LTLIBRARIES = libkdotp/libkdotp-0.1.la libmodelxx/libmodelxx-0.1.la
+
+#Tests which should succeed
+TESTS=tests/tests
+
+check_PROGRAMS = tests/tests
+tests_tests_SOURCES = 
+LIBS +=  -lm
+#Tests which should fail.
+XFAIL_TESTS=
+
+CLEANFILES = program_version.c
+
+program_version.c:
+       echo -n 'char *version_info = "' > program_version.c
+       bzr version-info | perl -ne 'chomp; print; print "\\n";' >> program_version.c 
+       echo '";' >> program_version.c
+
+include_HEADERS=
+include libkdotp.am
+include libmodelxx.am
+
+kdotp_kdotp_SOURCES = kdotp/kdotp.c++
+kdotp_kdotp_LDADD = libkdotp/libkdotp-0.1.la
+LIBS += $(GLIB_LIBS) $(GIO_LIBS)
+
+kdotp_makestruct_SOURCES = kdotp/makestruct.c++ kdotp/structspec_parser.y++ kdotp/structspec_lexer.l++
+kdotp_makestruct_LDADD = libkdotp/libkdotp-0.1.la libmodelxx/libmodelxx-0.1.la
+LIBS += $(GLIB_LIBS) $(GIO_LIBS)
diff --git a/configure.ac b/configure.ac
new file mode 100644 (file)
index 0000000..178e8d4
--- /dev/null
@@ -0,0 +1,128 @@
+AC_PREREQ(2.61)
+AC_INIT([gimme-alpha], [0.1], [gimme-alpha@pingenot.org])
+AM_INIT_AUTOMAKE([gnu -Wno-portability])
+AC_CONFIG_HEADERS([config.h])
+AC_CONFIG_MACRO_DIR([m4])
+
+AC_PROG_CC
+AC_PROG_CXX
+AC_PROG_LIBTOOL
+AC_PROG_INSTALL
+AM_PROG_LEX
+AC_PROG_YACC
+
+PKG_CHECK_MODULES(GLIB, glib-2.0 >= 2.6, have_glib=true, have_glib=false)
+AC_SUBST(GLIB_CFLAGS)
+AC_SUBST(GLIB_LIBS)
+
+PKG_CHECK_MODULES(GIO, gio-2.0 >= 2.18, have_gio=true, have_gio=false)
+AC_SUBST(GIO_CFLAGS)
+AC_SUBST(GIO_LIBS)
+
+PKG_CHECK_MODULES(FFTW3, fftw3 >= 3.1.2, have_fftw3=true, have_fftw3=false)
+AC_SUBST(FFTW3_CFLAGS)
+AC_SUBST(FFTW3_LIBS)
+
+dnl Check for GNU Scientific Lib, link to it if found.
+AC_CHECK_LIB([m],[cos])
+AC_CHECK_LIB([gslcblas],[cblas_dgemm])
+AC_CHECK_LIB([gsl],[gsl_blas_dgemm])
+
+dnl PKG_CHECK_MODULES(GTK, gtk+-2.0 >= 3.1, have_gtk=true, have_gtk=false)
+dnl AC_SUBST(GTK_CFLAGS)
+dnl AC_SUBST(GTK_LIBS)
+
+AC_ARG_ENABLE([debug],
+[  --enable-debug Turn on debugging],
+[case "${enableval}" in
+  yes) debug=true ;;
+  no) debug=false ;;
+  *) AC_MSG_ERROR([bad value ${enableval} for --enable-debug]) ;;
+esac],[debug=false])
+AM_CONDITIONAL([DEBUG], [test x$debug = xtrue])
+
+COMMMON_CFLAGS="-pipe -Wall -Werror -std=gnu99 -pedantic -Wno-unused-variable -Wno-unused-label -Wno-unused-parameter -Wno-unused-value -Wno-unused-function -march=native -mfpmath=sse -msse -mmmx -msse2 -msse3 -mssse3 -ftracer -fbranch-target-load-optimize"
+if test "x$debug" = "xtrue"; then
+  CFLAGS="$COMMMON_CFLAGS -O0 -g3"
+else
+  CFLAGS="$COMMMON_CFLAGS -O3 -frename-registers "
+fi
+dnl CPPFLAGS=
+
+AC_ARG_ENABLE([mudflap],
+[  --enable-mudflap Turn on mudflap, which debugs pointer use (verbosely)],
+[case "${enableval}" in
+  yes) mudflap=true ;;
+  no) mudflap=false ;;
+  *) AC_MSG_ERROR([bad value ${enableval} for --enable-mudflap]) ;;
+esac],[mudflap=false])
+AM_CONDITIONAL([MUDFLAP], [test x$mudflap = xtrue])
+if test "x$mudflap" = "xtrue"; then
+  CFLAGS="$CFLAGS -fmudflap -lmudflap"
+fi
+
+AC_ARG_ENABLE([profiling],
+[  --enable-profiling Turn on profiling],
+[case "${enableval}" in
+  yes) profiling=true ;;
+  no) profiling=false ;;
+  *) AC_MSG_ERROR([bad value ${enableval} for --enable-profiling]) ;;
+esac],[profiling=false])
+AM_CONDITIONAL([PROFILING], [test x$profiling = xtrue])
+if test "x$profiling" = "xtrue"; then
+  CFLAGS="$CFLAGS -pg -fprofile-generate"
+fi
+
+AC_ARG_ENABLE([openmpi],
+[  --enable-openmpi Turn on OpenMPI support],
+[case "${enableval}" in
+  yes) openmpi=true ;;
+  no) openmpi=false ;;
+  *) AC_MSG_ERROR([bad value ${enableval} for --enable-openmpi]) ;;
+esac],[mkl=false])
+AM_CONDITIONAL([OPENMPI], [test x$openmpi = xtrue])
+if test "x$openmpi" = "xtrue"; then
+  CFLAGS="$CFLAGS -DOPENMPI"
+fi
+
+AC_ARG_ENABLE([acml],
+[  --enable-acml Turn on AMD Core Math Library support],
+[case "${enableval}" in
+  yes) acml=true ;;
+  no) acml=false ;;
+  *) AC_MSG_ERROR([bad value ${enableval} for --enable-acml]) ;;
+esac],[mkl=false])
+AM_CONDITIONAL([ACML], [test x$acml = xtrue])
+if test "x$acml" = "xtrue"; then
+  CFLAGS="$CFLAGS -DACML"
+fi
+
+AC_ARG_ENABLE([mkl],
+[  --enable-mkl Turn on Intel's Math Kernel Library support],
+[case "${enableval}" in
+  yes) mkl=true ;;
+  no) mkl=false ;;
+  *) AC_MSG_ERROR([bad value ${enableval} for --enable-mkl]) ;;
+esac],[mkl=false])
+AM_CONDITIONAL([MKL], [test x$mkl = xtrue])
+if test "x$mkl" = "xtrue"; then
+  CFLAGS="$CFLAGS -DMKL"
+fi
+
+AC_ARG_ENABLE([atlas],
+[  --enable-atlas Turn on ATLAS support],
+[case "${enableval}" in
+  yes) atlas=true ;;
+  no) atlas=false ;;
+  *) AC_MSG_ERROR([bad value ${enableval} for --enable-atlas]) ;;
+esac],[atlas=false])
+AM_CONDITIONAL([ATLAS], [test x$atlas = xtrue])
+if test "x$atlas" = "xtrue"; then
+  CFLAGS="$CFLAGS -DATLAS"
+fi
+
+LIBKDOTP_ABI_VERSION=0
+LIBMODELXX_ABI_VERSION=0
+
+AC_CONFIG_FILES([Makefile])
+AC_OUTPUT
diff --git a/graph.c b/graph.c
deleted file mode 100644 (file)
index cd2b056..0000000
--- a/graph.c
+++ /dev/null
@@ -1,242 +0,0 @@
-/*
-** Graph.c
-** 
-** Made by (Johnny Q. Hacker)
-** Login   <solarion@johnathan>
-** 
-
-
-Copyright (C) 2008 Joseph Pingenot
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU Affero General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU Affero General Public License for more details.
-
-You should have received a copy of the GNU Affero General Public License
-along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-
-**Many thanks to Davyd Madeley for the excellent Cairo  Tutorial
-**  at http://gnomejournal.org/article/34/writing-a--using-cairo-and-gtk28
-
-** Started on  Thu Jul 17 10:51:32 2008 Johnny Q. Hacker
-** Last update Sun May 12 01:17:25 2002 Speed Blue
-*/
-
-#include <graph.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-
-#ifdef DEBUG
-#define DEBUG_AUTOAXIS
-#endif
-
-G_DEFINE_TYPE(Graph, graph, G_TYPE_OBJECT);
-
-static void graph_class_init(GraphClass *klass) {
-  GObjectClass *gobject_klass;
-  gobject_klass = G_OBJECT_CLASS(klass);
-}
-
-static void graph_init(Graph *graph) {
-  graph->symbol = CIRCLE;
-  graph->points = g_ptr_array_new();
-  graph->lines = NULL;
-  graph->xaxis = graph->yaxis = NULL;
-}
-
-Graph *graph_new(void) {
-  return g_object_new(GRAPH_TYPE, NULL);
-}
-
-/*1 means you're stupid and passed NULL*/
-int graph_add_graph_point(Graph* graph, struct graph_point *pt) {
-  if(pt == NULL) return 1;
-  g_ptr_array_add(graph->points, pt);
-  if((graph->points->len == 1) && ((graph->lines == NULL) || (graph->lines->len == 0))) {
-    graph->maxx = graph->minx = pt->x;
-    graph->maxy = graph->miny = pt->y;
-  }else{
-    if(pt->x > graph->maxx) graph->maxx = pt->x;
-    if(pt->x < graph->minx) graph->minx = pt->x;
-    if(pt->y > graph->maxy) graph->maxy = pt->y;
-    if(pt->y < graph->miny) graph->miny = pt->y;
-  }
-  return 0;
-}
-
-/*
- *
- *1 means failed to allocate point
- *NOTE: label is duplicated if not NULL (using g_strdup)
- */
-int graph_add_point(Graph* graph, double x, double y, const GString *label) {
-  struct graph_point *pt = (struct graph_point*)malloc(sizeof(struct graph_point));
-  if(pt == NULL) return 1;
-  pt->x = x;
-  pt->y = y;
-  pt->label = (label)?g_string_new(label->str):NULL;
-  graph_add_graph_point(graph, pt);
-  return 0;
-}
-
-int graph_add_graph_line(Graph* graph, struct graph_line *l) {
-  if(l == NULL) return 1;
-  if(graph->lines == NULL) {
-    if((graph->lines = g_ptr_array_new()) == NULL) return 1;
-  }
-  g_ptr_array_add(graph->lines, l);
-  if((graph->points->len == 0) && 
-     (graph->lines->len == 1)) {
-    graph->maxx = graph->minx = l->p0_x;
-    graph->maxy = graph->miny = l->p0_y;
-  }else{
-    if(l->p0_x > graph->maxx) graph->maxx = l->p0_x;
-    if(l->p0_x < graph->minx) graph->minx = l->p0_x;
-    if(l->p0_y > graph->maxy) graph->maxy = l->p0_y;
-    if(l->p0_y < graph->miny) graph->miny = l->p0_y;
-  }
-  if(l->p3_x > graph->maxx) graph->maxx = l->p3_x;
-  if(l->p3_x < graph->minx) graph->minx = l->p3_x;
-  if(l->p3_y > graph->maxy) graph->maxy = l->p3_y;
-  if(l->p3_y < graph->miny) graph->miny = l->p3_y;
-  return 0;
-}
-
-
-int graph_add_line(Graph* graph, double p0_x, double p0_y, double p1_x, double p1_y, double p2_x, double p2_y, double p3_x, double p3_y) {
-  #ifdef DEBUG
-  fprintf(stderr, "graph_add_line(%d, p0_x=%g, p0_y=%g, p1_x=%g, p1_y=%g, p2_x=%g, p2_y=%g, p3_x=%g, p3_y=%g\n", (unsigned int) graph, p0_x, p0_y, p1_x, p1_y, p2_x, p2_y, p3_x, p3_y);
-  #endif
-  struct graph_line *l;
-  if((l=(struct graph_line*)malloc(sizeof(struct graph_line))) == NULL) return 2;
-  l->p0_x=p0_x;
-  l->p0_y=p0_y;
-  l->p1_x=p1_x;
-  l->p1_y=p1_y;
-  l->p2_x=p2_x;
-  l->p2_y=p2_y;
-  l->p3_x=p3_x;
-  l->p3_y=p3_y;
-  return graph_add_graph_line(graph, l);
-}
-    
-struct cxt {
-  Graph *graph;
-  struct graph_point *p0;
-};
-    
-static void linear_interpolate(gpointer data, gpointer user_data) {
-  struct cxt *cxt = user_data;
-  struct graph_point *p3 = data;
-  if(cxt->p0 != NULL) {
-    double p1_x = (p3->x + 2*cxt->p0->x)/3.0;
-    double p1_y = (p3->y + 2*cxt->p0->y)/3.0;
-    double p2_x = (2*p3->x + cxt->p0->x)/3.0;
-    double p2_y = (2*p3->y + cxt->p0->y)/3.0;
-    graph_add_line(cxt->graph, cxt->p0->x, cxt->p0->y, p1_x, p1_y, p2_x, p2_y, p3->x, p3->y);
-  }
-  cxt->p0 = p3;
-}
-    
-void graph_add_linear_connectors(Graph* graph) {
-  struct cxt cxt;
-  cxt.graph = graph;
-  cxt.p0 = NULL;
-  g_ptr_array_foreach(graph->points, &linear_interpolate, &cxt);
-}
-
-void graph_bezier_linear_to_cubic(double x0, double x3, double *x1, double *x2) {
-  *x1 = (x3 + 2.0*x0)/3.0;
-  *x2 = (2.0*x3 + x0)/3.0;
-}
-
-void graph_bezier_linear_to_quadratic(double x0, double x3, double *x1) {
-  *x1 = (x3 + x0)/2.0;
-}
-
-void graph_bezier_quadratic_to_cubic(double x0, double x3, double *x1, double *x2) {
-  *x2 = (x3-2.0*(*x1))/3.0;
-  *x1 = (x0-2.0*(*x1))/3.0;
-}
-
-void graph_set_xaxis(Graph *g, struct graph_axis *axis) {
-  if(g->xaxis != NULL) {
-    free(g->xaxis);
-  }
-  g->xaxis=axis;
-}
-void graph_set_yaxis(Graph *g, struct graph_axis *axis) {
-  if(g->yaxis != NULL) {
-    free(g->yaxis);
-  }
-  g->yaxis=axis;
-}
-
-struct graph_axis* autoset_axis(Graph* g, GString* title, double min, double max) {
-  struct graph_axis *axis;
-  double range_mag;
-  double start_mag;
-  double stop_mag;
-  int i, j;
-  if(g->points->len == 0) {
-    return NULL;
-  }
-  if((axis=(struct graph_axis *)malloc(sizeof(struct graph_axis))) == NULL) {
-    return NULL;
-  }
-  if(g->points->len == 1) {
-    axis->major=1;
-    axis->minor=0;
-    axis->subminor=0;
-    axis->major_start=min;
-    axis->major_step=max;
-  }else{
-    range_mag = logb(max - min);
-    if(min == 0) 
-      start_mag = 0;
-    else
-      start_mag = copysign(pow(10, floor(log10(min))), min);
-    if(max == 0) 
-      stop_mag = 0;
-    else
-      stop_mag = copysign(pow(10, ceil(log10(max))), max);
-    for(i=1; i<9; i++) {
-      if(i*start_mag > min) break;
-    }
-    i--;
-    for(j=10; j>1; j--) {
-      if(j*(stop_mag/10) < max) break;
-    }
-    j++;
-    axis->major=10;
-    axis->minor=1;
-    axis->subminor=4;
-    axis->major_start=i*start_mag;
-    axis->major_step=(j*(stop_mag/10) - axis->major_start)/(axis->major);
-  }
-  axis->title=g_string_new(title->str);
-  #ifdef DEBUG_AUTOAXIS
-  fprintf(stderr, "graph_autoset_xaxis: xmin=%g, log10(xmin)=%g, floor=%g, pow=%g round=%g\n", min, log10(min), floor(log10(min)), pow(10, floor(log10(min))), round(pow(10, floor(log10(min)))));
-  fprintf(stderr, "graph_autoset_xaxis: xmax=%g, log10(xmax)=%g, floor=%g, pow=%g round=%g\n", max, log10(max), floor(log10(max)), pow(10, floor(log10(max))), round(pow(10, floor(log10(max)))));
-  fprintf(stderr, "graph_autoset_xaxis: xmin=%g,max=%g start_mag=%g, stop_mag=%g range_mag=%g\n", min, max, start_mag, stop_mag, range_mag);
-  #endif
-  return axis;
-}
-
-int graph_autoset_xaxis(Graph *g, GString *title) {
-  graph_set_xaxis(g, autoset_axis(g, title, g->minx, g->maxx));
-  return 0;
-}
-
-int graph_autoset_yaxis(Graph *g, GString *title) {
-  graph_set_yaxis(g, autoset_axis(g, title, g->miny, g->maxy));
-  return 0;
-}
diff --git a/graph.h b/graph.h
deleted file mode 100644 (file)
index 31d441f..0000000
--- a/graph.h
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
-** Graph.h
-** 
-** Made by Johnny Q. Hacker
-** Login   <solarion@johnathan>
-** 
-
-    Copyright (C) 2008 Joseph Pingenot
-
-    This program is free software: you can redistribute it and/or modify
-    it under the terms of the GNU Affero General Public License as published by
-    the Free Software Foundation, either version 3 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU Affero General Public License for more details.
-
-    You should have received a copy of the GNU Affero General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-** Started on  Thu Jul 17 10:51:32 2008 Johnny Q. Hacker
-** Last update Thu Jul 17 10:51:32 2008 Johnny Q. Hacker
-*/
-
-#ifndef        GRAPHCLASS_H_
-#define        GRAPHCLASS_H_
-
-#include <glib-2.0/glib-object.h>
-
-typedef enum {SQUARE, CIRCLE, STAR, PLUS, MINUS, CROSS} graph_symbol;
-
-struct graph_point {
-  double x;
-  double y;
-  GString *label;
-};
-
-/*Bezier line*/
-struct graph_line {
-  /*First point*/
-  double p0_x;
-  double p0_y;
-  /*Control pts*/
-  double p1_x;
-  double p1_y;
-  double p2_x;
-  double p2_y;
-  /*End point*/
-  double p3_x;
-  double p3_y;
-};
-
-struct graph_axis {
-  double major_start;
-  double major_step;
-  int major;
-  int minor;
-  int subminor;
-  GString *title;
-};
-
-typedef struct _Graph {
-  GObject parent_instance;
-  /*Array of n_points sets of x,y coords*/
-  GPtrArray *points;
-  /*This draws all of the lines (generally between points)*/
-  GPtrArray *lines;
-  double maxx;
-  double minx;
-  double maxy;
-  double miny;
-  graph_symbol symbol;
-  struct graph_axis *xaxis;
-  struct graph_axis *yaxis;
-} Graph;
-
-typedef struct _GraphClass {
-  GObjectClass parent_class;
-} GraphClass;
-
-#define GRAPH_TYPE (graph_get_type())
-#define GRAPH(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GRAPH_TYPE, Graph))
-#define GRAPH_CLASS(obj) (G_TYPE_CHECK_CLASS_CAST ((obj), GRAPH, GraphClass))
-#define IS_GRAPH(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GRAPH_TYPE))
-#define IS_GRAPH_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE ((obj), GRAPH_CLASS_TYPE))
-#define GRAPH_GET_CLASS (G_TYPE_INSTANCE_GET_CLASS ((obj), GRAPH, GraphClass))
-
-Graph *graph_new(void);
-int graph_add_point(Graph* graph, double x, double y, const GString *label);
-int graph_add_graph_point(Graph* graph, struct graph_point *pt);
-int graph_add_line(Graph* graph, double p0_x, double p0_y, double p1_x, double p1_y, double p2_x, double p2_y, double p3_x, double p3_y);
-int graph_add_graph_line(Graph* graph, struct graph_line *l);
-void graph_add_linear_connectors(Graph* graph);
-/*Provide x0, x3; x1 and x2 will be set*/
-void graph_bezier_linear_to_cubic(double x0, double x3, double *x1, double *x2);
-/*Provide x0, x1, x2.  x1 and x2 will be set appropriately.*/
-void graph_bezier_quadratic_to_cubic(double x0, double x3, double *x1, double *x2);
-void graph_set_xaxis(Graph *g, struct graph_axis *axis);
-void graph_set_yaxis(Graph *g, struct graph_axis *axis);
-int graph_autoset_xaxis(Graph *g, GString *title);
-int graph_autoset_yaxis(Graph *g, GString *title);
-
-
-
-#endif             /* !GRAPHCLASS_H_ */
diff --git a/graphwidget.c b/graphwidget.c
deleted file mode 100644 (file)
index beba3c9..0000000
+++ /dev/null
@@ -1,252 +0,0 @@
-/*
-** Graph.c
-** 
-** Made by (Johnny Q. Hacker)
-** Login   <solarion@johnathan>
-** 
-
-
-
-    Copyright (C) 2008 Joseph Pingenot
-
-    This program is free software: you can redistribute it and/or modify
-    it under the terms of the GNU Affero General Public License as published by
-    the Free Software Foundation, either version 3 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU Affero General Public License for more details.
-
-    You should have received a copy of the GNU Affero General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-**Many thanks to Davyd Madeley for the excellent Cairo Widget Tutorial
-**  at http://gnomejournal.org/article/34/writing-a-widget-using-cairo-and-gtk28
-
-** Started on  Thu Jul 17 10:51:32 2008 Johnny Q. Hacker
-** Last update Thu Oct  8 17:13:50 2009 Johnny Q. Hacker
-*/
-
-#include <graphwidget.h>
-#include <math.h>
-
-G_DEFINE_TYPE(GraphWidget, graph_widget, GTK_TYPE_DRAWING_AREA);
-
-#define INSET_PERCENT 0.1
-#define TITLE_PERCENT 0.15
-#define DEBUG_DRAW_AXIS
-
-struct drawing_context {
-  GtkWidget *widget;
-  cairo_t *cr;
-  double radius;
-  double xoffset;
-  double yoffset;
-  double xscaling;
-  double yscaling;
-  /*Semi-normalized maxima*/
-  double xmax;
-  double ymax;
-  cairo_matrix_t data_scale;
-  cairo_matrix_t data_xlat;
-};
-
-static void draw_point(gpointer data, gpointer user_data) {
-  struct drawing_context *cxt = user_data;
-  struct graph_point *pt = data;
-  double x = (pt->x + cxt->xoffset)*cxt->xscaling;
-  double y = (pt->y + cxt->yoffset)*cxt->yscaling;
-  cairo_move_to(cxt->cr, x, y);
-  cairo_arc(cxt->cr, x, y, cxt->radius, 0, 2*M_PI);
-  if(pt->label != NULL) {
-    cairo_save(cxt->cr);
-    cairo_scale(cxt->cr, 1, -1);
-    cairo_show_text(cxt->cr, pt->label->str);
-    cairo_restore(cxt->cr);
-  }
-}
-
-static void draw_lines(gpointer data, gpointer user_data) {
-  struct drawing_context *cxt = user_data;
-  struct graph_line *l = data;
-  double p0_x = (l->p0_x + cxt->xoffset)*cxt->xscaling;
-  double p0_y = (l->p0_y + cxt->yoffset)*cxt->yscaling;
-  double p1_x = (l->p1_x + cxt->xoffset)*cxt->xscaling;
-  double p1_y = (l->p1_y + cxt->yoffset)*cxt->yscaling;
-  double p2_x = (l->p2_x + cxt->xoffset)*cxt->xscaling;
-  double p2_y = (l->p2_y + cxt->yoffset)*cxt->yscaling;
-  double p3_x = (l->p3_x + cxt->xoffset)*cxt->xscaling;
-  double p3_y = (l->p3_y + cxt->yoffset)*cxt->yscaling;
-  #ifdef DEBUG_DRAW
-  fprintf(stderr, "draw_lines: p0_x=%g, p0_y=%g, p1_x=%g, p1_y=%g, p2_x=%g, p2_y=%g, p3_x=%g, p3_y=%g\n", p0_x, p0_y, p1_x, p1_y, p2_x, p2_y, p3_x, p3_y);
-  #endif
-  cairo_move_to(cxt->cr, p0_x, p0_y);
-  cairo_curve_to(cxt->cr, p1_x, p1_y, p2_x, p2_y, p3_x, p3_y);
-}
-
-static void draw_axis(struct drawing_context* cxt, struct graph_axis *axis, double scaling, double offset, double max) {
-  #ifdef DEBUG_DRAW_AXIS
-  fprintf(stderr, "draw_axis; major_start=%g, major_step=%g, >major=%d, minor=%d, subminor=%d, label=%s\n", axis->major_start, axis->major_step, axis->major, axis->minor, axis->subminor, axis->title->str);
-  #endif
-  cairo_move_to(cxt->cr, 0, 0);
-  cairo_line_to(cxt->cr, max, 0);
-  register int i, j, k;
-  register double pos, mpos, smpos;
-  for(i=0; i<axis->major; i++) {
-    pos=i*axis->major_step + axis->major_start;
-    cairo_move_to(cxt->cr, (pos + offset)*scaling, 0);
-    cairo_line_to(cxt->cr, (pos + offset)*scaling, 0.05);
-    for(k=0; k<axis->subminor; k++) {
-      smpos=(k+1)*(axis->major_step/(axis->minor+1)/(axis->subminor+1)) + pos;
-      cairo_move_to(cxt->cr, (smpos + offset)*scaling, 0);
-      cairo_line_to(cxt->cr, (smpos + offset)*scaling, 0.0125);
-    }
-    for(j=0; j<axis->minor; j++) {
-      mpos=(j+1)*(axis->major_step/(axis->minor+1)) + pos;
-      cairo_move_to(cxt->cr, (mpos + offset)*scaling, 0);
-      cairo_line_to(cxt->cr, (mpos + offset)*scaling, 0.025);
-      for(k=0; k<axis->subminor; k++) {
-       smpos=(k+1)*(axis->major_step/(axis->minor+1)/(axis->subminor+1)) + mpos;
-       cairo_move_to(cxt->cr, (smpos + offset)*scaling, 0);
-       cairo_line_to(cxt->cr, (smpos + offset)*scaling, 0.0125);
-      }
-    }
-  }
-  pos=i*axis->major_step + axis->major_start;
-  cairo_move_to(cxt->cr, (pos + offset)*scaling, 0);
-  cairo_line_to(cxt->cr, (pos + offset)*scaling, 0.05);
-}
-
-static void draw(GtkWidget *graph, cairo_t *cr) {
-  struct drawing_context cxt;
-  GraphWidget *gw = GRAPH_WIDGET(graph);
-  #ifdef DEBUG_DRAW
-  fprintf(stderr, "draw(%d, %d)\n", (int)graph, (int)cr);
-  fprintf(stderr, "allocation.x=%d, allocation.y=%d, allocation.height=%d, allocation.width=%d\n", graph->allocation.x, graph->allocation.y, graph->allocation.height, graph->allocation.width);
-  #endif
-  double x0=graph->allocation.x;
-  double y0=graph->allocation.y;
-  double height=graph->allocation.height;
-  double width=graph->allocation.width;
-  double minx = gw->graph->minx;
-  double maxx = gw->graph->maxx;
-  double miny = gw->graph->miny;
-  double maxy = gw->graph->maxy;
-  if(gw->graph->xaxis != NULL) {
-    minx = gw->graph->xaxis->major_start;
-    maxx = gw->graph->xaxis->major_start + gw->graph->xaxis->major_step*gw->graph->xaxis->major;
-  }
-  if(gw->graph->yaxis != NULL) {
-    miny = gw->graph->yaxis->major_start;
-    maxy = gw->graph->yaxis->major_start + gw->graph->yaxis->major_step*gw->graph->yaxis->major;
-  }
-  cxt.widget = graph;
-  cxt.cr = cr;
-  cxt.radius = 0.01;
-  /*Set up our semi-normalized scaling.  The shortest direction range
-    [0, 1]; the other range depends upon the relative sizes.*/
-  double effective_height = height;
-  double effective_width = width;
-  double inset, axis_inset;
-  if((INSET_PERCENT > 0) && (INSET_PERCENT < 1.0)) {
-    inset = ((effective_height > effective_width)?effective_width:effective_height)*INSET_PERCENT;
-    effective_height -= inset;
-    effective_width -= inset;
-  }
-  if((gw->graph->xaxis != NULL) && (gw->graph->yaxis != NULL)) {
-    /*key off the smaller size.*/
-    axis_inset = ((effective_height > effective_width)?effective_width:effective_height)*TITLE_PERCENT;
-    effective_height -= axis_inset;
-    effective_width -= axis_inset;
-  }else if(gw->graph->xaxis != NULL) {
-    effective_height -= effective_height*TITLE_PERCENT;
-  }else if(gw->graph->yaxis != NULL) {
-    effective_width -= effective_width*TITLE_PERCENT;
-  }
-  if(effective_width > effective_height) {
-    cxt.xmax = effective_width/effective_height;
-    cxt.ymax = 1.0;
-  }else{
-    cxt.xmax = 1.0;
-    cxt.ymax = effective_height/effective_width;
-  }
-  /*Convert from data space to the semi-normalized space*/
-  double xscaling = (gw->graph->points->len == 1)? cxt.xmax : (cxt.xmax/(maxx-minx));
-  double yscaling = (gw->graph->points->len == 1)? cxt.ymax : (cxt.ymax/(maxy-miny));
-  double xoffset = (gw->graph->points->len == 1)? (-minx/2) : (-minx);
-  double yoffset = (gw->graph->points->len == 1)? (-miny/2) : (-miny);
-  /*Finish up our context information.*/
-  cxt.xscaling = (gw->graph->points->len == 1)? cxt.xmax : (cxt.xmax/(((maxx - minx)==0)?1:(maxx-minx)));
-  cxt.yscaling = (gw->graph->points->len == 1)? cxt.ymax : (cxt.ymax/(((maxy - miny)==0)?1:(maxy-miny)));
-  cxt.xoffset = (gw->graph->points->len == 1)? (-minx/2) : (-minx);
-  cxt.yoffset = (gw->graph->points->len == 1)? (-miny/2) : (-miny);
-  cairo_matrix_translate(&(cxt.data_xlat), xoffset, yoffset);
-  cairo_matrix_scale(&(cxt.data_scale), xscaling, yscaling);
-  #ifdef DEBUG
-  fprintf(stderr, "minx=%g, maxx=%g, miny=%g, maxy=%g, xscaling=%g, yscaling=%g, xoffset=%g, yoffset=%g\n", minx, maxx, miny, maxy, cxt.xscaling, cxt.yscaling, cxt.xoffset, cxt.yoffset);
-  fprintf(stderr, "x0=%g, y0=%g, width=%g, height=%g\n", x0, y0, height, width);
-  fprintf(stderr, "translate=(%g, %g)\n", x0 + ((width>height)?(width-height)/2.0:0), y0+((width > height)?height:width) + ((height>width)?(height-width)/2.0:0));
-  #endif
-  double offset_height =  ((width>=height)?height*INSET_PERCENT:0);;
-  double offset_width = ((height>=width)?width*INSET_PERCENT:0); 
-  double inset_height = height - offset_height;
-  double inset_width = width - offset_width;
-  cairo_save(cr);
-  cairo_translate(cr, x0 + (width - effective_width) - inset/2, y0 + effective_height + inset/2);
-  cairo_scale(cr, effective_width/cxt.xmax, -effective_height/cxt.ymax);
-  cairo_set_line_width(cr, 0.005);
-  cairo_select_font_face (cr, "Georgia",
-                         CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
-  cairo_set_font_size (cr, 0.05);
-  if(gw->graph->lines != NULL) {
-    cairo_set_source_rgba(cr, 0, 0, 0, 0.25);
-    g_ptr_array_foreach(gw->graph->lines, &draw_lines, (gpointer)&cxt);
-    cairo_stroke(cr);
-  }
-  cairo_set_source_rgb(cr, 1, 1, 1);
-  cairo_fill_preserve(cr);
-  cairo_set_source_rgb(cr, 0, 0, 0);
-  g_ptr_array_foreach(gw->graph->points, &draw_point, (gpointer)&cxt);
-  if(gw->graph->xaxis != NULL) 
-    draw_axis(&cxt, gw->graph->xaxis, cxt.xscaling, cxt.xoffset, cxt.xmax);
-  if(gw->graph->yaxis != NULL) {
-    cairo_save(cr);
-    cairo_matrix_t matrix = { .xx=0, .xy = 1, .x0 = 0, .yx = 1, .yy = 0, .y0 = 0 };
-    cairo_transform(cr, &matrix);
-    draw_axis(&cxt, gw->graph->yaxis, cxt.yscaling, cxt.yoffset, cxt.ymax);
-    cairo_restore(cr);
-  }
-  cairo_stroke(cr);
-  cairo_restore(cr);
-}
-
-static gboolean graph_widget_expose(GtkWidget *graph, GdkEventExpose *event) {
-  cairo_t *cr = gdk_cairo_create(graph->window);
-  cairo_rectangle(cr, event->area.x, event->area.y, event->area.width, event->area.height);
-  cairo_clip(cr);
-  draw(graph, cr);
-  cairo_destroy(cr);
-  return FALSE;
-}
-
-static void graph_widget_class_init(GraphWidgetClass *klass) {
-  GtkWidgetClass *widget_class;
-  widget_class = GTK_WIDGET_CLASS(klass);
-  widget_class->expose_event = graph_widget_expose;
-}
-
-static void graph_widget_init(GraphWidget *graph) {
-  /*Get a graph.*/
-  graph->graph = graph_new();
-}
-
-GtkWidget *graph_widget_new(void) {
-  return g_object_new(GRAPH_WIDGET_TYPE, NULL);
-}
-
-Graph* graph_widget_get_graph(GraphWidget* gw) {
-  return gw->graph;
-}
-
diff --git a/graphwidget.h b/graphwidget.h
deleted file mode 100644 (file)
index cb2e390..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
-** Graph.h
-** 
-** Made by Johnny Q. Hacker
-** Login   <solarion@johnathan>
-** 
-
-
-
-    Copyright (C) 2008 Joseph Pingenot
-
-    This program is free software: you can redistribute it and/or modify
-    it under the terms of the GNU Affero General Public License as published by
-    the Free Software Foundation, either version 3 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU Affero General Public License for more details.
-
-    You should have received a copy of the GNU Affero General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-** Started on  Thu Jul 17 10:51:32 2008 Johnny Q. Hacker
-** Last update Thu Oct  8 14:28:34 2009 Johnny Q. Hacker
-*/
-
-#ifndef        GRAPHWIDGET_H_
-#define GRAPHWIDGET_H_
-
-#include <gtk/gtkdrawingarea.h>
-#include <graph.h>
-
-typedef struct _GraphWidget {
-  GtkDrawingArea parent_instance;
-  Graph *graph;
-} GraphWidget;
-
-typedef struct _GraphWidgetClass {
-  GtkDrawingAreaClass parent_class;
-} GraphWidgetClass;
-
-#define GRAPH_WIDGET_TYPE (graph_widget_get_type())
-#define GRAPH_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GRAPH_WIDGET_TYPE, GraphWidget))
-#define GRAPH_WIDGET_CLASS(obj) (G_TYPE_CHECK_CLASS_CAST ((obj), GRAPH_WIDGET, GraphWidgetClass))
-#define IS_GRAPH_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GRAPH_WIDGET_TYPE))
-#define IS_GRAPH_WIDGET_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE ((obj), GRAPH_WIDGET_CLASS_TYPE))
-#define GRAPH_WIDGET_GET_CLASS (G_TYPE_INSTANCE_GET_CLASS ((obj), GRAPH_WIDGET, GraphWidgetClass))
-
-GtkWidget* graph_widget_new(void);
-
-Graph* graph_widget_get_graph(GraphWidget* gw);
-
-#endif             /* !GRAPHWIDGET_H_ */
diff --git a/matdb-dotcode.c b/matdb-dotcode.c
deleted file mode 100644 (file)
index df195fb..0000000
+++ /dev/null
@@ -1,346 +0,0 @@
-/*
- * matdb-dotcode: reads in Craig's Dotcode materials database.
-
-
-
- Copyright (C) 2008 Joseph Pingenot
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-*/
-
-#include <matdb-dotcode.h>
-#define _GNU_SOURCE
-#include <stdio.h>
-#include <strings.h>
-#include <stdlib.h>
-
-#ifdef DEBUG
-#undef DEBUG
-#endif
-#ifdef DEBUG_2
-#undef DEBUG_2
-#endif
-
-/*Functions to be used by the hash.*/
-static void destroy_string(gpointer data) {
-  free((char*)data);
-}
-static void destroy_double(gpointer data){
-  free((double*)data);
-}
-static void destroy_inner_bowhash(gpointer data) {
-  g_hash_table_unref(data);
-}
-
-int insert_into_matdb(struct matdb *mdb, struct matdb_material **mat, struct matdb_bowing **bow) {
-  if((*mat) != NULL) {
-#ifdef DEBUG
-    fprintf(stderr, "inserting material %s\n", (*mat)->name->str);
-#endif
-    g_hash_table_insert(mdb->materials, (gpointer)g_strdup((*mat)->name->str), (gpointer)(*mat));
-    (*mat) = NULL;
-  }
-  if((*bow) != NULL) {
-#ifdef DEBUG
-    fprintf(stderr, "inserting bowing %s:%s\n", (*bow)->from->str, (*bow)->to->str);
-#endif
-    /*Inner table*/
-    GHashTable *it;
-    if((it=g_hash_table_lookup(mdb->bowings, (*bow)->from->str)) == NULL) {
-      if((it = g_hash_table_new_full(&g_str_hash, &g_str_equal, &destroy_string, &destroy_inner_bowhash)) == NULL) {
-       (*bow) = NULL;
-       return 1;
-      }
-      g_hash_table_insert(mdb->bowings, (*bow)->from->str, it);
-      #ifdef DEBUG
-      fprintf(stderr, "Got new hash table (from=%s)\n", (*bow)->from->str);
-      #endif
-    }
-    g_hash_table_insert(it, (gpointer)g_strdup((*bow)->to->str), (gpointer)(*bow));
-    (*bow) = NULL;
-  }
-  return 0;
-}
-
-/*Removes leading and trailing whitespace, comments, and reduces
-  redundant whitespace down to one tab, makes an empty line an empty string.*/
-static void prettify_line(char *line) {
-  register char *look;
-  register char *write;
-  register int in_whitespace;
-  register int leading_whitespace;
-  for(look=write=line, in_whitespace=0, leading_whitespace=1; *look != '\0'; look++) {
-#ifdef DEBUG_2
-    fprintf(stderr, " look=%d(%c) write=%d(%c) in_whitespace=%d leading_whitespace=%d: ", (look-line), *look, (write-line), *write, in_whitespace, leading_whitespace);
-#endif
-    if(*look == '#') {
-#ifdef DEBUG_2
-      fprintf(stderr, "comment\n");
-#endif
-      *write = '\0';
-      break;
-    }
-    switch(*look) {
-    case ' ':
-    case '\n':
-    case '\t':
-#ifdef DEBUG_2
-      fprintf(stderr, "whitespace\n");
-#endif
-      if((!leading_whitespace) && (!in_whitespace)) *write++ = '\t';
-      in_whitespace=1;
-      break;
-    default:
-#ifdef DEBUG_2
-      fprintf(stderr, "default\n");
-#endif
-      *write++ = *look;
-      in_whitespace=leading_whitespace=0;
-    }
-  }
-  *write='\0';
-  for(look=write=line; *look != '\0'; look++) {
-    switch(*look) {
-    case ' ':
-    case '\n':
-    case '\t':
-      if(*(look+1) == '\0') {
-       *look = '\0';
-      }
-    }
-  }
-}
-
-/*Error values:
- *   0: success
- *   1: failure malloc'ing / initializing mdb struct
- *   2: failure opening file.
- *   4: failure reading line.
- *   8: warning reading line: no tab separator (line parsing error)
- *  16: warning reading line: bad section declaration
- *  32: warning reading line: unable to allocate material struct.
- *  64: warning reading line: ignored line (unallocated material struct)
- * 128: warning reading line: unable to allocate bowing struct
- * 256: warning reading line: ignored line (unallocated bowing struct)
- * 512: warning reading file: improper section detected (programming
- *   error)
- *1024: warning reading file: no : separator in bowing materials
- *   description.
- *2048: warning reading file: unable to read numeric value for property.
- */
-struct matdb* read_matdb_dotcode(const GString *name, int* err) {
-#ifdef DEBUG_2
-  fprintf(stderr, "in read_matdb_dotcode(%s, %d)\n", name->str, *err);
-#endif
-  *err=0;
-  struct matdb *mdb = (struct matdb*)malloc(sizeof(struct matdb));
-  if(mdb == NULL) {*err = 1; return NULL;}
-
-  double *value;
-  if((mdb->materials = g_hash_table_new_full(&g_str_hash, &g_str_equal, &destroy_string, &destroy_material_gpointer)) == NULL) {
-    *err = 1;
-    free(mdb);
-    return NULL;
-  }
-  if((mdb->bowings = g_hash_table_new_full(&g_str_hash, &g_str_equal, &destroy_string, &destroy_bowing_gpointer)) == NULL) {
-    *err = 1;
-    g_hash_table_unref(mdb->materials);
-    free(mdb);
-    return NULL;
-  }
-  struct matdb_material *mat = NULL;
-  struct matdb_bowing *bow = NULL;
-  /*Valid sections: 
-   * 0 (no/global section)
-   * 1 (material)
-   * 2 (bow)
-   */
-  int section=0;
-  int n;
-  char *line;
-  FILE *infile = fopen(name->str, "r");
-  if(infile == NULL) {
-    g_hash_table_unref(mdb->materials);
-    g_hash_table_unref(mdb->bowings);
-    free(mdb);
-    *err=2;
-    return NULL;
-#ifdef DEBUG_2
-  }else{
-    fprintf(stderr, "infile=%x\n", (unsigned int)infile);
-#endif
-  }
-  int val;
-  while(!feof(infile)) {
-#ifdef DEBUG
-    fprintf(stderr, "mat=%x(%s), bow=%x(%s:%s)\n", (unsigned int)mat, mat?mat->name->str:"", (unsigned int)bow, bow?bow->from->str:"", bow?bow->to->str:"");
-#endif
-    line=NULL;
-    if((val = getline(&line, &n, infile)) == -1) {
-#ifdef DEBUG_2
-      fprintf(stderr, "getline returned %d\n", val); 
-#endif
-      if(!feof(infile)) *err = 4;
-      //fclose(infile);
-      break;
-    }
-#ifdef DEBUG_2
-    fprintf(stderr, "line=(%s)\n", line);
-#endif
-    prettify_line(line);
-#ifdef DEBUG
-    fprintf(stderr, "%d: prettified line=(%s)\n", section, line);
-#endif
-    if(*line == '\0') {
-      free(line);
-      continue;
-    }
-    char *i = index(line, '\t');
-    if(i == NULL) {
-      *err &= 8;
-    }
-    *i++ = '\0';
-    /*At this point, we have line which stores the first word on the
-      line, and i which stores the second word on the line.
-    */
-    char *to;
-    GHashTable *ht;
-#ifdef DEBUG_2
-    fprintf(stderr, "part_a=(%s) part_b=(%s)\n", line, i);
-#endif
-    /*If we have a material or bowing underway, save it off*/
-    if(strcasecmp(line, "material") == 0) {
-      insert_into_matdb(mdb, &mat, &bow);
-      if((mat = (struct matdb_material*)malloc(sizeof(struct matdb_material))) == NULL) {
-       *err &= 32;
-      }
-      if((mat->name = g_string_new(i)) == NULL) {
-       *err &= 32;
-       free(mat);
-       section=0;
-       continue;
-      }
-      if((mat->properties = g_hash_table_new_full(&g_str_hash, &g_str_equal, &destroy_string, &destroy_double)) == NULL) {
-       *err &= 32;
-       g_string_free(mat->name, TRUE);
-       free(bow);
-       section=0;
-       continue;
-      }
-#ifdef DEBUG_2
-      fprintf(stderr, "new material (%s):\n", i);
-#endif
-      section=1;
-    }else if(strcasecmp(line, "bow") == 0) {
-      insert_into_matdb(mdb, &mat, &bow);
-      if((bow = (struct matdb_bowing*)malloc(sizeof(struct matdb_bowing))) == NULL) {
-       *err &= 128;
-      }
-      if((to = index(i, ':')) == NULL) {
-       *err &= 1024;
-       free(bow);
-       section=0;
-       continue;
-      }
-      *to++ = '\0';
-      /*Same trick as before, but i now stores the from material,
-       and to the to material
-      */
-      if((bow->from = g_string_new(i)) == NULL) {
-       *err &= 128;
-       free(bow);
-       section=0;
-       continue;
-      }
-      if((bow->to = g_string_new(to)) == NULL) {
-       *err &= 128;
-       g_string_free(bow->from, TRUE);
-       free(bow);
-       section=0;
-       continue;
-      }
-      if((bow->properties = g_hash_table_new_full(&g_str_hash, &g_str_equal, &destroy_string, &destroy_double)) == NULL) {
-       *err &= 128;
-       g_string_free(bow->to, TRUE);
-       g_string_free(bow->from, TRUE);
-       free(bow);
-       section=0;
-       continue;
-      }
-#ifdef DEBUG_2
-      fprintf(stderr, "new bowing (%s:%s):\n", i, to);
-#endif
-      section=2;
-    }else{
-      #ifdef DEBUG
-      fprintf(stderr, "\t%d/%s\t", section, line);
-      #endif
-      /*Process a property.*/
-      switch(section) {
-      case 1:
-       #ifdef DEBUG
-       fprintf(stderr, "(1)\t");
-       #endif
-       ht = mat->properties;
-       break;
-      case 2:
-       #ifdef DEBUG
-       fprintf(stderr, "(2)\t");
-       #endif
-       ht = bow->properties;
-       break;
-      default:
-       #ifdef DEBUG
-       fprintf(stderr, "(default)\t");
-       #endif
-       *err &= 16;
-       section = 0;
-      }
-      if(section == 0) {
-       #ifdef DEBUG
-       fprintf(stderr, "section was 0\n");
-       #endif
-       continue;
-      }
-      if((value = (double*)malloc(sizeof(double))) == NULL) {
-       *err &= 2048;
-       #ifdef DEBUG
-       fprintf(stderr, "malloc of value failed\n");
-       #endif
-       continue;
-      }
-      int num;
-      if((num=sscanf(i, " %lg", value)) != 1) {
-       *err &= 2048;
-       free(value);
-       #ifdef DEBUG
-       fprintf(stderr, "bad sscanf to get value (scanned \"%s\", returned %d)\n", i, num);
-       #endif
-       continue;
-      }
-      g_hash_table_insert(ht, g_strdup(line), value);
-#ifdef DEBUG
-      fprintf(stderr, "%g(%s)\n", *value, line);
-#endif
-    }
-    free(line);
-    line=i=to=NULL;
-    value=NULL;
-  }
-  fclose(infile);
-  insert_into_matdb(mdb, &mat, &bow);
-  return mdb;
-}
-
diff --git a/matdb-dotcode.h b/matdb-dotcode.h
deleted file mode 100644 (file)
index ebe4719..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * matdb-dotcode: reads in Craig's Dotcode materials database.
-
-
-
-    Copyright (C) 2008 Joseph Pingenot
-
-    This program is free software: you can redistribute it and/or modify
-    it under the terms of the GNU Affero General Public License as published by
-    the Free Software Foundation, either version 3 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU Affero General Public License for more details.
-
-    You should have received a copy of the GNU Affero General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-*/
-
-#ifndef MATDB_DOTCODE_H_
-#define MATDB_DOTCODE_H_
-
-#include <matdb.h>
-
-struct matdb* read_matdb_dotcode(const GString *name, int *err);
-
-#endif
diff --git a/matdb.c b/matdb.c
deleted file mode 100644 (file)
index 644eb40..0000000
--- a/matdb.c
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * matdb: generic materials database information.
-
-
-
-    Copyright (C) 2008 Joseph Pingenot
-
-    This program is free software: you can redistribute it and/or modify
-    it under the terms of the GNU Affero General Public License as published by
-    the Free Software Foundation, either version 3 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU Affero General Public License for more details.
-
-    You should have received a copy of the GNU Affero General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-*/
-
-#include <matdb.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-static void print_property(gpointer key, gpointer value, gpointer user_data) {
-  fprintf(stderr, "\t\t%s=%g:\n", (char*)key, *(double*)value);
-}
-static void print_inner_bowing(gpointer key, gpointer value, gpointer user_data) {
-  struct matdb_bowing *bowing = (struct matdb_bowing*)value;
-  fprintf(stderr, "\tbowing %s:%s[%s:%s]:\n", bowing->from->str, bowing->to->str, (char*)user_data, (char*)key);
-  g_hash_table_foreach(bowing->properties, &print_property, NULL);
-}
-static void print_material(gpointer key, gpointer value, gpointer user_data) {
-  struct matdb_material *mat = (struct matdb_material*)value;
-  fprintf(stderr, "\tmaterial %s(%s):\n", mat->name->str, (char*)key);
-  g_hash_table_foreach(mat->properties, &print_property, NULL);
-}
-static void print_bowing(gpointer key, gpointer value, gpointer user_data) {
-  GHashTable *ht = value;
-  g_hash_table_foreach(ht, &print_inner_bowing, key);
-}
-
-void print_matdb(const struct matdb *mdb) {
-  fprintf(stderr, "matdb:\n");
-  g_hash_table_foreach(mdb->materials, &print_material, NULL);
-  g_hash_table_foreach(mdb->bowings, &print_bowing, NULL);
-}
-
-void destroy_material_gpointer(gpointer data) {
-  destroy_material((struct matdb_material *)data);
-}
-void destroy_bowing_gpointer(gpointer data) {
-  destroy_bowing((struct matdb_bowing *)data);
-}
-void destroy_material(struct matdb_material *mat) {
-  #ifdef DEBUG
-  fprintf(stderr, "destroy_material\n");
-  #endif
-  g_string_free(mat->name, TRUE);
-  g_hash_table_unref(mat->properties);
-  free(mat);
-}
-void destroy_bowing(struct matdb_bowing *bow) {
-  #ifdef DEBUG
-  fprintf(stderr, "destroy_bowing\n");
-  #endif
-  g_string_free(bow->from, TRUE);
-  g_string_free(bow->to, TRUE);
-  g_hash_table_unref(bow->properties);
-  free(bow);
-}
diff --git a/matdb.h b/matdb.h
deleted file mode 100644 (file)
index 19747f8..0000000
--- a/matdb.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * matdb: generic materials database information.
-
-
-
-    Copyright (C) 2008 Joseph Pingenot
-
-    This program is free software: you can redistribute it and/or modify
-    it under the terms of the GNU Affero General Public License as published by
-    the Free Software Foundation, either version 3 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU Affero General Public License for more details.
-
-    You should have received a copy of the GNU Affero General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-*/
-
-#ifndef MATDB_H_
-#define MATDB_H_
-
-#include <glib-2.0/glib.h>
-
-struct matdb_material {
-  GString *name;
-  GHashTable *properties;
-};
-
-struct matdb_bowing {
-  GString *from;
-  GString *to;
-  GHashTable *properties;
-};
-
-struct matdb {
-  GHashTable *materials;
-  GHashTable *bowings;
-};
-
-void print_matdb(const struct matdb *mdb);
-void destroy_material_gpointer(gpointer data);
-void destroy_bowing_gpointer(gpointer data);
-void destroy_material(struct matdb_material *mat);
-void destroy_bowing(struct matdb_bowing *bow);
-
-#endif
diff --git a/matdb.txt b/matdb.txt
deleted file mode 120000 (symlink)
index e69de29..0000000
diff --git a/scdataviz.c b/scdataviz.c
deleted file mode 100644 (file)
index 812cd26..0000000
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
-** scdataviz.c
-** 
-** Made by (Johnny Q. Hacker)
-** Login   <solarion@johnathan>
-** 
-** Holds the SC graphing widget.
-
-
-
-    Copyright (C) 2008 Joseph Pingenot
-
-    This program is free software: you can redistribute it and/or modify
-    it under the terms of the GNU Affero General Public License as published by
-    the Free Software Foundation, either version 3 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU Affero General Public License for more details.
-
-    You should have received a copy of the GNU Affero General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-** Started on  Thu Jul 17 11:03:27 2008 Johnny Q. Hacker
-** Last update Thu Oct  8 19:13:57 2009 Johnny Q. Hacker
-*/
-
-#include <gtk/gtk.h>
-#include <graphwidget.h>
-#include <matdb-dotcode.h>
-#include <stdlib.h>
-#include <strings.h>
-
-#define DEBUG_SHOW_ONLY_BOWED
-
-struct xy_properties {
-  GString *xprop;
-  GString *yprop;
-  Graph *graph;
-  struct matdb *mdb;
-  struct matdb_material *mat;
-};
-
-static void lookup_xy(GHashTable* propts, GString* xprop, GString* yprop, double **x, double **y) {
-  *x=g_hash_table_lookup(propts, xprop->str);
-  *y=g_hash_table_lookup(propts, yprop->str);
-}
-
-static void put_mat_in_graph(gpointer key, gpointer value, gpointer user_data) {
-  struct xy_properties *propmap = user_data;
-  struct matdb_material *mat = value;
-  if(!strcasecmp(mat->name->str, "vacuum")) return;
-  if(!strcasecmp(mat->name->str, "pvb")) return;
-  double *x, *y;
-  #ifdef DEBUG_ASSIGNMENT
-  fprintf(stderr, "put_mat_in_graph(%s) (x->%s, y->%s): ", (char*)key, propmap->xprop->str, propmap->yprop->str);
-  #endif
-  lookup_xy(mat->properties, propmap->xprop, propmap->yprop, &x, &y);
-  if((x != NULL) && (y != NULL)) {
-    graph_add_point(propmap->graph, *x, *y, mat->name);
-  #ifdef DEBUG_ASSIGNMENT
-    fprintf(stderr, "added (x->%s=%g, y->%s=%g)\n", propmap->xprop->str, *x, propmap->yprop->str, *y);
-  }else{
-    fprintf(stderr, "no such properties (x->%s, y->%s)\n", propmap->xprop->str, propmap->yprop->str);
-  #endif
-  }
-}
-
-static void inner_link_materials(gpointer key, gpointer value, gpointer user_data) {
-  struct xy_properties *propmap = user_data;
-  struct matdb_material *mat = value;
-  if(!strcasecmp(mat->name->str, "vacuum")) return;
-  if(!strcasecmp(mat->name->str, "pvb")) return;
-  if(g_string_equal(mat->name, propmap->mat->name)) return;
-  struct graph_line *l = (struct graph_line *)malloc(sizeof(struct graph_line));
-  if(l == NULL) return;
-  struct matdb_bowing *bow = NULL;
-  GHashTable *subtable;
-  double *p0_x, *p0_y, *p1_x, *p1_y, *p3_x, *p3_y;
-  lookup_xy(propmap->mat->properties, propmap->xprop, propmap->yprop, &p0_x, &p0_y);
-  lookup_xy(mat->properties, propmap->xprop, propmap->yprop, &p3_x, &p3_y);
-#ifdef DEBUG_ASSIGNMENT
-  fprintf(stderr, "%s:%s x=%s y=%s p0(%g,%g) p3(%g,%g)\n", propmap->mat->name->str, mat->name->str, propmap->xprop->str, propmap->yprop->str, (p0_x)?*p0_x:0, (p0_y)?*p0_y:0, (p3_x)?*p3_x:0, (p3_y)?*p3_y:0);
-#endif
-  if((p0_x != NULL) && (p0_y != NULL) && (p3_x != NULL) && (p3_y != NULL)) {
-    l->p0_x = *p0_x;
-    l->p0_y = *p0_y;
-    l->p3_x = *p3_x;
-    l->p3_y = *p3_y;
-    if((subtable = g_hash_table_lookup(propmap->mdb->bowings, propmap->mat->name->str)) == NULL) {
-      /*Try the other way 'round*/
-      if((subtable = g_hash_table_lookup(propmap->mdb->bowings, mat->name->str) )
-         != NULL) {
-       bow = g_hash_table_lookup(subtable, propmap->mat->name->str);
-      }
-    }else{
-      bow = g_hash_table_lookup(subtable, mat->name->str);
-    }
-    if(bow != NULL) {
-      if((p1_x = g_hash_table_lookup(bow->properties, propmap->xprop->str)) != NULL) {
-       l->p1_x = *p1_x/2.0;
-       graph_bezier_quadratic_to_cubic(l->p0_x, l->p3_x, &(l->p1_x), &(l->p2_x));
-      }else{
-       graph_bezier_linear_to_cubic(l->p0_x, l->p3_x, &(l->p1_x), &(l->p2_x));
-      }
-      if((p1_y = g_hash_table_lookup(bow->properties, propmap->yprop->str)) != NULL) {
-       l->p1_y = *p1_y/2.0;
-       graph_bezier_quadratic_to_cubic(l->p0_y, l->p3_y, &(l->p1_y), &(l->p2_y));
-      }else{
-       graph_bezier_linear_to_cubic(l->p0_y, l->p3_y, &(l->p1_y), &(l->p2_y));
-      }
-    }else{
-      #ifdef DEBUG_SHOW_ONLY_BOWED
-      free(l);
-      return;
-      #endif
-      graph_bezier_linear_to_cubic(l->p0_x, l->p3_x, &(l->p1_x), &(l->p2_x));
-      graph_bezier_linear_to_cubic(l->p0_y, l->p3_y, &(l->p1_y), &(l->p2_y));
-    }
-    #ifdef DEBUG_ASSIGNMENT
-    fprintf(stderr, "%s:%s p0(%g,%g) p1(%g,%g) p2(%g,%g), p3(%g,%g)\n", propmap->mat->name->str, mat->name->str, l->p0_x, l->p0_y, l->p1_x, l->p1_y, l->p2_x, l->p2_y, l->p3_x, l->p3_y);
-    #endif
-    graph_add_graph_line(propmap->graph, l);
-  }else{
-    free(l);
-  }
-}
-
-static void link_materials(gpointer key, gpointer value, gpointer user_data) {
-  struct xy_properties *propmap = user_data;
-  struct matdb_material *mat = value;
-  if(!strcasecmp(mat->name->str, "vacuum")) return;
-  if(!strcasecmp(mat->name->str, "pvb")) return;
-  propmap->mat = mat;
-  g_hash_table_foreach(propmap->mdb->materials, &inner_link_materials, propmap);
-}
-
-int main(int   argc, char *argv[]) 
-{
-    GtkWidget *window;
-    GtkWidget *graph;
-    GString *file = g_string_new("matdb.txt");
-    int err=0;
-    struct matdb *mdb = read_matdb_dotcode(file, &err);
-    //fprintf(stderr, "read_matdb_dotcode(%s, %d)=%x", file->str, err,
-    //(int)mdb);
-    //fprintf(stderr, "err=%d\n", err);
-    //print_matdb(mdb);
-    
-    gtk_init (&argc, &argv);
-    
-    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
-    graph = graph_widget_new();
-
-    struct xy_properties propmap;
-    propmap.xprop = g_string_new("a_lc");
-    propmap.yprop = g_string_new("E_g_Gamma");
-    propmap.graph = graph_widget_get_graph(GRAPH_WIDGET(graph));
-    propmap.mdb = mdb;
-    g_hash_table_foreach(mdb->materials, &put_mat_in_graph, &propmap);
-    //graph_add_linear_connectors(propmap.graph);
-    g_hash_table_foreach(mdb->materials, &link_materials, &propmap);
-    graph_autoset_xaxis(propmap.graph, propmap.xprop);
-    graph_autoset_yaxis(propmap.graph, propmap.yprop);
-
-    //Connect signals
-    g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);
-
-    gtk_container_add(GTK_CONTAINER(window), graph);
-    /*
-    graph_add_point(graph_widget_get_graph(graph), 5, 3);
-    graph_add_point(graph_widget_get_graph(graph), 8, 12);
-    graph_add_point(graph_widget_get_graph(graph), 11, 48);
-    */
-    
-    gtk_widget_show_all  (window);
-    
-    gtk_main ();
-    
-    return 0;
-}
diff --git a/src/graph.c b/src/graph.c
new file mode 100644 (file)
index 0000000..cd2b056
--- /dev/null
@@ -0,0 +1,242 @@
+/*
+** Graph.c
+** 
+** Made by (Johnny Q. Hacker)
+** Login   <solarion@johnathan>
+** 
+
+
+Copyright (C) 2008 Joseph Pingenot
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU Affero General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Affero General Public License for more details.
+
+You should have received a copy of the GNU Affero General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+**Many thanks to Davyd Madeley for the excellent Cairo  Tutorial
+**  at http://gnomejournal.org/article/34/writing-a--using-cairo-and-gtk28
+
+** Started on  Thu Jul 17 10:51:32 2008 Johnny Q. Hacker
+** Last update Sun May 12 01:17:25 2002 Speed Blue
+*/
+
+#include <graph.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+
+#ifdef DEBUG
+#define DEBUG_AUTOAXIS
+#endif
+
+G_DEFINE_TYPE(Graph, graph, G_TYPE_OBJECT);
+
+static void graph_class_init(GraphClass *klass) {
+  GObjectClass *gobject_klass;
+  gobject_klass = G_OBJECT_CLASS(klass);
+}
+
+static void graph_init(Graph *graph) {
+  graph->symbol = CIRCLE;
+  graph->points = g_ptr_array_new();
+  graph->lines = NULL;
+  graph->xaxis = graph->yaxis = NULL;
+}
+
+Graph *graph_new(void) {
+  return g_object_new(GRAPH_TYPE, NULL);
+}
+
+/*1 means you're stupid and passed NULL*/
+int graph_add_graph_point(Graph* graph, struct graph_point *pt) {
+  if(pt == NULL) return 1;
+  g_ptr_array_add(graph->points, pt);
+  if((graph->points->len == 1) && ((graph->lines == NULL) || (graph->lines->len == 0))) {
+    graph->maxx = graph->minx = pt->x;
+    graph->maxy = graph->miny = pt->y;
+  }else{
+    if(pt->x > graph->maxx) graph->maxx = pt->x;
+    if(pt->x < graph->minx) graph->minx = pt->x;
+    if(pt->y > graph->maxy) graph->maxy = pt->y;
+    if(pt->y < graph->miny) graph->miny = pt->y;
+  }
+  return 0;
+}
+
+/*
+ *
+ *1 means failed to allocate point
+ *NOTE: label is duplicated if not NULL (using g_strdup)
+ */
+int graph_add_point(Graph* graph, double x, double y, const GString *label) {
+  struct graph_point *pt = (struct graph_point*)malloc(sizeof(struct graph_point));
+  if(pt == NULL) return 1;
+  pt->x = x;
+  pt->y = y;
+  pt->label = (label)?g_string_new(label->str):NULL;
+  graph_add_graph_point(graph, pt);
+  return 0;
+}
+
+int graph_add_graph_line(Graph* graph, struct graph_line *l) {
+  if(l == NULL) return 1;
+  if(graph->lines == NULL) {
+    if((graph->lines = g_ptr_array_new()) == NULL) return 1;
+  }
+  g_ptr_array_add(graph->lines, l);
+  if((graph->points->len == 0) && 
+     (graph->lines->len == 1)) {
+    graph->maxx = graph->minx = l->p0_x;
+    graph->maxy = graph->miny = l->p0_y;
+  }else{
+    if(l->p0_x > graph->maxx) graph->maxx = l->p0_x;
+    if(l->p0_x < graph->minx) graph->minx = l->p0_x;
+    if(l->p0_y > graph->maxy) graph->maxy = l->p0_y;
+    if(l->p0_y < graph->miny) graph->miny = l->p0_y;
+  }
+  if(l->p3_x > graph->maxx) graph->maxx = l->p3_x;
+  if(l->p3_x < graph->minx) graph->minx = l->p3_x;
+  if(l->p3_y > graph->maxy) graph->maxy = l->p3_y;
+  if(l->p3_y < graph->miny) graph->miny = l->p3_y;
+  return 0;
+}
+
+
+int graph_add_line(Graph* graph, double p0_x, double p0_y, double p1_x, double p1_y, double p2_x, double p2_y, double p3_x, double p3_y) {
+  #ifdef DEBUG
+  fprintf(stderr, "graph_add_line(%d, p0_x=%g, p0_y=%g, p1_x=%g, p1_y=%g, p2_x=%g, p2_y=%g, p3_x=%g, p3_y=%g\n", (unsigned int) graph, p0_x, p0_y, p1_x, p1_y, p2_x, p2_y, p3_x, p3_y);
+  #endif
+  struct graph_line *l;
+  if((l=(struct graph_line*)malloc(sizeof(struct graph_line))) == NULL) return 2;
+  l->p0_x=p0_x;
+  l->p0_y=p0_y;
+  l->p1_x=p1_x;
+  l->p1_y=p1_y;
+  l->p2_x=p2_x;
+  l->p2_y=p2_y;
+  l->p3_x=p3_x;
+  l->p3_y=p3_y;
+  return graph_add_graph_line(graph, l);
+}
+    
+struct cxt {
+  Graph *graph;
+  struct graph_point *p0;
+};
+    
+static void linear_interpolate(gpointer data, gpointer user_data) {
+  struct cxt *cxt = user_data;
+  struct graph_point *p3 = data;
+  if(cxt->p0 != NULL) {
+    double p1_x = (p3->x + 2*cxt->p0->x)/3.0;
+    double p1_y = (p3->y + 2*cxt->p0->y)/3.0;
+    double p2_x = (2*p3->x + cxt->p0->x)/3.0;
+    double p2_y = (2*p3->y + cxt->p0->y)/3.0;
+    graph_add_line(cxt->graph, cxt->p0->x, cxt->p0->y, p1_x, p1_y, p2_x, p2_y, p3->x, p3->y);
+  }
+  cxt->p0 = p3;
+}
+    
+void graph_add_linear_connectors(Graph* graph) {
+  struct cxt cxt;
+  cxt.graph = graph;
+  cxt.p0 = NULL;
+  g_ptr_array_foreach(graph->points, &linear_interpolate, &cxt);
+}
+
+void graph_bezier_linear_to_cubic(double x0, double x3, double *x1, double *x2) {
+  *x1 = (x3 + 2.0*x0)/3.0;
+  *x2 = (2.0*x3 + x0)/3.0;
+}
+
+void graph_bezier_linear_to_quadratic(double x0, double x3, double *x1) {
+  *x1 = (x3 + x0)/2.0;
+}
+
+void graph_bezier_quadratic_to_cubic(double x0, double x3, double *x1, double *x2) {
+  *x2 = (x3-2.0*(*x1))/3.0;
+  *x1 = (x0-2.0*(*x1))/3.0;
+}
+
+void graph_set_xaxis(Graph *g, struct graph_axis *axis) {
+  if(g->xaxis != NULL) {
+    free(g->xaxis);
+  }
+  g->xaxis=axis;
+}
+void graph_set_yaxis(Graph *g, struct graph_axis *axis) {
+  if(g->yaxis != NULL) {
+    free(g->yaxis);
+  }
+  g->yaxis=axis;
+}
+
+struct graph_axis* autoset_axis(Graph* g, GString* title, double min, double max) {
+  struct graph_axis *axis;
+  double range_mag;
+  double start_mag;
+  double stop_mag;
+  int i, j;
+  if(g->points->len == 0) {
+    return NULL;
+  }
+  if((axis=(struct graph_axis *)malloc(sizeof(struct graph_axis))) == NULL) {
+    return NULL;
+  }
+  if(g->points->len == 1) {
+    axis->major=1;
+    axis->minor=0;
+    axis->subminor=0;
+    axis->major_start=min;
+    axis->major_step=max;
+  }else{
+    range_mag = logb(max - min);
+    if(min == 0) 
+      start_mag = 0;
+    else
+      start_mag = copysign(pow(10, floor(log10(min))), min);
+    if(max == 0) 
+      stop_mag = 0;
+    else
+      stop_mag = copysign(pow(10, ceil(log10(max))), max);
+    for(i=1; i<9; i++) {
+      if(i*start_mag > min) break;
+    }
+    i--;
+    for(j=10; j>1; j--) {
+      if(j*(stop_mag/10) < max) break;
+    }
+    j++;
+    axis->major=10;
+    axis->minor=1;
+    axis->subminor=4;
+    axis->major_start=i*start_mag;
+    axis->major_step=(j*(stop_mag/10) - axis->major_start)/(axis->major);
+  }
+  axis->title=g_string_new(title->str);
+  #ifdef DEBUG_AUTOAXIS
+  fprintf(stderr, "graph_autoset_xaxis: xmin=%g, log10(xmin)=%g, floor=%g, pow=%g round=%g\n", min, log10(min), floor(log10(min)), pow(10, floor(log10(min))), round(pow(10, floor(log10(min)))));
+  fprintf(stderr, "graph_autoset_xaxis: xmax=%g, log10(xmax)=%g, floor=%g, pow=%g round=%g\n", max, log10(max), floor(log10(max)), pow(10, floor(log10(max))), round(pow(10, floor(log10(max)))));
+  fprintf(stderr, "graph_autoset_xaxis: xmin=%g,max=%g start_mag=%g, stop_mag=%g range_mag=%g\n", min, max, start_mag, stop_mag, range_mag);
+  #endif
+  return axis;
+}
+
+int graph_autoset_xaxis(Graph *g, GString *title) {
+  graph_set_xaxis(g, autoset_axis(g, title, g->minx, g->maxx));
+  return 0;
+}
+
+int graph_autoset_yaxis(Graph *g, GString *title) {
+  graph_set_yaxis(g, autoset_axis(g, title, g->miny, g->maxy));
+  return 0;
+}
diff --git a/src/graph.h b/src/graph.h
new file mode 100644 (file)
index 0000000..31d441f
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+** Graph.h
+** 
+** Made by Johnny Q. Hacker
+** Login   <solarion@johnathan>
+** 
+
+    Copyright (C) 2008 Joseph Pingenot
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Affero General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Affero General Public License for more details.
+
+    You should have received a copy of the GNU Affero General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+** Started on  Thu Jul 17 10:51:32 2008 Johnny Q. Hacker
+** Last update Thu Jul 17 10:51:32 2008 Johnny Q. Hacker
+*/
+
+#ifndef        GRAPHCLASS_H_
+#define        GRAPHCLASS_H_
+
+#include <glib-2.0/glib-object.h>
+
+typedef enum {SQUARE, CIRCLE, STAR, PLUS, MINUS, CROSS} graph_symbol;
+
+struct graph_point {
+  double x;
+  double y;
+  GString *label;
+};
+
+/*Bezier line*/
+struct graph_line {
+  /*First point*/
+  double p0_x;
+  double p0_y;
+  /*Control pts*/
+  double p1_x;
+  double p1_y;
+  double p2_x;
+  double p2_y;
+  /*End point*/
+  double p3_x;
+  double p3_y;
+};
+
+struct graph_axis {
+  double major_start;
+  double major_step;
+  int major;
+  int minor;
+  int subminor;
+  GString *title;
+};
+
+typedef struct _Graph {
+  GObject parent_instance;
+  /*Array of n_points sets of x,y coords*/
+  GPtrArray *points;
+  /*This draws all of the lines (generally between points)*/
+  GPtrArray *lines;
+  double maxx;
+  double minx;
+  double maxy;
+  double miny;
+  graph_symbol symbol;
+  struct graph_axis *xaxis;
+  struct graph_axis *yaxis;
+} Graph;
+
+typedef struct _GraphClass {
+  GObjectClass parent_class;
+} GraphClass;
+
+#define GRAPH_TYPE (graph_get_type())
+#define GRAPH(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GRAPH_TYPE, Graph))
+#define GRAPH_CLASS(obj) (G_TYPE_CHECK_CLASS_CAST ((obj), GRAPH, GraphClass))
+#define IS_GRAPH(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GRAPH_TYPE))
+#define IS_GRAPH_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE ((obj), GRAPH_CLASS_TYPE))
+#define GRAPH_GET_CLASS (G_TYPE_INSTANCE_GET_CLASS ((obj), GRAPH, GraphClass))
+
+Graph *graph_new(void);
+int graph_add_point(Graph* graph, double x, double y, const GString *label);
+int graph_add_graph_point(Graph* graph, struct graph_point *pt);
+int graph_add_line(Graph* graph, double p0_x, double p0_y, double p1_x, double p1_y, double p2_x, double p2_y, double p3_x, double p3_y);
+int graph_add_graph_line(Graph* graph, struct graph_line *l);
+void graph_add_linear_connectors(Graph* graph);
+/*Provide x0, x3; x1 and x2 will be set*/
+void graph_bezier_linear_to_cubic(double x0, double x3, double *x1, double *x2);
+/*Provide x0, x1, x2.  x1 and x2 will be set appropriately.*/
+void graph_bezier_quadratic_to_cubic(double x0, double x3, double *x1, double *x2);
+void graph_set_xaxis(Graph *g, struct graph_axis *axis);
+void graph_set_yaxis(Graph *g, struct graph_axis *axis);
+int graph_autoset_xaxis(Graph *g, GString *title);
+int graph_autoset_yaxis(Graph *g, GString *title);
+
+
+
+#endif             /* !GRAPHCLASS_H_ */
diff --git a/src/graphwidget.c b/src/graphwidget.c
new file mode 100644 (file)
index 0000000..beba3c9
--- /dev/null
@@ -0,0 +1,252 @@
+/*
+** Graph.c
+** 
+** Made by (Johnny Q. Hacker)
+** Login   <solarion@johnathan>
+** 
+
+
+
+    Copyright (C) 2008 Joseph Pingenot
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Affero General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Affero General Public License for more details.
+
+    You should have received a copy of the GNU Affero General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+**Many thanks to Davyd Madeley for the excellent Cairo Widget Tutorial
+**  at http://gnomejournal.org/article/34/writing-a-widget-using-cairo-and-gtk28
+
+** Started on  Thu Jul 17 10:51:32 2008 Johnny Q. Hacker
+** Last update Thu Oct  8 17:13:50 2009 Johnny Q. Hacker
+*/
+
+#include <graphwidget.h>
+#include <math.h>
+
+G_DEFINE_TYPE(GraphWidget, graph_widget, GTK_TYPE_DRAWING_AREA);
+
+#define INSET_PERCENT 0.1
+#define TITLE_PERCENT 0.15
+#define DEBUG_DRAW_AXIS
+
+struct drawing_context {
+  GtkWidget *widget;
+  cairo_t *cr;
+  double radius;
+  double xoffset;
+  double yoffset;
+  double xscaling;
+  double yscaling;
+  /*Semi-normalized maxima*/
+  double xmax;
+  double ymax;
+  cairo_matrix_t data_scale;
+  cairo_matrix_t data_xlat;
+};
+
+static void draw_point(gpointer data, gpointer user_data) {
+  struct drawing_context *cxt = user_data;
+  struct graph_point *pt = data;
+  double x = (pt->x + cxt->xoffset)*cxt->xscaling;
+  double y = (pt->y + cxt->yoffset)*cxt->yscaling;
+  cairo_move_to(cxt->cr, x, y);
+  cairo_arc(cxt->cr, x, y, cxt->radius, 0, 2*M_PI);
+  if(pt->label != NULL) {
+    cairo_save(cxt->cr);
+    cairo_scale(cxt->cr, 1, -1);
+    cairo_show_text(cxt->cr, pt->label->str);
+    cairo_restore(cxt->cr);
+  }
+}
+
+static void draw_lines(gpointer data, gpointer user_data) {
+  struct drawing_context *cxt = user_data;
+  struct graph_line *l = data;
+  double p0_x = (l->p0_x + cxt->xoffset)*cxt->xscaling;
+  double p0_y = (l->p0_y + cxt->yoffset)*cxt->yscaling;
+  double p1_x = (l->p1_x + cxt->xoffset)*cxt->xscaling;
+  double p1_y = (l->p1_y + cxt->yoffset)*cxt->yscaling;
+  double p2_x = (l->p2_x + cxt->xoffset)*cxt->xscaling;
+  double p2_y = (l->p2_y + cxt->yoffset)*cxt->yscaling;
+  double p3_x = (l->p3_x + cxt->xoffset)*cxt->xscaling;
+  double p3_y = (l->p3_y + cxt->yoffset)*cxt->yscaling;
+  #ifdef DEBUG_DRAW
+  fprintf(stderr, "draw_lines: p0_x=%g, p0_y=%g, p1_x=%g, p1_y=%g, p2_x=%g, p2_y=%g, p3_x=%g, p3_y=%g\n", p0_x, p0_y, p1_x, p1_y, p2_x, p2_y, p3_x, p3_y);
+  #endif
+  cairo_move_to(cxt->cr, p0_x, p0_y);
+  cairo_curve_to(cxt->cr, p1_x, p1_y, p2_x, p2_y, p3_x, p3_y);
+}
+
+static void draw_axis(struct drawing_context* cxt, struct graph_axis *axis, double scaling, double offset, double max) {
+  #ifdef DEBUG_DRAW_AXIS
+  fprintf(stderr, "draw_axis; major_start=%g, major_step=%g, >major=%d, minor=%d, subminor=%d, label=%s\n", axis->major_start, axis->major_step, axis->major, axis->minor, axis->subminor, axis->title->str);
+  #endif
+  cairo_move_to(cxt->cr, 0, 0);
+  cairo_line_to(cxt->cr, max, 0);
+  register int i, j, k;
+  register double pos, mpos, smpos;
+  for(i=0; i<axis->major; i++) {
+    pos=i*axis->major_step + axis->major_start;
+    cairo_move_to(cxt->cr, (pos + offset)*scaling, 0);
+    cairo_line_to(cxt->cr, (pos + offset)*scaling, 0.05);
+    for(k=0; k<axis->subminor; k++) {
+      smpos=(k+1)*(axis->major_step/(axis->minor+1)/(axis->subminor+1)) + pos;
+      cairo_move_to(cxt->cr, (smpos + offset)*scaling, 0);
+      cairo_line_to(cxt->cr, (smpos + offset)*scaling, 0.0125);
+    }
+    for(j=0; j<axis->minor; j++) {
+      mpos=(j+1)*(axis->major_step/(axis->minor+1)) + pos;
+      cairo_move_to(cxt->cr, (mpos + offset)*scaling, 0);
+      cairo_line_to(cxt->cr, (mpos + offset)*scaling, 0.025);
+      for(k=0; k<axis->subminor; k++) {
+       smpos=(k+1)*(axis->major_step/(axis->minor+1)/(axis->subminor+1)) + mpos;
+       cairo_move_to(cxt->cr, (smpos + offset)*scaling, 0);
+       cairo_line_to(cxt->cr, (smpos + offset)*scaling, 0.0125);
+      }
+    }
+  }
+  pos=i*axis->major_step + axis->major_start;
+  cairo_move_to(cxt->cr, (pos + offset)*scaling, 0);
+  cairo_line_to(cxt->cr, (pos + offset)*scaling, 0.05);
+}
+
+static void draw(GtkWidget *graph, cairo_t *cr) {
+  struct drawing_context cxt;
+  GraphWidget *gw = GRAPH_WIDGET(graph);
+  #ifdef DEBUG_DRAW
+  fprintf(stderr, "draw(%d, %d)\n", (int)graph, (int)cr);
+  fprintf(stderr, "allocation.x=%d, allocation.y=%d, allocation.height=%d, allocation.width=%d\n", graph->allocation.x, graph->allocation.y, graph->allocation.height, graph->allocation.width);
+  #endif
+  double x0=graph->allocation.x;
+  double y0=graph->allocation.y;
+  double height=graph->allocation.height;
+  double width=graph->allocation.width;
+  double minx = gw->graph->minx;
+  double maxx = gw->graph->maxx;
+  double miny = gw->graph->miny;
+  double maxy = gw->graph->maxy;
+  if(gw->graph->xaxis != NULL) {
+    minx = gw->graph->xaxis->major_start;
+    maxx = gw->graph->xaxis->major_start + gw->graph->xaxis->major_step*gw->graph->xaxis->major;
+  }
+  if(gw->graph->yaxis != NULL) {
+    miny = gw->graph->yaxis->major_start;
+    maxy = gw->graph->yaxis->major_start + gw->graph->yaxis->major_step*gw->graph->yaxis->major;
+  }
+  cxt.widget = graph;
+  cxt.cr = cr;
+  cxt.radius = 0.01;
+  /*Set up our semi-normalized scaling.  The shortest direction range
+    [0, 1]; the other range depends upon the relative sizes.*/
+  double effective_height = height;
+  double effective_width = width;
+  double inset, axis_inset;
+  if((INSET_PERCENT > 0) && (INSET_PERCENT < 1.0)) {
+    inset = ((effective_height > effective_width)?effective_width:effective_height)*INSET_PERCENT;
+    effective_height -= inset;
+    effective_width -= inset;
+  }
+  if((gw->graph->xaxis != NULL) && (gw->graph->yaxis != NULL)) {
+    /*key off the smaller size.*/
+    axis_inset = ((effective_height > effective_width)?effective_width:effective_height)*TITLE_PERCENT;
+    effective_height -= axis_inset;
+    effective_width -= axis_inset;
+  }else if(gw->graph->xaxis != NULL) {
+    effective_height -= effective_height*TITLE_PERCENT;
+  }else if(gw->graph->yaxis != NULL) {
+    effective_width -= effective_width*TITLE_PERCENT;
+  }
+  if(effective_width > effective_height) {
+    cxt.xmax = effective_width/effective_height;
+    cxt.ymax = 1.0;
+  }else{
+    cxt.xmax = 1.0;
+    cxt.ymax = effective_height/effective_width;
+  }
+  /*Convert from data space to the semi-normalized space*/
+  double xscaling = (gw->graph->points->len == 1)? cxt.xmax : (cxt.xmax/(maxx-minx));
+  double yscaling = (gw->graph->points->len == 1)? cxt.ymax : (cxt.ymax/(maxy-miny));
+  double xoffset = (gw->graph->points->len == 1)? (-minx/2) : (-minx);
+  double yoffset = (gw->graph->points->len == 1)? (-miny/2) : (-miny);
+  /*Finish up our context information.*/
+  cxt.xscaling = (gw->graph->points->len == 1)? cxt.xmax : (cxt.xmax/(((maxx - minx)==0)?1:(maxx-minx)));
+  cxt.yscaling = (gw->graph->points->len == 1)? cxt.ymax : (cxt.ymax/(((maxy - miny)==0)?1:(maxy-miny)));
+  cxt.xoffset = (gw->graph->points->len == 1)? (-minx/2) : (-minx);
+  cxt.yoffset = (gw->graph->points->len == 1)? (-miny/2) : (-miny);
+  cairo_matrix_translate(&(cxt.data_xlat), xoffset, yoffset);
+  cairo_matrix_scale(&(cxt.data_scale), xscaling, yscaling);
+  #ifdef DEBUG
+  fprintf(stderr, "minx=%g, maxx=%g, miny=%g, maxy=%g, xscaling=%g, yscaling=%g, xoffset=%g, yoffset=%g\n", minx, maxx, miny, maxy, cxt.xscaling, cxt.yscaling, cxt.xoffset, cxt.yoffset);
+  fprintf(stderr, "x0=%g, y0=%g, width=%g, height=%g\n", x0, y0, height, width);
+  fprintf(stderr, "translate=(%g, %g)\n", x0 + ((width>height)?(width-height)/2.0:0), y0+((width > height)?height:width) + ((height>width)?(height-width)/2.0:0));
+  #endif
+  double offset_height =  ((width>=height)?height*INSET_PERCENT:0);;
+  double offset_width = ((height>=width)?width*INSET_PERCENT:0); 
+  double inset_height = height - offset_height;
+  double inset_width = width - offset_width;
+  cairo_save(cr);
+  cairo_translate(cr, x0 + (width - effective_width) - inset/2, y0 + effective_height + inset/2);
+  cairo_scale(cr, effective_width/cxt.xmax, -effective_height/cxt.ymax);
+  cairo_set_line_width(cr, 0.005);
+  cairo_select_font_face (cr, "Georgia",
+                         CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
+  cairo_set_font_size (cr, 0.05);
+  if(gw->graph->lines != NULL) {
+    cairo_set_source_rgba(cr, 0, 0, 0, 0.25);
+    g_ptr_array_foreach(gw->graph->lines, &draw_lines, (gpointer)&cxt);
+    cairo_stroke(cr);
+  }
+  cairo_set_source_rgb(cr, 1, 1, 1);
+  cairo_fill_preserve(cr);
+  cairo_set_source_rgb(cr, 0, 0, 0);
+  g_ptr_array_foreach(gw->graph->points, &draw_point, (gpointer)&cxt);
+  if(gw->graph->xaxis != NULL) 
+    draw_axis(&cxt, gw->graph->xaxis, cxt.xscaling, cxt.xoffset, cxt.xmax);
+  if(gw->graph->yaxis != NULL) {
+    cairo_save(cr);
+    cairo_matrix_t matrix = { .xx=0, .xy = 1, .x0 = 0, .yx = 1, .yy = 0, .y0 = 0 };
+    cairo_transform(cr, &matrix);
+    draw_axis(&cxt, gw->graph->yaxis, cxt.yscaling, cxt.yoffset, cxt.ymax);
+    cairo_restore(cr);
+  }
+  cairo_stroke(cr);
+  cairo_restore(cr);
+}
+
+static gboolean graph_widget_expose(GtkWidget *graph, GdkEventExpose *event) {
+  cairo_t *cr = gdk_cairo_create(graph->window);
+  cairo_rectangle(cr, event->area.x, event->area.y, event->area.width, event->area.height);
+  cairo_clip(cr);
+  draw(graph, cr);
+  cairo_destroy(cr);
+  return FALSE;
+}
+
+static void graph_widget_class_init(GraphWidgetClass *klass) {
+  GtkWidgetClass *widget_class;
+  widget_class = GTK_WIDGET_CLASS(klass);
+  widget_class->expose_event = graph_widget_expose;
+}
+
+static void graph_widget_init(GraphWidget *graph) {
+  /*Get a graph.*/
+  graph->graph = graph_new();
+}
+
+GtkWidget *graph_widget_new(void) {
+  return g_object_new(GRAPH_WIDGET_TYPE, NULL);
+}
+
+Graph* graph_widget_get_graph(GraphWidget* gw) {
+  return gw->graph;
+}
+
diff --git a/src/graphwidget.h b/src/graphwidget.h
new file mode 100644 (file)
index 0000000..cb2e390
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+** Graph.h
+** 
+** Made by Johnny Q. Hacker
+** Login   <solarion@johnathan>
+** 
+
+
+
+    Copyright (C) 2008 Joseph Pingenot
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Affero General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Affero General Public License for more details.
+
+    You should have received a copy of the GNU Affero General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+** Started on  Thu Jul 17 10:51:32 2008 Johnny Q. Hacker
+** Last update Thu Oct  8 14:28:34 2009 Johnny Q. Hacker
+*/
+
+#ifndef        GRAPHWIDGET_H_
+#define GRAPHWIDGET_H_
+
+#include <gtk/gtkdrawingarea.h>
+#include <graph.h>
+
+typedef struct _GraphWidget {
+  GtkDrawingArea parent_instance;
+  Graph *graph;
+} GraphWidget;
+
+typedef struct _GraphWidgetClass {
+  GtkDrawingAreaClass parent_class;
+} GraphWidgetClass;
+
+#define GRAPH_WIDGET_TYPE (graph_widget_get_type())
+#define GRAPH_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GRAPH_WIDGET_TYPE, GraphWidget))
+#define GRAPH_WIDGET_CLASS(obj) (G_TYPE_CHECK_CLASS_CAST ((obj), GRAPH_WIDGET, GraphWidgetClass))
+#define IS_GRAPH_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GRAPH_WIDGET_TYPE))
+#define IS_GRAPH_WIDGET_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE ((obj), GRAPH_WIDGET_CLASS_TYPE))
+#define GRAPH_WIDGET_GET_CLASS (G_TYPE_INSTANCE_GET_CLASS ((obj), GRAPH_WIDGET, GraphWidgetClass))
+
+GtkWidget* graph_widget_new(void);
+
+Graph* graph_widget_get_graph(GraphWidget* gw);
+
+#endif             /* !GRAPHWIDGET_H_ */
diff --git a/src/matdb-dotcode.c b/src/matdb-dotcode.c
new file mode 100644 (file)
index 0000000..df195fb
--- /dev/null
@@ -0,0 +1,346 @@
+/*
+ * matdb-dotcode: reads in Craig's Dotcode materials database.
+
+
+
+ Copyright (C) 2008 Joseph Pingenot
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include <matdb-dotcode.h>
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <strings.h>
+#include <stdlib.h>
+
+#ifdef DEBUG
+#undef DEBUG
+#endif
+#ifdef DEBUG_2
+#undef DEBUG_2
+#endif
+
+/*Functions to be used by the hash.*/
+static void destroy_string(gpointer data) {
+  free((char*)data);
+}
+static void destroy_double(gpointer data){
+  free((double*)data);
+}
+static void destroy_inner_bowhash(gpointer data) {
+  g_hash_table_unref(data);
+}
+
+int insert_into_matdb(struct matdb *mdb, struct matdb_material **mat, struct matdb_bowing **bow) {
+  if((*mat) != NULL) {
+#ifdef DEBUG
+    fprintf(stderr, "inserting material %s\n", (*mat)->name->str);
+#endif
+    g_hash_table_insert(mdb->materials, (gpointer)g_strdup((*mat)->name->str), (gpointer)(*mat));
+    (*mat) = NULL;
+  }
+  if((*bow) != NULL) {
+#ifdef DEBUG
+    fprintf(stderr, "inserting bowing %s:%s\n", (*bow)->from->str, (*bow)->to->str);
+#endif
+    /*Inner table*/
+    GHashTable *it;
+    if((it=g_hash_table_lookup(mdb->bowings, (*bow)->from->str)) == NULL) {
+      if((it = g_hash_table_new_full(&g_str_hash, &g_str_equal, &destroy_string, &destroy_inner_bowhash)) == NULL) {
+       (*bow) = NULL;
+       return 1;
+      }
+      g_hash_table_insert(mdb->bowings, (*bow)->from->str, it);
+      #ifdef DEBUG
+      fprintf(stderr, "Got new hash table (from=%s)\n", (*bow)->from->str);
+      #endif
+    }
+    g_hash_table_insert(it, (gpointer)g_strdup((*bow)->to->str), (gpointer)(*bow));
+    (*bow) = NULL;
+  }
+  return 0;
+}
+
+/*Removes leading and trailing whitespace, comments, and reduces
+  redundant whitespace down to one tab, makes an empty line an empty string.*/
+static void prettify_line(char *line) {
+  register char *look;
+  register char *write;
+  register int in_whitespace;
+  register int leading_whitespace;
+  for(look=write=line, in_whitespace=0, leading_whitespace=1; *look != '\0'; look++) {
+#ifdef DEBUG_2
+    fprintf(stderr, " look=%d(%c) write=%d(%c) in_whitespace=%d leading_whitespace=%d: ", (look-line), *look, (write-line), *write, in_whitespace, leading_whitespace);
+#endif
+    if(*look == '#') {
+#ifdef DEBUG_2
+      fprintf(stderr, "comment\n");
+#endif
+      *write = '\0';
+      break;
+    }
+    switch(*look) {
+    case ' ':
+    case '\n':
+    case '\t':
+#ifdef DEBUG_2
+      fprintf(stderr, "whitespace\n");
+#endif
+      if((!leading_whitespace) && (!in_whitespace)) *write++ = '\t';
+      in_whitespace=1;
+      break;
+    default:
+#ifdef DEBUG_2
+      fprintf(stderr, "default\n");
+#endif
+      *write++ = *look;
+      in_whitespace=leading_whitespace=0;
+    }
+  }
+  *write='\0';
+  for(look=write=line; *look != '\0'; look++) {
+    switch(*look) {
+    case ' ':
+    case '\n':
+    case '\t':
+      if(*(look+1) == '\0') {
+       *look = '\0';
+      }
+    }
+  }
+}
+
+/*Error values:
+ *   0: success
+ *   1: failure malloc'ing / initializing mdb struct
+ *   2: failure opening file.
+ *   4: failure reading line.
+ *   8: warning reading line: no tab separator (line parsing error)
+ *  16: warning reading line: bad section declaration
+ *  32: warning reading line: unable to allocate material struct.
+ *  64: warning reading line: ignored line (unallocated material struct)
+ * 128: warning reading line: unable to allocate bowing struct
+ * 256: warning reading line: ignored line (unallocated bowing struct)
+ * 512: warning reading file: improper section detected (programming
+ *   error)
+ *1024: warning reading file: no : separator in bowing materials
+ *   description.
+ *2048: warning reading file: unable to read numeric value for property.
+ */
+struct matdb* read_matdb_dotcode(const GString *name, int* err) {
+#ifdef DEBUG_2
+  fprintf(stderr, "in read_matdb_dotcode(%s, %d)\n", name->str, *err);
+#endif
+  *err=0;
+  struct matdb *mdb = (struct matdb*)malloc(sizeof(struct matdb));
+  if(mdb == NULL) {*err = 1; return NULL;}
+
+  double *value;
+  if((mdb->materials = g_hash_table_new_full(&g_str_hash, &g_str_equal, &destroy_string, &destroy_material_gpointer)) == NULL) {
+    *err = 1;
+    free(mdb);
+    return NULL;
+  }
+  if((mdb->bowings = g_hash_table_new_full(&g_str_hash, &g_str_equal, &destroy_string, &destroy_bowing_gpointer)) == NULL) {
+    *err = 1;
+    g_hash_table_unref(mdb->materials);
+    free(mdb);
+    return NULL;
+  }
+  struct matdb_material *mat = NULL;
+  struct matdb_bowing *bow = NULL;
+  /*Valid sections: 
+   * 0 (no/global section)
+   * 1 (material)
+   * 2 (bow)
+   */
+  int section=0;
+  int n;
+  char *line;
+  FILE *infile = fopen(name->str, "r");
+  if(infile == NULL) {
+    g_hash_table_unref(mdb->materials);
+    g_hash_table_unref(mdb->bowings);
+    free(mdb);
+    *err=2;
+    return NULL;
+#ifdef DEBUG_2
+  }else{
+    fprintf(stderr, "infile=%x\n", (unsigned int)infile);
+#endif
+  }
+  int val;
+  while(!feof(infile)) {
+#ifdef DEBUG
+    fprintf(stderr, "mat=%x(%s), bow=%x(%s:%s)\n", (unsigned int)mat, mat?mat->name->str:"", (unsigned int)bow, bow?bow->from->str:"", bow?bow->to->str:"");
+#endif
+    line=NULL;
+    if((val = getline(&line, &n, infile)) == -1) {
+#ifdef DEBUG_2
+      fprintf(stderr, "getline returned %d\n", val); 
+#endif
+      if(!feof(infile)) *err = 4;
+      //fclose(infile);
+      break;
+    }
+#ifdef DEBUG_2
+    fprintf(stderr, "line=(%s)\n", line);
+#endif
+    prettify_line(line);
+#ifdef DEBUG
+    fprintf(stderr, "%d: prettified line=(%s)\n", section, line);
+#endif
+    if(*line == '\0') {
+      free(line);
+      continue;
+    }
+    char *i = index(line, '\t');
+    if(i == NULL) {
+      *err &= 8;
+    }
+    *i++ = '\0';
+    /*At this point, we have line which stores the first word on the
+      line, and i which stores the second word on the line.
+    */
+    char *to;
+    GHashTable *ht;
+#ifdef DEBUG_2
+    fprintf(stderr, "part_a=(%s) part_b=(%s)\n", line, i);
+#endif
+    /*If we have a material or bowing underway, save it off*/
+    if(strcasecmp(line, "material") == 0) {
+      insert_into_matdb(mdb, &mat, &bow);
+      if((mat = (struct matdb_material*)malloc(sizeof(struct matdb_material))) == NULL) {
+       *err &= 32;
+      }
+      if((mat->name = g_string_new(i)) == NULL) {
+       *err &= 32;
+       free(mat);
+       section=0;
+       continue;
+      }
+      if((mat->properties = g_hash_table_new_full(&g_str_hash, &g_str_equal, &destroy_string, &destroy_double)) == NULL) {
+       *err &= 32;
+       g_string_free(mat->name, TRUE);
+       free(bow);
+       section=0;
+       continue;
+      }
+#ifdef DEBUG_2
+      fprintf(stderr, "new material (%s):\n", i);
+#endif
+      section=1;
+    }else if(strcasecmp(line, "bow") == 0) {
+      insert_into_matdb(mdb, &mat, &bow);
+      if((bow = (struct matdb_bowing*)malloc(sizeof(struct matdb_bowing))) == NULL) {
+       *err &= 128;
+      }
+      if((to = index(i, ':')) == NULL) {
+       *err &= 1024;
+       free(bow);
+       section=0;
+       continue;
+      }
+      *to++ = '\0';
+      /*Same trick as before, but i now stores the from material,
+       and to the to material
+      */
+      if((bow->from = g_string_new(i)) == NULL) {
+       *err &= 128;
+       free(bow);
+       section=0;
+       continue;
+      }
+      if((bow->to = g_string_new(to)) == NULL) {
+       *err &= 128;
+       g_string_free(bow->from, TRUE);
+       free(bow);
+       section=0;
+       continue;
+      }
+      if((bow->properties = g_hash_table_new_full(&g_str_hash, &g_str_equal, &destroy_string, &destroy_double)) == NULL) {
+       *err &= 128;
+       g_string_free(bow->to, TRUE);
+       g_string_free(bow->from, TRUE);
+       free(bow);
+       section=0;
+       continue;
+      }
+#ifdef DEBUG_2
+      fprintf(stderr, "new bowing (%s:%s):\n", i, to);
+#endif
+      section=2;
+    }else{
+      #ifdef DEBUG
+      fprintf(stderr, "\t%d/%s\t", section, line);
+      #endif
+      /*Process a property.*/
+      switch(section) {
+      case 1:
+       #ifdef DEBUG
+       fprintf(stderr, "(1)\t");
+       #endif
+       ht = mat->properties;
+       break;
+      case 2:
+       #ifdef DEBUG
+       fprintf(stderr, "(2)\t");
+       #endif
+       ht = bow->properties;
+       break;
+      default:
+       #ifdef DEBUG
+       fprintf(stderr, "(default)\t");
+       #endif
+       *err &= 16;
+       section = 0;
+      }
+      if(section == 0) {
+       #ifdef DEBUG
+       fprintf(stderr, "section was 0\n");
+       #endif
+       continue;
+      }
+      if((value = (double*)malloc(sizeof(double))) == NULL) {
+       *err &= 2048;
+       #ifdef DEBUG
+       fprintf(stderr, "malloc of value failed\n");
+       #endif
+       continue;
+      }
+      int num;
+      if((num=sscanf(i, " %lg", value)) != 1) {
+       *err &= 2048;
+       free(value);
+       #ifdef DEBUG
+       fprintf(stderr, "bad sscanf to get value (scanned \"%s\", returned %d)\n", i, num);
+       #endif
+       continue;
+      }
+      g_hash_table_insert(ht, g_strdup(line), value);
+#ifdef DEBUG
+      fprintf(stderr, "%g(%s)\n", *value, line);
+#endif
+    }
+    free(line);
+    line=i=to=NULL;
+    value=NULL;
+  }
+  fclose(infile);
+  insert_into_matdb(mdb, &mat, &bow);
+  return mdb;
+}
+
diff --git a/src/matdb-dotcode.h b/src/matdb-dotcode.h
new file mode 100644 (file)
index 0000000..ebe4719
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * matdb-dotcode: reads in Craig's Dotcode materials database.
+
+
+
+    Copyright (C) 2008 Joseph Pingenot
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Affero General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Affero General Public License for more details.
+
+    You should have received a copy of the GNU Affero General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef MATDB_DOTCODE_H_
+#define MATDB_DOTCODE_H_
+
+#include <matdb.h>
+
+struct matdb* read_matdb_dotcode(const GString *name, int *err);
+
+#endif
diff --git a/src/matdb.c b/src/matdb.c
new file mode 100644 (file)
index 0000000..644eb40
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * matdb: generic materials database information.
+
+
+
+    Copyright (C) 2008 Joseph Pingenot
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Affero General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Affero General Public License for more details.
+
+    You should have received a copy of the GNU Affero General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include <matdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+static void print_property(gpointer key, gpointer value, gpointer user_data) {
+  fprintf(stderr, "\t\t%s=%g:\n", (char*)key, *(double*)value);
+}
+static void print_inner_bowing(gpointer key, gpointer value, gpointer user_data) {
+  struct matdb_bowing *bowing = (struct matdb_bowing*)value;
+  fprintf(stderr, "\tbowing %s:%s[%s:%s]:\n", bowing->from->str, bowing->to->str, (char*)user_data, (char*)key);
+  g_hash_table_foreach(bowing->properties, &print_property, NULL);
+}
+static void print_material(gpointer key, gpointer value, gpointer user_data) {
+  struct matdb_material *mat = (struct matdb_material*)value;
+  fprintf(stderr, "\tmaterial %s(%s):\n", mat->name->str, (char*)key);
+  g_hash_table_foreach(mat->properties, &print_property, NULL);
+}
+static void print_bowing(gpointer key, gpointer value, gpointer user_data) {
+  GHashTable *ht = value;
+  g_hash_table_foreach(ht, &print_inner_bowing, key);
+}
+
+void print_matdb(const struct matdb *mdb) {
+  fprintf(stderr, "matdb:\n");
+  g_hash_table_foreach(mdb->materials, &print_material, NULL);
+  g_hash_table_foreach(mdb->bowings, &print_bowing, NULL);
+}
+
+void destroy_material_gpointer(gpointer data) {
+  destroy_material((struct matdb_material *)data);
+}
+void destroy_bowing_gpointer(gpointer data) {
+  destroy_bowing((struct matdb_bowing *)data);
+}
+void destroy_material(struct matdb_material *mat) {
+  #ifdef DEBUG
+  fprintf(stderr, "destroy_material\n");
+  #endif
+  g_string_free(mat->name, TRUE);
+  g_hash_table_unref(mat->properties);
+  free(mat);
+}
+void destroy_bowing(struct matdb_bowing *bow) {
+  #ifdef DEBUG
+  fprintf(stderr, "destroy_bowing\n");
+  #endif
+  g_string_free(bow->from, TRUE);
+  g_string_free(bow->to, TRUE);
+  g_hash_table_unref(bow->properties);
+  free(bow);
+}
diff --git a/src/matdb.h b/src/matdb.h
new file mode 100644 (file)
index 0000000..19747f8
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * matdb: generic materials database information.
+
+
+
+    Copyright (C) 2008 Joseph Pingenot
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Affero General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Affero General Public License for more details.
+
+    You should have received a copy of the GNU Affero General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef MATDB_H_
+#define MATDB_H_
+
+#include <glib-2.0/glib.h>
+
+struct matdb_material {
+  GString *name;
+  GHashTable *properties;
+};
+
+struct matdb_bowing {
+  GString *from;
+  GString *to;
+  GHashTable *properties;
+};
+
+struct matdb {
+  GHashTable *materials;
+  GHashTable *bowings;
+};
+
+void print_matdb(const struct matdb *mdb);
+void destroy_material_gpointer(gpointer data);
+void destroy_bowing_gpointer(gpointer data);
+void destroy_material(struct matdb_material *mat);
+void destroy_bowing(struct matdb_bowing *bow);
+
+#endif
diff --git a/src/scdataviz.c b/src/scdataviz.c
new file mode 100644 (file)
index 0000000..812cd26
--- /dev/null
@@ -0,0 +1,183 @@
+/*
+** scdataviz.c
+** 
+** Made by (Johnny Q. Hacker)
+** Login   <solarion@johnathan>
+** 
+** Holds the SC graphing widget.
+
+
+
+    Copyright (C) 2008 Joseph Pingenot
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Affero General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Affero General Public License for more details.
+
+    You should have received a copy of the GNU Affero General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+** Started on  Thu Jul 17 11:03:27 2008 Johnny Q. Hacker
+** Last update Thu Oct  8 19:13:57 2009 Johnny Q. Hacker
+*/
+
+#include <gtk/gtk.h>
+#include <graphwidget.h>
+#include <matdb-dotcode.h>
+#include <stdlib.h>
+#include <strings.h>
+
+#define DEBUG_SHOW_ONLY_BOWED
+
+struct xy_properties {
+  GString *xprop;
+  GString *yprop;
+  Graph *graph;
+  struct matdb *mdb;
+  struct matdb_material *mat;
+};
+
+static void lookup_xy(GHashTable* propts, GString* xprop, GString* yprop, double **x, double **y) {
+  *x=g_hash_table_lookup(propts, xprop->str);
+  *y=g_hash_table_lookup(propts, yprop->str);
+}
+
+static void put_mat_in_graph(gpointer key, gpointer value, gpointer user_data) {
+  struct xy_properties *propmap = user_data;
+  struct matdb_material *mat = value;
+  if(!strcasecmp(mat->name->str, "vacuum")) return;
+  if(!strcasecmp(mat->name->str, "pvb")) return;
+  double *x, *y;
+  #ifdef DEBUG_ASSIGNMENT
+  fprintf(stderr, "put_mat_in_graph(%s) (x->%s, y->%s): ", (char*)key, propmap->xprop->str, propmap->yprop->str);
+  #endif
+  lookup_xy(mat->properties, propmap->xprop, propmap->yprop, &x, &y);
+  if((x != NULL) && (y != NULL)) {
+    graph_add_point(propmap->graph, *x, *y, mat->name);
+  #ifdef DEBUG_ASSIGNMENT
+    fprintf(stderr, "added (x->%s=%g, y->%s=%g)\n", propmap->xprop->str, *x, propmap->yprop->str, *y);
+  }else{
+    fprintf(stderr, "no such properties (x->%s, y->%s)\n", propmap->xprop->str, propmap->yprop->str);
+  #endif
+  }
+}
+
+static void inner_link_materials(gpointer key, gpointer value, gpointer user_data) {
+  struct xy_properties *propmap = user_data;
+  struct matdb_material *mat = value;
+  if(!strcasecmp(mat->name->str, "vacuum")) return;
+  if(!strcasecmp(mat->name->str, "pvb")) return;
+  if(g_string_equal(mat->name, propmap->mat->name)) return;
+  struct graph_line *l = (struct graph_line *)malloc(sizeof(struct graph_line));
+  if(l == NULL) return;
+  struct matdb_bowing *bow = NULL;
+  GHashTable *subtable;
+  double *p0_x, *p0_y, *p1_x, *p1_y, *p3_x, *p3_y;
+  lookup_xy(propmap->mat->properties, propmap->xprop, propmap->yprop, &p0_x, &p0_y);
+  lookup_xy(mat->properties, propmap->xprop, propmap->yprop, &p3_x, &p3_y);
+#ifdef DEBUG_ASSIGNMENT
+  fprintf(stderr, "%s:%s x=%s y=%s p0(%g,%g) p3(%g,%g)\n", propmap->mat->name->str, mat->name->str, propmap->xprop->str, propmap->yprop->str, (p0_x)?*p0_x:0, (p0_y)?*p0_y:0, (p3_x)?*p3_x:0, (p3_y)?*p3_y:0);
+#endif
+  if((p0_x != NULL) && (p0_y != NULL) && (p3_x != NULL) && (p3_y != NULL)) {
+    l->p0_x = *p0_x;
+    l->p0_y = *p0_y;
+    l->p3_x = *p3_x;
+    l->p3_y = *p3_y;
+    if((subtable = g_hash_table_lookup(propmap->mdb->bowings, propmap->mat->name->str)) == NULL) {
+      /*Try the other way 'round*/
+      if((subtable = g_hash_table_lookup(propmap->mdb->bowings, mat->name->str) )
+         != NULL) {
+       bow = g_hash_table_lookup(subtable, propmap->mat->name->str);
+      }
+    }else{
+      bow = g_hash_table_lookup(subtable, mat->name->str);
+    }
+    if(bow != NULL) {
+      if((p1_x = g_hash_table_lookup(bow->properties, propmap->xprop->str)) != NULL) {
+       l->p1_x = *p1_x/2.0;
+       graph_bezier_quadratic_to_cubic(l->p0_x, l->p3_x, &(l->p1_x), &(l->p2_x));
+      }else{
+       graph_bezier_linear_to_cubic(l->p0_x, l->p3_x, &(l->p1_x), &(l->p2_x));
+      }
+      if((p1_y = g_hash_table_lookup(bow->properties, propmap->yprop->str)) != NULL) {
+       l->p1_y = *p1_y/2.0;
+       graph_bezier_quadratic_to_cubic(l->p0_y, l->p3_y, &(l->p1_y), &(l->p2_y));
+      }else{
+       graph_bezier_linear_to_cubic(l->p0_y, l->p3_y, &(l->p1_y), &(l->p2_y));
+      }
+    }else{
+      #ifdef DEBUG_SHOW_ONLY_BOWED
+      free(l);
+      return;
+      #endif
+      graph_bezier_linear_to_cubic(l->p0_x, l->p3_x, &(l->p1_x), &(l->p2_x));
+      graph_bezier_linear_to_cubic(l->p0_y, l->p3_y, &(l->p1_y), &(l->p2_y));
+    }
+    #ifdef DEBUG_ASSIGNMENT
+    fprintf(stderr, "%s:%s p0(%g,%g) p1(%g,%g) p2(%g,%g), p3(%g,%g)\n", propmap->mat->name->str, mat->name->str, l->p0_x, l->p0_y, l->p1_x, l->p1_y, l->p2_x, l->p2_y, l->p3_x, l->p3_y);
+    #endif
+    graph_add_graph_line(propmap->graph, l);
+  }else{
+    free(l);
+  }
+}
+
+static void link_materials(gpointer key, gpointer value, gpointer user_data) {
+  struct xy_properties *propmap = user_data;
+  struct matdb_material *mat = value;
+  if(!strcasecmp(mat->name->str, "vacuum")) return;
+  if(!strcasecmp(mat->name->str, "pvb")) return;
+  propmap->mat = mat;
+  g_hash_table_foreach(propmap->mdb->materials, &inner_link_materials, propmap);
+}
+
+int main(int   argc, char *argv[]) 
+{
+    GtkWidget *window;
+    GtkWidget *graph;
+    GString *file = g_string_new("matdb.txt");
+    int err=0;
+    struct matdb *mdb = read_matdb_dotcode(file, &err);
+    //fprintf(stderr, "read_matdb_dotcode(%s, %d)=%x", file->str, err,
+    //(int)mdb);
+    //fprintf(stderr, "err=%d\n", err);
+    //print_matdb(mdb);
+    
+    gtk_init (&argc, &argv);
+    
+    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+    graph = graph_widget_new();
+
+    struct xy_properties propmap;
+    propmap.xprop = g_string_new("a_lc");
+    propmap.yprop = g_string_new("E_g_Gamma");
+    propmap.graph = graph_widget_get_graph(GRAPH_WIDGET(graph));
+    propmap.mdb = mdb;
+    g_hash_table_foreach(mdb->materials, &put_mat_in_graph, &propmap);
+    //graph_add_linear_connectors(propmap.graph);
+    g_hash_table_foreach(mdb->materials, &link_materials, &propmap);
+    graph_autoset_xaxis(propmap.graph, propmap.xprop);
+    graph_autoset_yaxis(propmap.graph, propmap.yprop);
+
+    //Connect signals
+    g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);
+
+    gtk_container_add(GTK_CONTAINER(window), graph);
+    /*
+    graph_add_point(graph_widget_get_graph(graph), 5, 3);
+    graph_add_point(graph_widget_get_graph(graph), 8, 12);
+    graph_add_point(graph_widget_get_graph(graph), 11, 48);
+    */
+    
+    gtk_widget_show_all  (window);
+    
+    gtk_main ();
+    
+    return 0;
+}