summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile21
-rw-r--r--dive.c48
-rw-r--r--dive.h7
-rw-r--r--divelist.c5
-rw-r--r--equipment.c63
-rw-r--r--packaging/debian/control3
-rw-r--r--parse-xml.c74
-rw-r--r--statistics.c22
8 files changed, 183 insertions, 60 deletions
diff --git a/Makefile b/Makefile
index 20cbf8a57..1b1a31a8c 100644
--- a/Makefile
+++ b/Makefile
@@ -5,6 +5,7 @@ CFLAGS=-Wall -Wno-pointer-sign -g
INSTALL=install
PKGCONFIG=pkg-config
XML2CONFIG=xml2-config
+XSLCONFIG=xslt-config
# these locations seem to work for SuSE and Fedora
# prefix = $(HOME)
@@ -15,12 +16,14 @@ DESKTOPDIR = $(DATADIR)/applications
ICONPATH = $(DATADIR)/icons/hicolor
ICONDIR = $(ICONPATH)/scalable/apps
MANDIR = $(DATADIR)/man/man1
+XSLTDIR = $(DATADIR)/subsurface/xslt
gtk_update_icon_cache = gtk-update-icon-cache -f -t $(ICONPATH)
NAME = subsurface
ICONFILE = $(NAME).svg
DESKTOPFILE = $(NAME).desktop
MANFILES = $(NAME).1
+XSLTFILES = xslt/*.xslt
MACOSXINSTALL = /Applications/Subsurface.app
MACOSXFILES = packaging/macosx
@@ -77,7 +80,7 @@ LIBGTK = $(shell $(PKGCONFIG) --libs gtk+-2.0 glib-2.0 gconf-2.0)
LIBDIVECOMPUTERCFLAGS = $(LIBDIVECOMPUTERINCLUDES)
LIBDIVECOMPUTER = $(LIBDIVECOMPUTERARCHIVE) $(LIBUSB)
-LIBS = $(LIBXML2) $(LIBGTK) $(LIBDIVECOMPUTER) -lpthread
+LIBS = $(LIBXML2) $(LIBXSLT) $(LIBGTK) $(LIBDIVECOMPUTER) -lpthread
OBJS = main.o dive.o profile.o info.o equipment.o divelist.o \
parse-xml.o save-xml.o libdivecomputer.o print.o uemis.o \
@@ -98,12 +101,26 @@ install: $(NAME)
fi
$(INSTALL) -d -m 755 $(MANDIR)
$(INSTALL) -m 644 $(MANFILES) $(MANDIR)
+ @-if test ! -z "$(XSLT)"; then \
+ $(INSTALL) -d -m 755 $(DATADIR)/subsurface; \
+ $(INSTALL) -d -m 755 $(XSLTDIR); \
+ $(INSTALL) -m 644 $(XSLTFILES) $(XSLTDIR); \
+ fi
LIBXML2 = $(shell $(XML2CONFIG) --libs)
+LIBXSLT = $(shell $(XSLCONFIG) --libs)
XML2CFLAGS = $(shell $(XML2CONFIG) --cflags)
GLIB2CFLAGS = $(shell $(PKGCONFIG) --cflags glib-2.0)
GCONF2CFLAGS = $(shell $(PKGCONFIG) --cflags gconf-2.0)
GTK2CFLAGS = $(shell $(PKGCONFIG) --cflags gtk+-2.0)
+CFLAGS += $(shell $(XSLCONFIG) --cflags)
+
+ifneq ($(strip $(LIBXSLT)),)
+ # We still need proper paths and install options for OSX and Windows
+ ifeq ($(shell sh -c 'uname -s 2>/dev/null || echo not'),Linux)
+ XSLT=-DXSLT='"$(XSLTDIR)"'
+ endif
+endif
install-macosx: $(NAME)
$(INSTALL) -d -m 755 $(MACOSXINSTALL)/Contents/Resources
@@ -116,7 +133,7 @@ install-macosx: $(NAME)
$(INSTALL) $(MACOSXFILES)/Subsurface.icns $(MACOSXINSTALL)/Contents/Resources/
parse-xml.o: parse-xml.c dive.h
- $(CC) $(CFLAGS) $(GLIB2CFLAGS) -c $(XML2CFLAGS) parse-xml.c
+ $(CC) $(CFLAGS) $(GLIB2CFLAGS) -c $(XML2CFLAGS) $(XSLT) parse-xml.c
save-xml.o: save-xml.c dive.h
$(CC) $(CFLAGS) $(GLIB2CFLAGS) -c save-xml.c
diff --git a/dive.c b/dive.c
index cb94e7925..bd1b92619 100644
--- a/dive.c
+++ b/dive.c
@@ -207,46 +207,21 @@ static void update_temperature(temperature_t *temperature, int new)
}
}
-/*
- * If you have more than 32 cylinders, you'd better have a 64-bit build.
- * And if you have more than 64 cylinders, you need to use another tool,
- * or fix this up to do something odd.
- */
-static unsigned long fixup_pressure(struct dive *dive, struct sample *sample, unsigned long flags)
+static void fixup_pressure(struct dive *dive, struct sample *sample)
{
- unsigned long mask;
unsigned int pressure, index;
cylinder_t *cyl;
pressure = sample->cylinderpressure.mbar;
if (!pressure)
- return flags;
+ return;
index = sample->cylinderindex;
if (index >= MAX_CYLINDERS)
- return flags;
+ return;
cyl = dive->cylinder + index;
- if (!cyl->start.mbar)
- cyl->start.mbar = pressure;
- /*
- * If we already have an end pressure, without
- * ever having seen a sample for this cylinder,
- * that means that somebody set the end pressure
- * by hand
- */
- mask = 1ul << index;
- if (cyl->end.mbar) {
- if (!(flags & mask))
- return flags;
- }
- flags |= mask;
-
- /* we need to handle the user entering beginning and end tank pressures
- * - maybe even IF we have samples. But for now if we have air pressure
- * data in the samples, we use that instead of the minimum
- * if (!cyl->end.mbar || pressure < cyl->end.mbar)
- */
- cyl->end.mbar = pressure;
- return flags;
+ if (!cyl->sample_start.mbar)
+ cyl->sample_start.mbar = pressure;
+ cyl->sample_end.mbar = pressure;
}
struct dive *fixup_dive(struct dive *dive)
@@ -258,7 +233,6 @@ struct dive *fixup_dive(struct dive *dive)
int maxdepth = 0, mintemp = 0;
int lastdepth = 0;
int lasttemp = 0;
- unsigned long flags = 0;
for (i = 0; i < dive->samples; i++) {
struct sample *sample = dive->sample + i;
@@ -276,7 +250,7 @@ struct dive *fixup_dive(struct dive *dive)
maxdepth = depth;
}
- flags = fixup_pressure(dive, sample, flags);
+ fixup_pressure(dive, sample);
if (temp) {
/*
@@ -311,8 +285,12 @@ struct dive *fixup_dive(struct dive *dive)
add_people(dive->divemaster);
add_location(dive->location);
for (i = 0; i < MAX_CYLINDERS; i++) {
- cylinder_type_t *type = &dive->cylinder[i].type;
- add_cylinder_description(type);
+ cylinder_t *cyl = dive->cylinder + i;
+ add_cylinder_description(&cyl->type);
+ if (cyl->sample_start.mbar == cyl->start.mbar)
+ cyl->start.mbar = 0;
+ if (cyl->sample_end.mbar == cyl->end.mbar)
+ cyl->end.mbar = 0;
}
return dive;
diff --git a/dive.h b/dive.h
index cf11e1f89..0116a1cf7 100644
--- a/dive.h
+++ b/dive.h
@@ -5,6 +5,7 @@
#include <time.h>
#include <glib.h>
+#include <libxml/tree.h>
/*
* Some silly typedefs to make our units very explicit.
@@ -83,7 +84,7 @@ typedef struct {
typedef struct {
cylinder_type_t type;
struct gasmix gasmix;
- pressure_t start, end;
+ pressure_t start, end, sample_start, sample_end;
} cylinder_t;
extern int get_pressure_units(unsigned int mb, const char **units);
@@ -253,6 +254,10 @@ extern void parse_xml_init(void);
extern void parse_xml_file(const char *filename, GError **error);
extern void set_filename(const char *filename);
+#ifdef XSLT
+extern xmlDoc *test_xslt_transforms(xmlDoc *doc);
+#endif
+
extern void show_dive_info(struct dive *);
extern void flush_dive_info_changes(struct dive *);
diff --git a/divelist.c b/divelist.c
index 2d04eb5b0..eb8f23143 100644
--- a/divelist.c
+++ b/divelist.c
@@ -299,6 +299,7 @@ static double calculate_airuse(struct dive *dive)
int i;
for (i = 0; i < MAX_CYLINDERS; i++) {
+ pressure_t start, end;
cylinder_t *cyl = dive->cylinder + i;
int size = cyl->type.size.mliter;
double kilo_atm;
@@ -306,7 +307,9 @@ static double calculate_airuse(struct dive *dive)
if (!size)
continue;
- kilo_atm = (to_ATM(cyl->start) - to_ATM(cyl->end)) / 1000.0;
+ start = cyl->start.mbar ? cyl->start : cyl->sample_start;
+ end = cyl->end.mbar ? cyl->end : cyl->sample_end;
+ kilo_atm = (to_ATM(start) - to_ATM(end)) / 1000.0;
/* Liters of air at 1 atm == milliliters at 1k atm*/
airuse += kilo_atm * size;
diff --git a/equipment.c b/equipment.c
index c7a683b89..19abbe672 100644
--- a/equipment.c
+++ b/equipment.c
@@ -45,7 +45,8 @@ struct cylinder_widget {
const char *name;
GtkWidget *hbox;
GtkComboBox *description;
- GtkSpinButton *size, *pressure, *start, *end;
+ GtkSpinButton *size, *pressure;
+ GtkWidget *start, *end, *pressure_button;
GtkWidget *o2, *gasmix_button;
};
@@ -71,12 +72,12 @@ static int convert_volume_pressure(int ml, int mbar, double *v, double *p)
int decimals = 1;
double volume, pressure;
+ volume = ml / 1000.0;
if (mbar) {
if (output_units.volume == CUFT) {
volume = ml_to_cuft(ml);
volume *= bar_to_atm(mbar / 1000.0);
- } else
- volume = ml / 1000.0;
+ }
if (output_units.pressure == PSI) {
pressure = mbar_to_PSI(mbar);
@@ -98,14 +99,27 @@ static void set_cylinder_type_spinbuttons(struct cylinder_widget *cylinder, int
gtk_spin_button_set_value(cylinder->pressure, pressure);
}
-static void set_cylinder_pressure_spinbuttons(struct cylinder_widget *cylinder, int start, int end)
+static void set_cylinder_pressure_spinbuttons(struct cylinder_widget *cylinder, cylinder_t *cyl)
{
+ int set;
+ unsigned int start, end;
double pressure;
+ start = cyl->start.mbar;
+ end = cyl->end.mbar;
+ set = start || end;
+ if (!set) {
+ start = cyl->sample_start.mbar;
+ end = cyl->sample_end.mbar;
+ }
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cylinder->pressure_button), set);
+ gtk_widget_set_sensitive(cylinder->start, set);
+ gtk_widget_set_sensitive(cylinder->end, set);
+
convert_pressure(start, &pressure);
- gtk_spin_button_set_value(cylinder->start, pressure);
+ gtk_spin_button_set_value(GTK_SPIN_BUTTON(cylinder->start), pressure);
convert_pressure(end, &pressure);
- gtk_spin_button_set_value(cylinder->end, pressure);
+ gtk_spin_button_set_value(GTK_SPIN_BUTTON(cylinder->end), pressure);
}
/*
@@ -266,8 +280,7 @@ static void show_cylinder(cylinder_t *cyl, struct cylinder_widget *cylinder)
set_cylinder_type_spinbuttons(cylinder,
cyl->type.size.mliter, cyl->type.workingpressure.mbar);
- set_cylinder_pressure_spinbuttons(cylinder,
- cyl->start.mbar, cyl->end.mbar);
+ set_cylinder_pressure_spinbuttons(cylinder, cyl);
o2 = cyl->gasmix.o2.permille / 10.0;
gtk_widget_set_sensitive(cylinder->o2, !!o2);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cylinder->gasmix_button), !!o2);
@@ -283,18 +296,24 @@ static int cyl_nothing(cylinder_t *cyl)
!cyl->type.description &&
!cyl->gasmix.o2.permille &&
!cyl->gasmix.he.permille &&
+ !cyl->sample_start.mbar &&
+ !cyl->sample_end.mbar &&
!cyl->start.mbar &&
!cyl->end.mbar;
}
static void set_one_cylinder(int index, cylinder_t *cyl, GtkListStore *model, GtkTreeIter *iter)
{
+ unsigned int start, end;
+
+ start = cyl->start.mbar ? : cyl->sample_start.mbar;
+ end = cyl->end.mbar ? : cyl->sample_end.mbar;
gtk_list_store_set(model, iter,
CYL_DESC, cyl->type.description ? : "",
CYL_SIZE, cyl->type.size.mliter,
CYL_WORKP, cyl->type.workingpressure.mbar,
- CYL_STARTP, cyl->start.mbar,
- CYL_ENDP, cyl->end.mbar,
+ CYL_STARTP, start,
+ CYL_ENDP, end,
CYL_O2, cyl->gasmix.o2.permille,
CYL_HE, cyl->gasmix.he.permille,
-1);
@@ -397,8 +416,10 @@ static void record_cylinder_changes(cylinder_t *cyl, struct cylinder_widget *cyl
desc = gtk_combo_box_get_active_text(box);
volume = gtk_spin_button_get_value(cylinder->size);
pressure = gtk_spin_button_get_value(cylinder->pressure);
- start = gtk_spin_button_get_value(cylinder->start);
- end = gtk_spin_button_get_value(cylinder->end);
+ start = gtk_spin_button_get_value(GTK_SPIN_BUTTON(cylinder->start));
+ end = gtk_spin_button_get_value(GTK_SPIN_BUTTON(cylinder->end));
+ if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(cylinder->pressure_button)))
+ start = end = 0;
o2 = gtk_spin_button_get_value(GTK_SPIN_BUTTON(cylinder->o2))*10 + 0.5;
if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(cylinder->gasmix_button)))
o2 = 0;
@@ -490,6 +511,16 @@ static void nitrox_cb(GtkToggleButton *button, gpointer data)
gtk_widget_set_sensitive(cylinder->o2, state);
}
+static void pressure_cb(GtkToggleButton *button, gpointer data)
+{
+ struct cylinder_widget *cylinder = data;
+ int state;
+
+ state = gtk_toggle_button_get_active(button);
+ gtk_widget_set_sensitive(cylinder->start, state);
+ gtk_widget_set_sensitive(cylinder->end, state);
+}
+
static gboolean completion_cb(GtkEntryCompletion *widget, GtkTreeModel *model, GtkTreeIter *iter, struct cylinder_widget *cylinder)
{
const char *desc;
@@ -553,11 +584,15 @@ static void cylinder_widget(GtkWidget *vbox, struct cylinder_widget *cylinder, G
hbox = gtk_hbox_new(FALSE, 3);
gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, TRUE, 0);
+ cylinder->pressure_button = gtk_check_button_new();
+ gtk_box_pack_start(GTK_BOX(hbox), cylinder->pressure_button, FALSE, FALSE, 3);
+ g_signal_connect(cylinder->pressure_button, "toggled", G_CALLBACK(pressure_cb), cylinder);
+
widget = create_spinbutton(hbox, "Start Pressure", 0, 5000, 1);
- cylinder->start = GTK_SPIN_BUTTON(widget);
+ cylinder->start = widget;
widget = create_spinbutton(hbox, "End Pressure", 0, 5000, 1);
- cylinder->end = GTK_SPIN_BUTTON(widget);
+ cylinder->end = widget;
/*
* Cylinder gas mix: Air, Nitrox or Trimix
diff --git a/packaging/debian/control b/packaging/debian/control
index 7c2aa36e2..b90fe1cbe 100644
--- a/packaging/debian/control
+++ b/packaging/debian/control
@@ -2,7 +2,8 @@ Source: subsurface
Priority: optional
Maintainer: Roland Dreier <roland@digitalvampire.org>
Build-Depends: autoconf, automake, libtool, debhelper (>= 8), dh-autoreconf,
- pkg-config, libgtk2.0-dev, libgconf2-dev, libxml2-dev, libdivecomputer-dev
+ pkg-config, libgtk2.0-dev, libgconf2-dev, libxml2-dev, libdivecomputer-dev,
+ libxslt-dev
Standards-Version: 3.9.2
Section: utils
Homepage: http://subsurface.hohndel.org
diff --git a/parse-xml.c b/parse-xml.c
index 5eabc353c..bc4d4c546 100644
--- a/parse-xml.c
+++ b/parse-xml.c
@@ -3,10 +3,14 @@
#include <string.h>
#include <stdlib.h>
#include <errno.h>
+#include <unistd.h>
#define __USE_XOPEN
#include <time.h>
#include <libxml/parser.h>
#include <libxml/tree.h>
+#ifdef XSLT
+#include <libxslt/transform.h>
+#endif
#include "dive.h"
#include "uemis.h"
@@ -1466,6 +1470,9 @@ void parse_xml_file(const char *filename, GError **error)
set_filename(filename);
reset_all();
dive_start();
+#ifdef XSLT
+ doc = test_xslt_transforms(doc);
+#endif
traverse(xmlDocGetRootElement(doc));
dive_end();
xmlFreeDoc(doc);
@@ -1476,3 +1483,70 @@ void parse_xml_init(void)
{
LIBXML_TEST_VERSION
}
+
+#ifdef XSLT
+
+/* Maybe we'll want a environment variable that can override this.. */
+static const char *xslt_path = XSLT ":xslt:.";
+
+static xsltStylesheetPtr try_get_stylesheet(const char *path, int len, const char *name)
+{
+ xsltStylesheetPtr ret;
+ int namelen = strlen(name);
+ char *filename = malloc(len+1+namelen+1);
+
+ if (!filename)
+ return NULL;
+
+ memcpy(filename, path, len);
+ filename[len] = G_DIR_SEPARATOR;
+ memcpy(filename + len + 1, name, namelen+1);
+
+ ret = NULL;
+ if (!access(filename, R_OK))
+ ret = xsltParseStylesheetFile(filename);
+ free(filename);
+
+ return ret;
+}
+
+static xsltStylesheetPtr get_stylesheet(const char *name)
+{
+ const char *path = xslt_path, *next;
+
+ do {
+ int len;
+ xsltStylesheetPtr ret;
+
+ next = strchr(path, ':');
+ len = strlen(path);
+ if (next) {
+ len = next - path;
+ next++;
+ }
+ ret = try_get_stylesheet(path, len, name);
+ if (ret)
+ return ret;
+ } while ((path = next) != NULL);
+
+ return NULL;
+}
+
+xmlDoc *test_xslt_transforms(xmlDoc *doc)
+{
+ xmlDoc *transformed;
+ xsltStylesheetPtr xslt = NULL;
+ xmlNode *root_element = xmlDocGetRootElement(doc);
+ if (strcasecmp(root_element->name, "JDiveLog") == 0) {
+ xmlSubstituteEntitiesDefault(1);
+ xslt = get_stylesheet("jdivelog2subsurface.xslt");
+ if (xslt == NULL)
+ return doc;
+ transformed = xsltApplyStylesheet(xslt, doc, NULL);
+ xmlFreeDoc(doc);
+ xsltFreeStylesheet(xslt);
+ return transformed;
+ }
+ return doc;
+}
+#endif
diff --git a/statistics.c b/statistics.c
index d71422043..4c6379443 100644
--- a/statistics.c
+++ b/statistics.c
@@ -125,10 +125,18 @@ void show_dive_stats(struct dive *dive)
const char *unit;
int idx, offset, gas_used;
struct dive *prev_dive;
+ struct tm *tm;
process_all_dives(dive, &prev_dive);
- strftime(buf, 80, "%a, %b %d, %Y, %k:%M", gmtime(&dive->when));
+ tm = gmtime(&dive->when);
+ snprintf(buf, sizeof(buf),
+ "%s, %s %d, %d %2d:%02d",
+ weekday(tm->tm_wday),
+ monthname(tm->tm_mon),
+ tm->tm_mday, tm->tm_year + 1900,
+ tm->tm_hour, tm->tm_min);
+
set_label(info_stat_w.date, buf);
set_label(info_stat_w.dive_time, "%d min", (dive->duration.seconds + 30) / 60);
if (prev_dive)
@@ -157,11 +165,14 @@ void show_dive_stats(struct dive *dive)
/* for the O2/He readings just create a list of them */
for (idx = 0; idx < MAX_CYLINDERS; idx++) {
cylinder_t *cyl = &dive->cylinder[idx];
+ unsigned int start, end;
+
+ start = cyl->start.mbar ? : cyl->sample_start.mbar;
+ end = cyl->end.mbar ? : cyl->sample_end.mbar;
/* we assume that every valid cylinder has either a working pressure
* or a size; but for good measure let's also accept cylinders with
* a starting or ending pressure*/
- if (cyl->type.workingpressure.mbar || cyl->type.size.mliter ||
- cyl->start.mbar || cyl->end.mbar) {
+ if (cyl->type.workingpressure.mbar || cyl->type.size.mliter || start || end) {
/* 0% O2 strangely means air, so 21% - I don't like that at all */
int o2 = cyl->gasmix.o2.permille ? : 209;
if (offset > 0) {
@@ -174,9 +185,8 @@ void show_dive_stats(struct dive *dive)
}
/* and if we have size, start and end pressure, we can
* calculate the total gas used */
- if (cyl->type.size.mliter && cyl->start.mbar && cyl->end.mbar)
- gas_used += cyl->type.size.mliter / 1000.0 *
- (cyl->start.mbar - cyl->end.mbar);
+ if (cyl->type.size.mliter && start && end)
+ gas_used += cyl->type.size.mliter / 1000.0 * (start - end);
}
set_label(info_stat_w.o2he, buf);
if (gas_used) {