Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
1769 yogev_ezra 1
#include 
2
#include 
3
#include 
4
#include 
5
#include 
6
#include 
7
#include 
8
 
9
#include 
10
#include 
11
#include 
12
 
13
using namespace Menuet;
14
using namespace std;
15
 
16
const char file_prefix[] = "";
17
bool WasThreadCreatedBool = false;
18
 
19
struct TExceptToMessageLoop
20
{
21
	TExceptToMessageLoop() {}
22
};
23
 
24
struct TThreadDataStruct
25
{
26
	void *user;
27
	void *stack_begin;
28
	TWindowData *win_data;
29
	HWND hwnd;
30
	int flag;
31
	unsigned int win_time, me_time;
32
	void *picture;
33
	unsigned int picture_width, picture_height;
34
	deque *keys;
35
	unsigned int bmp_data_length;
36
	unsigned int *bmp_data;
37
	unsigned int mouse_state;
38
};
39
 
40
TThreadDataStruct /*__thread*/ ThreadDataStruct;
41
int nCmdShow;
42
HINSTANCE hInstance;
43
const char szWindowClass[] = "Menuet window";
44
 
45
void FinalizeThreadData()
46
{
47
	if (ThreadDataStruct.keys)
48
	{
49
		delete ThreadDataStruct.keys;
50
		ThreadDataStruct.keys = 0;
51
	}
52
	if (ThreadDataStruct.bmp_data)
53
	{
54
		delete[] ThreadDataStruct.bmp_data;
55
		ThreadDataStruct.bmp_data = 0;
56
	}
57
}
58
 
59
unsigned int CalculateNewTime()
60
{
61
	unsigned int t = GetTickCount();
62
	unsigned int dt = (unsigned int)(t - ThreadDataStruct.win_time) / 10U;
63
	ThreadDataStruct.me_time += dt;
64
	ThreadDataStruct.win_time += dt * 10;
65
	return t;
66
}
67
 
68
void DrawPicture(HDC hdc)
69
{
70
	TRecMutex xm;
71
	InitRecMutex(&xm);
72
	Lock(&xm);
73
	UnLock(&xm);
74
 
75
	int w = ThreadDataStruct.picture_width, h = ThreadDataStruct.picture_height;
76
	RECT rect;
77
	if (!ThreadDataStruct.picture || !ThreadDataStruct.hwnd || w <= 0 || h <= 0) return;
78
	if (GetClientRect(ThreadDataStruct.hwnd, &rect))
79
	{
80
		rect.right -= rect.left; rect.left = 0;
81
		rect.bottom -= rect.top; rect.top = 0;
82
		if (rect.right <= 0 || rect.bottom <= 0) return;
83
		if (w > rect.right) w = rect.right;
84
		if (h > rect.bottom) h = rect.bottom;
85
	}
86
	if (!ThreadDataStruct.bmp_data || ThreadDataStruct.bmp_data_length < w * h)
87
	{
88
		if (ThreadDataStruct.bmp_data) delete[] ThreadDataStruct.bmp_data;
89
		ThreadDataStruct.bmp_data_length = w * h;
90
		ThreadDataStruct.bmp_data = new unsigned int[ThreadDataStruct.bmp_data_length];
91
	}
92
	int i;
93
	unsigned char *p = (unsigned char*)ThreadDataStruct.picture;
94
	for (i = 0; i < w * h; i++)
95
	{
96
		ThreadDataStruct.bmp_data[i] = ((unsigned int)p[0]) +
97
				((unsigned int)p[1] << 8) + ((unsigned int)p[2] << 16);
98
		p += 3;
99
	}
100
	HBITMAP bitmap = CreateBitmap(w, h, 1, 32, ThreadDataStruct.bmp_data);
101
	if (bitmap)
102
	{
103
		HDC memdc = CreateCompatibleDC(hdc);
104
		if (memdc)
105
		{
106
			SelectObject(memdc, bitmap);
107
			BitBlt(hdc, 0, 0, w, h, memdc, 0, 0, SRCCOPY);
108
			DeleteObject(memdc);
109
		}
110
		DeleteObject(bitmap);
111
	}
112
}
113
 
