1 
2 /*
3  *  Ump - Unnamed Math Program
4  *  Copyright (c) 2005 by Mattias Hultgren <mattias_hultgren@tele2.se>
5  *
6  *  See main.cpp
7  */
8 
9 #include <math.h>
10 #include "matrix_editor.h"
11 #include "main.h"
12 #include "ump_editor.h"
13 #include "ump_simplewin.h"
14 #include "ump_advancedwin.h"
15 #include "ump_graphwin.h"
16 #include "ump_prefwin.h"
17 #include "ump_aboutwin.h"
18 #include "vector.h"
19 
20 const int matrix_editor_max_size = 500;
21 
22 struct MatrixEditorPage
23 {
24 	Matrix matrix;
25 	GtkWidget *rows, *cols, *rows_label, *cols_label;
26 	gint notebook_index;
27 };
28 
29 struct MatrixEditor
30 {
31 	Vector<MatrixEditorPage> pages;
32 	GtkWidget *window, *notebook, *vbox, *menu, *bottom_label;
33 	Format format;
34 }matrix_editor;
35 
36 
aboutwin_show_matrix_editor(void)37 void aboutwin_show_matrix_editor(void) { aboutwin_show(GTK_WINDOW(matrix_editor.window)); }
prefwin_show_matrix_editor(void)38 void prefwin_show_matrix_editor(void) { prefwin_show(GTK_WINDOW(matrix_editor.window)); }
39 
40 
41 void matrix_editor_add_matrix( const char *name, const Matrix &src, gint pos ) throw(error_obj);
42 
43 void matrix_element_got_focus( GtkWidget *widget, gpointer user_data );
44 gboolean matrix_size_update( GtkWidget *widget, GdkEventFocus *event, gpointer user_data );
45 void matrix_element_update_insert( GtkEditable *editable, gchar *new_text, gint new_text_length,
46 gint *position, gpointer user_data );
47 void matrix_element_update_delete( GtkEditable *editable, gint start_pos, gint end_pos,
48 gpointer user_data);
49 void matrix_element_update( GtkEditable *editable, gpointer user_data );
50 gboolean matrix_element_focus_out( GtkWidget *widget, GdkEventFocus *event, gpointer user_data );
51 
52 void menu_matrix_new(void);
53 void menu_matrix_new_with_name_func(void);
54 void menu_matrix_open(void);
55 void menu_matrix_close(void);
56 void menu_matrix_delete(void);
57 void menu_matrix_calc_inverse(void);
58 void menu_matrix_calc_transpose(void);
59 void menu_matrix_calc_determinant(void);
60 void menu_matrix_calc_adjoint(void);
61 void menu_matrix_calc_identity(void);
62 void menu_matrix_calc_add(void);
63 void menu_matrix_calc_substract(void);
64 void menu_matrix_calc_multiply(void);
65 void menu_matrix_calc_power(void);
66 void menu_matrix_calc_fill_with(void);
67 
68 
build_menu(void)69 GtkWidget* build_menu(void)
70 {
71 	GtkActionGroup *actions;
72 	GtkUIManager *ui_manager;
73 	GError *error = NULL;
74 	static const gchar *menu_str =
75 "<ui>"
76 "  <menubar name='MenuBar'>"
77 "    <menu action='FileMenu'>"
78 "      <menuitem action='Preferences'/>"
79 "      <separator/>"
80 "      <menuitem action='Close'/>"
81 "      <separator/>"
82 "      <menuitem action='Quit'/>"
83 "    </menu>"
84 "    <menu action='MatrixMenu'>"
85 "      <menuitem action='New'/>"
86 "      <menuitem action='NewName'/>"
87 "      <menuitem action='Open'/>"
88 "      <menuitem action='CloseMatrix'/>"
89 "      <menuitem action='Delete'/>"
90 "    </menu>"
91 "    <menu action='CalculateMenu'>"
92 "      <menuitem action='Add'/>"
93 "      <menuitem action='Substract'/>"
94 "      <menuitem action='Multiply'/>"
95 "      <menuitem action='Power'/>"
96 "      <separator/>"
97 "      <menuitem action='Adjoint'/>"
98 "      <menuitem action='Determinant'/>"
99 "      <menuitem action='Inverse'/>"
100 "      <menuitem action='Transpose'/>"
101 "      <separator/>"
102 "      <menuitem action='Identity'/>"
103 "      <menuitem action='FillWith'/>"
104 "      <separator/>"
105 "    </menu>"
106 "    <menu action='ToolsMenu'>"
107 "      <menuitem action='Simple'/>"
108 "      <menuitem action='Advanced'/>"
109 "      <menuitem action='Editor'/>"
110 "      <menuitem action='Graphtool'/>"
111 "    </menu>"
112 "    <menuitem action='About'/>"
113 "  </menubar>"
114 "</ui>";
115 	GtkActionEntry entries[] = {
116 { "FileMenu",    NULL,           menu_file },
117 { "Preferences", GTK_STOCK_PREFERENCES, menu_pref,     NULL,       NULL, G_CALLBACK(prefwin_show_matrix_editor) },
118 { "Close",       GTK_STOCK_CLOSE, menu_file_close,     "<ctrl>W",  NULL, G_CALLBACK(matrix_editor_close) },
119 { "Quit",        GTK_STOCK_QUIT, menu_file_quit,       "<ctrl>Q",  NULL, G_CALLBACK(UMP_gtk_quit) },
120 { "MatrixMenu",  NULL,           _("_Matrix") },
121 { "New",         GTK_STOCK_NEW,  menu_file_new,        "",         NULL, G_CALLBACK(menu_matrix_new) },
122 { "NewName",     GTK_STOCK_NEW,  _("New with name..."), "<ctrl>N", NULL, G_CALLBACK(menu_matrix_new_with_name_func) },
123 { "Open",        GTK_STOCK_OPEN, menu_file_open,       "<ctrl>O",  NULL, G_CALLBACK(menu_matrix_open) },
124 { "CloseMatrix", GTK_STOCK_CLOSE, menu_file_close,     "",         NULL, G_CALLBACK(menu_matrix_close) },
125 { "Delete",      NULL,           edit_edit_delete,     "",         NULL, G_CALLBACK(menu_matrix_delete) },
126 { "CalculateMenu", NULL,         _("_Calculate") },
127 { "Inverse",     NULL,           _("Inverse"),         NULL,       NULL, G_CALLBACK(menu_matrix_calc_inverse) },
128 { "Transpose",   NULL,           _("Transpose"),       NULL,       NULL, G_CALLBACK(menu_matrix_calc_transpose) },
129 { "Determinant", NULL,           _("Determinant"),     NULL,       NULL, G_CALLBACK(menu_matrix_calc_determinant) },
130 { "Adjoint",     NULL,           _("Adjoint"),         NULL,       NULL, G_CALLBACK(menu_matrix_calc_adjoint) },
131 { "Identity",    NULL,           _("Identity"),        NULL,       NULL, G_CALLBACK(menu_matrix_calc_identity) },
132 { "Power",       NULL,           _("Power..."),        NULL,       NULL, G_CALLBACK(menu_matrix_calc_power) },
133 { "FillWith",    NULL,           _("Fill with..."),    NULL,       NULL, G_CALLBACK(menu_matrix_calc_fill_with) },
134 { "Add",         NULL,           _("Add..."),          NULL,       NULL, G_CALLBACK(menu_matrix_calc_add) },
135 { "Substract",   NULL,           _("Substract..."),    NULL,       NULL, G_CALLBACK(menu_matrix_calc_substract) },
136 { "Multiply",    NULL,           _("Multiply..."),     NULL,       NULL, G_CALLBACK(menu_matrix_calc_multiply) },
137 { "ToolsMenu",   NULL,           menu_tools },
138 { "Simple",      NULL,           menu_tools_simple,    NULL,       NULL, G_CALLBACK(simplewin_show) },
139 { "Advanced",    NULL,           menu_tools_advanced,  NULL,       NULL, G_CALLBACK(advancedwin_show) },
140 { "Editor",      NULL,           menu_tools_editor,    NULL,       NULL, G_CALLBACK(editor_showwin) },
141 { "Graphtool",   NULL,           menu_tools_graphtool, NULL,       NULL, G_CALLBACK(graphwin_show) },
142 { "About",       NULL,           menu_about,           NULL,       NULL, G_CALLBACK(aboutwin_show_matrix_editor) }
143 };
144 	guint n_entries = G_N_ELEMENTS(entries);
145 
146 
147 	actions = gtk_action_group_new("Actions");
148 	gtk_action_group_add_actions(actions, entries, n_entries, NULL);
149 	ui_manager = gtk_ui_manager_new();
150 	gtk_ui_manager_insert_action_group(ui_manager, actions, 0);
151 	gtk_window_add_accel_group( GTK_WINDOW(matrix_editor.window), gtk_ui_manager_get_accel_group(ui_manager) );
152 	if(!gtk_ui_manager_add_ui_from_string(ui_manager, menu_str, -1, &error))
153 	{
154 		g_message("building menus failed: %s", error->message);
155 		g_error_free(error);
156 		return 0;
157 	}
158 	gtk_ui_manager_ensure_update(ui_manager);
159 
160 	return gtk_ui_manager_get_widget(ui_manager, "/MenuBar");
161 }
162 
163 
matrix_editor_show(void)164 GtkWindow* matrix_editor_show(void)
165 {
166 	matrix_editor.format.set_max_decimals( 20 );
167 	if( matrix_editor.window == 0 )
168 	{
169 		GtkWidget *tmp, *tmp2;
170 
171 		matrix_editor.window = gtk_window_new( GTK_WINDOW_TOPLEVEL );
172 
173 		gtk_window_set_title( GTK_WINDOW(matrix_editor.window), _("Ump - Matrix editor") );
174 		g_signal_connect_swapped( G_OBJECT(matrix_editor.window), "delete-event",
175 		                          G_CALLBACK(matrix_editor_close), NULL );
176 
177 		matrix_editor.vbox = gtk_vbox_new(FALSE,0);
178 		gtk_container_add( GTK_CONTAINER(matrix_editor.window), matrix_editor.vbox );
179 
180 
181 		if( (matrix_editor.menu = build_menu()) == 0 )
182 		{
183 			gtk_widget_destroy( matrix_editor.window );
184 			matrix_editor.window = 0;
185 			return 0;
186 		}
187 		gtk_box_pack_start( GTK_BOX(matrix_editor.vbox), matrix_editor.menu, FALSE, FALSE, 0 );
188 
189 		matrix_editor.notebook = gtk_notebook_new();
190 		gtk_box_pack_start( GTK_BOX(matrix_editor.vbox), matrix_editor.notebook, TRUE, TRUE, 3 );
191 
192 		gtk_notebook_set_scrollable( GTK_NOTEBOOK(matrix_editor.notebook), TRUE );
193 
194 		tmp = gtk_hbox_new( FALSE, 0 );
195 		gtk_box_pack_start( GTK_BOX(matrix_editor.vbox), tmp, FALSE, TRUE, 0 );
196 
197 		matrix_editor.bottom_label = gtk_label_new( PRG_NAME );
198 		gtk_misc_set_alignment(GTK_MISC(matrix_editor.bottom_label), 0.0f, 0.5f);
199 		gtk_misc_set_padding(GTK_MISC(matrix_editor.bottom_label), 2, 2);
200 		gtk_box_pack_start( GTK_BOX(tmp), matrix_editor.bottom_label, FALSE, TRUE, 0 );
201 
202 		tmp2 = gtk_statusbar_new();
203 		gtk_box_pack_start( GTK_BOX(tmp), tmp2, TRUE, TRUE, 0 );
204 
205 
206 		gtk_window_resize( GTK_WINDOW(matrix_editor.window), 500, 400 );
207 		open_windows |= MATRIX_EDITOR_WIN;
208 
209 		menu_matrix_new();
210 	}
211 	else
212 		gtk_window_present( GTK_WINDOW( matrix_editor.window ) );
213 
214 	return GTK_WINDOW(matrix_editor.window);
215 }
216 
matrix_editor_close(void)217 void matrix_editor_close(void)
218 {
219 	if( matrix_editor.window != 0 )
220 	{
221 		while( gtk_notebook_get_n_pages( GTK_NOTEBOOK(matrix_editor.notebook) ) != 0 )
222 			menu_matrix_close();
223 
224 		gtk_widget_destroy( matrix_editor.window );
225 		matrix_editor.window = 0;
226 
227 		matrix_editor.pages.clear();
228 
229 		open_windows &= ~MATRIX_EDITOR_WIN;
230 		if(open_windows == 0)
231 			UMP_gtk_quit();
232 	}
233 }
234 
matrix_editor_translate(void)235 void matrix_editor_translate(void)
236 {
237 	if( matrix_editor.window != 0 )
238 	{
239 		GtkWidget *new_menu;
240 
241 		gtk_window_set_title( GTK_WINDOW( matrix_editor.window ), _("Ump - Matrix editor") );
242 
243 
244 		if(( new_menu = build_menu()) == 0 )
245 			return;
246 
247 		gtk_widget_destroy( matrix_editor.menu );
248 		matrix_editor.menu = new_menu;
249 
250 		gtk_box_pack_start(GTK_BOX(matrix_editor.vbox), matrix_editor.menu, FALSE, FALSE, 0);
251 		gtk_box_reorder_child( GTK_BOX(matrix_editor.vbox), matrix_editor.menu, 0 );
252 
253 		for( uint32 i=0; i<matrix_editor.pages.get_size(); i++ )
254 		{
255 			gtk_label_set_label( GTK_LABEL(matrix_editor.pages[i]->rows_label), _("_Rows: ") );
256 
257 			gtk_label_set_label( GTK_LABEL(matrix_editor.pages[i]->cols_label), _("_Columns: ") );
258 		}
259 	}
260 }
261 
262 
matrix_editor_add_matrix(const char * name,const Matrix & src,gint pos)263 void matrix_editor_add_matrix( const char *name, const Matrix &src, gint pos ) throw(error_obj)
264 {
265 	MatrixEditorPage *page=0;
266 	GtkAdjustment *tmp_adj;
267 	GtkWidget *tmp, *vbox, *table;
268 	utf8_string str;
269 
270 	try
271 	{
272 		page = new MatrixEditorPage;
273 		page->matrix = src;
274 		matrix_editor.pages.insert_this( page, pos );
275 	}
276 	catch( error_obj error )
277 	{
278 		delete page;
279 		throw;
280 	}
281 	catch( ... ) {  delete page;  THROW_ERROR( ErrorType_Memory, _("Couldn't get memory.") );  }
282 
283 	if( pos == -1 )
284 		pos = matrix_editor.pages.get_size() -1;
285 
286 	matrix_editor.pages[pos]->notebook_index = 0;
287 	for( gint i=pos-1; i >= 0; i-- )
288 	{
289 		if( matrix_editor.pages[i]->notebook_index >= 0 )
290 		{
291 			matrix_editor.pages[pos]->notebook_index = matrix_editor.pages[i]->notebook_index +1;
292 			break;
293 		}
294 	}
295 
296 	vbox = gtk_vbox_new(FALSE,0);
297 	gtk_notebook_insert_page( GTK_NOTEBOOK(matrix_editor.notebook), vbox,
298 	gtk_label_new( name ), matrix_editor.pages[pos]->notebook_index );
299 
300 	tmp = gtk_hbox_new(FALSE, 3);
301 	gtk_box_pack_start( GTK_BOX(vbox), tmp, FALSE, TRUE, 3 );
302 
303 	page->rows_label = gtk_label_new_with_mnemonic( _("_Rows: ") );
304 	gtk_box_pack_start( GTK_BOX(tmp), page->rows_label, FALSE, TRUE, 3 );
305 
306 	tmp_adj = (GtkAdjustment *) gtk_adjustment_new( gdouble(src.get_height()), 1.0, gdouble(matrix_editor_max_size), 1.0, 5.0, 5.0);
307 	page->rows = gtk_spin_button_new(tmp_adj, 1.0, 0);
308 	gtk_box_pack_start( GTK_BOX(tmp), page->rows, FALSE, TRUE, 3 );
309 	gtk_label_set_mnemonic_widget( GTK_LABEL(page->rows_label), page->rows );
310 
311 
312 	page->cols_label = gtk_label_new_with_mnemonic( _("_Columns: ") );
313 	gtk_box_pack_start( GTK_BOX(tmp), page->cols_label, FALSE, TRUE, 3 );
314 
315 	tmp_adj = (GtkAdjustment *) gtk_adjustment_new( gdouble(src.get_width()), 1.0, gdouble(matrix_editor_max_size), 1.0, 5.0, 5.0);
316 	page->cols = gtk_spin_button_new(tmp_adj, 1.0, 0);
317 	gtk_box_pack_start( GTK_BOX(tmp), page->cols, FALSE, TRUE, 3 );
318 	gtk_label_set_mnemonic_widget( GTK_LABEL(page->cols_label), page->cols );
319 
320 
321 	tmp = gtk_scrolled_window_new( NULL, NULL );
322 	gtk_box_pack_start( GTK_BOX(vbox), tmp,  TRUE, TRUE, 3 );
323 	gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW(tmp), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC );
324 
325 	table = gtk_table_new( src.get_height(), src.get_width(), TRUE );
326 	gtk_scrolled_window_add_with_viewport( GTK_SCROLLED_WINDOW(tmp), table );
327 
328 	for( uint32 row=0; row<src.get_height(); row++ )
329 	{
330 		for( uint32 col=0; col<src.get_width(); col++ )
331 		{
332 			tmp = gtk_entry_new();
333 
334 			gtk_table_attach( GTK_TABLE(table), tmp, col, col+1, row, row+1, GTK_FILL, GTK_FILL, 0, 0 );
335 			gtk_widget_set_size_request( tmp, 100, 30 );
336 
337 			str.clear();
338 			src.get_complex( col+1, row+1 ).append_to_string( str, matrix_editor.format );
339 
340 			gtk_entry_set_text( GTK_ENTRY(tmp), str.c_str() );
341 
342 			g_signal_connect( GTK_OBJECT(tmp), "grab-focus",
343 			                  G_CALLBACK(matrix_element_got_focus),
344 			                  GUINT_TO_POINTER((guint(col+1)<<9) + guint(row+1)) );
345 
346 			g_signal_connect_after( GTK_OBJECT(tmp), "focus-in-event",
347 	    	                        G_CALLBACK(matrix_size_update), GINT_TO_POINTER(pos) );
348 
349 
350 			g_signal_connect_after( GTK_OBJECT(tmp), "focus-out-event",
351 			                        G_CALLBACK(matrix_element_focus_out),
352 			             GUINT_TO_POINTER( (guint(pos)<<18) + (guint(col+1)<<9) + guint(row+1) ) );
353 
354 			g_signal_connect_after( GTK_OBJECT(tmp), "insert-text",
355 			                        G_CALLBACK(matrix_element_update_insert),
356 			             GUINT_TO_POINTER( (guint(pos)<<18) + (guint(col+1)<<9) + guint(row+1) ) );
357 			g_signal_connect_after( GTK_OBJECT(tmp), "delete-text",
358 			                        G_CALLBACK(matrix_element_update_delete),
359 			             GUINT_TO_POINTER( (guint(pos)<<18) + (guint(col+1)<<9) + guint(row+1) ) );
360 		}
361 	}
362 }
363 
364 
matrix_close_by_name(const char * name)365 void matrix_close_by_name( const char *name )
366 {
367 	gint notebook_index, index;
368 
369 	for( notebook_index=0; ; notebook_index++ )
370 	{
371 		if( notebook_index == gtk_notebook_get_n_pages( GTK_NOTEBOOK(matrix_editor.notebook) ) )
372 			return;
373 
374 		if( strcmp( gtk_notebook_get_tab_label_text( GTK_NOTEBOOK(matrix_editor.notebook),
375 		      gtk_notebook_get_nth_page( GTK_NOTEBOOK(matrix_editor.notebook), notebook_index ) ),
376 			  name ) == 0 )
377 			break;
378 	}
379 
380 	for( index=0; index<matrix_editor.pages.get_size(); index++ )
381 	{
382 		if( notebook_index == matrix_editor.pages[index]->notebook_index )
383 			break;
384 	}
385 	if( index == matrix_editor.pages.get_size() )
386 	{
387 		printf( "index == matrix_editor.pages.get_size()....this is a bug\n" );
388 		return;
389 	}
390 
391 	gtk_notebook_remove_page( GTK_NOTEBOOK(matrix_editor.notebook), notebook_index );
392 
393 	if( index == (matrix_editor.pages.get_size() -1) )
394 	{
395 		matrix_editor.pages.remove( index );
396 
397 		while( index != 0 )
398 		{
399 			if( matrix_editor.pages[ index-1 ]->matrix.get_width() == 0 )
400 			{
401 				index--;
402 				matrix_editor.pages.remove( index );
403 			}
404 			else
405 				break;
406 		}
407 	}
408 	else if( index != matrix_editor.pages.get_size() )
409 	{
410 		matrix_editor.pages[index]->matrix.set_size( 0, 0 );
411 		matrix_editor.pages[index]->notebook_index = -1;
412 		for( ; index < matrix_editor.pages.get_size(); index++ )
413 			matrix_editor.pages[index]->notebook_index--;
414 	}
415 }
416 
417 /****************************************
418 *  Below follows all signal callbacks  *
419 ****************************************/
420 
matrix_element_got_focus(GtkWidget * widget,gpointer user_data)421 void matrix_element_got_focus( GtkWidget *widget, gpointer user_data )
422 {
423 	uint32 row, col;
424 	static char str[200];
425 
426 	col = GPOINTER_TO_UINT(user_data);
427 	row = 0x1ff & col;
428 	col >>= 9;
429 
430 	snprintf( str, 200, "%s: %lu %s: %lu", _("Column"), col, _("Row"), row );
431 
432 	gtk_label_set_label( GTK_LABEL(matrix_editor.bottom_label), str );
433 }
434 
matrix_update_page(int index)435 void matrix_update_page( int index ) throw(error_obj)
436 {
437 	gint notebook_index = matrix_editor.pages[index]->notebook_index;
438 
439 	matrix_editor_add_matrix(
440 	       gtk_notebook_get_tab_label_text( GTK_NOTEBOOK(matrix_editor.notebook),
441 	       gtk_notebook_get_nth_page( GTK_NOTEBOOK(matrix_editor.notebook), notebook_index )),
442 	       matrix_editor.pages[index]->matrix, index );
443 
444 	gtk_widget_show_all( matrix_editor.window );
445 	gtk_notebook_set_current_page( GTK_NOTEBOOK(matrix_editor.notebook), notebook_index );
446 	gtk_notebook_remove_page( GTK_NOTEBOOK(matrix_editor.notebook), notebook_index+1 );
447 
448 	matrix_editor.pages.remove( index+1 );
449 }
450 
matrix_size_update(GtkWidget * widget,GdkEventFocus * event,gpointer user_data)451 gboolean matrix_size_update( GtkWidget *widget, GdkEventFocus *event, gpointer user_data)
452 {
453 	int index, notebook_index;
454 	uint32 new_width, new_height;
455 	math::Variable *ptr;
456 
457 	index = GPOINTER_TO_INT(user_data);
458 	notebook_index = matrix_editor.pages[index]->notebook_index;
459 
460 	new_width = uint32(gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(matrix_editor.pages[index]->cols)));
461 	new_height = uint32(gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(matrix_editor.pages[index]->rows)));
462 
463 	try
464 	{
465 		if( matrix_editor.pages[index]->matrix.get_height() != new_height  ||
466 		    matrix_editor.pages[index]->matrix.get_width() != new_width )
467 		{
468 			Matrix matr, *src;
469 			matr.set_size( new_width, new_height );
470 			src = &(matrix_editor.pages[index]->matrix);
471 
472 			for( int r=1; r<=matr.get_height()  &&  r<=src->get_height(); r++ )
473 			{
474 				for( int c=1; c<=matr.get_width()  &&  c<=src->get_width(); c++ )
475 					matr.set_complex( c, r, src->get_complex( c, r ) );
476 			}
477 			*src = matr;
478 
479 			matrix_update_page( index );
480 
481 			ptr = math::global_varlist.get_pointer_rw( math::global_varlist.get_id(
482 			gtk_notebook_get_tab_label_text( GTK_NOTEBOOK(matrix_editor.notebook),
483 			gtk_notebook_get_nth_page( GTK_NOTEBOOK(matrix_editor.notebook), notebook_index ))));
484 
485 			*(ptr->get_matrix_rw()) = matr;
486 		}
487 	}
488 	catch( error_obj error )
489 	{
490 		GtkWidget *dialog;
491 		dialog = gtk_message_dialog_new( GTK_WINDOW(matrix_editor.window),
492 		                                 GTK_DIALOG_DESTROY_WITH_PARENT,
493 		                                 GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, error.msg );
494 		gtk_dialog_run(GTK_DIALOG(dialog));
495 		gtk_widget_destroy(dialog);
496 	}
497 	return FALSE;
498 }
499 
matrix_element_focus_out(GtkWidget * widget,GdkEventFocus * event,gpointer user_data)500 gboolean matrix_element_focus_out( GtkWidget *widget, GdkEventFocus *event, gpointer user_data )
501 {
502 	math::CodeLine calculater;
503 	math::Variable ans;
504 	utf8_string outstr;
505 	uint32 index, row, col;
506 	const gchar *str;
507 
508 	index = GPOINTER_TO_UINT(user_data);
509 	row = 0x1ff & index;
510 	index >>= 9;
511 	col = 0x1ff & index;
512 	index >>= 9;
513 
514 	str = gtk_entry_get_text( GTK_ENTRY(widget) );
515 
516 	try
517 	{
518 		calculater.set_code_line( str, false );
519 		calculater.calc( &ans );
520 
521 		matrix_editor.pages[index]->matrix.get_complex( col, row ).append_to_string( outstr,
522 		                                                                matrix_editor.format );
523 
524 		gtk_entry_set_text( GTK_ENTRY(widget), outstr.c_str() );
525 	}
526 	catch( error_obj error )
527 	{
528 		GtkWidget *dialog;
529 		dialog = gtk_message_dialog_new( GTK_WINDOW(matrix_editor.window),
530 		                                 GTK_DIALOG_DESTROY_WITH_PARENT,
531 		                                 GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, error.msg );
532 		gtk_dialog_run(GTK_DIALOG(dialog));
533 		gtk_widget_destroy(dialog);
534 	}
535 }
536 
matrix_element_update(GtkEditable * editable,gpointer user_data)537 void matrix_element_update( GtkEditable *editable, gpointer user_data )
538 {
539 	math::CodeLine calculater;
540 	math::Variable ans, *ptr;
541 	uint32 index, row, col;
542 	gchar *str;
543 
544 	index = GPOINTER_TO_UINT(user_data);
545 	row = 0x1ff & index;
546 	index >>= 9;
547 	col = 0x1ff & index;
548 	index >>= 9;
549 
550 	str = gtk_editable_get_chars( editable, 0, -1 );
551 
552 	try
553 	{
554 		calculater.set_code_line( str, false );
555 		calculater.calc( &ans );
556 
557 		matrix_editor.pages[index]->matrix.set_complex( col, row, *ans.get_complex() );
558 
559 		ptr = math::global_varlist.get_pointer_rw( math::global_varlist.get_id(
560 		gtk_notebook_get_tab_label_text( GTK_NOTEBOOK(matrix_editor.notebook),
561 		gtk_notebook_get_nth_page( GTK_NOTEBOOK(matrix_editor.notebook),
562 		matrix_editor.pages[index]->notebook_index ))));
563 
564 		*(ptr->get_matrix_rw()) = matrix_editor.pages[index]->matrix;
565 	}
566 	catch( ... ) { }
567 
568 	g_free( str );
569 }
570 
matrix_element_update_insert(GtkEditable * editable,gchar * new_text,gint new_text_length,gint * position,gpointer user_data)571 void matrix_element_update_insert( GtkEditable *editable, gchar *new_text, gint new_text_length,
572                                    gint *position, gpointer user_data )
573 {
574 	matrix_element_update( editable, user_data );
575 }
576 
matrix_element_update_delete(GtkEditable * editable,gint start_pos,gint end_pos,gpointer user_data)577 void matrix_element_update_delete( GtkEditable *editable, gint start_pos, gint end_pos,
578                                    gpointer user_data )
579 {
580 	matrix_element_update( editable, user_data );
581 }
582 
matrix_changed(math::Variable * ptr)583 void matrix_changed( math::Variable *ptr )
584 {
585 	gint notebook_index, index;
586 	const char *name = ptr->get_name()->c_str();
587 
588 	if( ptr->get_type() != math::VariableType_Matrix )
589 	{
590 		matrix_close_by_name( ptr->get_name()->c_str() );
591 		return;
592 	}
593 
594 	if( ptr->get_matrix()->get_width() > matrix_editor_max_size  ||
595 	    ptr->get_matrix()->get_width() == 0  ||
596 	    ptr->get_matrix()->get_height() > matrix_editor_max_size  ||
597 	    ptr->get_matrix()->get_height() == 0 )
598 	{
599 		matrix_close_by_name( ptr->get_name()->c_str() );
600 		return;
601 	}
602 
603 	for( notebook_index=0; ; notebook_index++ )
604 	{
605 		if( notebook_index == gtk_notebook_get_n_pages( GTK_NOTEBOOK(matrix_editor.notebook) ) )
606 			return;
607 
608 		if( strcmp( gtk_notebook_get_tab_label_text( GTK_NOTEBOOK(matrix_editor.notebook),
609 		      gtk_notebook_get_nth_page( GTK_NOTEBOOK(matrix_editor.notebook), notebook_index ) ),
610 		    name ) == 0 )
611 			break;
612 	}
613 
614 	for( index=0; index<matrix_editor.pages.get_size(); index++ )
615 	{
616 		if( notebook_index == matrix_editor.pages[index]->notebook_index )
617 			break;
618 	}
619 
620 	if( index != matrix_editor.pages.get_size() )
621 	{
622 		try{
623 			matrix_editor.pages[index]->matrix = *(ptr->get_matrix());
624 
625 			matrix_update_page( index );
626 		}
627 		catch( error_obj error )
628 		{
629 			GtkWidget *dialog;
630 			dialog = gtk_message_dialog_new( GTK_WINDOW(matrix_editor.window),
631 			                                 GTK_DIALOG_DESTROY_WITH_PARENT,
632 			                                 GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, error.msg );
633 			gtk_dialog_run(GTK_DIALOG(dialog));
634 			gtk_widget_destroy(dialog);
635 		}
636 	}
637 }
638 
matrix_deleted(math::Variable * ptr)639 void matrix_deleted( math::Variable *ptr )
640 {
641 	matrix_close_by_name( ptr->get_name()->c_str() );
642 }
643 
644 /***************************************
645 *  Below follows only menu callbacks  *
646 ***************************************/
647 
create_new_matrix_page(const char * name)648 void create_new_matrix_page( const char *name )
649 {
650 	Matrix tmp_matr;
651 	math::Variable var, *ptr;
652 	Complex value(0);
653 
654 	try
655 	{
656 		tmp_matr.set_size( 3, 3 );
657 		for( int i=1; i<=3; i++ )
658 			for( int i2=1; i2<=3; i2++ )
659 				tmp_matr.set_complex( i, i2, value );
660 
661 		matrix_editor_add_matrix( name, tmp_matr, -1 );
662 
663 		var.set_matrix( &tmp_matr );
664 		var.set_name( name );
665 
666 		math::global_varlist.create( var, false, true, true );
667 
668 		ptr = math::global_varlist.get_pointer_rw( math::global_varlist.get_id( name ) );
669 
670 		ptr->set_change_func( matrix_changed );
671 		ptr->set_delete_func( matrix_deleted );
672 	}
673 	catch( error_obj error )
674 	{
675 		GtkWidget *dialog;
676 		dialog = gtk_message_dialog_new( GTK_WINDOW(matrix_editor.window),
677 		                                 GTK_DIALOG_DESTROY_WITH_PARENT,
678 		                                 GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, error.msg );
679 		gtk_dialog_run(GTK_DIALOG(dialog));
680 		gtk_widget_destroy(dialog);
681 	}
682 
683 	gtk_widget_show_all( matrix_editor.window );
684 
685 	gtk_notebook_set_current_page( GTK_NOTEBOOK(matrix_editor.notebook),
686 	gtk_notebook_get_n_pages( GTK_NOTEBOOK(matrix_editor.notebook) )-1 );
687 }
688 
menu_matrix_new(void)689 void menu_matrix_new(void)
690 {
691 	char str[100];
692 	int i;
693 
694 	for( i=1; ; i++ )
695 	{
696 		snprintf( str, 100, "m%ld", i );
697 
698 		try{  math::global_varlist.get_id( str );  }
699 		catch( ... )  {  break;  }  // only throw "Variable not found"
700 	}
701 
702 	create_new_matrix_page( str );
703 }
704 
menu_matrix_new_with_name_func(void)705 void menu_matrix_new_with_name_func(void)
706 {
707 	GtkWidget *align, *dialog, *entry, *hbox, *label;
708 	const char *str;
709 
710 	dialog = gtk_dialog_new_with_buttons( _("New with name..."), GTK_WINDOW(matrix_editor.window),
711 	                                      GTK_DIALOG_MODAL,	GTK_STOCK_OK, GTK_RESPONSE_OK, NULL );
712 
713 	align = gtk_alignment_new( 0.0, 0.0, 1.0, 1.0 );
714 	gtk_container_set_border_width( GTK_CONTAINER(align), 5 );
715 	gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), align, FALSE, FALSE, 0);
716 
717 	hbox = gtk_hbox_new( FALSE, 3 );
718 	gtk_container_add( GTK_CONTAINER(align), hbox );
719 
720 	label = gtk_label_new( _("Name: ") );
721 	gtk_box_pack_start( GTK_BOX(hbox), label, FALSE, TRUE, 0 );
722 
723 	entry = gtk_entry_new();
724 	gtk_box_pack_start( GTK_BOX(hbox), entry, TRUE, TRUE, 0 );
725 
726 	gtk_widget_show_all( dialog );
727 
728 	while( true )
729 	{
730 		if( gtk_dialog_run( GTK_DIALOG(dialog) ) == GTK_RESPONSE_OK )
731 			str = gtk_entry_get_text( GTK_ENTRY(entry) );
732 		else
733 			break;
734 
735 		if( str[0] == '\0' )
736 			break;
737 		try
738 		{
739 			math::check_name_against_reserved( str );
740 
741 			try{  math::global_varlist.get_id( str );  }
742 			catch( ... )
743 			{
744 				create_new_matrix_page( str );
745 				break;
746 			}
747 			char tmp_err[ERROR_OBJ_MSG_LEN];
748 			snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("\"%s\" is not a unique name."), str );
749 			THROW_ERROR( ErrorType_General, tmp_err );
750 		}
751 		catch( error_obj error )
752 		{
753 			GtkWidget *dialog2;
754 			dialog2 = gtk_message_dialog_new( GTK_WINDOW(matrix_editor.window),
755 			                                  GTK_DIALOG_DESTROY_WITH_PARENT,
756 			                                  GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, error.msg );
757 			gtk_dialog_run(GTK_DIALOG(dialog2));
758 			gtk_widget_destroy(dialog2);
759 		}
760 	}
761 	gtk_widget_destroy( dialog );
762 }
763 
menu_matrix_open(void)764 void menu_matrix_open(void)
765 {
766 	GtkWidget *dialog, *treeview;
767 	GtkListStore *list_store;
768 	GtkTreeIter iter;
769 	gint i, i2;
770 	GtkCellRenderer *renderer;
771 	GtkTreeViewColumn *column;
772 	bool empty_list = true;
773 	char tmp_str[30];
774 
775 	enum { COLUMN_NAME, COLUMN_SIZE, N_COLUMNS };
776 
777 	list_store = gtk_list_store_new( N_COLUMNS, G_TYPE_STRING, G_TYPE_STRING );
778 
779 	for( i=1; i<=math::global_varlist.get_highest_idnr(); i++ )
780 	{
781 		const math::Variable *ptr;
782 		const char *name;
783 
784 		try{ ptr = math::global_varlist.get_pointer( i );  }
785 		catch( ... )  {  continue;  }  // only throw "Variable not found"
786 
787 		if( ptr->get_type() == math::VariableType_Matrix )
788 		{
789 			if( ptr->get_matrix()->get_width() == 0  ||  // don't add matrices of zero size
790 			    ptr->get_matrix()->get_height() == 0 )
791 				continue;
792 
793 			if( ptr->get_matrix()->get_width() > matrix_editor_max_size  ||  // don't add matrices of zero size
794 			    ptr->get_matrix()->get_height() > matrix_editor_max_size )
795 				continue;
796 
797 			name = ptr->get_name()->c_str();
798 
799 			for( i2=0; i2<gtk_notebook_get_n_pages( GTK_NOTEBOOK(matrix_editor.notebook) ); i2++ )
800 			{
801 				if( strcmp( name, gtk_notebook_get_tab_label_text( GTK_NOTEBOOK(matrix_editor.notebook),
802 				           gtk_notebook_get_nth_page( GTK_NOTEBOOK(matrix_editor.notebook), i2 ))) == 0 )
803 					break;
804 			}
805 
806 			if( i2 != gtk_notebook_get_n_pages( GTK_NOTEBOOK(matrix_editor.notebook) ) )
807 				continue; // this matrix is already open
808 
809 			snprintf( tmp_str, 30, "%lux%lu", ptr->get_matrix()->get_height(), ptr->get_matrix()->get_width() );
810 			gtk_list_store_append( list_store, &iter );
811 			gtk_list_store_set( list_store, &iter, COLUMN_NAME, name, COLUMN_SIZE, tmp_str, -1);
812 			empty_list = false;
813 		}
814 	}
815 
816 	if( empty_list )
817 	{
818 		dialog = gtk_message_dialog_new( GTK_WINDOW(matrix_editor.window),
819 		                                 GTK_DIALOG_DESTROY_WITH_PARENT,
820 		                                 GTK_MESSAGE_INFO, GTK_BUTTONS_CLOSE,
821 		                                 _("There is no matrix variable to open.") );
822 		gtk_dialog_run(GTK_DIALOG(dialog));
823 		gtk_widget_destroy(dialog);
824 
825 		return;
826 	}
827 
828 	gtk_tree_sortable_set_sort_column_id( GTK_TREE_SORTABLE(list_store), COLUMN_NAME,
829 	                                      GTK_SORT_ASCENDING );
830 
831 	dialog = gtk_dialog_new_with_buttons ( _("Open a matrix variable"),
832 	                                       GTK_WINDOW(matrix_editor.window),
833 	                                       GTK_DIALOG_DESTROY_WITH_PARENT,
834 	                                       GTK_STOCK_OK,     GTK_RESPONSE_ACCEPT,
835 	                                       GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
836 	                                       NULL );
837 
838 	treeview = gtk_tree_view_new_with_model( GTK_TREE_MODEL(list_store) );
839 	gtk_box_pack_start( GTK_BOX( GTK_DIALOG(dialog)->vbox ), treeview, TRUE, TRUE, 3 );
840 
841 	renderer = gtk_cell_renderer_text_new();
842 	column = gtk_tree_view_column_new_with_attributes( _("Name"), renderer, "text", COLUMN_NAME, NULL);
843 	gtk_tree_view_append_column( GTK_TREE_VIEW(treeview), column );
844 
845 	renderer = gtk_cell_renderer_text_new();
846 	column = gtk_tree_view_column_new_with_attributes( _("Size"), renderer, "text", COLUMN_SIZE, NULL);
847 	gtk_tree_view_append_column( GTK_TREE_VIEW(treeview), column );
848 
849 	gtk_widget_show( treeview );
850 
851 	switch( gtk_dialog_run( GTK_DIALOG(dialog) ) )
852 	{
853 	case GTK_RESPONSE_ACCEPT:
854 		{
855 			GtkTreeSelection *sel;
856 			GtkTreeModel *model;
857 			gchar *name;
858 			math::Variable *ptr;
859 
860 			sel = gtk_tree_view_get_selection( GTK_TREE_VIEW(treeview) );
861 
862 			if( gtk_tree_selection_get_selected( sel, &model, &iter ) )
863 			{
864 				gtk_tree_model_get( model, &iter, COLUMN_NAME, &name, -1 );
865 
866 				try
867 				{
868 					ptr = math::global_varlist.get_pointer_rw( math::global_varlist.get_id( name ) );
869 
870 					matrix_editor_add_matrix( name, *ptr->get_matrix(), -1 );
871 
872 					ptr->set_change_func( matrix_changed );
873 					ptr->set_delete_func( matrix_deleted );
874 				}
875 				catch( error_obj error )
876 				{
877 					GtkWidget *dialog;
878 					dialog = gtk_message_dialog_new( GTK_WINDOW(matrix_editor.window),
879 					                                 GTK_DIALOG_DESTROY_WITH_PARENT,
880 					                                 GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, error.msg );
881 					gtk_dialog_run(GTK_DIALOG(dialog));
882 					gtk_widget_destroy(dialog);
883 				}
884 				gtk_widget_show_all( matrix_editor.window );
885 				gtk_notebook_set_current_page( GTK_NOTEBOOK(matrix_editor.notebook),
886 				           gtk_notebook_get_n_pages( GTK_NOTEBOOK(matrix_editor.notebook) )-1 );
887 				g_free( name );
888 			}
889 		}
890 		break;
891 
892 	case GTK_RESPONSE_REJECT:
893 		break;
894 	}
895 	gtk_widget_destroy( dialog );
896 }
897 
menu_matrix_close(void)898 void menu_matrix_close(void)
899 {
900 	gint notebook_index;
901 	math::Variable *ptr;
902 
903 	notebook_index = gtk_notebook_get_current_page( GTK_NOTEBOOK(matrix_editor.notebook) );
904 
905 	if( notebook_index == -1 )
906 		return;
907 
908 	try
909 	{
910 		ptr = math::global_varlist.get_pointer_rw( math::global_varlist.get_id(
911 		         gtk_notebook_get_tab_label_text( GTK_NOTEBOOK(matrix_editor.notebook),
912 		         gtk_notebook_get_nth_page( GTK_NOTEBOOK(matrix_editor.notebook), notebook_index ))));
913 
914 		ptr->set_change_func( 0 );
915 		ptr->set_delete_func( 0 );
916 
917 		matrix_close_by_name(
918 		       gtk_notebook_get_tab_label_text( GTK_NOTEBOOK(matrix_editor.notebook),
919 		       gtk_notebook_get_nth_page( GTK_NOTEBOOK(matrix_editor.notebook), notebook_index ) ) );
920 	}
921 	catch( ... ){}
922 }
923 
menu_matrix_delete(void)924 void menu_matrix_delete(void)
925 {
926 	gint notebook_index;
927 
928 	notebook_index = gtk_notebook_get_current_page( GTK_NOTEBOOK(matrix_editor.notebook) );
929 
930 	if( notebook_index == -1 )
931 		return;
932 
933 	try
934 	{
935 		math::global_varlist.remove( math::global_varlist.get_id(
936 		        gtk_notebook_get_tab_label_text( GTK_NOTEBOOK(matrix_editor.notebook),
937 		        gtk_notebook_get_nth_page( GTK_NOTEBOOK(matrix_editor.notebook), notebook_index ) )
938 		      ) );
939 	}
940 	catch( error_obj error )
941 	{
942 		GtkWidget *dialog;
943 		dialog = gtk_message_dialog_new( GTK_WINDOW(matrix_editor.window),
944 		                                 GTK_DIALOG_DESTROY_WITH_PARENT,
945 		                                 GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, error.msg);
946 		gtk_dialog_run(GTK_DIALOG(dialog));
947 		gtk_widget_destroy(dialog);
948 	}
949 }
950 
menu_matrix_calc_inv_trans_adj(int which)951 void menu_matrix_calc_inv_trans_adj( int which ) //_identity
952 {
953 	gint notebook_index;
954 	math::Variable *ptr;
955 
956 	notebook_index = gtk_notebook_get_current_page( GTK_NOTEBOOK(matrix_editor.notebook) );
957 
958 	if( notebook_index == -1 )
959 		return;
960 
961 	try
962 	{
963 		ptr = math::global_varlist.get_pointer_rw( math::global_varlist.get_id(
964 		        gtk_notebook_get_tab_label_text( GTK_NOTEBOOK(matrix_editor.notebook),
965 		        gtk_notebook_get_nth_page( GTK_NOTEBOOK(matrix_editor.notebook), notebook_index ) )
966 		      ) );
967 		if( which == 0 )
968 			ptr->get_matrix_rw()->inverse();
969 		else if( which == 1 )
970 			ptr->get_matrix_rw()->trans();
971 		else if( which == 2 )
972 			ptr->get_matrix_rw()->adjoint();
973 		else
974 			ptr->get_matrix_rw()->identity();
975 		ptr->signal_changed();
976 	}
977 	catch( error_obj error )
978 	{
979 		GtkWidget *dialog;
980 		dialog = gtk_message_dialog_new( GTK_WINDOW(matrix_editor.window),
981 		                                 GTK_DIALOG_DESTROY_WITH_PARENT,
982 		                                 GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, error.msg );
983 		gtk_dialog_run(GTK_DIALOG(dialog));
984 		gtk_widget_destroy(dialog);
985 	}
986 }
987 
menu_matrix_calc_inverse(void)988 void menu_matrix_calc_inverse(void)
989 {
990 	menu_matrix_calc_inv_trans_adj( 0 );
991 }
menu_matrix_calc_transpose(void)992 void menu_matrix_calc_transpose(void)
993 {
994 	menu_matrix_calc_inv_trans_adj( 1 );
995 }
menu_matrix_calc_adjoint(void)996 void menu_matrix_calc_adjoint(void)
997 {
998 	menu_matrix_calc_inv_trans_adj( 2 );
999 }
menu_matrix_calc_identity(void)1000 void menu_matrix_calc_identity(void)
1001 {
1002 	menu_matrix_calc_inv_trans_adj( 3 );
1003 }
1004 
menu_matrix_calc_determinant(void)1005 void menu_matrix_calc_determinant(void)
1006 {
1007 	gint notebook_index;
1008 	Complex det;
1009 	const char *name;
1010 
1011 	notebook_index = gtk_notebook_get_current_page( GTK_NOTEBOOK(matrix_editor.notebook) );
1012 
1013 	if( notebook_index == -1 )
1014 		return;
1015 
1016 	try
1017 	{
1018 		name = gtk_notebook_get_tab_label_text( GTK_NOTEBOOK(matrix_editor.notebook),
1019 		         gtk_notebook_get_nth_page( GTK_NOTEBOOK(matrix_editor.notebook), notebook_index ) );
1020 		det = math::global_varlist.get_pointer( math::global_varlist.get_id(name) )
1021 		                                                   ->get_matrix()->det();
1022 
1023 		try
1024 		{
1025 			GtkWidget *dialog;
1026 			utf8_string ostr, tmp_str;
1027 
1028 			ostr = "det ";
1029 			tmp_str = name;
1030 			ostr.append( tmp_str );
1031 			tmp_str = " = ";
1032 			ostr.append( tmp_str );
1033 
1034 			det.append_to_string( ostr, matrix_editor.format );
1035 			dialog = gtk_message_dialog_new( GTK_WINDOW(matrix_editor.window),
1036 			                                 GTK_DIALOG_DESTROY_WITH_PARENT,
1037 			                                 GTK_MESSAGE_INFO, GTK_BUTTONS_CLOSE, ostr.c_str() );
1038 			gtk_dialog_run(GTK_DIALOG(dialog));
1039 			gtk_widget_destroy(dialog);
1040 		}
1041 		catch( error_obj error ) { throw; }
1042 		catch( ... ) { THROW_ERROR( ErrorType_Memory, _("Couldn't get memory.") ); }
1043 	}
1044 	catch( error_obj error )
1045 	{
1046 		GtkWidget *dialog;
1047 		dialog = gtk_message_dialog_new( GTK_WINDOW(matrix_editor.window),
1048 		                                 GTK_DIALOG_DESTROY_WITH_PARENT,
1049 		                                 GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, error.msg );
1050 		gtk_dialog_run(GTK_DIALOG(dialog));
1051 		gtk_widget_destroy(dialog);
1052 	}
1053 }
1054 
menu_matrix_calc_add_sub_mul(int which)1055 void menu_matrix_calc_add_sub_mul( int which )
1056 {
1057 	utf8_string base, str;
1058 	GtkWidget *dialog, *align, *vbox;
1059 	const char *name;
1060 	math::Variable *ptr;
1061 	const math::Variable *ptr2;
1062 	Vector<GtkWidget *> radios;
1063 	int i,nr;
1064 	bool valid;
1065 
1066 	try{
1067 		try{
1068 			if( which == 0 )
1069 				name = _("Add...");
1070 			else if( which == 1 )
1071 				name = _("Substract...");
1072 			else
1073 				name = _("Multiply...");
1074 			dialog = gtk_dialog_new_with_buttons( name, GTK_WINDOW(matrix_editor.window),
1075 			                                      GTK_DIALOG_MODAL, GTK_STOCK_OK,
1076 			                                      GTK_RESPONSE_OK, NULL );
1077 
1078 			base = gtk_notebook_get_tab_label_text( GTK_NOTEBOOK(matrix_editor.notebook),
1079 			         gtk_notebook_get_nth_page( GTK_NOTEBOOK(matrix_editor.notebook),
1080 			         gtk_notebook_get_current_page( GTK_NOTEBOOK(matrix_editor.notebook) ) ) );
1081 			ptr = math::global_varlist.get_pointer_rw( math::global_varlist.get_id(base.c_str()) );
1082 			if( which == 0 )
1083 				base.append( " += " );
1084 			else if( which == 1 )
1085 				base.append( " -= " );
1086 			else
1087 				base.append( " *= " );
1088 
1089 			align = gtk_alignment_new( 0.0, 0.0, 1.0, 1.0 );
1090 			gtk_container_set_border_width( GTK_CONTAINER(align), 5 );
1091 			gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), align, FALSE, FALSE, 0);
1092 
1093 			vbox = gtk_vbox_new( FALSE, 3 );
1094 			gtk_container_add( GTK_CONTAINER(align), vbox );
1095 
1096 			for( i=0,nr=0; i<gtk_notebook_get_n_pages(GTK_NOTEBOOK(matrix_editor.notebook)); i++ )
1097 			{
1098 				name = gtk_notebook_get_tab_label_text( GTK_NOTEBOOK(matrix_editor.notebook),
1099 				  gtk_notebook_get_nth_page( GTK_NOTEBOOK(matrix_editor.notebook), i ) );
1100 				ptr2 = math::global_varlist.get_pointer( math::global_varlist.get_id(name) );
1101 				if( which == 0  ||  which == 1 ) // add  or  substract
1102 					valid = ( ptr->get_matrix()->get_width() == ptr2->get_matrix()->get_width()  &&
1103 				              ptr->get_matrix()->get_height() == ptr2->get_matrix()->get_height() );
1104 				else // multiply
1105 					valid = ( ptr->get_matrix()->get_width() == ptr2->get_matrix()->get_height() );
1106 				if( valid )
1107 				{
1108 					str = base;
1109 
1110 					str.append( *ptr2->get_name() );
1111 
1112 					if(nr == 0)
1113 					{
1114 						radios.append( gtk_radio_button_new_with_label( NULL, str.c_str() ) );
1115 						gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(*radios[0]), TRUE );
1116 					}
1117 					else
1118 						radios.append( gtk_radio_button_new_with_label_from_widget(
1119 						                 GTK_RADIO_BUTTON(*radios[0]), str.c_str() ) );
1120 
1121 					gtk_box_pack_start(GTK_BOX(vbox), *radios[nr], FALSE, FALSE, 0);
1122 					nr++;
1123 				}
1124 			}
1125 
1126 			if( nr == 0 )
1127 				THROW_ERROR( ErrorType_General, _("No matching matrix found") );
1128 
1129 			gtk_widget_show_all(dialog);
1130 
1131 			switch(gtk_dialog_run( GTK_DIALOG(dialog) ))
1132 			{
1133 			case GTK_RESPONSE_OK:
1134 				for( i=0,nr=0; i<gtk_notebook_get_n_pages(GTK_NOTEBOOK(matrix_editor.notebook)); i++ )
1135 				{
1136 					name = gtk_notebook_get_tab_label_text( GTK_NOTEBOOK(matrix_editor.notebook),
1137 					  gtk_notebook_get_nth_page( GTK_NOTEBOOK(matrix_editor.notebook), i ) );
1138 					ptr2 = math::global_varlist.get_pointer( math::global_varlist.get_id(name) );
1139 					if( which == 0  ||  which == 1 ) // add  or  substract
1140 						valid = ( ptr->get_matrix()->get_width() == ptr2->get_matrix()->get_width()  &&
1141 								  ptr->get_matrix()->get_height() == ptr2->get_matrix()->get_height() );
1142 					else // multiply
1143 						valid = ( ptr->get_matrix()->get_width() == ptr2->get_matrix()->get_height() );
1144 					if( valid )
1145 					{
1146 						if( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(*radios[nr]) ) == TRUE )
1147 						{
1148 							Matrix matr;
1149 
1150 							if( which == 0) // add
1151 								matrix_add( &matr, ptr->get_matrix(), ptr2->get_matrix() );
1152 							else if( which == 1 ) // substract
1153 								matrix_sub( &matr, ptr->get_matrix(), ptr2->get_matrix() );
1154 							else // multiply
1155 								matrix_mul( &matr, ptr->get_matrix(), ptr2->get_matrix() );
1156 							ptr->set_matrix( &matr );
1157 							ptr->signal_changed();
1158 							break;
1159 						}
1160 						nr++;
1161 					}
1162 				}
1163 				break;
1164 
1165 			default:
1166 				break;
1167 			}
1168 		}
1169 		catch( error_obj error ) {  gtk_widget_destroy(dialog); throw error;  }
1170 		catch( ... ) { gtk_widget_destroy(dialog);  THROW_ERROR( ErrorType_Memory, _("Couldn't get memory.") ); }
1171 		gtk_widget_destroy(dialog);
1172 	}
1173 	catch( error_obj error )
1174 	{
1175 		GtkWidget *dialog;
1176 		dialog = gtk_message_dialog_new( GTK_WINDOW(matrix_editor.window),
1177 		                                 GTK_DIALOG_DESTROY_WITH_PARENT,
1178 		                                 GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, error.msg );
1179 		gtk_dialog_run(GTK_DIALOG(dialog));
1180 		gtk_widget_destroy(dialog);
1181 	}
1182 }
1183 
menu_matrix_calc_add(void)1184 void menu_matrix_calc_add(void)
1185 {
1186 	menu_matrix_calc_add_sub_mul( 0 );
1187 }
menu_matrix_calc_substract(void)1188 void menu_matrix_calc_substract(void)
1189 {
1190 	menu_matrix_calc_add_sub_mul( 1 );
1191 }
menu_matrix_calc_multiply(void)1192 void menu_matrix_calc_multiply(void)
1193 {
1194 	menu_matrix_calc_add_sub_mul( 2 );
1195 }
1196 
menu_matrix_calc_power_fill(int val)1197 void menu_matrix_calc_power_fill( int val )
1198 {
1199 	GtkWidget *align, *dialog, *entry, *hbox, *label;
1200 	const char *str, *name;
1201 	gint notebook_index;
1202 
1203 
1204 	notebook_index = gtk_notebook_get_current_page( GTK_NOTEBOOK(matrix_editor.notebook) );
1205 	if( notebook_index == -1 )
1206 		return;
1207 
1208 	if( val == 0 ) // power
1209 		dialog = gtk_dialog_new_with_buttons( _("Power..."), GTK_WINDOW(matrix_editor.window),
1210 		                                      GTK_DIALOG_MODAL,	GTK_STOCK_OK, GTK_RESPONSE_OK, NULL );
1211 	else // if( val == 1 ) // fill with
1212 		dialog = gtk_dialog_new_with_buttons( _("Fill with..."), GTK_WINDOW(matrix_editor.window),
1213 		                                      GTK_DIALOG_MODAL,	GTK_STOCK_OK, GTK_RESPONSE_OK, NULL );
1214 
1215 	align = gtk_alignment_new( 0.0, 0.0, 1.0, 1.0 );
1216 	gtk_container_set_border_width( GTK_CONTAINER(align), 5 );
1217 	gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), align, FALSE, FALSE, 0);
1218 
1219 	hbox = gtk_hbox_new( FALSE, 3 );
1220 	gtk_container_add( GTK_CONTAINER(align), hbox );
1221 
1222 	{
1223 		const char *trans;
1224 		if( val == 0 )
1225 			trans = _("Power: ");
1226 		else
1227 			trans = _("Fill with: ");
1228 		label = gtk_label_new( trans );
1229 	}
1230 	gtk_box_pack_start( GTK_BOX(hbox), label, FALSE, TRUE, 0 );
1231 
1232 	entry = gtk_entry_new();
1233 	gtk_box_pack_start( GTK_BOX(hbox), entry, TRUE, TRUE, 0 );
1234 
1235 	gtk_widget_show_all( dialog );
1236 
1237 	if( gtk_dialog_run( GTK_DIALOG(dialog) ) == GTK_RESPONSE_OK )
1238 		str = gtk_entry_get_text( GTK_ENTRY(entry) );
1239 	else
1240 	{
1241 		gtk_widget_destroy( dialog );
1242 		return;
1243 	}
1244 
1245 	try
1246 	{
1247 		math::CodeLine code;
1248 		math::Variable *var, ans;
1249 		Matrix matr_ans;
1250 
1251 		code.set_code_line( str );
1252 
1253 		code.calc( &ans );
1254 
1255 		name = gtk_notebook_get_tab_label_text( GTK_NOTEBOOK(matrix_editor.notebook),
1256 		         gtk_notebook_get_nth_page( GTK_NOTEBOOK(matrix_editor.notebook), notebook_index ) );
1257 		var = math::global_varlist.get_pointer_rw( math::global_varlist.get_id(name) );
1258 
1259 		if( val == 0 )
1260 		{
1261 			Integer power;
1262 
1263 			if( ans.get_complex()->imaginary != Real(0.0) )
1264 				THROW_ERROR( ErrorType_Domain, _("Domain error: Imaginary part must be zero.") );
1265 			if( !ans.get_complex()->real.isInteger() )
1266 				THROW_ERROR( ErrorType_Domain, _("Domain error: Can't raise a matrix to a non integer number.") );
1267 			ans.get_complex()->real.get_top( &power );
1268 			matrix_pow( &matr_ans, var->get_matrix(), power );
1269 			var->set_matrix( &matr_ans );
1270 		}
1271 		else //if( val == 1 )
1272 		{
1273 			var->get_matrix_rw()->fill( *ans.get_complex() );
1274 			var->signal_changed();
1275 		}
1276 	}
1277 	catch( error_obj error )
1278 	{
1279 		GtkWidget *dialog2;
1280 		dialog2 = gtk_message_dialog_new( GTK_WINDOW(matrix_editor.window),
1281 										  GTK_DIALOG_DESTROY_WITH_PARENT,
1282 										  GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, error.msg );
1283 		gtk_dialog_run( GTK_DIALOG(dialog2) );
1284 		gtk_widget_destroy( dialog2 );
1285 	}
1286 	gtk_widget_destroy( dialog );
1287 }
1288 
menu_matrix_calc_power(void)1289 void menu_matrix_calc_power(void)
1290 {
1291 	menu_matrix_calc_power_fill( 0 );
1292 }
menu_matrix_calc_fill_with(void)1293 void menu_matrix_calc_fill_with(void)
1294 {
1295 	menu_matrix_calc_power_fill( 1 );
1296 }
1297