/**********************************************************************
 
	Copyright (C) 2003 Hirohisa MORI <joshua@nichibun.ac.jp>
 
	This program is free software; you can redistribute it 
	and/or modify it under the terms of the GLOBALBASE 
	Library General Public License (G-LGPL) as published by 

	http://www.globalbase.org/
 
	This program is distributed in the hope that it will be 
	useful, but WITHOUT ANY WARRANTY; without even the 
	implied warranty of MERCHANTABILITY or FITNESS FOR A 
	PARTICULAR PURPOSE.

**********************************************************************/

#include	<windows.h>
#include	<ddeml.h>
#include	<stdio.h>
#include	"v.h"
#include	"gbview.h"
#include	"machine/param_gbview.h"
#include	"machine/msequence.h"
#include	"pri_level.h"
extern MS_INFO *order_ms;

#define min(a, b)  (((a) < (b)) ? (a) : (b)) 

static VDISPLAY *vd;
//extern GBVIEW_ENV env;
static int IsFirstTime;
static int IsCaptured;
static int IsMouseMove;

int window_update_flag;

extern void _redraw(VWINDOW * win,int x,int y,int w,int h);
extern void _button(VWINDOW * win,int subtype,int t,int x,int y);

void new_v_loop(VDISPLAY * d)
{
	MSG msg;
	SetWindowLong(NULL, GWL_USERDATA, (int)d);
	while( GetMessage(&msg, NULL, 0, 0) ) 
	{
		vd = d;
		TranslateMessage( &msg );
		DispatchMessage( &msg );
	}
}
/*
void new_v_loop(VDISPLAY * d)
{
	MSG msg;
	SetWindowLong(NULL, GWL_USERDATA, (int)d);
	while(1){
		if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)){ 
			if(msg.message == WM_QUIT)
				break;
			vd = d;
			TranslateMessage( &msg );
			DispatchMessage( &msg );
		}
		else if(order_ms){
			extern int user_interface_task_id;
			order_ms->result = (*(int(*)(void*))order_ms->func)(order_ms->arg);
			order_ms = NULL;
			wakeup_task((unsigned int)&user_interface_task_id);
		}
	}
}
*/


void v_loop(VDISPLAY *d){
	create_task(ms_loop,0,PRI_USER_INTERFACE);
	new_v_loop(d);
}

HDDEDATA CALLBACK ddeCallBackFunc(
  UINT uType,     // トランザクション型
  UINT uFmt,      // クリップボードデータ形式
  HCONV hconv,    // 対話のハンドル
  HSZ hsz1,       // 文字列のハンドル
  HSZ hsz2,       // 文字列のハンドル
  HDDEDATA hdata, // グローバルメモリオブジェクトのハンドル
  DWORD dwData1,  // トランザクション固有データ
  DWORD dwData2   // トランザクション固有データ
  ){
	return (HDDEDATA)0;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	PAINTSTRUCT ps;
	HDC hdc;
	RECT rt;
	int xPos,yPos;
	VWINDOW *win;

	switch( message ) 
	{
		case WM_PAINT:

			hdc = BeginPaint(hWnd, &ps);
			if(IsFirstTime)
			{
				win = _get_vwin(vd,hWnd);
				_redraw(win,ps.rcPaint.left,ps.rcPaint.top,ps.rcPaint.right-ps.rcPaint.left,ps.rcPaint.bottom-ps.rcPaint.top);
				IsFirstTime = 0;
			}
			
			BitBlt(hdc, 
				ps.rcPaint.left, 
				ps.rcPaint.top,
				ps.rcPaint.right,
				ps.rcPaint.bottom, 
				ghBufferDC,
				ps.rcPaint.left,
				ps.rcPaint.top, 
				SRCCOPY);
			
			EndPaint( hWnd, &ps );
			{
				if(window_update_flag){
					wakeup_task(&window_update_flag);
				}
			}
			break;

		case WM_LBUTTONDOWN:
			SetCapture(hWnd);
			IsCaptured  = 1;

			xPos = LOWORD(lParam);
			yPos = HIWORD(lParam); 
			IsMouseMove = 0;
			win = _get_vwin(vd,hWnd);
			if (win) 
			{
				_button(win,VES_BUTTON_PRESS,1/*time*/,xPos,yPos);
			}
			break;

		case WM_LBUTTONUP:
			ReleaseCapture();
			IsCaptured = 0;

			xPos = LOWORD(lParam);
			yPos = HIWORD(lParam);
			win = _get_vwin(vd,hWnd);
			if (win)
			{
				if(IsMouseMove)
					_button(win,VES_BUTTON_RELEASE,10000/*time*/,xPos,yPos);
				else
					_button(win,VES_BUTTON_RELEASE,1/*time*/,xPos,yPos);
			}
			IsMouseMove = 0;
			break;
			
		case WM_MOUSEMOVE:
			IsMouseMove = 1;
			xPos = LOWORD(lParam);
			yPos = HIWORD(lParam);  
			win = _get_vwin(vd,hWnd);
			if (win) 
			{
				VOBJECT *obj;
				hdc = GetDC(hWnd);
				_button(win,VES_BUTTON_MOTION,1,xPos,yPos);
				GetClientRect(hWnd,&rt);
				for ( obj = win->obj_list ; obj ; obj = obj->header.next )
				{
					if(obj->header.type == 2)
						(*obj->header.handler)(obj,VE_REDRAW,rt.left,rt.top,rt.right-rt.left,rt.bottom-rt.top);
				}
				ReleaseDC(hWnd,hdc);
				InvalidateRect(hWnd, NULL, FALSE);
			}

			break;

		case WM_DESTROY:
			{
				DeleteObject(SelectObject(ghBufferDC,ghBufferImageOld));
				DeleteDC(ghBufferDC);

				PostQuitMessage( 0 );
			}
			break;

		case WM_CREATE:
			{
				hdc = GetDC(hWnd);
				ghBufferDC = CreateCompatibleDC(hdc);
				ghBufferImage = CreateCompatibleBitmap(hdc,GetSystemMetrics(SM_CXSCREEN),GetSystemMetrics(SM_CYSCREEN));
				ghBufferImageOld = SelectObject(ghBufferDC,ghBufferImage);

				ReleaseDC(hWnd,hdc);

				IsFirstTime = 1;
				IsCaptured = 0;
			}
			break;

		case WM_SIZE:
			if(!IsFirstTime)
			{
				win = _get_vwin(vd,hWnd);
				if(win)
				{
					int w = LOWORD(lParam);
					int h = HIWORD(lParam);
					_redraw(win,0,0,w,h);
				}
			}
			break;
			
		default:
			return DefWindowProc( hWnd, message, wParam, lParam );
   }
   return 0;
}