114
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
115
{
116
	const int timeout = 20;
117
	unsigned int t;
118
	PAINTSTRUCT ps;
119
	HDC hdc;
120
	if (hWnd == ThreadDataStruct.hwnd && ThreadDataStruct.flag != -1)
121
	{
122
		int window_rect[4];
123
		switch (message)
124
		{
125
		case WM_CREATE:
126
			SetTimer(hWnd, 0, timeout, NULL);
127
			SendMessage(hWnd, WM_SIZE, SIZE_RESTORED, 0);
128
			return 0;
129
		case WM_TIMER:
130
			t = CalculateNewTime();
131
			while (MenuetOnIdle((TThreadData)(&ThreadDataStruct)) == 0 &&
132
					GetTickCount() - t + 2 < timeout);
133
			return 0;
134
		case WM_MOUSEMOVE:
135
			MenuetOnMouse((TThreadData)(&ThreadDataStruct));
136
			return 0;
137
		case WM_LBUTTONDOWN:
138
			if (!ThreadDataStruct.mouse_state) SetCapture(hWnd);
139
			ThreadDataStruct.mouse_state |= 1;
140
			MenuetOnMouse((TThreadData)(&ThreadDataStruct));
141
			return 0;
142
		case WM_LBUTTONUP:
143
			if (ThreadDataStruct.mouse_state & 1)
144
			{
145
				ThreadDataStruct.mouse_state &= ~1;
146
				if (!ThreadDataStruct.mouse_state) ReleaseCapture();
147
				MenuetOnMouse((TThreadData)(&ThreadDataStruct));
148
			}
149
			return 0;
150
		case WM_RBUTTONDOWN:
151
			if (!ThreadDataStruct.mouse_state) SetCapture(hWnd);
152
			ThreadDataStruct.mouse_state |= 2;
153
			MenuetOnMouse((TThreadData)(&ThreadDataStruct));
154
			return 0;
155
		case WM_RBUTTONUP:
156
			if (ThreadDataStruct.mouse_state & 2)
157
			{
158
				ThreadDataStruct.mouse_state &= ~2;
159
				if (!ThreadDataStruct.mouse_state) ReleaseCapture();
160
				MenuetOnMouse((TThreadData)(&ThreadDataStruct));
161
			}
162
			return 0;
163
		case WM_CAPTURECHANGED:
164
			if (ThreadDataStruct.mouse_state)
165
			{
166
				ThreadDataStruct.mouse_state = 0;
167
				MenuetOnMouse((TThreadData)(&ThreadDataStruct));
168
			}
169
			return 0;
170
		//case WM_SYSKEYDOWN: case WM_KEYDOWN:
171
		case WM_CHAR:
172
			ThreadDataStruct.keys->push_back((unsigned char)wParam);
173
			MenuetOnKeyPress((TThreadData)(&ThreadDataStruct));
174
			return 0;
175
		case WM_SIZE:
176
			GetProcessInfo(0, 0, 0, 0, window_rect);
177
			MenuetOnSize(window_rect, (TThreadData)(&ThreadDataStruct));
178
			InvalidateRect(hWnd, 0, 0);
179
			return 0;
180
		case WM_PAINT:
181
			hdc = BeginPaint(hWnd, &ps);
182
			if (ThreadDataStruct.picture) DrawPicture(hdc);
183
			EndPaint(hWnd, &ps);
184
			return 0;
185
		case WM_CLOSE:
186
			if (MenuetOnClose((TThreadData)(&ThreadDataStruct)))
187
			{
188
				ThreadDataStruct.flag = -1;
189
			}
190
			else return 0;
191
		case WM_DESTROY:
192
			PostQuitMessage(0);
193
			return 0;
194
		}
195
	}
196
	return DefWindowProc(hWnd, message, wParam, lParam);
197
}
198
 
199
ATOM MyRegisterClass()
200
{
201
	HBRUSH background = CreateSolidBrush(RGB(0, 0, 0));
202
	WNDCLASSEX wcex;
203
	wcex.cbSize = sizeof(WNDCLASSEX);
204
	wcex.style			= CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
205
	wcex.lpfnWndProc	= (WNDPROC)WndProc;
206
	wcex.cbClsExtra		= 0;
207
	wcex.cbWndExtra		= 0;
208
	wcex.hInstance		= hInstance;
209
	wcex.hIcon			= 0;
210
	wcex.hCursor		= LoadCursor(NULL, IDC_ARROW);
211
	wcex.hbrBackground	= background;
212
	wcex.lpszMenuName	= NULL;
213
	wcex.lpszClassName	= szWindowClass;
214
	wcex.hIconSm		= 0;
215
	ATOM ret = RegisterClassEx(&wcex);
216
	DeleteObject(background);
217
	return ret;
218
}
219
 
220
HWND InitInstance(int x, int y, int w, int h)
221
{
222
	HWND hWnd;
223
	MyRegisterClass();
224
	DWORD style = WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, exstyle = 0;
225
	hWnd = CreateWindowEx(exstyle, szWindowClass, ThreadDataStruct.win_data->Title, style,
226
				x, y, w, h, NULL, NULL, hInstance, NULL);
227
	if (!hWnd) return NULL;
228
	ShowWindow(hWnd, nCmdShow);
229
	UpdateWindow(hWnd);
230
	return hWnd;
231
}
232
 
