]> git.tdb.fi Git - ext/subsurface.git/blob - main.c
Fix import tracking
[ext/subsurface.git] / main.c
1 /* main.c */
2 #include <stdio.h>
3 #include <string.h>
4 #include <stdlib.h>
5 #include <time.h>
6
7 #include <gconf/gconf-client.h>
8
9 #include "dive.h"
10 #include "divelist.h"
11
12 GConfClient *gconf;
13 struct units output_units;
14
15 #define GCONF_NAME(x) "/apps/subsurface/" #x
16
17 /* random helper functions, used here or elsewhere */
18 static int sortfn(const void *_a, const void *_b)
19 {
20         const struct dive *a = *(void **)_a;
21         const struct dive *b = *(void **)_b;
22
23         if (a->when < b->when)
24                 return -1;
25         if (a->when > b->when)
26                 return 1;
27         return 0;
28 }
29
30 const char *weekday(int wday)
31 {
32         static const char wday_array[7][4] = {
33                 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
34         };
35         return wday_array[wday];
36 }
37
38 const char *monthname(int mon)
39 {
40         static const char month_array[12][4] = {
41                 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
42                 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
43         };
44         return month_array[mon];
45 }
46
47 /*
48  * When adding dives to the dive table, we try to renumber
49  * the new dives based on any old dives in the dive table.
50  *
51  * But we only do it if:
52  *
53  *  - the last dive in the old dive table was numbered
54  *
55  *  - all the new dives are strictly at the end (so the
56  *    "last dive" is at the same location in the dive table
57  *    after re-sorting the dives.
58  *
59  *  - none of the new dives have any numbers
60  *
61  * This catches the common case of importing new dives from
62  * a dive computer, and gives them proper numbers based on
63  * your old dive list. But it tries to be very conservative
64  * and not give numbers if there is *any* question about
65  * what the numbers should be - in which case you need to do
66  * a manual re-numbering.
67  */
68 static void try_to_renumber(struct dive *last, int preexisting)
69 {
70         int i, nr;
71
72         /*
73          * If the new dives aren't all strictly at the end,
74          * we're going to expect the user to do a manual
75          * renumbering.
76          */
77         if (get_dive(preexisting-1) != last)
78                 return;
79
80         /*
81          * If any of the new dives already had a number,
82          * we'll have to do a manual renumbering.
83          */
84         for (i = preexisting; i < dive_table.nr; i++) {
85                 struct dive *dive = get_dive(i);
86                 if (dive->number)
87                         return;
88         }
89
90         /*
91          * Ok, renumber..
92          */
93         nr = last->number;
94         for (i = preexisting; i < dive_table.nr; i++) {
95                 struct dive *dive = get_dive(i);
96                 dive->number = ++nr;
97         }
98 }
99
100 /*
101  * track whether we switched to importing dives
102  */
103 static gboolean imported = FALSE;
104
105 /*
106  * This doesn't really report anything at all. We just sort the
107  * dives, the GUI does the reporting
108  */
109 void report_dives(gboolean imported)
110 {
111         int i;
112         int preexisting = dive_table.preexisting;
113         struct dive *last;
114
115         /* This does the right thing for -1: NULL */
116         last = get_dive(preexisting-1);
117
118         qsort(dive_table.dives, dive_table.nr, sizeof(struct dive *), sortfn);
119
120         for (i = 1; i < dive_table.nr; i++) {
121                 struct dive **pp = &dive_table.dives[i-1];
122                 struct dive *prev = pp[0];
123                 struct dive *dive = pp[1];
124                 struct dive *merged;
125
126                 if (prev->when + prev->duration.seconds < dive->when)
127                         continue;
128
129                 merged = try_to_merge(prev, dive);
130                 if (!merged)
131                         continue;
132
133                 free(prev);
134                 free(dive);
135                 *pp = merged;
136                 dive_table.nr--;
137                 memmove(pp+1, pp+2, sizeof(*pp)*(dive_table.nr - i));
138
139                 /* Redo the new 'i'th dive */
140                 i--;
141         }
142
143         if (imported) {
144                 /* Was the previous dive table state numbered? */
145                 if (last && last->number)
146                         try_to_renumber(last, preexisting);
147
148                 /* did we have dives in the table and added more? */
149                 if (last && preexisting != dive_table.nr)
150                         mark_divelist_changed(TRUE);
151         }
152         dive_table.preexisting = dive_table.nr;
153         dive_list_update_dives();
154 }
155
156 static void parse_argument(const char *arg)
157 {
158         const char *p = arg+1;
159
160         do {
161                 switch (*p) {
162                 case 'v':
163                         verbose++;
164                         continue;
165                 case '-':
166                         /* long options with -- */
167                         if (strcmp(arg,"--import") == 0) {
168                                 /* mark the dives so far as the base,
169                                  * everything after is imported */
170                                 report_dives(FALSE);
171                                 imported = TRUE;
172                                 return;
173                         }
174                         /* fallthrough */
175                 default:
176                         fprintf(stderr, "Bad argument '%s'\n", arg);
177                         exit(1);
178                 }
179         } while (*++p);
180 }
181
182 void update_dive(struct dive *new_dive)
183 {
184         static struct dive *buffered_dive;
185         struct dive *old_dive = buffered_dive;
186
187         if (old_dive) {
188                 flush_dive_info_changes(old_dive);
189                 flush_dive_equipment_changes(old_dive);
190                 flush_divelist(old_dive);
191         }
192         if (new_dive) {
193                 show_dive_info(new_dive);
194                 show_dive_equipment(new_dive);
195         }
196         buffered_dive = new_dive;
197 }
198
199 void renumber_dives(int nr)
200 {
201         int i;
202
203         for (i = 0; i < dive_table.nr; i++) {
204                 struct dive *dive = dive_table.dives[i];
205                 dive->number = nr + i;
206         }
207         mark_divelist_changed(TRUE);
208 }
209
210 int main(int argc, char **argv)
211 {
212         int i;
213
214         output_units = SI_units;
215
216         parse_xml_init();
217
218         init_ui(argc, argv);
219         
220         for (i = 1; i < argc; i++) {
221                 const char *a = argv[i];
222
223                 if (a[0] == '-') {
224                         parse_argument(a);
225                         continue;
226                 }
227                 GError *error = NULL;
228                 parse_xml_file(a, &error);
229                 
230                 if (error != NULL)
231                 {
232                         report_error(error);
233                         g_error_free(error);
234                         error = NULL;
235                 }
236         }
237
238         report_dives(imported);
239
240         run_ui();
241         return 0;
242 }