#include "win32\win32guts.h"
#include <commdlg.h>
#ifndef _APRICOT_H_
#include "apricot.h"
#endif
#include "guts.h"
#include "File.h"
#include "Menu.h"
#include "Image.h"
#include "Region.h"
#include "Window.h"
#include "Application.h"

#ifdef __cplusplus
extern "C" {
#endif


#define  sys (( PDrawableData)(( PComponent) self)-> sysData)->
#define  dsys( view) (( PDrawableData)(( PComponent) view)-> sysData)->
#define var (( PWidget) self)->
#define HANDLE sys handle
#define DHANDLE(x) dsys(x) handle
#define GET_REGION(obj) (&(dsys(obj)s.region))

#define WinShowWindow(WND) SetWindowPos( WND, NULL, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|SWP_SHOWWINDOW|SWP_NOACTIVATE);
#define WinHideWindow(WND) SetWindowPos( WND, NULL, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|SWP_HIDEWINDOW);
#define apc_widget_redraw(self)  apc_widget_invalidate_rect(self,NULL)

void
process_transparents( Handle self)
{
	int i;
	RECT mr;
	objCheck;
	GetWindowRect(( HWND) var handle, &mr);
	for ( i = 0; i < var widgets. count; i++) {
		HWND xwnd;
		Handle x = var widgets. items[ i];
		dobjCheck(x);
		xwnd = DHANDLE(x);
		if ( dsys(x) options. aptTransparent && IsWindowVisible( xwnd)) {
			RECT r, dr;
			GetWindowRect( xwnd, &r);
			IntersectRect( &dr, &r, &mr);
			if ( !IsRectEmpty( &dr))
				InvalidateRect( xwnd, NULL, false);
		}
	}
}

typedef struct _ViewProfile {
	ColorSet colors;
	Point    pos;
	Point    size;
	Point    virtSize;
	Bool     enabled;
	Bool     visible;
	Bool     focused;
	Handle   capture;
	HRGN     shape;
} ViewProfile, *PViewProfile;


static void
get_view_ex( Handle self, PViewProfile p)
{
	int i;
	if ( !p) return;
	p-> capture   = apc_widget_is_captured( self);
	for ( i = 0; i <= ciMaxId; i++) p-> colors[ i] = apc_widget_get_color( self, i);
	if ( sys class_name == WC_FRAME) {
		p-> pos       = apc_window_get_client_pos( self);
		p-> size      = apc_window_get_client_size( self);
	} else {
		p-> pos       = apc_widget_get_pos( self);
		p-> size      = apc_widget_get_size( self);
	}
	p-> virtSize  = var virtualSize;
	p-> enabled   = apc_widget_is_enabled( self);
	p-> focused   = apc_widget_is_focused( self);
	p-> visible   = apc_widget_is_visible( self);
	p-> shape = CreateRectRgn(0,0,0,0);
	if ( sys class_name == WC_FRAME && is_apt(aptLayered))
		i = GetWindowRgn((HWND) var handle, p->shape);
	else
		i = GetWindowRgn( HANDLE, p->shape);
	if (!i) {
		DeleteObject(p->shape);
		p->shape = NULL;
	}
}

static void
set_view_ex( Handle self, PViewProfile p)
{
	int i;
	Bool clip_by_children;
	if ( sys class_name == WC_FRAME && is_apt(aptLayered)) {
		SetWindowRgn((HWND) var handle, p-> shape, true);
	} else
		SetWindowRgn( HANDLE, p-> shape, true);
	apc_widget_set_visible( self, false);
	for ( i = 0; i <= ciMaxId; i++) apc_widget_set_color( self, p-> colors[i], i);
	apc_widget_set_font( self, &var font);
	if ( sys class_name == WC_FRAME) {
		apc_window_set_client_rect( self, p-> pos. x, p-> pos. y, p-> size.x, p-> size.y);
	} else {
		apc_widget_set_rect( self, p-> pos. x, p-> pos. y, p-> size.x, p-> size.y);
	}
	var virtualSize = p-> virtSize;
	apc_widget_set_enabled( self, p-> enabled);
	if ( p-> focused) apc_widget_set_focused( self);

	clip_by_children = is_apt(aptClipByChildren);
	apt_set(aptClipByChildren); /* by default widget created with clipping */
	apc_widget_set_clip_by_children(self, clip_by_children);

	apc_widget_set_visible( self, p-> visible);
	if ( p-> capture) apc_widget_set_capture( self, 1, NULL_HANDLE);
	if ( !InvalidateRect(( HWND) var handle, NULL, false)) apiErr;
	process_transparents( self);
}

static Bool repost_msgs( PostMsg * msg, Handle self)
{
	PostMessage(( HWND) var handle, WM_POSTAL, ( WPARAM) self, ( LPARAM) msg);
	return false;
}

static Bool
create_group( Handle self, Handle owner, Bool clipOwner,
				Bool taskListed, int class_name, DWORD style, DWORD exstyle,
				Bool usePos, Bool useSize,
				ViewProfile * vprf, HWND parent_handle)
{
	HWND ret = NULL;
	HWND old        = HANDLE;
	HWND old2       = (HWND) var handle;
	HWND behind     = HWND_TOP;
	HWND ownerView  = ( HWND) (( PWidget) owner)-> handle;
	HWND parentView = (( PDrawableData)(( PComponent) owner)-> sysData)-> parent;
	int  count = 0;
	Bool reset = false;
	Handle * list = NULL;
	const WCHAR wnull = 0;

	if ( HANDLE)
	{
		int i;
		if (( DHANDLE( owner) == sys owner) && ( clipOwner == is_apt( aptClipOwner)))
		{
			behind = GetWindow( HANDLE, GW_HWNDPREV);
			if ( behind == NULL) behind = HWND_TOP;
		}
		var stage = csAxEvents;
		if ( kind_of( self, CWidget))
		{
			PWidget g = ( PWidget) self;
			list  = g-> widgets. items;
			count = g-> widgets. count;
		}
		var self-> end_paint_info( self);
		var self-> end_paint( self);
		reset = true;
		for( i = 0; i < count; i++)
			get_view_ex( list[ i], ( ViewProfile*)( dsys( list[ i]) recreate_data = malloc( sizeof( ViewProfile))));
	}

	switch (( int) class_name)
	{
	case WC_FRAME:
		{
			HWND frame;
			RECT r;
			int  rcp[4] = {0,0,0,0};
			Bool layered = is_apt(aptLayered);
			if ( !clipOwner) parentView = HWND_DESKTOP;
			if ( !taskListed && ( parentView == HWND_DESKTOP || parentView == NULL))
				parentView = DHANDLE( prima_guts.application);
			if ( !usePos)  rcp[0] = rcp[1] = CW_USEDEFAULT;
			if ( !useSize) rcp[2] = rcp[3] = CW_USEDEFAULT;
			if ( !( frame = CreateWindowExW( exstyle, layered ? L"LayeredFrame" : L"GenericFrame", &wnull,
					style | WS_CLIPCHILDREN,
					rcp[0], rcp[1], rcp[2], rcp[3],
					parentView, NULL, guts. instance, NULL)))
				apiErrRet;
			if ( !SetWindowPos( frame, behind, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE))
				apiErr;
			if (P_APPLICATION-> topExclModal &&
				(P_APPLICATION-> topExclModal != self)
				)
				if ( !SetWindowPos( frame, DHANDLE(P_APPLICATION-> topExclModal),
						0,0,0,0,SWP_NOMOVE | SWP_NOSIZE  | SWP_NOACTIVATE))
					apiErr;
			GetClientRect( frame, &r);
			if ( old2 )
				SetWindowLongPtr( old2, GWLP_USERDATA, 0);
			if ( old )
				SetWindowLongPtr( old, GWLP_USERDATA, 0);
			if ( layered ) {
				if ( !( ret = CreateWindowExW( WS_EX_LAYERED|WS_EX_TOOLWINDOW,  L"Generic", &wnull,
						WS_VISIBLE | WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
						r. left, r. top, r. right, r. bottom, NULL, NULL,
						guts. instance, NULL)))
					apiErr;
			} else {
				if ( !( ret = CreateWindowExW( 0,  L"Generic", &wnull,
						WS_VISIBLE | WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
						0, 0, r. right - r. left, r. bottom - r. top, frame, NULL,
						guts. instance, NULL)))
					apiErr;
			}
			sys last_size. x = r. right  - r. left;
			sys y_override = sys last_size. y = r. bottom - r. top;
			sys handle = frame;
			SetWindowLongPtr( frame, GWLP_USERDATA, (LONG_PTR) self);
		}
		break;
	case WC_CUSTOM:
		if ( !parent_handle && ( !clipOwner || owner == prima_guts.application)) {
				style &= ~WS_CHILD;
				style |= WS_POPUP;
				exstyle |= WS_EX_TOOLWINDOW;
		}
		if ( parent_handle) parentView = parent_handle;
		sys parent_handle = parent_handle;

		if ( old )
			SetWindowLongPtr( old, GWLP_USERDATA, 0);
		if ( !( ret = CreateWindowExW( exstyle,  L"Generic", &wnull,
				style | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, 0, 0, 0, 0,
				parentView, NULL, guts. instance, NULL)))
			apiErrRet;
		if ( !SetWindowPos( ret, behind, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE))
			apiErr;
		sys handle = ret;
		break;
	}

	apt_assign( aptClipOwner, clipOwner);
	apt_set( aptEnabled);
	apt_clear( aptRepaintPending );
	apt_clear( aptMovePending );
	sys class_name = class_name;
	sys parent  = ret;
	var handle  = ( Handle) ret;
	sys owner   = ownerView;
	if ( !reset)
		sys pointer = LoadCursor( guts. instance, IDC_ARROW);
	SetWindowLongPtr( ret, GWLP_USERDATA, (LONG_PTR) self);
	if ( reset)
	{
		int i;
		Handle oldOwner = var owner; var owner = owner;
		if ( sys class_name == WC_FRAME) {
			apc_window_set_client_rect( self, vprf-> pos. x, vprf-> pos. y, vprf-> size. x, vprf-> size. y);
		} else {
			apc_widget_set_rect( self, vprf-> pos. x, vprf-> pos. y, vprf-> size. x, vprf-> size. y);
		}
		var owner = oldOwner;
		for ( i = 0; i < count; i++) ((( PComponent) list[ i])-> self)-> recreate( list[ i]);
		if ( sys class_name == WC_FRAME)
		{
			SetMenu( HANDLE, GetMenu( old));
			SetMenu( old, NULL);
		}
		if ( old2 != old ) {
			if ( !DestroyWindow( old2 ))
				apiErr;
		}
		if ( !DestroyWindow( old))
			apiErr;
		if ( var postList) list_first_that( var postList, (PListProc) repost_msgs, ( void*)self);
	}
	PostMessage( ret, WM_PRIMA_CREATE, 0, 0);

	if ( !reset) {
		/* set manually cmMove and cmSize when windows are configured automatically */
		if ( !usePos) {
			Event e;
			Point sz = apc_window_get_client_pos( self);
			memset( &e, 0, sizeof(e));
			e. gen. source = self;
			e. cmd = cmMove;
			e. gen. P. x = sz. x;
			e. gen. P. y = sz. y;
			CComponent(self)->message( self, &e);
			if ( PObject( self)-> stage == csDead) return false;
		}
		if ( !useSize) {
			Event e;
			Point sz = apc_window_get_client_size( self);
			memset( &e, 0, sizeof(e));
			e. gen. source = self;
			e. cmd = cmSize;
			e. gen. P. x = e. gen. R. right = sz. x;
			e. gen. P. y = e. gen. R. top = sz. y;
			CComponent(self)->message( self, &e);
			if ( PObject( self)-> stage == csDead) return false;
		}
	}
	return true;
}

static void
notify_sys_handle( Handle self )
{
	Event ev = {cmSysHandle};
	objCheck;
	ev. gen. source = self;
	var self-> message( self, &ev);
}

// Window
Bool
apc_window_create(
	Handle self, Handle owner, int border_icons,
	int border_style, Bool taskList, int windowState,
	int on_top, Bool usePos, Bool useSize, Bool layered
) {
	Bool reset = false;
	ViewProfile vprf;
	int oStage = var stage;
	WCHAR * saved_caption = NULL;
	WindowData ws;
	HICON icon = (HICON) NULL_HANDLE;
	WINDOWPLACEMENT wp = {sizeof(WINDOWPLACEMENT)};
	DWORD style = WS_CLIPCHILDREN | WS_OVERLAPPED
		| (( border_icons &  biSystemMenu) ? WS_SYSMENU     : 0)
		| (( border_icons &  biMinimize)   ? WS_MINIMIZEBOX : 0)
		| (( border_icons &  biMaximize)   ? WS_MAXIMIZEBOX : 0)
		| (( border_icons &  biTitleBar)   ? 0              : WS_POPUP)
		| (( border_style == bsSizeable)   ? WS_THICKFRAME  : 0)
		| (( border_style == bsSingle  )   ? WS_BORDER      : 0)
		| (( border_style == bsDialog  )   ? WS_BORDER      : 0)
		| (( windowState == wsMinimized)  ? WS_MINIMIZE    : 0)
		| (( windowState == wsMaximized)  ? WS_MAXIMIZE    : 0)
	;
	DWORD exstyle = 0
		| (( border_style == bsDialog  )   ? WS_EX_DLGMODALFRAME : 0)
	;

	objCheck false;
	dobjCheck( owner) false;
	if ( guts. display_bm_info. bmiHeader. biBitCount <= 8) layered = false;

	if ( !kind_of( self, CWidget)) apcErrRet( errInvObject);
	apcErrClear;
	if (( var handle != NULL_HANDLE) && (
			( DHANDLE( owner) != sys owner)
		|| ( border_style != sys s. window. border_style)
		|| ( border_icons != sys s. window. border_icons)
		|| ( taskList    != is_apt( aptTaskList))
		|| ( layered     != is_apt( aptLayered))
	))
	{
		int len = GetWindowTextLengthW( HANDLE ) + 1;
		if (( saved_caption = (WCHAR*) malloc( sizeof(WCHAR) * len)) != NULL )
			GetWindowTextW( HANDLE, saved_caption, len );
		// Windows 8 shell is observed to send WM_SIZE(0,0) on ShowWindow(SW_SHOWNORMAL)
		// when application started with /min flag
		apt_set( aptIgnoreSizeMessages );
		apc_window_set_window_state( self, windowState);
		apt_clear( aptIgnoreSizeMessages );
		// prevent cmSize/cmWindowStage message loss if recreate goes with WS_XXX change.
		if ( sys recreate_data) {
			memcpy( &vprf, sys recreate_data, sizeof( vprf));
			free( sys recreate_data);
			sys recreate_data = NULL;
		} else
			get_view_ex( self, &vprf);
		ws = sys s. window;
		if ( !GetWindowPlacement( HANDLE, &wp)) apiErr;
		if ( wp. showCmd == SW_SHOWMINIMIZED && windowState != wsMinimized )
			wp. showCmd = ( windowState == wsMaximized ) ? SW_SHOWMAXIMIZED : SW_NORMAL;
		usePos = useSize = 1; // prevent using shell-position flags for recreate
		icon = ( HICON) SendMessage( HANDLE, WM_GETICON, ICON_BIG, 0);
		reset = true;
	}
	hwnd_lock( true);

	if ( !reset) apt_set( aptClipByChildren );
	apt_assign( aptLayeredRequested, layered );
	apt_assign( aptLayered, layered );

	if ( reset || ( var handle == NULL_HANDLE))
		if ( !create_group( self, owner, false,
				taskList, WC_FRAME, style, exstyle, usePos, useSize, &vprf, NULL)) {
			if ( on_top >= 0) {
				apt_assign( aptOnTop, on_top);
				if ( on_top > 0)
					SetWindowPos( sys handle, HWND_TOPMOST, 0, 0, 0, 0,
						SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
			}
			hwnd_lock( false);
			if ( saved_caption ) free( saved_caption );
			return false;
		}
	ws. border_style = sys s. window. border_style = border_style;
	ws. border_icons = sys s. window. border_icons = border_icons;
	ws. state       = sys s. window. state       = windowState;
	apt_assign( aptTaskList,  taskList);
	if ( usePos) apt_set( aptWinPosDetermined);
	if ( reset)
	{
		Handle oldOwner = var owner;

		var owner = owner;
		apc_window_set_window_state( self, windowState);
		var owner = oldOwner;
		set_view_ex( self, &vprf);
		sys s. window = ws;
		if ( windowState != wsMaximized)
			GetWindowRect( HANDLE, &wp. rcNormalPosition);
		if ( !SetWindowPlacement( HANDLE, &wp)) apiErr;
		var stage = oStage;
		if ( icon) SendMessage( HANDLE, WM_SETICON, ICON_BIG, ( LPARAM) icon);
	}
	else {
		guts. top_windows++;
	}
	if ( on_top >= 0) {
		apt_assign( aptOnTop, on_top);
		if ( on_top > 0)
			SetWindowPos( sys handle, HWND_TOPMOST, 0, 0, 0, 0,
				SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
	}
	SetWindowTextW( HANDLE, saved_caption );
	if ( saved_caption ) free( saved_caption );
	hwnd_lock( false);
	if ( reset ) {
		notify_sys_handle( self );
		if ( layered ) hwnd_repaint_layered(self, false);
	}
	return guts.apc_error == 0;
}

Bool
apc_window_activate( Handle self)
{
	if ( self) {
		HWND w;
		objCheck false;
		w = HANDLE;
		SetForegroundWindow( w);
		SetActiveWindow( w);
		return true;
	}
	return false;
}

Bool
apc_window_is_active( Handle self)
{
	return apc_window_get_active() == self;
}

Handle
apc_window_get_active( void)
{
	Handle self = hwnd_to_view( GetActiveWindow());
	if ( !self)
		return NULL_HANDLE;
	if ( sys class_name == WC_FRAME)
		return self;
	else if ( !is_apt( aptClipOwner)) {
		return hwnd_top_level( self);
	} else
		return NULL_HANDLE;
}

Bool
apc_window_close( Handle self)
{
	objCheck true;
	if ( !PostMessage( HANDLE, WM_CLOSE, 0, 0)) apiErrRet;
	return true;
}

int
apc_window_get_border_icons( Handle self)
{
	objCheck 0;
	return sys s. window. border_icons;
}

int
apc_window_get_border_style( Handle self)
{
	objCheck 0;
	return sys s. window. border_style;
}

ApiHandle
apc_window_get_client_handle( Handle self)
{
	objCheck 0;
	return ( ApiHandle) var handle;
}

Point
apc_window_get_client_pos( Handle self)
{
	Point delta = get_window_borders( sys s. window. border_style);
	Handle parent = var self-> get_parent( self);
	Point p = {0,0}, sz   = CWidget( parent)-> get_size( parent);
	RECT  r;

	objCheck p;
	if ( apc_window_get_window_state( self) == wsMinimized) {
		WINDOWPLACEMENT w = { sizeof( WINDOWPLACEMENT)};
		if ( !GetWindowPlacement( HANDLE, &w)) apiErr;
		p. x = w. rcNormalPosition. left + delta. x;
		p. y = sz. y - w. rcNormalPosition. bottom + delta. y;
	} else {
		GetWindowRect( HANDLE, &r);
		p. x = r. left + delta. x;
		p. y = sz. y - r. bottom + delta. y;
	}
	return p;
}

Point
apc_window_get_client_size( Handle self)
{
	RECT r;
	Point p = { 0,0};
	objCheck p;
	if ( apc_window_get_window_state( self) == wsMinimized) {
		// cannot acquire client extension at this time. Using heuristic calculations.
		WINDOWPLACEMENT w = {sizeof(WINDOWPLACEMENT)};
		Point delta = get_window_borders( sys s. window. border_style);
		int   menuY  = (( PWindow) self)-> menu ? GetSystemMetrics( SM_CYMENU) : 0;
		int   titleY = ( sys s. window. border_icons & biTitleBar) ?
							GetSystemMetrics( SM_CYCAPTION) : 0;
		if ( !GetWindowPlacement( HANDLE, &w)) apiErr;
		p. x = w. rcNormalPosition. right  - w. rcNormalPosition. left - delta. x * 2;
		p. y = w. rcNormalPosition. bottom - w. rcNormalPosition. top  - delta. y * 2
			- menuY - titleY;
	} else {
		GetWindowRect(( HWND) var handle, &r);
		p. x = r. right - r. left;
		p. y = r. bottom - r. top;
	}
	return p;
}

Bool
apc_window_get_icon( Handle self, Handle icon)
{
	HICON    p;
	HCURSOR  save;
	Bool ret;

	objCheck false;
	p = ( HICON) SendMessage( HANDLE, WM_GETICON, ICON_BIG, 0);
	if ( icon == NULL_HANDLE) return p != NULL;

	save = sys pointer;
	sys pointer = p;
	ret = apc_pointer_get_bitmap( self, icon);
	sys pointer = save;
	return ret;
}

int
apc_window_get_window_state( Handle self)
{
	WINDOWPLACEMENT s = {sizeof( WINDOWPLACEMENT)};
	objCheck wsNormal;
	if ( sys s.window.state == wsFullscreen ) return wsFullscreen;
	if ( !GetWindowPlacement( HANDLE, &s)) apiErr;
	if ( s. showCmd == SW_SHOWMAXIMIZED) return wsMaximized;
	if ( s. showCmd == SW_SHOWMINIMIZED) return wsMinimized;
	return wsNormal;
}

Bool
apc_window_get_task_listed( Handle self)
{
	objCheck false;
	return is_apt( aptTaskList);
}

Bool
apc_window_get_on_top( Handle self)
{
	objCheck false;
	return is_apt( aptOnTop);
}

Bool
apc_window_set_caption( Handle self, const char * caption, Bool utf8)
{
	objCheck false;
	if ( utf8) {
		WCHAR * c = alloc_utf8_to_wchar( caption, -1, NULL);
		if ( !( rc = SetWindowTextW( HANDLE, c))) apiErr;
		free( c);
	} else {
		if ( !( rc = SetWindowTextA( HANDLE, caption))) apiErr;
	}
	return rc == 0;
}

Bool
apc_window_set_client_pos( Handle self, int x, int y)
{
	Point delta = get_window_borders( sys s. window. border_style);
	RECT  r;
	Handle parent = var self-> get_parent( self);
	Point sz = CWidget( parent)-> get_size( parent);

	objCheck false;
	if ( !hwnd_check_limits( x, y, true)) apcErrRet( errInvParams);
	apt_set( aptWinPosDetermined);

	if ( var stage == csConstructing && apc_window_get_window_state( self) != wsNormal) {
		WINDOWPLACEMENT w = {sizeof(WINDOWPLACEMENT)};
		if ( !GetWindowPlacement( HANDLE, &w)) apiErr;
		w. rcNormalPosition. top    += sz. y - y + delta. y - w. rcNormalPosition. bottom;
		w. rcNormalPosition. bottom  = sz. y - y + delta. y;
		w. rcNormalPosition. right  += x - delta. x - w. rcNormalPosition. left;
		w. rcNormalPosition. left    = x - delta. x;
		w. flags   = 0;
		if ( !SetWindowPlacement( HANDLE, &w)) apiErr;
	} else {
		if ( !GetWindowRect( HANDLE, &r)) apiErr;
		x -= delta. x;
		y  = sz. y - ( r. bottom - r. top) - y + delta. y;
		SetWindowPos( HANDLE, 0, x, y, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
	}
	return true;
}

Bool
apc_window_set_client_size( Handle self, int x, int y)
{
	RECT r, c, c2;
	HWND h;
	int  ws = apc_window_get_window_state( self);

	objCheck false;
	if ( !hwnd_check_limits( x, y, false)) apcErrRet( errInvParams);

	h = HANDLE;
	if (( var stage == csConstructing && ws != wsNormal) || ws == wsMinimized) {
		WINDOWPLACEMENT w = {sizeof(WINDOWPLACEMENT)};
		Point delta = get_window_borders( sys s. window. border_style);

		var virtualSize. x = x;
		var virtualSize. y = y;
		if ( x < 0) x = 0;
		if ( y < 0) y = 0;
		if ( !GetWindowPlacement( h, &w)) apiErr;
		if ( !GetWindowRect( h, &c2)) apiErr;
		if ( ws == wsMaximized) {
			if ( !GetClientRect( h, &c)) apiErr;
		}
		else {
			// cannot acquire client extension at this time. Using heuristic calculations.
			int  menuY = (( PWindow) self)-> menu ? GetSystemMetrics( SM_CYMENU) : 0;
			int   titleY = ( sys s. window. border_icons & biTitleBar) ?
								GetSystemMetrics( SM_CYCAPTION) : 0;
			c = c2;
			c. right  -= delta. x * 2;
			c. bottom -= delta. y * 2 + menuY + titleY;
		}
		w. rcNormalPosition. top    = w. rcNormalPosition. bottom - y - ( c2. bottom - c2. top - c. bottom + c. top);
		w. rcNormalPosition. right  = x + ( c2. right - c2. left - c. right + c. left) + w. rcNormalPosition. left;
		w. flags   = 0;
		if ( !SetWindowPlacement( h, &w)) apiErr;
	} else {
		if ( !GetWindowRect( h, &r)) apiErr;
		if ( !GetClientRect( h, &c)) apiErr;
		sys size_lock_level++;
		var virtualSize. x = x;
		var virtualSize. y = y;
		if ( x < 0) x = 0;
		if ( y < 0) y = 0;
		SetWindowPos( h, 0,
			r. left,
			r. top - y + ( c. bottom - c. top),
			x + r. right  - r. left - c. right + c. left,
			y + r. bottom - r. top  - c. bottom + c. top,
			SWP_NOZORDER | SWP_NOACTIVATE |
				( is_apt( aptWinPosDetermined) ? 0 : SWP_NOMOVE)
			);
		sys size_lock_level--;
	}
	return true;
}

Bool
apc_window_set_client_rect( Handle self, int x, int y, int width, int height)
{
	RECT r, c, c2;
	HWND h;
	int  ws = apc_window_get_window_state( self);
	Point delta = get_window_borders( sys s. window. border_style);
	Handle parent = var self-> get_parent( self);
	Point sz = CWidget( parent)-> get_size( parent);

	objCheck false;
	if ( !hwnd_check_limits( x, y, false)) apcErrRet( errInvParams);
	if ( !hwnd_check_limits( width, height, false)) apcErrRet( errInvParams);
	apt_set( aptWinPosDetermined);

	h = HANDLE;
	if (( var stage == csConstructing && ws != wsNormal) || ws == wsMinimized) {
		WINDOWPLACEMENT w = {sizeof(WINDOWPLACEMENT)};
		Point delta = get_window_borders( sys s. window. border_style);

		var virtualSize. x = width;
		var virtualSize. y = height;
		if ( width < 0) width = 0;
		if ( height < 0) height = 0;
		if ( !GetWindowPlacement( h, &w)) apiErr;
		if ( !GetWindowRect( h, &c2)) apiErr;
		if ( ws == wsMaximized) {
			if ( !GetClientRect( h, &c)) apiErr;
		}
		else {
			// cannot acquire client extension at this time. Using heuristic calculations.
			int  menuY = (( PWindow) self)-> menu ? GetSystemMetrics( SM_CYMENU) : 0;
			int   titleY = ( sys s. window. border_icons & biTitleBar) ?
								GetSystemMetrics( SM_CYCAPTION) : 0;
			c = c2;
			c. right  -= delta. x * 2;
			c. bottom -= delta. y * 2 + menuY + titleY;
		}
		w. rcNormalPosition. bottom = sz. y - y + delta. y;
		w. rcNormalPosition. left   = x - delta. x;
		w. rcNormalPosition. top    = w. rcNormalPosition. bottom - height - ( c2. bottom - c2. top - c. bottom + c. top);
		w. rcNormalPosition. right  = width + ( c2. right - c2. left - c. right + c. left) + w. rcNormalPosition. left;
		w. flags   = 0;
		if ( !SetWindowPlacement( h, &w)) apiErr;
	} else {
		if ( !GetWindowRect( h, &r)) apiErr;
		if ( !GetClientRect( h, &c)) apiErr;
		sys size_lock_level++;
		x -= delta. x;
		y  = sz. y - y - height - ( r. bottom - r. top  - c. bottom + c. top) + delta. y;
		var virtualSize. x = width;
		var virtualSize. y = height;
		if ( width < 0) width = 0;
		if ( height < 0) height = 0;
		SetWindowPos( h, 0,
			x, y,
			width + r. right  - r. left - c. right + c. left,
			height + r. bottom - r. top  - c. bottom + c. top,
			SWP_NOZORDER | SWP_NOACTIVATE);
		sys size_lock_level--;
	}
	return true;
}

Bool
apc_window_set_menu( Handle self, Handle menu)
{
	Point size;
	objCheck false;
	apcErrClear;
	size = var self-> get_size( self);
	SetMenu( HANDLE, menu ? ( HMENU) (( PComponent) menu)-> handle : NULL);
	DrawMenuBar( HANDLE);
	if ( apc_window_get_window_state( self) == wsNormal)
		var self-> set_size( self, size);
	return guts.apc_error == 0;
}

Bool
apc_window_set_effects( Handle self, HV * effects )
{
	return false;
}

Bool
apc_window_set_icon( Handle self, Handle icon)
{
	HICON i;
	objCheck false;
	i = icon ? image_make_icon_handle( icon, guts. icon_size_large, NULL) : NULL;
	i = ( HICON) SendMessage( HANDLE, WM_SETICON, ICON_BIG, ( LPARAM) i);
	if ( i) DestroyIcon( i);
	return true;
}

Bool
apc_window_set_window_state( Handle self, int state)
{
	int  fl = -1;
	objCheck false;

	switch (state) {
		case wsMaximized  : fl = SW_SHOWMAXIMIZED; break;
		case wsMinimized  : fl = SW_MINIMIZE;      break;
		case wsNormal     : fl = SW_SHOWNORMAL;    break;
		case wsFullscreen :
			break;
		default:
			return false;
	}

	/* Code from https://devblogs.microsoft.com/oldnewthing/20100412-00

	Raymon Chen says:
	An important flag to pass here is SWP_FRAME_CHANGED, which tells the window
	manager to recalculate the window decorations (which we need it to do because
	we just changed them) */

	if ( sys s. window. state == wsFullscreen ) {
		DWORD style = GetWindowLong(HANDLE, GWL_STYLE);
		if ( state == wsMinimized ) {
			/* minimize first, then apply visual changes */
			ShowWindow( HANDLE, fl);
			fl = -1;
		}
		SetWindowLong(HANDLE, GWL_STYLE, style | WS_OVERLAPPEDWINDOW);
		SetWindowPlacement(HANDLE, &sys s.window.fs_saved_placement);
		SetWindowPos(HANDLE,
			NULL, 0, 0, 0, 0,
			SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_FRAMECHANGED
		);
	}

	if ( fl > 0)
		ShowWindow( HANDLE, fl);

	if ( state == wsFullscreen ) {
		Event e;
		MONITORINFO     m = {sizeof(MONITORINFO)};
		sys s.window.fs_saved_placement.length = sizeof(WINDOWPLACEMENT);
		if (
			GetWindowPlacement(HANDLE, &sys s.window.fs_saved_placement) &&
			GetMonitorInfo(MonitorFromWindow(HANDLE, MONITOR_DEFAULTTOPRIMARY), &m)
		) {
			DWORD style = GetWindowLong(HANDLE, GWL_STYLE);
			SetWindowLong(HANDLE, GWL_STYLE, style & ~WS_OVERLAPPEDWINDOW);
			SetWindowPos(HANDLE, HWND_TOP,
				m.rcMonitor.left, m.rcMonitor.top,
				m.rcMonitor.right  - m.rcMonitor.left,
				m.rcMonitor.bottom - m.rcMonitor.top,
				SWP_NOOWNERZORDER | SWP_FRAMECHANGED
			);
		} else
			return false;

		if ( sys s. window. state == wsMinimized ) {
			/* prevent cmWindowState.wsMaximized */
			int v = is_apt(aptIgnoreSizeMessages);
			apt_set(aptIgnoreSizeMessages);
			ShowWindow( HANDLE, SW_SHOWMAXIMIZED );
			if ( !v) apt_clear(aptIgnoreSizeMessages);
		}

		memset( &e, 0, sizeof(e));
		e.cmd = cmWindowState;
		e.gen.source = self;
		e.gen.i      = wsFullscreen;
		CComponent(self)->message( self, &e);
		if ( PObject( self)-> stage == csDead) return false;

		sys s.window.state = wsFullscreen;
		hwnd_repaint_layered( self, false );
	}

	sys s.window.state = state;
	return true;
}

static Bool
window_start_modal( Handle self, Bool shared, Handle insertBefore)
{
	HWND wnd;
	HWND active = GetActiveWindow();

	objCheck false;
	wnd = HANDLE;
	if ( sys class_name != WC_FRAME) { apcErr( errInvParams); return false; }

	sys s. window. old_foc = apc_widget_get_focused();
	if ( sys s. window. old_foc) protect_object( sys s. window. old_foc);
	sys s. window. old_active = active;

	// setting window up
	guts. sys_focus_disabled = 1;
	CWindow( self)-> exec_enter_proc( self, shared, insertBefore);
	apc_widget_set_enabled( self, 1);
	SetWindowPos( wnd, 0, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|SWP_SHOWWINDOW);
	if ( sys s. window. state == wsMinimized)
		ShowWindow( wnd, SW_RESTORE);
	if ( !insertBefore) {
		SetActiveWindow( wnd);
		SetForegroundWindow( wnd);
	} else {
		HWND zorder;
		dobjCheck( insertBefore) false;
		zorder = GetWindow( DHANDLE( insertBefore), GW_HWNDNEXT);
		if ( !zorder) zorder = HWND_BOTTOM;
		SetWindowPos( wnd, zorder, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
		if ( active)
			SetActiveWindow( active);
	}
	objCheck false;
	PostMessage( wnd, WM_DLGENTERMODAL, 1, 0);
	guts. sys_focus_disabled = 0;
	return true;
}

Bool
apc_window_execute( Handle self, Handle insertBefore)
{
	objCheck false;
	if ( !window_start_modal( self, false, insertBefore))
		return false;
	while (
		!guts. application_stop_signal &&
		(( PWindow) self)-> modal &&
		yield(true)
	);
	return true;
}

Bool
apc_window_execute_shared( Handle self, Handle insertBefore)
{
	objCheck false;
	return window_start_modal( self, true, insertBefore);
}

Bool
apc_window_end_modal( Handle self)
{
	HWND wnd;
	objCheck false;
	wnd = HANDLE;
	guts. sys_focus_disabled = 1;
	CWindow( self)-> exec_leave_proc( self);
	WinHideWindow( wnd);
	objCheck false;
	apc_widget_set_enabled( self, 0);
	objCheck false;
	if ( prima_guts.application) {
		Handle who = Application_popup_modal( prima_guts.application);
		if ( sys s. window. old_active)
			SetActiveWindow( sys s. window. old_active);
		if ( !who && var owner)
			CWidget( var owner)-> set_selected( var owner, 1);
		if (( who = sys s. window. old_foc)) {
			if ( PWidget( who)-> stage == csNormal)
				CWidget( who)-> set_focused( who, 1);
			unprotect_object( who);
		}
	}
	guts. sys_focus_disabled = 0;
	return true;
}

// View management
Bool
apc_widget_map_points( Handle self, Bool toScreen, int count, Point * p)
{
	int i;
	Point sz = ((( PWidget) self)-> self)-> get_size( self);
	Point appSz = apc_application_get_size( prima_guts.application);

	if ( self == prima_guts.application)
		return true;

	objCheck false;

	if ( toScreen) {
		for ( i = 0; i < count; i++)
			p[i]. y = sz. y - p[i]. y;
		MapWindowPoints(( HWND) var handle, NULL, ( POINT * ) p, count);
		for ( i = 0; i < count; i++)
			p[i]. y = appSz. y - p[i].y;
	} else {
		for ( i = 0; i < count; i++)
			p[i]. y = appSz. y - p[i]. y;
		MapWindowPoints( NULL, ( HWND) var handle, ( POINT * ) p, count);
		for ( i = 0; i < count; i++)
			p[i]. y = sz. y - p[i]. y;
	}
	return true;
}

Color
apc_widget_map_color( Handle self, Color color)
{
	if ((( color & clSysFlag) != 0) && (( color & wcMask) == 0)) color |= var widgetClass;
	return remap_color( remap_color( color, true), false);
}

Bool
apc_widget_create( Handle self, Handle owner, Bool clipOwner, ApiHandle parent_handle, Bool layered)
{
	Bool reset = false, redraw = false;
	ViewProfile vprf;
	int oStage = var stage;
	int exstyle;

	objCheck false;
	dobjCheck( owner) false;

	if ( !kind_of( self, CWidget)) apcErr( errInvObject);
	apcErrClear;

	if ( parent_handle && !IsWindow(( HWND) parent_handle))
		return false;

	exstyle = 0;
	if ( guts. display_bm_info. bmiHeader. biBitCount <= 8) layered = false;

	redraw = is_apt( aptLayeredRequested ) != layered;
	apt_assign( aptLayeredRequested, layered );
	apt_clear( aptLayered );
	if ( layered && (( owner == prima_guts.application || !clipOwner ))) {
		apt_set( aptLayered );
		exstyle |= WS_EX_LAYERED;
	}

	if (( var handle != NULL_HANDLE) &&
			(( DHANDLE( owner) != sys owner)                 ||
			(( HWND) parent_handle != sys parent_handle)       ||
			( clipOwner       != is_apt( aptClipOwner))
		))
	{
		if ( sys recreate_data) {
			memcpy( &vprf, sys recreate_data, sizeof( vprf));
			free( sys recreate_data);
			sys recreate_data = NULL;
		} else
			get_view_ex( self, &vprf);
		reset = true;
	}
	if ( !reset) apt_set( aptClipByChildren );
	if ( reset || ( var handle == NULL_HANDLE))
		create_group( self, owner, clipOwner, 0, WC_CUSTOM,
			WS_CHILD, exstyle, 1, 1, &vprf, ( HWND) parent_handle);
	apt_set( aptWinPosDetermined);
	if ( reset)
	{
		Handle oldOwner = var owner; var owner = owner;
		set_view_ex( self, &vprf);
		var owner = oldOwner;
		var stage = oStage;
	}
	if ( redraw) apc_widget_redraw( self);
	if ( reset) {
		notify_sys_handle( self );
		apc_widget_redraw( self);
	}
	return guts.apc_error == 0;
}

Bool
apc_widget_begin_paint( Handle self, Bool insideOnPaint)
{
	Bool useRPDraw = false;
	objCheck false;
	apcErrClear;

	if ( is_apt( aptLayeredPaint )) {
		sys transform2 = sys layered_paint_offset;
	} else if ( is_apt( aptTransparent)) {
		if ( IsWindowVisible(( HWND) var handle)) {
			HWND parent = GetParent( HANDLE);
			if ( !parent) {
				MSG  msg;
				list_add( &guts. transp, self);
				WinHideWindow(( HWND) var handle);
				if ( parent) apcUpdateWindow( parent);
				while ( PeekMessage( &msg, NULL, WM_PAINT, WM_PAINT, PM_REMOVE)) {
					DispatchMessage(&msg);
					exception_check_raise();
				}
				if ( !parent) Sleep( 1);
				WinShowWindow(( HWND) var handle);
				apcUpdateWindow(( HWND) var handle);
				list_delete( &guts. transp, self);
			} else
				useRPDraw = true;
		}
		sys transform2. x = 0;
		sys transform2. y = 0;
	} else {
		sys transform2. x = 0;
		sys transform2. y = 0;
	}

	apt_set( aptWinPS);
	apt_set( aptCompatiblePS);
	apt_assign( aptWM_PAINT, insideOnPaint);
	sys effective_view. x = var w;
	sys effective_view. y = var h;

	if ( is_apt( aptLayeredPaint )) {
		sys ps = sys layered_paint_surface;
	} else if ( is_apt( aptLayered )) {
		RECT r;

		insideOnPaint = false;
		GetWindowRect( HANDLE, &r);
		sys ps2     = GetDC(NULL);
		sys ps      = CreateCompatibleDC(sys ps2);
		sys bm      = CreateCompatibleBitmap(sys ps2, r. right - r. left, r. bottom - r. top);
		sys stock_bitmap = SelectObject(sys ps, sys bm);
	} else if ( insideOnPaint) {
		if ( !( sys ps = BeginPaint(( HWND) var handle, &sys paint_struct))) apiErrRet;
	} else {
		if ( !( sys ps = GetDC(( HWND) var handle))) apiErrRet;
	}

	if ( !is_apt(aptLayeredPaint) && is_opt( optBuffered) && insideOnPaint) {
		RECT r;
		HBITMAP bm;
		HDC dc;

		GetClipBox( sys ps, &r);
		sys effective_view.x = r. right  - r. left;
		sys effective_view.y = r. bottom - r. top;

		if ( sys effective_view.x  == 0 || sys effective_view.y == 0) {
			if ( !EndPaint(( HWND) var handle, &sys paint_struct)) apiErr;
			apt_clear( aptWinPS);
			apt_clear( aptWM_PAINT);
			apt_clear( aptCompatiblePS);
			sys ps = NULL;
			return false;
		}

		if ( !( dc = CreateCompatibleDC( sys ps))) apiErr;

		if ( sys pal) {
			sys stock_palette = SelectPalette( dc, sys pal, 1);
			RealizePalette( dc);
			sys pal2 = SelectPalette( sys ps, sys pal, 1);
			RealizePalette( sys ps);
		}

		if ( guts. display_bm_info. bmiHeader. biBitCount == 8)
			apt_clear( aptCompatiblePS);

		bm = CreateCompatibleBitmap( sys ps, sys effective_view.x, sys effective_view.y);

		if ( bm) {
			sys ps2 = sys ps;
			sys ps  = dc;
			sys stock_bitmap = SelectObject( dc, bm);
			sys bm = bm;
			sys transform2. x = r. left;
			sys transform2. y = r. top;
			apt_set( aptBitmap);
		} else
			apiErr;
	} else if ( !is_apt(aptLayered) && !is_apt(aptLayeredPaint)) {
		if ( sys pal) {
			sys stock_palette = SelectPalette( sys ps, sys pal, 1);
			RealizePalette( sys ps);
		}
	}

	if ( useRPDraw) {
		HDC dc;
		Handle owner = var owner;
		Point tr = dsys(owner)transform2;
		Point ed = apc_widget_get_pos( self);
		Point sz = apc_widget_get_size( self);
		Point so = CWidget(owner)-> get_size( owner);
		Bool flag;
		int saved_dc_state;
		POINT brushorg;
		FLOAT miter;

		CWidget( owner)-> begin_paint( owner);
		dc = dsys( owner) ps;
		dsys( owner) ps = sys ps;
		dsys(owner) transform2. x += ed. x;
		dsys(owner) transform2. y += so. y - sz. y - ed. y;
		apc_gp_set_text_out_baseline( owner, dsys(owner) options. aptTextOutBaseline);

		saved_dc_state = SaveDC( sys ps );
		SelectObject( sys ps, GetCurrentObject( dc, OBJ_PEN));
		SelectObject( sys ps, GetCurrentObject( dc, OBJ_BRUSH));
		SelectObject( sys ps, GetCurrentObject( dc, OBJ_FONT));
		SelectObject( sys ps, GetCurrentObject( dc, OBJ_PAL));
		SelectObject( sys ps, GetCurrentObject( dc, OBJ_EXTPEN));
		SetTextAlign( sys ps, GetTextAlign( dc ));
		GetBrushOrgEx( dc, &brushorg);
		SetBrushOrgEx( sys ps, brushorg.x, brushorg.y, NULL);
		GetMiterLimit( dc, &miter);
		SetMiterLimit( sys ps, miter, NULL);
		SetBkMode( sys ps, GetBkMode( dc ));
		SetROP2( sys ps, GetROP2( dc ));
		SetStretchBltMode( sys ps, GetStretchBltMode( dc ));

		flag = exception_block(true);
		CWidget( owner)-> notify( owner, "sH", "Paint", owner);
		exception_block(flag);

		RestoreDC( sys ps, saved_dc_state);

		dsys(owner)transform2 = tr;
		dsys(owner)ps = dc;
		CWidget( owner)-> end_paint( owner);
	}

	hwnd_enter_paint( self);

	if ( is_apt(aptLayeredPaint)) {
		Rect r;
		r. left   = 0;
		r. bottom = 0;
		r. right  = sys last_size. x - 1;
		r. top    = sys last_size. y - 1;
		apc_gp_set_clip_rect(self, r);
	}

	return true;
}

Bool
apc_widget_begin_paint_info( Handle self)
{
	HRGN rgn;
	objCheck false;
	apt_set( aptWinPS);
	apt_set( aptCompatiblePS);
	sys transform2. x = 0;
	sys transform2. y = 0;
	if ( !( sys ps = GetDC(( HWND) var handle))) apiErrRet;
	hwnd_enter_paint( self);
	rgn = CreateRectRgn( 0, 0, 0, 0);
	SelectClipRgn( sys ps, rgn);
	DeleteObject( rgn);
	return true;
}


Bool
apc_widget_destroy( Handle self)
{
	objCheck false;
	SetWindowLongPtr( HANDLE, GWLP_USERDATA, 0);
	if ( sys pointer2) {
		if ( sys pointer2 == sys pointer) SetCursor( NULL); // un-use resource first
		if ( !DestroyCursor( sys pointer2)) apiErr;
	}
	if ( sys recreate_data) free( sys recreate_data);
	if ( self == last_mouse_over) last_mouse_over = NULL_HANDLE;
	if ( self == guts.drag_target) guts.drag_target = NULL_HANDLE;
	if ( var handle == NULL_HANDLE) return true;

	if ( sys class_name == WC_FRAME)
		guts. top_windows--;

	if ( !DestroyWindow( HANDLE)) apiErrRet;
	return true;
}

PFont
apc_widget_default_font( PFont copyTo)
{
	*copyTo = guts. window_font;
	copyTo-> pitch = fpDefault;
	return copyTo;
}

static void
subpaint_layered_widgets( HWND self, HDC ps, HDC alpha_dc, POINT screen_offset, HRGN parent_shape)
{
	HWND child = GetTopWindow( self );
	if ( child ) child = GetWindow( child, GW_HWNDLAST );
	while ( child != NULL ) {
		Handle h;
		RECT r;
		HRGN shape;
		Event ev;
		POINT child_offset, size;

		h = hwnd_to_view(child);
		if ( h == NULL_HANDLE || !IsWindowVisible(child) || !dsys(h) options. aptClipOwner) {
			child = GetWindow( child, GW_HWNDPREV);
			continue;
		}

		GetWindowRect( child, &r);
		r. left   -= screen_offset. x;
		r. top    -= screen_offset. y;
		r. right  -= screen_offset. x;
		r. bottom -= screen_offset. y;
		size. x = r.right  - r. left;
		size. y = r.bottom - r. top;
		child_offset. x = r. left;
		child_offset. y = r. top;

		dsys(h) options. aptLayeredPaint = 1;
		dsys(h) layered_paint_offset. x = -r. left;
		dsys(h) layered_paint_offset. y = -r. top;
		dsys(h) layered_paint_surface   = ps;

		shape = CreateRectRgn(0,0,0,0);
		if ( GetWindowRgn( child, shape)) {
			HRGN rect = CreateRectRgn( 0, 0, size.x, size.y);
			CombineRgn( shape, shape, rect, RGN_AND);
			DeleteObject( rect );
		} else {
			DeleteObject( shape );
			shape = CreateRectRgn( 0, 0, size.x, size.y);
		}
		OffsetRgn( shape, child_offset. x, child_offset. y);
		if ( parent_shape ) CombineRgn( shape, shape, parent_shape, RGN_AND );
		dsys(h) layered_parent_region = shape;

		ev. cmd = cmPaint;
		CWidget(h)-> message( h, &ev);

		if ( !dsys(h) options. aptLayeredRequested) {
			/* assigning opaque alpha over the child rect so Windows passes mouse events in */
			StretchBlt( ps, r.left, r.top, size.x, size.y, alpha_dc, 0, 0, 1, 1, SRCPAINT);
		}
		dsys(h) options. aptLayeredPaint = 0;

		subpaint_layered_widgets( child, ps, alpha_dc, screen_offset, shape);

		DeleteObject( shape );
		child = GetWindow( child, GW_HWNDPREV);
	}
}

Bool
apc_widget_end_paint( Handle self)
{
	objCheck false;

	hwnd_leave_paint( self);

	if ( is_apt( aptLayeredPaint )) {
		// do nothing
	} else if ( is_apt( aptLayered )) {
		RECT r;
		SIZE size;
		POINT src, pos, *ppos = NULL;
		BLENDFUNCTION bf;
		HBITMAP alpha_bm, stock_alpha_bm;
		HDC alpha_dc;
		uint32_t * alpha_pixels;

		GetWindowRect((HWND) var handle, &r);
		if ( r. right - r. left <= 0 || r. bottom - r. top <= 0)
			goto SKIP_ALPHA;

		alpha_dc = CreateCompatibleDC( sys ps );
		alpha_bm = image_create_argb_dib_section( alpha_dc, 1, 1, &alpha_pixels);
		stock_alpha_bm = SelectObject( alpha_dc, alpha_bm);
		*alpha_pixels = 0xFF000000;

		/* subpaint children */
		src. x = r. left;
		src. y = r. top;
		subpaint_layered_widgets((HWND) var handle, sys ps, alpha_dc, src, NULL);

		SelectObject( alpha_dc, stock_alpha_bm);
		DeleteObject( alpha_bm );
		DeleteDC( alpha_dc );

		size. cx = r. right - r. left;
		size. cy = r. bottom - r. top;
		src. x = 0;
		src. y = 0;
		bf. AlphaFormat         = AC_SRC_ALPHA;
		bf. SourceConstantAlpha = 255;
		bf. BlendFlags          = 0;
		bf. BlendOp             = AC_SRC_OVER;
		if (is_apt(aptMovePending)) {
			pos. x = sys layered_pos. x;
			pos. y = sys layered_pos. y;
			ppos = &pos;
			apt_clear(aptMovePending);
		}
		if ( !UpdateLayeredWindow((HWND) var handle, NULL, ppos, &size, sys ps, &src, 0, &bf, ULW_ALPHA))
			apiErr;
	SKIP_ALPHA:
		SelectObject(sys ps, sys stock_bitmap);
		DeleteObject(sys bm);
		DeleteDC(sys ps);
		ReleaseDC(( HWND) var handle, sys ps2);
		sys ps = sys ps2 = NULL;
		sys bm = sys stock_bitmap = NULL;
	} else if ( is_opt( optBuffered)) {
		apt_clear( aptBitmap);
		if ( sys bm != NULL) {
			if ( !BitBlt( sys ps2,
				sys transform2. x, sys transform2. y,
				sys effective_view.x, sys effective_view.y,
				sys ps, 0, 0, SRCCOPY
				)) apiErr;
			if ( sys stock_bitmap)
				SelectObject( sys ps, sys stock_bitmap);
			DeleteObject( sys bm);
		}

		if ( sys pal) {
			SelectPalette( sys ps2, sys pal2, 1);
			SelectPalette( sys ps, sys stock_palette, 1);
			RealizePalette( sys ps2);
			sys pal2 = NULL;
		}

		DeleteDC( sys ps);
		sys ps = sys ps2;
		sys bm = NULL;
		sys ps2 = NULL;
		sys stock_bitmap = NULL;
	}

	if ( !is_apt(aptLayeredPaint) && sys ps != NULL) {
		if ( is_apt( aptWinPS) && is_apt( aptWM_PAINT)) {
			if ( !EndPaint(( HWND) var handle, &sys paint_struct)) apiErr;
		} else if ( is_apt( aptWinPS))
			if ( !ReleaseDC(( HWND) var handle, sys ps)) apiErr;
	}
	sys ps = NULL;
	sys pal2 = NULL;
	apt_clear( aptWinPS);
	apt_clear( aptWM_PAINT);
	apt_clear( aptCompatiblePS);
	return true;
}

Bool
apc_widget_end_paint_info( Handle self)
{
	Bool ok = true;
	objCheck false;
	hwnd_leave_paint( self);
	if ( !( ok = ReleaseDC(( HWND) var handle, sys ps))) apiErr;
	sys ps = NULL;
	apt_clear( aptWinPS);
	apt_clear( aptCompatiblePS);
	return ok;
}

Bool
apc_widget_get_clip_by_children( Handle self)
{
	objCheck false;
	return is_apt(aptClipByChildren);
}

Bool
apc_widget_get_clip_owner( Handle self)
{
	objCheck false;
	return is_apt( aptClipOwner);
}

Color
apc_widget_get_color( Handle self, int index)
{
	objCheck clInvalid;
	return sys view_colors[ index];
}

Bool
apc_widget_get_first_click( Handle self)
{
	objCheck false;
	return is_apt( aptFirstClick);
}

Handle
apc_widget_get_focused()
{
	return hwnd_to_view( GetFocus());
}

static PRECT map_Rect( Handle self, Rect * rect)
{
	RECT  __rectangle;
	objCheck ( PRECT) rect;
	GetWindowRect(( HWND) var handle, &__rectangle);
	if ( is_apt( aptClipOwner) && ( var owner != prima_guts.application))
		MapWindowPoints( NULL, ( HWND)((( PWidget) var owner)-> handle), ( LPPOINT) &__rectangle, 2);
	rect-> bottom = ( __rectangle. bottom - __rectangle. top) - rect-> bottom;
	rect-> top    = ( __rectangle. bottom - __rectangle. top) - rect-> top;
// that is due the difference in field placement between Rect and RECT structures
	if ( rect-> bottom > rect-> top) {
		LONG i = rect-> bottom;
		rect-> bottom = rect-> top;
		rect-> top    = i;
	}
	return ( PRECT) rect;
}

static Rect * map_RECT( Handle self, RECT * rect)
{
	RECT __rectangle;
	objCheck ( Rect*)rect;
	GetWindowRect(( HWND) var handle, &__rectangle);
	if ( is_apt( aptClipOwner) && ( var owner != prima_guts.application))
		MapWindowPoints( NULL, ( HWND)((( PWidget) var owner)-> handle), ( LPPOINT)&__rectangle, 2);
	rect-> bottom = ( __rectangle. bottom - __rectangle. top) - rect-> bottom;
	rect-> top    = ( __rectangle. bottom - __rectangle. top) - rect-> top;
// that is due the difference in field placement between Rect and RECT structures
	if ( rect-> bottom < rect-> top) {
		LONG i = rect-> bottom;
		rect-> bottom = rect-> top;
		rect-> top    = i;
	}
	return ( Rect *) rect;
}

ApiHandle
apc_widget_get_handle( Handle self)
{
	objCheck 0;
	return ( ApiHandle) HANDLE;
}

ApiHandle
apc_widget_get_parent_handle( Handle self)
{
	objCheck 0;
	return ( ApiHandle) sys parent_handle;
}


Rect
apc_widget_get_invalid_rect( Handle self)
{
	Rect r  = {0,0,0,0};
	objCheck r;
	if ( GetUpdateRect(( HWND) var handle, ( PRECT) &r, false))
		return *( map_RECT( self, ( PRECT) &r));
	return r;
}

Bool
apc_widget_get_layered_request( Handle self)
{
	return is_apt( aptLayeredRequested);
}

Bool
apc_widget_surface_is_buffered( Handle self)
{
	return sys bm != NULL || is_apt(aptLayeredPaint);
}

Bool
apc_widget_surface_is_layered( Handle self)
{
	Handle top;
	objCheck false;

	if ( is_apt( aptLayered)) return true;
	top = hwnd_layered_top_level(self);
	if ( top && dsys(top) options. aptLayered ) return true;
	return false;
}

Point
apc_widget_get_pos( Handle self)
{
	RECT  r;
	Point p, sz = {0,0};
	Handle parent;
	objCheck sz;
	parent = is_apt( aptClipOwner) ? var owner : prima_guts.application;
	sz = ((( PWidget) parent)-> self)-> get_size( parent);
	if ( sys class_name == WC_FRAME && apc_window_get_window_state( self) == wsMinimized) {
		WINDOWPLACEMENT w = {sizeof(WINDOWPLACEMENT)};
		if ( !GetWindowPlacement( HANDLE, &w)) apiErr;
		p. x = w. rcNormalPosition. left;
		p. y = sz. y - w. rcNormalPosition. bottom;
	} else if ( is_apt( aptMovePending)) {
		GetWindowRect( HANDLE, &r);
		p. x = sys layered_pos. x;
		p. y = sys layered_pos. y + r. bottom - r.top;
	} else {
		GetWindowRect( HANDLE, &r);
		if ( is_apt( aptClipOwner) && ( var owner != prima_guts.application))
			MapWindowPoints( NULL, ( HWND)((( PWidget) var owner)-> handle), ( LPPOINT)&r, 2);
		p. x = r. left;
		p. y = sz. y - r. bottom;
	}
	return p;
}

Point
apc_widget_get_size( Handle self)
{
	RECT r;
	Point p = {0,0};
	objCheck p;
	if ( sys class_name == WC_FRAME && apc_window_get_window_state( self) == wsMinimized) {
		WINDOWPLACEMENT w = {sizeof(WINDOWPLACEMENT)};
		if ( !GetWindowPlacement( HANDLE, &w)) apiErr;
		p. x = w. rcNormalPosition. right  - w. rcNormalPosition. left;
		p. y = w. rcNormalPosition. bottom - w. rcNormalPosition. top;
	} else {
		GetWindowRect( HANDLE, &r);
		if ( is_apt( aptClipOwner) && ( var owner != prima_guts.application))
			MapWindowPoints( NULL, ( HWND)((( PWidget) var owner)-> handle), ( LPPOINT)&r, 2);
		p. x = r. right - r. left;
		p. y = r. bottom - r. top;
	}
	return p;
}

Handle
apc_widget_get_z_order( Handle self, int zOrderId)
{
	Handle h;
	HWND   w;
	UINT   cmd1, cmd2;
	objCheck NULL_HANDLE;

	switch ( zOrderId) {
	case zoFirst:
		cmd1 = GW_HWNDFIRST;
		cmd2 = GW_HWNDNEXT;
		break;
	case zoLast:
		cmd1 = GW_HWNDLAST;
		cmd2 = GW_HWNDPREV;
		break;
	case zoNext:
		cmd1 = cmd2 = GW_HWNDNEXT;
		break;
	case zoPrev:
		cmd1 = cmd2 = GW_HWNDPREV;
		break;
	default:
		apcErr( errInvParams);
		return NULL_HANDLE;
	}

	w = GetWindow( HANDLE, cmd1);
	if ( !w) return NULL_HANDLE;
	h = hwnd_to_view( w);
	while ( h == NULL_HANDLE) {
		w = GetWindow( w, cmd2);
		if ( !w) return NULL_HANDLE;
		h = hwnd_to_view( w);
	}

	return h;
}

Bool
apc_widget_get_shape( Handle self, Handle mask)
{
	HRGN rgn;
	int res;
	RECT rect;

	if ( !mask ) {
		rgn = CreateRectRgn(0,0,0,0);
		res = GetWindowRgn( HANDLE, rgn);
		res = GetClipRgn( sys ps, rgn );
		DeleteObject(rgn);
		return res != ERROR;
	}

	rgn = GET_REGION(mask)-> region;
	res = GetWindowRgn( HANDLE, rgn);
	if ( res == ERROR)
		return false;

	GetRgnBox(rgn, &rect);
	OffsetRgn( rgn, -sys extra_pos. x, -sys extra_pos. y);
	GET_REGION(mask)-> aperture = sys last_size. y - rect.top;

	return true;
}


Bool
apc_widget_get_sync_paint( Handle self)
{
	objCheck false;
	return is_apt( aptSyncPaint);
}

Bool
apc_widget_get_transparent( Handle self)
{
	objCheck false;
	return is_apt( aptTransparent);
}

Bool
apc_widget_is_captured( Handle self)
{
	objCheck false;
	return GetCapture() == ( HWND) var handle;
}

Bool
apc_widget_is_enabled( Handle self)
{
	objCheck false;
	return is_apt( aptEnabled);
	// return IsWindowEnabled( HANDLE);
}

Bool
apc_widget_is_responsive( Handle self)
{
	Bool ena = true;
	objCheck false;
	while ( ena && self != prima_guts.application) {
		// ena  = IsWindowEnabled( HANDLE);
		ena  = is_apt( aptEnabled);
		self = var owner;
	}
	return ena;
}

Bool
apc_widget_is_focused( Handle self)
{
	objCheck false;
	return is_apt( aptFocused);
}

Bool
apc_widget_is_visible( Handle self)
{
	objCheck false;
	return ( GetWindowLong(HANDLE, GWL_STYLE) & WS_VISIBLE) ? 1 : 0;
}

Bool
apc_widget_is_showing( Handle self)
{
	objCheck false;
	return IsWindowVisible( HANDLE);
}

Bool
apc_widget_is_exposed( Handle self)
{
	HWND h;
	HRGN rgnSave = NULL;
	HRGN rgn     = NULL;
	int  rgnSaveType, rgnType;

	objCheck false;

	h = ( HWND) var handle;
	if ( !IsWindowVisible( h)) return false;

	rgnSave = CreateRectRgn(0,0,0,0);
	rgn     = CreateRectRgn(0,0,0,0);
	rgnSaveType = GetUpdateRgn( h, rgnSave, FALSE);
	rgnSaveType = ( rgnSaveType == COMPLEXREGION || rgnSaveType == SIMPLEREGION);

	if ( rgnSaveType) ValidateRect( h, NULL);

	InvalidateRect( h, NULL, false);
	rgnType = GetUpdateRgn( h, rgn, FALSE);
	ValidateRect( h, NULL);

	if ( rgnSaveType) InvalidateRgn( h, rgnSave, FALSE);
	DeleteObject( rgnSave);
	DeleteObject( rgn);
	return ( rgnType == COMPLEXREGION || rgnType == SIMPLEREGION);
}

Bool
apc_widget_invalidate_rect( Handle self, Rect * rect)
{
	PRECT pRect = rect ? map_Rect( self, rect) : NULL;
	objCheck false;
	if ( !InvalidateRect (( HWND) var handle, pRect, false)) apiErr;
	hwnd_repaint_layered( self, false );
	if ( is_apt( aptSyncPaint) && !apcUpdateWindow(( HWND) var handle)) apiErr;
	objCheck false;
	process_transparents( self);
	return true;
}

int
apc_widget_scroll( Handle self, int horiz, int vert, Rect * r, Rect *cr, Bool scrollChildren)
{
	PRECT pRect = r ? map_Rect( self, r) : NULL;
	PRECT pClipRect = cr ? map_Rect( self, cr) : NULL;
	Point sz = apc_widget_get_size( self);
	int ret;
	objCheck scrError;

	HideCaret(( HWND) var handle);

	if ( pClipRect) {
		if ( pClipRect-> left < 0) pClipRect-> left = 0;
		if ( pClipRect-> top  < 0) pClipRect-> top = 0;
		if ( pClipRect-> right  > sz. x) pClipRect-> right = sz. x;
		if ( pClipRect-> bottom > sz. y) pClipRect-> bottom = sz. y;
	}

	if ( pRect) {
		if ( pRect-> left < -sz. x * 2) pRect-> left = -sz. x * 2;
		if ( pRect-> top  < -sz. y * 2) pRect-> top = -sz. y * 2;
		if ( pRect-> right  > sz. x * 2) pRect-> right = sz. x * 2;
		if ( pRect-> bottom > sz. y * 2) pRect-> bottom = sz. y * 2;
	}

	if ( horiz > sz. x || horiz < -sz. x || vert > sz. y || vert < -sz. y) {
		if ( pRect && pClipRect) {
			RECT rc;
			UnionRect( &rc, (RECT*)pRect, (RECT*)pClipRect);
			InvalidateRect(( HWND) var handle, &rc, false);
		} else
			InvalidateRect(( HWND) var handle, pRect ? pRect : pClipRect, false);
		ret = scrExpose;
	} else {
		int rr = ScrollWindowEx(( HWND) var handle,
			horiz, -vert, pRect, pClipRect, NULL, NULL,
			SW_INVALIDATE | ( scrollChildren ? SW_SCROLLCHILDREN : 0)
		);
		if (!rr) apiErr;
		ret = ( rr == 1 ) ? scrNoExpose : scrExpose;
	}

	objCheck scrError;
	if ( is_apt( aptSyncPaint) && !apcUpdateWindow(( HWND) var handle)) apiErr;
	process_transparents( self);
	ShowCaret(( HWND) var handle);

	return ret;
}

Bool
apc_widget_set_capture( Handle self, Bool capture, Handle confineTo)
{
	objCheck false;
	if ( capture) {
		SetCapture(( HWND) var handle);
		if ( confineTo) {
			RECT r;
			GetWindowRect(( HWND) PComponent( confineTo)-> handle, &r);
			if ( !ClipCursor( &r)) apiErrRet;
		}
	} else {
		if ( !ReleaseCapture()) apiErrRet;
		if ( !ClipCursor( NULL)) apiErrRet;
	}
	return true;
}

#define check_swap( parm1, parm2) if ( parm1 > parm2) { int parm3 = parm1; parm1 = parm2; parm2 = parm3;}

Bool
apc_widget_set_clip_by_children( Handle self, Bool clip_by_children)
{
	objCheck false;
	LONG f;
	MSG  msg;
	Bool is_clipped;

	is_clipped = is_apt(aptClipByChildren);
	clip_by_children = !!clip_by_children;
	if ( is_clipped == clip_by_children )
		return true;

	if ( sys class_name == WC_FRAME) {
		f = GetWindowLong(( HWND ) var handle, GWL_STYLE);
		if ( clip_by_children )
			f |= WS_CLIPCHILDREN;
		else
			f &= ~WS_CLIPCHILDREN;
		SetWindowLong(( HWND ) var handle, GWL_STYLE, f);
		while ( PeekMessage( &msg, (HWND) var handle, WM_MOUSEMOVE, WM_MOUSEMOVE, PM_REMOVE));
	}

	f = GetWindowLong(HANDLE, GWL_STYLE);
	if ( clip_by_children )
		f |= WS_CLIPCHILDREN;
	else
		f &= ~WS_CLIPCHILDREN;
	SetWindowLong( HANDLE, GWL_STYLE, f);
	while ( PeekMessage( &msg, HANDLE, WM_MOUSEMOVE, WM_MOUSEMOVE, PM_REMOVE));
	return true;
}

Bool
apc_widget_set_color( Handle self, Color color, int index)
{
	Event ev = {cmColorChanged};
	objCheck false;
	sys view_colors[ index] = color;

	ev. gen. source = self;
	ev. gen. i      = index;
	var self-> message( self, &ev);
	return true;
}

Bool
apc_widget_set_enabled( Handle self, Bool enable)
{
	objCheck false;
	apt_assign( aptEnabled, enable);
	if (( sys class_name == WC_FRAME) || ( var owner == prima_guts.application))
		EnableWindow( HANDLE, enable);
	else
		SendMessage( HANDLE, WM_ENABLE, ( WPARAM) enable, 0);
	return true;
}

Bool
apc_widget_set_first_click( Handle self, Bool firstClick)
{
	objCheck false;
	apt_assign( aptFirstClick, firstClick);
	return true;
}

Bool
apc_widget_set_focused( Handle self)
{
	if ( self && ( self != Application_map_focus( prima_guts.application, self)))
		return false;
	guts. sys_focus_granted++;
	SetFocus( self ? (( HWND) var handle) : NULL);
	guts. sys_focus_granted--;
	return true;
}

Bool
apc_widget_set_font( Handle self, PFont font)
{
	Event ev = {cmFontChanged};
	objCheck false;
	ev. gen. source = self;
	var self-> message( self, &ev);
	return true;
}

Bool
apc_widget_set_palette( Handle self)
{
	objCheck false;
	apc_gp_set_palette( self);
	if ( guts. display_bm_info. bmiHeader. biBitCount == 8)
		palette_change( self);
	return true;
}

Bool
apc_widget_set_pos( Handle self, int x, int y)
{
	Handle parent;
	Point sz;
	RECT r;

	objCheck false;
	if ( !hwnd_check_limits( x, y, true)) apcErrRet( errInvParams);

	parent = is_apt( aptClipOwner) ? var owner : prima_guts.application;
	sz = ((( PWidget) parent)-> self)-> get_size( parent);
	apt_set( aptWinPosDetermined);

	if ( sys class_name == WC_FRAME) {
		HWND h = HANDLE;
		int  ws = apc_window_get_window_state( self);
		if (( var stage == csConstructing && ws != wsNormal) || ( ws == wsMinimized)) {
			WINDOWPLACEMENT w = {sizeof(WINDOWPLACEMENT)};
			if ( !GetWindowPlacement( h, &w)) apiErrRet;
			w. rcNormalPosition. top    += sz. y - y - w. rcNormalPosition. bottom;
			w. rcNormalPosition. bottom  = sz. y - y;
			w. rcNormalPosition. right  += x - w. rcNormalPosition. left;
			w. rcNormalPosition. left    = x;
			w. flags = 0;
			if ( !SetWindowPlacement( h, &w)) apiErrRet;
			return true;
		}
	}
	if ( !GetWindowRect( HANDLE, &r)) apiErrRet;
	if ( is_apt( aptClipOwner) && ( var owner != prima_guts.application))
		MapWindowPoints( NULL, ( HWND)((( PWidget) var owner)-> handle), ( LPPOINT)&r, 2);
	if ( sys parent_handle) {
		POINT ppos;
		ppos. x = x;
		ppos. y = dsys( prima_guts.application) last_size. y - y;
		MapWindowPoints( NULL, sys parent_handle, ( LPPOINT)&ppos, 1);
		GetWindowRect( sys parent_handle, &r);
		x = ppos. x;
		y = ppos. y;
	} else
		y = sz. y - y - r. bottom + r. top;

	if ( is_apt(aptLayered) && is_apt(aptRepaintPending)) {
		apt_set(aptMovePending);
		sys layered_pos. x = x;
		sys layered_pos. y = y;
	} else {
		if ( !SetWindowPos( HANDLE, 0, x, y, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE)) apiErrRet;
	}
	return true;
}

Bool
apc_widget_set_size( Handle self, int width, int height)
{
	RECT r;
	HWND h;
	objCheck false;

	if ( !hwnd_check_limits( width, height, false)) apcErrRet( errInvParams);
	h = HANDLE;
	if ( sys class_name == WC_FRAME) {
		int  ws = apc_window_get_window_state( self);
		if (( var stage == csConstructing && ws != wsNormal) || ( ws == wsMinimized)) {
			WINDOWPLACEMENT w = {sizeof(WINDOWPLACEMENT)};
			if ( !GetWindowPlacement( h, &w)) apiErrRet;
			if ( width  < 0) width = 0;
			if ( height < 0) height = 0;
			w. rcNormalPosition. top    = w. rcNormalPosition. bottom - height;
			w. rcNormalPosition. right  = width + w. rcNormalPosition. left;
			w. flags = 0;
			if ( !SetWindowPlacement( h, &w)) apiErrRet;
			return true;
		}
	}
	if ( !GetWindowRect( h, &r)) apiErrRet;
	if ( is_apt( aptClipOwner) && ( var owner != prima_guts.application))
		MapWindowPoints( NULL, ( HWND)((( PWidget) var owner)-> handle), ( LPPOINT)&r, 2);
	if ( sys parent_handle)
		MapWindowPoints( NULL, sys parent_handle, ( LPPOINT)&r, 2);

	if ( sys class_name != WC_FRAME) {
		sys size_lock_level++;
		var virtualSize. x = width;
		var virtualSize. y = height;
	}
	if ( height < 0) height = 0;
	if ( width  < 0) width  = 0;
	if ( is_apt(aptMovePending)) {
		int dx = r. right  - r. left;
		int dy = r. bottom - r. top;
		r. left = sys layered_pos. x;
		r. top  = sys layered_pos. y;
		r. right  = r. left + dx;
		r. bottom = r. top  + dy;
		apt_clear(aptMovePending);
	}
	if ( !SetWindowPos( h, 0,
		r. left, r. bottom - height,
		width, height,
		SWP_NOZORDER | SWP_NOACTIVATE |
			( is_apt( aptWinPosDetermined) ? 0 : SWP_NOMOVE)
		)) apiErrRet;
	hwnd_repaint_layered( self, false );
	if ( sys class_name != WC_FRAME) sys size_lock_level--;
	return true;
}

Bool
apc_widget_set_rect( Handle self, int x, int y, int width, int height)
{
	HWND h;
	Handle parent;
	Point sz;
	objCheck false;

	if ( !hwnd_check_limits( width, height, false)) apcErrRet( errInvParams);
	if ( !hwnd_check_limits( x, y, true)) apcErrRet( errInvParams);

	parent = is_apt( aptClipOwner) ? var owner : prima_guts.application;
	sz = ((( PWidget) parent)-> self)-> get_size( parent);
	apt_set( aptWinPosDetermined);

	h = HANDLE;
	if ( sys class_name == WC_FRAME) {
		int  ws = apc_window_get_window_state( self);
		if (( var stage == csConstructing && ws != wsNormal) || ( ws == wsMinimized)) {
			WINDOWPLACEMENT w = {sizeof(WINDOWPLACEMENT)};
			if ( !GetWindowPlacement( h, &w)) apiErrRet;
			if ( width  < 0) width = 0;
			if ( height < 0) height = 0;
			w. rcNormalPosition. left    = x;
			w. rcNormalPosition. bottom  = sz. y - y;
			w. rcNormalPosition. right   = x + width;
			w. rcNormalPosition. top     = sz. y - y - height;
			w. flags = 0;
			if ( !SetWindowPlacement( h, &w)) apiErrRet;
			return true;
		}
	}

	if ( sys class_name != WC_FRAME) {
		sys size_lock_level++;
		var virtualSize. x = width;
		var virtualSize. y = height;
	}
	if ( height < 0) height = 0;
	if ( width  < 0) width  = 0;
	if ( sys parent_handle) {
		POINT ppos;
		ppos. x = x;
		ppos. y = dsys( prima_guts.application) last_size. y - y;
		MapWindowPoints( NULL, sys parent_handle, ( LPPOINT)&ppos, 1);
		x = ppos. x;
		y = ppos. y;
	} else
		y = sz. y - y - height;

	apt_clear(aptMovePending);
	if ( !SetWindowPos( h, 0, x, y, width, height, SWP_NOZORDER | SWP_NOACTIVATE))
		apiErrRet;
	hwnd_repaint_layered( self, false );
	if ( sys class_name != WC_FRAME) sys size_lock_level--;
	return true;
}


Bool
apc_widget_set_size_bounds( Handle self, Point min, Point max)
{
	return true;
}

Bool
apc_widget_set_shape( Handle self, Handle mask)
{
	HRGN rgn = NULL;
	RECT xr;
	objCheck false;
	Point sz;

	if ( !mask) {
		if ( sys class_name == WC_FRAME && is_apt(aptLayered))
			SetWindowRgn((HWND) var handle, NULL, true);
		else
			SetWindowRgn( HANDLE, NULL, true);
		hwnd_repaint_layered( self, false );
		return true;
	}


	sz = apc_widget_get_size( self);
	rgn = CreateRectRgn(0,0,0,0);
	CombineRgn( rgn, GET_REGION(mask)->region, NULL, RGN_COPY);
	GetRgnBox( rgn, &xr);
	sys extra_bounds. x = xr. right - 1;
	sys extra_bounds. y = GET_REGION(mask)->aperture;
	if ( sys class_name == WC_FRAME && !is_apt(aptLayered)) {
		Point delta = get_window_borders( sys s. window. border_style);
		Point p     = sys extra_bounds;
		HRGN  r1, r2;

		OffsetRgn( rgn, delta.x, sz. y - p.y - delta.y);
		sys extra_pos. x = delta.x;
		sys extra_pos. y = sz. y - p.y - delta.y;
		r1 = CreateRectRgn( 0, 0, 8192, 8192);
		r2 = CreateRectRgn( delta. x, sz. y - delta. y - p.y,
			delta.x + p.x, sz. y - delta. y);
		CombineRgn( r1, r1, r2, RGN_XOR);
		CombineRgn( rgn, rgn, r1, RGN_OR);
		DeleteObject( r1);
		DeleteObject( r2);
		if ( !SetWindowRgn( HANDLE, rgn, true))
			apiErrRet;
		DeleteObject(rgn);
	} else if ( sys class_name == WC_FRAME ) {
		sys extra_pos. x = sys extra_pos. y = 0;
		OffsetRgn( rgn, 0, GET_REGION(mask)->aperture - xr.bottom - 1);
		if ( !SetWindowRgn((HWND) var handle, rgn, true))
			apiErrRet;
	} else {
		sys extra_pos. x = sys extra_pos. y = 0;
		OffsetRgn( rgn, 0, sz.y - GET_REGION(mask)->aperture);
		if ( !SetWindowRgn( HANDLE, rgn, true))
			apiErrRet;
	}
	DeleteObject(rgn);

	if ( is_apt(aptMovePending)) {
		apt_clear(aptMovePending);
		if ( !SetWindowPos( HANDLE, 0, sys layered_pos. x, sys layered_pos. y, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE))
			apiErrRet;
	}
	hwnd_repaint_layered( self, false );
	return true;
}

Bool
apc_widget_set_sync_paint( Handle self, Bool syncPaint)
{
	objCheck false;
	apt_assign( aptSyncPaint, syncPaint );
	return true;
}

Bool
apc_widget_set_transparent( Handle self, Bool transparent)
{
	objCheck false;
	if ( sys class_name == WC_FRAME)
		return false;
	apt_assign( aptTransparent, transparent);
	return true;
}

Bool
apc_widget_set_visible( Handle self, Bool show)
{
	objCheck false;
	if ( !SetWindowPos( HANDLE, NULL, 0, 0, 0, 0,
		( show ? SWP_SHOWWINDOW : SWP_HIDEWINDOW)
		| SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE)) apiErrRet;
	objCheck false;
	if ( !is_apt( aptClipOwner)) {
		InvalidateRect(( HWND) var handle, NULL, false);
		objCheck false;
		process_transparents( self);
	}
	hwnd_repaint_layered(self, false);
	return true;
}

Bool
apc_widget_set_z_order( Handle self, Handle behind, Bool top)
{
	HWND opt = ( top) ? HWND_TOP : HWND_BOTTOM;
	objCheck false;
	if ( behind != NULL_HANDLE) {
		dobjCheck( behind) false;
		opt = DHANDLE( behind);
	}
	if ( !SetWindowPos( HANDLE, opt, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE)) apiErrRet;
	return true;
}

Bool
apc_widget_update( Handle self)
{
	objCheck false;
	if ( !apcUpdateWindow(( HWND) var handle)) apiErrRet;
	return true;
}

Bool
apc_widget_validate_rect( Handle self, Rect rect)
{
	objCheck false;
	if ( !ValidateRect (( HWND) var handle, map_Rect( self, &rect))) apiErrRet;
	return true;
}


#ifdef __cplusplus
}
#endif
