Subversion Repositories Kolibri OS

Rev

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

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