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