Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1805 yogev_ezra 1
#ifndef __MENUET_H_INCLUDED_
2
#define __MENUET_H_INCLUDED_
3
 
4
#include 
5
 
6
// Menuet interface.
7
 
8
namespace Menuet   // All menuet functions, types and data are nested in the (Menuet) namespace.
9
{
10
	const char *DebugPrefix = "User program: ";
11
 
12
	struct TWindowData   // Data for drawing a window.
13
	{
14
		unsigned short WindowType, HeaderType;
15
		unsigned long WindowColor, HeaderColor, BorderColor, TitleColor;
16
		const char *Title;
17
	};
18
 
19
	struct TStartData   // This structure is used only for MenuetOnStart function.
20
	{
21
		unsigned short Left, Width, Top, Height; // Initial window rectangle.
22
		TWindowData WinData;
23
	};
24
 
25
	typedef void **TThreadData;   // Thread data are the fast identifier of thread, contains user dword in
26
			//_ the zero element and stack beginning (or zero if it is unknown) in the first element.
27
			//_ The stack will be deleted from dynamic memory at the finish of the thread if stack beginning is not zero.
28
 
29
	struct TMutex;   // Simple mutex can be locked only once at a time.
30
#define MENUET_MUTEX_INIT {}   // Simple mutex initializer, cat be redefined in a realization of the library
31
 
32
	struct TRecMutex;   // Recursive mutex can be locked many times by a single thread at a time.
33
#define MENUET_REC_MUTEX_INIT {}   // Recursive mutex initializer, cat be redefined in a realization of the library
34
 
35
	// Some functions have two forms: the fast form with (thread_data) parameter and the form without it.
36
	// Note: pass only thread data of current thread as (thread_data) parameter to these functions.
37
 
38
	void Main();   // Main function is called at program startup.
39
	void* ThreadMain(void *user = 0, void *stack_begin = 0);
40
			// Called at thread startup, (user) is placed in thread data as a user dword,
41
			//_ (stack_begin) is placed in thread data as a stack beginning.
42
			//_ Return new value of stack beginning that can be changed in the thread data.
43
	void GetWindowData(TWindowData &win_data);   // Write current window data to (win_data).
44
	void GetWindowData(TWindowData &win_data, TThreadData thread_data);
45
	void SetWindowData(const TWindowData &win_data);   // Replace current window data by (win_data).
46
	void SetWindowData(const TWindowData &win_data, TThreadData thread_data);
47
	void CloseWindow();   // Close current window when returning to message loop.
48
	void CloseWindow(TThreadData thread_data);
49
	void Redraw(int frame = 0);   // Redraw current window immediately, if (frame) is positive redraw the frame too,
50
	void Redraw(int frame, TThreadData thread_data);   //_ if (frame) is negative redraw only invalideted window.
51
	void Invalidate(int frame = 0);   // Redraw current window when no message will be is the queue,
52
	void Invalidate(int frame, TThreadData thread_data);   //_ if (frame) is positive redraw the frame too,
53
														   //_ if (frame) is negative do nothing.
54
	void MoveWindow(const int window_rect[/* 4 */]);   // Move and resize current window.
55
 
56
	void Abort();   // Abnormally terminate a program.
57
	void ExitProcess();   // Exit from the process, don't call any destructors of global varyables
58
	void ExitThread();   // Exit from the current thread
59
	void ExitThread(TThreadData thread_data);
60
	void ReturnMessageLoop();   // Return to the message loop of the thread. Exit from the thread
61
	void ReturnMessageLoop(TThreadData thread_data);   //_ if it is called from (MenuetOnStart).
62
 
63
	void Delay(unsigned int time);   // Delay the execution of the program during (time) hundredth seconds.
64
	unsigned int Clock();   // Return the time from starting of the system to this moment in hundredth of seconds.
65
	int GetPackedTime();   // Return the current time of day in binary-decimal format 0x00SSMMHH.
66
	void GetTime(int t[/* 3 */]);   // Write the current time to (t): t[0] = second, t[1] = minute, t[2] = hour.
67
	int GetPackedDate();   // Return the current date in binary-decimal format 0x00YYDDMM.
68
	void GetDate(int d[/* 3 */]);   // Write the current date to (d): d[0] = day, d[1] = month, d[2] = year.
69
	void GetTimeDate(int t[/* 6 */]);   // Write the current time and date to (t): t[0] = second,
70
										//_ t[1] = minute, t[2] = hour, t[3] = day, t[4] = month, t[5] = year.
71
	void ReadCommonColors(unsigned int colors[/* 10 */]);   // Writes standart window colors to (colors).
72
	unsigned int GetProcessInfo(unsigned int *use_cpu, char process_name[/* 13 */], unsigned int *use_memory,
73
								unsigned int *pid, int window_rect[/* 4 */], unsigned int pid_for = -1);
74
								// Write (pid_for) process information to variables parameters points, return
75
								//_ the number of processes. (pid_for) equal to (-1) means current process.
76
	unsigned int GetPid();   // Return the current thread identifier (pid).
77
	unsigned int GetPid(TThreadData thread_data);
78
	TThreadData GetThreadData();   // Return the thread data of the current thread.
79
	TThreadData GetThreadData(unsigned int pid);   // Return the thread data of the thread with the given pid.
80
 
81
	void* GetPicture(unsigned short &width, unsigned short &height);
82
	void* GetPicture(unsigned short &width, unsigned short &height, TThreadData thread_data);
83
			// Return the picture on the window and write its width and height to (width) and (height).
84
	void SetPicture(void *picture, unsigned short width, unsigned short height);
85
	void SetPicture(void *picture, unsigned short width, unsigned short height, TThreadData thread_data);
86
			// Replace the picture on the window by the given picture with the given width and height.
87
	void GetBorderHeader(unsigned short &border_size, unsigned short &header_size);
88
	void GetBorderHeader(unsigned short &border_size, unsigned short &header_size, TThreadData thread_data);
89
			// Write the border thickness to (border_size) and header height to (header_size).
90
	void GetClientSize(unsigned short &width, unsigned short &height);
91
	void GetClientSize(unsigned short &width, unsigned short &height, TThreadData thread_data);
92
			// Write the client area width and height to (width) and (height) parameters.
93
	void GetClientSize(unsigned short &width, unsigned short &height, int win_width, int win_height);
94
	void GetClientSize(unsigned short &width, unsigned short &height, int win_width, int win_height, TThreadData thread_data);
95
			// Write the client area size of window with the width (win_width)
96
			//_ and height (win_height) to (width) and (height) parameters.
97
	void GetScreenSize(unsigned short &width, unsigned short &height);
98
			// Write the screen width and height to (width) and (height) parameters.
99
 
100
	void InitMutex(TMutex *mutex);   // Initialize the simple mutex.
101
	void InitRecMutex(TRecMutex *mutex);   // Initialize the recursive mutex.
102
	bool TryLock(TMutex *mutex);   // Try to lock the mutex without waitting, return true if lock.
103
	bool TryLock(TRecMutex *mutex);
104
	bool TryLock(TRecMutex *mutex, TThreadData thread_data);
105
	bool TryLock(TRecMutex *mutex, unsigned int pid);
106
	void Lock(TMutex *mutex);   // Lock mutex and wait for it if this necessary.
107
	void Lock(TRecMutex *mutex);
108
	void Lock(TRecMutex *mutex, TThreadData thread_data);
109
	void Lock(TRecMutex *mutex, unsigned int pid);
110
	bool LockTime(TMutex *mutex, int time);
111
	bool LockTime(TRecMutex *mutex, int time);   // Lock mutex and wait for it during (time) hundredth seconds.
112
	bool LockTime(TRecMutex *mutex, int time, TThreadData thread_data);
113
	bool LockTime(TRecMutex *mutex, int time, unsigned int pid);
114
	void UnLock(TMutex *mutex);   // Unlock mutex
115
	void UnLock(TRecMutex *mutex);
116
	void UnLock(TRecMutex *mutex, TThreadData thread_data);
117
	void UnLock(TRecMutex *mutex, unsigned int pid);
118
 
119
	void DebugPutChar(char c);   // Put the character to the debug board.
120
	void DebugPutString(const char *s);   // Put the string to the debug board.
121
	int GetKey();   // Return key pressed by user or -1 if no key was pressed.
122
	int GetMouseButton();   // Return buttons pressed: 0 - no buttons, 1 - left button, 2 - right button, 3 - both buttons.
123
	void GetMousePosition(short &x, short &y, bool absolute = false);
124
			// Write mouse position to (x) and (y): absolute if (absolute) is true and relative the window otherwise.
125
	void GetMousePosPicture(short &x, short &y);
126
 
127
	int GetThreadNumber();   // Return the number of threads currently executing.
128
	bool WasThreadCreated();   // Return true if there was created at least one thread except the main thred.
129
	unsigned int CreateThread(void *user = 0, unsigned int stack_size = 0, void *stack_end = 0);
130
			// Create a new thread with the user dword (user) and stack pointer (stack_end).
131
			//_ If (stack_end) is zero, create stack in dynamic memory of size (stack_size) or
132
			//_ the same size as the main thread if (stack_size) less that 4096. Set the beginning
133
			//_ of the stack if (stack_end) is zero or (stack_size) is not zero, in this case stack
134
			//_ will be deleted automaticaly from dynamic memory at the finish of the thread.
135
}
136
 
