//========================================================================
//
//  WINPTR.C -- A Program for locating the Windows Pointer
//
//  (c) Douglas Boling, 1992
//
//  For better readability, set tab stops to every 3 characters.
//
//========================================================================

#include <windows.h>

#include "winptr.h"
 
//------------------------------------------------------------------------
//Function prototypes
//------------------------------------------------------------------------
int	PASCAL 		WinMain (HANDLE, HANDLE, LPSTR, int);
long	FAR PASCAL	WndProc (HWND, WORD, WORD, LONG);

VOID	FAR PASCAL	GetStatus (PHOOKSTAT);
BOOL	FAR PASCAL	LocatePointer (VOID);
BOOL	FAR PASCAL	SetLocate (BOOL);
BOOL	FAR PASCAL	SetTriggers (WORD, WORD);
BOOL	FAR PASCAL	SetCursorID (WORD);
BOOL	FAR PASCAL	SetArrowOnly (BOOL);
 
char		szAppName[] = "WinPtr";
char		szProfileName[] = "WINPTR.INI";
HANDLE  	hInstance;

//=======================================================================
//
// Program Entry Point (WinMain)
//
//=======================================================================
int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,
	            LPSTR lpszCmdParam, int nCmdShow) {


   HWND			hwnd;
	HANDLE		hAccel;
   MSG			msg;
   WNDCLASS		wndclass;

	if (!hPrevInstance) {
      wndclass.style          = CS_HREDRAW | CS_VREDRAW;
      wndclass.lpfnWndProc    = WndProc;
      wndclass.cbClsExtra     = 0;
      wndclass.cbWndExtra     = DLGWINDOWEXTRA;
      wndclass.hInstance      = hInstance;
      wndclass.hIcon          = LoadIcon (hInstance, szAppName);
      wndclass.hCursor        = LoadCursor (NULL, IDC_ARROW);
      wndclass.hbrBackground  = COLOR_WINDOW + 1;
      wndclass.lpszMenuName   = 0;
      wndclass.lpszClassName  = szAppName;

      RegisterClass (&wndclass);
   }
   hwnd = CreateDialog (hInstance, szAppName, 0, NULL);

	if (lpszCmdParam[0] == '/' || lpszCmdParam[0] == '-') 
		if (lpszCmdParam[1] == 'i' || lpszCmdParam[1] == 'I') 
			nCmdShow |= SW_MINIMIZE;

	ShowWindow (hwnd, nCmdShow);
	hAccel = LoadAccelerators (hInstance, szAppName);

	while (GetMessage (&msg, NULL, 0, 0)) {
		if (!TranslateAccelerator (hwnd, hAccel, &msg)) {
		   TranslateMessage (&msg);
		   DispatchMessage (&msg);
		}
	}
	SetLocate(FALSE);
   return msg.wParam;
}

//========================================================================
//
// Routines that replace standard library functions.
//
//========================================================================

//------------------------------------------------------------------------
// STRCPY - Copy String.
//------------------------------------------------------------------------
VOID strcpy (char * pDest, char * pSrc) {

	while (*pDest++ = *pSrc++);
}

//------------------------------------------------------------------------
// STRCAT - Concatinate String.
//------------------------------------------------------------------------
VOID strcat (char * pDest, char * pSrc) {

	while (*pDest)
		*pDest++;
	strcpy (pDest, pSrc);
}

//------------------------------------------------------------------------
// ITOA - Convert integer to ASCII
// NOTE:  This routine only works for sBase <= 10
//------------------------------------------------------------------------
VOID itoa (int sNum, char * pDest, int sBase) {

	char *pTemp;
	char	c;

	pTemp = pDest;
	//
	// Convert string
	//
	do {
		*pDest++ = (char)(sNum % sBase) + '0';
	} while (sNum /= sBase);

 	*pDest-- = 0;
	//
	// Reverse string
	//
	while (pDest > pTemp) {
		c = *pTemp;
		*pTemp++ = *pDest;
		*pDest-- = c;
	}
}

