summaryrefslogblamecommitdiffstats
path: root/main.c
blob: 20f3fb97ecf449ca1ff67e5c032bc24dcc97316a (plain) (tree)
1
2
3
4
5
6
7
8
9
10
            
                   
                  
                   
                   
                       
                 
                     
 



                    
                          
                                                     










                                                 
                             

                                                                                           
          
                                   


                              


                                                                                            
          
                                   
 
  



















































                                                               



                                               

                                                               
                                       
 
              



                                                    
 
                                                                              












                                                                     

                                                                                   







                                                                     
 
                          

                                                                 
 
                                                         
                                                    
                                               
                                 









                                           



                                                                     
                                                    

                                         



                                                                                                 
                                         





                                                                    




                                              
                                         
         
                                 
                       
                                                             
                                          
         
                                 
 
                           




                                                        
                                     
         
                                    
 

                               
                                     
                         
 

                                                             
                                                      
                                
                                           
                                                       
                                
 
                                                   
                         
                              
 





                                                                                 





                                          
                                     
                                     
                                            
 





                                            

                                                                     
                                                   
                                                                          
                                              
                                       
         
                               
                                     
                 
                  
                         
                                                   
 


                                  
                 
/* main.c */
#include <locale.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <libintl.h>
#include <glib/gi18n.h>

#include "dive.h"
#include "divelist.h"

#ifdef DEBUGFILE
char *debugfilename;
FILE *debugfile;
#endif

struct units output_units;

/* random helper functions, used here or elsewhere */
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;
}

const char *weekday(int wday)
{
	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")
	};
	return _(wday_array[wday]);
}

const char *monthname(int mon)
{
	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"),
	};
	return _(month_array[mon]);
}

/*
 * 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;
	}
}

/*
 * track whether we switched to importing dives
 */
static gboolean imported = FALSE;

/*
 * This doesn't really report anything at all. We just sort the
 * dives, the GUI does the reporting
 */
void report_dives(gboolean is_imported)
{
	int i;
	int preexisting = dive_table.preexisting;
	struct dive *last;

	/* This does the right thing for -1: NULL */
	last = get_dive(preexisting-1);

	qsort(dive_table.dives, dive_table.nr, sizeof(struct dive *), sortfn);

	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;

		/* careful - we might free the dive that last points to. Oops... */
		if (last == prev || last == dive)
			last = merged;
		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--;
	}

	if (is_imported) {
		/* Was the previous dive table state numbered? */
		if (last && last->number)
			try_to_renumber(last, preexisting);

		/* did we add dives to the dive table? */
		if (preexisting != dive_table.nr)
			mark_divelist_changed(TRUE);
	}
	dive_table.preexisting = dive_table.nr;
	dive_list_update_dives();
}

static void parse_argument(const char *arg)
{
	const char *p = arg+1;

	do {
		switch (*p) {
		case 'v':
			verbose++;
			continue;
		case '-':
			/* long options with -- */
			if (strcmp(arg,"--import") == 0) {
				/* mark the dives so far as the base,
				 * everything after is imported */
				report_dives(FALSE);
				imported = TRUE;
				return;
			}
			/* fallthrough */
		case 'p':
			/* ignore process serial number argument when run as native macosx app */
			if (strncmp(arg, "-psn_", 5) == 0) {
				return;
			}
			/* fallthrough */
		default:
			fprintf(stderr, "Bad argument '%s'\n", arg);
			exit(1);
		}
	} while (*++p);
}

void update_dive(struct dive *new_dive)
{
	static struct dive *buffered_dive;
	struct dive *old_dive = buffered_dive;

	if (old_dive) {
		flush_divelist(old_dive);
	}
	show_dive_info(new_dive);
	if (new_dive) {
		show_dive_equipment(new_dive, W_IDX_PRIMARY);
		show_dive_stats(new_dive);
	}
	buffered_dive = new_dive;
}

void renumber_dives(int nr)
{
	int i;

	for (i = 0; i < dive_table.nr; i++) {
		struct dive *dive = dive_table.dives[i];
		dive->number = nr + i;
		flush_divelist(dive);
	}
	mark_divelist_changed(TRUE);
}

int main(int argc, char **argv)
{
	int i;
	gboolean no_filenames = TRUE;
	const char *path;

	/* 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 */
	path = subsurface_gettext_domainpath(argv[0]);
	setlocale( LC_ALL, "" );
	bindtextdomain("subsurface", path);
	bind_textdomain_codeset("subsurface", "utf-8");
	textdomain("subsurface");
	output_units = SI_units;

	subsurface_command_line_init(&argc, &argv);
	parse_xml_init();

	init_ui(&argc, &argv);

#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
	for (i = 1; i < argc; i++) {
		const char *a = argv[i];

		if (a[0] == '-') {
			parse_argument(a);
			continue;
		}
		no_filenames = FALSE;
		GError *error = NULL;
		parse_file(a, &error, TRUE);

		if (error != NULL)
		{
			report_error(error);
			g_error_free(error);
			error = NULL;
		}
	}
	if (no_filenames) {
		GError *error = NULL;
		const char *filename = subsurface_default_filename();
		parse_file(filename, &error, TRUE);
		/* don't report errors - this file may not exist, but make
		   sure we remember this as the filename in use */
		set_filename(filename, FALSE);
		free((void *)filename);
	}
	report_dives(imported);
	if (dive_table.nr == 0)
		show_dive_info(NULL);
	run_ui();
	exit_ui();

	parse_xml_exit();
	subsurface_command_line_exit(&argc, &argv);

#ifdef DEBUGFILE
	if (debugfile)
		fclose(debugfile);
#endif
	return 0;
}