示例#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
文件: ssindex.c 项目: nzinfo/gnumeric
static void
cb_index_cell (G_GNUC_UNUSED gpointer ignore,
	       GnmCell const *cell, IndexerState *state)
{
	if (cell->value != NULL && VALUE_IS_STRING (cell->value)) {
		char const *str = value_peek_string (cell->value);
		if (str != NULL && *str)
			gsf_xml_out_simple_element (state->output, "data", str);
	}
}
示例#3
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;
}
示例#4
0
static GnmValue *
cb_sylk_write_cell (GnmCellIter const *iter, SylkWriter *state)
{
	GnmValue const *v;
	GnmExprTop const *texpr;
	GnmExprArrayCorner const *array;

	if (iter->pp.eval.row != state->cur_row)
		gsf_output_printf (state->output, "C;Y%d;X%d",
			(state->cur_row = iter->pp.eval.row) + 1,
			iter->pp.eval.col + 1);
	else
		gsf_output_printf (state->output, "C;X%d",
			iter->pp.eval.col + 1);

	if (NULL != (v = iter->cell->value)) {
		if (VALUE_IS_STRING (v)) {
			gsf_output_write (state->output, 3, ";K\"");
			sylk_write (state, v->v_str.val->str);
			gsf_output_write (state->output, 1, "\"");
		} else if (VALUE_IS_NUMBER (v) || VALUE_IS_ERROR (v)) {
			GString *res = g_string_sized_new (10);
			value_get_as_gstring (v, res, state->convs);
			gsf_output_write (state->output, 2, ";K");
			gsf_output_write (state->output, res->len, res->str);
			g_string_free (res, TRUE);
		} /* ignore the rest */
	}

	if (NULL != (texpr = iter->cell->base.texpr)) {
		if (NULL != (array = gnm_expr_top_get_array_corner (texpr))) {
			gsf_output_printf (state->output, ";R%d;C%d;M",
				iter->pp.eval.row + array->rows,
				iter->pp.eval.col + array->cols);
		} else if (gnm_expr_top_is_array_elem (texpr, NULL, NULL)) {
			gsf_output_write (state->output, 2, ";I");
			texpr = NULL;
		} else
			gsf_output_write (state->output, 2, ";E");

		if (texpr != NULL) {
			GnmConventionsOut out;
			out.accum = g_string_new (NULL);
			out.pp    = &iter->pp;
			out.convs = state->convs;
			gnm_expr_top_as_gstring (texpr, &out);
			sylk_write (state, out.accum->str);
			g_string_free (out.accum, TRUE);
		}
	}
	gsf_output_write (state->output, 2, "\r\n");
	return NULL;
}
示例#5
0
static gboolean
criteria_test_match (GnmValue const *x, GnmCriteria *crit)
{
	if (!crit->has_rx)
		return FALSE;

	// Only strings are matched
	if (!VALUE_IS_STRING (x))
		return FALSE;

	return go_regexec (&crit->rx, value_peek_string (x), 0, NULL, 0) ==
		GO_REG_OK;
}
示例#6
0
static GnmValue *
callback_function_and (GnmEvalPos const *ep, GnmValue const *value, void *closure)
{
	int *result = closure;

	if (!VALUE_IS_STRING (value)) {
		gboolean err;
		*result = value_get_as_bool (value, &err) && *result;
		if (err)
			return value_new_error_VALUE (ep);
	}

	return NULL;
}
示例#7
0
GnmValue *
gnm_ifs_func (GPtrArray *data, GPtrArray *crits, GnmValue const *vals,
	      float_range_function_t fun, GnmStdError err,
	      GnmEvalPos const *ep, CollectFlags flags)
{
	int sx, sy, x, y;
	unsigned ui, N = 0, nalloc = 0;
	gnm_float *xs = NULL;
	GnmValue *res = NULL;
	gnm_float fres;

	g_return_val_if_fail (data->len == crits->len, NULL);

	if (flags & ~(COLLECT_IGNORE_STRINGS |
		      COLLECT_IGNORE_BOOLS |
		      COLLECT_IGNORE_BLANKS |
		      COLLECT_IGNORE_ERRORS)) {
		g_warning ("unsupported flags in gnm_ifs_func %x", flags);
	}

	sx = value_area_get_width (vals, ep);
	sy = value_area_get_height (vals, ep);
	for (ui = 0; ui < data->len; ui++) {
		GnmValue const *datai = g_ptr_array_index (data, ui);
		if (value_area_get_width (datai, ep) != sx ||
		    value_area_get_height (datai, ep) != sy)
			return value_new_error_VALUE (ep);
	}

	for (y = 0; y < sy; y++) {
		for (x = 0; x < sx; x++) {
			GnmValue const *v;
			gboolean match = TRUE;

			for (ui = 0; match && ui < crits->len; ui++) {
				GnmCriteria *crit = g_ptr_array_index (crits, ui);
				GnmValue const *datai = g_ptr_array_index (data, ui);
				v = value_area_get_x_y (datai, x, y, ep);

				match = crit->fun (v, crit);
			}
			if (!match)
				continue;

			// Match.  Maybe collect the data point.

			v = value_area_get_x_y (vals, x, y, ep);
			if ((flags & COLLECT_IGNORE_STRINGS) && VALUE_IS_STRING (v))
				continue;
			if ((flags & COLLECT_IGNORE_BOOLS) && VALUE_IS_BOOLEAN (v))
				continue;
			if ((flags & COLLECT_IGNORE_BLANKS) && VALUE_IS_EMPTY (v))
				continue;
			if ((flags & COLLECT_IGNORE_ERRORS) && VALUE_IS_ERROR (v))
				continue;

			if (VALUE_IS_ERROR (v)) {
				res = value_dup (v);
				goto out;
			}

			if (N >= nalloc) {
				nalloc = (2 * nalloc) + 100;
				xs = g_renew (gnm_float, xs, nalloc);
			}
			xs[N++] = value_get_as_float (v);
		}
	}

	if (fun (xs, N, &fres)) {
		res = value_new_error_std (ep, err);
	} else
		res = value_new_float (fres);

out:
	g_free (xs);
	return res;
}
示例#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
文件: html.c 项目: GNOME/gnumeric
static void
html_write_cell_content (GsfOutput *output, GnmCell *cell, GnmStyle const *style, html_version_t version)
{
	guint r = 0;
	guint g = 0;
	guint b = 0;
	char *rendered_string;
	gboolean hidden = gnm_style_get_contents_hidden (style);
	GnmHLink* hlink = gnm_style_get_hlink (style);
	const guchar* hlink_target = NULL;

	if (hlink && GNM_IS_HLINK_URL (hlink)) {
		hlink_target = gnm_hlink_get_target (hlink);
	}

	if (version == HTML32 && hidden)
		gsf_output_puts (output, "<!-- 'HIDDEN DATA' -->");
	else {
		if (style != NULL) {
			if (gnm_style_get_font_italic (style))
				gsf_output_puts (output, "<i>");
			if (gnm_style_get_font_bold (style))
				gsf_output_puts (output, "<b>");
			if (gnm_style_get_font_uline (style) != UNDERLINE_NONE)
				gsf_output_puts (output, "<u>");
			if (font_is_monospaced (style))
				gsf_output_puts (output, "<tt>");
			if (gnm_style_get_font_strike (style)) {
				if (version == HTML32)
					gsf_output_puts (output, "<strike>");
				else
					gsf_output_puts (output,
							 "<span style=\"text-decoration: line-through;\">");
			}
			switch (gnm_style_get_font_script (style)) {
			case GO_FONT_SCRIPT_SUB:
				gsf_output_puts (output, "<sub>");
				break;
			case GO_FONT_SCRIPT_SUPER:
				gsf_output_puts (output, "<sup>");
				break;
			default:
				break;
			}
		}

		if (hlink_target)
			gsf_output_printf (output, "<a href=\"%s\">", hlink_target);

		if (cell != NULL) {
			const PangoAttrList * markup = NULL;

			if (style != NULL && version != HTML40) {
				html_get_text_color (cell, style, &r, &g, &b);
				if (r > 0 || g > 0 || b > 0)
					gsf_output_printf (output, "<font color=\"#%02X%02X%02X\">", r, g, b);
			}

			if (VALUE_IS_STRING (cell->value)
			    && (VALUE_FMT (cell->value) != NULL)
			    && go_format_is_markup (VALUE_FMT (cell->value)))
				markup = go_format_get_markup (VALUE_FMT (cell->value));

			if (markup != NULL) {
				GString *str = g_string_new ("");
				value_get_as_gstring (cell->value, str, NULL);
				html_new_markup (output, markup, str->str, version);
				g_string_free (str, TRUE);
			} else {
				rendered_string = gnm_cell_get_rendered_text (cell);
				html_print_encoded (output, rendered_string);
				g_free (rendered_string);
			}
		}

		if (r > 0 || g > 0 || b > 0)
			gsf_output_puts (output, "</font>");
		if (hlink_target)
			gsf_output_puts (output, "</a>");
		if (style != NULL) {
			if (gnm_style_get_font_strike (style)) {
				if (version == HTML32)
					gsf_output_puts (output, "</strike>");
				else
					gsf_output_puts (output, "</span>");
			}
			switch (gnm_style_get_font_script (style)) {
			case GO_FONT_SCRIPT_SUB:
				gsf_output_puts (output, "</sub>");
				break;
			case GO_FONT_SCRIPT_SUPER:
				gsf_output_puts (output, "</sup>");
				break;
			default:
				break;
			}
			if (font_is_monospaced (style))
				gsf_output_puts (output, "</tt>");
			if (gnm_style_get_font_uline (style) != UNDERLINE_NONE)
				gsf_output_puts (output, "</u>");
			if (gnm_style_get_font_bold (style))
				gsf_output_puts (output, "</b>");
			if (gnm_style_get_font_italic (style))
				gsf_output_puts (output, "</i>");
		}
	}
}
示例#10
0
/**
 * wbcg_edit_start:
 * @wbcg:       The workbook to be edited.
 * @blankp:   If true, erase current cell contents first.  If false, leave the
 *            contents alone.
 * @cursorp:  If true, create an editing cursor in the current sheet.  (If
 *            false, the text will be editing in the edit box above the sheet,
 *            but this is not handled by this function.)
 *
 * Initiate editing of a cell in the sheet.  Note that we have two modes of
 * editing:
 *  1) in-cell editing when you just start typing, and
 *  2) above sheet editing when you hit F2.
 *
 * Returns TRUE if we did indeed start editing.  Returns FALSE if the
 * cell-to-be-edited was locked.
 */