//========================================================================
//
// Routines used by WndProc
//
//========================================================================
//------------------------------------------------------------------------
// Set Enable Text
//------------------------------------------------------------------------
VOID SetEnableText (HWND hwnd, BOOL bEnable) {

	if (bEnable) {
		SetWindowText (hwnd, "WinPtr - Enabled");
		SetDlgItemText (hwnd, IDD_ENABLE, "Disable");
	} else {
		SetWindowText (hwnd, "WinPtr - Disabled");
		SetDlgItemText (hwnd, IDD_ENABLE, "Enable");
	}
	return;
}

//------------------------------------------------------------------------
// Set Move Trigger Text
//------------------------------------------------------------------------
VOID SetMoveTrigText (HWND hwnd, WORD wMoveTrig) {

	char	szTemp[80];
	char	szTemp1[10];

	itoa (wMoveTrig, szTemp1, 10);
	strcpy (szTemp, "Movement Trigger: ");
	strcat (szTemp, szTemp1);
	strcat (szTemp, " Pels");
	SetDlgItemText (hwnd, IDD_MOVETEXT, szTemp);
	return;
}

//------------------------------------------------------------------------
// Set Time Trigger Text
//------------------------------------------------------------------------
VOID SetTimeTrigText (HWND hwnd, WORD wTimeTrig) {

	char	szTemp[80];
	char	szTemp1[10];
		
	itoa (wTimeTrig, szTemp1, 10);
	strcpy (szTemp, "Persistance Time: ");
	strcat (szTemp, szTemp1);
	strcat (szTemp, " mS");
	SetDlgItemText (hwnd, IDD_TIMETEXT, szTemp);
	return;
}

//------------------------------------------------------------------------
//
// About box dialog procedure
//
//------------------------------------------------------------------------
BOOL FAR PASCAL AboutDlgProc (HWND hwnd, WORD message, WORD wParam, 
                               LONG lParam) {

	switch (message) {

		case WM_COMMAND:

			switch (wParam) {

				case IDOK:

					EndDialog (hwnd, 1);
					return TRUE;
			}
			break;

		case WM_CLOSE:
			EndDialog (hwnd, 0);
			return TRUE;
	}
	return FALSE;	
}

