예제 #1
0
static CritType
criteria_inspect_values (GnmValue const *x, gnm_float *xr, gnm_float *yr,
			 GnmCriteria *crit, gboolean coerce_to_float)
{
	GnmValue const *y = crit->x;

	if (x == NULL || y == NULL)
		return CRIT_NULL;

	switch (y->v_any.type) {
	case VALUE_BOOLEAN:
		/* If we're searching for a bool -- even one that is
		   from a string search value -- we match only bools.  */
		if (!VALUE_IS_BOOLEAN (x))
			return CRIT_WRONGTYPE;
		*xr = value_get_as_float (x);
		*yr = value_get_as_float (y);
		return CRIT_FLOAT;

	case VALUE_EMPTY:
		return CRIT_WRONGTYPE;

	case VALUE_STRING:
		if (!VALUE_IS_STRING (x))
			return CRIT_WRONGTYPE;
		return CRIT_STRING;

	default:
		g_warning ("This should not happen.  Please report.");
		return CRIT_WRONGTYPE;

	case VALUE_FLOAT: {
		GnmValue *vx;
		*yr = value_get_as_float (y);

		if (VALUE_IS_BOOLEAN (x) || VALUE_IS_ERROR (x))
			return CRIT_WRONGTYPE;
		else if (VALUE_IS_FLOAT (x)) {
			*xr = value_get_as_float (x);
			return CRIT_FLOAT;
		}

		if (!coerce_to_float)
			return CRIT_WRONGTYPE;

		vx = format_match (value_peek_string (x), NULL, crit->date_conv);
		if (VALUE_IS_EMPTY (vx) ||
		    VALUE_IS_BOOLEAN (y) != VALUE_IS_BOOLEAN (vx)) {
			value_release (vx);
			return CRIT_WRONGTYPE;
		}

		*xr = value_get_as_float (vx);
		value_release (vx);
		return CRIT_FLOAT;
	}
	}
}
예제 #2
0
/**
 * paste_cell:
 * @target_col:  Column to put the cell into
 * @target_row:  Row to put the cell into.
 * @src:         A #GnmCelCopy with the content to paste
 * @paste_flags: Bit mask that describes the paste options.
 *
 *  Pastes a cell in the spreadsheet.
 */
static void
paste_cell (int target_col, int target_row,
	    GnmCellCopy const *src,
	    const struct paste_cell_data *dat)
{
	Sheet *dst_sheet = dat->pt->sheet;
	int paste_flags = dat->pt->paste_flags;

	if (paste_flags & PASTE_OPER_MASK)
		paste_cell_with_operation (dst_sheet, target_col, target_row,
					   &dat->rinfo, src, paste_flags);
	else {
		GnmCell *dst = sheet_cell_fetch (dst_sheet, target_col, target_row);
		if (NULL != src->texpr && (paste_flags & PASTE_CONTENTS)) {
			GnmExprTop const *relo = gnm_expr_top_relocate (
				src->texpr, &dat->rinfo, FALSE);
			if (paste_flags & PASTE_TRANSPOSE) {
				GnmExprTop const *trelo =
					gnm_expr_top_transpose (relo ? relo : src->texpr);
				if (trelo) {
					if (relo)
						gnm_expr_top_unref (relo);
					relo = trelo;
				}
			} else if (!relo && gnm_expr_top_is_array_corner (src->texpr)) {
				/* We must not share array expressions.  */
				relo = gnm_expr_top_new (gnm_expr_copy (src->texpr->expr));
			}
			gnm_cell_set_expr_and_value (dst, relo ? relo : src->texpr,
						 value_dup (src->val), TRUE);
			if (NULL != relo)
				gnm_expr_top_unref (relo);
		} else {
			GnmValue *newval = NULL;
			GnmValue const *oldval = src->val;

			if (dat->translate_dates && oldval && VALUE_IS_FLOAT (oldval)) {
				GOFormat const *fmt = VALUE_FMT (oldval)
					? VALUE_FMT (oldval)
					: gnm_style_get_format (gnm_cell_get_style (dst));
				if (go_format_is_date (fmt) > 0) {
					gnm_float fnew = go_date_conv_translate
						(value_get_as_float (oldval),
						 dat->cr->date_conv,
						 workbook_date_conv (dst_sheet->workbook));
					newval = value_new_float (fnew);
					value_set_fmt (newval, VALUE_FMT (oldval));
				}
			}

			if (!newval)
				newval = value_dup (src->val);
			gnm_cell_set_value (dst, newval);
		}
	}
}
예제 #3
0
static char *
try_auto_date (GnmValue *value, const GOFormat *format,
	       GODateConventions const *date_conv)
{
	gnm_float v, vr, vs;
	GOFormat *actual;
	char *res;
	gboolean needs_date, needs_time, needs_frac_sec;
	gboolean is_date;
	int is_time;
	GString *xlfmt;
	GDate date;

	format = gnm_format_specialize (format, value);
	is_date = go_format_is_date (format) > 0;
	is_time = go_format_is_time (format);

	if (!is_date && is_time <= 0)
		return NULL;

	/* We don't want to coerce strings.  */
	if (!VALUE_IS_FLOAT (value))
		return NULL;

	/* Verify that the date is valid.  */
	if (!datetime_value_to_g (&date, value, date_conv))
		return NULL;

	v = value_get_as_float (value);
	vr = gnm_fake_round (v);
	vs = (24 * 60 * 60) * gnm_abs (v - vr);

	needs_date = is_time < 2 && (is_date || gnm_abs (v) >= 1);
	needs_time = is_time > 0 || gnm_abs (v - vr) > 1e-9;
	needs_frac_sec = needs_time && gnm_abs (vs - gnm_fake_round (vs)) >= 0.5e-3;

	xlfmt = g_string_new (NULL);
	if (needs_date) g_string_append (xlfmt, "yyyy/mm/dd");
	if (needs_time) {
		if (needs_date)
			g_string_append_c (xlfmt, ' ');
		if (is_time == 2)
			g_string_append (xlfmt, "[h]:mm:ss");
		else
			g_string_append (xlfmt, "hh:mm:ss");
		if (needs_frac_sec)
			g_string_append (xlfmt, ".000");
	}
	actual = go_format_new_from_XL (xlfmt->str);
	g_string_free (xlfmt, TRUE);
	res = format_value (actual, value, -1, date_conv);
	go_format_unref (actual);

	return res;
}
예제 #4
0
/*
 * Finds a column index of a field.
 */
