1 
2 /*
3  *  Ump - Unnamed Math Program
4  *  Copyright (c) 2004-2006 by Mattias Hultgren <mattias_hultgren@tele2.se>
5  *
6  *  See main.cpp
7  */
8 
9 #ifndef NO_GTK
10 	#include <gtk/gtk.h>
11 	#include "ump_picturewin.h"
12 #endif
13 #include "addon_functions.h"
14 #include "main.h"
15 #include "keyfile.h"
16 #include <string.h>
17 
18 
19 extern void (*TEXTVIEW_FUNCTION)(const utf8_string &string);
20 extern void (*QUIT_FUNCTION)(void);
21 
22 void term_quit(void);
23 void term_showtext(const utf8_string &string);
24 
25 
26 
string_replace_escapes(utf8_string & str)27 void string_replace_escapes( utf8_string &str ) throw(error_obj)
28 {
29 	char tkn[] = " ";
30 
31 	try
32 	{
33 		for( uint32 i=0; i<str.get_length(); i++ )
34 		{
35 			if( str.test_character( i, "\0" ) )
36 				break;
37 			else if( str.test_character( i, "\\" ) )
38 			{
39 				if( str.test_character( i+1, "n" ) )
40 					tkn[0] = '\n';
41 				else if( str.test_character( i+1, "\\" ) )
42 					tkn[0] = '\\';
43 				else if( str.test_character( i+1, "t" ) )
44 					tkn[0] = '\t';
45 				else
46 					tkn[0] = '\0';
47 				if( tkn[0] != '\0' )
48 					str.replace( i, 2, tkn );
49 			}
50 		}
51 	}
52 	catch(...) {  THROW_ERROR( ErrorType_Memory, _("Couldn't get memory.") );  }
53 }
54 
55 
addon_load_picture(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)56 void addon_load_picture( Variable *res, Variable *left, const Variable *right, VariableList *private_varlist ) throw(error_obj)
57 {
58 	if( left != 0  ||  right == 0 )
59 		THROW_ERROR( ErrorType_General, "Internal error: load_picture wasn't called the right way" );
60 
61 	if( res == 0 )
62 		return;
63 
64 	if( right->get_type() != math::VariableType_String )
65 	{
66 		char tmp_err[ERROR_OBJ_MSG_LEN];
67 		snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "load_picture" );
68 		THROW_ERROR( ErrorType_General, tmp_err );
69 	}
70 
71 	math::Picture pic;
72 
73 	pic.pic.load_pcx( right->get_string()->c_str() );
74 
75 	res->set_picture( &pic );
76 }
77 
addon_save_picture(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)78 void addon_save_picture( Variable *res, Variable *left, const Variable *right, VariableList *private_varlist ) throw(error_obj)
79 {
80 	const math::Picture *pic;
81 	const math::Array *array;
82 
83 	if( left != 0  ||  right == 0 )
84 		THROW_ERROR( ErrorType_General, "Internal error: save_picture wasn't called the right way" );
85 
86 	if( right->get_type() != math::VariableType_Array )
87 	{
88 		char tmp_err[ERROR_OBJ_MSG_LEN];
89 		snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "save_picture" );
90 		THROW_ERROR( ErrorType_General, tmp_err );
91 	}
92 
93 	array = right->get_array();
94 
95 	if(array->get_size() != 2)
96 		THROW_ERROR( ErrorType_General, _("Wrong number of arguments for 'save_picture'") );
97 
98 	if( ( array->get_variable(0)->get_type() != math::VariableType_Picture) |
99 	    ( array->get_variable(1)->get_type() != math::VariableType_String) )
100 	{
101 		char tmp_err[ERROR_OBJ_MSG_LEN];
102 		snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "save_picture" );
103 		THROW_ERROR( ErrorType_General, tmp_err );
104 	}
105 
106 	pic = array->get_variable(0)->get_picture();
107 
108 	pic->pic.save_pcx( array->get_variable(1)->get_string()->c_str() );
109 
110 	if( res != 0 )
111 		res->set_picture( pic );
112 }
113 
addon_load(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)114 void addon_load( Variable *res, Variable *left, const Variable *right, VariableList *private_varlist ) throw(error_obj)
115 {
116 	if( left != 0  ||  right == 0 )
117 		THROW_ERROR( ErrorType_General, "Internal error: load wasn't called the right way" );
118 
119 	if(right->get_type() != math::VariableType_String)
120 	{
121 		char tmp_err[ERROR_OBJ_MSG_LEN];
122 		snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "load" );
123 		THROW_ERROR( ErrorType_General, tmp_err );
124 	}
125 
126 	math::CodeBlock code;
127 
128 	code.set_code_from_file( *right->get_string() );
129 
130 	if( res != 0 )
131 		res->set_string( "File loaded" );
132 }
133 
addon_print(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)134 void addon_print(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
135 {
136 	utf8_string str;
137 
138 	if( left != 0  ||  right == 0 )
139 		THROW_ERROR( ErrorType_General, "Internal error: print wasn't called the right way" );
140 
141 	if(right->get_type() != math::VariableType_String)
142 	{
143 		char tmp_err[ERROR_OBJ_MSG_LEN];
144 		snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "print" );
145 		THROW_ERROR( ErrorType_General, tmp_err );
146 	}
147 
148 	str = *right->get_string();
149 
150 	string_replace_escapes( str );
151 
152 	(*TEXTVIEW_FUNCTION)(str);
153 
154 	if( res != 0 )
155 		res->set_string( str );
156 }
157 
addon_text_message(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)158 void addon_text_message(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
159 {
160 	const math::Array *array;
161 	char s[10];
162 	utf8_string title, msg;
163 
164 	if( left != 0  ||  right == 0 )
165 		THROW_ERROR( ErrorType_General, "Internal error: message wasn't called the right way" );
166 
167 	if(right->get_type() != math::VariableType_Array)
168 	{
169 		char tmp_err[ERROR_OBJ_MSG_LEN];
170 		snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "message" );
171 		THROW_ERROR( ErrorType_General, tmp_err );
172 	}
173 
174 	array = right->get_array();
175 	if( array->get_size() != 2 )
176 	{
177 		char tmp_err[ERROR_OBJ_MSG_LEN];
178 		snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "message" );
179 		THROW_ERROR( ErrorType_General, tmp_err );
180 	}
181 
182 	for( int i=0; i<2; i++ )
183 	{
184 		if( array->get_variable(i)->get_type() != math::VariableType_String )
185 		{
186 			char tmp_err[ERROR_OBJ_MSG_LEN];
187 			snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "message" );
188 			THROW_ERROR( ErrorType_General, tmp_err );
189 		}
190 	}
191 
192 	title = *( array->get_variable(0)->get_string() );
193 	msg = *( array->get_variable(1)->get_string() );
194 
195 	string_replace_escapes( msg );
196 
197 	term_showtext( title );
198 	term_showtext( "\n" );
199 	term_showtext( msg );
200 
201 	fgets( s, 2, stdin );
202 
203 	if( res != 0 )
204 		res->set_void();
205 }
206 
addon_text_menu(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)207 void addon_text_menu(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
208 {
209 	const math::Array *array;
210 	uint32 index;
211 	utf8_string ostr;
212 	char str[25];
213 
214 	if( left != 0  ||  right == 0  ||  res == 0 )
215 		THROW_ERROR( ErrorType_General, "Internal error: menu wasn't called the right way" );
216 
217 	if(right->get_type() != math::VariableType_Array)
218 	{
219 		char tmp_err[ERROR_OBJ_MSG_LEN];
220 		snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "menu" );
221 		THROW_ERROR( ErrorType_General, tmp_err );
222 	}
223 
224 	array = right->get_array();
225 	if( array->get_size() < 3 )
226 	{
227 		char tmp_err[ERROR_OBJ_MSG_LEN];
228 		snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "menu" );
229 		THROW_ERROR( ErrorType_General, tmp_err );
230 	}
231 
232 	for( index=0; index<array->get_size(); index++ )
233 	{
234 		if( array->get_variable(index)->get_type() != math::VariableType_String )
235 		{
236 			char tmp_err[ERROR_OBJ_MSG_LEN];
237 			snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "menu" );
238 			THROW_ERROR( ErrorType_General, tmp_err );
239 		}
240 	}
241 
242 	term_showtext( *( array->get_variable(0)->get_string() ) );
243 	term_showtext( "\n\n" );
244 	term_showtext( *( array->get_variable(1)->get_string() ) );
245 	term_showtext( "\n\n" );
246 
247 	for( index=2; index<array->get_size(); index++ )
248 	{
249 		snprintf( str, 20, "%lu - ", index-1 );
250 		ostr = str;
251 		ostr.append( *( array->get_variable(index)->get_string() ) );
252 		ostr.append( "\n" );
253 		term_showtext( ostr.c_str() );
254 	}
255 	term_showtext( "? " );
256 	fgets( str, 20, stdin );
257 	if( sscanf( str, "%lu", &index ) == 0 )
258 	{
259 		res->set_complex( Complex( -1 ) );
260 		return;
261 	}
262 
263 	if( index == 0  ||  index >= (array->get_size() +1) )
264 	{
265 		res->set_complex( Complex( -1 ) );
266 		return;
267 	}
268 
269 	res->set_string( *( array->get_variable(index+1)->get_string() ) );
270 }
271 
addon_text_input(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)272 void addon_text_input(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
273 {
274 	const math::Array *array;
275 	uint32 index;
276 	char str[500];
277 	math::Variable *tmp;
278 	const utf8_string *varname;
279 	utf8_string input, type_string;
280 	math::CodeLine code;
281 	math::Variable var_tmp;
282 
283 	if( left != 0  ||  right == 0 )
284 		THROW_ERROR( ErrorType_General, "Internal error: input wasn't called the right way" );
285 
286 	if(right->get_type() != math::VariableType_Array)
287 	{
288 		char tmp_err[ERROR_OBJ_MSG_LEN];
289 		snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "input" );
290 		THROW_ERROR( ErrorType_General, tmp_err );
291 	}
292 
293 	array = right->get_array();
294 	if( (array->get_size() % 4) != 1 )
295 	{
296 		char tmp_err[ERROR_OBJ_MSG_LEN];
297 		snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "input" );
298 		THROW_ERROR( ErrorType_General, tmp_err );
299 	}
300 
301 	if( array->get_variable(0)->get_type() != math::VariableType_String )
302 	{
303 		char tmp_err[ERROR_OBJ_MSG_LEN];
304 		snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "input" );
305 		THROW_ERROR( ErrorType_General, tmp_err );
306 	}
307 
308 	term_showtext( *( array->get_variable(0)->get_string() ) );
309 	term_showtext( "\n\n" );
310 
311 	for( index=1; index<array->get_size(); index += 4 )
312 	{
313 		if( array->get_variable(index)->get_type() != math::VariableType_String )
314 		{
315 			char tmp_err[ERROR_OBJ_MSG_LEN];
316 			snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "input" );
317 			THROW_ERROR( ErrorType_General, tmp_err );
318 		}
319 		if( array->get_variable(index+1)->get_type() != math::VariableType_String )
320 		{
321 			char tmp_err[ERROR_OBJ_MSG_LEN];
322 			snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "input" );
323 			THROW_ERROR( ErrorType_General, tmp_err );
324 		}
325 		if( array->get_variable(index+2)->has_name() == false )
326 		{
327 			char tmp_err[ERROR_OBJ_MSG_LEN];
328 			snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "input" );
329 			THROW_ERROR( ErrorType_General, tmp_err );
330 		}
331 		if( array->get_variable(index+3)->get_type() != math::VariableType_String )
332 		{
333 			char tmp_err[ERROR_OBJ_MSG_LEN];
334 			snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "input" );
335 			THROW_ERROR( ErrorType_General, tmp_err );
336 		}
337 
338 		addon_text_input_rerun_input:
339 		term_showtext( *( array->get_variable(index)->get_string() ) );
340 
341 		if( array->get_variable(index+3)->get_string()->get_length() > 0 )
342 		{
343 			term_showtext( " (" );
344 			term_showtext( *( array->get_variable(index+3)->get_string() ) );
345 			term_showtext( "): " );
346 		}
347 		else
348 			term_showtext( ": " );
349 
350 		fgets( str, 500, stdin );
351 		for( int i=0; str[i] != '\0'; i++ )
352 		{
353 			if( str[i] == '\n'  ||  str[i] == '\r' )
354 			{
355 				str[i] = '\0';
356 				break;
357 			}
358 		}
359 
360 		varname = array->get_variable(index+2)->get_name();
361 		if( private_varlist )
362 		{
363 			try{
364 				tmp = private_varlist->get_pointer_rw( private_varlist->get_id( (*varname).c_str() ) );
365 			}
366 			catch(...) {
367 				tmp = math::global_varlist.get_pointer_rw( math::global_varlist.get_id( (*varname).c_str() ) );
368 			}
369 		}
370 		else
371 			tmp = math::global_varlist.get_pointer_rw( math::global_varlist.get_id( (*varname).c_str() ) );
372 
373 		if( str[0] == '\0' )
374 		{
375 			if( array->get_variable(index+3)->get_string()->get_length() == 0 )
376 				goto addon_text_input_rerun_input;
377 			input = *( array->get_variable(index+3)->get_string() );
378 		}
379 		else
380 			input = str;
381 
382 		type_string = *( array->get_variable(index+1)->get_string() );
383 		if( type_string == "String" )
384 			tmp->set_string( input );
385 		else if( type_string == "Integer" )
386 		{
387 			Integer int_tmp;
388 
389 			code.set_code_line( input.c_str() );
390 			code.calc( &var_tmp, private_varlist );
391 
392 			math::argument_check( "input", &var_tmp, math::type_integer, &int_tmp, math::type_end );
393 			tmp->set_complex( Complex( int_tmp ) );
394 		}
395 		else if( type_string == "Complex" )
396 		{
397 			Complex complex_tmp;
398 
399 			code.set_code_line( input.c_str() );
400 			code.calc( &var_tmp, private_varlist );
401 
402 			math::argument_check( "input", &var_tmp, math::type_complex, &complex_tmp,
403 			                      math::type_end );
404 			tmp->set_complex( complex_tmp );
405 		}
406 		else
407 			THROW_ERROR( ErrorType_General, _("Unknown conversion type for function input") );
408 	}
409 
410 	if( res != 0 )
411 		res->set_boolean( true );
412 }
413 
addon_viewall(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)414 void addon_viewall(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
415 {
416 	if( left != 0  ||  right != 0 )
417 		THROW_ERROR( ErrorType_General, "Internal error: viewall wasn't called the right way" );
418 
419 	uint32 i,high;
420 	const Variable *var;
421 
422 	if(private_varlist == 0)
423 		private_varlist = &math::global_varlist;
424 
425 	high = private_varlist->get_highest_idnr();
426 
427 	for(i=1;i<=high;i++)
428 	{
429 		try{  var = private_varlist->get_pointer_rw(i);  }
430 		catch(...)
431 		{
432 			continue; // try next idnr...
433 		}
434 
435 		{
436 			utf8_string str;
437 			var->append_to_string( str, format, true );
438 			(*TEXTVIEW_FUNCTION)( str );
439 			str = "\n";
440 			(*TEXTVIEW_FUNCTION)( str );
441 		}
442 	}
443 	(*TEXTVIEW_FUNCTION)("\n");
444 
445 	if( private_varlist != &math::global_varlist)
446 		addon_viewall( 0, left, right, 0 );
447 
448 	if( res != 0 )
449 		res->set_void();
450 }
451 
addon_view(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)452 void addon_view(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
453 {
454 	utf8_string outstr, trans_str;
455 	const utf8_string *str;
456 	const Variable *var;
457 	uint32 idnr;
458 	bool deletable;
459 
460 	if( left != 0  ||  right == 0 )
461 		THROW_ERROR( ErrorType_General, "Internal error: view wasn't called the right way" );
462 
463 	if(right->has_name())
464 		str = right->get_name();
465 	else if(right->get_type() == math::VariableType_String)
466 		str = right->get_string();
467 	else
468 	{
469 		char tmp_err[ERROR_OBJ_MSG_LEN];
470 		snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "view" );
471 		THROW_ERROR( ErrorType_General, tmp_err );
472 	}
473 
474 	idnr = math::global_varlist.get_id(str->c_str());
475 	var = math::global_varlist.get_pointer(idnr);
476 	deletable = math::global_varlist.get_deletable(idnr);
477 
478 	trans_str = "\n";
479 	trans_str.append( _("Type: ") );
480 	if( var->get_isconstant() )
481 		trans_str.append( _("Constant") );
482 	else
483 		trans_str.append( _("Variable") );
484 	(*TEXTVIEW_FUNCTION)( trans_str );
485 
486 	if( deletable == false )
487 	{
488 		trans_str = "\n  ";
489 		trans_str.append( _("Undeletable") );
490 
491 		if( var->get_can_change_type() == false )
492 		{
493 			trans_str.append( "  " );
494 			trans_str.append( _("Type-locked") );
495 		}
496 		(*TEXTVIEW_FUNCTION)( trans_str );
497 	}
498 	else if( var->get_can_change_type() == false )
499 	{
500 		trans_str = "\n  ";
501 		trans_str.append( _("Type-locked") );
502 		(*TEXTVIEW_FUNCTION)( trans_str );
503 	}
504 
505 	trans_str = "\n";
506 	trans_str.append( _("Sub-type: ") );
507 	(*TEXTVIEW_FUNCTION)( trans_str );
508 	(*TEXTVIEW_FUNCTION)(math::VARIABLE_TYPE_NAMES[var->get_type()]);
509 
510 	outstr = "\n\n";
511 	(*TEXTVIEW_FUNCTION)( outstr );
512 	var->append_to_string( outstr, format, false );
513 	(*TEXTVIEW_FUNCTION)( outstr );
514 	outstr = "\n\n";
515 	(*TEXTVIEW_FUNCTION)( outstr );
516 
517 	if( res != 0 )
518 		res->set_void();
519 }
520 
addon_quit(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)521 void addon_quit(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
522 {
523 	(*QUIT_FUNCTION)();
524 }
525 
526 #ifndef NO_GTK
addon_show(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)527 void addon_show(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
528 {
529 	const math::Picture *pic;
530 
531 	if( left != 0  ||  right == 0 )
532 		THROW_ERROR( ErrorType_General, "Internal error: show wasn't called the right way" );
533 
534 	if( right->get_type() != math::VariableType_Picture )
535 	{
536 		char tmp_err[ERROR_OBJ_MSG_LEN];
537 		snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "show" );
538 		THROW_ERROR( ErrorType_General, tmp_err );
539 	}
540 
541 	pic = right->get_picture();
542 
543 	if( right->has_name() )
544 	{
545 		utf8_string str;
546 
547 		str = *right->get_name();
548 		str.append( " - " );
549 		str.append( PRG_NAME );
550 
551 		picturewin_show( str.c_str(), *pic );
552 	}
553 	else
554 		picturewin_show( PRG_NAME, *pic );
555 
556 	if( res != 0 )
557 		*res = *right;
558 }
559 
addon_message(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)560 void addon_message(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
561 {
562 	const math::Array *array;
563 	GtkWidget *dialog;
564 	utf8_string title, msg;
565 
566 	if( left != 0  ||  right == 0 )
567 		THROW_ERROR( ErrorType_General, "Internal error: message wasn't called the right way" );
568 
569 	if( right->get_type() != math::VariableType_Array )
570 	{
571 		char tmp_err[ERROR_OBJ_MSG_LEN];
572 		snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "message" );
573 		THROW_ERROR( ErrorType_General, tmp_err );
574 	}
575 
576 	array = right->get_array();
577 	if( array->get_size() != 2 )
578 	{
579 		char tmp_err[ERROR_OBJ_MSG_LEN];
580 		snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "message" );
581 		THROW_ERROR( ErrorType_General, tmp_err );
582 	}
583 
584 	for( int i=0; i<2; i++ )
585 	{
586 		if( array->get_variable(i)->get_type() != math::VariableType_String )
587 		{
588 			char tmp_err[ERROR_OBJ_MSG_LEN];
589 			snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "message" );
590 			THROW_ERROR( ErrorType_General, tmp_err );
591 		}
592 	}
593 
594 	title = *( array->get_variable(0)->get_string() );
595 	msg = *( array->get_variable(1)->get_string() );
596 
597 	string_replace_escapes( msg );
598 
599 	dialog = gtk_message_dialog_new( NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_INFO, GTK_BUTTONS_OK,
600 	                                 "%s", msg.c_str() );
601 
602 	gtk_window_set_title( GTK_WINDOW(dialog), title.c_str() );
603 
604 	gtk_dialog_run(GTK_DIALOG(dialog));
605 	gtk_widget_destroy(dialog);
606 
607 	if( res != 0 )
608 		res->set_void();
609 }
610 
addon_menu(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)611 void addon_menu(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
612 {
613 	GtkWidget *dialog, *label, *align, *vbox, **radio;
614 	uint32 index;
615 	const math::Array *array;
616 
617 	if( left != 0  ||  right == 0  ||  res == 0 )
618 		THROW_ERROR( ErrorType_General, "Internal error: menu wasn't called the right way" );
619 
620 	if( right->get_type() != math::VariableType_Array )
621 	{
622 		char tmp_err[ERROR_OBJ_MSG_LEN];
623 		snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "menu" );
624 		THROW_ERROR( ErrorType_General, tmp_err );
625 	}
626 
627 	array = right->get_array();
628 	if( array->get_size() < 3 )
629 	{
630 		char tmp_err[ERROR_OBJ_MSG_LEN];
631 		snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "menu" );
632 		THROW_ERROR( ErrorType_General, tmp_err );
633 	}
634 
635 	for( index=0; index<array->get_size(); index++ )
636 	{
637 		if( array->get_variable(index)->get_type() != math::VariableType_String )
638 		{
639 			char tmp_err[ERROR_OBJ_MSG_LEN];
640 			snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "menu" );
641 			THROW_ERROR( ErrorType_General, tmp_err );
642 		}
643 	}
644 
645 	try
646 	{
647 		radio = new GtkWidget* [array->get_size()-2];
648 	}
649 	catch(...) {  THROW_ERROR( ErrorType_Memory, _("Couldn't get memory.") );  }
650 
651 	dialog = gtk_dialog_new_with_buttons( NULL, NULL, GTK_DIALOG_MODAL,
652 	                                      GTK_STOCK_OK, GTK_RESPONSE_OK, NULL);
653 
654 	align = gtk_alignment_new( 0.0, 0.0, 1.0, 1.0 );
655 	gtk_container_set_border_width( GTK_CONTAINER(align), 5 );
656 	gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), align, FALSE, FALSE, 0);
657 
658 	vbox = gtk_vbox_new( FALSE, 3 );
659 	gtk_container_add( GTK_CONTAINER(align), vbox );
660 
661 	gtk_window_set_title( GTK_WINDOW(dialog), array->get_variable(0)->get_string()->c_str() );
662 
663 	label = gtk_label_new( array->get_variable(1)->get_string()->c_str() );
664 	gtk_misc_set_alignment( GTK_MISC(label), 0.0, 0.5 );
665 	gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
666 
667 
668 	for( index=2; index<array->get_size(); index++ )
669 	{
670 		if( index == 2 )
671 		{
672 			radio[0] = gtk_radio_button_new_with_label( NULL,
673 			  array->get_variable(index)->get_string()->c_str() );
674 			gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(radio[0]), TRUE );
675 		}
676 		else
677 			radio[index-2] = gtk_radio_button_new_with_label_from_widget(
678 			  GTK_RADIO_BUTTON(radio[0]), array->get_variable(index)->get_string()->c_str() );
679 
680 		gtk_box_pack_start(GTK_BOX(vbox), radio[index-2], FALSE, FALSE, 0);
681 	}
682 
683 	gtk_widget_show_all(dialog);
684 
685 	switch(gtk_dialog_run( GTK_DIALOG(dialog) ))
686 	{
687 	case GTK_RESPONSE_OK:
688 
689 		for( index=2; index<array->get_size(); index++ )
690 		{
691 			if(gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(radio[index-2]) ) == TRUE)
692 				break;
693 		}
694 		break;
695 
696 	default:
697 		gtk_widget_destroy(dialog);
698 		delete [] radio;
699 
700 		res->set_complex( Complex(-1) );
701 		return;
702 	}
703 	gtk_widget_destroy(dialog);
704 	delete [] radio;
705 
706 	res->set_string( *( array->get_variable(index)->get_string() ) );
707 }
708 
addon_input(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)709 void addon_input(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
710 {
711 	GtkWidget *dialog, *label, *align, *table, **entry;
712 	uint32 index;
713 	const math::Array *array;
714 	utf8_string input, type_string;
715 	const utf8_string *varname;
716 	math::Variable *tmp, var_tmp;
717 	math::CodeLine code;
718 
719 	if( left != 0  ||  right == 0 )
720 		THROW_ERROR( ErrorType_General, "Internal error: input wasn't called the right way" );
721 
722 	if(right->get_type() != math::VariableType_Array)
723 	{
724 		char tmp_err[ERROR_OBJ_MSG_LEN];
725 		snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "input" );
726 		THROW_ERROR( ErrorType_General, tmp_err );
727 	}
728 	array = right->get_array();
729 	if( (array->get_size() % 4 ) != 1 )
730 	{
731 		char tmp_err[ERROR_OBJ_MSG_LEN];
732 		snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "input" );
733 		THROW_ERROR( ErrorType_General, tmp_err );
734 	}
735 
736 	if( array->get_variable(0)->get_type() != math::VariableType_String )
737 	{
738 		char tmp_err[ERROR_OBJ_MSG_LEN];
739 		snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "input" );
740 		THROW_ERROR( ErrorType_General, tmp_err );
741 	}
742 
743 	for( index=1; index<array->get_size(); index += 4 )
744 	{
745 		if( array->get_variable(index)->get_type() != math::VariableType_String )
746 		{
747 			char tmp_err[ERROR_OBJ_MSG_LEN];
748 			snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "input" );
749 			THROW_ERROR( ErrorType_General, tmp_err );
750 		}
751 		if( array->get_variable(index+1)->get_type() != math::VariableType_String )
752 		{
753 			char tmp_err[ERROR_OBJ_MSG_LEN];
754 			snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "input" );
755 			THROW_ERROR( ErrorType_General, tmp_err );
756 		}
757 		if( array->get_variable(index+2)->has_name() == false )
758 		{
759 			char tmp_err[ERROR_OBJ_MSG_LEN];
760 			snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "input" );
761 			THROW_ERROR( ErrorType_General, tmp_err );
762 		}
763 		if( array->get_variable(index+3)->get_type() != math::VariableType_String )
764 		{
765 			char tmp_err[ERROR_OBJ_MSG_LEN];
766 			snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "input" );
767 			THROW_ERROR( ErrorType_General, tmp_err );
768 		}
769 	}
770 
771 	try
772 	{
773 		entry = new GtkWidget* [array->get_size() / 4];
774 	}
775 	catch(...) {  THROW_ERROR( ErrorType_Memory, _("Couldn't get memory.") );  }
776 
777 	try
778 	{
779 		dialog = gtk_dialog_new_with_buttons( NULL, NULL, GTK_DIALOG_MODAL,
780 		                                      GTK_STOCK_OK, GTK_RESPONSE_OK, NULL);
781 
782 		gtk_window_set_title( GTK_WINDOW(dialog), array->get_variable(0)->get_string()->c_str() );
783 
784 		align = gtk_alignment_new( 0.0, 0.0, 1.0, 1.0 );
785 		gtk_container_set_border_width( GTK_CONTAINER(align), 5 );
786 		gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), align, FALSE, FALSE, 0);
787 
788 		table = gtk_table_new ( array->get_size() / 4, 2, FALSE );
789 		gtk_table_set_row_spacings( GTK_TABLE(table), 3 );
790 		gtk_table_set_col_spacings( GTK_TABLE(table), 3 );
791 
792 		gtk_container_add( GTK_CONTAINER(align), table );
793 
794 		for( index=0; index<(array->get_size()-1); index += 4 )
795 		{
796 			label = gtk_label_new( array->get_variable(index+1)->get_string()->c_str() );
797 			gtk_misc_set_alignment( GTK_MISC(label), 0.0, 0.5 );
798 			gtk_table_attach( GTK_TABLE(table), label, 0, 1, index/4, index/4+1, GTK_FILL,
799 			                  GTK_FILL, 0, 0 );
800 
801 			entry[index/4] = gtk_entry_new();
802 			gtk_entry_set_max_length( GTK_ENTRY(entry[index/4]), 500 );
803 			gtk_entry_set_activates_default( GTK_ENTRY(entry[index/4]), FALSE );
804 			if( array->get_variable(index+4)->get_string()->get_length() > 0 )
805 				gtk_entry_set_text( GTK_ENTRY(entry[index/4]),
806 				                    array->get_variable(index+4)->get_string()->c_str() );
807 			else
808 				gtk_entry_set_text( GTK_ENTRY(entry[index/4]), "" );
809 			gtk_table_attach( GTK_TABLE(table), entry[index/4], 1, 2, index/4, index/4+1, GTK_FILL,
810 			                  GTK_FILL, 0, 0 );
811 		}
812 		gtk_widget_show_all(dialog);
813 
814 		switch(gtk_dialog_run( GTK_DIALOG(dialog) ))
815 		{
816 		case GTK_RESPONSE_OK:
817 
818 			for( index=0; index<(array->get_size()-1); index += 4 )
819 			{
820 				varname = array->get_variable(index+3)->get_name();
821 				if(private_varlist)
822 				{
823 					try{
824 						tmp = private_varlist->get_pointer_rw( private_varlist->get_id(
825 						               (*varname).c_str() ) );
826 					}
827 					catch(...) {
828 						tmp = math::global_varlist.get_pointer_rw( math::global_varlist.get_id(
829 						               (*varname).c_str() ) );
830 					}
831 				}
832 				else
833 					tmp = math::global_varlist.get_pointer_rw( math::global_varlist.get_id(
834 					               (*varname).c_str() ) );
835 
836 				input = gtk_entry_get_text( GTK_ENTRY(entry[index/4]) );
837 
838 				type_string = *( array->get_variable(index+2)->get_string() );
839 				if( type_string == "String" )
840 					tmp->set_string( input );
841 				else if( type_string == "Integer" )
842 				{
843 					Integer int_tmp;
844 
845 					code.set_code_line( input.c_str() );
846 					code.calc( &var_tmp, private_varlist );
847 
848 					math::argument_check( "input", &var_tmp, math::type_integer, &int_tmp,
849 					                      math::type_end );
850 					tmp->set_complex( Complex( int_tmp ) );
851 				}
852 				else if( type_string == "Complex" )
853 				{
854 					Complex complex_tmp;
855 
856 					code.set_code_line( input.c_str() );
857 					code.calc( &var_tmp, private_varlist );
858 
859 					math::argument_check( "input", &var_tmp, math::type_complex, &complex_tmp,
860 					                      math::type_end );
861 					tmp->set_complex( complex_tmp );
862 				}
863 				else
864 					THROW_ERROR( ErrorType_General, _("Unknown conversion type in function input") );
865 			}
866 			break;
867 
868 		default:
869 			gtk_widget_destroy(dialog);
870 			delete [] entry;
871 			entry = 0;
872 
873 			if( res != 0 )
874 				res->set_boolean( false );
875 			return;
876 		}
877 		gtk_widget_destroy(dialog);
878 	}
879 	catch(...)
880 	{
881 		gtk_widget_destroy(dialog);
882 		delete [] entry;
883 		throw;
884 	}
885 	delete [] entry;
886 
887 	if( res != 0 )
888 		res->set_boolean( true );
889 }
890 
891 #endif
892