1 /*
2  * Part of WCM Commander
3  * https://github.com/corporateshark/WCMCommander
4  * wcm@linderdaum.com
5  */
6 
7 #include <algorithm>
8 
9 #include <wal.h>
10 #include "wcm-config.h"
11 #include "color-style.h"
12 #include "string-util.h"
13 #include "vfs.h"
14 #include "fontdlg.h"
15 #include "ncfonts.h"
16 #include "ncwin.h"
17 #include "ltext.h"
18 #include "globals.h"
19 #include "folder-history.h"
20 #include "view-history.h"
21 #include "nchistory.h"
22 
23 #ifdef _WIN32
24 #  include "w32util.h"
25 #endif
26 
27 #define __STDC_FORMAT_MACROS
28 #include <stdint.h>
29 
30 #if !defined(_MSC_VER) || _MSC_VER >= 1700
31 #  include <inttypes.h>
32 #endif
33 
34 #include <map>
35 
36 
Find(const char * section,const char * var)37 std::string* IniHash::Find( const char* section, const char* var )
38 {
39 	cstrhash< std::string >* h = hash.exist( section );
40 
41 	if ( !h )
42 	{
43 		return 0;
44 	}
45 
46 	return h->exist( var );
47 }
48 
Create(const char * section,const char * var)49 std::string* IniHash::Create( const char* section, const char* var )
50 {
51 	return &(hash[section][var]);
52 }
53 
Delete(const char * section,const char * var)54 void IniHash::Delete( const char* section, const char* var )
55 {
56 	hash[section].del( var, false );
57 }
58 
SetStrValue(const char * section,const char * var,const char * value)59 void IniHash::SetStrValue( const char* section, const char* var, const char* value )
60 {
61 	if ( !value )
62 	{
63 		Delete( section, var ); return;
64 	}
65 
66 	std::string* p = Create( section, var );
67 	if ( p )
68 	{
69 		*p = value;
70 	}
71 }
72 
SetIntValue(const char * section,const char * var,int value)73 void IniHash::SetIntValue( const char* section, const char* var, int value )
74 {
75 	SetStrValue( section, var, ToString(value).c_str() );
76 }
77 
SetBoolValue(const char * section,const char * var,bool value)78 void IniHash::SetBoolValue( const char* section, const char* var, bool value )
79 {
80 	SetIntValue( section, var, value ? 1 : 0 );
81 }
82 
GetStrValue(const char * section,const char * var,const char * def)83 const char* IniHash::GetStrValue( const char* section, const char* var, const char* def )
84 {
85 	std::string* p = Find( section, var );
86 	return (p && p->data()) ? p->data() : def;
87 }
88 
GetIntValue(const char * section,const char * var,int def)89 int IniHash::GetIntValue( const char* section, const char* var, int def )
90 {
91 	std::string* p = Find( section, var );
92 	return (p && p->data()) ? atoi( p->data() ) : def;
93 }
94 
GetBoolValue(const char * section,const char * var,bool def)95 bool IniHash::GetBoolValue( const char* section, const char* var, bool def )
96 {
97 	const int n = GetIntValue( section, var, def ? 1 : 0 );
98 	return n ? true : false;
99 }
100 
101 
102 #ifndef _WIN32
103 
104 #define DEFAULT_CONFIG_PATH UNIX_CONFIG_DIR_PATH "/config.default"
105 
106 class TextInStream
107 {
108 private:
109 	int bufSize;
110 	std::vector<char> buffer;
111 	int pos;
112 	int count;
FillBuffer()113 	bool FillBuffer()
114 	{
115 		if ( pos < count ) { return true; }
116 		if ( count <= 0 ) { return false; }
117 		count = Read( buffer.data(), bufSize );
118 		pos = 0;
119 		return count > 0;
120 	}
121 
122 public:
TextInStream(int _bSize=1024)123 	TextInStream( int _bSize = 1024 )
124 		: bufSize( _bSize > 0 ? _bSize : 1024 )
125 		, pos( 1 )
126 		, count( 1 )
127 	{
128 		buffer.resize( bufSize );
129 	}
~TextInStream()130 	~TextInStream() {}
131 
GetC()132 	int GetC()
133 	{
134 		FillBuffer();
135 		return pos < count ? buffer[pos++] : EOF;
136 	}
137 
138 	bool GetLine( char* s, int size );
139 
140 protected:
141 	virtual int Read( char* buf, int size ) = 0; //can throw
142 };
143 
144 
GetLine(char * s,int size)145 bool TextInStream::GetLine( char* s, int size )
146 {
147 	if ( size <= 0 ) { return true; }
148 
149 	if ( !FillBuffer() ) { return false; }
150 
151 	if ( size == 1 ) { *s = 0; return true; }
152 
153 	size--;
154 
155 	while ( true )
156 	{
157 		if ( pos >= count && !FillBuffer() ) { break; }
158 
159 		char* b = buffer.data() + pos;
160 		char* e = buffer.data() + count;
161 
162 		for ( ; b < e; b++ ) if ( *b == '\n' ) { break; }
163 
164 		if ( size > 0 )
165 		{
166 			int n = b - ( buffer.data() + pos );
167 
168 			if ( n > size ) { n = size; }
169 
170 			memcpy( s, buffer.data() + pos, n );
171 			size -= n;
172 			s += n;
173 		}
174 
175 		pos = b - buffer.data();
176 
177 		if ( b < e )
178 		{
179 			pos++;
180 			break;
181 		}
182 	}
183 
184 	*s = 0;
185 
186 	return true;
187 }
188 
189 class TextOutStream
190 {
191 private:
192 	int bufSize;
193 	std::vector<char> buffer;
194 	int pos;
195 public:
TextOutStream(int _bSize=1024)196 	TextOutStream( int _bSize = 1024 ): bufSize( _bSize > 0 ? _bSize : 1024 ), pos( 0 ) { buffer.resize( bufSize ); }
Flush()197 	void Flush() {  if ( pos > 0 ) { Write( buffer.data(), pos ); pos = 0; } }
PutC(int c)198 	void PutC( int c ) { if ( pos >= bufSize ) { Flush(); } buffer[pos++] = c; }
199 	void Put( const char* s, int size );
Put(const char * s)200 	void Put( const char* s ) { Put( s, strlen( s ) ); }
~TextOutStream()201 	~TextOutStream() {}
202 protected:
203 	virtual void Write( char* buf, int size ) = 0; //can throw
Clear()204 	void Clear() { pos = 0; }
205 };
206 
207 
Put(const char * s,int size)208 void TextOutStream::Put( const char* s, int size )
209 {
210 	while ( size > 0 )
211 	{
212 		if ( pos >= bufSize ) { Flush(); }
213 
214 		int n = bufSize - pos;
215 
216 		if ( n > size ) { n = size; }
217 
218 		memcpy( buffer.data() + pos, s, n );
219 		pos += n;
220 		size -= n;
221 		s += n;
222 	}
223 }
224 
225 class SysTextFileIn: public TextInStream
226 {
227 	File f;
228 public:
SysTextFileIn(int bSize=4096)229 	SysTextFileIn( int bSize = 4096 ): TextInStream( bSize ) {}
Open(const sys_char_t * fileName)230 	void Open( const sys_char_t* fileName ) { f.Open( fileName, FOPEN_READ ); }
Close()231 	void Close() { f.Close(); }
~SysTextFileIn()232 	~SysTextFileIn() {}
233 
234 protected:
235 	virtual int Read( char* buf, int size );
236 };
237 
Read(char * buf,int size)238 int SysTextFileIn::Read( char* buf, int size ) { return f.Read( buf, size ); }
239 
240 
241 class SysTextFileOut: public TextOutStream
242 {
243 	File f;
244 public:
SysTextFileOut(int bSize=4096)245 	SysTextFileOut( int bSize = 4096 ): TextOutStream( bSize ) {}
Open(const sys_char_t * fileName)246 	void Open( const sys_char_t* fileName ) { Clear(); f.Open( fileName, FOPEN_WRITE | FOPEN_CREATE | FOPEN_TRUNC ); }
Close()247 	void Close() { f.Close(); }
~SysTextFileOut()248 	~SysTextFileOut() {}
249 
250 protected:
251 	virtual void Write( char* buf, int size );
252 };
253 
Write(char * buf,int size)254 void SysTextFileOut::Write( char* buf, int size ) {  f.Write( buf, size ); }
255 
256 
257 static FSPath configDirPath( CS_UTF8, "???" );
258 
259 
LoadIniHash(IniHash & iniHash,const sys_char_t * fileName)260 void LoadIniHash( IniHash& iniHash, const sys_char_t* fileName )
261 {
262 	SysTextFileIn in;
263 
264 	try
265 	{
266 		in.Open( fileName );
267 	}
268 	catch ( csyserr* ex )
269 	{
270 		if ( SysErrorIsFileNotFound( ex->code ) )
271 		{
272 			ex->destroy();
273 			return;
274 		}
275 
276 		throw;
277 	}
278 
279 	char buf[4096];
280 	std::string section;
281 
282 	while ( in.GetLine( buf, sizeof( buf ) ) )
283 	{
284 
285 		char* s = buf;
286 
287 		while ( IsSpace( *s ) ) { s++; }
288 
289 		if ( !*s || *s == '#' ) { continue; }
290 
291 		if ( *s == '[' )
292 		{
293 			s++;
294 
295 			while ( IsSpace( *s ) ) { s++; }
296 
297 			char* t = s;
298 
299 			while ( *t && *t != ']' ) { t++; }
300 
301 			if ( *t != ']' ) { continue; }
302 
303 			while ( t > s && IsSpace( *( t - 1 ) ) ) { t--; }
304 
305 			*t = 0;
306 
307 			section = s;
308 
309 		}
310 		else
311 		{
312 			if ( section.empty() ) { continue; }
313 
314 			char* t = s;
315 
316 			while ( *t && *t != '=' ) { t++; }
317 
318 			if ( *t != '=' ) { continue; }
319 
320 			char* v = t + 1;
321 
322 			while ( t > s && IsSpace( *( t - 1 ) ) ) { t--; }
323 
324 			*t = 0;
325 
326 			while ( IsSpace( *v ) ) { v++; }
327 
328 			t = v;
329 
330 			while ( *t ) { t++; }
331 
332 			while ( t > v && IsSpace( *( t - 1 ) ) ) { t--; }
333 
334 			*t = 0;
335 
336 			iniHash.SetStrValue( section.data(), s, v );
337 		}
338 	}
339 
340 	in.Close();
341 }
342 
IniHashLoad(IniHash & iniHash,const char * sectName)343 void IniHashLoad( IniHash& iniHash, const char* sectName )
344 {
345 	FSPath path = configDirPath;
346 	path.Push( CS_UTF8, carray_cat<char>( sectName, ".cfg" ).data() );
347 
348 	LoadIniHash( iniHash, (sys_char_t*) path.GetString( sys_charset_id ) );
349 }
350 
strless(const char * a,const char * b)351 inline bool strless( const char* a, const char* b )
352 {
353 	const char* s1 = a;
354 	const char* s2 = b;
355 
356 	while ( *s1 && *s1 == *s2 ) { s1++; s2++; };
357 
358 	return *s1 <= *s2;
359 }
360 
SaveIniHash(IniHash & iniHash,const sys_char_t * fileName)361 void SaveIniHash( IniHash& iniHash, const sys_char_t* fileName )
362 {
363 	SysTextFileOut out;
364 	out.Open( fileName );
365 
366 	if ( iniHash.Size() > 0 )
367 	{
368 		std::vector<const char*> secList = iniHash.Keys();
369 
370 		std::sort( secList.begin(), secList.end(), strless );
371 
372 		for ( int i = 0, count = secList.size(); i < count; i++ )
373 		{
374 			out.Put( "\n[" );
375 			out.Put( secList[i] );
376 			out.Put( "]\n" );
377 			cstrhash< std::string >* h = iniHash.Exist( secList[i] );
378 
379 			if ( !h ) { continue; }
380 
381 			std::vector<const char*> varList = h->keys();
382 
383 			std::sort( varList.begin(), varList.end(), strless );
384 
385 			for ( int j = 0; j < h->count(); j++ )
386 			{
387 				out.Put( varList[j] );
388 				out.PutC( '=' );
389 				std::string* p = h->exist( varList[j] );
390 
391 				if ( p && p->data() ) { out.Put( p->data() ); }
392 
393 				out.PutC( '\n' );
394 			}
395 		}
396 	}
397 
398 	out.Flush();
399 	out.Close();
400 }
401 
IniHashSave(IniHash & iniHash,const char * sectName)402 void IniHashSave( IniHash& iniHash, const char* sectName )
403 {
404 	FSPath path = configDirPath;
405 	path.Push( CS_UTF8, carray_cat<char>( sectName, ".cfg" ).data() );
406 
407 	SaveIniHash( iniHash, (sys_char_t*) path.GetString( sys_charset_id ) );
408 }
409 
410 
LoadStringList(const char * section,std::vector<std::string> & list)411 bool LoadStringList( const char* section, std::vector< std::string >& list )
412 {
413 	try
414 	{
415 		SysTextFileIn in;
416 
417 		FSPath path = configDirPath;
418 		path.Push( CS_UTF8, carray_cat<char>( section, ".cfg" ).data() );
419 		in.Open( ( sys_char_t* )path.GetString( sys_charset_id ) );
420 
421 		char buf[4096];
422 
423 		while ( in.GetLine( buf, sizeof( buf ) ) )
424 		{
425 			char* s = buf;
426 
427 			while ( *s > 0 && *s <= ' ' ) { s++; }
428 
429 			if ( *s ) { list.push_back( std::string( s ) ); }
430 		}
431 	}
432 	catch ( cexception* ex )
433 	{
434 		ex->destroy();
435 		return false;
436 	}
437 
438 	return true;
439 }
440 
441 
SaveStringList(const char * section,std::vector<std::string> & list)442 void SaveStringList( const char* section, std::vector< std::string >& list )
443 {
444 	try
445 	{
446 		SysTextFileOut out;
447 
448 		FSPath path = configDirPath;
449 		path.Push( CS_UTF8, carray_cat<char>( section, ".cfg" ).data() );
450 		out.Open( ( sys_char_t* )path.GetString( sys_charset_id ) );
451 
452 		for ( int i = 0; i < ( int )list.size(); i++ )
453 		{
454 			if ( list[i].c_str() && list[i][0] )
455 			{
456 				out.Put( list[i].c_str() );
457 				out.PutC( '\n' );
458 			}
459 		}
460 
461 		out.Flush();
462 		out.Close();
463 
464 	}
465 	catch ( cexception* ex )
466 	{
467 		ex->destroy();
468 		return ;
469 	}
470 }
471 
472 
473 #else
474 //старый клочек, надо перепроверить
475 static const char* regapp = "WCM commander";
476 static const char* regcomp = "WCM";
477 
478 #define COMPANY regcomp
479 #define APPNAME regapp
480 
GetAppProfileKey()481 static HKEY GetAppProfileKey()
482 {
483 	if ( !regapp || !regcomp ) { return NULL; }
484 
485 	HKEY hsoft = NULL;
486 	HKEY hcomp = NULL;
487 	HKEY happ  = NULL;
488 
489 	if ( RegOpenKeyExA( HKEY_CURRENT_USER, "software", 0, KEY_WRITE | KEY_READ,
490 	                    &hsoft ) == ERROR_SUCCESS )
491 	{
492 		DWORD dw;
493 
494 		if ( RegCreateKeyExA( hsoft, COMPANY, 0, REG_NONE,
495 		                      REG_OPTION_NON_VOLATILE, KEY_WRITE | KEY_READ, NULL,
496 		                      &hcomp, &dw ) == ERROR_SUCCESS )
497 		{
498 			RegCreateKeyExA( hcomp, APPNAME, 0, REG_NONE,
499 			                 REG_OPTION_NON_VOLATILE, KEY_WRITE | KEY_READ, NULL,
500 			                 &happ, &dw );
501 		}
502 	}
503 
504 	if ( hsoft != NULL ) { RegCloseKey( hsoft ); }
505 
506 	if ( hcomp != NULL ) { RegCloseKey( hcomp ); }
507 
508 	return happ;
509 }
510 
GetSection(HKEY hKey,const char * sectname)511 HKEY GetSection( HKEY hKey, const char* sectname )
512 {
513 	ASSERT( sectname && *sectname );
514 	if ( !hKey )
515 	{
516 		return NULL;
517 	}
518 
519 	DWORD dw;
520 	HKEY hsect;
521 	RegCreateKeyEx( hKey, sectname, 0, REG_NONE,
522 		REG_OPTION_NON_VOLATILE, KEY_WRITE | KEY_READ | KEY_QUERY_VALUE, NULL,
523 		&hsect, &dw );
524 
525 	return hsect;
526 }
527 
GetSection(const char * sectname)528 HKEY GetSection( const char* sectname )
529 {
530 	ASSERT( sectname && *sectname );
531 	HKEY happ = GetAppProfileKey();
532 	if ( !happ )
533 	{
534 		return NULL;
535 	}
536 
537 	HKEY hsect = GetSection( happ, sectname );
538 	RegCloseKey( happ );
539 	return hsect;
540 }
541 
RegReadKeys(HKEY hKey)542 std::vector<std::string> RegReadKeys( HKEY hKey )
543 {
544 	if ( !hKey )
545 	{
546 		return std::vector<std::string>();
547 	}
548 
549 	std::vector<std::string> keys;
550 
551 	DWORD dwIndex = 0, dwSize;
552 	char buf[256];
553 	while ( RegEnumKeyEx( hKey, dwIndex++, buf, &(dwSize = 256), NULL, NULL, NULL, NULL ) == ERROR_SUCCESS )
554 	{
555 		std::string str( buf );
556 		keys.push_back( str );
557 	}
558 
559 	return keys;
560 }
561 
RegReadIniHash(HKEY hKey,IniHash & iniHash)562 void RegReadIniHash( HKEY hKey, IniHash& iniHash )
563 {
564 	char bufName[256];
565 	char bufValue[4096];
566 
567 	std::vector<std::string> keys = RegReadKeys( hKey );
568 	for ( int i = 0, count = keys.size(); i < count; i++ )
569 	{
570 		std::string section = keys.at( i );
571 		HKEY hSect = GetSection( hKey, section.c_str() );
572 
573 		DWORD dwIndex = 0, dwNameSize, dwValueSize;
574 		while ( RegEnumValue( hSect, dwIndex++, bufName, &(dwNameSize = 256), NULL, NULL, (LPBYTE) bufValue, &(dwValueSize = 4096) ) == ERROR_SUCCESS )
575 		{
576 			iniHash.SetStrValue( section.c_str(), bufName, bufValue );
577 		}
578 
579 		RegCloseKey( hSect );
580 	}
581 }
582 
RegWriteIniHash(HKEY hKey,IniHash & iniHash)583 void RegWriteIniHash( HKEY hKey, IniHash& iniHash )
584 {
585 	std::vector<const char*> secList = iniHash.Keys();
586 	//std::sort( secList.begin(), secList.end(), strless );
587 
588 	for ( int i = 0, sectCount = secList.size(); i < sectCount; i++ )
589 	{
590 		const char* section = secList[i];
591 		cstrhash<std::string>* h = iniHash.Exist( section );
592 		if ( !h )
593 		{
594 			continue;
595 		}
596 
597 		std::vector<const char*> varList = h->keys();
598 		//std::sort( varList.begin(), varList.end(), strless );
599 		HKEY hSect = GetSection( hKey, section );
600 		if ( !hSect )
601 		{
602 			continue;
603 		}
604 
605 		for ( int j = 0, varCount = varList.size(); j < varCount; j++ )
606 		{
607 			const char* var = varList[j];
608 			std::string* p = h->exist( var );
609 			if ( p && p->c_str() )
610 			{
611 				RegSetValueEx( hSect, var, 0, REG_SZ, (LPBYTE) p->c_str(), p->size() + 1 );
612 			}
613 		}
614 
615 		RegCloseKey( hSect );
616 	}
617 }
618 
RegReadInt(const char * sect,const char * what,DWORD def)619 DWORD RegReadInt( const char* sect, const  char* what, DWORD def )
620 {
621 	HKEY hsect = GetSection( sect );
622 
623 	if ( !hsect ) { return def; }
624 
625 	DWORD dwValue;
626 	DWORD dwType;
627 	DWORD dwCount = sizeof( DWORD );
628 	LONG lResult = RegQueryValueEx( hsect, ( LPTSTR )what, NULL, &dwType,
629 	                                ( LPBYTE )&dwValue, &dwCount );
630 	RegCloseKey( hsect );
631 
632 	if ( lResult == ERROR_SUCCESS )
633 	{
634 		ASSERT( dwType == REG_DWORD );
635 		ASSERT( dwCount == sizeof( dwValue ) );
636 		return ( UINT )dwValue;
637 	}
638 
639 	return def;
640 }
641 
RegReadString(char const * sect,const char * what,const char * def)642 std::string RegReadString( char const* sect, const char* what, const char* def )
643 {
644 	HKEY hsect = GetSection( sect );
645 
646 	if ( !hsect ) { return def ? def : std::string(); }
647 
648 	std::string strValue;
649 	DWORD dwType, dwCount;
650 	LONG lResult = RegQueryValueEx( hsect, ( LPTSTR )what, NULL, &dwType, NULL, &dwCount );
651 
652 	if ( lResult == ERROR_SUCCESS )
653 	{
654 		ASSERT( dwType == REG_SZ );
655 
656 		//TODO: possible memory leak, needs to be checked!!!
657 		char* Buf = (char*)alloca( dwCount + 1 );
658 		Buf[dwCount] = 0;
659 
660 		lResult = RegQueryValueEx( hsect, ( LPTSTR )what, NULL, &dwType, ( LPBYTE )Buf, &dwCount );
661 
662 		strValue = std::string( Buf );
663 	}
664 
665 	RegCloseKey( hsect );
666 
667 	if ( lResult == ERROR_SUCCESS )
668 	{
669 		ASSERT( dwType == REG_SZ );
670 		return strValue;
671 	}
672 
673 	return def ? def : std::string();
674 }
675 
RegGetBinSize(const char * sect,const char * what)676 int RegGetBinSize( const char* sect, const char* what )
677 {
678 	HKEY hsect = GetSection( sect );
679 
680 	if ( hsect == NULL ) { return -1; }
681 
682 	DWORD dwType, dwCount;
683 	LONG lResult = RegQueryValueEx( hsect, ( LPTSTR )what, NULL, &dwType,
684 	                                NULL, &dwCount );
685 	RegCloseKey( hsect );
686 
687 	if ( lResult != ERROR_SUCCESS ) { return -1; }
688 
689 	return dwCount;
690 
691 }
692 
RegReadBin(const char * sect,const char * what,const void * data,int size)693 bool RegReadBin( const char* sect, const char* what, const void* data, int size )
694 {
695 	HKEY hsect = GetSection( sect );
696 
697 	if ( hsect == NULL ) { return false; }
698 
699 	DWORD dwType, dwCount;
700 	LONG lResult = RegQueryValueEx( hsect, ( LPTSTR )what, NULL, &dwType,
701 	                                NULL, &dwCount );
702 
703 	if ( lResult != ERROR_SUCCESS || dwCount != ( DWORD )size )
704 	{
705 		RegCloseKey( hsect );
706 		return false;
707 	}
708 
709 	if ( lResult == ERROR_SUCCESS )
710 	{
711 		ASSERT( dwType == REG_BINARY );
712 		lResult = RegQueryValueEx( hsect, ( LPTSTR )what, NULL, &dwType,
713 		                           ( LPBYTE )data, &dwCount );
714 	}
715 
716 	RegCloseKey( hsect );
717 	return ( lResult == ERROR_SUCCESS );
718 }
719 
RegWriteInt(const char * sect,const char * what,DWORD data)720 bool RegWriteInt( const char* sect, const char* what, DWORD data )
721 {
722 	HKEY hsect = GetSection( sect );
723 
724 	if ( hsect == NULL ) { return false; }
725 
726 	LONG lResult = RegSetValueEx( hsect, what, 0, REG_DWORD,
727 	                              ( LPBYTE )&data, sizeof( data ) );
728 	RegCloseKey( hsect );
729 	return lResult == ERROR_SUCCESS;
730 }
731 
RegWriteString(const char * sect,const char * what,const char * data)732 bool RegWriteString( const char* sect, const char* what, const char* data )
733 {
734 	if ( !data ) { return false; }
735 
736 	HKEY hsect = GetSection( sect );
737 
738 	if ( hsect == NULL ) { return false; }
739 
740 	LONG lResult = RegSetValueEx( hsect, what, 0, REG_SZ,
741 	                              ( LPBYTE )data, strlen( data ) + 1 );
742 	RegCloseKey( hsect );
743 	return lResult == ERROR_SUCCESS;
744 }
745 
RegWriteBin(const char * sect,const char * what,const void * data,int size)746 bool RegWriteBin( const char* sect, const char* what, const void* data, int size )
747 {
748 	HKEY hsect = GetSection( sect );
749 
750 	if ( hsect == NULL ) { return false; }
751 
752 	LONG lResult = RegSetValueEx( hsect, what, 0, REG_BINARY,
753 	                              ( LPBYTE )data, size );
754 	RegCloseKey( hsect );
755 	return lResult == ERROR_SUCCESS;
756 }
757 
LoadStringList(const char * section,std::vector<std::string> & list)758 bool LoadStringList( const char* section, std::vector< std::string >& list )
759 {
760 	char name[64];
761 	list.clear();
762 
763 	for ( int i = 1; ; i++ )
764 	{
765 		Lsnprintf( name, sizeof( name ), "v%i", i );
766 		std::string s = RegReadString( section, name, "" );
767 
768 		if ( s.empty() ) { break; }
769 
770 		list.push_back( s );
771 	}
772 
773 	return true;
774 }
775 
SaveStringList(const char * section,std::vector<std::string> & list)776 void SaveStringList( const char* section, std::vector< std::string >& list )
777 {
778 	int n = 1;
779 	char name[64];
780 
781 	for ( size_t i = 0; i < list.size(); i++ )
782 	{
783 		if ( list[i].data() && list[i][0] )
784 		{
785 			Lsnprintf( name, sizeof( name ), "v%i", n );
786 
787 			if ( !RegWriteString( section, name, list[i].data() ) )
788 			{
789 				break;
790 			}
791 
792 			n++;
793 		}
794 	}
795 
796 	Lsnprintf( name, sizeof( name ), "v%i", n );
797 	RegWriteString( section, name, "" );
798 }
799 
IniHashLoad(IniHash & iniHash,const char * sectName)800 void IniHashLoad( IniHash& iniHash, const char* sectName )
801 {
802 	HKEY hKey = GetSection( sectName );
803 	if ( hKey )
804 	{
805 		RegReadIniHash( hKey, iniHash );
806 		RegCloseKey( hKey );
807 	}
808 }
809 
IniHashSave(IniHash & iniHash,const char * sectName)810 void IniHashSave( IniHash& iniHash, const char* sectName )
811 {
812 	HKEY hKey = GetSection( sectName );
813 	if ( hKey )
814 	{
815 		RegWriteIniHash( hKey, iniHash );
816 		RegCloseKey( hKey );
817 	}
818 }
819 
820 #endif
821 
822 const char* sectionSystem = "system";
823 const char* sectionPanel = "panel";
824 const char* sectionEditor = "editor";
825 const char* sectionViewer = "viewer";
826 const char* sectionTerminal = "terminal";
827 const char* sectionFonts = "fonts";
828 
829 static const char* CommandsHistorySection = "CommandsHistory";
830 static const char* FilesAssociationsSection = "FilesAssociations";
831 static const char* HighlightingRulesSection = "HighlightingRules";
832 static const char* UserMenuSection = "UserMenu";
833 
clWcmConfig()834 clWcmConfig::clWcmConfig()
835 	: systemAskOpenExec( true )
836 	, systemEscPanel( true )
837 	, systemEscCommandLine( true )
838 	, systemBackSpaceUpDir( false )
839 	, systemAutoComplete( true )
840 	, systemAutoSaveSetup( true )
841 	, systemShowHostName( false )
842 	, systemStorePasswords( false )
843 	, systemLang( "+" )
844 
845 	, panelShowHiddenFiles( true )
846 	, panelCaseSensitive( false )
847 	, panelSelectFolders( false )
848 	, panelShowDotsInRoot( false )
849 	, panelShowFolderIcons( true )
850 	, panelShowExecutableIcons( true )
851 	, panelShowLinkIcons( true )
852 	, panelShowScrollbar( true )
853 	, panelShowSpacesMode( ePanelSpacesMode_Trailing )
854 	, panelModeLeft( 0 )
855 	, panelModeRight( 0 )
856 
857 	, editSavePos( true )
858 	, editAutoIdent( false )
859 	, editTabSize( 3 )
860 	, editShl( true )
861 	, editClearHistoryAfterSaving( true )
862 
863 	, terminalBackspaceKey( 0 )
864 
865 	, styleShow3DUI( false )
866 	, styleColorTheme( "" )
867 	, styleShowToolBar( true )
868 	, styleShowButtonBar( true )
869 	, styleShowButtonBarIcons( true )
870 	, styleShowMenuBar( true )
871 
872 	, windowX( 0 )
873 	, windowY( 0 )
874 	, windowWidth( 0 )
875 	, windowHeight( 0 )
876 {
877 #ifndef _WIN32
878 	MapBool( sectionSystem, "ask_open_exec", &systemAskOpenExec, systemAskOpenExec );
879 #endif
880 	MapBool( sectionSystem, "esc_panel", &systemEscPanel, systemEscPanel );
881 	MapBool( sectionSystem, "esc_panel", &systemEscCommandLine, systemEscCommandLine );
882 	MapBool( sectionSystem, "back_updir", &systemBackSpaceUpDir, systemBackSpaceUpDir );
883 	MapBool( sectionSystem, "auto_complete", &systemAutoComplete, systemAutoComplete );
884 	MapBool( sectionSystem, "auto_save_setup", &systemAutoSaveSetup, systemAutoSaveSetup );
885 	MapBool( sectionSystem, "show_hostname", &systemShowHostName, systemShowHostName );
886 	MapBool( sectionSystem, "store_passwords", &systemStorePasswords, systemStorePasswords );
887 	MapStr( sectionSystem,  "lang", &systemLang );
888 
889 	MapBool( sectionSystem, "show_toolbar", &styleShowToolBar, styleShowToolBar );
890 	MapBool( sectionSystem, "show_buttonbar", &styleShowButtonBar, styleShowButtonBar );
891 	MapBool( sectionSystem, "show_buttonbaricons", &styleShowButtonBarIcons, styleShowButtonBarIcons );
892 	MapBool( sectionSystem, "show_menubar", &styleShowMenuBar, styleShowMenuBar );
893 	MapBool( sectionPanel, "show_3d_ui", &styleShow3DUI, styleShow3DUI );
894 	MapStr( sectionPanel, "color_theme", &styleColorTheme, "" );
895 
896 	MapBool( sectionPanel, "show_hidden_files",   &panelShowHiddenFiles, panelShowHiddenFiles );
897 	MapBool( sectionPanel, "case_sensitive_sort", &panelCaseSensitive, panelCaseSensitive );
898 	MapBool( sectionPanel, "select_folders",   &panelSelectFolders, panelSelectFolders );
899 	MapBool( sectionPanel, "show_dots",     &panelShowDotsInRoot, panelShowDotsInRoot );
900 	MapBool( sectionPanel, "show_foldericons",     &panelShowFolderIcons, panelShowFolderIcons );
901 	MapBool( sectionPanel, "show_executableicons",     &panelShowExecutableIcons, panelShowExecutableIcons );
902 	MapBool( sectionPanel, "show_linkicons",     &panelShowLinkIcons, panelShowLinkIcons );
903 	MapBool( sectionPanel, "show_scrollbar",     &panelShowScrollbar, panelShowScrollbar );
904 	MapInt( sectionPanel,  "show_spaces_mode",     ( int* )&panelShowSpacesMode, panelShowSpacesMode );
905 	MapInt( sectionPanel,  "mode_left",     &panelModeLeft, panelModeLeft );
906 	MapInt( sectionPanel,  "mode_right",    &panelModeRight, panelModeRight );
907 
908 #ifdef _WIN32
909 	const char* defPanelPath = "C:\\";
910 #else
911 	const char* defPanelPath = "/";
912 #endif
913 
914 	MapStr( sectionPanel,  "left_panel_path", &leftPanelPath, defPanelPath );
915 	MapStr( sectionPanel,  "right_panel_path", &rightPanelPath, defPanelPath );
916 
917 	MapBool( sectionEditor, "save_file_position",    &editSavePos, editSavePos );
918 	MapBool( sectionEditor, "auto_ident",   &editAutoIdent, editAutoIdent );
919 	MapInt( sectionEditor, "tab_size",   &editTabSize, editTabSize );
920 	MapBool( sectionEditor, "highlighting", &editShl, editShl );
921 	MapBool( sectionEditor, "editClearHistoryAfterSaving", &editClearHistoryAfterSaving, editClearHistoryAfterSaving );
922 
923 	MapInt( sectionTerminal, "backspace_key",  &terminalBackspaceKey, terminalBackspaceKey );
924 
925 	MapStr( sectionFonts, "panel_font",  &panelFontUri );
926 	MapStr( sectionFonts, "viewer_font", &viewerFontUri );
927 	MapStr( sectionFonts, "editor_font", &editorFontUri );
928 	MapStr( sectionFonts, "dialog_font", &dialogFontUri );
929 	MapStr( sectionFonts, "terminal_font",  &terminalFontUri );
930 	MapStr( sectionFonts, "helptext_font",  &helpTextFontUri );
931 	MapStr( sectionFonts, "helpbold_font",  &helpBoldFontUri );
932 	MapStr( sectionFonts, "helphead_font",  &helpHeadFontUri );
933 
934 	MapInt( sectionSystem,  "windowX",      &windowX,      windowX );
935 	MapInt( sectionSystem,  "windowY",      &windowY,      windowY );
936 	MapInt( sectionSystem,  "windowWidth",  &windowWidth,  windowWidth );
937 	MapInt( sectionSystem,  "windowHeight", &windowHeight, windowHeight );
938 }
939 
ImpCurrentFonts()940 void clWcmConfig::ImpCurrentFonts()
941 {
942 	panelFontUri = g_PanelFont.ptr() ? g_PanelFont->uri() : "";
943 	viewerFontUri = g_ViewerFont.ptr() ? g_ViewerFont->uri() : "";
944 	editorFontUri = g_EditorFont.ptr() ? g_EditorFont->uri() : "";
945 	dialogFontUri  = g_DialogFont.ptr() ? g_DialogFont->uri() : "";
946 	terminalFontUri  = g_TerminalFont.ptr() ? g_TerminalFont->uri() : "";
947 	helpTextFontUri  = g_HelpTextFont.ptr() ? g_HelpTextFont->uri() : "";
948 	helpBoldFontUri  = g_HelpBoldFont.ptr() ? g_HelpBoldFont->uri() : "";
949 	helpHeadFontUri  = g_HelpHeadFont.ptr() ? g_HelpHeadFont->uri() : "";
950 }
951 
MapInt(const char * Section,const char * Name,int * pInt,int def)952 void clWcmConfig::MapInt( const char* Section, const char* Name, int* pInt, int def )
953 {
954 	sNode Node = sNode::CreateIntNode( Section, Name, pInt, def );
955 	m_MapList.push_back( Node );
956 }
957 
MapBool(const char * Section,const char * Name,bool * pBool,bool def)958 void clWcmConfig::MapBool( const char* Section, const char* Name, bool* pBool, bool def )
959 {
960 	sNode Node = sNode::CreateBoolNode( Section, Name, pBool, def );
961 	m_MapList.push_back( Node );
962 }
963 
MapStr(const char * Section,const char * Name,std::string * pStr,const char * def)964 void clWcmConfig::MapStr( const char* Section, const char* Name, std::string* pStr, const char* def )
965 {
966 	sNode Node = sNode::CreateStrNode( Section, Name, pStr, def );
967 	m_MapList.push_back( Node );
968 }
969 
970 class clConfigHelper
971 {
972 public:
clConfigHelper()973 	clConfigHelper() : m_SectionName( "" ) {}
974 
SetSectionName(const char * SectionName)975 	void SetSectionName( const char* SectionName )
976 	{
977 		m_SectionName = SectionName;
978 	}
979 
980 protected:
981 	const char* m_SectionName;
982 };
983 
984 class clConfigWriter: public clConfigHelper
985 {
986 public:
987 #if defined(_WIN32)
clConfigWriter()988 	clConfigWriter() {}
989 #else
990 	explicit clConfigWriter( IniHash& hash ) : m_Hash( hash ) {}
991 #endif
992 
Write(const char * KeyNamePattern,int i,const std::string & Data)993 	void Write( const char* KeyNamePattern, int i, const std::string&  Data )
994 	{
995 		this->Write( KeyNamePattern, i, Data.c_str() );
996 	}
997 
Write(const char * KeyNamePattern,int i,const char * Data)998 	void Write( const char* KeyNamePattern, int i, const char* Data )
999 	{
1000 		char Buf[4096];
1001 		Lsnprintf( Buf, sizeof( Buf ), KeyNamePattern, i );
1002 #ifdef _WIN32
1003 		RegWriteString( m_SectionName, Buf, Data );
1004 #else
1005 		m_Hash.SetStrValue( m_SectionName, Buf, Data );
1006 #endif
1007 	}
WriteBool(const char * KeyNamePattern,int i,bool Data)1008 	void WriteBool( const char* KeyNamePattern, int i, bool Data )
1009 	{
1010 		char Buf[4096];
1011 		Lsnprintf( Buf, sizeof( Buf ), KeyNamePattern, i );
1012 #ifdef _WIN32
1013 		RegWriteInt( m_SectionName, Buf, ( int )Data );
1014 #else
1015 		m_Hash.SetBoolValue( m_SectionName, Buf, Data );
1016 #endif
1017 	}
WriteInt(const char * KeyNamePattern,int i,int Data)1018 	void WriteInt( const char* KeyNamePattern, int i, int Data )
1019 	{
1020 		char Buf[4096];
1021 		Lsnprintf( Buf, sizeof( Buf ), KeyNamePattern, i );
1022 #ifdef _WIN32
1023 		RegWriteInt( m_SectionName, Buf, Data );
1024 #else
1025 		m_Hash.SetIntValue( m_SectionName, Buf, Data );
1026 #endif
1027 	}
1028 
1029 private:
1030 #if !defined(_WIN32)
1031 	IniHash& m_Hash;
1032 #endif
1033 };
1034 
1035 class clConfigReader: public clConfigHelper
1036 {
1037 public:
1038 #if defined(_WIN32)
clConfigReader()1039 	clConfigReader() {}
1040 #else
1041 	explicit clConfigReader( IniHash& hash ): m_Hash( hash ) {}
1042 #endif
1043 
Read(const char * KeyNamePattern,int i)1044 	std::string Read( const char* KeyNamePattern, int i )
1045 	{
1046 		char Buf[4096];
1047 		Lsnprintf( Buf, sizeof( Buf ), KeyNamePattern, i );
1048 #ifdef _WIN32
1049 		std::string Result = RegReadString( m_SectionName, Buf, "" );
1050 #else
1051 		std::string Result = m_Hash.GetStrValue( m_SectionName, Buf, "" );
1052 #endif
1053 		return Result;
1054 	}
ReadBool(const char * KeyNamePattern,int i,bool DefaultValue)1055 	bool ReadBool( const char* KeyNamePattern, int i, bool DefaultValue )
1056 	{
1057 		char Buf[4096];
1058 		Lsnprintf( Buf, sizeof( Buf ), KeyNamePattern, i );
1059 #ifdef _WIN32
1060 		bool Result = RegReadInt( m_SectionName, Buf, DefaultValue ) != 0;
1061 #else
1062 		bool Result = m_Hash.GetBoolValue( m_SectionName, Buf, DefaultValue );
1063 #endif
1064 		return Result;
1065 	}
ReadInt(const char * KeyNamePattern,int i,int DefaultValue)1066 	int ReadInt( const char* KeyNamePattern, int i, int DefaultValue )
1067 	{
1068 		char Buf[4096];
1069 		Lsnprintf( Buf, sizeof( Buf ), KeyNamePattern, i );
1070 #ifdef _WIN32
1071 		int Result = RegReadInt( m_SectionName, Buf, DefaultValue );
1072 #else
1073 		int Result = m_Hash.GetIntValue( m_SectionName, Buf, DefaultValue );
1074 #endif
1075 		return Result;
1076 	}
1077 
1078 private:
1079 #if !defined(_WIN32)
1080 	IniHash& m_Hash;
1081 #endif
1082 };
1083 
SaveFileAssociations(NCWin * nc,IniHash & hash)1084 void SaveFileAssociations( NCWin* nc
1085 #ifndef _WIN32
1086                            , IniHash& hash
1087 #endif
1088                          )
1089 {
1090 	if ( !nc ) { return; }
1091 
1092 #if defined(_WIN32)
1093 	clConfigWriter Cfg;
1094 #else
1095 	clConfigWriter Cfg( hash );
1096 #endif
1097 	Cfg.SetSectionName( FilesAssociationsSection );
1098 
1099 	const std::vector<clNCFileAssociation>& Assoc = g_Env.GetFileAssociations();
1100 
1101 	for ( size_t i = 0; i < Assoc.size(); i++ )
1102 	{
1103 		const clNCFileAssociation& A = Assoc[i];
1104 
1105 		std::string Mask_utf8 = unicode_to_utf8_string( A.GetMask().data() );
1106 		std::string Description_utf8 = unicode_to_utf8_string( A.GetDescription().data() );
1107 		std::string Execute_utf8 = unicode_to_utf8_string( A.GetExecuteCommand().data() );
1108 		std::string ExecuteSecondary_utf8 = unicode_to_utf8_string( A.GetExecuteCommandSecondary().data() );
1109 		std::string View_utf8 = unicode_to_utf8_string( A.GetViewCommand().data() );
1110 		std::string ViewSecondary_utf8 = unicode_to_utf8_string( A.GetViewCommandSecondary().data() );
1111 		std::string Edit_utf8 = unicode_to_utf8_string( A.GetEditCommand().data() );
1112 		std::string EditSecondary_utf8 = unicode_to_utf8_string( A.GetEditCommandSecondary().data() );
1113 
1114 		Cfg.Write( "Mask%i", i, Mask_utf8 );
1115 		Cfg.Write( "Description%i", i, Description_utf8 );
1116 		Cfg.Write( "Execute%i", i, Execute_utf8 );
1117 		Cfg.Write( "ExecuteSecondary%i", i, ExecuteSecondary_utf8 );
1118 		Cfg.Write( "View%i", i, View_utf8 );
1119 		Cfg.Write( "ViewSecondary%i", i, ViewSecondary_utf8 );
1120 		Cfg.Write( "Edit%i", i, Edit_utf8 );
1121 		Cfg.Write( "EditSecondary%i", i, EditSecondary_utf8 );
1122 		Cfg.WriteBool( "HasTerminal%i", i, A.GetHasTerminal() );
1123 	}
1124 
1125 	// end marker
1126 	Cfg.Write( "Mask%i", Assoc.size(), "" );
1127 }
1128 
LoadFileAssociations(NCWin * nc,IniHash & hash)1129 void LoadFileAssociations( NCWin* nc
1130 #ifndef _WIN32
1131                            , IniHash& hash
1132 #endif
1133                          )
1134 {
1135 	if ( !nc ) { return; }
1136 
1137 #if defined(_WIN32)
1138 	clConfigReader Cfg;
1139 #else
1140 	clConfigReader Cfg( hash );
1141 #endif
1142 	Cfg.SetSectionName( FilesAssociationsSection );
1143 
1144 	int i = 0;
1145 
1146 	std::vector<clNCFileAssociation> Assoc;
1147 
1148 	while ( true )
1149 	{
1150 		std::string Mask = Cfg.Read( "Mask%i", i );
1151 		std::string Description = Cfg.Read( "Description%i", i );
1152 		std::string Execute = Cfg.Read( "Execute%i", i );
1153 		std::string ExecuteSecondary = Cfg.Read( "ExecuteSecondary%i", i );
1154 		std::string View = Cfg.Read( "View%i", i );
1155 		std::string ViewSecondary = Cfg.Read( "ViewSecondary%i", i );
1156 		std::string Edit = Cfg.Read( "Edit%i", i );
1157 		std::string EditSecondary = Cfg.Read( "EditSecondary%i", i );
1158 		bool HasTerminal = Cfg.ReadBool( "HasTerminal%i", i, true );
1159 
1160 		if ( Mask.empty() ) { break; }
1161 
1162 		clNCFileAssociation A;
1163 		A.SetMask( utf8str_to_unicode( Mask ) );
1164 		A.SetDescription( utf8str_to_unicode( Description ) );
1165 		A.SetExecuteCommand( utf8str_to_unicode( Execute ) );
1166 		A.SetExecuteCommandSecondary( utf8str_to_unicode( ExecuteSecondary ) );
1167 		A.SetViewCommand( utf8str_to_unicode( View ) );
1168 		A.SetViewCommandSecondary( utf8str_to_unicode( ViewSecondary ) );
1169 		A.SetEditCommand( utf8str_to_unicode( Edit ) );
1170 		A.SetEditCommandSecondary( utf8str_to_unicode( EditSecondary ) );
1171 		A.SetHasTerminal( HasTerminal );
1172 		Assoc.push_back( A );
1173 
1174 		i++;
1175 	}
1176 
1177 	g_Env.SetFileAssociations( Assoc );
1178 }
1179 
SaveUserMenu(NCWin * nc,IniHash & hash)1180 void SaveUserMenu( NCWin* nc
1181 #ifndef _WIN32
1182                    , IniHash& hash
1183 #endif
1184                  )
1185 {
1186 	if ( !nc ) { return; }
1187 
1188 #if defined(_WIN32)
1189 	clConfigWriter Cfg;
1190 #else
1191 	clConfigWriter Cfg( hash );
1192 #endif
1193 	Cfg.SetSectionName( UserMenuSection );
1194 
1195 	const std::vector<clNCUserMenuItem>& Items = g_Env.GetUserMenuItems();
1196 
1197 	for ( size_t i = 0; i < Items.size(); i++ )
1198 	{
1199 		const clNCUserMenuItem& A = Items[i];
1200 
1201 		std::string Description_utf8 = unicode_to_utf8_string( A.GetDescription().GetRawText() );
1202 		std::string Execute_utf8 = unicode_to_utf8_string( A.GetCommand().data() );
1203 
1204 		Cfg.Write( "Description%i", i, Description_utf8 );
1205 		Cfg.Write( "Execute%i", i, Execute_utf8 );
1206 	}
1207 
1208 	// end marker
1209 	Cfg.Write( "Mask%i", Items.size(), "" );
1210 }
1211 
LoadUserMenu(NCWin * nc,IniHash & hash)1212 void LoadUserMenu( NCWin* nc
1213 #ifndef _WIN32
1214                    , IniHash& hash
1215 #endif
1216                  )
1217 {
1218 	if ( !nc ) { return; }
1219 
1220 #if defined(_WIN32)
1221 	clConfigReader Cfg;
1222 #else
1223 	clConfigReader Cfg( hash );
1224 #endif
1225 	Cfg.SetSectionName( UserMenuSection );
1226 
1227 	int i = 0;
1228 
1229 	std::vector<clNCUserMenuItem> Items;
1230 
1231 	while ( true )
1232 	{
1233 		std::string Description = Cfg.Read( "Description%i", i );
1234 		std::string Execute = Cfg.Read( "Execute%i", i );
1235 
1236 		if ( Description.empty() ) { break; }
1237 
1238 		clNCUserMenuItem A;
1239 		A.SetDescription( utf8str_to_unicode( Description ) );
1240 		A.SetCommand( utf8str_to_unicode( Execute ) );
1241 		Items.push_back( A );
1242 
1243 		i++;
1244 	}
1245 
1246 	g_Env.SetUserMenuItems( Items );
1247 }
1248 
SaveFileHighlightingRules(NCWin * nc,IniHash & hash)1249 void SaveFileHighlightingRules( NCWin* nc
1250 #ifndef _WIN32
1251                                 , IniHash& hash
1252 #endif
1253                               )
1254 {
1255 	if ( !nc ) { return; }
1256 
1257 #if defined(_WIN32)
1258 	clConfigWriter Cfg;
1259 #else
1260 	clConfigWriter Cfg( hash );
1261 #endif
1262 	Cfg.SetSectionName( HighlightingRulesSection );
1263 
1264 	const std::vector<clNCFileHighlightingRule>& Rules = g_Env.GetFileHighlightingRules();
1265 
1266 	for ( size_t i = 0; i < Rules.size(); i++ )
1267 	{
1268 		const clNCFileHighlightingRule& A = Rules[i];
1269 
1270 		std::string Mask_utf8 = unicode_to_utf8_string( A.GetMask().data() );
1271 		std::string Description_utf8 = unicode_to_utf8_string( A.GetDescription().data() );
1272 
1273 		char Buf[0xFFFF];
1274 		Lsnprintf( Buf, sizeof( Buf ) - 1, "Min = %" PRIu64 " Max = %" PRIu64 " Attribs = %" PRIu64, A.GetSizeMin(), A.GetSizeMax(), A.GetAttributesMask() );
1275 
1276 		Cfg.Write( "Mask%i", i, Mask_utf8 );
1277 		Cfg.Write( "Description%i", i, Description_utf8 );
1278 		Cfg.Write( "SizeAttribs%i", i, Buf );
1279 		Cfg.WriteInt( "ColorNormal%i", i, A.GetColorNormal() );
1280 		Cfg.WriteInt( "ColorNormalBackground%i", i, A.GetColorNormalBackground() );
1281 		Cfg.WriteInt( "ColorSelected%i", i, A.GetColorSelected() );
1282 		Cfg.WriteInt( "ColorSelectedBackground%i", i, A.GetColorSelectedBackground() );
1283 		Cfg.WriteInt( "ColorUnderCursorNormal%i", i, A.GetColorUnderCursorNormal() );
1284 		Cfg.WriteInt( "ColorUnderCursorNormalBackground%i", i, A.GetColorUnderCursorNormalBackground() );
1285 		Cfg.WriteInt( "ColorUnderCursorSelected%i", i, A.GetColorUnderCursorSelected() );
1286 		Cfg.WriteInt( "ColorUnderCursorSelectedBackground%i", i, A.GetColorUnderCursorSelectedBackground() );
1287 		Cfg.WriteBool( "MaskEnabled%i", i, A.IsMaskEnabled() );
1288 	}
1289 
1290 	// end marker
1291 	Cfg.Write( "Mask%i", Rules.size(), "" );
1292 }
1293 
LoadFileHighlightingRules(NCWin * nc,IniHash & hash)1294 void LoadFileHighlightingRules( NCWin* nc
1295 #ifndef _WIN32
1296                                 , IniHash& hash
1297 #endif
1298                               )
1299 {
1300 	if ( !nc ) { return; }
1301 
1302 #if defined(_WIN32)
1303 	clConfigReader Cfg;
1304 #else
1305 	clConfigReader Cfg( hash );
1306 #endif
1307 	Cfg.SetSectionName( HighlightingRulesSection );
1308 
1309 	int i = 0;
1310 
1311 	std::vector<clNCFileHighlightingRule> Rules;
1312 
1313 	while ( true )
1314 	{
1315 		std::string Mask = Cfg.Read( "Mask%i", i );
1316 		std::string Description = Cfg.Read( "Description%i", i );
1317 
1318 		std::string Line = Cfg.Read( "SizeAttribs%i", i );
1319 
1320 		uint64_t SizeMin, SizeMax, AttribsMask;
1321 
1322 		int NumRead = 0;
1323 
1324 		if ( !Line.empty() )
1325 		{
1326 			NumRead = Lsscanf( Line.c_str(), "Min = %" PRIu64 " Max = %" PRIu64 " Attribs = %" PRIu64, &SizeMin, &SizeMax, &AttribsMask );
1327 		}
1328 
1329 		if ( NumRead != 3 )
1330 		{
1331 			SizeMin = 0;
1332 			SizeMax = 0;
1333 			AttribsMask = 0;
1334 		}
1335 
1336 		if ( !Mask.data() || !*Mask.data() ) { break; }
1337 
1338 		clNCFileHighlightingRule R;
1339 		R.SetMask( utf8str_to_unicode( Mask ) );
1340 		R.SetDescription( utf8str_to_unicode( Description ) );
1341 		R.SetSizeMin( SizeMin );
1342 		R.SetSizeMax( SizeMax );
1343 		R.SetAttributesMask( AttribsMask );
1344 		R.SetColorNormal( Cfg.ReadInt( "ColorNormal%i", i, R.GetColorNormal() ) );
1345 		R.SetColorNormalBackground( Cfg.ReadInt( "ColorNormalBackground%i", i, R.GetColorNormalBackground() ) );
1346 		R.SetColorSelected( Cfg.ReadInt( "ColorSelected%i", i, R.GetColorSelected() ) );
1347 		R.SetColorSelectedBackground( Cfg.ReadInt( "ColorSelectedBackground%i", i, R.GetColorSelectedBackground() ) );
1348 		R.SetColorUnderCursorNormal( Cfg.ReadInt( "ColorUnderCursorNormal%i", i, R.GetColorUnderCursorNormal() ) );
1349 		R.SetColorUnderCursorNormalBackground( Cfg.ReadInt( "ColorUnderCursorNormalBackground%i", i, R.GetColorUnderCursorNormalBackground( ) ) );
1350 		R.SetColorUnderCursorSelected( Cfg.ReadInt( "ColorUnderCursorSelected%i", i, R.GetColorUnderCursorSelected() ) );
1351 		R.SetColorUnderCursorSelectedBackground( Cfg.ReadInt( "ColorUnderCursorSelectedBackground%i", i, R.GetColorUnderCursorSelectedBackground() ) );
1352 
1353 		Rules.push_back( R );
1354 
1355 		i++;
1356 	}
1357 
1358 	g_Env.SetFileHighlightingRules( Rules );
1359 }
1360 
SaveCommandsHistory(NCWin * nc,IniHash & hash)1361 void SaveCommandsHistory( NCWin* nc
1362 #ifndef _WIN32
1363                           , IniHash& hash
1364 #endif
1365                         )
1366 {
1367 	if ( !nc ) { return; }
1368 
1369 #if defined(_WIN32)
1370 	clConfigWriter Cfg;
1371 #else
1372 	clConfigWriter Cfg( hash );
1373 #endif
1374 	Cfg.SetSectionName( CommandsHistorySection );
1375 
1376 	int Count = nc->GetHistory()->Count();
1377 
1378 	for ( int i = 0; i < Count; i++ )
1379 	{
1380 		const unicode_t* Hist = ( *nc->GetHistory() )[Count - i - 1];
1381 
1382 		Cfg.Write( "Command%i", i, unicode_to_utf8_string( Hist ) );
1383 	}
1384 }
1385 
LoadCommandsHistory(NCWin * nc,IniHash & hash)1386 void LoadCommandsHistory( NCWin* nc
1387 #ifndef _WIN32
1388                           , IniHash& hash
1389 #endif
1390                         )
1391 {
1392 	if ( !nc ) { return; }
1393 
1394 #if defined(_WIN32)
1395 	clConfigReader Cfg;
1396 #else
1397 	clConfigReader Cfg( hash );
1398 #endif
1399 	Cfg.SetSectionName( CommandsHistorySection );
1400 
1401 	nc->GetHistory()->Clear();
1402 
1403 	int i = 0;
1404 
1405 	while ( true )
1406 	{
1407 		std::string Cmd = Cfg.Read( "Command%i", i );
1408 
1409 		if ( Cmd.empty() ) { break; }
1410 
1411 		nc->GetHistory()->Put( utf8str_to_unicode( Cmd ).data() );
1412 
1413 		i++;
1414 	}
1415 }
1416 
FileExists(const char * name)1417 bool FileExists( const char* name )
1418 {
1419 	struct stat sb;
1420 
1421 	if ( stat( name, &sb ) ) { return false; }
1422 
1423 	return true;
1424 }
1425 
Load(NCWin * nc,const std::string & StartupDir)1426 void clWcmConfig::Load( NCWin* nc, const std::string& StartupDir )
1427 {
1428 #ifdef _WIN32
1429 
1430 	for ( size_t i = 0; i < m_MapList.size(); i++ )
1431 	{
1432 		sNode& Node = m_MapList[i];
1433 
1434 		if ( Node.m_Type == MT_BOOL && Node.m_Current.m_Bool != 0 )
1435 		{
1436 			*Node.m_Current.m_Bool = RegReadInt( Node.m_Section, Node.m_Name, Node.GetDefaultBool() ) != 0;
1437 		}
1438 		else if ( Node.m_Type == MT_INT && Node.m_Current.m_Int != 0 )
1439 		{
1440 			*Node.m_Current.m_Int = RegReadInt( Node.m_Section, Node.m_Name, Node.GetDefaultInt() );
1441 		}
1442 		else if ( Node.m_Type == MT_STR && Node.m_Current.m_Str != 0 )
1443 		{
1444 			*Node.m_Current.m_Str = RegReadString( Node.m_Section, Node.m_Name, Node.GetDefaultStr() );
1445 		}
1446 	}
1447 
1448 
1449 	LoadCommandsHistory( nc );
1450 	LoadFileAssociations( nc );
1451 	LoadFileHighlightingRules( nc );
1452 	LoadUserMenu( nc );
1453 
1454 #else
1455 	IniHash hash;
1456 	FSPath path = configDirPath;
1457 	path.Push( CS_UTF8, "config" );
1458 
1459 	LoadIniHash( hash, DEFAULT_CONFIG_PATH );
1460 	LoadIniHash( hash, ( sys_char_t* )path.GetString( sys_charset_id ) );
1461 
1462 	for ( size_t i = 0; i < m_MapList.size(); i++ )
1463 	{
1464 		sNode& Node = m_MapList[i];
1465 
1466 		if ( Node.m_Type == MT_BOOL && Node.m_Current.m_Bool != 0 )
1467 		{
1468 			*Node.m_Current.m_Bool = hash.GetBoolValue( Node.m_Section, Node.m_Name, Node.GetDefaultBool() );
1469 		}
1470 		else if ( Node.m_Type == MT_INT && Node.m_Current.m_Int != 0 )
1471 		{
1472 			*Node.m_Current.m_Int = hash.GetIntValue( Node.m_Section, Node.m_Name, Node.GetDefaultInt() );
1473 		}
1474 		else if ( Node.m_Type == MT_STR && Node.m_Current.m_Str != 0 )
1475 		{
1476 			const char* s = hash.GetStrValue( Node.m_Section, Node.m_Name, Node.GetDefaultStr() );
1477 
1478 			if ( s )
1479 			{
1480 				*Node.m_Current.m_Str = s;
1481 			}
1482 			else
1483 			{
1484 				( *Node.m_Current.m_Str ).clear();
1485 			}
1486 		}
1487 
1488 	}
1489 
1490 	LoadCommandsHistory( nc, hash );
1491 	LoadFileAssociations( nc, hash );
1492 	LoadFileHighlightingRules( nc, hash );
1493 	LoadUserMenu( nc, hash );
1494 
1495 #endif
1496 
1497 	if ( editTabSize <= 0 || editTabSize > 64 ) { editTabSize = 3; }
1498 
1499 	LoadFoldersHistory();
1500 	LoadViewHistory();
1501 	LoadFieldsHistory();
1502 }
1503 
Save(NCWin * nc)1504 void clWcmConfig::Save( NCWin* nc )
1505 {
1506 	if ( nc )
1507 	{
1508 		// do not save locations on non-persistent FS
1509 		leftPanelPath = nc->GetLeftPanel()->GetLastPersistentPath();
1510 		rightPanelPath = nc->GetRightPanel()->GetLastPersistentPath();
1511 
1512 		crect Rect = nc->ScreenRect();
1513 		windowX = Rect.top;
1514 		windowY = Rect.left;
1515 		windowWidth = Rect.Width();
1516 		windowHeight = Rect.Height();
1517 	}
1518 
1519 #ifdef _WIN32
1520 
1521 	for ( size_t i = 0; i < m_MapList.size( ); i++ )
1522 	{
1523 		sNode& Node = m_MapList[i];
1524 
1525 		if ( Node.m_Type == MT_BOOL && Node.m_Current.m_Bool != 0 )
1526 		{
1527 			RegWriteInt( Node.m_Section, Node.m_Name, *Node.m_Current.m_Bool );
1528 		}
1529 		else if ( Node.m_Type == MT_INT && Node.m_Current.m_Int != 0 )
1530 		{
1531 			RegWriteInt( Node.m_Section, Node.m_Name, *Node.m_Current.m_Int );
1532 		}
1533 		else if ( Node.m_Type == MT_STR && Node.m_Current.m_Str != 0 )
1534 		{
1535 			RegWriteString( Node.m_Section, Node.m_Name, Node.m_Current.m_Str->data() );
1536 		}
1537 	}
1538 
1539 	SaveCommandsHistory( nc );
1540 	SaveFileAssociations( nc );
1541 	SaveFileHighlightingRules( nc );
1542 	SaveUserMenu( nc );
1543 
1544 #else
1545 	IniHash hash;
1546 	FSPath path = configDirPath;
1547 	path.Push( CS_UTF8, "config" );
1548 
1549 	LoadIniHash( hash, ( sys_char_t* )path.GetString( sys_charset_id ) );
1550 
1551 	for ( size_t i = 0; i < m_MapList.size(); i++ )
1552 	{
1553 		sNode& Node = m_MapList[i];
1554 
1555 		if ( Node.m_Type == MT_BOOL && Node.m_Current.m_Bool != 0 )
1556 		{
1557 			hash.SetBoolValue( Node.m_Section, Node.m_Name, *Node.m_Current.m_Bool );
1558 		}
1559 		else if ( Node.m_Type == MT_INT && Node.m_Current.m_Int != 0 )
1560 		{
1561 			hash.SetIntValue( Node.m_Section, Node.m_Name, *Node.m_Current.m_Int );
1562 		}
1563 		else if ( Node.m_Type == MT_STR && Node.m_Current.m_Str != 0 )
1564 		{
1565 			hash.SetStrValue( Node.m_Section, Node.m_Name, Node.m_Current.m_Str->data() );
1566 		}
1567 	}
1568 
1569 	SaveCommandsHistory( nc, hash );
1570 	SaveFileAssociations( nc, hash );
1571 	SaveFileHighlightingRules( nc, hash );
1572 	SaveUserMenu( nc, hash );
1573 
1574 	SaveIniHash( hash,( sys_char_t* ) path.GetString( sys_charset_id ) );
1575 #endif
1576 
1577 	SaveFoldersHistory();
1578 	SaveViewHistory();
1579 	SaveFieldsHistory();
1580 }
1581 
1582 
InitConfigPath()1583 void InitConfigPath()
1584 {
1585 #if !defined( _WIN32 )
1586 
1587 	const sys_char_t* home = ( sys_char_t* ) getenv( "HOME" );
1588 
1589 	if ( home )
1590 	{
1591 		FSPath path( sys_charset_id, home );
1592 		path.Push( CS_UTF8, ".wcm" );
1593 		FSSys fs;
1594 		FSStat st;
1595 		int err;
1596 
1597 		if ( fs.Stat( path, &st, &err, 0 ) )
1598 		{
1599 			if ( fs.IsENOENT( err ) ) //директорий не существует
1600 			{
1601 				if ( fs.MkDir( path, 0700, &err,  0 ) )
1602 				{
1603 					fprintf( stderr, "can`t create config directory %s (%s)", path.GetUtf8(), fs.StrError( err ).GetUtf8() );
1604 					return;
1605 				}
1606 
1607 			}
1608 			else
1609 			{
1610 				fprintf( stderr, "can`t create config directory statuc %s (%s)", path.GetUtf8(), fs.StrError( err ).GetUtf8() );
1611 				return;
1612 			}
1613 		}
1614 		else if ( !st.IsDir() )
1615 		{
1616 			fprintf( stderr, "err: '%s' is not directory", path.GetUtf8() );
1617 			return;
1618 		}
1619 
1620 		configDirPath = path;
1621 	}
1622 	else
1623 	{
1624 		fprintf( stderr, "err: HOME env value not found" );
1625 	}
1626 
1627 #endif
1628 }
1629 
1630 
1631 
1632 ////////////////////////////////  PanelOptDlg
1633 
1634 class PanelOptDialog: public NCVertDialog
1635 {
1636 	Layout iL;
1637 public:
1638 	SButton  showHiddenButton;
1639 	SButton  caseSensitive;
1640 	SButton  selectFolders;
1641 	SButton  showDotsInRoot;
1642 	SButton  showFolderIcons;
1643 	SButton  showExecutableIcons;
1644 	SButton  showLinkIcons;
1645 	SButton  showScrollbar;
1646 
1647 	StaticLine showSpacesStatic;
1648 	SButton  showSpacesNoneButton;
1649 	SButton  showSpacesAllButton;
1650 	SButton  showSpacesTrailingButton;
1651 
1652 	PanelOptDialog( NCDialogParent* parent );
1653 	virtual ~PanelOptDialog();
1654 };
1655 
~PanelOptDialog()1656 PanelOptDialog::~PanelOptDialog() {}
1657 
PanelOptDialog(NCDialogParent * parent)1658 PanelOptDialog::PanelOptDialog( NCDialogParent* parent )
1659 	:  NCVertDialog( ::createDialogAsChild, 0, parent, utf8_to_unicode( _LT( "Panel settings" ) ).data(), bListOkCancel )
1660 	, iL( 16, 3 )
1661 	, showHiddenButton( 0, this, utf8_to_unicode( _LT( "Show &hidden files" ) ).data(), 0, g_WcmConfig.panelShowHiddenFiles )
1662 	, caseSensitive( 0, this, utf8_to_unicode( _LT( "C&ase sensitive sort" ) ).data(), 0, g_WcmConfig.panelCaseSensitive )
1663 	, selectFolders( 0, this, utf8_to_unicode( _LT( "Select &folders" ) ).data(), 0, g_WcmConfig.panelSelectFolders )
1664 	, showDotsInRoot( 0, this, utf8_to_unicode( _LT( "Show .. in the &root folder" ) ).data(), 0, g_WcmConfig.panelShowDotsInRoot )
1665 	, showFolderIcons( 0, this, utf8_to_unicode( _LT( "Show folder &icons" ) ).data(), 0, g_WcmConfig.panelShowFolderIcons )
1666 	, showExecutableIcons( 0, this, utf8_to_unicode( _LT( "Show &executable icons" ) ).data(), 0, g_WcmConfig.panelShowExecutableIcons )
1667 	, showLinkIcons( 0, this, utf8_to_unicode( _LT( "Show &link icons" ) ).data(), 0, g_WcmConfig.panelShowLinkIcons )
1668 	, showScrollbar( 0, this, utf8_to_unicode( _LT( "Show &scrollbar" ) ).data(), 0, g_WcmConfig.panelShowScrollbar )
1669 	, showSpacesStatic( 0, this, utf8_to_unicode( _LT( "Show spaces as · in names:" ) ).data() )
1670 	, showSpacesNoneButton( 0, this, utf8_to_unicode( _LT( "No" ) ).data(), 1, g_WcmConfig.panelShowSpacesMode != 1 && g_WcmConfig.panelShowSpacesMode != 2 )
1671 	, showSpacesAllButton( 0, this,  utf8_to_unicode( _LT( "All" ) ).data(), 1, g_WcmConfig.panelShowSpacesMode == 1 )
1672 	, showSpacesTrailingButton( 0, this, utf8_to_unicode( _LT( "Trailing only" ) ).data(), 1, g_WcmConfig.panelShowSpacesMode == 2 )
1673 {
1674 	iL.AddWinAndEnable( &showHiddenButton,  0, 0 );
1675 	showHiddenButton.SetFocus();
1676 	iL.AddWinAndEnable( &caseSensitive,  1, 0 );
1677 	iL.AddWinAndEnable( &selectFolders,  2, 0 );
1678 	iL.AddWinAndEnable( &showDotsInRoot, 3, 0 );
1679 	iL.AddWinAndEnable( &showFolderIcons, 4, 0 );
1680 	iL.AddWinAndEnable( &showExecutableIcons, 5, 0 );
1681 	iL.AddWinAndEnable( &showLinkIcons, 6, 0 );
1682 	iL.AddWinAndEnable( &showScrollbar, 7, 0 );
1683 	iL.AddWinAndEnable( &showSpacesStatic, 8, 0 );
1684 	iL.AddWinAndEnable( &showSpacesNoneButton, 9, 0 );
1685 	iL.AddWinAndEnable( &showSpacesAllButton, 10, 0 );
1686 	iL.AddWinAndEnable( &showSpacesTrailingButton, 11, 0 );
1687 
1688 	AddLayout( &iL );
1689 	SetEnterCmd( CMD_OK );
1690 
1691 	showHiddenButton.SetFocus();
1692 
1693 	order.append( &showHiddenButton );
1694 	order.append( &caseSensitive );
1695 	order.append( &selectFolders );
1696 	order.append( &showDotsInRoot );
1697 	order.append( &showFolderIcons );
1698 	order.append( &showExecutableIcons );
1699 	order.append( &showLinkIcons );
1700 	order.append( &showScrollbar );
1701 	order.append( &showSpacesNoneButton );
1702 	order.append( &showSpacesAllButton );
1703 	order.append( &showSpacesTrailingButton );
1704 	SetPosition();
1705 }
1706 
DoPanelConfigDialog(NCDialogParent * parent)1707 bool DoPanelConfigDialog( NCDialogParent* parent )
1708 {
1709 	PanelOptDialog dlg( parent );
1710 
1711 	if ( dlg.DoModal() == CMD_OK )
1712 	{
1713 		g_WcmConfig.panelShowHiddenFiles = dlg.showHiddenButton.IsSet();
1714 		g_WcmConfig.panelCaseSensitive = dlg.caseSensitive.IsSet();
1715 		g_WcmConfig.panelSelectFolders = dlg.selectFolders.IsSet();
1716 		g_WcmConfig.panelShowDotsInRoot = dlg.showDotsInRoot.IsSet();
1717 		g_WcmConfig.panelShowFolderIcons  = dlg.showFolderIcons.IsSet();
1718 		g_WcmConfig.panelShowExecutableIcons  = dlg.showExecutableIcons.IsSet();
1719 		g_WcmConfig.panelShowLinkIcons  = dlg.showLinkIcons.IsSet();
1720 		g_WcmConfig.panelShowScrollbar = dlg.showScrollbar.IsSet();
1721 
1722 		if ( dlg.showSpacesTrailingButton.IsSet() )
1723 		{
1724 			g_WcmConfig.panelShowSpacesMode = ePanelSpacesMode_Trailing;
1725 		}
1726 		else if ( dlg.showSpacesAllButton.IsSet() )
1727 		{
1728 			g_WcmConfig.panelShowSpacesMode = ePanelSpacesMode_All;
1729 		}
1730 		else
1731 		{
1732 			g_WcmConfig.panelShowSpacesMode = ePanelSpacesMode_None;
1733 		}
1734 
1735 		return true;
1736 	}
1737 
1738 	return false;
1739 }
1740 
1741 
1742 ////////////////////////////////  EditOptDlg
1743 
1744 
1745 class EditOptDialog: public NCVertDialog
1746 {
1747 	Layout iL;
1748 public:
1749 	SButton  saveFilePosButton;
1750 	SButton  autoIdentButton;
1751 	SButton  shlButton;
1752 	SButton  clearHistoryButton;
1753 
1754 	StaticLabel tabText;
1755 	EditLine tabEdit;
1756 
1757 	EditOptDialog( NCDialogParent* parent );
1758 //	virtual bool EventChildKey(Win* child, cevent_key* pEvent);
1759 //	virtual bool Command(int id, int subId, Win *win, void *data);
1760 	virtual ~EditOptDialog();
1761 };
1762 
~EditOptDialog()1763 EditOptDialog::~EditOptDialog() {}
1764 
EditOptDialog(NCDialogParent * parent)1765 EditOptDialog::EditOptDialog( NCDialogParent* parent )
1766 	:  NCVertDialog( ::createDialogAsChild, 0, parent, utf8_to_unicode( _LT( "Editor" ) ).data(), bListOkCancel ),
1767 	   iL( 16, 2 ),
1768 
1769 	   saveFilePosButton( 0, this, utf8_to_unicode( _LT( "Save file &position" ) ).data(), 0, g_WcmConfig.editSavePos ),
1770 	   autoIdentButton( 0, this, utf8_to_unicode( _LT( "Auto &indent" ) ).data(), 0, g_WcmConfig.editAutoIdent ),
1771 	   shlButton( 0, this, utf8_to_unicode( _LT( "Syntax &highlighting" ) ).data(), 0, g_WcmConfig.editShl ),
1772 	   clearHistoryButton( 0, this, utf8_to_unicode( _LT( "&Clear history after saving" ) ).data(), 0, g_WcmConfig.editClearHistoryAfterSaving ),
1773 	   tabText( 0, this, utf8_to_unicode( _LT( "&Tab size:" ) ).data(), &tabEdit ),
1774 	   tabEdit( 0, this, 0, 0, 16 )
1775 {
1776 	char buf[0x100];
1777 	Lsnprintf( buf, sizeof( buf ) - 1, "%i", g_WcmConfig.editTabSize );
1778 	tabEdit.SetText( utf8_to_unicode( buf ).data(), true );
1779 
1780 	iL.AddWinAndEnable( &saveFilePosButton,  0, 0, 0, 1 );
1781 	iL.AddWinAndEnable( &autoIdentButton,    1, 0, 1, 1 );
1782 	iL.AddWinAndEnable( &shlButton,          2, 0, 2, 1 );
1783 	iL.AddWinAndEnable( &clearHistoryButton, 3, 0, 3, 1 );
1784 	iL.AddWinAndEnable( &tabText,            4, 0, 4, 0 );
1785 	iL.AddWinAndEnable( &tabEdit,            4, 1, 5, 1 );
1786 	AddLayout( &iL );
1787 	SetEnterCmd( CMD_OK );
1788 
1789 	saveFilePosButton.SetFocus();
1790 
1791 	order.append( &saveFilePosButton );
1792 	order.append( &autoIdentButton );
1793 	order.append( &shlButton );
1794 	order.append( &clearHistoryButton );
1795 	order.append( &tabEdit );
1796 	SetPosition();
1797 }
1798 
DoEditConfigDialog(NCDialogParent * parent)1799 bool DoEditConfigDialog( NCDialogParent* parent )
1800 {
1801 	EditOptDialog dlg( parent );
1802 
1803 	if ( dlg.DoModal() == CMD_OK )
1804 	{
1805 		g_WcmConfig.editSavePos = dlg.saveFilePosButton.IsSet();
1806 		g_WcmConfig.editAutoIdent = dlg.autoIdentButton.IsSet();
1807 		g_WcmConfig.editShl = dlg.shlButton.IsSet();
1808 		g_WcmConfig.editClearHistoryAfterSaving = dlg.clearHistoryButton.IsSet();
1809 
1810 		int tabSize = atoi( unicode_to_utf8( dlg.tabEdit.GetText().data() ).data() );
1811 
1812 		if ( tabSize > 0 && tabSize <= 64 )
1813 		{
1814 			g_WcmConfig.editTabSize = tabSize;
1815 		}
1816 
1817 		return true;
1818 	}
1819 
1820 	return false;
1821 }
1822 
1823 
1824 
1825 ////////////////////////// StyleOptDialog
1826 
1827 class StyleOptDialog: public NCVertDialog
1828 {
1829 	void RefreshFontInfo();
1830 	Layout iL;
1831 public:
1832 	struct Node
1833 	{
1834 		std::string name;
1835 		cfont* oldFont;
1836 		std::string* pUri;
1837 		clPtr<cfont> newFont;
1838 		bool fixed;
NodeStyleOptDialog::Node1839 		Node(): oldFont( 0 ) {}
NodeStyleOptDialog::Node1840 		Node( const char* n, bool fix,  cfont* old, std::string* uri )
1841 			: name( n )
1842 			, oldFont( old )
1843 			, pUri( uri )
1844 			, fixed( fix )
1845 		{}
1846 	};
1847 
1848 	ccollect<Node>* pList;
1849 
1850 	SButton  styleShow3DUIButton;
1851 	StaticLine colorStatic;
1852 	ComboBox styleList;
1853 
1854 
1855 	StaticLine showStatic;
1856 	SButton  showToolbarButton;
1857 	SButton  showButtonbarButton;
1858 	SButton  showButtonbarIconsButton;
1859 	SButton  showMenubarButton;
1860 
1861 	StaticLine fontsStatic;
1862 	TextList fontList;
1863 	StaticLine fontNameStatic;
1864 	Button changeButton;
1865 	Button changeX11Button;
1866 
1867 
1868 	StyleOptDialog( NCDialogParent* parent, ccollect<Node>* p );
1869 	virtual bool EventChildKey( Win* child, cevent_key* pEvent );
1870 	virtual bool Command( int id, int subId, Win* win, void* data );
1871 	virtual ~StyleOptDialog();
1872 };
1873 
~StyleOptDialog()1874 StyleOptDialog::~StyleOptDialog() {}
1875 
RefreshFontInfo()1876 void StyleOptDialog::RefreshFontInfo()
1877 {
1878 	int count = pList->count();
1879 	int cur = fontList.GetCurrent();
1880 
1881 	const char* s = "";
1882 
1883 	if ( count >= 0 && cur >= 0 && cur < count )
1884 	{
1885 		int n = fontList.GetCurrentInt();
1886 
1887 		if ( pList->get( n ).newFont.ptr() )
1888 		{
1889 			s = pList->get( n ).newFont->printable_name();
1890 		}
1891 		else if ( pList->get( n ).oldFont )
1892 		{
1893 			s = pList->get( n ).oldFont->printable_name();
1894 		}
1895 	}
1896 
1897 	fontNameStatic.SetText( utf8_to_unicode( s ).data() );
1898 }
1899 
1900 #define CMD_CHFONT 1000
1901 #define CMD_CHFONTX11 1001
1902 
StyleOptDialog(NCDialogParent * parent,ccollect<Node> * p)1903 StyleOptDialog::StyleOptDialog( NCDialogParent* parent, ccollect<Node>* p )
1904 	:  NCVertDialog( ::createDialogAsChild, 0, parent, utf8_to_unicode( _LT( "Style" ) ).data(), bListOkCancel ),
1905 	   iL( 16, 3 ),
1906 	   pList( p ),
1907 	   styleShow3DUIButton( 0, this, utf8_to_unicode( _LT( "&3D buttons" ) ).data(), 0, g_WcmConfig.styleShow3DUI ),
1908 	   colorStatic( 0, this, utf8_to_unicode( _LT( "Colors:" ) ).data() ),
1909 	   styleList( 0, this, 1, 5, ComboBox::READONLY ),
1910 
1911 	   showStatic( 0, this, utf8_to_unicode( _LT( "Items:" ) ).data() ),
1912 	   showToolbarButton( 0, this, utf8_to_unicode( _LT( "Show &toolbar" ) ).data(), 0, g_WcmConfig.styleShowToolBar ),
1913 	   showButtonbarButton( 0, this, utf8_to_unicode( _LT( "Show b&uttonbar" ) ).data(), 0, g_WcmConfig.styleShowButtonBar ),
1914 	   showButtonbarIconsButton( 0, this, utf8_to_unicode( _LT( "Show buttonbar &icons" ) ).data(), 0, g_WcmConfig.styleShowButtonBarIcons ),
1915 	   showMenubarButton( 0, this, utf8_to_unicode( _LT( "Show &menubar" ) ).data(), 0, g_WcmConfig.styleShowMenuBar ),
1916 
1917 	   fontsStatic( 0, this, utf8_to_unicode( _LT( "Fonts:" ) ).data() ),
1918 	   fontList( Win::WT_CHILD, WH_TABFOCUS | WH_CLICKFOCUS, 0, this, VListWin::SINGLE_SELECT, VListWin::BORDER_3D, 0 ),
1919 	   fontNameStatic( 0, this, utf8_to_unicode( "--------------------------------------------------" ).data() ),
1920 	   changeButton( 0, this, utf8_to_unicode( _LT( "Set &font..." ) ).data(), CMD_CHFONT ),
1921 	   changeX11Button( 0, this, utf8_to_unicode( _LT( "Set &X11 font..." ) ).data(), CMD_CHFONTX11 )
1922 {
1923 	iL.AddWinAndEnable( &styleShow3DUIButton, 0, 1 );
1924 	iL.AddWinAndEnable( &colorStatic, 1, 0 );
1925 
1926 	iL.AddWinAndEnable( &styleList, 2, 1 );
1927 
1928 	iL.AddWinAndEnable( &showStatic,  5, 0 );
1929 	iL.AddWinAndEnable( &showToolbarButton, 6, 1 );
1930 	iL.AddWinAndEnable( &showButtonbarButton,  7, 1 );
1931 	iL.AddWinAndEnable( &showButtonbarIconsButton,  8, 1 );
1932 	iL.AddWinAndEnable( &showMenubarButton,  9, 1 );
1933 	iL.LineSet( 10, 10 );
1934 	iL.AddWinAndEnable( &fontsStatic, 11, 0 );
1935 	iL.ColSet( 0, 12, 12, 12 );
1936 	iL.SetColGrowth( 1 );
1937 
1938 	for ( int i = 0; i < pList->count(); i++ )
1939 	{
1940 		fontList.Append( utf8_to_unicode( pList->get( i ).name.data() ).data(), i );
1941 	}
1942 
1943 	fontList.MoveCurrent( 0 );
1944 	RefreshFontInfo();
1945 
1946 	LSize lsize = fontList.GetLSize();
1947 	lsize.y.minimal = lsize.y.ideal = 100;
1948 	lsize.y.maximal = 1000;
1949 	lsize.x.minimal = lsize.x.ideal = 300;
1950 	lsize.x.maximal = 1000;
1951 	fontList.SetLSize( lsize );
1952 
1953 	iL.AddWinAndEnable( &fontList, 11, 1 );
1954 
1955 	fontNameStatic.Enable();
1956 	fontNameStatic.Show();
1957 
1958 	lsize = fontNameStatic.GetLSize();
1959 	lsize.x.minimal = 500;
1960 	lsize.x.maximal = 1000;
1961 	fontNameStatic.SetLSize( lsize );
1962 
1963 	iL.AddWin( &fontNameStatic, 12, 1 );
1964 #ifdef USEFREETYPE
1965 	iL.AddWinAndEnable( &changeButton, 13, 1 );
1966 #endif
1967 
1968 #ifdef _WIN32
1969 	iL.AddWinAndEnable( &changeButton, 13, 1 );
1970 #else
1971 	iL.AddWinAndEnable( &changeX11Button, 14, 1 );
1972 	iL.LineSet( 13, 10 );
1973 #endif
1974 
1975 #ifdef USEFREETYPE
1976 	LSize l1 = changeButton.GetLSize();
1977 	LSize l2 = changeX11Button.GetLSize();
1978 
1979 	if ( l1.x.minimal < l2.x.minimal ) { l1.x.minimal = l2.x.minimal; }
1980 
1981 	l1.x.maximal = l1.x.minimal;
1982 	changeButton.SetLSize( l1 );
1983 	changeX11Button.SetLSize( l1 );
1984 #endif
1985 
1986 	AddLayout( &iL );
1987 	SetEnterCmd( CMD_OK );
1988 
1989 	auto styles = GetColorStyles();
1990 	for ( auto style : styles )
1991 	{
1992 		styleList.Append( style.c_str() );
1993 	}
1994 
1995 	auto it = std::find( styles.begin(), styles.end(), g_WcmConfig.styleColorTheme);
1996 	int index = it == styles.end() ? 0 : (int) std::distance(styles.begin(), it);
1997 
1998 	styleList.MoveCurrent( index );
1999 	styleList.SetFocus();
2000 
2001 	order.append( &styleShow3DUIButton );
2002 	order.append( &styleList );
2003 	order.append( &showToolbarButton );
2004 	order.append( &showButtonbarButton );
2005 	order.append( &showButtonbarIconsButton );
2006 	order.append( &showMenubarButton );
2007 	order.append( &fontList );
2008 	order.append( &changeButton );
2009 	order.append( &changeX11Button );
2010 	SetPosition();
2011 }
2012 
Command(int id,int subId,Win * win,void * data)2013 bool StyleOptDialog::Command( int id, int subId, Win* win, void* data )
2014 {
2015 
2016 	if ( win == &fontList )
2017 	{
2018 		RefreshFontInfo();
2019 		return true;
2020 	}
2021 
2022 #ifdef _WIN32
2023 
2024 	if ( id == CMD_CHFONT )
2025 	{
2026 		int count = pList->count();
2027 		int cur = fontList.GetCurrent();
2028 
2029 		if ( count <= 0 || cur < 0 || cur >= count ) { return true; }
2030 
2031 		LOGFONT lf;
2032 		std::string* pUri = pList->get( fontList.GetCurrentInt() ).pUri;
2033 		cfont::UriToLogFont( &lf, pUri && pUri->data() ?  pUri->data() : 0 );
2034 
2035 		CHOOSEFONT cf;
2036 		memset( &cf, 0, sizeof( cf ) );
2037 		cf.lStructSize = sizeof( cf );
2038 		cf.hwndOwner = GetID();
2039 		cf.lpLogFont = &lf;
2040 		cf.Flags = CF_SCREENFONTS | CF_EFFECTS | CF_INITTOLOGFONTSTRUCT ;
2041 
2042 		if ( pList->get( fontList.GetCurrentInt() ).fixed )
2043 		{
2044 			cf.Flags |= CF_FIXEDPITCHONLY;
2045 		}
2046 
2047 
2048 		if ( ChooseFont( &cf ) )
2049 		{
2050 			clPtr<cfont> p = new cfont( cfont::LogFontToUru( lf ).data() );
2051 
2052 			if ( p.ptr() )
2053 			{
2054 				pList->get( fontList.GetCurrentInt() ).newFont = p;
2055 				RefreshFontInfo();
2056 			}
2057 		}
2058 
2059 		return true;
2060 	}
2061 
2062 #else
2063 
2064 	if ( id == CMD_CHFONT )
2065 	{
2066 		int count = pList->count();
2067 		int cur = fontList.GetCurrent();
2068 
2069 		if ( count <= 0 || cur < 0 || cur >= count ) { return true; }
2070 
2071 		std::string* pUri = pList->get( fontList.GetCurrentInt() ).pUri;
2072 
2073 		clPtr<cfont> p = SelectFTFont( ( NCDialogParent* )Parent(), pList->get( fontList.GetCurrentInt() ).fixed, ( pUri && !pUri->empty() ) ? pUri->c_str() : nullptr );
2074 
2075 		if ( p.ptr() )
2076 		{
2077 			pList->get( fontList.GetCurrentInt() ).newFont = p;
2078 			RefreshFontInfo();
2079 		}
2080 
2081 		return true;
2082 	}
2083 
2084 	if ( id == CMD_CHFONTX11 )
2085 	{
2086 		int count = pList->count();
2087 		int cur = fontList.GetCurrent();
2088 
2089 		if ( count <= 0 || cur < 0 || cur >= count ) { return true; }
2090 
2091 		clPtr<cfont> p = SelectX11Font( ( NCDialogParent* )Parent(), pList->get( fontList.GetCurrentInt() ).fixed );
2092 
2093 		if ( p.ptr() )
2094 		{
2095 			pList->get( fontList.GetCurrentInt() ).newFont = p;
2096 			RefreshFontInfo();
2097 		}
2098 
2099 		return true;
2100 	}
2101 
2102 #endif
2103 
2104 	return NCVertDialog::Command( id, subId, win, data );
2105 }
2106 
EventChildKey(Win * child,cevent_key * pEvent)2107 bool StyleOptDialog::EventChildKey( Win* child, cevent_key* pEvent )
2108 {
2109 	if ( pEvent->Type() == EV_KEYDOWN )
2110 	{
2111 		bool IsReturn = ( pEvent->Key() == VK_RETURN ) && ( child == &changeButton || child == &changeX11Button );
2112 		bool IsUpDown = ( pEvent->Key() == VK_UP || pEvent->Key() == VK_DOWN ) && child == &fontList;
2113 
2114 		if ( IsReturn || IsUpDown )
2115 		{
2116 			return false;
2117 		}
2118 	};
2119 
2120 	return NCVertDialog::EventChildKey( child, pEvent );
2121 }
2122 
DoStyleConfigDialog(NCDialogParent * parent)2123 bool DoStyleConfigDialog( NCDialogParent* parent )
2124 {
2125 	g_WcmConfig.ImpCurrentFonts();
2126 	ccollect<StyleOptDialog::Node> list;
2127 	list.append( StyleOptDialog::Node(  _LT( "Panel" ) ,  false,   g_PanelFont.ptr(), &g_WcmConfig.panelFontUri ) );
2128 	list.append( StyleOptDialog::Node(  _LT( "Dialog" ),  false,   g_DialogFont.ptr(), &g_WcmConfig.dialogFontUri ) );
2129 	list.append( StyleOptDialog::Node(  _LT( "Viewer" ),  true,    g_ViewerFont.ptr(), &g_WcmConfig.viewerFontUri ) );
2130 	list.append( StyleOptDialog::Node(  _LT( "Editor" ),  true,    g_EditorFont.ptr(), &g_WcmConfig.editorFontUri ) );
2131 	list.append( StyleOptDialog::Node(  _LT( "Terminal" ),   true, g_TerminalFont.ptr(), &g_WcmConfig.terminalFontUri ) );
2132 	list.append( StyleOptDialog::Node(  _LT( "Help text" ),  false,   g_HelpTextFont.ptr(), &g_WcmConfig.helpTextFontUri ) );
2133 	list.append( StyleOptDialog::Node(  _LT( "Help bold text" ),   false,   g_HelpBoldFont.ptr(), &g_WcmConfig.helpBoldFontUri ) );
2134 	list.append( StyleOptDialog::Node(  _LT( "Help header text" ), false,   g_HelpHeadFont.ptr(), &g_WcmConfig.helpHeadFontUri ) );
2135 
2136 	StyleOptDialog dlg( parent, &list );
2137 
2138 	if ( dlg.DoModal() == CMD_OK )
2139 	{
2140 		g_WcmConfig.styleColorTheme = dlg.styleList.GetTextStr();
2141 		SetColorStyle( g_WcmConfig.styleColorTheme);
2142 
2143 		g_WcmConfig.styleShow3DUI = dlg.styleShow3DUIButton.IsSet();
2144 		g_WcmConfig.styleShowToolBar = dlg.showToolbarButton.IsSet( );
2145 		g_WcmConfig.styleShowButtonBar = dlg.showButtonbarButton.IsSet( );
2146 		g_WcmConfig.styleShowButtonBarIcons = dlg.showButtonbarIconsButton.IsSet( );
2147 		g_WcmConfig.styleShowMenuBar = dlg.showMenubarButton.IsSet( );
2148 
2149 		for ( int i = 0; i < list.count(); i++ )
2150 		{
2151 			if ( list[i].newFont.ptr() && list[i].newFont->uri()[0] && list[i].pUri )
2152 			{
2153 				*( list[i].pUri ) = list[i].newFont->uri();
2154 			}
2155 		}
2156 
2157 		if ( parent ) { parent->Command( CMD_MENU_INFO, SCMD_MENU_CANCEL, nullptr, nullptr ); }
2158 
2159 		return true;
2160 	}
2161 
2162 	return false;
2163 }
2164 
2165 struct LangListNode
2166 {
2167 	std::string id;
2168 	std::string name;
LangListNodeLangListNode2169 	LangListNode() {}
LangListNodeLangListNode2170 	LangListNode( const char* i, const char* n ): id( i ), name( n ) {}
2171 };
2172 
2173 class CfgLangDialog: public NCDialog
2174 {
2175 	TextList _list;
2176 	ccollect<LangListNode>* nodeList;
2177 public:
CfgLangDialog(NCDialogParent * parent,const char * id,ccollect<LangListNode> * nl)2178 	CfgLangDialog( NCDialogParent* parent, const char* id, ccollect<LangListNode>* nl )
2179 		:  NCDialog( createDialogAsChild, 0, parent, utf8_to_unicode( _LT( "Language" ) ).data(), bListOkCancel ),
2180 		   _list( Win::WT_CHILD, Win::WH_TABFOCUS | WH_CLICKFOCUS, 0, this, VListWin::SINGLE_SELECT, VListWin::BORDER_3D, 0 ),
2181 		   nodeList( nl )
2182 
2183 	{
2184 		_list.Append( utf8_to_unicode( _LT( "Autodetect" ) ).data() ); //0
2185 		_list.Append( utf8_to_unicode( _LT( "English" ) ).data() ); //1
2186 
2187 		for ( int i = 0; i < nl->count(); i++ )
2188 		{
2189 			_list.Append( utf8_to_unicode( nl->get( i ).name.data() ).data() );
2190 		}
2191 
2192 		int cur = 0;
2193 
2194 		if ( id[0] == '+' ) { cur = 0; }
2195 		else if ( id[0] == '-' ) { cur = 1; }
2196 		else
2197 		{
2198 			for ( int i = 0; i < nl->count(); i++ )
2199 				if ( !strcmp( id, nl->get( i ).id.data() ) )
2200 				{
2201 					cur = i + 2;
2202 					break;
2203 				}
2204 		}
2205 
2206 		_list.MoveCurrent( cur );
2207 
2208 		_list.Enable();
2209 		_list.Show();
2210 		_list.SetFocus();
2211 		LSRange h( 10, 1000, 10 );
2212 		LSRange w( 50, 1000, 30 );
2213 		_list.SetHeightRange( h ); //in characters
2214 		_list.SetWidthRange( w ); //in characters
2215 
2216 		AddWin( &_list );
2217 		SetEnterCmd( CMD_OK );
2218 		SetPosition();
2219 	};
2220 
2221 	const char* GetId();
2222 
2223 	virtual bool Command( int id, int subId, Win* win, void* data );
2224 
2225 	virtual ~CfgLangDialog();
2226 };
2227 
GetId()2228 const char* CfgLangDialog::GetId()
2229 {
2230 	int n = _list.GetCurrent();
2231 
2232 	if ( n <= 0 ) { return "+"; }
2233 
2234 	if ( n == 1 ) { return "-"; }
2235 
2236 	n -= 2;
2237 
2238 	if ( n >= nodeList->count() ) { return "+"; }
2239 
2240 	return nodeList->get( n ).id.data();
2241 }
2242 
Command(int id,int subId,Win * win,void * data)2243 bool CfgLangDialog::Command( int id, int subId, Win* win, void* data )
2244 {
2245 	if ( id == CMD_ITEM_CLICK && win == &_list )
2246 	{
2247 		EndModal( CMD_OK );
2248 	}
2249 
2250 	return NCDialog::Command( id, subId, win, data );
2251 }
2252 
~CfgLangDialog()2253 CfgLangDialog::~CfgLangDialog() {}
2254 
2255 
IsSpace(char c)2256 inline bool IsSpace( char c ) { return c > 0 && c <= 0x20; }
2257 
LangListLoad(sys_char_t * fileName,ccollect<LangListNode> & list)2258 static bool LangListLoad( sys_char_t* fileName, ccollect<LangListNode>& list )
2259 {
2260 	list.clear();
2261 
2262 	try
2263 	{
2264 		BFile f;
2265 		f.Open( fileName );
2266 		char buf[4096];
2267 
2268 		while ( f.GetStr( buf, sizeof( buf ) ) )
2269 		{
2270 			char* s = buf;
2271 
2272 			while ( IsSpace( *s ) ) { s++; }
2273 
2274 			if ( *s == '#' ) { continue; }
2275 
2276 			if ( !*s ) { continue; }
2277 
2278 			ccollect<char, 0x100> id;
2279 			ccollect<char, 0x100> name;
2280 
2281 			while ( *s && !IsSpace( *s ) )
2282 			{
2283 				id.append( *s );
2284 				s++;
2285 			}
2286 
2287 			while ( IsSpace( *s ) ) { s++; }
2288 
2289 			int lastNs = -1;
2290 
2291 			for ( int i = 0; *s; i++, s++ )
2292 			{
2293 				if ( *s == '#' ) { break; }
2294 
2295 				if ( !IsSpace( *s ) ) { lastNs = i; }
2296 
2297 				name.append( *s );
2298 			}
2299 
2300 			if ( id.count() <= 0 || lastNs < 0 ) { continue; }
2301 
2302 			id.append( 0 );
2303 			name.append( 0 );
2304 			name[lastNs + 1] = 0;
2305 
2306 			LangListNode( id.ptr(), name.ptr() );
2307 			list.append( LangListNode( id.ptr(), name.ptr() ) );
2308 		}
2309 	}
2310 	catch ( cexception* ex )
2311 	{
2312 		ex->destroy();
2313 		return false;
2314 	}
2315 
2316 	return true;
2317 }
2318 
2319 
2320 ////////////////////////////////  SysOptDlg
2321 
2322 class SysOptDialog: public NCVertDialog
2323 {
2324 	Layout m_iL;
2325 public:
2326 	std::string m_CurLangId;
2327 	ccollect<LangListNode> m_List;
2328 	void SetCurLang( const char* id );
2329 
2330 	SButton  m_AskOpenExecButton;
2331 	SButton  m_EscPanelButton;
2332 	SButton  m_EscCommandLineButton;
2333 	SButton  m_BackUpDirButton;
2334 	SButton  m_AutoCompleteButton;
2335 	SButton  m_AutoSaveSetupButton;
2336 	SButton  m_ShowHostNameButton;
2337 	SButton  m_StorePasswordsButton;
2338 
2339 	StaticLabel m_LangStatic;
2340 	StaticLine m_LangVal;
2341 	Button m_LangButton;
2342 
2343 	SysOptDialog( NCDialogParent* parent );
2344 	virtual bool Command( int id, int subId, Win* win, void* data );
2345 	virtual bool EventChildKey( Win* child, cevent_key* pEvent );
2346 	virtual ~SysOptDialog();
2347 };
2348 
SetCurLang(const char * id)2349 void SysOptDialog::SetCurLang( const char* id )
2350 {
2351 	m_CurLangId = std::string( id );
2352 
2353 	if ( id[0] == '-' )
2354 	{
2355 		m_LangVal.SetText( utf8_to_unicode( _LT( "English" ) ).data() );
2356 	}
2357 	else if ( id[0] == '+' )
2358 	{
2359 		m_LangVal.SetText( utf8_to_unicode( _LT( "Autodetect" ) ).data() );
2360 	}
2361 	else
2362 	{
2363 		for ( int i = 0; i < m_List.count(); i++ )
2364 		{
2365 			if ( !strcmp( m_List[i].id.data(), id ) )
2366 			{
2367 				m_LangVal.SetText( utf8_to_unicode( m_List[i].name.data( ) ).data( ) );
2368 				return;
2369 			}
2370 		}
2371 
2372 		m_LangVal.SetText( utf8_to_unicode( id ).data( ) );
2373 	}
2374 }
2375 
~SysOptDialog()2376 SysOptDialog::~SysOptDialog() {}
2377 
SysOptDialog(NCDialogParent * parent)2378 SysOptDialog::SysOptDialog( NCDialogParent* parent )
2379 	: NCVertDialog( ::createDialogAsChild, 0, parent, utf8_to_unicode( _LT( "System settings" ) ).data(), bListOkCancel )
2380 	, m_iL( 16, 3 )
2381 	, m_AskOpenExecButton( 0, this, utf8_to_unicode( _LT( "Ask user if Exec/Open conflict" ) ).data(), 0, g_WcmConfig.systemAskOpenExec )
2382 	, m_EscPanelButton( 0, this, utf8_to_unicode( _LT( "Enable &ESC key to show/hide panels" ) ).data(), 0, g_WcmConfig.systemEscPanel )
2383 	, m_EscCommandLineButton( 0, this, utf8_to_unicode( _LT( "Enable &ESC key to clear the command line" ) ).data(), 0, g_WcmConfig.systemEscCommandLine )
2384 	, m_BackUpDirButton( 0, this, utf8_to_unicode( _LT( "Enable &BACKSPACE key to go up dir" ) ).data(), 0, g_WcmConfig.systemBackSpaceUpDir )
2385 	, m_AutoCompleteButton( 0, this, utf8_to_unicode( _LT( "Enable &autocomplete" ) ).data(), 0, g_WcmConfig.systemAutoComplete )
2386 	, m_AutoSaveSetupButton( 0, this, utf8_to_unicode( _LT( "Auto &save setup" ) ).data(), 0, g_WcmConfig.systemAutoSaveSetup )
2387 	, m_ShowHostNameButton( 0, this, utf8_to_unicode( _LT( "Show &host name" ) ).data(), 0, g_WcmConfig.systemShowHostName )
2388 	, m_StorePasswordsButton( 0, this, utf8_to_unicode( _LT( "Store &passwords" ) ).data(), 0, g_WcmConfig.systemStorePasswords )
2389 	, m_LangStatic( 0, this, utf8_to_unicode( _LT( "&Language:" ) ).data( ), &m_LangButton )
2390 	, m_LangVal( 0, this, utf8_to_unicode( "______________________" ).data( ) )
2391 	, m_LangButton( 0, this, utf8_to_unicode( ">" ).data( ), 1000 )
2392 {
2393 
2394 #ifndef _WIN32
2395 	m_iL.AddWinAndEnable( &m_AskOpenExecButton, 0, 0, 0, 2 );
2396 #endif
2397 	m_iL.AddWinAndEnable( &m_EscPanelButton, 1, 0, 1, 2 );
2398 	m_iL.AddWinAndEnable( &m_EscCommandLineButton, 2, 0, 2, 2 );
2399 	m_iL.AddWinAndEnable( &m_BackUpDirButton, 3, 0, 3, 2 );
2400 	m_iL.AddWinAndEnable( &m_AutoCompleteButton, 4, 0, 4, 2 );
2401 	m_iL.AddWinAndEnable( &m_AutoSaveSetupButton, 5, 0, 5, 2 );
2402 	m_iL.AddWinAndEnable( &m_ShowHostNameButton, 6, 0, 6, 2 );
2403 	m_iL.AddWinAndEnable( &m_StorePasswordsButton, 7, 0, 7, 2 );
2404 
2405 	m_iL.AddWinAndEnable( &m_LangStatic, 8, 0 );
2406 	m_iL.AddWinAndEnable( &m_LangVal, 8, 2 );
2407 	m_iL.AddWinAndEnable( &m_LangButton, 8, 1 );
2408 
2409 	m_iL.SetColGrowth( 2 );
2410 
2411 	AddLayout( &m_iL );
2412 	SetEnterCmd( CMD_OK );
2413 
2414 #ifndef _WIN32
2415 	m_AskOpenExecButton.SetFocus();
2416 	order.append( &m_AskOpenExecButton );
2417 #endif
2418 	order.append( &m_EscPanelButton );
2419 	order.append( &m_EscCommandLineButton );
2420 	order.append( &m_BackUpDirButton );
2421 	order.append( &m_AutoCompleteButton );
2422 	order.append( &m_AutoSaveSetupButton );
2423 	order.append( &m_ShowHostNameButton );
2424 	order.append( &m_StorePasswordsButton );
2425 	order.append( &m_LangButton );
2426 
2427 	SetPosition();
2428 
2429 #ifdef _WIN32
2430 	LangListLoad( carray_cat<sys_char_t>( GetAppPath( ).data( ), utf8_to_sys( "\\lang\\list" ).data( ) ).data( ), m_List );
2431 #else
2432 
2433 	if ( !LangListLoad( utf8_to_sys( "install-files/share/wcm/lang/list" ).data(), m_List ) )
2434 	{
2435 		LangListLoad( utf8_to_sys( UNIX_CONFIG_DIR_PATH "/lang/list" ).data(), m_List );
2436 	}
2437 
2438 #endif
2439 
2440 	SetCurLang( g_WcmConfig.systemLang.data() ? g_WcmConfig.systemLang.data() : "+" );
2441 }
2442 
Command(int id,int subId,Win * win,void * data)2443 bool SysOptDialog::Command( int id, int subId, Win* win, void* data )
2444 {
2445 	if ( id == 1000 )
2446 	{
2447 		CfgLangDialog dlg( ( NCDialogParent* )Parent(), m_CurLangId.c_str(), &m_List );
2448 
2449 		if ( dlg.DoModal() == CMD_OK )
2450 		{
2451 			SetCurLang( dlg.GetId() );
2452 		}
2453 
2454 		return true;
2455 	}
2456 
2457 	return NCVertDialog::Command( id, subId, win, data );
2458 }
2459 
EventChildKey(Win * child,cevent_key * pEvent)2460 bool SysOptDialog::EventChildKey( Win* child, cevent_key* pEvent )
2461 {
2462 	if ( pEvent->Type() == EV_KEYDOWN )
2463 	{
2464 		if ( pEvent->Key() == VK_RETURN && m_LangButton.InFocus() ) //prevent autoenter
2465 		{
2466 			return false;
2467 		}
2468 
2469 	};
2470 
2471 	return NCVertDialog::EventChildKey( child, pEvent );
2472 }
2473 
2474 
DoSystemConfigDialog(NCDialogParent * parent)2475 bool DoSystemConfigDialog( NCDialogParent* parent )
2476 {
2477 	SysOptDialog dlg( parent );
2478 
2479 	if ( dlg.DoModal() == CMD_OK )
2480 	{
2481 		g_WcmConfig.systemAskOpenExec = dlg.m_AskOpenExecButton.IsSet();
2482 		g_WcmConfig.systemEscPanel = dlg.m_EscPanelButton.IsSet();
2483 		g_WcmConfig.systemEscCommandLine = dlg.m_EscCommandLineButton.IsSet();
2484 		g_WcmConfig.systemBackSpaceUpDir = dlg.m_BackUpDirButton.IsSet( );
2485 		g_WcmConfig.systemAutoComplete = dlg.m_AutoCompleteButton.IsSet( );
2486 		g_WcmConfig.systemAutoSaveSetup = dlg.m_AutoSaveSetupButton.IsSet( );
2487 		g_WcmConfig.systemShowHostName = dlg.m_ShowHostNameButton.IsSet( );
2488 		g_WcmConfig.systemStorePasswords = dlg.m_StorePasswordsButton.IsSet( );
2489 		const char* s = g_WcmConfig.systemLang.data();
2490 
2491 		if ( !s ) { s = "+"; }
2492 
2493 		bool langChanged = strcmp( dlg.m_CurLangId.data( ), s ) != 0;
2494 		g_WcmConfig.systemLang = dlg.m_CurLangId.data( );
2495 
2496 		if ( langChanged )
2497 		{
2498 			NCMessageBox( parent, _LT( "Note" ),
2499 			              _LT( "Language changed. \nFor effect you must save config and restart" ), false );
2500 		}
2501 
2502 		return true;
2503 	}
2504 
2505 	return false;
2506 }
2507 
2508 
2509 ////////////////////////// TerminalOptDialog
2510 
2511 class TerminalOptDialog: public NCVertDialog
2512 {
2513 	Layout iL;
2514 public:
2515 	StaticLine backspaceKeyStatic;
2516 	SButton  backspaceAsciiButton;
2517 	SButton  backspaceCtrlHButton;
2518 
2519 	TerminalOptDialog( NCDialogParent* parent );
2520 	//virtual bool EventChildKey(Win* child, cevent_key* pEvent);
2521 	//virtual bool Command(int id, int subId, Win *win, void *data);
2522 	virtual ~TerminalOptDialog();
2523 };
2524 
2525 
TerminalOptDialog(NCDialogParent * parent)2526 TerminalOptDialog::TerminalOptDialog( NCDialogParent* parent )
2527 	:  NCVertDialog( ::createDialogAsChild, 0, parent, utf8_to_unicode( _LT( "Terminal options" ) ).data(), bListOkCancel ),
2528 	   iL( 16, 3 ),
2529 	   backspaceKeyStatic( 0, this, utf8_to_unicode( _LT( "Backspace key:" ) ).data() ),
2530 	   backspaceAsciiButton( 0, this, utf8_to_unicode( "ASCII DEL" ).data(), 1, g_WcmConfig.terminalBackspaceKey == 0 ),
2531 	   backspaceCtrlHButton( 0, this,  utf8_to_unicode( "Ctrl H" ).data(), 1, g_WcmConfig.terminalBackspaceKey == 1 )
2532 {
2533 	iL.AddWin( &backspaceKeyStatic,   0, 0, 0, 1 );
2534 	backspaceKeyStatic.Enable();
2535 	backspaceKeyStatic.Show();
2536 	iL.AddWin( &backspaceAsciiButton, 1, 1 );
2537 	backspaceAsciiButton.Enable();
2538 	backspaceAsciiButton.Show();
2539 	iL.AddWin( &backspaceCtrlHButton, 2, 1 );
2540 	backspaceCtrlHButton.Enable();
2541 	backspaceCtrlHButton.Show();
2542 
2543 	iL.ColSet( 0, 10, 10, 10 );
2544 	iL.SetColGrowth( 1 );
2545 
2546 	AddLayout( &iL );
2547 	SetEnterCmd( CMD_OK );
2548 
2549 	backspaceAsciiButton.SetFocus();
2550 
2551 	order.append( &backspaceAsciiButton );
2552 	order.append( &backspaceCtrlHButton );
2553 	SetPosition();
2554 }
2555 
~TerminalOptDialog()2556 TerminalOptDialog::~TerminalOptDialog() {}
2557 
2558 
DoTerminalConfigDialog(NCDialogParent * parent)2559 bool DoTerminalConfigDialog( NCDialogParent* parent )
2560 {
2561 	TerminalOptDialog dlg( parent );
2562 
2563 	if ( dlg.DoModal() == CMD_OK )
2564 	{
2565 		g_WcmConfig.terminalBackspaceKey = dlg.backspaceCtrlHButton.IsSet() ? 1 : 0;
2566 		return true;
2567 	}
2568 
2569 	return false;
2570 }
2571