int
find_column_of_field (GnmEvalPos const *ep,
		      GnmValue const *database, GnmValue const *field)
{
        Sheet *sheet;
        GnmCell  *cell;
	gchar *field_name;
	int   begin_col, end_col, row, n, column;
	int   offset;

	// I'm not certain we should demand this, but the code clearly wants
	// it.
	if (!VALUE_IS_CELLRANGE (database))
		return -1;

	offset = database->v_range.cell.a.col;

	if (VALUE_IS_FLOAT (field))
		return value_get_as_int (field) + offset - 1;

	if (!VALUE_IS_STRING (field))
		return -1;

	sheet = eval_sheet (database->v_range.cell.a.sheet, ep->sheet);
	field_name = value_get_as_string (field);
	column = -1;

	/* find the column that is labeled after `field_name' */
	begin_col = database->v_range.cell.a.col;
	end_col = database->v_range.cell.b.col;
	row = database->v_range.cell.a.row;

	for (n = begin_col; n <= end_col; n++) {
		char const *txt;
		gboolean match;

		cell = sheet_cell_get (sheet, n, row);
		if (cell == NULL)
			continue;
		gnm_cell_eval (cell);

		txt = cell->value
			? value_peek_string (cell->value)
			: "";
		match = (g_ascii_strcasecmp (field_name, txt) == 0);
		if (match) {
			column = n;
			break;
		}
	}

	g_free (field_name);
	return column;
}
예제 #5
0
static void
set_value (GnmNlsolve *nl, int i, gnm_float x)
{
	GnmCell *cell = g_ptr_array_index (nl->vars, i);
	if (cell->value &&
	    VALUE_IS_FLOAT (cell->value) &&
	    value_get_as_float (cell->value) == x)
		return;

	gnm_cell_set_value (cell, value_new_float (x));
	cell_queue_recalc (cell);
}
예제 #6
0
static char *
try_auto_float (GnmValue *value, const GOFormat *format,
	       GODateConventions const *date_conv)
{
	gboolean is_date;
	int is_time;

	if (!VALUE_IS_FLOAT (value))
		return NULL;

	format = gnm_format_specialize (format, value);
	is_date = go_format_is_date (format) > 0;
	is_time = go_format_is_time (format);

	if (is_date || is_time > 0)
		return NULL;

	return format_value (go_format_general (), value, -1, date_conv);
}
예제 #7
0
파일: dif.c 프로젝트: GNOME/gnumeric
/*
 * Write _current_ sheet of the workbook to a DIF format file
 */
