/* (c) Copyright 1986 MICROGRAFX, Inc.,
   1820 N. Greenville Ave., Richardson, Tx. 75081.

**********************************************************************
**********************************************************************

				THERME.C

**********************************************************************
**********************************************************************

This Module defines the all routines that control the application.
When the application is loaded, Windows calls the WinMain procedure.  
WinMain initializes key variables used by the various functions in the 
application and creates a window for it via the initialization 
function.  It then waits for input values, passing them to the window 
procedure each time an event occurs. */

#include <windows.h>
#include "therme.h"
#include "stdlib.h"
#include "string.h"

/* *************************** History **************************** */

/* 11/24/86 (PML) - signoff */

/* ************************** Constants *************************** */

#define LOCAL

#define APP_CLASS	 "Therme"	/* Window Class Name */
#define HIGHTEMP	 100		/* Highest Displayable Temp */
#define LOWTEMP 	 -20		/* Lowest Displayable Temp */
#define ICON_NAME	 "ClassIcon"	/* Resource Icon ID String */
#define IDABOUT 	 005		/* ID for About... */
#define MENUNAME	 "MainMenu"	/* Resource Menu ID String */
#define VIEWPORT_ORGX	 0		/* Viewport Origin X Coord */
#define VIEWPORT_ORGY	 0		/* Viewport Origin Y Coord */
#define WINDOW_EXTX	 1000		/* Window Extent X Coord */
#define WINDOW_EXTY	 1000		/* Window Extent Y Coord */
#define WINDOW_ORGX	 0		/* Window Origin X Coord */
#define WINDOW_ORGY	 0		/* Window Origin Y Coord */
#define WND_NAME	 "Therme"	/* Window Name */

/* ************************** Local Data ************************** */

BOOL   bCurrentTempMode = TRUE,		/* TRUE for Farenheit */
       bOldTempMode = TRUE;		/* Previous Temp Mode */
char   ProStringBuffer [80];		/* Profile String Buffer */
HANDLE hModule,				/* Instance Handle */
       hWindow;				/* Window Handle */
int    GraphicTemp = 0,			/* Graphic Temp Setting */
       DegreeInc = 1,			/* Temperature Increment */
       OldTemp,				/* Previous Temp Setting */
       MathTemp;			/* Math Temp. Conversion */
PAINTSTRUCT Paint;			/* Window Paint Structure */
RECT   ClientRect;			/* Client Area Rect. */
WORD   ViewportWidth,			/* Viewport X Extent */
       ViewportHeight,			/* Viewport Y Extent */
       ViewportOriginX = 0,		/* Viewport X Extent */
       ViewportOriginY = 0;		/* Viewport Y Extent */

/* ************************ Local Routines ************************ */

LOCAL BOOL NEAR PASCAL command (HWND,WORD);
LOCAL WORD NEAR PASCAL dialog_box (HWND,LPSTR,FARPROC);
LOCAL HWND NEAR PASCAL init_app (HANDLE,HANDLE,LPSTR,int);
LOCAL void NEAR PASCAL paint_window (HDC,WORD,WORD);
LOCAL BOOL NEAR PASCAL show_menu (HANDLE,HWND);

LOCAL BOOL NEAR PASCAL command (hWindow,Choice)
   /* This routine receives and processes menu input. It calls the 
      various dialog box functions and initiating the print task */
HWND hWindow;
WORD Choice;
{
	BOOL	bHandled = TRUE;
	BYTE	Item;
	FARPROC lpPrintProc;
	HANDLE	hPrintDlg;
	HDC	hPrintDC;
	int	PrintResult;
	PSTR	pDriverName,
		pPortName;
	WORD	HRes,
		VRes;

	switch (Choice)
	{
	case IDABOUT:
	   dialog_box (hWindow,(LPSTR) "AboutDlg",about_dialog);
	   break;

	case SET_TEMPERATURE:
	   dialog_box (hWindow,(LPSTR) "SetTempDlg",set_temp_dialog);
	   break;

	case PRINT:
	   GetProfileString ((LPSTR) "windows",
			     (LPSTR) "device",
			     NULL,
			     (LPSTR) ProStringBuffer,
			     80);
	   pDriverName = strchr (ProStringBuffer,',');
	   *pDriverName = '\0';
	   pDriverName++;
	   pPortName = strchr (pDriverName,',');
	   *pPortName = '\0';
	   pPortName++;
	   hPrintDC = CreateDC ((LPSTR) pDriverName,
				(LPSTR) ProStringBuffer,
				(LPSTR) pPortName,
				NULL);
	   if (hPrintDC == NULL)
	      Item = MessageBox (hWindow,
			(LPSTR) "Cannot Print. Please Select Printer",
			(LPSTR) NULL,
			MB_OK | MB_ICONHAND);
	   else
	   {
	      HRes = GetDeviceCaps (hPrintDC,HORZRES);
	      VRes = GetDeviceCaps (hPrintDC,VERTRES);
	      lpPrintProc = MakeProcInstance (print_dialog,hModule);
	      hPrintDlg = CreateDialog (hModule,(LPSTR) "SpoolDlg",
				hWindow,lpPrintProc);
	      PrintResult = Escape (hPrintDC,STARTDOC,11,
				(LPSTR) "Thermometer",NULL);
	      if (PrintResult == -1)
		 Item = MessageBox (hWindow,
		(LPSTR) "Cannot Print.  Bad Port or Insuffic. Memory",
				   (LPSTR) NULL,
				   MB_OK | MB_ICONHAND);
	      else
	      {
	      paint_window (hPrintDC,HRes,VRes);
	      Escape (hPrintDC,NEWFRAME,NULL,NULL,NULL);
	      Escape (hPrintDC,ENDDOC,NULL,NULL,NULL);
	      DestroyWindow (hPrintDlg);
	      DeleteDC (hPrintDC);
	      FreeProcInstance (lpPrintProc);
	      }
	   }
	   break;

	default:
	   bHandled = FALSE;
	}

	return (bHandled);
}

