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