///////////////////////////////////////////////////////////////////////
// Copyright (C) Andru 2007                                          //
// mail: dr.andru@gmail.com                                          //
// site: http://andru.2x4.ru                                         //
//                                                                   //
// OMEGA Engine is free software.                                    //
//                                                                   //
// You may redistribute it and/or modify it under the terms of the   //
// GNU General Public License, as published by the Free Software     //
// Foundation; either version 2 of the License, or (at your option)  //
// any later version.                                                //
//                                                                   //
// this module 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 General Public License for more details.              //
//                                                                   //
// You should have received a copy of the GNU General Public License //
// along with this module.  If not, write to:                        //
// 	The Free Software Foundation, Inc.,                              //
// 	51 Franklin Street, Fifth Floor                                  //
// 	Boston, MA  02110-1301, USA.                                     //
///////////////////////////////////////////////////////////////////////
unit ENGINE_WINDOW;

{$I DEFINES.pas}

interface
uses
  Windows,
  Messages,
  OpenGL,

  ENGINE_CONST,
  ENGINE_VAR,
  ENGINE_UTILS,
  ENGINE_MAIN,
  ENGINE_LOG,

  UTILS;

procedure OE_SetWndOnTop( Enable : Boolean ); stdcall;

procedure OE_SetWndPosition( X, Y : Integer ); stdcall;

procedure OE_SetWndName( NewName : PChar ); stdcall;

procedure OE_ShowCursor( Show : Boolean ); stdcall;

procedure OE_ResizeWindow( Width, Height : Integer ); stdcall;


function Wnd_Create : Boolean;

function Wnd_Destroy : Boolean;

procedure Wnd_Resize;

procedure Wnd_SetStyle;

//----------------------------------------------------------------------------//
                                 IMPLEMENTATION
//----------------------------------------------------------------------------//
uses
  ENGINE_GL;

procedure OE_SetWndOnTop;
Begin
if ( Enable ) and ( wnd_StyleEx and WS_EX_TOPMOST = 0 ) Then
  wnd_StyleEx := wnd_StyleEx or WS_EX_TOPMOST
else
  if ( not Enable ) and ( wnd_StyleEx and WS_EX_TOPMOST > 0 ) Then
    wnd_StyleEx := wnd_StyleEx xor WS_EX_TOPMOST;
End;

procedure OE_SetWndPosition;
  var
    Rect : TRect;
Begin
wnd_X := X;
wnd_Y := Y;
if app_Work Then
  if not app_FullScreen Then
    begin
      GetWindowRect( wnd_HWND, Rect );
      SetWindowPos( wnd_HWND, 0, X, Y, Rect.Right - Rect.Left, Rect.Bottom - Rect.Top, SWP_NOZORDER or SWP_NOACTIVATE or SWP_SHOWWINDOW );
      Wnd_Resize;
    end;
End;

procedure OE_SetWndName;
Begin

wnd_Caption := NewName;
SetWindowText( wnd_HWND, wnd_Caption );

End;

procedure OE_ShowCursor;
Begin
if app_Cursor <> Show Then
  ShowCursor( Show );
End;

procedure OE_ResizeWindow;
Begin

ogl_Width  := Width;
ogl_Height := Height;
CropW      := Width;
CropH      := Height;
Wnd_Resize;

End;

function Wnd_Create;
Begin

Result := FALSE;

wnd_CpnSize  := GetSystemMetrics( SM_CYCAPTION );
wnd_BrdSizeX := GetSystemMetrics( SM_CXDLGFRAME );
wnd_BrdSizeY := GetSystemMetrics( SM_CYDLGFRAME );

with wnd_Class do
  begin
    cbSize        := sizeof( TWNDClassEX );
    style         := CS_DBLCLKS or // Разрешены двойные щелчки
                     CS_OWNDC;     // Окно имеет свой контекст
    lpfnWndProc   := @eng_Mess;
    cbClsExtra    := 0;
    cbWndExtra    := 0;
    hInstance     := wnd_INST;
    hIcon         := LoadIcon      ( wnd_INST, IDI_WINLOGO );
    hIconSm       := LoadIcon      ( wnd_INST, IDI_WINLOGO );
    hCursor       := LoadCursor    ( wnd_INST, IDC_ARROW );
    lpszMenuName  := nil;
    hbrBackGround := GetStockObject( NULL_BRUSH );
    lpszClassName := wnd_ClassName;
  end;

