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