LOCAL WORD NEAR PASCAL dialog_box (hWindow,lpDialog,lpCallBack)
   /* This function displays a given dialog box and returns the value 
      ret'd by the dialog box call-back function.  The function first 
      creates a relocation-independent version of the call-back 
      function, then calls DialogBox. If Windows indicates an 
      insufficient memory condition exists, then the user is so 
      informed. Additionally, since the drawing area always needs to 
      be updated after a dialog box is removed, the client area of the 
      window is invalidated so as to be completely redrawn. */
HWND	hWindow;
LPSTR	lpDialog;
FARPROC lpCallBack;
{
	BYTE	Item;
	FARPROC lpProc = MakeProcInstance (lpCallBack,hModule);
	int	Result = DialogBox (hModule,lpDialog,hWindow,lpProc);

	if (Result == -1)
	{
	   Item = MessageBox (hWindow,
		(LPSTR) "Not Enough Memory To Display Dialog Box",
			     (LPSTR) NULL,
			     MB_OK | MB_ICONHAND);

	}

	FreeProcInstance (lpProc);

	InvalidateRect (hWindow,(LPRECT) &ClientRect,TRUE);

	return (Result);
}

LOCAL HWND NEAR PASCAL init_app (hPrevious,hInstance,lpCmdLine,Show)
   /* This function handles the initialization of the sample 
      application.  This includes registering the window class, 
      creating the window, and loading the menus. The viewport 
      coordinates of the client area of the window are also 
      established in globally available variables */
HANDLE hPrevious,
       hInstance;
int    Show;
LPSTR  lpCmdLine;
{
	BOOL	    bRegistered;
	HWND	    hWindow;
	WNDCLASS    Class;

	hModule = hInstance;

	Class.style	    = CS_OWNDC | CS_VREDRAW | CS_HREDRAW;
	Class.lpfnWndProc   = AppWndProc;
	Class.cbClsExtra    = NULL;
	Class.cbWndExtra    = NULL;
	Class.hInstance     = hInstance;
	Class.hCursor	    = LoadCursor(NULL,IDC_ARROW);
	Class.hIcon	    = LoadIcon(hInstance,(LPSTR) "ClassIcon");
	Class.hbrBackground = GetStockObject (WHITE_BRUSH);
	Class.lpszMenuName  = (LPSTR) NULL;
	Class.lpszClassName = (LPSTR) APP_CLASS;

	bRegistered = RegisterClass((LPWNDCLASS) &Class);

	hWindow = CreateWindow ((LPSTR) APP_CLASS,
				(LPSTR) WND_NAME,
				WS_TILEDWINDOW,
				0,
				0,
				0,
				0,
				(HWND) NULL,
				(HMENU) NULL,
				(HANDLE) hInstance,
				(LPSTR) NULL);

	ShowWindow (hWindow,Show);

	GetClientRect (hWindow,(LPRECT) &ClientRect);
	ViewportWidth = ClientRect.right;
	ViewportHeight= ClientRect.bottom;

	show_menu (hInstance,hWindow);

	return (hWindow);
}

LOCAL void NEAR PASCAL paint_window (hDC,ExtentX,ExtentY)
   /* This function erases the window background and repaints the 
      thermometer using the given device context.  The variable 
      GraphicTemp is used to visibly update the rectangle that 
      represents the temperature. */
