Beispiel #1
0
/**
 * gnm_scenario_apply:
 * @sc: #GnmScenario
 *
 * Returns: (transfer full): the newly allocated #GOUndo.
 **/
GOUndo *
gnm_scenario_apply (GnmScenario *sc)
{
	GOUndo *undo = NULL;
	GSList *l;

	g_return_val_if_fail (GNM_IS_SCENARIO (sc), NULL);

	for (l = sc->items; l; l = l->next) {
		GnmScenarioItem *sci = l->data;
		GnmValue const *val = sci->value;
		GnmSheetRange sr;
		Sheet *sheet;

		if (!gnm_scenario_item_valid (sci, &sr))
			continue;
		sheet = eval_sheet (sr.sheet, sc->sheet);

		if (val) {
			/* FIXME: think about arrays.  */
			GnmCell *cell = sheet_cell_fetch
				(sheet,
				 sr.range.start.col,
				 sr.range.start.row);
			sheet_cell_set_value (cell, value_dup (val));
		} else {
			GOUndo *u = clipboard_copy_range_undo (sheet,
							       &sr.range);
			/* FIXME: Clear the range.  */
			undo = go_undo_combine (undo, u);
		}
	}

	return undo;
}
Beispiel #2
0
/*
 * We need a horizontal strip of 5 cells containing:
 *
 * 0. Formula cell.
 * 1: X value cell.
 * 2: Y target value.
 * 3: Min value.
 * 4: Max value.
 */
static void
dialog_goal_seek_test (Sheet *sheet, const GnmRange *range)
{
	GoalSeekState state;
	GnmCell *cell;
	int r, c;
	GoalSeekStatus status;

	g_return_if_fail (range->start.row == range->end.row);
	g_return_if_fail (range->start.col + 4 == range->end.col);

	memset (&state, 0, sizeof (state));
	r = range->start.row;
	c = range->start.col;

	state.wb = sheet->workbook;
	state.sheet = sheet;

	state.set_cell = sheet_cell_fetch (sheet, c + 0, r);
	state.change_cell = sheet_cell_fetch (sheet, c + 1, r);
	state.old_value = value_dup (state.change_cell->value);

	cell = sheet_cell_fetch (sheet, c + 2, r);
	state.target_value = value_get_as_float (cell->value);

	cell = sheet_cell_fetch (sheet, c + 3, r);
	state.xmin = VALUE_IS_EMPTY (cell->value)
		? -max_range_val
		: value_get_as_float (cell->value);

	cell = sheet_cell_fetch (sheet, c + 4, r);
	state.xmax = VALUE_IS_EMPTY (cell->value)
		? max_range_val
		: value_get_as_float (cell->value);

	status = gnumeric_goal_seek (&state);
	if (status == GOAL_SEEK_OK) {
		/* Nothing */
	} else {
		sheet_cell_set_value (state.change_cell,
				      value_new_error_VALUE (NULL));
	}

	value_release (state.old_value);
}
Beispiel #3
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);
		}
	}
}
Beispiel #4
0
static GnmValue *
summary_cb (int col, int row, GnmValue *v, summary_cb_t *p)
{
	char  *tmp = dao_find_name (p->sheet, col, row);
	int   *index;

	/* Check if some of the previous scenarios already included that
	 * cell. If so, it's row will be put into *index. */
	index = g_hash_table_lookup (p->names, tmp);
	if (index != NULL) {
		dao_set_cell_value (&p->dao, 2 + p->col, 3 + *index,
				    value_dup (v));

		/* Set the colors. */
		dao_set_colors (&p->dao, 2 + p->col, 3 + *index,
				2 + p->col, 3 + *index,
				gnm_color_new_go (GO_COLOR_BLACK),
				gnm_color_new_go (LIGHT_GRAY));

	} else {
		/* New cell. */
		GnmCell *cell;
		int  *r;

		/* Changing cell name. */
		dao_set_cell (&p->dao, 0, 3 + p->row, tmp);

		/* GnmValue of the cell in this scenario. */
		dao_set_cell_value (&p->dao, 2 + p->col, 3 + p->row,
				    value_dup (v));

		/* Current value of the cell. */
		cell = sheet_cell_fetch (p->sheet, col, row);
		dao_set_cell_value (&p->dao, 1, 3 + p->row,
				    value_dup (cell->value));

		/* Set the colors. */
		dao_set_colors (&p->dao, 2 + p->col, 3 + p->row,
				2 + p->col, 3 + p->row,
				gnm_color_new_go (GO_COLOR_BLACK),
				gnm_color_new_go (LIGHT_GRAY));

		/* Insert row number into the hash table. */
		r  = g_new (int, 1);
		*r = p->row;
		g_hash_table_insert (p->names, tmp, r);

		/* Increment the nbr of rows. */
		p->row++;
	}

	return v;
}
Beispiel #5
0
static void
paste_cell_with_operation (Sheet *dst_sheet,
			   int target_col, int target_row,
			   GnmExprRelocateInfo const *rinfo,
			   GnmCellCopy const *src,
			   int paste_flags)
{
	GnmCell *dst;
	GnmExprOp op;

	if (src->texpr == NULL &&
	    !VALUE_IS_EMPTY (src->val) &&
	    !VALUE_IS_NUMBER (src->val))
		return;

	dst = sheet_cell_fetch (dst_sheet, target_col, target_row);
	if (!cell_has_expr_or_number_or_blank (dst))
		return;

	op = paste_op_to_expr_op (paste_flags);
	/* FIXME : This does not handle arrays, linked cells, ranges, etc. */
	if ((paste_flags & PASTE_CONTENTS) &&
	    (NULL != src->texpr || gnm_cell_has_expr (dst))) {
		GnmExpr const *old_expr    = contents_as_expr (dst->base.texpr, dst->value);
		GnmExpr const *copied_expr = contents_as_expr (src->texpr, src->val);
		GnmExprTop const *res = gnm_expr_top_new (gnm_expr_new_binary (old_expr, op, copied_expr));
		GnmExprTop const *relo = gnm_expr_top_relocate (res, rinfo, FALSE);
		if (relo) {
			gnm_cell_set_expr (dst, relo);
			gnm_expr_top_unref (relo);
		} else
			gnm_cell_set_expr (dst, res);
		gnm_expr_top_unref (res);
	} else {
		GnmValue  *value;
		GnmEvalPos pos;
		GnmExpr const *expr = gnm_expr_new_binary (
			gnm_expr_new_constant (value_dup (dst->value)),
			op,
			gnm_expr_new_constant (value_dup (src->val)));
		GnmExprTop const *texpr = gnm_expr_top_new (expr);

		eval_pos_init_cell (&pos, dst);
		pos.dep = NULL; /* no dynamic deps */
		value = gnm_expr_top_eval (texpr, &pos,
					   GNM_EXPR_EVAL_SCALAR_NON_EMPTY);
		gnm_expr_top_unref (texpr);
		gnm_cell_set_value (dst, value);
	}
}
Beispiel #6
0
static void
thrash_insert (Sheet *sheet)
{
	int     j;
	GnmStyle *style1 = gnm_style_new ();
	GnmStyle *style2 = gnm_style_new ();

	gnm_style_set_font_bold   (style1, TRUE);
	gnm_style_set_font_italic (style1, TRUE);
	gnm_style_set_font_size   (style2, 20.0);

	for (j = 0; j < INSERT_HEIGHT; j++) {
		GnmRange r;
		int i;

		for (i = 0; i < INSERT_WIDTH; i++) {
			GnmCell    *cell;
			GnmStyle *setstyle;

			r.start.col = i;
			r.start.row = j;
			r.end       = r.start;

			if (((i / 31) % 2) == 0)
				setstyle = style1;
			else
				setstyle = style2;

			gnm_style_ref (setstyle);
			sheet_style_attach (sheet, &r, setstyle);

			cell = sheet_cell_fetch (sheet, i, j);

			gnm_cell_set_value (cell, value_new_int (i), NULL);
		}

		r.start.col = 0;
		r.start.row = MAX (0, j - 1);
		r.end.col   = gnm_sheet_get_max_cols (sheet);
		r.end.row   = MIN (gnm_sheet_get_max_rows (sheet), j + 1);

		sheet_style_optimize (sheet, r);
	}

	gnm_style_unref (style1);
	gnm_style_unref (style2);
}
Beispiel #7
0
static void
add_cell (Sheet *sheet, const psiconv_sheet_cell psi_cell,
	  const psiconv_formula_list psi_formulas, const GnmStyle * default_style)
{
	GnmCell *cell;
	GnmValue *val;
	GnmExprTop const *expr = NULL;

	cell = sheet_cell_fetch (sheet, psi_cell->column, psi_cell->row);
	if (!cell)
		return;

	val = value_new_from_psi_cell (psi_cell);

	if (psi_cell->calculated)
		expr = expr_new_from_formula (psi_cell, psi_formulas);

	if (expr != NULL) {
		/* TODO : is there a notion of parse format ?
		 * How does it store a user entered date ?
		 */
		if (val != NULL)
			gnm_cell_set_expr_and_value (cell, expr, val, TRUE);
		else
			gnm_cell_set_expr (cell, expr);
	} else if (val != NULL) {
		/* TODO : is there a notion of parse format ?
		 * How does it store a user entered date ?
		 */
		gnm_cell_set_value (cell, val);
	} else {
		/* TODO : send this warning to iocontext with details of
		 * which sheet and cell.
		 */
		g_warning ("Cell with no value or expression ?");
	}
	if (expr)
		gnm_expr_top_unref (expr);

	/* TODO: Perhaps this must be moved above set_format */
	set_style(sheet,psi_cell->row,psi_cell->column,psi_cell->layout,
	          default_style);
}
Beispiel #8
0
static GnmCell *
single_cell (Sheet *sheet, GnmExprEntry *gee)
{
	int col, row;
	gboolean issingle;
	GnmValue *v = gnm_expr_entry_parse_as_value (gee, sheet);

	if (!v) return NULL;

	col = v->v_range.cell.a.col;
	row = v->v_range.cell.a.row;
	issingle = (col == v->v_range.cell.b.col && row == v->v_range.cell.b.row);

	value_release (v);

	if (issingle)
		return sheet_cell_fetch (sheet, col, row);
	else
		return NULL;
}
Beispiel #9
0
/* NOTE : Make sure to set up any merged regions in the target range BEFORE
 * this is called.
 */
