/*    
	Splash.c	1.35
    	Copyright 1997 Willows Software, Inc. 

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.

This library 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.  See the GNU
Library General Public License for more details.

You should have received a copy of the GNU Library General Public
License along with this library; see the file COPYING.LIB.  If
not, write to the Free Software Foundation, Inc., 675 Mass Ave,
Cambridge, MA 02139, USA.


For more information about the Willows Twin Libraries.

	http://www.willows.com	

To send email to the maintainer of the Willows Twin Libraries.

	mailto:twin@willows.com 

 */

#include <string.h>

#include "windows.h"
#include "GdiDC.h"
#include "Splash.h"
#include "About.h"
#include "Driver.h"
#include "KrnTask.h"

LRESULT TWIN_SplashWndProc(HWND,UINT,WPARAM,LPARAM);

static HTASK hSplashTask;
static HWND hWndSplash;
static HBITMAP hSplashBmp;
static char SplashClass[] = "WillowsSplashClass";
static BOOL HoldSplash = TRUE;
static BOOL ButtonDown = FALSE;
static BOOL fSplashActive = FALSE;
static BOOL fPostQuitWhenDone = FALSE;
static BOOL fExit = FALSE;
static int FailID = 0;

static void DestroySplash(void);

static HFONT
SelectMessageFont(HDC hDC, int Width, LPSTR Message)
{
	int MsgLen;
	int FontSize;
	DWORD MsgExt;
	HFONT hFont;
	HFONT hOldFont;

	MsgLen = strlen(Message);

	for ( FontSize = 14; FontSize >= 6; FontSize -= 2 )
	{
	    hFont = CreateFont(FontSize, 0,0,0,500, 0,0,0,0, 0,0,0,0, "Arial");
	    hOldFont = SelectObject(hDC, hFont);
	    MsgExt = GetTextExtent(hDC, Message, MsgLen);
	    SelectObject(hDC, hOldFont);
	    if ( (int)LOWORD(MsgExt) < Width - 8 )
		break;
	    if (FontSize > 6)
		DeleteObject(hFont);
	}

	return hFont;
}

static void SplashInit(HINSTANCE hInstance)
{
    WNDCLASS wc;
    BITMAP bm;
    int nWidth, nHeight;
    static DWORD dwTicks = 0;

    hSplashBmp = LoadBitmap(0,"SPLASH");
    if (hSplashBmp == 0)
	return;
    memset((LPSTR)&wc,0,sizeof(WNDCLASS));
    wc.lpfnWndProc = (WNDPROC)TWIN_SplashWndProc;
    wc.hInstance = hInstance;
    wc.hbrBackground = GetStockObject(WHITE_BRUSH);
    wc.lpszClassName = SplashClass;
    if (!RegisterClass(&wc))
	return;

    GetObject(hSplashBmp,sizeof(BITMAP),&bm);
    nWidth = GetSystemMetrics(SM_CXBORDER) * 2 + bm.bmWidth;
    nHeight = GetSystemMetrics(SM_CYBORDER) * 2 + bm.bmHeight;
	    
    hWndSplash = CreateWindowEx(WS_EX_TOPMOST,
				SplashClass,
				(LPSTR)NULL,
				WS_POPUP|WS_BORDER,
				(GetSystemMetrics(SM_CXSCREEN) - nWidth)/2,
				(GetSystemMetrics(SM_CYSCREEN) - nHeight)/2,
				nWidth, nHeight,
				(HWND)0,0,hInstance,(LPVOID)NULL);
    if (!hWndSplash)
	return;
    ShowWindow(hWndSplash,SW_NORMAL);
    UpdateWindow(hWndSplash);
    sndPlaySound("SystemStart", SND_ASYNC|SND_NODEFAULT);
    dwTicks = GetTickCount();
}

