; Common properties names.
iglobal
  property propOwnFont, 'OwnFont'
  property propOldWinProc, 'OldWinProc'
  property propUserWinProc, 'UserWinProc'
endg

;initialize CreateCommonProperties
;begin
;        stdcall CreateProperty, propAlign
;        stdcall CreateProperty, propAutoSize
;        stdcall CreateProperty, propOwnFont
;        stdcall CreateProperty, propOldWinProc
;        stdcall CreateProperty, propUserWinProc
;        return
;endp
;
;finalize DeleteCommonProperties
;begin
;        stdcall DestroyProperty, propAlign
;        stdcall DestroyProperty, propAutoSize
;        stdcall DestroyProperty, propOwnFont
;        stdcall DestroyProperty, propOldWinProc
;        stdcall DestroyProperty, propUserWinProc
;        return
;endp
;

;*********************************************************************************************
; CreateForm
; Creates form window with all children from template.
; Arguments:
;   ptrTemplate - pointer to the form template. See TWinTemplate structure and
;                 WinTemplate macro in 'form.inc' for details.
; Returns:
;   EBX - handle of the created form. It's more useful to use ebx for this purpose to
;         allow using of folowing sequence without eax preserving:
;
;         stdcall CreateForm, xxxx
;         stdcall ShowModal, ebx
;         ... some API calls ...
;         invoke DestroyWindow, ebx
;
;*********************************************************************************************
proc CreateForm, .ptrTemplate, .hOwner
begin
        push    esi edi

        mov     esi, [.ptrTemplate]
        stdcall _DoCreateForm, [.hOwner]
        invoke  SendMessageW, ebx, FM_AFTERCREATE, 0, 0

        pop     edi esi
        return
endp

;----- internal called from create form ------------------------------------

proc _DoCreateForm, .hParent

.hwnd   dd      ?
.style  dd      ?
.info   MONITORINFO

.ptr1 dd ?
.ptr2 dd ?

begin
        push    edi

        mov     [.info.cbSize], 0

        test    [esi+TWinTemplate.style], WS_CHILD
        jnz     .loop

        cmp     [.hParent], 0
        je      .loop

        invoke  MonitorFromWindow, [.hParent], 2
        mov     [.info.cbSize], sizeof.MONITORINFO
        lea     ecx, [.info]
        invoke  GetMonitorInfoW, eax, ecx


.loop:
        push    [esi+TWinTemplate.WinProc]      ; ???
        push    [hInstance]
        movzx   eax, [esi+TWinTemplate.ID]
        movsx   edx, [esi+TWinTemplate.height]
        movsx   ecx, [esi+TWinTemplate.width]
        push    eax
        push    [.hParent]
        push    edx
        push    ecx

        movsx   edx, [esi+TWinTemplate.top]
        movsx   eax, [esi+TWinTemplate.left]

        cmp     [.info.cbSize], 0
        je      @f
        add     edx, [.info.rcWork.top]
        add     eax, [.info.rcWork.left]
@@:
        push    edx
        push    eax

        mov     eax, [esi+TWinTemplate.style]
        mov     [.style], eax
        test    eax, WS_CHILD
        jnz     .styleok

        and     eax, not WS_VISIBLE

.styleok:
        push    eax     ; style

        stdcall utf8ToWideChar, [esi+TWinTemplate.ptrText]
        mov     [.ptr1], eax
        push    eax

        stdcall utf8ToWideChar, [esi+TWinTemplate.ptrClass]
        mov     [.ptr2], eax
        push    eax

        push    [esi+TWinTemplate.styleEx]
        invoke  CreateWindowExW

        stdcall FreeMem, [.ptr1]
        stdcall FreeMem, [.ptr2]

        mov     [.hwnd], eax
        cmp     [esi+TWinTemplate.WinProc], 0
        je      .subclassok

        stdcall SubclassWindow, eax, [esi+TWinTemplate.WinProc]

