2011-09-01 23:27:52 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <ctype.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <time.h>
|
|
|
|
|
|
|
|
#include "dive.h"
|
|
|
|
|
2011-09-04 21:56:21 +00:00
|
|
|
static void show_milli(FILE *f, const char *pre, int value, const char *unit, const char *post)
|
2011-09-01 23:27:52 +00:00
|
|
|
{
|
2011-09-04 22:08:31 +00:00
|
|
|
int i;
|
|
|
|
char buf[4];
|
|
|
|
unsigned v;
|
|
|
|
|
2011-09-04 21:56:21 +00:00
|
|
|
fputs(pre, f);
|
2011-09-04 22:08:31 +00:00
|
|
|
v = value;
|
2011-09-04 21:56:21 +00:00
|
|
|
if (value < 0) {
|
|
|
|
putc('-', f);
|
2011-09-04 22:08:31 +00:00
|
|
|
v = -value;
|
|
|
|
}
|
|
|
|
for (i = 2; i >= 0; i--) {
|
|
|
|
buf[i] = (v % 10) + '0';
|
|
|
|
v /= 10;
|
2011-09-01 23:27:52 +00:00
|
|
|
}
|
2011-09-04 22:08:31 +00:00
|
|
|
buf[3] = 0;
|
|
|
|
if (buf[2] == '0') {
|
|
|
|
buf[2] = 0;
|
|
|
|
if (buf[1] == '0')
|
|
|
|
buf[1] = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
fprintf(f, "%u.%s%s%s", v, buf, unit, post);
|
2011-09-04 21:56:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void show_temperature(FILE *f, temperature_t temp, const char *pre, const char *post)
|
|
|
|
{
|
|
|
|
if (temp.mkelvin)
|
|
|
|
show_milli(f, pre, temp.mkelvin - 273150, " C", post);
|
2011-09-01 23:27:52 +00:00
|
|
|
}
|
|
|
|
|
2011-09-01 23:59:10 +00:00
|
|
|
static void show_depth(FILE *f, depth_t depth, const char *pre, const char *post)
|
|
|
|
{
|
|
|
|
if (depth.mm)
|
2011-09-04 21:56:21 +00:00
|
|
|
show_milli(f, pre, depth.mm, " m", post);
|
2011-09-01 23:59:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void show_duration(FILE *f, duration_t duration, const char *pre, const char *post)
|
|
|
|
{
|
|
|
|
if (duration.seconds)
|
2011-09-02 00:37:41 +00:00
|
|
|
fprintf(f, "%s%u:%02u min%s", pre, FRACTION(duration.seconds, 60), post);
|
2011-09-01 23:59:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void show_pressure(FILE *f, pressure_t pressure, const char *pre, const char *post)
|
|
|
|
{
|
|
|
|
if (pressure.mbar)
|
2011-09-04 21:56:21 +00:00
|
|
|
show_milli(f, pre, pressure.mbar, " bar", post);
|
2011-09-01 23:59:10 +00:00
|
|
|
}
|
|
|
|
|
2012-11-12 19:57:49 +00:00
|
|
|
static void show_salinity(FILE *f, int salinity, const char *pre, const char *post)
|
|
|
|
{
|
|
|
|
if (salinity)
|
|
|
|
fprintf(f, "%s%.1f kg/l%s", pre, salinity / 10.0, post);
|
|
|
|
}
|
2011-09-02 02:56:04 +00:00
|
|
|
/*
|
|
|
|
* We're outputting utf8 in xml.
|
|
|
|
* We need to quote the characters <, >, &.
|
|
|
|
*
|
2011-09-02 03:28:17 +00:00
|
|
|
* Technically I don't think we'd necessarily need to quote the control
|
|
|
|
* characters, but at least libxml2 doesn't like them. It doesn't even
|
|
|
|
* allow them quoted. So we just skip them and replace them with '?'.
|
|
|
|
*
|
2012-08-27 20:19:06 +00:00
|
|
|
* If we do this for attributes, we need to quote the quotes we use too.
|
2011-09-02 02:56:04 +00:00
|
|
|
*/
|
2012-08-27 20:19:06 +00:00
|
|
|
static void quote(FILE *f, const char *text, int is_attribute)
|
2011-09-02 02:56:04 +00:00
|
|
|
{
|
|
|
|
const char *p = text;
|
|
|
|
|
|
|
|
for (;;) {
|
|
|
|
const char *escape;
|
|
|
|
|
|
|
|
switch (*p++) {
|
|
|
|
default:
|
|
|
|
continue;
|
|
|
|
case 0:
|
|
|
|
escape = NULL;
|
|
|
|
break;
|
2011-09-02 03:28:17 +00:00
|
|
|
case 1 ... 8:
|
|
|
|
case 11: case 12:
|
|
|
|
case 14 ... 31:
|
|
|
|
escape = "?";
|
|
|
|
break;
|
2011-09-02 02:56:04 +00:00
|
|
|
case '<':
|
|
|
|
escape = "<";
|
|
|
|
break;
|
|
|
|
case '>':
|
|
|
|
escape = ">";
|
|
|
|
break;
|
|
|
|
case '&':
|
|
|
|
escape = "&";
|
|
|
|
break;
|
2012-08-27 16:38:23 +00:00
|
|
|
case '\'':
|
2012-08-27 20:19:06 +00:00
|
|
|
if (!is_attribute)
|
|
|
|
continue;
|
2012-08-27 16:38:23 +00:00
|
|
|
escape = "'";
|
|
|
|
break;
|
|
|
|
case '\"':
|
2012-08-27 20:19:06 +00:00
|
|
|
if (!is_attribute)
|
|
|
|
continue;
|
2012-08-27 16:38:23 +00:00
|
|
|
escape = """;
|
|
|
|
break;
|
2011-09-02 02:56:04 +00:00
|
|
|
}
|
|
|
|
fwrite(text, (p - text - 1), 1, f);
|
|
|
|
if (!escape)
|
|
|
|
break;
|
|
|
|
fputs(escape, f);
|
|
|
|
text = p;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-27 20:19:06 +00:00
|
|
|
static void show_utf8(FILE *f, const char *text, const char *pre, const char *post, int is_attribute)
|
2011-09-02 02:56:04 +00:00
|
|
|
{
|
|
|
|
int len;
|
|
|
|
|
|
|
|
if (!text)
|
|
|
|
return;
|
|
|
|
while (isspace(*text))
|
|
|
|
text++;
|
|
|
|
len = strlen(text);
|
|
|
|
if (!len)
|
|
|
|
return;
|
|
|
|
while (len && isspace(text[len-1]))
|
|
|
|
len--;
|
|
|
|
/* FIXME! Quoting! */
|
|
|
|
fputs(pre, f);
|
2012-08-27 20:19:06 +00:00
|
|
|
quote(f, text, is_attribute);
|
2011-09-02 02:56:04 +00:00
|
|
|
fputs(post, f);
|
|
|
|
}
|
|
|
|
|
2011-09-05 16:39:55 +00:00
|
|
|
static void save_depths(FILE *f, struct dive *dive)
|
|
|
|
{
|
|
|
|
/* What's the point of this dive entry again? */
|
|
|
|
if (!dive->maxdepth.mm && !dive->meandepth.mm)
|
|
|
|
return;
|
|
|
|
|
|
|
|
fputs(" <depth", f);
|
|
|
|
show_depth(f, dive->maxdepth, " max='", "'");
|
|
|
|
show_depth(f, dive->meandepth, " mean='", "'");
|
|
|
|
fputs(" />\n", f);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void save_temperatures(FILE *f, struct dive *dive)
|
|
|
|
{
|
|
|
|
if (!dive->airtemp.mkelvin && !dive->watertemp.mkelvin)
|
|
|
|
return;
|
|
|
|
fputs(" <temperature", f);
|
|
|
|
show_temperature(f, dive->airtemp, " air='", "'");
|
|
|
|
show_temperature(f, dive->watertemp, " water='", "'");
|
|
|
|
fputs(" />\n", f);
|
|
|
|
}
|
|
|
|
|
2012-11-12 19:57:49 +00:00
|
|
|
static void save_airpressure(FILE *f, struct dive *dive)
|
|
|
|
{
|
|
|
|
if (!dive->surface_pressure.mbar)
|
|
|
|
return;
|
|
|
|
fputs(" <surface", f);
|
|
|
|
show_pressure(f, dive->surface_pressure, " pressure='", "'");
|
|
|
|
fputs(" />\n", f);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void save_salinity(FILE *f, struct dive *dive)
|
|
|
|
{
|
|
|
|
if (!dive->salinity)
|
|
|
|
return;
|
|
|
|
fputs(" <water ", f);
|
|
|
|
show_salinity(f, dive->salinity, " salinity='", "'");
|
|
|
|
fputs(" />\n", f);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-09-16 01:16:07 +00:00
|
|
|
static void show_location(FILE *f, struct dive *dive)
|
|
|
|
{
|
|
|
|
char buffer[80];
|
|
|
|
const char *prefix = " <location>";
|
|
|
|
double latitude = dive->latitude;
|
|
|
|
double longitude = dive->longitude;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Ok, theoretically I guess you could dive at
|
|
|
|
* exactly 0,0. But we don't support that. So
|
|
|
|
* if you do, just fudge it a bit, and say that
|
|
|
|
* you dove a few meters away.
|
|
|
|
*/
|
|
|
|
if (latitude || longitude) {
|
|
|
|
int len = snprintf(buffer, sizeof(buffer)-4,
|
2012-11-18 17:55:41 +00:00
|
|
|
" <location gps=");
|
|
|
|
char *buf = buffer + len;
|
|
|
|
|
|
|
|
len = strlen(g_ascii_formatd(buf, 80, "'%.12g ", latitude));
|
|
|
|
buf += len;
|
|
|
|
len = strlen(g_ascii_formatd(buf, 80, "%.12g'>", longitude));
|
|
|
|
buf += len;
|
|
|
|
len = buf - buffer;
|
2011-09-16 01:16:07 +00:00
|
|
|
if (!dive->location) {
|
|
|
|
memcpy(&buffer[len-1], "/>\n", 4);
|
|
|
|
fputs(buffer, f);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
prefix = buffer;
|
|
|
|
}
|
2012-08-27 20:19:06 +00:00
|
|
|
show_utf8(f, dive->location, prefix,"</location>\n", 0);
|
2011-09-16 01:16:07 +00:00
|
|
|
}
|
|
|
|
|
2011-09-01 23:27:52 +00:00
|
|
|
static void save_overview(FILE *f, struct dive *dive)
|
|
|
|
{
|
2011-09-05 16:39:55 +00:00
|
|
|
save_depths(f, dive);
|
|
|
|
save_temperatures(f, dive);
|
2012-11-12 19:57:49 +00:00
|
|
|
save_airpressure(f, dive);
|
|
|
|
save_salinity(f, dive);
|
2011-09-02 00:37:41 +00:00
|
|
|
show_duration(f, dive->surfacetime, " <surfacetime>", "</surfacetime>\n");
|
2011-09-16 01:16:07 +00:00
|
|
|
show_location(f, dive);
|
2012-08-27 20:19:06 +00:00
|
|
|
show_utf8(f, dive->divemaster, " <divemaster>","</divemaster>\n", 0);
|
|
|
|
show_utf8(f, dive->buddy, " <buddy>","</buddy>\n", 0);
|
|
|
|
show_utf8(f, dive->notes, " <notes>","</notes>\n", 0);
|
|
|
|
show_utf8(f, dive->suit, " <suit>","</suit>\n", 0);
|
2011-09-01 23:27:52 +00:00
|
|
|
}
|
|
|
|
|
Fix missing save of (almost empty) cylinder information
If we have no explicit cylinder info at all (it's normal air, no size or
working pressure information, and no beginning/end pressure information),
we don't save the cylinders in question because that would be redundant.
Such non-saved cylinders may still show up in the equipment list because
there may be implicit mention of them elsewhere, notably due to sample
data, so not saving them is the right thing to do - there is nothing to
save.
However, we missed one case: if there were other cylinders that *did* have
explicit information in it following such an uninteresting cylinder, we do
need to save the cylinder information for the useless case - if only in
order to be able to save the non-useless information for subsequent
cylinders.
This patch does that. Now, if you had an air-filled cylinder with no
information as your first cylinder, and a 51% nitrox as your second one,
it will save that information as
<cylinder />
<cylinder o2='51.0%' />
rather than dropping the cylinder information entirely.
This bug has been there for a long time, and was hidden by the fact that
normally you'd fill in cylinder descriptions etc after importing new
dives. It also used to be that we saved the cylinder beginning/end
pressure even if that was generated from the sample data, so if you
imported from a air-integrated computer and had samples for that cylinder,
we used to save it even though it was technically redundant.
We stopped saving redundant air sample information in commit 0089dd8819b7
("Don't save cylinder start/end pressures unless set by hand").
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Removed start and end in save_cylinder_info(). These two variables are no
longer used.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2012-09-21 21:06:57 +00:00
|
|
|
static int nr_cylinders(struct dive *dive)
|
|
|
|
{
|
|
|
|
int nr;
|
|
|
|
|
|
|
|
for (nr = MAX_CYLINDERS; nr; --nr) {
|
|
|
|
cylinder_t *cylinder = dive->cylinder+nr-1;
|
|
|
|
if (!cylinder_nodata(cylinder))
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return nr;
|
|
|
|
}
|
|
|
|
|
2011-09-04 03:31:18 +00:00
|
|
|
static void save_cylinder_info(FILE *f, struct dive *dive)
|
2011-09-01 23:27:52 +00:00
|
|
|
{
|
Fix missing save of (almost empty) cylinder information
If we have no explicit cylinder info at all (it's normal air, no size or
working pressure information, and no beginning/end pressure information),
we don't save the cylinders in question because that would be redundant.
Such non-saved cylinders may still show up in the equipment list because
there may be implicit mention of them elsewhere, notably due to sample
data, so not saving them is the right thing to do - there is nothing to
save.
However, we missed one case: if there were other cylinders that *did* have
explicit information in it following such an uninteresting cylinder, we do
need to save the cylinder information for the useless case - if only in
order to be able to save the non-useless information for subsequent
cylinders.
This patch does that. Now, if you had an air-filled cylinder with no
information as your first cylinder, and a 51% nitrox as your second one,
it will save that information as
<cylinder />
<cylinder o2='51.0%' />
rather than dropping the cylinder information entirely.
This bug has been there for a long time, and was hidden by the fact that
normally you'd fill in cylinder descriptions etc after importing new
dives. It also used to be that we saved the cylinder beginning/end
pressure even if that was generated from the sample data, so if you
imported from a air-integrated computer and had samples for that cylinder,
we used to save it even though it was technically redundant.
We stopped saving redundant air sample information in commit 0089dd8819b7
("Don't save cylinder start/end pressures unless set by hand").
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Removed start and end in save_cylinder_info(). These two variables are no
longer used.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2012-09-21 21:06:57 +00:00
|
|
|
int i, nr;
|
2011-09-01 23:27:52 +00:00
|
|
|
|
Fix missing save of (almost empty) cylinder information
If we have no explicit cylinder info at all (it's normal air, no size or
working pressure information, and no beginning/end pressure information),
we don't save the cylinders in question because that would be redundant.
Such non-saved cylinders may still show up in the equipment list because
there may be implicit mention of them elsewhere, notably due to sample
data, so not saving them is the right thing to do - there is nothing to
save.
However, we missed one case: if there were other cylinders that *did* have
explicit information in it following such an uninteresting cylinder, we do
need to save the cylinder information for the useless case - if only in
order to be able to save the non-useless information for subsequent
cylinders.
This patch does that. Now, if you had an air-filled cylinder with no
information as your first cylinder, and a 51% nitrox as your second one,
it will save that information as
<cylinder />
<cylinder o2='51.0%' />
rather than dropping the cylinder information entirely.
This bug has been there for a long time, and was hidden by the fact that
normally you'd fill in cylinder descriptions etc after importing new
dives. It also used to be that we saved the cylinder beginning/end
pressure even if that was generated from the sample data, so if you
imported from a air-integrated computer and had samples for that cylinder,
we used to save it even though it was technically redundant.
We stopped saving redundant air sample information in commit 0089dd8819b7
("Don't save cylinder start/end pressures unless set by hand").
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Removed start and end in save_cylinder_info(). These two variables are no
longer used.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2012-09-21 21:06:57 +00:00
|
|
|
nr = nr_cylinders(dive);
|
|
|
|
|
|
|
|
for (i = 0; i < nr; i++) {
|
2011-09-04 03:31:18 +00:00
|
|
|
cylinder_t *cylinder = dive->cylinder+i;
|
|
|
|
int volume = cylinder->type.size.mliter;
|
2011-09-04 20:34:22 +00:00
|
|
|
const char *description = cylinder->type.description;
|
2011-09-04 03:31:18 +00:00
|
|
|
int o2 = cylinder->gasmix.o2.permille;
|
|
|
|
int he = cylinder->gasmix.he.permille;
|
2011-09-01 23:27:52 +00:00
|
|
|
|
2011-09-04 03:31:18 +00:00
|
|
|
fprintf(f, " <cylinder");
|
Don't save cylinder working pressure
It was a mistake to save it - and I did it just because other dive
managers did. It's a totally nonsensical measure, and nobody cares.
The only thing that matters is the size of the cylinder, and the
*actual* pressures. Those give actual air consumption numbers, and are
meaningful and unambiguous.
So the "working pressure" for a cylinder is pointless except for two
things:
- if you don't know the actual physical size, you need the "working
pressure" along with the air size (eg "85 cuft") in order to compute
the physical size. So we do use the working pressure on *input* from
systems that report cylinder sizes that way.
- People may well want to know what kind of cylinder they were diving,
and again, you can make a good guess about this from the working
pressure. So saving information like "HP100+" for the cylinder would
be a good thing.
But notice how in neither case do we actually want to save the working
pressure itself. And in fact saving it actually makes the output format
ambiguous: if we give both size and working pressure, what does 'size'
mean? Is it physical size in liters, or air size in cu ft?
So saving working pressure is just wrong. Get rid of it.
I'm going to add some kind of "cylinder description" thing, which we can
save instead (and perhaps guess standard cylinders from input like the
working pressure from dive logs that don't do this sanely - which is all
of them, as far as I can tell).
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2011-09-04 18:23:41 +00:00
|
|
|
if (volume)
|
2011-09-04 21:56:21 +00:00
|
|
|
show_milli(f, " size='", volume, " l", "'");
|
2011-09-10 22:17:33 +00:00
|
|
|
show_pressure(f, cylinder->type.workingpressure, " workpressure='", "'");
|
2011-09-12 20:41:37 +00:00
|
|
|
if (description && *description)
|
2011-09-04 22:07:47 +00:00
|
|
|
fprintf(f, " description='%s'", description);
|
2011-11-10 23:42:37 +00:00
|
|
|
if (o2) {
|
|
|
|
fprintf(f, " o2='%u.%u%%'", FRACTION(o2, 10));
|
|
|
|
if (he)
|
|
|
|
fprintf(f, " he='%u.%u%%'", FRACTION(he, 10));
|
|
|
|
}
|
2011-09-05 16:12:54 +00:00
|
|
|
show_pressure(f, cylinder->start, " start='", "'");
|
|
|
|
show_pressure(f, cylinder->end, " end='", "'");
|
2011-09-04 03:31:18 +00:00
|
|
|
fprintf(f, " />\n");
|
2011-09-01 23:27:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-12-24 03:41:16 +00:00
|
|
|
static void save_weightsystem_info(FILE *f, struct dive *dive)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < MAX_WEIGHTSYSTEMS; i++) {
|
|
|
|
weightsystem_t *ws = dive->weightsystem+i;
|
|
|
|
int grams = ws->weight.grams;
|
|
|
|
const char *description = ws->description;
|
|
|
|
|
|
|
|
/* No weight information at all? */
|
|
|
|
if (grams == 0)
|
|
|
|
return;
|
|
|
|
fprintf(f, " <weightsystem");
|
|
|
|
show_milli(f, " weight='", grams, " kg", "'");
|
|
|
|
if (description && *description)
|
|
|
|
fprintf(f, " description='%s'", description);
|
|
|
|
fprintf(f, " />\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-09-23 01:02:54 +00:00
|
|
|
static void show_index(FILE *f, int value, const char *pre, const char *post)
|
|
|
|
{
|
|
|
|
if (value)
|
|
|
|
fprintf(f, " %s%d%s", pre, value, post);
|
|
|
|
}
|
|
|
|
|
2011-09-01 23:27:52 +00:00
|
|
|
static void save_sample(FILE *f, struct sample *sample)
|
|
|
|
{
|
2011-09-04 21:56:21 +00:00
|
|
|
fprintf(f, " <sample time='%u:%02u min'", FRACTION(sample->time.seconds,60));
|
|
|
|
show_milli(f, " depth='", sample->depth.mm, " m", "'");
|
2011-09-02 00:37:41 +00:00
|
|
|
show_temperature(f, sample->temperature, " temp='", "'");
|
2011-09-04 03:31:18 +00:00
|
|
|
show_pressure(f, sample->cylinderpressure, " pressure='", "'");
|
|
|
|
if (sample->cylinderindex)
|
|
|
|
fprintf(f, " cylinderindex='%d'", sample->cylinderindex);
|
2011-09-02 00:37:41 +00:00
|
|
|
fprintf(f, " />\n");
|
2011-09-01 23:27:52 +00:00
|
|
|
}
|
|
|
|
|
2011-09-23 01:02:54 +00:00
|
|
|
static void save_one_event(FILE *f, struct event *ev)
|
|
|
|
{
|
|
|
|
fprintf(f, " <event time='%d:%02d min'", FRACTION(ev->time.seconds,60));
|
|
|
|
show_index(f, ev->type, "type='", "'");
|
|
|
|
show_index(f, ev->flags, "flags='", "'");
|
|
|
|
show_index(f, ev->value, "value='", "'");
|
2012-08-27 20:19:06 +00:00
|
|
|
show_utf8(f, ev->name, " name='", "'", 1);
|
2011-09-23 01:02:54 +00:00
|
|
|
fprintf(f, " />\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void save_events(FILE *f, struct event *ev)
|
|
|
|
{
|
|
|
|
while (ev) {
|
|
|
|
save_one_event(f, ev);
|
|
|
|
ev = ev->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-11-25 02:50:21 +00:00
|
|
|
static void show_date(FILE *f, timestamp_t when)
|
2012-08-22 05:04:24 +00:00
|
|
|
{
|
2012-09-20 00:35:52 +00:00
|
|
|
struct tm tm;
|
|
|
|
|
2012-11-25 02:50:21 +00:00
|
|
|
utc_mkdate(when, &tm);
|
2012-08-22 05:04:24 +00:00
|
|
|
|
|
|
|
fprintf(f, " date='%04u-%02u-%02u'",
|
2012-09-20 00:35:52 +00:00
|
|
|
tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday);
|
2012-08-30 00:24:15 +00:00
|
|
|
fprintf(f, " time='%02u:%02u:%02u'",
|
2012-09-20 00:35:52 +00:00
|
|
|
tm.tm_hour, tm.tm_min, tm.tm_sec);
|
2012-11-25 02:50:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void save_trip(FILE *f, dive_trip_t *trip)
|
|
|
|
{
|
|
|
|
fprintf(f, "<trip");
|
|
|
|
show_date(f, trip->when);
|
2012-08-22 05:04:24 +00:00
|
|
|
if (trip->location)
|
2012-08-27 22:36:27 +00:00
|
|
|
show_utf8(f, trip->location, " location=\'","\'", 1);
|
New XML format for saving dives
This patch makes the trips nest, and it also fixes the fact that you never
saved the trip notes (you could edit it, but saving would throw it away).
I did *not* change the indentation of the dives, so the trip stuff shows
up the the beginning of the line, at the same level as the <dive> and
<dives> thing. I think it's fairly readable xml, though, and we haven't
really had proper "indentation shows nesting" anyway, since the top-level
"<dives>" thing also didn't indent stuff inside of it.
Anyway, the way I wrote it, it still parses your old "INTRIP" stuff etc,
so as far as I know, it should happily read the old-style XML too. At
least it seemed to work with your xml file that already had the old-style
one (I haven't committed my divetrips, exactly because I didn't like the
new format).
It always saves in the new style, though.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2012-09-30 19:36:18 +00:00
|
|
|
fprintf(f, ">\n");
|
|
|
|
if (trip->notes)
|
|
|
|
show_utf8(f, trip->notes, "<notes>","</notes>\n", 0);
|
2012-08-22 05:04:24 +00:00
|
|
|
}
|
|
|
|
|
2012-11-25 02:50:21 +00:00
|
|
|
static void save_dc(FILE *f, struct dive *dive, struct divecomputer *dc)
|
2011-09-01 23:27:52 +00:00
|
|
|
{
|
|
|
|
int i;
|
2012-11-25 04:29:14 +00:00
|
|
|
|
|
|
|
fprintf(f, " <divecomputer");
|
2012-11-25 19:44:27 +00:00
|
|
|
if (dc->model)
|
|
|
|
show_utf8(f, dc->model, " model='", "'", 1);
|
|
|
|
if (dc->deviceid)
|
|
|
|
fprintf(f, " deviceid='%08x'", dc->deviceid);
|
|
|
|
if (dc->diveid)
|
|
|
|
fprintf(f, " diveid='%08x'", dc->diveid);
|
2012-11-25 04:29:14 +00:00
|
|
|
if (dc->when && dc->when != dive->when)
|
|
|
|
show_date(f, dc->when);
|
|
|
|
fprintf(f, ">\n");
|
2012-11-25 02:50:21 +00:00
|
|
|
save_events(f, dc->events);
|
|
|
|
for (i = 0; i < dc->samples; i++)
|
|
|
|
save_sample(f, dc->sample+i);
|
2012-11-25 04:29:14 +00:00
|
|
|
fprintf(f, " </divecomputer>\n");
|
2012-11-25 02:50:21 +00:00
|
|
|
}
|
2012-09-20 00:35:52 +00:00
|
|
|
|
2012-11-25 02:50:21 +00:00
|
|
|
static void save_dive(FILE *f, struct dive *dive)
|
|
|
|
{
|
|
|
|
struct divecomputer *dc;
|
2011-09-01 23:27:52 +00:00
|
|
|
|
2011-09-11 18:36:33 +00:00
|
|
|
fputs("<dive", f);
|
2011-09-11 18:36:33 +00:00
|
|
|
if (dive->number)
|
|
|
|
fprintf(f, " number='%d'", dive->number);
|
2012-11-26 22:52:07 +00:00
|
|
|
if (dive->tripflag == NO_TRIP)
|
|
|
|
fprintf(f, " tripflag='NOTRIP'");
|
2011-12-08 04:49:22 +00:00
|
|
|
if (dive->rating)
|
|
|
|
fprintf(f, " rating='%d'", dive->rating);
|
2012-10-28 22:49:02 +00:00
|
|
|
if (dive->visibility)
|
|
|
|
fprintf(f, " visibility='%d'", dive->visibility);
|
2012-11-25 02:50:21 +00:00
|
|
|
show_date(f, dive->when);
|
2011-09-11 18:36:33 +00:00
|
|
|
fprintf(f, " duration='%u:%02u min'>\n",
|
2011-09-05 16:39:55 +00:00
|
|
|
FRACTION(dive->duration.seconds, 60));
|
2011-09-01 23:27:52 +00:00
|
|
|
save_overview(f, dive);
|
2011-09-04 03:31:18 +00:00
|
|
|
save_cylinder_info(f, dive);
|
2011-12-24 03:41:16 +00:00
|
|
|
save_weightsystem_info(f, dive);
|
2012-11-25 02:50:21 +00:00
|
|
|
|
|
|
|
/* Save the dive computer data */
|
|
|
|
dc = &dive->dc;
|
|
|
|
do {
|
|
|
|
save_dc(f, dive, dc);
|
|
|
|
dc = dc->next;
|
|
|
|
} while (dc);
|
|
|
|
|
2011-09-01 23:27:52 +00:00
|
|
|
fprintf(f, "</dive>\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
#define VERSION 1
|
|
|
|
|
|
|
|
void save_dives(const char *filename)
|
|
|
|
{
|
|
|
|
int i;
|
New XML format for saving dives
This patch makes the trips nest, and it also fixes the fact that you never
saved the trip notes (you could edit it, but saving would throw it away).
I did *not* change the indentation of the dives, so the trip stuff shows
up the the beginning of the line, at the same level as the <dive> and
<dives> thing. I think it's fairly readable xml, though, and we haven't
really had proper "indentation shows nesting" anyway, since the top-level
"<dives>" thing also didn't indent stuff inside of it.
Anyway, the way I wrote it, it still parses your old "INTRIP" stuff etc,
so as far as I know, it should happily read the old-style XML too. At
least it seemed to work with your xml file that already had the old-style
one (I haven't committed my divetrips, exactly because I didn't like the
new format).
It always saves in the new style, though.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2012-09-30 19:36:18 +00:00
|
|
|
struct dive *dive;
|
|
|
|
dive_trip_t *trip = NULL;
|
2012-08-22 05:04:24 +00:00
|
|
|
|
2012-10-03 14:29:01 +00:00
|
|
|
FILE *f = g_fopen(filename, "w");
|
2011-09-01 23:27:52 +00:00
|
|
|
|
|
|
|
if (!f)
|
|
|
|
return;
|
2011-09-02 02:56:04 +00:00
|
|
|
|
|
|
|
/* Flush any edits of current dives back to the dives! */
|
2011-09-11 19:53:59 +00:00
|
|
|
update_dive(current_dive);
|
2011-09-02 02:56:04 +00:00
|
|
|
|
2011-09-15 16:43:14 +00:00
|
|
|
fprintf(f, "<dives>\n<program name='subsurface' version='%d'></program>\n", VERSION);
|
2012-08-22 05:04:24 +00:00
|
|
|
|
|
|
|
/* save the dives */
|
New XML format for saving dives
This patch makes the trips nest, and it also fixes the fact that you never
saved the trip notes (you could edit it, but saving would throw it away).
I did *not* change the indentation of the dives, so the trip stuff shows
up the the beginning of the line, at the same level as the <dive> and
<dives> thing. I think it's fairly readable xml, though, and we haven't
really had proper "indentation shows nesting" anyway, since the top-level
"<dives>" thing also didn't indent stuff inside of it.
Anyway, the way I wrote it, it still parses your old "INTRIP" stuff etc,
so as far as I know, it should happily read the old-style XML too. At
least it seemed to work with your xml file that already had the old-style
one (I haven't committed my divetrips, exactly because I didn't like the
new format).
It always saves in the new style, though.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2012-09-30 19:36:18 +00:00
|
|
|
for_each_dive(i, dive) {
|
|
|
|
dive_trip_t *thistrip = dive->divetrip;
|
|
|
|
if (trip != thistrip) {
|
|
|
|
/* Close the old trip? */
|
|
|
|
if (trip)
|
|
|
|
fprintf(f, "</trip>\n");
|
|
|
|
/* Open the new one */
|
|
|
|
if (thistrip)
|
|
|
|
save_trip(f, thistrip);
|
|
|
|
trip = thistrip;
|
|
|
|
}
|
2011-09-01 23:27:52 +00:00
|
|
|
save_dive(f, get_dive(i));
|
New XML format for saving dives
This patch makes the trips nest, and it also fixes the fact that you never
saved the trip notes (you could edit it, but saving would throw it away).
I did *not* change the indentation of the dives, so the trip stuff shows
up the the beginning of the line, at the same level as the <dive> and
<dives> thing. I think it's fairly readable xml, though, and we haven't
really had proper "indentation shows nesting" anyway, since the top-level
"<dives>" thing also didn't indent stuff inside of it.
Anyway, the way I wrote it, it still parses your old "INTRIP" stuff etc,
so as far as I know, it should happily read the old-style XML too. At
least it seemed to work with your xml file that already had the old-style
one (I haven't committed my divetrips, exactly because I didn't like the
new format).
It always saves in the new style, though.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2012-09-30 19:36:18 +00:00
|
|
|
}
|
|
|
|
if (trip)
|
|
|
|
fprintf(f, "</trip>\n");
|
2011-09-01 23:27:52 +00:00
|
|
|
fprintf(f, "</dives>\n");
|
2011-09-04 16:50:31 +00:00
|
|
|
fclose(f);
|
2011-09-01 23:27:52 +00:00
|
|
|
}
|