static void
paste_link (GnmPasteTarget const *pt, int top, int left,
	    GnmCellRegion const *cr)
{
	GnmCellPos pos;
	GnmCellRef source_cell_ref;
	int x, y;

	/* Not possible to link to arbitrary (non gnumeric) sources yet. */
	/* TODO : eventually support interprocess gnumeric links */
	if (cr->origin_sheet == NULL)
		return;

	/* TODO : support relative links ? */
	source_cell_ref.col_relative = 0;
	source_cell_ref.row_relative = 0;
	source_cell_ref.sheet = (cr->origin_sheet != pt->sheet)
		? cr->origin_sheet : NULL;
	pos.col = left;
	for (x = 0 ; x < cr->cols ; x++, pos.col++) {
		source_cell_ref.col = cr->base.col + x;
		pos.row = top;
		for (y = 0 ; y < cr->rows ; y++, pos.row++) {
			GnmExprTop const *texpr;
			GnmCell *cell =
				sheet_cell_fetch (pt->sheet, pos.col, pos.row);

			/* This could easily be made smarter */
			if (!gnm_cell_is_merged (cell) &&
			    gnm_sheet_merge_contains_pos (pt->sheet, &pos))
					continue;
			source_cell_ref.row = cr->base.row + y;
			texpr = gnm_expr_top_new (gnm_expr_new_cellref (&source_cell_ref));
			gnm_cell_set_expr (cell, texpr);
			gnm_expr_top_unref (texpr);
		}
	}
}
Beispiel #10
0
static GnmCell *
pg_fetch_cell (GnmPreviewGrid *pg, int col, int row)
{
	GnmPreviewGridClass *klass = GNM_PREVIEW_GRID_GET_CLASS (pg);
	GnmCell *cell;
	GnmValue *v = NULL;

	g_return_val_if_fail (klass != NULL, NULL);
	g_return_val_if_fail (pg != NULL, NULL);
	g_return_val_if_fail (col >= 0 && col < gnm_sheet_get_max_cols (pg->sheet), NULL);
	g_return_val_if_fail (row >= 0 && row < gnm_sheet_get_max_rows (pg->sheet), NULL);

	if (NULL != klass->get_cell_value)
		v = (klass->get_cell_value) (pg, col, row);
	if (NULL == v)
		v = value_dup (pg->defaults.value);

	cell = sheet_cell_fetch (pg->sheet, col, row);
	gnm_cell_set_value (cell, v);

	gnm_cell_render_value (cell, TRUE);

	return cell;
}
Beispiel #11
0
static gboolean
sylk_rtd_c_parse (SylkReader *state, char *str)
{
	GnmValue *val = NULL;
	GnmExprTop const *texpr = NULL;
	gboolean is_array = FALSE;
	int r = -1, c = -1, tmp;
	char *next;

	for (; *str != '\0' ; str = next) {
		next = sylk_next_token (str);
		switch (*str) {
		case 'X': if (sylk_parse_int (str+1, &tmp)) state->pp.eval.col = tmp - 1; break;
		case 'Y': if (sylk_parse_int (str+1, &tmp)) state->pp.eval.row = tmp - 1; break;

		case 'K': /* ;K value: Value of the cell. */
			if (val != NULL) {
				sylk_read_warning (state, _("Multiple values in the same cell"));
				value_release (val);
				val = NULL;
			}
			val = sylk_parse_value (state, str+1);
			break;

		case 'E':
			if (texpr != NULL) {
				sylk_read_warning (state, _("Multiple expressions in the same cell"));
				gnm_expr_top_unref (texpr);
			}
			texpr = sylk_parse_expr (state, str+1);
			break;
		case 'M' : /* ;M exp: Expression stored with UL corner of matrix (;R ;C defines
		  the lower right corner).  If the ;M field is supported, the
		  ;K record is ignored.  Note that no ;E field is written. */
			if (texpr != NULL) {
				sylk_read_warning (state, _("Multiple expressions in the same cell"));
				gnm_expr_top_unref (texpr);
			}
			texpr = sylk_parse_expr (state, str+1);
			is_array = TRUE;
			break;

		case 'I' : /* ;I: Inside a matrix or table (at row ;R, col ;C) C record for UL
		      corner must precede this record.  Note that any ;K field is
		      ignored if the ;I field is supported.  No ;E field is written
		      out. */
			is_array = TRUE;
			break;
		case 'C' : sylk_parse_int (str+1, &c); break;
		case 'R' : sylk_parse_int (str+1, &r); break;

		case 'A' : /* ;Aauthor:^[ :text 1) till end of line 2) excel extension */
			sylk_parse_comment (state, str+1);
			break;

		case 'G' : /* ;G: Defines shared value (may not have an ;E for this record). */
		case 'D' : /* ;D: Defines shared expression. */
		case 'S' : /* ;S: Shared expression/value given at row ;R, col ;C.  C record
		  for ;R, ;C must precede this one.  Note that no ;E or ;K
		  fields are written here (not allowed on Excel macro sheets). */

		case 'N' : /* ;N: Cell NOT protected/locked (if ;N present in ;ID record). */
		case 'P' : /* ;P: Cell protected/locked (if ;N not present in ;ID record).
		  Note if this occurs for any cell, we protect the entire
		  sheet. */

		case 'H' : /* ;H: Cell hidden. */

		case 'T' : /* ;Tref,ref: UL corner of table (;R ;C defines the lower left
		  corner).  Note that the defined rectangle is the INSIDE of
		  the table only.  Formulas and input cells are above and to
		  the left of this rectangle.  The row and column input cells
		  are given in by the two refs (possibly only one).  Note that
		  Excel's input refs are single cells only. */

		default:
			break;
		}
	}

	if (val != NULL || texpr != NULL) {
		GnmCell *cell = sheet_cell_fetch (state->pp.sheet,
			state->pp.eval.col, state->pp.eval.row);

		if (is_array) {
			if (texpr) {
				GnmRange rg;
				rg.start = state->pp.eval;
				rg.end.col = c - 1;
				rg.end.row = r - 1;

				gnm_cell_set_array (state->pp.sheet,
						    &rg,
						    texpr);
				gnm_expr_top_unref (texpr);
			}
			if (NULL != val)
				gnm_cell_assign_value (cell, val);
		} else if (NULL != texpr) {
			if (NULL != val)
				gnm_cell_set_expr_and_value (cell, texpr, val, TRUE);
			else
				gnm_cell_set_expr (cell, texpr);
			gnm_expr_top_unref (texpr);
		} else if (NULL != val)
			gnm_cell_set_value (cell, val);
	}

	return TRUE;
}
Beispiel #12
0
G_MODULE_EXPORT void
paradox_file_open (GOFileOpener const *fo, GOIOContext *io_context,
                   WorkbookView *wb_view, GsfInput *input)
{
	Workbook  *wb;
	pxdoc_t	  *pxdoc;
	pxhead_t	*pxh;
	pxfield_t	*pxf;
	char	*data;
	char	  *name;
	Sheet	  *sheet;
	GnmCell	  *cell;
	GnmValue	  *val = NULL;
	GOErrorInfo *open_error = NULL;
	guint row, i, j, offset;

#ifdef PX_MEMORY_DEBUGGING
	PX_mp_init ();
#endif

#ifdef PX_MEMORY_DEBUGGING
	pxdoc = PX_new2 (gn_errorhandler, PX_mp_malloc, PX_mp_realloc, PX_mp_free);
#else
	pxdoc = PX_new2 (gn_errorhandler, gn_malloc, gn_realloc, gn_free);
#endif
	if (PX_open_gsf (pxdoc, input) < 0) {
		go_io_error_info_set (io_context, go_error_info_new_str_with_details (
					    _("Error while opening Paradox file."),
					    open_error));
		return;
	}
	pxh = pxdoc->px_head;

	PX_set_targetencoding (pxdoc, "UTF-8");

	wb = wb_view_get_workbook (wb_view);
	name = workbook_sheet_get_free_name (wb, pxh->px_tablename, FALSE, TRUE);
	sheet = sheet_new (wb, name, 256, 65536);
	g_free (name);
	workbook_sheet_attach (wb, sheet);

	pxf = pxh->px_fields;
	for (i = 0 ; i < (guint) pxh->px_numfields; i++) {
		char str[30], *str2;
		char ctypes[26] = {'?',
				   'A', 'D', 'S', 'I', '$', 'N', '?', '?',
				   'L', '?', '?', 'M', 'B', 'F', 'O', 'G',
				   '?', '?', '?', 'T', '@', '+', '#', 'Y',
				   };
		cell = sheet_cell_fetch (sheet, i, 0);
		if (pxf->px_ftype == pxfBCD)
			snprintf (str, 30, "%s,%c,%d", pxf->px_fname, ctypes[(int)pxf->px_ftype], pxf->px_fdc);
		else
			snprintf (str, 30, "%s,%c,%d", pxf->px_fname, ctypes[(int)pxf->px_ftype], pxf->px_flen);
#if PXLIB_MAJOR_VERSION == 0 && (PXLIB_MINOR_VERION < 3 || (PXLIB_MAJOR_VERSION == 3 && PXLIB_MICRO_VERSION == 0))
		/* Convert the field names to utf-8. This is actually in pxlib
		 * responsibility, but hasn't been implemented yet. For the mean time
		 * we *misuse* PX_get_data_alpha()
		 */
		PX_get_data_alpha (pxdoc, str, strlen (str), &str2);
		gnm_cell_set_text (cell, str2);
		pxdoc->free (pxdoc, str2);
#else
		gnm_cell_set_text (cell, str);
#endif
		pxf++;
	}
	{
		GnmRange r;
		GnmStyle *bold = gnm_style_new ();
		gnm_style_set_font_bold (bold, TRUE);
		sheet_style_apply_range	(sheet,
			range_init (&r, 0, 0, pxh->px_numfields-1, 0), bold);
	}

	if ((data = (char *) pxdoc->malloc (pxdoc, pxh->px_recordsize, _("Could not allocate memory for record."))) == NULL) {
		go_io_error_info_set (io_context, go_error_info_new_str_with_details (
					    _("Error while opening Paradox file."),
					    open_error));
		return;
	}
	row = 1;
	for (j = 0; j < (guint)pxh->px_numrecords; j++) {
		pxdatablockinfo_t pxdbinfo;
		int isdeleted = 0;
		if (NULL != PX_get_record2 (pxdoc, j, data, &isdeleted, &pxdbinfo)) {
			offset = 0;
			pxf = pxh->px_fields;
			for (i = 0; i < (guint) pxh->px_numfields ; i++) {
				cell = sheet_cell_fetch (sheet, i, row);
				val = NULL;
				switch (pxf->px_ftype) {
				case pxfAlpha: {
					char *value;
					if (0 < PX_get_data_alpha (pxdoc, &data[offset], pxf->px_flen, &value)) {
						val = value_new_string_nocopy (value);
/*							value_set_fmt (val, field->fmt); */
					}
					break;
				}
				case pxfShort: {
					short int value;
					if (0 < PX_get_data_short (pxdoc, &data[offset], pxf->px_flen, &value)) {
						val = value_new_int (value);
					}
					break;
				}
				case pxfAutoInc:
				case pxfLong: {
					long value;
					if (0 < PX_get_data_long (pxdoc, &data[offset], pxf->px_flen, &value)) {
						val = value_new_int (value);
					}
					break;
				}
				case pxfCurrency:
				case pxfNumber: {
					double value;
					if (0 < PX_get_data_double (pxdoc, &data[offset], pxf->px_flen, &value)) {
						val = value_new_float (value);
						if (pxf->px_ftype == pxfCurrency)
							value_set_fmt (val, go_format_default_money ());
					}
					break;
				}
				case pxfTimestamp: {
					double value;
					if (0 < PX_get_data_double (pxdoc, &data[offset], pxf->px_flen, &value)) {
						value = value / 86400000.0;
						/* 693594 = number of days up to 31.12.1899 */
						value -= 693594;
						val = value_new_float (value);
						value_set_fmt (val, go_format_default_date_time ());
					}
					break;
				}
				case  pxfLogical: {
					char value;
					if (0 < PX_get_data_byte (pxdoc, &data[offset], pxf->px_flen, &value)) {
						val = value_new_bool (value ? TRUE : FALSE);
					}
					break;
				}
				case pxfDate: {
					long value;
					int year, month, day;
					GDate *date;
					if (0 < PX_get_data_long (pxdoc, &data[offset], pxf->px_flen, &value)) {
						PX_SdnToGregorian (value+1721425, &year, &month, &day);
						date = g_date_new_dmy (day, month, year);
						val = value_new_int (go_date_g_to_serial (date, NULL));
						value_set_fmt (val, go_format_default_date ());
						g_date_free (date);
					}
					break;
				}
				case pxfTime: {
					long value;
					if (0 < PX_get_data_long (pxdoc, &data[offset], pxf->px_flen, &value)) {
						val = value_new_float (value/86400000.0);
						value_set_fmt (val, go_format_default_time ());
					}
					break;
				}
				case pxfBCD: {
					char *value;
					if (0 < PX_get_data_bcd (pxdoc, &data[offset], pxf->px_fdc, &value)) {
						val = value_new_string_nocopy (value);
					}
					break;
				}
				case pxfMemoBLOb: {
					char *value;
					int size, mod_nr;
					if (0 < PX_get_data_blob (pxdoc, &data[offset], pxf->px_flen, &mod_nr, &size, &value)) {
						val = value_new_string_nocopy (value);
					}
					break;
				}
				default:
					val = value_new_string_nocopy (
						g_strdup_printf (_("Field type %d is not supported."), pxf->px_ftype));
				}
				if (val)
					gnm_cell_set_value (cell, val);
				offset += pxf->px_flen;
				pxf++;
			}
			if (pxh->px_filetype == pxfFileTypPrimIndex) {
				short int value;
				cell = sheet_cell_fetch (sheet, i++, row);
				if (0 < PX_get_data_short (pxdoc, &data[offset], 2, &value)) {
					val = value_new_int (value);
					gnm_cell_set_value (cell, val);
				}
				offset += 2;
				cell = sheet_cell_fetch (sheet, i++, row);
				if (0 < PX_get_data_short (pxdoc, &data[offset], 2, &value)) {
					val = value_new_int (value);
					gnm_cell_set_value (cell, val);
				}
				offset += 2;
				cell = sheet_cell_fetch (sheet, i++, row);
				if (0 < PX_get_data_short (pxdoc, &data[offset], 2, &value)) {
					val = value_new_int (value);
					gnm_cell_set_value (cell, val);
				}
				cell = sheet_cell_fetch (sheet, i++, row);
				val = value_new_int (pxdbinfo.number);
				gnm_cell_set_value (cell, val);
			}
		}
		row++;
	}
	pxdoc->free (pxdoc, data);

	PX_close (pxdoc);
	PX_delete (pxdoc);

	sheet_flag_recompute_spans (sheet);
}
Beispiel #13
0
/*
 * Raturns FALSE on EOF.
 */