233
int ThreadMainProc(void *user)
234
{
235
	ThreadMain(user, 0);
236
	return 0;
237
}
238
 
239
namespace Menuet
240
{
241
	void Main() {ThreadMain();}
242
 
243
	void* ThreadMain(void *user, void *stack_begin)
244
	{
245
		TStartData start_data;
246
		ThreadDataStruct.user = user;
247
		ThreadDataStruct.stack_begin = stack_begin;
248
		ThreadDataStruct.win_data = &start_data.WinData;
249
		ThreadDataStruct.hwnd = 0;
250
		ThreadDataStruct.flag = 0;
251
		ThreadDataStruct.win_time = GetTickCount();
252
		ThreadDataStruct.me_time = ThreadDataStruct.win_time / 10;
253
		ThreadDataStruct.keys = new deque;
254
		ThreadDataStruct.bmp_data_length = 0;
255
		ThreadDataStruct.bmp_data = 0;
256
		ThreadDataStruct.mouse_state = 0;
257
		start_data.Left = 50; start_data.Width = 256;
258
		start_data.Top = 50; start_data.Height = 256;
259
		start_data.WinData.WindowType = 0x03;
260
		start_data.WinData.HeaderType = 0x80;
261
		start_data.WinData.WindowColor = 0xFFFFFF;
262
		start_data.WinData.HeaderColor = 0x6060FF;
263
		start_data.WinData.BorderColor = 0x000000;
264
		start_data.WinData.TitleColor = 0xFFFF40;
265
		start_data.WinData.Title = 0;
266
		if (MenuetOnStart(start_data, (TThreadData)(&ThreadDataStruct)))
267
		{
268
			while (ThreadDataStruct.flag < 0)
269
			{
270
				ThreadDataStruct.flag &= ~0x80000000;
271
				if (MenuetOnClose((TThreadData)(&ThreadDataStruct)))
272
				{
273
					ThreadDataStruct.flag = -1;
274
					break;
275
				}
276
			}
277
			if (ThreadDataStruct.flag >= 0)
278
			{
279
				assert((ThreadDataStruct.hwnd = InitInstance(start_data.Left,
280
							start_data.Top, start_data.Width, start_data.Height)) != NULL);
281
				assert(SendMessage(ThreadDataStruct.hwnd, WM_CREATE, 0, 0) == 0);
282
				MSG msg;
283
				HACCEL hAccelTable = 0;
284
				while (GetMessage(&msg, NULL, 0, 0))
285
				{
286
					if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
287
					{
288
						TranslateMessage(&msg);
289
						DispatchMessage(&msg);
290
					}
291
				}
292
			}
293
			assert(ThreadDataStruct.flag == -1);
294
		}
295
		FinalizeThreadData();
296
		return ThreadDataStruct.stack_begin;
297
	}
298
 
299
	void GetWindowData(TWindowData &win_data)
300
	{
301
		win_data = *ThreadDataStruct.win_data;
302
	}
303
 
304
	void GetWindowData(TWindowData &win_data, TThreadData thread_data)
305
	{
306
		win_data = *((TThreadDataStruct*)thread_data)->win_data;
307
	}
308
 
309
	void SetWindowData(const TWindowData &win_data)
310
	{
311
		*ThreadDataStruct.win_data = win_data;
312
		if (ThreadDataStruct.hwnd)
313
		{
314
			SetWindowText(ThreadDataStruct.hwnd, ThreadDataStruct.win_data->Title);
315
			InvalidateRect(ThreadDataStruct.hwnd, NULL, FALSE);
316
		}
317
	}
318
 
319
	void SetWindowData(const TWindowData &win_data, TThreadData thread_data)
320
	{
321
		*((TThreadDataStruct*)thread_data)->win_data = win_data;
322
		if (((TThreadDataStruct*)thread_data)->hwnd)
323
		{
324
			SetWindowText(((TThreadDataStruct*)thread_data)->hwnd,
325
						((TThreadDataStruct*)thread_data)->win_data->Title);
326
			InvalidateRect(((TThreadDataStruct*)thread_data)->hwnd, NULL, FALSE);
327
		}
328
	}
329
 
330
	void CloseWindow()
331
	{
332
		if (ThreadDataStruct.hwnd)
333
		{
334
			SendMessage(ThreadDataStruct.hwnd, WM_CLOSE, 0, 0);
335
		}
336
		else ThreadDataStruct.flag |= 0x80000000;
337
	}
338
 
339
	void CloseWindow(TThreadData thread_data)
340
	{
341
		if (((TThreadDataStruct*)thread_data)->hwnd)
342
		{
343
			SendMessage(((TThreadDataStruct*)thread_data)->hwnd, WM_CLOSE, 0, 0);
344
		}
345
		else ((TThreadDataStruct*)thread_data)->flag |= 0x80000000;
346
	}
347
 
348
	void Redraw(int /*frame*/)
349
	{
350
		if (ThreadDataStruct.hwnd)
351
		{
352
			InvalidateRect(ThreadDataStruct.hwnd, NULL, FALSE);
353
			SendMessage(ThreadDataStruct.hwnd, WM_PAINT, 0, 0);
354
		}
355
	}
356
 
357
	void Redraw(int /*frame*/, TThreadData thread_data)
358
	{
359
		if (((TThreadDataStruct*)thread_data)->hwnd)
360
		{
361
			InvalidateRect(((TThreadDataStruct*)thread_data)->hwnd, NULL, FALSE);
362
			SendMessage(((TThreadDataStruct*)thread_data)->hwnd, WM_PAINT, 0, 0);
363
		}
364
	}
365
 
366
	void Invalidate(int /*frame*/)
367
	{
368
		if (ThreadDataStruct.hwnd)
369
		{
370
			InvalidateRect(ThreadDataStruct.hwnd, NULL, FALSE);
371
		}
372
	}
373
 
374
	void Invalidate(int /*frame*/, TThreadData thread_data)
375
	{
376
		if (((TThreadDataStruct*)thread_data)->hwnd)
377
		{
378
			InvalidateRect(((TThreadDataStruct*)thread_data)->hwnd, NULL, FALSE);
379
		}
380
	}
381
 
382
	void MoveWindow(const int window_rect[/* 4 */])
383
	{
384
		if (!ThreadDataStruct.hwnd) return;
385
		RECT rect;
386
		if (window_rect[0] == -1 || window_rect[1] == -1 ||
387
			window_rect[2] == -1 || window_rect[3] == -1)
388
		{
389
			if (!GetWindowRect(ThreadDataStruct.hwnd, &rect)) return;
390
			::MoveWindow(ThreadDataStruct.hwnd,
391
					(window_rect[0] == -1) ? rect.left : window_rect[0],
392
					(window_rect[1] == -1) ? rect.top : window_rect[1],
393
					(window_rect[2] == -1) ? (rect.right - rect.left) : window_rect[2],
394
					(window_rect[3] == -1) ? (rect.bottom - rect.top) : window_rect[3], TRUE);
395
		}
396
		else
397
		{
398
			::MoveWindow(ThreadDataStruct.hwnd, window_rect[0],
399
					window_rect[1], window_rect[2], window_rect[3], TRUE);
400
		}
401
	}
402
 
403
	void Abort()
404
	{
405
		if (ThreadDataStruct.hwnd) KillTimer(ThreadDataStruct.hwnd, 0);
406
		abort();
407
	}
408
 
409
	void ExitProcess() {::ExitProcess(0);}
410
 
411
	void ExitThread() {FinalizeThreadData(); ::ExitThread(0);}
412
 
413
	void ExitThread(TThreadData) {FinalizeThreadData(); ::ExitThread(0);}
414
 
415
	void ReturnMessageLoop()
416
	{
417
		TExceptToMessageLoop ex;
418
		throw(ex);
419
	}
420
 
421
	void ReturnMessageLoop(TThreadData)
422
	{
423
		TExceptToMessageLoop ex;
424
		throw(ex);
425
	}
426
 
427
	void Delay(unsigned int time) {Sleep(time * 10);}
428
 
429
	unsigned int Clock() {CalculateNewTime(); return ThreadDataStruct.me_time;}
430
 
431
	int GetPackedTime()
432
	{
433
		SYSTEMTIME time;
434
		GetSystemTime(&time);
435
		int t;
436
		t = (time.wSecond / 10) * 16 + (time.wSecond % 10);
437
		t = (time.wMinute / 10) * 16 + (time.wMinute % 10) + (t << 8);
438
		t = (time.wHour / 10) * 16 + (time.wHour % 10) + (t << 8);
439
		return t;
440
	}
441
 
442
	void GetTime(int t[/* 3 */])
443
	{
444
		SYSTEMTIME time;
445
		GetSystemTime(&time);
446
		t[0] = time.wSecond;
447
		t[1] = time.wMinute;
448
		t[2] = time.wHour;
449
	}
450
 
451
	int GetPackedDate()
452
	{
453
		SYSTEMTIME time;
454
		GetSystemTime(&time);
455
		int t;
456
		t = ((time.wYear / 10) % 10) * 16 + (time.wYear % 10);
457
		t = (time.wDay / 10) * 16 + (time.wDay % 10) + (t << 8);
458
		t = (time.wMonth / 10) * 16 + (time.wMonth % 10) + (t << 8);
459
		return t;
460
	}
461
 
462
	void GetDate(int d[/* 3 */])
463
	{
464
		SYSTEMTIME time;
465
		GetSystemTime(&time);
466
		d[0] = time.wDay;
467
		d[1] = time.wMonth;
468
		d[2] = time.wYear;
469
	}
470
 
471
	void GetTimeDate(int t[/* 6 */])
472
	{
473
		SYSTEMTIME time;
474
		GetSystemTime(&time);
475
		t[0] = time.wSecond;
476
		t[1] = time.wMinute;
477
		t[2] = time.wHour;
478
		t[3] = time.wDay;
479
		t[4] = time.wMonth;
480
		t[5] = time.wYear;
481
	}
482
 
483
	void ReadCommonColors(unsigned int colors[/* 10 */])
484
	{
485
		int i;
486
		for (i = 0; i < 10; i++) colors[i] = 0;
487
	}
488
 
489
	unsigned int GetProcessInfo(unsigned int *use_cpu, char process_name[/* 13 */], unsigned int *use_memory,
490
								unsigned int *pid, int window_rect[/* 4 */], unsigned int pid_for)
491
	{
492
		if (use_cpu) *use_cpu = 0;
493
		if (process_name) strcpy(process_name, "noname");
494
		if (use_memory) *use_memory = 0;
495
		if (pid)
496
		{
497
			if ((pid_for | 15) == -1) pid_for = getpid();
498
			*pid = pid_for;
499
		}
500
		if (window_rect)
501
		{
502
			RECT rect;
503
			if (ThreadDataStruct.hwnd && GetWindowRect(ThreadDataStruct.hwnd, &rect))
504
			{
505
				window_rect[0] = rect.left;
506
				window_rect[1] = rect.top;
507
				window_rect[2] = rect.right - rect.left;
508
				window_rect[3] = rect.bottom - rect.top;
509
			}
510
			else
511
			{
512
				window_rect[0] = 0; window_rect[1] = 0;
513
				window_rect[2] = 0; window_rect[3] = 0;
514
			}
515
		}
516
		return 1;
517
	}
518
 
519
	unsigned int GetPid() {return GetCurrentThreadId();}
520
 
521
	unsigned int GetPid(TThreadData /*thread_data*/) {return GetCurrentThreadId();}
522
 
523
	TThreadData GetThreadData() {return (TThreadData)(&ThreadDataStruct);}
524
 
525
	TThreadData GetThreadData(unsigned int /*pid*/) {return (TThreadData)(&ThreadDataStruct);}
526
 
527
	void* GetPicture(unsigned short &width, unsigned short &height)
528
	{
529
		width = (unsigned short)ThreadDataStruct.picture_width;
530
		height = (unsigned short)ThreadDataStruct.picture_height;
531
		return ThreadDataStruct.picture;
532
	}
533
 
534
	void* GetPicture(unsigned short &width, unsigned short &height, TThreadData thread_data)
535
	{
536
		width = (unsigned short)((TThreadDataStruct*)thread_data)->picture_width;
537
		height = (unsigned short)((TThreadDataStruct*)thread_data)->picture_height;
538
		return ((TThreadDataStruct*)thread_data)->picture;
539
	}
540
 
541
	void SetPicture(void *picture, unsigned short width, unsigned short height)
542
	{
543
		ThreadDataStruct.picture_width = width;
544
		ThreadDataStruct.picture_height = height;
545
		ThreadDataStruct.picture = picture;
546
		if (ThreadDataStruct.hwnd)
547
		{
548
			InvalidateRect(ThreadDataStruct.hwnd, NULL, FALSE);
549
		}
550
	}
551
 
552
	void SetPicture(void *picture, unsigned short width, unsigned short height, TThreadData thread_data)
553
	{
554
		((TThreadDataStruct*)thread_data)->picture_width = width;
555
		((TThreadDataStruct*)thread_data)->picture_height = height;
556
		((TThreadDataStruct*)thread_data)->picture = picture;
557
		if (((TThreadDataStruct*)thread_data)->hwnd)
558
		{
559
			InvalidateRect(((TThreadDataStruct*)thread_data)->hwnd, NULL, FALSE);
560
		}
561
	}
562
 
563
	void GetBorderHeader(unsigned short &border_size, unsigned short &header_size)
564
	{
565
		border_size = (unsigned short)GetSystemMetrics(SM_CXFRAME);
566
		header_size = (unsigned short)(GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYCAPTION));
567
	}