HDC  hDC;
WORD ExtentX,
     ExtentY;
{
	char	    Buffer[3];
	int	    StartHashX = 460,
		    StartHashY = 100,
		    EndHashX   = 485,
		    EndHashY   = 100,
		    HashCount  = 12,
		    HashInc    = 5,
		    Degree     = HIGHTEMP,
		    StringLength;
	PSTR	    pDegreeString;

	SetMapMode (hDC,MM_ISOTROPIC);
	SetWindowOrg (hDC,0,0);
	SetWindowExt (hDC,1000,1000);
	SetViewportOrg (hDC,ViewportOriginX,ViewportOriginY);
	SetViewportExt (hDC,ExtentX,ExtentY);
	FillRect (hDC,(LPRECT) &Paint.rcPaint,
			GetStockObject (WHITE_BRUSH));

	Rectangle (hDC,460,50,540,725);
	SelectObject (hDC,CreateSolidBrush (RGB (255,00,00)));
	Ellipse (hDC,375,700,625,950);
	Rectangle (hDC,480,(600 - (GraphicTemp * 5)),520,700);
	SelectObject (hDC,GetStockObject (WHITE_BRUSH));

	for (;HashCount>=1;--HashCount)
	{
	   pDegreeString = itoa (Degree,Buffer,10);
	   StringLength = strlen (pDegreeString);
	   MoveTo (hDC,StartHashX,StartHashY);
	   TextOut (hDC,
		    (StartHashX-75),
		    (StartHashY-15),
		    pDegreeString,
		    StringLength);
	   LineTo (hDC,EndHashX,EndHashY);
	   MoveTo (hDC,(EndHashX + 30),(EndHashY + 25));
	   LineTo (hDC,(EndHashX + 55),(EndHashY + 25));
	   Degree = Degree - HashInc;
	   pDegreeString = itoa (Degree,Buffer,10);
	   StringLength = strlen (pDegreeString);
	   TextOut (hDC,
		    (EndHashX + 65),
		    (EndHashY + 10),
		    pDegreeString,
		    StringLength);

	   StartHashY = StartHashY + 50;
	   EndHashY = EndHashY + 50;
	   Degree = Degree - HashInc;
	}

}

LOCAL BOOL NEAR PASCAL show_menu (hInstance,hWindow)
   /* This function loads and displays the available menu resources, 
      and adds the "About..." option to the system menu. */
HANDLE hInstance;
HWND   hWindow;
{
	BOOL	 bSetMenu;
	HMENU	 hMenuResource,
		 hSysMenu;

	hMenuResource = LoadMenu (hInstance,(LPSTR) MENUNAME);
	bSetMenu = SetMenu (hWindow,hMenuResource);
	hSysMenu = GetSystemMenu(hWindow,0);
	ChangeMenu (hSysMenu,NULL,(LPSTR) NULL,NULL,
		MF_SEPARATOR | MF_APPEND);
	ChangeMenu (hSysMenu,IDABOUT,(LPSTR) "About...",IDABOUT,
		MF_APPEND);
	return (bSetMenu);
}

/* ********************** Exported Routines *********************** */

long FAR PASCAL AppWndProc (hWindow,Message,Word,Long)
   /* This Routine handles all input to the application.  Any input 
      values that the routine chooses not to handle are passed to the 
      default window procedure. */
HWND	 hWindow;
unsigned Message;
WORD	 Word;
long	 Long;
{
	BOOL bHandled = TRUE;
	long Result;

	if (Message == WM_COMMAND || Message == WM_SYSCOMMAND)
		bHandled = command (hWindow,Word);
	else if (Message == WM_PAINT)
	{
	   paint_window (BeginPaint (hWindow,(LPPAINTSTRUCT) &Paint),
			ViewportWidth,
			ViewportHeight);
	   EndPaint (hWindow,(LPPAINTSTRUCT) &Paint);
	}
	else
	   bHandled = FALSE;

	if (bHandled == TRUE)
	   Result = (long) 0;
	else
	   Result = DefWindowProc (hWindow,Message,Word,Long);

	return (Result);

}

BOOL FAR PASCAL about_dialog (hDialog,Message,Word,Long)
HWND hDialog;
unsigned Message;
WORD Word;
LONG Long;
 /* This function is called by Windows to handle input to the About...
    dialog box.  Since "OK" is the only option available to the user, 
    only one message is processed, namely, WM_COMMAND. */
{
	BOOL Result = TRUE;

	if (Message == WM_COMMAND)
	   EndDialog (hDialog,Result);
	else
	   Result = FALSE;

	return (Result);

}

BOOL FAR PASCAL print_dialog (hDialog,Message,Word,Long)
HWND hDialog;
unsigned Message;
WORD Word;
LONG Long;
   /* This function processes input to the modeless dialog box created 
      when the user selects the "Print" command from the file menu. */
{
	BOOL Result = TRUE;

	if (Message == WM_COMMAND && Word == IDCANCEL)
	   EndDialog (hDialog,Result);
	else
	   Result = FALSE;

	return (Result);

}