static void SplashMain()
{
    MSG msg;

    fPostQuitWhenDone = 1;
    SplashInit(TWIN_GetInstanceFromTask(GetCurrentTask()));
    
    while (GetMessage(&msg, hWndSplash, 0, 0) ) {
	TranslateMessage(&msg);
	DispatchMessage(&msg);
    }

    TWIN_ReadyAllTasks();
    DeleteTask(GetCurrentTask());
}

void
SplashScreen(WORD wAction, LONG lParam)
{
    MSG msg;

#ifdef NOSPLASH
    return;		/* Skip splash screen for now, ljw 1/11/96 */
#else

    switch( wAction )
    {
    case SPLASH_INIT:
	if (fSplashActive)
	    return;

	hSplashTask = CreateTask();
	fSplashActive = TRUE;
	if (!TWIN_InitializeAnotherNativeTask(hSplashTask, (DWORD) SplashMain))
	    SplashInit(0);
	else
	    DirectedYield(hSplashTask);
	
	break;

    case SPLASH_WAIT:
	if (!fSplashActive || (hWndSplash == 0) || !IsWindow(hWndSplash))
	    break;

	/* This is completely bogus!  There must be a better way!	*/
	/* The problem is that we don't want to create windows if the	*/
	/* splash screen is still up, but we do want to do all other	*/
	/* possible processing.  Unfortunately, when multiple tasks are	*/
	/* running, only the native task is allowed to fall into this   */
	/* GetMessage() loop.  All other tasks just simply need to wait */
	/* for the screen to go away.					*/
	if (GetCurrentTask() == GetWindowTask(hWndSplash)) {
	    while ( HoldSplash && GetMessage(&msg, hWndSplash, 0, 0) ) {
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	    }
	    if (!HoldSplash)
		while (PeekMessage(&msg,hWndSplash,
			WM_TIMER,WM_TIMER,PM_REMOVE));
	}
	else {
	    while ( HoldSplash )
		InternalYield();

	    return;
	}
	
        DestroySplash();

    } /* end-switch */

#endif
}

LRESULT 
TWIN_SplashWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    HDC hDC,hDCMem;
    HBITMAP hBitmap;
    BITMAP bm;

    switch (message) {

	case WM_NCCREATE:
	    SetTimer(hWnd, ID_SPLASHTIMER, SPLASH_TIME, NULL);
	    return 1;

	case WM_DESTROY:
	    if (fPostQuitWhenDone)
		PostQuitMessage(0);
	    return 1;

	case WM_TIMER:
	    KillTimer(hWnd, ID_SPLASHTIMER);
	    if ( !ButtonDown )
		DestroySplash();
	    return 0;

	case WM_LBUTTONDOWN:
	    ButtonDown = TRUE;
	    return 0;

	case WM_LBUTTONUP:
	    DestroySplash();
	    return 0;

	case WM_PAINT:
	    hDC = GetDCEx(hWnd,(HRGN)0,DCX_INTERSECTUPDATE);
	    hDCMem = CreateCompatibleDC(hDC);
	    hBitmap = SelectObject(hDCMem,hSplashBmp);
	    GetObject(hSplashBmp,sizeof(BITMAP),&bm);
	    BitBlt(hDC,0,0,bm.bmWidth,bm.bmHeight,hDCMem,0,0,SRCCOPY);
	    SelectObject(hDCMem,hBitmap);
	    DeleteDC(hDCMem);
	    ValidateRect(hWnd, NULL);
	    ReleaseDC(hWnd,hDC);
	    return 0;

	default:
	    return DefWindowProc(hWnd,message,wParam,lParam);
    }
}

static
void DestroySplash(void)
{
    if(hWndSplash)
	DestroyWindow(hWndSplash);

    hWndSplash = 0;
    UnregisterClass(SplashClass,0);

    if(hSplashBmp)
	DeleteObject(hSplashBmp);

    hSplashBmp = 0;
    fSplashActive = FALSE;
    HoldSplash = FALSE;

}
