+gboolean no_cylinders(cylinder_t *cyl)
+{
+ int i;
+
+ for (i = 0; i < MAX_CYLINDERS; i++)
+ if (!cylinder_none(cyl + i))
+ return FALSE;
+ return TRUE;
+}
+
+/* descriptions are equal if they are both NULL or both non-NULL
+ and the same text */
+gboolean description_equal(const char *desc1, const char *desc2)
+{
+ return ((! desc1 && ! desc2) ||
+ (desc1 && desc2 && strcmp(desc1, desc2) == 0));
+}
+
+/* when checking for the same cylinder we want the size and description to match
+ but don't compare the start and end pressures */
+static gboolean one_cylinder_equal(cylinder_t *cyl1, cylinder_t *cyl2)
+{
+ return cyl1->type.size.mliter == cyl2->type.size.mliter &&
+ cyl1->type.workingpressure.mbar == cyl2->type.workingpressure.mbar &&
+ cyl1->gasmix.o2.permille == cyl2->gasmix.o2.permille &&
+ cyl1->gasmix.he.permille == cyl2->gasmix.he.permille &&
+ description_equal(cyl1->type.description, cyl2->type.description);
+}
+
+gboolean cylinders_equal(cylinder_t *cyl1, cylinder_t *cyl2)
+{
+ int i;
+
+ for (i = 0; i < MAX_CYLINDERS; i++)
+ if (!one_cylinder_equal(cyl1 + i, cyl2 + i))
+ return FALSE;
+ return TRUE;
+}
+
+static gboolean weightsystem_none(void *_data)