137
// Function, defined outside.
138
 
139
bool MenuetOnStart(Menuet::TStartData &me_start, Menuet::TThreadData thread_data);
140
			// Window will be created iff return value is true.
141
bool MenuetOnClose(Menuet::TThreadData thread_data);     // Window will be closed iff return value is true.
142
int MenuetOnIdle(Menuet::TThreadData thread_data);       // Return the time to wait next message.
143
void MenuetOnSize(int window_rect[/* 4 */], Menuet::TThreadData thread_data);  // When the window is resized.
144
void MenuetOnKeyPress(Menuet::TThreadData thread_data);  // When user press a key.
145
void MenuetOnMouse(Menuet::TThreadData thread_data);     // When user move a mouse.
146
 
147
#ifdef __MENUET__
148
 
149
namespace Menuet
150
{
151
// Structures.
152
 
153
	struct TMutex   // Simple mutex can be locked only once at a time.
154
	{
155
		unsigned int mut;
156
	};
157
#undef  MENUET_MUTEX_INIT
158
#define MENUET_MUTEX_INIT {0x40}   // Simple mutex initializer, cat be redefined in a realization of the library
159
 
160
	struct TRecMutex   // Recursive mutex can be locked many times by a single thread at a time.
161
	{
162
		unsigned int mut, pid;
163
	};
164
#undef  MENUET_REC_MUTEX_INIT
165
#define MENUET_REC_MUTEX_INIT {0x20,-1}   // Recursive mutex initializer, cat be redefined in a realization of the library
166
 
167
// Global variables.
168
 
169
	volatile TThreadData _ThreadTable[256];
170
	volatile unsigned int _ThreadScanCount[2] = {0, 0};
171
	volatile int _ThreadNumber = 1;
172
	volatile int _ExitProcessNow = 0;
173
	TMutex _ThreadMutex = MENUET_MUTEX_INIT;
174
	unsigned int _ThreadSavedBegProc[4];
175
 
176
// Inline functions.
177
 
178
	inline void GetWindowData(TWindowData &win_data) {GetWindowData(win_data, GetThreadData());}
179
 
180
	inline void SetWindowData(const TWindowData &win_data) {SetWindowData(win_data, GetThreadData());}
181
 
182
	inline void CloseWindow() {CloseWindow(GetThreadData());}
183
 
184
	inline void Redraw(int frame) {Redraw(frame, GetThreadData());}
185
 
186
	inline void Invalidate(int frame) {Invalidate(frame, GetThreadData());}
187
 
188
	inline void* GetPicture(unsigned short &width, unsigned short &height)
189
	{
190
		return GetPicture(width, height, GetThreadData());
191
	}
192
 
193
	inline void SetPicture(void *picture, unsigned short width, unsigned short height)
194
	{
195
		SetPicture(picture, width, height, GetThreadData());
196
	}
197
 
198
	inline void GetBorderHeader(unsigned short &border_size, unsigned short &header_size)
199
	{
200
		GetBorderHeader(border_size, header_size, GetThreadData());
201
	}
202
 
203
	inline void GetClientSize(unsigned short &width, unsigned short &height)
204
	{
205
		unsigned int pid;
206
		int rect[4];
207
		GetProcessInfo(0, 0, 0, &pid, rect);
208
		GetClientSize(width, height, rect[2], rect[3], GetThreadData(pid));
209
	}
210
 
211
	inline void GetClientSize(unsigned short &width, unsigned short &height, TThreadData thread_data)
212
	{
213
		int rect[4];
214
		GetProcessInfo(0, 0, 0, 0, rect);
215
		GetClientSize(width, height, rect[2], rect[3], thread_data);
216
	}
217
 
218
	inline void GetClientSize(unsigned short &width, unsigned short &height, int win_width, int win_height)
219
	{
220
		GetClientSize(width, height, win_width, win_height, GetThreadData());
221
	}
222
 
223
	inline void GetTimeDate(int t[/* 6 */]) {GetTime(t); GetDate(t + 3);}
224
 
225
	inline void InitMutex(TMutex *mutex) {mutex->mut = 0;}
226
 
227
	inline void InitRecMutex(TRecMutex *mutex) {mutex->mut = 0; mutex->pid = -1;}
228
 
229
	inline bool TryLock(TRecMutex *mutex) {return TryLock(mutex, GetPid());}
230
 
231
	inline bool TryLock(TRecMutex *mutex, TThreadData thread_data) {return TryLock(mutex, GetPid(thread_data));}
232
 
233
	inline void Lock(TRecMutex *mutex) {Lock(mutex, GetPid());}
234
 
235
	inline void Lock(TRecMutex *mutex, TThreadData thread_data) {Lock(mutex, GetPid(thread_data));}
236
 
237
	inline bool LockTime(TRecMutex *mutex, int time) {return LockTime(mutex, time, GetPid());}
238
 
239
	inline bool LockTime(TRecMutex *mutex, int time, TThreadData thread_data)
240
				{return LockTime(mutex, time, GetPid(thread_data));}
241
 
242
	inline void UnLock(TRecMutex *mutex) {UnLock(mutex, GetPid());}
243
 
244
	inline void UnLock(TRecMutex *mutex, TThreadData thread_data) {UnLock(mutex, GetPid(thread_data));}
245
 
246
	inline int GetThreadNumber() {return _ThreadNumber;}
247
 
248
// Constants from fasm.
249
 
250
#include 
251
 
252
// Functions.
253
 
254
	unsigned char _HashByte(unsigned int value);
255
	unsigned short _HashWord(unsigned int value);
256
	unsigned int _HashDword(unsigned int value);
257
 
258
	void _GetStartData(TStartData &start_data, TThreadData thread_data)
259
	{
260
		start_data.Left = (unsigned short)((unsigned long)thread_data[MENUET_THREAD_DATA_X] >> 16);
261
		start_data.Width = (unsigned short)((unsigned long)thread_data[MENUET_THREAD_DATA_X]);
262
		start_data.Top = (unsigned short)((unsigned long)thread_data[MENUET_THREAD_DATA_Y] >> 16);
263
		start_data.Height = (unsigned short)((unsigned long)thread_data[MENUET_THREAD_DATA_Y]);
264
		GetWindowData(start_data.WinData, thread_data);
265
	}
266
 
267
	void _SetStartData(const TStartData &start_data, TThreadData thread_data)
268
	{
269
		(unsigned long&)thread_data[MENUET_THREAD_DATA_X] =
270
					((unsigned int)start_data.Left << 16) | start_data.Width;
271
		(unsigned long&)thread_data[MENUET_THREAD_DATA_Y] =
272
					((unsigned int)start_data.Top << 16) | start_data.Height;
273
		SetWindowData(start_data.WinData, thread_data);
274
	}
275
 
276
	void _ApplyCommonColors(TWindowData &win_data)
277
	{
278
		unsigned int colors[10];
279
		ReadCommonColors(colors);
280
		win_data.WindowColor = colors[5];
281
		win_data.HeaderColor = colors[1];
282
		win_data.BorderColor = colors[0];
283
		win_data.TitleColor = colors[4];
284
	}
285
 
286
	void _SetValueFunctionPriority(void *beg, int n)
287
	{
288
		int k, i;
289
		unsigned char num[256];
290
		for (i = 0; i < 256; i++) num[i] = 0;
291
		for (k = 0; k < n; k++)
292
		{
293
			i = ((unsigned char*)beg + 6*k)[1];
294
			((unsigned char*)beg + 6*k)[0] = num[i];
295
			if (num[i] != 255) num[i]++;
296
		}
297
	}
298
 
299
	void _CallFunctionPriority(void *beg, void *end, bool reverse = false)
300
	{
301
		struct _Local
302
		{
303
			static int cmp(void *beg, int i, int j)
304
			{
305
				unsigned char *x = (unsigned char*)beg + 6*i;
306
				unsigned char *y = (unsigned char*)beg + 6*j;
307
				if (*(unsigned short*)x < *(unsigned short*)y) return -1;
308
				if (*(unsigned short*)x > *(unsigned short*)y) return 1;
309
				return 0;
310
			}
311
 
312
			static void swap(void *beg, int i, int j)
313
			{
314
				unsigned char *x = (unsigned char*)beg + 6*i;
315
				unsigned char *y = (unsigned char*)beg + 6*j;
316
				short s;
317
				int t;
318
				s = *(short*)x; *(short*)x = *(short*)y; *(short*)y = s;
319
				x += 2; y += 2;
320
				t = *(int*)x; *(int*)x = *(int*)y; *(int*)y = t;
321
			}
322
 
323
			static void call(void *beg, int i)
324
			{
325
				unsigned char *x = (unsigned char*)beg + 6*i;
326
				(*(void(**)())(x+2))();
327
			}
328
		};
329
 
330
		if (!beg || !end || end <= beg) return;
331
		int i, j, k, m, n;
332
		n = ((unsigned char*)end - (unsigned char*)beg) / 6;
333
		if (n <= 0) return;
334
		_SetValueFunctionPriority(beg, n);
335
		m = n; k = n;
336
		while (m > 1)
337
		{
338
			if (k > 0) k--;
339
			else _Local::swap(beg, 0, --m);
340
			j = k;
341
			for (;;)
342
			{
343
				 i = j;
344
				 if (2*i + 1 >= m) break;
345
				 if (_Local::cmp(beg, 2*i + 1, j) > 0) j = 2*i + 1;
346
				 if (2*i + 2 < m && _Local::cmp(beg, 2*i + 2, j) > 0) j = 2*i + 2;
347
				 if (i == j) break;
348
				 _Local::swap(beg, i, j);
349
			}
350
		}
351
		if (!reverse)
352
		{
353
			for (k = 0; k < n; k++) _Local::call(beg, k);
354
		}
355
		else
356
		{
357
			for (k = n-1; k >= 0; k--) _Local::call(beg, k);
358
		}
359
	}
360
 
361
	bool _CallStart(TThreadData thread_data, void *init = 0, void *init_end = 0)
362
	{
363
		struct _TThreadDataTemplate
364
		{
365
			unsigned int data[12];
366
		};
367
		static const _TThreadDataTemplate _ThreadDataTemplate =
368
			{{3, 0x00320100, 0x00320100, 0x33FFFFFF, 0x806060FF, 0x00000000, 0x00FFFF40, 0, 0, 0, -1, -1}};
369
 
370
		unsigned int pid = GetPid();
371
		volatile TThreadData *thread_table_item;
372
		Lock(&_ThreadMutex);
373
		if (_ExitProcessNow) ExitProcess();
374
		thread_table_item = &_ThreadTable[_HashByte(pid)];
375
		thread_data[MENUET_THREAD_DATA_NEXT] = (void*)*thread_table_item;
376
		(unsigned int&)thread_data[MENUET_THREAD_DATA_PID] = pid;
377
		*(_TThreadDataTemplate*)(thread_data + MENUET_THREAD_DATA_FLAG) = _ThreadDataTemplate;
378
		*thread_table_item = thread_data;
379
		UnLock(&_ThreadMutex);
380
		if (_ExitProcessNow) ExitProcess();
381
		_CallFunctionPriority(init, init_end, false);
382
		TStartData start_data;
383
		_GetStartData(start_data, thread_data);
384
//		_ApplyCommonColors(start_data.WinData);
385
		(unsigned int&)thread_data[MENUET_THREAD_DATA_FLAG] |= 0x40000000;
386
		thread_data[MENUET_THREAD_DATA_TITLE] = (void*)(&start_data);
387
		if (!MenuetOnStart(start_data, thread_data)) return false;
388
		(unsigned int&)thread_data[MENUET_THREAD_DATA_FLAG] &= ~0x40000000;
389
		_SetStartData(start_data, thread_data);
390
		return true;
391
	}
392
 
393
	void _RemoveThreadData(TThreadData thread_data, void *exit = 0, void *exit_end = 0)
394
	{
395
		_CallFunctionPriority(exit, exit_end, true);
396
		volatile TThreadData *thread_table_item;
397
		Lock(&_ThreadMutex);
398
		if (_ExitProcessNow) ExitProcess();
399
		thread_table_item = &_ThreadTable[_HashByte(GetPid(thread_data))];
400
		while (*thread_table_item)
401
		{
402
			if (*thread_table_item == thread_data)
403
			{
404
				*thread_table_item = (TThreadData)thread_data[MENUET_THREAD_DATA_NEXT];
405
				break;
406
			}
407
			thread_table_item = (TThreadData*)(*thread_table_item + MENUET_THREAD_DATA_NEXT);
408
		}
409
		UnLock(&_ThreadMutex);
410
		if (_ExitProcessNow) ExitProcess();
411
	}
412
 
413
	void GetWindowData(TWindowData &win_data, TThreadData thread_data)
414
	{
415
		if ((unsigned int)thread_data[MENUET_THREAD_DATA_FLAG] & 0x40000000)
416
		{
417
			win_data = ((TStartData*)thread_data[MENUET_THREAD_DATA_TITLE])->WinData;
418
			return;
419
		}
420
		win_data.WindowType = (unsigned short)((unsigned int)thread_data[MENUET_THREAD_DATA_C_WINDOW] >> 24);
421
		win_data.HeaderType = (unsigned short)((unsigned int)thread_data[MENUET_THREAD_DATA_C_HEADER] >> 24);
422
		win_data.WindowColor = (unsigned int)thread_data[MENUET_THREAD_DATA_C_WINDOW] & 0xFFFFFF;
423
		win_data.HeaderColor = (unsigned int)thread_data[MENUET_THREAD_DATA_C_HEADER] & 0xFFFFFF;
424
		win_data.BorderColor = (unsigned int)thread_data[MENUET_THREAD_DATA_C_BORDER] & 0xFFFFFF;
425
		win_data.TitleColor = (unsigned int)thread_data[MENUET_THREAD_DATA_C_TITLE] & 0xFFFFFF;
426
		win_data.Title = (char*)thread_data[MENUET_THREAD_DATA_TITLE];
427
	}
428
 
429
	void SetWindowData(const TWindowData &win_data, TThreadData thread_data)
430
	{
431
		if ((unsigned int)thread_data[MENUET_THREAD_DATA_FLAG] & 0x40000000)
432
		{
433
			((TStartData*)thread_data[MENUET_THREAD_DATA_TITLE])->WinData = win_data;
434
			return;
435
		}
436
		(unsigned int&)thread_data[MENUET_THREAD_DATA_C_WINDOW] =
437
					((unsigned int)win_data.WindowType << 24) | (win_data.WindowColor & 0xFFFFFF);
438
		(unsigned int&)thread_data[MENUET_THREAD_DATA_C_HEADER] =
439
					((unsigned int)win_data.HeaderType << 24) | (win_data.HeaderColor & 0xFFFFFF);
440
		(unsigned int&)thread_data[MENUET_THREAD_DATA_C_BORDER] = win_data.BorderColor & 0xFFFFFF;
441
		(unsigned int&)thread_data[MENUET_THREAD_DATA_C_TITLE] = win_data.TitleColor & 0xFFFFFF;
442
		thread_data[MENUET_THREAD_DATA_TITLE] = (void*)win_data.Title;
443
		Invalidate(1, thread_data);
444
	}
445
 
446
	void CloseWindow(TThreadData thread_data)
447
	{
448
		(unsigned int&)thread_data[MENUET_THREAD_DATA_FLAG] |= 0x80000000;
449
	}
450
 
451
	void Invalidate(int frame, TThreadData thread_data)
452
	{
453
		if (frame < 0) return;
454
		(unsigned int&)thread_data[MENUET_THREAD_DATA_FLAG] |= (frame ? 3 : 1);
455
	}
456
 
457
	void* GetPicture(unsigned short &width, unsigned short &height, TThreadData thread_data)
458
	{
459
		width = (unsigned short)((unsigned int)thread_data[MENUET_THREAD_DATA_SZ_PICT] >> 16);
460
		height = (unsigned short)((unsigned int)thread_data[MENUET_THREAD_DATA_SZ_PICT]);
461
		return (void*)thread_data[MENUET_THREAD_DATA_PICTURE];
462
	}
463
 
464
	void SetPicture(void *picture, unsigned short width, unsigned short height, TThreadData thread_data)
465
	{
466
		thread_data[MENUET_THREAD_DATA_PICTURE] = (void*)picture;
467
		(unsigned int&)thread_data[MENUET_THREAD_DATA_SZ_PICT] =
468
					(width == 0 || height == 0) ? 0 : (((unsigned int)width << 16) | height);
469
		Invalidate(0, thread_data);
470
	}
471
 
472
	int _GetSkinHeader();
473
 
474
	void GetBorderHeader(unsigned short &border_size, unsigned short &header_size, TThreadData thread_data)
475
	{
476
		int win_type = ((unsigned int)thread_data[MENUET_THREAD_DATA_FLAG] & 0x40000000) ?
477
			((TStartData*)thread_data[MENUET_THREAD_DATA_TITLE])->WinData.WindowType :
478
		   ((unsigned int)thread_data[MENUET_THREAD_DATA_C_WINDOW] >> 24);
479
		border_size = MENUET_BORDER_SIZE;
480
		header_size = short(((win_type & 15) == 3) ? _GetSkinHeader() : MENUET_HEADER_SIZE);
481
	}
482
 
483
	void GetClientSize(unsigned short &width, unsigned short &height,
484
						int win_width, int win_height, TThreadData thread_data)
485
	{
486
		const int MAX_SIZE = 32767;
487
		unsigned short border_size, header_size;
488
		GetBorderHeader(border_size, header_size, thread_data);
489
		win_width -= 2 * border_size;
490
		win_height -= border_size + header_size;
491
		if (win_width < 0) win_width = 0;
492
		else if (win_width > MAX_SIZE) win_width = MAX_SIZE;
493
		if (win_height < 0) win_height = 0;
494
		else if (win_height > MAX_SIZE) win_height = MAX_SIZE;
495
		width = (unsigned short)win_width;
496
		height = (unsigned short)win_height;
497
	}
498
 
499
	void GetMousePosPicture(short &x, short &y)
500
	{
501
		unsigned short dx, dy;
502
		GetMousePosition(x, y);
503
		GetBorderHeader(dx, dy);
504
		x -= dx; y -= dy;
505
	}
506
}
507
 
508
#else   // def __MENUET__
509
 
510
namespace Menuet
511
{
512
	struct TMutex
513
	{
514
		unsigned int mut;
515
 
516
		TMutex();
517
		~TMutex();
518
	};
519
#undef  MENUET_MUTEX_INIT
520
#define MENUET_MUTEX_INIT  TMutex()
521
 
522
	struct TRecMutex
523
	{
524
		unsigned int mut;
525
 
526
		TRecMutex();
527
		~TRecMutex();
528
	};
529
#undef  MENUET_REC_MUTEX_INIT
530
#define MENUET_REC_MUTEX_INIT  TRecMutex()
531
}
532
 
533
#endif  // else: def __MENUET__
534
 
535
#endif  // ndef __MENUET_H_INCLUDED_
536