static gboolean
dif_parse_data (DifInputContext *ctxt)
{
	gboolean too_many_rows = FALSE, too_many_columns = FALSE;
	gint row = -1, col = 0;
	gint val_type;
	GnmCell *cell;
	gchar *msg;

	while (1) {
		if (!dif_get_line (ctxt))
			return FALSE;

		val_type = atoi (ctxt->line);
		if (val_type == 0) {
			gchar const *comma = strchr (ctxt->line, ',');
			if (comma == NULL)
				go_io_warning (ctxt->io_context,
						_("Syntax error at line %d. Ignoring."),
						ctxt->line_no);
			else if (col > gnm_sheet_get_max_cols (ctxt->sheet)) {
				too_many_columns = TRUE;
				break;
			} else {
				gnm_float num = gnm_strto (comma+1, NULL);
				GnmValue *v = NULL;

				if (!dif_get_line (ctxt))
					return FALSE;

				if (0 == strcmp (ctxt->line, "V")) {		/* V       value */
					v = value_new_float (num);
				} else if (0 == strcmp (ctxt->line, "NA")) {	/* NA      not available res must be O */
					v = value_new_error_NA (NULL);
				} else if (0 == strcmp (ctxt->line, "TRUE")) {	/* TRUE    bool T	 res must be 1 */
					v = value_new_bool (TRUE);
				} else if (0 == strcmp (ctxt->line, "FALSE")) {	/* FALSE   bool F	 res must be O */
					v = value_new_bool (TRUE);
				} else if (0 == strcmp (ctxt->line, "ERROR")) {	/* ERROR   err		 res must be O */
					go_io_warning (ctxt->io_context,
							_("Unknown value type '%s' at line %d. Ignoring."),
							ctxt->line, ctxt->line_no);
				}

				if (NULL != v) {
					cell = sheet_cell_fetch (ctxt->sheet, col, row);
					gnm_cell_set_value (cell, v);
				}
				col++;
			}
		} else if (val_type == 1) {
			if (!dif_get_line (ctxt))
				return FALSE;
			if (col > gnm_sheet_get_max_cols (ctxt->sheet)) {
				too_many_columns = TRUE;
				continue;
			}
			cell = sheet_cell_fetch (ctxt->sheet, col, row);
			if (ctxt->line_len >= 2 &&
			    ctxt->line[0] == '"' && ctxt->line[ctxt->line_len - 1] == '"') {
				ctxt->line[ctxt->line_len - 1] = '\0';
				gnm_cell_set_text (cell, ctxt->line + 1);
			} else
				gnm_cell_set_text (cell, ctxt->line);
			col++;
		} else if (val_type == -1) {
			if (!dif_get_line (ctxt))
				return FALSE;
			if (strcmp (ctxt->line, "BOT") == 0) {
				col = 0;
				row++;
				if (row > gnm_sheet_get_max_rows (ctxt->sheet)) {
					too_many_rows = TRUE;
					break;
				}
			} else if (strcmp (ctxt->line, "EOD") == 0) {
				break;
			} else {
				msg = g_strdup_printf (
				      _("Unknown data value \"%s\" at line %d. Ignoring."),
				      ctxt->line, ctxt->line_no);
				g_warning ("%s", msg);
				g_free (msg);
			}
		} else {
			msg = g_strdup_printf (
			      _("Unknown value type %d at line %d. Ignoring."),
			      val_type, ctxt->line_no);
			g_warning ("%s", msg);
			g_free (msg);
			(void) dif_get_line (ctxt);
		}
	}

	if (too_many_rows) {
		g_warning (_("DIF file has more than the maximum number of rows %d. "
		             "Ignoring remaining rows."), gnm_sheet_get_max_rows (ctxt->sheet));
	}
	if (too_many_columns) {
		g_warning (_("DIF file has more than the maximum number of columns %d. "
		             "Ignoring remaining columns."), gnm_sheet_get_max_cols (ctxt->sheet));
	}

	return TRUE;
}
Beispiel #14
0
static void
html_read_row (htmlNodePtr cur, htmlDocPtr doc, GnmHtmlTableCtxt *tc)
{
	htmlNodePtr ptr;
	int col = -1;

	for (ptr = cur->children; ptr != NULL ; ptr = ptr->next) {
		if (xmlStrEqual (ptr->name, CC2XML ("td")) ||
		    xmlStrEqual (ptr->name, CC2XML ("th"))) {
			GString *buf;
			xmlBufferPtr a_buf;
			xmlAttrPtr   props;
			int colspan = 1;
			int rowspan = 1;
			GnmCellPos pos;
			GnmStyle *mstyle;
			GSList *hrefs = NULL;
			GnmHLink *lnk = NULL;

			/* Check whether we need to skip merges from above */
			pos.row = tc->row;
			pos.col = col + 1;
			while (gnm_sheet_merge_contains_pos (tc->sheet, &pos)) {
				col++;
				pos.col++;
			}

			/* Do we span across multiple rows or cols? */
			props = ptr->properties;
			while (props) {
				if (xmlStrEqual (props->name, CC2XML ("colspan")) && props->children)
				    colspan = atoi (CXML2C (props->children->content));
				if (xmlStrEqual (props->name, CC2XML ("rowspan")) && props->children)
				    rowspan = atoi (CXML2C (props->children->content));
				props = props->next;
			}
			if (colspan < 1)
				colspan = 1;
			if (rowspan < 1)
				rowspan = 1;

			/* Let's figure out the content of the cell */
			buf = g_string_new (NULL);
			a_buf = xmlBufferCreate ();

			mstyle = gnm_style_new_default ();
			if (xmlStrEqual (ptr->name, CC2XML ("th")))
				gnm_style_set_font_bold (mstyle, TRUE);

			html_read_content (ptr, buf, mstyle, a_buf,
					   &hrefs, TRUE, doc, tc);


			if (g_slist_length (hrefs) >= 1 &&
			    buf->len > 0) {
				/* One hyperlink, and text to make it
				 * visible */
				char *url;
				xmlBufferPtr h_buf = xmlBufferCreate ();

				hrefs = g_slist_reverse (hrefs);
				htmlNodeDump (
					h_buf, doc, (htmlNodePtr)hrefs->data);
				url = g_strndup (
					CXML2C (h_buf->content), h_buf->use);
				if (strncmp (url, "mailto:",
					     strlen ("mailto:")) == 0)
					lnk = gnm_hlink_new (
						gnm_hlink_email_get_type (),
						tc->sheet);
				else
					lnk = gnm_hlink_new (
						gnm_hlink_url_get_type (),
						tc->sheet);
				gnm_hlink_set_target (lnk, url);
				gnm_style_set_hlink (mstyle, lnk);
				gnm_style_set_font_uline (mstyle,
							  UNDERLINE_SINGLE);
				gnm_style_set_font_color (mstyle,
							  gnm_color_new_go (GO_COLOR_BLUE));
				g_free (url);
				xmlBufferFree (h_buf);
			}
			if (g_slist_length (hrefs) > 1 || buf->len <= 0) {
				/* Multiple links,
				 * or no text to give hyperlink style,
				 * so put them in a comment */
				GSList *l;

				for (l = hrefs; l != NULL; l = l->next) {
					htmlNodeDump (a_buf, doc,
						      (htmlNodePtr)l->data);
					xmlBufferAdd (a_buf, CC2XML ("\n"),
						      -1);
				}
			}
			g_slist_free (hrefs);
			if (buf->len > 0) {
				GnmCell *cell = sheet_cell_fetch (tc->sheet, col + 1, tc->row);
				sheet_style_set_pos (tc->sheet, col + 1, tc->row, mstyle);
				gnm_cell_set_text (cell, buf->str);
			} else
				gnm_style_unref (mstyle);

			if (a_buf->use > 0) {
				char *name;

				name = g_strndup (CXML2C (a_buf->content), a_buf->use);
				cell_set_comment (tc->sheet, &pos, NULL, name, NULL);
				g_free (name);
			}
			g_string_free (buf, TRUE);
			xmlBufferFree (a_buf);

			/* If necessary create the merge */
			if (colspan > 1 || rowspan > 1) {
				GnmRange range;
				GnmRange *r = &range;

				range_init (r, col + 1, tc->row, col + colspan, tc->row + rowspan - 1);
				gnm_sheet_merge_add (tc->sheet, r, FALSE, NULL);
			}

			col += colspan;
		}
	}
}
Beispiel #15
0
/**
 * wbcg_edit_finish:
 * @wbcg: #WBCGtk
 * @result: what should we do with the content
 * @showed_dialog: If non-NULL will indicate if a dialog was displayed.
 *
 * Return: TRUE if editing completed successfully, or we were no editing.
 **/