568
 
569
	void GetBorderHeader(unsigned short &border_size, unsigned short &header_size, TThreadData /*thread_data*/)
570
	{
571
		border_size = (unsigned short)GetSystemMetrics(SM_CXFRAME);
572
		header_size = (unsigned short)(GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYCAPTION));
573
	}
574
 
575
	void GetClientSize(unsigned short &width, unsigned short &height)
576
	{
577
		if (!ThreadDataStruct.hwnd) {width = 0; height = 0; return;}
578
		RECT rect;
579
		GetClientRect(ThreadDataStruct.hwnd, &rect);
580
		width = (unsigned short)(rect.right - rect.left);
581
		height = (unsigned short)(rect.bottom - rect.top);
582
	}
583
 
584
	void GetClientSize(unsigned short &width, unsigned short &height, TThreadData thread_data)
585
	{
586
		if (!((TThreadDataStruct*)thread_data)->hwnd) {width = 0; height = 0; return;}
587
		RECT rect;
588
		GetClientRect(((TThreadDataStruct*)thread_data)->hwnd, &rect);
589
		width = (unsigned short)(rect.right - rect.left);
590
		height = (unsigned short)(rect.bottom - rect.top);
591
	}
592
 
593
	void GetClientSize(unsigned short &width, unsigned short &height, int win_width, int win_height)
