1 /*
2  *  tracker/wince/WinCE_main.cpp
3  *
4  *  Copyright 2009 Peter Barth
5  *
6  *  This file is part of Milkytracker.
7  *
8  *  Milkytracker is free software: you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation, either version 3 of the License, or
11  *  (at your option) any later version.
12  *
13  *  Milkytracker is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with Milkytracker.  If not, see <http://www.gnu.org/licenses/>.
20  *
21  */
22 
23 // ------------------ WinCE -------------------------------
24 #include <windows.h>
25 #include <aygshell.h>
26 #include <gx.h>
27 #include "WinCE_main.h"
28 #include "VirtualKeyToScanCodeTable.h"
29 // ------------------ tracker -----------------------------
30 #include "PPUI.h"
31 #include "PPMutex.h"
32 #include "Screen.h"
33 #include "Tracker.h"
34 #include "DisplayDevice_GAPI.h"
35 #include "ButtonMapper.h"
36 #include "WaitStateThread.h"
37 #include "LogoSmall.h"
38 #include "XMFile.h"
39 #include "GlobalColorConfig.h"
40 
41 #define WINDOWS_DEFAULT_TIMER
42 #undef RESOLUTION_CHECK
43 
44 #define MAX_LOADSTRING			100
45 #define DBLCLKTIME				1000
46 #define DRAGSENSITIVITY			2
47 
48 HINSTANCE				hInst;					// The current instance
49 WNDCLASS				wc;
50 HWND					hwndCB;					// The command bar handle
51 HWND					hWnd;
52 
53 BOOL					gxInit			= FALSE;
54 BOOL					taskBar			= TRUE;
55 BOOL					gxActive    	= FALSE;
56 
57 PPMutex*				globalMutex 	= NULL;
58 
59 unsigned short*			vScreen			= NULL;
60 PPSize					windowSize(DISPLAYDEVICE_WIDTH,DISPLAYDEVICE_HEIGHT);
61 
62 // Global GAPI variables:
63 GXDisplayProperties		gx_displayprop;
64 
65 #ifndef WINDOWS_DEFAULT_TIMER
66 	#include "WinCE_ThreadTimer.h"
67 	#define WM_MYTIMER (WM_USER + 10)
68 
69 	static CThreadTimer			myThreadTimer;
70 
MyThreadTimerProc(void * obj,UINT idEvent)71 	void MyThreadTimerProc(void* obj, UINT idEvent)
72 	{
73 		SendMessage(hWnd, WM_MYTIMER, 0, 0);
74 	}
75 #endif
76 
77 // ------------------ Tracker --------------------------------------------------------------------------
78 EOrientation				orientation			= eOrientation90CW;
79 pp_int32					doublePixels		= FALSE;
80 pp_int32					allowVirtualKeys	= FALSE;
81 pp_int32					hideTaskBar			= TRUE;
82 pp_int32					dontTurnOffDevice	= FALSE;
83 
84 static PPScreen*			myTrackerScreen = NULL;
85 static Tracker*				myTracker		= NULL;
86 static PPDisplayDevice*		myDisplayDevice = NULL;
87 
88 // ------------------- Logger -----------------------------
89 #ifdef DEBUG
90 #include "Logger.h"
91 #include "Simple.h"
92 #include "PPSystem.h"
93 static CLogger*				logger			= NULL;
94 #endif
95 
96 void				TrackerCreate();
97 void				TrackerStartUp(bool showSplash);
98 void				TrackerInitGUI(bool showSplash);
99 
100 // ------------------ Forward declarations of functions included in this code module: ------------------
101 void				TaskBar(bool show);
102 ATOM				MyRegisterClass(HINSTANCE, LPTSTR);
103 BOOL				InitInstance(HINSTANCE, int);
104 LRESULT CALLBACK	WndProc(HWND, UINT, WPARAM, LPARAM);
105 
106 // ------------------ debugging forwards ---------------------------------------------------------------
107 void				drawString(const char*, unsigned short*, unsigned int, unsigned int, unsigned int, unsigned short);
108 
109 // ------------------- update screen -------------------------------------------------------------------
110 void				UpdateScreen(unsigned short*);
111 void				UpdateScreen();
112 void 				DrawBackground(bool shade = true);
113 bool 				NeedsDrawBackground();
114 
115 
116 //////////////////////////////////////////////////////////////////////////
117 // Exported functions:
118 // PPGetTickCount() is used for milisecond timing
119 // QueryKeyModifiers is used for detecting the state of the modifier keys
120 // SuspendFullScreen() is used to disable full screen mode
121 // ResumeFullScreen() is used to disable full screen mode
122 //////////////////////////////////////////////////////////////////////////
PPGetTickCount()123 pp_uint32 PPGetTickCount()
124 {
125 	return ::GetTickCount();
126 }
127 
QueryKeyModifiers()128 void QueryKeyModifiers()
129 {
130 	if (::GetAsyncKeyState(VK_SHIFT)>>15)
131 		setKeyModifier(KeyModifierSHIFT);
132 	else
133 		clearKeyModifier(KeyModifierSHIFT);
134 
135 	if (::GetAsyncKeyState(VK_MENU)>>15)
136 		setKeyModifier(KeyModifierALT);
137 	else
138 		clearKeyModifier(KeyModifierALT);
139 
140 	if (::GetAsyncKeyState(VK_CONTROL)>>15)
141 		setKeyModifier(KeyModifierCTRL);
142 	else
143 		clearKeyModifier(KeyModifierCTRL);
144 }
145 
SuspendFullScreen()146 void SuspendFullScreen()
147 {
148 	GXCloseInput();
149 	GXCloseDisplay();
150 	TaskBar(true);
151 	gxActive = FALSE;
152 	ShowWindow(hWnd, SW_SHOW);
153 }
154 
ResumeFullScreen()155 void ResumeFullScreen()
156 {
157 	ShowWindow(hWnd, SW_SHOW);
158 	TaskBar(false);
159 	SHSipPreference(hWnd, SIP_FORCEDOWN);
160 	GXOpenDisplay(hWnd, GX_FULLSCREEN);
161 	GXOpenInput();
162 	gxActive = TRUE;
163 
164 	// clear screen with shade if necessary
165 	if (NeedsDrawBackground())
166 		DrawBackground();
167 
168 	UpdateScreen();
169 }
170 
171 
172 //////////////////////////////////////////////////////////////////////////
173 // Taskbar handling
174 //////////////////////////////////////////////////////////////////////////
TaskBar(bool show)175 void TaskBar(bool show)
176 {
177 	if (!hideTaskBar)
178 		return;
179 
180 	RECT rc;
181 	GetWindowRect( hWnd, &rc );
182 	HWND hWndTB = FindWindow(TEXT("HHTaskbar"),NULL);
183 	if (show && hWndTB)
184 	{
185 		if (taskBar) return;
186 		SHFullScreen( hWnd, SHFS_SHOWTASKBAR | SHFS_SHOWSIPBUTTON + SHFS_SHOWSTARTICON );
187 		ShowWindow( hWndTB, SW_SHOW );
188 		MoveWindow( hWnd, rc.left, rc.top + 26, rc.right, rc.bottom - 26, TRUE );
189 		taskBar = TRUE;
190 	}
191 	else if (hWndTB)
192 	{
193 		if (!taskBar) return;
194 		SHFullScreen( hWnd, SHFS_HIDETASKBAR | SHFS_HIDESIPBUTTON + SHFS_HIDESTARTICON );
195 		ShowWindow( hWndTB, SW_HIDE );
196 		MoveWindow( hWnd, rc.left, rc.top - 26, rc.right, rc.bottom + 26, TRUE );
197 		taskBar = FALSE;
198 	}
199 }
200 
201 //////////////////////////////////////////////////////////////////////////
202 // Init GAPI
203 // To-do: Should go into DisplayDevice someday
204 //////////////////////////////////////////////////////////////////////////
InitGAPI(HWND hWnd)205 BOOL InitGAPI(HWND hWnd)
206 {
207 	TaskBar(false);
208 
209 	// Attempt to take over the screen
210 	if (GXOpenDisplay( hWnd, GX_FULLSCREEN) == 0)
211 		return FALSE;
212 
213 	gxActive = TRUE;
214 
215 	// Get display properties
216 	gx_displayprop = GXGetDisplayProperties();
217 
218 #ifdef RESOLUTION_CHECK
219 	if ((gx_displayprop.cyHeight!=320)||(gx_displayprop.cxWidth!=240))
220 	{
221 		// Only dealing with 240x320 resolution in this code
222 		GXCloseDisplay();
223 		MessageBox(hWnd,L"Sorry, only supporting 240x320 display devices",L"Sorry!", MB_OK);
224 		return FALSE;
225 	}
226 #endif
227 
228 	// Check for 16 bit color display
229 	if (gx_displayprop.cBPP != 16)
230 	{
231 		// Only dealing with 16 bit color in this code
232 		GXCloseDisplay();
233 		MessageBox(hWnd,L"Sorry, only supporting 16bit color",L"Sorry!", MB_OK);
234 		return FALSE;
235 	}
236 
237 	// Take over button handling
238 	GXOpenInput();
239 
240 	globalMutex = new PPMutex();
241 
242 	return TRUE;
243 }
244 
245 //////////////////////////////////////////////////////////////////////////
246 // Dispose GAPI
247 //////////////////////////////////////////////////////////////////////////
ExitGAPI()248 void ExitGAPI()
249 {
250 	if (gxActive)
251 	{
252 		// Clean up
253 		GXSuspend();
254 		GXCloseInput();
255 		GXCloseDisplay();
256 		TaskBar(true);
257 		gxActive = false;
258 	}
259 }
260 
HandleCommandLine(LPCTSTR lpCmdLine)261 void HandleCommandLine(LPCTSTR lpCmdLine)
262 {
263 	// Retrieve input file
264 	PPSystemString fileInput(lpCmdLine);
265 
266 	// When there is something specified, check if it's an existing file
267 	if (fileInput.length() && XMFile::exists(fileInput))
268 	{
269 		PPSystemString* strPtr = &fileInput;
270 
271 		PPEvent event(eFileDragDropped, &strPtr, sizeof(PPSystemString*));
272 		myTrackerScreen->raiseEvent(&event);
273 	}
274 }
275 
WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPTSTR lpCmdLine,int nCmdShow)276 int WINAPI WinMain(	HINSTANCE hInstance,
277 					HINSTANCE hPrevInstance,
278 					LPTSTR    lpCmdLine,
279 					int       nCmdShow)
280 {
281 #ifdef DEBUG
282 	SimpleString path(System::getConfigFileName(_T("milky.log")));
283 	CLogger _logger(path);
284 	logger = &_logger;
285 #endif
286 
287 	MSG msg;
288 	HACCEL hAccelTable;
289 
290 	// Perform application initialization:
291 	if (!InitInstance (hInstance, nCmdShow))
292 	{
293 		TaskBar(true);
294 		return FALSE;
295 	}
296 
297 	HandleCommandLine(lpCmdLine);
298 
299 #ifndef WINDOWS_DEFAULT_TIMER
300 	HANDLE hThread = GetCurrentThread();
301 	SetThreadPriority(hThread, THREAD_PRIORITY_BELOW_NORMAL);
302 #endif
303 
304 	hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_FIRSTGX);
305 
306 	while (GetMessage(&msg, NULL, 0, 0))
307 	{
308 		TranslateMessage(&msg);
309 		DispatchMessage(&msg);
310 	}
311 
312 	delete myTracker;
313 	delete myTrackerScreen;
314 
315 	ExitGAPI();
316 
317 	delete globalMutex;
318 
319 	return msg.wParam;
320 }
321 
322 
MyRegisterClass(HINSTANCE hInstance,LPTSTR szWindowClass)323 ATOM MyRegisterClass(HINSTANCE hInstance, LPTSTR szWindowClass)
324 {
325 	WNDCLASS	wc;
326 
327     wc.style			= CS_HREDRAW | CS_VREDRAW;
328     wc.lpfnWndProc		= (WNDPROC) WndProc;
329     wc.cbClsExtra		= 0;
330     wc.cbWndExtra		= 0;
331     wc.hInstance		= hInstance;
332     wc.hIcon			= NULL;
333 	//wc.hIcon			= LoadIcon(hInstance, MAKEINTRESOURCE(IDI_GAPI1));
334     wc.hCursor			= 0;
335     wc.hbrBackground	= (HBRUSH) GetStockObject(HOLLOW_BRUSH);
336     wc.lpszMenuName		= 0;
337     wc.lpszClassName	= szWindowClass;
338 
339 	return RegisterClass(&wc);
340 }
341 
InitInstance(HINSTANCE hInstance,int nCmdShow)342 BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
343 {
344 	TCHAR	szTitle[MAX_LOADSTRING];			// The title bar text
345 	TCHAR	szWindowClass[MAX_LOADSTRING];		// The window class name
346 
347 	hInst = hInstance;		// Store instance handle in our global variable
348 	// Initialize global strings
349 	LoadString(hInstance, IDC_FIRSTGX, szWindowClass, MAX_LOADSTRING);
350 	LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
351 
352 	//If it is already running, then focus on the window
353 	hWnd = FindWindow(szWindowClass, szTitle);
354 	if (hWnd)
355 	{
356 		SetForegroundWindow ((HWND) (((DWORD)hWnd) | 0x01));
357 		return 0;
358 	}
359 
360 	MyRegisterClass(hInstance, szWindowClass);
361 
362 	RECT	rect;
363 	GetClientRect(hWnd, &rect);
364 
365 	hWnd = CreateWindow(szWindowClass,
366 						szTitle,
367 						WS_VISIBLE,
368 						CW_USEDEFAULT,
369 						CW_USEDEFAULT,
370 						CW_USEDEFAULT,
371 						CW_USEDEFAULT,
372 						NULL,
373 						NULL,
374 						hInstance,
375 						NULL);
376 	if (!hWnd)
377 	{
378 		return FALSE;
379 	}
380 
381 	// This will also load local WinCE config
382 	InitButtonRemapper();
383 
384 	if (!InitGAPI(hWnd))
385 		return FALSE;
386 
387 	TrackerCreate();
388 
389 	bool showSplash = myTracker->getShowSplashFlagFromDatabase();
390 
391 	TrackerInitGUI(showSplash);
392 	TrackerStartUp(showSplash);
393 
394 	UpdateScreen();
395 
396 	// Create timers
397 #ifdef WINDOWS_DEFAULT_TIMER
398 	SetTimer(hWnd, 10, 20, NULL);
399 #else
400 	myThreadTimer.SetTimer (NULL, 1, 20, MyThreadTimerProc);
401 #endif
402 	return TRUE;
403 }
404 
405 //////////////////////////////////////////////////////////////////////////
406 // Convert final coordinates from current orientation
407 //////////////////////////////////////////////////////////////////////////
POINTFROMPARAM(PPPoint & point,int param)408 void POINTFROMPARAM(PPPoint& point, int param)
409 {
410 	const unsigned int screenWidth = ::windowSize.width;
411 	const unsigned int screenHeight = ::windowSize.height;
412 
413 	switch (orientation)
414 	{
415 		case eOrientation90CW:
416 		{
417 			int hCenter = (gx_displayprop.cxWidth >> 1) - ((screenHeight<<doublePixels) >> 1);
418 			if (hCenter < 0) hCenter = 0;
419 			int vCenter = (gx_displayprop.cyHeight >> 1) - ((screenWidth<<doublePixels) >> 1);
420 			if (vCenter < 0) vCenter = 0;
421 
422 			point.y = LOWORD(param) - hCenter;
423 			point.x = (gx_displayprop.cyHeight - 1 - (HIWORD(param) + vCenter));
424 			break;
425 		}
426 
427 		case eOrientation90CCW:
428 		{
429 			int hCenter = (gx_displayprop.cxWidth >> 1) - ((screenHeight<<doublePixels) >> 1);
430 			if (hCenter < 0) hCenter = 0;
431 			int vCenter = (gx_displayprop.cyHeight >> 1) - ((screenWidth<<doublePixels) >> 1);
432 			if (vCenter < 0) vCenter = 0;
433 
434 			point.y = gx_displayprop.cxWidth - 1 - (LOWORD(param) + hCenter);
435 			point.x = HIWORD(param) - vCenter;
436 			break;
437 		}
438 
439 		case eOrientationNormal:
440 			int hCenter = (gx_displayprop.cxWidth >> 1) - ((screenWidth<<doublePixels) >> 1);
441 			if (hCenter < 0) hCenter = 0;
442 			int vCenter = (gx_displayprop.cyHeight >> 1) - ((screenHeight<<doublePixels) >> 1);
443 			if (vCenter < 0) vCenter = 0;
444 
445 			point.x = LOWORD(param) - hCenter;
446 			point.y = HIWORD(param) - vCenter;
447 			break;
448 	}
449 
450 	point.x >>= doublePixels;
451 	point.y >>= doublePixels;
452 }
453 
454 
UpdateScreen(unsigned short * vScreen)455 void UpdateScreen(unsigned short* vScreen)
456 {
457 	if (!gxActive)
458 		return;
459 
460 	globalMutex->lock();
461 
462 	// Get the start of the screen memory from the GX function.
463 	unsigned short * buffer  = (unsigned short *) GXBeginDraw();
464 	unsigned short * line_buffer  = buffer;
465 
466 
467 	if (buffer == NULL)
468 	{
469 		globalMutex->unlock();
470 		return;
471 	}
472 
473 	const unsigned int screenWidth = ::windowSize.width;
474 	const unsigned int screenHeight = ::windowSize.height;
475 
476 	const unsigned int hcbxpitch = gx_displayprop.cbxPitch >> 1;
477 	const unsigned int hcbypitch = gx_displayprop.cbyPitch >> 1;
478 
479 	const unsigned int hRes = gx_displayprop.cxWidth >> doublePixels;
480 	const unsigned int vRes = gx_displayprop.cyHeight >> doublePixels;
481 
482 	unsigned short* vscr = vScreen;
483 
484 	if (gx_displayprop.ffFormat & kfDirect565)
485 	{
486 
487 		switch (orientation)
488 		{
489 			case eOrientation90CW:
490 			{
491 				// PocketPC: gx_displayprop.cxWidth = 240, gx_displayprop.cyHeight = 320
492 
493 				const unsigned int width = hRes > screenHeight ? screenHeight : hRes;
494 				const unsigned int height = vRes > screenWidth ? screenWidth : vRes;
495 
496 				int hCenter = (gx_displayprop.cxWidth >> 1) - ((screenHeight<<doublePixels) >> 1);
497 				if (hCenter < 0) hCenter = 0;
498 				int vCenter = (gx_displayprop.cyHeight >> 1) - ((screenWidth<<doublePixels) >> 1);
499 				if (vCenter < 0) vCenter = 0;
500 
501 				if (!doublePixels)
502 				{
503 					for (unsigned int x=0; x<width; x++)
504 					{
505 						unsigned short* pixel = (buffer+(x+hCenter)*hcbxpitch)+((gx_displayprop.cyHeight-1+vCenter)*hcbypitch);
506 
507 						for (unsigned int y=0; y<height; y++)
508 						{
509 							*pixel = *vscr;
510 							pixel-=hcbypitch;
511 							vscr++;
512 						}
513 
514 						vscr+=screenWidth-height;
515 					}
516 				}
517 				else
518 				{
519 					for (unsigned int x=0; x<width; x++)
520 					{
521 						unsigned int y;
522 
523 						unsigned short* pixel = (buffer+(x*2+hCenter)*hcbxpitch)+((gx_displayprop.cyHeight-1+vCenter)*hcbypitch);
524 						unsigned short* src = vscr;
525 						for (y=0; y<height; y++)
526 						{
527 							*pixel = *vscr;
528 							pixel-=hcbypitch;
529 							*pixel = *vscr;
530 							pixel-=hcbypitch;
531 							vscr++;
532 						}
533 
534 						pixel = buffer+((x*2+1+hCenter)*hcbxpitch)+((gx_displayprop.cyHeight-1+vCenter)*hcbypitch);
535 						vscr = src;
536 						for (y=0; y<height; y++)
537 						{
538 							*pixel = *vscr;
539 							pixel-=hcbypitch;
540 							*pixel = *vscr;
541 							pixel-=hcbypitch;
542 							vscr++;
543 						}
544 
545 						vscr+=screenWidth-height;
546 					}
547 				}
548 				break;
549 			};
550 
551 			case eOrientation90CCW:
552 			{
553 				// PocketPC: gx_displayprop.cxWidth = 240, gx_displayprop.cyHeight = 320
554 
555 				const unsigned int width = hRes > screenHeight ? screenHeight : hRes;
556 				const unsigned int height = vRes > screenWidth ? screenWidth : vRes;
557 
558 				int hCenter = (gx_displayprop.cxWidth >> 1) - ((screenHeight<<doublePixels) >> 1);
559 				if (hCenter < 0) hCenter = 0;
560 				int vCenter = (gx_displayprop.cyHeight >> 1) - ((screenWidth<<doublePixels) >> 1);
561 				if (vCenter < 0) vCenter = 0;
562 
563 				if (!doublePixels)
564 				{
565 					for (unsigned int x=0; x<width; x++)
566 					{
567 						unsigned short* pixel = (buffer+(gx_displayprop.cxWidth-1-x-hCenter)*hcbxpitch + (vCenter*hcbypitch));
568 
569 						for (unsigned int y=0; y<height; y++)
570 						{
571 							*pixel = *vscr;
572 							pixel+=hcbypitch;
573 							vscr++;
574 						}
575 
576 						vscr+=screenWidth-height;
577 					}
578 				}
579 				else
580 				{
581 					for (unsigned int x=0; x<width; x++)
582 					{
583 						unsigned int y;
584 
585 						unsigned short* pixel = (buffer+(gx_displayprop.cxWidth-1-x*2-hCenter)*hcbxpitch + (vCenter*hcbypitch));
586 						unsigned short* src = vscr;
587 						for (y=0; y<height; y++)
588 						{
589 							*pixel = *vscr;
590 							pixel+=hcbypitch;
591 							*pixel = *vscr;
592 							pixel+=hcbypitch;
593 							vscr++;
594 						}
595 
596 						pixel = (buffer+(gx_displayprop.cxWidth-1-(x*2+1)-hCenter)*hcbxpitch + (vCenter*hcbypitch));
597 						vscr = src;
598 						for (y=0; y<height; y++)
599 						{
600 							*pixel = *vscr;
601 							pixel+=hcbypitch;
602 							*pixel = *vscr;
603 							pixel+=hcbypitch;
604 							vscr++;
605 						}
606 
607 						vscr+=screenWidth-height;
608 					}
609 				}
610 
611 				break;
612 			};
613 
614 			case eOrientationNormal:
615 			{
616 				const unsigned int width = hRes > screenWidth ? screenWidth : hRes;
617 				const unsigned int height = vRes > screenHeight ? screenHeight : vRes;
618 
619 				int hCenter = (gx_displayprop.cxWidth >> 1) - ((screenWidth<<doublePixels) >> 1);
620 				if (hCenter < 0) hCenter = 0;
621 				int vCenter = (gx_displayprop.cyHeight >> 1) - ((screenHeight<<doublePixels) >> 1);
622 				if (vCenter < 0) vCenter = 0;
623 
624 				if (!doublePixels)
625 				{
626 					for (unsigned int y=0; y<height; y++)
627 					{
628 						unsigned short* pixel = buffer + hCenter*hcbxpitch + (vCenter+y)*hcbypitch;
629 						for (unsigned int x=0; x<width; x++)
630 						{
631 							*pixel=*vscr;
632 							pixel += hcbxpitch;
633 							vscr++;
634 						}
635 
636 						vscr+=screenWidth-width;
637 					}
638 				}
639 				else
640 				{
641 					for (unsigned int y=0; y<height; y++)
642 					{
643 						unsigned int x;
644 
645 						unsigned short* pixel = buffer + (y*2 + vCenter)*hcbypitch + hCenter*hcbxpitch;
646 						unsigned short* src = vscr;
647 						for (x=0; x<width; x++)
648 						{
649 							*pixel=*vscr;
650 							pixel += hcbxpitch;
651 							*pixel=*vscr;
652 							pixel += hcbxpitch;
653 							vscr++;
654 						}
655 
656 						pixel = buffer + ((y*2+1) + vCenter)*hcbypitch + hCenter*hcbxpitch;
657 						vscr = src;
658 						for (x=0; x<width; x++)
659 						{
660 							*pixel=*vscr;
661 							pixel += hcbxpitch;
662 							*pixel=*vscr;
663 							pixel += hcbxpitch;
664 							vscr++;
665 						}
666 
667 						vscr+=screenWidth-width;
668 					}
669 
670 				}
671 
672 				break;
673 			};
674 		}
675 
676 	}
677 	else
678 	{
679 		// 15 bit color is not supported
680 	}
681 
682 	// End the drawing code
683 	GXEndDraw();
684 
685 	globalMutex->unlock();
686 }
687 
UpdateScreenRegion(unsigned short * vScreen,const PPRect & rect)688 void UpdateScreenRegion(unsigned short* vScreen, const PPRect& rect)
689 {
690 	if (!gxActive)
691 		return;
692 
693 	globalMutex->lock();
694 
695 	// Get the start of the screen memory from the GX function.
696 	unsigned short * buffer  = (unsigned short *) GXBeginDraw();
697 	unsigned short * line_buffer  = buffer;
698 
699 	if (buffer == NULL)
700 	{
701 		globalMutex->unlock();
702 		return;
703 	}
704 
705 	const unsigned int screenWidth = ::windowSize.width;
706 	const unsigned int screenHeight = ::windowSize.height;
707 
708 	const unsigned int hcbxpitch = gx_displayprop.cbxPitch >> 1;
709 	const unsigned int hcbypitch = gx_displayprop.cbyPitch >> 1;
710 
711 	const unsigned int hRes = gx_displayprop.cxWidth >> doublePixels;
712 	const unsigned int vRes = gx_displayprop.cyHeight >> doublePixels;
713 
714 	unsigned short* vscr = vScreen + rect.y1 * screenWidth + rect.x1;
715 
716 	if (gx_displayprop.ffFormat & kfDirect565)
717 	{
718 
719 		switch (orientation)
720 		{
721 			case eOrientation90CW:
722 			{
723 				// PocketPC: gx_displayprop.cxWidth = 240, gx_displayprop.cyHeight = 320
724 
725 				const unsigned int width = hRes > screenHeight ? screenHeight : hRes;
726 				const unsigned int height = vRes > screenWidth ? screenWidth : vRes;
727 
728 				if (rect.x1 >= (signed)height || rect.y1 >= (signed)width)
729 					break;
730 
731 				int hCenter = (gx_displayprop.cxWidth >> 1) - ((screenHeight<<doublePixels) >> 1);
732 				if (hCenter < 0) hCenter = 0;
733 				int vCenter = (gx_displayprop.cyHeight >> 1) - ((screenWidth<<doublePixels) >> 1);
734 				if (vCenter < 0) vCenter = 0;
735 
736 				int rx2 = rect.x2;
737 				int ry2 = rect.y2;
738 
739 				if (rx2 > (signed)height) rx2 = height;
740 				if (ry2 > (signed)width) ry2 = width;
741 
742 				if (!doublePixels)
743 				{
744 					for (int x=rect.y1; x<ry2; x++)
745 					{
746 						unsigned short* pixel = (buffer+(x+hCenter)*hcbxpitch)+((gx_displayprop.cyHeight-1+vCenter)*hcbypitch) - (rect.x1*hcbypitch);
747 
748 						for (int y=rect.x1; y<rx2; y++)
749 						{
750 							*pixel = *vscr;
751 							pixel-=hcbypitch;
752 							vscr++;
753 						}
754 
755 						vscr+=screenWidth - (rx2 - rect.x1);
756 					}
757 				}
758 				else
759 				{
760 					for (int x=rect.y1; x<ry2; x++)
761 					{
762 						int y;
763 
764 						unsigned short* pixel = (buffer+(x*2+hCenter)*hcbxpitch)+((gx_displayprop.cyHeight-1+vCenter)*hcbypitch) - (rect.x1*2*hcbypitch);
765 						unsigned short* src = vscr;
766 						for (y=rect.x1; y<rx2; y++)
767 						{
768 							*pixel = *vscr;
769 							pixel-=hcbypitch;
770 							*pixel = *vscr;
771 							pixel-=hcbypitch;
772 							vscr++;
773 						}
774 
775 						pixel = (buffer+(x*2+1+hCenter)*hcbxpitch)+((gx_displayprop.cyHeight-1+vCenter)*hcbypitch) - ((rect.x1*2)*hcbypitch);
776 						vscr = src;
777 						for (y=rect.x1; y<rx2; y++)
778 						{
779 							*pixel = *vscr;
780 							pixel-=hcbypitch;
781 							*pixel = *vscr;
782 							pixel-=hcbypitch;
783 							vscr++;
784 						}
785 
786 						vscr+=screenWidth - (rx2 - rect.x1);
787 					}
788 				}
789 				break;
790 			};
791 
792 			case eOrientation90CCW:
793 			{
794 				// PocketPC: gx_displayprop.cxWidth = 240, gx_displayprop.cyHeight = 320
795 
796 				const unsigned int width = hRes > screenHeight ? screenHeight : hRes;
797 				const unsigned int height = vRes > screenWidth ? screenWidth : vRes;
798 
799 				if (rect.x1 >= (signed)height || rect.y1 >= (signed)width)
800 					break;
801 
802 				int hCenter = (gx_displayprop.cxWidth >> 1) - ((screenHeight<<doublePixels) >> 1);
803 				if (hCenter < 0) hCenter = 0;
804 				int vCenter = (gx_displayprop.cyHeight >> 1) - ((screenWidth<<doublePixels) >> 1);
805 				if (vCenter < 0) vCenter = 0;
806 
807 				int rx2 = rect.x2;
808 				int ry2 = rect.y2;
809 
810 				if (rx2 > (signed)height) rx2 = height;
811 				if (ry2 > (signed)width) ry2 = width;
812 
813 				if (!doublePixels)
814 				{
815 					for (int x=rect.y1; x<ry2; x++)
816 					{
817 						unsigned short* pixel = (buffer+(gx_displayprop.cxWidth-1-x-hCenter)*hcbxpitch) + ((rect.x1+vCenter)*hcbypitch);
818 
819 						for (int y=rect.x1; y<rx2; y++)
820 						{
821 							*pixel = *vscr;
822 							pixel+=hcbypitch;
823 							vscr++;
824 						}
825 
826 						vscr+=screenWidth - (rx2 - rect.x1);
827 					}
828 				}
829 				else
830 				{
831 					for (int x=rect.y1; x<ry2; x++)
832 					{
833 						int y;
834 
835 						unsigned short* pixel = (buffer+(gx_displayprop.cxWidth-1-x*2-hCenter)*hcbxpitch) + (((rect.x1*2)+vCenter)*hcbypitch);
836 						unsigned short* src = vscr;
837 						for (y=rect.x1; y<rx2; y++)
838 						{
839 							*pixel = *vscr;
840 							pixel+=hcbypitch;
841 							*pixel = *vscr;
842 							pixel+=hcbypitch;
843 							vscr++;
844 						}
845 
846 						pixel = (buffer+(gx_displayprop.cxWidth-1-(x*2+1)-hCenter)*hcbxpitch) + (((rect.x1*2)+vCenter)*hcbypitch);
847 						vscr = src;
848 						for (y=rect.x1; y<rx2; y++)
849 						{
850 							*pixel = *vscr;
851 							pixel+=hcbypitch;
852 							*pixel = *vscr;
853 							pixel+=hcbypitch;
854 							vscr++;
855 						}
856 
857 						vscr+=screenWidth - (rx2 - rect.x1);
858 					}
859 				}
860 				break;
861 			};
862 
863 			case eOrientationNormal:
864 			{
865 				int width = hRes > screenWidth ? screenWidth : hRes;
866 				int height = vRes > screenHeight ? screenHeight : vRes;
867 
868 				if (rect.x1 >= width || rect.y1 >= height)
869 					break;
870 
871 				int hCenter = (gx_displayprop.cxWidth >> 1) - ((screenWidth<<doublePixels) >> 1);
872 				if (hCenter < 0) hCenter = 0;
873 				int vCenter = (gx_displayprop.cyHeight >> 1) - ((screenHeight<<doublePixels) >> 1);
874 				if (vCenter < 0) vCenter = 0;
875 
876 				int rx2 = rect.x2;
877 				int ry2 = rect.y2;
878 
879 				if (rx2 > width) rx2 = width;
880 				if (ry2 > height) ry2 = height;
881 
882 				if (!doublePixels)
883 				{
884 					for (int y=rect.y1; y<ry2; y++)
885 					{
886 						unsigned short* pixel = buffer+((rect.x1+hCenter)*hcbxpitch) + ((y+vCenter)*hcbypitch);
887 						for (int x=rect.x1; x<rx2; x++)
888 
889 						{
890 							*pixel = *vscr;
891 							pixel+=hcbxpitch;
892 							vscr++;
893 						}
894 
895 						vscr+=screenWidth - (rx2 - rect.x1);
896 					}
897 				}
898 				else
899 				{
900 					for (int y=rect.y1; y<ry2; y++)
901 					{
902 						int x;
903 
904 						unsigned short* pixel = buffer+((rect.x1*2+hCenter)*hcbxpitch) + ((y*2+vCenter)*hcbypitch);
905 						unsigned short* src = vscr;
906 						for (x=rect.x1; x<rx2; x++)
907 						{
908 							*pixel = *vscr;
909 							pixel+=hcbxpitch;
910 							*pixel = *vscr;
911 							pixel+=hcbxpitch;
912 							vscr++;
913 						}
914 
915 						pixel = buffer+((rect.x1*2+hCenter)*hcbxpitch) + ((y*2+1+vCenter)*hcbypitch);
916 						vscr = src;
917 						for (x=rect.x1; x<rx2; x++)
918 						{
919 							*pixel = *vscr;
920 							pixel+=hcbxpitch;
921 							*pixel = *vscr;
922 							pixel+=hcbxpitch;
923 							vscr++;
924 						}
925 
926 						vscr+=screenWidth - (rx2 - rect.x1);
927 					}
928 				}
929 
930 				break;
931 			};
932 		}
933 
934 	}
935 	else
936 	{
937 		// 15 bit color is not supported
938 	}
939 
940 	// End the drawing code
941 	GXEndDraw();
942 
943 	globalMutex->unlock();
944 }
945 
UpdateScreen()946 void UpdateScreen()
947 {
948 	if (myTrackerScreen)
949 	{
950 		myTrackerScreen->paint();
951 	}
952 	UpdateScreen(vScreen);
953 }
954 
DrawBackground(bool shade)955 void DrawBackground(bool shade)
956 {
957 	if (!gxActive)
958 		return;
959 
960 	globalMutex->lock();
961 
962 	// Get the start of the screen memory from the GX function.
963 	unsigned short * buffer  = (unsigned short *) GXBeginDraw();
964 
965 	if (buffer == NULL)
966 	{
967 		globalMutex->unlock();
968 		return;
969 	}
970 
971 	const unsigned int screenWidth = gx_displayprop.cxWidth;
972 	const unsigned int screenHeight = gx_displayprop.cyHeight;
973 
974 	const unsigned int hcbxpitch = gx_displayprop.cbxPitch >> 1;
975 	const unsigned int hcbypitch = gx_displayprop.cbyPitch >> 1;
976 
977 	if (shade)
978 	{
979 		PPColor col = GlobalColorConfig::getInstance()->getColor(GlobalColorConfig::ColorTheme);
980 
981 		PPColor srcCol = col, dstCol = col;
982 		srcCol.scaleFixed(32768);
983 
984 		for (unsigned int y = 0; y < screenHeight; y++)
985 			for (unsigned int x = 0;  x < screenWidth; x++)
986 			{
987 				unsigned short* pixel = buffer+x*hcbxpitch+y*hcbypitch;
988 
989 				int r,g,b;
990 
991 				switch (orientation)
992 				{
993 					case eOrientation90CW:
994 					{
995 						int s = (x*65536) / screenWidth;
996 
997 						r = ((srcCol.r) * s + dstCol.r * (65535-s)) >> (16 + 3);
998 						g = ((srcCol.g) * s + dstCol.g * (65535-s)) >> (16 + 2);
999 						b = ((srcCol.b) * s + dstCol.b * (65535-s)) >> (16 + 3);
1000 						break;
1001 					}
1002 
1003 					case eOrientation90CCW:
1004 					{
1005 						int s = (x*65536) / screenWidth;
1006 
1007 						r = ((srcCol.r) * (65535-s) + dstCol.r * s) >> (16 + 3);
1008 						g = ((srcCol.g) * (65535-s) + dstCol.g * s) >> (16 + 2);
1009 						b = ((srcCol.b) * (65535-s) + dstCol.b * s) >> (16 + 3);
1010 						break;
1011 					}
1012 
1013 					case eOrientationNormal:
1014 					{
1015 						int s = (y*65536) / screenHeight;
1016 
1017 						r = ((srcCol.r) * s + dstCol.r * (65535-s)) >> (16 + 3);
1018 						g = ((srcCol.g) * s + dstCol.g * (65535-s)) >> (16 + 2);
1019 						b = ((srcCol.b) * s + dstCol.b * (65535-s)) >> (16 + 3);
1020 						break;
1021 					}
1022 				}
1023 
1024 				*pixel = (r << 11) + (g << 5) + b;
1025 			}
1026 	}
1027 	else
1028 	{
1029 		for (unsigned int y = 0; y < screenHeight; y++)
1030 			for (unsigned int x = 0;  x < screenWidth; x++)
1031 			{
1032 				unsigned short* pixel = buffer+x*hcbxpitch+y*hcbypitch;
1033 				*pixel = 0;
1034 			}
1035 	}
1036 
1037 	// End the drawing code
1038 	GXEndDraw();
1039 
1040 	globalMutex->unlock();
1041 }
1042 
NeedsDrawBackground()1043 bool NeedsDrawBackground()
1044 {
1045 	switch (orientation)
1046 	{
1047 		case eOrientation90CCW:
1048 		case eOrientation90CW:
1049 		{
1050 			return (gx_displayprop.cxWidth != (unsigned)windowSize.height) || (gx_displayprop.cyHeight != (unsigned)windowSize.width);
1051 		}
1052 
1053 		case eOrientationNormal:
1054 		{
1055 			return (gx_displayprop.cxWidth != (unsigned)windowSize.width) || (gx_displayprop.cyHeight != (unsigned)windowSize.height);
1056 		}
1057 	}
1058 
1059 	return false;
1060 }
1061 
TrackerCreate()1062 void TrackerCreate()
1063 {
1064 	myTracker = new Tracker();
1065 
1066 	windowSize = myTracker->getWindowSizeFromDatabase();
1067 #ifdef __LOWRES__
1068 	windowSize.width = DISPLAYDEVICE_WIDTH;
1069 	windowSize.height = DISPLAYDEVICE_HEIGHT;
1070 #endif
1071 
1072 	// Allocate virtual screen
1073 	vScreen = new unsigned short[windowSize.width*windowSize.height];
1074 
1075 	// Clear virtual screen
1076 	memset(vScreen, 0, windowSize.width*windowSize.height*sizeof(unsigned short));
1077 
1078 	myDisplayDevice = new PPDisplayDevice(hWnd, windowSize.width, windowSize.height);
1079 
1080 	myDisplayDevice->setSize(windowSize);
1081 
1082 	myTrackerScreen = new PPScreen(myDisplayDevice, myTracker);
1083 	myTracker->setScreen(myTrackerScreen);
1084 }
1085 
1086 
TrackerStartUp(bool showSplash)1087 void TrackerStartUp(bool showSplash)
1088 {
1089 	// Startup procedure
1090 	myTracker->startUp(true);
1091 
1092 	WaitStateThread::getInstance()->activate(FALSE);
1093 
1094 	myTrackerScreen->enableDisplay(true);
1095 
1096 	if (showSplash)
1097 		myTracker->hideSplash();
1098 
1099 	// clear screen with shade if necessary
1100 	if (NeedsDrawBackground())
1101 		DrawBackground();
1102 
1103 	myTrackerScreen->paint(false);
1104 }
1105 
TrackerInitGUI(bool showSplash)1106 void TrackerInitGUI(bool showSplash)
1107 {
1108 	// clear screen with black if necessary
1109 	if (NeedsDrawBackground())
1110 		DrawBackground(false);
1111 
1112 	if (showSplash)
1113 		myTracker->showSplash();
1114 
1115 	myTrackerScreen->enableDisplay(false);
1116 
1117 	// Put init message on screen
1118 	drawString("initializing", vScreen, windowSize.width, (windowSize.width>>1)-12*4, (windowSize.height>>1)-12, 0xFFFF);
1119 
1120 	WaitStateThread::getInstance()->setDisplayResolution(windowSize.width, windowSize.height);
1121 
1122 	WaitStateThread::getInstance()->activate(TRUE, TRUE, FALSE);
1123 }
1124 
1125 #ifdef DEBUG
LogWinMsg(CLogger & logger,LPCTSTR msg,LPARAM lParam)1126 void LogWinMsg(CLogger& logger, LPCTSTR msg, LPARAM lParam)
1127 {
1128 	TCHAR dummy[1024];
1129 
1130 	wsprintf(dummy, _T("%x"), lParam);
1131 
1132 	SimpleString logstr(msg);
1133 	logstr.append(_T(": "));
1134 	logstr.append(dummy);
1135 
1136 	logger.Log(logstr);
1137 }
1138 
1139 
LogMouseDown(CLogger & logger,LPARAM lParam,const PPPoint & point)1140 void LogMouseDown(CLogger& logger, LPARAM lParam, const PPPoint& point)
1141 {
1142 	TCHAR dummy[1024];
1143 
1144 	wsprintf(dummy, _T("Before: %i, %i"), LOWORD(lParam), HIWORD(lParam));
1145 
1146 	SimpleString logstr(dummy);
1147 	logstr.append(_T(" "));
1148 	wsprintf(dummy, _T("After: %i, %i"), point.x, point.y);
1149 	logstr.append(dummy);
1150 
1151 	logger.Log(logstr);
1152 }
1153 #endif
1154 
WndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)1155 LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
1156 {
1157 	static bool     LMouseDrag  = false;
1158 	static PPPoint	LMouseDragStartPoint;
1159 	static bool     RMouseDrag  = false;
1160 	static PPPoint	RMouseDragStartPoint;
1161 
1162 	static DWORD	ltime;
1163 	static PPPoint	llastClickPosition = PPPoint(0,0);
1164 	static WORD		lClickCount = 0;
1165 
1166 	static BOOL		lMouseDown = FALSE;
1167 	static DWORD	lButtonDownStartTime;
1168 
1169 	static BOOL		rMouseDown = FALSE;
1170 	static DWORD	rtime;
1171 	static PPPoint	rlastClickPosition = PPPoint(0,0);
1172 	static WORD		rClickCount = 0;
1173 
1174 	static DWORD	rButtonDownStartTime;
1175 
1176 	static DWORD	timerTicker = 0;
1177 	static DWORD	idleResetCounter = 1;
1178 
1179 	static PPPoint	p;
1180 
1181 	if (lClickCount > 4)
1182 	{
1183 		lClickCount = 0;
1184 	}
1185 	if (rClickCount > 4)
1186 	{
1187 		rClickCount = 0;
1188 	}
1189 
1190 	switch (msg)
1191 	{
1192 #ifdef WINDOWS_DEFAULT_TIMER
1193 		case WM_PAINT:
1194 			DefWindowProc(hWnd, msg, wParam, lParam);
1195 			return 0;
1196 #else
1197 		case WM_PAINT:
1198 			return 0;
1199 #endif
1200 
1201 		case WM_SIZE:
1202 		{
1203 #ifdef DEBUG
1204 			LogWinMsg(*logger, _T("WM_SIZE"), lParam);
1205 #endif
1206 			break;
1207 		}
1208 
1209 		// ----- left mousebutton -------------------------------
1210 		case WM_LBUTTONDOWN:
1211 		{
1212 			if (!myTrackerScreen || rMouseDown)
1213 				break;
1214 
1215 			POINTFROMPARAM(p, lParam);
1216 
1217 #ifdef DEBUG
1218 			LogWinMsg(*logger, _T("WM_LBUTTONDOWN"), lParam);
1219 			LogMouseDown(*logger, lParam, p);
1220 #endif
1221 
1222 			PPEvent myEvent(eLMouseDown, &p, sizeof(PPPoint));
1223 			myTrackerScreen->raiseEvent(&myEvent);
1224 
1225 			lMouseDown = TRUE;
1226 			//lButtonDownStartTime = timerTicker;
1227 			lButtonDownStartTime = GetTickCount();
1228 
1229 			if (!lClickCount)
1230 			{
1231 				ltime = GetTickCount();
1232 				POINTFROMPARAM(llastClickPosition, lParam);
1233 			}
1234 			else if (lClickCount == 2)
1235 			{
1236 				DWORD deltat = GetTickCount() - ltime;
1237 				if (deltat > DBLCLKTIME)
1238 				{
1239 					lClickCount = 0;
1240 					ltime = GetTickCount();
1241 					POINTFROMPARAM(llastClickPosition, lParam);
1242 				}
1243 			}
1244 			lClickCount++;
1245 			break;
1246 		}
1247 
1248 		// ----- right mousebutton -------------------------------
1249 		case WM_RBUTTONDOWN:
1250 		{
1251 			if (!myTrackerScreen || lMouseDown)
1252 				break;
1253 
1254 			POINTFROMPARAM(p, lParam);
1255 
1256 			PPEvent myEvent(eRMouseDown, &p, sizeof(PPPoint));
1257 			myTrackerScreen->raiseEvent(&myEvent);
1258 
1259 			rMouseDown = TRUE;
1260 			//rButtonDownStartTime = timerTicker;
1261 			rButtonDownStartTime = GetTickCount();
1262 
1263 			if (!rClickCount)
1264 			{
1265 				rtime = GetTickCount();
1266 				POINTFROMPARAM(rlastClickPosition, lParam);
1267 			}
1268 			else if (rClickCount == 2)
1269 			{
1270 				DWORD deltat = GetTickCount() - rtime;
1271 				if (deltat > DBLCLKTIME)
1272 				{
1273 					rClickCount = 0;
1274 					rtime = GetTickCount();
1275 					POINTFROMPARAM(rlastClickPosition, lParam);
1276 				}
1277 			}
1278 			rClickCount++;
1279 			break;
1280 		}
1281 
1282 		// ----- left mousebutton -------------------------------
1283 		case WM_LBUTTONUP:
1284 		{
1285 			LMouseDrag = false;
1286 
1287 			if (!myTrackerScreen || !lMouseDown)
1288 				break;
1289 
1290 			lClickCount++;
1291 
1292 			if (lClickCount == 4)
1293 			{
1294 				DWORD deltat = GetTickCount() - ltime;
1295 
1296 				if (deltat < DBLCLKTIME)
1297 				{
1298 					POINTFROMPARAM(p, lParam);
1299 
1300 					if (abs(p.x - llastClickPosition.x) < 4 &&
1301 						abs(p.y - llastClickPosition.y) < 4)
1302 					{
1303 
1304 						PPEvent myEvent(eLMouseDoubleClick, &p, sizeof(PPPoint));
1305 						myTrackerScreen->raiseEvent(&myEvent);
1306 					}
1307 				}
1308 
1309 				lClickCount = 0;
1310 
1311 			}
1312 
1313 			POINTFROMPARAM(p, lParam);
1314 			PPEvent myEvent(eLMouseUp, &p, sizeof(PPPoint));
1315 			myTrackerScreen->raiseEvent(&myEvent);
1316 			lMouseDown = FALSE;
1317 			break;
1318 		}
1319 
1320 		// ----- right mousebutton -------------------------------
1321 		case WM_RBUTTONUP:
1322 		{
1323 			RMouseDrag = false;
1324 
1325 			if (!myTrackerScreen || !rMouseDown)
1326 				break;
1327 
1328 			rClickCount++;
1329 
1330 			if (rClickCount == 4)
1331 			{
1332 				DWORD deltat = GetTickCount() - rtime;
1333 				if (deltat < DBLCLKTIME)
1334 				{
1335 					POINTFROMPARAM(p, lParam);
1336 					if (abs(p.x - rlastClickPosition.x) < 4 &&
1337 						abs(p.y - rlastClickPosition.y) < 4)
1338 					{
1339 						PPEvent myEvent(eRMouseDoubleClick, &p, sizeof(PPPoint));
1340 						myTrackerScreen->raiseEvent(&myEvent);
1341 					}
1342 				}
1343 
1344 				rClickCount = 0;
1345 			}
1346 
1347 			POINTFROMPARAM(p, lParam);
1348 			PPEvent myEvent(eRMouseUp, &p, sizeof(PPPoint));
1349 			myTrackerScreen->raiseEvent(&myEvent);
1350 			rMouseDown = FALSE;
1351 			break;
1352 		}
1353 
1354 		case WM_MOUSEMOVE:
1355 		{
1356 			if (!myTrackerScreen)
1357 				break;
1358 
1359 			if ((wParam&MK_LBUTTON) && lMouseDown)
1360 			{
1361 				POINTFROMPARAM(p, lParam);
1362 
1363 				if (!LMouseDrag)
1364 				{
1365 					LMouseDragStartPoint = p;
1366 					LMouseDrag = true;
1367 				}
1368 
1369 				if (LMouseDrag && (abs(LMouseDragStartPoint.x - p.x) >= DRAGSENSITIVITY ||
1370 					abs(LMouseDragStartPoint.y - p.y) >= DRAGSENSITIVITY))
1371 				{
1372 					PPEvent myEvent(eLMouseDrag, &p, sizeof(PPPoint));
1373 					myTrackerScreen->raiseEvent(&myEvent);
1374 				}
1375 
1376 			}
1377 			else if ((wParam&MK_RBUTTON) && rMouseDown)
1378 			{
1379 				POINTFROMPARAM(p, lParam);
1380 
1381 				if (!RMouseDrag)
1382 				{
1383 					RMouseDragStartPoint = p;
1384 					RMouseDrag = true;
1385 				}
1386 
1387 				if (RMouseDrag && (abs(RMouseDragStartPoint.x - p.x) >= DRAGSENSITIVITY ||
1388 					abs(RMouseDragStartPoint.y - p.y) >= DRAGSENSITIVITY))
1389 				{
1390 
1391 					PPEvent myEvent(eRMouseDrag, &p, sizeof(PPPoint));
1392 					myTrackerScreen->raiseEvent(&myEvent);
1393 				}
1394 
1395 			}
1396 			else
1397 			{
1398 				POINTFROMPARAM(p, lParam);
1399 				PPEvent myEvent(eMouseMoved, &p, sizeof(PPPoint));
1400 				myTrackerScreen->raiseEvent(&myEvent);
1401 			}
1402 			break;
1403 		}
1404 
1405 #ifdef WINDOWS_DEFAULT_TIMER
1406 		case WM_TIMER:
1407 #else
1408 		case WM_MYTIMER:
1409 #endif
1410 		{
1411 			if (!myTrackerScreen)
1412 				break;
1413 
1414 			if (!(timerTicker % 1))
1415 			{
1416 				PPEvent myEvent(eTimer);
1417 				myTrackerScreen->raiseEvent(&myEvent);
1418 			}
1419 
1420 			// reset idle timer, so the device will not turn off
1421 			// automatically
1422 			// handle with care and use only when forced to do so
1423 			if (!(idleResetCounter & 1023) && dontTurnOffDevice)
1424 			{
1425 				SystemIdleTimerReset();
1426 			}
1427 
1428 			idleResetCounter++;
1429 			timerTicker++;
1430 			DWORD currentTime = GetTickCount();
1431 
1432 			if (lMouseDown &&
1433 				(currentTime - lButtonDownStartTime) > 500)
1434 			{
1435 				PPEvent myEvent(eLMouseRepeat, &p, sizeof(PPPoint));
1436 				myTrackerScreen->raiseEvent(&myEvent);
1437 			}
1438 			else if (rMouseDown &&
1439 				(currentTime - rButtonDownStartTime) > 500)
1440 			{
1441 				PPEvent myEvent(eRMouseRepeat, &p, sizeof(PPPoint));
1442 				myTrackerScreen->raiseEvent(&myEvent);
1443 			}
1444 
1445 			break;
1446 		}
1447 
1448 		case WM_CLOSE:
1449 		{
1450 			if (myTrackerScreen && myTracker)
1451 			{
1452 				PPEvent e(eAppQuit);
1453 				myTrackerScreen->raiseEvent(&e);
1454 
1455 				bool res = myTracker->shutDown();
1456 
1457 				if (res)
1458 					DestroyWindow(hWnd);
1459 			}
1460 			else
1461 			{
1462 				DestroyWindow(hWnd);
1463 			}
1464 
1465 			break;
1466 		}
1467 
1468 		case WM_SETTINGCHANGE:
1469 			TaskBar(false);
1470 			break;
1471 
1472 
1473 		case WM_KEYDOWN:
1474 		case WM_SYSKEYDOWN:
1475 
1476 #ifdef DEBUG
1477 			::PostMessage(hWnd, WM_CLOSE, 0, 0);
1478 #endif
1479 
1480 			if (wParam < 256)
1481 			{
1482 				if (mappings[wParam].keyModifiers != 0xFFFF &&
1483 					mappings[wParam].virtualKeyCode != 0xFFFF)
1484 				{
1485 					pp_int32 i;
1486 
1487 					WORD vkModifiers[3] = {VK_ALT, VK_SHIFT, VK_CONTROL};
1488 
1489 					for (i = 0; i < 3; i++)
1490 						if (mappings[wParam].keyModifiers & (1 << i))
1491 						{
1492 							// modifier key:
1493 							// scan code and character code remains zero
1494 							pp_uint16 vk[3] = {vkModifiers[i], 0, 0};
1495 							PPEvent eventKeyDown(eKeyDown, &vk, sizeof(vk));
1496 							myTrackerScreen->raiseEvent(&eventKeyDown);
1497 						}
1498 
1499 					setForceKeyModifier((KeyModifiers)mappings[wParam].keyModifiers);
1500 
1501 					// functionality key:
1502 					// scan code and character code remains zero
1503 					pp_uint16 vk[3] = {mappings[wParam].virtualKeyCode, 0, 0};
1504 					PPEvent eventKeyDown(eKeyDown, &vk, sizeof(vk));
1505 					myTrackerScreen->raiseEvent(&eventKeyDown);
1506 				}
1507 				else if (allowVirtualKeys)
1508 				{
1509 					QueryKeyModifiers();
1510 
1511 					WORD character = MapVirtualKey(wParam & 0xFFFF, 2);
1512 
1513 					// Check for right ALT key
1514 					if (::GetAsyncKeyState(VK_RMENU)>>15)
1515 						wParam = VK_RMENU;
1516 					// Check for right CTRL key
1517 					else if (::GetAsyncKeyState(VK_RCONTROL)>>15)
1518 						wParam = VK_RCONTROL;
1519 
1520 					if (wParam == VK_MENU)
1521 						wParam = VK_ALT;
1522 
1523 					// Since scancodes probably differ from desktop keyboards
1524 					// we do some virtual key => scancode transformation here
1525 					WORD chr[3] = {wParam, vkeyToScancode[wParam&255], character};
1526 
1527 					PPEvent myEvent(eKeyDown, &chr, sizeof(chr));
1528 
1529 					myTrackerScreen->raiseEvent(&myEvent);
1530 				}
1531 			}
1532 
1533 			break;
1534 
1535 		case WM_KEYUP:
1536 		case WM_SYSKEYUP:
1537 			if (wParam < 256)
1538 			{
1539 				if (mappings[wParam].keyModifiers != 0xFFFF &&
1540 					mappings[wParam].virtualKeyCode != 0xFFFF)
1541 				{
1542 					pp_int32 i;
1543 
1544 					WORD vkModifiers[3] = {VK_ALT, VK_SHIFT, VK_CONTROL};
1545 
1546 					// functionality key:
1547 					// scan code and character code remains zero
1548 					pp_uint16 vk[3] = {mappings[wParam].virtualKeyCode, 0, 0};
1549 					PPEvent eventKeyUp(eKeyUp, &vk, sizeof(vk));
1550 					myTrackerScreen->raiseEvent(&eventKeyUp);
1551 
1552 					for (i = 0; i < 3; i++)
1553 						if (mappings[wParam].keyModifiers & (1 << (2-i)))
1554 						{
1555 							// modifier key:
1556 							// scan code and character code remains zero
1557 							pp_uint16 vk[3] = {vkModifiers[i], 0, 0};
1558 							PPEvent eventKeyUp(eKeyUp, &vk, sizeof(vk));
1559 							myTrackerScreen->raiseEvent(&eventKeyUp);
1560 						}
1561 
1562 					clearForceKeyModifier((KeyModifiers)mappings[wParam].keyModifiers);
1563 				}
1564 				else if (allowVirtualKeys)
1565 				{
1566 					WORD character = MapVirtualKey(wParam & 0xFFFF, 2);
1567 
1568 					if (wParam == VK_MENU)
1569 						wParam = VK_ALT;
1570 
1571 					// Since scancodes probably differ from desktop keyboards
1572 					// we do some virtual key => scancode transformation here
1573 					WORD chr[3] = {wParam, vkeyToScancode[wParam&255], character};
1574 
1575 					PPEvent myEvent(eKeyUp, &chr, sizeof(chr));
1576 
1577 					myTrackerScreen->raiseEvent(&myEvent);
1578 				}
1579 			}
1580 
1581 			break;
1582 
1583 		case WM_CHAR:
1584 		{
1585 			WORD chr = wParam;
1586 
1587 			if (chr < 32 || chr > 127)
1588 				break;
1589 
1590 			PPEvent myEvent(eKeyChar, &chr, sizeof(chr));
1591 
1592 			myTrackerScreen->raiseEvent(&myEvent);
1593 
1594 			break;
1595 		}
1596 
1597 		case WM_DESTROY:
1598 			PostQuitMessage(0);
1599 			break;
1600 
1601 		case WM_KILLFOCUS:
1602 			GXSuspend();
1603 			break;
1604 
1605 		case WM_SETFOCUS:
1606 			GXResume();
1607 			break;
1608 
1609 		/*case WM_SETTINGCHANGE:
1610 			SHHandleWMSettingChange(hWnd, wParam,lParam,&s_sai);
1611      		break;*/
1612 	}
1613 
1614 	return DefWindowProc(hWnd, msg, wParam, lParam);
1615 }
1616 
1617 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1618 // -------------------------- debugging --------------------------------------------------------------------- //
1619 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
drawChar(unsigned short * buffer,unsigned int pitch,unsigned int chr,unsigned int tx,unsigned int ty,unsigned short col)1620 void drawChar(unsigned short* buffer, unsigned int pitch, unsigned int chr,unsigned int tx,unsigned int ty,unsigned short col)
1621 {
1622 	PPFont* font = PPFont::getFont(PPFont::FONT_SYSTEM);
1623 
1624     unsigned int x,y;
1625 
1626     for (y=0;y<8;y++)
1627         for (x=0;x<8;x++)
1628 			if (font->getPixelBit(chr, x, y))
1629                 buffer[((ty+y)*pitch+(tx+x))]=col;
1630 }
1631 
drawString(const char * textBuffer,unsigned short * drawBuffer,unsigned int pitch,unsigned int posx,unsigned int posy,unsigned short col)1632 void drawString(const char* textBuffer,unsigned short* drawBuffer, unsigned int pitch, unsigned int posx,unsigned int posy, unsigned short col)
1633 {
1634     unsigned int x = posx;
1635     while (*textBuffer)
1636 	{
1637         drawChar(drawBuffer, pitch, *textBuffer,x,posy,col);
1638         textBuffer++;
1639         x+=8;
1640     }
1641 }
1642