/* The basic idea of this module is to create lisp callable functions
   for the T symbols in the cygwin library libgdi32.a.  To do this, I
   used a awk program which parsed the function headers, and created
   the functions here.  So most of them are not tested.
   Once a function is tested remove the untested comment from the function.
   This file is LGPL'd, and copyright assigned to the FSF.
   Dan Stanger 4/9/02
*/
#include "lispbibl.c"
#define DEFMODULE(a,b)
#define DEFUN(funname,lambdalist,signature) LISPFUN signature
#define DEFVAR(varname)
#define WIDECHAR(o,e)  &TheSstring(o)->data[0]
#define memclr(p,n) memset(p,0,n)
#define NO_STRICT
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#define encoding (C_terminal_encoding(),value1)
DEFMODULE(gdi,"GDI")

local object lookupHash(int hwnd, int message);

LRESULT CALLBACK WindowProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)
{
printf("HWND %x UINT %d WPARAM %d LPARAM %d\n",hWnd,message,wParam,lParam);
  switch (message) {
   // When window is created, the callback gets done before the createwindow
   // returns with a handle.  To get around this, and this is NOT thread
   // safe, store a alist of messages and functions.  Then call a
   // lisp function with the window handle and the alist, and store
   // the new list in the hash table.
   case WM_NCCREATE:
   {
     object p;
     begin_callback();
     p = allocate_fpointer(hWnd);
     pushSTACK(p);
     funcall(O(onCreate),1);
     end_callback();
     return TRUE;
   }
   case WM_CREATE:
   {
      break;
   }
   case WM_PAINT:
   {
     PAINTSTRUCT paintStruct;
     object func;
//asm("int3");
     BeginPaint(hWnd,&paintStruct);
     begin_callback();
     func = lookupHash(hWnd, message);
     if(!nullp(func))
     {
        pushSTACK(allocate_fpointer(paintStruct.hdc));
        funcall(func,1);
     }
     end_callback();
     EndPaint(hWnd,&paintStruct);
     break;
   }
   case WM_CLOSE:
   {
     object func;
//asm("int3");
     begin_callback();
     func = lookupHash(hWnd, message);
     if(!nullp(func))
     {
        pushSTACK(allocate_fpointer(hWnd));
        funcall(func,1);
        end_callback();
     }
     else
     {
        end_callback();
        return (DefWindowProc(hWnd, message, wParam, lParam));
     }
     break;
   }
   case WM_KEYDOWN:
     switch (wParam)
     {
       case VK_CANCEL:
       case VK_CLEAR:
       case VK_PAUSE:
       case VK_PRIOR:
       case VK_NEXT:
       case VK_END:
       case VK_HOME:
       case VK_LEFT:
       case VK_UP:
       case VK_RIGHT:
       case VK_DOWN:
       case VK_SELECT:
       case VK_PRINT:
       case VK_EXECUTE:
       case VK_INSERT:
       case VK_DELETE:
       case VK_HELP:
       case VK_NUMLOCK:
       case VK_SCROLL:
       case VK_F1:
       case VK_F2:
       case VK_F3:
       case VK_F4:
       case VK_F5:
       case VK_F6:
       case VK_F7:
       case VK_F8:
       case VK_F9:
       case VK_F10:
       case VK_F11:
       case VK_F12:
       default:
       {
         begin_callback();
         object func = lookupHash(hWnd, message);
         if(!nullp(func))
         {
            pushSTACK(allocate_fpointer(lParam));
            pushSTACK(fixnum(wParam));
            funcall(func,2);
         }
         end_callback();
         break;
       }
     }
     break;
   case WM_LBUTTONDOWN:
   case WM_MBUTTONDOWN:
   case WM_RBUTTONDOWN:
   case WM_MBUTTONUP:
   case WM_LBUTTONUP:
   case WM_RBUTTONUP:
   case WM_MOUSEMOVE:
   case WM_MOUSEWHEEL:
   case WM_ERASEBKGND:
   case WM_KILLFOCUS:
   case WM_SETFOCUS:
   case WM_QUIT:
   case WM_DESTROY:
   case WM_SYSCHAR: /* alt-keys go here */
   case WM_CHAR:
   case WM_LBUTTONDBLCLK:
   case WM_MBUTTONDBLCLK:
   case WM_RBUTTONDBLCLK:
   case WM_MOVE:	
   case WM_SIZE:			
   case WM_DESTROYCLIPBOARD:
   default:        /* Passes it on if unproccessed    */
     return (DefWindowProc(hWnd, message, wParam, lParam));
    }
    return 0L;
}
local object lookupHash(int hwnd, int message){
printf("lookupHash hwnd %x message %d\n",hwnd,message);
   Car(O(localCons)) = allocate_fpointer(hwnd);
   Cdr(O(localCons)) = fixnum(message);
   pushSTACK(O(localCons));
   pushSTACK(O(functions));
   funcall(S(gethash),2);
   return value1;
}

DEFVAR(functions,`nil`)
DEFVAR(localCons,`nil`)
DEFVAR(onCreate,`nil`)
DEFUN( GDI:INITC, h f)
{
  O(localCons) = allocate_cons();
  O(onCreate) = popSTACK();
  O(functions) = popSTACK();
  value1 = allocate_fpointer(GetModuleHandle(0));
  mv_count=1;
  return;
}
local LPSTR idc[] ={
   0,
   IDC_ARROW,
   IDC_IBEAM,
   IDC_WAIT,
   IDC_CROSS,
   IDC_UPARROW,
   IDC_SIZENWSE,
   IDC_SIZENESW,
   IDC_SIZEWE,
   IDC_SIZENS,
   IDC_SIZEALL,
   IDC_NO,
   IDC_HAND,
   IDC_APPSTARTING,
   IDC_HELP,
   IDC_ICON,
   IDC_SIZE
};
DEFUN( GDI:GETIDC, h)
{
  object arg = popSTACK();
  check_uint32(arg);
  value1 = allocate_fpointer(idc[I_to_uint32(arg)]);
  mv_count=1;
  return;
}
 
DEFUN( GDI:MAKEFPOINTER, h)
{
  value1 = allocate_fpointer(I_to_uint32(popSTACK()));
  mv_count=1;
  return;
}
DEFUN( GDI:MESSAGELOOP,)
{
  MSG m;
  while (GetMessage(&m, (HWND) NULL, 0, 0)) { 
    TranslateMessage(&m); 
    DispatchMessage(&m); 
  } 
  value1 = fixnum(m.wParam);
  mv_count=1;
  return;
}