594
	{
595
		win_width -= 2*GetSystemMetrics(SM_CXFRAME);
596
		win_height -= 2*GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYCAPTION);
597
		if (win_width < 0) win_width = 0;
598
		if (win_height < 0) win_height = 0;
599
		width = (unsigned short)win_width; height = (unsigned short)win_height;
600
	}
601
 
602
	void GetClientSize(unsigned short &width, unsigned short &height,
603
						int win_width, int win_height, TThreadData /*thread_data*/)
604
	{
605
		win_width -= 2*GetSystemMetrics(SM_CXFRAME);
606
		win_height -= 2*GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYCAPTION);
607
		if (win_width < 0) win_width = 0;
608
		if (win_height < 0) win_height = 0;
609
		width = (unsigned short)win_width; height = (unsigned short)win_height;
610
	}
611
 
612
	void GetScreenSize(unsigned short &width, unsigned short &height)
613
	{
614
		width = (unsigned short)GetSystemMetrics(SM_CXFULLSCREEN);
615
		height = (unsigned short)GetSystemMetrics(SM_CYFULLSCREEN);
616
	}
617
 
618
	TMutex::TMutex() {mut = (unsigned int)CreateMutex(NULL, FALSE, NULL);}
619
 
620
	TMutex::~TMutex() {if (mut) {CloseHandle((HANDLE)mut); mut = 0;}}