void
dif_file_save (GOFileSaver const *fs, GOIOContext *io_context,
               WorkbookView const *wbv, GsfOutput *out)
{
	GnmLocale *locale;
	Sheet *sheet;
	GnmRange r;
	gint row, col;
	gboolean ok = TRUE;

	sheet = wb_view_cur_sheet (wbv);
	if (sheet == NULL) {
		go_io_error_string (io_context, _("Cannot get default sheet."));
		return;
	}

	r = sheet_get_extent (sheet, FALSE, TRUE);

	/* Write out the standard headers */
	gsf_output_puts   (out, "TABLE\n"   "0,1\n" "\"GNUMERIC\"\n");
	gsf_output_printf (out, "VECTORS\n" "0,%d\n" "\"\"\n", r.end.col+1);
	gsf_output_printf (out, "TUPLES\n"  "0,%d\n" "\"\"\n", r.end.row+1);
	gsf_output_puts   (out, "DATA\n"    "0,0\n"  "\"\"\n");

	locale = gnm_push_C_locale ();

	/* Process all cells */
	for (row = r.start.row; ok && row <= r.end.row; row++) {
		gsf_output_puts (out, "-1,0\n" "BOT\n");
		for (col = r.start.col; col <= r.end.col; col++) {
			GnmCell *cell = sheet_cell_get (sheet, col, row);
			if (gnm_cell_is_empty (cell)) {
				gsf_output_puts(out, "1,0\n" "\"\"\n");
			} else if (VALUE_IS_BOOLEAN (cell->value)) {
				if (value_get_as_checked_bool (cell->value))
					gsf_output_puts(out, "0,1\n" "TRUE\n");
				else
					gsf_output_puts(out, "0,0\n" "FALSE\n");
			} else if (VALUE_IS_ERROR (cell->value)) {
				if (value_error_classify (cell->value) == GNM_ERROR_NA)
					gsf_output_puts(out, "0,0\n" "NA\n");
				else
					gsf_output_puts(out, "0,0\n" "ERROR\n");
			} else if (VALUE_IS_FLOAT (cell->value))
				gsf_output_printf (out, "0,%" GNM_FORMAT_g "\n" "V\n",
					value_get_as_float (cell->value));
			else {
				gchar *str = gnm_cell_get_rendered_text (cell);
				ok = gsf_output_printf (out,
							 "1,0\n" "\"%s\"\n",
							 str);
				g_free (str);
			}
		}
	}

	gsf_output_puts (out, "-1,0\n" "EOD\n");

	gnm_pop_C_locale (locale);

	if (!ok)
		go_io_error_string (io_context, _("Error while saving DIF file."));
}
예제 #8
0
static void
search_get_value (gint row, gint column, gpointer _dd, GValue *value)
{
	DialogState *dd = (DialogState *)_dd;
	GnumericLazyList *ll = GNUMERIC_LAZY_LIST (gtk_tree_view_get_model (dd->matches_table));
	GnmSearchFilterResult *item = g_ptr_array_index (dd->matches, row);
	GnmCell *cell;
	GnmComment *comment;

	if (item->locus == GNM_SRL_COMMENT) {
		cell = NULL;
		comment = sheet_get_comment (item->ep.sheet, &item->ep.eval);
	} else {
		cell = sheet_cell_get (item->ep.sheet,
				       item->ep.eval.col,
				       item->ep.eval.row);
		comment = NULL;
	}

	g_value_init (value, ll->column_headers[column]);

#if 0
	g_print ("col=%d,row=%d\n", column, row);
#endif

	switch (column) {
	case COL_SHEET:
		g_value_set_string (value, item->ep.sheet->name_unquoted);
		return;
	case COL_CELL:
		g_value_set_string (value, cellpos_as_string (&item->ep.eval));
		return;
	case COL_TYPE:
		switch (item->locus) {
		case GNM_SRL_COMMENT:
			g_value_set_static_string (value, _("Comment"));
			return;
		case GNM_SRL_VALUE:
			g_value_set_static_string (value, _("Result"));
			return;
		case GNM_SRL_CONTENTS: {
			GnmValue *v = cell ? cell->value : NULL;
			char const *type;

			gboolean is_expr = cell && gnm_cell_has_expr (cell);
			gboolean is_value = !is_expr && !gnm_cell_is_empty (cell) && v;

			if (!cell)
				type = _("Deleted");
			else if (is_expr)
				type = _("Expression");
			else if (is_value && VALUE_IS_STRING (v))
				type = _("String");
			else if (is_value && VALUE_IS_FLOAT (v))
				type = _("Number");
			else
				type = _("Other value");

			g_value_set_static_string (value, type);
			return;
		}

#ifndef DEBUG_SWITCH_ENUM
	default:
		g_assert_not_reached ();
#endif
		}

	case COL_CONTENTS:
		switch (item->locus) {
		case GNM_SRL_COMMENT:
			if (comment)
				g_value_set_string (value, cell_comment_text_get (comment));
			else
				g_value_set_static_string (value, _("Deleted"));
			return;
		case GNM_SRL_VALUE:
			if (cell && cell->value)
				g_value_take_string (value, value_get_as_string (cell->value));
			else
				g_value_set_static_string (value, _("Deleted"));
			return;
		case GNM_SRL_CONTENTS:
			if (cell)
				g_value_take_string (value, gnm_cell_get_entered_text (cell));
			else
				g_value_set_static_string (value, _("Deleted"));
			return;
#ifndef DEBUG_SWITCH_ENUM
	default:
		g_assert_not_reached ();
#endif
		}

#ifndef DEBUG_SWITCH_ENUM
	default:
		g_assert_not_reached ();
#endif
	}
}
예제 #9
0
/**
 * FIXME: In the long term this needs optimising.
 **/
