1 /*
2  * workbook-cmd-format.c: Workbook format commands hooked to the menus
3  *
4  * Author:
5  *   Miguel de Icaza (miguel@gnu.org)
6  *   Jody Goldberg (jody@gnome.org)
7  */
8 #include <gnumeric-config.h>
9 #include <glib/gi18n-lib.h>
10 #include <gnumeric.h>
11 #include <workbook-cmd-format.h>
12 
13 #include <cell.h>
14 #include <dependent.h>
15 #include <expr.h>
16 #include <func.h>
17 #include <ranges.h>
18 #include <gui-util.h>
19 #include <selection.h>
20 #include <sheet-merge.h>
21 #include <sheet-view.h>
22 #include <value.h>
23 #include <workbook-control.h>
24 #include <workbook-view.h>
25 #include <workbook.h>
26 #include <application.h>
27 #include <dialogs/dialogs.h>
28 #include <sheet.h>
29 #include <commands.h>
30 #include <style-border.h>
31 #include <style-color.h>
32 
33 struct closure_colrow_resize {
34 	gboolean	 is_cols;
35 	ColRowIndexList *selection;
36 };
37 
38 static gboolean
cb_colrow_collect(G_GNUC_UNUSED SheetView * sv,GnmRange const * r,gpointer user_data)39 cb_colrow_collect (G_GNUC_UNUSED SheetView *sv, GnmRange const *r, gpointer user_data)
40 {
41 	struct closure_colrow_resize *info = user_data;
42 	int first, last;
43 
44 	if (info->is_cols) {
45 		first = r->start.col;
46 		last = r->end.col;
47 	} else {
48 		first = r->start.row;
49 		last = r->end.row;
50 	}
51 
52 	info->selection = colrow_get_index_list (first, last, info->selection);
53 	return TRUE;
54 }
55 
56 void
workbook_cmd_resize_selected_colrow(WorkbookControl * wbc,Sheet * sheet,gboolean is_cols,int new_size_pixels)57 workbook_cmd_resize_selected_colrow (WorkbookControl *wbc, Sheet *sheet,
58 				     gboolean is_cols, int new_size_pixels)
59 {
60 	struct closure_colrow_resize closure;
61 	closure.is_cols = is_cols;
62 	closure.selection = NULL;
63 	sv_selection_foreach (sheet_get_view (sheet, wb_control_view (wbc)),
64 		&cb_colrow_collect, &closure);
65 	cmd_resize_colrow (wbc, sheet, is_cols, closure.selection, new_size_pixels);
66 }
67 
68 void
workbook_cmd_autofit_selection(WorkbookControl * wbc,Sheet * sheet,gboolean is_cols)69 workbook_cmd_autofit_selection  (WorkbookControl *wbc, Sheet *sheet,
70 			gboolean is_cols)
71 {
72 	SheetView *sv = sheet_get_view (sheet, wb_control_view (wbc));
73 	struct closure_colrow_resize closure;
74 	closure.is_cols = is_cols;
75 	closure.selection = NULL;
76 	sv_selection_foreach (sv, &cb_colrow_collect, &closure);
77 	cmd_autofit_selection (wbc, sv, sheet, is_cols, closure.selection);
78 }
79 
80 void
workbook_cmd_inc_indent(WorkbookControl * wbc)81 workbook_cmd_inc_indent (WorkbookControl *wbc)
82 {
83 	WorkbookView const *wbv = wb_control_view (wbc);
84 	int i;
85 
86 	g_return_if_fail (wbv != NULL);
87 	g_return_if_fail (wbv->current_style != NULL);
88 
89 	i = gnm_style_get_indent (wbv->current_style);
90 	if (i < 20) {
91 		GnmStyle *style = gnm_style_new ();
92 
93 		if (GNM_HALIGN_LEFT != gnm_style_get_align_h (wbv->current_style))
94 			gnm_style_set_align_h (style, GNM_HALIGN_LEFT);
95 		gnm_style_set_indent (style, i+1);
96 		cmd_selection_format (wbc, style, NULL, _("Increase Indent"));
97 	}
98 }
99 
100 void
workbook_cmd_dec_indent(WorkbookControl * wbc)101 workbook_cmd_dec_indent (WorkbookControl *wbc)
102 {
103 	WorkbookView const *wbv = wb_control_view (wbc);
104 	int i;
105 
106 	g_return_if_fail (wbv != NULL);
107 	g_return_if_fail (wbv->current_style != NULL);
108 
109 	i = gnm_style_get_indent (wbv->current_style);
110 	if (i > 0) {
111 		GnmStyle *style = gnm_style_new ();
112 		gnm_style_set_indent (style, i-1);
113 		cmd_selection_format (wbc, style, NULL, _("Decrease Indent"));
114 	}
115 }
116 
117 struct workbook_cmd_wrap_sort_t {
118 	GnmExprList    *args;
119 	GnmRange const *r;
120 	Workbook *wb;
121 };
122 
123 static GnmValue *
cb_get_cell_content(GnmCellIter const * iter,struct workbook_cmd_wrap_sort_t * cl)124 cb_get_cell_content (GnmCellIter const *iter, struct workbook_cmd_wrap_sort_t *cl)
125 {
126 	GnmExpr const *expr;
127 
128 	if (iter->cell == NULL)
129 		expr = gnm_expr_new_constant (value_new_empty ());
130 	else if (gnm_cell_has_expr (iter->cell)) {
131 		char	 *text;
132 		GnmParsePos pp;
133 		GnmExprTop const *texpr;
134 
135 		parse_pos_init (&pp, cl->wb, iter->pp.sheet,
136 				cl->r->start.col, cl->r->start.row);
137 		text = gnm_expr_as_string   ((iter->cell)->base.texpr->expr,
138 					     &iter->pp, NULL);
139 		texpr = gnm_expr_parse_str (text, &pp, GNM_EXPR_PARSE_DEFAULT,
140 					    NULL, NULL);
141 		g_free (text);
142 		expr = gnm_expr_copy (texpr->expr);
143 		gnm_expr_top_unref (texpr);
144 
145 	} else if (iter->cell->value != NULL)
146 		expr = gnm_expr_new_constant (value_dup (iter->cell->value));
147 	else
148 		expr = gnm_expr_new_constant (value_new_empty ());
149 
150 	cl->args = gnm_expr_list_prepend (cl->args, expr);
151 	return NULL;
152 }
153 
154 void
workbook_cmd_wrap_sort(WorkbookControl * wbc,int type)155 workbook_cmd_wrap_sort (WorkbookControl *wbc, int type)
156 {
157 	WorkbookView const *wbv = wb_control_view (wbc);
158 	SheetView *sv = wb_view_cur_sheet_view (wbv);
159 	GSList *l = sv->selections, *merges;
160 	GnmExpr const *expr;
161 	GnmFunc	   *fd_sort;
162 	GnmFunc	   *fd_array;
163 	GnmExprTop const *texpr;
164 	struct workbook_cmd_wrap_sort_t cl = {NULL, NULL, NULL};
165 
166 	cl.r = selection_first_range
167 		(sv, GO_CMD_CONTEXT (wbc), _("Wrap SORT"));
168 	cl.wb = wb_control_get_workbook (wbc);
169 
170 	if (g_slist_length (l) > 1) {
171 		go_cmd_context_error_invalid (GO_CMD_CONTEXT (wbc), _("Wrap SORT"),
172 			_("A single selection is required."));
173 
174 		return;
175 	}
176 	if (range_height (cl.r) > 1 && range_width (cl.r) > 1) {
177 		go_cmd_context_error_invalid
178 			(GO_CMD_CONTEXT (wbc), _("Wrap SORT"),
179 			 _("An n\342\250\2571 or 1\342\250\257n "
180 			   "selection is required."));
181 		return;
182 	}
183 	if (range_height (cl.r) == 1 && range_width (cl.r) == 1) {
184 		go_cmd_context_error_invalid
185 			(GO_CMD_CONTEXT (wbc), _("Wrap SORT"),
186 			 _("There is no point in sorting a single cell."));
187 		return;
188 	}
189 	merges = gnm_sheet_merge_get_overlap (sv->sheet, cl.r);
190 	if (merges != NULL) {
191 		g_slist_free (merges);
192 		go_cmd_context_error_invalid
193 			(GO_CMD_CONTEXT (wbc), _("Wrap SORT"),
194 			 _("The range to be sorted may not contain any merged cells."));
195 		return;
196 	}
197 	fd_sort = gnm_func_lookup_or_add_placeholder ("sort");
198 	fd_array = gnm_func_lookup_or_add_placeholder ("array");
199 
200 	sheet_foreach_cell_in_range
201 		(sv->sheet, CELL_ITER_ALL, cl.r,
202 		 (CellIterFunc)&cb_get_cell_content, &cl);
203 
204 	cl.args = g_slist_reverse (cl.args);
205 	expr = gnm_expr_new_funcall (fd_array, cl.args);
206 	expr = gnm_expr_new_funcall2
207 		(fd_sort, expr, gnm_expr_new_constant (value_new_int (type)));
208 	texpr = gnm_expr_top_new (expr);
209 	cmd_area_set_array_expr (wbc, sv, texpr);
210 	gnm_expr_top_unref (texpr);
211 }
212