2011-09-20 19:40:34 +00:00
|
|
|
/* main.c */
|
2012-10-11 00:42:59 +00:00
|
|
|
#include <locale.h>
|
2011-08-31 01:40:25 +00:00
|
|
|
#include <stdio.h>
|
2011-09-02 23:40:28 +00:00
|
|
|
#include <string.h>
|
2011-08-31 01:40:25 +00:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <time.h>
|
2012-10-11 00:42:59 +00:00
|
|
|
#include <libintl.h>
|
|
|
|
#include <glib/gi18n.h>
|
2011-08-31 01:40:25 +00:00
|
|
|
|
|
|
|
#include "dive.h"
|
2011-09-05 19:12:58 +00:00
|
|
|
#include "divelist.h"
|
2011-09-20 18:24:15 +00:00
|
|
|
|
2012-09-26 15:30:37 +00:00
|
|
|
#ifdef DEBUGFILE
|
|
|
|
char *debugfilename;
|
|
|
|
FILE *debugfile;
|
|
|
|
#endif
|
|
|
|
|
2011-09-07 02:07:17 +00:00
|
|
|
struct units output_units;
|
|
|
|
|
2011-09-20 19:40:34 +00:00
|
|
|
/* random helper functions, used here or elsewhere */
|
2011-08-31 01:40:25 +00:00
|
|
|
static int sortfn(const void *_a, const void *_b)
|
|
|
|
{
|
|
|
|
const struct dive *a = *(void **)_a;
|
|
|
|
const struct dive *b = *(void **)_b;
|
|
|
|
|
|
|
|
if (a->when < b->when)
|
|
|
|
return -1;
|
|
|
|
if (a->when > b->when)
|
|
|
|
return 1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-09-20 19:40:34 +00:00
|
|
|
const char *weekday(int wday)
|
|
|
|
{
|
2012-10-11 00:42:59 +00:00
|
|
|
static const char wday_array[7][7] = {
|
|
|
|
/*++GETTEXT: these are three letter days - we allow up to six code bytes */
|
|
|
|
N_("Sun"), N_("Mon"), N_("Tue"), N_("Wed"), N_("Thu"), N_("Fri"), N_("Sat")
|
2011-09-20 19:40:34 +00:00
|
|
|
};
|
2012-10-15 21:37:59 +00:00
|
|
|
return _(wday_array[wday]);
|
2011-09-20 19:40:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
const char *monthname(int mon)
|
|
|
|
{
|
2012-10-11 00:42:59 +00:00
|
|
|
static const char month_array[12][7] = {
|
|
|
|
/*++GETTEXT: these are three letter months - we allow up to six code bytes*/
|
|
|
|
N_("Jan"), N_("Feb"), N_("Mar"), N_("Apr"), N_("May"), N_("Jun"),
|
|
|
|
N_("Jul"), N_("Aug"), N_("Sep"), N_("Oct"), N_("Nov"), N_("Dec"),
|
2011-09-20 19:40:34 +00:00
|
|
|
};
|
2012-10-15 21:37:59 +00:00
|
|
|
return _(month_array[mon]);
|
2011-09-20 19:40:34 +00:00
|
|
|
}
|
|
|
|
|
2011-10-05 15:31:31 +00:00
|
|
|
/*
|
|
|
|
* When adding dives to the dive table, we try to renumber
|
|
|
|
* the new dives based on any old dives in the dive table.
|
|
|
|
*
|
|
|
|
* But we only do it if:
|
|
|
|
*
|
|
|
|
* - the last dive in the old dive table was numbered
|
|
|
|
*
|
|
|
|
* - all the new dives are strictly at the end (so the
|
|
|
|
* "last dive" is at the same location in the dive table
|
|
|
|
* after re-sorting the dives.
|
|
|
|
*
|
|
|
|
* - none of the new dives have any numbers
|
|
|
|
*
|
|
|
|
* This catches the common case of importing new dives from
|
|
|
|
* a dive computer, and gives them proper numbers based on
|
|
|
|
* your old dive list. But it tries to be very conservative
|
|
|
|
* and not give numbers if there is *any* question about
|
|
|
|
* what the numbers should be - in which case you need to do
|
|
|
|
* a manual re-numbering.
|
|
|
|
*/
|
|
|
|
static void try_to_renumber(struct dive *last, int preexisting)
|
|
|
|
{
|
|
|
|
int i, nr;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If the new dives aren't all strictly at the end,
|
|
|
|
* we're going to expect the user to do a manual
|
|
|
|
* renumbering.
|
|
|
|
*/
|
|
|
|
if (get_dive(preexisting-1) != last)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If any of the new dives already had a number,
|
|
|
|
* we'll have to do a manual renumbering.
|
|
|
|
*/
|
|
|
|
for (i = preexisting; i < dive_table.nr; i++) {
|
|
|
|
struct dive *dive = get_dive(i);
|
|
|
|
if (dive->number)
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Ok, renumber..
|
|
|
|
*/
|
|
|
|
nr = last->number;
|
|
|
|
for (i = preexisting; i < dive_table.nr; i++) {
|
|
|
|
struct dive *dive = get_dive(i);
|
|
|
|
dive->number = ++nr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-10-05 21:09:49 +00:00
|
|
|
/*
|
|
|
|
* track whether we switched to importing dives
|
|
|
|
*/
|
|
|
|
static gboolean imported = FALSE;
|
|
|
|
|
2011-08-31 02:48:00 +00:00
|
|
|
/*
|
|
|
|
* This doesn't really report anything at all. We just sort the
|
|
|
|
* dives, the GUI does the reporting
|
|
|
|
*/
|
2012-01-05 16:16:08 +00:00
|
|
|
void report_dives(gboolean is_imported)
|
2011-08-31 01:40:25 +00:00
|
|
|
{
|
2011-09-02 23:40:28 +00:00
|
|
|
int i;
|
2011-10-05 15:31:31 +00:00
|
|
|
int preexisting = dive_table.preexisting;
|
|
|
|
struct dive *last;
|
|
|
|
|
|
|
|
/* This does the right thing for -1: NULL */
|
|
|
|
last = get_dive(preexisting-1);
|
2011-09-02 23:40:28 +00:00
|
|
|
|
2011-08-31 01:40:25 +00:00
|
|
|
qsort(dive_table.dives, dive_table.nr, sizeof(struct dive *), sortfn);
|
2011-09-02 23:40:28 +00:00
|
|
|
|
|
|
|
for (i = 1; i < dive_table.nr; i++) {
|
|
|
|
struct dive **pp = &dive_table.dives[i-1];
|
|
|
|
struct dive *prev = pp[0];
|
|
|
|
struct dive *dive = pp[1];
|
|
|
|
struct dive *merged;
|
|
|
|
|
|
|
|
if (prev->when + prev->duration.seconds < dive->when)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
merged = try_to_merge(prev, dive);
|
|
|
|
if (!merged)
|
|
|
|
continue;
|
|
|
|
|
2012-09-16 03:47:53 +00:00
|
|
|
/* careful - we might free the dive that last points to. Oops... */
|
|
|
|
if (last == prev || last == dive)
|
|
|
|
last = merged;
|
2011-09-02 23:40:28 +00:00
|
|
|
free(prev);
|
|
|
|
free(dive);
|
|
|
|
*pp = merged;
|
|
|
|
dive_table.nr--;
|
|
|
|
memmove(pp+1, pp+2, sizeof(*pp)*(dive_table.nr - i));
|
|
|
|
|
|
|
|
/* Redo the new 'i'th dive */
|
|
|
|
i--;
|
|
|
|
}
|
2011-10-05 15:06:48 +00:00
|
|
|
|
2012-01-05 16:16:08 +00:00
|
|
|
if (is_imported) {
|
2011-10-05 18:36:15 +00:00
|
|
|
/* Was the previous dive table state numbered? */
|
|
|
|
if (last && last->number)
|
|
|
|
try_to_renumber(last, preexisting);
|
2011-10-05 15:31:31 +00:00
|
|
|
|
2012-09-10 21:44:48 +00:00
|
|
|
/* did we add dives to the dive table? */
|
|
|
|
if (preexisting != dive_table.nr)
|
2011-10-05 18:36:15 +00:00
|
|
|
mark_divelist_changed(TRUE);
|
|
|
|
}
|
2011-10-05 15:31:31 +00:00
|
|
|
dive_table.preexisting = dive_table.nr;
|
2011-10-05 15:06:48 +00:00
|
|
|
dive_list_update_dives();
|
2011-08-31 01:40:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void parse_argument(const char *arg)
|
|
|
|
{
|
|
|
|
const char *p = arg+1;
|
|
|
|
|
|
|
|
do {
|
|
|
|
switch (*p) {
|
|
|
|
case 'v':
|
|
|
|
verbose++;
|
|
|
|
continue;
|
2011-10-05 18:36:15 +00:00
|
|
|
case '-':
|
|
|
|
/* long options with -- */
|
|
|
|
if (strcmp(arg,"--import") == 0) {
|
|
|
|
/* mark the dives so far as the base,
|
|
|
|
* everything after is imported */
|
2011-10-05 21:09:49 +00:00
|
|
|
report_dives(FALSE);
|
|
|
|
imported = TRUE;
|
2011-10-05 18:36:15 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
/* fallthrough */
|
2011-10-30 19:56:28 +00:00
|
|
|
case 'p':
|
|
|
|
/* ignore process serial number argument when run as native macosx app */
|
|
|
|
if (strncmp(arg, "-psn_", 5) == 0) {
|
|
|
|
return;
|
|
|
|
}
|
2012-08-26 21:41:05 +00:00
|
|
|
/* fallthrough */
|
2011-08-31 01:40:25 +00:00
|
|
|
default:
|
|
|
|
fprintf(stderr, "Bad argument '%s'\n", arg);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
} while (*++p);
|
|
|
|
}
|
|
|
|
|
2011-09-10 00:10:17 +00:00
|
|
|
void update_dive(struct dive *new_dive)
|
|
|
|
{
|
|
|
|
static struct dive *buffered_dive;
|
|
|
|
struct dive *old_dive = buffered_dive;
|
|
|
|
|
|
|
|
if (old_dive) {
|
2011-09-20 17:06:24 +00:00
|
|
|
flush_divelist(old_dive);
|
2011-09-10 00:10:17 +00:00
|
|
|
}
|
|
|
|
if (new_dive) {
|
|
|
|
show_dive_info(new_dive);
|
2012-08-15 22:21:34 +00:00
|
|
|
show_dive_equipment(new_dive, W_IDX_PRIMARY);
|
2011-11-02 16:10:57 +00:00
|
|
|
show_dive_stats(new_dive);
|
2011-09-10 00:10:17 +00:00
|
|
|
}
|
2011-09-11 20:43:37 +00:00
|
|
|
buffered_dive = new_dive;
|
2011-09-10 00:10:17 +00:00
|
|
|
}
|
|
|
|
|
2011-09-20 19:40:34 +00:00
|
|
|
void renumber_dives(int nr)
|
2011-09-11 22:39:46 +00:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < dive_table.nr; i++) {
|
|
|
|
struct dive *dive = dive_table.dives[i];
|
|
|
|
dive->number = nr + i;
|
2011-10-23 15:50:14 +00:00
|
|
|
flush_divelist(dive);
|
2011-09-11 22:39:46 +00:00
|
|
|
}
|
2011-10-05 16:24:52 +00:00
|
|
|
mark_divelist_changed(TRUE);
|
2011-09-11 22:39:46 +00:00
|
|
|
}
|
|
|
|
|
2011-08-31 01:40:25 +00:00
|
|
|
int main(int argc, char **argv)
|
|
|
|
{
|
|
|
|
int i;
|
2012-09-09 16:06:44 +00:00
|
|
|
gboolean no_filenames = TRUE;
|
2012-10-15 12:44:01 +00:00
|
|
|
const char *path;
|
2011-08-31 01:40:25 +00:00
|
|
|
|
2012-10-11 00:42:59 +00:00
|
|
|
/* set up l18n - the search directory needs to change
|
|
|
|
* so that it uses the correct system directory when
|
|
|
|
* subsurface isn't run from the local directory */
|
2012-10-18 21:30:45 +00:00
|
|
|
path = subsurface_gettext_domainpath(argv[0]);
|
2012-10-15 23:32:11 +00:00
|
|
|
setlocale( LC_ALL, "" );
|
2012-10-15 12:44:01 +00:00
|
|
|
bindtextdomain("subsurface", path);
|
2012-10-11 00:42:59 +00:00
|
|
|
bind_textdomain_codeset("subsurface", "utf-8");
|
|
|
|
textdomain("subsurface");
|
2011-09-07 02:07:17 +00:00
|
|
|
output_units = SI_units;
|
2011-09-27 17:16:40 +00:00
|
|
|
|
2012-10-04 00:44:47 +00:00
|
|
|
subsurface_command_line_init(&argc, &argv);
|
2011-08-31 01:40:25 +00:00
|
|
|
parse_xml_init();
|
|
|
|
|
2011-11-02 00:09:15 +00:00
|
|
|
init_ui(&argc, &argv);
|
2012-08-26 21:41:05 +00:00
|
|
|
|
2012-09-26 15:30:37 +00:00
|
|
|
#ifdef DEBUGFILE
|
|
|
|
debugfilename = (char *)subsurface_default_filename();
|
|
|
|
strncpy(debugfilename + strlen(debugfilename) - 3, "log", 3);
|
|
|
|
if (g_mkdir_with_parents(g_path_get_dirname(debugfilename), 0664) != 0 ||
|
|
|
|
(debugfile = g_fopen(debugfilename, "w")) == NULL)
|
|
|
|
printf("oh boy, can't create debugfile");
|
|
|
|
#endif
|
2011-09-05 20:14:53 +00:00
|
|
|
for (i = 1; i < argc; i++) {
|
|
|
|
const char *a = argv[i];
|
|
|
|
|
|
|
|
if (a[0] == '-') {
|
|
|
|
parse_argument(a);
|
|
|
|
continue;
|
|
|
|
}
|
2012-09-09 16:06:44 +00:00
|
|
|
no_filenames = FALSE;
|
2011-09-05 20:14:53 +00:00
|
|
|
GError *error = NULL;
|
2012-10-09 12:50:16 +00:00
|
|
|
parse_file(a, &error, TRUE);
|
2012-08-26 21:41:05 +00:00
|
|
|
|
2011-09-05 20:14:53 +00:00
|
|
|
if (error != NULL)
|
|
|
|
{
|
|
|
|
report_error(error);
|
|
|
|
g_error_free(error);
|
|
|
|
error = NULL;
|
|
|
|
}
|
|
|
|
}
|
2012-09-09 16:06:44 +00:00
|
|
|
if (no_filenames) {
|
|
|
|
GError *error = NULL;
|
|
|
|
const char *filename = subsurface_default_filename();
|
2012-10-09 12:50:16 +00:00
|
|
|
parse_file(filename, &error, TRUE);
|
2012-09-09 16:06:44 +00:00
|
|
|
/* don't report errors - this file may not exist, but make
|
|
|
|
sure we remember this as the filename in use */
|
2012-09-10 19:27:00 +00:00
|
|
|
set_filename(filename, FALSE);
|
2012-09-30 03:57:48 +00:00
|
|
|
free((void *)filename);
|
2012-09-09 16:06:44 +00:00
|
|
|
}
|
2011-10-05 21:09:49 +00:00
|
|
|
report_dives(imported);
|
2012-09-16 10:04:37 +00:00
|
|
|
if (dive_table.nr == 0)
|
|
|
|
show_dive_info(NULL);
|
2011-09-20 19:40:34 +00:00
|
|
|
run_ui();
|
2012-05-02 17:03:48 +00:00
|
|
|
exit_ui();
|
2012-09-18 15:33:55 +00:00
|
|
|
|
|
|
|
parse_xml_exit();
|
2012-10-04 00:44:47 +00:00
|
|
|
subsurface_command_line_exit(&argc, &argv);
|
2012-09-18 15:33:55 +00:00
|
|
|
|
2012-09-26 15:30:37 +00:00
|
|
|
#ifdef DEBUGFILE
|
|
|
|
if (debugfile)
|
|
|
|
fclose(debugfile);
|
|
|
|
#endif
|
2011-08-31 01:40:25 +00:00
|
|
|
return 0;
|
|
|
|
}
|