static GnmValue *
val_to_base (GnmFuncEvalInfo *ei,
	     GnmValue const *value,
	     GnmValue const *aplaces,
	     int src_base, int dest_base,
	     gnm_float min_value, gnm_float max_value,
	     Val2BaseFlags flags)
{
	int digit, min, max, places;
	gnm_float v;
	GString *buffer;
	GnmValue *vstring = NULL;

	g_return_val_if_fail (src_base > 1 && src_base <= 36,
			      value_new_error_VALUE (ei->pos));
	g_return_val_if_fail (dest_base > 1 && dest_base <= 36,
			      value_new_error_VALUE (ei->pos));

	/* func.c ought to take care of this.  */
	if (VALUE_IS_BOOLEAN (value))
		return value_new_error_VALUE (ei->pos);
	if (aplaces && VALUE_IS_BOOLEAN (aplaces))
		return value_new_error_VALUE (ei->pos);

	switch (value->type) {
	default:
		return value_new_error_NUM (ei->pos);

	case VALUE_STRING:
		if (flags & V2B_STRINGS_GENERAL) {
			vstring = format_match_number
				(value_peek_string (value), NULL,
				 workbook_date_conv (ei->pos->sheet->workbook));
			if (!vstring || !VALUE_IS_FLOAT (vstring)) {
				value_release (vstring);
				return value_new_error_VALUE (ei->pos);
			}
		} else {
			char const *str = value_peek_string (value);
			size_t len;
			gboolean hsuffix = FALSE;
			char *err;

			if ((flags & V2B_STRINGS_BLANK_ZERO) && *str == 0)
				str = "0";

			/* This prevents leading spaces, signs, etc, and "".  */
			if (!g_ascii_isalnum (*str))
				return value_new_error_NUM (ei->pos);

			len = strlen (str);
			/* We check length in bytes.  Since we are going to
			   require nothing but digits, that is fine.  */
			if ((flags & V2B_STRINGS_MAXLEN) && len > 10)
				return value_new_error_NUM (ei->pos);

			if (flags & V2B_STRINGS_0XH) {
				if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X'))
					str += 2;
				else if (str[len - 1] == 'h' || str[len - 1] == 'H')
					hsuffix = TRUE;
			}

			v = g_ascii_strtoll (str, &err, src_base);
			if (err == str || err[hsuffix] != 0)
				return value_new_error_NUM (ei->pos);

			if (v < min_value || v > max_value)
				return value_new_error_NUM (ei->pos);

			break;
		}
		/* Fall through.  */

	case VALUE_FLOAT: {
		gnm_float val = gnm_fake_trunc (value_get_as_float (vstring ? vstring : value));
		char buf[GNM_MANT_DIG + 10];
		char *err;

		value_release (vstring);

		if (val < min_value || val > max_value)
			return value_new_error_NUM (ei->pos);

		g_ascii_formatd (buf, sizeof (buf) - 1,
				 "%.0" GNM_FORMAT_f,
				 val);

		v = g_ascii_strtoll (buf, &err, src_base);
		if (*err != 0)
			return value_new_error_NUM (ei->pos);
		break;
	}
	}

	if (src_base != 10) {
		gnm_float b10 = gnm_pow (src_base, 10);
		if (v >= b10 / 2) /* N's complement */
			v = v - b10;
	}

	if (flags & V2B_NUMBER)
		return value_new_float (v);

	if (v < 0) {
		min = 1;
		max = 10;
		v += gnm_pow (dest_base, max);
	} else {
		if (v == 0)
			min = max = 1;
		else
			min = max = (int)(gnm_log (v + 0.5) /
					  gnm_log (dest_base)) + 1;
	}

	if (aplaces) {
		gnm_float fplaces = value_get_as_float (aplaces);
		if (fplaces < min || fplaces > 10)
			return value_new_error_NUM (ei->pos);
		places = (int)fplaces;
		if (v >= 0 && places > max)
			max = places;
	} else
		places = 1;

	buffer = g_string_sized_new (max);
	g_string_set_size (buffer, max);

	for (digit = max - 1; digit >= 0; digit--) {
		int thisdigit = gnm_fmod (v + 0.5, dest_base);
		v = gnm_floor ((v + 0.5) / dest_base);
		buffer->str[digit] =
			thisdigit["0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"];
	}

	return value_new_string_nocopy (g_string_free (buffer, FALSE));
}