1 
2 ///////////////////////////////////////////////////////////
3 //                                                       //
4 //                         SAGA                          //
5 //                                                       //
6 //      System for Automated Geoscientific Analyses      //
7 //                                                       //
8 //                Command Line Interface                 //
9 //                                                       //
10 //                   Program: SAGA_CMD                   //
11 //                                                       //
12 //-------------------------------------------------------//
13 //                                                       //
14 //                        tool.cpp                       //
15 //                                                       //
16 //          Copyright (C) 2005 by Olaf Conrad            //
17 //                                                       //
18 //-------------------------------------------------------//
19 //                                                       //
20 // This file is part of 'SAGA - System for Automated     //
21 // Geoscientific Analyses'. SAGA is free software; you   //
22 // can redistribute it and/or modify it under the terms  //
23 // of the GNU General Public License as published by the //
24 // Free Software Foundation, either version 2 of the     //
25 // License, or (at your option) any later version.       //
26 //                                                       //
27 // SAGA is distributed in the hope that it will be       //
28 // useful, but WITHOUT ANY WARRANTY; without even the    //
29 // implied warranty of MERCHANTABILITY or FITNESS FOR A  //
30 // PARTICULAR PURPOSE. See the GNU General Public        //
31 // License for more details.                             //
32 //                                                       //
33 // You should have received a copy of the GNU Lesser     //
34 // General Public License along with this program; if    //
35 // not, see <http://www.gnu.org/licenses/>.              //
36 //                                                       //
37 //-------------------------------------------------------//
38 //                                                       //
39 //    contact:    Olaf Conrad                            //
40 //                Institute of Geography                 //
41 //                University of Goettingen               //
42 //                Goldschmidtstr. 5                      //
43 //                37077 Goettingen                       //
44 //                Germany                                //
45 //                                                       //
46 //    e-mail:     oconrad@saga-gis.org                   //
47 //                                                       //
48 ///////////////////////////////////////////////////////////
49 
50 //---------------------------------------------------------
51 #include <wx/datetime.h>
52 
53 #include "callback.h"
54 
55 #include "tool.h"
56 
57 
58 ///////////////////////////////////////////////////////////
59 //                                                       //
60 //                                                       //
61 //                                                       //
62 ///////////////////////////////////////////////////////////
63 
64 //---------------------------------------------------------
CCMD_Tool(void)65 CCMD_Tool::CCMD_Tool(void)
66 {
67 	m_pTool	= NULL;
68 }
69 
CCMD_Tool(CSG_Tool * pTool)70 CCMD_Tool::CCMD_Tool(CSG_Tool *pTool)
71 {
72 	Create(pTool);
73 }
74 
75 //---------------------------------------------------------
~CCMD_Tool(void)76 CCMD_Tool::~CCMD_Tool(void)
77 {
78 	Destroy();
79 }
80 
81 
82 ///////////////////////////////////////////////////////////
83 //                                                       //
84 ///////////////////////////////////////////////////////////
85 
86 //---------------------------------------------------------
Create(CSG_Tool * pTool)87 bool CCMD_Tool::Create(CSG_Tool *pTool)
88 {
89 	Destroy();
90 
91 	if( (m_pTool = pTool) != NULL )
92 	{
93 		_Set_Parameters(m_pTool->Get_Parameters());
94 
95 		for(int i=0; i<m_pTool->Get_Parameters_Count(); i++)
96 		{
97 			_Set_Parameters(m_pTool->Get_Parameters(i));
98 		}
99 
100 		return( true );
101 	}
102 
103 	return( false );
104 }
105 
106 //---------------------------------------------------------
Destroy(void)107 void CCMD_Tool::Destroy(void)
108 {
109 	m_pTool	= NULL;
110 
111 	m_CMD.Reset();
112 	m_CMD.SetSwitchChars("-");
113 }
114 
115 //---------------------------------------------------------
Usage(void)116 void CCMD_Tool::Usage(void)
117 {
118 	if( m_pTool )
119 	{
120 		wxString	Usage	= wxString::Format("\nUsage: saga_cmd %s %s %s",
121 			m_pTool->Get_Library().c_str(),
122 			m_pTool->Get_ID     ().c_str(),
123 			m_CMD.GetUsageString().AfterFirst(' ').AfterFirst(' ')
124 		);
125 
126 		SG_Printf(&Usage);
127 	}
128 }
129 
130 
131 ///////////////////////////////////////////////////////////
132 //                                                       //
133 ///////////////////////////////////////////////////////////
134 
135 //---------------------------------------------------------
Execute(int argc,char * argv[])136 bool CCMD_Tool::Execute(int argc, char *argv[])
137 {
138 	if( !m_pTool )
139 	{
140 		return( false );
141 	}
142 
143 	if( argc <= 1 )
144 	{
145 		Usage();
146 
147 		return( false );
148 	}
149 
150 	//-----------------------------------------------------
151 	// m_CMD.SetCmdLine(argc, argv);
152 	//
153 	// We can't do it this way (passing argv as char**) because then we use an
154 	// overload of the method which (re-)sets the locale from the current
155 	// enviromment; in order to prevent this, we use wxString overload
156 	{
157 		wxString	sCmdLine;
158 
159 		for(int i=1; i<argc; i++)
160 		{
161 			sCmdLine	+= wxString(i == 1 ? "\"" : " \"") + argv[i] + "\"";
162 		}
163 
164 		m_CMD.SetCmdLine(sCmdLine);
165 	}
166 
167 	if( m_CMD.Parse(false) != 0 )
168 	{
169 		Usage();
170 
171 		return( false );
172 	}
173 
174 	//-----------------------------------------------------
175 	bool	bResult	= _Get_Parameters(m_pTool->Get_Parameters(), true);
176 
177 	for(int i=0; bResult && i<m_pTool->Get_Parameters_Count(); i++)
178 	{
179 		bResult	= _Get_Parameters(m_pTool->Get_Parameters(i), true);
180 	}
181 
182 	if( !bResult )
183 	{
184 		Usage();
185 
186 		return( false );
187 	}
188 
189 	//-----------------------------------------------------
190 	CMD_Set_Tool(this);
191 
192 	if( m_pTool->On_Before_Execution() )
193 	{
194 		bResult	= m_pTool->Execute(true);
195 
196 		m_pTool->On_After_Execution();
197 	}
198 
199 	CMD_Set_Tool(NULL);
200 
201 	//-----------------------------------------------------
202 	if( bResult )
203 	{
204 		_Save_Output(m_pTool->Get_Parameters());
205 
206 		for(int i=0; i<m_pTool->Get_Parameters_Count(); i++)
207 		{
208 			_Save_Output(m_pTool->Get_Parameters(i));
209 		}
210 
211 		SG_Get_Data_Manager().Delete_Unsaved();	// remove temporary data to save memory resources
212 	}
213 	else
214 	{
215 		CMD_Print_Error(_TL("executing tool"), m_pTool->Get_Name());
216 	}
217 
218 	SG_UI_ProgressAndMsg_Reset(); SG_UI_Process_Set_Okay();
219 
220 	return( bResult );
221 }
222 
223 
224 ///////////////////////////////////////////////////////////
225 //                                                       //
226 ///////////////////////////////////////////////////////////
227 
228 //---------------------------------------------------------
_Get_ID(CSG_Parameter * pParameter,const wxString & Modifier)229 wxString CCMD_Tool::_Get_ID(CSG_Parameter *pParameter, const wxString &Modifier)
230 {
231 	wxString	ID(pParameter->Get_Parameters()->Get_Identifier().c_str());
232 
233 	if( ID.Length() > 0 )
234 	{
235 		ID	+= "_";
236 	}
237 
238 	ID	+= pParameter->Get_Identifier();
239 
240 	if( Modifier.Length() > 0 )
241 	{
242 		ID	+= "_" + Modifier;
243 	}
244 
245 	ID.Replace(".", "_");
246 
247 	return( ID );
248 }
249 
250 
251 ///////////////////////////////////////////////////////////
252 //                                                       //
253 ///////////////////////////////////////////////////////////
254 
255 //---------------------------------------------------------
_Set_Parameters(CSG_Parameters * pParameters)256 bool CCMD_Tool::_Set_Parameters(CSG_Parameters *pParameters)
257 {
258 	if( !pParameters )
259 	{
260 		return( false );
261 	}
262 
263 	//-----------------------------------------------------
264 	for(int i=0; i<pParameters->Get_Count(); i++)
265 	{
266 		CSG_Parameter	*pParameter	= pParameters->Get_Parameter(i);
267 
268 		//-------------------------------------------------
269 		if( pParameter->is_DataObject() )	// reset data object parameters, avoids problems when tool is called more than once without un-/reloading
270 		{
271 			pParameter->Set_Value(DATAOBJECT_NOTSET);
272 		}
273 		else if( pParameter->is_DataObject_List() )
274 		{
275 			pParameter->asList()->Del_Items();
276 		}
277 
278 		//-------------------------------------------------
279 		if( pParameter->do_UseInCMD() == false )
280 		{
281 			continue;
282 		}
283 
284 		wxString	Description	= pParameter->Get_Description(
285 			PARAMETER_DESCRIPTION_NAME|PARAMETER_DESCRIPTION_TYPE|PARAMETER_DESCRIPTION_PROPERTIES, SG_T("\n\t")
286 		).c_str();
287 
288 		Description.Replace("\xb", "");	// unicode problem: quick'n'dirty bug fix, to be replaced
289 
290 		if( pParameter->is_Input() || pParameter->is_Output() )
291 		{
292 			m_CMD.AddOption(_Get_ID(pParameter), wxEmptyString, Description, wxCMD_LINE_VAL_STRING, wxCMD_LINE_NEEDS_SEPARATOR|wxCMD_LINE_PARAM_OPTIONAL);
293 		}
294 
295 		//-------------------------------------------------
296 		else if( pParameter->is_Option() && !pParameter->is_Information() )
297 		{
298 			switch( pParameter->Get_Type() )
299 			{
300 			case PARAMETER_TYPE_Parameters  :
301 				_Set_Parameters(pParameter->asParameters());
302 				break;
303 
304 			case PARAMETER_TYPE_Bool        :
305 				m_CMD.AddOption(_Get_ID(pParameter), wxEmptyString, Description, wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL);
306 				break;
307 
308 			case PARAMETER_TYPE_Int         :
309 				m_CMD.AddOption(_Get_ID(pParameter), wxEmptyString, Description, wxCMD_LINE_VAL_NUMBER, wxCMD_LINE_PARAM_OPTIONAL);
310 				break;
311 
312 			case PARAMETER_TYPE_Choice      :
313 			case PARAMETER_TYPE_Choices     :
314 			case PARAMETER_TYPE_Table_Field :
315 			case PARAMETER_TYPE_Table_Fields:
316 				m_CMD.AddOption(_Get_ID(pParameter), wxEmptyString, Description, wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL);
317 				break;
318 
319 			case PARAMETER_TYPE_Double      :
320 			case PARAMETER_TYPE_Degree      :
321 				m_CMD.AddOption(_Get_ID(pParameter), wxEmptyString, Description, wxCMD_LINE_VAL_DOUBLE, wxCMD_LINE_PARAM_OPTIONAL);
322 				break;
323 
324 			case PARAMETER_TYPE_Date        :
325 				m_CMD.AddOption(_Get_ID(pParameter), wxEmptyString, Description, wxCMD_LINE_VAL_DATE  , wxCMD_LINE_PARAM_OPTIONAL);
326 				break;
327 
328 			case PARAMETER_TYPE_Range       :
329 				m_CMD.AddOption(_Get_ID(pParameter, "MIN"), wxEmptyString, Description, wxCMD_LINE_VAL_DOUBLE, wxCMD_LINE_PARAM_OPTIONAL);
330 				m_CMD.AddOption(_Get_ID(pParameter, "MAX"), wxEmptyString, Description, wxCMD_LINE_VAL_DOUBLE, wxCMD_LINE_PARAM_OPTIONAL);
331 				break;
332 
333 			case PARAMETER_TYPE_Color       :
334 				m_CMD.AddOption(_Get_ID(pParameter), wxEmptyString, Description, wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL);
335 				break;
336 
337 			case PARAMETER_TYPE_Colors      :
338 				m_CMD.AddOption(_Get_ID(pParameter), wxEmptyString, Description, wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL);
339 				break;
340 
341 			case PARAMETER_TYPE_String      :
342 			case PARAMETER_TYPE_Text        :
343 			case PARAMETER_TYPE_FilePath    :
344 				m_CMD.AddOption(_Get_ID(pParameter), wxEmptyString, Description, wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL);
345 				break;
346 
347 			case PARAMETER_TYPE_FixedTable  :
348 				m_CMD.AddOption(_Get_ID(pParameter), wxEmptyString, Description, wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL);
349 				break;
350 
351 			case PARAMETER_TYPE_Grid_System :
352 				if( pParameter->Get_Children_Count() == 0 )
353 				{
354 					m_CMD.AddOption(_Get_ID(pParameter,    "D"), wxEmptyString, _TL("Cell Size"                          ), wxCMD_LINE_VAL_DOUBLE, wxCMD_LINE_PARAM_OPTIONAL);
355 					m_CMD.AddOption(_Get_ID(pParameter,    "X"), wxEmptyString, _TL("Lower Left Center Cell X-Coordinate"), wxCMD_LINE_VAL_DOUBLE, wxCMD_LINE_PARAM_OPTIONAL);
356 					m_CMD.AddOption(_Get_ID(pParameter,    "Y"), wxEmptyString, _TL("Lower Left Center Cell Y-Coordinate"), wxCMD_LINE_VAL_DOUBLE, wxCMD_LINE_PARAM_OPTIONAL);
357 					m_CMD.AddOption(_Get_ID(pParameter,   "NX"), wxEmptyString, _TL("Number of Columns"                  ), wxCMD_LINE_VAL_NUMBER, wxCMD_LINE_PARAM_OPTIONAL);
358 					m_CMD.AddOption(_Get_ID(pParameter,   "NY"), wxEmptyString, _TL("Number of Rows"                     ), wxCMD_LINE_VAL_NUMBER, wxCMD_LINE_PARAM_OPTIONAL);
359 					m_CMD.AddOption(_Get_ID(pParameter, "FILE"), wxEmptyString, _TL("Grid File"                          ), wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL);
360 				}
361 				break;
362 
363 			default:
364 				break;
365 			}
366 		}
367 	}
368 
369 	return( true );
370 }
371 
372 
373 ///////////////////////////////////////////////////////////
374 //                                                       //
375 ///////////////////////////////////////////////////////////
376 
377 //---------------------------------------------------------
_Get_Parameters(CSG_Parameters * pParameters,bool bInitialize)378 bool CCMD_Tool::_Get_Parameters(CSG_Parameters *pParameters, bool bInitialize)
379 {
380 	if( !pParameters )
381 	{
382 		return( false );
383 	}
384 
385 	if( bInitialize )
386 	{
387 		pParameters->Restore_Defaults();
388 	}
389 
390 	//-----------------------------------------------------
391 	return( _Get_Options(pParameters, bInitialize)	// options might 'disable' some input, so check all options before the input is checked!
392 		&&  _Get_Input  (pParameters)
393 		&&  _Get_Options(pParameters, false)		// setting input might have reset some options, so check options one more time!
394 	);
395 }
396 
397 //---------------------------------------------------------
_Get_Options(CSG_Parameters * pParameters,bool bInitialize)398 bool CCMD_Tool::_Get_Options(CSG_Parameters *pParameters, bool bInitialize)
399 {
400 	for(int i=0; i<pParameters->Get_Count(); i++)
401 	{
402 		CSG_Parameter	*pParameter	= pParameters->Get_Parameter(i);
403 
404 		if( pParameter->do_UseInCMD() == false )
405 		{
406 			// ignore here
407 		}
408 
409 		else if( pParameter->is_Input() )
410 		{
411 			// nop now, loading options first
412 		}
413 
414 		else if( pParameter->is_Output() )
415 		{
416 			if( pParameter->is_DataObject() && pParameter->is_Optional() && !pParameter->asDataObject() && m_CMD.Found(_Get_ID(pParameter)) )
417 			{
418 				pParameter->Set_Value(DATAOBJECT_CREATE);
419 			}
420 		}
421 
422 		else if( pParameter->is_Option() && !pParameter->is_Information() )
423 		{
424 			long		l;
425 			double		d;
426 			wxString	s;
427 
428 			switch( pParameter->Get_Type() )
429 			{
430 			default:
431 				break;
432 
433 			case PARAMETER_TYPE_Parameters:
434 				_Get_Parameters(pParameter->asParameters(), bInitialize);
435 
436 				pParameter->has_Changed();
437 				break;
438 
439 			case PARAMETER_TYPE_Bool:
440 				if( m_CMD.Found(_Get_ID(pParameter), &s) )
441 				{
442 					if(      (s.ToLong(&l) && l == 1) || !s.CmpNoCase("true" ) )
443 					{
444 						pParameter->Set_Value(1);
445 					}
446 					else if( (s.ToLong(&l) && l == 0) || !s.CmpNoCase("false") )
447 					{
448 						pParameter->Set_Value(0);
449 					}
450 					else
451 					{
452 						CMD_Print_Error(pParameter->Get_Name(), _TL("invalid boolean value ('0', '1', 'false', 'true')"));
453 
454 						return( false );
455 					}
456 				}
457 				break;
458 
459 			case PARAMETER_TYPE_Int:
460 				if( m_CMD.Found(_Get_ID(pParameter), &l) )
461 				{
462 					pParameter->Set_Value((int)l);
463 				}
464 				break;
465 
466 			case PARAMETER_TYPE_Choice:
467 				if( m_CMD.Found(_Get_ID(pParameter), &s) )
468 				{
469 					if( s.ToLong(&l) )
470 					{
471 						pParameter->Set_Value((int)l);
472 					}
473 					else
474 					{
475 						pParameter->Set_Value(CSG_String(&s));
476 					}
477 				}
478 				break;
479 
480 			case PARAMETER_TYPE_Choices:
481 				if( m_CMD.Found(_Get_ID(pParameter), &s) )
482 				{
483 					pParameter->Set_Value(CSG_String(&s));
484 				}
485 				break;
486 
487 			case PARAMETER_TYPE_Double:
488 			case PARAMETER_TYPE_Degree:
489 				if( m_CMD.Found(_Get_ID(pParameter), &d) )
490 				{
491 					pParameter->Set_Value(d);
492 				}
493 				break;
494 
495 			case PARAMETER_TYPE_Date:
496 				{
497 					wxDateTime	Date;
498 
499 					if( m_CMD.Found(_Get_ID(pParameter), &Date) )
500 					{
501 						pParameter->Set_Value(Date.GetJDN());
502 					}
503 				}
504 				break;
505 
506 			case PARAMETER_TYPE_Range:
507 				if( m_CMD.Found(_Get_ID(pParameter, "MIN"), &d) )
508 				{
509 					pParameter->asRange()->Set_Min(d);
510 
511 					pParameter->has_Changed();
512 				}
513 
514 				if( m_CMD.Found(_Get_ID(pParameter, "MAX"), &d) )
515 				{
516 					pParameter->asRange()->Set_Max(d);
517 
518 					pParameter->has_Changed();
519 				}
520 				break;
521 
522 			case PARAMETER_TYPE_Color:
523 				if( m_CMD.Found(_Get_ID(pParameter), &s) )
524 				{
525 					pParameter->Set_Value(CSG_String(&s));
526 				}
527 				break;
528 
529 			case PARAMETER_TYPE_Colors:
530 				if( m_CMD.Found(_Get_ID(pParameter), &s) )
531 				{
532 					pParameter->asColors()->Load(CSG_String(&s));
533 				}
534 				break;
535 
536 			case PARAMETER_TYPE_String:
537 				if( m_CMD.Found(_Get_ID(pParameter), &s) )
538 				{
539 					pParameter->Set_Value(CSG_String(&s));
540 				}
541 				break;
542 
543 			case PARAMETER_TYPE_Text:
544 				if( m_CMD.Found(_Get_ID(pParameter), &s) )
545 				{
546 					CSG_File	Stream;
547 
548 					if( Stream.Open(CSG_String(&s)) )
549 					{
550 						CSG_String	t;
551 
552 						Stream.Read(t, Stream.Length());
553 
554 						pParameter->Set_Value(t.c_str());
555 					}
556 					else
557 					{
558 						pParameter->Set_Value(CSG_String(&s));
559 					}
560 				}
561 				break;
562 
563 			case PARAMETER_TYPE_FilePath:
564 				if( m_CMD.Found(_Get_ID(pParameter), &s) )
565 				{
566 					if( pParameter->asFilePath()->is_Multiple() )
567 					{
568 						s.Prepend("\"");
569 						s.Replace(";", "\" \"");
570 						s.Append ("\"");
571 					}
572 
573 					pParameter->Set_Value(CSG_String(&s));
574 				}
575 				break;
576 
577 			case PARAMETER_TYPE_FixedTable:
578 				if( m_CMD.Found(_Get_ID(pParameter), &s) )
579 				{
580 					CSG_Table	Table(&s);
581 
582 					pParameter->asTable()->Assign_Values(&Table);
583 
584 					pParameter->has_Changed();
585 				}
586 				break;
587 
588 			case PARAMETER_TYPE_Grid_System:
589 				if( pParameter->Get_Children_Count() == 0 )
590 				{
591 					CSG_Grid_File_Info Info; double x, y; long nx, ny;
592 
593 					if( m_CMD.Found(_Get_ID(pParameter, "FILE"), &s) && Info.Create(&s) )
594 					{
595 						pParameter->asGrid_System()->Create(Info.m_System);
596 					}
597 					else if( m_CMD.Found(_Get_ID(pParameter, "NX"), &nx)
598 						&&   m_CMD.Found(_Get_ID(pParameter, "NY"), &ny)
599 						&&   m_CMD.Found(_Get_ID(pParameter,  "X"), &x )
600 						&&   m_CMD.Found(_Get_ID(pParameter,  "Y"), &y )
601 						&&   m_CMD.Found(_Get_ID(pParameter,  "D"), &d ) )
602 					{
603 						pParameter->asGrid_System()->Create(d, x, y, (int)nx, (int)ny);
604 					}
605 					else
606 					{
607 						pParameter->asGrid_System()->Create(0., 0., 0., 0, 0);
608 					}
609 				}
610 				break;
611 			}
612 		}
613 	}
614 
615 	//-----------------------------------------------------
616 	m_pTool->Update_Parameter_States();
617 
618 	return( true );
619 }
620 
621 //---------------------------------------------------------
_Get_Input(CSG_Parameters * pParameters)622 bool CCMD_Tool::_Get_Input(CSG_Parameters *pParameters)
623 {
624 	for(int i=0; i<pParameters->Get_Count(); i++)
625 	{
626 		CSG_Parameter	*pParameter	= pParameters->Get_Parameter(i);
627 
628 		if( pParameter->is_Input() )
629 		{
630 			if( !_Load_Input(pParameter) )
631 			{
632 				CMD_Print_Error(pParameter->Get_Name());
633 
634 				return( false );
635 			}
636 		}
637 
638 		else if( pParameter->is_Option() && !pParameter->is_Information() )
639 		{
640 			long		l;
641 			wxString	s;
642 
643 			switch( pParameter->Get_Type() )
644 			{
645 			default:
646 				break;
647 
648 			case PARAMETER_TYPE_Table_Field:
649 				if( m_CMD.Found(_Get_ID(pParameter), &s) )
650 				{
651 					if( s.ToLong(&l) )
652 					{
653 						pParameter->Set_Value((int)l);
654 					}
655 					else
656 					{
657 						pParameter->Set_Value(CSG_String(&s));
658 					}
659 				}
660 				break;
661 
662 			case PARAMETER_TYPE_Table_Fields:
663 				if( m_CMD.Found(_Get_ID(pParameter), &s) )
664 				{
665 					pParameter->Set_Value(CSG_String(&s));
666 				}
667 				break;
668 			}
669 		}
670 	}
671 
672 	//-----------------------------------------------------
673 	return( true );
674 }
675 
676 
677 ///////////////////////////////////////////////////////////
678 //                                                       //
679 ///////////////////////////////////////////////////////////
680 
681 //---------------------------------------------------------
_Load_Input(CSG_Parameter * pParameter)682 bool CCMD_Tool::_Load_Input(CSG_Parameter *pParameter)
683 {
684 	wxString	FileName;
685 
686 	if(	!pParameter->is_Input() || !pParameter->is_Enabled() )
687 	{
688 		return( true );
689 	}
690 
691 	if( !m_CMD.Found(_Get_ID(pParameter), &FileName) )
692 	{
693 		if( !pParameter->is_Optional() )
694 		{
695 			wxString	Msg(wxString::Format(_TL("The value for the option '%s' must be specified."), _Get_ID(pParameter)));
696 
697 			CMD_Print_Error(&Msg);
698 
699 			return( false );
700 		}
701 
702 		return( true );
703 	}
704 
705 	if( pParameter->is_DataObject() )
706 	{
707 		if( !SG_Get_Data_Manager().Find(&FileName) && !SG_Get_Data_Manager().Add(&FileName) && !pParameter->is_Optional() )
708 		{
709 			CMD_Print_Error(_TL("input file"), &FileName);
710 
711 			return( false );
712 		}
713 
714 		return( pParameter->Set_Value(SG_Get_Data_Manager().Find(&FileName, false)) );
715 	}
716 
717 	else if( pParameter->is_DataObject_List() )
718 	{
719 		pParameter->asList()->Del_Items();
720 
721 		wxString	FileNames(FileName);
722 
723 		do
724 		{
725 			FileName	= FileNames.BeforeFirst(';').Trim(false);
726 			FileNames	= FileNames.AfterFirst (';');
727 
728 			if( !SG_Get_Data_Manager().Find(&FileName) )
729 			{
730 				SG_Get_Data_Manager().Add(&FileName);
731 			}
732 
733 			pParameter->asList()->Add_Item(SG_Get_Data_Manager().Find(&FileName, false));
734 		}
735 		while( FileNames.Length() > 0 );
736 
737 		pParameter->has_Changed();
738 
739 		if( pParameter->Get_Parent() && pParameter->Get_Parent()->Get_Type() == PARAMETER_TYPE_Grid_System )
740 		{
741 			pParameter->Get_Parent()->has_Changed();
742 		}
743 	}
744 
745 	return( true );
746 }
747 
748 
749 ///////////////////////////////////////////////////////////
750 //                                                       //
751 ///////////////////////////////////////////////////////////
752 
753 //---------------------------------------------------------
_Save_Output(CSG_Parameters * pParameters)754 bool CCMD_Tool::_Save_Output(CSG_Parameters *pParameters)
755 {
756 	for(int j=0; j<pParameters->Get_Count(); j++)
757 	{
758 		wxString	FileName;
759 
760 		CSG_Parameter	*pParameter	= pParameters->Get_Parameter(j);
761 
762 		//-------------------------------------------------
763 		if( pParameter->is_Input() )
764 		{
765 			if( pParameter->is_DataObject() )
766 			{
767 				CSG_Data_Object	*pObject	= pParameter->asDataObject();
768 
769 				if( pObject && pObject->is_Modified() && SG_File_Exists(pObject->Get_File_Name()) )
770 				{
771 					_Save_Output(pObject, pObject->Get_File_Name());
772 				}
773 			}
774 
775 			else if( pParameter->is_DataObject_List() )
776 			{
777 				for(int i=0; i<pParameter->asList()->Get_Item_Count(); i++)
778 				{
779 					CSG_Data_Object	*pObject	= pParameter->asList()->Get_Item(i);
780 
781 					if( pObject->is_Modified() && SG_File_Exists(pObject->Get_File_Name()) )
782 					{
783 						_Save_Output(pObject, pObject->Get_File_Name());
784 					}
785 				}
786 			}
787 		}
788 
789 		//-------------------------------------------------
790 		else if( pParameter->is_Output() &&  m_CMD.Found(_Get_ID(pParameter), &FileName) && FileName.Length() > 0 )
791 		{
792 			if( pParameter->is_DataObject() )
793 			{
794 				if( pParameter->asDataObject() )
795 				{
796 					_Save_Output(pParameter->asDataObject(), &FileName);
797 				}
798 			}
799 
800 			else if( pParameter->is_DataObject_List() )
801 			{
802 				CSG_Strings	FileNames	= SG_String_Tokenize(&FileName, ";", SG_TOKEN_STRTOK);	// do not return empty tokens
803 
804 				if( FileNames.Get_Count() > 0 )
805 				{
806 					int	nFileNames	= pParameter->asList()->Get_Item_Count() <= FileNames.Get_Count() ? FileNames.Get_Count() : FileNames.Get_Count() - 1;
807 
808 					for(int i=0; i<pParameter->asList()->Get_Item_Count(); i++)
809 					{
810 						if( i < nFileNames )
811 						{
812 							_Save_Output(pParameter->asList()->Get_Item(i), FileNames[i]);
813 						}
814 						else
815 						{
816 							CSG_String	fPath	= SG_File_Get_Path     (FileNames[nFileNames]);
817 							CSG_String	fName	= SG_File_Get_Name     (FileNames[nFileNames], false);
818 							CSG_String	fExt	= SG_File_Get_Extension(FileNames[nFileNames]);
819 
820 							if( fName.is_Empty() || !fName.Cmp("*") )
821 							{
822 								fName	= pParameter->asList()->Get_Item(i)->Get_Name();
823 							}
824 							else
825 							{
826 								fName	+= CSG_String::Format("%0*d", SG_Get_Digit_Count(pParameter->asList()->Get_Item_Count()), 1 + i - nFileNames);
827 							}
828 
829 							_Save_Output(pParameter->asList()->Get_Item(i), SG_File_Make_Path(fPath, fName, fExt));
830 						}
831 					}
832 				}
833 			}
834 		}
835 	}
836 
837 	return( true );
838 }
839 
840 //---------------------------------------------------------
_Save_Output(CSG_Data_Object * pObject,const CSG_String & FileName)841 bool CCMD_Tool::_Save_Output(CSG_Data_Object *pObject, const CSG_String &FileName)
842 {
843 	pObject->Set_Name(SG_File_Get_Name(FileName, false));
844 
845 	return( pObject->Save(FileName) );
846 }
847 
848 
849 ///////////////////////////////////////////////////////////
850 //                                                       //
851 //                                                       //
852 //                                                       //
853 ///////////////////////////////////////////////////////////
854 
855 //---------------------------------------------------------
856