///
//  ESWindowProc()
//
//      Main window procedure
//
LRESULT WINAPI ESWindowProc ( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) 
{
   static POINT mousePoint;

   LRESULT  lRet = 1; 

   switch (uMsg) 
   { 
      case WM_CREATE:
         break;

      case WM_SIZE:
         {
            ESContext *esContext = (ESContext*)(LONG_PTR) GetWindowLongPtr ( hWnd, GWL_USERDATA );
            if ( esContext ) {
               esContext->width = LOWORD( lParam );
               esContext->height = HIWORD( lParam );
               InvalidateRect( esContext->hWnd, NULL, FALSE );
            }
         }

      case WM_PAINT:
         {
            ESContext *esContext = (ESContext*)(LONG_PTR) GetWindowLongPtr ( hWnd, GWL_USERDATA );
            
            if ( esContext && esContext->drawFunc )
               esContext->drawFunc ( esContext );
            
            if ( esContext )
              ValidateRect( esContext->hWnd, NULL );
         }
         break;

      case WM_DESTROY:
         PostQuitMessage(0);             
         break; 

      case WM_LBUTTONDOWN:
         {
            ESContext *esContext = (ESContext*)(LONG_PTR) GetWindowLongPtr ( hWnd, GWL_USERDATA );

			mousePoint.x = GET_X_LPARAM(lParam);
			mousePoint.y = GET_Y_LPARAM(lParam);

            if ( esContext && esContext->lButtomDownFunc )
                esContext->lButtomDownFunc ( esContext, (int) mousePoint.x, (int) mousePoint.y );
         }
         break;

      case WM_LBUTTONUP:
         {
            POINT      point;
            ESContext *esContext = (ESContext*)(LONG_PTR) GetWindowLongPtr ( hWnd, GWL_USERDATA );

			point.x = GET_X_LPARAM(lParam);
			point.y = GET_Y_LPARAM(lParam);

            if ( esContext && esContext->lButtomUpFunc )
                esContext->lButtomUpFunc ( esContext, (int) point.x, (int) point.y );
         }
         break;

      case WM_MOUSEMOVE:
         {
            POINT      point;

            ESContext *esContext = (ESContext*)(LONG_PTR) GetWindowLongPtr ( hWnd, GWL_USERDATA );

			point.x = GET_X_LPARAM(lParam);
			point.y = GET_Y_LPARAM(lParam);

            if (wParam & MK_LBUTTON) // drag event
                if ( esContext && esContext->mouseDragFunc )
                    esContext->mouseDragFunc ( esContext, 
                                               (int) mousePoint.x, (int) mousePoint.y,
                                               (int) point.x, (int) point.y );

            mousePoint = point; // point update
         }
         break;

      case WM_CHAR:
         {
            POINT      point;
            ESContext *esContext = (ESContext*)(LONG_PTR) GetWindowLongPtr ( hWnd, GWL_USERDATA );
            
            GetCursorPos( &point );

            if ( esContext && esContext->keyFunc )
	            esContext->keyFunc ( esContext, (unsigned char) wParam, 
		                             (int) point.x, (int) point.y );
         }
         break;
         
      default: 
         lRet = DefWindowProc (hWnd, uMsg, wParam, lParam); 
         break; 
   } 

   return lRet; 
}