+#if DEBUG_SELECTION_TRACKING
+ printf("add %d to selection of %d entries\n", idx, amount_selected);
+#endif
+ if (is_in_st(idx, NULL))
+ return;
+ if (amount_selected >= st_size) {
+ selectiontracker = realloc(selectiontracker, dive_table.nr * sizeof(int));
+ st_size = dive_table.nr;
+ }
+ selectiontracker[amount_selected] = idx;
+ amount_selected++;
+ if (amount_selected == 1)
+ selected_dive = idx;
+#if DEBUG_SELECTION_TRACKING
+ printf("increased amount_selected to %d\n", amount_selected);
+ dump_selection();
+#endif
+}
+
+void track_unselect(int idx)
+{
+ if (idx < 0)
+ return;
+
+#if DEBUG_SELECTION_TRACKING
+ printf("remove %d from selection of %d entries\n", idx, amount_selected);
+#endif
+ int atpos;
+
+ if (! is_in_st(idx, &atpos))
+ return;
+ memmove(selectiontracker + atpos,
+ selectiontracker + atpos + 1,
+ (amount_selected - atpos - 1) * sizeof(int));
+ amount_selected--;
+#if DEBUG_SELECTION_TRACKING
+ printf("removed %d at pos %d and decreased amount_selected to %d\n", idx, atpos, amount_selected);
+ dump_selection();
+#endif
+}
+
+/* when subsurface starts we want to have the last dive selected. So we simply
+ walk to the first leaf (and skip the summary entries - which have negative
+ DIVE_INDEX) */
+static void first_leaf(GtkTreeModel *model, GtkTreeIter *iter, int *diveidx)
+{
+ GtkTreeIter parent;
+ GtkTreePath *tpath;
+
+ while (*diveidx < 0) {
+ memcpy(&parent, iter, sizeof(parent));
+ tpath = gtk_tree_model_get_path(model, &parent);
+ if (!gtk_tree_model_iter_children(model, iter, &parent))
+ /* we should never have a parent without child */
+ return;
+ if(!gtk_tree_view_row_expanded(GTK_TREE_VIEW(dive_list.tree_view), tpath))
+ gtk_tree_view_expand_row(GTK_TREE_VIEW(dive_list.tree_view), tpath, FALSE);
+ gtk_tree_model_get(GTK_TREE_MODEL(model), iter, DIVE_INDEX, diveidx, -1);
+ track_select(*diveidx);
+ }
+}
+
+/* if we click on a summary dive, we actually want to select / unselect
+ all the dives "below" it */
+static void select_children(GtkTreeModel *model, GtkTreeSelection * selection,
+ GtkTreeIter *iter, gboolean was_selected)
+{
+ int i, nr_children;
+ gboolean unexpand = FALSE;
+ GtkTreeIter parent;
+ GtkTreePath *tpath;
+
+ memcpy(&parent, iter, sizeof(parent));
+
+ tpath = gtk_tree_model_get_path(model, &parent);
+
+ /* stupid gtk doesn't allow us to select rows that are invisible; so if the
+ user clicks on a row that isn't expanded, we briefly expand it, select the
+ children, and then unexpand it again */
+ if(!gtk_tree_view_row_expanded(GTK_TREE_VIEW(dive_list.tree_view), tpath)) {
+ unexpand = TRUE;
+ gtk_tree_view_expand_row(GTK_TREE_VIEW(dive_list.tree_view), tpath, FALSE);
+ }
+ nr_children = gtk_tree_model_iter_n_children(model, &parent);
+ for (i = 0; i < nr_children; i++) {
+ gtk_tree_model_iter_nth_child(model, iter, &parent, i);
+ if (was_selected)
+ gtk_tree_selection_unselect_iter(selection, iter);
+ else
+ gtk_tree_selection_select_iter(selection, iter);
+ }
+ if (unexpand)
+ gtk_tree_view_collapse_row(GTK_TREE_VIEW(dive_list.tree_view), tpath);
+}
+
+/* make sure that if we expand a summary row that is selected, the children show
+ up as selected, too */
+void row_expanded_cb(GtkTreeView *tree_view, GtkTreeIter *iter, GtkTreePath *path, gpointer data)
+{
+ GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(dive_list.tree_view));
+
+ if (gtk_tree_selection_path_is_selected(selection, path))
+ select_children(GTK_TREE_MODEL(dive_list.model), selection, iter, FALSE);
+}
+
+/* this is called _before_ the selection is changed, for every single entry;
+ * we simply have it call down the tree to make sure that summary items toggle
+ * their children */
+gboolean modify_selection_cb(GtkTreeSelection *selection, GtkTreeModel *model,
+ GtkTreePath *path, gboolean was_selected, gpointer userdata)
+{
+ GtkTreeIter iter;
+ int dive_idx;
+
+ if (gtk_tree_model_get_iter(model, &iter, path)) {
+ gtk_tree_model_get(model, &iter, DIVE_INDEX, &dive_idx, -1);
+ /* turns out we need to move the selectiontracker here */
+ if (was_selected)
+ track_unselect(dive_idx);
+ else
+ track_select(dive_idx);
+ if (dive_idx < 0) {
+ select_children(model, selection, &iter, was_selected);
+ }
+ }
+ /* allow this selection to proceed */
+ return TRUE;
+}
+
+/* this is called when gtk thinks that the selection has changed */
+static void selection_cb(GtkTreeSelection *selection, gpointer userdata)
+{
+ process_selected_dives(selected_dives, selectiontracker, GTK_TREE_MODEL(dive_list.model));