1 /*
2    Copyright (c) by Valery Goryachev (Wal)
3 */
4 
5 #pragma once
6 
7 #if defined( _MSC_VER )
8 #  pragma warning( disable:4100 ) // C4100 : unreferenced formal parameter
9 #endif
10 
11 #ifdef _WIN32
12 #  if !defined( NOMINMAX )
13 #     define NOMINMAX
14 #  endif
15 #  include <windows.h>
16 typedef HWND WinID;
17 extern HINSTANCE appInstance;
18 #else
19 #  include <X11/Xlib.h>
20 #  include <X11/keysym.h>
21 #  include <wchar.h>
22 typedef Window WinID;
23 #endif
24 
25 #include <stdarg.h>
26 #include <unordered_map>
27 
28 namespace wal
29 {
30 
31 	enum CoreCommands
32 	{
33 		CMD_CHECK = 0, //команда проверки (поддерживается команда или нет) номер команды в этом случае передается в подкоманде
34 		CMD_OK = 1,
35 		CMD_CANCEL = 2,
36 		CMD_YES = 3,
37 		CMD_NO = 4,
38 		CMD_PUT_RESULTS_TO_TEMP_PANEL = 5 // XXX should be in global CMD_ID space. There is no one yet
39 	};
40 
41 	struct cpoint;
42 	struct crect;
43 	class cpen;
44 	class cbrush;
45 	class cfont;
46 	class cevent;
47 	//...
48 	class crgn;
49 	class cicon;
50 	class Win;
51 	class GC;
52 	class Layout;
53 
54 	struct cpoint
55 	{
56 		int x, y;
cpointcpoint57 		cpoint() {}
cpointcpoint58 		cpoint( int _x, int _y ): x( _x ), y( _y ) {}
cpointcpoint59 		cpoint( const cpoint& a ): x( a.x ), y( a.y ) {}
60 		cpoint& operator = ( const cpoint& a ) {x = a.x; y = a.y; return *this;}
Setcpoint61 		cpoint& Set( int _x, int _y ) {x = _x; y = _y; return *this;}
62 		cpoint& operator + ( const cpoint& a ) { x += a.x; y += a.y; return *this; }
63 		cpoint& operator - ( const cpoint& a ) { x -= a.x; y -= a.y; return *this; }
64 		bool operator == ( const cpoint& a ) const { return x == a.x && y == a.y; }
65 	};
66 
67 	struct crect
68 	{
69 		int left, top;
70 		int right, bottom;
crectcrect71 		crect(): left( 0 ), top( 0 ), right( 0 ), bottom( 0 ) {}
crectcrect72 		crect( const cpoint& lt, const cpoint& rb ): left( lt.x ), top( lt.y ), right( rb.x ), bottom( rb.y ) {}
crectcrect73 		crect( int _left, int _top, int _right, int _bottom ): left( _left ), top( _top ), right( _right ), bottom( _bottom ) {}
Setcrect74 		void Set( int _left, int _top, int _right, int _bottom ) {left = _left; right = _right; top = _top; bottom = _bottom;}
75 
Inccrect76 		void Inc() { left--; right++; top--; bottom++; }
Deccrect77 		void Dec() { left++; right--; top++; bottom--; }
78 
Inccrect79 		void Inc( int n ) { left -= n; right += n; top -= n; bottom += n; }
Deccrect80 		void Dec( int n ) { left += n; right -= n; top += n; bottom -= n; }
81 
Heightcrect82 		int Height() const { return bottom - top; }
Widthcrect83 		int Width()const { return right - left; }
Increct84 		bool In( cpoint p )const { return p.x >= left && p.x < right && p.y >= top && p.y < bottom; }
85 		bool operator == ( const crect& a ) const { return left == a.left && right == a.right && top == a.top && bottom == a.bottom; }
86 		bool operator != ( const crect& a ) const { return !( *this == a ); }
IsEmptycrect87 		bool IsEmpty() const { return bottom <= top || right <= left; }
Zerocrect88 		void Zero() { left = top = right = bottom = 0; }
SetWidthcrect89 		void SetWidth( int w ) { right = left + w; }
SetHeightcrect90 		void SetHeight( int h ) { bottom = top + h; }
91 
Crosscrect92 		bool Cross( const crect& a ) const
93 		{
94 			crect b( left > a.left ? left : a.left, top > a.top ? top : a.top,
95 			         right < a.right ? right : a.right, bottom < a.bottom ? bottom : a.bottom );
96 			return !b.IsEmpty();
97 		}
98 	};
99 
100 }; //namespace wal
101 
102 #include "swl_layout.h"
103 
104 namespace wal
105 {
106 
107 	void AppInit();
108 	int AppRun();
109 	void AppExit();
110 
111 #ifdef _WIN32
112 	enum Keyboard
113 	{
114 		VK_NUMPAD_CENTER = 0x0C,
115 		VK_NUMPAD_RETURN = 0xFFFF,
116 
117 		VK_LMETA      = VK_LWIN,
118 		VK_RMETA      = VK_RWIN,
119 
120 #ifndef VK_SLASH
121 		VK_SLASH      =   0xBF,
122 #endif
123 
124 #ifndef VK_BACKSLASH
125 		VK_BACKSLASH  =   0xDC,
126 #endif
127 
128 #ifndef VK_GRAVE
129 		VK_GRAVE = 0xC0,
130 #endif
131 		VK_0 = 0x30,
132 		VK_1 = 0x31,
133 		VK_2 = 0x32,
134 		VK_3 = 0x33,
135 		VK_4 = 0x34,
136 		VK_5 = 0x35,
137 		VK_6 = 0x36,
138 		VK_7 = 0x37,
139 		VK_8 = 0x38,
140 		VK_9 = 0x39,
141 
142 		VK_A = 0x41,
143 		VK_B = 0x42,
144 		VK_C = 0x43,
145 		VK_D = 0x44,
146 		VK_E = 0x45,
147 		VK_F = 0x46,
148 		VK_G = 0x47,
149 		VK_H = 0x48,
150 		VK_I = 0x49,
151 		VK_J = 0x4A,
152 		VK_K = 0x4B,
153 		VK_L = 0x4C,
154 		VK_M = 0x4D,
155 		VK_N = 0x4E,
156 		VK_O = 0x4F,
157 		VK_P = 0x50,
158 		VK_Q = 0x51,
159 		VK_R = 0x52,
160 		VK_S = 0x53,
161 		VK_T = 0x54,
162 		VK_U = 0x55,
163 		VK_V = 0x56,
164 		VK_W = 0x57,
165 		VK_X = 0x58,
166 		VK_Y = 0x59,
167 		VK_Z = 0x5A,
168 
169 		VK_BRACKETLEFT = 219,
170 		VK_BRACKETRIGHT = 221,
171 	};
172 
173 
174 #endif
175 
176 
177 #ifndef _WIN32
178 	enum Keyboard
179 	{
180 		VK_NUMPAD_CENTER = XK_KP_Begin,
181 
182 		VK_ESCAPE = XK_Escape,
183 		VK_TAB = XK_Tab,
184 		VK_RETURN = XK_Return,
185 		VK_NUMPAD_RETURN = XK_KP_Enter,
186 		VK_BACK = XK_BackSpace,
187 		VK_LEFT = XK_Left,
188 		VK_RIGHT = XK_Right,
189 		VK_HOME = XK_Home,
190 		VK_END = XK_End,
191 		VK_UP = XK_Up,
192 		VK_DOWN = XK_Down,
193 		VK_SPACE = XK_space, //XK_KP_Space,
194 		VK_DELETE = XK_Delete,
195 		VK_NEXT = XK_Next,
196 		VK_PRIOR = XK_Prior,
197 		VK_OEM_PLUS = XK_equal,
198 
199 		VK_ADD = XK_KP_Add,
200 		VK_SUBTRACT = XK_KP_Subtract,
201 		VK_MULTIPLY = XK_KP_Multiply,
202 
203 		VK_DIVIDE = XK_KP_Divide,
204 		VK_SLASH      =   XK_slash,
205 		VK_BACKSLASH  =   XK_backslash,
206 
207 		VK_GRAVE = XK_grave,
208 
209 		VK_INSERT = XK_Insert,
210 
211 		VK_LMETA = XK_Meta_L,
212 		VK_RMETA = XK_Meta_R,
213 
214 		VK_LCONTROL = XK_Control_L,
215 		VK_RCONTROL = XK_Control_R,
216 		VK_LSHIFT = XK_Shift_L,
217 		VK_RSHIFT = XK_Shift_R,
218 
219 		VK_LMENU = XK_Alt_L,
220 		VK_RMENU = XK_Alt_R,
221 
222 		VK_F1 = XK_F1,
223 		VK_F2 = XK_F2,
224 		VK_F3 = XK_F3,
225 		VK_F4 = XK_F4,
226 		VK_F5 = XK_F5,
227 		VK_F6 = XK_F6,
228 		VK_F7 = XK_F7,
229 		VK_F8 = XK_F8,
230 		VK_F9 = XK_F9,
231 		VK_F10 = XK_F10,
232 		VK_F11 = XK_F11,
233 		VK_F12 = XK_F12,
234 
235 		VK_1 = XK_1,
236 		VK_2 = XK_2,
237 		VK_3 = XK_3,
238 		VK_4 = XK_4,
239 		VK_5 = XK_5,
240 		VK_6 = XK_6,
241 		VK_7 = XK_7,
242 		VK_8 = XK_8,
243 		VK_9 = XK_9,
244 		VK_0 = XK_0,
245 
246 		VK_BRACKETLEFT = XK_bracketleft,
247 		VK_BRACKETRIGHT = XK_bracketright,
248 
249 #define S(a) VK_##a = XK_##a
250 		S( A ),
251 		S( B ),
252 		S( C ),
253 		S( D ),
254 		S( E ),
255 		S( F ),
256 		S( G ),
257 		S( H ),
258 		S( I ),
259 		S( J ),
260 		S( K ),
261 		S( L ),
262 		S( M ),
263 		S( N ),
264 		S( O ),
265 		S( P ),
266 		S( Q ),
267 		S( R ),
268 		S( S ),
269 		S( T ),
270 		S( U ),
271 		S( V ),
272 		S( W ),
273 		S( X ),
274 		S( Y ),
275 		S( Z )
276 #undef s
277 	};
278 #endif
279 
280 	enum events
281 	{
282 		EV_NONE = 0,
283 		EV_CLOSE,
284 		EV_SHOW,
285 		EV_ACTIVATE,
286 
287 		EV_KEYDOWN = 10,
288 		EV_KEYUP,
289 
290 		EV_MOUSE_MOVE = 20,
291 		EV_MOUSE_PRESS,
292 		EV_MOUSE_RELEASE,
293 		EV_MOUSE_DOUBLE,
294 		EV_MOUSE_WHELL,
295 
296 		EV_ENTER,
297 		EV_LEAVE,
298 		EV_SETFOCUS = 30,
299 		EV_KILLFOCUS,
300 		EV_SIZE = 50,
301 		EV_MOVE,
302 		EV_TIMER = 70,
303 	};
304 
305 
306 	enum KEYMODFLAG
307 	{
308 		KM_SHIFT = 0x0001,
309 		KM_CTRL = 0x0002,
310 		KM_ALT  = 0x0004,
311 		EXT_KM_RSHIFT = 0x0008,
312 		EXT_KM_LSHIFT = 0x0010,
313 		EXT_KM_RCTRL = 0x0020,
314 		EXT_KM_LCTRL = 0x0040,
315 		EXT_KM_RALT = 0x00080,
316 		EXT_KM_LALT = 0x00100
317 	};
318 
319 	class cevent//: public iIntrusiveCounter
320 	{
321 		int type;
322 	public:
cevent()323 		cevent(): type( EV_NONE ) {}
cevent(int t)324 		cevent( int t ): type( t ) {}
Type()325 		int Type() const {return type; }
326 		virtual ~cevent();
327 	};
328 
329 	class cevent_show: public cevent
330 	{
331 		bool show;
332 	public:
cevent_show(bool sh)333 		cevent_show( bool sh ): cevent( EV_SHOW ), show( sh ) {}
Show()334 		bool Show() { return show; }
335 		virtual ~cevent_show();
336 	};
337 
338 	class cevent_activate: public cevent
339 	{
340 		bool activated;
341 		Win* who;
342 	public:
cevent_activate(bool act,Win * w)343 		cevent_activate( bool act, Win* w ): cevent( EV_ACTIVATE ), activated( act ), who( w ) {}
Activated()344 		bool Activated() { return activated; }
Who()345 		Win* Who() { return who; }
346 		virtual ~cevent_activate();
347 	};
348 
349 	class cevent_input: public cevent
350 	{
351 		unsigned keyMods;
352 	public:
cevent_input(int t,unsigned km)353 		cevent_input( int t, unsigned km ): cevent( t ), keyMods( km ) {}
Mod()354 		unsigned Mod() { return keyMods & (KM_ALT|KM_CTRL|KM_SHIFT); }
ExtMod()355 		unsigned ExtMod() { return keyMods; }
356 		virtual ~cevent_input();
357 	};
358 
359 	enum MOUSEBUTTON
360 	{
361 		MB_L  = 0x01,
362 		MB_M  = 0x02,
363 		MB_R  = 0x04,
364 		MB_X1 = 0x08,
365 		MB_X2 = 0x10
366 	};
367 
368 	class cevent_mouse: public cevent_input
369 	{
370 		cpoint point;
371 		unsigned buttonFlag;
372 		int button;
373 		//int whellDistance;
374 	public:
cevent_mouse(int type,cpoint p,int b,unsigned bf,unsigned km)375 		cevent_mouse( int type, cpoint p, int b, unsigned bf, unsigned km )
376 			: cevent_input( type, km ), point( p ), buttonFlag( bf ), button( b ) {};
377 
Point()378 		cpoint& Point() { return point; }
ButtonFlag()379 		unsigned ButtonFlag() { return buttonFlag; }
ButtonL()380 		bool ButtonL() { return ( buttonFlag & MB_L ) != 0; }
ButtonR()381 		bool ButtonR() { return ( buttonFlag & MB_R ) != 0; }
Button()382 		int Button() { return button; }
383 		virtual ~cevent_mouse();
384 	};
385 
386 	class cevent_key: public cevent_input
387 	{
388 		int       m_Key;  // virtual key code (Windows virtual keys are used)
389 		int       m_Count;
390 		unicode_t m_Chr;
391 		bool      m_FromMouseWheel;
392 	public:
cevent_key(int type,int k,unsigned km,int cnt,unicode_t ch,bool FromMouseWheel)393 		cevent_key( int type, int k, unsigned km, int cnt, unicode_t ch, bool FromMouseWheel )
394 			: cevent_input( type, km )
395 			, m_Key( k )
396 			, m_Count( cnt )
397 			, m_Chr( ch )
398 			, m_FromMouseWheel( FromMouseWheel )
399 		{};
400 		virtual ~cevent_key();
Key()401 		int Key() const { return m_Key; }
Count()402 		int Count() const { return m_Count; }
IsFromMouseWheel()403 		bool IsFromMouseWheel() const { return m_FromMouseWheel; }
Char()404 		unicode_t Char() const { return m_Chr; };
405 	};
406 
407 	class cevent_size: public cevent
408 	{
409 		cpoint size;
410 	public:
cevent_size(cpoint s)411 		cevent_size( cpoint s ): cevent( EV_SIZE ), size( s ) {};
Size()412 		cpoint& Size() { return size; }
413 		virtual ~cevent_size();
414 	};
415 
416 	class cevent_move: public cevent
417 	{
418 		cpoint pos;
419 	public:
cevent_move(cpoint s)420 		cevent_move( cpoint s ): cevent( EV_MOVE ), pos( s ) {};
Pos()421 		cpoint& Pos() { return pos; }
422 		virtual ~cevent_move();
423 	};
424 
425 
426 
427 
428 #ifdef _WIN32
429 #else
430 	unsigned CreateColorFromRGB( unsigned );
431 #endif
432 
433 
434 	class cfont: public iIntrusiveCounter
435 	{
cfont()436 		cfont() {}
cfont(const cfont &)437 		cfont( const cfont& ) {}
438 		void operator = ( const cfont& ) {}
439 		friend class GC;
440 
441 #ifdef _WIN32
442 		HFONT handle;
443 		bool external; //true если внешний хэндл (чтоб не удалять в деструкторе)
drop()444 		void drop() { if ( handle && !external ) { ::DeleteObject( handle ); } handle = 0;  }
445 #else
446 		enum { TYPE_X11 = 0, TYPE_FT = 1 };
447 		int type;
448 		void* data;
449 
450 		//XFontStruct *xfs;
451 
452 		void drop();
453 #endif
454 
455 		std::string _uri;
456 		std::string _name;
457 	public:
458 #ifdef _WIN32
459 		static void SetWin32Charset( unsigned );
cfont(HFONT hf)460 		cfont( HFONT hf ): handle( hf ), external( true ) {};
Ok()461 		bool Ok() { return handle != NULL; }
462 
463 		static std::vector<char> LogFontToUru( LOGFONT& lf );
464 		static void UriToLogFont( LOGFONT* plf, const char* uri );
465 #else
466 		static void SetWin32Charset( unsigned ) {};
467 		bool Ok() { return data != 0; }
468 #endif
469 
470 		enum Weight { X3 = 0, Normal, Light, Bold };
471 		enum Flags { Italic = 1, Fixed = 2 };
472 
473 		cfont( GC& gc, const char* name, int pointSize, cfont::Weight weight = Normal, unsigned flags = 0 );
474 		cfont( const char* fileName, int pointSize ); //FreeType
475 		cfont( const char* uri );
476 		const char* uri();
477 		const char* printable_name();
478 
~cfont()479 		~cfont() { drop(); }
480 
481 		static clPtr<cfont> New( GC& gc, const char* name, int pointSize, cfont::Weight weight = Normal, unsigned flags = 0 )
482 		{
483 			clPtr<cfont> p = new cfont( gc, name, pointSize, weight, flags );
484 
485 			if ( !p->Ok() ) { return clPtr<cfont>(); }
486 
487 			return p;
488 		}
489 
New(const char * fileName,int pointSize)490 		static clPtr<cfont> New( const char* fileName, int pointSize )
491 		{
492 			clPtr<cfont> p = new cfont( fileName, pointSize );
493 
494 			if ( !p->Ok( ) ) { return clPtr<cfont>( ); }
495 
496 			return p;
497 		}
498 
New(const char * x11string)499 		static clPtr<cfont> New( const char* x11string )
500 		{
501 			clPtr<cfont> p = new cfont( x11string );
502 
503 			if ( !p->Ok( ) ) { return clPtr<cfont>( ); }
504 
505 			return p;
506 		}
507 
508 #ifdef USEFREETYPE
509 		struct FTInfo: public iIntrusiveCounter
510 		{
511 			enum {FIXED_WIDTH = 1};
512 			unsigned flags;
513 			std::string name;
514 			std::string styleName;
515 		};
516 		static clPtr<FTInfo> GetFTFileInfo( const char* path );
517 #endif
518 
519 	};
520 
521 	class XPMImage
522 	{
523 		int colorCount;
524 		std::vector<unsigned> colors;
525 		int none;
526 		int width, height;
527 		std::vector<int> data;
528 	public:
529 		void Clear();
XPMImage()530 		XPMImage(): colorCount( 0 ), none( -1 ), width( 0 ), height( 0 ) {}
531 
Width()532 		int Width() const { return width; }
Height()533 		int Height() const { return height; }
534 
Colors()535 		const unsigned* Colors() const { return colors.data(); }
Data()536 		const int* Data() const { return data.data(); }
537 
538 		bool Load( const char** list, int count );
539 		//void Load(InStream &stream);
~XPMImage()540 		~XPMImage() {}
541 	};
542 
543 	class Image32
544 	{
545 		int _width;
546 		int _height;
547 		std::vector<uint32_t> _data;
548 //		std::vector<uint32_t*> _lines;
549 
Image32(const Image32 &)550 		Image32( const Image32& ) {}
551 		void operator=( const Image32& ) {}
552 
553 	public:
Image32()554 		Image32(): _width( 0 ), _height( 0 ) {}
555 
556 		void alloc( int w, int c );
557 
558 		void fill( int left, int top, int right, int bottom, unsigned c );
fill(const crect & r,unsigned c)559 		void fill( const crect& r, unsigned c ) { fill( r.left, r.top, r.right, r.bottom, c ); }
560 
561 		void copy( const Image32& a );
562 		void copy( const Image32& a, int w, int h );
563 
564 		void copy( const XPMImage& xpm );
565 
566 		void clear();
567 
get(int x,int y)568 		uint32_t get( int x, int y )
569 		{
570 			//return ( x >= 0 && x < _width && y >= 0 && y < _height ) ? _lines[y][x] : 0xFF;
571 			return ( x >= 0 && x < _width && y >= 0 && y < _height ) ? _data[ y * _width + x ] : 0xFF;
572 		}
573 
line(int y)574 		uint32_t* line( int y ) { return &_data[ y * _width ]; }
575 
Image32(int w,int h)576 		Image32( int w, int h ) { alloc( w, h ); }
577 
width()578 		int width() const { return _width; }
height()579 		int height() const { return _height; }
580 
~Image32()581 		~Image32() {}
582 	};
583 
584 
585 #ifdef _WIN32
586 
587 	class Win32CompatibleBitmap: public iIntrusiveCounter
588 	{
589 		HBITMAP handle;
590 		int _w, _h;
591 		std::vector<char> mask;
592 		void clear();
593 		void init( int w, int h );
594 	public:
Win32CompatibleBitmap()595 		Win32CompatibleBitmap(): handle( 0 ), _w( 0 ), _h( 0 ) {}
Win32CompatibleBitmap(int w,int h)596 		Win32CompatibleBitmap( int w, int h ): handle( 0 ) { init( w, h ); }
Win32CompatibleBitmap(Image32 & image)597 		Win32CompatibleBitmap( Image32& image ) { Set( image ); }
598 		void Set( Image32& image );
599 		void Put( wal::GC& gc, int src_x, int src_y, int dest_x, int dest_y, int w, int h );
600 		~Win32CompatibleBitmap();
601 	};
602 
603 #else
604 //for X
605 	class IntXImage
606 	{
607 		XImage im;
608 		std::vector<char> data;
609 		std::vector<char> mask;
610 
611 		void init( int w, int h );
clear()612 		void clear() { data.clear(); mask.clear(); }
613 	public:
IntXImage(int w,int h)614 		IntXImage( int w, int h ) { init( w, h ); }
615 		IntXImage( Image32& image );
616 		void Set( Image32& image );
617 		void Set( Image32& image, unsigned bgColor );
618 		void Put( wal::GC& gc, int src_x, int src_y, int dest_x, int dest_y, int w, int h );
GetXImage()619 		XImage* GetXImage() {return data.data() ? &im : 0; };
620 		~IntXImage();
621 	};
622 #endif
623 
624 
625 ////////  Screen compatible image
626 	class SCImage
627 	{
628 		int width;
629 		int height;
630 
631 #ifdef _WIN32
632 		HBITMAP handle;
633 #else
634 		Pixmap handle;
635 #endif
636 
SCImage(const SCImage &)637 		SCImage( const SCImage& ) {};
638 		void operator = ( const SCImage& ) {};
639 	public:
640 		SCImage();
641 		void Destroy();
642 		void Create( int w, int h );
Width()643 		int Width() const { return width; };
Height()644 		int Height()const { return height; };
645 
646 #ifdef _WIN32
GetX11Handle()647 		HBITMAP GetX11Handle() { return handle; };
648 #else
GetXDrawable()649 		Pixmap GetXDrawable() { return handle; };
650 #endif
651 
652 		~SCImage();
653 	};
654 
655 
656 	struct IconData
657 	{
658 		int counter;
659 		Image32 image;
660 
661 #ifdef _WIN32
662 		clPtr<Win32CompatibleBitmap> normal;
663 		clPtr<Win32CompatibleBitmap> disabled;
664 
665 #else
666 		//x11 cache
667 		struct Node: public iIntrusiveCounter
668 		{
669 			SCImage image;
670 			std::vector<char> mask;
671 			unsigned bgColor;
672 		};
673 
674 		clPtr<Node> normal;
675 		clPtr<Node> disabled;
676 #endif
677 	};
678 
679 
680 //создавать и копировать можно в любом потоке, а рисовать только в основном
681 	class cicon: public iIntrusiveCounter
682 	{
683 		IconData* data;
684 	public:
cicon()685 		cicon(): data( 0 ) {}
686 
687 		void Copy( const cicon& );
688 
cicon(const cicon & a)689 		cicon( const cicon& a ): data( 0 ) { Copy( a ); }
690 		cicon& operator = ( const cicon& a ) { Copy( a ); return *this; }
691 
Width()692 		int Width() const { return data ? data->image.width() : 0; }
Height()693 		int Height() const { return data ? data->image.height() : 0; }
Valid()694 		bool Valid() const { return data != 0; }
695 
696 		void Draw( wal::GC& gc, int x, int y, bool enabled = true );
697 		void DrawF( wal::GC& gc, int x, int y, bool enabled = true );
698 		void Clear();
699 
700 		void Load( int id, int w /*= 16*/, int h /*= 16*/ );
701 		void Load( const Image32&, int w, int h );
702 		void Load( const char** list, int w, int h );
703 
cicon(int id,int w,int h)704 		cicon( int id, int w /*= 16*/, int h /*= 16*/ ): data( 0 ) { Load( id, w, h ); }
cicon(const char ** xpm,int w,int h)705 		cicon( const char** xpm, int w /*= 16*/, int h /*= 16*/ ): data( 0 ) { Load( xpm, w, h ); }
706 
707 		static void SetCmdIcon( int cmd, const Image32&, int w = 16, int h = 16 );
708 		static void SetCmdIcon( int cmd, const char** s, int w = 16, int h = 16 );
709 
710 		static void ClearCmdIcons( int cmd );
~cicon()711 		~cicon() { Clear(); }
712 	private:
713 		static Mutex iconCopyMutex;
714 		static Mutex iconListMutex;
715 	};
716 
717 
718 
719 
720 
721 	class GC: public iIntrusiveCounter
722 	{
723 	public:
724 		enum LineStyle
725 		{
726 			SOLID = 0,
727 			DOT
728 		};
729 	private:
GC()730 		GC() {};
731 		GC( const GC& ) = delete;
732 		GC& operator=( const GC& ) = delete;
733 #ifdef _WIN32
734 		friend LRESULT CALLBACK WProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam );
735 		friend class cfont;
736 
737 		struct crgn
738 		{
739 			HRGN handle;
crgncrgn740 			crgn(): handle( 0 ) {}
dropcrgn741 			void drop() { if ( handle ) { ::DeleteObject( handle ); handle = 0; } }
742 			void Set( crect* rect = 0 ) { drop(); if ( rect ) { handle = ::CreateRectRgn( rect->left, rect->top, rect->right, rect->bottom ); } }
~crgncrgn743 			~crgn() { drop(); }
744 		};
745 
746 		HDC handle;
747 		bool needDelete;
748 		HPEN savedPen;
749 		HBRUSH savedBrush;
750 		HFONT savedFont;
751 		crgn rgn;
752 
753 		HPEN linePen;
754 		HBRUSH fillBrush;
755 		unsigned fillRgb;
756 		unsigned lineRgb;
757 		unsigned lineWidth;
758 		int lineStyle;
759 		unsigned textRgb;
760 		//unsigned textColor;
761 		bool textColorSet;
762 		bool bkColorSet;
763 
764 		int bkMode; // -1 - неизвестно 0 - transparent 1 - OPAQUE
765 		GC( HDC h, bool needDel );
766 		void Restore();
767 
768 #else
769 		::GC gc;
770 		XGCValues gcValues;
771 		unsigned long valueMask;
772 		static XFontStruct* defaultFontStruct;
773 		int lineX, lineY;
774 		Window winId;
775 		int fontAscent;
776 		cfont* curFont;
777 
778 		unsigned lineRgb, lineColor;
779 		unsigned textRgb, textColor;
780 		unsigned fillRgb, fillColor;
781 
782 		void CheckValues();
783 		void SetFg( unsigned );
784 		void SetBg( unsigned );
785 
786 		void _Init( Drawable id );
787 	public:
GetXDrawable()788 		Drawable GetXDrawable() { return winId; }
789 
790 #endif
791 
792 	public:
793 
794 		GC( Win* win );
795 		GC( SCImage* win );
796 #ifndef _WIN32
797 		GC( Drawable id );
798 #endif
799 
800 		void SetFillColor( unsigned rgb );
801 		void SetLine( unsigned rgb, int width = 1, int style = SOLID );
802 		void SetTextColor( unsigned rgb );
803 
TextRgb()804 		unsigned TextRgb() const { return textRgb; }
FillRgb()805 		unsigned FillRgb() const { return fillRgb; }
806 
807 
808 		void Set( cfont* font );
809 
810 		void FillRect( crect r );
811 		void FillRectXor( crect r );
812 		void SetClipRgn( crect* r = 0 );
813 
814 		void DrawIcon( int x, int y, cicon* ico );
815 		void DrawIconF( int x, int y, cicon* ico );
816 
817 		void TextOut( int x, int y, const unicode_t* s, int charCount = -1 );
818 		void TextOutF( int x, int y, const unicode_t* s, int charCount = -1 );
819 		void MoveTo( int x, int y );
820 		void LineTo( int x, int y );
821 		void SetPixel( int x, int y, unsigned rgb );
822 		cpoint GetTextExtents( const unicode_t* s, int charCount = -1 );
823 		void Ellipce( crect r );
824 
825 #ifdef _WIN32
W32Handle()826 		HDC W32Handle() { return handle; };
827 #else
XHandle()828 		::GC XHandle() { return gc; }
829 #endif
830 		virtual ~GC();
831 	};
832 
833 #define CI_WIN 0  //class ID
834 
835 //extern unsigned* (*SysGetColors)(Win *w);
836 //extern unsigned (*SysGetColor)(Win *w, int colorId);
837 	extern cfont* ( *SysGetFont )( Win* w, int fontId );
838 
839 ///////////////////////////////// Ui
840 
841 	extern int GetUiID( const char* name );
842 
843 	struct UiValueNode: public iIntrusiveCounter
844 	{
845 		enum {INT = 1, STR = 2};
846 		int flags;
847 		int64_t i;
848 		std::string s;
849 
UiValueNodeUiValueNode850 		UiValueNode( int64_t n ): flags( INT ), i( n ) {};
UiValueNodeUiValueNode851 		UiValueNode( const char* a ): flags( STR ), s( a ) {}
852 
853 		int64_t Int();
854 		const char* Str();
855 	};
856 
857 	class UiParzer;
858 
859 	class UiValue
860 	{
861 		friend class UiRules;
862 		ccollect<clPtr<UiValueNode> > list;
863 		UiValue* next;
UiValue(UiValue * nx)864 		UiValue( UiValue* nx ): next( nx ) {};
Append(int64_t n)865 		void Append( int64_t n ) { clPtr<UiValueNode> v = new UiValueNode( n ); list.append( v ); }
Append(const char * s)866 		void Append( const char* s ) { clPtr<UiValueNode> v = new UiValueNode( s ); list.append( v ); }
867 		bool ParzeNode( UiParzer& parzer );
868 		void Parze( UiParzer& parzer );
869 	public:
870 		UiValue();
Int(int n)871 		int64_t Int( int n ) { return n >= 0 && n < list.count() ? list[n]->Int() : 0 ; }
Int()872 		int64_t Int() { return Int( 0 ); }
Str(int n)873 		const char* Str( int n ) { return n >= 0 && n < list.count() ? list[n]->Str() : "" ; }
Str()874 		const char* Str() { return Str( 0 ); }
Count()875 		int Count() { return list.count(); }
876 		~UiValue();
877 	};
878 
879 	struct UiSelector;
880 	class UiRules;
881 
882 	class UiCache
883 	{
884 		bool updated;
885 		struct Node
886 		{
887 			UiSelector* s;
888 			UiValue* v;
NodeNode889 			Node(): s( 0 ), v( 0 ) {}
NodeNode890 			Node( UiSelector* _s, UiValue* _v ): s( _s ), v( _v ) {}
891 		};
892 
893 		std::unordered_map<int, ccollect<Node> > hash;
894 	public:
895 		struct ObjNode
896 		{
897 			int classId;
898 			int nameId;
ObjNodeObjNode899 			ObjNode(): classId( 0 ), nameId( 0 ) {}
ObjNodeObjNode900 			ObjNode( int c, int n ): classId( c ), nameId( n ) {}
901 		};
902 
903 		UiCache();
904 
Updated()905 		bool Updated() const {return updated;}
Clear()906 		void Clear() { hash.clear(); updated = false; }
907 		void Update( UiRules& rules, ObjNode* list, int listCount );
908 		UiValue* Get( int id, int item, int* condList );
909 		~UiCache();
910 	};
911 
912 	struct UiCondList
913 	{
914 		enum {N = 16};
915 		int buf[N];
916 
ClearUiCondList917 		void Clear() { for ( int i = 0; i < N; i++ ) { buf[i] = 0; } }
UiCondListUiCondList918 		UiCondList() { Clear(); }
919 		void Set( int id, bool yes );
920 	};
921 
922 	extern int uiEnabled;
923 	extern int uiFocus;
924 	extern int uiItem;
925 	extern int uiClassWin;
926 	extern int uiColor;
927 	extern int uiHotkeyColor;
928 	extern int uiBackground;
929 	extern int uiFrameColor;
930 	extern int uiCurrentItem;
931 	extern int uiFocusFrameColor;
932 	extern int uiButtonColor;//for scrollbar ...
933 	extern int uiMarkColor; //marked text color
934 	extern int uiMarkBackground;
935 	extern int uiCurrentItemFrame;
936 	extern int uiLineColor;
937 	extern int uiPointerColor;
938 	extern int uiOdd;
939 
940 	extern int uiVariable;
941 	extern int uiValue;
942 
943 	class Win: public iIntrusiveCounter
944 	{
945 
946 #ifdef _WIN32
947 		friend LRESULT CALLBACK WProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam );
948 #else
949 		friend int DoEvents( XEvent* event );
950 		friend void DrawExposeRect( Win* w );
951 #endif
952 		friend class Layout;
953 		friend struct LItemWin;
954 	public:
955 		enum WTYPE
956 		{
957 			WT_MAIN = 1,
958 			WT_POPUP = 2,
959 			WT_CHILD = 4
960 		};
961 
962 		enum WHINT
963 		{
964 			WH_MINBOX = 8,
965 			WH_MAXBOX = 0x10,
966 			WH_SYSMENU = 0x20,
967 			WH_RESIZE = 0x40,
968 			WH_TABFOCUS = 0x80,
969 			WH_CLICKFOCUS = 0x100,
970 			WH_USEDEFPOS = 0x200 //for WT_MAIN (in win32) use default width and height
971 		};
972 
973 		enum STATE
974 		{
975 			S_VISIBLE = 1,
976 			S_ENABLED = 4
977 		};
978 
979 		enum SHOW_TYPE
980 		{
981 			SHOW_ACTIVE = 0,
982 			SHOW_INACTIVE = 1,
983 			SHOW_MAXIMIZE = 2
984 		};
985 
986 	private:
987 		static WinID focusWinId;
988 
989 		WinID handle;
990 		Win* parent;
991 		wal::ccollect<Win*> childList;
992 		WTYPE type;
993 
994 		WinID blockedBy; //Каким модальным окном заблокировано
995 		void* modal; //если не 0 то окно в модальном состоянии
996 
997 		unsigned whint;
998 		unsigned state;
999 		bool captured;
1000 		WinID lastFocusChild;
1001 
1002 		LSize lSize;
1003 		Layout* upLayout, *layout;
1004 		int uiNameId;
1005 		UiCache uiCache;
1006 
SetState(unsigned s)1007 		void SetState( unsigned s ) { state |= s; }
ClearState(unsigned s)1008 		void ClearState( unsigned s ) { state &= ~s; }
1009 
1010 		bool IsOneParentWith( WinID h );
1011 		void PopupTreeList( ccollect<WinID>& list ); //добавляет в список текущее окно и его попапы
1012 
1013 		Win* FocusNPChild( bool next );
1014 
1015 #ifdef _WIN32
1016 
1017 #else
1018 		WinID reparent; //last reparent id
1019 
1020 
1021 		crect position; // in parent coordinates
1022 		crect exposeRect;
1023 		void AddExposeRect( crect r );
1024 		SHOW_TYPE showType;
1025 
1026 		friend void KeyEvent( int type, XKeyEvent* event );
1027 #endif
1028 	protected:
UiSetNameId(int id)1029 		void UiSetNameId( int id ) { uiNameId = id; }
1030 
1031 #ifdef _WIN32
1032 		class CaptureSD
1033 		{
1034 			friend class Win;
1035 			HWND h;
1036 		public:
CaptureSD()1037 			CaptureSD(): h( 0 ) {};
1038 		};
1039 #else
1040 		class CaptureSD
1041 		{
1042 			friend class Win;
1043 			Window h;
1044 		public:
CaptureSD()1045 			CaptureSD(): h( None ) {};
1046 		};
1047 #endif
1048 
1049 	public:
1050 		Win( WTYPE t, unsigned hints = 0, Win* _parent = nullptr, const crect* rect = nullptr, int uiNId = 0 );
1051 
GetID()1052 		WinID GetID() { return handle; }
Parent()1053 		Win* Parent() { return parent; }
Type()1054 		WTYPE Type() { return type; }
Blocked()1055 		WinID Blocked() { return blockedBy; }
ChildCount()1056 		int ChildCount() { return childList.count(); }
GetChild(int n)1057 		Win* GetChild( int n ) { return ( n >= 0 && n < childList.count() ) ? childList[n] : 0; }
1058 
FocusNextChild()1059 		Win* FocusNextChild() { return FocusNPChild( true ); }
FocusPrevChild()1060 		Win* FocusPrevChild() { return FocusNPChild( false ); }
1061 
1062 		crect ClientRect();
1063 		crect ScreenRect();
1064 		crect Rect();
1065 
1066 		void ClientToScreen( int* x, int* y );
1067 
SetTabFocusFlag(bool enable)1068 		void SetTabFocusFlag( bool enable ) { if ( enable ) { whint |= WH_TABFOCUS; } else { whint &= ~WH_TABFOCUS; } }
SetClickFocusFlag(bool enable)1069 		void SetClickFocusFlag( bool enable ) { if ( enable ) { whint |= WH_CLICKFOCUS; } else { whint &= ~WH_CLICKFOCUS; } }
1070 
Repaint()1071 		virtual void Repaint()
1072 		{
1073 			wal::GC gc( this );
1074 			this->Paint( gc, this->ClientRect() );
1075 		}
1076 
1077 		void Maximize();
1078 		void Show( SHOW_TYPE type = SHOW_ACTIVE );
1079 		void Hide();
1080 
GetLSize(LSize * ls)1081 		void GetLSize( LSize* ls ) { ( state & S_VISIBLE ) ? *ls = lSize : LSize(); }
GetLSize()1082 		LSize GetLSize() { return ( state & S_VISIBLE ) ? lSize : LSize(); }
SetLSize(const LSize & ls)1083 		void SetLSize( const LSize& ls ) { lSize = ls; if ( parent && parent->layout ) { parent->layout->valid = false; } } //main and popup ???
1084 		void RecalcLayouts();
SetLayout(Layout * pl)1085 		void SetLayout( Layout* pl ) { layout = pl; if ( layout ) { SetLSize( layout->GetLSize() ); } RecalcLayouts(); }
1086 
1087 		void SetIdealSize();
1088 		void SetTimer( int id, unsigned period );
1089 		void ResetTimer( int id, unsigned period );
1090 		void DelTimer( int id );
1091 		void DelAllTimers();
1092 
1093 		void ThreadCreate( int id, void* ( *f )( void* ), void* d );
1094 		virtual void ThreadSignal( int id, int data );
1095 		virtual void ThreadStopped( int id, void* data );
1096 
1097 		int DoModal();
IsModal()1098 		bool IsModal() { return modal != 0; }
1099 		void EndModal( int id );
1100 
1101 		void Move( crect rect, bool repaint = true );
1102 
1103 		bool IsEnabled();
InFocus()1104 		virtual bool InFocus() { return handle == focusWinId; }
1105 		bool IsVisible();
1106 		void Enable( bool en = true );
1107 		void Activate();
1108 		bool SetCapture( CaptureSD* sd = nullptr );
1109 		void ReleaseCapture( CaptureSD* sd = nullptr );
1110 		void OnTop();
IsCaptured()1111 		bool IsCaptured() { return captured; }
1112 		void Invalidate();
1113 		virtual void SetFocus();
1114 
1115 		void SetName( const unicode_t* name );
1116 		void SetName( const char* utf8Name );
1117 
UiCacheClear()1118 		void UiCacheClear() { uiCache.Clear(); }
1119 		virtual int UiGetClassId();
UiGetNameId()1120 		int UiGetNameId() { return uiNameId; }
1121 		unsigned UiGetColor( int id, int nodeId, UiCondList* cl, unsigned def );
1122 
1123 		virtual void Paint( GC& gc, const crect& paintRect );
1124 
1125 		virtual bool Event( cevent* pEvent );
1126 		virtual bool EventMouse( cevent_mouse* pEvent );
1127 		virtual bool EventChildKey( Win* child, cevent_key* pEvent );
1128 		// overridden in dialog elements to help dialog winow to find child that matches the hotkey
1129 		// returns window to activate on the hotkey, or 0 if the key is unknown
IsHisHotKey(cevent_key * pEvent)1130 		virtual Win* IsHisHotKey( cevent_key* pEvent ) { return 0; };
1131 		virtual bool EventKey( cevent_key* pEvent );
1132 		virtual bool EventFocus( bool recv );
1133 		virtual bool EventActivate( bool activated, Win* w );
1134 		virtual bool EventShow( bool show );
1135 		virtual bool EventClose();
1136 		virtual void EventEnterLeave( cevent* pEvent );
1137 		virtual void EventTimer( int tid );
1138 		virtual void EventSize( cevent_size* pEvent );
1139 		virtual void EventMove( cevent_move* pEvent );
1140 
1141 //	virtual void EventMouseLeave();
1142 
1143 		virtual bool Command( int id, int subId, Win* win, void* data ); //control command or info
1144 		virtual bool Broadcast( int id, int subId, Win* win, void* data );
1145 
1146 		int SendBroadcast( int id, int subId, Win* win, void* data, int level = 1 );
1147 
1148 		virtual ~Win();
1149 
1150 		//Not for each
Block(WinID id)1151 		void Block( WinID id ) { if ( !blockedBy ) { blockedBy = id; } }
Unblock(WinID id)1152 		void Unblock( WinID id ) { if ( blockedBy == id ) { blockedBy = 0; } }
1153 		bool UnblockTree( WinID id );
1154 
1155 
1156 		//Fonts ...
1157 		virtual cfont* GetChildFont( Win* w, int fontId );
1158 
1159 		cfont* GetFont( int fontId = 0 ) { return parent ? parent->GetChildFont( this, fontId ) : SysGetFont( this, fontId ); }
1160 
1161 		//вызывается при изменении фонтов или каких то глобальных параметров, которые могут поменять пропорции окон
1162 		//в функции нужно пересчитать LSize
1163 		virtual void OnChangeStyles();
1164 
1165 		//вызывает у всех дочерних окон OnChangeStyles и RecalcLayouts
1166 		static void StylesChanged( Win* w );
1167 
1168 #ifndef _WIN32
1169 		static void SetIcon( const char** xpm );
1170 #endif
1171 #if defined _DEBUG
1172 		void dbg_dump(int indent=0);
1173 #else
dbg_dump()1174 		void dbg_dump(){}
1175 #endif
1176 
1177 	};
1178 
1179 	bool WinThreadSignal( int data ); //signalize window from thread
1180 
1181 
1182 	class ClipboardText
1183 	{
1184 		enum { BUF_SIZE = 1024 };
1185 		ccollect< std::vector<unicode_t>, 0x100 > list;
1186 		int count;
1187 		void CopyFrom( const ClipboardText& a );
1188 	public:
1189 		ClipboardText();
Count()1190 		int Count() const  { return count; }
1191 		void Clear();
1192 		void Append( unicode_t c );
1193 		void AppendUnicodeStr( const unicode_t* c );
1194 		ClipboardText( const ClipboardText& a );
1195 		ClipboardText& operator = ( const ClipboardText& a );
Get(int n)1196 		unicode_t Get( int n ) const
1197 		{
1198 			ASSERT( n >= 0 && n < count );
1199 			return n >= 0 && n < count ? list.const_item( n / BUF_SIZE ).at( n % BUF_SIZE ) : 0;
1200 		}
1201 		unicode_t operator[]( int n ) const { return Get( n ); }
1202 	};
1203 
1204 
1205 	void ClipboardSetText( Win* w, ClipboardText& text );
1206 	void ClipboardGetText( Win* w, ClipboardText* text );
1207 	void ClipboardClear();
1208 }; //namespace wal
1209 
1210 namespace wal
1211 {
1212 	cpoint GetScreenSize();
1213 	cpoint StaticTextSize( GC& gc, const unicode_t* s, cfont* font = 0 );
1214 	void DrawStaticText( GC& gc, int x, int y, const unicode_t* s, cfont* font = 0, bool transparent = true );
1215 	unsigned ColorTone( unsigned color, int tone /*0-255*/ );
1216 	void DrawPixelList( GC& gc, unsigned short* s, int x, int y, unsigned color );
1217 	void Draw3DButtonW2( GC& gc, crect r, unsigned bg, bool up );
1218 
DrawBorder(GC & gc,crect r,unsigned color)1219 	inline void DrawBorder( GC& gc, crect r, unsigned color )
1220 	{
1221 		gc.SetLine( color );
1222 		gc.MoveTo( r.right - 1, r.top );
1223 		gc.LineTo( r.left, r.top );
1224 		gc.LineTo( r.left, r.bottom - 1 );
1225 		gc.LineTo( r.right - 1, r.bottom - 1 );
1226 		gc.LineTo( r.right - 1, r.top );
1227 	}
1228 
1229 	extern void UiReadFile( const sys_char_t* fileName ); //can throw
1230 	extern void UiReadMem( const char* s ); //can throw
1231 
1232 }; //namespace wal
1233