if RegisterClassEx( wnd_Class ) = 0 Then
  begin
    E_Error( ERR_CANT_REG_WINDOW );
    app_Work := FALSE;
    Exit;
  end;

if ( app_FullScreen ) or ( ( scr_Width = wnd_Width ) and ( scr_Height = wnd_Height ) ) Then
  begin
    wnd_Style := WS_POPUP or WS_VISIBLE;
    wnd_HWND := CreateWindowEx(
                                0,
                                wnd_ClassName,
                                wnd_Caption,
                                wnd_Style,
                                0, 0,
                                scr_Width, scr_Height,
                                0,
                                0,
                                wnd_INST,
                                nil
                              )
  end else
    begin
      wnd_Style := WS_CAPTION or WS_MINIMIZEBOX or WS_SYSMENU or WS_VISIBLE;
      wnd_HWND := CreateWindowEx(
                                  wnd_StyleEx,
                                  wnd_ClassName,
                                  wnd_Caption,
                                  wnd_Style,
                                  wnd_X, wnd_Y,
                                  wnd_Width  + wnd_BrdSizeX * 2,
                                  wnd_Height + wnd_BrdSizeY * 2 + wnd_CpnSize,
                                  0,
                                  0,
                                  wnd_INST,
                                  nil
                                );
  end;
if wnd_HWND = 0 Then
  begin
    E_Error( ERR_CANT_CREATE_WINDOW );
    app_Work := FALSE;
    Exit;
  end;

wnd_DC := GetDC( wnd_HWND );
if wnd_DC = 0 Then
  begin
    E_Error( ERR_CANT_DC );
    app_Work := FALSE;
    Exit;
  end;

Result := TRUE;

End;

function Wnd_Destroy;
Begin

Result := FALSE;

if app_FullScreen Then
  if ChangeDisplaySettings( DEVMODE( nil^ ),
                            CDS_FULLSCREEN * Byte( app_FullScreen = TRUE ) ) = DISP_CHANGE_FAILED Then
    E_Error( ERR_CANT_RESTORE_OLDSETTINGS );

if not wglMakeCurrent( wnd_DC, 0 ) Then
  E_Error( ERR_CANT_GLCONTEXTR );

if not wglDeleteContext( wnd_GLRC ) Then
  begin
    E_Error( ERR_CANT_GLCONTEXTD );
    wnd_GLRC := 0;
  end;

if ( wnd_DC > 0 ) and ( ReleaseDC( wnd_HWND, wnd_DC ) = 0 ) Then
  begin
    E_Error( ERR_CANT_RELEASE_DC );
    wnd_DC := 0;
  end;

if ( wnd_HWND <> 0 ) and ( not DestroyWindow( wnd_HWND ) ) Then
  begin
    E_Error( ERR_CANT_DESTROY_WINDOW );
    wnd_HWND := 0;
  end;

if not UnRegisterClass( wnd_ClassName, wnd_INST ) Then
  begin
    E_Error( ERR_CANT_UNREG_WINDOW );
    wnd_INST := 0;
  end;

ShowCursor( not app_Cursor );

Result := TRUE;

End;

procedure Wnd_Resize;
Begin
glViewport( 0, 0, ogl_Width, ogl_Height );
GL_Set2DMatrix;
End;

procedure Wnd_SetStyle;
  var
    r  : TRect;
begin
if app_FullScreen Then
  wnd_Style := WS_POPUP or WS_VISIBLE
else
  wnd_Style := WS_CAPTION or WS_MINIMIZEBOX or WS_SYSMENU or WS_VISIBLE;
  
if app_FullScreen Then
  begin
    ogl_X := 0;
    ogl_Y := 0;
    SetRect( r, 0, 0, scr_Width, scr_Height )
  end else
    begin
      ogl_X := GetSystemMetrics( SM_CXSIZEFRAME );
      ogl_Y := GetSystemMetrics( SM_CYCAPTION ) + GetSystemMetrics( SM_CYSIZEFRAME );
      SetRect( r, 0, 0,
               wnd_Width  + ogl_X,
               wnd_Height + ogl_Y );
    end;

AdjustWindowRectEx( r, 0, FALSE, wnd_Style );
SetWindowLong( wnd_HWND, GWL_STYLE, wnd_Style );
SetWindowPos ( wnd_HWND, 0, 0, 0, r.Right - r.Left, r.Bottom - r.Top, SWP_NOZORDER or SWP_NOACTIVATE or SWP_SHOWWINDOW );
End;

end.