BOOL FAR PASCAL set_temp_dialog (hDialog,Message,Word,Long)
HWND hDialog;
unsigned Message;
WORD Word;
LONG Long;
   /* This function is called by Windows to process input to the Set 
      Temperature dialog box.  It looks for input from the scroll bars 
      and updates the associated control each time a WM_VSCROLL 
      message is received.  As part of the dialog's initialization, 
      the current temperature is remembered in case the user changes 
      it and then cancels the dialog.  This ensures that the correct 
      temperature will be displayed.  The GraphicTemp variable is used 
      for visible updating of the Thermometer when MathTemp falls 
      within displayable limits. */
{
	BOOL Result = TRUE;

	if (Message == WM_INITDIALOG)
	{
	   SetDlgItemInt (hDialog,SET_DEGS,MathTemp,1);
	   OldTemp = MathTemp;
	   bOldTempMode = bCurrentTempMode;
	   if (bCurrentTempMode == TRUE)
	      CheckRadioButton (hDialog,FARENHEIT,CELSIUS,FARENHEIT);
	   else
	      CheckRadioButton (hDialog,FARENHEIT,CELSIUS,CELSIUS);
	}
	else if (Message == WM_COMMAND)
	{
	   switch (Word)
	   {
	      case CELSIUS:
		 CheckRadioButton (hDialog,FARENHEIT,CELSIUS,CELSIUS);
		 if (bCurrentTempMode == TRUE)
		 {
		    MathTemp = (5*(MathTemp - 32))/9;
		    if (MathTemp > HIGHTEMP)
		       GraphicTemp = HIGHTEMP;
		    else if (MathTemp < LOWTEMP)
		       GraphicTemp = LOWTEMP;
		    else
		       GraphicTemp = MathTemp;

		    bCurrentTempMode = FALSE;
		    SetDlgItemInt (hDialog,SET_DEGS,MathTemp,1);
		 }
		 else
		    break;

		 break;

	      case FARENHEIT:
		 CheckRadioButton (hDialog,FARENHEIT,CELSIUS,FARENHEIT);
		 if (bCurrentTempMode == FALSE)
		 {
		    MathTemp = ((9*MathTemp)/5)+32;
		    if (MathTemp > HIGHTEMP)
		       GraphicTemp = HIGHTEMP;
		    else if (MathTemp < LOWTEMP)
		       GraphicTemp = LOWTEMP;
		    else
		       GraphicTemp = MathTemp;
		    bCurrentTempMode = TRUE;
		    SetDlgItemInt (hDialog,SET_DEGS,MathTemp,1);
		 }
		 else
		    break;

		 break;

	      case IDOK:
		 EndDialog (hDialog,Word);
		 break;
	      case IDCANCEL:
		 MathTemp = OldTemp;
		 bCurrentTempMode = bOldTempMode;
		 EndDialog (hDialog,Word);
		 break;
	      default:
		 ;
	   }
	}
	else if (Message == WM_VSCROLL)
	{
	   switch (Word)
	   {
	      case SB_LINEUP:
		 MathTemp = MathTemp + DegreeInc;
		 break;
	      case SB_LINEDOWN:
		 MathTemp = MathTemp - DegreeInc;
		 break;
	      default:
		 MathTemp = MathTemp + 0;
	   }

	   if (MathTemp < LOWTEMP)
	   {
	      GraphicTemp = LOWTEMP;
	      SetDlgItemInt (hDialog,SET_DEGS,MathTemp,1);
	   }
	   else if (MathTemp > HIGHTEMP)
	   {
	      GraphicTemp = HIGHTEMP;
	      SetDlgItemInt (hDialog,SET_DEGS,MathTemp,1);
	   }
	   else
	   {
	      GraphicTemp = MathTemp;
	      SetDlgItemInt (hDialog,SET_DEGS,MathTemp,1);
	   }

	}

	else
	   Result = FALSE;

	return (Result);

}

int FAR PASCAL WinMain(hInstance,hPrevious,lpCmdLine,Show)
   /* This routine is called whenever a new instance of the 
      application is created.  First, init_app is called so that all 
      necessary initialization can take place.  Then a loop is created 
      that waits for input to the application and dispatches the input 
      values to the application's window procedure. */
HANDLE hInstance,
       hPrevious;
LPSTR  lpCmdLine;
int    Show;
{
	HWND hWindow;

	hWindow = init_app (hPrevious,hInstance,lpCmdLine,Show);

	if (hWindow != NULL)
	{
		MSG Message;

		while (GetMessage ((LPMSG) &Message,NULL,0,0))
		{
			TranslateMessage ((LPMSG) &Message);
			DispatchMessage ((LPMSG) &Message);
		}
	}
	return (0);
}
