/*==============================================================*\
 *  Pnt.c - routines for the painting of the main window
 *	Copyright 1990, 1992 IBM Corp.
 *--------------------------------------------------------------
 *
 *  DISCLAIMER OF WARRANTIES.  The following [enclosed] code is
 *  sample code created by IBM Corporation. This sample code is not
 *  part of any standard or IBM product and is provided to you solely
 *  for	 the purpose of assisting you in the development of your
 *  applications.  The code is provided "AS IS", without
 *  warranty of any kind.  IBM shall not be liable for any damages
 *  arising out of your use of the sample code, even if they have been
 *  advised of the possibility of   such damages.
 *
 *--------------------------------------------------------------
 *  This module contains the code for the main client window
 *  painting
 *
\*==============================================================*/



/*--------------------------------------------------------------*\
 *  Include files, macros, defined constants, and externs
\*--------------------------------------------------------------*/

#define INCL_WINMESSAGEMGR
#define INCL_WINWINDOWMGR
#define INCL_GPICONTROL
#define INCL_GPIPRIMITIVES
#define INCL_GPILCIDS
#define INCL_DOSPROCESS
#define INCL_WINFRAMEMGR
#define INCL_WINSCROLLBARS

#include <os2.h>
#include <stdlib.h>
#include <string.h>
#include "svrqmain.h"
#include "svrqglbl.h"
/*--------------------------------------------------------------*\
 *  Entry point declarations
\*--------------------------------------------------------------*/

#include "svrqxtrn.h"


/* returns offset from beginning of circular queue */
#define	 BUFF_OFFSET(index, offset)  (((index)+(offset) < MAX_MESSAGES) ? (index)+(offset) : (index)+(offset)-MAX_MESSAGES)

/*--------------------------------------------------------------*\
 *  Global (module) variables
\*--------------------------------------------------------------*/

HWND  hwndHscroll, hwndVscroll ;
LONG  sHscrollMax=0, sVscrollMax=0, sHscrollPos=0, sVscrollPos=0, cxChar,
      cxCaps, cyChar, cyDesc, cxClient, cyClient, cxTextTotal;


/****************************************************************\
 *  Main client painting routine
 *--------------------------------------------------------------
 *
 *  Name:   MainPaint(hwnd)
 *
 *  Purpose: Paints the main client window.
 *
 *  Usage:  Routine is called whenver the client window
 *	    procedure receives a WM_PAINT message
 *
 *  Method:
 *	    - begins painting by calling WinBeginPaint
 *		and retrieving the HPS for the window
 *	    - performs any painting desired
 *	    - ends painting by calling WinEndPaint
 *
 *  Returns:
 *
\****************************************************************/
VOID MainPaint(HWND hwnd,				     /* handle to window */
	       CHAR SvrQMsgs[MAX_MESSAGES][MESSAGE_LEN+38],  /* array of messages */
	       unsigned int uiIndex,			     /* beginning of circular array */
	       SHORT sTotalMsgs)			     /* total number of messages */
{
   RECTL	 rclInvalid;
   HPS		 hps;
   LONG		 sPaintBeg, sPaintEnd, sLine;
   POINTL	 ptl;
   unsigned int	 uiOffset;

   uiOffset = (sTotalMsgs < MAX_MESSAGES) ? 0 : uiIndex;

   hps = WinBeginPaint(hwnd, NULLHANDLE, (PRECTL)&rclInvalid);
   GpiErase(hps);

   sPaintBeg = max(0, sVscrollPos + (cyClient - rclInvalid.yTop) / cyChar);
   sPaintEnd = min(sTotalMsgs, sVscrollPos + (cyClient - rclInvalid.yBottom) / cyChar + 1);

   for (sLine = sPaintBeg ; sLine < sPaintEnd ; sLine++)
   {
      ptl.x = cxCaps - sHscrollPos ;
      ptl.y = cyClient - cyChar * (BUFF_OFFSET(uiOffset,sLine) + 1 - sVscrollPos) + cyDesc ;

      GpiCharStringAt (hps, &ptl,
		       (LONG) strlen (SvrQMsgs[BUFF_OFFSET(uiOffset,sLine)]),
		       SvrQMsgs[BUFF_OFFSET(uiOffset,sLine)]) ;
   }

   WinEndPaint (hps) ;
}   /* MainPaint() */


/****************************************************************\
 *  Initialization routine
 *--------------------------------------------------------------
 *
 *  Name:   InitMainWindow(hwnd, mp1, mp2)
 *
 *  Purpose: Performs initialization functions required
 *		when the main window is Copyright.
 *
 *  Usage:  Called once during the WM_CREATE processing when
 *	    the main window is Copyright.
 *
 *  Method:
 *
 *  Returns: value to be returned from the WM_CREATE message:
 *	    TRUE - window creation should stop
 *	    FALSE - window creation should continue
\****************************************************************/

