]> git.saurik.com Git - wxWidgets.git/blob - src/mac/uma.cpp
Fixed double deletion in region iterator
[wxWidgets.git] / src / mac / uma.cpp
1 #include "wx/defs.h"
2 #include "wx/dc.h"
3 #include "wx/mac/uma.h"
4 #include <MacTextEditor.h>
5
6 #ifndef __DARWIN__
7 # include <Navigation.h>
8 # if defined(TARGET_CARBON)
9 # if PM_USE_SESSION_APIS
10 # include <PMCore.h>
11 # endif
12 # include <PMApplication.h>
13 # else
14 # include <Printing.h>
15 # endif
16 #endif
17
18 // since we have decided that we only support 8.6 upwards we are
19 // checking for these minimum requirements in the startup code of
20 // the application so all wxWindows code can safely assume that appearance 1.1
21 // windows manager, control manager, navigation services etc. are
22 // present
23
24 static bool sUMAHasAppearance = false ;
25 static long sUMAAppearanceVersion = 0 ;
26 static bool sUMAHasAquaLayout = false ;
27 static bool sUMASystemInitialized = false ;
28
29 extern int gAGABackgroundColor ;
30 bool UMAHasAppearance() { return sUMAHasAppearance ; }
31 long UMAGetAppearanceVersion() { return sUMAAppearanceVersion ; }
32
33 static bool sUMAHasWindowManager = false ;
34 static long sUMAWindowManagerAttr = 0 ;
35
36 bool UMAHasWindowManager() { return sUMAHasWindowManager ; }
37 long UMAGetWindowManagerAttr() { return sUMAWindowManagerAttr ; }
38 bool UMAHasAquaLayout() { return sUMAHasAquaLayout ; }
39 bool UMASystemIsInitialized() { return sUMASystemInitialized ; }
40
41 void UMACleanupToolbox()
42 {
43 if ( sUMAHasAppearance )
44 {
45 UnregisterAppearanceClient() ;
46 }
47 if ( NavServicesAvailable() )
48 {
49 NavUnload() ;
50 }
51 if ( TXNTerminateTextension != (void*) kUnresolvedCFragSymbolAddress )
52 TXNTerminateTextension( ) ;
53 }
54 void UMAInitToolbox( UInt16 inMoreMastersCalls )
55 {
56 #if !TARGET_CARBON
57 ::MaxApplZone();
58 for (long i = 1; i <= inMoreMastersCalls; i++)
59 ::MoreMasters();
60
61 ::InitGraf(&qd.thePort);
62 ::InitFonts();
63 ::InitMenus();
64 ::TEInit();
65 ::InitDialogs(0L);
66 ::FlushEvents(everyEvent, 0);
67 ::InitCursor();
68 long total,contig;
69 PurgeSpace(&total, &contig);
70 #else
71 InitCursor();
72 #endif
73
74 long theAppearance ;
75 if ( Gestalt( gestaltAppearanceAttr, &theAppearance ) == noErr )
76 {
77 sUMAHasAppearance = true ;
78 RegisterAppearanceClient();
79 if ( Gestalt( gestaltAppearanceVersion, &theAppearance ) == noErr )
80 {
81 sUMAAppearanceVersion = theAppearance ;
82 }
83 else
84 {
85 sUMAAppearanceVersion = 0x0100 ;
86 }
87 }
88 if ( Gestalt( gestaltWindowMgrAttr, &sUMAWindowManagerAttr ) == noErr )
89 {
90 sUMAHasWindowManager = sUMAWindowManagerAttr & gestaltWindowMgrPresent ;
91 }
92
93 #if TARGET_CARBON
94 // Call currently implicitely done : InitFloatingWindows() ;
95 #else
96 if ( sUMAHasWindowManager )
97 InitFloatingWindows() ;
98 else
99 InitWindows();
100 #endif
101
102 if ( NavServicesAvailable() )
103 {
104 NavLoad() ;
105 }
106
107 if ( TXNInitTextension != (void*) kUnresolvedCFragSymbolAddress )
108 {
109 FontFamilyID fontId ;
110 Str255 fontName ;
111 SInt16 fontSize ;
112 Style fontStyle ;
113 GetThemeFont(kThemeSmallSystemFont , GetApplicationScript() , fontName , &fontSize , &fontStyle ) ;
114 GetFNum( fontName, &fontId );
115
116 TXNMacOSPreferredFontDescription fontDescriptions[] =
117 {
118 { fontId , (fontSize << 16) ,kTXNDefaultFontStyle, kTXNSystemDefaultEncoding } ,
119 } ;
120 int noOfFontDescriptions = sizeof( fontDescriptions ) / sizeof(TXNMacOSPreferredFontDescription) ;
121 #if TARGET_CARBON
122 --noOfFontDescriptions ;
123 #endif
124 // kTXNAlwaysUseQuickDrawTextMask might be desirable because of speed increases but it crashes the app under OS X upon key stroke
125 TXNInitTextension(fontDescriptions, noOfFontDescriptions, ( kTXNWantMoviesMask | kTXNWantSoundMask | kTXNWantGraphicsMask));
126 }
127
128 long menuMgrAttr ;
129 Gestalt( gestaltMenuMgrAttr , &menuMgrAttr ) ;
130 if ( menuMgrAttr & gestaltMenuMgrAquaLayoutMask )
131 sUMAHasAquaLayout = true ;
132 sUMASystemInitialized = true ;
133
134 }
135
136 /*
137 Boolean CanUseATSUI()
138 {
139 long result;
140 OSErr err = Gestalt(gestaltATSUVersion, &result);
141 return (err == noErr);
142 }
143 */
144 // process manager
145 long UMAGetProcessMode()
146 {
147 OSErr err ;
148 ProcessInfoRec processinfo;
149 ProcessSerialNumber procno ;
150
151 procno.highLongOfPSN = NULL ;
152 procno.lowLongOfPSN = kCurrentProcess ;
153 processinfo.processInfoLength = sizeof(ProcessInfoRec);
154 processinfo.processName = NULL;
155 processinfo.processAppSpec = NULL;
156
157 err = ::GetProcessInformation( &procno , &processinfo ) ;
158 wxASSERT( err == noErr ) ;
159 return processinfo.processMode ;
160 }
161
162 bool UMAGetProcessModeDoesActivateOnFGSwitch()
163 {
164 return UMAGetProcessMode() & modeDoesActivateOnFGSwitch ;
165 }
166
167 // menu manager
168
169 void UMASetMenuTitle( MenuRef menu , StringPtr title )
170 {
171 /*
172 #if !TARGET_CARBON
173 long size = GetHandleSize( (Handle) menu ) ;
174 const long headersize = 14 ;
175 int oldlen = (**menu).menuData[0] + 1;
176 int newlen = title[0] + 1 ;
177
178 if ( oldlen < newlen )
179 {
180 // enlarge before adjusting
181 SetHandleSize( (Handle) menu , size + (newlen - oldlen ) );
182 }
183
184 if ( oldlen != newlen )
185 memmove( (char*) (**menu).menuData + newlen , (char*) (**menu).menuData + oldlen , size - headersize - oldlen ) ;
186
187 memcpy( (char*) (**menu).menuData , title , newlen ) ;
188 if ( oldlen > newlen )
189 {
190 // shrink after
191 SetHandleSize( (Handle) menu , size + (newlen - oldlen ) ) ;
192 }
193 #else
194 */
195 SetMenuTitle( menu , title ) ;
196 //#endif
197 }
198
199 UInt32 UMAMenuEvent( EventRecord *inEvent )
200 {
201 return MenuEvent( inEvent ) ;
202 }
203
204 void UMAEnableMenuItem( MenuRef inMenu , MenuItemIndex inItem )
205 {
206 EnableMenuItem( inMenu , inItem ) ;
207 }
208
209 void UMADisableMenuItem( MenuRef inMenu , MenuItemIndex inItem )
210 {
211 DisableMenuItem( inMenu , inItem ) ;
212 }
213
214 void UMAAppendSubMenuItem( MenuRef menu , StringPtr l , SInt16 id )
215 {
216 Str255 label ;
217 memcpy( label , l , l[0]+1 ) ;
218 // hardcoded adding of the submenu combination for mac
219
220 int theEnd = label[0] + 1;
221 if (theEnd > 251)
222 theEnd = 251; // mac allows only 255 characters
223 label[theEnd++] = '/';
224 label[theEnd++] = hMenuCmd;
225 label[theEnd++] = '!';
226 label[theEnd++] = id ;
227 label[theEnd] = 0x00;
228 label[0] = theEnd;
229 MacAppendMenu(menu, label);
230 }
231
232 void UMAInsertSubMenuItem( MenuRef menu , StringPtr l , MenuItemIndex item , SInt16 id )
233 {
234 Str255 label ;
235 memcpy( label , l , l[0]+1 ) ;
236 // hardcoded adding of the submenu combination for mac
237
238 int theEnd = label[0] + 1;
239 if (theEnd > 251)
240 theEnd = 251; // mac allows only 255 characters
241 label[theEnd++] = '/';
242 label[theEnd++] = hMenuCmd;
243 label[theEnd++] = '!';
244 label[theEnd++] = id;
245 label[theEnd] = 0x00;
246 label[0] = theEnd;
247 MacInsertMenuItem(menu, label , item);
248 }
249
250 void UMAAppendMenuItem( MenuRef menu , StringPtr l , SInt16 key, UInt8 modifiers )
251 {
252 Str255 label ;
253 memcpy( label , l , l[0]+1 ) ;
254 if ( key )
255 {
256 int pos = label[0] ;
257 label[++pos] = '/';
258 label[++pos] = toupper( key );
259 label[0] = pos ;
260 }
261 MacAppendMenu( menu , label ) ;
262 }
263
264 void UMAInsertMenuItem( MenuRef menu , StringPtr l , MenuItemIndex item , SInt16 key, UInt8 modifiers )
265 {
266 Str255 label ;
267 memcpy( label , l , l[0]+1 ) ;
268 if ( key )
269 {
270 int pos = label[0] ;
271 label[++pos] = '/';
272 label[++pos] = toupper( key );
273 label[0] = pos ;
274 }
275 MacInsertMenuItem( menu , label , item) ;
276 }
277
278 // quickdraw
279
280 int gPrOpenCounter = 0 ;
281
282 OSStatus UMAPrOpen(void *macPrintSession)
283 {
284 #if !TARGET_CARBON
285 OSErr err = noErr ;
286 ++gPrOpenCounter ;
287 if ( gPrOpenCounter == 1 )
288 {
289 PrOpen() ;
290 err = PrError() ;
291 wxASSERT( err == noErr ) ;
292 }
293 return err ;
294 #else
295 OSStatus err = noErr ;
296 ++gPrOpenCounter ;
297 if ( gPrOpenCounter == 1 )
298 {
299 #if PM_USE_SESSION_APIS
300 err = PMCreateSession((PMPrintSession *)macPrintSession) ;
301 #else
302 err = PMBegin() ;
303 #endif
304 wxASSERT( err == noErr ) ;
305 }
306 return err ;
307 #endif
308 }
309
310 OSStatus UMAPrClose(void *macPrintSession)
311 {
312 #if !TARGET_CARBON
313 OSErr err = noErr ;
314 wxASSERT( gPrOpenCounter >= 1 ) ;
315 if ( gPrOpenCounter == 1 )
316 {
317 PrClose() ;
318 err = PrError() ;
319 wxASSERT( err == noErr ) ;
320 }
321 --gPrOpenCounter ;
322 return err ;
323 #else
324 OSStatus err = noErr ;
325 wxASSERT( gPrOpenCounter >= 1 ) ;
326 if ( gPrOpenCounter == 1 )
327 {
328 #if PM_USE_SESSION_APIS
329 err = PMRelease(*(PMPrintSession *)macPrintSession) ;
330 *(PMPrintSession *)macPrintSession = kPMNoReference;
331 #else
332 err = PMEnd() ;
333 #endif
334 }
335 --gPrOpenCounter ;
336 return err ;
337 #endif
338 }
339
340 #if !TARGET_CARBON
341
342 pascal QDGlobalsPtr GetQDGlobalsPtr (void) ;
343 pascal QDGlobalsPtr GetQDGlobalsPtr (void)
344 {
345 return QDGlobalsPtr (* (Ptr*) LMGetCurrentA5 ( ) - 0xCA);
346 }
347
348 #endif
349
350 void UMAShowWatchCursor()
351 {
352 OSErr err = noErr;
353
354 CursHandle watchFob = GetCursor (watchCursor);
355
356 if (!watchFob)
357 err = nilHandleErr;
358 else
359 {
360 #if TARGET_CARBON
361 // Cursor preservedArrow;
362 // GetQDGlobalsArrow (&preservedArrow);
363 // SetQDGlobalsArrow (*watchFob);
364 // InitCursor ( );
365 // SetQDGlobalsArrow (&preservedArrow);
366 SetCursor (*watchFob);
367 #else
368 SetCursor (*watchFob);
369 #endif
370 }
371 }
372
373 void UMAShowArrowCursor()
374 {
375 #if TARGET_CARBON
376 Cursor arrow;
377 SetCursor (GetQDGlobalsArrow (&arrow));
378 #else
379 SetCursor (&(qd.arrow));
380 #endif
381 }
382
383 // window manager
384
385 GrafPtr UMAGetWindowPort( WindowRef inWindowRef )
386 {
387 wxASSERT( inWindowRef != NULL ) ;
388 #if TARGET_CARBON
389 return (GrafPtr) GetWindowPort( inWindowRef ) ;
390 #else
391 return (GrafPtr) inWindowRef ;
392 #endif
393 }
394
395 void UMADisposeWindow( WindowRef inWindowRef )
396 {
397 wxASSERT( inWindowRef != NULL ) ;
398 DisposeWindow( inWindowRef ) ;
399 }
400
401 void UMASetWTitleC( WindowRef inWindowRef , const char *title )
402 {
403 Str255 ptitle ;
404 strncpy( (char*)ptitle , title , 96 ) ;
405 ptitle[96] = 0 ;
406 #if TARGET_CARBON
407 c2pstrcpy( ptitle, (char *)ptitle ) ;
408 #else
409 c2pstr( (char*)ptitle ) ;
410 #endif
411 SetWTitle( inWindowRef , ptitle ) ;
412 }
413
414 void UMAGetWTitleC( WindowRef inWindowRef , char *title )
415 {
416 GetWTitle( inWindowRef , (unsigned char*)title ) ;
417 #if TARGET_CARBON
418 p2cstrcpy( title, (unsigned char *)title ) ;
419 #else
420 p2cstr( (unsigned char*)title ) ;
421 #endif
422 }
423
424 // appearance additions
425
426 void UMAActivateControl( ControlHandle inControl )
427 {
428 // we have to add the control after again to the update rgn
429 // otherwise updates get lost
430 if ( !IsControlActive( inControl ) )
431 {
432 bool visible = IsControlVisible( inControl ) ;
433 if ( visible )
434 SetControlVisibility( inControl , false , false ) ;
435 ::ActivateControl( inControl ) ;
436 if ( visible ) {
437 SetControlVisibility( inControl , true , false ) ;
438 Rect ctrlBounds ;
439 InvalWindowRect(GetControlOwner(inControl),GetControlBounds(inControl,&ctrlBounds) ) ;
440 }
441 }
442 }
443
444 void UMADrawControl( ControlHandle inControl )
445 {
446 WindowRef theWindow = GetControlOwner(inControl) ;
447 RgnHandle updateRgn = NewRgn() ;
448 GetWindowUpdateRgn( theWindow , updateRgn ) ;
449 Point zero = { 0 , 0 } ;
450 LocalToGlobal( &zero ) ;
451 OffsetRgn( updateRgn , -zero.h , -zero.v ) ;
452 ::DrawControlInCurrentPort( inControl ) ;
453 InvalWindowRgn( theWindow, updateRgn) ;
454 DisposeRgn( updateRgn ) ;
455 }
456
457 void UMAMoveControl( ControlHandle inControl , short x , short y )
458 {
459 bool visible = IsControlVisible( inControl ) ;
460 if ( visible ) {
461 SetControlVisibility( inControl , false , false ) ;
462 Rect ctrlBounds ;
463 InvalWindowRect(GetControlOwner(inControl),GetControlBounds(inControl,&ctrlBounds) ) ;
464 }
465 ::MoveControl( inControl , x , y ) ;
466 if ( visible ) {
467 SetControlVisibility( inControl , true , false ) ;
468 Rect ctrlBounds ;
469 InvalWindowRect(GetControlOwner(inControl),GetControlBounds(inControl,&ctrlBounds) ) ;
470 }
471 }
472
473 void UMASizeControl( ControlHandle inControl , short x , short y )
474 {
475 bool visible = IsControlVisible( inControl ) ;
476 if ( visible ) {
477 SetControlVisibility( inControl , false , false ) ;
478 Rect ctrlBounds ;
479 InvalWindowRect(GetControlOwner(inControl),GetControlBounds(inControl,&ctrlBounds) ) ;
480 }
481 ::SizeControl( inControl , x , y ) ;
482 if ( visible ) {
483 SetControlVisibility( inControl , true , false ) ;
484 Rect ctrlBounds ;
485 InvalWindowRect(GetControlOwner(inControl),GetControlBounds(inControl,&ctrlBounds) ) ;
486 }
487 }
488
489 void UMADeactivateControl( ControlHandle inControl )
490 {
491 // we have to add the control after again to the update rgn
492 // otherwise updates get lost
493 bool visible = IsControlVisible( inControl ) ;
494 if ( visible )
495 SetControlVisibility( inControl , false , false ) ;
496 ::DeactivateControl( inControl ) ;
497 if ( visible ) {
498 SetControlVisibility( inControl , true , false ) ;
499 Rect ctrlBounds ;
500 InvalWindowRect(GetControlOwner(inControl),GetControlBounds(inControl,&ctrlBounds) ) ;
501 }
502 }
503 // shows the control and adds the region to the update region
504 void UMAShowControl (ControlHandle inControl)
505 {
506 SetControlVisibility( inControl , true , false ) ;
507 Rect ctrlBounds ;
508 InvalWindowRect(GetControlOwner(inControl),GetControlBounds(inControl,&ctrlBounds) ) ;
509 }
510
511 // shows the control and adds the region to the update region
512 void UMAHideControl (ControlHandle inControl)
513 {
514 SetControlVisibility( inControl , false , false ) ;
515 Rect ctrlBounds ;
516 InvalWindowRect(GetControlOwner(inControl),GetControlBounds(inControl,&ctrlBounds) ) ;
517 }
518 // keyboard focus
519 OSErr UMASetKeyboardFocus (WindowPtr inWindow,
520 ControlHandle inControl,
521 ControlFocusPart inPart)
522 {
523 OSErr err = noErr;
524 GrafPtr port ;
525 GetPort( &port ) ;
526
527 SetPortWindowPort( inWindow ) ;
528
529 err = SetKeyboardFocus( inWindow , inControl , inPart ) ;
530 SetPort( port ) ;
531 return err ;
532 }
533
534
535
536
537 // events
538 void UMAUpdateControls( WindowPtr inWindow , RgnHandle inRgn )
539 {
540 RgnHandle updateRgn = NewRgn() ;
541 GetWindowUpdateRgn( inWindow , updateRgn ) ;
542
543 Point zero = { 0 , 0 } ;
544 LocalToGlobal( &zero ) ;
545 OffsetRgn( updateRgn , -zero.h , -zero.v ) ;
546
547 UpdateControls( inWindow , inRgn ) ;
548 InvalWindowRgn( inWindow, updateRgn) ;
549 DisposeRgn( updateRgn ) ;
550
551 }
552
553 bool UMAIsWindowFloating( WindowRef inWindow )
554 {
555 WindowClass cl ;
556
557 GetWindowClass( inWindow , &cl ) ;
558 return cl == kFloatingWindowClass ;
559 }
560
561 bool UMAIsWindowModal( WindowRef inWindow )
562 {
563 WindowClass cl ;
564
565 GetWindowClass( inWindow , &cl ) ;
566 return cl < kFloatingWindowClass ;
567 }
568
569 // others
570
571 void UMAHighlightAndActivateWindow( WindowRef inWindowRef , bool inActivate )
572 {
573 if ( inWindowRef )
574 {
575 // bool isHighlighted = IsWindowHighlited( inWindowRef ) ;
576 // if ( inActivate != isHightlited )
577 GrafPtr port ;
578 GetPort( &port ) ;
579 SetPortWindowPort( inWindowRef ) ;
580 HiliteWindow( inWindowRef , inActivate ) ;
581 ControlHandle control = NULL ;
582 ::GetRootControl( inWindowRef , & control ) ;
583 if ( control )
584 {
585 if ( inActivate )
586 UMAActivateControl( control ) ;
587 else
588 UMADeactivateControl( control ) ;
589 }
590 SetPort( port ) ;
591 }
592 }
593 OSStatus UMADrawThemePlacard( const Rect *inRect , ThemeDrawState inState )
594 {
595 return ::DrawThemePlacard( inRect , inState ) ;
596 }
597
598 #if !TARGET_CARBON
599 static OSStatus helpMenuStatus = noErr ;
600 static MenuItemIndex firstCustomItemIndex = 0 ;
601 #endif
602
603 OSStatus UMAGetHelpMenu(
604 MenuRef * outHelpMenu,
605 MenuItemIndex * outFirstCustomItemIndex)
606 {
607 #if TARGET_CARBON
608 return HMGetHelpMenu( outHelpMenu , outFirstCustomItemIndex ) ;
609 #else
610 MenuRef helpMenuHandle ;
611 helpMenuStatus = HMGetHelpMenuHandle( &helpMenuHandle ) ;
612 if ( firstCustomItemIndex == 0 && helpMenuStatus == noErr )
613 {
614 firstCustomItemIndex = CountMenuItems( helpMenuHandle ) + 1 ;
615 }
616 if ( outFirstCustomItemIndex )
617 {
618 *outFirstCustomItemIndex = firstCustomItemIndex ;
619 }
620 *outHelpMenu = helpMenuHandle ;
621 return helpMenuStatus ;
622 #endif
623 }
624
625 wxMacPortStateHelper::wxMacPortStateHelper( GrafPtr newport)
626 {
627 m_clip = NULL ;
628 Setup( newport ) ;
629 }
630
631 wxMacPortStateHelper::wxMacPortStateHelper()
632 {
633 m_clip = NULL ;
634 }
635
636 void wxMacPortStateHelper::Setup( GrafPtr newport )
637 {
638 GetPort( &m_oldPort ) ;
639 SetPort( newport ) ;
640 wxASSERT_MSG( m_clip == NULL , "Cannot call setup twice" ) ;
641 m_clip = NewRgn() ;
642 GetClip( m_clip );
643 m_textFont = GetPortTextFont( (CGrafPtr) newport);
644 m_textSize = GetPortTextSize( (CGrafPtr) newport);
645 m_textStyle = GetPortTextFace( (CGrafPtr) newport);
646 m_textMode = GetPortTextMode( (CGrafPtr) newport);
647 GetThemeDrawingState( &m_drawingState ) ;
648 m_currentPort = newport ;
649 }
650 void wxMacPortStateHelper::Clear()
651 {
652 if ( m_clip )
653 {
654 DisposeRgn( m_clip ) ;
655 DisposeThemeDrawingState( m_drawingState ) ;
656 m_clip = NULL ;
657 }
658 }
659
660 wxMacPortStateHelper::~wxMacPortStateHelper()
661 {
662 if ( m_clip )
663 {
664 SetPort( m_currentPort ) ;
665 SetClip( m_clip ) ;
666 DisposeRgn( m_clip ) ;
667 TextFont( m_textFont );
668 TextSize( m_textSize );
669 TextFace( m_textStyle );
670 TextMode( m_textMode );
671 SetThemeDrawingState( m_drawingState , true ) ;
672 SetPort( m_oldPort ) ;
673 }
674 }
675