]> git.saurik.com Git - wxWidgets.git/blob - src/mac/carbon/utils.cpp
must be static of course, otherwise items just get appended for every menu-build
[wxWidgets.git] / src / mac / carbon / utils.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: utils.cpp
3 // Purpose: Various utilities
4 // Author: Stefan Csomor
5 // Modified by:
6 // Created: 1998-01-01
7 // RCS-ID: $Id$
8 // Copyright: (c) Stefan Csomor
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
13 // Note: this is done in utilscmn.cpp now.
14 // #pragma implementation "utils.h"
15 #endif
16
17 #include "wx/wxprec.h"
18
19 #include "wx/utils.h"
20 #include "wx/app.h"
21 #include "wx/apptrait.h"
22
23 #if wxUSE_GUI
24 #include "wx/mac/uma.h"
25 #include "wx/font.h"
26 #include "wx/toplevel.h"
27 #else
28 #include "wx/intl.h"
29 #endif
30
31 #include <ctype.h>
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <stdarg.h>
37
38 #include "MoreFilesX.h"
39
40 #ifndef __DARWIN__
41 #include <Threads.h>
42 #include <Sound.h>
43 #endif
44
45 #if wxUSE_GUI
46 #if TARGET_API_MAC_OSX
47 #include <CoreServices/CoreServices.h>
48 #else
49 #include <DriverServices.h>
50 #include <Multiprocessing.h>
51 #endif
52
53 #include <ATSUnicode.h>
54 #include <TextCommon.h>
55 #include <TextEncodingConverter.h>
56 #endif // wxUSE_GUI
57
58 #include "wx/mac/private.h" // includes mac headers
59
60 #if defined(__MWERKS__) && wxUSE_UNICODE
61 #include <wtime.h>
62 #endif
63
64 // ---------------------------------------------------------------------------
65 // code used in both base and GUI compilation
66 // ---------------------------------------------------------------------------
67
68 // our OS version is the same in non GUI and GUI cases
69 static int DoGetOSVersion(int *majorVsn, int *minorVsn)
70 {
71 long theSystem ;
72
73 // are there x-platform conventions ?
74
75 Gestalt(gestaltSystemVersion, &theSystem) ;
76 if (minorVsn != NULL) {
77 *minorVsn = (theSystem & 0xFF ) ;
78 }
79 if (majorVsn != NULL) {
80 *majorVsn = (theSystem >> 8 ) ;
81 }
82 #ifdef __DARWIN__
83 return wxMAC_DARWIN;
84 #else
85 return wxMAC;
86 #endif
87 }
88
89
90 #if wxUSE_BASE
91
92 // ----------------------------------------------------------------------------
93 // debugging support
94 // ----------------------------------------------------------------------------
95
96 #if defined(__WXDEBUG__) && defined(__WXMAC__) && !defined(__DARWIN__) && defined(__MWERKS__) && (__MWERKS__ >= 0x2400)
97
98 // MetroNub stuff doesn't seem to work in CodeWarrior 5.3 Carbon builds...
99
100 #ifndef __MetroNubUtils__
101 #include "MetroNubUtils.h"
102 #endif
103
104 #ifndef __GESTALT__
105 #include <Gestalt.h>
106 #endif
107
108 #if TARGET_API_MAC_CARBON
109
110 #include <CodeFragments.h>
111
112 extern "C" long CallUniversalProc(UniversalProcPtr theProcPtr, ProcInfoType procInfo, ...);
113
114 ProcPtr gCallUniversalProc_Proc = NULL;
115
116 #endif
117
118 static MetroNubUserEntryBlock* gMetroNubEntry = NULL;
119
120 static long fRunOnce = false;
121
122 /* ---------------------------------------------------------------------------
123 IsMetroNubInstalled
124 --------------------------------------------------------------------------- */
125
126 Boolean IsMetroNubInstalled()
127 {
128 if (!fRunOnce)
129 {
130 long result, value;
131
132 fRunOnce = true;
133 gMetroNubEntry = NULL;
134
135 if (Gestalt(gestaltSystemVersion, &value) == noErr && value < 0x1000)
136 {
137 /* look for MetroNub's Gestalt selector */
138 if (Gestalt(kMetroNubUserSignature, &result) == noErr)
139 {
140
141 #if TARGET_API_MAC_CARBON
142 if (gCallUniversalProc_Proc == NULL)
143 {
144 CFragConnectionID connectionID;
145 Ptr mainAddress;
146 Str255 errorString;
147 ProcPtr symbolAddress;
148 OSErr err;
149 CFragSymbolClass symbolClass;
150
151 symbolAddress = NULL;
152 err = GetSharedLibrary("\pInterfaceLib", kPowerPCCFragArch, kFindCFrag,
153 &connectionID, &mainAddress, errorString);
154
155 if (err != noErr)
156 {
157 gCallUniversalProc_Proc = NULL;
158 goto end;
159 }
160
161 err = FindSymbol(connectionID, "\pCallUniversalProc",
162 (Ptr *) &gCallUniversalProc_Proc, &symbolClass);
163
164 if (err != noErr)
165 {
166 gCallUniversalProc_Proc = NULL;
167 goto end;
168 }
169 }
170 #endif
171
172 {
173 MetroNubUserEntryBlock* block = (MetroNubUserEntryBlock *)result;
174
175 /* make sure the version of the API is compatible */
176 if (block->apiLowVersion <= kMetroNubUserAPIVersion &&
177 kMetroNubUserAPIVersion <= block->apiHiVersion)
178 gMetroNubEntry = block; /* success! */
179 }
180
181 }
182 }
183 }
184
185 end:
186
187 #if TARGET_API_MAC_CARBON
188 return (gMetroNubEntry != NULL && gCallUniversalProc_Proc != NULL);
189 #else
190 return (gMetroNubEntry != NULL);
191 #endif
192 }
193
194 /* ---------------------------------------------------------------------------
195 IsMWDebuggerRunning [v1 API]
196 --------------------------------------------------------------------------- */
197
198 Boolean IsMWDebuggerRunning()
199 {
200 if (IsMetroNubInstalled())
201 return CallIsDebuggerRunningProc(gMetroNubEntry->isDebuggerRunning);
202 else
203 return false;
204 }
205
206 /* ---------------------------------------------------------------------------
207 AmIBeingMWDebugged [v1 API]
208 --------------------------------------------------------------------------- */
209
210 Boolean AmIBeingMWDebugged()
211 {
212 if (IsMetroNubInstalled())
213 return CallAmIBeingDebuggedProc(gMetroNubEntry->amIBeingDebugged);
214 else
215 return false;
216 }
217
218 extern bool WXDLLEXPORT wxIsDebuggerRunning()
219 {
220 return IsMWDebuggerRunning() && AmIBeingMWDebugged();
221 }
222
223 #else
224
225 extern bool WXDLLEXPORT wxIsDebuggerRunning()
226 {
227 return false;
228 }
229
230 #endif // defined(__WXMAC__) && !defined(__DARWIN__) && (__MWERKS__ >= 0x2400)
231
232
233 #ifndef __DARWIN__
234 // defined in unix/utilsunx.cpp for Mac OS X
235
236 // get full hostname (with domain name if possible)
237 bool wxGetFullHostName(wxChar *buf, int maxSize)
238 {
239 return wxGetHostName(buf, maxSize);
240 }
241
242 // Get hostname only (without domain name)
243 bool wxGetHostName(wxChar *buf, int maxSize)
244 {
245 // Gets Chooser name of user by examining a System resource.
246
247 const short kComputerNameID = -16413;
248
249 short oldResFile = CurResFile() ;
250 UseResFile(0);
251 StringHandle chooserName = (StringHandle)::GetString(kComputerNameID);
252 UseResFile(oldResFile);
253
254 if (chooserName && *chooserName)
255 {
256 HLock( (Handle) chooserName ) ;
257 wxString name = wxMacMakeStringFromPascal( *chooserName ) ;
258 HUnlock( (Handle) chooserName ) ;
259 ReleaseResource( (Handle) chooserName ) ;
260 wxStrncpy( buf , name , maxSize - 1 ) ;
261 }
262 else
263 buf[0] = 0 ;
264
265 return true;
266 }
267
268 // Get user ID e.g. jacs
269 bool wxGetUserId(wxChar *buf, int maxSize)
270 {
271 return wxGetUserName( buf , maxSize ) ;
272 }
273
274 const wxChar* wxGetHomeDir(wxString *pstr)
275 {
276 *pstr = wxMacFindFolder( (short) kOnSystemDisk, kPreferencesFolderType, kDontCreateFolder ) ;
277 return pstr->c_str() ;
278 }
279
280 // Get user name e.g. Stefan Csomor
281 bool wxGetUserName(wxChar *buf, int maxSize)
282 {
283 // Gets Chooser name of user by examining a System resource.
284
285 const short kChooserNameID = -16096;
286
287 short oldResFile = CurResFile() ;
288 UseResFile(0);
289 StringHandle chooserName = (StringHandle)::GetString(kChooserNameID);
290 UseResFile(oldResFile);
291
292 if (chooserName && *chooserName)
293 {
294 HLock( (Handle) chooserName ) ;
295 wxString name = wxMacMakeStringFromPascal( *chooserName ) ;
296 HUnlock( (Handle) chooserName ) ;
297 ReleaseResource( (Handle) chooserName ) ;
298 wxStrncpy( buf , name , maxSize - 1 ) ;
299 }
300 else
301 buf[0] = 0 ;
302
303 return true;
304 }
305
306 int wxKill(long pid, wxSignal sig , wxKillError *rc, int flags)
307 {
308 // TODO
309 return 0;
310 }
311
312 WXDLLEXPORT bool wxGetEnv(const wxString& var, wxString *value)
313 {
314 // TODO : under classic there is no environement support, under X yes
315 return false ;
316 }
317
318 // set the env var name to the given value, return true on success
319 WXDLLEXPORT bool wxSetEnv(const wxString& var, const wxChar *value)
320 {
321 // TODO : under classic there is no environement support, under X yes
322 return false ;
323 }
324
325 //
326 // Execute a program in an Interactive Shell
327 //
328 bool wxShell(const wxString& command)
329 {
330 // TODO
331 return false;
332 }
333
334 // Shutdown or reboot the PC
335 bool wxShutdown(wxShutdownFlags wFlags)
336 {
337 // TODO
338 return false;
339 }
340
341 wxPowerType wxGetPowerType()
342 {
343 // TODO
344 return wxPOWER_UNKNOWN;
345 }
346
347 wxBatteryState wxGetBatteryState()
348 {
349 // TODO
350 return wxBATTERY_UNKNOWN_STATE;
351 }
352
353 // Get free memory in bytes, or -1 if cannot determine amount (e.g. on UNIX)
354 wxMemorySize wxGetFreeMemory()
355 {
356 return (wxMemorySize)FreeMem() ;
357 }
358
359 #ifndef __DARWIN__
360
361 void wxMicroSleep(unsigned long microseconds)
362 {
363 AbsoluteTime wakeup = AddDurationToAbsolute( microseconds * durationMicrosecond , UpTime());
364 MPDelayUntil( & wakeup);
365 }
366
367 void wxMilliSleep(unsigned long milliseconds)
368 {
369 AbsoluteTime wakeup = AddDurationToAbsolute( milliseconds, UpTime());
370 MPDelayUntil( & wakeup);
371 }
372
373 void wxSleep(int nSecs)
374 {
375 wxMilliSleep(1000*nSecs);
376 }
377
378 #endif
379
380 // Consume all events until no more left
381 void wxFlushEvents()
382 {
383 }
384
385 #endif // !__DARWIN__
386
387 // Emit a beeeeeep
388 void wxBell()
389 {
390 SysBeep(30);
391 }
392
393 wxToolkitInfo& wxConsoleAppTraits::GetToolkitInfo()
394 {
395 static wxToolkitInfo info;
396 info.os = DoGetOSVersion(&info.versionMajor, &info.versionMinor);
397 info.name = _T("wxBase");
398 return info;
399 }
400
401 #endif // wxUSE_BASE
402
403 #if wxUSE_GUI
404
405 wxToolkitInfo& wxGUIAppTraits::GetToolkitInfo()
406 {
407 static wxToolkitInfo info;
408 info.os = DoGetOSVersion(&info.versionMajor, &info.versionMinor);
409 info.shortName = _T("mac");
410 info.name = _T("wxMac");
411 #ifdef __WXUNIVERSAL__
412 info.shortName << _T("univ");
413 info.name << _T("/wxUniversal");
414 #endif
415 return info;
416 }
417
418 // Reading and writing resources (eg WIN.INI, .Xdefaults)
419 #if wxUSE_RESOURCES
420 bool wxWriteResource(const wxString& section, const wxString& entry, const wxString& value, const wxString& file)
421 {
422 // TODO
423 return false;
424 }
425
426 bool wxWriteResource(const wxString& section, const wxString& entry, float value, const wxString& file)
427 {
428 wxString buf;
429 buf.Printf(wxT("%.4f"), value);
430
431 return wxWriteResource(section, entry, buf, file);
432 }
433
434 bool wxWriteResource(const wxString& section, const wxString& entry, long value, const wxString& file)
435 {
436 wxString buf;
437 buf.Printf(wxT("%ld"), value);
438
439 return wxWriteResource(section, entry, buf, file);
440 }
441
442 bool wxWriteResource(const wxString& section, const wxString& entry, int value, const wxString& file)
443 {
444 wxString buf;
445 buf.Printf(wxT("%d"), value);
446
447 return wxWriteResource(section, entry, buf, file);
448 }
449
450 bool wxGetResource(const wxString& section, const wxString& entry, char **value, const wxString& file)
451 {
452 // TODO
453 return false;
454 }
455
456 bool wxGetResource(const wxString& section, const wxString& entry, float *value, const wxString& file)
457 {
458 char *s = NULL;
459 bool succ = wxGetResource(section, entry, (char **)&s, file);
460 if (succ)
461 {
462 *value = (float)strtod(s, NULL);
463 delete[] s;
464 return true;
465 }
466 else return false;
467 }
468
469 bool wxGetResource(const wxString& section, const wxString& entry, long *value, const wxString& file)
470 {
471 char *s = NULL;
472 bool succ = wxGetResource(section, entry, (char **)&s, file);
473 if (succ)
474 {
475 *value = strtol(s, NULL, 10);
476 delete[] s;
477 return true;
478 }
479 else return false;
480 }
481
482 bool wxGetResource(const wxString& section, const wxString& entry, int *value, const wxString& file)
483 {
484 char *s = NULL;
485 bool succ = wxGetResource(section, entry, (char **)&s, file);
486 if (succ)
487 {
488 *value = (int)strtol(s, NULL, 10);
489 delete[] s;
490 return true;
491 }
492 else return false;
493 }
494 #endif // wxUSE_RESOURCES
495
496 int gs_wxBusyCursorCount = 0;
497 extern wxCursor gMacCurrentCursor ;
498 wxCursor gMacStoredActiveCursor ;
499
500 // Set the cursor to the busy cursor for all windows
501 void wxBeginBusyCursor(wxCursor *cursor)
502 {
503 if (gs_wxBusyCursorCount++ == 0)
504 {
505 gMacStoredActiveCursor = gMacCurrentCursor ;
506 cursor->MacInstall() ;
507 }
508 //else: nothing to do, already set
509 }
510
511 // Restore cursor to normal
512 void wxEndBusyCursor()
513 {
514 wxCHECK_RET( gs_wxBusyCursorCount > 0,
515 wxT("no matching wxBeginBusyCursor() for wxEndBusyCursor()") );
516
517 if (--gs_wxBusyCursorCount == 0)
518 {
519 gMacStoredActiveCursor.MacInstall() ;
520 gMacStoredActiveCursor = wxNullCursor ;
521 }
522 }
523
524 // true if we're between the above two calls
525 bool wxIsBusy()
526 {
527 return (gs_wxBusyCursorCount > 0);
528 }
529
530 #endif // wxUSE_GUI
531
532 #if wxUSE_BASE
533
534 wxString wxMacFindFolder( short vol,
535 OSType folderType,
536 Boolean createFolder)
537 {
538 FSRef fsRef ;
539 wxString strDir ;
540
541 if ( FSFindFolder( vol, folderType, createFolder, &fsRef) == noErr)
542 strDir = wxMacFSRefToPath( &fsRef ) + wxFILE_SEP_PATH ;
543
544 return strDir ;
545 }
546
547 #endif // wxUSE_BASE
548
549 #if wxUSE_GUI
550
551 // Check whether this window wants to process messages, e.g. Stop button
552 // in long calculations.
553 bool wxCheckForInterrupt(wxWindow *wnd)
554 {
555 // TODO
556 return false;
557 }
558
559 void wxGetMousePosition( int* x, int* y )
560 {
561 Point pt ;
562
563 GetMouse( &pt ) ;
564 LocalToGlobal( &pt ) ;
565 *x = pt.h ;
566 *y = pt.v ;
567 };
568
569 // Return true if we have a colour display
570 bool wxColourDisplay()
571 {
572 return true;
573 }
574
575 // Returns depth of screen
576 int wxDisplayDepth()
577 {
578 Rect globRect ;
579 SetRect(&globRect, -32760, -32760, 32760, 32760);
580 GDHandle theMaxDevice;
581
582 int theDepth = 8;
583 theMaxDevice = GetMaxDevice(&globRect);
584 if (theMaxDevice != nil)
585 theDepth = (**(**theMaxDevice).gdPMap).pixelSize;
586
587 return theDepth ;
588 }
589
590 // Get size of display
591 void wxDisplaySize(int *width, int *height)
592 {
593 BitMap screenBits;
594 GetQDGlobalsScreenBits( &screenBits );
595
596 if (width != NULL) {
597 *width = screenBits.bounds.right - screenBits.bounds.left ;
598 }
599 if (height != NULL) {
600 *height = screenBits.bounds.bottom - screenBits.bounds.top ;
601 }
602 }
603
604 void wxDisplaySizeMM(int *width, int *height)
605 {
606 wxDisplaySize(width, height);
607 // on mac 72 is fixed (at least now ;-)
608 float cvPt2Mm = 25.4 / 72;
609
610 if (width != NULL) {
611 *width = int( *width * cvPt2Mm );
612 }
613 if (height != NULL) {
614 *height = int( *height * cvPt2Mm );
615 }
616 }
617
618 void wxClientDisplayRect(int *x, int *y, int *width, int *height)
619 {
620 Rect r ;
621 GetAvailableWindowPositioningBounds( GetMainDevice() , &r ) ;
622 if ( x )
623 *x = r.left ;
624 if ( y )
625 *y = r.top ;
626 if ( width )
627 *width = r.right - r.left ;
628 if ( height )
629 *height = r.bottom - r.top ;
630 }
631
632 wxWindow* wxFindWindowAtPoint(const wxPoint& pt)
633 {
634 return wxGenericFindWindowAtPoint(pt);
635 }
636
637 #endif // wxUSE_GUI
638
639 #if wxUSE_BASE
640
641 wxString wxGetOsDescription()
642 {
643 #ifdef WXWIN_OS_DESCRIPTION
644 // use configure generated description if available
645 return wxString(wxT("MacOS (")) + wxT(WXWIN_OS_DESCRIPTION) + wxString(wxT(")"));
646 #else
647 return wxT("MacOS") ; //TODO:define further
648 #endif
649 }
650
651 #ifndef __DARWIN__
652 wxChar *wxGetUserHome (const wxString& user)
653 {
654 // TODO
655 return NULL;
656 }
657
658 bool wxGetDiskSpace(const wxString& path, wxLongLong *pTotal, wxLongLong *pFree)
659 {
660 if ( path.empty() )
661 return false;
662
663 wxString p = path ;
664 if (p[0u] == ':' ) {
665 p = wxGetCwd() + p ;
666 }
667
668 int pos = p.Find(':') ;
669 if ( pos != wxNOT_FOUND ) {
670 p = p.Mid(1,pos) ;
671 }
672
673 p = p + wxT(":") ;
674
675 OSErr err = noErr ;
676
677 FSRef fsRef ;
678 err = wxMacPathToFSRef( p , &fsRef ) ;
679 if ( noErr == err )
680 {
681 FSVolumeRefNum vRefNum ;
682 err = FSGetVRefNum( &fsRef , &vRefNum ) ;
683 if ( noErr == err )
684 {
685 UInt64 freeBytes , totalBytes ;
686 err = FSGetVInfo( vRefNum , NULL , &freeBytes , &totalBytes ) ;
687 if ( noErr == err )
688 {
689 if ( pTotal )
690 *pTotal = wxLongLong( totalBytes ) ;
691 if ( pFree )
692 *pFree = wxLongLong( freeBytes ) ;
693 }
694 }
695 }
696
697 return err == noErr ;
698 }
699 #endif // !__DARWIN__
700
701 //---------------------------------------------------------------------------
702 // wxMac Specific utility functions
703 //---------------------------------------------------------------------------
704
705 void wxMacStringToPascal( const wxString&from , StringPtr to )
706 {
707 wxCharBuffer buf = from.mb_str( wxConvLocal ) ;
708 int len = strlen(buf) ;
709
710 if ( len > 255 )
711 len = 255 ;
712 to[0] = len ;
713 memcpy( (char*) &to[1] , buf , len ) ;
714 }
715
716 wxString wxMacMakeStringFromPascal( ConstStringPtr from )
717 {
718 return wxString( (char*) &from[1] , wxConvLocal , from[0] ) ;
719 }
720
721
722 // ----------------------------------------------------------------------------
723 // Common Event Support
724 // ----------------------------------------------------------------------------
725
726
727 extern ProcessSerialNumber gAppProcess ;
728
729 void wxMacWakeUp()
730 {
731 ProcessSerialNumber psn ;
732 Boolean isSame ;
733 psn.highLongOfPSN = 0 ;
734 psn.lowLongOfPSN = kCurrentProcess ;
735 SameProcess( &gAppProcess , &psn , &isSame ) ;
736 if ( isSame )
737 {
738 #if TARGET_CARBON
739 static wxMacCarbonEvent s_wakeupEvent ;
740 OSStatus err = noErr ;
741 if ( !s_wakeupEvent.IsValid() )
742 {
743 err = s_wakeupEvent.Create( 'WXMC', 'WXMC', GetCurrentEventTime(),
744 kEventAttributeNone ) ;
745 }
746 if ( err == noErr )
747 {
748 if ( IsEventInQueue( GetMainEventQueue() , s_wakeupEvent ) )
749 return ;
750 s_wakeupEvent.SetTime(0) ;
751 err = PostEventToQueue(GetMainEventQueue(), s_wakeupEvent,
752 kEventPriorityHigh);
753 }
754 #else
755 PostEvent( nullEvent , 0 ) ;
756 #endif
757 }
758 else
759 {
760 WakeUpProcess( &gAppProcess ) ;
761 }
762 }
763
764 #endif // wxUSE_BASE
765
766 #if wxUSE_GUI
767
768 // ----------------------------------------------------------------------------
769 // Native Struct Conversions
770 // ----------------------------------------------------------------------------
771
772
773 void wxMacRectToNative( const wxRect *wx , Rect *n )
774 {
775 n->left = wx->x ;
776 n->top = wx->y ;
777 n->right = wx->x + wx->width ;
778 n->bottom = wx->y + wx->height ;
779 }
780
781 void wxMacNativeToRect( const Rect *n , wxRect* wx )
782 {
783 wx->x = n->left ;
784 wx->y = n->top ;
785 wx->width = n->right - n->left ;
786 wx->height = n->bottom - n->top ;
787 }
788
789 void wxMacPointToNative( const wxPoint* wx , Point *n )
790 {
791 n->h = wx->x ;
792 n->v = wx->y ;
793 }
794
795 void wxMacNativeToPoint( const Point *n , wxPoint* wx )
796 {
797 wx->x = n->h ;
798 wx->y = n->v ;
799 }
800
801 // ----------------------------------------------------------------------------
802 // Carbon Event Support
803 // ----------------------------------------------------------------------------
804
805
806 OSStatus wxMacCarbonEvent::GetParameter(EventParamName inName, EventParamType inDesiredType, UInt32 inBufferSize, void * outData)
807 {
808 return ::GetEventParameter( m_eventRef , inName , inDesiredType , NULL , inBufferSize , NULL , outData ) ;
809 }
810
811 OSStatus wxMacCarbonEvent::SetParameter(EventParamName inName, EventParamType inType, UInt32 inBufferSize, const void * inData)
812 {
813 return ::SetEventParameter( m_eventRef , inName , inType , inBufferSize , inData ) ;
814 }
815
816 // ----------------------------------------------------------------------------
817 // Control Access Support
818 // ----------------------------------------------------------------------------
819
820 wxMacControl::wxMacControl(wxWindow* peer , bool isRootControl )
821 {
822 Init() ;
823 m_peer = peer ;
824 m_isRootControl = isRootControl ;
825 m_isCompositing = peer->MacGetTopLevelWindow()->MacUsesCompositing() ;
826 }
827
828 wxMacControl::wxMacControl( wxWindow* peer , ControlRef control )
829 {
830 Init() ;
831 m_peer = peer ;
832 m_isCompositing = peer->MacGetTopLevelWindow()->MacUsesCompositing() ;
833 m_controlRef = control ;
834 }
835
836 wxMacControl::wxMacControl( wxWindow* peer , WXWidget control )
837 {
838 Init() ;
839 m_peer = peer ;
840 m_isCompositing = peer->MacGetTopLevelWindow()->MacUsesCompositing() ;
841 m_controlRef = (ControlRef) control ;
842 }
843
844 wxMacControl::~wxMacControl()
845 {
846 }
847
848 void wxMacControl::Init()
849 {
850 m_peer = NULL ;
851 m_controlRef = NULL ;
852 m_needsFocusRect = false ;
853 m_isCompositing = false ;
854 m_isRootControl = false ;
855 }
856
857 void wxMacControl::Dispose()
858 {
859 ::DisposeControl( m_controlRef ) ;
860 m_controlRef = NULL ;
861 }
862
863 void wxMacControl::SetReference( SInt32 data )
864 {
865 SetControlReference( m_controlRef , data ) ;
866 }
867
868 OSStatus wxMacControl::GetData(ControlPartCode inPartCode , ResType inTag , Size inBufferSize , void * inOutBuffer , Size * outActualSize ) const
869 {
870 return ::GetControlData( m_controlRef , inPartCode , inTag , inBufferSize , inOutBuffer , outActualSize ) ;
871 }
872
873 OSStatus wxMacControl::GetDataSize(ControlPartCode inPartCode , ResType inTag , Size * outActualSize ) const
874 {
875 return ::GetControlDataSize( m_controlRef , inPartCode , inTag , outActualSize ) ;
876 }
877
878 OSStatus wxMacControl::SetData(ControlPartCode inPartCode , ResType inTag , Size inSize , const void * inData)
879 {
880 return ::SetControlData( m_controlRef , inPartCode , inTag , inSize , inData ) ;
881 }
882
883 OSStatus wxMacControl::SendEvent( EventRef event , OptionBits inOptions )
884 {
885 #if TARGET_API_MAC_OSX
886 return SendEventToEventTargetWithOptions( event,
887 HIObjectGetEventTarget( (HIObjectRef) m_controlRef ), inOptions );
888 #else
889 #pragma unused(inOptions)
890 return SendEventToEventTarget(event,GetControlEventTarget( m_controlRef ) ) ;
891 #endif
892 }
893
894 OSStatus wxMacControl::SendHICommand( HICommand &command , OptionBits inOptions )
895 {
896 wxMacCarbonEvent event( kEventClassCommand , kEventCommandProcess ) ;
897 event.SetParameter<HICommand>(kEventParamDirectObject,command) ;
898 return SendEvent( event , inOptions ) ;
899 }
900
901 OSStatus wxMacControl::SendHICommand( UInt32 commandID , OptionBits inOptions )
902 {
903 HICommand command ;
904 memset( &command, 0 , sizeof(command) ) ;
905 command.commandID = commandID ;
906 return SendHICommand( command , inOptions ) ;
907 }
908
909 void wxMacControl::Flash( ControlPartCode part , UInt32 ticks )
910 {
911 HiliteControl( m_controlRef , part ) ;
912 unsigned long finalTicks ;
913 Delay( ticks , &finalTicks ) ;
914 HiliteControl( m_controlRef , kControlNoPart ) ;
915 }
916
917 SInt32 wxMacControl::GetValue() const
918 {
919 return ::GetControl32BitValue( m_controlRef ) ;
920 }
921
922 SInt32 wxMacControl::GetMaximum() const
923 {
924 return ::GetControl32BitMaximum( m_controlRef ) ;
925 }
926
927 SInt32 wxMacControl::GetMinimum() const
928 {
929 return ::GetControl32BitMinimum( m_controlRef ) ;
930 }
931
932 void wxMacControl::SetValue( SInt32 v )
933 {
934 ::SetControl32BitValue( m_controlRef , v ) ;
935 }
936
937 void wxMacControl::SetMinimum( SInt32 v )
938 {
939 ::SetControl32BitMinimum( m_controlRef , v ) ;
940 }
941
942 void wxMacControl::SetMaximum( SInt32 v )
943 {
944 ::SetControl32BitMaximum( m_controlRef , v ) ;
945 }
946
947 void wxMacControl::SetValueAndRange( SInt32 value , SInt32 minimum , SInt32 maximum )
948 {
949 ::SetControl32BitMinimum( m_controlRef , minimum ) ;
950 ::SetControl32BitMaximum( m_controlRef , maximum ) ;
951 ::SetControl32BitValue( m_controlRef , value ) ;
952 }
953
954 OSStatus wxMacControl::SetFocus( ControlFocusPart focusPart )
955 {
956 return SetKeyboardFocus( GetControlOwner( m_controlRef ) ,
957 m_controlRef , focusPart ) ;
958 }
959
960 bool wxMacControl::HasFocus() const
961 {
962 ControlRef control ;
963 GetKeyboardFocus( GetUserFocusWindow() , &control ) ;
964 return control == m_controlRef ;
965 }
966
967 void wxMacControl::SetNeedsFocusRect( bool needs )
968 {
969 m_needsFocusRect = needs ;
970 }
971
972 bool wxMacControl::NeedsFocusRect() const
973 {
974 return m_needsFocusRect ;
975 }
976
977 void wxMacControl::VisibilityChanged(bool shown)
978 {
979 }
980
981 void wxMacControl::SuperChangedPosition()
982 {
983 }
984
985 void wxMacControl::SetFont( const wxFont & font , const wxColour& foreground , long windowStyle )
986 {
987 m_font = font ;
988 ControlFontStyleRec fontStyle;
989 if ( font.MacGetThemeFontID() != kThemeCurrentPortFont )
990 {
991 switch( font.MacGetThemeFontID() )
992 {
993 case kThemeSmallSystemFont : fontStyle.font = kControlFontSmallSystemFont ; break ;
994 case 109 /*mini font */ : fontStyle.font = -5 ; break ;
995 case kThemeSystemFont : fontStyle.font = kControlFontBigSystemFont ; break ;
996 default : fontStyle.font = kControlFontBigSystemFont ; break ;
997 }
998 fontStyle.flags = kControlUseFontMask ;
999 }
1000 else
1001 {
1002 fontStyle.font = font.MacGetFontNum() ;
1003 fontStyle.style = font.MacGetFontStyle() ;
1004 fontStyle.size = font.MacGetFontSize() ;
1005 fontStyle.flags = kControlUseFontMask | kControlUseFaceMask | kControlUseSizeMask ;
1006 }
1007
1008 fontStyle.just = teJustLeft ;
1009 fontStyle.flags |= kControlUseJustMask ;
1010 if ( ( windowStyle & wxALIGN_MASK ) & wxALIGN_CENTER_HORIZONTAL )
1011 fontStyle.just = teJustCenter ;
1012 else if ( ( windowStyle & wxALIGN_MASK ) & wxALIGN_RIGHT )
1013 fontStyle.just = teJustRight ;
1014
1015
1016 // we only should do this in case of a non-standard color, as otherwise 'disabled' controls
1017 // won't get grayed out by the system anymore
1018
1019 if ( foreground != *wxBLACK )
1020 {
1021 fontStyle.foreColor = MAC_WXCOLORREF(foreground.GetPixel() ) ;
1022 fontStyle.flags |= kControlUseForeColorMask ;
1023 }
1024
1025 ::SetControlFontStyle( m_controlRef , &fontStyle );
1026 }
1027
1028 void wxMacControl::SetBackground( const wxBrush &WXUNUSED(brush) )
1029 {
1030 // TODO
1031 // setting up a color proc is not recommended anymore
1032 }
1033
1034 void wxMacControl::SetRange( SInt32 minimum , SInt32 maximum )
1035 {
1036 ::SetControl32BitMinimum( m_controlRef , minimum ) ;
1037 ::SetControl32BitMaximum( m_controlRef , maximum ) ;
1038 }
1039
1040 short wxMacControl::HandleKey( SInt16 keyCode, SInt16 charCode, EventModifiers modifiers )
1041 {
1042 return HandleControlKey( m_controlRef , keyCode , charCode , modifiers ) ;
1043 }
1044
1045 void wxMacControl::SetActionProc( ControlActionUPP actionProc )
1046 {
1047 SetControlAction( m_controlRef , actionProc ) ;
1048 }
1049
1050 void wxMacControl::SetViewSize( SInt32 viewSize )
1051 {
1052 SetControlViewSize(m_controlRef , viewSize ) ;
1053 }
1054
1055 SInt32 wxMacControl::GetViewSize() const
1056 {
1057 return GetControlViewSize( m_controlRef ) ;
1058 }
1059
1060 bool wxMacControl::IsVisible() const
1061 {
1062 return IsControlVisible( m_controlRef ) ;
1063 }
1064
1065 void wxMacControl::SetVisibility( bool visible , bool redraw )
1066 {
1067 SetControlVisibility( m_controlRef , visible , redraw ) ;
1068 }
1069
1070 bool wxMacControl::IsEnabled() const
1071 {
1072 #if TARGET_API_MAC_OSX
1073 return IsControlEnabled( m_controlRef ) ;
1074 #else
1075 return IsControlActive( m_controlRef ) ;
1076 #endif
1077 }
1078
1079 bool wxMacControl::IsActive() const
1080 {
1081 return IsControlActive( m_controlRef ) ;
1082 }
1083
1084 void wxMacControl::Enable( bool enable )
1085 {
1086 #if TARGET_API_MAC_OSX
1087 if ( enable )
1088 EnableControl( m_controlRef ) ;
1089 else
1090 DisableControl( m_controlRef ) ;
1091 #else
1092 if ( enable )
1093 ActivateControl( m_controlRef ) ;
1094 else
1095 DeactivateControl( m_controlRef ) ;
1096 #endif
1097 }
1098
1099 void wxMacControl::SetDrawingEnabled( bool enable )
1100 {
1101 #if TARGET_API_MAC_OSX
1102 HIViewSetDrawingEnabled( m_controlRef , enable ) ;
1103 #endif
1104 }
1105
1106 #if TARGET_API_MAC_OSX
1107 bool wxMacControl::GetNeedsDisplay() const
1108 {
1109 #if TARGET_API_MAC_OSX
1110 if ( m_isCompositing )
1111 {
1112 return HIViewGetNeedsDisplay( m_controlRef ) ;
1113 }
1114 else
1115 #endif
1116 {
1117 if ( !IsVisible() )
1118 return false ;
1119
1120 Rect controlBounds ;
1121 GetControlBounds( m_controlRef, &controlBounds ) ;
1122 RgnHandle rgn = NewRgn() ;
1123 GetWindowRegion ( GetControlOwner( m_controlRef ) , kWindowUpdateRgn , rgn ) ;
1124 Boolean intersect = RectInRgn ( &controlBounds , rgn ) ;
1125 DisposeRgn( rgn ) ;
1126 return intersect ;
1127 }
1128
1129 }
1130 #endif
1131
1132 void wxMacControl::SetNeedsDisplay( RgnHandle where )
1133 {
1134 if ( !IsVisible() )
1135 return ;
1136
1137 #if TARGET_API_MAC_OSX
1138 if ( m_isCompositing )
1139 {
1140 HIViewSetNeedsDisplayInRegion( m_controlRef , where , true ) ;
1141 }
1142 else
1143 #endif
1144 {
1145 Rect controlBounds ;
1146 GetControlBounds( m_controlRef, &controlBounds ) ;
1147 RgnHandle update = NewRgn() ;
1148 CopyRgn( where , update ) ;
1149 OffsetRgn( update , controlBounds.left , controlBounds.top ) ;
1150 InvalWindowRgn( GetControlOwner( m_controlRef) , update ) ;
1151 }
1152 }
1153
1154 void wxMacControl::SetNeedsDisplay( Rect* where )
1155 {
1156 if ( !IsVisible() )
1157 return ;
1158
1159 #if TARGET_API_MAC_OSX
1160 if ( m_isCompositing )
1161 {
1162 if ( where != NULL )
1163 {
1164 RgnHandle update = NewRgn() ;
1165 RectRgn( update , where ) ;
1166 HIViewSetNeedsDisplayInRegion( m_controlRef , update , true ) ;
1167 DisposeRgn( update ) ;
1168 }
1169 else
1170 HIViewSetNeedsDisplay( m_controlRef , true ) ;
1171 }
1172 else
1173 #endif
1174 {
1175 Rect controlBounds ;
1176 GetControlBounds( m_controlRef, &controlBounds ) ;
1177 if ( where )
1178 {
1179 Rect whereLocal = *where ;
1180 OffsetRect( &whereLocal , controlBounds.left , controlBounds.top ) ;
1181 SectRect( &controlBounds , &whereLocal, &controlBounds ) ;
1182 }
1183 InvalWindowRect( GetControlOwner( m_controlRef) , &controlBounds ) ;
1184 }
1185 }
1186
1187 void wxMacControl::Convert( wxPoint *pt , wxMacControl *from , wxMacControl *to )
1188 {
1189 #if TARGET_API_MAC_OSX
1190 if ( from->m_peer->MacGetTopLevelWindow()->MacUsesCompositing() )
1191 {
1192 HIPoint hiPoint ;
1193 hiPoint.x = pt->x ;
1194 hiPoint.y = pt->y ;
1195 HIViewConvertPoint( &hiPoint , from->m_controlRef , to->m_controlRef ) ;
1196 pt->x = (int)hiPoint.x ;
1197 pt->y = (int)hiPoint.y ;
1198 }
1199 else
1200 #endif
1201 {
1202 Rect fromRect ;
1203 Rect toRect ;
1204 GetControlBounds( from->m_controlRef , &fromRect ) ;
1205 GetControlBounds( to->m_controlRef , &toRect ) ;
1206 if ( from->m_isRootControl )
1207 fromRect.left = fromRect.top = 0 ;
1208 if ( to->m_isRootControl )
1209 toRect.left = toRect.top = 0 ;
1210
1211 pt->x = pt->x + fromRect.left - toRect.left ;
1212 pt->y = pt->y + fromRect.top - toRect.top ;
1213 }
1214 }
1215
1216 void wxMacControl::SetRect( Rect *r )
1217 {
1218 #if TARGET_API_MAC_OSX
1219 if ( m_isCompositing )
1220 {
1221 //A HIRect is actually a CGRect on OSX - which consists of two structures -
1222 //CGPoint and CGSize, which have two floats each
1223 HIRect hir = { { r->left , r->top }, { r->right - r->left , r->bottom - r->top } } ;
1224 HIViewSetFrame ( m_controlRef , &hir ) ;
1225 // eventuall we might have to do a SetVisibility( false , true ) ;
1226 // before and a SetVisibility( true , true ) ; after
1227 }
1228 else
1229 #endif
1230 {
1231 bool vis = IsVisible() ;
1232 if ( vis )
1233 {
1234 Rect former ;
1235 GetControlBounds( m_controlRef , &former ) ;
1236 InvalWindowRect( GetControlOwner( m_controlRef ) , &former ) ;
1237 }
1238
1239 Rect controlBounds = *r ;
1240
1241 // since the rect passed in is always (even in non-compositing) relative
1242 // to the (native) parent, we have to adjust to window relative here
1243 wxMacControl* parent = m_peer->GetParent()->GetPeer() ;
1244 if( parent->m_isRootControl == false )
1245 {
1246 Rect superRect ;
1247 GetControlBounds( parent->m_controlRef , &superRect ) ;
1248 OffsetRect( &controlBounds , superRect.left , superRect.top ) ;
1249 }
1250
1251 SetControlBounds( m_controlRef , &controlBounds ) ;
1252 if ( vis )
1253 {
1254 InvalWindowRect( GetControlOwner( m_controlRef ) , &controlBounds ) ;
1255 }
1256 }
1257 }
1258
1259 void wxMacControl::GetRect( Rect *r )
1260 {
1261 GetControlBounds( m_controlRef , r ) ;
1262 if ( m_isCompositing == false )
1263 {
1264 // correct the case of the root control
1265 if ( m_isRootControl )
1266 {
1267 WindowRef wr = GetControlOwner( m_controlRef ) ;
1268 GetWindowBounds( wr , kWindowContentRgn , r ) ;
1269 r->right -= r->left ;
1270 r->bottom -= r->top ;
1271 r->left = 0 ;
1272 r->top = 0 ;
1273 }
1274 else
1275 {
1276 wxMacControl* parent = m_peer->GetParent()->GetPeer() ;
1277 if( parent->m_isRootControl == false )
1278 {
1279 Rect superRect ;
1280 GetControlBounds( parent->m_controlRef , &superRect ) ;
1281 OffsetRect( r , -superRect.left , -superRect.top ) ;
1282 }
1283 }
1284 }
1285 }
1286
1287 void wxMacControl::GetRectInWindowCoords( Rect *r )
1288 {
1289 UMAGetControlBoundsInWindowCoords( m_controlRef , r ) ;
1290 }
1291
1292 void wxMacControl::GetBestRect( Rect *r )
1293 {
1294 short baselineoffset ;
1295 GetBestControlRect( m_controlRef , r , &baselineoffset ) ;
1296 }
1297
1298 void wxMacControl::SetTitle( const wxString &title )
1299 {
1300 wxFontEncoding encoding;
1301
1302 if ( m_font.Ok() )
1303 encoding = m_font.GetEncoding();
1304 else
1305 encoding = wxFont::GetDefaultEncoding();
1306
1307 UMASetControlTitle( m_controlRef , title , encoding ) ;
1308 }
1309
1310 void wxMacControl::GetFeatures( UInt32 * features )
1311 {
1312 GetControlFeatures( m_controlRef , features ) ;
1313 }
1314
1315 OSStatus wxMacControl::GetRegion( ControlPartCode partCode , RgnHandle region )
1316 {
1317 OSStatus err = GetControlRegion( m_controlRef , partCode , region ) ;
1318 if ( m_isCompositing == false )
1319 {
1320 if ( !m_isRootControl )
1321 {
1322 Rect r ;
1323 GetControlBounds(m_controlRef, &r ) ;
1324 if ( !EmptyRgn( region ) )
1325 OffsetRgn( region , -r.left , -r.top ) ;
1326 }
1327 }
1328 return err ;
1329 }
1330
1331 OSStatus wxMacControl::SetZOrder( bool above , wxMacControl* other )
1332 {
1333 #if TARGET_API_MAC_OSX
1334 return HIViewSetZOrder( m_controlRef,above ? kHIViewZOrderAbove : kHIViewZOrderBelow,
1335 (other != NULL) ? other->m_controlRef : NULL) ;
1336 #else
1337 return 0 ;
1338 #endif
1339 }
1340
1341
1342 #if TARGET_API_MAC_OSX
1343 // SetNeedsDisplay would not invalidate the children
1344 static void InvalidateControlAndChildren( HIViewRef control )
1345 {
1346 HIViewSetNeedsDisplay( control , true ) ;
1347 UInt16 childrenCount = 0 ;
1348 OSStatus err = CountSubControls( control , &childrenCount ) ;
1349 if ( err == errControlIsNotEmbedder )
1350 return ;
1351 wxASSERT_MSG( err == noErr , wxT("Unexpected error when accessing subcontrols") ) ;
1352
1353 for ( UInt16 i = childrenCount ; i >=1 ; --i )
1354 {
1355 HIViewRef child ;
1356 err = GetIndexedSubControl( control , i , & child ) ;
1357 if ( err == errControlIsNotEmbedder )
1358 return ;
1359 InvalidateControlAndChildren( child ) ;
1360 }
1361 }
1362 #endif
1363
1364 void wxMacControl::InvalidateWithChildren()
1365 {
1366 #if TARGET_API_MAC_OSX
1367 InvalidateControlAndChildren( m_controlRef ) ;
1368 #endif
1369 }
1370
1371 void wxMacControl::ScrollRect( wxRect *r , int dx , int dy )
1372 {
1373 wxASSERT( r != NULL ) ;
1374 #if TARGET_API_MAC_OSX
1375 if ( m_isCompositing )
1376 {
1377 HIRect scrollarea = CGRectMake( r->x , r->y , r->width , r->height) ;
1378 HIViewScrollRect ( m_controlRef , &scrollarea , dx ,dy ) ;
1379 }
1380 else
1381 #endif
1382 {
1383 Rect bounds ;
1384 GetControlBounds( m_controlRef , &bounds ) ;
1385 bounds.left += r->x ;
1386 bounds.top += r->y ;
1387 bounds.bottom = bounds.top + r->height ;
1388 bounds.right = bounds.left + r->width ;
1389 wxMacWindowClipper clip( m_peer ) ;
1390 RgnHandle updateRgn = NewRgn() ;
1391 ::ScrollRect( &bounds , dx , dy , updateRgn ) ;
1392 InvalWindowRgn( GetControlOwner( m_controlRef ) , updateRgn ) ;
1393 }
1394 }
1395
1396
1397 // SetNeedsDisplay would not invalidate the children
1398
1399 //
1400 // Databrowser
1401 //
1402
1403 OSStatus wxMacControl::SetSelectionFlags( DataBrowserSelectionFlags options )
1404 {
1405 return SetDataBrowserSelectionFlags( m_controlRef , options ) ;
1406 }
1407
1408 OSStatus wxMacControl::AddListViewColumn( DataBrowserListViewColumnDesc *columnDesc,
1409 DataBrowserTableViewColumnIndex position )
1410 {
1411 return AddDataBrowserListViewColumn( m_controlRef , columnDesc, position ) ;
1412 }
1413
1414 OSStatus wxMacControl::AutoSizeListViewColumns()
1415 {
1416 return AutoSizeDataBrowserListViewColumns(m_controlRef) ;
1417 }
1418
1419 OSStatus wxMacControl::SetHasScrollBars( bool horiz , bool vert )
1420 {
1421 return SetDataBrowserHasScrollBars( m_controlRef , horiz , vert ) ;
1422 }
1423
1424 OSStatus wxMacControl::SetTableViewHiliteStyle( DataBrowserTableViewHiliteStyle hiliteStyle )
1425 {
1426 return SetDataBrowserTableViewHiliteStyle( m_controlRef , hiliteStyle ) ;
1427 }
1428
1429 OSStatus wxMacControl::SetListViewHeaderBtnHeight(UInt16 height)
1430 {
1431 return SetDataBrowserListViewHeaderBtnHeight( m_controlRef ,height ) ;
1432 }
1433
1434 OSStatus wxMacControl::SetCallbacks(const DataBrowserCallbacks * callbacks)
1435 {
1436 return SetDataBrowserCallbacks( m_controlRef , callbacks ) ;
1437 }
1438
1439 OSStatus wxMacControl::UpdateItems( DataBrowserItemID container, UInt32 numItems,
1440 const DataBrowserItemID* items,
1441 DataBrowserPropertyID preSortProperty,
1442 DataBrowserPropertyID propertyID )
1443 {
1444 return UpdateDataBrowserItems( m_controlRef , container, numItems, items, preSortProperty, propertyID ) ;
1445 }
1446
1447 bool wxMacControl::IsItemSelected( DataBrowserItemID item )
1448 {
1449 return IsDataBrowserItemSelected( m_controlRef , item ) ;
1450 }
1451
1452 OSStatus wxMacControl::AddItems( DataBrowserItemID container, UInt32 numItems,
1453 const DataBrowserItemID* items,
1454 DataBrowserPropertyID preSortProperty )
1455 {
1456 return AddDataBrowserItems( m_controlRef , container, numItems, items, preSortProperty ) ;
1457 }
1458
1459 OSStatus wxMacControl::RemoveItems( DataBrowserItemID container, UInt32 numItems,
1460 const DataBrowserItemID* items,
1461 DataBrowserPropertyID preSortProperty )
1462 {
1463 return RemoveDataBrowserItems( m_controlRef , container, numItems, items, preSortProperty ) ;
1464 }
1465
1466 OSStatus wxMacControl::RevealItem( DataBrowserItemID item,
1467 DataBrowserPropertyID propertyID,
1468 DataBrowserRevealOptions options )
1469 {
1470 return RevealDataBrowserItem( m_controlRef , item , propertyID , options ) ;
1471 }
1472
1473 OSStatus wxMacControl::SetSelectedItems(UInt32 numItems,
1474 const DataBrowserItemID * items,
1475 DataBrowserSetOption operation )
1476 {
1477 return SetDataBrowserSelectedItems( m_controlRef , numItems , items, operation ) ;
1478 }
1479
1480 OSStatus wxMacControl::GetSelectionAnchor( DataBrowserItemID * first, DataBrowserItemID * last )
1481 {
1482 return GetDataBrowserSelectionAnchor( m_controlRef , first , last ) ;
1483 }
1484
1485 //
1486 // Tab Control
1487 //
1488
1489 OSStatus wxMacControl::SetTabEnabled( SInt16 tabNo , bool enable )
1490 {
1491 return ::SetTabEnabled( m_controlRef , tabNo , enable ) ;
1492 }
1493
1494 //
1495 // Quartz Support
1496 //
1497
1498 #ifdef __WXMAC_OSX__
1499 // snippets from Sketch Sample from Apple :
1500
1501 #define kGenericRGBProfilePathStr "/System/Library/ColorSync/Profiles/Generic RGB Profile.icc"
1502 /*
1503 This function locates, opens, and returns the profile reference for the calibrated
1504 Generic RGB color space. It is up to the caller to call CMCloseProfile when done
1505 with the profile reference this function returns.
1506 */
1507 CMProfileRef wxMacOpenGenericProfile(void)
1508 {
1509 static CMProfileRef cachedRGBProfileRef = NULL;
1510
1511 // we only create the profile reference once
1512 if (cachedRGBProfileRef == NULL)
1513 {
1514 CMProfileLocation loc;
1515
1516 loc.locType = cmPathBasedProfile;
1517 strcpy(loc.u.pathLoc.path, kGenericRGBProfilePathStr);
1518
1519 verify_noerr( CMOpenProfile(&cachedRGBProfileRef, &loc) );
1520 }
1521
1522 if (cachedRGBProfileRef)
1523 {
1524 // clone the profile reference so that the caller has their own reference, not our cached one
1525 CMCloneProfileRef(cachedRGBProfileRef);
1526 }
1527
1528 return cachedRGBProfileRef;
1529 }
1530
1531 /*
1532 Return the generic RGB color space. This is a 'get' function and the caller should
1533 not release the returned value unless the caller retains it first. Usually callers
1534 of this routine will immediately use the returned colorspace with CoreGraphics
1535 so they typically do not need to retain it themselves.
1536
1537 This function creates the generic RGB color space once and hangs onto it so it can
1538 return it whenever this function is called.
1539 */
1540
1541 CGColorSpaceRef wxMacGetGenericRGBColorSpace()
1542 {
1543 static CGColorSpaceRef genericRGBColorSpace = NULL;
1544
1545 if (genericRGBColorSpace == NULL)
1546 {
1547 CMProfileRef genericRGBProfile = wxMacOpenGenericProfile();
1548
1549 if (genericRGBProfile)
1550 {
1551 genericRGBColorSpace = CGColorSpaceCreateWithPlatformColorSpace(genericRGBProfile);
1552 wxASSERT_MSG( genericRGBColorSpace != NULL, wxT("couldn't create the generic RGB color space") ) ;
1553
1554 // we opened the profile so it is up to us to close it
1555 CMCloseProfile(genericRGBProfile);
1556 }
1557 }
1558 return genericRGBColorSpace;
1559 }
1560 #endif
1561
1562 #endif // wxUSE_GUI
1563