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 "Icon.h"
10 #include "Widget.h"
11 #include "Window.h"
12 
13 #ifdef __cplusplus
14 extern "C" {
15 #endif
16 
17 
18 #define  sys (( PDrawableData)(( PComponent) self)-> sysData)->
19 #define  dsys( view) (( PDrawableData)(( PComponent) view)-> sysData)->
20 #define var (( PWidget) self)->
21 #define HANDLE sys handle
22 #define DHANDLE(x) dsys(x) handle
23 
24 static void
map_tildas(WCHAR * buf,int len)25 map_tildas( WCHAR * buf, int len)
26 {
27 	int j;
28 	for ( j = 0; j < len; j++) {
29 		if ( buf[ j] == '~') {
30 			if ( buf[ j + 1] == '~')
31 				j++;
32 			else if ( buf[ j + 1])
33 				buf[ j] = '&';
34 			continue;
35 		} else if ( buf[ j] == '&') {
36 			memmove( buf + j + 1, buf + j, (len - j + 1) * sizeof( WCHAR));
37 			j++;
38 			len++;
39 			continue;
40 		}
41 	}
42 }
43 
44 
45 static WCHAR *
map_text_accel(PMenuItemReg i)46 map_text_accel( PMenuItemReg i)
47 {
48 	char * c;
49 	int l1, l2 = 0, amps = 0;
50 	WCHAR *buf, *text, *accel = NULL;
51 
52 	c = i-> text;
53 	while (*c++) if ( *c == '&') amps++;
54 	if ( i-> flags. utf8_text ) {
55 		text = alloc_utf8_to_wchar( i-> text, prima_utf8_length( i-> text, -1), &l1);
56 	} else {
57 		l1 = strlen( i-> text);
58 		text = alloc_ascii_to_wchar( i-> text, l1);
59 	}
60 
61 	if ( i-> accel ) {
62 		c = i-> accel;
63 		while (*c++) if ( *c == '&') amps++;
64 		if ( i-> flags. utf8_accel ) {
65 			accel = alloc_utf8_to_wchar( i-> accel, prima_utf8_length( i-> accel, -1), &l2);
66 		} else {
67 			l2 = strlen( i-> accel);
68 			accel = alloc_ascii_to_wchar( i-> accel, l2);
69 		}
70 	}
71 
72 	buf = malloc(sizeof(WCHAR) * (l1 + l2 + amps + 2));
73 
74 	memcpy( buf, text, l1 * sizeof(WCHAR));
75 	free(text);
76 
77 	if ( i->accel ) {
78 		buf[l1] = '\t';
79 		memcpy( buf + l1 + 1, accel, l2 * sizeof(WCHAR));
80 		free(accel);
81 		l2++;
82 	}
83 
84 	buf[l1 + l2] = 0;
85 	map_tildas( buf, l1 + l2);
86 
87 	return buf;
88 }
89 
90 /* Convert 1-bit icons to bitmaps, icons to argb, others to pixmaps */
91 static HBITMAP
create_menu_bitmap(Handle bitmap)92 create_menu_bitmap( Handle bitmap )
93 {
94 	HBITMAP ret = NULL;
95 	PIcon i = (PIcon) bitmap;
96 
97 	if ( i == NULL || i-> stage >= csDead )
98 		return NULL;
99 
100 	if (kind_of(bitmap, CIcon)) {
101 		if (( i-> type & imBPP) == 1) {
102 			ret = image_create_bitmap( bitmap);
103 		} else {
104 			Handle dup = CImage(bitmap)->dup(bitmap);
105 			CIcon(dup)->set_autoMasking(dup, amNone);
106 			if ( i-> type != imRGB )
107 				CIcon(dup)->set_type(dup, imRGB);
108 			if ( i-> maskType != 8 )
109 				CIcon(dup)->set_maskType(dup, 8);
110 			CIcon(dup)-> premultiply_alpha(dup, NULL);
111 			ret = image_create_bitmap( dup);
112 			Object_destroy(dup);
113 		}
114 	} else {
115 		if (( i-> type & imBPP) == 1) {
116 			Handle dup = CImage(bitmap)->dup(bitmap);
117 			CIcon(dup)->set_type(dup, 4);
118 			ret = image_create_bitmap( bitmap);
119 			Object_destroy(dup);
120 		}
121 	}
122 
123 	if ( ret == NULL )
124 		ret = image_create_bitmap( bitmap);
125 
126 	return ret;
127 }
128 
129 typedef struct {
130 	HMENU menu;
131 	int   id;
132 } BitmapKey;
133 
134 static void
build_bitmap_key(HMENU menu,PMenuItemReg m,BitmapKey * key)135 build_bitmap_key( HMENU menu, PMenuItemReg m, BitmapKey * key)
136 {
137 	memset(key, 0, sizeof(BitmapKey));
138 	key->menu = menu;
139 	key->id   = m->id;
140 }
141 
142 static HBITMAP
unchecked_bitmap(void)143 unchecked_bitmap(void)
144 {
145 	int cx, x1, y1, x2, y2, i, sz;
146 	HDC dc;
147 	uint32_t * ptr;
148 	HPEN stock_pen;
149 	HPEN stock_brush;
150 	HBITMAP stock_bm;
151 
152 	if ( uncheckedBitmap == (HBITMAP)(-1)) return NULL;
153 	if ( uncheckedBitmap != NULL) return uncheckedBitmap;
154 
155 	uncheckedBitmap = (HBITMAP) -1;
156 
157 	cx = GetSystemMetrics( SM_CXMENUCHECK ) - 1;
158 	dc = GetDC(NULL);
159 	if ( !( uncheckedBitmap = image_create_argb_dib_section( dc, cx, cx, &ptr))) {
160 		DeleteDC(dc);
161 		return NULL;
162 	}
163 	DeleteDC(dc);
164 
165 	dc = CreateCompatibleDC(NULL);
166 	stock_bm = SelectObject( dc, uncheckedBitmap);
167 
168 	sz = cx * cx;
169 	bzero(ptr, sz * 4);
170 	x1 = y1 = (cx > 10) ? cx / 4 : 0;
171 	x2 = y2 = cx - x1;
172 
173 	stock_brush = SelectObject( dc, hBrushHollow);
174 
175 	stock_pen = SelectObject( dc, CreatePen( PS_SOLID, 0, 0x404040));
176 	MoveToEx( dc, x1, y2, NULL);
177 	LineTo( dc, x2, y2);
178 	LineTo( dc, x2, y1);
179 
180 	DeleteObject( SelectObject( dc, CreatePen( PS_SOLID, 0, GetSysColor(COLOR_BTNSHADOW))));
181 	MoveToEx( dc, x2, y1, NULL);
182 	LineTo( dc, x1, y1);
183 	LineTo( dc, x1, y2 + 1);
184 
185 	x1++; y1++; x2--; y2--;
186 	MoveToEx( dc, x1, y2, NULL);
187 	LineTo( dc, x2, y2);
188 	LineTo( dc, x2, y1);
189 
190 	DeleteObject( SelectObject( dc, CreatePen( PS_SOLID, 0, GetSysColor(COLOR_BTNHIGHLIGHT))));
191 	MoveToEx( dc, x2, y1, NULL);
192 	LineTo( dc, x1, y1);
193 	LineTo( dc, x1, y2 + 1);
194 
195 	for ( i = 0; i < sz; i++, ptr++)
196 		if ( *ptr )
197 			*ptr |= 0xff000000;
198 
199 	DeleteObject(SelectObject( dc, stock_brush ));
200 	SelectObject( dc, stock_pen );
201 	SelectObject(dc, stock_bm);
202 	DeleteDC(dc);
203 
204 	return uncheckedBitmap;
205 }
206 
207 static HMENU
add_item(Bool menuType,Handle menu,PMenuItemReg i)208 add_item( Bool menuType, Handle menu, PMenuItemReg i)
209 {
210 	MENUITEMINFOW mii;
211 	HMENU m;
212 	PMenuWndData mwd;
213 	PMenuItemReg first;
214 
215 	if ( i == NULL) return NULL;
216 
217 	if ( menuType)
218 		m = CreateMenu();
219 	else
220 		m = CreatePopupMenu();
221 
222 	if ( !m) {
223 		apiErr;
224 		return NULL;
225 	}
226 	mwd = ( PMenuWndData) malloc( sizeof( MenuWndData));
227 	if ( !mwd) {
228 		DestroyMenu( m);
229 		return NULL;
230 	}
231 	mwd-> menu = menu;
232 	first      = i;
233 	hash_store( menuMan, &m, sizeof(HMENU), mwd);
234 
235 	while ( i != NULL)
236 	{
237 		bzero( &mii, sizeof(mii));
238 		mii.cbSize   = sizeof(mii);
239 		mii.fMask    = MIIM_STATE | MIIM_SUBMENU | MIIM_TYPE | MIIM_ID | MIIM_DATA;
240 
241 		mii.fType    = 0;
242 		mii.fType   |= ( i-> flags. divider    ) ? MFT_SEPARATOR    : 0;
243 		mii.fType   |= ( i-> bitmap            ) ? MFT_BITMAP       : 0;
244 		mii.fType   |= ( i-> text              ) ? MFT_STRING       : 0;
245 		mii.fType   |= ( i-> flags. rightAdjust) ? MFT_RIGHTJUSTIFY : 0;
246 		mii.fType   |= ( i-> flags. custom_draw) ? MFT_OWNERDRAW    : 0;
247 
248 		mii.fState   = 0;
249 		mii.fState  |= ( i-> flags. checked    ) ? MFS_CHECKED      : 0;
250 		mii.fState  |= ( i-> flags. disabled   ) ? MFS_GRAYED       : 0;
251 
252 		mii.wID      = i-> id + MENU_ID_AUTOSTART;
253 		mii.hSubMenu = add_item( menuType, menu, i-> down);
254 		mii.dwItemData = menu;
255 
256 		if (!( i-> flags. divider && i-> flags. rightAdjust)) {
257 			if ( i-> text)
258 				mii. dwTypeData = map_text_accel( i);
259 			else if ( i-> bitmap )
260 				mii. dwTypeData = (WCHAR*) create_menu_bitmap( i-> bitmap);
261 			if ( i-> icon ) {
262 				BitmapKey key;
263 				HBITMAP bitmap = create_menu_bitmap( i-> icon);
264 				build_bitmap_key(m, i, &key);
265 				hash_store( menuBitmapMan, &key, sizeof(key), (void*) bitmap);
266 				mii. fMask |= MIIM_CHECKMARKS;
267 				mii. hbmpChecked = mii. hbmpUnchecked = bitmap;
268 			} else if ( i-> flags. autotoggle ) {
269 				mii. fMask |= MIIM_CHECKMARKS;
270 				mii. hbmpUnchecked = unchecked_bitmap();
271 			}
272 			InsertMenuItemW( m, -1, true, &mii);
273 			if ( i-> text && mii.dwTypeData)
274 				free( mii. dwTypeData);
275 		}
276 
277 		i = i-> next;
278 	}
279 
280 	mwd-> id = first-> id;
281 	return m;
282 }
283 
284 Bool
apc_menu_create(Handle self,Handle owner)285 apc_menu_create( Handle self, Handle owner)
286 {
287 	objCheck false;
288 	dobjCheck( owner) false;
289 	sys className = WC_MENU;
290 	sys owner     = DHANDLE( owner);
291 	return true;
292 }
293 
294 static Bool
clear_menus(PMenuWndData item,int keyLen,void * key,void * params)295 clear_menus( PMenuWndData item, int keyLen, void * key, void * params)
296 {
297 	if ( item-> menu == ( Handle) params)
298 		hash_delete( menuMan, key, keyLen, true);
299 	return false;
300 }
301 
302 static Bool
clear_bitmaps(void * bm,int keyLen,BitmapKey * key,void * menu)303 clear_bitmaps(void * bm, int keyLen, BitmapKey * key, void * menu)
304 {
305 	if ( key-> menu == ( HMENU) menu)
306 		hash_delete( menuBitmapMan, key, keyLen, true);
307 	return false;
308 }
309 
310 Bool
apc_menu_destroy(Handle self)311 apc_menu_destroy( Handle self)
312 {
313 	if ( var handle) {
314 		objCheck false;
315 		hash_first_that( menuMan, clear_menus, ( void *) self, NULL, NULL);
316 		hash_first_that( menuBitmapMan, clear_bitmaps, ( void *) var handle, NULL, NULL);
317 		if ( IsMenu(( HMENU) var handle) && !DestroyMenu(( HMENU) var handle)) apiErrRet;
318 		return true;
319 	}
320 	return false;
321 }
322 
323 PFont
apc_menu_default_font(PFont copyTo)324 apc_menu_default_font( PFont copyTo)
325 {
326 	*copyTo = guts. menuFont;
327 	copyTo-> pitch = fpDefault;
328 	return copyTo;
329 }
330 
331 Color
apc_menu_get_color(Handle self,int index)332 apc_menu_get_color( Handle self, int index)
333 {
334 	return remap_color( index | var widgetClass, true);
335 }
336 
337 PFont
apc_menu_get_font(Handle self,PFont font)338 apc_menu_get_font( Handle self, PFont font)
339 {
340 	return apc_menu_default_font( font);
341 }
342 
343 Bool
apc_menu_set_color(Handle self,Color color,int index)344 apc_menu_set_color( Handle self, Color color, int index)
345 {
346 	return true;
347 }
348 
349 Bool
apc_menu_set_font(Handle self,PFont font)350 apc_menu_set_font( Handle self, PFont font)
351 {
352 	return true;
353 }
354 
355 static void
free_bitmaps(BitmapKey * key,PMenuItemReg m)356 free_bitmaps( BitmapKey *key, PMenuItemReg m)
357 {
358 	if ( m-> icon ) {
359 		key-> id = m-> id;
360 		hash_delete( menuBitmapMan, &key, sizeof(key), false);
361 	}
362 	if ( m-> next )
363 		free_bitmaps( key, m-> next);
364 	if ( m-> down )
365 		free_bitmaps( key, m-> down);
366 }
367 
368 static void
free_submenus(HMENU menu)369 free_submenus(HMENU menu)
370 {
371 	int i, n;
372 	hash_delete( menuMan, &menu, sizeof(HMENU), true);
373 	n = GetMenuItemCount(menu);
374 	for ( i = 0; i < n; i++) {
375 		HMENU submenu = GetSubMenu(menu, i);
376 		if ( submenu )
377 			free_submenus(submenu);
378 	}
379 }
380 
381 Bool
apc_menu_item_delete(Handle self,PMenuItemReg m)382 apc_menu_item_delete( Handle self, PMenuItemReg m)
383 {
384 	PWindow owner = NULL;
385 	Point size;
386 	Bool resize;
387 	BitmapKey key;
388 	MENUITEMINFO mii;
389 
390 	objCheck false;
391 	dobjCheck( var owner) false;
392 	if (( resize = kind_of( var owner, CWindow) &&
393 		kind_of( self, CMenu) &&
394 		var stage <= csNormal &&
395 		((( PAbstractMenu) self)-> self)-> get_selected( self))) {
396 		owner = ( PWindow) var owner;
397 		size = owner-> self-> get_size( var owner);
398 	}
399 
400 	build_bitmap_key((HMENU) var handle, m, &key);
401 	free_bitmaps(&key, m);
402 
403 	bzero(&mii, sizeof(mii));
404 	mii.cbSize = sizeof(mii);
405 	mii.fMask  = MIIM_SUBMENU;
406 	GetMenuItemInfo(( HMENU) var handle, m->id + MENU_ID_AUTOSTART, false, &mii);
407 	if (mii.hSubMenu) free_submenus(mii.hSubMenu);
408 
409 	DeleteMenu(( HMENU) var handle, m-> id + MENU_ID_AUTOSTART, MF_BYCOMMAND);
410 	DrawMenuBar( DHANDLE( var owner));
411 	if ( resize && apc_window_get_window_state( var owner) == wsNormal)
412 		owner-> self-> set_size( var owner, size);
413 	return true;
414 }
415 
416 Bool
apc_menu_item_set_accel(Handle self,PMenuItemReg m)417 apc_menu_item_set_accel( Handle self, PMenuItemReg m)
418 {
419 	UINT flags;
420 	WCHAR * buf;
421 
422 	if ( !var handle) return false;
423 	objCheck false;
424 	flags = GetMenuState(( HMENU) var handle, m-> id + MENU_ID_AUTOSTART, MF_BYCOMMAND);
425 	if ( flags == 0xFFFFFFFF) return false;
426 
427 	if ( flags & MF_BITMAP)
428 		flags = ( flags & ~MF_BITMAP) | MF_STRING;
429 
430 	apcErrClear;
431 	buf = map_text_accel( m);
432 	if ( !ModifyMenuW(( HMENU) var handle, m-> id + MENU_ID_AUTOSTART, flags,
433 						m-> id + MENU_ID_AUTOSTART, buf))
434 		apiErr;
435 	free( buf);
436 	return rc == errOk;
437 }
438 
439 Bool
apc_menu_item_set_check(Handle self,PMenuItemReg m)440 apc_menu_item_set_check( Handle self, PMenuItemReg m)
441 {
442 	DWORD res;
443 	if ( !var handle) return false;
444 	objCheck false;
445 	res = CheckMenuItem(( HMENU) var handle,
446 		m-> id + MENU_ID_AUTOSTART, MF_BYCOMMAND | ( m-> flags. checked ? MF_CHECKED : MF_UNCHECKED));
447 	return res != 0xFFFFFFFF;
448 }
449 
450 static Bool
update_check_icons(Handle self,PMenuItemReg m)451 update_check_icons( Handle self, PMenuItemReg m)
452 {
453 	UINT flags;
454 	HBITMAP bitmap = NULL;
455 	BitmapKey key;
456 	Bool ret = true;
457 	MENUITEMINFO mii;
458 
459 	if ( !var handle) return false;
460 	objCheck false;
461 	flags = GetMenuState(( HMENU) var handle, m-> id + MENU_ID_AUTOSTART, MF_BYCOMMAND);
462 	if ( flags == 0xFFFFFFFF) return false;
463 
464 	build_bitmap_key((HMENU) var handle, m, &key);
465 	hash_delete( menuBitmapMan, &key, sizeof(key), false);
466 
467 	bzero(&mii, sizeof(mii));
468 	mii.cbSize = sizeof(mii);
469 	mii.fMask  = MIIM_CHECKMARKS;
470 
471 	if ( m-> icon ) {
472 		if ( ( bitmap = create_menu_bitmap( m-> icon)) != NULL)
473 			hash_store( menuBitmapMan, &key, sizeof(key), (void*) bitmap);
474 		else {
475 			apiErr;
476 			ret = false;
477 		}
478 		mii.hbmpChecked = mii.hbmpUnchecked = bitmap;
479 	} else if ( m-> flags.autotoggle ) {
480 		mii. hbmpUnchecked = unchecked_bitmap();
481 	}
482 
483 
484 	return ret;
485 }
486 
487 Bool
apc_menu_item_set_autotoggle(Handle self,PMenuItemReg m)488 apc_menu_item_set_autotoggle( Handle self, PMenuItemReg m)
489 {
490 	return update_check_icons(self, m);
491 }
492 
493 Bool
apc_menu_item_set_enabled(Handle self,PMenuItemReg m)494 apc_menu_item_set_enabled( Handle self, PMenuItemReg m)
495 {
496 	DWORD res;
497 	if ( !var handle) return false;
498 	objCheck false;
499 	res = EnableMenuItem(( HMENU) var handle, m-> id + MENU_ID_AUTOSTART, MF_BYCOMMAND | (
500 		m-> flags. disabled ? MF_GRAYED : MF_ENABLED
501 	));
502 	DrawMenuBar( DHANDLE( var owner));
503 	return res != 0xFFFFFFFF;
504 }
505 
506 Bool
apc_menu_item_set_key(Handle self,PMenuItemReg m)507 apc_menu_item_set_key( Handle self, PMenuItemReg m)
508 {
509 	return true;
510 }
511 
512 Bool
apc_menu_item_set_text(Handle self,PMenuItemReg m)513 apc_menu_item_set_text( Handle self, PMenuItemReg m)
514 {
515 	WCHAR * buf;
516 	UINT flags;
517 
518 	if ( !var handle) return false;
519 	objCheck false;
520 	flags = GetMenuState(( HMENU) var handle, m-> id + MENU_ID_AUTOSTART, MF_BYCOMMAND);
521 	if ( flags == 0xFFFFFFFF) return false;
522 
523 	if ( flags & MF_BITMAP)
524 		flags = ( flags & ~MF_BITMAP) | MF_STRING;
525 
526 	apcErrClear;
527 	buf = map_text_accel( m);
528 	if ( !ModifyMenuW(( HMENU) var handle, m-> id + MENU_ID_AUTOSTART, flags,
529 			m-> id + MENU_ID_AUTOSTART, (WCHAR*) buf)) apiErr;
530 	free( buf);
531 	return rc == errOk;
532 }
533 
534 Bool
apc_menu_item_set_image(Handle self,PMenuItemReg m)535 apc_menu_item_set_image( Handle self, PMenuItemReg m)
536 {
537 	UINT flags;
538 
539 	if ( !var handle) return false;
540 	objCheck false;
541 	dobjCheck( m-> bitmap) false;
542 	flags = GetMenuState(( HMENU) var handle, m-> id + MENU_ID_AUTOSTART, MF_BYCOMMAND);
543 	if ( flags == 0xFFFFFFFF) return false;
544 
545 	flags |= MF_BITMAP;
546 
547 	if ( !ModifyMenuW(( HMENU) var handle, m-> id + MENU_ID_AUTOSTART, flags,
548 		m-> id + MENU_ID_AUTOSTART,
549 		( LPCWSTR) create_menu_bitmap( m-> bitmap))) apiErrRet;
550 	return true;
551 }
552 
553 Bool
apc_menu_item_set_icon(Handle self,PMenuItemReg m)554 apc_menu_item_set_icon( Handle self, PMenuItemReg m)
555 {
556 	return update_check_icons(self, m);
557 }
558 
559 ApiHandle
apc_menu_get_handle(Handle self)560 apc_menu_get_handle( Handle self)
561 {
562 	objCheck 0;
563 	return ( ApiHandle) var handle;
564 }
565 
566 Bool
apc_menu_update(Handle self,PMenuItemReg oldBranch,PMenuItemReg newBranch)567 apc_menu_update( Handle self, PMenuItemReg oldBranch, PMenuItemReg newBranch)
568 {
569 	objCheck false;
570 	dobjCheck( var owner) false;
571 
572 	if ( kind_of( var owner, CWindow) &&
573 		kind_of( self, CMenu) &&
574 		var stage <= csNormal &&
575 		((( PAbstractMenu) self)-> self)-> get_selected( self)) {
576 		HMENU h = GetMenu( DHANDLE( var owner));
577 		PWindow owner = ( PWindow) var owner;
578 		Point size = owner-> self-> get_size( var owner);
579 		if ( h) {
580 			hash_first_that( menuBitmapMan, clear_bitmaps, ( void *) h, NULL, NULL);
581 			DestroyMenu( h);
582 		}
583 		hash_first_that( menuMan, clear_menus, ( void *) self, NULL, NULL);
584 		var handle = ( Handle) add_item( kind_of( self, CMenu), self, (( PMenu) self)-> tree);
585 		SetMenu( DHANDLE( var owner), self ? ( HMENU) var handle : NULL);
586 		DrawMenuBar( DHANDLE( var owner));
587 		if ( apc_window_get_window_state( var owner) == wsNormal)
588 			owner-> self-> set_size( var owner, size);
589 	} else {
590 		if ( var handle) {
591 			hash_first_that( menuBitmapMan, clear_bitmaps, ( void *) var handle, NULL, NULL);
592 			DestroyMenu(( HMENU) var handle);
593 		}
594 		hash_first_that( menuMan, clear_menus, ( void *) self, NULL, NULL);
595 		var handle = ( Handle) add_item( kind_of( self, CMenu), self, (( PMenu) self)-> tree);
596 	}
597 	return true;
598 }
599 
600 Bool
apc_popup_create(Handle self,Handle owner)601 apc_popup_create( Handle self, Handle owner)
602 {
603 	objCheck false;
604 	dobjCheck( owner) false;
605 	sys owner = DHANDLE( owner);
606 	sys className = WC_MENU;
607 	return true;
608 }
609 
610 PFont
apc_popup_default_font(PFont font)611 apc_popup_default_font( PFont font)
612 {
613 	return apc_menu_default_font( font);
614 }
615 
616 Bool
apc_popup(Handle self,int x,int y,Rect * anchor)617 apc_popup( Handle self, int x, int y, Rect * anchor)
618 {
619 	TPMPARAMS tpm;
620 	HWND owner;
621 	Bool ret = true;
622 	objCheck false;
623 
624 	if ( guts. popupActive) return false;
625 
626 	y = dsys( var owner) lastSize. y - y;
627 	owner = ( HWND)(( PComponent) var owner)-> handle;
628 	if ( var owner != application) {
629 		POINT pt;
630 		pt. x = x;
631 		pt. y = y;
632 		if ( !MapWindowPoints( owner, NULL, &pt, 1)) apiErr;
633 		x = pt.x;
634 		y = pt.y;
635 	}
636 	if ( anchor &&
637 		anchor-> left   &&
638 		anchor-> right  &&
639 		anchor-> top    &&
640 		anchor-> bottom
641 		)
642 	{
643 		RECT r;
644 		GetWindowRect( owner, &r);
645 		tpm. cbSize = sizeof( tpm);
646 		tpm. rcExclude. left   = anchor-> left;
647 		tpm. rcExclude. right  = anchor-> right;
648 		tpm. rcExclude. top    = r. bottom - r. top - anchor-> top;
649 		tpm. rcExclude. bottom = r. bottom - r. top - anchor-> bottom;
650 		if ( !MapWindowPoints( owner, NULL, ( PPOINT) &tpm. rcExclude, 2)) apiErr;
651 	} else
652 		anchor = NULL;
653 
654 	guts. popupActive = 1;
655 	ret = TrackPopupMenuEx(
656 		( HMENU) var handle, TPM_LEFTBUTTON|TPM_LEFTALIGN|TPM_RIGHTBUTTON,
657 		x, y, owner, anchor ? &tpm : NULL);
658 	guts. popupActive = 0;
659 	return ret;
660 }
661 
662 Bool
apc_menu_item_begin_paint(Handle self,PEvent event)663 apc_menu_item_begin_paint( Handle self, PEvent event)
664 {
665 	objCheck false;
666 	apcErrClear;
667 
668 	self = event->gen.H;
669 	sys transform2. x = 0;
670 	sys transform2. y = 0;
671 	apt_set( aptCompatiblePS);
672 	sys ps = (HDC) event->gen.p;
673 	sys lastSize = event->gen.P;
674 	sys s.menuitem.saved_dc = SaveDC(sys ps);
675 	hwnd_enter_paint( self);
676 	return true;
677 }
678 
679 Bool
apc_menu_item_end_paint(Handle self,PEvent event)680 apc_menu_item_end_paint( Handle self, PEvent event)
681 {
682 	objCheck false;
683 	self = event->gen.H;
684 	hwnd_leave_paint( self);
685 	RestoreDC(sys ps, sys s.menuitem.saved_dc);
686 	sys ps = NULL;
687 	apt_clear( aptCompatiblePS);
688 	return true;
689 }
690 
691 
692 #ifdef __cplusplus
693 }
694 #endif
695