gboolean
wbcg_edit_finish (WBCGtk *wbcg, WBCEditResult result,
		  gboolean *showed_dialog)
{
	Sheet *sheet;
	SheetView *sv;
	WorkbookControl *wbc;
	WorkbookView	*wbv;

	g_return_val_if_fail (GNM_IS_WBC_GTK (wbcg), FALSE);

	wbc = GNM_WBC (wbcg);
	wbv = wb_control_view (wbc);

	wbcg_focus_cur_scg (wbcg);

	gnm_expr_entry_close_tips (wbcg_get_entry_logical (wbcg));

	if (showed_dialog != NULL)
		*showed_dialog = FALSE;

	/* Remove the range selection cursor if it exists */
	if (NULL != wbcg->rangesel)
		scg_rangesel_stop (wbcg->rangesel, result == WBC_EDIT_REJECT);

	if (!wbcg_is_editing (wbcg)) {
		/* We may have a guru up even if we are not editing. remove it.
		 * Do NOT remove until later it if we are editing, it is possible
		 * that we may want to continue editing.
		 */
		if (wbcg->edit_line.guru != NULL) {
			GtkWidget *w = wbcg->edit_line.guru;
			wbc_gtk_detach_guru (wbcg);
			gtk_widget_destroy (w);
		}

		return TRUE;
	}

	g_return_val_if_fail (IS_SHEET (wbcg->editing_sheet), TRUE);

	sheet = wbcg->editing_sheet;
	sv = sheet_get_view (sheet, wbv);

	/* Save the results before changing focus */
	if (result != WBC_EDIT_REJECT) {
		ValidationStatus valid = GNM_VALIDATION_STATUS_VALID;
		char *free_txt = NULL;
		char const *txt;
		GnmStyle const *mstyle;
		char const *expr_txt = NULL;
		GOFormat const *fmt;
		GnmValue *value;
		GOUndo *u = NULL;
		GSList	*selection = selection_get_ranges (sv, FALSE);
		GnmParsePos    pp;
		GnmExprTop const *texpr = NULL;

		parse_pos_init_editpos (&pp, sv);

		/* Array only works on single range.  */
		if (result == WBC_EDIT_ACCEPT_ARRAY &&
		    (selection == NULL || selection->next != NULL))
			result = WBC_EDIT_ACCEPT_RANGE;

		/******* Check whether we would split a range ********/

		switch (result) {
		case (WBC_EDIT_ACCEPT_RANGE):
		case (WBC_EDIT_ACCEPT_ARRAY): {
			if (sheet_ranges_split_region (sheet, selection,
						       GO_CMD_CONTEXT (wbc), _("Set Text"))) {
				range_fragment_free (selection);
				if (showed_dialog != NULL)
					*showed_dialog = TRUE;
				return FALSE;
			}

			if (result == WBC_EDIT_ACCEPT_ARRAY &&
			    sheet_range_contains_merges_or_arrays
			    	(sheet, selection->data,
				 GO_CMD_CONTEXT (wbc), _("Set Text"),
				 TRUE, FALSE)) {
				range_fragment_free (selection);
				if (showed_dialog != NULL)
					*showed_dialog = TRUE;
				return FALSE;
			}

			break;
		}
		case (WBC_EDIT_ACCEPT_WO_AC):
		case (WBC_EDIT_ACCEPT): {
			GnmCell const *cell = sheet_cell_get
				(sheet, sv->edit_pos.col, sv->edit_pos.row);
			if (gnm_cell_is_nonsingleton_array (cell)) {
				gnm_cmd_context_error_splits_array (GO_CMD_CONTEXT (wbc),
								    _("Set Text"), NULL);
				if (showed_dialog != NULL)
					*showed_dialog = TRUE;
				range_fragment_free (selection);
				return FALSE;
			}
			break;
		}
		case (WBC_EDIT_REJECT):
		default:
			/* We should not be able to get here! */
			break;
		}


		/******* Check whether the range is locked ********/

		switch (result) {
		case (WBC_EDIT_ACCEPT_RANGE):
		case (WBC_EDIT_ACCEPT_ARRAY): {
			if (cmd_selection_is_locked_effective (sheet, selection, wbc,
							       _("Set Text"))) {
				range_fragment_free (selection);
				if (showed_dialog != NULL)
					*showed_dialog = TRUE;
				return FALSE;
			}
			break;
		}
		case (WBC_EDIT_ACCEPT_WO_AC):
		case (WBC_EDIT_ACCEPT): {
			GnmRange r;
			r.end = r.start = pp.eval;

			if (cmd_cell_range_is_locked_effective (sheet, &r, wbc,
							       _("Set Text"))) {
				range_fragment_free (selection);
				if (showed_dialog != NULL)
					*showed_dialog = TRUE;
				return FALSE;
			}
			break;
		}
		case (WBC_EDIT_REJECT):
		default:
			/* We should not be able to get here! */
			break;
		}
		/*****************************************************/

		txt = wbcg_edit_get_display_text (wbcg);
		mstyle = sheet_style_get (sheet, sv->edit_pos.col, sv->edit_pos.row);
		fmt = gnm_cell_get_format (sheet_cell_fetch (sheet, sv->edit_pos.col,
							     sv->edit_pos.row));

		value = format_match (txt, fmt,
				      workbook_date_conv (sheet->workbook));
		if (value == NULL)
			expr_txt = gnm_expr_char_start_p (txt);
		else
			value_release (value);

		/* NOTE : do not modify gnm_expr_char_start_p to exclude "-"
		 * it _can_ start an expression, which is required for rangesel
		 * it just isn't an expression. */
		if (expr_txt != NULL && *expr_txt != '\0' && strcmp (expr_txt, "-")) {
			GnmExprTop const *texpr_test = NULL;
			GnmParseError  perr;

			parse_error_init (&perr);
			texpr_test = gnm_expr_parse_str (expr_txt,
							 &pp, GNM_EXPR_PARSE_DEFAULT, NULL, &perr);
			/* Try adding a single extra closing paren to see if it helps */
			if (texpr_test == NULL && perr.err != NULL &&
			    perr.err->code == PERR_MISSING_PAREN_CLOSE) {
				GnmParseError tmp_err;
				char *tmp = g_strconcat (txt, ")", NULL);
				parse_error_init (&tmp_err);
				texpr_test = gnm_expr_parse_str (gnm_expr_char_start_p (tmp),
								 &pp, GNM_EXPR_PARSE_DEFAULT,
								 NULL, &tmp_err);
				parse_error_free (&tmp_err);

				if (texpr_test != NULL) {
					txt = free_txt = tmp;
					expr_txt = gnm_expr_char_start_p (txt);
				} else
					g_free (tmp);
			}

			if (texpr_test == NULL && perr.err != NULL) {
				ValidationStatus reedit;

				/* set focus _before_ selection.  gtk2 seems to
				 * screw with selection in gtk_entry_grab_focus
				 * (no longer required now that we clear
				 * gtk-entry-select-on-focus) */
				gtk_window_set_focus (wbcg_toplevel (wbcg),
						      (GtkWidget *) wbcg_get_entry (wbcg));

				if (perr.begin_char != 0 || perr.end_char != 0) {
					int offset = expr_txt - txt;
					gtk_editable_select_region (GTK_EDITABLE (wbcg_get_entry (wbcg)),
								    offset + perr.begin_char,
								    offset + perr.end_char);
				} else
					gtk_editable_set_position (
								   GTK_EDITABLE (wbcg_get_entry (wbcg)), -1);

				reedit = wb_control_validation_msg (GNM_WBC (wbcg),
								    GNM_VALIDATION_STYLE_PARSE_ERROR, NULL,
								    perr.err->message);
				if (showed_dialog != NULL)
					*showed_dialog = TRUE;

				parse_error_free (&perr);
				if (reedit == GNM_VALIDATION_STATUS_INVALID_EDIT) {
					range_fragment_free (selection);
					return FALSE;
				}
				/* restore focus to sheet , or we'll leave edit
				 * mode only to jump right back in the new
				 * cell because it looks like someone just
				 * focused on the edit line (eg hit F2) */
				wbcg_focus_cur_scg (wbcg);
			}
			if (texpr_test != NULL)
				gnm_expr_top_unref (texpr_test);
		}

		/* We only enter an array formula if the text is a formula */
		if (result == WBC_EDIT_ACCEPT_ARRAY && !expr_txt)
			result = WBC_EDIT_ACCEPT_RANGE;

		if (result == WBC_EDIT_ACCEPT_ARRAY) {
			GnmParsePos pp_array;
			GnmRange *r = selection->data;

			parse_pos_init (&pp_array, sheet->workbook, sheet, r->start.col, r->start.row);

			if ((texpr = gnm_expr_parse_str
			     (expr_txt, &pp_array, GNM_EXPR_PARSE_DEFAULT,
			      sheet_get_conventions (sheet), NULL)) == NULL)
				result = WBC_EDIT_ACCEPT_RANGE;
		}

		/* We need to save the information that we will temporarily overwrite */
		/* We then assign the information. No need to worry about formatting */
		/* Finally we can check the validation! */

		switch (result) {
		case (WBC_EDIT_ACCEPT_RANGE): {
			GSList	*l;

			for (l = selection; l != NULL; l = l->next) {
				GnmRange *r = l->data;
				u = go_undo_combine (u,  clipboard_copy_range_undo (sheet, r));
			}
			for (l = selection; l != NULL; l = l->next) {
				GnmRange *r = l->data;
				/* We do this separately since there may be overlap between ranges */
				sheet_range_set_text (&pp, r, txt);
				valid =	gnm_validation_eval_range (wbc, sheet, &sv->edit_pos, r,
							       showed_dialog);
				if (valid != GNM_VALIDATION_STATUS_VALID)
					break;
			}
			break;
		}
		case (WBC_EDIT_ACCEPT_ARRAY): {
			GnmRange *r = selection->data;

			u = go_undo_combine (u,  clipboard_copy_range_undo (sheet, r));
			if (texpr) {
				gnm_expr_top_ref (texpr);
				gnm_cell_set_array_formula (sheet,
							    r->start.col, r->start.row,
							    r->end.col, r->end.row,
							    texpr);
				sheet_region_queue_recalc (sheet, r);
			}
			valid =	gnm_validation_eval_range (wbc, sheet, &sv->edit_pos, r,
						       showed_dialog);
			break;
		}
		case (WBC_EDIT_ACCEPT_WO_AC):
		case (WBC_EDIT_ACCEPT): {
			GnmRange r;
			GnmCell *cell;

			range_init_cellpos (&r, &sv->edit_pos);
			u = clipboard_copy_range_undo (sheet, &r);

			cell = sheet_cell_fetch (sheet,
						 sv->edit_pos.col,
						 sv->edit_pos.row);
			sheet_cell_set_text (cell, txt, wbcg->edit_line.markup);
			valid = gnm_validation_eval (wbc, mstyle, sheet, &sv->edit_pos, showed_dialog);
			break;
		}
		case (WBC_EDIT_REJECT):
		default:
			/* We should not be able to get here! */
			break;
		}

		range_fragment_free (selection);

		/* We need to rebuild the original info first. */

		go_undo_undo (u);
		g_object_unref (u);

		/* Now we can respond to our validation information */

		if (valid != GNM_VALIDATION_STATUS_VALID) {
			result = WBC_EDIT_REJECT;
			if (valid == GNM_VALIDATION_STATUS_INVALID_EDIT) {
				gtk_window_set_focus (wbcg_toplevel (wbcg),
					(GtkWidget *) wbcg_get_entry (wbcg));
				g_free (free_txt);
				if (texpr != NULL)
					gnm_expr_top_unref (texpr);
				return FALSE;
			}
		} else {
			if (result == WBC_EDIT_ACCEPT_ARRAY) {
				cmd_area_set_array_expr (wbc, sv, texpr);

			} else {
				PangoAttrList *res_markup = wbcg->edit_line.markup
					? pango_attr_list_copy (wbcg->edit_line.markup)
					: NULL;
				if (result == WBC_EDIT_ACCEPT)
					cmd_set_text (wbc, sheet, &sv->edit_pos, txt, res_markup, TRUE);
				else if (result == WBC_EDIT_ACCEPT_WO_AC)
					cmd_set_text (wbc, sheet, &sv->edit_pos, txt, res_markup, FALSE);
				else
					cmd_area_set_text (wbc, sv, txt, res_markup);
				if (res_markup)
					pango_attr_list_unref (res_markup);
			}
		}
		if (texpr != NULL)
			gnm_expr_top_unref (texpr);
		g_free (free_txt);
	} else {
		if (sv == wb_control_cur_sheet_view (wbc)) {
			/* Redraw the cell contents in case there was a span */
			GnmRange tmp; tmp.start = tmp.end = sv->edit_pos;
			sheet_range_bounding_box (sv->sheet, &tmp);
			sv_redraw_range (wb_control_cur_sheet_view (wbc), &tmp);
		}

		/* Reload the entry widget with the original contents */
		wb_view_edit_line_set (wbv, wbc);
	}

	/* Stop editing */
	wbcg->editing = FALSE;
	wbcg->editing_sheet = NULL;
	wbcg->editing_cell = NULL;

	if (wbcg->edit_line.guru != NULL) {
		GtkWidget *w = wbcg->edit_line.guru;
		wbc_gtk_detach_guru (wbcg);
		gtk_widget_destroy (w);
	}

	if (wbcg->edit_line.signal_insert) {
		g_signal_handler_disconnect (wbcg_get_entry (wbcg),
					     wbcg->edit_line.signal_insert);
		wbcg->edit_line.signal_insert = 0;
	}
	if (wbcg->edit_line.signal_delete) {
		g_signal_handler_disconnect (wbcg_get_entry (wbcg),
					     wbcg->edit_line.signal_delete);
		wbcg->edit_line.signal_delete = 0;
	}
	if (wbcg->edit_line.signal_cursor_pos) {
		g_signal_handler_disconnect (wbcg_get_entry (wbcg),
					     wbcg->edit_line.signal_cursor_pos);
		wbcg->edit_line.signal_cursor_pos = 0;
	}
	if (wbcg->edit_line.signal_selection_bound) {
		g_signal_handler_disconnect (wbcg_get_entry (wbcg),
					     wbcg->edit_line.signal_selection_bound);
		wbcg->edit_line.signal_selection_bound = 0;
	}

	if (wbcg->edit_line.cell_attrs != NULL) {
		pango_attr_list_unref (wbcg->edit_line.cell_attrs);
		wbcg->edit_line.cell_attrs = NULL;
	}

	if (wbcg->edit_line.markup) {
		pango_attr_list_unref (wbcg->edit_line.markup);
		wbcg->edit_line.markup = NULL;
	}

	if (wbcg->edit_line.full_content != NULL) {
		pango_attr_list_unref (wbcg->edit_line.full_content);
		wbcg->edit_line.full_content = NULL;
	}

	if (wbcg->edit_line.cur_fmt) {
		pango_attr_list_unref (wbcg->edit_line.cur_fmt);
		wbcg->edit_line.cur_fmt = NULL;
	}

	/* set pos to 0, to ensure that if we start editing by clicking on the
	 * editline at the last position, we'll get the right style feedback */
	gtk_editable_set_position ((GtkEditable *) wbcg_get_entry (wbcg), 0);

	wb_control_update_action_sensitivity (wbc);

	if (!sheet->workbook->during_destruction) {
		/* restore focus to original sheet in case things were being selected
		 * on a different page.  Do no go through the view, rangesel is
		 * specific to the control.  */
		wb_control_sheet_focus (wbc, sheet);
		/* Only the edit sheet has an edit cursor */
		scg_edit_stop (wbcg_cur_scg (wbcg));
	}
	wbcg_auto_complete_destroy (wbcg);
	wb_control_style_feedback (wbc, NULL);	/* in case markup messed with things */

	return TRUE;
}
Beispiel #16
0
/**
 * cb_dialog_apply_clicked:
 * @button:
 * @state:
 *
 * Close (destroy) the dialog
 **/