621
 
622
	TRecMutex::TRecMutex() {mut = (unsigned int)CreateMutex(NULL, FALSE, NULL);}
623
 
624
	TRecMutex::~TRecMutex() {if (mut) {CloseHandle((HANDLE)mut); mut = 0;}}
625
 
626
	void InitMutex(TMutex *mutex) {if (!mutex->mut) *mutex = TMutex();}
627
 
628
	void InitRecMutex(TRecMutex *mutex) {if (!mutex->mut) *mutex = TRecMutex();}
629
 
630
	bool TryLock(TMutex *mutex)
631
	{
632
		DWORD ret = WaitForSingleObject((HANDLE)mutex->mut, 0);
633
		return ret == WAIT_OBJECT_0 || ret == WAIT_ABANDONED;
634
	}
635
 
636
	bool TryLock(TRecMutex *mutex, unsigned int /*pid*/)
637
	{
638
		DWORD ret = WaitForSingleObject((HANDLE)mutex->mut, 0);
639
		return ret == WAIT_OBJECT_0 || ret == WAIT_ABANDONED;
640
	}
641
 
642
	bool TryLock(TRecMutex *mutex)
643
	{
644
		DWORD ret = WaitForSingleObject((HANDLE)mutex->mut, 0);
645
		return ret == WAIT_OBJECT_0 || ret == WAIT_ABANDONED;
646
	}
647
 
648
	bool TryLock(TRecMutex *mutex, TThreadData /*thread_data*/)
649
	{
650
		DWORD ret = WaitForSingleObject((HANDLE)mutex->mut, 0);
651
		return ret == WAIT_OBJECT_0 || ret == WAIT_ABANDONED;
652
	}
653
 
654
	void Lock(TMutex *mutex)
655
	{
656
		WaitForSingleObject((HANDLE)mutex->mut, INFINITE);
657
	}
658
 
659
	void Lock(TRecMutex *mutex, unsigned int /*pid*/)
660
	{
661
		WaitForSingleObject((HANDLE)mutex->mut, INFINITE);
662
	}
663
 
664
	void Lock(TRecMutex *mutex)
665
	{
666
		WaitForSingleObject((HANDLE)mutex->mut, INFINITE);
667
	}
668
 
669
	void Lock(TRecMutex *mutex, TThreadData /*thread_data*/)
