1 
2 ///////////////////////////////////////////////////////////
3 //                                                       //
4 //                         SAGA                          //
5 //                                                       //
6 //      System for Automated Geoscientific Analyses      //
7 //                                                       //
8 //           Application Programming Interface           //
9 //                                                       //
10 //                  Library: SAGA_API                    //
11 //                                                       //
12 //-------------------------------------------------------//
13 //                                                       //
14 //                    api_file.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'.                              //
22 //                                                       //
23 // This library is free software; you can redistribute   //
24 // it and/or modify it under the terms of the GNU Lesser //
25 // General Public License as published by the Free       //
26 // Software Foundation, either version 2.1 of the        //
27 // License, or (at your option) any later version.       //
28 //                                                       //
29 // This library is distributed in the hope that it will  //
30 // be useful, but WITHOUT ANY WARRANTY; without even the //
31 // implied warranty of MERCHANTABILITY or FITNESS FOR A  //
32 // PARTICULAR PURPOSE. See the GNU Lesser General Public //
33 // License for more details.                             //
34 //                                                       //
35 // You should have received a copy of the GNU Lesser     //
36 // General Public License along with this program; if    //
37 // not, see <http://www.gnu.org/licenses/>.              //
38 //                                                       //
39 //-------------------------------------------------------//
40 //                                                       //
41 //    contact:    Olaf Conrad                            //
42 //                Institute of Geography                 //
43 //                University of Goettingen               //
44 //                Goldschmidtstr. 5                      //
45 //                37077 Goettingen                       //
46 //                Germany                                //
47 //                                                       //
48 //    e-mail:     oconrad@saga-gis.org                   //
49 //                                                       //
50 ///////////////////////////////////////////////////////////
51 
52 //---------------------------------------------------------
53 #include <wx/utils.h>
54 #include <wx/filename.h>
55 #include <wx/dir.h>
56 #include <wx/wxcrtvararg.h>
57 #include <wx/wfstream.h>
58 #include <wx/zipstrm.h>
59 #include <wx/txtstrm.h>
60 #include <wx/log.h>
61 #include <wx/version.h>
62 
63 #include "api_core.h"
64 
65 
66 ///////////////////////////////////////////////////////////
67 //														 //
68 //														 //
69 //														 //
70 ///////////////////////////////////////////////////////////
71 
72 //---------------------------------------------------------
73 #define m_pStream_Base	((wxStreamBase   *)m_pStream)
74 #define m_pStream_In	((wxInputStream  *)m_pStream)
75 #define m_pStream_Out	((wxOutputStream *)m_pStream)
76 
77 
78 ///////////////////////////////////////////////////////////
79 //														 //
80 //														 //
81 //														 //
82 ///////////////////////////////////////////////////////////
83 
84 //---------------------------------------------------------
CSG_File(void)85 CSG_File::CSG_File(void)
86 {
87 	On_Construction();
88 }
89 
90 //---------------------------------------------------------
CSG_File(const CSG_String & FileName,int Mode,bool bBinary,int Encoding)91 CSG_File::CSG_File(const CSG_String &FileName, int Mode, bool bBinary, int Encoding)
92 {
93 	On_Construction();
94 
95 	Open(FileName, Mode, bBinary, Encoding);
96 }
97 
98 //---------------------------------------------------------
~CSG_File(void)99 CSG_File::~CSG_File(void)
100 {
101 	Close();
102 }
103 
104 
105 ///////////////////////////////////////////////////////////
106 //														 //
107 ///////////////////////////////////////////////////////////
108 
109 //---------------------------------------------------------
Open(const CSG_String & FileName,int Mode,bool bBinary,int Encoding)110 bool CSG_File::Open(const CSG_String &FileName, int Mode, bool bBinary, int Encoding)
111 {
112 	Close();
113 
114 	if( Mode == SG_FILE_R && !SG_File_Exists(FileName) )
115 	{
116 		return( false );
117 	}
118 
119 	m_FileName	= FileName;
120 	m_Mode		= Mode;
121 
122 	Set_Encoding(Encoding);
123 
124 	switch( m_Mode )
125 	{
126 	case SG_FILE_W:
127 		m_pStream	= new wxFFileOutputStream(FileName.c_str(), bBinary ? "wb" : "w");
128 		break;
129 
130 	case SG_FILE_R:
131 		m_pStream	= new wxFFileInputStream (FileName.c_str(), bBinary ? "rb" : "r");
132 		break;
133 
134 	default: // SG_FILE_RW
135 		m_pStream	= new wxFFileStream      (FileName.c_str(), SG_File_Exists(FileName)
136 			? (bBinary ? "r+b" : "r+")
137 			: (bBinary ? "w+b" : "w+")
138 		);
139 		break;
140 	}
141 
142 	if( !m_pStream || !m_pStream_Base->IsOk() )
143 	{
144 		Close();
145 
146 		return( false );
147 	}
148 
149 	return( true );
150 }
151 
152 //---------------------------------------------------------
Close(void)153 bool CSG_File::Close(void)
154 {
155 	if( m_pStream )
156 	{
157 		delete(m_pStream_Base);
158 
159 		m_pStream	= NULL;
160 	}
161 
162 	Set_Encoding(SG_FILE_ENCODING_UNDEFINED);
163 
164 	return( true );
165 }
166 
167 
168 ///////////////////////////////////////////////////////////
169 //														 //
170 ///////////////////////////////////////////////////////////
171 
172 //---------------------------------------------------------
On_Construction(void)173 void CSG_File::On_Construction(void)
174 {
175 	m_pStream	= NULL;
176 	m_pConvert	= NULL;
177 	m_Encoding	= SG_FILE_ENCODING_UNDEFINED;
178 }
179 
180 //---------------------------------------------------------
Set_Encoding(int Encoding)181 bool CSG_File::Set_Encoding(int Encoding)
182 {
183 	if( m_pConvert )
184 	{
185 		if( m_pConvert != &wxConvLocal
186 		&&  m_pConvert != &wxConvLibc
187 		&&  m_pConvert != &wxConvUTF7
188 		&&  m_pConvert != &wxConvUTF8 )
189 		{
190 			delete((wxMBConv *)m_pConvert);
191 		}
192 
193 		m_pConvert	= NULL;
194 	}
195 
196 	m_Encoding	= Encoding;
197 
198 	switch( Encoding )
199 	{
200 	case SG_FILE_ENCODING_ANSI   : break;
201 	case SG_FILE_ENCODING_UTF7   : m_pConvert = &wxConvUTF7          ; break;
202 	case SG_FILE_ENCODING_UTF8   : m_pConvert = &wxConvUTF8          ; break;
203 	case SG_FILE_ENCODING_UTF16LE: m_pConvert = new wxMBConvUTF16LE(); break;
204 	case SG_FILE_ENCODING_UTF16BE: m_pConvert = new wxMBConvUTF16BE(); break;
205 	case SG_FILE_ENCODING_UTF32LE: m_pConvert = new wxMBConvUTF32LE(); break;
206 	case SG_FILE_ENCODING_UTF32BE: m_pConvert = new wxMBConvUTF32BE(); break;
207 	default                      : break;
208 	}
209 
210 	return( true );
211 }
212 
213 
214 ///////////////////////////////////////////////////////////
215 //														 //
216 ///////////////////////////////////////////////////////////
217 
218 //---------------------------------------------------------
Length(void) const219 sLong CSG_File::Length(void) const
220 {
221 	return( m_pStream ? m_pStream_Base->GetLength() : -1 );
222 }
223 
224 //---------------------------------------------------------
is_EOF(void) const225 bool CSG_File::is_EOF(void)	const
226 {
227 	return( is_Reading() && m_pStream_In->Eof() );
228 }
229 
230 //---------------------------------------------------------
Seek(sLong Offset,int Origin) const231 bool CSG_File::Seek(sLong Offset, int Origin) const
232 {
233 	if( m_pStream )
234 	{
235 		wxSeekMode	Seek = Origin == SG_FILE_CURRENT ? wxFromCurrent : Origin == SG_FILE_END ? wxFromEnd : wxFromStart;
236 
237 		switch( m_Mode )
238 		{
239 		case SG_FILE_R : return( m_pStream_In ->SeekI(Offset, Seek) != wxInvalidOffset );
240 		case SG_FILE_W : return( m_pStream_Out->SeekO(Offset, Seek) != wxInvalidOffset );
241 		case SG_FILE_RW: return( m_pStream_In ->SeekI(Offset, Seek) != wxInvalidOffset
242 							&&   m_pStream_Out->SeekO(Offset, Seek) != wxInvalidOffset );
243 		}
244 	}
245 
246 	return( false );
247 }
248 
249 //---------------------------------------------------------
Seek_Start(void) const250 bool CSG_File::Seek_Start(void) const	{	return( Seek(0, SEEK_SET) );	}
Seek_End(void) const251 bool CSG_File::Seek_End  (void) const	{	return( Seek(0, SEEK_END) );	}
252 
253 //---------------------------------------------------------
Tell(void) const254 sLong CSG_File::Tell(void) const
255 {
256 	if( m_pStream )
257 	{
258 		switch( m_Mode )
259 		{
260 		case SG_FILE_R : return( m_pStream_In ->TellI() );
261 		case SG_FILE_W : return( m_pStream_Out->TellO() );
262 		case SG_FILE_RW: return( m_pStream_In ->TellI() );
263 		}
264 	}
265 
266 	return( -1 );
267 }
268 
269 //---------------------------------------------------------
Printf(const char * Format,...)270 int CSG_File::Printf(const char *Format, ...)
271 {
272 	if( !is_Writing() )
273 	{
274 		return( 0 );
275 	}
276 
277 	wxString	String;
278 
279 #ifdef _SAGA_LINUX
280 	wxString _Format(Format); _Format.Replace("%s", "%ls");	// workaround as we only use wide characters since wx 2.9.4 so interpret strings as multibyte
281 	va_list	argptr; va_start(argptr, _Format);
282 	int	Result	= String.PrintfV(_Format, argptr);
283 #else
284 	va_list	argptr; va_start(argptr, Format);
285 	int	Result	= String.PrintfV(Format, argptr);
286 #endif
287 	va_end(argptr);
288 
289 	Write(&String);
290 
291 	return( Result );
292 }
293 
294 //---------------------------------------------------------
Printf(const wchar_t * Format,...)295 int CSG_File::Printf(const wchar_t *Format, ...)
296 {
297 	if( !is_Writing() )
298 	{
299 		return( 0 );
300 	}
301 
302 	wxString	String;
303 
304 #ifdef _SAGA_LINUX
305 	wxString _Format(Format); _Format.Replace("%s", "%ls");	// workaround as we only use wide characters since wx 2.9.4 so interpret strings as multibyte
306 	va_list	argptr; va_start(argptr, _Format);
307 	int	Result	= String.PrintfV(_Format, argptr);
308 #else
309 	va_list	argptr; va_start(argptr, Format);
310 	int	Result	= String.PrintfV(Format, argptr);
311 #endif
312 
313 	va_end(argptr);
314 
315 	Write(&String);
316 
317 	return( Result );
318 }
319 
320 //---------------------------------------------------------
Read(void * Buffer,size_t Size,size_t Count) const321 size_t CSG_File::Read(void *Buffer, size_t Size, size_t Count) const
322 {
323 	return( !is_Reading() || Size == 0 || Count == 0 ? 0 :
324 		m_pStream_In->Read(Buffer, Size * Count).LastRead() / Size
325 	);
326 }
327 
Read(CSG_String & Buffer,size_t Size) const328 size_t CSG_File::Read(CSG_String &Buffer, size_t Size) const
329 {
330 	if( is_Reading() && Size > 0 )
331 	{
332 		CSG_Buffer	s(Size + 1);
333 
334 		size_t	 i	= Read(s.Get_Data(), sizeof(char), Size);
335 
336 		if( i > 0 )
337 		{
338 			s[Size] = '\0';
339 
340 			Buffer	= s.Get_Data();
341 
342 			return( i );
343 		}
344 	}
345 
346 	Buffer.Clear();
347 
348 	return( 0 );
349 }
350 
351 //---------------------------------------------------------
Write(void * Buffer,size_t Size,size_t Count) const352 size_t CSG_File::Write(void *Buffer, size_t Size, size_t Count) const
353 {
354 	return( !is_Writing() || Size == 0 || Count == 0 ? 0 :
355 		m_pStream_Out->Write(Buffer, Size * Count).LastWrite()
356 	);
357 }
358 
Write(const CSG_String & Buffer) const359 size_t CSG_File::Write(const CSG_String &Buffer) const
360 {
361 	if( m_pConvert )
362 	{
363 		wxString	_Buffer(Buffer.w_str());
364 
365 		const wxScopedCharBuffer s(_Buffer.mb_str(*((wxMBConv *)m_pConvert)));
366 
367 		return( Write((void *)s.data(), sizeof(char), s.length()) );
368 	}
369 
370 	CSG_Buffer	s(Buffer.to_ASCII());
371 
372 	return( Write((void *)s.Get_Data(), sizeof(char), s.Get_Size()) );
373 }
374 
375 //---------------------------------------------------------
Read_Line(CSG_String & sLine) const376 bool CSG_File::Read_Line(CSG_String &sLine)	const
377 {
378 	if( !is_Reading() || is_EOF() )
379 	{
380 		return( false );
381 	}
382 
383 	if( m_pConvert )
384 	{
385 		wxTextInputStream	Stream(*m_pStream_In, " \t", *((wxMBConv *)m_pConvert));
386 
387 		wxString	s(Stream.ReadLine());	sLine	= CSG_String(&s);
388 	}
389 	else
390 	{
391 		wxTextInputStream	Stream(*m_pStream_In, " \t");
392 
393 		wxString	s(Stream.ReadLine());	sLine	= CSG_String(&s);
394 	}
395 
396 	return( !sLine.is_Empty() || !is_EOF() );
397 }
398 
399 //---------------------------------------------------------
Read_Char(void) const400 int CSG_File::Read_Char(void) const
401 {
402 	return( !is_Reading() ? 0 : m_pStream_In->GetC() );
403 }
404 
405 //---------------------------------------------------------
Read_Int(bool bByteOrderBig) const406 int CSG_File::Read_Int(bool bByteOrderBig) const
407 {
408 	int		Value	= 0;
409 
410 	if( Read(&Value, sizeof(Value)) == 1 )
411 	{
412 		if( bByteOrderBig )
413 		{
414 			SG_Swap_Bytes(&Value, sizeof(Value));
415 		}
416 	}
417 
418 	return( Value );
419 }
420 
Write_Int(int Value,bool bByteOrderBig)421 bool CSG_File::Write_Int(int Value, bool bByteOrderBig)
422 {
423 	if( bByteOrderBig )
424 	{
425 		SG_Swap_Bytes(&Value, sizeof(Value));
426 	}
427 
428 	return( Write(&Value, sizeof(Value)) == sizeof(Value) );
429 }
430 
431 //---------------------------------------------------------
Read_Double(bool bByteOrderBig) const432 double CSG_File::Read_Double(bool bByteOrderBig) const
433 {
434 	double	Value	= 0;
435 
436 	if( Read(&Value, sizeof(Value)) == 1 )
437 	{
438 		if( bByteOrderBig )
439 		{
440 			SG_Swap_Bytes(&Value, sizeof(Value));
441 		}
442 	}
443 
444 	return( Value );
445 }
446 
Write_Double(double Value,bool bByteOrderBig)447 bool CSG_File::Write_Double(double Value, bool bByteOrderBig)
448 {
449 	if( bByteOrderBig )
450 	{
451 		SG_Swap_Bytes(&Value, sizeof(Value));
452 	}
453 
454 	return( Write(&Value, sizeof(Value)) == sizeof(Value) );
455 }
456 
457 //---------------------------------------------------------
Scan(int & Value) const458 bool CSG_File::Scan(int &Value) const
459 {
460 	if( is_Reading() )
461 	{
462 		int		c;
463 
464 		while( !is_EOF() && isspace(c = Read_Char()) );	// remove leading white space
465 
466 		if( isdigit(c) || strchr("-+", c) )
467 		{
468 			CSG_String	s	= (char)c;
469 
470 			while( !is_EOF() && isdigit(c = Read_Char()) )
471 			{
472 				s	+= (char)c;
473 			}
474 
475 			return( s.asInt(Value) );
476 		}
477 	}
478 
479 	return( false );
480 }
481 
Scan(double & Value) const482 bool CSG_File::Scan(double &Value) const
483 {
484 	if( is_Reading() )
485 	{
486 		int		c;
487 
488 		while( !is_EOF() && isspace(c = Read_Char()) );	// remove leading white space
489 
490 		if( isdigit(c) || strchr("-+.,eE", c) )
491 		{
492 			CSG_String	s	= (char)c;
493 
494 			while( !is_EOF() && (isdigit(c = Read_Char()) || strchr(".,eE", c) || strchr("", c)) )
495 			{
496 				s	+= (char)c;
497 			}
498 
499 			return( s.asDouble(Value) );
500 		}
501 	}
502 
503 	return( false );
504 }
505 
Scan(CSG_String & Value,SG_Char Separator) const506 bool CSG_File::Scan(CSG_String &Value, SG_Char Separator) const
507 {
508 	if( is_Reading() && !is_EOF() )
509 	{
510 		Value.Clear();
511 
512 		int		c;
513 
514 		while( !is_EOF() && (c = Read_Char()) != Separator && c != EOF )
515 		{
516 			Value	+= (char)c;
517 		}
518 
519 		return( true );
520 	}
521 
522 	return( false );
523 }
524 
525 //---------------------------------------------------------
Scan_Int(void) const526 int CSG_File::Scan_Int(void) const
527 {
528 	int		Value;
529 
530 	return( Scan(Value) ? Value : 0 );
531 }
532 
Scan_Double(void) const533 double CSG_File::Scan_Double(void) const
534 {
535 	double	Value;
536 
537 	return( Scan(Value) ? Value : 0.0 );
538 }
539 
Scan_String(SG_Char Separator) const540 CSG_String CSG_File::Scan_String(SG_Char Separator) const
541 {
542 	CSG_String	Value;
543 
544 	Scan(Value, Separator);
545 
546 	return( Value );
547 }
548 
549 
550 ///////////////////////////////////////////////////////////
551 //														 //
552 //														 //
553 //														 //
554 ///////////////////////////////////////////////////////////
555 
556 //---------------------------------------------------------
CSG_File_Zip(void)557 CSG_File_Zip::CSG_File_Zip(void)
558 {
559 	On_Construction();
560 }
561 
562 //---------------------------------------------------------
CSG_File_Zip(const CSG_String & FileName,int Mode,int Encoding)563 CSG_File_Zip::CSG_File_Zip(const CSG_String &FileName, int Mode, int Encoding)
564 {
565 	On_Construction();
566 
567 	Open(FileName, Mode, Encoding);
568 }
569 
570 //---------------------------------------------------------
~CSG_File_Zip(void)571 CSG_File_Zip::~CSG_File_Zip(void)
572 {
573 	Close();
574 }
575 
576 //---------------------------------------------------------
Open(const CSG_String & FileName,int Mode,int Encoding)577 bool CSG_File_Zip::Open(const CSG_String &FileName, int Mode, int Encoding)
578 {
579 	wxLogNull	logNo;	// suppress user notification dialog for invalid zip files
580 
581 	Close();
582 
583 	m_Mode	= Mode;
584 
585 	Set_Encoding(Encoding);
586 
587 	if( Mode == SG_FILE_W )
588 	{
589 		m_pStream	= new wxZipOutputStream(new wxFileOutputStream(FileName.c_str()));
590 	}
591 	else if( Mode == SG_FILE_R && SG_File_Exists(FileName) )
592 	{
593 		m_pStream	= new wxZipInputStream (new wxFileInputStream (FileName.c_str()));
594 	}
595 
596 	if( !m_pStream || !m_pStream_Base->IsOk() )
597 	{
598 		Close();
599 
600 		return( false );
601 	}
602 
603 	if( is_Reading() )
604 	{
605 		wxZipEntry	*pEntry;
606 
607 		while( (pEntry = ((wxZipInputStream *)m_pStream)->GetNextEntry()) != NULL )
608 		{
609 			m_Files	+= pEntry;
610 		}
611 	}
612 
613 	return( true );
614 }
615 
616 //---------------------------------------------------------
Close(void)617 bool CSG_File_Zip::Close(void)
618 {
619 	for(size_t i=0; i<m_Files.Get_Size(); i++)
620 	{
621 		delete((wxZipEntry *)m_Files[i]);
622 	}
623 
624 	m_Files.Set_Array(0);
625 
626 	return( CSG_File::Close() );
627 }
628 
629 //---------------------------------------------------------
Add_Directory(const CSG_String & Name)630 bool CSG_File_Zip::Add_Directory(const CSG_String &Name)
631 {
632 	return( is_Writing() && ((wxZipOutputStream *)m_pStream)->PutNextDirEntry(Name.c_str()) );
633 }
634 
635 //---------------------------------------------------------
Add_File(const CSG_String & Name,bool bBinary)636 bool CSG_File_Zip::Add_File(const CSG_String &Name, bool bBinary)
637 {
638 	if( is_Writing() )
639 	{
640 		wxZipEntry	*pEntry	= new wxZipEntry(Name.c_str());
641 
642 		pEntry->SetIsText(bBinary == false);
643 
644 		#if wxCHECK_VERSION(3, 1, 1)
645 		((wxZipOutputStream *)m_pStream)->SetFormat(wxZIP_FORMAT_ZIP64);
646 		#endif
647 
648 		if( ((wxZipOutputStream *)m_pStream)->PutNextEntry(pEntry) )
649 		{
650 			m_FileName	= Name;
651 
652 			return( true );
653 		}
654 	}
655 
656 	return( false );
657 }
658 
659 //---------------------------------------------------------
is_Directory(size_t Index)660 bool CSG_File_Zip::is_Directory(size_t Index)
661 {
662 	if( is_Reading() && m_Files[Index] )
663 	{
664 		return( ((wxZipEntry *)m_Files[Index])->IsDir() );
665 	}
666 
667 	return( false );
668 }
669 
670 //---------------------------------------------------------
Get_File(size_t Index)671 bool CSG_File_Zip::Get_File(size_t Index)
672 {
673 	if( is_Reading() && m_Files[Index] )
674 	{
675 		if( ((wxZipInputStream *)m_pStream)->OpenEntry(*(wxZipEntry *)m_Files[Index]) )
676 		{
677 			m_FileName	= Get_File_Name(Index);
678 
679 			return( true );
680 		}
681 	}
682 
683 	return( false );
684 }
685 
686 //---------------------------------------------------------
Get_File(const CSG_String & Name)687 bool CSG_File_Zip::Get_File(const CSG_String &Name)
688 {
689 	if( is_Reading() )
690 	{
691 		for(size_t i=0; i<m_Files.Get_Size(); i++)
692 		{
693 			if( !((wxZipEntry *)m_Files[i])->GetName().Cmp(Name.c_str()) )
694 			{
695 				return( Get_File(i) );
696 			}
697 		}
698 	}
699 
700 	return( false );
701 }
702 
703 //---------------------------------------------------------
Get_File_Name(size_t Index)704 CSG_String CSG_File_Zip::Get_File_Name(size_t Index)
705 {
706 	CSG_String	s;
707 
708 	if( is_Reading() && m_Files[Index] )
709 	{
710 		wxString Name(((wxZipEntry *)m_Files[Index])->GetName()); s	= &Name;
711 	}
712 
713 	return( s );
714 }
715 
716 
717 ///////////////////////////////////////////////////////////
718 //														 //
719 //														 //
720 //														 //
721 ///////////////////////////////////////////////////////////
722 
723 //---------------------------------------------------------
SG_Dir_Exists(const CSG_String & Directory)724 bool			SG_Dir_Exists(const CSG_String &Directory)
725 {
726 	return( wxFileName::DirExists(Directory.c_str()) );
727 }
728 
729 //---------------------------------------------------------
SG_Dir_Create(const CSG_String & Directory)730 bool			SG_Dir_Create(const CSG_String &Directory)
731 {
732 	if( SG_Dir_Exists(Directory) )
733 	{
734 		return( true );
735 	}
736 
737 	return( wxFileName::Mkdir(Directory.c_str()) );
738 }
739 
740 //---------------------------------------------------------
SG_Dir_Delete(const CSG_String & Directory,bool bRecursive)741 bool			SG_Dir_Delete(const CSG_String &Directory, bool bRecursive)
742 {
743 	if( !SG_Dir_Exists(Directory) )
744 	{
745 		return( true );
746 	}
747 
748 	return( wxDir::Remove(Directory.c_str(), bRecursive ? wxPATH_RMDIR_RECURSIVE : 0) );
749 }
750 
751 //---------------------------------------------------------
SG_Dir_Get_Current(void)752 CSG_String		SG_Dir_Get_Current(void)
753 {
754 	wxString cwd = wxFileName::GetCwd();
755 
756 	return( CSG_String(&cwd) );
757 }
758 
759 //---------------------------------------------------------
SG_Dir_Get_Temp(void)760 CSG_String		SG_Dir_Get_Temp(void)
761 {
762 	wxString fname = wxFileName::GetTempDir();
763 
764 	return( CSG_String(&fname) );
765 }
766 
767 //---------------------------------------------------------
SG_Dir_List_Subdirectories(CSG_Strings & List,const CSG_String & Directory)768 bool			SG_Dir_List_Subdirectories	(CSG_Strings &List, const CSG_String &Directory)
769 {
770 	List.Clear();
771 
772 	wxDir	Dir;
773 
774 	if( Dir.Open(Directory.c_str()) )
775 	{
776 		wxString	FileName;
777 
778 		if( Dir.GetFirst(&FileName, wxEmptyString, wxDIR_DIRS) )
779 		{
780 			do
781 			{
782 				List	+= SG_File_Make_Path(Directory, &FileName);
783 			}
784 			while( Dir.GetNext(&FileName) );
785 		}
786 	}
787 
788 	return( List.Get_Count() > 0 );
789 }
790 
791 //---------------------------------------------------------
SG_Dir_List_Files(CSG_Strings & List,const CSG_String & Directory)792 bool			SG_Dir_List_Files			(CSG_Strings &List, const CSG_String &Directory)
793 {
794 	return( SG_Dir_List_Files(List, Directory, "") );
795 }
796 
SG_Dir_List_Files(CSG_Strings & List,const CSG_String & Directory,const CSG_String & Extension)797 bool			SG_Dir_List_Files			(CSG_Strings &List, const CSG_String &Directory, const CSG_String &Extension)
798 {
799 	List.Clear();
800 
801 	wxDir	Dir;
802 
803 	if( Dir.Open(Directory.c_str()) )
804 	{
805 		wxString	FileName;
806 
807 		if( Dir.GetFirst(&FileName, wxEmptyString, wxDIR_FILES) )
808 		{
809 			do
810 			{
811 				if( Extension.is_Empty() || SG_File_Cmp_Extension(&FileName, Extension) )
812 				{
813 					List	+= SG_File_Make_Path(Directory, &FileName);
814 				}
815 			}
816 			while( Dir.GetNext(&FileName) );
817 		}
818 	}
819 
820 	return( List.Get_Count() > 0 );
821 }
822 
823 
824 ///////////////////////////////////////////////////////////
825 //														 //
826 //														 //
827 //														 //
828 ///////////////////////////////////////////////////////////
829 
830 //---------------------------------------------------------
SG_File_Exists(const CSG_String & FileName)831 bool			SG_File_Exists(const CSG_String &FileName)
832 {
833 	return( wxFileExists(FileName.c_str()) );
834 }
835 
836 //---------------------------------------------------------
SG_File_Delete(const CSG_String & FileName)837 bool			SG_File_Delete(const CSG_String &FileName)
838 {
839 	return( SG_File_Exists(FileName) && wxRemoveFile(FileName.c_str()) );
840 }
841 
842 //---------------------------------------------------------
SG_File_Get_Name_Temp(const CSG_String & Prefix)843 CSG_String		SG_File_Get_Name_Temp(const CSG_String &Prefix)
844 {
845 	return( SG_File_Get_Name_Temp(Prefix, "") );
846 }
847 
SG_File_Get_Name_Temp(const CSG_String & Prefix,const CSG_String & Directory)848 CSG_String		SG_File_Get_Name_Temp(const CSG_String &Prefix, const CSG_String &Directory)
849 {
850 	if( !SG_Dir_Exists(Directory) )
851 	{
852 		return( CSG_String(wxFileName::CreateTempFileName(Prefix.c_str()).wc_str()) );
853 	}
854 
855 	return( CSG_String(wxFileName::CreateTempFileName(SG_File_Make_Path(Directory, Prefix).w_str()).wc_str()) );
856 }
857 
858 //---------------------------------------------------------
SG_File_Get_Name(const CSG_String & full_Path,bool bExtension)859 CSG_String		SG_File_Get_Name(const CSG_String &full_Path, bool bExtension)
860 {
861 	wxFileName	fn(full_Path.c_str());
862 
863 	if( bExtension )
864 	{
865 		wxString s(fn.GetFullName()); return( CSG_String(&s) );
866 	}
867 
868 	wxString s(fn.GetName()); return( &s );
869 }
870 
871 //---------------------------------------------------------
SG_File_Get_Path(const CSG_String & full_Path)872 CSG_String		SG_File_Get_Path(const CSG_String &full_Path)
873 {
874 	wxString	s(wxFileName(full_Path.c_str()).GetPath(wxPATH_GET_VOLUME|wxPATH_GET_SEPARATOR));
875 
876 	return( CSG_String(&s) );
877 }
878 
879 //---------------------------------------------------------
SG_File_Get_Path_Absolute(const CSG_String & full_Path)880 CSG_String		SG_File_Get_Path_Absolute(const CSG_String &full_Path)
881 {
882 	wxFileName	fn(full_Path.c_str());
883 
884 	fn.MakeAbsolute();
885 
886 	wxString s(fn.GetFullPath()); return( &s );
887 }
888 
889 //---------------------------------------------------------
SG_File_Get_Path_Relative(const CSG_String & Directory,const CSG_String & full_Path)890 CSG_String		SG_File_Get_Path_Relative(const CSG_String &Directory, const CSG_String &full_Path)
891 {
892 	wxFileName	fn(full_Path.c_str());
893 
894 	fn.MakeRelativeTo(Directory.c_str());
895 
896 	wxString s(fn.GetFullPath()); return( &s );
897 }
898 
899 //---------------------------------------------------------
SG_File_Make_Path(const CSG_String & Directory,const CSG_String & Name)900 CSG_String		SG_File_Make_Path(const CSG_String &Directory, const CSG_String &Name)
901 {
902 	return( SG_File_Make_Path(Directory, Name, "") );
903 }
904 
SG_File_Make_Path(const CSG_String & Directory,const CSG_String & Name,const CSG_String & Extension)905 CSG_String		SG_File_Make_Path(const CSG_String &Directory, const CSG_String &Name, const CSG_String &Extension)
906 {
907 	wxFileName	fn;
908 
909 	fn.AssignDir(!Directory.is_Empty() ? Directory.c_str() : SG_File_Get_Path(Name).c_str());
910 
911 	if( !Extension.is_Empty() )
912 	{
913 		fn.SetName		(SG_File_Get_Name(Name, false).c_str());
914 		fn.SetExt		(Extension.c_str());
915 	}
916 	else
917 	{
918 		fn.SetFullName	(SG_File_Get_Name(Name,  true).c_str());
919 	}
920 
921 	wxString s(fn.GetFullPath()); return( &s );
922 }
923 
924 //---------------------------------------------------------
SG_File_Cmp_Extension(const CSG_String & FileName,const CSG_String & Extension)925 bool			SG_File_Cmp_Extension(const CSG_String &FileName, const CSG_String &Extension)
926 {
927 	return( SG_File_Get_Extension(FileName).CmpNoCase(Extension) == 0 );
928 }
929 
930 //---------------------------------------------------------
SG_File_Set_Extension(CSG_String & FileName,const CSG_String & Extension)931 bool			SG_File_Set_Extension(CSG_String &FileName, const CSG_String &Extension)
932 {
933 	if( FileName.Length() > 0 )
934 	{
935 		wxFileName	fn(FileName.c_str());
936 
937 		fn.SetExt(Extension.c_str());
938 
939 		wxString s(fn.GetFullPath());
940 
941 		FileName	= &s;
942 
943 		return( true );
944 	}
945 
946 	return( false );
947 }
948 
949 //---------------------------------------------------------
SG_File_Get_Extension(const CSG_String & FileName)950 CSG_String		SG_File_Get_Extension(const CSG_String &FileName)
951 {
952 	wxFileName	fn(FileName.c_str());
953 
954 	wxString s(fn.GetExt()); return( &s );
955 }
956 
957 
958 ///////////////////////////////////////////////////////////
959 //														 //
960 //														 //
961 //														 //
962 ///////////////////////////////////////////////////////////
963 
964 //---------------------------------------------------------
SG_Get_Environment(const CSG_String & Variable,CSG_String * Value)965 bool			SG_Get_Environment(const CSG_String &Variable, CSG_String *Value)
966 {
967 	if( Value == NULL )
968 	{
969 		return( wxGetEnv(Variable.w_str(), NULL) );
970 	}
971 
972 	wxString	s;
973 
974 	if( wxGetEnv(Variable.w_str(), &s) )
975 	{
976 		*Value	= s.wc_str();
977 
978 		return( true );
979 	}
980 
981 	return( false );
982 }
983 
984 //---------------------------------------------------------
SG_Set_Environment(const CSG_String & Variable,const CSG_String & Value)985 bool			SG_Set_Environment(const CSG_String &Variable, const CSG_String &Value)
986 {
987 	return( wxSetEnv(Variable.w_str(), Value.w_str()) );
988 }
989 
990 
991 ///////////////////////////////////////////////////////////
992 //														 //
993 //														 //
994 //														 //
995 ///////////////////////////////////////////////////////////
996 
997 //---------------------------------------------------------
998