/*
 * Default dialog procedure
 *
 * Copyright 1993 Alexandre Julliard
 */

static char Copyright[] = "Copyright  Alexandre Julliard, 1993";

#include "windows.h"
#include "dialog.h"
#include "win.h"
#include "stddebug.h"
/* #define DEBUG_DIALOG /* */
/* #undef  DEBUG_DIALOG /* */
#include "debug.h"


extern HWND DIALOG_GetFirstTabItem( HWND hwndDlg );  /* windows/dialog.c */


/***********************************************************************
 *           DEFDLG_SetFocus
 *
 * Set the focus to a control of the dialog, selecting the text if
 * the control is an edit dialog.
 */
static void DEFDLG_SetFocus( HWND hwndDlg, HWND hwndCtrl )
{
    int dlgCode;
    HWND hwndPrev = GetFocus();

    if (IsChild( hwndDlg, hwndPrev ))
    {
        if (SendMessage( hwndPrev, WM_GETDLGCODE, 0, 0 ) & DLGC_HASSETSEL)
            SendMessage( hwndPrev, EM_SETSEL, TRUE, MAKELONG( -1, 0 ) );
    }
    if (SendMessage( hwndCtrl, WM_GETDLGCODE, 0, 0 ) & DLGC_HASSETSEL)
        SendMessage( hwndCtrl, EM_SETSEL, FALSE, MAKELONG( 0, -1 ) );
    SetFocus( hwndCtrl );
}


/***********************************************************************
 *           DEFDLG_SaveFocus
 */
static BOOL DEFDLG_SaveFocus( HWND hwnd, DIALOGINFO *infoPtr )
{
    HWND hwndFocus = GetFocus();

    if (!hwndFocus || !IsChild( hwnd, hwndFocus )) return FALSE;
    if (!infoPtr->hwndFocus) return FALSE;  /* Already saved */
    infoPtr->hwndFocus = hwndFocus;
      /* Remove default button */
    return TRUE;
}


/***********************************************************************
 *           DEFDLG_RestoreFocus
 */
static BOOL DEFDLG_RestoreFocus( HWND hwnd, DIALOGINFO *infoPtr )
{
    if (!infoPtr->hwndFocus || IsIconic(hwnd)) return FALSE;
    if (!IsWindow( infoPtr->hwndFocus )) return FALSE;
    DEFDLG_SetFocus( hwnd, infoPtr->hwndFocus );
    infoPtr->hwndFocus = 0;
    return TRUE;
}


/***********************************************************************
 *           DEFDLG_FindDefButton
 *
 * Find the current default push-button.
 */
static HWND DEFDLG_FindDefButton( HWND hwndDlg )
{
    HWND hwndChild = GetWindow( hwndDlg, GW_CHILD );
    while (hwndChild)
    {
        if (SendMessage( hwndChild, WM_GETDLGCODE, 0, 0 ) & DLGC_DEFPUSHBUTTON)
            break;
        hwndChild = GetWindow( hwndChild, GW_HWNDNEXT );
    }
    return hwndChild;
}


/***********************************************************************
 *           DEFDLG_SetDefButton
 *
 * Set the new default button to be hwndNew.
 */
static BOOL DEFDLG_SetDefButton( HWND hwndDlg, DIALOGINFO *dlgInfo,
                                 HWND hwndNew )
{
    if (hwndNew &&
        !(SendMessage( hwndNew, WM_GETDLGCODE, 0, 0 ) & DLGC_UNDEFPUSHBUTTON))
        return FALSE;  /* Destination is not a push button */
    
    if (dlgInfo->msgResult)  /* There's already a default pushbutton */
    {
        HWND hwndOld = GetDlgItem( hwndDlg, dlgInfo->msgResult );
        if (SendMessage( hwndOld, WM_GETDLGCODE, 0, 0 ) & DLGC_DEFPUSHBUTTON)
            SendMessage( hwndOld, BM_SETSTYLE, BS_PUSHBUTTON, TRUE );
    }
    if (hwndNew)
    {
        SendMessage( hwndNew, BM_SETSTYLE, BS_DEFPUSHBUTTON, TRUE );
        dlgInfo->msgResult = GetDlgCtrlID( hwndNew );
    }
    else dlgInfo->msgResult = 0;
    return TRUE;
}