670
	{
671
		WaitForSingleObject((HANDLE)mutex->mut, INFINITE);
672
	}
673
 
674
	bool LockTime(TMutex *mutex, unsigned int time)
675
	{
676
		DWORD ret = WaitForSingleObject((HANDLE)mutex->mut, time * 10);
677
		return ret == WAIT_OBJECT_0 || ret == WAIT_ABANDONED;
678
	}
679
 
680
	bool LockTime(TRecMutex *mutex, unsigned int time, unsigned int /*pid*/)
681
	{
682
		DWORD ret = WaitForSingleObject((HANDLE)mutex->mut, time * 10);
683
		return ret == WAIT_OBJECT_0 || ret == WAIT_ABANDONED;
684
	}
685
 
686
	bool LockTime(TRecMutex *mutex, unsigned int time)
687
	{
688
		DWORD ret = WaitForSingleObject((HANDLE)mutex->mut, time * 10);
689
		return ret == WAIT_OBJECT_0 || ret == WAIT_ABANDONED;
690
	}
691
 
692
	bool LockTime(TRecMutex *mutex, unsigned int time, TThreadData /*thread_data*/)
693
	{
694
		DWORD ret = WaitForSingleObject((HANDLE)mutex->mut, time * 10);
695
		return ret == WAIT_OBJECT_0 || ret == WAIT_ABANDONED;
696
	}
697
 
698
	void UnLock(TMutex *mutex)
699
	{
700
		ReleaseMutex((HANDLE)mutex->mut);
701
	}
702
 
703
	void UnLock(TRecMutex *mutex, unsigned int /*pid*/)
704
	{
705
		ReleaseMutex((HANDLE)mutex->mut);
706
	}
707
 
708
	void UnLock(TRecMutex *mutex)
709
	{
710
		ReleaseMutex((HANDLE)mutex->mut);
711
	}
712
 
713
	void UnLock(TRecMutex *mutex, TThreadData /*thread_data*/)
714
	{
715
		ReleaseMutex((HANDLE)mutex->mut);
716
	}
717
 
718
	void DebugPutChar(char c)
719
	{
720
		DWORD num_written;
721
		WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), &c, 1, &num_written, NULL);
722
	}
723
 
724
	void DebugPutString(const char *s)
725
	{
726
		DWORD num_written;
727
		WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), s, strlen(s), &num_written, NULL);
728
	}
729
 
730
	int GetKey()
731
	{
732
		if (ThreadDataStruct.keys->empty()) return -1;
733
		else
734
		{
735
			unsigned char c = ThreadDataStruct.keys->front();
736
			ThreadDataStruct.keys->pop_front();
737
			return c;
738
		}
739
	}
740
 
741
	int GetMouseButton()
742
	{
743
		return ThreadDataStruct.mouse_state;
744
	}
745
 
746
	void GetMousePosition(short &x, short &y, bool absolute)
747
	{
748
		POINT point;
749
		if (!GetCursorPos(&point)) {x = -1; y = -1;}
750
		else if (absolute) {x = (short)point.x; y = (short)point.y;}
751
		else
752
		{
753
			RECT rect;
754
			if (!ThreadDataStruct.hwnd || !GetWindowRect(ThreadDataStruct.hwnd, &rect))
755
			{
756
				x = -1; y = -1;
757
			}
758
			else
759
			{
760
				x = (short)(point.x - rect.left);
761
				y = (short)(point.y - rect.top);
762
			}
763
		}
764
	}
765
 
766
	void GetMousePosPicture(short &x, short &y)
767
	{
768
		POINT point;
769
		if (!GetCursorPos(&point)) {x = -1; y = -1;}
770
		else if (!ThreadDataStruct.hwnd || !ScreenToClient(ThreadDataStruct.hwnd, &point))
771
		{
772
			x = -1; y = -1;
773
		}
774
		else
775
		{
776
			x = (short)point.x;
777
			y = (short)point.y;
778
		}
779
	}
780
 
781
	bool WasThreadCreated() {return WasThreadCreatedBool;}
782
 
783
	unsigned int CreateThread(void *user, unsigned int stack_size, void* /*stack_end*/)
784
	{
785
		unsigned long pid = -1;
786
		WasThreadCreatedBool = true;
787
		if (!::CreateThread(NULL, stack_size, (LPTHREAD_START_ROUTINE)ThreadMainProc, user, 0, &pid))
788
		{
789
			return -1;
790
		}
791
		return pid;
792
	}
793
 
794
	unsigned int StrLen(const char *str) {return ::strlen(str);}
795
 
796
	char *StrCopy(char *dest, const char *src) {return ::strcpy(dest, src);}
797
 