.subclassok:

        invoke  SendMessageW, [.hParent], WM_GETFONT, 0, 0
        stdcall ControlSetFont, [.hwnd], eax

        movzx   edi, [esi+TWinTemplate.flags]
        add     esi, sizeof.TWinTemplate

        test    edi, wtParent
        jz      @f

        stdcall _DoCreateForm, [.hwnd]

@@:
        test    [.style], WS_CHILD
        jnz     .visible_ok

        test    [.style], WS_VISIBLE
        jz      .visible_ok

        mov     eax, SW_SHOWNORMAL
        test    [.style], WS_MAXIMIZE
        jz      .maximize_ok

        mov     eax, SW_MAXIMIZE

.maximize_ok:
        test    [.style], WS_MINIMIZE
        jz      .show_cmd_ok

        mov     eax, SW_MINIMIZE

.show_cmd_ok:
        invoke  ShowWindow, [.hwnd], eax

.visible_ok:
        test    edi, wtEnd
        jz      .loop

        mov     ebx, [.hwnd]
        pop     edi
        return
endp



proc SubclassWindow, .hwnd, .ptrUserProc
begin
        invoke  GetWindowLongW, [.hwnd], GWL_WNDPROC
        invoke  SetPropW, [.hwnd], [propOldWinProc], eax
        invoke  SetPropW, [.hwnd], [propUserWinProc], [.ptrUserProc]
        invoke  SetWindowLongW, [.hwnd], GWL_WNDPROC, UniversalWinProc
        invoke  SendMessageW, [.hwnd], AM_INITWINDOW, 0, 0
        return
endp


proc UnSubclassWindow, .hwnd
begin
        invoke  GetPropW, [.hwnd], [propOldWinProc]
        test    eax, eax
        jz      .exit

        invoke  SetWindowLongW, [.hwnd], GWL_WNDPROC, eax
        invoke  RemovePropW, [.hwnd], propOldWinProc
        invoke  RemovePropW, [.hwnd], propUserWinProc
.exit:
        return
endp


proc UniversalWinProc, .hwnd, .wmsg, .wparam, .lparam
begin
        invoke  GetPropW, [.hwnd], [propUserWinProc]
        test    eax, eax
        jz      .oldproc

        push    ebx esi edi
        mov     ebx, [.wmsg]
        stdcall eax, [.hwnd], ebx, [.wparam], [.lparam]
        pop     edi esi ebx
        jnc     .finish

.oldproc:
if defined SplitGridWinProc
        push    ebx esi edi
        stdcall SplitGridWinProc, [.hwnd], [.wmsg], [.wparam], [.lparam]
        pop     edi esi ebx
        jnc     .finish
end if

        invoke  GetPropW, [.hwnd], [propOldWinProc]
        invoke  CallWindowProcW, eax, [.hwnd], [.wmsg], [.wparam], [.lparam]

.finish:
        return
endp



;----------------------------------------------------------------------
; Set the font of some window if propOwnFont = FALSE
;----------------------------------------------------------------------
proc ControlSetFont, .hwnd, .hFont
begin
        invoke  GetPropW, [.hwnd], [propOwnFont]
        test    eax, eax
        jnz     .exit

        invoke  SendMessageW, [.hwnd], WM_SETFONT, [.hFont], TRUE
        mov     eax, TRUE

.exit:
        return
endp


; Various property related string procedures
proc CreateProperty, .ptrProp
begin
        push    ebx
        mov     ebx, [.ptrProp]
        invoke  IsBadReadPtr, ebx, 4
        test    eax, eax
        jnz     .exit

        invoke  IsBadStringPtr, [ebx], 256
        test    eax, eax
        jnz     .exit

        invoke  AddAtomW, [ebx]
        movzx   eax, ax
        mov     [ebx], eax
.exit:
        pop     ebx
        return
endp


proc DestroyProperty, .ptrProp
begin
        push    ebx
        mov     ebx, [.ptrProp]
        invoke  IsBadReadPtr, ebx, 4
        test    eax, eax
        jnz     .exit

        invoke  DeleteAtom, [ebx]
.exit:
        pop     ebx
        return
endp