//========================================================================
//
// Main Window Procedure.
//
//========================================================================
long FAR PASCAL WndProc (HWND hwnd, WORD message, WORD wParam, LONG lParam) {

	static	FARPROC	lpfnAboutDlgProc;
	int	   i,j;
	HOOKSTAT	hsHook;
	char		szTemp[10];

   switch (message) {
	
      case WM_CREATE:

			hInstance = ((LPCREATESTRUCT) lParam)->hInstance;
			//
			//Create thunk for dialog box 
			//
			lpfnAboutDlgProc = MakeProcInstance (AboutDlgProc, 
			                                     hInstance);
			//
			//Get and set initial trigger, cursor, and pos values 
			//
			i = GetPrivateProfileInt (szAppName, "MoveTrig", 
			                          10, szProfileName);
			j = GetPrivateProfileInt (szAppName, "TimeTrig", 
			                          300, szProfileName);
			SetTriggers (i, j);

			i = GetPrivateProfileInt (szAppName, "Cursor", 
			                          1, szProfileName);
			SetCursorID (i);

			i = GetPrivateProfileInt (szAppName, "ArrowOnly", 
			                          1, szProfileName);
			SetArrowOnly (i);

			SetLocate(TRUE);
			return 0;


		case WM_SIZE:

			GetStatus (&hsHook);
			SetScrollRange (GetDlgItem (hwnd, IDD_MOVETRIG), 
			                SB_CTL, 0, 200, FALSE);

			if (hsHook.wTimeTrig > 100) 
				i = 100 + ((hsHook.wMoveTrig - 100) / 5);
			else
				i = hsHook.wMoveTrig;
			SetScrollPos (GetDlgItem (hwnd, IDD_MOVETRIG), 
			              SB_CTL, hsHook.wMoveTrig, TRUE);


			SetScrollRange (GetDlgItem (hwnd, IDD_TIMETRIG), 
			                SB_CTL, 0, 500, FALSE);

			if (hsHook.wTimeTrig > 100) 
				i = 100 + ((hsHook.wTimeTrig - 100) / 10);
			else
				i = hsHook.wTimeTrig;
			SetScrollPos (GetDlgItem (hwnd, IDD_TIMETRIG), 
			              SB_CTL, i, TRUE);

			SetMoveTrigText (hwnd, hsHook.wMoveTrig);
			SetTimeTrigText (hwnd, hsHook.wTimeTrig);
			SetEnableText (hwnd, hsHook.bEnabled);
			if (hsHook.bArrowOnly)
				CheckDlgButton (hwnd, IDD_ARROWONLY, 1);
			else 
				CheckDlgButton (hwnd, IDD_ARROWONLY, 0);

			break;


		case WM_COMMAND:

			GetStatus (&hsHook);
			switch (wParam) {

				case IDD_ABOUT:
					DialogBox (hInstance, "About", hwnd, lpfnAboutDlgProc);
					return 0;

				case IDD_ARROWONLY:
					if (hsHook.bArrowOnly) {
						SetArrowOnly (FALSE);
						CheckDlgButton (hwnd, IDD_ARROWONLY, 0);
					} else {
						SetArrowOnly (TRUE);
						CheckDlgButton (hwnd, IDD_ARROWONLY, 1);
					}								
					return 0;

				case IDD_ENABLE:
					if (hsHook.bEnabled) {
						if (SetLocate(FALSE)) 
							SetEnableText (hwnd, FALSE);
					} else {
						if (SetLocate(TRUE)) 
							SetEnableText (hwnd, TRUE);
					}								
					return 0;

				case IDD_SETCUR:
					hsHook.wCursorID++;
					if (hsHook.wCursorID > 10)
						hsHook.wCursorID = 1;
					SetCursorID (hsHook.wCursorID);
					return 0;

				case IDD_EXIT:
	   		   SendMessage (hwnd, WM_CLOSE, 0, 0);
					return 0;
			}
			break;

		case WM_HSCROLL:

			i = GetScrollPos (HIWORD (lParam), SB_CTL);	// Get Scroll bar Pos
			j = GetDlgCtrlID (HIWORD (lParam));			// Get Scroll bar ID

			switch (wParam) {
				case SB_LINEUP:
					i--;
					break;

				case SB_LINEDOWN:
					i++;
					break;

				case SB_PAGEUP:
					i -= 10;
					break;

				case SB_PAGEDOWN:
					i += 10;
					break;

				case SB_THUMBTRACK:
				case SB_THUMBPOSITION:
					i = LOWORD (lParam);
					break;
			}
			SetScrollPos (HIWORD (lParam), SB_CTL, i, TRUE);

			GetStatus (&hsHook);
			if (j == IDD_MOVETRIG) {
				if (i > 100) i = 100 + ((i - 100) * 5);
				SetMoveTrigText (hwnd, i);
				SetTriggers (i, hsHook.wTimeTrig);
			} else {
				if (i > 100) i = 100 + ((i - 100) * 10);
				SetTimeTrigText (hwnd, i);
				SetTriggers (hsHook.wMoveTrig, i);
			}
			break;

		case WM_DESTROY:
			//
			//Save Trigger values
			//
			GetStatus (&hsHook);

			itoa (hsHook.wCursorID, szTemp, 10);
			WritePrivateProfileString (szAppName, "Cursor", szTemp, 
			                           szProfileName);
			itoa (hsHook.wMoveTrig, szTemp, 10);
			WritePrivateProfileString (szAppName, "MoveTrig", szTemp, 
			                           szProfileName);
			itoa (hsHook.wTimeTrig, szTemp, 10);
			WritePrivateProfileString (szAppName, "TimeTrig", szTemp, 
			                           szProfileName);
			itoa (hsHook.bArrowOnly, szTemp, 10);
			WritePrivateProfileString (szAppName, "ArrowOnly", szTemp, 
			                           szProfileName);
			PostQuitMessage (0);
			return 0;
	}
	return DefWindowProc (hwnd, message, wParam, lParam);
}

