+struct cylinder_widget {
+ int index, changed;
+ const char *name;
+ GtkWidget *hbox;
+ GtkComboBox *description;
+ GtkSpinButton *size, *pressure;
+ GtkWidget *o2, *gasmix_button;
+};
+
+static struct cylinder_widget gtk_cylinder[MAX_CYLINDERS];
+
+static void set_cylinder_spinbuttons(struct cylinder_widget *cylinder, int ml, int mbar)
+{
+ double volume, pressure;
+
+ volume = ml / 1000.0;
+ pressure = mbar / 1000.0;
+ if (mbar) {
+ if (output_units.volume == CUFT) {
+ volume /= 28.3168466; /* Liters to cuft */
+ volume *= pressure / 1.01325;
+ }
+ if (output_units.pressure == PSI) {
+ pressure *= 14.5037738; /* Bar to PSI */
+ }
+ }
+
+ gtk_spin_button_set_value(cylinder->size, volume);
+ gtk_spin_button_set_value(cylinder->pressure, pressure);
+}
+
+static void cylinder_cb(GtkComboBox *combo_box, gpointer data)
+{
+ GtkTreeIter iter;
+ GtkTreeModel *model = gtk_combo_box_get_model(combo_box);
+ GValue value1 = {0, }, value2 = {0,};
+ struct cylinder_widget *cylinder = data;
+ cylinder_t *cyl = current_dive->cylinder + cylinder->index;
+
+ /* Did the user set it to some non-standard value? */
+ if (!gtk_combo_box_get_active_iter(combo_box, &iter)) {
+ cylinder->changed = 1;
+ return;
+ }
+
+ /*
+ * We get "change" signal callbacks just because we set
+ * the description by hand. Whatever. So ignore them if
+ * they are no-ops.
+ */
+ if (!cylinder->changed && cyl->type.description) {
+ int same;
+ char *desc = gtk_combo_box_get_active_text(combo_box);
+
+ same = !strcmp(desc, cyl->type.description);
+ g_free(desc);
+ if (same)
+ return;
+ }
+ cylinder->changed = 1;
+
+ gtk_tree_model_get_value(model, &iter, 1, &value1);
+ gtk_tree_model_get_value(model, &iter, 2, &value2);
+
+ set_cylinder_spinbuttons(cylinder, g_value_get_int(&value1), g_value_get_int(&value2));
+}
+
+/*
+ * The gtk_tree_model_foreach() interface is bad. It could have
+ * returned whether the callback ever returned true
+ */
+static int found_match = 0;