// Window.cpp: implementation of the CWindow class.
//
//////////////////////////////////////////////////////////////////////
#include <os/os.h>
#include "Window.h"
#include "ClipSurface.h"
#include <string.h>
#include <malloc.h>
#include <gui/messages.h>
#include <kernel/proc.h>
#include <stdio.h>
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
//dword thrGetTls();
extern CWindow* desktop;
int new_window_x, new_window_y;
CWindow::CWindow(const windowdef_t* def, IWindowServer* srv)
{
surface_t desc;
m_refs = 0;
m_srv = srv;
m_surf = srv->GetScreen();
m_font = srv->GetFont(1);
m_first = m_last = m_prev = m_next = m_parent = NULL;
m_surf->GetSurfaceDesc(&desc);
if (def->flags & WIN_TITLE)
m_title = wcsdup(def->title);
else
m_title = wcsdup(L"");
if (def->flags & WIN_X)
left = def->x;
else
{
left = new_window_x;
new_window_x += 20;
if (new_window_x + 100 > desc.nWidth)
new_window_x = 0;
}
if (def->flags & WIN_Y)
top = def->y;
else
{
top = new_window_y;
new_window_y += 20;
if (new_window_y + 100 > desc.nHeight)
new_window_y = 0;
}
if (def->flags & WIN_WIDTH)
right = left + def->width;
else
right = left + 100;
if (def->flags & WIN_HEIGHT)
bottom = top + def->height;
else
bottom = top + 100;
if (def->flags & WIN_PARENT)
m_parent = (CWindow*) def->parent;
else
m_parent = desktop;
if (m_parent)
{
m_parent->AddRef();
m_prev = m_parent->m_last;
if (m_parent->m_last)
m_parent->m_last->m_next = this;
m_parent->m_last = this;
if (m_parent->m_first == NULL)
m_parent->m_first = this;
}
if (def->flags & WIN_WNDPROC)
m_attribs[ATTR_WNDPROC] = (dword) def->wndproc;
else
m_attribs[ATTR_WNDPROC] = NULL;
m_invalid_rect.SetEmpty();
m_attribs[ATTR_PROCESS] = (dword) procCurrent();
m_attribs[ATTR_MSGQUEUE] = thrGetInfo()->queue;
InvalidateRect(this);
}
CWindow::~CWindow()
{
if (m_prev)
m_prev->m_next = m_next;
if (m_next)
m_next->m_prev = m_prev;
if (m_parent)
{
m_parent->RemoveChild(this);
m_parent->Release();
}
free(m_title);
m_surf->Release();
if (m_font)
m_font->Release();
m_srv->Release();
}
HRESULT CWindow::QueryInterface(REFIID iid, void ** ppvObject)
{
if (InlineIsEqualGUID(iid, IID_IUnknown) ||
InlineIsEqualGUID(iid, IID_IWindow))
{
AddRef();
*ppvObject = (IWindow*) this;
return S_OK;
}
else
return E_FAIL;
}
void CWindow::OnPaint(ISurface* surf, const rectangle_t* rect)
{
}
void CWindow::PostMessage(dword message, dword param)
{
IMsgQueue* queue = (IMsgQueue*) m_attribs[ATTR_MSGQUEUE];
queue->PostMessage(this, message, param);
}
void CWindow::RemoveChild(CWindow* child)
{
if (m_first == child)
m_first = child->m_next;
if (m_last == child)
m_last = child->m_prev;
InvalidateRect(child);
UpdateWindow();
}
dword CWindow::GetAttrib(dword index)
{
return m_attribs[index];
}
ISurface* CWindow::GetSurface()
{
rectangle_t rect;
m_surf->AddRef();
rect = *this;
if (m_parent)
m_parent->ClientToScreen(&rect);
return new CClipSurface(m_surf, rect);
}
HRESULT CWindow::InvalidateRect(const rectangle_t* rect)
{
CWindow* child;
m_invalid_rect.UnionRect(rect);
for (child = m_first; child; child = child->m_next)
child->InvalidateRect(rect);
PostMessage(WM_PAINT, 0);
return S_OK;
}
HRESULT CWindow::UpdateWindow()
{
CWindow* child;
ISurface* surf;
if (!m_invalid_rect.IsEmpty())
{
surf = GetSurface();
OnPaint(surf, m_invalid_rect);
surf->Release();
m_invalid_rect.SetEmpty();
}
for (child = m_first; child; child = child->m_next)
child->UpdateWindow();
return S_OK;
}
HRESULT CWindow::DefWndProc(dword message, dword param)
{
switch (message)
{
case WM_PAINT:
UpdateWindow();
break;
}
return S_OK;
}
IWindow* CWindow::GetFirstChild()
{
if (m_first)
{
m_first->AddRef();
return m_first;
}
else
return NULL;
}
HRESULT CWindow::ClientToScreen(rectangle_t* rect)
{
if (m_parent)
m_parent->ClientToScreen(rect);
rect->OffsetRect(left, top);
return S_OK;
}