798
	void *MemCopy(void *dest, const void *src, unsigned int n) {return ::memcpy(dest, src, n);}
799
 
800
	void *MemSet(void *s, char c, unsigned int n) {return ::memset(s, c, n);}
801
 
802
	double Floor(double x) {return floor(x);}
803
 
804
	void *Alloc(unsigned int size) {return malloc(size);}
805
 
806
	void *ReAlloc(void *mem, unsigned int size) {return realloc(mem, size);}
807
 
808
	void Free(void *mem) {free(mem);}
809
 
810
	TFileData FileOpen(const char *name, unsigned int /*buffer_length*/)
811
	{
812
		if (!name || !name[0]) return 0;
813
		TFileData file_data = (TFileData)Alloc(sizeof(unsigned int) +
814
					strlen(file_prefix) + strlen(name) + 1);
815
		if (!file_data) return 0;
816
		file_data->data = 0;
817
		strcpy((char*)file_data + sizeof(unsigned int), file_prefix);
818
		strcat((char*)file_data + sizeof(unsigned int), name);
819
		return file_data;
820
	}
821
 
822
	int FileClose(TFileData file_data)
823
	{
824
		if (!file_data) return -1;
825
		if (file_data->data) CloseHandle((HANDLE)file_data->data);
826
		Free(file_data);
827
		return 0;
828
	}
829
 
830
	bool FileEof(TFileData file_data)
831
	{
832
		unsigned int pos;
833
		if (FileTestRead(file_data) < 0) return false;
834
		pos = SetFilePointer((HANDLE)file_data->data, 0, NULL, FILE_CURRENT);
835
		if (pos == -1) return false;
836
		return pos >= GetFileSize((HANDLE)file_data->data, NULL);
837
	}
838
 
839
	unsigned int FileGetPosition(TFileData file_data)
840
	{
841
		unsigned int pos;
842
		if (FileTestRead(file_data) < 0) return 0;
843
		pos = SetFilePointer((HANDLE)file_data->data, 0, NULL, FILE_CURRENT);
844
		return (pos == -1) ? 0 : pos;
845
	}
846
 
847
	void FileSetPosition(TFileData file_data, unsigned int pos)
848
	{
849
		if (FileTestRead(file_data) < 0) return;
850
		SetFilePointer((HANDLE)file_data->data, pos, NULL, FILE_BEGIN);
851
	}
852
 
853
	void FileReset(TFileData file_data)
854
	{
855
		if (!file_data || !file_data->data) return;
856
		FlushFileBuffers((HANDLE)file_data->data);
857
	}
858
 
859
	unsigned int FileGetLength(TFileData file_data)
860
	{
861
		if (FileTestRead(file_data) < 0) return -1;
862
		return GetFileSize((HANDLE)file_data->data, NULL);
863
	}
864
 
865
	int FileTestRead(TFileData file_data)
866
	{
867
		if (!file_data) return -1;
868
		if (!file_data->data)
869
		{
870
			file_data->data = (unsigned int)CreateFile((char*)file_data + sizeof(unsigned int),
871
					GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING,
872
					FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, 0);
873
			if (!file_data->data) return -512;
874
		}
875
		return 0;
876
	}
877
 
878
	int FileRead(TFileData file_data, void *mem, int size)
879
	{
880
		if (!file_data || !mem || size <= 0) return -1;
881
		int res = FileTestRead(file_data);
882
		if (res < 0) return res;
883
		if (!ReadFile((HANDLE)file_data->data, mem, size, (unsigned long*)&res, NULL))
884
		{
885
			return -512;
886
		}
887
		return (res >= 0) ? res : (-1);
888
	}
889
}
890
 
891
bool CheckAllocConsole(LPSTR lpCmdLine)
892
{
893
	char Console[] = "-console";
894
	int ConsoleL = ::strlen(Console);
895
	char *s;
896
	for (s = lpCmdLine; *s; s++)
897
	{
898
		if ((s == lpCmdLine || isspace(s[-1])) && memcmp(s, Console, ConsoleL) == 0 &&
899
			(!s[ConsoleL] || isspace(s[ConsoleL])))
900
		{
901
			AllocConsole();
902
			SetConsoleTitle("Debug Console");
903
			return true;
904
		}
905
	}
906
	return false;
907
}
908
 
909
int APIENTRY WinMain(HINSTANCE hInstance,
910
					 HINSTANCE /*hPrevInstance*/,
911
					 LPSTR     lpCmdLine,
912
					 int       nCmdShow)
913
{
914
	::nCmdShow = nCmdShow;
915
	::hInstance = hInstance;
916
	CheckAllocConsole(lpCmdLine);
917
	Main();
918
	//::ExitThread(0);
919
	return 0;
920
}
921