static void
cb_dialog_apply_clicked (G_GNUC_UNUSED GtkWidget *button,
			 GoalSeekState *state)
{
	char *status_str;
	GoalSeekStatus status;
	GnmValue *target;
	GnmRangeRef const *r;
	GOFormat *format;

	if (state->warning_dialog != NULL)
		gtk_widget_destroy (state->warning_dialog);

	/* set up source */
	target = gnm_expr_entry_parse_as_value (state->set_cell_entry,
						state->sheet);
	if (target == NULL) {
		go_gtk_notice_nonmodal_dialog (GTK_WINDOW(state->dialog),
					  &(state->warning_dialog),
					  GTK_MESSAGE_ERROR,
					  _("You should introduce a valid cell "
					    "name in 'Set Cell:'!"));
		gnm_expr_entry_grab_focus (state->set_cell_entry, TRUE);
		return;
	}
	r = &target->v_range.cell;
	state->set_cell = sheet_cell_get (r->a.sheet, r->a.col, r->a.row);
	value_release (target);
	if (state->set_cell == NULL || !gnm_cell_has_expr (state->set_cell)) {
		go_gtk_notice_nonmodal_dialog (GTK_WINDOW(state->dialog),
					  &(state->warning_dialog),
					  GTK_MESSAGE_ERROR,
					  _("The cell named in 'Set Cell:' "
					    "must contain a formula!"));
		gnm_expr_entry_grab_focus (state->set_cell_entry, TRUE);
		return;
	}

	/* set up source */
	target = gnm_expr_entry_parse_as_value (state->change_cell_entry,
						state->sheet);
	if (target == NULL) {
		go_gtk_notice_nonmodal_dialog (GTK_WINDOW(state->dialog),
					  &(state->warning_dialog),
					  GTK_MESSAGE_ERROR,
					  _("You should introduce a valid cell "
					    "name in 'By Changing Cell:'!"));
		gnm_expr_entry_grab_focus (state->change_cell_entry, TRUE);
		return;
	}

	r = &target->v_range.cell;
	state->change_cell = sheet_cell_fetch (r->a.sheet, r->a.col, r->a.row);
	value_release (target);
	if (gnm_cell_has_expr (state->change_cell)) {
		go_gtk_notice_nonmodal_dialog (GTK_WINDOW(state->dialog),
					  &(state->warning_dialog),
					  GTK_MESSAGE_ERROR,
					  _("The cell named in 'By changing cell' "
					    "must not contain a formula."));
		gnm_expr_entry_grab_focus (state->change_cell_entry, TRUE);
		return;
	}


	format = gnm_style_get_format (gnm_cell_get_style (state->set_cell));
	if (entry_to_float_with_format (GTK_ENTRY(state->to_value_entry),
					&state->target_value, TRUE, format)){
		go_gtk_notice_nonmodal_dialog (GTK_WINDOW(state->dialog),
					  &(state->warning_dialog),
					  GTK_MESSAGE_ERROR,
					  _("The value given in 'To Value:' "
					    "is not valid."));
		focus_on_entry (GTK_ENTRY(state->to_value_entry));
		return;
	}

	format = gnm_style_get_format (gnm_cell_get_style (state->change_cell));
	if (entry_to_float_with_format (GTK_ENTRY(state->at_least_entry),
					 &state->xmin, TRUE, format)) {
		state->xmin = -max_range_val;
		gtk_entry_set_text (GTK_ENTRY (state->at_least_entry), "");
	}

	if (entry_to_float_with_format (GTK_ENTRY(state->at_most_entry), &state->xmax,
					TRUE, format)) {
		state->xmax = +max_range_val;
		gtk_entry_set_text (GTK_ENTRY (state->at_most_entry), "");
	}

	if ((state->old_cell != NULL) && (state->old_value != NULL)) {
		sheet_cell_set_value (state->old_cell, state->old_value);
		workbook_recalc (state->wb);
		state->old_value = NULL;
	}
	state->old_cell = state->change_cell;
	state->old_value = value_dup (state->change_cell->value);

	status = gnumeric_goal_seek (state);

	switch (status) {
	case GOAL_SEEK_OK: {
		const char *actual_str;
		const char *solution_str;
		GOFormat *format = go_format_general ();
		GnmValue *error_value = value_new_float (state->target_value -
						      value_get_as_float (state->set_cell->value));
		char *target_str = format_value (format, error_value, NULL, -1,
						 workbook_date_conv (state->wb));
		gtk_label_set_text (GTK_LABEL (state->target_value_label), target_str);
		g_free (target_str);
		value_release (error_value);

		status_str =
			g_strdup_printf (_("Goal seeking with cell %s found a solution."),
					 cell_name (state->set_cell));
		gtk_label_set_text (GTK_LABEL (state->result_label), status_str);
		g_free (status_str);

		/* FIXME?  Do a format?  */
		actual_str = state->set_cell->value
			? value_peek_string (state->set_cell->value)
			: "";
		gtk_label_set_text (GTK_LABEL (state->current_value_label), actual_str);

		solution_str = state->change_cell->value
			? value_peek_string (state->change_cell->value)
			: "";
		gtk_label_set_text (GTK_LABEL (state->solution_label), solution_str);

		break;
	}

	default:
		status_str =
			g_strdup_printf (_("Goal seeking with cell %s did not find a solution."),
					 cell_name (state->set_cell));
		gtk_label_set_text (GTK_LABEL (state->result_label), status_str);
		g_free (status_str);
		gtk_label_set_text (GTK_LABEL (state->current_value_label), "");
		gtk_label_set_text (GTK_LABEL (state->solution_label), "");
		gtk_label_set_text (GTK_LABEL (state->target_value_label), "");
		break;
	}
	state->cancelled = FALSE;

	gtk_widget_show (state->result_table);
	return;
}