gboolean
wbcg_edit_start (WBCGtk *wbcg,
		 gboolean blankp, gboolean cursorp)
{
	/* We could save this, but the situation is rare, if confusing.  */
	static gboolean warn_on_text_format = TRUE;
	SheetView *sv;
	SheetControlGUI *scg;
	GnmCell *cell;
	char *text = NULL;
	int col, row;
	WorkbookView *wbv;
	int cursor_pos = -1;

	g_return_val_if_fail (GNM_IS_WBC_GTK (wbcg), FALSE);

	if (wbcg_is_editing (wbcg))
		return TRUE;

	/* Avoid recursion, and do not begin editing if a guru is up */
	if (wbcg->inside_editing || wbc_gtk_get_guru (wbcg) != NULL)
		return TRUE;
	wbcg->inside_editing = TRUE;

	wbv = wb_control_view (GNM_WBC (wbcg));
	sv = wb_control_cur_sheet_view (GNM_WBC (wbcg));
	scg = wbcg_cur_scg (wbcg);

	col = sv->edit_pos.col;
	row = sv->edit_pos.row;

	/* don't edit a locked cell */
	/* TODO : extend this to disable edits that cannot succeed
	 * like editing a single cell of an array.  I think we have enough
	 * information if we look at the selection.
	 */
	if (wb_view_is_protected (wbv, TRUE) &&
	    gnm_style_get_contents_locked (sheet_style_get (sv->sheet, col, row))) {
		char *pos =  g_strdup_printf ( _("%s!%s is locked"),
			sv->sheet->name_quoted, cell_coord_name (col, row));
		go_cmd_context_error_invalid (GO_CMD_CONTEXT (wbcg), pos,
			wb_view_is_protected (wbv, FALSE)
			 ? _("Unprotect the workbook to enable editing.")
			 : _("Unprotect the sheet to enable editing."));
		wbcg->inside_editing = FALSE;
		g_free (pos);
		return FALSE;
	}

	cell = sheet_cell_get (sv->sheet, col, row);
	if (cell &&
	    warn_on_text_format &&
	    go_format_is_text (gnm_cell_get_format (cell)) &&
	    (gnm_cell_has_expr (cell) || !VALUE_IS_STRING (cell->value))) {
		gint res; /* Using GtkResponseType would yield a warning on the switch */
		GtkWidget *check;
		GtkWidget *align;

		GtkWidget *d = gnm_message_dialog_create
			(wbcg_toplevel (wbcg),
			 GTK_DIALOG_DESTROY_WITH_PARENT,
			 GTK_MESSAGE_WARNING,
			 _("You are about to edit a cell with \"text\" format."),
			 _("The cell does not currently contain text, though, so if "
			   "you go on editing then the contents will be turned into "
			   "text."));
		gtk_dialog_add_button (GTK_DIALOG (d), GTK_STOCK_EDIT, GTK_RESPONSE_OK);
		go_gtk_dialog_add_button
			(GTK_DIALOG (d), _("Remove format"), GTK_STOCK_REMOVE,
			 GNM_RESPONSE_REMOVE);
		gtk_dialog_add_button (GTK_DIALOG (d), GNM_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
		gtk_dialog_set_default_response (GTK_DIALOG (d), GTK_RESPONSE_CANCEL);

		check = gtk_check_button_new_with_label (_("Show this dialog next time."));
		g_signal_connect (check, "toggled", G_CALLBACK (cb_warn_toggled), &warn_on_text_format);
		gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check), TRUE);
		align = gtk_alignment_new (0.5, 0.5, 0, 0);
		gtk_container_add (GTK_CONTAINER (align), check);
		gtk_widget_show_all (align);
		gtk_box_pack_end (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (d))), align, TRUE, TRUE, 0);
		res = go_gtk_dialog_run (GTK_DIALOG (d), wbcg_toplevel (wbcg));

		switch (res) {
		case GNM_RESPONSE_REMOVE: {
			GnmStyle *style = gnm_style_new ();
			gnm_style_set_format (style, go_format_general ());
			if (!cmd_selection_format (GNM_WBC (wbcg),
						   style, NULL, NULL))
				break;
			/* Fall through.  */
		}
		default:
		case GTK_RESPONSE_CANCEL:
			wbcg->inside_editing = FALSE;
			return FALSE;
		case GTK_RESPONSE_OK:
			break;
		}
	}

	gnm_app_clipboard_unant ();

	if (blankp)
		gtk_entry_set_text (wbcg_get_entry (wbcg), "");
	else if (cell != NULL) {
		gboolean quoted = FALSE;

		text = gnm_cell_get_text_for_editing (cell, sv->sheet, &quoted, &cursor_pos);

		if (text)
			gtk_entry_set_text (wbcg_get_entry (wbcg), text);

		if (cell->value != NULL) {
			GOFormat const *fmt = VALUE_FMT (cell->value);
			if (fmt != NULL && go_format_is_markup (fmt)) {
				PangoAttrList *markup =
					pango_attr_list_copy ((PangoAttrList *)go_format_get_markup (fmt));
				if (quoted)
					go_pango_attr_list_open_hole (markup, 0, 1);
				wbcg_edit_init_markup (wbcg, markup);
			}
		}
	}

	gnm_expr_entry_set_scg (wbcg->edit_line.entry, scg);
	gnm_expr_entry_set_flags (wbcg->edit_line.entry,
		GNM_EE_SHEET_OPTIONAL | GNM_EE_FORMULA_ONLY,
		GNM_EE_SINGLE_RANGE | GNM_EE_SHEET_OPTIONAL | GNM_EE_FORMULA_ONLY | GNM_EE_FORCE_REL_REF | GNM_EE_FORCE_ABS_REF);
	scg_edit_start (scg);

	/* Redraw the cell contents in case there was a span */
	sheet_redraw_region (sv->sheet, col, row, col, row);

	if (cursorp && /* autocompletion code will not work in the edit line */
	    wbv->do_auto_completion &&
	    (text == NULL || g_unichar_isalpha (g_utf8_get_char (text)))) {
		wbcg->auto_complete = gnm_complete_sheet_new (
			sv->sheet, col, row,
			workbook_edit_complete_notify, wbcg);
		wbcg->auto_completing = TRUE;
		wbcg->auto_max_size = 0;
	} else
		wbcg->auto_complete = NULL;

	/* Give the focus to the edit line */
	if (!cursorp)
		gtk_window_set_focus (wbcg_toplevel (wbcg),
			(GtkWidget *) wbcg_get_entry (wbcg));

	wbcg->editing = TRUE;
	wbcg->editing_sheet = sv->sheet;
	wbcg->editing_cell = cell;

	/* If this assert fails, it means editing was not shut down
	 * properly before
	 */
	g_return_val_if_fail (wbcg->edit_line.signal_changed == 0, TRUE);
	wbcg->edit_line.signal_changed = g_signal_connect (
		G_OBJECT (wbcg_get_entry (wbcg)),
		"changed",
		G_CALLBACK (cb_entry_changed), wbcg);
	wbcg->edit_line.signal_insert = g_signal_connect (
		G_OBJECT (wbcg_get_entry (wbcg)),
		"insert-text",
		G_CALLBACK (cb_entry_insert_text), wbcg);
	wbcg->edit_line.signal_delete = g_signal_connect (
		G_OBJECT (wbcg_get_entry (wbcg)),
		"delete-text",
		G_CALLBACK (cb_entry_delete_text), wbcg);
	wbcg->edit_line.signal_cursor_pos = g_signal_connect_swapped (
		G_OBJECT (wbcg_get_entry (wbcg)),
		"notify::cursor-position",
		G_CALLBACK (cb_entry_cursor_pos), wbcg);
	wbcg->edit_line.signal_selection_bound = g_signal_connect_swapped (
		G_OBJECT (wbcg_get_entry (wbcg)),
		"notify::selection-bound",
		G_CALLBACK (cb_entry_cursor_pos), wbcg);

	g_free (text);
	wb_control_update_action_sensitivity (GNM_WBC (wbcg));

	wbcg->inside_editing = FALSE;

	gtk_editable_set_position (GTK_EDITABLE (wbcg_get_entry (wbcg)), cursor_pos);

	return TRUE;
}
示例#11
0
/*
 *	helpers:
 */