MRESULT InitMainWindow(HWND hwnd,      /* handle to the main client window */
		       MPARAM mp1,     /* first parameter of WM_CREATE message */
		       MPARAM mp2)     /* second parameter of WM_CREATE message */
{
   FONTMETRICS fm;
   HPS	       hps;

   hps = WinGetPS (hwnd) ;
   GpiQueryFontMetrics (hps, (LONG) sizeof fm, &fm) ;

   cxChar = fm.lAveCharWidth ;
   cxCaps = fm.lEmInc ;
   cyChar = fm.lMaxBaselineExt ;
   cyDesc = fm.lMaxDescender ;

   WinReleasePS (hps) ;

   cxTextTotal = MESSAGE_LEN * cxChar ;

   hwndHscroll = WinWindowFromID (
		       WinQueryWindow (hwnd, QW_PARENT),
		       FID_HORZSCROLL) ;

   hwndVscroll = WinWindowFromID (
		       WinQueryWindow (hwnd, QW_PARENT),
		       FID_VERTSCROLL) ;

   return (MRFROMLONG(0));
}


/****************************************************************\
 *  Window sizing routine
 *--------------------------------------------------------------
 *
 *  Name:   InitMainWindow(hwnd, mp1, mp2)
 *
 *  Purpose: Adjusts scroll bars and window parameters
 *		when the main window is resized.
 *
 *  Usage:  Called when the client window receives a WM_SIZE
 *	    message.
 *
 *  Method:
 *
 *  Returns:
\****************************************************************/

MRESULT MainSize(HWND	hwnd,	 /* handle to the main client window */
		 USHORT sTotalMsgs,
		 MPARAM mp1,	 /* first parameter of WM_CREATE message */
		 MPARAM mp2)	 /* second parameter of WM_CREATE message */
{

   cxClient = SHORT1FROMMP (mp2) ;
   cyClient = SHORT2FROMMP (mp2) ;

   sHscrollMax = max (0, cxTextTotal - cxClient) ;
   sHscrollPos = min (sHscrollPos, sHscrollMax) ;

   WinSendMsg (hwndHscroll, SBM_SETSCROLLBAR,
			    MPFROM2SHORT (sHscrollPos, 0),
			    MPFROM2SHORT (0, sHscrollMax)) ;

   WinEnableWindow (hwndHscroll, (BOOL)((sHscrollMax != 0) ? TRUE : FALSE)) ;

   sVscrollMax = max (0, sTotalMsgs - cyClient / cyChar) ;
   sVscrollPos = min (sVscrollPos, sVscrollMax) ;

   WinSendMsg (hwndVscroll, SBM_SETSCROLLBAR,
			    MPFROM2SHORT (sVscrollPos, 0),
			    MPFROM2SHORT (0, sVscrollMax)) ;

   WinEnableWindow (hwndVscroll, (BOOL)((sVscrollMax != 0) ? TRUE : FALSE)) ;

   /* referenced to prevent compiler error */
   return (MRFROMLONG(0));
}


/****************************************************************\
 *  Horizontal scrolling routine
 *--------------------------------------------------------------
 *
 *  Name:   MainHorizScroll(hwnd, mp1, mp2)
 *
 *  Purpose: Scrolls window horizontally.
 *
 *  Usage:  Called when the client window receives a WM_HSCROLL
 *	    message.
 *
 *  Method:
 *
 *  Returns:
\****************************************************************/

MRESULT MainHorizScroll(HWND hwnd,   /* handle to the main client window */
			MPARAM mp2)  /* second parameter of WM_CREATE message */
{
   LONG sHscrollInc;

   switch (SHORT2FROMMP (mp2))
   {
      case SB_LINELEFT:
	 sHscrollInc = -cxCaps ;
	 break ;

      case SB_LINERIGHT:
	 sHscrollInc = cxCaps ;
	 break ;

      case SB_PAGELEFT:
	 sHscrollInc = -8 * cxCaps ;
	 break ;

      case SB_PAGERIGHT:
	 sHscrollInc = 8 * cxCaps ;
	 break ;

      case SB_SLIDERPOSITION:
	 sHscrollInc = SHORT1FROMMP (mp2) - sHscrollPos;
	 break ;

      default:
	 sHscrollInc = 0;
	 break ;
   }

   sHscrollInc = max (-sHscrollPos,
		 min (sHscrollInc, sHscrollMax - sHscrollPos)) ;

   if (sHscrollInc != 0)
   {
      sHscrollPos += sHscrollInc ;
      WinScrollWindow ((HWND)hwnd, -sHscrollInc, 0, (PRECTL)NULL,
		       (PRECTL)NULL, (HRGN)NULL, (PRECTL)NULL,
		       SW_INVALIDATERGN);

      WinSendMsg (hwndHscroll, SBM_SETPOS,
		  MPFROMSHORT (sHscrollPos), MPVOID) ;
   }
   return (MRFROMLONG(0));
}


/****************************************************************\
 *  Vertical scrolling routine
 *--------------------------------------------------------------
 *
 *  Name:   MainVertScroll(hwnd, mp2)
 *
 *  Purpose: Scrolls window vertically.
 *
 *  Usage:  Called when the client window receives a WM_VSCROLL
 *	    message.
 *
 *  Method:
 *
 *  Returns:
\****************************************************************/