/***********************************************************************
 *           DefDlgProc   (USER.308)
 */
LONG DefDlgProc( HWND hwnd, WORD msg, WORD wParam, LONG lParam )
{
    DIALOGINFO * dlgInfo;
    BOOL result = FALSE;
    WND * wndPtr = WIN_FindWndPtr( hwnd );
    
    if (!wndPtr) return 0;
    dlgInfo = (DIALOGINFO *)&wndPtr->wExtra;

    dprintf_dialog(stddeb, "DefDlgProc: %d %04x %d %08x\n", 
		   hwnd, msg, wParam, lParam );

    dlgInfo->msgResult = 0;
    if (dlgInfo->dlgProc)
    {
	  /* Call dialog procedure */
	result = (BOOL)CallWindowProc( dlgInfo->dlgProc, hwnd, 
				       msg, wParam, lParam );

	  /* Check if window destroyed by dialog procedure */
	wndPtr = WIN_FindWndPtr( hwnd );
	if (!wndPtr) return result;
    }
    
    if (!result) switch(msg)
    {
	case WM_INITDIALOG:
	    break;

        case WM_ERASEBKGND:
	    FillWindow( hwnd, hwnd, (HDC)wParam, (HBRUSH)CTLCOLOR_DLG );
	    return TRUE;

	case WM_NCDESTROY:

	      /* Free dialog heap (if created) */
	    if (dlgInfo->hDialogHeap)
	    {
		GlobalUnlock(dlgInfo->hDialogHeap);
		GlobalFree(dlgInfo->hDialogHeap);
		dlgInfo->hDialogHeap = 0;
	    }

	      /* Delete font */
	    if (dlgInfo->hUserFont)
	    {
		DeleteObject( dlgInfo->hUserFont );
		dlgInfo->hUserFont = 0;
	    }

	      /* Delete menu */
	    if (dlgInfo->hMenu)
	    {		
		DestroyMenu( dlgInfo->hMenu );
		dlgInfo->hMenu = 0;
	    }

	      /* Window clean-up */
	    DefWindowProc( hwnd, msg, wParam, lParam );
	    break;

	case WM_SHOWWINDOW:
	    if (!wParam) DEFDLG_SaveFocus( hwnd, dlgInfo );
	    return DefWindowProc( hwnd, msg, wParam, lParam );

	case WM_ACTIVATE:
	    if (wParam) DEFDLG_RestoreFocus( hwnd, dlgInfo );
	    else DEFDLG_SaveFocus( hwnd, dlgInfo );
	    break;

	case WM_SETFOCUS:
	    DEFDLG_RestoreFocus( hwnd, dlgInfo );
	    break;

        case DM_SETDEFID:
            if (dlgInfo->fEnd) return TRUE;
            DEFDLG_SetDefButton( hwnd, dlgInfo,
                                 wParam ? GetDlgItem( hwnd, wParam ) : 0 );
            return TRUE;

        case DM_GETDEFID:
            if (dlgInfo->fEnd || !dlgInfo->msgResult) return 0;
            return MAKELONG( dlgInfo->msgResult, DC_HASDEFID );

	case WM_NEXTDLGCTL:
	    {
                HWND hwndDest = wParam;
                if (!lParam)
                {
                    HWND hwndPrev = GetFocus();
                    if (!hwndPrev)  /* Set focus to the first item */
                        hwndDest = DIALOG_GetFirstTabItem( hwnd );
                    else
                        hwndDest = GetNextDlgTabItem( hwnd, hwndPrev, wParam );
                }
                if (hwndDest) DEFDLG_SetFocus( hwnd, hwndDest );
                DEFDLG_SetDefButton( hwnd, dlgInfo, hwndDest );
            }
            break;

	default:
	    return DefWindowProc( hwnd, msg, wParam, lParam );
    }
        
    return result;
}