static gboolean
_gui_get_first_account(Config *config, gchar **username, gchar **key, gchar **secret)
{
	Section *section;
	Section *child;
	Value *value;
	gint count;
	gint result = 0;
	gboolean success = FALSE;

	g_debug("Getting account data from configuration...");

	*username = NULL;
	*key = NULL;
	*secret = NULL;

	/* get root section from configuration */
	section = config_get_root(config);

	/* find "Accounts" section */
	if((section = section_find_first_child(section, "Twitter")) && (section = section_find_first_child(section, "Accounts")))
	{
		count = section_n_children(section);

		/* set account data */
		for(gint i = 0; i < count && !success; ++i)
		{
			child = section_nth_child(section, i);

			if(!g_ascii_strcasecmp(section_get_name(child), "Account"))
			{
				++result;
			
				if((value = section_find_first_value(child, "username")) && VALUE_IS_STRING(value))
				{
					*username = g_strdup(value_get_string(value));
					g_debug("Found username: \"%s\"", *username);
				}

				if((value = section_find_first_value(child, "oauth_access_key")) && VALUE_IS_STRING(value))
				{
					*key = g_strdup(value_get_string(value));
					g_debug("Found username: \"%s\"", *key);
				}

				if((value = section_find_first_value(child, "oauth_access_secret")) && VALUE_IS_STRING(value))
				{
					*secret = g_strdup(value_get_string(value));
					g_debug("Found username: \"%s\"", *secret);
				}
			}

			if(*username && *key && *secret)
			{
				success = TRUE;
			}
		}
	}

	if(!success)
	{
		g_free(*username);
		g_free(*key);
		g_free(*secret);
	}

	return success;
}