+
+\f
+
+
+/* Returns the CASENUMth case, or a null pointer on failure.
+ */
+struct ccase *
+psppire_data_store_get_case (const PsppireDataStore *ds,
+ casenumber casenum)
+{
+ g_return_val_if_fail (ds, FALSE);
+ g_return_val_if_fail (ds->datasheet, FALSE);
+
+ return datasheet_get_row (ds->datasheet, casenum);
+}
+
+
+gboolean
+psppire_data_store_delete_cases (PsppireDataStore *ds, casenumber first,
+ casenumber n_cases)
+{
+ g_return_val_if_fail (ds, FALSE);
+ g_return_val_if_fail (ds->datasheet, FALSE);
+
+ g_return_val_if_fail (first + n_cases <=
+ psppire_data_store_get_case_count (ds), FALSE);
+
+
+ datasheet_delete_rows (ds->datasheet, first, n_cases);
+
+ g_signal_emit (ds, signals [CASES_DELETED], 0, first, n_cases);
+ psppire_sheet_model_rows_deleted (PSPPIRE_SHEET_MODEL (ds), first, n_cases);
+
+ return TRUE;
+}
+
+
+
+/* Insert case CC into the case file before POSN */
+static gboolean
+psppire_data_store_insert_case (PsppireDataStore *ds,
+ struct ccase *cc,
+ casenumber posn)
+{
+ bool result ;
+
+ g_return_val_if_fail (ds, FALSE);
+ g_return_val_if_fail (ds->datasheet, FALSE);
+
+ case_ref (cc);
+ result = datasheet_insert_rows (ds->datasheet, posn, &cc, 1);
+
+ if ( result )
+ {
+ g_signal_emit (ds, signals [CASE_INSERTED], 0, posn);
+ psppire_sheet_model_rows_inserted (PSPPIRE_SHEET_MODEL (ds), posn, 1);
+ }
+ else
+ g_warning ("Cannot insert case at position %ld\n", posn);
+
+ return result;
+}
+
+
+/* Copies the IDXth value from case CASENUM into VALUE, which
+ must be of the correct width for IDX.
+ Returns true if successful, false on failure. */
+static bool
+psppire_data_store_get_value (const PsppireDataStore *ds,
+ casenumber casenum, size_t idx,
+ union value *value)
+{
+ g_return_val_if_fail (ds, false);
+ g_return_val_if_fail (ds->datasheet, false);
+ g_return_val_if_fail (idx < datasheet_get_n_columns (ds->datasheet), false);
+
+ return datasheet_get_value (ds->datasheet, casenum, idx, value);
+}
+
+
+
+/* Set the IDXth value of case C to V.
+ V must be the correct width for IDX.
+ Returns true if successful, false on I/O error. */
+static gboolean
+psppire_data_store_set_value (PsppireDataStore *ds, casenumber casenum,
+ gint idx, union value *v)
+{
+ bool ok;
+
+ g_return_val_if_fail (ds, FALSE);
+ g_return_val_if_fail (ds->datasheet, FALSE);
+
+ g_return_val_if_fail (idx < datasheet_get_n_columns (ds->datasheet), FALSE);
+
+ ok = datasheet_put_value (ds->datasheet, casenum, idx, v);
+ if (ok)
+ g_signal_emit (ds, signals [CASE_CHANGED], 0, casenum);
+
+ return ok;
+}
+
+
+
+
+/* Set the IDXth value of case C using D_IN */
+static gboolean
+psppire_data_store_data_in (PsppireDataStore *ds, casenumber casenum, gint idx,
+ struct substring input, const struct fmt_spec *fmt)
+{
+ union value value;
+ int width;
+ bool ok;
+
+ g_return_val_if_fail (ds, FALSE);
+ g_return_val_if_fail (ds->datasheet, FALSE);
+
+ g_return_val_if_fail (idx < datasheet_get_n_columns (ds->datasheet), FALSE);
+
+ width = fmt_var_width (fmt);
+ g_return_val_if_fail (caseproto_get_width (
+ datasheet_get_proto (ds->datasheet), idx) == width,
+ FALSE);
+ value_init (&value, width);
+ ok = (datasheet_get_value (ds->datasheet, casenum, idx, &value)
+ && data_in (input, LEGACY_NATIVE, fmt->type, 0, 0, 0, &value, width)
+ && datasheet_put_value (ds->datasheet, casenum, idx, &value));
+ value_destroy (&value, width);
+
+ if (ok)
+ g_signal_emit (ds, signals [CASE_CHANGED], 0, casenum);
+
+ return ok;
+}
+
+/* Resize the cases in the casefile, by inserting a value of the
+ given WIDTH into every one of them at the position immediately
+ preceding WHERE.
+*/
+static gboolean
+psppire_data_store_insert_value (PsppireDataStore *ds,
+ gint width, gint where)
+{
+ union value value;
+
+ g_return_val_if_fail (ds, FALSE);
+
+ g_assert (width >= 0);
+
+ if ( ! ds->datasheet )
+ ds->datasheet = datasheet_create (NULL);
+
+ value_init (&value, width);
+ if (width == 0)
+ value.f = 0;
+ else
+ value_set_missing (&value, width);
+
+ datasheet_insert_column (ds->datasheet, &value, width, where);
+
+ return TRUE;
+}
+
+static gboolean
+get_row_overstrike (const PsppireSheetModel *model, gint row)
+{
+ union value val;
+ PsppireDataStore *ds = PSPPIRE_DATA_STORE (model);
+
+ const struct dictionary *dict = ds->dict->dict;
+
+ const struct variable *filter = dict_get_filter (dict);
+
+ if ( row < 0 || row >= datasheet_get_n_rows (ds->datasheet))
+ return FALSE;
+
+ if ( ! filter)
+ return FALSE;
+
+ g_assert (var_is_numeric (filter));
+
+ value_init (&val, 0);
+ if ( ! datasheet_get_value (ds->datasheet, row,
+ var_get_case_index (filter),
+ &val) )
+ return FALSE;
+
+
+ return (val.f == 0.0);
+}