1 #include "win32\win32guts.h"
2 #include <commdlg.h>
3 #ifndef _APRICOT_H_
4 #include "apricot.h"
5 #endif
6 #include "guts.h"
7 #include "File.h"
8 #include "Menu.h"
9 #include "Image.h"
10 #include "Region.h"
11 #include "Window.h"
12 #include "Application.h"
13 
14 #ifdef __cplusplus
15 extern "C" {
16 #endif
17 
18 
19 #define  sys (( PDrawableData)(( PComponent) self)-> sysData)->
20 #define  dsys( view) (( PDrawableData)(( PComponent) view)-> sysData)->
21 #define var (( PWidget) self)->
22 #define HANDLE sys handle
23 #define DHANDLE(x) dsys(x) handle
24 #define GET_REGION(obj) (&(dsys(obj)s.region))
25 
26 #define WinShowWindow(WND) SetWindowPos( WND, NULL, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|SWP_SHOWWINDOW|SWP_NOACTIVATE);
27 #define WinHideWindow(WND) SetWindowPos( WND, NULL, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|SWP_HIDEWINDOW);
28 #define apc_widget_redraw(self)  apc_widget_invalidate_rect(self,NULL)
29 
30 void
process_transparents(Handle self)31 process_transparents( Handle self)
32 {
33 	int i;
34 	RECT mr;
35 	objCheck;
36 	GetWindowRect(( HWND) var handle, &mr);
37 	for ( i = 0; i < var widgets. count; i++) {
38 		HWND xwnd;
39 		Handle x = var widgets. items[ i];
40 		dobjCheck(x);
41 		xwnd = DHANDLE(x);
42 		if ( dsys(x) options. aptTransparent && IsWindowVisible( xwnd)) {
43 			RECT r, dr;
44 			GetWindowRect( xwnd, &r);
45 			IntersectRect( &dr, &r, &mr);
46 			if ( !IsRectEmpty( &dr))
47 				InvalidateRect( xwnd, NULL, false);
48 		}
49 	}
50 }
51 
52 typedef struct _ViewProfile {
53 	ColorSet colors;
54 	Point    pos;
55 	Point    size;
56 	Point    virtSize;
57 	Bool     enabled;
58 	Bool     visible;
59 	Bool     focused;
60 	Handle   capture;
61 	HRGN     shape;
62 } ViewProfile, *PViewProfile;
63 
64 
65 static void
get_view_ex(Handle self,PViewProfile p)66 get_view_ex( Handle self, PViewProfile p)
67 {
68 	int i;
69 	if ( !p) return;
70 	p-> capture   = apc_widget_is_captured( self);
71 	for ( i = 0; i <= ciMaxId; i++) p-> colors[ i] = apc_widget_get_color( self, i);
72 	if ( sys className == WC_FRAME) {
73 		p-> pos       = apc_window_get_client_pos( self);
74 		p-> size      = apc_window_get_client_size( self);
75 	} else {
76 		p-> pos       = apc_widget_get_pos( self);
77 		p-> size      = apc_widget_get_size( self);
78 	}
79 	p-> virtSize  = var virtualSize;
80 	p-> enabled   = apc_widget_is_enabled( self);
81 	p-> focused   = apc_widget_is_focused( self);
82 	p-> visible   = apc_widget_is_visible( self);
83 	p-> shape = CreateRectRgn(0,0,0,0);
84 	if ( sys className == WC_FRAME && is_apt(aptLayered))
85 		i = GetWindowRgn((HWND) var handle, p->shape);
86 	else
87 		i = GetWindowRgn( HANDLE, p->shape);
88 	if (!i) {
89 		DeleteObject(p->shape);
90 		p->shape = NULL;
91 	}
92 }
93 
94 static void
set_view_ex(Handle self,PViewProfile p)95 set_view_ex( Handle self, PViewProfile p)
96 {
97 	int i;
98 	Bool clip_by_children;
99 	if ( sys className == WC_FRAME && is_apt(aptLayered)) {
100 		SetWindowRgn((HWND) var handle, p-> shape, true);
101 	} else
102 		SetWindowRgn( HANDLE, p-> shape, true);
103 	apc_widget_set_visible( self, false);
104 	for ( i = 0; i <= ciMaxId; i++) apc_widget_set_color( self, p-> colors[i], i);
105 	apc_widget_set_font( self, &var font);
106 	if ( sys className == WC_FRAME) {
107 		apc_window_set_client_rect( self, p-> pos. x, p-> pos. y, p-> size.x, p-> size.y);
108 	} else {
109 		apc_widget_set_rect( self, p-> pos. x, p-> pos. y, p-> size.x, p-> size.y);
110 	}
111 	var virtualSize = p-> virtSize;
112 	apc_widget_set_enabled( self, p-> enabled);
113 	if ( p-> focused) apc_widget_set_focused( self);
114 
115 	clip_by_children = is_apt(aptClipByChildren);
116 	apt_set(aptClipByChildren); /* by default widget created with clipping */
117 	apc_widget_set_clip_by_children(self, clip_by_children);
118 
119 	apc_widget_set_visible( self, p-> visible);
120 	if ( p-> capture) apc_widget_set_capture( self, 1, NULL_HANDLE);
121 	if ( !InvalidateRect(( HWND) var handle, NULL, false)) apiErr;
122 	process_transparents( self);
123 }
124 
repost_msgs(PostMsg * msg,Handle self)125 static Bool repost_msgs( PostMsg * msg, Handle self)
126 {
127 	PostMessage(( HWND) var handle, WM_POSTAL, ( WPARAM) self, ( LPARAM) msg);
128 	return false;
129 }
130 
131 static Bool
create_group(Handle self,Handle owner,Bool syncPaint,Bool clipOwner,Bool taskListed,int className,DWORD style,DWORD exstyle,Bool usePos,Bool useSize,ViewProfile * vprf,HWND parentHandle)132 create_group( Handle self, Handle owner, Bool syncPaint, Bool clipOwner,
133 				Bool taskListed, int className, DWORD style, DWORD exstyle,
134 				Bool usePos, Bool useSize,
135 				ViewProfile * vprf, HWND parentHandle)
136 {
137 	HWND ret = NULL;
138 	HWND old        = HANDLE;
139 	HWND old2       = (HWND) var handle;
140 	HWND behind     = HWND_TOP;
141 	HWND ownerView  = ( HWND) (( PWidget) owner)-> handle;
142 	HWND parentView = (( PDrawableData)(( PComponent) owner)-> sysData)-> parent;
143 	int  count = 0;
144 	Bool reset = false;
145 	Handle * list = NULL;
146 	const WCHAR wnull = 0;
147 
148 	if ( HANDLE)
149 	{
150 		int i;
151 		if (( DHANDLE( owner) == sys owner) && ( clipOwner == is_apt( aptClipOwner)))
152 		{
153 			behind = GetWindow( HANDLE, GW_HWNDPREV);
154 			if ( behind == NULL) behind = HWND_TOP;
155 		}
156 		var stage = csAxEvents;
157 		if ( kind_of( self, CWidget))
158 		{
159 			PWidget g = ( PWidget) self;
160 			list  = g-> widgets. items;
161 			count = g-> widgets. count;
162 		}
163 		var self-> end_paint_info( self);
164 		var self-> end_paint( self);
165 		reset = true;
166 		for( i = 0; i < count; i++)
167 			get_view_ex( list[ i], ( ViewProfile*)( dsys( list[ i]) recreateData = malloc( sizeof( ViewProfile))));
168 	}
169 
170 	switch (( int) className)
171 	{
172 	case WC_FRAME:
173 		{
174 			HWND frame;
175 			RECT r;
176 			int  rcp[4] = {0,0,0,0};
177 			Bool layered = is_apt(aptLayered);
178 			if ( !clipOwner) parentView = HWND_DESKTOP;
179 			if ( !taskListed && ( parentView == HWND_DESKTOP || parentView == NULL))
180 				parentView = DHANDLE( application);
181 			if ( !usePos)  rcp[0] = rcp[1] = CW_USEDEFAULT;
182 			if ( !useSize) rcp[2] = rcp[3] = CW_USEDEFAULT;
183 			if ( !( frame = CreateWindowExW( exstyle, layered ? L"LayeredFrame" : L"GenericFrame", &wnull,
184 					style | WS_CLIPCHILDREN,
185 					rcp[0], rcp[1], rcp[2], rcp[3],
186 					parentView, NULL, guts. instance, NULL)))
187 				apiErrRet;
188 			if ( !SetWindowPos( frame, behind, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE))
189 				apiErr;
190 			if ((( PApplication) application)-> topExclModal &&
191 				((( PApplication) application)-> topExclModal != self)
192 				)
193 				if ( !SetWindowPos( frame, DHANDLE((( PApplication) application)-> topExclModal),
194 						0,0,0,0,SWP_NOMOVE | SWP_NOSIZE  | SWP_NOACTIVATE))
195 					apiErr;
196 			GetClientRect( frame, &r);
197 			if ( old2 )
198 				SetWindowLongPtr( old2, GWLP_USERDATA, 0);
199 			if ( old )
200 				SetWindowLongPtr( old, GWLP_USERDATA, 0);
201 			if ( layered ) {
202 				if ( !( ret = CreateWindowExW( WS_EX_LAYERED|WS_EX_TOOLWINDOW,  L"Generic", &wnull,
203 						WS_VISIBLE | WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
204 						r. left, r. top, r. right, r. bottom, NULL, NULL,
205 						guts. instance, NULL)))
206 					apiErr;
207 			} else {
208 				if ( !( ret = CreateWindowExW( 0,  L"Generic", &wnull,
209 						WS_VISIBLE | WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
210 						0, 0, r. right - r. left, r. bottom - r. top, frame, NULL,
211 						guts. instance, NULL)))
212 					apiErr;
213 			}
214 			sys lastSize. x = r. right  - r. left;
215 			sys yOverride = sys lastSize. y = r. bottom - r. top;
216 			sys handle = frame;
217 			SetWindowLongPtr( frame, GWLP_USERDATA, ( LONG) self);
218 		}
219 		break;
220 	case WC_CUSTOM:
221 		if ( !parentHandle && ( !clipOwner || owner == application)) {
222 				style &= ~WS_CHILD;
223 				style |= WS_POPUP;
224 				exstyle |= WS_EX_TOOLWINDOW;
225 		}
226 		if ( parentHandle) parentView = parentHandle;
227 		sys parentHandle = parentHandle;
228 
229 		if ( old )
230 			SetWindowLongPtr( old, GWLP_USERDATA, 0);
231 		if ( !( ret = CreateWindowExW( exstyle,  L"Generic", &wnull,
232 				style | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, 0, 0, 0, 0,
233 				parentView, NULL, guts. instance, NULL)))
234 			apiErrRet;
235 		if ( !SetWindowPos( ret, behind, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE))
236 			apiErr;
237 		sys handle = ret;
238 		break;
239 	}
240 
241 	apt_assign( aptClipOwner, clipOwner);
242 	apt_assign( aptSyncPaint, syncPaint);
243 	apt_set( aptEnabled);
244 	apt_clear( aptRepaintPending );
245 	apt_clear( aptMovePending );
246 	sys className = className;
247 	sys parent  = ret;
248 	var handle  = ( Handle) ret;
249 	sys owner   = ownerView;
250 	if ( !reset)
251 		sys pointer = LoadCursor( guts. instance, IDC_ARROW);
252 	SetWindowLongPtr( ret, GWLP_USERDATA, ( LONG) self);
253 
254 	if ( reset)
255 	{
256 		int i;
257 		Handle oldOwner = var owner; var owner = owner;
258 		if ( sys className == WC_FRAME) {
259 			apc_window_set_client_rect( self, vprf-> pos. x, vprf-> pos. y, vprf-> size. x, vprf-> size. y);
260 		} else {
261 			apc_widget_set_rect( self, vprf-> pos. x, vprf-> pos. y, vprf-> size. x, vprf-> size. y);
262 		}
263 		var owner = oldOwner;
264 		for ( i = 0; i < count; i++) ((( PComponent) list[ i])-> self)-> recreate( list[ i]);
265 		if ( sys className == WC_FRAME)
266 		{
267 			SetMenu( HANDLE, GetMenu( old));
268 			SetMenu( old, NULL);
269 		}
270 		if ( old2 != old ) {
271 			if ( !DestroyWindow( old2 ))
272 				apiErr;
273 		}
274 		if ( !DestroyWindow( old))
275 			apiErr;
276 		if ( var postList) list_first_that( var postList, repost_msgs, ( void*)self);
277 	}
278 	PostMessage( ret, WM_PRIMA_CREATE, 0, 0);
279 
280 	if ( !reset) {
281 		/* set manually cmMove and cmSize when windows are configured automatically */
282 		if ( !usePos) {
283 			Event e;
284 			Point sz = apc_window_get_client_pos( self);
285 			memset( &e, 0, sizeof(e));
286 			e. gen. source = self;
287 			e. cmd = cmMove;
288 			e. gen. P. x = sz. x;
289 			e. gen. P. y = sz. y;
290 			CComponent(self)->message( self, &e);
291 			if ( PObject( self)-> stage == csDead) return false;
292 		}
293 		if ( !useSize) {
294 			Event e;
295 			Point sz = apc_window_get_client_size( self);
296 			memset( &e, 0, sizeof(e));
297 			e. gen. source = self;
298 			e. cmd = cmSize;
299 			e. gen. P. x = e. gen. R. right = sz. x;
300 			e. gen. P. y = e. gen. R. top = sz. y;
301 			CComponent(self)->message( self, &e);
302 			if ( PObject( self)-> stage == csDead) return false;
303 		}
304 	}
305 	return true;
306 }
307 
308 static void
notify_sys_handle(Handle self)309 notify_sys_handle( Handle self )
310 {
311 	Event ev = {cmSysHandle};
312 	objCheck;
313 	ev. gen. source = self;
314 	var self-> message( self, &ev);
315 }
316 
317 // Window
318 Bool
apc_window_create(Handle self,Handle owner,Bool syncPaint,int borderIcons,int borderStyle,Bool taskList,int windowState,int on_top,Bool usePos,Bool useSize,Bool layered)319 apc_window_create( Handle self, Handle owner, Bool syncPaint, int borderIcons,
320 						int borderStyle, Bool taskList, int windowState,
321 						int on_top, Bool usePos, Bool useSize, Bool layered)
322 {
323 	Bool reset = false;
324 	ViewProfile vprf;
325 	int oStage = var stage;
326 	WCHAR * saved_caption = NULL;
327 	WindowData ws;
328 	HICON icon = (HICON) NULL_HANDLE;
329 	WINDOWPLACEMENT wp = {sizeof(WINDOWPLACEMENT)};
330 	DWORD style = WS_CLIPCHILDREN | WS_OVERLAPPED
331 		| (( borderIcons &  biSystemMenu) ? WS_SYSMENU     : 0)
332 		| (( borderIcons &  biMinimize)   ? WS_MINIMIZEBOX : 0)
333 		| (( borderIcons &  biMaximize)   ? WS_MAXIMIZEBOX : 0)
334 		| (( borderIcons &  biTitleBar)   ? 0              : WS_POPUP)
335 		| (( borderStyle == bsSizeable)   ? WS_THICKFRAME  : 0)
336 		| (( borderStyle == bsSingle  )   ? WS_BORDER      : 0)
337 		| (( borderStyle == bsDialog  )   ? WS_BORDER      : 0)
338 		| (( windowState == wsMinimized)  ? WS_MINIMIZE    : 0)
339 		| (( windowState == wsMaximized)  ? WS_MAXIMIZE    : 0)
340 	;
341 	DWORD exstyle = 0
342 		| (( borderStyle == bsDialog  )   ? WS_EX_DLGMODALFRAME : 0)
343 	;
344 
345 	objCheck false;
346 	dobjCheck( owner) false;
347 	if ( guts. displayBMInfo. bmiHeader. biBitCount <= 8) layered = false;
348 
349 	if ( !kind_of( self, CWidget)) apcErrRet( errInvObject);
350 	apcErrClear;
351 	if (( var handle != NULL_HANDLE) && (
352 			( DHANDLE( owner) != sys owner)
353 		|| ( borderStyle != sys s. window. borderStyle)
354 		|| ( borderIcons != sys s. window. borderIcons)
355 		|| ( taskList    != is_apt( aptTaskList))
356 		|| ( layered     != is_apt( aptLayered))
357 	))
358 	{
359 		int len = GetWindowTextLengthW( HANDLE ) + 1;
360 		if (( saved_caption = (WCHAR*) malloc( sizeof(WCHAR) * len)) != NULL )
361 			GetWindowTextW( HANDLE, saved_caption, len );
362 		// Windows 8 shell is observed to send WM_SIZE(0,0) on ShowWindow(SW_SHOWNORMAL)
363 		// when application started with /min flag
364 		apt_set( aptIgnoreSizeMessages );
365 		apc_window_set_window_state( self, windowState);
366 		apt_clear( aptIgnoreSizeMessages );
367 		// prevent cmSize/cmWindowStage message loss if recreate goes with WS_XXX change.
368 		if ( sys recreateData) {
369 			memcpy( &vprf, sys recreateData, sizeof( vprf));
370 			free( sys recreateData);
371 			sys recreateData = NULL;
372 		} else
373 			get_view_ex( self, &vprf);
374 		ws = sys s. window;
375 		if ( !GetWindowPlacement( HANDLE, &wp)) apiErr;
376 		if ( wp. showCmd == SW_SHOWMINIMIZED && windowState != wsMinimized )
377 			wp. showCmd = ( windowState == wsMaximized ) ? SW_SHOWMAXIMIZED : SW_NORMAL;
378 		usePos = useSize = 1; // prevent using shell-position flags for recreate
379 		icon = ( HICON) SendMessage( HANDLE, WM_GETICON, ICON_BIG, 0);
380 		reset = true;
381 	}
382 	HWND_lock( true);
383 
384 	if ( !reset) apt_set( aptClipByChildren );
385 	apt_assign( aptLayeredRequested, layered );
386 	apt_assign( aptLayered, layered );
387 
388 	if ( reset || ( var handle == NULL_HANDLE))
389 		if ( !create_group( self, owner, syncPaint, false,
390 				taskList, WC_FRAME, style, exstyle, usePos, useSize, &vprf, NULL)) {
391 			if ( on_top >= 0) {
392 				apt_assign( aptOnTop, on_top);
393 				if ( on_top > 0)
394 					SetWindowPos( sys handle, HWND_TOPMOST, 0, 0, 0, 0,
395 						SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
396 			}
397 			HWND_lock( false);
398 			if ( saved_caption ) free( saved_caption );
399 			return false;
400 		}
401 	ws. borderStyle = sys s. window. borderStyle = borderStyle;
402 	ws. borderIcons = sys s. window. borderIcons = borderIcons;
403 	ws. state       = sys s. window. state       = windowState;
404 	apt_assign( aptSyncPaint, syncPaint);
405 	apt_assign( aptTaskList,  taskList);
406 	if ( usePos) apt_set( aptWinPosDetermined);
407 	if ( reset)
408 	{
409 		Handle oldOwner = var owner;
410 
411 		var owner = owner;
412 		apc_window_set_window_state( self, windowState);
413 		var owner = oldOwner;
414 		set_view_ex( self, &vprf);
415 		sys s. window = ws;
416 		if ( windowState != wsMaximized)
417 			GetWindowRect( HANDLE, &wp. rcNormalPosition);
418 		if ( !SetWindowPlacement( HANDLE, &wp)) apiErr;
419 		var stage = oStage;
420 		if ( icon) SendMessage( HANDLE, WM_SETICON, ICON_BIG, ( LPARAM) icon);
421 	}
422 	else {
423 		guts. topWindows++;
424 	}
425 	if ( on_top >= 0) {
426 		apt_assign( aptOnTop, on_top);
427 		if ( on_top > 0)
428 			SetWindowPos( sys handle, HWND_TOPMOST, 0, 0, 0, 0,
429 				SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
430 	}
431 	SetWindowTextW( HANDLE, saved_caption );
432 	if ( saved_caption ) free( saved_caption );
433 	HWND_lock( false);
434 	if ( reset ) {
435 		notify_sys_handle( self );
436 		if ( layered ) hwnd_repaint_layered(self, false);
437 	}
438 	return apcError == 0;
439 }
440 
441 Bool
apc_window_activate(Handle self)442 apc_window_activate( Handle self)
443 {
444 	if ( self) {
445 		HWND w;
446 		objCheck false;
447 		w = HANDLE;
448 		SetForegroundWindow( w);
449 		SetActiveWindow( w);
450 		return true;
451 	}
452 	return false;
453 }
454 
455 Bool
apc_window_is_active(Handle self)456 apc_window_is_active( Handle self)
457 {
458 	return apc_window_get_active() == self;
459 }
460 
461 Handle
apc_window_get_active(void)462 apc_window_get_active( void)
463 {
464 	Handle self = hwnd_to_view( GetActiveWindow());
465 	if ( !self)
466 		return NULL_HANDLE;
467 	if ( sys className == WC_FRAME)
468 		return self;
469 	else if ( !is_apt( aptClipOwner)) {
470 		return hwnd_top_level( self);
471 	} else
472 		return NULL_HANDLE;
473 }
474 
475 Bool
apc_window_close(Handle self)476 apc_window_close( Handle self)
477 {
478 	objCheck true;
479 	if ( !PostMessage( HANDLE, WM_CLOSE, 0, 0)) apiErrRet;
480 	return true;
481 }
482 
483 int
apc_window_get_border_icons(Handle self)484 apc_window_get_border_icons( Handle self)
485 {
486 	objCheck 0;
487 	return sys s. window. borderIcons;
488 }
489 
490 int
apc_window_get_border_style(Handle self)491 apc_window_get_border_style( Handle self)
492 {
493 	objCheck 0;
494 	return sys s. window. borderStyle;
495 }
496 
497 ApiHandle
apc_window_get_client_handle(Handle self)498 apc_window_get_client_handle( Handle self)
499 {
500 	objCheck 0;
501 	return ( ApiHandle) var handle;
502 }
503 
504 Point
apc_window_get_client_pos(Handle self)505 apc_window_get_client_pos( Handle self)
506 {
507 	Point delta = get_window_borders( sys s. window. borderStyle);
508 	Handle parent = var self-> get_parent( self);
509 	Point p = {0,0}, sz   = CWidget( parent)-> get_size( parent);
510 	RECT  r;
511 
512 	objCheck p;
513 	if ( apc_window_get_window_state( self) == wsMinimized) {
514 		WINDOWPLACEMENT w = { sizeof( WINDOWPLACEMENT)};
515 		if ( !GetWindowPlacement( HANDLE, &w)) apiErr;
516 		p. x = w. rcNormalPosition. left + delta. x;
517 		p. y = sz. y - w. rcNormalPosition. bottom + delta. y;
518 	} else {
519 		GetWindowRect( HANDLE, &r);
520 		p. x = r. left + delta. x;
521 		p. y = sz. y - r. bottom + delta. y;
522 	}
523 	return p;
524 }
525 
526 Point
apc_window_get_client_size(Handle self)527 apc_window_get_client_size( Handle self)
528 {
529 	RECT r;
530 	Point p = { 0,0};
531 	objCheck p;
532 	if ( apc_window_get_window_state( self) == wsMinimized) {
533 		// cannot acquire client extension at this time. Using euristic calculations.
534 		WINDOWPLACEMENT w = {sizeof(WINDOWPLACEMENT)};
535 		Point delta = get_window_borders( sys s. window. borderStyle);
536 		int   menuY  = (( PWindow) self)-> menu ? GetSystemMetrics( SM_CYMENU) : 0;
537 		int   titleY = ( sys s. window. borderIcons & biTitleBar) ?
538 							GetSystemMetrics( SM_CYCAPTION) : 0;
539 		if ( !GetWindowPlacement( HANDLE, &w)) apiErr;
540 		p. x = w. rcNormalPosition. right  - w. rcNormalPosition. left - delta. x * 2;
541 		p. y = w. rcNormalPosition. bottom - w. rcNormalPosition. top  - delta. y * 2
542 			- menuY - titleY;
543 	} else {
544 		GetWindowRect(( HWND) var handle, &r);
545 		p. x = r. right - r. left;
546 		p. y = r. bottom - r. top;
547 	}
548 	return p;
549 }
550 
551 Bool
apc_window_get_icon(Handle self,Handle icon)552 apc_window_get_icon( Handle self, Handle icon)
553 {
554 	HICON    p;
555 	HCURSOR  save;
556 	Bool ret;
557 
558 	objCheck false;
559 	p = ( HICON) SendMessage( HANDLE, WM_GETICON, ICON_BIG, 0);
560 	if ( icon == NULL_HANDLE) return p != NULL;
561 
562 	save = sys pointer;
563 	sys pointer = p;
564 	ret = apc_pointer_get_bitmap( self, icon);
565 	sys pointer = save;
566 	return ret;
567 }
568 
569 int
apc_window_get_window_state(Handle self)570 apc_window_get_window_state( Handle self)
571 {
572 	WINDOWPLACEMENT s = {sizeof( WINDOWPLACEMENT)};
573 	objCheck wsNormal;
574 	if ( !GetWindowPlacement( HANDLE, &s)) apiErr;
575 	if ( s. showCmd == SW_SHOWMAXIMIZED) return wsMaximized;
576 	if ( s. showCmd == SW_SHOWMINIMIZED) return wsMinimized;
577 	return wsNormal;
578 }
579 
580 Bool
apc_window_get_task_listed(Handle self)581 apc_window_get_task_listed( Handle self)
582 {
583 	objCheck false;
584 	return is_apt( aptTaskList);
585 }
586 
587 Bool
apc_window_get_on_top(Handle self)588 apc_window_get_on_top( Handle self)
589 {
590 	objCheck false;
591 	return is_apt( aptOnTop);
592 }
593 
594 Bool
apc_window_set_caption(Handle self,const char * caption,Bool utf8)595 apc_window_set_caption( Handle self, const char * caption, Bool utf8)
596 {
597 	objCheck false;
598 	if ( utf8) {
599 		WCHAR * c = alloc_utf8_to_wchar( caption, -1, NULL);
600 		if ( !( rc = SetWindowTextW( HANDLE, c))) apiErr;
601 		free( c);
602 	} else {
603 		if ( !( rc = SetWindowTextA( HANDLE, caption))) apiErr;
604 	}
605 	return rc == 0;
606 }
607 
608 Bool
apc_window_set_client_pos(Handle self,int x,int y)609 apc_window_set_client_pos( Handle self, int x, int y)
610 {
611 	Point delta = get_window_borders( sys s. window. borderStyle);
612 	RECT  r;
613 	Handle parent = var self-> get_parent( self);
614 	Point sz = CWidget( parent)-> get_size( parent);
615 
616 	objCheck false;
617 	if ( !hwnd_check_limits( x, y, true)) apcErrRet( errInvParams);
618 	apt_set( aptWinPosDetermined);
619 
620 	if ( var stage == csConstructing && apc_window_get_window_state( self) != wsNormal) {
621 		WINDOWPLACEMENT w = {sizeof(WINDOWPLACEMENT)};
622 		if ( !GetWindowPlacement( HANDLE, &w)) apiErr;
623 		w. rcNormalPosition. top    += sz. y - y + delta. y - w. rcNormalPosition. bottom;
624 		w. rcNormalPosition. bottom  = sz. y - y + delta. y;
625 		w. rcNormalPosition. right  += x - delta. x - w. rcNormalPosition. left;
626 		w. rcNormalPosition. left    = x - delta. x;
627 		w. flags   = 0;
628 		if ( !SetWindowPlacement( HANDLE, &w)) apiErr;
629 	} else {
630 		if ( !GetWindowRect( HANDLE, &r)) apiErr;
631 		x -= delta. x;
632 		y  = sz. y - ( r. bottom - r. top) - y + delta. y;
633 		SetWindowPos( HANDLE, 0, x, y, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
634 	}
635 	return true;
636 }
637 
638 Bool
apc_window_set_client_size(Handle self,int x,int y)639 apc_window_set_client_size( Handle self, int x, int y)
640 {
641 	RECT r, c, c2;
642 	HWND h;
643 	int  ws = apc_window_get_window_state( self);
644 
645 	objCheck false;
646 	if ( !hwnd_check_limits( x, y, false)) apcErrRet( errInvParams);
647 
648 	h = HANDLE;
649 	if (( var stage == csConstructing && ws != wsNormal) || ws == wsMinimized) {
650 		WINDOWPLACEMENT w = {sizeof(WINDOWPLACEMENT)};
651 		Point delta = get_window_borders( sys s. window. borderStyle);
652 
653 		var virtualSize. x = x;
654 		var virtualSize. y = y;
655 		if ( x < 0) x = 0;
656 		if ( y < 0) y = 0;
657 		if ( !GetWindowPlacement( h, &w)) apiErr;
658 		if ( !GetWindowRect( h, &c2)) apiErr;
659 		if ( ws == wsMaximized) {
660 			if ( !GetClientRect( h, &c)) apiErr;
661 		}
662 		else {
663 			// cannot acquire client extension at this time. Using euristic calculations.
664 			int  menuY = (( PWindow) self)-> menu ? GetSystemMetrics( SM_CYMENU) : 0;
665 			int   titleY = ( sys s. window. borderIcons & biTitleBar) ?
666 								GetSystemMetrics( SM_CYCAPTION) : 0;
667 			c = c2;
668 			c. right  -= delta. x * 2;
669 			c. bottom -= delta. y * 2 + menuY + titleY;
670 		}
671 		w. rcNormalPosition. top    = w. rcNormalPosition. bottom - y - ( c2. bottom - c2. top - c. bottom + c. top);
672 		w. rcNormalPosition. right  = x + ( c2. right - c2. left - c. right + c. left) + w. rcNormalPosition. left;
673 		w. flags   = 0;
674 		if ( !SetWindowPlacement( h, &w)) apiErr;
675 	} else {
676 		if ( !GetWindowRect( h, &r)) apiErr;
677 		if ( !GetClientRect( h, &c)) apiErr;
678 		sys sizeLockLevel++;
679 		var virtualSize. x = x;
680 		var virtualSize. y = y;
681 		if ( x < 0) x = 0;
682 		if ( y < 0) y = 0;
683 		SetWindowPos( h, 0,
684 			r. left,
685 			r. top - y + ( c. bottom - c. top),
686 			x + r. right  - r. left - c. right + c. left,
687 			y + r. bottom - r. top  - c. bottom + c. top,
688 			SWP_NOZORDER | SWP_NOACTIVATE |
689 				( is_apt( aptWinPosDetermined) ? 0 : SWP_NOMOVE)
690 			);
691 		sys sizeLockLevel--;
692 	}
693 	return true;
694 }
695 
696 Bool
apc_window_set_client_rect(Handle self,int x,int y,int width,int height)697 apc_window_set_client_rect( Handle self, int x, int y, int width, int height)
698 {
699 	RECT r, c, c2;
700 	HWND h;
701 	int  ws = apc_window_get_window_state( self);
702 	Point delta = get_window_borders( sys s. window. borderStyle);
703 	Handle parent = var self-> get_parent( self);
704 	Point sz = CWidget( parent)-> get_size( parent);
705 
706 	objCheck false;
707 	if ( !hwnd_check_limits( x, y, false)) apcErrRet( errInvParams);
708 	if ( !hwnd_check_limits( width, height, false)) apcErrRet( errInvParams);
709 	apt_set( aptWinPosDetermined);
710 
711 	h = HANDLE;
712 	if (( var stage == csConstructing && ws != wsNormal) || ws == wsMinimized) {
713 		WINDOWPLACEMENT w = {sizeof(WINDOWPLACEMENT)};
714 		Point delta = get_window_borders( sys s. window. borderStyle);
715 
716 		var virtualSize. x = width;
717 		var virtualSize. y = height;
718 		if ( width < 0) width = 0;
719 		if ( height < 0) height = 0;
720 		if ( !GetWindowPlacement( h, &w)) apiErr;
721 		if ( !GetWindowRect( h, &c2)) apiErr;
722 		if ( ws == wsMaximized) {
723 			if ( !GetClientRect( h, &c)) apiErr;
724 		}
725 		else {
726 			// cannot acquire client extension at this time. Using euristic calculations.
727 			int  menuY = (( PWindow) self)-> menu ? GetSystemMetrics( SM_CYMENU) : 0;
728 			int   titleY = ( sys s. window. borderIcons & biTitleBar) ?
729 								GetSystemMetrics( SM_CYCAPTION) : 0;
730 			c = c2;
731 			c. right  -= delta. x * 2;
732 			c. bottom -= delta. y * 2 + menuY + titleY;
733 		}
734 		w. rcNormalPosition. bottom = sz. y - y + delta. y;
735 		w. rcNormalPosition. left   = x - delta. x;
736 		w. rcNormalPosition. top    = w. rcNormalPosition. bottom - height - ( c2. bottom - c2. top - c. bottom + c. top);
737 		w. rcNormalPosition. right  = width + ( c2. right - c2. left - c. right + c. left) + w. rcNormalPosition. left;
738 		w. flags   = 0;
739 		if ( !SetWindowPlacement( h, &w)) apiErr;
740 	} else {
741 		if ( !GetWindowRect( h, &r)) apiErr;
742 		if ( !GetClientRect( h, &c)) apiErr;
743 		sys sizeLockLevel++;
744 		x -= delta. x;
745 		y  = sz. y - y - height - ( r. bottom - r. top  - c. bottom + c. top) + delta. y;
746 		var virtualSize. x = width;
747 		var virtualSize. y = height;
748 		if ( width < 0) width = 0;
749 		if ( height < 0) height = 0;
750 		SetWindowPos( h, 0,
751 			x, y,
752 			width + r. right  - r. left - c. right + c. left,
753 			height + r. bottom - r. top  - c. bottom + c. top,
754 			SWP_NOZORDER | SWP_NOACTIVATE);
755 		sys sizeLockLevel--;
756 	}
757 	return true;
758 }
759 
760 Bool
apc_window_set_menu(Handle self,Handle menu)761 apc_window_set_menu( Handle self, Handle menu)
762 {
763 	Point size;
764 	objCheck false;
765 	apcErrClear;
766 	size = var self-> get_size( self);
767 	SetMenu( HANDLE, menu ? ( HMENU) (( PComponent) menu)-> handle : NULL);
768 	DrawMenuBar( HANDLE);
769 	if ( apc_window_get_window_state( self) == wsNormal)
770 		var self-> set_size( self, size);
771 	return apcError == 0;
772 }
773 
774 Bool
apc_window_set_effects(Handle self,HV * effects)775 apc_window_set_effects( Handle self, HV * effects )
776 {
777 	return false;
778 }
779 
780 Bool
apc_window_set_icon(Handle self,Handle icon)781 apc_window_set_icon( Handle self, Handle icon)
782 {
783 	HICON i;
784 	objCheck false;
785 	i = icon ? image_make_icon_handle( icon, guts. iconSizeLarge, NULL) : NULL;
786 	i = ( HICON) SendMessage( HANDLE, WM_SETICON, ICON_BIG, ( LPARAM) i);
787 	if ( i) DestroyIcon( i);
788 	return true;
789 }
790 
791 Bool
apc_window_set_window_state(Handle self,int state)792 apc_window_set_window_state( Handle self, int state)
793 {
794 	int  fl = -1;
795 	objCheck false;
796 	switch ( state)
797 	{
798 		case wsMaximized: fl = SW_SHOWMAXIMIZED; break;
799 		case wsMinimized: fl = SW_MINIMIZE; break;
800 		case wsNormal   : fl = SW_SHOWNORMAL; break;
801 	}
802 	if ( fl > 0)
803 	{
804 		ShowWindow( HANDLE, fl);
805 		sys s. window. state = state;
806 	}
807 	return true;
808 }
809 
810 static Bool
window_start_modal(Handle self,Bool shared,Handle insertBefore)811 window_start_modal( Handle self, Bool shared, Handle insertBefore)
812 {
813 	HWND wnd;
814 	HWND active = GetActiveWindow();
815 
816 	objCheck false;
817 	wnd = HANDLE;
818 	if ( sys className != WC_FRAME) { apcErr( errInvParams); return false; }
819 
820 	sys s. window. oldFoc = apc_widget_get_focused();
821 	if ( sys s. window. oldFoc) protect_object( sys s. window. oldFoc);
822 	sys s. window. oldActive = active;
823 
824 	// setting window up
825 	guts. focSysDisabled = 1;
826 	CWindow( self)-> exec_enter_proc( self, shared, insertBefore);
827 	apc_widget_set_enabled( self, 1);
828 	SetWindowPos( wnd, 0, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|SWP_SHOWWINDOW);
829 	if ( sys s. window. state == wsMinimized)
830 		ShowWindow( wnd, SW_RESTORE);
831 	if ( !insertBefore) {
832 		SetActiveWindow( wnd);
833 		SetForegroundWindow( wnd);
834 	} else {
835 		HWND zorder;
836 		dobjCheck( insertBefore) false;
837 		zorder = GetWindow( DHANDLE( insertBefore), GW_HWNDNEXT);
838 		if ( !zorder) zorder = HWND_BOTTOM;
839 		SetWindowPos( wnd, zorder, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
840 		if ( active)
841 			SetActiveWindow( active);
842 	}
843 	objCheck false;
844 	PostMessage( wnd, WM_DLGENTERMODAL, 1, 0);
845 	guts. focSysDisabled = 0;
846 	return true;
847 }
848 
849 Bool
apc_window_execute(Handle self,Handle insertBefore)850 apc_window_execute( Handle self, Handle insertBefore)
851 {
852 	objCheck false;
853 	if ( !window_start_modal( self, false, insertBefore))
854 		return false;
855 	// message loop
856 	{
857 		MSG msg;
858 		while ( GetMessage( &msg, NULL, 0, 0)) {
859 			if ( !process_msg( &msg)) {
860 				if ( !appDead)
861 					PostThreadMessage( guts. mainThreadId, WM_TERMINATE, 0, 0);
862 				break;
863 			}
864 			if ( self && !(( PWindow) self)-> modal)
865 				break;
866 		}
867 	}
868 	// !!note - at this point object may be unaccessible (except var area only).
869 	return true;
870 }
871 
872 Bool
apc_window_execute_shared(Handle self,Handle insertBefore)873 apc_window_execute_shared( Handle self, Handle insertBefore)
874 {
875 	objCheck false;
876 	return window_start_modal( self, true, insertBefore);
877 }
878 
879 Bool
apc_window_end_modal(Handle self)880 apc_window_end_modal( Handle self)
881 {
882 	HWND wnd;
883 	objCheck false;
884 	wnd = HANDLE;
885 	guts. focSysDisabled = 1;
886 	CWindow( self)-> exec_leave_proc( self);
887 	WinHideWindow( wnd);
888 	objCheck false;
889 	apc_widget_set_enabled( self, 0);
890 	objCheck false;
891 	if ( application) {
892 		Handle who = Application_popup_modal( application);
893 		if ( sys s. window. oldActive)
894 			SetActiveWindow( sys s. window. oldActive);
895 		if ( !who && var owner)
896 			CWidget( var owner)-> set_selected( var owner, 1);
897 		if (( who = sys s. window. oldFoc)) {
898 			if ( PWidget( who)-> stage == csNormal)
899 				CWidget( who)-> set_focused( who, 1);
900 			unprotect_object( who);
901 		}
902 	}
903 	guts. focSysDisabled = 0;
904 	return true;
905 }
906 
907 // View management
908 Bool
apc_widget_map_points(Handle self,Bool toScreen,int count,Point * p)909 apc_widget_map_points( Handle self, Bool toScreen, int count, Point * p)
910 {
911 	int i;
912 	Point sz = ((( PWidget) self)-> self)-> get_size( self);
913 	Point appSz = apc_application_get_size( application);
914 
915 	if ( self == application)
916 		return true;
917 
918 	objCheck false;
919 
920 	if ( toScreen) {
921 		for ( i = 0; i < count; i++)
922 			p[i]. y = sz. y - p[i]. y;
923 		MapWindowPoints(( HWND) var handle, NULL, ( POINT * ) p, count);
924 		for ( i = 0; i < count; i++)
925 			p[i]. y = appSz. y - p[i].y;
926 	} else {
927 		for ( i = 0; i < count; i++)
928 			p[i]. y = appSz. y - p[i]. y;
929 		MapWindowPoints( NULL, ( HWND) var handle, ( POINT * ) p, count);
930 		for ( i = 0; i < count; i++)
931 			p[i]. y = sz. y - p[i]. y;
932 	}
933 	return true;
934 }
935 
936 Color
apc_widget_map_color(Handle self,Color color)937 apc_widget_map_color( Handle self, Color color)
938 {
939 	if ((( color & clSysFlag) != 0) && (( color & wcMask) == 0)) color |= var widgetClass;
940 	return remap_color( remap_color( color, true), false);
941 }
942 
943 Bool
apc_widget_create(Handle self,Handle owner,Bool syncPaint,Bool clipOwner,Bool transparent,ApiHandle parentHandle,Bool layered)944 apc_widget_create( Handle self, Handle owner, Bool syncPaint, Bool clipOwner,
945 						Bool transparent, ApiHandle parentHandle, Bool layered)
946 {
947 	Bool reset = false, redraw = false;
948 	ViewProfile vprf;
949 	int oStage = var stage;
950 	int exstyle;
951 
952 	objCheck false;
953 	dobjCheck( owner) false;
954 
955 	if ( !kind_of( self, CWidget)) apcErr( errInvObject);
956 	apcErrClear;
957 
958 	if ( parentHandle && !IsWindow(( HWND) parentHandle))
959 		return false;
960 
961 	exstyle = 0;
962 	if ( guts. displayBMInfo. bmiHeader. biBitCount <= 8) layered = false;
963 
964 	redraw = is_apt( aptLayeredRequested ) != layered;
965 	apt_assign( aptLayeredRequested, layered );
966 	apt_clear( aptLayered );
967 	if ( layered && (( owner == application || !clipOwner ))) {
968 		apt_set( aptLayered );
969 		exstyle |= WS_EX_LAYERED;
970 	}
971 
972 	if (( var handle != NULL_HANDLE) &&
973 			(( DHANDLE( owner) != sys owner)                 ||
974 			(( HWND) parentHandle != sys parentHandle)       ||
975 			( clipOwner       != is_apt( aptClipOwner))
976 		))
977 	{
978 		if ( sys recreateData) {
979 			memcpy( &vprf, sys recreateData, sizeof( vprf));
980 			free( sys recreateData);
981 			sys recreateData = NULL;
982 		} else
983 			get_view_ex( self, &vprf);
984 		reset = true;
985 	}
986 	if ( !reset) apt_set( aptClipByChildren );
987 	if ( reset || ( var handle == NULL_HANDLE))
988 		create_group( self, owner, syncPaint, clipOwner, 0, WC_CUSTOM,
989 			WS_CHILD, exstyle, 1, 1, &vprf, ( HWND) parentHandle);
990 	apt_set( aptWinPosDetermined);
991 	if ( reset)
992 	{
993 		Handle oldOwner = var owner; var owner = owner;
994 		set_view_ex( self, &vprf);
995 		var owner = oldOwner;
996 		var stage = oStage;
997 	}
998 	if ( is_apt( aptTransparent) != transparent && !reset)
999 		redraw = true;
1000 	if ( redraw) apc_widget_redraw( self);
1001 	apt_assign( aptTransparent, transparent);
1002 	if ( reset) {
1003 		notify_sys_handle( self );
1004 		apc_widget_redraw( self);
1005 	}
1006 	return apcError == 0;
1007 }
1008 
1009 Bool
apc_widget_begin_paint(Handle self,Bool insideOnPaint)1010 apc_widget_begin_paint( Handle self, Bool insideOnPaint)
1011 {
1012 	Bool useRPDraw = false;
1013 	objCheck false;
1014 	apcErrClear;
1015 
1016 	if ( is_apt( aptLayeredPaint )) {
1017 		sys transform2 = sys layeredPaintOffset;
1018 	} else if ( is_apt( aptTransparent)) {
1019 		if ( IsWindowVisible(( HWND) var handle)) {
1020 			HWND parent = GetParent( HANDLE);
1021 			if ( !parent) {
1022 				MSG  msg;
1023 				list_add( &guts. transp, self);
1024 				WinHideWindow(( HWND) var handle);
1025 				if ( parent) apcUpdateWindow( parent);
1026 				while ( PeekMessage( &msg, NULL, WM_PAINT, WM_PAINT, PM_REMOVE)) {
1027 					DispatchMessage(&msg);
1028 					exception_check_raise();
1029 				}
1030 				if ( !parent) Sleep( 1);
1031 				WinShowWindow(( HWND) var handle);
1032 				apcUpdateWindow(( HWND) var handle);
1033 				list_delete( &guts. transp, self);
1034 			} else
1035 				useRPDraw = true;
1036 		}
1037 		sys transform2. x = 0;
1038 		sys transform2. y = 0;
1039 	} else {
1040 		sys transform2. x = 0;
1041 		sys transform2. y = 0;
1042 	}
1043 
1044 	apt_set( aptWinPS);
1045 	apt_set( aptCompatiblePS);
1046 	apt_assign( aptWM_PAINT, insideOnPaint);
1047 
1048 	if ( is_apt( aptLayeredPaint )) {
1049 		sys ps = sys layeredPaintSurface;
1050 	} else if ( is_apt( aptLayered )) {
1051 		RECT r;
1052 
1053 		insideOnPaint = false;
1054 		GetWindowRect( HANDLE, &r);
1055 		sys ps2     = GetDC(NULL);
1056 		sys ps      = CreateCompatibleDC(sys ps2);
1057 		sys bm      = CreateCompatibleBitmap(sys ps2, r. right - r. left, r. bottom - r. top);
1058 		sys stockBM = SelectObject(sys ps, sys bm);
1059 	} else if ( insideOnPaint) {
1060 		if ( !( sys ps = BeginPaint(( HWND) var handle, &sys paintStruc))) apiErrRet;
1061 	} else {
1062 		if ( !( sys ps = GetDC(( HWND) var handle))) apiErrRet;
1063 	}
1064 
1065 	if ( !is_apt(aptLayeredPaint) && is_opt( optBuffered) && insideOnPaint) {
1066 		RECT r;
1067 		HBITMAP bm;
1068 		HDC dc;
1069 
1070 		GetClipBox( sys ps, &r);
1071 		var w = r. right  - r. left;
1072 		var h = r. bottom - r. top;
1073 
1074 		if ( var w == 0 || var h == 0) {
1075 			if ( !EndPaint(( HWND) var handle, &sys paintStruc)) apiErr;
1076 			apt_clear( aptWinPS);
1077 			apt_clear( aptWM_PAINT);
1078 			apt_clear( aptCompatiblePS);
1079 			sys ps = NULL;
1080 			return false;
1081 		}
1082 
1083 		if ( !( dc = CreateCompatibleDC( sys ps))) apiErr;
1084 
1085 		if ( sys pal) {
1086 			sys stockPalette = SelectPalette( dc, sys pal, 1);
1087 			RealizePalette( dc);
1088 			sys pal2 = SelectPalette( sys ps, sys pal, 1);
1089 			RealizePalette( sys ps);
1090 		}
1091 
1092 		if ( guts. displayBMInfo. bmiHeader. biBitCount == 8)
1093 			apt_clear( aptCompatiblePS);
1094 
1095 		bm = CreateCompatibleBitmap( sys ps, var w, var h);
1096 
1097 		if ( bm) {
1098 			sys ps2 = sys ps;
1099 			sys ps  = dc;
1100 			sys stockBM = SelectObject( dc, bm);
1101 			sys bm = bm;
1102 			SetBrushOrgEx( dc, -r. left, -r. top, NULL);
1103 			apc_gp_set_transform( self, -r. left, -r. top);
1104 			sys transform2. x = r. left;
1105 			sys transform2. y = r. top;
1106 			apt_set( aptBitmap);
1107 		} else
1108 			apiErr;
1109 	} else if ( !is_apt(aptLayered) && !is_apt(aptLayeredPaint)) {
1110 		if ( sys pal) {
1111 			sys stockPalette = SelectPalette( sys ps, sys pal, 1);
1112 			RealizePalette( sys ps);
1113 		}
1114 	}
1115 
1116 	if ( useRPDraw) {
1117 		HDC dc;
1118 		Handle owner = var owner;
1119 		Point tr = dsys(owner)transform2;
1120 		Point ed = apc_widget_get_pos( self);
1121 		Point sz = apc_widget_get_size( self);
1122 		Point so = CWidget(owner)-> get_size( owner);
1123 		Bool flag;
1124 		int saved_dc_state;
1125 		POINT brushorg;
1126 		FLOAT miter;
1127 
1128 		CWidget( owner)-> begin_paint( owner);
1129 		dc = dsys( owner) ps;
1130 		dsys( owner) ps = sys ps;
1131 		dsys(owner) transform2. x += ed. x;
1132 		dsys(owner) transform2. y += so. y - sz. y - ed. y;
1133 		apc_gp_set_transform( owner, 0, 0);
1134 		apc_gp_set_text_out_baseline( owner, dsys(owner) options. aptTextOutBaseline);
1135 
1136 		saved_dc_state = SaveDC( sys ps );
1137 		SelectObject( sys ps, GetCurrentObject( dc, OBJ_PEN));
1138 		SelectObject( sys ps, GetCurrentObject( dc, OBJ_BRUSH));
1139 		SelectObject( sys ps, GetCurrentObject( dc, OBJ_FONT));
1140 		SelectObject( sys ps, GetCurrentObject( dc, OBJ_PAL));
1141 		SelectObject( sys ps, GetCurrentObject( dc, OBJ_EXTPEN));
1142 		SetTextAlign( sys ps, GetTextAlign( dc ));
1143 		GetBrushOrgEx( dc, &brushorg);
1144 		SetBrushOrgEx( sys ps, brushorg.x, brushorg.y, NULL);
1145 		GetMiterLimit( dc, &miter);
1146 		SetMiterLimit( sys ps, miter, NULL);
1147 		SetBkMode( sys ps, GetBkMode( dc ));
1148 		SetROP2( sys ps, GetROP2( dc ));
1149 		SetStretchBltMode( sys ps, GetStretchBltMode( dc ));
1150 
1151 		flag = exception_block(true);
1152 		CWidget( owner)-> notify( owner, "sH", "Paint", owner);
1153 		exception_block(flag);
1154 
1155 		RestoreDC( sys ps, saved_dc_state);
1156 
1157 		dsys(owner)transform2 = tr;
1158 		apc_gp_set_transform( owner, 0, 0);
1159 		dsys( owner) ps = dc;
1160 		CWidget( owner)-> end_paint( owner);
1161 	}
1162 
1163 	hwnd_enter_paint( self);
1164 
1165 	if ( useRPDraw) {
1166 		apc_gp_set_transform( self, sys transform. x, sys transform. y);
1167 	}
1168 
1169 	if ( is_apt(aptLayeredPaint)) {
1170 		Rect r;
1171 		r. left   = 0;
1172 		r. bottom = 0;
1173 		r. right  = sys lastSize. x - 1;
1174 		r. top    = sys lastSize. y - 1;
1175 		apc_gp_set_clip_rect(self, r);
1176 	}
1177 
1178 	return true;
1179 }
1180 
1181 Bool
apc_widget_begin_paint_info(Handle self)1182 apc_widget_begin_paint_info( Handle self)
1183 {
1184 	HRGN rgn;
1185 	objCheck false;
1186 	apt_set( aptWinPS);
1187 	apt_set( aptCompatiblePS);
1188 	sys transform2. x = 0;
1189 	sys transform2. y = 0;
1190 	if ( !( sys ps = GetDC(( HWND) var handle))) apiErrRet;
1191 	hwnd_enter_paint( self);
1192 	rgn = CreateRectRgn( 0, 0, 0, 0);
1193 	SelectClipRgn( sys ps, rgn);
1194 	DeleteObject( rgn);
1195 	return true;
1196 }
1197 
1198 
1199 Bool
apc_widget_destroy(Handle self)1200 apc_widget_destroy( Handle self)
1201 {
1202 	objCheck false;
1203 	SetWindowLongPtr( HANDLE, GWLP_USERDATA, 0);
1204 	if ( sys pointer2) {
1205 		if ( sys pointer2 == sys pointer) SetCursor( NULL); // un-use resource first
1206 		if ( !DestroyCursor( sys pointer2)) apiErr;
1207 	}
1208 	if ( sys recreateData) free( sys recreateData);
1209 	if ( self == lastMouseOver) lastMouseOver = NULL_HANDLE;
1210 	if ( self == guts.dragTarget) guts.dragTarget = NULL_HANDLE;
1211 	if ( var handle == NULL_HANDLE) return true;
1212 
1213 	if ( sys className == WC_FRAME)
1214 		guts. topWindows--;
1215 
1216 	if ( !DestroyWindow( HANDLE)) apiErrRet;
1217 	return true;
1218 }
1219 
1220 PFont
apc_widget_default_font(PFont copyTo)1221 apc_widget_default_font( PFont copyTo)
1222 {
1223 	*copyTo = guts. windowFont;
1224 	copyTo-> pitch = fpDefault;
1225 	return copyTo;
1226 }
1227 
1228 static void
subpaint_layered_widgets(HWND self,HDC ps,HDC alpha_dc,POINT screen_offset,HRGN parent_shape)1229 subpaint_layered_widgets( HWND self, HDC ps, HDC alpha_dc, POINT screen_offset, HRGN parent_shape)
1230 {
1231 	HWND child = GetTopWindow( self );
1232 	if ( child ) child = GetWindow( child, GW_HWNDLAST );
1233 	while ( child != NULL ) {
1234 		Handle h;
1235 		RECT r;
1236 		HRGN shape;
1237 		Event ev;
1238 		POINT child_offset, size;
1239 
1240 		h = hwnd_to_view(child);
1241 		if ( h == NULL_HANDLE || !IsWindowVisible(child) || !dsys(h) options. aptClipOwner) {
1242 			child = GetWindow( child, GW_HWNDPREV);
1243 			continue;
1244 		}
1245 
1246 		GetWindowRect( child, &r);
1247 		r. left   -= screen_offset. x;
1248 		r. top    -= screen_offset. y;
1249 		r. right  -= screen_offset. x;
1250 		r. bottom -= screen_offset. y;
1251 		size. x = r.right  - r. left;
1252 		size. y = r.bottom - r. top;
1253 		child_offset. x = r. left;
1254 		child_offset. y = r. top;
1255 
1256 		dsys(h) options. aptLayeredPaint = 1;
1257 		dsys(h) layeredPaintOffset. x = -r. left;
1258 		dsys(h) layeredPaintOffset. y = -r. top;
1259 		dsys(h) layeredPaintSurface   = ps;
1260 
1261 		shape = CreateRectRgn(0,0,0,0);
1262 		if ( GetWindowRgn( child, shape)) {
1263 			HRGN rect = CreateRectRgn( 0, 0, size.x, size.y);
1264 			CombineRgn( shape, shape, rect, RGN_AND);
1265 			DeleteObject( rect );
1266 		} else {
1267 			DeleteObject( shape );
1268 			shape = CreateRectRgn( 0, 0, size.x, size.y);
1269 		}
1270 		OffsetRgn( shape, child_offset. x, child_offset. y);
1271 		if ( parent_shape ) CombineRgn( shape, shape, parent_shape, RGN_AND );
1272 		dsys(h) layeredParentRegion = shape;
1273 
1274 		ev. cmd = cmPaint;
1275 		CWidget(h)-> message( h, &ev);
1276 
1277 		if ( !dsys(h) options. aptLayeredRequested) {
1278 			/* assigning opaque alpha over the child rect so Windows passes mouse events in */
1279 			StretchBlt( ps, r.left, r.top, size.x, size.y, alpha_dc, 0, 0, 1, 1, SRCPAINT);
1280 		}
1281 		dsys(h) options. aptLayeredPaint = 0;
1282 
1283 		subpaint_layered_widgets( child, ps, alpha_dc, screen_offset, shape);
1284 
1285 		DeleteObject( shape );
1286 		child = GetWindow( child, GW_HWNDPREV);
1287 	}
1288 }
1289 
1290 Bool
apc_widget_end_paint(Handle self)1291 apc_widget_end_paint( Handle self)
1292 {
1293 	objCheck false;
1294 
1295 	hwnd_leave_paint( self);
1296 
1297 	if ( is_apt( aptLayeredPaint )) {
1298 		// do nothing
1299 	} else if ( is_apt( aptLayered )) {
1300 		RECT r;
1301 		SIZE size;
1302 		POINT src, pos, *ppos = NULL;
1303 		BLENDFUNCTION bf;
1304 		HBITMAP alpha_bm, stock_alpha_bm;
1305 		HDC alpha_dc;
1306 		uint32_t * alpha_pixels;
1307 
1308 		GetWindowRect((HWND) var handle, &r);
1309 		if ( r. right - r. left <= 0 || r. bottom - r. top <= 0)
1310 			goto SKIP_ALPHA;
1311 
1312 		alpha_dc = CreateCompatibleDC( sys ps );
1313 		alpha_bm = image_create_argb_dib_section( alpha_dc, 1, 1, &alpha_pixels);
1314 		stock_alpha_bm = SelectObject( alpha_dc, alpha_bm);
1315 		*alpha_pixels = 0xFF000000;
1316 
1317 		/* subpaint children */
1318 		src. x = r. left;
1319 		src. y = r. top;
1320 		subpaint_layered_widgets((HWND) var handle, sys ps, alpha_dc, src, NULL);
1321 
1322 		SelectObject( alpha_dc, stock_alpha_bm);
1323 		DeleteObject( alpha_bm );
1324 		DeleteDC( alpha_dc );
1325 
1326 		size. cx = r. right - r. left;
1327 		size. cy = r. bottom - r. top;
1328 		src. x = 0;
1329 		src. y = 0;
1330 		bf. AlphaFormat         = AC_SRC_ALPHA;
1331 		bf. SourceConstantAlpha = 255;
1332 		bf. BlendFlags          = 0;
1333 		bf. BlendOp             = AC_SRC_OVER;
1334 		if (is_apt(aptMovePending)) {
1335 			pos. x = sys layeredPos. x;
1336 			pos. y = sys layeredPos. y;
1337 			ppos = &pos;
1338 			apt_clear(aptMovePending);
1339 		}
1340 		if ( !UpdateLayeredWindow((HWND) var handle, NULL, ppos, &size, sys ps, &src, 0, &bf, ULW_ALPHA))
1341 			apiErr;
1342 	SKIP_ALPHA:
1343 		SelectObject(sys ps, sys stockBM);
1344 		DeleteObject(sys bm);
1345 		DeleteDC(sys ps);
1346 		ReleaseDC(( HWND) var handle, sys ps2);
1347 		sys ps = sys ps2 = NULL;
1348 		sys bm = sys stockBM = NULL;
1349 	} else if ( is_opt( optBuffered)) {
1350 		apt_clear( aptBitmap);
1351 		if ( sys bm != NULL) {
1352 			if ( !BitBlt( sys ps2, sys transform2. x, sys transform2. y, var w, var h, sys ps, 0, 0, SRCCOPY)) apiErr;
1353 			if ( sys stockBM)
1354 				SelectObject( sys ps, sys stockBM);
1355 			DeleteObject( sys bm);
1356 		}
1357 
1358 		if ( sys pal) {
1359 			SelectPalette( sys ps2, sys pal2, 1);
1360 			SelectPalette( sys ps, sys stockPalette, 1);
1361 			RealizePalette( sys ps2);
1362 			sys pal2 = NULL;
1363 		}
1364 
1365 		DeleteDC( sys ps);
1366 		sys ps = sys ps2;
1367 		sys bm = NULL;
1368 		sys ps2 = NULL;
1369 		sys stockBM = NULL;
1370 	}
1371 
1372 	if ( !is_apt(aptLayeredPaint) && sys ps != NULL) {
1373 		if ( is_apt( aptWinPS) && is_apt( aptWM_PAINT)) {
1374 			if ( !EndPaint(( HWND) var handle, &sys paintStruc)) apiErr;
1375 		} else if ( is_apt( aptWinPS))
1376 			if ( !ReleaseDC(( HWND) var handle, sys ps)) apiErr;
1377 	}
1378 	sys ps = NULL;
1379 	sys pal2 = NULL;
1380 	apt_clear( aptWinPS);
1381 	apt_clear( aptWM_PAINT);
1382 	apt_clear( aptCompatiblePS);
1383 	return true;
1384 }
1385 
1386 Bool
apc_widget_end_paint_info(Handle self)1387 apc_widget_end_paint_info( Handle self)
1388 {
1389 	Bool ok = true;
1390 	objCheck false;
1391 	hwnd_leave_paint( self);
1392 	if ( !( ok = ReleaseDC(( HWND) var handle, sys ps))) apiErr;
1393 	sys ps = NULL;
1394 	apt_clear( aptWinPS);
1395 	apt_clear( aptCompatiblePS);
1396 	return ok;
1397 }
1398 
1399 Bool
apc_widget_get_clip_by_children(Handle self)1400 apc_widget_get_clip_by_children( Handle self)
1401 {
1402 	objCheck false;
1403 	return is_apt(aptClipByChildren);
1404 }
1405 
1406 Bool
apc_widget_get_clip_owner(Handle self)1407 apc_widget_get_clip_owner( Handle self)
1408 {
1409 	objCheck false;
1410 	return is_apt( aptClipOwner);
1411 }
1412 
1413 Color
apc_widget_get_color(Handle self,int index)1414 apc_widget_get_color( Handle self, int index)
1415 {
1416 	objCheck clInvalid;
1417 	return sys viewColors[ index];
1418 }
1419 
1420 Bool
apc_widget_get_first_click(Handle self)1421 apc_widget_get_first_click( Handle self)
1422 {
1423 	objCheck false;
1424 	return is_apt( aptFirstClick);
1425 }
1426 
1427 Handle
apc_widget_get_focused()1428 apc_widget_get_focused()
1429 {
1430 	return hwnd_to_view( GetFocus());
1431 }
1432 
map_Rect(Handle self,Rect * rect)1433 static PRECT map_Rect( Handle self, Rect * rect)
1434 {
1435 	RECT  __rectangle;
1436 	objCheck ( PRECT) rect;
1437 	GetWindowRect(( HWND) var handle, &__rectangle);
1438 	if ( is_apt( aptClipOwner) && ( var owner != application))
1439 		MapWindowPoints( NULL, ( HWND)((( PWidget) var owner)-> handle), ( LPPOINT) &__rectangle, 2);
1440 	rect-> bottom = ( __rectangle. bottom - __rectangle. top) - rect-> bottom;
1441 	rect-> top    = ( __rectangle. bottom - __rectangle. top) - rect-> top;
1442 // that is due the difference in field placement between Rect and RECT structures
1443 	if ( rect-> bottom > rect-> top) {
1444 		LONG i = rect-> bottom;
1445 		rect-> bottom = rect-> top;
1446 		rect-> top    = i;
1447 	}
1448 	return ( PRECT) rect;
1449 }
1450 
map_RECT(Handle self,RECT * rect)1451 static Rect * map_RECT( Handle self, RECT * rect)
1452 {
1453 	RECT __rectangle;
1454 	objCheck ( Rect*)rect;
1455 	GetWindowRect(( HWND) var handle, &__rectangle);
1456 	if ( is_apt( aptClipOwner) && ( var owner != application))
1457 		MapWindowPoints( NULL, ( HWND)((( PWidget) var owner)-> handle), ( LPPOINT)&__rectangle, 2);
1458 	rect-> bottom = ( __rectangle. bottom - __rectangle. top) - rect-> bottom;
1459 	rect-> top    = ( __rectangle. bottom - __rectangle. top) - rect-> top;
1460 // that is due the difference in field placement between Rect and RECT structures
1461 	if ( rect-> bottom < rect-> top) {
1462 		LONG i = rect-> bottom;
1463 		rect-> bottom = rect-> top;
1464 		rect-> top    = i;
1465 	}
1466 	return ( Rect *) rect;
1467 }
1468 
1469 ApiHandle
apc_widget_get_handle(Handle self)1470 apc_widget_get_handle( Handle self)
1471 {
1472 	objCheck 0;
1473 	return ( ApiHandle) HANDLE;
1474 }
1475 
1476 ApiHandle
apc_widget_get_parent_handle(Handle self)1477 apc_widget_get_parent_handle( Handle self)
1478 {
1479 	objCheck 0;
1480 	return ( ApiHandle) sys parentHandle;
1481 }
1482 
1483 
1484 Rect
apc_widget_get_invalid_rect(Handle self)1485 apc_widget_get_invalid_rect( Handle self)
1486 {
1487 	Rect r  = {0,0,0,0};
1488 	objCheck r;
1489 	if ( GetUpdateRect(( HWND) var handle, ( PRECT) &r, false))
1490 		return *( map_RECT( self, ( PRECT) &r));
1491 	return r;
1492 }
1493 
1494 Bool
apc_widget_get_layered_request(Handle self)1495 apc_widget_get_layered_request( Handle self)
1496 {
1497 	return is_apt( aptLayeredRequested);
1498 }
1499 
1500 Bool
apc_widget_surface_is_layered(Handle self)1501 apc_widget_surface_is_layered( Handle self)
1502 {
1503 	Handle top;
1504 	objCheck false;
1505 
1506 	if ( is_apt( aptLayered)) return true;
1507 	top = hwnd_layered_top_level(self);
1508 	if ( top && dsys(top) options. aptLayered ) return true;
1509 	return false;
1510 }
1511 
1512 Point
apc_widget_get_pos(Handle self)1513 apc_widget_get_pos( Handle self)
1514 {
1515 	RECT  r;
1516 	Point p, sz = {0,0};
1517 	Handle parent;
1518 	objCheck sz;
1519 	parent = is_apt( aptClipOwner) ? var owner : application;
1520 	sz = ((( PWidget) parent)-> self)-> get_size( parent);
1521 	if ( sys className == WC_FRAME && apc_window_get_window_state( self) == wsMinimized) {
1522 		WINDOWPLACEMENT w = {sizeof(WINDOWPLACEMENT)};
1523 		if ( !GetWindowPlacement( HANDLE, &w)) apiErr;
1524 		p. x = w. rcNormalPosition. left;
1525 		p. y = sz. y - w. rcNormalPosition. bottom;
1526 	} else if ( is_apt( aptMovePending)) {
1527 		GetWindowRect( HANDLE, &r);
1528 		p. x = sys layeredPos. x;
1529 		p. y = sys layeredPos. y + r. bottom - r.top;
1530 	} else {
1531 		GetWindowRect( HANDLE, &r);
1532 		if ( is_apt( aptClipOwner) && ( var owner != application))
1533 			MapWindowPoints( NULL, ( HWND)((( PWidget) var owner)-> handle), ( LPPOINT)&r, 2);
1534 		p. x = r. left;
1535 		p. y = sz. y - r. bottom;
1536 	}
1537 	return p;
1538 }
1539 
1540 Point
apc_widget_get_size(Handle self)1541 apc_widget_get_size( Handle self)
1542 {
1543 	RECT r;
1544 	Point p = {0,0};
1545 	objCheck p;
1546 	if ( sys className == WC_FRAME && apc_window_get_window_state( self) == wsMinimized) {
1547 		WINDOWPLACEMENT w = {sizeof(WINDOWPLACEMENT)};
1548 		if ( !GetWindowPlacement( HANDLE, &w)) apiErr;
1549 		p. x = w. rcNormalPosition. right  - w. rcNormalPosition. left;
1550 		p. y = w. rcNormalPosition. bottom - w. rcNormalPosition. top;
1551 	} else {
1552 		GetWindowRect( HANDLE, &r);
1553 		if ( is_apt( aptClipOwner) && ( var owner != application))
1554 			MapWindowPoints( NULL, ( HWND)((( PWidget) var owner)-> handle), ( LPPOINT)&r, 2);
1555 		p. x = r. right - r. left;
1556 		p. y = r. bottom - r. top;
1557 	}
1558 	return p;
1559 }
1560 
1561 Handle
apc_widget_get_z_order(Handle self,int zOrderId)1562 apc_widget_get_z_order( Handle self, int zOrderId)
1563 {
1564 	Handle h;
1565 	HWND   w;
1566 	UINT   cmd1, cmd2;
1567 	objCheck NULL_HANDLE;
1568 
1569 	switch ( zOrderId) {
1570 	case zoFirst:
1571 		cmd1 = GW_HWNDFIRST;
1572 		cmd2 = GW_HWNDNEXT;
1573 		break;
1574 	case zoLast:
1575 		cmd1 = GW_HWNDLAST;
1576 		cmd2 = GW_HWNDPREV;
1577 		break;
1578 	case zoNext:
1579 		cmd1 = cmd2 = GW_HWNDNEXT;
1580 		break;
1581 	case zoPrev:
1582 		cmd1 = cmd2 = GW_HWNDPREV;
1583 		break;
1584 	default:
1585 		apcErr( errInvParams);
1586 		return NULL_HANDLE;
1587 	}
1588 
1589 	w = GetWindow( HANDLE, cmd1);
1590 	if ( !w) return NULL_HANDLE;
1591 	h = hwnd_to_view( w);
1592 	while ( h == NULL_HANDLE) {
1593 		w = GetWindow( w, cmd2);
1594 		if ( !w) return NULL_HANDLE;
1595 		h = hwnd_to_view( w);
1596 	}
1597 
1598 	return h;
1599 }
1600 
1601 Bool
apc_widget_get_shape(Handle self,Handle mask)1602 apc_widget_get_shape( Handle self, Handle mask)
1603 {
1604 	HRGN rgn;
1605 	int res;
1606 	RECT rect;
1607 
1608 	if ( !mask ) {
1609 		rgn = CreateRectRgn(0,0,0,0);
1610 		res = GetWindowRgn( HANDLE, rgn);
1611 		res = GetClipRgn( sys ps, rgn );
1612 		DeleteObject(rgn);
1613 		return res != ERROR;
1614 	}
1615 
1616 	rgn = GET_REGION(mask)-> region;
1617 	res = GetWindowRgn( HANDLE, rgn);
1618 	if ( res == ERROR)
1619 		return false;
1620 
1621 	GetRgnBox(rgn, &rect);
1622 	OffsetRgn( rgn, -sys extraPos. x, -sys extraPos. y);
1623 	GET_REGION(mask)-> aperture = sys lastSize. y - rect.top;
1624 
1625 	return true;
1626 }
1627 
1628 
1629 Bool
apc_widget_get_sync_paint(Handle self)1630 apc_widget_get_sync_paint( Handle self)
1631 {
1632 	objCheck false;
1633 	return is_apt( aptSyncPaint);
1634 }
1635 
1636 Bool
apc_widget_get_transparent(Handle self)1637 apc_widget_get_transparent( Handle self)
1638 {
1639 	objCheck false;
1640 	return is_apt( aptTransparent);
1641 }
1642 
1643 Bool
apc_widget_is_captured(Handle self)1644 apc_widget_is_captured( Handle self)
1645 {
1646 	objCheck false;
1647 	return GetCapture() == ( HWND) var handle;
1648 }
1649 
1650 Bool
apc_widget_is_enabled(Handle self)1651 apc_widget_is_enabled( Handle self)
1652 {
1653 	objCheck false;
1654 	return is_apt( aptEnabled);
1655 	// return IsWindowEnabled( HANDLE);
1656 }
1657 
1658 Bool
apc_widget_is_responsive(Handle self)1659 apc_widget_is_responsive( Handle self)
1660 {
1661 	Bool ena = true;
1662 	objCheck false;
1663 	while ( ena && self != application) {
1664 		// ena  = IsWindowEnabled( HANDLE);
1665 		ena  = is_apt( aptEnabled);
1666 		self = var owner;
1667 	}
1668 	return ena;
1669 }
1670 
1671 Bool
apc_widget_is_focused(Handle self)1672 apc_widget_is_focused( Handle self)
1673 {
1674 	objCheck false;
1675 	return is_apt( aptFocused);
1676 }
1677 
1678 Bool
apc_widget_is_visible(Handle self)1679 apc_widget_is_visible( Handle self)
1680 {
1681 	objCheck false;
1682 	return ( GetWindowLong(HANDLE, GWL_STYLE) & WS_VISIBLE) ? 1 : 0;
1683 }
1684 
1685 Bool
apc_widget_is_showing(Handle self)1686 apc_widget_is_showing( Handle self)
1687 {
1688 	objCheck false;
1689 	return IsWindowVisible( HANDLE);
1690 }
1691 
1692 Bool
apc_widget_is_exposed(Handle self)1693 apc_widget_is_exposed( Handle self)
1694 {
1695 	HWND h;
1696 	HRGN rgnSave = NULL;
1697 	HRGN rgn     = NULL;
1698 	int  rgnSaveType, rgnType;
1699 
1700 	objCheck false;
1701 
1702 	h = ( HWND) var handle;
1703 	if ( !IsWindowVisible( h)) return false;
1704 
1705 	rgnSave = CreateRectRgn(0,0,0,0);
1706 	rgn     = CreateRectRgn(0,0,0,0);
1707 	rgnSaveType = GetUpdateRgn( h, rgnSave, FALSE);
1708 	rgnSaveType = ( rgnSaveType == COMPLEXREGION || rgnSaveType == SIMPLEREGION);
1709 
1710 	if ( rgnSaveType) ValidateRect( h, NULL);
1711 
1712 	InvalidateRect( h, NULL, false);
1713 	rgnType = GetUpdateRgn( h, rgn, FALSE);
1714 	ValidateRect( h, NULL);
1715 
1716 	if ( rgnSaveType) InvalidateRgn( h, rgnSave, FALSE);
1717 	DeleteObject( rgnSave);
1718 	DeleteObject( rgn);
1719 	return ( rgnType == COMPLEXREGION || rgnType == SIMPLEREGION);
1720 }
1721 
1722 Bool
apc_widget_invalidate_rect(Handle self,Rect * rect)1723 apc_widget_invalidate_rect( Handle self, Rect * rect)
1724 {
1725 	PRECT pRect = rect ? map_Rect( self, rect) : NULL;
1726 	objCheck false;
1727 	if ( !InvalidateRect (( HWND) var handle, pRect, false)) apiErr;
1728 	hwnd_repaint_layered( self, false );
1729 	if ( is_apt( aptSyncPaint) && !apcUpdateWindow(( HWND) var handle)) apiErr;
1730 	objCheck false;
1731 	process_transparents( self);
1732 	return true;
1733 }
1734 
1735 int
apc_widget_scroll(Handle self,int horiz,int vert,Rect * r,Rect * cr,Bool scrollChildren)1736 apc_widget_scroll( Handle self, int horiz, int vert, Rect * r, Rect *cr, Bool scrollChildren)
1737 {
1738 	PRECT pRect = r ? map_Rect( self, r) : NULL;
1739 	PRECT pClipRect = cr ? map_Rect( self, cr) : NULL;
1740 	Point sz = apc_widget_get_size( self);
1741 	int ret;
1742 	objCheck scrError;
1743 
1744 	HideCaret(( HWND) var handle);
1745 
1746 	if ( pClipRect) {
1747 		if ( pClipRect-> left < 0) pClipRect-> left = 0;
1748 		if ( pClipRect-> top  < 0) pClipRect-> top = 0;
1749 		if ( pClipRect-> right  > sz. x) pClipRect-> right = sz. x;
1750 		if ( pClipRect-> bottom > sz. y) pClipRect-> bottom = sz. y;
1751 	}
1752 
1753 	if ( pRect) {
1754 		if ( pRect-> left < -sz. x * 2) pRect-> left = -sz. x * 2;
1755 		if ( pRect-> top  < -sz. y * 2) pRect-> top = -sz. y * 2;
1756 		if ( pRect-> right  > sz. x * 2) pRect-> right = sz. x * 2;
1757 		if ( pRect-> bottom > sz. y * 2) pRect-> bottom = sz. y * 2;
1758 	}
1759 
1760 	if ( horiz > sz. x || horiz < -sz. x || vert > sz. y || vert < -sz. y) {
1761 		if ( pRect && pClipRect) {
1762 			RECT rc;
1763 			UnionRect( &rc, (RECT*)pRect, (RECT*)pClipRect);
1764 			InvalidateRect(( HWND) var handle, &rc, false);
1765 		} else
1766 			InvalidateRect(( HWND) var handle, pRect ? pRect : pClipRect, false);
1767 		ret = scrExpose;
1768 	} else {
1769 		int rr = ScrollWindowEx(( HWND) var handle,
1770 			horiz, -vert, pRect, pClipRect, NULL, NULL,
1771 			SW_INVALIDATE | ( scrollChildren ? SW_SCROLLCHILDREN : 0)
1772 		);
1773 		if (!rr) apiErr;
1774 		ret = ( rr == 1 ) ? scrNoExpose : scrExpose;
1775 	}
1776 
1777 	objCheck scrError;
1778 	if ( is_apt( aptSyncPaint) && !apcUpdateWindow(( HWND) var handle)) apiErr;
1779 	process_transparents( self);
1780 	ShowCaret(( HWND) var handle);
1781 
1782 	return ret;
1783 }
1784 
1785 Bool
apc_widget_set_capture(Handle self,Bool capture,Handle confineTo)1786 apc_widget_set_capture( Handle self, Bool capture, Handle confineTo)
1787 {
1788 	objCheck false;
1789 	if ( capture) {
1790 		SetCapture(( HWND) var handle);
1791 		if ( confineTo) {
1792 			RECT r;
1793 			GetWindowRect(( HWND) PComponent( confineTo)-> handle, &r);
1794 			if ( !ClipCursor( &r)) apiErrRet;
1795 		}
1796 	} else {
1797 		if ( !ReleaseCapture()) apiErrRet;
1798 		if ( !ClipCursor( NULL)) apiErrRet;
1799 	}
1800 	return true;
1801 }
1802 
1803 #define check_swap( parm1, parm2) if ( parm1 > parm2) { int parm3 = parm1; parm1 = parm2; parm2 = parm3;}
1804 
1805 Bool
apc_widget_set_clip_by_children(Handle self,Bool clip_by_children)1806 apc_widget_set_clip_by_children( Handle self, Bool clip_by_children)
1807 {
1808 	objCheck false;
1809 	LONG f;
1810 	MSG  msg;
1811 	Bool is_clipped;
1812 
1813 	is_clipped = is_apt(aptClipByChildren);
1814 	clip_by_children = !!clip_by_children;
1815 	if ( is_clipped == clip_by_children )
1816 		return true;
1817 
1818 	if ( sys className == WC_FRAME) {
1819 		f = GetWindowLong(( HWND ) var handle, GWL_STYLE);
1820 		if ( clip_by_children )
1821 			f |= WS_CLIPCHILDREN;
1822 		else
1823 			f &= ~WS_CLIPCHILDREN;
1824 		SetWindowLong(( HWND ) var handle, GWL_STYLE, f);
1825 		while ( PeekMessage( &msg, (HWND) var handle, WM_MOUSEMOVE, WM_MOUSEMOVE, PM_REMOVE));
1826 	}
1827 
1828 	f = GetWindowLong(HANDLE, GWL_STYLE);
1829 	if ( clip_by_children )
1830 		f |= WS_CLIPCHILDREN;
1831 	else
1832 		f &= ~WS_CLIPCHILDREN;
1833 	SetWindowLong( HANDLE, GWL_STYLE, f);
1834 	while ( PeekMessage( &msg, HANDLE, WM_MOUSEMOVE, WM_MOUSEMOVE, PM_REMOVE));
1835 	return true;
1836 }
1837 
1838 Bool
apc_widget_set_color(Handle self,Color color,int index)1839 apc_widget_set_color( Handle self, Color color, int index)
1840 {
1841 	Event ev = {cmColorChanged};
1842 	objCheck false;
1843 	sys viewColors[ index] = color;
1844 
1845 	ev. gen. source = self;
1846 	ev. gen. i      = index;
1847 	var self-> message( self, &ev);
1848 	return true;
1849 }
1850 
1851 Bool
apc_widget_set_enabled(Handle self,Bool enable)1852 apc_widget_set_enabled( Handle self, Bool enable)
1853 {
1854 	objCheck false;
1855 	apt_assign( aptEnabled, enable);
1856 	if (( sys className == WC_FRAME) || ( var owner == application))
1857 		EnableWindow( HANDLE, enable);
1858 	else
1859 		SendMessage( HANDLE, WM_ENABLE, ( WPARAM) enable, 0);
1860 	return true;
1861 }
1862 
1863 Bool
apc_widget_set_first_click(Handle self,Bool firstClick)1864 apc_widget_set_first_click( Handle self, Bool firstClick)
1865 {
1866 	objCheck false;
1867 	apt_assign( aptFirstClick, firstClick);
1868 	return true;
1869 }
1870 
1871 Bool
apc_widget_set_focused(Handle self)1872 apc_widget_set_focused( Handle self)
1873 {
1874 	if ( self && ( self != Application_map_focus( application, self)))
1875 		return false;
1876 	guts. focSysGranted++;
1877 	SetFocus( self ? (( HWND) var handle) : NULL);
1878 	guts. focSysGranted--;
1879 	return true;
1880 }
1881 
1882 Bool
apc_widget_set_font(Handle self,PFont font)1883 apc_widget_set_font( Handle self, PFont font)
1884 {
1885 	Event ev = {cmFontChanged};
1886 	objCheck false;
1887 	ev. gen. source = self;
1888 	var self-> message( self, &ev);
1889 	return true;
1890 }
1891 
1892 Bool
apc_widget_set_palette(Handle self)1893 apc_widget_set_palette( Handle self)
1894 {
1895 	objCheck false;
1896 	apc_gp_set_palette( self);
1897 	if ( guts. displayBMInfo. bmiHeader. biBitCount == 8)
1898 		palette_change( self);
1899 	return true;
1900 }
1901 
1902 Bool
apc_widget_set_pos(Handle self,int x,int y)1903 apc_widget_set_pos( Handle self, int x, int y)
1904 {
1905 	Handle parent;
1906 	Point sz;
1907 	RECT r;
1908 
1909 	objCheck false;
1910 	if ( !hwnd_check_limits( x, y, true)) apcErrRet( errInvParams);
1911 
1912 	parent = is_apt( aptClipOwner) ? var owner : application;
1913 	sz = ((( PWidget) parent)-> self)-> get_size( parent);
1914 	apt_set( aptWinPosDetermined);
1915 
1916 	if ( sys className == WC_FRAME) {
1917 		HWND h = HANDLE;
1918 		int  ws = apc_window_get_window_state( self);
1919 		if (( var stage == csConstructing && ws != wsNormal) || ( ws == wsMinimized)) {
1920 			WINDOWPLACEMENT w = {sizeof(WINDOWPLACEMENT)};
1921 			if ( !GetWindowPlacement( h, &w)) apiErrRet;
1922 			w. rcNormalPosition. top    += sz. y - y - w. rcNormalPosition. bottom;
1923 			w. rcNormalPosition. bottom  = sz. y - y;
1924 			w. rcNormalPosition. right  += x - w. rcNormalPosition. left;
1925 			w. rcNormalPosition. left    = x;
1926 			w. flags = 0;
1927 			if ( !SetWindowPlacement( h, &w)) apiErrRet;
1928 			return true;
1929 		}
1930 	}
1931 	if ( !GetWindowRect( HANDLE, &r)) apiErrRet;
1932 	if ( is_apt( aptClipOwner) && ( var owner != application))
1933 		MapWindowPoints( NULL, ( HWND)((( PWidget) var owner)-> handle), ( LPPOINT)&r, 2);
1934 	if ( sys parentHandle) {
1935 		POINT ppos;
1936 		ppos. x = x;
1937 		ppos. y = dsys( application) lastSize. y - y;
1938 		MapWindowPoints( NULL, sys parentHandle, ( LPPOINT)&ppos, 1);
1939 		GetWindowRect( sys parentHandle, &r);
1940 		x = ppos. x;
1941 		y = ppos. y;
1942 	} else
1943 		y = sz. y - y - r. bottom + r. top;
1944 
1945 	if ( is_apt(aptLayered) && is_apt(aptRepaintPending)) {
1946 		apt_set(aptMovePending);
1947 		sys layeredPos. x = x;
1948 		sys layeredPos. y = y;
1949 	} else {
1950 		if ( !SetWindowPos( HANDLE, 0, x, y, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE)) apiErrRet;
1951 	}
1952 	return true;
1953 }
1954 
1955 Bool
apc_widget_set_size(Handle self,int width,int height)1956 apc_widget_set_size( Handle self, int width, int height)
1957 {
1958 	RECT r;
1959 	HWND h;
1960 	objCheck false;
1961 
1962 	if ( !hwnd_check_limits( width, height, false)) apcErrRet( errInvParams);
1963 	h = HANDLE;
1964 	if ( sys className == WC_FRAME) {
1965 		int  ws = apc_window_get_window_state( self);
1966 		if (( var stage == csConstructing && ws != wsNormal) || ( ws == wsMinimized)) {
1967 			WINDOWPLACEMENT w = {sizeof(WINDOWPLACEMENT)};
1968 			if ( !GetWindowPlacement( h, &w)) apiErrRet;
1969 			if ( width  < 0) width = 0;
1970 			if ( height < 0) height = 0;
1971 			w. rcNormalPosition. top    = w. rcNormalPosition. bottom - height;
1972 			w. rcNormalPosition. right  = width + w. rcNormalPosition. left;
1973 			w. flags = 0;
1974 			if ( !SetWindowPlacement( h, &w)) apiErrRet;
1975 			return true;
1976 		}
1977 	}
1978 	if ( !GetWindowRect( h, &r)) apiErrRet;
1979 	if ( is_apt( aptClipOwner) && ( var owner != application))
1980 		MapWindowPoints( NULL, ( HWND)((( PWidget) var owner)-> handle), ( LPPOINT)&r, 2);
1981 	if ( sys parentHandle)
1982 		MapWindowPoints( NULL, sys parentHandle, ( LPPOINT)&r, 2);
1983 
1984 	if ( sys className != WC_FRAME) {
1985 		sys sizeLockLevel++;
1986 		var virtualSize. x = width;
1987 		var virtualSize. y = height;
1988 	}
1989 	if ( height < 0) height = 0;
1990 	if ( width  < 0) width  = 0;
1991 	if ( is_apt(aptMovePending)) {
1992 		int dx = r. right  - r. left;
1993 		int dy = r. bottom - r. top;
1994 		r. left = sys layeredPos. x;
1995 		r. top  = sys layeredPos. y;
1996 		r. right  = r. left + dx;
1997 		r. bottom = r. top  + dy;
1998 		apt_clear(aptMovePending);
1999 	}
2000 	if ( !SetWindowPos( h, 0,
2001 		r. left, r. bottom - height,
2002 		width, height,
2003 		SWP_NOZORDER | SWP_NOACTIVATE |
2004 			( is_apt( aptWinPosDetermined) ? 0 : SWP_NOMOVE)
2005 		)) apiErrRet;
2006 	hwnd_repaint_layered( self, false );
2007 	if ( sys className != WC_FRAME) sys sizeLockLevel--;
2008 	return true;
2009 }
2010 
2011 Bool
apc_widget_set_rect(Handle self,int x,int y,int width,int height)2012 apc_widget_set_rect( Handle self, int x, int y, int width, int height)
2013 {
2014 	HWND h;
2015 	Handle parent;
2016 	Point sz;
2017 	objCheck false;
2018 
2019 	if ( !hwnd_check_limits( width, height, false)) apcErrRet( errInvParams);
2020 	if ( !hwnd_check_limits( x, y, true)) apcErrRet( errInvParams);
2021 
2022 	parent = is_apt( aptClipOwner) ? var owner : application;
2023 	sz = ((( PWidget) parent)-> self)-> get_size( parent);
2024 	apt_set( aptWinPosDetermined);
2025 
2026 	h = HANDLE;
2027 	if ( sys className == WC_FRAME) {
2028 		int  ws = apc_window_get_window_state( self);
2029 		if (( var stage == csConstructing && ws != wsNormal) || ( ws == wsMinimized)) {
2030 			WINDOWPLACEMENT w = {sizeof(WINDOWPLACEMENT)};
2031 			if ( !GetWindowPlacement( h, &w)) apiErrRet;
2032 			if ( width  < 0) width = 0;
2033 			if ( height < 0) height = 0;
2034 			w. rcNormalPosition. left    = x;
2035 			w. rcNormalPosition. bottom  = sz. y - y;
2036 			w. rcNormalPosition. right   = x + width;
2037 			w. rcNormalPosition. top     = sz. y - y - height;
2038 			w. flags = 0;
2039 			if ( !SetWindowPlacement( h, &w)) apiErrRet;
2040 			return true;
2041 		}
2042 	}
2043 
2044 	if ( sys className != WC_FRAME) {
2045 		sys sizeLockLevel++;
2046 		var virtualSize. x = width;
2047 		var virtualSize. y = height;
2048 	}
2049 	if ( height < 0) height = 0;
2050 	if ( width  < 0) width  = 0;
2051 	if ( sys parentHandle) {
2052 		POINT ppos;
2053 		ppos. x = x;
2054 		ppos. y = dsys( application) lastSize. y - y;
2055 		MapWindowPoints( NULL, sys parentHandle, ( LPPOINT)&ppos, 1);
2056 		x = ppos. x;
2057 		y = ppos. y;
2058 	} else
2059 		y = sz. y - y - height;
2060 
2061 	apt_clear(aptMovePending);
2062 	if ( !SetWindowPos( h, 0, x, y, width, height, SWP_NOZORDER | SWP_NOACTIVATE))
2063 		apiErrRet;
2064 	hwnd_repaint_layered( self, false );
2065 	if ( sys className != WC_FRAME) sys sizeLockLevel--;
2066 	return true;
2067 }
2068 
2069 
2070 Bool
apc_widget_set_size_bounds(Handle self,Point min,Point max)2071 apc_widget_set_size_bounds( Handle self, Point min, Point max)
2072 {
2073 	return true;
2074 }
2075 
2076 Bool
apc_widget_set_shape(Handle self,Handle mask)2077 apc_widget_set_shape( Handle self, Handle mask)
2078 {
2079 	HRGN rgn = NULL;
2080 	RECT xr;
2081 	objCheck false;
2082 
2083 	if ( !mask) {
2084 		if ( sys className == WC_FRAME && is_apt(aptLayered))
2085 			SetWindowRgn((HWND) var handle, NULL, true);
2086 		else
2087 			SetWindowRgn( HANDLE, NULL, true);
2088 		hwnd_repaint_layered( self, false );
2089 		return true;
2090 	}
2091 
2092 
2093 	rgn = CreateRectRgn(0,0,0,0);
2094 	CombineRgn( rgn, GET_REGION(mask)->region, NULL, RGN_COPY);
2095 	GetRgnBox( rgn, &xr);
2096 	sys extraBounds. x = xr. right - 1;
2097 	sys extraBounds. y = GET_REGION(mask)->aperture;
2098 	if ( sys className == WC_FRAME && !is_apt(aptLayered)) {
2099 		Point delta = get_window_borders( sys s. window. borderStyle);
2100 		Point sz    = apc_widget_get_size( self);
2101 		Point p     = sys extraBounds;
2102 		HRGN  r1, r2;
2103 
2104 		OffsetRgn( rgn, delta.x, sz. y - p.y - delta.y);
2105 		sys extraPos. x = delta.x;
2106 		sys extraPos. y = sz. y - p.y - delta.y;
2107 		r1 = CreateRectRgn( 0, 0, 8192, 8192);
2108 		r2 = CreateRectRgn( delta. x, sz. y - delta. y - p.y,
2109 			delta.x + p.x, sz. y - delta. y);
2110 		CombineRgn( r1, r1, r2, RGN_XOR);
2111 		CombineRgn( rgn, rgn, r1, RGN_OR);
2112 		DeleteObject( r1);
2113 		DeleteObject( r2);
2114 		if ( !SetWindowRgn( HANDLE, rgn, true))
2115 			apiErrRet;
2116 		DeleteObject(rgn);
2117 	} else if ( sys className == WC_FRAME ) {
2118 		sys extraPos. x = sys extraPos. y = 0;
2119 		if ( !SetWindowRgn((HWND) var handle, rgn, true))
2120 			apiErrRet;
2121 	} else {
2122 		sys extraPos. x = sys extraPos. y = 0;
2123 		if ( !SetWindowRgn( HANDLE, rgn, true))
2124 			apiErrRet;
2125 	}
2126 	DeleteObject(rgn);
2127 
2128 	if ( is_apt(aptMovePending)) {
2129 		apt_clear(aptMovePending);
2130 		if ( !SetWindowPos( HANDLE, 0, sys layeredPos. x, sys layeredPos. y, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE))
2131 			apiErrRet;
2132 	}
2133 	hwnd_repaint_layered( self, false );
2134 	return true;
2135 }
2136 
2137 Bool
apc_widget_set_visible(Handle self,Bool show)2138 apc_widget_set_visible( Handle self, Bool show)
2139 {
2140 	objCheck false;
2141 	if ( !SetWindowPos( HANDLE, NULL, 0, 0, 0, 0,
2142 		( show ? SWP_SHOWWINDOW : SWP_HIDEWINDOW)
2143 		| SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE)) apiErrRet;
2144 	objCheck false;
2145 	if ( !is_apt( aptClipOwner)) {
2146 		InvalidateRect(( HWND) var handle, NULL, false);
2147 		objCheck false;
2148 		process_transparents( self);
2149 	}
2150 	hwnd_repaint_layered(self, false);
2151 	return true;
2152 }
2153 
2154 Bool
apc_widget_set_z_order(Handle self,Handle behind,Bool top)2155 apc_widget_set_z_order( Handle self, Handle behind, Bool top)
2156 {
2157 	HWND opt = ( top) ? HWND_TOP : HWND_BOTTOM;
2158 	objCheck false;
2159 	if ( behind != NULL_HANDLE) {
2160 		dobjCheck( behind) false;
2161 		opt = DHANDLE( behind);
2162 	}
2163 	if ( !SetWindowPos( HANDLE, opt, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE)) apiErrRet;
2164 	return true;
2165 }
2166 
2167 Bool
apc_widget_update(Handle self)2168 apc_widget_update( Handle self)
2169 {
2170 	objCheck false;
2171 	if ( !apcUpdateWindow(( HWND) var handle)) apiErrRet;
2172 	return true;
2173 }
2174 
2175 Bool
apc_widget_validate_rect(Handle self,Rect rect)2176 apc_widget_validate_rect( Handle self, Rect rect)
2177 {
2178 	objCheck false;
2179 	if ( !ValidateRect (( HWND) var handle, map_Rect( self, &rect))) apiErrRet;
2180 	return true;
2181 }
2182 
2183 
2184 #ifdef __cplusplus
2185 }
2186 #endif
2187