MRESULT MainVertScroll(HWND hwnd,      /* handle to the main client window */
		       MPARAM mp2)     /* second parameter of WM_CREATE message */
{
   LONG sVscrollInc;

   switch (SHORT2FROMMP (mp2))
   {
      case SB_LINEUP:
	 sVscrollInc = -1 ;
	 break ;

      case SB_LINEDOWN:
	 sVscrollInc = 1 ;
	 break ;

      case SB_PAGEUP:
	 sVscrollInc = min (-1, -cyClient / cyChar) ;
	 break ;

      case SB_PAGEDOWN:
	 sVscrollInc = max (1, cyClient / cyChar) ;
	 break ;

      case SB_SLIDERTRACK:
	 sVscrollInc = SHORT1FROMMP (mp2) - sVscrollPos;
	 break ;

      default:
	 sVscrollInc = 0;
	 break ;
   }

   sVscrollInc = max (-sVscrollPos,
		 min (sVscrollInc, sVscrollMax - sVscrollPos)) ;

   if (sVscrollInc != 0)
   {
      sVscrollPos += sVscrollInc ;
      WinScrollWindow ((HWND)hwnd, 0, (cyChar * sVscrollInc),
		     (PRECTL)NULL, (PRECTL)NULL, (HRGN)NULL,
		     (PRECTL)NULL, SW_INVALIDATERGN);

      WinSendMsg (hwndVscroll, SBM_SETPOS,
		  MPFROMSHORT (sVscrollPos), MPVOID) ;
      WinUpdateWindow (hwnd) ;
   }
   return (MRFROMLONG(0));
}


/****************************************************************\
 *  Update messages
 *--------------------------------------------------------------
 *
 *  Name:   MainCharHScroll(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
 *
 *  Purpose:
 *
 *  Usage:
 *
 *  Method:
 *
 *  Returns:
\****************************************************************/

MRESULT MainCharHScroll(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
{

   /* referenced to prevent compiler error */
   hwnd = hwnd;
   return (WinSendMsg(hwndHscroll, msg, mp1, mp2));
}


/****************************************************************\
 *  Update messages
 *--------------------------------------------------------------
 *
 *  Name:   MainCharVScroll(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
 *
 *  Purpose:
 *
 *  Usage:
 *
 *  Method:
 *
 *  Returns:
\****************************************************************/

MRESULT MainCharVScroll(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
{

   return (WinSendMsg(hwndVscroll, msg, mp1, mp2));
}


/****************************************************************\
 *  Update messages
 *--------------------------------------------------------------
 *
 *  Name:   MainUpdateMsg(hwnd)
 *
 *  Purpose: Update portion of screen with new messages.
 *
 *  Usage:  Called when a new message is read from the queue.
 *
 *  Method:
 *
 *  Returns:
\****************************************************************/

VOID MainUpdateMsg(HWND hwnd,
		   CHAR SvrQMsgs[MAX_MESSAGES][MESSAGE_LEN+38],
		   unsigned int index,
		   SHORT sTotalMsgs)
{
   RECTL rclInvalid;

   /* if it will fit in the window */
   if (sTotalMsgs <= cyClient/cyChar + sVscrollPos + 1)
   {
      rclInvalid.yBottom = (LONG)max(0, cyClient - sTotalMsgs * cyChar);
      rclInvalid.yTop = (LONG)(cyClient - (sTotalMsgs - sVscrollPos - 1) * cyChar);
      rclInvalid.xLeft = 0L;
      rclInvalid.xRight = (LONG)cxClient;
      WinInvalidateRect(hwnd, &rclInvalid, FALSE);
      MainPaint(hwnd, SvrQMsgs, index, sTotalMsgs);
   }

   /* if lines exceed window */
   if (sTotalMsgs > cyClient/cyChar)
   {
      WinEnableWindow (hwndVscroll, TRUE) ;
      sVscrollMax = sTotalMsgs - cyClient / cyChar;
      sVscrollPos = min (sVscrollPos, sVscrollMax) ;

      WinSendMsg (hwndVscroll, SBM_SETSCROLLBAR,
			       MPFROM2SHORT (sVscrollPos, 0),
			       MPFROM2SHORT (0, sVscrollMax)) ;

      /* if new msg is just off screen */
      if (sTotalMsgs == cyClient/cyChar + sVscrollPos + 1)
      {
	 MainVertScroll(hwnd, MPFROM2SHORT(0, SB_LINEDOWN));
      }

      else
      {
	 DosBeep(1000, 100);
      }
   }
}



VOID MainPurgeWindow()
{

   sVscrollMax = 0;
   sVscrollPos = 0;
   WinSendMsg (hwndVscroll, SBM_SETSCROLLBAR,
			    MPFROM2SHORT (sVscrollPos, 0),
			    MPFROM2SHORT (0, sVscrollMax)) ;

   WinEnableWindow (hwndVscroll, FALSE) ;
   WinInvalidateRect(hwndMain, NULL, FALSE);
}
