git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@54119 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Stefan Csomor
2008-06-11 16:46:03 +00:00
parent 29ed833473
commit 489468feaa
139 changed files with 85695 additions and 0 deletions

View File

@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
<plist version="0.9">
<dict>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleIdentifier</key>
<string>org.wxwindows.IDENTIFIER</string>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
<string>EXECUTABLE</string>
<key>CFBundleIconFile</key>
<string>wxmac.icns</string>
<key>CFBundleName</key>
<string>EXECUTABLE</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>VERSION</string>
<key>CFBundleShortVersionString</key>
<string>VERSION</string>
<key>CFBundleGetInfoString</key>
<string>EXECUTABLE version VERSION, (c) 2002-2006 wxWidgets</string>
<key>CFBundleLongVersionString</key>
<string>VERSION, (c) 2002-2006 wxWidgets</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright 2002-2006 wxWidgets</string>
<key>LSRequiresCarbon</key>
<true/>
<key>CSResourcesFileMapped</key>
<true/>
</dict>
</plist>

View File

@@ -0,0 +1,92 @@
///////////////////////////////////////////////////////////////////////////////
// Name: mac/carbon/aboutdlg.cpp
// Purpose: native wxAboutBox() implementation for wxMac
// Author: Vadim Zeitlin
// Created: 2006-10-08
// RCS-ID: $Id$
// Copyright: (c) 2006 Vadim Zeitlin <vadim@wxwindows.org>
// Licence: wxWindows licence
///////////////////////////////////////////////////////////////////////////////
// ============================================================================
// declarations
// ============================================================================
// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------
// for compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"
#if wxUSE_ABOUTDLG
#ifndef WX_PRECOMP
#endif //WX_PRECOMP
#include "wx/aboutdlg.h"
#include "wx/generic/aboutdlgg.h"
#include "wx/mac/private.h"
// helper class for HIAboutBox options
class AboutBoxOptions : public wxCFRef<CFMutableDictionaryRef>
{
public:
AboutBoxOptions() : wxCFRef<CFMutableDictionaryRef>
(
CFDictionaryCreateMutable
(
kCFAllocatorDefault,
4, // there are at most 4 values
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks
)
)
{
}
void Set(CFStringRef key, const wxString& value)
{
CFDictionarySetValue(*this, key, wxCFStringRef(value));
}
};
// ============================================================================
// implementation
// ============================================================================
void wxAboutBox(const wxAboutDialogInfo& info)
{
// Mac native about box currently can show only name, version, copyright
// and description fields and we also shoehorn the credits text into the
// description but if we have anything else we must use the generic version
#ifndef __LP64__
if ( info.IsSimple() )
{
AboutBoxOptions opts;
opts.Set(kHIAboutBoxNameKey, info.GetName());
if ( info.HasVersion() )
{
opts.Set(kHIAboutBoxVersionKey,
wxString::Format(_("Version %s"), info.GetVersion()));
}
if ( info.HasCopyright() )
opts.Set(kHIAboutBoxCopyrightKey, info.GetCopyright());
opts.Set(kHIAboutBoxDescriptionKey, info.GetDescriptionAndCredits());
HIAboutBox(opts);
}
else // simple "native" version is not enough
#endif
{
// we need to use the full-blown generic version
wxGenericAboutBox(info);
}
}
#endif // wxUSE_ABOUTDLG

109
src/osx/carbon/accel.cpp Normal file
View File

@@ -0,0 +1,109 @@
/////////////////////////////////////////////////////////////////////////////
// Name: src/mac/carbon/accel.cpp
// Purpose: wxAcceleratorTable
// Author: Stefan Csomor
// Modified by:
// Created: 1998-01-01
// RCS-ID: $Id$
// Copyright: (c) Stefan Csomor
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
#include "wx/wxprec.h"
#include "wx/accel.h"
#ifndef WX_PRECOMP
#include "wx/string.h"
#endif
#ifndef __WXUNIVERSAL__
IMPLEMENT_DYNAMIC_CLASS(wxAcceleratorTable, wxObject)
// ----------------------------------------------------------------------------
// wxAccelList: a list of wxAcceleratorEntries
// ----------------------------------------------------------------------------
WX_DECLARE_LIST(wxAcceleratorEntry, wxAccelList);
#include "wx/listimpl.cpp"
WX_DEFINE_LIST(wxAccelList)
// ----------------------------------------------------------------------------
// wxAccelRefData: the data used by wxAcceleratorTable
// ----------------------------------------------------------------------------
class WXDLLEXPORT wxAcceleratorRefData: public wxObjectRefData
{
friend class wxAcceleratorTable;
public:
wxAcceleratorRefData();
virtual ~wxAcceleratorRefData();
wxAccelList m_accels;
};
#define M_ACCELDATA ((wxAcceleratorRefData *)m_refData)
wxAcceleratorRefData::wxAcceleratorRefData()
: m_accels()
{
}
wxAcceleratorRefData::~wxAcceleratorRefData()
{
WX_CLEAR_LIST( wxAccelList, m_accels );
}
wxAcceleratorTable::wxAcceleratorTable()
{
m_refData = NULL;
}
wxAcceleratorTable::~wxAcceleratorTable()
{
}
// Create from an array
wxAcceleratorTable::wxAcceleratorTable(int n, const wxAcceleratorEntry entries[])
{
m_refData = new wxAcceleratorRefData;
for (int i = 0; i < n; i++)
{
int flag = entries[i].GetFlags();
int keycode = entries[i].GetKeyCode();
int command = entries[i].GetCommand();
if ((keycode >= (int)'a') && (keycode <= (int)'z')) keycode = (int)toupper( (char)keycode );
M_ACCELDATA->m_accels.Append( new wxAcceleratorEntry( flag, keycode, command ) );
}
}
bool wxAcceleratorTable::IsOk() const
{
return (m_refData != NULL);
}
int wxAcceleratorTable::GetCommand( wxKeyEvent &event )
{
if (!Ok()) return -1;
wxAccelList::compatibility_iterator node = M_ACCELDATA->m_accels.GetFirst();
while (node)
{
wxAcceleratorEntry *entry = node->GetData();
if ((event.m_keyCode == entry->GetKeyCode()) &&
(((entry->GetFlags() & wxACCEL_CTRL) != 0) == event.ControlDown()) &&
(((entry->GetFlags() & wxACCEL_SHIFT) != 0) == event.ShiftDown()) &&
(((entry->GetFlags() & wxACCEL_ALT) != 0) == event.AltDown()) &&
(((entry->GetFlags() & wxACCEL_CMD) != 0) == event.CmdDown()))
{
return entry->GetCommand();
}
node = node->GetNext();
}
return -1;
}
#endif

1648
src/osx/carbon/app.cpp Normal file

File diff suppressed because it is too large Load Diff

1
src/osx/carbon/apprsrc.h Normal file
View File

@@ -0,0 +1 @@
// TODO REMOVE

1
src/osx/carbon/apprsrc.r Normal file
View File

@@ -0,0 +1 @@
/* not needed anymore */

108
src/osx/carbon/artmac.cpp Normal file
View File

@@ -0,0 +1,108 @@
/////////////////////////////////////////////////////////////////////////////
// Name: src/mac/carbon/artmac.cpp
// Purpose: wxArtProvider instance with native Mac stock icons
// Author: Alan Shouls
// Created: 2006-10-30
// RCS-ID: $Id$
// Copyright: (c) wxWindows team
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
// ---------------------------------------------------------------------------
// headers
// ---------------------------------------------------------------------------
// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"
#if defined(__BORLANDC__)
#pragma hdrstop
#endif
#ifndef WX_PRECOMP
#include "wx/image.h"
#endif
#include "wx/artprov.h"
#include "wx/image.h"
// ----------------------------------------------------------------------------
// wxMacArtProvider
// ----------------------------------------------------------------------------
class wxMacArtProvider : public wxArtProvider
{
protected:
virtual wxBitmap CreateBitmap(const wxArtID& id, const wxArtClient& client,
const wxSize& size);
virtual wxIconBundle CreateIconBundle(const wxArtID& id,
const wxArtClient& client);
};
/* static */ void wxArtProvider::InitNativeProvider()
{
wxArtProvider::Push(new wxMacArtProvider);
}
// ----------------------------------------------------------------------------
// helper macros
// ----------------------------------------------------------------------------
#define CREATE_STD_ICON(iconId, xpmRc) \
{ \
wxIconBundle icon(_T(iconId), wxBITMAP_TYPE_ICON_RESOURCE); \
return icon; \
}
// Macro used in CreateBitmap to get wxICON_FOO icons:
#define ART_MSGBOX(artId, iconId, xpmRc) \
if ( id == artId ) \
{ \
CREATE_STD_ICON(#iconId, xpmRc) \
}
static wxIconBundle wxMacArtProvider_CreateIconBundle(const wxArtID& id)
{
ART_MSGBOX(wxART_ERROR, wxICON_ERROR, error)
ART_MSGBOX(wxART_INFORMATION, wxICON_INFORMATION, info)
ART_MSGBOX(wxART_WARNING, wxICON_WARNING, warning)
ART_MSGBOX(wxART_QUESTION, wxICON_QUESTION, question)
ART_MSGBOX(wxART_FOLDER, wxICON_FOLDER, folder)
ART_MSGBOX(wxART_FOLDER_OPEN, wxICON_FOLDER_OPEN, folder_open)
ART_MSGBOX(wxART_NORMAL_FILE, wxICON_NORMAL_FILE, deffile)
return wxNullIconBundle;
}
// ----------------------------------------------------------------------------
// CreateIconBundle
// ----------------------------------------------------------------------------
wxIconBundle wxMacArtProvider::CreateIconBundle(const wxArtID& id, const wxArtClient& client)
{
// On the Mac folders in lists are always drawn closed, so if an open
// folder icon is asked for we will ask for a closed one in its place
if ( client == wxART_LIST && id == wxART_FOLDER_OPEN )
return wxMacArtProvider_CreateIconBundle(wxART_FOLDER);
return wxMacArtProvider_CreateIconBundle(id);
}
// ----------------------------------------------------------------------------
// CreateBitmap
// ----------------------------------------------------------------------------
wxBitmap wxMacArtProvider::CreateBitmap(const wxArtID& id,
const wxArtClient& client,
const wxSize& reqSize)
{
wxIconBundle ic(CreateIconBundle(id, client));
if (ic.IsOk())
{
wxIcon theIcon(ic.GetIcon(reqSize));
return wxBitmap(theIcon);
}
return wxNullBitmap;
}

1721
src/osx/carbon/bitmap.cpp Normal file

File diff suppressed because it is too large Load Diff

189
src/osx/carbon/bmpbuttn.cpp Normal file
View File

@@ -0,0 +1,189 @@
/////////////////////////////////////////////////////////////////////////////
// Name: src/mac/carbon/bmpbuttn.cpp
// Purpose: wxBitmapButton
// Author: Stefan Csomor
// Modified by:
// Created: 1998-01-01
// RCS-ID: $Id$
// Copyright: (c) Stefan Csomor
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
#include "wx/wxprec.h"
#if wxUSE_BMPBUTTON
#include "wx/bmpbuttn.h"
#include "wx/image.h"
#ifndef WX_PRECOMP
#include "wx/dcmemory.h"
#endif
IMPLEMENT_DYNAMIC_CLASS(wxBitmapButton, wxButton)
#include "wx/mac/uma.h"
//---------------------------------------------------------------------------
// Helper functions
static wxBitmap wxMakeStdSizeBitmap(const wxBitmap& bitmap)
{
// in Mac OS X the icon controls (which are used for borderless bitmap
// buttons) can have only one of the few standard sizes and if they
// don't, the OS rescales them automatically resulting in really ugly
// images, so centre the image in a square of standard size instead
// the supported sizes, sorted in decreasng order
static const int stdSizes[] = { 128, 48, 32, 16, 0 };
const int width = bitmap.GetWidth();
const int height = bitmap.GetHeight();
wxBitmap newBmp(bitmap);
int n;
for ( n = 0; n < (int)WXSIZEOF(stdSizes); n++ )
{
const int sizeStd = stdSizes[n];
if ( width > sizeStd || height > sizeStd )
{
// it will become -1 if the bitmap is larger than the biggest
// supported size, this is intentional
n--;
break;
}
}
if ( n != -1 )
{
const int sizeStd = stdSizes[n];
if ( width != sizeStd || height != sizeStd )
{
wxASSERT_MSG( width <= sizeStd && height <= sizeStd,
_T("bitmap shouldn't be cropped") );
wxImage square_image = bitmap.ConvertToImage();
newBmp = square_image.Size
(
wxSize(sizeStd, sizeStd),
wxPoint((sizeStd - width)/2, (sizeStd-height)/2)
);
}
}
//else: let the system rescale the bitmap
return newBmp;
}
//---------------------------------------------------------------------------
bool wxBitmapButton::Create( wxWindow *parent,
wxWindowID id, const wxBitmap& bitmap,
const wxPoint& pos,
const wxSize& size,
long style,
const wxValidator& validator,
const wxString& name )
{
m_macIsUserPane = false;
// since bitmapbuttonbase is subclass of button calling wxBitmapButtonBase::Create
// essentially creates an additional button
if ( !wxControl::Create( parent, id, pos, size, style, validator, name ) )
return false;
if ( style & wxBU_AUTODRAW )
{
m_marginX =
m_marginY = wxDEFAULT_BUTTON_MARGIN;
}
else
{
m_marginX =
m_marginY = 0;
}
OSStatus err = noErr;
ControlButtonContentInfo info;
Rect bounds = wxMacGetBoundsForControl( this, pos, size );
m_peer = new wxMacControl( this );
if ( bitmap.Ok() && HasFlag(wxBORDER_NONE) )
m_bmpNormal = wxMakeStdSizeBitmap(bitmap);
else
m_bmpNormal = bitmap;
if ( HasFlag( wxBORDER_NONE ) )
{
// contrary to the docs this control only works with iconrefs
wxMacCreateBitmapButton( &info, m_bmpNormal, kControlContentIconRef );
err = CreateIconControl(
MAC_WXHWND(parent->MacGetTopLevelWindowRef()),
&bounds, &info, false, m_peer->GetControlRefAddr() );
}
else
{
wxMacCreateBitmapButton( &info, m_bmpNormal );
err = CreateBevelButtonControl(
MAC_WXHWND(parent->MacGetTopLevelWindowRef()), &bounds, CFSTR(""),
((style & wxBU_AUTODRAW) ? kControlBevelButtonSmallBevel : kControlBevelButtonNormalBevel ),
kControlBehaviorOffsetContents, &info, 0, 0, 0, m_peer->GetControlRefAddr() );
}
verify_noerr( err );
wxMacReleaseBitmapButton( &info );
wxASSERT_MSG( m_peer != NULL && m_peer->Ok(), wxT("No valid native Mac control") );
MacPostControlCreate( pos, size );
return true;
}
void wxBitmapButton::SetBitmapLabel( const wxBitmap& bitmap )
{
if ( HasFlag( wxBORDER_NONE ) )
m_bmpNormal = wxMakeStdSizeBitmap(bitmap);
else
m_bmpNormal = bitmap;
InvalidateBestSize();
ControlButtonContentInfo info;
if ( HasFlag( wxBORDER_NONE ) )
{
wxMacCreateBitmapButton( &info, m_bmpNormal, kControlContentIconRef );
if ( info.contentType != kControlNoContent )
m_peer->SetData( kControlIconPart, kControlIconContentTag, info );
}
else
{
wxMacCreateBitmapButton( &info, m_bmpNormal );
if ( info.contentType != kControlNoContent )
m_peer->SetData( kControlButtonPart, kControlBevelButtonContentTag, info );
}
wxMacReleaseBitmapButton( &info );
}
wxSize wxBitmapButton::DoGetBestSize() const
{
wxSize best;
best.x = 2 * m_marginX;
best.y = 2 * m_marginY;
if ( m_bmpNormal.Ok() )
{
best.x += m_bmpNormal.GetWidth();
best.y += m_bmpNormal.GetHeight();
}
return best;
}
#endif

192
src/osx/carbon/brush.cpp Normal file
View File

@@ -0,0 +1,192 @@
/////////////////////////////////////////////////////////////////////////////
// Name: src/mac/carbon/brush.cpp
// Purpose: wxBrush
// Author: Stefan Csomor
// Modified by:
// Created: 1998-01-01
// RCS-ID: $Id$
// Copyright: (c) Stefan Csomor
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
#include "wx/wxprec.h"
#include "wx/brush.h"
#ifndef WX_PRECOMP
#include "wx/utils.h"
#endif
#include "wx/mac/private.h"
IMPLEMENT_DYNAMIC_CLASS(wxBrush, wxGDIObject)
class WXDLLEXPORT wxBrushRefData: public wxGDIRefData
{
public:
wxBrushRefData(const wxColour& colour = wxNullColour, wxBrushStyle style = wxBRUSHSTYLE_SOLID);
wxBrushRefData(const wxBitmap& stipple);
wxBrushRefData(const wxBrushRefData& data);
virtual ~wxBrushRefData();
bool operator==(const wxBrushRefData& data) const;
const wxColour& GetColour() const { return m_colour; }
wxBrushStyle GetStyle() const { return m_style; }
wxBitmap *GetStipple() { return &m_stipple; }
void SetColour(const wxColour& colour) { m_colour = colour; }
void SetStyle(wxBrushStyle style) { m_style = style; }
void SetStipple(const wxBitmap& stipple) { DoSetStipple(stipple); }
protected:
void DoSetStipple(const wxBitmap& stipple);
wxBitmap m_stipple;
wxColour m_colour;
wxBrushStyle m_style;
};
#define M_BRUSHDATA ((wxBrushRefData *)m_refData)
wxBrushRefData::wxBrushRefData(const wxColour& colour, wxBrushStyle style)
: m_colour(colour), m_style( style )
{
}
wxBrushRefData::wxBrushRefData(const wxBitmap& stipple)
{
DoSetStipple( stipple );
}
wxBrushRefData::wxBrushRefData(const wxBrushRefData& data)
: wxGDIRefData() ,
m_stipple(data.m_stipple),
m_colour(data.m_colour),
m_style(data.m_style)
{
}
wxBrushRefData::~wxBrushRefData()
{
}
bool wxBrushRefData::operator==(const wxBrushRefData& data) const
{
return m_style == data.m_style &&
m_colour == data.m_colour &&
m_stipple.IsSameAs(data.m_stipple);
}
void wxBrushRefData::DoSetStipple(const wxBitmap& stipple)
{
m_stipple = stipple;
m_style = stipple.GetMask() ? wxBRUSHSTYLE_STIPPLE_MASK_OPAQUE : wxBRUSHSTYLE_STIPPLE;
}
//
//
//
wxBrush::wxBrush()
{
}
wxBrush::~wxBrush()
{
}
wxBrush::wxBrush(const wxColour& col, wxBrushStyle style)
{
m_refData = new wxBrushRefData( col, style );
}
#if FUTURE_WXWIN_COMPATIBILITY_3_0
wxBrush::wxBrush(const wxColour& col, int style)
{
m_refData = new wxBrushRefData(col, (wxBrushStyle)style);
}
#endif
wxBrush::wxBrush(const wxBitmap& stipple)
{
m_refData = new wxBrushRefData( stipple );
}
// ----------------------------------------------------------------------------
// wxBrush house keeping stuff
// ----------------------------------------------------------------------------
bool wxBrush::operator==(const wxBrush& brush) const
{
const wxBrushRefData *brushData = (wxBrushRefData *)brush.m_refData;
// an invalid brush is considered to be only equal to another invalid brush
return m_refData ? (brushData && *M_BRUSHDATA == *brushData) : !brushData;
}
wxGDIRefData *wxBrush::CreateGDIRefData() const
{
return new wxBrushRefData;
}
wxGDIRefData *wxBrush::CloneGDIRefData(const wxGDIRefData *data) const
{
return new wxBrushRefData(*(const wxBrushRefData *)data);
}
// ----------------------------------------------------------------------------
// wxBrush accessors
// ----------------------------------------------------------------------------
wxColour wxBrush::GetColour() const
{
wxCHECK_MSG( Ok(), wxNullColour, _T("invalid brush") );
return M_BRUSHDATA->GetColour();
}
wxBrushStyle wxBrush::GetStyle() const
{
wxCHECK_MSG( Ok(), wxBRUSHSTYLE_INVALID, _T("invalid brush") );
return M_BRUSHDATA->GetStyle();
}
wxBitmap *wxBrush::GetStipple() const
{
wxCHECK_MSG( Ok(), NULL, _T("invalid brush") );
return M_BRUSHDATA->GetStipple();
}
// ----------------------------------------------------------------------------
// wxBrush setters
// ----------------------------------------------------------------------------
void wxBrush::SetColour(const wxColour& col)
{
AllocExclusive();
M_BRUSHDATA->SetColour(col);
}
void wxBrush::SetColour(unsigned char r, unsigned char g, unsigned char b)
{
AllocExclusive();
M_BRUSHDATA->SetColour(wxColour(r, g, b));
}
void wxBrush::SetStyle(wxBrushStyle style)
{
AllocExclusive();
M_BRUSHDATA->SetStyle(style);
}
void wxBrush::SetStipple(const wxBitmap& stipple)
{
AllocExclusive();
M_BRUSHDATA->SetStipple(stipple);
}

273
src/osx/carbon/button.cpp Normal file
View File

@@ -0,0 +1,273 @@
/////////////////////////////////////////////////////////////////////////////
// Name: src/mac/carbon/button.cpp
// Purpose: wxButton
// Author: Stefan Csomor
// Modified by:
// Created: 1998-01-01
// RCS-ID: $Id$
// Copyright: (c) Stefan Csomor
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
#include "wx/wxprec.h"
#include "wx/button.h"
#ifndef WX_PRECOMP
#include "wx/panel.h"
#include "wx/toplevel.h"
#include "wx/dcclient.h"
#endif
#include "wx/stockitem.h"
#include "wx/mac/uma.h"
IMPLEMENT_DYNAMIC_CLASS(wxButton, wxControl)
bool wxButton::Create(wxWindow *parent,
wxWindowID id,
const wxString& lbl,
const wxPoint& pos,
const wxSize& size,
long style,
const wxValidator& validator,
const wxString& name)
{
wxString label(lbl);
if (label.empty() && wxIsStockID(id))
label = wxGetStockLabel(id);
m_macIsUserPane = false ;
if ( !wxButtonBase::Create(parent, id, pos, size, style, validator, name) )
return false;
m_labelOrig = m_label = label ;
OSStatus err;
Rect bounds = wxMacGetBoundsForControl( this , pos , size ) ;
m_peer = new wxMacControl(this) ;
if ( id == wxID_HELP )
{
ControlButtonContentInfo info ;
info.contentType = kControlContentIconRef ;
GetIconRef(kOnSystemDisk, kSystemIconsCreator, kHelpIcon, &info.u.iconRef);
err = CreateRoundButtonControl(
MAC_WXHWND(parent->MacGetTopLevelWindowRef()),
&bounds, kControlRoundButtonNormalSize,
&info, m_peer->GetControlRefAddr() );
}
else if ( label.Find('\n' ) == wxNOT_FOUND && label.Find('\r' ) == wxNOT_FOUND)
{
// Button height is static in Mac, can't be changed, so we need to force it here
if ( GetWindowVariant() == wxWINDOW_VARIANT_NORMAL || GetWindowVariant() == wxWINDOW_VARIANT_LARGE )
{
bounds.bottom = bounds.top + 20 ;
m_maxHeight = 20 ;
}
else if ( GetWindowVariant() == wxWINDOW_VARIANT_SMALL )
{
bounds.bottom = bounds.top + 17 ;
m_maxHeight = 17 ;
}
else if ( GetWindowVariant() == wxWINDOW_VARIANT_MINI )
{
bounds.bottom = bounds.top + 15 ;
m_maxHeight = 15 ;
}
err = CreatePushButtonControl(
MAC_WXHWND(parent->MacGetTopLevelWindowRef()),
&bounds, CFSTR(""), m_peer->GetControlRefAddr() );
}
else
{
ControlButtonContentInfo info ;
info.contentType = kControlNoContent ;
err = CreateBevelButtonControl(
MAC_WXHWND(parent->MacGetTopLevelWindowRef()) , &bounds, CFSTR(""),
kControlBevelButtonLargeBevel, kControlBehaviorPushbutton,
&info, 0, 0, 0, m_peer->GetControlRefAddr() );
}
verify_noerr( err );
wxASSERT_MSG( m_peer != NULL && m_peer->Ok() , wxT("No valid Mac control") ) ;
MacPostControlCreate( pos, size );
return true;
}
wxWindow *wxButton::SetDefault()
{
wxWindow *btnOldDefault = wxButtonBase::SetDefault();
if ( btnOldDefault )
{
// cast needed to access the protected member
btnOldDefault->GetPeer()->SetData(kControlButtonPart , kControlPushButtonDefaultTag , (Boolean) 0 ) ;
}
m_peer->SetData(kControlButtonPart , kControlPushButtonDefaultTag , (Boolean) 1 ) ;
return btnOldDefault;
}
wxSize wxButton::DoGetBestSize() const
{
if ( GetId() == wxID_HELP )
return wxSize( 20 , 20 ) ;
wxSize sz = GetDefaultSize() ;
switch (GetWindowVariant())
{
case wxWINDOW_VARIANT_NORMAL:
case wxWINDOW_VARIANT_LARGE:
sz.y = 20 ;
break;
case wxWINDOW_VARIANT_SMALL:
sz.y = 17 ;
break;
case wxWINDOW_VARIANT_MINI:
sz.y = 15 ;
break;
default:
break;
}
Rect bestsize = { 0 , 0 , 0 , 0 } ;
m_peer->GetBestRect( &bestsize ) ;
int wBtn;
if ( EmptyRect( &bestsize ) || ( GetWindowStyle() & wxBU_EXACTFIT) )
{
Point bounds;
ControlFontStyleRec controlFont;
OSStatus err = m_peer->GetData<ControlFontStyleRec>( kControlEntireControl, kControlFontStyleTag, &controlFont );
verify_noerr( err );
wxCFStringRef str( m_label, GetFont().GetEncoding() );
#if wxMAC_USE_ATSU_TEXT
SInt16 baseline;
if ( m_font.MacGetThemeFontID() != kThemeCurrentPortFont )
{
err = GetThemeTextDimensions(
(!m_label.empty() ? (CFStringRef)str : CFSTR(" ")),
m_font.MacGetThemeFontID(), kThemeStateActive, false, &bounds, &baseline );
verify_noerr( err );
}
else
#endif
{
wxClientDC dc(const_cast<wxButton*>(this));
wxCoord width, height ;
dc.GetTextExtent( m_label , &width, &height);
bounds.h = width;
bounds.v = height;
}
wBtn = bounds.h + sz.y;
}
else
{
wBtn = bestsize.right - bestsize.left ;
// non 'normal' window variants don't return the correct height
// sz.y = bestsize.bottom - bestsize.top ;
}
if ((wBtn > sz.x) || ( GetWindowStyle() & wxBU_EXACTFIT))
sz.x = wBtn;
return sz ;
}
wxSize wxButton::GetDefaultSize()
{
int wBtn = 70 ;
int hBtn = 20 ;
return wxSize(wBtn, hBtn);
}
void wxButton::Command (wxCommandEvent & event)
{
m_peer->Flash(kControlButtonPart) ;
ProcessCommand(event);
}
wxInt32 wxButton::MacControlHit(WXEVENTHANDLERREF WXUNUSED(handler) , WXEVENTREF WXUNUSED(event) )
{
wxCommandEvent event(wxEVT_COMMAND_BUTTON_CLICKED, m_windowId);
event.SetEventObject(this);
ProcessCommand(event);
return noErr;
}
//-------------------------------------------------------
// wxDisclosureTriangle
//-------------------------------------------------------
bool wxDisclosureTriangle::Create(wxWindow *parent, wxWindowID id, const wxString& label,
const wxPoint& pos, const wxSize& size, long style,const wxValidator& validator, const wxString& name )
{
m_macIsUserPane = false ;
if ( !wxControl::Create(parent, id, pos, size, style, validator, name) )
return false;
Rect bounds = wxMacGetBoundsForControl( this , pos , size ) ;
m_peer = new wxMacControl(this) ;
OSStatus err = CreateDisclosureTriangleControl(
MAC_WXHWND(parent->MacGetTopLevelWindowRef()) , &bounds,
kControlDisclosureTrianglePointDefault,
wxCFStringRef( label ),
0, // closed
TRUE, // draw title
TRUE, // auto toggle back and forth
m_peer->GetControlRefAddr() );
verify_noerr( err );
wxASSERT_MSG( m_peer != NULL && m_peer->Ok() , wxT("No valid Mac control") ) ;
MacPostControlCreate( pos, size );
// passing the text in the param doesn't seem to work, so lets do if again
SetLabel( label );
return true;
}
void wxDisclosureTriangle::SetOpen( bool open )
{
m_peer->SetValue( open ? 1 : 0 );
}
bool wxDisclosureTriangle::IsOpen() const
{
return m_peer->GetValue() == 1;
}
wxInt32 wxDisclosureTriangle::MacControlHit( WXEVENTHANDLERREF WXUNUSED(handler) , WXEVENTREF WXUNUSED(event) )
{
// Just emit button event for now
wxCommandEvent event(wxEVT_COMMAND_BUTTON_CLICKED, m_windowId);
event.SetEventObject(this);
ProcessCommand(event);
return noErr;
}
wxSize wxDisclosureTriangle::DoGetBestSize() const
{
return wxSize(16,16);
}

View File

@@ -0,0 +1,7 @@
// carbon for 9
data 'carb' (0) {
$"0000" /* .. */
};
// the plist resource should only be included in the application
// since it contains the bundle information and should not be duplicated

2311
src/osx/carbon/cfsocket.cpp Normal file

File diff suppressed because it is too large Load Diff

186
src/osx/carbon/checkbox.cpp Normal file
View File

@@ -0,0 +1,186 @@
/////////////////////////////////////////////////////////////////////////////
// Name: src/mac/carbon/checkbox.cpp
// Purpose: wxCheckBox
// Author: Stefan Csomor
// Modified by:
// Created: 04/01/98
// RCS-ID: $Id$
// Copyright: (c) Stefan Csomor
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
#include "wx/wxprec.h"
#if wxUSE_CHECKBOX
#include "wx/checkbox.h"
#include "wx/mac/uma.h"
IMPLEMENT_DYNAMIC_CLASS(wxCheckBox, wxControl)
IMPLEMENT_DYNAMIC_CLASS(wxBitmapCheckBox, wxCheckBox)
// Single check box item
bool wxCheckBox::Create(wxWindow *parent,
wxWindowID id,
const wxString& label,
const wxPoint& pos,
const wxSize& size,
long style,
const wxValidator& validator,
const wxString& name)
{
m_macIsUserPane = false ;
if ( !wxCheckBoxBase::Create(parent, id, pos, size, style, validator, name) )
return false;
m_labelOrig = m_label = label ;
SInt32 maxValue = 1 /* kControlCheckboxCheckedValue */;
if (style & wxCHK_3STATE)
maxValue = 2 /* kControlCheckboxMixedValue */;
Rect bounds = wxMacGetBoundsForControl( this , pos , size ) ;
m_peer = new wxMacControl( this ) ;
verify_noerr( CreateCheckBoxControl(MAC_WXHWND(parent->MacGetTopLevelWindowRef()), &bounds ,
CFSTR("") , 0 , false , m_peer->GetControlRefAddr() ) );
m_peer->SetMaximum( maxValue ) ;
MacPostControlCreate(pos, size) ;
return true;
}
void wxCheckBox::SetValue(bool val)
{
if (val)
Set3StateValue(wxCHK_CHECKED);
else
Set3StateValue(wxCHK_UNCHECKED);
}
bool wxCheckBox::GetValue() const
{
return (DoGet3StateValue() != 0);
}
void wxCheckBox::Command(wxCommandEvent & event)
{
int state = event.GetInt();
wxCHECK_RET( (state == wxCHK_UNCHECKED) || (state == wxCHK_CHECKED)
|| (state == wxCHK_UNDETERMINED),
wxT("event.GetInt() returned an invalid checkbox state") );
Set3StateValue((wxCheckBoxState)state);
ProcessCommand(event);
}
wxCheckBoxState wxCheckBox::DoGet3StateValue() const
{
return (wxCheckBoxState)m_peer->GetValue() ;
}
void wxCheckBox::DoSet3StateValue(wxCheckBoxState val)
{
m_peer->SetValue( val ) ;
}
wxInt32 wxCheckBox::MacControlHit( WXEVENTHANDLERREF WXUNUSED(handler) , WXEVENTREF WXUNUSED(event) )
{
wxCheckBoxState origState, newState;
newState = origState = Get3StateValue();
switch (origState)
{
case wxCHK_UNCHECKED:
newState = wxCHK_CHECKED;
break;
case wxCHK_CHECKED:
// If the style flag to allow the user setting the undetermined state is set,
// then set the state to undetermined; otherwise set state to unchecked.
newState = Is3rdStateAllowedForUser() ? wxCHK_UNDETERMINED : wxCHK_UNCHECKED;
break;
case wxCHK_UNDETERMINED:
newState = wxCHK_UNCHECKED;
break;
default:
break;
}
if (newState != origState)
{
Set3StateValue( newState );
wxCommandEvent event( wxEVT_COMMAND_CHECKBOX_CLICKED, m_windowId );
event.SetInt( newState );
event.SetEventObject( this );
ProcessCommand( event );
}
return noErr;
}
// Bitmap checkbox
bool wxBitmapCheckBox::Create(wxWindow *parent,
wxWindowID id,
const wxBitmap *WXUNUSED(label),
const wxPoint& WXUNUSED(pos),
const wxSize& WXUNUSED(size),
long style,
const wxValidator& wxVALIDATOR_PARAM(validator),
const wxString& name)
{
SetName(name);
#if wxUSE_VALIDATORS
SetValidator(validator);
#endif
m_windowStyle = style;
if (parent)
parent->AddChild(this);
if ( id == -1 )
m_windowId = NewControlId();
else
m_windowId = id;
// TODO: Create the bitmap checkbox
return false;
}
void wxBitmapCheckBox::SetLabel(const wxBitmap *WXUNUSED(bitmap))
{
// TODO
wxFAIL_MSG(wxT("wxBitmapCheckBox::SetLabel() not yet implemented"));
}
void wxBitmapCheckBox::SetSize(int x, int y, int width, int height, int sizeFlags)
{
wxControl::SetSize( x , y , width , height , sizeFlags ) ;
}
void wxBitmapCheckBox::SetValue(bool WXUNUSED(val))
{
// TODO
wxFAIL_MSG(wxT("wxBitmapCheckBox::SetValue() not yet implemented"));
}
bool wxBitmapCheckBox::GetValue() const
{
// TODO
wxFAIL_MSG(wxT("wxBitmapCheckBox::GetValue() not yet implemented"));
return false;
}
#endif

273
src/osx/carbon/checklst.cpp Normal file
View File

@@ -0,0 +1,273 @@
///////////////////////////////////////////////////////////////////////////////
// Name: src/mac/carbon/checklst.cpp
// Purpose: implementation of wxCheckListBox class
// Author: Stefan Csomor
// Modified by:
// Created: 1998-01-01
// RCS-ID: $Id$
// Copyright: (c) Stefan Csomor
// Licence: wxWindows licence
///////////////////////////////////////////////////////////////////////////////
//
// new DataBrowser-based version
#include "wx/wxprec.h"
#if wxUSE_CHECKLISTBOX
#include "wx/checklst.h"
#ifndef WX_PRECOMP
#include "wx/arrstr.h"
#endif
#include "wx/mac/uma.h"
IMPLEMENT_DYNAMIC_CLASS(wxCheckListBox, wxListBox)
BEGIN_EVENT_TABLE(wxCheckListBox, wxListBox)
END_EVENT_TABLE()
class wxMacDataBrowserCheckListControl : public wxMacDataBrowserListControl , public wxMacCheckListControl
{
public:
wxMacDataBrowserCheckListControl( wxListBox *peer, const wxPoint& pos, const wxSize& size, long style );
wxMacDataBrowserCheckListControl() {}
virtual ~wxMacDataBrowserCheckListControl();
virtual wxMacDataItem* CreateItem();
virtual bool MacIsChecked(unsigned int n) const;
virtual void MacCheck(unsigned int n, bool bCheck = true);
DECLARE_DYNAMIC_CLASS_NO_COPY(wxMacDataBrowserCheckListControl)
};
IMPLEMENT_DYNAMIC_CLASS( wxMacDataBrowserCheckListControl , wxMacDataBrowserListControl )
void wxCheckListBox::Init()
{
}
bool wxCheckListBox::Create(
wxWindow *parent,
wxWindowID id,
const wxPoint &pos,
const wxSize &size,
const wxArrayString& choices,
long style,
const wxValidator& validator,
const wxString &name )
{
wxCArrayString chs( choices );
return Create( parent, id, pos, size, chs.GetCount(), chs.GetStrings(), style, validator, name );
}
bool wxCheckListBox::Create(
wxWindow *parent,
wxWindowID id,
const wxPoint& pos,
const wxSize& size,
int n,
const wxString choices[],
long style,
const wxValidator& validator,
const wxString& name )
{
m_macIsUserPane = false;
wxASSERT_MSG( !(style & wxLB_MULTIPLE) || !(style & wxLB_EXTENDED),
wxT("only one of listbox selection modes can be specified") );
if ( !wxListBoxBase::Create( parent, id, pos, size, style & ~(wxHSCROLL | wxVSCROLL), validator, name ) )
return false;
// this will be increased by our Append command
wxMacDataBrowserCheckListControl* control = new wxMacDataBrowserCheckListControl( this, pos, size, style );
// TODO CHECK control->SetClientDataType( m_clientDataItemsType );
m_peer = control;
MacPostControlCreate(pos,size);
InsertItems( n , choices , 0 );
// Needed because it is a wxControlWithItems
SetInitialSize( size );
return true;
}
// ----------------------------------------------------------------------------
// wxCheckListBox functions
// ----------------------------------------------------------------------------
bool wxCheckListBox::IsChecked(unsigned int item) const
{
wxCHECK_MSG( IsValid(item), false,
wxT("invalid index in wxCheckListBox::IsChecked") );
return GetPeer()->MacIsChecked( item );
}
void wxCheckListBox::Check(unsigned int item, bool check)
{
wxCHECK_RET( IsValid(item),
wxT("invalid index in wxCheckListBox::Check") );
bool isChecked = GetPeer()->MacIsChecked( item );
if ( check != isChecked )
{
GetPeer()->MacCheck( item , check );
}
}
wxMacCheckListControl* wxCheckListBox::GetPeer() const
{
wxMacDataBrowserCheckListControl *lb = wxDynamicCast(m_peer,wxMacDataBrowserCheckListControl);
return lb ? wx_static_cast(wxMacCheckListControl*,lb) : 0 ;
}
const short kCheckboxColumnId = 1026;
wxMacDataBrowserCheckListControl::wxMacDataBrowserCheckListControl( wxListBox *peer, const wxPoint& pos, const wxSize& size, long style)
: wxMacDataBrowserListControl( peer, pos, size, style )
{
OSStatus err = noErr;
DataBrowserListViewColumnDesc columnDesc;
columnDesc.headerBtnDesc.titleOffset = 0;
columnDesc.headerBtnDesc.version = kDataBrowserListViewLatestHeaderDesc;
columnDesc.headerBtnDesc.btnFontStyle.flags =
kControlUseFontMask | kControlUseJustMask;
columnDesc.headerBtnDesc.btnContentInfo.contentType = kControlNoContent;
columnDesc.headerBtnDesc.btnFontStyle.just = teFlushDefault;
columnDesc.headerBtnDesc.btnFontStyle.font = kControlFontViewSystemFont;
columnDesc.headerBtnDesc.btnFontStyle.style = normal;
columnDesc.headerBtnDesc.titleString = NULL;
columnDesc.headerBtnDesc.minimumWidth = 30;
columnDesc.headerBtnDesc.maximumWidth = 30;
columnDesc.propertyDesc.propertyID = kCheckboxColumnId;
columnDesc.propertyDesc.propertyType = kDataBrowserCheckboxType;
columnDesc.propertyDesc.propertyFlags =
kDataBrowserPropertyIsMutable
| kDataBrowserTableViewSelectionColumn
| kDataBrowserDefaultPropertyFlags;
err = AddColumn( &columnDesc, 0 );
verify_noerr( err );
}
wxMacDataBrowserCheckListControl::~wxMacDataBrowserCheckListControl()
{
}
class wxMacCheckListBoxItem : public wxMacListBoxItem
{
public :
wxMacCheckListBoxItem()
{
m_isChecked = false;
}
virtual ~wxMacCheckListBoxItem()
{
}
virtual OSStatus GetSetData( wxMacDataItemBrowserControl *owner ,
DataBrowserPropertyID property,
DataBrowserItemDataRef itemData,
bool changeValue )
{
OSStatus err = errDataBrowserPropertyNotSupported;
wxCheckListBox *checklist = wxDynamicCast( owner->GetPeer() , wxCheckListBox );
wxCHECK_MSG( checklist != NULL , errDataBrowserPropertyNotSupported , wxT("wxCheckListBox expected"));
if ( !changeValue )
{
switch (property)
{
case kCheckboxColumnId:
verify_noerr(SetDataBrowserItemDataButtonValue( itemData, m_isChecked ? kThemeButtonOn : kThemeButtonOff ));
err = noErr;
break;
case kDataBrowserItemIsEditableProperty:
verify_noerr(SetDataBrowserItemDataBooleanValue( itemData, true ));
err = noErr;
break;
default:
break;
}
}
else
{
switch (property)
{
case kCheckboxColumnId:
{
// we have to change this behind the back, since Check() would be triggering another update round
bool newVal = !m_isChecked;
verify_noerr(SetDataBrowserItemDataButtonValue( itemData, newVal ? kThemeButtonOn : kThemeButtonOff ));
m_isChecked = newVal;
err = noErr;
wxCommandEvent event( wxEVT_COMMAND_CHECKLISTBOX_TOGGLED, checklist->GetId() );
event.SetInt( owner->GetLineFromItem( this ) );
event.SetEventObject( checklist );
checklist->HandleWindowEvent( event );
}
break;
default:
break;
}
}
if ( err == errDataBrowserPropertyNotSupported )
err = wxMacListBoxItem::GetSetData( owner , property, itemData , changeValue);
return err;
}
void Check( bool check )
{
m_isChecked = check;
}
bool IsChecked() const
{
return m_isChecked;
}
protected :
bool m_isChecked;
};
wxMacDataItem* wxMacDataBrowserCheckListControl::CreateItem()
{
return new wxMacCheckListBoxItem();
}
void wxMacDataBrowserCheckListControl::MacCheck( unsigned int n, bool bCheck)
{
wxMacCheckListBoxItem* item = wx_static_cast(wxMacCheckListBoxItem*, GetItemFromLine( n) );
item->Check( bCheck);
UpdateItem(wxMacDataBrowserRootContainer, item , kCheckboxColumnId);
}
bool wxMacDataBrowserCheckListControl::MacIsChecked( unsigned int n) const
{
wxMacCheckListBoxItem * item = wx_static_cast( wxMacCheckListBoxItem*, GetItemFromLine( n ) );
return item->IsChecked();
}
#endif // wxUSE_CHECKLISTBOX

308
src/osx/carbon/choice.cpp Normal file
View File

@@ -0,0 +1,308 @@
/////////////////////////////////////////////////////////////////////////////
// Name: src/mac/carbon/choice.cpp
// Purpose: wxChoice
// Author: Stefan Csomor
// Modified by:
// Created: 1998-01-01
// RCS-ID: $Id$
// Copyright: (c) Stefan Csomor
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
#include "wx/wxprec.h"
#if wxUSE_CHOICE
#include "wx/choice.h"
#ifndef WX_PRECOMP
#include "wx/menu.h"
#include "wx/dcclient.h"
#endif
#include "wx/mac/uma.h"
extern MenuHandle NewUniqueMenu() ;
IMPLEMENT_DYNAMIC_CLASS(wxChoice, wxControlWithItems)
wxChoice::~wxChoice()
{
if ( HasClientObjectData() )
{
unsigned int i, max = GetCount();
for ( i = 0; i < max; ++i )
delete GetClientObject( i );
}
// DeleteMenu( m_macPopUpMenuId ) ;
// DisposeMenu( m_macPopUpMenuHandle ) ;
}
bool wxChoice::Create(wxWindow *parent,
wxWindowID id,
const wxPoint& pos,
const wxSize& size,
const wxArrayString& choices,
long style,
const wxValidator& validator,
const wxString& name )
{
if ( !Create( parent, id, pos, size, 0, NULL, style, validator, name ) )
return false;
Append( choices );
if ( !choices.empty() )
SetSelection( 0 );
SetInitialSize( size );
return true;
}
bool wxChoice::Create(wxWindow *parent,
wxWindowID id,
const wxPoint& pos,
const wxSize& size,
int n,
const wxString choices[],
long style,
const wxValidator& validator,
const wxString& name )
{
m_macIsUserPane = false;
if ( !wxChoiceBase::Create( parent, id, pos, size, style, validator, name ) )
return false;
Rect bounds = wxMacGetBoundsForControl( this , pos , size );
m_peer = new wxMacControl( this ) ;
OSStatus err = CreatePopupButtonControl(
MAC_WXHWND(parent->MacGetTopLevelWindowRef()) , &bounds , CFSTR("") ,
-12345 , false /* no variable width */ , 0 , 0 , 0 , m_peer->GetControlRefAddr() );
verify_noerr( err );
m_macPopUpMenuHandle = NewUniqueMenu() ;
m_peer->SetData<MenuHandle>( kControlNoPart , kControlPopupButtonMenuHandleTag , (MenuHandle) m_macPopUpMenuHandle ) ;
m_peer->SetValueAndRange( n > 0 ? 1 : 0 , 0 , 0 );
MacPostControlCreate( pos, size );
#if !wxUSE_STL
if ( style & wxCB_SORT )
// autosort
m_strings = wxArrayString( 1 );
#endif
Append(n, choices);
// Set the first item as being selected
if (n > 0)
SetSelection( 0 );
// Needed because it is a wxControlWithItems
SetInitialSize( size );
return true;
}
// ----------------------------------------------------------------------------
// adding/deleting items to/from the list
// ----------------------------------------------------------------------------
int wxChoice::DoInsertItems(const wxArrayStringsAdapter & items,
unsigned int pos,
void **clientData, wxClientDataType type)
{
const unsigned int numItems = items.GetCount();
for( unsigned int i = 0; i < numItems; ++i, ++pos )
{
unsigned int idx;
#if wxUSE_STL
if ( IsSorted() )
{
wxArrayString::iterator
insertPoint = std::lower_bound( m_strings.begin(), m_strings.end(), items[i] );
idx = insertPoint - m_strings.begin();
m_strings.insert( insertPoint, items[i] );
}
else
#endif // wxUSE_STL
{
idx = pos;
m_strings.Insert( items[i], idx );
}
UMAInsertMenuItem(MAC_WXHMENU( m_macPopUpMenuHandle ),
items[i],
GetFont().GetEncoding(),
idx);
m_datas.Insert( NULL, idx );
AssignNewItemClientData(idx, clientData, i, type);
}
m_peer->SetMaximum( GetCount() );
return pos - 1;
}
void wxChoice::DoDeleteOneItem(unsigned int n)
{
wxCHECK_RET( IsValid(n) , wxT("wxChoice::Delete: invalid index") );
if ( HasClientObjectData() )
delete GetClientObject( n );
::DeleteMenuItem( MAC_WXHMENU(m_macPopUpMenuHandle) , n + 1 ) ;
m_strings.RemoveAt( n ) ;
m_datas.RemoveAt( n ) ;
m_peer->SetMaximum( GetCount() ) ;
}
void wxChoice::DoClear()
{
for ( unsigned int i = 0 ; i < GetCount() ; i++ )
{
::DeleteMenuItem( MAC_WXHMENU(m_macPopUpMenuHandle) , 1 ) ;
}
m_strings.Empty() ;
m_datas.Empty() ;
m_peer->SetMaximum( 0 ) ;
}
// ----------------------------------------------------------------------------
// selection
// ----------------------------------------------------------------------------
int wxChoice::GetSelection() const
{
return m_peer->GetValue() - 1 ;
}
void wxChoice::SetSelection( int n )
{
m_peer->SetValue( n + 1 ) ;
}
// ----------------------------------------------------------------------------
// string list functions
// ----------------------------------------------------------------------------
unsigned int wxChoice::GetCount() const
{
return m_strings.GetCount() ;
}
int wxChoice::FindString( const wxString& s, bool bCase ) const
{
#if !wxUSE_STL
// Avoid assert for non-default args passed to sorted array Index
if ( IsSorted() )
bCase = true;
#endif
return m_strings.Index( s , bCase ) ;
}
void wxChoice::SetString(unsigned int n, const wxString& s)
{
wxCHECK_RET( IsValid(n), wxT("wxChoice::SetString(): invalid index") );
m_strings[n] = s ;
// apple menu pos is 1-based
UMASetMenuItemText( MAC_WXHMENU(m_macPopUpMenuHandle) , n + 1 , s , wxFont::GetDefaultEncoding() ) ;
}
wxString wxChoice::GetString(unsigned int n) const
{
wxCHECK_MSG( IsValid(n), wxEmptyString, wxT("wxChoice::GetString(): invalid index") );
return m_strings[n] ;
}
// ----------------------------------------------------------------------------
// client data
// ----------------------------------------------------------------------------
void wxChoice::DoSetItemClientData(unsigned int n, void* clientData)
{
wxCHECK_RET( IsValid(n), wxT("wxChoice::DoSetItemClientData: invalid index") );
m_datas[n] = (char*)clientData ;
}
void * wxChoice::DoGetItemClientData(unsigned int n) const
{
wxCHECK_MSG( IsValid(n), NULL, wxT("wxChoice::DoGetClientData: invalid index") );
return (void *)m_datas[n];
}
wxInt32 wxChoice::MacControlHit( WXEVENTHANDLERREF WXUNUSED(handler) , WXEVENTREF WXUNUSED(event) )
{
wxCommandEvent event( wxEVT_COMMAND_CHOICE_SELECTED, m_windowId );
// actually n should be made sure by the os to be a valid selection, but ...
int n = GetSelection();
if ( n > -1 )
{
event.SetInt( n );
event.SetString( GetStringSelection() );
event.SetEventObject( this );
if ( HasClientObjectData() )
event.SetClientObject( GetClientObject( n ) );
else if ( HasClientUntypedData() )
event.SetClientData( GetClientData( n ) );
ProcessCommand( event );
}
return noErr ;
}
wxSize wxChoice::DoGetBestSize() const
{
int lbWidth = GetCount() > 0 ? 20 : 100; // some defaults
int lbHeight = 20;
int wLine;
SInt32 metric ;
GetThemeMetric( kThemeMetricPopupButtonHeight , &metric );
lbHeight = metric ;
{
wxClientDC dc(const_cast<wxChoice*>(this));
// Find the widest line
for(unsigned int i = 0; i < GetCount(); i++)
{
wxString str(GetString(i));
wxCoord width, height ;
dc.GetTextExtent( str , &width, &height);
wLine = width ;
lbWidth = wxMax( lbWidth, wLine ) ;
}
// Add room for the popup arrow
lbWidth += 2 * lbHeight ;
wxCoord width, height ;
dc.GetTextExtent( wxT("X"), &width, &height);
int cx = width ;
lbHeight += 4;
lbWidth += cx ;
}
return wxSize( lbWidth, lbHeight );
}
#endif // wxUSE_CHOICE

209
src/osx/carbon/clipbrd.cpp Normal file
View File

@@ -0,0 +1,209 @@
/////////////////////////////////////////////////////////////////////////////
// Name: src/mac/carbon/clipbrd.cpp
// Purpose: Clipboard functionality
// Author: Stefan Csomor;
// Generalized clipboard implementation by Matthew Flatt
// Modified by:
// Created: 1998-01-01
// RCS-ID: $Id$
// Copyright: (c) Stefan Csomor
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
#include "wx/wxprec.h"
#if wxUSE_CLIPBOARD
#include "wx/clipbrd.h"
#ifndef WX_PRECOMP
#include "wx/intl.h"
#include "wx/log.h"
#include "wx/app.h"
#include "wx/utils.h"
#include "wx/frame.h"
#include "wx/bitmap.h"
#endif
#include "wx/metafile.h"
#include "wx/mac/uma.h"
#define wxUSE_DATAOBJ 1
#include <string.h>
// the trace mask we use with wxLogTrace() - call
// wxLog::AddTraceMask(TRACE_CLIPBOARD) to enable the trace messages from here
// (there will be a *lot* of them!)
#define TRACE_CLIPBOARD _T("clipboard")
IMPLEMENT_DYNAMIC_CLASS(wxClipboard, wxObject)
wxClipboard::wxClipboard()
{
m_open = false;
m_data = NULL ;
PasteboardRef clipboard = 0;
OSStatus err = PasteboardCreate( kPasteboardClipboard, &clipboard );
if (err != noErr)
{
wxLogSysError( wxT("Failed to create the clipboard.") );
}
m_pasteboard.reset(clipboard);
}
wxClipboard::~wxClipboard()
{
m_pasteboard.reset((PasteboardRef)0);
delete m_data;
}
void wxClipboard::Clear()
{
if (m_data != NULL)
{
delete m_data;
m_data = NULL;
}
OSStatus err = PasteboardClear( m_pasteboard );
if (err != noErr)
{
wxLogSysError( wxT("Failed to empty the clipboard.") );
}
}
bool wxClipboard::Flush()
{
return false;
}
bool wxClipboard::Open()
{
wxCHECK_MSG( !m_open, false, wxT("clipboard already open") );
m_open = true;
return true;
}
bool wxClipboard::IsOpened() const
{
return m_open;
}
bool wxClipboard::SetData( wxDataObject *data )
{
if ( IsUsingPrimarySelection() )
return false;
wxCHECK_MSG( m_open, false, wxT("clipboard not open") );
wxCHECK_MSG( data, false, wxT("data is invalid") );
Clear();
// as we can only store one wxDataObject,
// this is the same in this implementation
return AddData( data );
}
bool wxClipboard::AddData( wxDataObject *data )
{
if ( IsUsingPrimarySelection() )
return false;
wxCHECK_MSG( m_open, false, wxT("clipboard not open") );
wxCHECK_MSG( data, false, wxT("data is invalid") );
// we can only store one wxDataObject
Clear();
PasteboardSyncFlags syncFlags = PasteboardSynchronize( m_pasteboard );
wxCHECK_MSG( !(syncFlags&kPasteboardModified), false, wxT("clipboard modified after clear") );
wxCHECK_MSG( (syncFlags&kPasteboardClientIsOwner), false, wxT("client couldn't own clipboard") );
m_data = data;
data->AddToPasteboard( m_pasteboard, 1 );
return true;
}
void wxClipboard::Close()
{
wxCHECK_RET( m_open, wxT("clipboard not open") );
m_open = false;
// Get rid of cached object.
// If this is not done, copying data from
// another application will only work once
if (m_data)
{
delete m_data;
m_data = (wxDataObject*) NULL;
}
}
bool wxClipboard::IsSupported( const wxDataFormat &dataFormat )
{
wxLogTrace(TRACE_CLIPBOARD, wxT("Checking if format %s is available"),
dataFormat.GetId().c_str());
if ( m_data )
return m_data->IsSupported( dataFormat );
return wxDataObject::IsFormatInPasteboard( m_pasteboard, dataFormat );
}
bool wxClipboard::GetData( wxDataObject& data )
{
if ( IsUsingPrimarySelection() )
return false;
wxCHECK_MSG( m_open, false, wxT("clipboard not open") );
size_t formatcount = data.GetFormatCount() + 1;
wxDataFormat *array = new wxDataFormat[ formatcount ];
array[0] = data.GetPreferredFormat();
data.GetAllFormats( &array[1] );
bool transferred = false;
if ( m_data )
{
for (size_t i = 0; !transferred && i < formatcount; i++)
{
wxDataFormat format = array[ i ];
if ( m_data->IsSupported( format ) )
{
int dataSize = m_data->GetDataSize( format );
transferred = true;
if (dataSize == 0)
{
data.SetData( format, 0, 0 );
}
else
{
char *d = new char[ dataSize ];
m_data->GetDataHere( format, (void*)d );
data.SetData( format, dataSize, d );
delete [] d;
}
}
}
}
// get formats from wxDataObjects
if ( !transferred )
{
transferred = data.GetFromPasteboard( m_pasteboard ) ;
}
delete [] array;
return transferred;
}
#endif

View File

@@ -0,0 +1,75 @@
/////////////////////////////////////////////////////////////////////////////
// Name: colordlg.cpp
// Purpose: wxColourDialog class. NOTE: you can use the generic class
// if you wish, instead of implementing this.
// Author: Stefan Csomor
// Modified by:
// Created: 1998-01-01
// RCS-ID: $Id$
// Copyright: (c) Stefan Csomor
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
#include "wx/wxprec.h"
#include "wx/mac/colordlg.h"
#include "wx/fontdlg.h"
#if !USE_NATIVE_FONT_DIALOG_FOR_MACOSX
IMPLEMENT_DYNAMIC_CLASS(wxColourDialog, wxDialog)
#include "wx/mac/private.h"
/*
* wxColourDialog
*/
wxColourDialog::wxColourDialog()
{
m_dialogParent = NULL;
}
wxColourDialog::wxColourDialog(wxWindow *parent, wxColourData *data)
{
Create(parent, data);
}
bool wxColourDialog::Create(wxWindow *parent, wxColourData *data)
{
m_dialogParent = parent;
if (data)
m_colourData = *data;
return true;
}
int wxColourDialog::ShowModal()
{
RGBColor currentColor ;
m_colourData.m_dataColour.GetRGBColor( currentColor );
NColorPickerInfo info;
OSStatus err ;
memset(&info, 0, sizeof(info)) ;
// TODO : use parent to determine better position and then kAtSpecifiedOrigin
info.placeWhere = kCenterOnMainScreen ;
info.flags = kColorPickerDialogIsMoveable | kColorPickerDialogIsModal ;
info.theColor.color.rgb.red = currentColor.red ;
info.theColor.color.rgb.green = currentColor.green ;
info.theColor.color.rgb.blue = currentColor.blue ;
err = NPickColor(&info);
if ((err == noErr) && info.newColorChosen)
{
currentColor.red = info.theColor.color.rgb.red ;
currentColor.green = info.theColor.color.rgb.green ;
currentColor.blue = info.theColor.color.rgb.blue ;
m_colourData.m_dataColour = currentColor;
return wxID_OK;
}
return wxID_CANCEL;
}
#endif

View File

@@ -0,0 +1,193 @@
/////////////////////////////////////////////////////////////////////////////
// Name: src/mac/carbon/colordlg.mm
// Purpose: wxColourDialog class. NOTE: you can use the generic class
// if you wish, instead of implementing this.
// Author: Ryan Norton
// Modified by:
// Created: 2004-11-16
// RCS-ID: $Id$
// Copyright: (c) Ryan Norton
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
// ===========================================================================
// declarations
// ===========================================================================
// ---------------------------------------------------------------------------
// headers
// ---------------------------------------------------------------------------
#include "wx/wxprec.h"
#include "wx/mac/colordlg.h"
#include "wx/fontdlg.h"
// ============================================================================
// implementation
// ============================================================================
//Mac OSX 10.2+ only
#if USE_NATIVE_FONT_DIALOG_FOR_MACOSX
IMPLEMENT_DYNAMIC_CLASS(wxColourDialog, wxDialog)
// Cocoa headers
#include "wx/cocoa/autorelease.h"
#include "wx/cocoa/string.h"
#import <AppKit/NSFont.h>
#import <AppKit/NSFontManager.h>
#import <AppKit/NSFontPanel.h>
#import <AppKit/NSColor.h>
#import <AppKit/NSColorPanel.h>
// ---------------------------------------------------------------------------
// wxCPWCDelegate - Window Closed delegate
// ---------------------------------------------------------------------------
@interface wxCPWCDelegate : NSObject
{
bool m_bIsClosed;
}
// Delegate methods
- (id)init;
- (BOOL)windowShouldClose:(id)sender;
- (BOOL)isClosed;
@end // interface wxNSFontPanelDelegate : NSObject
@implementation wxCPWCDelegate : NSObject
- (id)init
{
[super init];
m_bIsClosed = false;
return self;
}
- (BOOL)windowShouldClose:(id)sender
{
wxUnusedVar(sender);
m_bIsClosed = true;
[NSApp abortModal];
[NSApp stopModal];
return YES;
}
- (BOOL)isClosed
{
return m_bIsClosed;
}
@end // wxNSFontPanelDelegate
/*
* wxColourDialog
*/
wxColourDialog::wxColourDialog()
{
m_dialogParent = NULL;
}
wxColourDialog::wxColourDialog(wxWindow *parent, wxColourData *data)
{
Create(parent, data);
}
bool wxColourDialog::Create(wxWindow *parent, wxColourData *data)
{
m_dialogParent = parent;
if (data)
m_colourData = *data;
//
// This is the key call - this initializes
// events and window stuff for cocoa for carbon
// applications.
//
// This is also the only call here that is
// 10.2+ specific (the rest is OSX only),
// which, ironically, the carbon font
// panel requires.
//
bool bOK = NSApplicationLoad();
//autorelease pool - req'd for carbon
NSAutoreleasePool *thePool;
thePool = [[NSAutoreleasePool alloc] init];
if(m_colourData.m_dataColour.Ok())
[[NSColorPanel sharedColorPanel] setColor:
[NSColor colorWithCalibratedRed:m_colourData.m_dataColour.Red() / 255.0
green:m_colourData.m_dataColour.Green() / 255.0
blue:m_colourData.m_dataColour.Blue() / 255.0
alpha:1.0]
];
else
[[NSColorPanel sharedColorPanel] setColor:[NSColor blackColor]];
//We're done - free up the pool
[thePool release];
return bOK;
}
int wxColourDialog::ShowModal()
{
//Start the pool. Required for carbon interaction
//(For those curious, the only thing that happens
//if you don't do this is a bunch of error
//messages about leaks on the console,
//with no windows shown or anything).
NSAutoreleasePool *thePool;
thePool = [[NSAutoreleasePool alloc] init];
//Get the shared color and font panel
NSColorPanel* theColorPanel = [NSColorPanel sharedColorPanel];
//Create and assign the delegates (cocoa event handlers) so
//we can tell if a window has closed/open or not
wxCPWCDelegate* theCPDelegate = [[wxCPWCDelegate alloc] init];
[theColorPanel setDelegate:theCPDelegate];
//
// Start the color panel modal loop
//
NSModalSession session = [NSApp beginModalSessionForWindow:theColorPanel];
for (;;)
{
[NSApp runModalSession:session];
//If the color panel is closed, return the font panel modal loop
if ([theCPDelegate isClosed])
break;
}
[NSApp endModalSession:session];
//free up the memory for the delegates - we don't need them anymore
[theCPDelegate release];
//Get the shared color panel along with the chosen color and set the chosen color
NSColor* theColor = [[theColorPanel color] colorUsingColorSpaceName:NSCalibratedRGBColorSpace];
m_colourData.m_dataColour.Set(
(unsigned char) ([theColor redComponent] * 255.0),
(unsigned char) ([theColor greenComponent] * 255.0),
(unsigned char) ([theColor blueComponent] * 255.0)
);
//Release the pool, we're done :)
[thePool release];
//Return ID_OK - there are no "apply" buttons or the like
//on either the font or color panel
return wxID_OK;
}
#endif //use native font dialog

147
src/osx/carbon/colour.cpp Normal file
View File

@@ -0,0 +1,147 @@
/////////////////////////////////////////////////////////////////////////////
// Name: src/mac/carbon/colour.cpp
// Purpose: wxColour class
// Author: Stefan Csomor
// Modified by:
// Created: 1998-01-01
// RCS-ID: $Id$
// Copyright: (c) Stefan Csomor
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
#include "wx/wxprec.h"
#include "wx/colour.h"
#ifndef WX_PRECOMP
#include "wx/gdicmn.h"
#endif
#include "wx/mac/private.h"
IMPLEMENT_DYNAMIC_CLASS(wxColour, wxObject)
#if wxMAC_USE_QUICKDRAW
wxColour::wxColour(const RGBColor& col)
{
InitRGBColor(col);
}
#endif
wxColour::wxColour(CGColorRef col)
{
InitCGColorRef(col);
}
#if wxMAC_USE_QUICKDRAW
void wxColour::GetRGBColor( RGBColor *col ) const
{
col->red = (m_red << 8) + m_red;
col->blue = (m_blue << 8) + m_blue;
col->green = (m_green << 8) + m_green;
}
wxColour& wxColour::operator=(const RGBColor& col)
{
InitRGBColor(col);
return *this;
}
#endif
wxColour& wxColour::operator=(CGColorRef col)
{
InitCGColorRef(col);
return *this;
}
wxColour& wxColour::operator=(const wxColour& col)
{
m_red = col.m_red;
m_green = col.m_green;
m_blue = col.m_blue;
m_alpha = col.m_alpha;
m_cgColour = col.m_cgColour;
return *this;
}
void wxColour::InitRGBA (ChannelType r, ChannelType g, ChannelType b, ChannelType a)
{
m_red = r;
m_green = g;
m_blue = b;
m_alpha = a ;
CGColorRef col = 0 ;
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
if ( CGColorCreateGenericRGB )
col = CGColorCreateGenericRGB( (CGFloat)(r / 255.0), (CGFloat) (g / 255.0), (CGFloat) (b / 255.0), (CGFloat) (a / 255.0) );
else
#endif
{
CGFloat components[4] = { (CGFloat)(r / 255.0), (CGFloat) (g / 255.0), (CGFloat) (b / 255.0), (CGFloat) (a / 255.0) } ;
col = CGColorCreate( wxMacGetGenericRGBColorSpace() , components ) ;
}
m_cgColour.reset( col );
}
#if wxMAC_USE_QUICKDRAW
void wxColour::InitRGBColor( const RGBColor& col )
{
m_red = col.red >> 8;
m_blue = col.blue >> 8;
m_green = col.green >> 8;
m_alpha = wxALPHA_OPAQUE;
CGColorRef cfcol;
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
if ( CGColorCreateGenericRGB )
cfcol = CGColorCreateGenericRGB((CGFloat)(col.red / 65535.0), (CGFloat)(col.green / 65535.0),
(CGFloat)(col.blue / 65535.0), (CGFloat) 1.0 );
else
#endif
{
CGFloat components[4] = { (CGFloat)(col.red / 65535.0), (CGFloat)(col.green / 65535.0),
(CGFloat)(col.blue / 65535.0), (CGFloat) 1.0 } ;
cfcol = CGColorCreate( wxMacGetGenericRGBColorSpace() , components ) ;
}
m_cgColour.reset( cfcol );
}
#endif
void wxColour::InitCGColorRef( CGColorRef col )
{
m_cgColour.reset( col );
size_t noComp = CGColorGetNumberOfComponents( col );
if ( noComp >= 1 && noComp <= 4 )
{
// TODO verify whether we really are on a RGB color space
m_alpha = wxALPHA_OPAQUE;
const CGFloat *components = CGColorGetComponents( col );
if ( noComp >= 3 )
{
m_red = (int)(components[0]*255+0.5);
m_green = (int)(components[1]*255+0.5);
m_blue = (int)(components[2]*255+0.5);
if ( noComp == 4 )
m_alpha = (int)(components[3]*255+0.5);
}
else
{
m_red = (int)(components[0]*255+0.5);
m_green = (int)(components[0]*255+0.5);
m_blue = (int)(components[0]*255+0.5);
}
}
else
{
m_alpha = wxALPHA_OPAQUE;
m_red = m_green = m_blue = 0;
}
}
bool wxColour::operator == (const wxColour& colour) const
{
return ( (IsOk() == colour.IsOk()) && (!IsOk() ||
CGColorEqualToColor( m_cgColour, colour.m_cgColour ) ) );
}

668
src/osx/carbon/combobox.cpp Normal file
View File

@@ -0,0 +1,668 @@
/////////////////////////////////////////////////////////////////////////////
// Name: src/mac/carbon/combobox.cpp
// Purpose: wxComboBox class
// Author: Stefan Csomor, Dan "Bud" Keith (composite combobox)
// Modified by:
// Created: 1998-01-01
// RCS-ID: $Id$
// Copyright: (c) Stefan Csomor
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
#include "wx/wxprec.h"
#if wxUSE_COMBOBOX
#include "wx/combobox.h"
#ifndef WX_PRECOMP
#include "wx/button.h"
#include "wx/menu.h"
#include "wx/containr.h"
#include "wx/toplevel.h"
#include "wx/textctrl.h"
#endif
#include "wx/mac/uma.h"
IMPLEMENT_DYNAMIC_CLASS(wxComboBox, wxControl)
WX_DELEGATE_TO_CONTROL_CONTAINER(wxComboBox, wxControl)
BEGIN_EVENT_TABLE(wxComboBox, wxControl)
WX_EVENT_TABLE_CONTROL_CONTAINER(wxComboBox)
END_EVENT_TABLE()
static int nextPopUpMenuId = 1000 ;
MenuHandle NewUniqueMenu()
{
MenuHandle handle = UMANewMenu(nextPopUpMenuId, wxString(wxT("Menu")), wxFont::GetDefaultEncoding() );
nextPopUpMenuId++ ;
return handle ;
}
// ----------------------------------------------------------------------------
// constants
// ----------------------------------------------------------------------------
// the margin between the text control and the choice
// margin should be bigger on OS X due to blue highlight
// around text control.
static const wxCoord MARGIN = 4;
// this is the border a focus rect on OSX is needing
static const int TEXTFOCUSBORDER = 3 ;
// ----------------------------------------------------------------------------
// wxComboBoxText: text control forwards events to combobox
// ----------------------------------------------------------------------------
class wxComboBoxText : public wxTextCtrl
{
public:
wxComboBoxText( wxComboBox * cb )
: wxTextCtrl( cb , 1 )
{
m_cb = cb;
SetTriggerOnSetValue( false );
}
protected:
void OnChar( wxKeyEvent& event )
{
// Allows processing the tab key to go to the next control
if (event.GetKeyCode() == WXK_TAB)
{
wxNavigationKeyEvent NavEvent;
NavEvent.SetEventObject(this);
NavEvent.SetDirection(true);
NavEvent.SetWindowChange(false);
// Get the parent of the combo and have it process the navigation?
if (m_cb->GetParent()->HandleWindowEvent(NavEvent))
return;
}
// send the event to the combobox class in case the user has bound EVT_CHAR
wxKeyEvent kevt(event);
kevt.SetEventObject(m_cb);
if (m_cb->HandleWindowEvent(kevt))
// If the event was handled and not skipped then we're done
return;
if ( event.GetKeyCode() == WXK_RETURN )
{
wxCommandEvent event(wxEVT_COMMAND_TEXT_ENTER, m_cb->GetId());
event.SetString( GetValue() );
event.SetInt( m_cb->GetSelection() );
event.SetEventObject( m_cb );
// This will invoke the dialog default action,
// such as the clicking the default button.
if (!m_cb->HandleWindowEvent( event ))
{
wxTopLevelWindow *tlw = wxDynamicCast(wxGetTopLevelParent(this), wxTopLevelWindow);
if ( tlw && tlw->GetDefaultItem() )
{
wxButton *def = wxDynamicCast(tlw->GetDefaultItem(), wxButton);
if ( def && def->IsEnabled() )
{
wxCommandEvent event( wxEVT_COMMAND_BUTTON_CLICKED, def->GetId() );
event.SetEventObject(def);
def->Command(event);
}
}
return;
}
}
event.Skip();
}
void OnKeyUp( wxKeyEvent& event )
{
event.SetEventObject(m_cb);
event.SetId(m_cb->GetId());
if (! m_cb->HandleWindowEvent(event))
event.Skip();
}
void OnKeyDown( wxKeyEvent& event )
{
event.SetEventObject(m_cb);
event.SetId(m_cb->GetId());
if (! m_cb->HandleWindowEvent(event))
event.Skip();
}
void OnText( wxCommandEvent& event )
{
event.SetEventObject(m_cb);
event.SetId(m_cb->GetId());
if (! m_cb->HandleWindowEvent(event))
event.Skip();
}
private:
wxComboBox *m_cb;
DECLARE_EVENT_TABLE()
};
BEGIN_EVENT_TABLE(wxComboBoxText, wxTextCtrl)
EVT_KEY_DOWN(wxComboBoxText::OnKeyDown)
EVT_CHAR(wxComboBoxText::OnChar)
EVT_KEY_UP(wxComboBoxText::OnKeyUp)
EVT_TEXT(wxID_ANY, wxComboBoxText::OnText)
END_EVENT_TABLE()
class wxComboBoxChoice : public wxChoice
{
public:
wxComboBoxChoice( wxComboBox *cb, int style )
: wxChoice( cb , 1 , wxDefaultPosition , wxDefaultSize , 0 , NULL , style & (wxCB_SORT) )
{
m_cb = cb;
}
int GetPopupWidth() const
{
switch ( GetWindowVariant() )
{
case wxWINDOW_VARIANT_NORMAL :
case wxWINDOW_VARIANT_LARGE :
return 24 ;
default :
return 21 ;
}
}
protected:
void OnChoice( wxCommandEvent& e )
{
wxString s = e.GetString();
m_cb->DelegateChoice( s );
wxCommandEvent event2(wxEVT_COMMAND_COMBOBOX_SELECTED, m_cb->GetId() );
event2.SetInt(m_cb->GetSelection());
event2.SetEventObject(m_cb);
event2.SetString(m_cb->GetStringSelection());
m_cb->ProcessCommand(event2);
// For consistency with MSW and GTK, also send a text updated event
// After all, the text is updated when a selection is made
wxCommandEvent TextEvent( wxEVT_COMMAND_TEXT_UPDATED, m_cb->GetId() );
TextEvent.SetString( m_cb->GetStringSelection() );
TextEvent.SetEventObject( m_cb );
m_cb->ProcessCommand( TextEvent );
}
virtual wxSize DoGetBestSize() const
{
wxSize sz = wxChoice::DoGetBestSize() ;
if (! m_cb->HasFlag(wxCB_READONLY) )
sz.x = GetPopupWidth() ;
return sz ;
}
private:
wxComboBox *m_cb;
friend class wxComboBox;
DECLARE_EVENT_TABLE()
};
BEGIN_EVENT_TABLE(wxComboBoxChoice, wxChoice)
EVT_CHOICE(wxID_ANY, wxComboBoxChoice::OnChoice)
END_EVENT_TABLE()
wxComboBox::~wxComboBox()
{
// delete the controls now, don't leave them alive even though they would
// still be eventually deleted by our parent - but it will be too late, the
// user code expects them to be gone now
if (m_text != NULL)
{
delete m_text;
m_text = NULL;
}
if (m_choice != NULL)
{
delete m_choice;
m_choice = NULL;
}
}
// ----------------------------------------------------------------------------
// geometry
// ----------------------------------------------------------------------------
wxSize wxComboBox::DoGetBestSize() const
{
if (!m_choice && !m_text)
return GetSize();
wxSize size = m_choice->GetBestSize();
if ( m_text != NULL )
{
wxSize sizeText = m_text->GetBestSize();
if (sizeText.y > size.y)
size.y = sizeText.y;
size.x = m_choice->GetPopupWidth() + sizeText.x + MARGIN;
size.x += TEXTFOCUSBORDER ;
size.y += 2 * TEXTFOCUSBORDER ;
}
else
{
// clipping is too tight
size.y += 1 ;
}
return size;
}
void wxComboBox::DoMoveWindow(int x, int y, int width, int height)
{
wxControl::DoMoveWindow( x, y, width , height );
if ( m_text == NULL )
{
// we might not be fully constructed yet, therefore watch out...
if ( m_choice )
m_choice->SetSize(0, 0 , width, -1);
}
else
{
wxCoord wText = width - m_choice->GetPopupWidth() - MARGIN;
m_text->SetSize(TEXTFOCUSBORDER, TEXTFOCUSBORDER, wText, -1);
// put it at an inset of 1 to have outer area shadows drawn as well
m_choice->SetSize(TEXTFOCUSBORDER + wText + MARGIN - 1 , TEXTFOCUSBORDER, m_choice->GetPopupWidth() , -1);
}
}
// ----------------------------------------------------------------------------
// operations forwarded to the subcontrols
// ----------------------------------------------------------------------------
bool wxComboBox::Enable(bool enable)
{
if ( !wxControl::Enable(enable) )
return false;
if (m_text)
m_text->Enable(enable);
return true;
}
bool wxComboBox::Show(bool show)
{
if ( !wxControl::Show(show) )
return false;
return true;
}
void wxComboBox::DelegateTextChanged( const wxString& value )
{
SetStringSelection( value );
}
void wxComboBox::DelegateChoice( const wxString& value )
{
SetStringSelection( value );
}
void wxComboBox::Init()
{
WX_INIT_CONTROL_CONTAINER();
}
bool wxComboBox::Create(wxWindow *parent,
wxWindowID id,
const wxString& value,
const wxPoint& pos,
const wxSize& size,
const wxArrayString& choices,
long style,
const wxValidator& validator,
const wxString& name)
{
if ( !Create( parent, id, value, pos, size, 0, NULL,
style, validator, name ) )
return false;
Append(choices);
return true;
}
bool wxComboBox::Create(wxWindow *parent,
wxWindowID id,
const wxString& value,
const wxPoint& pos,
const wxSize& size,
int n,
const wxString choices[],
long style,
const wxValidator& validator,
const wxString& name)
{
if ( !wxControl::Create(parent, id, wxDefaultPosition, wxDefaultSize, style ,
validator, name) )
{
return false;
}
wxSize csize = size;
if ( style & wxCB_READONLY )
{
m_text = NULL;
}
else
{
m_text = new wxComboBoxText(this);
if ( size.y == -1 )
{
csize.y = m_text->GetSize().y ;
csize.y += 2 * TEXTFOCUSBORDER ;
}
}
m_choice = new wxComboBoxChoice(this, style );
DoSetSize(pos.x, pos.y, csize.x, csize.y);
Append( n, choices );
// Needed because it is a wxControlWithItems
SetInitialSize(size);
SetStringSelection(value);
return true;
}
wxString wxComboBox::GetValue() const
{
wxString result;
if ( m_text == NULL )
result = m_choice->GetString( m_choice->GetSelection() );
else
result = m_text->GetValue();
return result;
}
unsigned int wxComboBox::GetCount() const
{
return m_choice->GetCount() ;
}
void wxComboBox::SetValue(const wxString& value)
{
if ( HasFlag(wxCB_READONLY) )
SetStringSelection( value ) ;
else
m_text->SetValue( value );
}
void wxComboBox::WriteText(const wxString& text)
{
m_text->WriteText(text);
}
void wxComboBox::GetSelection(long *from, long *to) const
{
m_text->GetSelection(from, to);
}
// Clipboard operations
void wxComboBox::Copy()
{
if ( m_text != NULL )
m_text->Copy();
}
void wxComboBox::Cut()
{
if ( m_text != NULL )
m_text->Cut();
}
void wxComboBox::Paste()
{
if ( m_text != NULL )
m_text->Paste();
}
void wxComboBox::SetEditable(bool editable)
{
if ( ( m_text == NULL ) && editable )
{
m_text = new wxComboBoxText( this );
}
else if ( ( m_text != NULL ) && !editable )
{
delete m_text;
m_text = NULL;
}
int currentX, currentY;
GetPosition( &currentX, &currentY );
int currentW, currentH;
GetSize( &currentW, &currentH );
DoMoveWindow( currentX, currentY, currentW, currentH );
}
void wxComboBox::SetInsertionPoint(long pos)
{
if ( m_text )
m_text->SetInsertionPoint(pos);
}
void wxComboBox::SetInsertionPointEnd()
{
if ( m_text )
m_text->SetInsertionPointEnd();
}
long wxComboBox::GetInsertionPoint() const
{
if ( m_text )
return m_text->GetInsertionPoint();
return 0;
}
wxTextPos wxComboBox::GetLastPosition() const
{
if ( m_text )
return m_text->GetLastPosition();
return 0;
}
void wxComboBox::Replace(long from, long to, const wxString& value)
{
if ( m_text )
m_text->Replace(from,to,value);
}
void wxComboBox::Remove(long from, long to)
{
if ( m_text )
m_text->Remove(from,to);
}
void wxComboBox::SetSelection(long from, long to)
{
if ( m_text )
m_text->SetSelection(from,to);
}
int wxComboBox::DoInsertItems(const wxArrayStringsAdapter& items,
unsigned int pos,
void **clientData,
wxClientDataType type)
{
return m_choice->DoInsertItems(items, pos, clientData, type);
}
void wxComboBox::DoSetItemClientData(unsigned int n, void* clientData)
{
return m_choice->DoSetItemClientData( n , clientData ) ;
}
void* wxComboBox::DoGetItemClientData(unsigned int n) const
{
return m_choice->DoGetItemClientData( n ) ;
}
wxClientDataType wxComboBox::GetClientDataType() const
{
return m_choice->GetClientDataType();
}
void wxComboBox::SetClientDataType(wxClientDataType clientDataItemsType)
{
m_choice->SetClientDataType(clientDataItemsType);
}
void wxComboBox::DoDeleteOneItem(unsigned int n)
{
m_choice->DoDeleteOneItem( n );
}
void wxComboBox::DoClear()
{
m_choice->DoClear();
}
int wxComboBox::GetSelection() const
{
return m_choice->GetSelection();
}
void wxComboBox::SetSelection(int n)
{
m_choice->SetSelection( n );
if ( m_text != NULL )
m_text->SetValue(n != wxNOT_FOUND ? GetString(n) : wxString(wxEmptyString));
}
int wxComboBox::FindString(const wxString& s, bool bCase) const
{
return m_choice->FindString( s, bCase );
}
wxString wxComboBox::GetString(unsigned int n) const
{
return m_choice->GetString( n );
}
wxString wxComboBox::GetStringSelection() const
{
int sel = GetSelection();
if (sel != wxNOT_FOUND)
return wxString(this->GetString((unsigned int)sel));
else
return wxEmptyString;
}
void wxComboBox::SetString(unsigned int n, const wxString& s)
{
m_choice->SetString( n , s );
}
bool wxComboBox::IsEditable() const
{
return m_text != NULL && !HasFlag(wxCB_READONLY);
}
void wxComboBox::Undo()
{
if (m_text != NULL)
m_text->Undo();
}
void wxComboBox::Redo()
{
if (m_text != NULL)
m_text->Redo();
}
void wxComboBox::SelectAll()
{
if (m_text != NULL)
m_text->SelectAll();
}
bool wxComboBox::CanCopy() const
{
if (m_text != NULL)
return m_text->CanCopy();
else
return false;
}
bool wxComboBox::CanCut() const
{
if (m_text != NULL)
return m_text->CanCut();
else
return false;
}
bool wxComboBox::CanPaste() const
{
if (m_text != NULL)
return m_text->CanPaste();
else
return false;
}
bool wxComboBox::CanUndo() const
{
if (m_text != NULL)
return m_text->CanUndo();
else
return false;
}
bool wxComboBox::CanRedo() const
{
if (m_text != NULL)
return m_text->CanRedo();
else
return false;
}
wxInt32 wxComboBox::MacControlHit( WXEVENTHANDLERREF WXUNUSED(handler) , WXEVENTREF WXUNUSED(event) )
{
/*
For consistency with other platforms, clicking in the text area does not constitute a selection
wxCommandEvent event(wxEVT_COMMAND_COMBOBOX_SELECTED, m_windowId );
event.SetInt(GetSelection());
event.SetEventObject(this);
event.SetString(GetStringSelection());
ProcessCommand(event);
*/
return noErr ;
}
#endif // wxUSE_COMBOBOX

793
src/osx/carbon/combobxc.cpp Normal file
View File

@@ -0,0 +1,793 @@
/////////////////////////////////////////////////////////////////////////////
// Name: src/mac/carbon/combobxc.cpp
// Purpose: wxComboBox class using HIView ComboBox
// Author: Stefan Csomor
// Modified by:
// Created: 1998-01-01
// RCS-ID: $Id$
// Copyright: (c) Stefan Csomor
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
#include "wx/wxprec.h"
#include "wx/combobox.h"
#ifndef WX_PRECOMP
#include "wx/button.h"
#include "wx/menu.h"
#endif
#include "wx/mac/uma.h"
#if TARGET_API_MAC_OSX
#ifndef __HIVIEW__
#include <HIToolbox/HIView.h>
#endif
#endif
IMPLEMENT_DYNAMIC_CLASS(wxComboBox, wxControl)
#if TARGET_API_MAC_OSX
#define USE_HICOMBOBOX 1 //use hi combobox define
#else
#define USE_HICOMBOBOX 0
#endif
static int nextPopUpMenuId = 1000;
MenuHandle NewUniqueMenu()
{
MenuHandle handle = NewMenu( nextPopUpMenuId , "\pMenu" );
nextPopUpMenuId++;
return handle;
}
#if USE_HICOMBOBOX
static const EventTypeSpec eventList[] =
{
{ kEventClassTextField , kEventTextAccepted } ,
};
static pascal OSStatus wxMacComboBoxEventHandler( EventHandlerCallRef handler , EventRef event , void *data )
{
OSStatus result = eventNotHandledErr;
wxComboBox* cb = (wxComboBox*) data;
wxMacCarbonEvent cEvent( event );
switch( cEvent.GetClass() )
{
case kEventClassTextField :
switch( cEvent.GetKind() )
{
case kEventTextAccepted :
{
wxCommandEvent event( wxEVT_COMMAND_COMBOBOX_SELECTED, cb->GetId() );
event.SetInt( cb->GetSelection() );
event.SetString( cb->GetStringSelection() );
event.SetEventObject( cb );
cb->HandleWindowEvent( event );
}
break;
default :
break;
}
break;
default :
break;
}
return result;
}
DEFINE_ONE_SHOT_HANDLER_GETTER( wxMacComboBoxEventHandler )
#endif
// ----------------------------------------------------------------------------
// constants
// ----------------------------------------------------------------------------
// the margin between the text control and the choice
static const wxCoord MARGIN = 2;
#if TARGET_API_MAC_OSX
static const int POPUPWIDTH = 24;
#else
static const int POPUPWIDTH = 18;
#endif
static const int POPUPHEIGHT = 23;
// ----------------------------------------------------------------------------
// wxComboBoxText: text control forwards events to combobox
// ----------------------------------------------------------------------------
class wxComboBoxText : public wxTextCtrl
{
public:
wxComboBoxText( wxComboBox * cb )
: wxTextCtrl( cb , 1 )
{
m_cb = cb;
}
protected:
void OnChar( wxKeyEvent& event )
{
if ( event.GetKeyCode() == WXK_RETURN )
{
wxString value = GetValue();
if ( m_cb->GetCount() == 0 )
{
// make Enter generate "selected" event if there is only one item
// in the combobox - without it, it's impossible to select it at
// all!
wxCommandEvent event( wxEVT_COMMAND_COMBOBOX_SELECTED, m_cb->GetId() );
event.SetInt( 0 );
event.SetString( value );
event.SetEventObject( m_cb );
m_cb->HandleWindowEvent( event );
}
else
{
// add the item to the list if it's not there yet
if ( m_cb->FindString(value) == wxNOT_FOUND )
{
m_cb->Append(value);
m_cb->SetStringSelection(value);
// and generate the selected event for it
wxCommandEvent event( wxEVT_COMMAND_COMBOBOX_SELECTED, m_cb->GetId() );
event.SetInt( m_cb->GetCount() - 1 );
event.SetString( value );
event.SetEventObject( m_cb );
m_cb->HandleWindowEvent( event );
}
// This will invoke the dialog default action, such
// as the clicking the default button.
wxTopLevelWindow *tlw = wxDynamicCast(wxGetTopLevelParent(this), wxTopLevelWindow);
if ( tlw && tlw->GetDefaultItem() )
{
wxButton *def = wxDynamicCast(tlw->GetDefaultItem(), wxButton);
if ( def && def->IsEnabled() )
{
wxCommandEvent event(wxEVT_COMMAND_BUTTON_CLICKED, def->GetId() );
event.SetEventObject(def);
def->Command(event);
return;
}
}
return;
}
}
event.Skip();
}
private:
wxComboBox *m_cb;
DECLARE_EVENT_TABLE()
};
BEGIN_EVENT_TABLE(wxComboBoxText, wxTextCtrl)
EVT_CHAR( wxComboBoxText::OnChar)
END_EVENT_TABLE()
class wxComboBoxChoice : public wxChoice
{
public:
wxComboBoxChoice(wxComboBox *cb, int style)
: wxChoice( cb , 1 )
{
m_cb = cb;
}
protected:
void OnChoice( wxCommandEvent& e )
{
wxString s = e.GetString();
m_cb->DelegateChoice( s );
wxCommandEvent event2(wxEVT_COMMAND_COMBOBOX_SELECTED, m_cb->GetId() );
event2.SetInt(m_cb->GetSelection());
event2.SetEventObject(m_cb);
event2.SetString(m_cb->GetStringSelection());
m_cb->ProcessCommand(event2);
}
virtual wxSize DoGetBestSize() const
{
wxSize sz = wxChoice::DoGetBestSize();
sz.x = POPUPWIDTH;
return sz;
}
private:
wxComboBox *m_cb;
DECLARE_EVENT_TABLE()
};
BEGIN_EVENT_TABLE(wxComboBoxChoice, wxChoice)
EVT_CHOICE(wxID_ANY, wxComboBoxChoice::OnChoice)
END_EVENT_TABLE()
wxComboBox::~wxComboBox()
{
// delete the controls now, don't leave them alive even though they would
// still be eventually deleted by our parent - but it will be too late, the
// user code expects them to be gone now
if (m_text != NULL) {
delete m_text;
m_text = NULL;
}
if (m_choice != NULL) {
delete m_choice;
m_choice = NULL;
}
}
// ----------------------------------------------------------------------------
// geometry
// ----------------------------------------------------------------------------
wxSize wxComboBox::DoGetBestSize() const
{
#if USE_HICOMBOBOX
return wxControl::DoGetBestSize();
#else
wxSize size = m_choice->GetBestSize();
if ( m_text != NULL )
{
wxSize sizeText = m_text->GetBestSize();
size.x = POPUPWIDTH + sizeText.x + MARGIN;
}
return size;
#endif
}
void wxComboBox::DoMoveWindow(int x, int y, int width, int height) {
#if USE_HICOMBOBOX
wxControl::DoMoveWindow(x, y, width, height);
#else
height = POPUPHEIGHT;
wxControl::DoMoveWindow(x, y, width, height);
if ( m_text == NULL )
{
// we might not be fully constructed yet, therefore watch out...
if ( m_choice )
m_choice->SetSize(0, 0 , width, wxDefaultCoord);
}
else
{
wxCoord wText = width - POPUPWIDTH - MARGIN;
m_text->SetSize(0, 0, wText, height);
m_choice->SetSize(0 + wText + MARGIN, 0, POPUPWIDTH, wxDefaultCoord);
}
#endif
}
// ----------------------------------------------------------------------------
// operations forwarded to the subcontrols
// ----------------------------------------------------------------------------
bool wxComboBox::Enable(bool enable)
{
if ( !wxControl::Enable(enable) )
return false;
return true;
}
bool wxComboBox::Show(bool show)
{
if ( !wxControl::Show(show) )
return false;
return true;
}
void wxComboBox::SetFocus()
{
#if USE_HICOMBOBOX
wxControl::SetFocus();
#else
if ( m_text != NULL) {
m_text->SetFocus();
}
#endif
}
void wxComboBox::DelegateTextChanged( const wxString& value )
{
SetStringSelection( value );
}
void wxComboBox::DelegateChoice( const wxString& value )
{
SetStringSelection( value );
}
bool wxComboBox::Create(wxWindow *parent, wxWindowID id,
const wxString& value,
const wxPoint& pos,
const wxSize& size,
const wxArrayString& choices,
long style,
const wxValidator& validator,
const wxString& name)
{
wxCArrayString chs( choices );
return Create( parent, id, value, pos, size, chs.GetCount(),
chs.GetStrings(), style, validator, name );
}
bool wxComboBox::Create(wxWindow *parent, wxWindowID id,
const wxString& value,
const wxPoint& pos,
const wxSize& size,
int n, const wxString choices[],
long style,
const wxValidator& validator,
const wxString& name)
{
m_text = NULL;
m_choice = NULL;
#if USE_HICOMBOBOX
m_macIsUserPane = false;
#endif
if ( !wxControl::Create(parent, id, wxDefaultPosition, wxDefaultSize, style ,
wxDefaultValidator, name) )
{
return false;
}
#if USE_HICOMBOBOX
Rect bounds = wxMacGetBoundsForControl( this , pos , size );
HIRect hiRect;
hiRect.origin.x = 20; //bounds.left;
hiRect.origin.y = 25; //bounds.top;
hiRect.size.width = 120;// bounds.right - bounds.left;
hiRect.size.height = 24;
//For some reason, this code causes the combo box not to be displayed at all.
//hiRect.origin.x = bounds.left;
//hiRect.origin.y = bounds.top;
//hiRect.size.width = bounds.right - bounds.left;
//hiRect.size.height = bounds.bottom - bounds.top;
//printf("left = %d, right = %d, top = %d, bottom = %d\n", bounds.left, bounds.right, bounds.top, bounds.bottom);
//printf("x = %d, y = %d, width = %d, height = %d\n", hibounds.origin.x, hibounds.origin.y, hibounds.size.width, hibounds.size.height);
m_peer = new wxMacControl(this);
verify_noerr( HIComboBoxCreate( &hiRect, CFSTR(""), NULL, NULL, kHIComboBoxStandardAttributes, m_peer->GetControlRefAddr() ) );
m_peer->SetMinimum( 0 );
m_peer->SetMaximum( 100);
if ( n > 0 )
m_peer->SetValue( 1 );
MacPostControlCreate(pos,size);
Append( choices[ i ] );
HIViewSetVisible( m_peer->GetControlRef(), true );
SetSelection(0);
EventHandlerRef comboEventHandler;
InstallControlEventHandler( m_peer->GetControlRef(), GetwxMacComboBoxEventHandlerUPP(),
GetEventTypeCount(eventList), eventList, this,
(EventHandlerRef *)&comboEventHandler);
#else
m_choice = new wxComboBoxChoice(this, style );
m_choice->SetMinSize( wxSize( POPUPWIDTH , POPUPHEIGHT ) );
wxSize csize = size;
if ( style & wxCB_READONLY )
{
m_text = NULL;
}
else
{
m_text = new wxComboBoxText(this);
if ( size.y == wxDefaultCoord ) {
csize.y = m_text->GetSize().y;
}
}
DoSetSize(pos.x, pos.y, csize.x, csize.y);
m_choice->Append( n, choices );
SetInitialSize(csize); // Needed because it is a wxControlWithItems
#endif
return true;
}
wxString wxComboBox::GetValue() const
{
#if USE_HICOMBOBOX
CFStringRef myString;
HIComboBoxCopyTextItemAtIndex( m_peer->GetControlRef(), (CFIndex)GetSelection(), &myString );
return wxMacCFStringHolder( myString, GetFont().GetEncoding() ).AsString();
#else
wxString result;
if ( m_text == NULL )
{
result = m_choice->GetString( m_choice->GetSelection() );
}
else
{
result = m_text->GetValue();
}
return result;
#endif
}
void wxComboBox::SetValue(const wxString& value)
{
#if USE_HICOMBOBOX
#else
int s = FindString (value);
if (s == wxNOT_FOUND && !HasFlag(wxCB_READONLY) )
{
m_choice->Append(value);
}
SetStringSelection( value );
#endif
}
// Clipboard operations
void wxComboBox::Copy()
{
if ( m_text != NULL )
{
m_text->Copy();
}
}
void wxComboBox::Cut()
{
if ( m_text != NULL )
{
m_text->Cut();
}
}
void wxComboBox::Paste()
{
if ( m_text != NULL )
{
m_text->Paste();
}
}
void wxComboBox::SetEditable(bool editable)
{
if ( ( m_text == NULL ) && editable )
{
m_text = new wxComboBoxText( this );
}
else if ( ( m_text != NULL ) && !editable )
{
delete m_text;
m_text = NULL;
}
int currentX, currentY;
GetPosition( &currentX, &currentY );
int currentW, currentH;
GetSize( &currentW, &currentH );
DoMoveWindow( currentX, currentY, currentW, currentH );
}
void wxComboBox::SetInsertionPoint(long pos)
{
// TODO
}
void wxComboBox::SetInsertionPointEnd()
{
// TODO
}
long wxComboBox::GetInsertionPoint() const
{
// TODO
return 0;
}
wxTextPos wxComboBox::GetLastPosition() const
{
// TODO
return 0;
}
void wxComboBox::Replace(long from, long to, const wxString& value)
{
// TODO
}
void wxComboBox::Remove(long from, long to)
{
// TODO
}
void wxComboBox::SetSelection(long from, long to)
{
// TODO
}
int wxComboBox::DoInsertItems(const wxArrayStringsAdapter& items,
unsigned int pos,
void **clientData, wxClientDataType type)
{
#if USE_HICOMBOBOX
const unsigned int count = items.GetCount();
for ( unsigned int i = 0; i < count; ++i, ++pos )
{
HIComboBoxInsertTextItemAtIndex(m_peer->GetControlRef(),
(CFIndex)pos,
wxMacCFStringHolder(items[i],
GetFont().GetEncoding()));
AssignNewItemClientData(pos, clientData, i, type);
}
//SetControl32BitMaximum( m_peer->GetControlRef(), GetCount() );
return pos - 1;
#else
return m_choice->DoInsertItems( items, pos, clientData, type );
#endif
}
void wxComboBox::DoSetItemClientData(unsigned int n, void* clientData)
{
#if USE_HICOMBOBOX
return; //TODO
#else
return m_choice->DoSetItemClientData( n , clientData );
#endif
}
void* wxComboBox::DoGetItemClientData(unsigned int n) const
{
#if USE_HICOMBOBOX
return NULL; //TODO
#else
return m_choice->DoGetItemClientData( n );
#endif
}
unsigned int wxComboBox::GetCount() const {
#if USE_HICOMBOBOX
return (unsigned int) HIComboBoxGetItemCount( m_peer->GetControlRef() );
#else
return m_choice->GetCount();
#endif
}
void wxComboBox::DoDeleteOneItem(unsigned int n)
{
#if USE_HICOMBOBOX
HIComboBoxRemoveItemAtIndex( m_peer->GetControlRef(), (CFIndex)n );
#else
m_choice->Delete( n );
#endif
}
void wxComboBox::DoClear()
{
#if USE_HICOMBOBOX
for ( CFIndex i = GetCount() - 1; i >= 0; ++ i )
verify_noerr( HIComboBoxRemoveItemAtIndex( m_peer->GetControlRef(), i ) );
m_peer->SetData<CFStringRef>(kHIComboBoxEditTextPart,kControlEditTextCFStringTag,CFSTR(""));
#else
m_choice->Clear();
#endif
}
int wxComboBox::GetSelection() const
{
#if USE_HICOMBOBOX
return FindString( GetStringSelection() );
#else
return m_choice->GetSelection();
#endif
}
void wxComboBox::SetSelection(int n)
{
#if USE_HICOMBOBOX
SetControl32BitValue( m_peer->GetControlRef() , n + 1 );
#else
m_choice->SetSelection( n );
if ( m_text != NULL )
{
m_text->SetValue(GetString(n));
}
#endif
}
int wxComboBox::FindString(const wxString& s, bool bCase) const
{
#if USE_HICOMBOBOX
for( unsigned int i = 0 ; i < GetCount() ; i++ )
{
if (GetString(i).IsSameAs(s, bCase) )
return i ;
}
return wxNOT_FOUND;
#else
return m_choice->FindString( s, bCase );
#endif
}
wxString wxComboBox::GetString(unsigned int n) const
{
#if USE_HICOMBOBOX
CFStringRef itemText;
HIComboBoxCopyTextItemAtIndex( m_peer->GetControlRef(), (CFIndex)n, &itemText );
return wxMacCFStringHolder(itemText).AsString();
#else
return m_choice->GetString( n );
#endif
}
wxString wxComboBox::GetStringSelection() const
{
#if USE_HICOMBOBOX
return wxMacCFStringHolder(m_peer->GetData<CFStringRef>(kHIComboBoxEditTextPart,kControlEditTextCFStringTag)).AsString();
#else
int sel = GetSelection ();
if (sel != wxNOT_FOUND)
return wxString(this->GetString((unsigned int)sel));
else
return wxEmptyString;
#endif
}
void wxComboBox::SetString(unsigned int n, const wxString& s)
{
#if USE_HICOMBOBOX
verify_noerr ( HIComboBoxInsertTextItemAtIndex( m_peer->GetControlRef(), (CFIndex) n,
wxMacCFStringHolder(s, GetFont().GetEncoding()) ) );
verify_noerr ( HIComboBoxRemoveItemAtIndex( m_peer->GetControlRef(), (CFIndex) n + 1 ) );
#else
m_choice->SetString( n , s );
#endif
}
bool wxComboBox::IsEditable() const
{
#if USE_HICOMBOBOX
// TODO
return !HasFlag(wxCB_READONLY);
#else
return m_text != NULL && !HasFlag(wxCB_READONLY);
#endif
}
void wxComboBox::Undo()
{
#if USE_HICOMBOBOX
// TODO
#else
if (m_text != NULL)
m_text->Undo();
#endif
}
void wxComboBox::Redo()
{
#if USE_HICOMBOBOX
// TODO
#else
if (m_text != NULL)
m_text->Redo();
#endif
}
void wxComboBox::SelectAll()
{
#if USE_HICOMBOBOX
// TODO
#else
if (m_text != NULL)
m_text->SelectAll();
#endif
}
bool wxComboBox::CanCopy() const
{
#if USE_HICOMBOBOX
// TODO
return false;
#else
if (m_text != NULL)
return m_text->CanCopy();
else
return false;
#endif
}
bool wxComboBox::CanCut() const
{
#if USE_HICOMBOBOX
// TODO
return false;
#else
if (m_text != NULL)
return m_text->CanCut();
else
return false;
#endif
}
bool wxComboBox::CanPaste() const
{
#if USE_HICOMBOBOX
// TODO
return false;
#else
if (m_text != NULL)
return m_text->CanPaste();
else
return false;
#endif
}
bool wxComboBox::CanUndo() const
{
#if USE_HICOMBOBOX
// TODO
return false;
#else
if (m_text != NULL)
return m_text->CanUndo();
else
return false;
#endif
}
bool wxComboBox::CanRedo() const
{
#if USE_HICOMBOBOX
// TODO
return false;
#else
if (m_text != NULL)
return m_text->CanRedo();
else
return false;
#endif
}
wxInt32 wxComboBox::MacControlHit(WXEVENTHANDLERREF WXUNUSED(handler) , WXEVENTREF WXUNUSED(event) )
{
wxCommandEvent event(wxEVT_COMMAND_COMBOBOX_SELECTED, m_windowId );
event.SetInt(GetSelection());
event.SetEventObject(this);
event.SetString(GetStringSelection());
ProcessCommand(event);
return noErr;
}

View File

@@ -0,0 +1,97 @@
/////////////////////////////////////////////////////////////////////////////
// Name: src/mac/carbon/control.cpp
// Purpose: wxControl class
// Author: Stefan Csomor
// Modified by:
// Created: 1998-01-01
// RCS-ID: $Id$
// Copyright: (c) Stefan Csomor
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
#include "wx/wxprec.h"
#include "wx/control.h"
#ifndef WX_PRECOMP
#include "wx/app.h"
#include "wx/panel.h"
#include "wx/dc.h"
#include "wx/dcclient.h"
#include "wx/button.h"
#include "wx/dialog.h"
#include "wx/scrolbar.h"
#include "wx/stattext.h"
#include "wx/statbox.h"
#include "wx/radiobox.h"
#include "wx/sizer.h"
#endif // WX_PRECOMP
#include "wx/notebook.h"
#include "wx/tabctrl.h"
#include "wx/spinbutt.h"
#include "wx/mac/uma.h"
#include "wx/mac/private.h"
IMPLEMENT_ABSTRACT_CLASS(wxControl, wxWindow)
wxControl::wxControl()
{
}
bool wxControl::Create( wxWindow *parent,
wxWindowID id,
const wxPoint& pos,
const wxSize& size,
long style,
const wxValidator& validator,
const wxString& name )
{
bool rval = wxWindow::Create( parent, id, pos, size, style, name );
#if 0
// no automatic inheritance as we most often need transparent backgrounds
if ( parent )
{
m_backgroundColour = parent->GetBackgroundColour();
m_foregroundColour = parent->GetForegroundColour();
}
#endif
#if wxUSE_VALIDATORS
if (rval)
SetValidator( validator );
#endif
return rval;
}
wxControl::~wxControl()
{
m_isBeingDeleted = true;
}
bool wxControl::ProcessCommand( wxCommandEvent &event )
{
// Tries:
// 1) OnCommand, starting at this window and working up parent hierarchy
// 2) OnCommand then calls ProcessEvent to search the event tables.
return HandleWindowEvent( event );
}
void wxControl::OnKeyDown( wxKeyEvent &WXUNUSED(event) )
{
if ( m_peer == NULL || !m_peer->Ok() )
return;
UInt32 keyCode, modifiers;
char charCode;
GetEventParameter( (EventRef)wxTheApp->MacGetCurrentEvent(), kEventParamKeyCode, typeUInt32, NULL, sizeof(UInt32), NULL, &keyCode );
GetEventParameter( (EventRef)wxTheApp->MacGetCurrentEvent(), kEventParamKeyMacCharCodes, typeChar, NULL, sizeof(char), NULL, &charCode );
GetEventParameter( (EventRef)wxTheApp->MacGetCurrentEvent(), kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &modifiers );
m_peer->HandleKey( keyCode, charCode, modifiers );
}

159
src/osx/carbon/corersrc.r Normal file
View File

@@ -0,0 +1,159 @@
#ifdef __UNIX__
#include <Carbon.r>
#else
#include <Types.r>
#if UNIVERSAL_INTERFACES_VERSION > 0x320
#include <ControlDefinitions.r>
#endif
#endif
resource 'ldes' ( 128 )
{
versionZero
{
0 ,
0 ,
0 ,
0 ,
hasVertScroll ,
noHorizScroll ,
0 ,
noGrowSpace ,
}
} ;
resource 'ldes' ( 129 )
{
versionZero
{
0 ,
0 ,
0 ,
0 ,
hasVertScroll ,
hasHorizScroll ,
0 ,
noGrowSpace ,
}
} ;
data 'CURS' (10) {
$"0000 03E0 0630 0808 1004 31C6 2362 2222"
$"2362 31C6 1004 0808 0630 03E0 0000 0000"
$"0000 03E0 07F0 0FF8 1FFC 3FFE 3FFE 3FFE"
$"3FFE 3FFE 1FFC 0FF8 07F0 03E0 0000 0000"
$"0007 0008"
};
data 'CURS' (11) {
$"0000 0000 0000 0000 0000 0000 0000 0000"
$"0000 0000 0000 0000 0000 0000 0000 0000"
$"0000 0000 0000 0000 0000 0000 0000 0000"
$"0000 0000 0000 0000 0000 0000 0000 0000"
$"0000 0000"
};
data 'CURS' (12) {
$"00F0 0088 0108 0190 0270 0220 0440 0440"
$"0880 0880 1100 1E00 1C00 1800 1000 0000"
$"00F0 00F8 01F8 01F0 03F0 03E0 07C0 07C0"
$"0F80 0F80 1F00 1E00 1C00 1800 1000 0000"
$"000E 0003"
};
data 'CURS' (13) {
$"0000 1E00 2100 4080 4080 4080 4080 2180"
$"1FC0 00E0 0070 0038 001C 000E 0006 0000"
$"3F00 7F80 FFC0 FFC0 FFC0 FFC0 FFC0 7FC0"
$"3FE0 1FF0 00F8 007C 003E 001F 000F 0007"
$"0004 0004"
};
data 'CURS' (14) {
$"0000 07E0 1FF0 3838 3C0C 6E0E 6706 6386"
$"61C6 60E6 7076 303C 1C1C 0FF8 07E0 0000"
$"0540 0FF0 3FF8 3C3C 7E0E FF0F 6F86 E7C7"
$"63E6 E1F7 70FE 707E 3C3C 1FFC 0FF0 0540"
$"0007 0007"
};
data 'CURS' (15) {
$"0000 0380 0380 0380 0380 0380 0380 0FE0"
$"1FF0 1FF0 0000 1FF0 1FF0 1550 1550 1550"
$"07C0 07C0 07C0 07C0 07C0 07C0 0FE0 1FF0"
$"3FF8 3FF8 3FF8 3FF8 3FF8 3FF8 3FF8 3FF8"
$"000B 0007"
};
data 'CURS' (16) {
$"00C0 0140 0640 08C0 3180 47FE 8001 8001"
$"81FE 8040 01C0 0040 03C0 C080 3F80 0000"
$"00C0 01C0 07C0 0FC0 3F80 7FFE FFFF FFFF"
$"FFFE FFC0 FFC0 FFC0 FFC0 FF80 3F80 0000"
$"0006 000F"
};
data 'CURS' (17) {
$"0100 0280 0260 0310 018C 7FE3 8000 8000"
$"7F80 0200 0380 0200 03C0 0107 01F8 0000"
$"0100 0380 03E0 03F0 01FC 7FFF FFFF FFFF"
$"FFFF 03FF 03FF 03FF 03FF 01FF 01F8 0000"
$"0006 0000"
};
data 'CURS' (18) {
$"0000 4078 60FC 71CE 7986 7C06 7E0E 7F1C"
$"7FB8 7C30 6C30 4600 0630 0330 0300 0000"
$"C078 E0FC F1FE FBFF FFCF FF8F FF1F FFBE"
$"FFFC FE78 FF78 EFF8 CFF8 87F8 07F8 0300"
$"0001 0001"
};
data 'CURS' (19) {
$"0000 0002 0006 000E 001E 003E 007E 00FE"
$"01FE 003E 0036 0062 0060 00C0 00C0 0000"
$"0003 0007 000F 001F 003F 007F 00FF 01FF"
$"03FF 07FF 007F 00F7 00F3 01E1 01E0 01C0"
$"0001 000E"
};
data 'CURS' (20) {
$"0000 0080 01C0 03E0 0080 0080 0080 1FFC"
$"1FFC 0080 0080 0080 03E0 01C0 0080 0000"
$"0080 01C0 03E0 07F0 0FF8 01C0 3FFE 3FFE"
$"3FFE 3FFE 01C0 0FF8 07F0 03E0 01C0 0080"
$"0007 0008"
};
data 'CURS' (21) {
$"0000 0080 01C0 03E0 0080 0888 188C 3FFE"
$"188C 0888 0080 03E0 01C0 0080 0000 0000"
$"0080 01C0 03E0 07F0 0BE8 1DDC 3FFE 7FFF"
$"3FFE 1DDC 0BE8 07F0 03E0 01C0 0080 0000"
$"0007 0008"
};
data 'CURS' (22) {
$"0000 001E 000E 060E 0712 03A0 01C0 00E0"
$"0170 1238 1C18 1C00 1E00 0000 0000 0000"
$"007F 003F 0E1F 0F0F 0F97 07E3 03E1 21F0"
$"31F8 3A7C 3C3C 3E1C 3F00 3F80 0000 0000"
$"0006 0009"
};
data 'CURS' (23) {
$"0000 7800 7000 7060 48E0 05C0 0380 0700"
$"0E80 1C48 1838 0038 0078 0000 0000 0000"
$"FE00 FC00 F870 F0F0 E9F0 C7E0 87C0 0F84"
$"1F8C 3E5C 3C3C 387C 00FC 01FC 0000 0000"
$"0006 0006"
};
data 'CURS' (24) {
$"0006 000E 001C 0018 0020 0040 00F8 0004"
$"1FF4 200C 2AA8 1FF0 1F80 3800 6000 8000"
$"000F 001F 003E 007C 0070 00E0 01FC 3FF6"
$"7FF6 7FFE 7FFC 7FF8 3FF0 7FC0 F800 E000"
$"000A 0006"
};

697
src/osx/carbon/cursor.cpp Normal file
View File

@@ -0,0 +1,697 @@
/////////////////////////////////////////////////////////////////////////////
// Name: src/mac/carbon/cursor.cpp
// Purpose: wxCursor class
// Author: Stefan Csomor
// Modified by:
// Created: 1998-01-01
// RCS-ID: $Id$
// Copyright: (c) Stefan Csomor
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
#include "wx/wxprec.h"
#include "wx/cursor.h"
#ifndef WX_PRECOMP
#include "wx/app.h"
#include "wx/icon.h"
#include "wx/image.h"
#endif // WX_PRECOMP
#include "wx/xpmdecod.h"
#include "wx/mac/private.h"
IMPLEMENT_DYNAMIC_CLASS(wxCursor, wxGDIObject)
class WXDLLEXPORT wxCursorRefData: public wxGDIRefData
{
public:
wxCursorRefData();
wxCursorRefData(const wxCursorRefData& cursor);
virtual ~wxCursorRefData();
virtual bool IsOk() const
{
if ( m_hCursor != NULL )
return true;
#if !wxMAC_USE_COCOA
if ( m_themeCursor != -1 )
return true;
#endif
return false;
}
protected:
#if wxMAC_USE_COCOA
WX_NSCursor m_hCursor;
#else
WXHCURSOR m_hCursor;
bool m_disposeHandle;
bool m_releaseHandle;
bool m_isColorCursor;
long m_themeCursor;
#endif
friend class wxCursor;
DECLARE_NO_ASSIGN_CLASS(wxCursorRefData)
};
#define M_CURSORDATA wx_static_cast(wxCursorRefData*, m_refData)
ClassicCursor gMacCursors[kwxCursorLast+1] =
{
{
{0x0000, 0x03E0, 0x0630, 0x0808, 0x1004, 0x31C6, 0x2362, 0x2222,
0x2362, 0x31C6, 0x1004, 0x0808, 0x0630, 0x03E0, 0x0000, 0x0000},
{0x0000, 0x03E0, 0x07F0, 0x0FF8, 0x1FFC, 0x3FFE, 0x3FFE, 0x3FFE,
0x3FFE, 0x3FFE, 0x1FFC, 0x0FF8, 0x07F0, 0x03E0, 0x0000, 0x0000},
{0x0007, 0x0008}
},
{
{0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000},
{0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000},
{0x0000, 0x0000}
},
{
{0x00F0, 0x0088, 0x0108, 0x0190, 0x0270, 0x0220, 0x0440, 0x0440,
0x0880, 0x0880, 0x1100, 0x1E00, 0x1C00, 0x1800, 0x1000, 0x0000},
{0x00F0, 0x00F8, 0x01F8, 0x01F0, 0x03F0, 0x03E0, 0x07C0, 0x07C0,
0x0F80, 0x0F80, 0x1F00, 0x1E00, 0x1C00, 0x1800, 0x1000, 0x0000},
{0x000E, 0x0003}
},
{
{0x0000, 0x1E00, 0x2100, 0x4080, 0x4080, 0x4080, 0x4080, 0x2180,
0x1FC0, 0x00E0, 0x0070, 0x0038, 0x001C, 0x000E, 0x0006, 0x0000},
{0x3F00, 0x7F80, 0xFFC0, 0xFFC0, 0xFFC0, 0xFFC0, 0xFFC0, 0x7FC0,
0x3FE0, 0x1FF0, 0x00F8, 0x007C, 0x003E, 0x001F, 0x000F, 0x0007},
{0x0004, 0x0004}
},
{
{0x0000, 0x07E0, 0x1FF0, 0x3838, 0x3C0C, 0x6E0E, 0x6706, 0x6386,
0x61C6, 0x60E6, 0x7076, 0x303C, 0x1C1C, 0x0FF8, 0x07E0, 0x0000},
{0x0540, 0x0FF0, 0x3FF8, 0x3C3C, 0x7E0E, 0xFF0F, 0x6F86, 0xE7C7,
0x63E6, 0xE1F7, 0x70FE, 0x707E, 0x3C3C, 0x1FFC, 0x0FF0, 0x0540},
{0x0007, 0x0007}
},
{
{0x0000, 0x0380, 0x0380, 0x0380, 0x0380, 0x0380, 0x0380, 0x0FE0,
0x1FF0, 0x1FF0, 0x0000, 0x1FF0, 0x1FF0, 0x1550, 0x1550, 0x1550},
{0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x0FE0, 0x1FF0,
0x3FF8, 0x3FF8, 0x3FF8, 0x3FF8, 0x3FF8, 0x3FF8, 0x3FF8, 0x3FF8},
{0x000B, 0x0007}
},
{
{0x00C0, 0x0140, 0x0640, 0x08C0, 0x3180, 0x47FE, 0x8001, 0x8001,
0x81FE, 0x8040, 0x01C0, 0x0040, 0x03C0, 0xC080, 0x3F80, 0x0000},
{0x00C0, 0x01C0, 0x07C0, 0x0FC0, 0x3F80, 0x7FFE, 0xFFFF, 0xFFFF,
0xFFFE, 0xFFC0, 0xFFC0, 0xFFC0, 0xFFC0, 0xFF80, 0x3F80, 0x0000},
{0x0006, 0x000F}
},
{
{0x0100, 0x0280, 0x0260, 0x0310, 0x018C, 0x7FE3, 0x8000, 0x8000,
0x7F80, 0x0200, 0x0380, 0x0200, 0x03C0, 0x0107, 0x01F8, 0x0000},
{0x0100, 0x0380, 0x03E0, 0x03F0, 0x01FC, 0x7FFF, 0xFFFF, 0xFFFF,
0xFFFF, 0x03FF, 0x03FF, 0x03FF, 0x03FF, 0x01FF, 0x01F8, 0x0000},
{0x0006, 0x0000}
},
{
{0x0000, 0x4078, 0x60FC, 0x71CE, 0x7986, 0x7C06, 0x7E0E, 0x7F1C,
0x7FB8, 0x7C30, 0x6C30, 0x4600, 0x0630, 0x0330, 0x0300, 0x0000},
{0xC078, 0xE0FC, 0xF1FE, 0xFBFF, 0xFFCF, 0xFF8F, 0xFF1F, 0xFFBE,
0xFFFC, 0xFE78, 0xFF78, 0xEFF8, 0xCFF8, 0x87F8, 0x07F8, 0x0300},
{0x0001, 0x0001}
},
{
{0x0000, 0x0002, 0x0006, 0x000E, 0x001E, 0x003E, 0x007E, 0x00FE,
0x01FE, 0x003E, 0x0036, 0x0062, 0x0060, 0x00C0, 0x00C0, 0x0000},
{0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF, 0x01FF,
0x03FF, 0x07FF, 0x007F, 0x00F7, 0x00F3, 0x01E1, 0x01E0, 0x01C0},
{0x0001, 0x000E}
},
{
{0x0000, 0x0080, 0x01C0, 0x03E0, 0x0080, 0x0080, 0x0080, 0x1FFC,
0x1FFC, 0x0080, 0x0080, 0x0080, 0x03E0, 0x01C0, 0x0080, 0x0000},
{0x0080, 0x01C0, 0x03E0, 0x07F0, 0x0FF8, 0x01C0, 0x3FFE, 0x3FFE,
0x3FFE, 0x3FFE, 0x01C0, 0x0FF8, 0x07F0, 0x03E0, 0x01C0, 0x0080},
{0x0007, 0x0008}
},
{
{0x0000, 0x0080, 0x01C0, 0x03E0, 0x0080, 0x0888, 0x188C, 0x3FFE,
0x188C, 0x0888, 0x0080, 0x03E0, 0x01C0, 0x0080, 0x0000, 0x0000},
{0x0080, 0x01C0, 0x03E0, 0x07F0, 0x0BE8, 0x1DDC, 0x3FFE, 0x7FFF,
0x3FFE, 0x1DDC, 0x0BE8, 0x07F0, 0x03E0, 0x01C0, 0x0080, 0x0000},
{0x0007, 0x0008}
},
{
{0x0000, 0x001E, 0x000E, 0x060E, 0x0712, 0x03A0, 0x01C0, 0x00E0,
0x0170, 0x1238, 0x1C18, 0x1C00, 0x1E00, 0x0000, 0x0000, 0x0000},
{0x007F, 0x003F, 0x0E1F, 0x0F0F, 0x0F97, 0x07E3, 0x03E1, 0x21F0,
0x31F8, 0x3A7C, 0x3C3C, 0x3E1C, 0x3F00, 0x3F80, 0x0000, 0x0000},
{0x0006, 0x0009}
},
{
{0x0000, 0x7800, 0x7000, 0x7060, 0x48E0, 0x05C0, 0x0380, 0x0700,
0x0E80, 0x1C48, 0x1838, 0x0038, 0x0078, 0x0000, 0x0000, 0x0000},
{0xFE00, 0xFC00, 0xF870, 0xF0F0, 0xE9F0, 0xC7E0, 0x87C0, 0x0F84,
0x1F8C, 0x3E5C, 0x3C3C, 0x387C, 0x00FC, 0x01FC, 0x0000, 0x0000},
{0x0006, 0x0006}
},
{
{0x0006, 0x000E, 0x001C, 0x0018, 0x0020, 0x0040, 0x00F8, 0x0004,
0x1FF4, 0x200C, 0x2AA8, 0x1FF0, 0x1F80, 0x3800, 0x6000, 0x8000},
{0x000F, 0x001F, 0x003E, 0x007C, 0x0070, 0x00E0, 0x01FC, 0x3FF6,
0x7FF6, 0x7FFE, 0x7FFC, 0x7FF8, 0x3FF0, 0x7FC0, 0xF800, 0xE000},
{0x000A, 0x0006}
},
};
wxCursor gMacCurrentCursor ;
#if !wxMAC_USE_COCOA
CursHandle wxGetStockCursor( int number )
{
wxASSERT_MSG( number >= 0 && number <=kwxCursorLast , wxT("invalid stock cursor id") ) ;
CursHandle c = (CursHandle) NewHandle( sizeof(Cursor) ) ;
memcpy( *c, &gMacCursors[number], sizeof(Cursor) ) ;
#ifndef WORDS_BIGENDIAN
short *sptr = (short*) *c ;
for ( int i = 0 ; i < 2 * 16 /* image and mask */ ; ++i, ++sptr )
{
*sptr = CFSwapInt16( *sptr ) ;
}
#endif
return c ;
}
#endif
wxCursorRefData::wxCursorRefData()
{
m_hCursor = NULL;
#if wxMAC_USE_COCOA
#else
m_disposeHandle = false;
m_releaseHandle = false;
m_isColorCursor = false;
m_themeCursor = -1;
#endif
}
wxCursorRefData::wxCursorRefData(const wxCursorRefData& cursor)
{
// FIXME: need to copy the cursor
m_hCursor = NULL;
#if wxMAC_USE_COCOA
wxUnusedVar(cursor);
#else
m_disposeHandle = false;
m_releaseHandle = false;
m_isColorCursor = cursor.m_isColorCursor;
m_themeCursor = cursor.m_themeCursor;
#endif
}
wxCursorRefData::~wxCursorRefData()
{
#if wxMAC_USE_COCOA
if ( m_hCursor )
wxMacCocoaRelease(m_hCursor);
#else
if ( m_isColorCursor )
{
#ifndef __LP64__
::DisposeCCursor( (CCrsrHandle) m_hCursor ) ;
#endif
}
else if ( m_disposeHandle )
{
::DisposeHandle( (Handle ) m_hCursor ) ;
}
else if ( m_releaseHandle )
{
// we don't release the resource since it may already
// be in use again
}
#endif
}
wxCursor::wxCursor()
{
}
wxCursor::wxCursor(const char WXUNUSED(bits)[], int WXUNUSED(width), int WXUNUSED(height),
int WXUNUSED(hotSpotX), int WXUNUSED(hotSpotY), const char WXUNUSED(maskBits)[])
{
}
wxCursor::wxCursor( const wxImage &image )
{
#if wxUSE_IMAGE
CreateFromImage( image ) ;
#endif
}
wxCursor::wxCursor(const char* const* bits)
{
(void) CreateFromXpm(bits);
}
wxGDIRefData *wxCursor::CreateGDIRefData() const
{
return new wxCursorRefData;
}
wxGDIRefData *wxCursor::CloneGDIRefData(const wxGDIRefData *data) const
{
return new wxCursorRefData(*wx_static_cast(const wxCursorRefData *, data));
}
bool wxCursor::CreateFromXpm(const char* const* bits)
{
#if wxUSE_IMAGE
wxCHECK_MSG( bits != NULL, false, wxT("invalid cursor data") );
wxXPMDecoder decoder;
wxImage img = decoder.ReadData(bits);
wxCHECK_MSG( img.Ok(), false, wxT("invalid cursor data") );
CreateFromImage( img ) ;
return true;
#else
return false;
#endif
}
WXHCURSOR wxCursor::GetHCURSOR() const
{
return (M_CURSORDATA ? M_CURSORDATA->m_hCursor : 0);
}
#if !wxMAC_USE_COCOA
short GetCTabIndex( CTabHandle colors , RGBColor *col )
{
short retval = 0 ;
unsigned long bestdiff = 0xFFFF ;
for ( int i = 0 ; i < (**colors).ctSize ; ++i )
{
unsigned long diff = abs(col->red - (**colors).ctTable[i].rgb.red ) +
abs(col->green - (**colors).ctTable[i].rgb.green ) +
abs(col->blue - (**colors).ctTable[i].rgb.blue ) ;
if ( diff < bestdiff )
{
bestdiff = diff ;
retval = (**colors).ctTable[i].value ;
}
}
return retval ;
}
#endif
#if wxUSE_IMAGE
void wxCursor::CreateFromImage(const wxImage & image)
{
m_refData = new wxCursorRefData;
int hotSpotX = image.GetOptionInt(wxIMAGE_OPTION_CUR_HOTSPOT_X);
int hotSpotY = image.GetOptionInt(wxIMAGE_OPTION_CUR_HOTSPOT_Y);
#if wxMAC_USE_COCOA
wxBitmap bmp( image );
CGImageRef cgimage = wxMacCreateCGImageFromBitmap(bmp);
if ( cgimage )
{
M_CURSORDATA->m_hCursor = wxMacCocoaCreateCursorFromCGImage( cgimage, hotSpotX, hotSpotY );
CFRelease( cgimage );
}
#else
#ifndef __LP64__
int w = 16;
int h = 16;
int image_w = image.GetWidth();
int image_h = image.GetHeight();
wxASSERT_MSG( hotSpotX >= 0 && hotSpotX < image_w &&
hotSpotY >= 0 && hotSpotY < image_h,
wxT("invalid cursor hot spot coordinates") );
wxImage image16(image); // final image of correct size
// if image is too small then place it in the center, resize it if too big
if ((w > image_w) && (h > image_h))
{
wxPoint offset((w - image_w) / 2, (h - image_h) / 2);
hotSpotX = hotSpotX + offset.x;
hotSpotY = hotSpotY + offset.y;
image16 = image.Size(wxSize(w, h), offset);
}
else if ((w != image_w) || (h != image_h))
{
hotSpotX = int(hotSpotX * double(w) / double(image_w));
hotSpotY = int(hotSpotY * double(h) / double(image_h));
image16 = image.Scale(w, h);
}
unsigned char * rgbBits = image16.GetData();
bool bHasMask = image16.HasMask() ;
PixMapHandle pm = (PixMapHandle) NewHandleClear( sizeof(PixMap) ) ;
short extent = 16 ;
short bytesPerPixel = 1 ;
short depth = 8 ;
Rect bounds = { 0 , 0 , extent , extent } ;
CCrsrHandle ch = (CCrsrHandle) NewHandleClear( sizeof(CCrsr) ) ;
CTabHandle newColors = GetCTable( 8 ) ;
HandToHand( (Handle *) &newColors );
// set the values to the indices
for ( int i = 0 ; i < (**newColors).ctSize ; ++i )
{
(**newColors).ctTable[i].value = i ;
}
HLock( (Handle)ch );
(**ch).crsrType = 0x8001; // color cursors
(**ch).crsrMap = pm;
short bytesPerRow = bytesPerPixel * extent;
(**pm).baseAddr = 0;
(**pm).rowBytes = bytesPerRow | 0x8000;
(**pm).bounds = bounds;
(**pm).pmVersion = 0;
(**pm).packType = 0;
(**pm).packSize = 0;
(**pm).hRes = 0x00480000; // 72 DPI default res
(**pm).vRes = 0x00480000; // 72 DPI default res
(**pm).pixelSize = depth;
(**pm).pixelType = 0;
(**pm).cmpCount = 1;
(**pm).cmpSize = depth;
(**pm).pmTable = newColors;
(**ch).crsrData = NewHandleClear( extent * bytesPerRow ) ;
(**ch).crsrXData = NULL ;
(**ch).crsrXValid = 0;
(**ch).crsrXHandle = NULL;
(**ch).crsrHotSpot.h = hotSpotX ;
(**ch).crsrHotSpot.v = hotSpotY ;
(**ch).crsrXTable = 0 ;
(**ch).crsrID = GetCTSeed() ;
memset( (**ch).crsr1Data , 0 , sizeof( Bits16 ) ) ;
memset( (**ch).crsrMask , 0 , sizeof( Bits16 ) ) ;
unsigned char mr = image16.GetMaskRed() ;
unsigned char mg = image16.GetMaskGreen() ;
unsigned char mb = image16.GetMaskBlue() ;
for ( int y = 0 ; y < h ; ++y )
{
short rowbits = 0, maskbits = 0 ;
for ( int x = 0 ; x < w ; ++x )
{
long pos = (y * w + x) * 3;
unsigned char r = rgbBits[pos] ;
unsigned char g = rgbBits[pos + 1] ;
unsigned char b = rgbBits[pos + 2] ;
RGBColor col = { 0xFFFF, 0xFFFF, 0xFFFF } ;
if ( bHasMask && r == mr && g == mg && b == mb )
{
// masked area, does not appear anywhere
}
else
{
if ( (int)r + (int)g + (int)b < 0x0200 )
rowbits |= ( 1 << (15 - x) ) ;
maskbits |= ( 1 << (15 - x) ) ;
wxColor( r , g , b ).GetRGBColor( &col );
}
*((*(**ch).crsrData) + y * bytesPerRow + x) =
GetCTabIndex( newColors , &col) ;
}
#ifdef WORDS_BIGENDIAN
(**ch).crsr1Data[y] = rowbits ;
(**ch).crsrMask[y] = maskbits ;
#else
(**ch).crsr1Data[y] = CFSwapInt16(rowbits) ;
(**ch).crsrMask[y] = CFSwapInt16(maskbits) ;
#endif
}
if ( !bHasMask )
memcpy( (**ch).crsrMask , (**ch).crsr1Data , sizeof( Bits16) ) ;
HUnlock( (Handle)ch ) ;
M_CURSORDATA->m_hCursor = ch ;
M_CURSORDATA->m_isColorCursor = true ;
#endif
#endif
}
#endif //wxUSE_IMAGE
wxCursor::wxCursor(const wxString& cursor_file, wxBitmapType flags, int hotSpotX, int hotSpotY)
{
m_refData = new wxCursorRefData;
if ( flags == wxBITMAP_TYPE_MACCURSOR_RESOURCE )
{
#if wxMAC_USE_COCOA
wxFAIL_MSG( wxT("Not implemented") );
#else
#ifndef __LP64__
Str255 theName ;
wxMacStringToPascal( cursor_file , theName ) ;
Handle resHandle = ::GetNamedResource( 'crsr' , theName ) ;
if ( resHandle )
{
short theId = -1 ;
OSType theType ;
GetResInfo( resHandle , &theId , &theType , theName ) ;
ReleaseResource( resHandle ) ;
M_CURSORDATA->m_hCursor = GetCCursor( theId ) ;
if ( M_CURSORDATA->m_hCursor )
M_CURSORDATA->m_isColorCursor = true ;
}
else
{
Handle resHandle = ::GetNamedResource( 'CURS' , theName ) ;
if ( resHandle )
{
short theId = -1 ;
OSType theType ;
GetResInfo( resHandle , &theId , &theType , theName ) ;
ReleaseResource( resHandle ) ;
M_CURSORDATA->m_hCursor = GetCursor( theId ) ;
if ( M_CURSORDATA->m_hCursor )
M_CURSORDATA->m_releaseHandle = true ;
}
}
#endif
#endif
}
else
{
#if wxUSE_IMAGE
wxImage image ;
image.LoadFile( cursor_file, flags ) ;
if ( image.Ok() )
{
image.SetOption( wxIMAGE_OPTION_CUR_HOTSPOT_X, hotSpotX ) ;
image.SetOption( wxIMAGE_OPTION_CUR_HOTSPOT_Y, hotSpotY ) ;
m_refData->DecRef() ;
m_refData = NULL ;
CreateFromImage( image ) ;
}
#endif
}
}
// Cursors by stock number
wxCursor::wxCursor(int cursor_type)
{
m_refData = new wxCursorRefData;
#if wxMAC_USE_COCOA
M_CURSORDATA->m_hCursor = wxMacCocoaCreateStockCursor( cursor_type );
#else
switch (cursor_type)
{
case wxCURSOR_COPY_ARROW:
M_CURSORDATA->m_themeCursor = kThemeCopyArrowCursor;
break;
case wxCURSOR_WAIT:
M_CURSORDATA->m_themeCursor = kThemeWatchCursor;
break;
case wxCURSOR_IBEAM:
M_CURSORDATA->m_themeCursor = kThemeIBeamCursor;
break;
case wxCURSOR_CROSS:
M_CURSORDATA->m_themeCursor = kThemeCrossCursor;
break;
case wxCURSOR_SIZENWSE:
M_CURSORDATA->m_hCursor = wxGetStockCursor(kwxCursorSizeNWSE);
break;
case wxCURSOR_SIZENESW:
M_CURSORDATA->m_hCursor = wxGetStockCursor(kwxCursorSizeNESW);
break;
case wxCURSOR_SIZEWE:
M_CURSORDATA->m_themeCursor = kThemeResizeLeftRightCursor;
break;
case wxCURSOR_SIZENS:
M_CURSORDATA->m_hCursor = wxGetStockCursor(kwxCursorSizeNS);
break;
case wxCURSOR_SIZING:
M_CURSORDATA->m_hCursor = wxGetStockCursor(kwxCursorSize);
break;
case wxCURSOR_HAND:
M_CURSORDATA->m_themeCursor = kThemePointingHandCursor;
break;
case wxCURSOR_BULLSEYE:
M_CURSORDATA->m_hCursor = wxGetStockCursor(kwxCursorBullseye);
break;
case wxCURSOR_PENCIL:
M_CURSORDATA->m_hCursor = wxGetStockCursor(kwxCursorPencil);
break;
case wxCURSOR_MAGNIFIER:
M_CURSORDATA->m_hCursor = wxGetStockCursor(kwxCursorMagnifier);
break;
case wxCURSOR_NO_ENTRY:
M_CURSORDATA->m_hCursor = wxGetStockCursor(kwxCursorNoEntry);
break;
case wxCURSOR_WATCH:
M_CURSORDATA->m_themeCursor = kThemeWatchCursor;
break;
case wxCURSOR_PAINT_BRUSH:
M_CURSORDATA->m_hCursor = wxGetStockCursor(kwxCursorPaintBrush);
break;
case wxCURSOR_POINT_LEFT:
M_CURSORDATA->m_hCursor = wxGetStockCursor(kwxCursorPointLeft);
break;
case wxCURSOR_POINT_RIGHT:
M_CURSORDATA->m_hCursor = wxGetStockCursor(kwxCursorPointRight);
break;
case wxCURSOR_QUESTION_ARROW:
M_CURSORDATA->m_hCursor = wxGetStockCursor(kwxCursorQuestionArrow);
break;
case wxCURSOR_BLANK:
M_CURSORDATA->m_hCursor = wxGetStockCursor(kwxCursorBlank);
break;
case wxCURSOR_RIGHT_ARROW:
M_CURSORDATA->m_hCursor = wxGetStockCursor(kwxCursorRightArrow);
break;
case wxCURSOR_SPRAYCAN:
M_CURSORDATA->m_hCursor = wxGetStockCursor(kwxCursorRoller);
break;
case wxCURSOR_CHAR:
case wxCURSOR_ARROW:
case wxCURSOR_LEFT_BUTTON:
case wxCURSOR_RIGHT_BUTTON:
case wxCURSOR_MIDDLE_BUTTON:
default:
M_CURSORDATA->m_themeCursor = kThemeArrowCursor;
break;
}
if ( M_CURSORDATA->m_themeCursor == -1 )
M_CURSORDATA->m_releaseHandle = true;
#endif
}
void wxCursor::MacInstall() const
{
gMacCurrentCursor = *this ;
#if wxMAC_USE_COCOA
if ( IsOk() )
wxMacCocoaSetCursor( M_CURSORDATA->m_hCursor );
#else
if ( m_refData && M_CURSORDATA->m_themeCursor != -1 )
{
SetThemeCursor( M_CURSORDATA->m_themeCursor ) ;
}
else if ( m_refData && M_CURSORDATA->m_hCursor )
{
#ifndef __LP64__
if ( M_CURSORDATA->m_isColorCursor )
::SetCCursor( (CCrsrHandle) M_CURSORDATA->m_hCursor ) ;
else
::SetCursor( * (CursHandle) M_CURSORDATA->m_hCursor ) ;
#endif
}
else
{
SetThemeCursor( kThemeArrowCursor ) ;
}
#endif
}
wxCursor::~wxCursor()
{
}
// Global cursor setting
wxCursor gGlobalCursor;
void wxSetCursor(const wxCursor& cursor)
{
cursor.MacInstall() ;
gGlobalCursor = cursor;
}

1145
src/osx/carbon/databrow.cpp Normal file

File diff suppressed because it is too large Load Diff

753
src/osx/carbon/dataobj.cpp Normal file
View File

@@ -0,0 +1,753 @@
///////////////////////////////////////////////////////////////////////////////
// Name: src/mac/carbon/dataobj.cpp
// Purpose: implementation of wxDataObject class
// Author: Stefan Csomor
// Modified by:
// Created: 10/21/99
// RCS-ID: $Id$
// Copyright: (c) 1999 Stefan Csomor
// Licence: wxWindows licence
///////////////////////////////////////////////////////////////////////////////
// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"
#if wxUSE_DATAOBJ
#include "wx/dataobj.h"
#ifndef WX_PRECOMP
#include "wx/intl.h"
#include "wx/log.h"
#include "wx/dcmemory.h"
#include "wx/image.h"
#endif
#include "wx/mstream.h"
#include "wx/metafile.h"
#include "wx/tokenzr.h"
#include "wx/mac/uma.h"
#ifdef __DARWIN__
#include <QuickTime/QuickTime.h>
#endif
// ----------------------------------------------------------------------------
// wxDataFormat
// ----------------------------------------------------------------------------
wxDataFormat::wxDataFormat()
{
m_type = wxDF_INVALID;
m_format = 0;
}
wxDataFormat::wxDataFormat( wxDataFormatId vType )
{
m_format = 0;
m_type = wxDF_INVALID;
SetType( vType );
}
wxDataFormat::wxDataFormat( const wxChar *zId )
{
m_format = 0;
m_type = wxDF_INVALID;
SetId( zId );
}
wxDataFormat::wxDataFormat( const wxString& rId )
{
m_format = 0;
m_type = wxDF_INVALID;
SetId( rId );
}
wxDataFormat::wxDataFormat(const wxDataFormat& rFormat)
{
if ( rFormat.m_format )
m_format = (NativeFormat) CFStringCreateCopy(NULL, (CFStringRef)rFormat.m_format);
else
m_format = 0;
m_type = rFormat.m_type;
m_id = rFormat.m_id;
}
wxDataFormat::wxDataFormat( NativeFormat vFormat )
{
m_format = 0;
m_type = wxDF_INVALID;
SetId( vFormat );
}
wxDataFormat::~wxDataFormat()
{
if ( m_format != 0 )
{
CFRelease( (CFStringRef) m_format );
m_format = 0;
}
}
// in order to be correct for 10.3 we restrict to the available types there
// http://developer.apple.com/qa/qa2005/qa1406.html
// TODO : Use UTCoreTypes.h constants once we support 10.4+ only
wxDataFormat& wxDataFormat::operator=(const wxDataFormat& rFormat)
{
if ( m_format != 0 )
{
CFRelease( (CFStringRef) m_format );
m_format = 0;
}
if ( rFormat.m_format )
m_format = (NativeFormat) CFStringCreateCopy(NULL, (CFStringRef)rFormat.m_format);
m_type = rFormat.m_type;
m_id = rFormat.m_id;
return *this;
}
void wxDataFormat::SetType( wxDataFormatId dataType )
{
m_type = dataType;
if ( m_format != 0 )
{
CFRelease( (CFStringRef) m_format );
m_format = 0;
}
switch (m_type)
{
case wxDF_TEXT:
m_format = (long) CFStringCreateCopy( NULL, CFSTR("public.plain-text") );
break;
case wxDF_UNICODETEXT:
m_format = (long) CFStringCreateCopy( NULL, CFSTR("public.utf16-plain-text") );
break;
case wxDF_BITMAP:
m_format = (long) CFStringCreateCopy( NULL, CFSTR("public.tiff") );
break;
case wxDF_METAFILE:
m_format = (long) CFStringCreateCopy( NULL, CFSTR("com.adobe.pdf") );
break;
case wxDF_FILENAME:
m_format = (long) CFStringCreateCopy( NULL, CFSTR("public.file-url") );
break;
default:
wxFAIL_MSG( wxT("invalid data format") );
break;
}
}
wxString wxDataFormat::GetId() const
{
return wxCFStringRef(wxCFRetain((CFStringRef)m_format)).AsString();
}
void wxDataFormat::SetId( NativeFormat format )
{
if ( m_format != 0 )
{
CFRelease( (CFStringRef) m_format );
m_format = 0;
}
m_format = (NativeFormat) CFStringCreateCopy(NULL, (CFStringRef)format);
if ( UTTypeConformsTo( (CFStringRef)format, CFSTR("public.utf16-plain-text") ) )
{
m_type = wxDF_UNICODETEXT;
}
else if ( UTTypeConformsTo( (CFStringRef)format, CFSTR("public.plain-text") ) )
{
m_type = wxDF_TEXT;
}
else if ( UTTypeConformsTo( (CFStringRef)format, CFSTR("public.tiff") ) )
{
m_type = wxDF_BITMAP;
}
else if ( UTTypeConformsTo( (CFStringRef)format, CFSTR("com.adobe.pdf") ) )
{
m_type = wxDF_METAFILE;
}
else if ( UTTypeConformsTo( (CFStringRef)format, CFSTR("public.file-url") ) )
{
m_type = wxDF_FILENAME;
}
else
{
m_type = wxDF_PRIVATE;
m_id = wxCFStringRef( (CFStringRef) CFRetain((CFStringRef) format )).AsString();
}
}
void wxDataFormat::SetId( const wxString& zId )
{
m_type = wxDF_PRIVATE;
m_id = zId;
if ( m_format != 0 )
{
CFRelease( (CFStringRef) m_format );
m_format = 0;
}
// since it is private, no need to conform to anything ...
m_format = (long) wxCFRetain( (CFStringRef) wxCFStringRef(m_id) );
}
bool wxDataFormat::operator==(const wxDataFormat& format) const
{
if (IsStandard() || format.IsStandard())
return (format.m_type == m_type);
else
return ( UTTypeConformsTo( (CFStringRef) m_format , (CFStringRef) format.m_format ) );
}
//-------------------------------------------------------------------------
// wxDataObject
//-------------------------------------------------------------------------
wxDataObject::wxDataObject()
{
}
bool wxDataObject::IsSupportedFormat( const wxDataFormat& rFormat, Direction vDir ) const
{
size_t nFormatCount = GetFormatCount( vDir );
bool found = false;
if (nFormatCount == 1)
{
found = (rFormat == GetPreferredFormat());
}
else
{
wxDataFormat *pFormats = new wxDataFormat[nFormatCount];
GetAllFormats( pFormats, vDir );
for (size_t n = 0; n < nFormatCount; n++)
{
if (pFormats[n] == rFormat)
{
found = true;
break;
}
}
delete [] pFormats;
}
return found;
}
void wxDataObject::AddToPasteboard( void * pb, int itemID )
{
PasteboardRef pasteboard = (PasteboardRef) pb;
// get formats from wxDataObjects
wxDataFormat *array = new wxDataFormat[ GetFormatCount() ];
GetAllFormats( array );
for (size_t i = 0; i < GetFormatCount(); i++)
{
wxDataFormat thisFormat = array[ i ];
// add four bytes at the end for data objs like text that
// have a datasize = strlen but still need a buffer for the
// string including trailing zero
size_t datasize = GetDataSize( thisFormat );
size_t sz = datasize + 4;
void* buf = malloc( sz );
if ( buf != NULL )
{
// empty the buffer because in some case GetDataHere does not fill buf
memset( buf, 0, sz );
if ( GetDataHere( array[ i ], buf ) )
{
int counter = 1 ;
if ( thisFormat.GetType() == wxDF_FILENAME )
{
// the data is D-normalized UTF8 strings of filenames delimited with \n
char *fname = strtok((char*) buf,"\n");
while (fname != NULL)
{
// translate the filepath into a fileurl and put that into the pasteobard
CFStringRef path = CFStringCreateWithBytes(NULL,(UInt8*)fname,strlen(fname),kCFStringEncodingUTF8,false);
CFURLRef url = CFURLCreateWithFileSystemPath(NULL, path , kCFURLPOSIXPathStyle, false);
CFRelease(path);
CFDataRef data = CFURLCreateData(NULL,url,kCFStringEncodingUTF8,true);
CFRelease(url);
PasteboardPutItemFlavor( pasteboard, (PasteboardItemID) counter,
(CFStringRef) thisFormat.GetFormatId() , data, kPasteboardFlavorNoFlags);
CFRelease( data );
counter++;
fname = strtok (NULL,"\n");
}
}
else
{
CFDataRef data = CFDataCreate( kCFAllocatorDefault, (UInt8*)buf, datasize );
if ( thisFormat.GetType() == wxDF_TEXT )
PasteboardPutItemFlavor( pasteboard, (PasteboardItemID) itemID,
CFSTR("com.apple.traditional-mac-plain-text") , data, kPasteboardFlavorNoFlags);
else
PasteboardPutItemFlavor( pasteboard, (PasteboardItemID) itemID,
(CFStringRef) thisFormat.GetFormatId() , data, kPasteboardFlavorNoFlags);
CFRelease( data );
}
}
free( buf );
}
}
delete [] array;
}
bool wxDataObject::IsFormatInPasteboard( void * pb, const wxDataFormat &dataFormat )
{
PasteboardRef pasteboard = (PasteboardRef) pb;
bool hasData = false;
OSStatus err = noErr;
ItemCount itemCount;
// we synchronize here once again, so we don't mind which flags get returned
PasteboardSynchronize( pasteboard );
err = PasteboardGetItemCount( pasteboard, &itemCount );
if ( err == noErr )
{
for( UInt32 itemIndex = 1; itemIndex <= itemCount && hasData == false ; itemIndex++ )
{
PasteboardItemID itemID;
CFArrayRef flavorTypeArray;
CFIndex flavorCount;
err = PasteboardGetItemIdentifier( pasteboard, itemIndex, &itemID );
if ( err != noErr )
continue;
err = PasteboardCopyItemFlavors( pasteboard, itemID, &flavorTypeArray );
if ( err != noErr )
continue;
flavorCount = CFArrayGetCount( flavorTypeArray );
for( CFIndex flavorIndex = 0; flavorIndex < flavorCount && hasData == false ; flavorIndex++ )
{
CFStringRef flavorType;
flavorType = (CFStringRef)CFArrayGetValueAtIndex( flavorTypeArray,
flavorIndex );
wxDataFormat flavorFormat( (wxDataFormat::NativeFormat) flavorType );
if ( dataFormat == flavorFormat )
hasData = true;
else if ( dataFormat.GetType() == wxDF_UNICODETEXT && flavorFormat.GetType() == wxDF_TEXT )
hasData = true;
}
CFRelease (flavorTypeArray);
}
}
return hasData;
}
bool wxDataObject::GetFromPasteboard( void * pb )
{
PasteboardRef pasteboard = (PasteboardRef) pb;
size_t formatcount = GetFormatCount() + 1;
wxDataFormat *array = new wxDataFormat[ formatcount ];
array[0] = GetPreferredFormat();
GetAllFormats( &array[1] );
ItemCount itemCount = 0;
wxString filenamesPassed;
bool transferred = false;
// we synchronize here once again, so we don't mind which flags get returned
PasteboardSynchronize( pasteboard );
OSStatus err = PasteboardGetItemCount( pasteboard, &itemCount );
if ( err == noErr )
{
for (size_t i = 0; !transferred && i < formatcount; i++)
{
// go through the data in our order of preference
wxDataFormat dataFormat = array[ i ];
for( UInt32 itemIndex = 1; itemIndex <= itemCount && transferred == false ; itemIndex++ )
{
PasteboardItemID itemID = 0;
CFArrayRef flavorTypeArray = NULL;
CFIndex flavorCount = 0;
err = PasteboardGetItemIdentifier( pasteboard, itemIndex, &itemID );
if ( err != noErr )
continue;
err = PasteboardCopyItemFlavors( pasteboard, itemID, &flavorTypeArray );
if ( err != noErr )
continue;
flavorCount = CFArrayGetCount( flavorTypeArray );
for( CFIndex flavorIndex = 0; !transferred && flavorIndex < flavorCount ; flavorIndex++ )
{
CFStringRef flavorType;
CFDataRef flavorData;
CFIndex flavorDataSize;
flavorType = (CFStringRef)CFArrayGetValueAtIndex( flavorTypeArray,
flavorIndex );
wxDataFormat flavorFormat( (wxDataFormat::NativeFormat) flavorType );
if ( dataFormat == flavorFormat )
{
err = PasteboardCopyItemFlavorData( pasteboard, itemID, flavorType , &flavorData );
if ( err == noErr )
{
flavorDataSize = CFDataGetLength( flavorData );
if (dataFormat.GetType() == wxDF_FILENAME )
{
// revert the translation and decomposition to arrive at a proper utf8 string again
CFURLRef url = CFURLCreateWithBytes( kCFAllocatorDefault, CFDataGetBytePtr( flavorData ), flavorDataSize, kCFStringEncodingUTF8, NULL );
CFStringRef cfString = CFURLCopyFileSystemPath( url, kCFURLPOSIXPathStyle );
CFRelease( url );
CFMutableStringRef cfMutableString = CFStringCreateMutableCopy(NULL, 0, cfString);
CFRelease( cfString );
CFStringNormalize(cfMutableString,kCFStringNormalizationFormC);
wxString path = wxCFStringRef(cfMutableString).AsString();
if (!path.empty())
filenamesPassed += path + wxT("\n");
}
else
{
// because some data implementation expect trailing a trailing NUL, we add some headroom
void *buf = malloc( flavorDataSize + 4 );
if ( buf )
{
memset( buf, 0, flavorDataSize + 4 );
memcpy( buf, CFDataGetBytePtr( flavorData ), flavorDataSize );
if (dataFormat.GetType() == wxDF_TEXT)
wxMacConvertNewlines10To13( (char*) buf );
SetData( flavorFormat, flavorDataSize, buf );
transferred = true;
free( buf );
}
}
CFRelease (flavorData);
}
}
else if ( dataFormat.GetType() == wxDF_UNICODETEXT && flavorFormat.GetType() == wxDF_TEXT )
{
err = PasteboardCopyItemFlavorData( pasteboard, itemID, flavorType, &flavorData );
if ( err == noErr )
{
flavorDataSize = CFDataGetLength( flavorData );
void *asciibuf = malloc( flavorDataSize + 1 );
if ( asciibuf )
{
memset( asciibuf, 0, flavorDataSize + 1 );
memcpy( asciibuf, CFDataGetBytePtr( flavorData ), flavorDataSize );
CFRelease (flavorData);
SetData( wxDF_TEXT, flavorDataSize, asciibuf );
transferred = true;
free( asciibuf );
}
else
CFRelease (flavorData);
}
}
}
CFRelease( flavorTypeArray );
}
if (filenamesPassed.length() > 0)
{
wxCharBuffer buf = filenamesPassed.fn_str();
SetData( wxDF_FILENAME, strlen( buf ), (const char*)buf );
transferred = true;
}
}
}
return transferred;
}
bool wxDataObject::HasDataInPasteboard( void * pb )
{
PasteboardRef pasteboard = (PasteboardRef) pb;
size_t formatcount = GetFormatCount() + 1;
wxDataFormat *array = new wxDataFormat[ formatcount ];
array[0] = GetPreferredFormat();
GetAllFormats( &array[1] );
ItemCount itemCount = 0;
bool hasData = false;
// we synchronize here once again, so we don't mind which flags get returned
PasteboardSynchronize( pasteboard );
OSStatus err = PasteboardGetItemCount( pasteboard, &itemCount );
if ( err == noErr )
{
for (size_t i = 0; !hasData && i < formatcount; i++)
{
// go through the data in our order of preference
wxDataFormat dataFormat = array[ i ];
for( UInt32 itemIndex = 1; itemIndex <= itemCount && hasData == false ; itemIndex++ )
{
PasteboardItemID itemID = 0;
CFArrayRef flavorTypeArray = NULL;
CFIndex flavorCount = 0;
err = PasteboardGetItemIdentifier( pasteboard, itemIndex, &itemID );
if ( err != noErr )
continue;
err = PasteboardCopyItemFlavors( pasteboard, itemID, &flavorTypeArray );
if ( err != noErr )
continue;
flavorCount = CFArrayGetCount( flavorTypeArray );
for( CFIndex flavorIndex = 0; !hasData && flavorIndex < flavorCount ; flavorIndex++ )
{
CFStringRef flavorType;
flavorType = (CFStringRef)CFArrayGetValueAtIndex( flavorTypeArray,
flavorIndex );
wxDataFormat flavorFormat( (wxDataFormat::NativeFormat) flavorType );
if ( dataFormat == flavorFormat ||
dataFormat.GetType() == wxDF_UNICODETEXT && flavorFormat.GetType() == wxDF_TEXT )
{
hasData = true;
}
}
CFRelease( flavorTypeArray );
}
}
}
return hasData;
}
// ----------------------------------------------------------------------------
// wxTextDataObject
// ----------------------------------------------------------------------------
#if wxUSE_UNICODE
void wxTextDataObject::GetAllFormats(wxDataFormat *formats,
wxDataObjectBase::Direction WXUNUSED(dir)) const
{
*formats++ = wxDataFormat( wxDF_TEXT );
*formats = wxDataFormat( wxDF_UNICODETEXT );
}
#endif
// ----------------------------------------------------------------------------
// wxFileDataObject
// ----------------------------------------------------------------------------
void wxFileDataObject::GetFileNames( wxCharBuffer &buf ) const
{
wxString filenames;
for (size_t i = 0; i < m_filenames.GetCount(); i++)
{
filenames += m_filenames[i];
filenames += wxT('\n');
}
buf = filenames.fn_str();
}
bool wxFileDataObject::GetDataHere( void *pBuf ) const
{
if (pBuf == NULL)
return false;
wxCharBuffer buf;
size_t buffLength;
GetFileNames( buf );
buffLength = strlen( buf );
memcpy( pBuf, (const char*)buf, buffLength + 1 );
return true;
}
size_t wxFileDataObject::GetDataSize() const
{
wxCharBuffer buf;
size_t buffLength;
GetFileNames( buf );
buffLength = strlen( buf );
// terminating 0
return buffLength + 1;
}
bool wxFileDataObject::SetData( size_t WXUNUSED(nSize), const void *pBuf )
{
wxString filenames;
#if wxUSE_UNICODE
filenames = wxString( (const char*)pBuf, *wxConvFileName );
#else
filenames = wxString (wxConvLocal.cWC2WX(wxConvFileName->cMB2WC( (const char*)pBuf)));
#endif
m_filenames = wxStringTokenize( filenames, wxT("\n"), wxTOKEN_STRTOK );
return true;
}
void wxFileDataObject::AddFile( const wxString& rFilename )
{
m_filenames.Add( rFilename );
}
// ----------------------------------------------------------------------------
// wxBitmapDataObject
// ----------------------------------------------------------------------------
wxBitmapDataObject::wxBitmapDataObject()
{
Init();
}
wxBitmapDataObject::wxBitmapDataObject( const wxBitmap& rBitmap )
: wxBitmapDataObjectBase( rBitmap )
{
Init();
if (m_bitmap.Ok())
{
SetBitmap( rBitmap );
}
}
wxBitmapDataObject::~wxBitmapDataObject()
{
Clear();
}
void wxBitmapDataObject::SetBitmap( const wxBitmap& rBitmap )
{
Clear();
wxBitmapDataObjectBase::SetBitmap( rBitmap );
if (m_bitmap.Ok())
{
CGImageRef cgImageRef = (CGImageRef) m_bitmap.CreateCGImage();
CFMutableDataRef data = CFDataCreateMutable(kCFAllocatorDefault, 0);
CGImageDestinationRef destination = CGImageDestinationCreateWithData( data , kUTTypeTIFF , 1 , NULL );
if ( destination )
{
CGImageDestinationAddImage( destination, cgImageRef, NULL );
CGImageDestinationFinalize( destination );
CFRelease( destination );
}
m_pictHandle = NewHandle(CFDataGetLength(data));
if ( m_pictHandle )
{
memcpy( *(Handle)m_pictHandle, (const char *)CFDataGetBytePtr(data), CFDataGetLength(data) );
}
CFRelease( data );
CGImageRelease(cgImageRef);
}
}
void wxBitmapDataObject::Init()
{
m_pictHandle = NULL;
m_pictCreated = false;
}
void wxBitmapDataObject::Clear()
{
if (m_pictHandle != NULL)
{
DisposeHandle( (Handle) m_pictHandle );
m_pictHandle = NULL;
}
m_pictCreated = false;
}
bool wxBitmapDataObject::GetDataHere( void *pBuf ) const
{
if (m_pictHandle == NULL)
{
wxFAIL_MSG( wxT("attempt to copy empty bitmap failed") );
return false;
}
if (pBuf == NULL)
return false;
memcpy( pBuf, *(Handle)m_pictHandle, GetHandleSize( (Handle)m_pictHandle ) );
return true;
}
size_t wxBitmapDataObject::GetDataSize() const
{
if (m_pictHandle != NULL)
return GetHandleSize( (Handle)m_pictHandle );
else
return 0;
}
Handle MacCreateDataReferenceHandle(Handle theDataHandle)
{
Handle dataRef = NULL;
OSErr err = noErr;
// Create a data reference handle for our data.
err = PtrToHand( &theDataHandle, &dataRef, sizeof(Handle));
return dataRef;
}
bool wxBitmapDataObject::SetData( size_t nSize, const void *pBuf )
{
Clear();
if ((pBuf == NULL) || (nSize == 0))
return false;
Handle picHandle = NewHandle( nSize );
memcpy( *picHandle, pBuf, nSize );
m_pictHandle = picHandle;
CGImageRef cgImageRef = 0;
CFDataRef data = CFDataCreateWithBytesNoCopy( kCFAllocatorDefault, (const UInt8*) pBuf, nSize, kCFAllocatorNull);
CGImageSourceRef source = CGImageSourceCreateWithData( data, NULL );
if ( source )
{
cgImageRef = CGImageSourceCreateImageAtIndex(source, 0, NULL);
}
CFRelease( source );
CFRelease( data );
if ( cgImageRef )
{
m_bitmap.Create( CGImageGetWidth(cgImageRef) , CGImageGetHeight(cgImageRef) );
CGRect r = CGRectMake( 0 , 0 , CGImageGetWidth(cgImageRef) , CGImageGetHeight(cgImageRef) );
// since our context is upside down we dont use CGContextDrawImage
wxMacDrawCGImage( (CGContextRef) m_bitmap.GetHBITMAP() , &r, cgImageRef ) ;
CGImageRelease(cgImageRef);
cgImageRef = NULL;
}
return m_bitmap.Ok();
}
#endif

1575
src/osx/carbon/dataview.cpp Normal file

File diff suppressed because it is too large Load Diff

194
src/osx/carbon/dcclient.cpp Normal file
View File

@@ -0,0 +1,194 @@
/////////////////////////////////////////////////////////////////////////////
// Name: src/mac/carbon/dcclient.cpp
// Purpose: wxClientDCImpl class
// Author: Stefan Csomor
// Modified by:
// Created: 01/02/97
// RCS-ID: $Id$
// Copyright: (c) Stefan Csomor
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
#include "wx/wxprec.h"
#include "wx/dcclient.h"
#ifndef WX_PRECOMP
#include "wx/log.h"
#include "wx/window.h"
#include "wx/dcmemory.h"
#include "wx/settings.h"
#include "wx/toplevel.h"
#include "wx/math.h"
#include "wx/region.h"
#endif
#include "wx/graphics.h"
#include "wx/rawbmp.h"
#include "wx/mac/private.h"
//-----------------------------------------------------------------------------
// wxWindowDCImpl
//-----------------------------------------------------------------------------
IMPLEMENT_ABSTRACT_CLASS(wxWindowDCImpl, wxGCDCImpl)
wxWindowDCImpl::wxWindowDCImpl( wxDC *owner )
: wxGCDCImpl( owner )
{
m_release = false;
}
wxWindowDCImpl::wxWindowDCImpl( wxDC *owner, wxWindow *window )
: wxGCDCImpl( owner )
{
m_window = window;
WindowRef rootwindow = (WindowRef) window->MacGetTopLevelWindowRef() ;
if (!rootwindow)
return;
m_ok = true ;
m_window->GetSize( &m_width , &m_height);
if ( !m_window->IsShownOnScreen() )
m_width = m_height = 0;
CGContextRef cg = (CGContextRef) window->MacGetCGContextRef();
m_release = false;
if ( cg == NULL )
{
SetGraphicsContext( wxGraphicsContext::Create( window ) ) ;
}
else
{
CGContextSaveGState( cg );
m_release = true ;
// make sure the context is having its origin at the wx-window coordinates of the
// view (read at the top of window.cpp about the differences)
if ( window->MacGetLeftBorderSize() != 0 || window->MacGetTopBorderSize() != 0 )
CGContextTranslateCTM( cg , -window->MacGetLeftBorderSize() , -window->MacGetTopBorderSize() );
SetGraphicsContext( wxGraphicsContext::CreateFromNative( cg ) );
}
DoSetClippingRegion( 0 , 0 , m_width , m_height ) ;
SetBackground(wxBrush(window->GetBackgroundColour(),wxSOLID));
SetFont( window->GetFont() ) ;
}
wxWindowDCImpl::~wxWindowDCImpl()
{
if ( m_release )
{
// this must not necessarily be the current context, we must restore the state of the
// cg we started with above (before the CGContextTranslateCTM call)
CGContextRef cg = (CGContextRef) m_window->MacGetCGContextRef();
CGContextRestoreGState(cg);
}
}
void wxWindowDCImpl::DoGetSize( int* width, int* height ) const
{
if ( width )
*width = m_width;
if ( height )
*height = m_height;
}
wxBitmap wxWindowDCImpl::DoGetAsBitmap(const wxRect *subrect) const
{
// wxScreenDC is derived from wxWindowDC, so a screen dc will
// call this method when a Blit is performed with it as a source.
if (!m_window)
return wxNullBitmap;
#ifdef __LP64__
return wxNullBitmap;
#else
ControlRef handle = (ControlRef) m_window->GetHandle();
if ( !handle )
return wxNullBitmap;
HIRect rect;
CGImageRef image;
CGContextRef context;
void* data;
size_t bytesPerRow;
HIViewCreateOffscreenImage( handle, 0, &rect, &image);
int width = subrect != NULL ? subrect->width : (int)rect.size.width;
int height = subrect != NULL ? subrect->height : (int)rect.size.height ;
wxBitmap bmp = wxBitmap(width, height, 32);
context = (CGContextRef)bmp.GetHBITMAP();
CGContextSaveGState(context);
CGContextTranslateCTM( context, 0, height );
CGContextScaleCTM( context, 1, -1 );
if ( subrect )
rect = CGRectOffset( rect, -subrect->x, -subrect->y ) ;
CGContextDrawImage( context, rect, image );
CGContextRestoreGState(context);
return bmp;
#endif
}
/*
* wxClientDCImpl
*/
IMPLEMENT_ABSTRACT_CLASS(wxClientDCImpl, wxWindowDCImpl)
wxClientDCImpl::wxClientDCImpl( wxDC *owner )
: wxWindowDCImpl( owner )
{
}
wxClientDCImpl::wxClientDCImpl( wxDC *owner, wxWindow *window ) :
wxWindowDCImpl( owner, window )
{
wxCHECK_RET( window, _T("invalid window in wxClientDCImpl") );
wxPoint origin = window->GetClientAreaOrigin() ;
m_window->GetClientSize( &m_width , &m_height);
if ( !m_window->IsShownOnScreen() )
m_width = m_height = 0;
SetDeviceOrigin( origin.x, origin.y );
DoSetClippingRegion( 0 , 0 , m_width , m_height ) ;
}
wxClientDCImpl::~wxClientDCImpl()
{
}
/*
* wxPaintDCImpl
*/
IMPLEMENT_ABSTRACT_CLASS(wxPaintDCImpl, wxWindowDCImpl)
wxPaintDCImpl::wxPaintDCImpl( wxDC *owner )
: wxWindowDCImpl( owner )
{
}
wxPaintDCImpl::wxPaintDCImpl( wxDC *owner, wxWindow *window ) :
wxWindowDCImpl( owner, window )
{
wxPoint origin = window->GetClientAreaOrigin() ;
m_window->GetClientSize( &m_width , &m_height);
SetDeviceOrigin( origin.x, origin.y );
DoSetClippingRegion( 0 , 0 , m_width , m_height ) ;
}
wxPaintDCImpl::~wxPaintDCImpl()
{
}

116
src/osx/carbon/dcmemory.cpp Normal file
View File

@@ -0,0 +1,116 @@
/////////////////////////////////////////////////////////////////////////////
// Name: src/mac/carbon/dcmemory.cpp
// Purpose: wxMemoryDC class
// Author: Stefan Csomor
// Modified by:
// Created: 01/02/97
// RCS-ID: $Id$
// Copyright: (c) Stefan Csomor
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
#include "wx/wxprec.h"
#include "wx/dcmemory.h"
#include "wx/graphics.h"
#include "wx/mac/dcmemory.h"
#include "wx/mac/private.h"
//-----------------------------------------------------------------------------
// wxMemoryDCImpl
//-----------------------------------------------------------------------------
IMPLEMENT_ABSTRACT_CLASS(wxMemoryDCImpl,wxPaintDCImpl)
wxMemoryDCImpl::wxMemoryDCImpl( wxMemoryDC *owner )
: wxPaintDCImpl( owner )
{
Init();
}
wxMemoryDCImpl::wxMemoryDCImpl( wxMemoryDC *owner, wxBitmap& bitmap )
: wxPaintDCImpl( owner )
{
Init();
DoSelect(bitmap);
}
wxMemoryDCImpl::wxMemoryDCImpl( wxMemoryDC *owner, wxDC * WXUNUSED(dc) )
: wxPaintDCImpl( owner )
{
Init();
}
void wxMemoryDCImpl::Init()
{
m_ok = true;
SetBackground(*wxWHITE_BRUSH);
SetBrush(*wxWHITE_BRUSH);
SetPen(*wxBLACK_PEN);
SetFont(*wxNORMAL_FONT);
m_ok = false;
}
wxMemoryDCImpl::~wxMemoryDCImpl()
{
if ( m_selected.Ok() )
{
m_selected.EndRawAccess() ;
delete m_graphicContext ;
m_graphicContext = NULL ;
}
}
void wxMemoryDCImpl::DoSelect( const wxBitmap& bitmap )
{
if ( m_selected.Ok() )
{
m_selected.EndRawAccess() ;
delete m_graphicContext ;
m_graphicContext = NULL ;
}
m_selected = bitmap;
if (m_selected.Ok())
{
if ( m_selected.GetDepth() != 1 )
m_selected.UseAlpha() ;
m_selected.BeginRawAccess() ;
m_width = bitmap.GetWidth();
m_height = bitmap.GetHeight();
CGColorSpaceRef genericColorSpace = wxMacGetGenericRGBColorSpace();
CGContextRef bmCtx = (CGContextRef) m_selected.GetHBITMAP();
if ( bmCtx )
{
CGContextSetFillColorSpace( bmCtx, genericColorSpace );
CGContextSetStrokeColorSpace( bmCtx, genericColorSpace );
SetGraphicsContext( wxGraphicsContext::CreateFromNative( bmCtx ) );
}
m_ok = (m_graphicContext != NULL) ;
}
else
{
m_ok = false;
}
}
void wxMemoryDCImpl::DoGetSize( int *width, int *height ) const
{
if (m_selected.Ok())
{
if (width)
(*width) = m_selected.GetWidth();
if (height)
(*height) = m_selected.GetHeight();
}
else
{
if (width)
(*width) = 0;
if (height)
(*height) = 0;
}
}

393
src/osx/carbon/dcprint.cpp Normal file
View File

@@ -0,0 +1,393 @@
/////////////////////////////////////////////////////////////////////////////
// Name: src/mac/carbon/dcprint.cpp
// Purpose: wxPrinterDC class
// Author: Julian Smart
// Modified by:
// Created: 01/02/97
// RCS-ID: $Id$
// Copyright: (c) Julian Smart
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"
#if wxUSE_PRINTING_ARCHITECTURE
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#include "wx/dcprint.h"
#ifndef WX_PRECOMP
#include "wx/msgdlg.h"
#include "wx/math.h"
#endif
#include "wx/mac/uma.h"
#include "wx/mac/private/print.h"
#include "wx/mac/carbon/dcprint.h"
#include "wx/graphics.h"
IMPLEMENT_ABSTRACT_CLASS(wxPrinterDCImpl, wxGCDCImpl)
class wxNativePrinterDC
{
public :
wxNativePrinterDC() {}
virtual ~wxNativePrinterDC() {}
virtual bool StartDoc( wxPrinterDC* dc , const wxString& message ) = 0;
virtual void EndDoc( wxPrinterDC* dc ) = 0;
virtual void StartPage( wxPrinterDC* dc ) = 0;
virtual void EndPage( wxPrinterDC* dc ) = 0;
virtual void GetSize( int *w , int *h) const = 0 ;
virtual wxSize GetPPI() const = 0 ;
// returns 0 in case of no Error, otherwise platform specific error codes
virtual wxUint32 GetStatus() const = 0 ;
bool Ok() { return GetStatus() == 0 ; }
static wxNativePrinterDC* Create(wxPrintData* data) ;
} ;
class wxMacCarbonPrinterDC : public wxNativePrinterDC
{
public :
wxMacCarbonPrinterDC( wxPrintData* data ) ;
virtual ~wxMacCarbonPrinterDC() ;
virtual bool StartDoc( wxPrinterDC* dc , const wxString& message ) ;
virtual void EndDoc( wxPrinterDC* dc ) ;
virtual void StartPage( wxPrinterDC* dc ) ;
virtual void EndPage( wxPrinterDC* dc ) ;
virtual wxUint32 GetStatus() const { return m_err ; }
virtual void GetSize( int *w , int *h) const ;
virtual wxSize GetPPI() const ;
private :
wxCoord m_maxX ;
wxCoord m_maxY ;
wxSize m_ppi ;
OSStatus m_err ;
} ;
wxMacCarbonPrinterDC::wxMacCarbonPrinterDC( wxPrintData* data )
{
m_err = noErr ;
wxMacCarbonPrintData *native = (wxMacCarbonPrintData*) data->GetNativeData() ;
PMRect rPage;
m_err = PMGetAdjustedPageRect(native->m_macPageFormat, &rPage);
if ( m_err != noErr )
return;
m_maxX = wxCoord(rPage.right - rPage.left) ;
m_maxY = wxCoord(rPage.bottom - rPage.top);
PMResolution res;
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
if ( PMPrinterGetOutputResolution != NULL )
{
PMPrinter printer;
m_err = PMSessionGetCurrentPrinter(native->m_macPrintSession, &printer);
if ( m_err == noErr )
{
m_err = PMPrinterGetOutputResolution( printer, native->m_macPrintSettings, &res) ;
if ( m_err == -9589 /* kPMKeyNotFound */ )
{
m_err = noErr ;
res.hRes = res.vRes = 300;
}
}
}
else
#endif
{
#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
m_err = PMGetResolution((PMPageFormat) (native->m_macPageFormat), &res);
#endif
}
m_ppi = wxSize(int(res.hRes), int(res.vRes));
}
wxMacCarbonPrinterDC::~wxMacCarbonPrinterDC()
{
}
wxNativePrinterDC* wxNativePrinterDC::Create(wxPrintData* data)
{
return new wxMacCarbonPrinterDC(data) ;
}
bool wxMacCarbonPrinterDC::StartDoc( wxPrinterDC* dc , const wxString& WXUNUSED(message) )
{
if ( m_err )
return false ;
wxPrinterDCImpl *impl = (wxPrinterDCImpl*) dc->GetImpl();
wxMacCarbonPrintData *native = (wxMacCarbonPrintData*) impl->GetPrintData().GetNativeData() ;
m_err = PMSessionBeginCGDocumentNoDialog(native->m_macPrintSession,
native->m_macPrintSettings,
native->m_macPageFormat);
if ( m_err != noErr )
return false;
PMRect rPage;
m_err = PMGetAdjustedPageRect(native->m_macPageFormat, &rPage);
if ( m_err != noErr )
return false ;
m_maxX = wxCoord(rPage.right - rPage.left) ;
m_maxY = wxCoord(rPage.bottom - rPage.top);
PMResolution res;
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
if ( PMPrinterGetOutputResolution != NULL )
{
PMPrinter printer;
m_err = PMSessionGetCurrentPrinter(native->m_macPrintSession, &printer);
if ( m_err == noErr )
{
m_err = PMPrinterGetOutputResolution( printer, native->m_macPrintSettings, &res) ;
if ( m_err == -9589 /* kPMKeyNotFound */ )
{
m_err = noErr ;
res.hRes = res.vRes = 300;
}
}
}
else
#endif
{
#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
m_err = PMGetResolution((PMPageFormat) (native->m_macPageFormat), &res);
#endif
}
m_ppi = wxSize(int(res.hRes), int(res.vRes));
return true ;
}
void wxMacCarbonPrinterDC::EndDoc( wxPrinterDC* dc )
{
if ( m_err )
return ;
wxPrinterDCImpl *impl = (wxPrinterDCImpl*) dc->GetImpl();
wxMacCarbonPrintData *native = (wxMacCarbonPrintData*) impl->GetPrintData().GetNativeData() ;
m_err = PMSessionEndDocumentNoDialog(native->m_macPrintSession);
}
void wxMacCarbonPrinterDC::StartPage( wxPrinterDC* dc )
{
if ( m_err )
return ;
wxPrinterDCImpl *impl = (wxPrinterDCImpl*) dc->GetImpl();
wxMacCarbonPrintData *native = (wxMacCarbonPrintData*) impl->GetPrintData().GetNativeData() ;
m_err = PMSessionBeginPageNoDialog(native->m_macPrintSession,
native->m_macPageFormat,
nil);
CGContextRef pageContext;
if ( m_err == noErr )
{
m_err = PMSessionGetCGGraphicsContext(native->m_macPrintSession,
&pageContext );
}
if ( m_err != noErr )
{
PMSessionEndPageNoDialog(native->m_macPrintSession);
PMSessionEndDocumentNoDialog(native->m_macPrintSession);
}
else
{
PMRect rPage;
m_err = PMGetAdjustedPageRect(native->m_macPageFormat, &rPage);
if ( !m_err )
{
PMRect paperRect ;
PMGetAdjustedPaperRect( native->m_macPageFormat , &paperRect ) ;
// make sure (0,0) is at the upper left of the printable area (wx conventions)
// Core Graphics initially has the lower left of the paper as 0,0
CGContextTranslateCTM( pageContext , (CGFloat) -paperRect.left , (CGFloat) paperRect.bottom ) ;
CGContextScaleCTM( pageContext , 1 , -1 ) ;
}
// since this is a non-critical error, we set the flag back
m_err = noErr ;
}
impl->SetGraphicsContext( wxGraphicsContext::CreateFromNative( pageContext ) );
}
void wxMacCarbonPrinterDC::EndPage( wxPrinterDC* dc )
{
if ( m_err )
return ;
wxPrinterDCImpl *impl = (wxPrinterDCImpl*) dc->GetImpl();
wxMacCarbonPrintData *native = (wxMacCarbonPrintData*) impl->GetPrintData().GetNativeData() ;
m_err = PMSessionEndPageNoDialog(native->m_macPrintSession);
if ( m_err != noErr )
{
PMSessionEndDocumentNoDialog(native->m_macPrintSession);
}
// the cg context we got when starting the page isn't valid anymore, so replace it
impl->SetGraphicsContext( wxGraphicsContext::Create() );
}
void wxMacCarbonPrinterDC::GetSize( int *w , int *h) const
{
if ( w )
*w = m_maxX ;
if ( h )
*h = m_maxY ;
}
wxSize wxMacCarbonPrinterDC::GetPPI() const
{
return m_ppi ;
};
//
//
//
wxPrinterDCImpl::wxPrinterDCImpl( wxPrinterDC *owner, const wxPrintData& printdata )
: wxGCDCImpl( owner )
{
m_ok = false ;
m_printData = printdata ;
m_printData.ConvertToNative() ;
m_nativePrinterDC = wxNativePrinterDC::Create( &m_printData ) ;
if ( m_nativePrinterDC )
{
m_ok = m_nativePrinterDC->Ok() ;
if ( !m_ok )
{
wxString message ;
message.Printf( wxT("Print Error %u"), m_nativePrinterDC->GetStatus() ) ;
wxMessageDialog dialog( NULL , message , wxEmptyString, wxICON_HAND | wxOK) ;
dialog.ShowModal();
}
else
{
wxSize sz = GetPPI();
m_mm_to_pix_x = mm2inches * sz.x;
m_mm_to_pix_y = mm2inches * sz.y;
}
// we need at least a measuring context because people start measuring before a page
// gets printed at all
SetGraphicsContext( wxGraphicsContext::Create() );
}
}
wxSize wxPrinterDCImpl::GetPPI() const
{
return m_nativePrinterDC->GetPPI() ;
}
wxPrinterDCImpl::~wxPrinterDCImpl()
{
delete m_nativePrinterDC ;
}
bool wxPrinterDCImpl::StartDoc( const wxString& message )
{
wxASSERT_MSG( IsOk() , wxT("Called wxPrinterDC::StartDoc from an invalid object") ) ;
if ( !m_ok )
return false ;
if ( m_nativePrinterDC->StartDoc( (wxPrinterDC*) GetOwner(), message ) )
{
// in case we have to do additional things when successful
}
m_ok = m_nativePrinterDC->Ok() ;
if ( !m_ok )
{
wxString message ;
message.Printf( wxT("Print Error %u"), m_nativePrinterDC->GetStatus() ) ;
wxMessageDialog dialog( NULL , message , wxEmptyString, wxICON_HAND | wxOK) ;
dialog.ShowModal();
}
return m_ok ;
}
void wxPrinterDCImpl::EndDoc(void)
{
if ( !m_ok )
return ;
m_nativePrinterDC->EndDoc( (wxPrinterDC*) GetOwner() ) ;
m_ok = m_nativePrinterDC->Ok() ;
if ( !m_ok )
{
wxString message ;
message.Printf( wxT("Print Error %u"), m_nativePrinterDC->GetStatus() ) ;
wxMessageDialog dialog( NULL , message , wxEmptyString, wxICON_HAND | wxOK) ;
dialog.ShowModal();
}
}
wxRect wxPrinterDCImpl::GetPaperRect()
{
wxCoord w, h;
GetOwner()->GetSize(&w, &h);
wxRect pageRect(0, 0, w, h);
wxMacCarbonPrintData *native = (wxMacCarbonPrintData*) m_printData.GetNativeData() ;
OSStatus err = noErr ;
PMRect rPaper;
err = PMGetAdjustedPaperRect(native->m_macPageFormat, &rPaper);
if ( err != noErr )
return pageRect;
return wxRect(wxCoord(rPaper.left), wxCoord(rPaper.top),
wxCoord(rPaper.right - rPaper.left), wxCoord(rPaper.bottom - rPaper.top));
}
void wxPrinterDCImpl::StartPage()
{
if ( !m_ok )
return ;
m_logicalFunction = wxCOPY;
// m_textAlignment = wxALIGN_TOP_LEFT;
m_backgroundMode = wxTRANSPARENT;
m_textForegroundColour = *wxBLACK;
m_textBackgroundColour = *wxWHITE;
m_pen = *wxBLACK_PEN;
m_font = *wxNORMAL_FONT;
m_brush = *wxTRANSPARENT_BRUSH;
m_backgroundBrush = *wxWHITE_BRUSH;
m_nativePrinterDC->StartPage( (wxPrinterDC*) GetOwner() ) ;
m_ok = m_nativePrinterDC->Ok() ;
}
void wxPrinterDCImpl::EndPage()
{
if ( !m_ok )
return ;
m_nativePrinterDC->EndPage( (wxPrinterDC*) GetOwner() );
m_ok = m_nativePrinterDC->Ok() ;
}
void wxPrinterDCImpl::DoGetSize(int *width, int *height) const
{
wxCHECK_RET( m_ok , _T("GetSize() doesn't work without a valid wxPrinterDC") );
m_nativePrinterDC->GetSize(width, height ) ;
}
#endif

View File

@@ -0,0 +1,59 @@
/////////////////////////////////////////////////////////////////////////////
// Name: src/mac/carbon/dcscreen.cpp
// Purpose: wxScreenDC class
// Author: Stefan Csomor
// Modified by:
// Created: 1998-01-01
// RCS-ID: $Id$
// Copyright: (c) Stefan Csomor
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
#include "wx/wxprec.h"
#include "wx/dcscreen.h"
#include "wx/mac/carbon/dcscreen.h"
#include "wx/mac/uma.h"
#include "wx/graphics.h"
IMPLEMENT_ABSTRACT_CLASS(wxScreenDCImpl, wxWindowDCImpl)
// TODO : for the Screenshot use case, which doesn't work in Quartz
// we should do a GetAsBitmap using something like
// http://www.cocoabuilder.com/archive/message/cocoa/2005/8/13/144256
// Create a DC representing the whole screen
wxScreenDCImpl::wxScreenDCImpl( wxDC *owner ) :
wxWindowDCImpl( owner )
{
#ifdef __LP64__
m_graphicContext = NULL;
m_ok = false ;
#else
CGRect cgbounds ;
cgbounds = CGDisplayBounds(CGMainDisplayID());
Rect bounds;
bounds.top = (short)cgbounds.origin.y;
bounds.left = (short)cgbounds.origin.x;
bounds.bottom = bounds.top + (short)cgbounds.size.height;
bounds.right = bounds.left + (short)cgbounds.size.width;
WindowAttributes overlayAttributes = kWindowIgnoreClicksAttribute;
CreateNewWindow( kOverlayWindowClass, overlayAttributes, &bounds, (WindowRef*) &m_overlayWindow );
ShowWindow((WindowRef)m_overlayWindow);
SetGraphicsContext( wxGraphicsContext::CreateFromNativeWindow( m_overlayWindow ) );
m_width = (wxCoord)cgbounds.size.width;
m_height = (wxCoord)cgbounds.size.height;
m_ok = true ;
#endif
}
wxScreenDCImpl::~wxScreenDCImpl()
{
delete m_graphicContext;
m_graphicContext = NULL;
#ifdef __LP64__
#else
DisposeWindow((WindowRef) m_overlayWindow );
#endif
}

185
src/osx/carbon/dialog.cpp Normal file
View File

@@ -0,0 +1,185 @@
/////////////////////////////////////////////////////////////////////////////
// Name: src/mac/carbon/dialog.cpp
// Purpose: wxDialog class
// Author: Stefan Csomor
// Modified by:
// Created: 1998-01-01
// RCS-ID: $Id$
// Copyright: (c) Stefan Csomor
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
#include "wx/wxprec.h"
#include "wx/dialog.h"
#ifndef WX_PRECOMP
#include "wx/app.h"
#include "wx/utils.h"
#include "wx/frame.h"
#include "wx/settings.h"
#endif // WX_PRECOMP
#include "wx/mac/uma.h"
// Lists to keep track of windows, so we can disable/enable them
// for modal dialogs
wxList wxModalDialogs;
IMPLEMENT_DYNAMIC_CLASS(wxDialog, wxTopLevelWindow)
void wxDialog::Init()
{
m_isModalStyle = false;
}
bool wxDialog::Create( wxWindow *parent,
wxWindowID id,
const wxString& title,
const wxPoint& pos,
const wxSize& size,
long style,
const wxString& name )
{
SetExtraStyle( GetExtraStyle() | wxTOPLEVEL_EX_DIALOG );
// All dialogs should really have this style...
style |= wxTAB_TRAVERSAL;
// ...but not these styles
style &= ~(wxYES | wxOK | wxNO); // | wxCANCEL
if ( !wxTopLevelWindow::Create( parent, id, title, pos, size, style, name ) )
return false;
return true;
}
void wxDialog::SetModal( bool flag )
{
if ( flag )
{
m_isModalStyle = true;
SetWindowModality( (WindowRef)MacGetWindowRef(), kWindowModalityAppModal, NULL ) ;
}
else
{
m_isModalStyle = false;
}
}
wxDialog::~wxDialog()
{
m_isBeingDeleted = true;
// if the dialog is modal, this will end its event loop
Show(false);
}
// On mac command-stop does the same thing as Esc, let the base class know
// about it
bool wxDialog::IsEscapeKey(const wxKeyEvent& event)
{
if ( event.GetKeyCode() == '.' && event.GetModifiers() == wxMOD_CMD )
return true;
return wxDialogBase::IsEscapeKey(event);
}
bool wxDialog::IsModal() const
{
return wxModalDialogs.Find((wxDialog *)this) != NULL; // const_cast
// return m_isModalStyle;
}
bool wxDialog::Show(bool show)
{
if ( !wxDialogBase::Show(show) )
// nothing to do
return false;
if (show && CanDoLayoutAdaptation())
DoLayoutAdaptation();
if ( show )
// usually will result in TransferDataToWindow() being called
InitDialog();
HiliteMenu(0);
if ( m_isModalStyle )
{
if ( show )
{
DoShowModal();
}
else // end of modal dialog
{
// this will cause IsModalShowing() return false and our local
// message loop will terminate
wxModalDialogs.DeleteObject(this);
}
}
return true;
}
void wxDialog::DoShowModal()
{
wxCHECK_RET( !IsModal(), wxT("DoShowModal() called twice") );
wxModalDialogs.Append(this);
SetFocus() ;
WindowRef windowRef = (WindowRef) MacGetWindowRef();
WindowGroupRef windowGroup;
WindowGroupRef formerParentGroup;
bool resetGroupParent = false;
if ( GetParent() == NULL )
{
windowGroup = GetWindowGroup(windowRef) ;
formerParentGroup = GetWindowGroupParent( windowGroup );
SetWindowGroupParent( windowGroup, GetWindowGroupOfClass( kMovableModalWindowClass ) );
resetGroupParent = true;
}
BeginAppModalStateForWindow(windowRef) ;
while ( IsModal() )
{
wxTheApp->MacDoOneEvent() ;
// calls process idle itself
}
EndAppModalStateForWindow(windowRef) ;
if ( resetGroupParent )
{
SetWindowGroupParent( windowGroup , formerParentGroup );
}
}
// Replacement for Show(true) for modal dialogs - returns return code
int wxDialog::ShowModal()
{
if ( !m_isModalStyle )
SetModal(true);
Show(true);
return GetReturnCode();
}
// NB: this function (surprizingly) may be called for both modal and modeless
// dialogs and should work for both of them
void wxDialog::EndModal(int retCode)
{
SetReturnCode(retCode);
Show(false);
SetModal(false);
}

145
src/osx/carbon/dirdlg.cpp Normal file
View File

@@ -0,0 +1,145 @@
/////////////////////////////////////////////////////////////////////////////
// Name: src/mac/carbon/dirdlg.cpp
// Purpose: wxDirDialog
// Author: Stefan Csomor
// Modified by:
// Created: 1998-01-01
// RCS-ID: $Id$
// Copyright: (c) Stefan Csomor
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
#include "wx/wxprec.h"
#if wxUSE_DIRDLG
#include "wx/dirdlg.h"
#ifndef WX_PRECOMP
#include "wx/utils.h"
#include "wx/dialog.h"
#include "wx/cmndata.h"
#endif // WX_PRECOMP
#include "wx/filename.h"
#include "wx/mac/private.h"
#ifdef __DARWIN__
#include <Carbon/Carbon.h>
#else
#include <Navigation.h>
#endif
IMPLEMENT_CLASS(wxDirDialog, wxDialog)
static pascal void NavEventProc(
NavEventCallbackMessage inSelector,
NavCBRecPtr ioParams,
NavCallBackUserData ioUserData );
static NavEventUPP sStandardNavEventFilter = NewNavEventUPP(NavEventProc);
static pascal void NavEventProc(
NavEventCallbackMessage inSelector,
NavCBRecPtr ioParams,
NavCallBackUserData ioUserData )
{
wxDirDialog * data = ( wxDirDialog *) ioUserData ;
if ( inSelector == kNavCBStart )
{
if (data && !data->GetPath().empty() )
{
// Set default location for the modern Navigation APIs
// Apple Technical Q&A 1151
FSRef theFile;
wxMacPathToFSRef(data->GetPath(), &theFile);
AEDesc theLocation = { typeNull, NULL };
if (noErr == ::AECreateDesc(typeFSRef, &theFile, sizeof(FSRef), &theLocation))
::NavCustomControl(ioParams->context, kNavCtlSetLocation, (void *) &theLocation);
}
}
}
wxDirDialog::wxDirDialog(wxWindow *parent,
const wxString& message,
const wxString& defaultPath,
long WXUNUSED(style),
const wxPoint& WXUNUSED(pos),
const wxSize& WXUNUSED(size),
const wxString& WXUNUSED(name))
{
wxASSERT_MSG( NavServicesAvailable() , wxT("Navigation Services are not running") ) ;
m_message = message;
m_parent = parent;
m_path = defaultPath;
}
int wxDirDialog::ShowModal()
{
NavDialogRef dialog = NULL;
NavDialogCreationOptions options;
NavReplyRecord reply ;
bool disposeReply = false ;
OSStatus err = noErr;
err = NavGetDefaultDialogCreationOptions(&options);
options.optionFlags &= ~kNavAllowMultipleFiles;
if (err == noErr)
{
wxCFStringRef message(m_message, GetFont().GetEncoding());
options.message = message;
err = NavCreateChooseFolderDialog(&options, sStandardNavEventFilter , NULL, this , &dialog);
if (err == noErr)
{
err = NavDialogRun(dialog);
if ( err == noErr )
{
err = NavDialogGetReply(dialog, &reply);
disposeReply = true ;
}
}
}
if ( err == noErr )
{
if ( reply.validRecord )
{
FSRef folderInfo;
AEDesc specDesc ;
OSErr err = ::AECoerceDesc( &reply.selection , typeFSRef, &specDesc);
if ( err != noErr )
{
m_path = wxEmptyString ;
}
else
{
folderInfo = **(FSRef**) specDesc.dataHandle;
m_path = wxMacFSRefToPath( &folderInfo ) ;
if (specDesc.dataHandle != nil)
{
::AEDisposeDesc(&specDesc);
}
}
}
else
{
err = paramErr ; // could be any error, only used for giving back wxID_CANCEL
}
}
if ( disposeReply )
::NavDisposeReply(&reply);
// apparently cancelling shouldn't change m_path
if ( err != noErr && err != userCanceledErr )
m_path = wxEmptyString ;
if ( dialog )
::NavDialogDispose(dialog);
return (err == noErr) ? wxID_OK : wxID_CANCEL ;
}
#endif

269
src/osx/carbon/dirmac.cpp Normal file
View File

@@ -0,0 +1,269 @@
/////////////////////////////////////////////////////////////////////////////
// Name: mac/dirmac.cpp
// Purpose: wxDir implementation for Mac
// Author: Stefan Csomor
// Modified by:
// Created: 08.12.99
// RCS-ID: $Id$
// Copyright: (c) 1999 Stefan Csomor <csomor@advanced.ch>
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
// ============================================================================
// declarations
// ============================================================================
// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------
// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#include "wx/dir.h"
#ifndef WX_PRECOMP
#include "wx/intl.h"
#include "wx/log.h"
#endif // PCH
#include "wx/filefn.h" // for wxDirExists()
#include "wx/filename.h"
#include "wx/mac/private.h"
// ----------------------------------------------------------------------------
// private classes
// ----------------------------------------------------------------------------
// this class stores everything we need to enumerate the files
class wxDirData
{
public:
wxDirData(const wxString& dirname);
~wxDirData();
void Close() ;
void SetFileSpec(const wxString& filespec) { m_filespec = filespec; }
void SetFlags(int flags) { m_flags = flags; }
bool Read(wxString *filename); // reads the next
void Rewind() ;
const wxString& GetName() const { return m_dirname; }
private:
FSIterator m_iterator ;
wxString m_dirname;
wxString m_filespec;
int m_flags;
};
// ============================================================================
// implementation
// ============================================================================
// ----------------------------------------------------------------------------
// wxDirData
// ----------------------------------------------------------------------------
wxDirData::wxDirData(const wxString& dirname)
: m_dirname(dirname)
{
// throw away the trailing slashes
size_t n = m_dirname.length();
wxCHECK_RET( n, _T("empty dir name in wxDir") );
while ( n > 0 && wxIsPathSeparator(m_dirname[--n]) )
;
m_dirname.Truncate(n + 1);
m_iterator = NULL ;
}
wxDirData::~wxDirData()
{
Close() ;
}
void wxDirData::Close()
{
if ( m_iterator )
{
FSCloseIterator( m_iterator ) ;
m_iterator = NULL ;
}
}
void wxDirData::Rewind()
{
Close() ;
}
bool wxDirData::Read(wxString *filename)
{
wxString result;
OSStatus err = noErr ;
if ( NULL == m_iterator )
{
FSRef dirRef;
err = wxMacPathToFSRef( m_dirname , &dirRef ) ;
if ( err == noErr )
{
err = FSOpenIterator(&dirRef, kFSIterateFlat, &m_iterator);
}
if ( err )
{
Close() ;
return false ;
}
}
wxString name ;
wxString lowerfilespec = m_filespec.Lower();
while( noErr == err )
{
HFSUniStr255 uniname ;
FSRef fileRef;
FSCatalogInfo catalogInfo;
ItemCount fetched = 0;
err = FSGetCatalogInfoBulk( m_iterator, 1, &fetched, NULL, kFSCatInfoNodeFlags | kFSCatInfoFinderInfo , &catalogInfo , &fileRef, NULL, &uniname );
// expected error codes
if ( errFSNoMoreItems == err )
return false ;
if ( afpAccessDenied == err )
return false ;
if ( noErr != err )
break ;
name = wxMacHFSUniStrToString( &uniname ) ;
wxString lowername = name.Lower();
if ( ( name == wxT(".") || name == wxT("..") ) && !(m_flags & wxDIR_DOTDOT) )
continue;
if ( ( name[0U] == '.' ) && !(m_flags & wxDIR_HIDDEN ) )
continue ;
if ( (((FileInfo*)&catalogInfo.finderInfo)->finderFlags & kIsInvisible ) && !(m_flags & wxDIR_HIDDEN ) )
continue ;
// its a dir and we don't want it
if ( (catalogInfo.nodeFlags & kFSNodeIsDirectoryMask) && !(m_flags & wxDIR_DIRS) )
continue ;
// its a file but we don't want it
if ( (catalogInfo.nodeFlags & kFSNodeIsDirectoryMask) == 0 && !(m_flags & wxDIR_FILES ) )
continue ;
if ( m_filespec.empty() || m_filespec == wxT("*.*") || m_filespec == wxT("*") )
{
}
else if ( !wxMatchWild(lowerfilespec, lowername , false) )
{
continue ;
}
break ;
}
if ( err != noErr )
{
return false ;
}
*filename = name ;
return true;
}
// ----------------------------------------------------------------------------
// wxDir helpers
// ----------------------------------------------------------------------------
/* static */
bool wxDir::Exists(const wxString& dir)
{
return wxDirExists(dir);
}
// ----------------------------------------------------------------------------
// wxDir construction/destruction
// ----------------------------------------------------------------------------
wxDir::wxDir(const wxString& dirname)
{
m_data = NULL;
(void)Open(dirname);
}
bool wxDir::Open(const wxString& dirname)
{
delete m_data;
m_data = new wxDirData(dirname);
return true;
}
bool wxDir::IsOpened() const
{
return m_data != NULL;
}
wxString wxDir::GetName() const
{
wxString name;
if ( m_data )
{
name = m_data->GetName();
if ( !name.empty() && (name.Last() == _T('/')) )
{
// chop off the last (back)slash
name.Truncate(name.length() - 1);
}
}
return name;
}
wxDir::~wxDir()
{
delete m_data;
m_data = NULL;
}
// ----------------------------------------------------------------------------
// wxDir enumerating
// ----------------------------------------------------------------------------
bool wxDir::GetFirst(wxString *filename,
const wxString& filespec,
int flags) const
{
wxCHECK_MSG( IsOpened(), false, _T("must wxDir::Open() first") );
m_data->Rewind();
m_data->SetFileSpec(filespec);
m_data->SetFlags(flags);
return GetNext(filename);
}
bool wxDir::GetNext(wxString *filename) const
{
wxCHECK_MSG( IsOpened(), false, _T("must wxDir::Open() first") );
wxCHECK_MSG( filename, false, _T("bad pointer in wxDir::GetNext()") );
return m_data->Read(filename);
}

255
src/osx/carbon/display.cpp Normal file
View File

@@ -0,0 +1,255 @@
/////////////////////////////////////////////////////////////////////////////
// Name: src/mac/carbon/display.cpp
// Purpose: Mac implementation of wxDisplay class
// Author: Ryan Norton & Brian Victor
// Modified by: Royce Mitchell III, Vadim Zeitlin
// Created: 06/21/02
// RCS-ID: $Id$
// Copyright: (c) wxWidgets team
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
// ============================================================================
// declarations
// ============================================================================
// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#if wxUSE_DISPLAY
#include "wx/display.h"
#ifndef WX_PRECOMP
#include "wx/dynarray.h"
#include "wx/log.h"
#include "wx/string.h"
#include "wx/gdicmn.h"
#endif
#include <Carbon/Carbon.h>
#include "wx/display_impl.h"
// ----------------------------------------------------------------------------
// display classes implementation
// ----------------------------------------------------------------------------
class wxDisplayImplMacOSX : public wxDisplayImpl
{
public:
wxDisplayImplMacOSX(unsigned n, CGDirectDisplayID id)
: wxDisplayImpl(n),
m_id(id)
{
}
virtual wxRect GetGeometry() const;
virtual wxRect GetClientArea() const;
virtual wxString GetName() const { return wxString(); }
virtual wxArrayVideoModes GetModes(const wxVideoMode& mode) const;
virtual wxVideoMode GetCurrentMode() const;
virtual bool ChangeMode(const wxVideoMode& mode);
private:
CGDirectDisplayID m_id;
DECLARE_NO_COPY_CLASS(wxDisplayImplMacOSX)
};
class wxDisplayFactoryMacOSX : public wxDisplayFactory
{
public:
wxDisplayFactoryMacOSX() {}
virtual wxDisplayImpl *CreateDisplay(unsigned n);
virtual unsigned GetCount();
virtual int GetFromPoint(const wxPoint& pt);
protected:
DECLARE_NO_COPY_CLASS(wxDisplayFactoryMacOSX)
};
// ============================================================================
// wxDisplayFactoryMacOSX implementation
// ============================================================================
unsigned wxDisplayFactoryMacOSX::GetCount()
{
CGDisplayCount count;
#ifdef __WXDEBUG__
CGDisplayErr err =
#endif
CGGetActiveDisplayList(0, NULL, &count);
wxASSERT(err == CGDisplayNoErr);
return count;
}
int wxDisplayFactoryMacOSX::GetFromPoint(const wxPoint& p)
{
CGPoint thePoint = {(float)p.x, (float)p.y};
CGDirectDisplayID theID;
CGDisplayCount theCount;
CGDisplayErr err = CGGetDisplaysWithPoint(thePoint, 1, &theID, &theCount);
wxASSERT(err == CGDisplayNoErr);
int nWhich = wxNOT_FOUND;
if (theCount)
{
theCount = GetCount();
CGDirectDisplayID* theIDs = new CGDirectDisplayID[theCount];
err = CGGetActiveDisplayList(theCount, theIDs, &theCount);
wxASSERT(err == CGDisplayNoErr);
for (nWhich = 0; nWhich < (int) theCount; ++nWhich)
{
if (theIDs[nWhich] == theID)
break;
}
delete [] theIDs;
if (nWhich == (int) theCount)
{
wxFAIL_MSG(wxT("Failed to find display in display list"));
nWhich = wxNOT_FOUND;
}
}
return nWhich;
}
wxDisplayImpl *wxDisplayFactoryMacOSX::CreateDisplay(unsigned n)
{
CGDisplayCount theCount = GetCount();
CGDirectDisplayID* theIDs = new CGDirectDisplayID[theCount];
#ifdef __WXDEBUG__
CGDisplayErr err =
#endif
CGGetActiveDisplayList(theCount, theIDs, &theCount);
wxASSERT( err == CGDisplayNoErr );
wxASSERT( n < theCount );
wxDisplayImplMacOSX *display = new wxDisplayImplMacOSX(n, theIDs[n]);
delete [] theIDs;
return display;
}
// ============================================================================
// wxDisplayImplMacOSX implementation
// ============================================================================
wxRect wxDisplayImplMacOSX::GetGeometry() const
{
CGRect theRect = CGDisplayBounds(m_id);
return wxRect( (int)theRect.origin.x,
(int)theRect.origin.y,
(int)theRect.size.width,
(int)theRect.size.height ); //floats
}
wxRect wxDisplayImplMacOSX::GetClientArea() const
{
// VZ: I don't know how to get client area for arbitrary display but
// wxGetClientDisplayRect() does work correctly for at least the main
// one (TODO: do it correctly for the other displays too)
if ( IsPrimary() )
return wxGetClientDisplayRect();
return wxDisplayImpl::GetClientArea();
}
static int wxCFDictKeyToInt( CFDictionaryRef desc, CFStringRef key )
{
CFNumberRef value = (CFNumberRef) CFDictionaryGetValue( desc, key );
if (value == NULL)
return 0;
int num = 0;
CFNumberGetValue( value, kCFNumberIntType, &num );
return num;
}
wxArrayVideoModes wxDisplayImplMacOSX::GetModes(const wxVideoMode& mode) const
{
wxArrayVideoModes resultModes;
CFArrayRef theArray = CGDisplayAvailableModes( m_id );
for (CFIndex i = 0; i < CFArrayGetCount(theArray); ++i)
{
CFDictionaryRef theValue = (CFDictionaryRef) CFArrayGetValueAtIndex( theArray, i );
wxVideoMode theMode(
wxCFDictKeyToInt( theValue, kCGDisplayWidth ),
wxCFDictKeyToInt( theValue, kCGDisplayHeight ),
wxCFDictKeyToInt( theValue, kCGDisplayBitsPerPixel ),
wxCFDictKeyToInt( theValue, kCGDisplayRefreshRate ));
if (theMode.Matches( mode ))
resultModes.Add( theMode );
}
return resultModes;
}
wxVideoMode wxDisplayImplMacOSX::GetCurrentMode() const
{
CFDictionaryRef theValue = CGDisplayCurrentMode( m_id );
return wxVideoMode(
wxCFDictKeyToInt( theValue, kCGDisplayWidth ),
wxCFDictKeyToInt( theValue, kCGDisplayHeight ),
wxCFDictKeyToInt( theValue, kCGDisplayBitsPerPixel ),
wxCFDictKeyToInt( theValue, kCGDisplayRefreshRate ));
}
bool wxDisplayImplMacOSX::ChangeMode( const wxVideoMode& mode )
{
// Changing to default mode (wxDefaultVideoMode) doesn't
// work because we don't have access to the system's 'scrn'
// resource which holds the user's mode which the system
// will return to after this app is done
boolean_t bExactMatch;
CFDictionaryRef theCGMode = CGDisplayBestModeForParametersAndRefreshRate(
m_id,
(size_t)mode.GetDepth(),
(size_t)mode.GetWidth(),
(size_t)mode.GetHeight(),
(double)mode.GetRefresh(),
&bExactMatch );
bool bOK = bExactMatch;
if (bOK)
bOK = CGDisplaySwitchToMode( m_id, theCGMode ) == CGDisplayNoErr;
return bOK;
}
// ============================================================================
// wxDisplay::CreateFactory()
// ============================================================================
/* static */ wxDisplayFactory *wxDisplay::CreateFactory()
{
return new wxDisplayFactoryMacOSX;
}
#endif // wxUSE_DISPLAY

562
src/osx/carbon/dnd.cpp Normal file
View File

@@ -0,0 +1,562 @@
///////////////////////////////////////////////////////////////////////////////
// Name: src/mac/carbon/dnd.cpp
// Purpose: wxDropTarget, wxDropSource implementations
// Author: Stefan Csomor
// Modified by:
// Created: 1998-01-01
// RCS-ID: $Id$
// Copyright: (c) 1998 Stefan Csomor
// Licence: wxWindows licence
///////////////////////////////////////////////////////////////////////////////
#include "wx/wxprec.h"
#if wxUSE_DRAG_AND_DROP
#include "wx/dnd.h"
#ifndef WX_PRECOMP
#include "wx/app.h"
#include "wx/toplevel.h"
#include "wx/gdicmn.h"
#endif // WX_PRECOMP
#include "wx/mac/private.h"
// ----------------------------------------------------------------------------
// globals
// ----------------------------------------------------------------------------
typedef struct
{
wxWindow *m_currentTargetWindow;
wxDropTarget *m_currentTarget;
wxDropSource *m_currentSource;
wxDragResult m_result;
int m_flags;
} MacTrackingGlobals;
MacTrackingGlobals gTrackingGlobals;
void wxMacEnsureTrackingHandlersInstalled();
//----------------------------------------------------------------------------
// wxDropTarget
//----------------------------------------------------------------------------
wxDropTarget::wxDropTarget( wxDataObject *data )
: wxDropTargetBase( data )
{
wxMacEnsureTrackingHandlersInstalled();
}
wxDragResult wxDropTarget::OnDragOver(
wxCoord WXUNUSED(x), wxCoord WXUNUSED(y),
wxDragResult def )
{
return CurrentDragHasSupportedFormat() ? def : wxDragNone;
}
bool wxDropTarget::OnDrop( wxCoord WXUNUSED(x), wxCoord WXUNUSED(y) )
{
if (m_dataObject == NULL)
return false;
return CurrentDragHasSupportedFormat();
}
wxDragResult wxDropTarget::OnData(
wxCoord WXUNUSED(x), wxCoord WXUNUSED(y),
wxDragResult def )
{
if (m_dataObject == NULL)
return wxDragNone;
if (!CurrentDragHasSupportedFormat())
return wxDragNone;
return GetData() ? def : wxDragNone;
}
bool wxDropTarget::CurrentDragHasSupportedFormat()
{
bool supported = false;
if (m_dataObject == NULL)
return false;
if ( gTrackingGlobals.m_currentSource != NULL )
{
wxDataObject* data = gTrackingGlobals.m_currentSource->GetDataObject();
if ( data )
{
size_t formatcount = data->GetFormatCount();
wxDataFormat *array = new wxDataFormat[formatcount];
data->GetAllFormats( array );
for (size_t i = 0; !supported && i < formatcount; i++)
{
wxDataFormat format = array[i];
if ( m_dataObject->IsSupported( format ) )
{
supported = true;
break;
}
}
delete [] array;
}
}
if ( !supported )
{
PasteboardRef pasteboard;
if ( GetDragPasteboard( (DragReference)m_currentDrag, &pasteboard ) == noErr )
{
supported = m_dataObject->HasDataInPasteboard( pasteboard );
}
}
return supported;
}
bool wxDropTarget::GetData()
{
if (m_dataObject == NULL)
return false;
if ( !CurrentDragHasSupportedFormat() )
return false;
bool transferred = false;
if ( gTrackingGlobals.m_currentSource != NULL )
{
wxDataObject* data = gTrackingGlobals.m_currentSource->GetDataObject();
if (data != NULL)
{
size_t formatcount = data->GetFormatCount();
wxDataFormat *array = new wxDataFormat[formatcount];
data->GetAllFormats( array );
for (size_t i = 0; !transferred && i < formatcount; i++)
{
wxDataFormat format = array[i];
if ( m_dataObject->IsSupported( format ) )
{
int size = data->GetDataSize( format );
transferred = true;
if (size == 0)
{
m_dataObject->SetData( format, 0, 0 );
}
else
{
char *d = new char[size];
data->GetDataHere( format, (void*)d );
m_dataObject->SetData( format, size, d );
delete [] d;
}
}
}
delete [] array;
}
}
if ( !transferred )
{
PasteboardRef pasteboard;
if ( GetDragPasteboard( (DragReference)m_currentDrag, &pasteboard ) == noErr )
{
transferred = m_dataObject->GetFromPasteboard( pasteboard );
}
}
return transferred;
}
//-------------------------------------------------------------------------
// wxDropSource
//-------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// drag request
wxDropSource::wxDropSource(wxWindow *win,
const wxCursor &cursorCopy,
const wxCursor &cursorMove,
const wxCursor &cursorStop)
: wxDropSourceBase(cursorCopy, cursorMove, cursorStop)
{
wxMacEnsureTrackingHandlersInstalled();
m_window = win;
}
wxDropSource::wxDropSource(wxDataObject& data,
wxWindow *win,
const wxCursor &cursorCopy,
const wxCursor &cursorMove,
const wxCursor &cursorStop)
: wxDropSourceBase(cursorCopy, cursorMove, cursorStop)
{
wxMacEnsureTrackingHandlersInstalled();
SetData( data );
m_window = win;
}
wxDropSource::~wxDropSource()
{
}
OSStatus wxMacPromiseKeeper(PasteboardRef WXUNUSED(inPasteboard),
PasteboardItemID WXUNUSED(inItem),
CFStringRef WXUNUSED(inFlavorType),
void * WXUNUSED(inContext))
{
OSStatus err = noErr;
// we might add promises here later, inContext is the wxDropSource*
return err;
}
wxDragResult wxDropSource::DoDragDrop(int flags)
{
wxASSERT_MSG( m_data, wxT("Drop source: no data") );
if ((m_data == NULL) || (m_data->GetFormatCount() == 0))
return (wxDragResult)wxDragNone;
DragReference theDrag;
RgnHandle dragRegion;
OSStatus err = noErr;
PasteboardRef pasteboard;
// add data to drag
err = PasteboardCreate( kPasteboardUniqueName, &pasteboard );
if ( err != noErr )
return wxDragNone;
// we add a dummy promise keeper because of strange messages when linking against carbon debug
err = PasteboardSetPromiseKeeper( pasteboard, wxMacPromiseKeeper, this );
if ( err != noErr )
{
CFRelease( pasteboard );
return wxDragNone;
}
err = PasteboardClear( pasteboard );
if ( err != noErr )
{
CFRelease( pasteboard );
return wxDragNone;
}
PasteboardSynchronize( pasteboard );
m_data->AddToPasteboard( pasteboard, 1 );
if (NewDragWithPasteboard( pasteboard , &theDrag) != noErr)
{
CFRelease( pasteboard );
return wxDragNone;
}
dragRegion = NewRgn();
RgnHandle tempRgn = NewRgn();
EventRecord rec;
ConvertEventRefToEventRecord( (EventRef) wxTheApp->MacGetCurrentEvent(), &rec );
const short dragRegionOuterBoundary = 10;
const short dragRegionInnerBoundary = 9;
SetRectRgn(
dragRegion,
rec.where.h - dragRegionOuterBoundary,
rec.where.v - dragRegionOuterBoundary,
rec.where.h + dragRegionOuterBoundary,
rec.where.v + dragRegionOuterBoundary );
SetRectRgn(
tempRgn,
rec.where.h - dragRegionInnerBoundary,
rec.where.v - dragRegionInnerBoundary,
rec.where.h + dragRegionInnerBoundary,
rec.where.v + dragRegionInnerBoundary );
DiffRgn( dragRegion, tempRgn, dragRegion );
DisposeRgn( tempRgn );
// TODO: work with promises in order to return data
// only when drag was successfully completed
gTrackingGlobals.m_currentSource = this;
gTrackingGlobals.m_result = wxDragNone;
gTrackingGlobals.m_flags = flags;
err = TrackDrag( theDrag, &rec, dragRegion );
DisposeRgn( dragRegion );
DisposeDrag( theDrag );
CFRelease( pasteboard );
gTrackingGlobals.m_currentSource = NULL;
return gTrackingGlobals.m_result;
}
bool wxDropSource::MacInstallDefaultCursor(wxDragResult effect)
{
const wxCursor& cursor = GetCursor(effect);
bool result = cursor.Ok();
if ( result )
cursor.MacInstall();
return result;
}
bool gTrackingGlobalsInstalled = false;
// passing the globals via refcon is not needed by the CFM and later architectures anymore
// but I'll leave it in there, just in case...
pascal OSErr wxMacWindowDragTrackingHandler(
DragTrackingMessage theMessage, WindowPtr theWindow,
void *handlerRefCon, DragReference theDrag );
pascal OSErr wxMacWindowDragReceiveHandler(
WindowPtr theWindow, void *handlerRefCon,
DragReference theDrag );
void wxMacEnsureTrackingHandlersInstalled()
{
if ( !gTrackingGlobalsInstalled )
{
OSStatus err;
err = InstallTrackingHandler( NewDragTrackingHandlerUPP(wxMacWindowDragTrackingHandler), 0L, &gTrackingGlobals );
verify_noerr( err );
err = InstallReceiveHandler( NewDragReceiveHandlerUPP(wxMacWindowDragReceiveHandler), 0L, &gTrackingGlobals );
verify_noerr( err );
gTrackingGlobalsInstalled = true;
}
}
pascal OSErr wxMacWindowDragTrackingHandler(
DragTrackingMessage theMessage, WindowPtr theWindow,
void *handlerRefCon, DragReference theDrag )
{
MacTrackingGlobals* trackingGlobals = (MacTrackingGlobals*) handlerRefCon;
Point mouse, localMouse;
DragAttributes attributes;
GetDragAttributes( theDrag, &attributes );
wxNonOwnedWindow* toplevel = wxFindWinFromMacWindow( theWindow );
bool optionDown = GetCurrentKeyModifiers() & optionKey;
wxDragResult result = optionDown ? wxDragCopy : wxDragMove;
switch (theMessage)
{
case kDragTrackingEnterHandler:
case kDragTrackingLeaveHandler:
break;
case kDragTrackingEnterWindow:
if (trackingGlobals != NULL)
{
trackingGlobals->m_currentTargetWindow = NULL;
trackingGlobals->m_currentTarget = NULL;
}
break;
case kDragTrackingInWindow:
if (trackingGlobals == NULL)
break;
if (toplevel == NULL)
break;
GetDragMouse( theDrag, &mouse, 0L );
localMouse = mouse;
wxMacGlobalToLocal( theWindow, &localMouse );
{
wxWindow *win = NULL;
ControlPartCode controlPart;
ControlRef control = FindControlUnderMouse( localMouse, theWindow, &controlPart );
if ( control )
win = wxFindControlFromMacControl( control );
else
win = toplevel;
int localx, localy;
localx = localMouse.h;
localy = localMouse.v;
if ( win )
win->MacRootWindowToWindow( &localx, &localy );
if ( win != trackingGlobals->m_currentTargetWindow )
{
if ( trackingGlobals->m_currentTargetWindow )
{
// this window is left
if ( trackingGlobals->m_currentTarget )
{
#ifndef __LP64__
HideDragHilite( theDrag );
#endif
trackingGlobals->m_currentTarget->SetCurrentDrag( theDrag );
trackingGlobals->m_currentTarget->OnLeave();
trackingGlobals->m_currentTarget = NULL;
trackingGlobals->m_currentTargetWindow = NULL;
}
}
if ( win )
{
// this window is entered
trackingGlobals->m_currentTargetWindow = win;
trackingGlobals->m_currentTarget = win->GetDropTarget();
{
if ( trackingGlobals->m_currentTarget )
{
trackingGlobals->m_currentTarget->SetCurrentDrag( theDrag );
result = trackingGlobals->m_currentTarget->OnEnter( localx, localy, result );
}
if ( result != wxDragNone )
{
int x, y;
x = y = 0;
win->MacWindowToRootWindow( &x, &y );
RgnHandle hiliteRgn = NewRgn();
Rect r = { y, x, y + win->GetSize().y, x + win->GetSize().x };
RectRgn( hiliteRgn, &r );
#ifndef __LP64__
ShowDragHilite( theDrag, hiliteRgn, true );
#endif
DisposeRgn( hiliteRgn );
}
}
}
}
else
{
if ( trackingGlobals->m_currentTarget )
{
trackingGlobals->m_currentTarget->SetCurrentDrag( theDrag );
result = trackingGlobals->m_currentTarget->OnDragOver( localx, localy, result );
}
}
// set cursor for OnEnter and OnDragOver
if ( trackingGlobals->m_currentSource && !trackingGlobals->m_currentSource->GiveFeedback( result ) )
{
if ( !trackingGlobals->m_currentSource->MacInstallDefaultCursor( result ) )
{
int cursorID = wxCURSOR_NONE;
switch (result)
{
case wxDragCopy:
cursorID = wxCURSOR_COPY_ARROW;
break;
case wxDragMove:
cursorID = wxCURSOR_ARROW;
break;
case wxDragNone:
cursorID = wxCURSOR_NO_ENTRY;
break;
case wxDragError:
case wxDragLink:
case wxDragCancel:
default:
// put these here to make gcc happy
;
}
if (cursorID != wxCURSOR_NONE)
{
wxCursor cursor( cursorID );
cursor.MacInstall();
}
}
}
}
break;
case kDragTrackingLeaveWindow:
if (trackingGlobals == NULL)
break;
if (trackingGlobals->m_currentTarget)
{
trackingGlobals->m_currentTarget->SetCurrentDrag( theDrag );
trackingGlobals->m_currentTarget->OnLeave();
#ifndef __LP64__
HideDragHilite( theDrag );
#endif
trackingGlobals->m_currentTarget = NULL;
}
trackingGlobals->m_currentTargetWindow = NULL;
break;
default:
break;
}
return noErr;
}
pascal OSErr wxMacWindowDragReceiveHandler(
WindowPtr theWindow,
void *handlerRefCon,
DragReference theDrag)
{
MacTrackingGlobals* trackingGlobals = (MacTrackingGlobals*)handlerRefCon;
if ( trackingGlobals->m_currentTarget )
{
Point mouse, localMouse;
int localx, localy;
trackingGlobals->m_currentTarget->SetCurrentDrag( theDrag );
GetDragMouse( theDrag, &mouse, 0L );
localMouse = mouse;
wxMacGlobalToLocal( theWindow, &localMouse );
localx = localMouse.h;
localy = localMouse.v;
// TODO : should we use client coordinates?
if ( trackingGlobals->m_currentTargetWindow )
trackingGlobals->m_currentTargetWindow->MacRootWindowToWindow( &localx, &localy );
if ( trackingGlobals->m_currentTarget->OnDrop( localx, localy ) )
{
// the option key indicates copy in Mac UI, if it's not pressed do
// move by default if it's allowed at all
wxDragResult
result = !(trackingGlobals->m_flags & wxDrag_AllowMove) ||
(GetCurrentKeyModifiers() & optionKey)
? wxDragCopy
: wxDragMove;
trackingGlobals->m_result =
trackingGlobals->m_currentTarget->OnData( localx, localy, result );
}
}
return noErr;
}
#endif // wxUSE_DRAG_AND_DROP

199
src/osx/carbon/drawer.cpp Normal file
View File

@@ -0,0 +1,199 @@
/////////////////////////////////////////////////////////////////////////////
// Name: drawer.cpp
// Purpose: Drawer child window classes.
// Drawer windows appear under their parent window and
// behave like a drawer, opening and closing to reveal
// content that does not need to be visible at all times.
// Author: Jason Bagley
// Modified by: Ryan Norton (To make it work :), plus bug fixes)
// Created: 2004-30-01
// RCS-ID: $Id$
// Copyright: (c) Jason Bagley; Art & Logic, Inc.
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
#include "wx/wxprec.h"
#include "wx/mac/private.h"
#if defined( __WXMAC__ )
#include "wx/mac/carbon/drawer.h"
IMPLEMENT_DYNAMIC_CLASS(wxDrawerWindow, wxWindow)
// Use constants for now.
// These can be made into member variables and set dynamically.
const int kLeadingOffset = 20;
const int kTrailingOffset = 20;
// Converts Mac window edge constants to wxDirections, wxLEFT, wxRIGHT, etc.
static wxDirection WindowEdgeToDirection(OptionBits edge);
// Convert wxDirections to MAc window edge constants.
static OptionBits DirectionToWindowEdge(wxDirection direction);
wxDrawerWindow::wxDrawerWindow()
{
}
wxDrawerWindow::~wxDrawerWindow()
{
m_isBeingDeleted = TRUE;
this->Show(FALSE);
}
bool wxDrawerWindow::Create(wxWindow *parent,
wxWindowID id, const wxString& title,
wxSize size, wxDirection edge, const wxString& name)
{
wxASSERT_MSG(NULL != parent, wxT("wxDrawerWindows must be attached to a parent window."));
// Constrain the drawer size to the parent window.
const wxSize parentSize(parent->GetClientSize());
if (wxLEFT == edge || wxRIGHT == edge)
{
if (size.GetHeight() > parentSize.GetHeight())
size.SetHeight(parentSize.GetHeight() - (kLeadingOffset + kTrailingOffset));
}
else
{
if (size.GetWidth() > parentSize.GetWidth())
size.SetWidth(parentSize.GetWidth() - (kLeadingOffset + kTrailingOffset));
}
// Create the drawer window.
const wxPoint pos(0, 0);
const wxSize dummySize(0,0);
const long style = wxFRAME_DRAWER;
bool success = wxWindow::Create(parent, id, pos, dummySize, style, name);
if (success)
{
this->MacCreateRealWindow(pos, size, style, name);
success = (m_macWindow != NULL);
}
if (success)
{
// Use drawer brush.
SetBackgroundColour( wxColour( wxMacCreateCGColorFromHITheme( kThemeBrushDrawerBackground ) ) );
::SetThemeWindowBackground((WindowRef)m_macWindow, kThemeBrushDrawerBackground, false);
// Leading and trailing offset are gaps from parent window edges
// to where the drawer starts.
::SetDrawerOffsets((WindowRef)m_macWindow, kLeadingOffset, kTrailingOffset);
// Set the drawers parent.
// Is there a better way to get the parent's WindowRef?
wxTopLevelWindow* tlwParent = wxDynamicCast(parent, wxTopLevelWindow);
if (NULL != tlwParent)
{
OSStatus status = ::SetDrawerParent((WindowRef)m_macWindow,
(WindowRef)tlwParent->MacGetWindowRef());
success = (noErr == status);
}
else
success = false;
}
return success && SetPreferredEdge(edge);
}
wxDirection wxDrawerWindow::GetCurrentEdge() const
{
const OptionBits edge = ::GetDrawerCurrentEdge((WindowRef)m_macWindow);
return WindowEdgeToDirection(edge);
}
wxDirection wxDrawerWindow::GetPreferredEdge() const
{
const OptionBits edge = ::GetDrawerPreferredEdge((WindowRef)m_macWindow);
return WindowEdgeToDirection(edge);
}
bool wxDrawerWindow::IsOpen() const
{
WindowDrawerState state = ::GetDrawerState((WindowRef)m_macWindow);
return (state == kWindowDrawerOpen || state == kWindowDrawerOpening);
}
bool wxDrawerWindow::Open(bool show)
{
static const Boolean kAsynchronous = true;
OSStatus status = noErr;
if (show)
{
const OptionBits preferredEdge = ::GetDrawerPreferredEdge((WindowRef)m_macWindow);
status = ::OpenDrawer((WindowRef)m_macWindow, preferredEdge, kAsynchronous);
}
else
status = ::CloseDrawer((WindowRef)m_macWindow, kAsynchronous);
return (noErr == status);
}
bool wxDrawerWindow::SetPreferredEdge(wxDirection edge)
{
const OSStatus status = ::SetDrawerPreferredEdge((WindowRef)m_macWindow,
DirectionToWindowEdge(edge));
return (noErr == status);
}
OptionBits DirectionToWindowEdge(wxDirection direction)
{
OptionBits edge;
switch (direction)
{
case wxTOP:
edge = kWindowEdgeTop;
break;
case wxBOTTOM:
edge = kWindowEdgeBottom;
break;
case wxRIGHT:
edge = kWindowEdgeRight;
break;
case wxLEFT:
default:
edge = kWindowEdgeLeft;
break;
}
return edge;
}
wxDirection WindowEdgeToDirection(OptionBits edge)
{
wxDirection direction;
switch (edge)
{
case kWindowEdgeTop:
direction = wxTOP;
break;
case kWindowEdgeBottom:
direction = wxBOTTOM;
break;
case kWindowEdgeRight:
direction = wxRIGHT;
break;
case kWindowEdgeDefault: // store current preferred and return that here?
case kWindowEdgeLeft:
default:
direction = wxLEFT;
break;
}
return direction;
}
#endif // defined( __WXMAC__ )

0
src/osx/carbon/dummy.txt Normal file
View File

109
src/osx/carbon/evtloop.cpp Normal file
View File

@@ -0,0 +1,109 @@
///////////////////////////////////////////////////////////////////////////////
// Name: src/mac/carbon/evtloop.cpp
// Purpose: implementation of wxEventLoop for wxMac
// Author: Vadim Zeitlin
// Modified by:
// Created: 2006-01-12
// RCS-ID: $Id$
// Copyright: (c) 2006 Vadim Zeitlin <vadim@wxwindows.org>
// Licence: wxWindows licence
///////////////////////////////////////////////////////////////////////////////
// ============================================================================
// declarations
// ============================================================================
// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------
// for compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#include "wx/evtloop.h"
#ifndef WX_PRECOMP
#include "wx/app.h"
#endif // WX_PRECOMP
#ifdef __DARWIN__
#include <Carbon/Carbon.h>
#else
#include <Carbon.h>
#endif
// ============================================================================
// wxEventLoop implementation
// ============================================================================
// ----------------------------------------------------------------------------
// high level functions for RunApplicationEventLoop() case
// ----------------------------------------------------------------------------
#if wxMAC_USE_RUN_APP_EVENT_LOOP
int wxGUIEventLoop::Run()
{
wxEventLoopActivator activate(this);
RunApplicationEventLoop();
return m_exitcode;
}
void wxGUIEventLoop::Exit(int rc)
{
m_exitcode = rc;
QuitApplicationEventLoop();
OnExit();
}
#else // manual event loop
// ----------------------------------------------------------------------------
// functions only used by wxEventLoopManual-based implementation
// ----------------------------------------------------------------------------
void wxGUIEventLoop::WakeUp()
{
extern void wxMacWakeUp();
wxMacWakeUp();
}
#endif // high/low-level event loop
// ----------------------------------------------------------------------------
// low level functions used in both cases
// ----------------------------------------------------------------------------
bool wxGUIEventLoop::Pending() const
{
EventRef theEvent;
return ReceiveNextEvent
(
0, // we want any event at all so we don't specify neither
NULL, // the number of event types nor the types themselves
kEventDurationNoWait,
false, // don't remove the event from queue
&theEvent
) == noErr;
}
bool wxGUIEventLoop::Dispatch()
{
// TODO: we probably should do the dispatching directly from here but for
// now it's easier to forward to wxApp which has all the code to do
// it
if ( !wxTheApp )
return false;
wxTheApp->MacDoOneEvent();
return true;
}

436
src/osx/carbon/filedlg.cpp Normal file
View File

@@ -0,0 +1,436 @@
/////////////////////////////////////////////////////////////////////////////
// Name: src/mac/carbon/filedlg.cpp
// Purpose: wxFileDialog
// Author: Stefan Csomor
// Modified by:
// Created: 1998-01-01
// RCS-ID: $Id$
// Copyright: (c) Stefan Csomor
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
#include "wx/wxprec.h"
#if wxUSE_FILEDLG
#include "wx/filedlg.h"
#ifndef WX_PRECOMP
#include "wx/intl.h"
#include "wx/app.h"
#include "wx/utils.h"
#include "wx/dialog.h"
#endif
#include "wx/tokenzr.h"
#include "wx/filename.h"
#include "wx/mac/private.h"
#ifndef __DARWIN__
#include <Navigation.h>
#include "PLStringFuncs.h"
#endif
IMPLEMENT_CLASS(wxFileDialog, wxFileDialogBase)
// the data we need to pass to our standard file hook routine
// includes a pointer to the dialog, a pointer to the standard
// file reply record (so we can inspect the current selection)
// and a copy of the "previous" file spec of the reply record
// so we can see if the selection has changed
struct OpenUserDataRec
{
int currentfilter ;
bool saveMode ;
wxArrayString name ;
wxArrayString extensions ;
wxArrayLong filtermactypes ;
wxString defaultLocation;
CFArrayRef menuitems ;
};
typedef struct OpenUserDataRec
OpenUserDataRec, *OpenUserDataRecPtr;
static pascal void NavEventProc(
NavEventCallbackMessage inSelector,
NavCBRecPtr ioParams,
NavCallBackUserData ioUserData );
static NavEventUPP sStandardNavEventFilter = NewNavEventUPP(NavEventProc);
static pascal void NavEventProc(
NavEventCallbackMessage inSelector,
NavCBRecPtr ioParams,
NavCallBackUserData ioUserData )
{
OpenUserDataRec * data = ( OpenUserDataRec *) ioUserData ;
if (inSelector == kNavCBEvent)
{
}
else if ( inSelector == kNavCBStart )
{
if (data && !(data->defaultLocation).empty())
{
// Set default location for the modern Navigation APIs
// Apple Technical Q&A 1151
FSRef theFile;
wxMacPathToFSRef(data->defaultLocation, &theFile);
AEDesc theLocation = { typeNull, NULL };
if (noErr == ::AECreateDesc(typeFSRef, &theFile, sizeof(FSRef), &theLocation))
::NavCustomControl(ioParams->context, kNavCtlSetLocation, (void *) &theLocation);
}
if( data->extensions.GetCount() > 0 )
{
NavMenuItemSpec menuItem;
memset( &menuItem, 0, sizeof(menuItem) );
menuItem.version = kNavMenuItemSpecVersion;
menuItem.menuType = data->currentfilter;
::NavCustomControl(ioParams->context, kNavCtlSelectCustomType, &menuItem);
}
}
else if ( inSelector == kNavCBPopupMenuSelect )
{
NavMenuItemSpec * menu = (NavMenuItemSpec *) ioParams->eventData.eventDataParms.param ;
const size_t numFilters = data->extensions.GetCount();
if ( menu->menuType < numFilters )
{
data->currentfilter = menu->menuType ;
if ( data->saveMode )
{
int i = menu->menuType ;
// isolate the first extension string
wxString firstExtension = data->extensions[i].BeforeFirst('|').BeforeFirst(';');
wxString extension = firstExtension.AfterLast('.') ;
wxString sfilename ;
wxCFStringRef cfString( wxCFRetain( NavDialogGetSaveFileName( ioParams->context ) ) );
sfilename = cfString.AsString() ;
int pos = sfilename.Find('.', true) ;
if ( pos != wxNOT_FOUND && extension != wxT("*") )
{
sfilename = sfilename.Left(pos+1)+extension ;
cfString = wxCFStringRef( sfilename , wxFONTENCODING_DEFAULT ) ;
NavDialogSetSaveFileName( ioParams->context , cfString ) ;
}
}
}
}
}
void MakeUserDataRec(OpenUserDataRec *myData , const wxString& filter )
{
myData->menuitems = NULL ;
myData->currentfilter = 0 ;
myData->saveMode = false ;
if ( !filter.empty() )
{
wxString filter2(filter) ;
int filterIndex = 0;
bool isName = true ;
wxString current ;
for ( unsigned int i = 0; i < filter2.length() ; i++ )
{
if ( filter2.GetChar(i) == wxT('|') )
{
if ( isName )
{
myData->name.Add( current ) ;
}
else
{
myData->extensions.Add( current ) ;
++filterIndex ;
}
isName = !isName ;
current = wxEmptyString ;
}
else
{
current += filter2.GetChar(i) ;
}
}
// we allow for compatibility reason to have a single filter expression (like *.*) without
// an explanatory text, in that case the first part is name and extension at the same time
wxASSERT_MSG( filterIndex == 0 || !isName , wxT("incorrect format of format string") ) ;
if ( current.empty() )
myData->extensions.Add( myData->name[filterIndex] ) ;
else
myData->extensions.Add( current ) ;
if ( filterIndex == 0 || isName )
myData->name.Add( current ) ;
++filterIndex ;
const size_t extCount = myData->extensions.GetCount();
for ( size_t i = 0 ; i < extCount; i++ )
{
wxUint32 fileType, creator;
wxString extension = myData->extensions[i];
// Remove leading '*'
if (extension.length() && (extension.GetChar(0) == '*'))
extension = extension.Mid( 1 );
// Remove leading '.'
if (extension.length() && (extension.GetChar(0) == '.'))
extension = extension.Mid( 1 );
if (wxFileName::MacFindDefaultTypeAndCreator( extension, &fileType, &creator ))
myData->filtermactypes.Add( (OSType)fileType );
else
myData->filtermactypes.Add( '****' ); // We'll fail safe if it's not recognized
}
}
}
static Boolean CheckFile( const wxString &filename , OSType type , OpenUserDataRecPtr data)
{
wxString file(filename) ;
file.MakeUpper() ;
if ( data->extensions.GetCount() > 0 )
{
//for ( int i = 0 ; i < data->numfilters ; ++i )
int i = data->currentfilter ;
if ( data->extensions[i].Right(2) == wxT(".*") )
return true ;
{
if ( type == (OSType)data->filtermactypes[i] )
return true ;
wxStringTokenizer tokenizer( data->extensions[i] , wxT(";") ) ;
while ( tokenizer.HasMoreTokens() )
{
wxString extension = tokenizer.GetNextToken() ;
if ( extension.GetChar(0) == '*' )
extension = extension.Mid(1) ;
extension.MakeUpper();
if ( file.length() >= extension.length() && extension == file.Right(extension.length() ) )
return true ;
}
}
return false ;
}
return true ;
}
// end wxmac
wxFileDialog::wxFileDialog(
wxWindow *parent, const wxString& message,
const wxString& defaultDir, const wxString& defaultFileName, const wxString& wildCard,
long style, const wxPoint& pos, const wxSize& sz, const wxString& name)
: wxFileDialogBase(parent, message, defaultDir, defaultFileName, wildCard, style, pos, sz, name)
{
wxASSERT_MSG( NavServicesAvailable() , wxT("Navigation Services are not running") ) ;
}
pascal Boolean CrossPlatformFilterCallback(
AEDesc *theItem,
void *info,
void *callBackUD,
NavFilterModes filterMode )
{
OpenUserDataRecPtr data = (OpenUserDataRecPtr) callBackUD ;
if (filterMode == kNavFilteringBrowserList)
{
// We allow navigation to all folders. For files, we check against the current
// filter string.
// However, packages should be dealt with like files and not like folders. So
// check if a folder is a package before deciding what to do.
NavFileOrFolderInfo* theInfo = (NavFileOrFolderInfo*) info ;
FSRef fsref;
if ( theInfo->isFolder )
{
// check bundle bit (using Finder Services - used by OS9 on some bundles)
FSCatalogInfo catalogInfo;
if (FSGetCatalogInfo (&fsref, kFSCatInfoFinderInfo, &catalogInfo, NULL, NULL, NULL) != noErr)
return true;
// Check bundle item (using Launch Services - used by OS-X through info.plist or APP)
LSItemInfoRecord lsInfo;
if (LSCopyItemInfoForRef(&fsref, kLSRequestBasicFlagsOnly, &lsInfo ) != noErr)
return true;
// If it's not a bundle, then it's a normal folder and it passes our filter
FileInfo *fileInfo = (FileInfo *) catalogInfo.finderInfo;
if ( !(fileInfo->finderFlags & kHasBundle) &&
!(lsInfo.flags & (kLSItemInfoIsApplication | kLSItemInfoIsPackage)) )
return true;
}
else
{
AECoerceDesc (theItem, typeFSRef, theItem);
if ( AEGetDescData (theItem, &fsref, sizeof (FSRef)) == noErr)
{
wxString file = wxMacFSRefToPath( &fsref ) ;
return CheckFile( file , theInfo->fileAndFolder.fileInfo.finderInfo.fdType , data ) ;
}
}
}
return true;
}
int wxFileDialog::ShowModal()
{
OSErr err;
NavDialogCreationOptions dialogCreateOptions;
// set default options
::NavGetDefaultDialogCreationOptions(&dialogCreateOptions);
// this was always unset in the old code
dialogCreateOptions.optionFlags &= ~kNavSelectDefaultLocation;
wxCFStringRef message(m_message, GetFont().GetEncoding());
dialogCreateOptions.windowTitle = message;
wxCFStringRef defaultFileName(m_fileName, GetFont().GetEncoding());
dialogCreateOptions.saveFileName = defaultFileName;
NavDialogRef dialog;
NavObjectFilterUPP navFilterUPP = NULL;
OpenUserDataRec myData;
myData.defaultLocation = m_dir;
MakeUserDataRec(&myData , m_wildCard);
myData.currentfilter = m_filterIndex;
size_t numFilters = myData.extensions.GetCount();
if (numFilters)
{
CFMutableArrayRef popup = CFArrayCreateMutable( kCFAllocatorDefault ,
numFilters , &kCFTypeArrayCallBacks ) ;
dialogCreateOptions.popupExtension = popup ;
myData.menuitems = dialogCreateOptions.popupExtension ;
for ( size_t i = 0 ; i < numFilters ; ++i )
{
CFArrayAppendValue( popup , (CFStringRef) wxCFStringRef( myData.name[i] , GetFont().GetEncoding() ) ) ;
}
}
if (HasFdFlag(wxFD_SAVE))
{
myData.saveMode = true;
dialogCreateOptions.optionFlags |= kNavDontAutoTranslate;
dialogCreateOptions.optionFlags |= kNavDontAddTranslateItems;
if (!numFilters)
dialogCreateOptions.optionFlags |= kNavNoTypePopup;
// The extension is important
if (numFilters < 2)
dialogCreateOptions.optionFlags |= kNavPreserveSaveFileExtension;
if (!(m_windowStyle & wxFD_OVERWRITE_PROMPT))
dialogCreateOptions.optionFlags |= kNavDontConfirmReplacement;
err = ::NavCreatePutFileDialog(
&dialogCreateOptions,
kNavGenericSignature, // Suppresses the 'Default' (top) menu item
kNavGenericSignature,
sStandardNavEventFilter,
&myData, // for defaultLocation
&dialog );
}
else
{
// let the user select bundles/programs in dialogs
dialogCreateOptions.optionFlags |= kNavSupportPackages;
navFilterUPP = NewNavObjectFilterUPP(CrossPlatformFilterCallback);
err = ::NavCreateGetFileDialog(
&dialogCreateOptions,
NULL, // NavTypeListHandle
sStandardNavEventFilter,
NULL, // NavPreviewUPP
navFilterUPP,
(void *) &myData, // inClientData
&dialog );
}
if (err == noErr)
err = ::NavDialogRun(dialog);
// clean up filter related data, etc.
if (navFilterUPP)
::DisposeNavObjectFilterUPP(navFilterUPP);
if (err != noErr)
{
::NavDialogDispose(dialog);
return wxID_CANCEL;
}
NavReplyRecord navReply;
err = ::NavDialogGetReply(dialog, &navReply);
if (err == noErr && navReply.validRecord)
{
AEKeyword theKeyword;
DescType actualType;
Size actualSize;
FSRef theFSRef;
wxString thePath ;
long count;
m_filterIndex = myData.currentfilter;
::AECountItems( &navReply.selection, &count );
for (long i = 1; i <= count; ++i)
{
err = ::AEGetNthPtr(
&(navReply.selection), i, typeFSRef, &theKeyword, &actualType,
&theFSRef, sizeof(theFSRef), &actualSize );
if (err != noErr)
break;
if (HasFdFlag(wxFD_SAVE))
thePath = wxMacFSRefToPath( &theFSRef, navReply.saveFileName );
else
thePath = wxMacFSRefToPath( &theFSRef );
if (!thePath)
{
::NavDisposeReply(&navReply);
::NavDialogDispose(dialog);
return wxID_CANCEL;
}
m_path = thePath;
m_paths.Add(m_path);
m_fileName = wxFileNameFromPath(m_path);
m_fileNames.Add(m_fileName);
}
// set these to the first hit
m_path = m_paths[0];
m_fileName = wxFileNameFromPath(m_path);
m_dir = wxPathOnly(m_path);
}
::NavDisposeReply(&navReply);
::NavDialogDispose(dialog);
return (err == noErr) ? wxID_OK : wxID_CANCEL;
}
#endif // wxUSE_FILEDLG

1021
src/osx/carbon/font.cpp Normal file

File diff suppressed because it is too large Load Diff

828
src/osx/carbon/fontdlg.cpp Normal file
View File

@@ -0,0 +1,828 @@
/////////////////////////////////////////////////////////////////////////////
// Name: src/mac/carbon/fontdlg.cpp
// Purpose: wxFontDialog class for carbon 10.2+.
// Author: Ryan Norton
// Modified by:
// Created: 1998-01-01
// RCS-ID: $Id$
// Copyright: (c) Ryan Norton
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
// ===========================================================================
// declarations
// ===========================================================================
// ---------------------------------------------------------------------------
// headers
// ---------------------------------------------------------------------------
// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"
#if wxUSE_FONTDLG
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#ifndef WX_PRECOMP
#include "wx/intl.h"
#include "wx/crt.h"
#include "wx/dcclient.h"
#include "wx/frame.h"
#include "wx/textctrl.h"
#include "wx/listbox.h"
#include "wx/checkbox.h"
#include "wx/choice.h"
#include "wx/sizer.h"
#include "wx/stattext.h"
#include "wx/button.h"
#endif
#include "wx/fontdlg.h"
#if wxMAC_USE_EXPERIMENTAL_FONTDIALOG
IMPLEMENT_DYNAMIC_CLASS(wxFontDialog, wxDialog)
#include "wx/mac/uma.h"
// ---------------------------------------------------------------------------
// wxFontDialog
// ---------------------------------------------------------------------------
static const EventTypeSpec eventList[] =
{
{ kEventClassFont, kEventFontSelection } ,
} ;
pascal OSStatus
wxMacCarbonFontPanelHandler(EventHandlerCallRef WXUNUSED(nextHandler),
EventRef event,
void *userData)
{
OSStatus result = eventNotHandledErr ;
wxFontDialog *fontdialog = (wxFontDialog*) userData ;
wxFontData& fontdata= fontdialog->GetFontData() ;
wxMacCarbonEvent cEvent( event );
switch(cEvent.GetKind())
{
case kEventFontSelection :
{
bool setup = false ;
#if wxMAC_USE_CORE_TEXT
if ( UMAGetSystemVersion() >= 0x1050 )
{
CTFontDescriptorRef descr;
if ( cEvent.GetParameter<CTFontDescriptorRef>( kEventParamCTFontDescriptor, typeCTFontDescriptorRef, &descr ) == noErr )
{
wxFont font;
font.MacCreateFromCTFontDescriptor(descr);
fontdata.SetChosenFont( font ) ;
setup = true;
}
}
#endif
#if wxMAC_USE_ATSU_TEXT
ATSUFontID fontId = 0 ;
if ( !setup && (cEvent.GetParameter<ATSUFontID>(kEventParamATSUFontID, &fontId) == noErr) )
{
FMFontStyle fontStyle = cEvent.GetParameter<FMFontStyle>(kEventParamFMFontStyle);
FMFontSize fontSize = cEvent.GetParameter<FMFontSize>(kEventParamFMFontSize);
CFStringRef cfName = NULL;
#if 1
FMFontFamily fontFamily = cEvent.GetParameter<FMFontFamily>(kEventParamFMFontFamily);
ATSFontFamilyRef atsfontfamilyref = FMGetATSFontFamilyRefFromFontFamily( fontFamily ) ;
OSStatus err = ATSFontFamilyGetName( atsfontfamilyref , kATSOptionFlagsDefault , &cfName ) ;
if ( err == noErr )
{
wxFAIL_MSG("ATSFontFamilyGetName failed");
}
#else
// we don't use the ATSU naming anymore
ByteCount actualLength = 0;
char *c = NULL;
OSStatus err = ATSUFindFontName(fontId , kFontFamilyName, kFontUnicodePlatform, kFontNoScriptCode,
kFontNoLanguageCode , 0 , NULL , &actualLength , NULL );
if ( err == noErr)
{
actualLength += 1 ;
char *c = (char*)malloc( actualLength );
err = ATSUFindFontName(fontId, kFontFamilyName, kFontUnicodePlatform, kFontNoScriptCode,
kFontNoLanguageCode, actualLength, c , NULL, NULL);
cfName = CFStringCreateWithCharacters(NULL, (UniChar*) c, (actualLength-1) >> 1);
}
else
{
err = ATSUFindFontName(fontId , kFontFamilyName, kFontNoPlatformCode, kFontNoScriptCode,
kFontNoLanguageCode , 0 , NULL , &actualLength , NULL );
if ( err == noErr )
{
actualLength += 1 ;
c = (char*)malloc(actualLength);
err = ATSUFindFontName(fontId, kFontFamilyName, kFontNoPlatformCode, kFontNoScriptCode,
kFontNoLanguageCode, actualLength, c , NULL, NULL);
c[actualLength-1] = 0;
cfName = CFStringCreateWithCString(NULL, c, kCFStringEncodingMacRoman );
}
}
if ( c!=NULL )
free(c);
#endif
if ( cfName!=NULL )
{
fontdata.m_chosenFont.SetFaceName(wxCFStringRef(cfName).AsString(wxLocale::GetSystemEncoding()));
fontdata.m_chosenFont.SetPointSize(fontSize);
fontdata.m_chosenFont.SetStyle(fontStyle & italic ? wxFONTSTYLE_ITALIC : wxFONTSTYLE_NORMAL);
fontdata.m_chosenFont.SetUnderlined((fontStyle & underline)!=0);
fontdata.m_chosenFont.SetWeight(fontStyle & bold ? wxFONTWEIGHT_BOLD : wxFONTWEIGHT_NORMAL);
}
}
#endif // wxMAC_USE_ATSU_TEXT
// retrieving the color
RGBColor fontColor ;
if ( cEvent.GetParameter<RGBColor>(kEventParamFontColor, &fontColor) == noErr )
{
fontdata.m_fontColour = fontColor;
}
else
{
CFDictionaryRef dict ;
if ( cEvent.GetParameter<CFDictionaryRef>(kEventParamDictionary, &dict) == noErr )
{
CFDictionaryRef attributesDict ;
if ( CFDictionaryGetValueIfPresent(dict, kFontPanelAttributesKey, (const void **)&attributesDict) )
{
CFDataRef tagsData;
CFDataRef sizesData;
CFDataRef valuesData;
if ( CFDictionaryGetValueIfPresent(attributesDict, kFontPanelAttributeTagsKey, (const void **)&tagsData) &&
CFDictionaryGetValueIfPresent(attributesDict, kFontPanelAttributeSizesKey, (const void **)&sizesData) &&
CFDictionaryGetValueIfPresent(attributesDict, kFontPanelAttributeValuesKey, (const void **)&valuesData) )
{
ItemCount count = CFDataGetLength(tagsData)/sizeof(ATSUAttributeTag);
ATSUAttributeTag *tagPtr = (ATSUAttributeTag *)CFDataGetBytePtr(tagsData);
ByteCount *sizePtr = (ByteCount *)CFDataGetBytePtr(sizesData);
UInt32 *bytePtr = (UInt32*)CFDataGetBytePtr(valuesData);
ATSUAttributeValuePtr valuesPtr = bytePtr ;
for ( ItemCount i = 0 ; i < count ; ++i)
{
if ( tagPtr[i] == kATSUColorTag && sizePtr[i] == sizeof(RGBColor))
{
fontdata.m_fontColour = *(RGBColor *)valuesPtr;
break ;
}
bytePtr = (UInt32*)( (UInt8*)bytePtr + sizePtr[i]);
}
}
}
}
}
}
break ;
}
return result ;
}
DEFINE_ONE_SHOT_HANDLER_GETTER( wxMacCarbonFontPanelHandler )
wxFontDialog::wxFontDialog()
{
}
wxFontDialog::wxFontDialog(wxWindow *parent, const wxFontData& data)
{
Create(parent, data);
}
wxFontDialog::~wxFontDialog()
{
}
bool wxFontDialog::Create(wxWindow *WXUNUSED(parent), const wxFontData& data)
{
m_fontData = data;
return true ;
}
int wxFontDialog::ShowModal()
{
OSStatus err ;
wxFont font = *wxNORMAL_FONT ;
if ( m_fontData.m_initialFont.Ok() )
{
font = m_fontData.m_initialFont ;
}
bool setup = false;
#if wxMAC_USE_CORE_TEXT
if ( UMAGetSystemVersion() >= 0x1050 )
{
CTFontDescriptorRef descr = (CTFontDescriptorRef)font.MacGetCTFontDescriptor();
err = SetFontInfoForSelection (kFontSelectionCoreTextType,1, &descr , NULL);
setup = true;
}
#endif
#if wxMAC_USE_ATSU_TEXT
if ( !setup )
{
ATSUStyle style = (ATSUStyle)font.MacGetATSUStyle();
err = SetFontInfoForSelection (kFontSelectionATSUIType,1, &style , NULL);
setup = true;
}
#endif
// just clicking on ENTER will not send us any font setting event, therefore we have to make sure
// that field is already correct
m_fontData.m_chosenFont = font ;
EventHandlerRef handler ;
err = InstallApplicationEventHandler( GetwxMacCarbonFontPanelHandlerUPP(), GetEventTypeCount(eventList), eventList, this , &handler );
if ( !FPIsFontPanelVisible() )
FPShowHideFontPanel();
int retval = RunMixedFontDialog(this);
::RemoveEventHandler(handler);
return retval ;
}
#else
#if !USE_NATIVE_FONT_DIALOG_FOR_MACOSX
#undef wxFontDialog
#include "wx/mac/fontdlg.h"
#include "wx/fontenum.h"
#include "wx/colordlg.h"
#include "wx/spinctrl.h"
// ---------------------------------------------------------------------------
// wxFontDialog stub for mac OS's without a native font dialog
// ---------------------------------------------------------------------------
static const wxChar *FontFamilyIntToString(int family);
static int FontFamilyStringToInt(const wxChar *family);
//-----------------------------------------------------------------------------
// helper class - wxFontPreviewCtrl
//-----------------------------------------------------------------------------
class WXDLLEXPORT wxFontPreviewCtrl : public wxWindow
{
public:
wxFontPreviewCtrl(wxWindow *parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& sz = wxDefaultSize, long style = 0) :
wxWindow(parent, id, pos, sz, style)
{
SetBackgroundColour(*wxWHITE);
}
private:
void OnPaint(wxPaintEvent& event);
DECLARE_EVENT_TABLE()
};
BEGIN_EVENT_TABLE(wxFontPreviewCtrl, wxWindow)
EVT_PAINT(wxFontPreviewCtrl::OnPaint)
END_EVENT_TABLE()
void wxFontPreviewCtrl::OnPaint(wxPaintEvent& WXUNUSED(event))
{
wxPaintDC dc(this);
wxSize size = GetSize();
wxFont font = GetFont();
if ( font.Ok() )
{
dc.SetFont(font);
// Calculate vertical centre
long w = 0, h = 0;
dc.GetTextExtent( wxT("X"), &w, &h);
dc.SetTextForeground(GetForegroundColour());
dc.SetClippingRegion(2, 2, size.x-4, size.y-4);
dc.DrawText(_("ABCDEFGabcdefg12345"),
10, size.y/2 - h/2);
dc.DestroyClippingRegion();
}
}
/*
* A control for displaying a small preview of a colour or bitmap
*/
class wxFontColourSwatchCtrl: public wxControl
{
DECLARE_CLASS(wxFontColourSwatchCtrl)
public:
wxFontColourSwatchCtrl(wxWindow* parent, wxWindowID id, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = 0);
virtual ~wxFontColourSwatchCtrl();
void OnPaint(wxPaintEvent& event);
void OnMouseEvent(wxMouseEvent& event);
void SetColour(const wxColour& colour) { m_colour = colour; SetBackgroundColour(m_colour); }
wxColour& GetColour() { return m_colour; }
virtual wxSize DoGetBestSize() const { return GetSize(); }
protected:
wxColour m_colour;
DECLARE_EVENT_TABLE()
};
/*
* A control for displaying a small preview of a colour or bitmap
*/
BEGIN_EVENT_TABLE(wxFontColourSwatchCtrl, wxControl)
EVT_MOUSE_EVENTS(wxFontColourSwatchCtrl::OnMouseEvent)
END_EVENT_TABLE()
IMPLEMENT_CLASS(wxFontColourSwatchCtrl, wxControl)
wxFontColourSwatchCtrl::wxFontColourSwatchCtrl(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style):
wxControl(parent, id, pos, size, style)
{
SetColour(* wxWHITE);
SetBackgroundStyle(wxBG_STYLE_COLOUR);
}
wxFontColourSwatchCtrl::~wxFontColourSwatchCtrl()
{
}
void wxFontColourSwatchCtrl::OnMouseEvent(wxMouseEvent& event)
{
if (event.LeftDown())
{
wxWindow* parent = GetParent();
while (parent != NULL && !parent->IsKindOf(CLASSINFO(wxDialog)) && !parent->IsKindOf(CLASSINFO(wxFrame)))
parent = parent->GetParent();
wxColourData data;
data.SetChooseFull(true);
data.SetColour(m_colour);
wxColourDialog *dialog = new wxColourDialog(parent, &data);
// Crashes on wxMac (no m_peer)
#ifndef __WXMAC__
dialog->SetTitle(_("Background colour"));
#endif
if (dialog->ShowModal() == wxID_OK)
{
wxColourData retData = dialog->GetColourData();
m_colour = retData.GetColour();
SetBackgroundColour(m_colour);
}
dialog->Destroy();
Refresh();
wxCommandEvent event(wxEVT_COMMAND_BUTTON_CLICKED, GetId());
HandleWindowEvent(event);
}
}
/*!
* wxFontDialog type definition
*/
IMPLEMENT_DYNAMIC_CLASS( wxFontDialog, wxDialog )
/*!
* wxFontDialog event table definition
*/
BEGIN_EVENT_TABLE( wxFontDialog, wxDialog )
EVT_LISTBOX( wxID_FONTDIALOG_FACENAME, wxFontDialog::OnFontdialogFacenameSelected )
EVT_SPINCTRL( wxID_FONTDIALOG_FONTSIZE, wxFontDialog::OnFontdialogFontsizeUpdated )
EVT_TEXT( wxID_FONTDIALOG_FONTSIZE, wxFontDialog::OnFontdialogFontsizeTextUpdated )
EVT_CHECKBOX( wxID_FONTDIALOG_BOLD, wxFontDialog::OnFontdialogBoldClick )
EVT_CHECKBOX( wxID_FONTDIALOG_ITALIC, wxFontDialog::OnFontdialogItalicClick )
EVT_CHECKBOX( wxID_FONTDIALOG_UNDERLINED, wxFontDialog::OnFontdialogUnderlinedClick )
EVT_BUTTON( wxID_OK, wxFontDialog::OnOkClick )
EVT_BUTTON(wxID_FONTDIALOG_COLOUR, wxFontDialog::OnColourChanged)
END_EVENT_TABLE()
/*!
* wxFontDialog constructors
*/
wxFontDialog::wxFontDialog( )
{
m_dialogParent = NULL;
}
wxFontDialog::wxFontDialog(wxWindow* parent, const wxFontData& fontData)
{
m_dialogParent = NULL;
Create(parent, fontData);
}
wxFontDialog::~wxFontDialog()
{
// empty
}
/*!
* wxFontDialog creator
*/
bool wxFontDialog::Create(wxWindow* parent, const wxFontData& fontData)
{
m_fontData = fontData;
m_suppressUpdates = false;
wxString caption = _("Font");
m_facenameCtrl = NULL;
m_sizeCtrl = NULL;
m_boldCtrl = NULL;
m_italicCtrl = NULL;
m_underlinedCtrl = NULL;
m_colourCtrl = NULL;
m_previewCtrl = NULL;
InitializeFont();
SetExtraStyle(GetExtraStyle()|wxWS_EX_BLOCK_EVENTS);
wxDialog::Create( parent, wxID_ANY, caption, wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER );
CreateControls();
GetSizer()->Fit(this);
GetSizer()->SetSizeHints(this);
Centre();
return true;
}
/*!
* Control creation for wxFontDialog
*/
void wxFontDialog::CreateControls()
{
wxFontDialog* itemDialog1 = this;
wxBoxSizer* itemBoxSizer2 = new wxBoxSizer(wxVERTICAL);
itemDialog1->SetSizer(itemBoxSizer2);
wxBoxSizer* itemBoxSizer3 = new wxBoxSizer(wxVERTICAL);
itemBoxSizer2->Add(itemBoxSizer3, 1, wxGROW|wxALL, 5);
wxFlexGridSizer* itemFlexGridSizer4 = new wxFlexGridSizer(6, 2, 10, 0);
itemFlexGridSizer4->AddGrowableRow(4);
itemFlexGridSizer4->AddGrowableCol(1);
itemBoxSizer3->Add(itemFlexGridSizer4, 1, wxGROW|wxALL, 5);
wxStaticText* itemStaticText5 = new wxStaticText( itemDialog1, wxID_STATIC, _("Font:"), wxDefaultPosition, wxDefaultSize, 0 );
itemFlexGridSizer4->Add(itemStaticText5, 0, wxALIGN_RIGHT|wxALIGN_TOP|wxALL, 5);
wxBoxSizer* itemBoxSizer6 = new wxBoxSizer(wxVERTICAL);
itemFlexGridSizer4->Add(itemBoxSizer6, 0, wxGROW|wxGROW, 5);
wxString* m_facenameCtrlStrings = NULL;
m_facenameCtrl = new wxListBox( itemDialog1, wxID_FONTDIALOG_FACENAME, wxDefaultPosition, wxSize(320, 100), 0, m_facenameCtrlStrings, wxLB_SINGLE );
itemBoxSizer6->Add(m_facenameCtrl, 0, wxGROW|wxALL, 5);
wxStaticText* itemStaticText8 = new wxStaticText( itemDialog1, wxID_STATIC, _("Size:"), wxDefaultPosition, wxDefaultSize, 0 );
itemFlexGridSizer4->Add(itemStaticText8, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxALL, 5);
m_sizeCtrl = new wxSpinCtrl( itemDialog1, wxID_FONTDIALOG_FONTSIZE, _T("12"), wxDefaultPosition, wxSize(60, -1), wxSP_ARROW_KEYS, 1, 300, 12 );
m_sizeCtrl->SetHelpText(_("The font size in points."));
if (ShowToolTips())
m_sizeCtrl->SetToolTip(_("The font size in points."));
itemFlexGridSizer4->Add(m_sizeCtrl, 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxALL, 5);
wxStaticText* itemStaticText10 = new wxStaticText( itemDialog1, wxID_STATIC, _("Style:"), wxDefaultPosition, wxDefaultSize, 0 );
itemFlexGridSizer4->Add(itemStaticText10, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxALL, 5);
wxBoxSizer* itemBoxSizer11 = new wxBoxSizer(wxHORIZONTAL);
itemFlexGridSizer4->Add(itemBoxSizer11, 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL, 5);
m_boldCtrl = new wxCheckBox( itemDialog1, wxID_FONTDIALOG_BOLD, _("Bold"), wxDefaultPosition, wxDefaultSize, wxCHK_2STATE );
m_boldCtrl->SetValue(false);
m_boldCtrl->SetHelpText(_("Check to make the font bold."));
if (ShowToolTips())
m_boldCtrl->SetToolTip(_("Check to make the font bold."));
itemBoxSizer11->Add(m_boldCtrl, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
m_italicCtrl = new wxCheckBox( itemDialog1, wxID_FONTDIALOG_ITALIC, _("Italic"), wxDefaultPosition, wxDefaultSize, wxCHK_2STATE );
m_italicCtrl->SetValue(false);
m_italicCtrl->SetHelpText(_("Check to make the font italic."));
if (ShowToolTips())
m_italicCtrl->SetToolTip(_("Check to make the font italic."));
itemBoxSizer11->Add(m_italicCtrl, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
if (m_fontData.GetEnableEffects())
{
m_underlinedCtrl = new wxCheckBox( itemDialog1, wxID_FONTDIALOG_UNDERLINED, _("Underlined"), wxDefaultPosition, wxDefaultSize, wxCHK_2STATE );
m_underlinedCtrl->SetValue(false);
m_underlinedCtrl->SetHelpText(_("Check to make the font underlined."));
if (ShowToolTips())
m_underlinedCtrl->SetToolTip(_("Check to make the font underlined."));
itemBoxSizer11->Add(m_underlinedCtrl, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
}
if (m_fontData.GetEnableEffects())
{
wxStaticText* itemStaticText15 = new wxStaticText( itemDialog1, wxID_STATIC, _("Colour:"), wxDefaultPosition, wxDefaultSize, 0 );
itemFlexGridSizer4->Add(itemStaticText15, 0, wxALIGN_RIGHT|wxALIGN_TOP|wxALL, 5);
m_colourCtrl = new wxFontColourSwatchCtrl( itemDialog1, wxID_FONTDIALOG_COLOUR, wxDefaultPosition, wxSize(-1, 30), wxSUNKEN_BORDER|wxTAB_TRAVERSAL );
m_colourCtrl->SetHelpText(_("Click to change the font colour."));
if (ShowToolTips())
m_colourCtrl->SetToolTip(_("Click to change the font colour."));
itemFlexGridSizer4->Add(m_colourCtrl, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 5);
}
wxStaticText* itemStaticText17 = new wxStaticText( itemDialog1, wxID_STATIC, _("Preview:"), wxDefaultPosition, wxDefaultSize, 0 );
itemFlexGridSizer4->Add(itemStaticText17, 0, wxALIGN_RIGHT|wxALIGN_TOP|wxALL, 5);
m_previewCtrl = new wxFontPreviewCtrl( itemDialog1, wxID_FONTDIALOG_PREVIEW, wxDefaultPosition, wxSize(-1, 70), wxSUNKEN_BORDER|wxTAB_TRAVERSAL );
m_previewCtrl->SetHelpText(_("Shows a preview of the font."));
if (ShowToolTips())
m_previewCtrl->SetToolTip(_("Shows a preview of the font."));
itemFlexGridSizer4->Add(m_previewCtrl, 1, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 5);
wxBoxSizer* itemBoxSizer19 = new wxBoxSizer(wxHORIZONTAL);
itemBoxSizer3->Add(itemBoxSizer19, 0, wxALIGN_RIGHT|wxALL, 5);
wxButton* itemButton20 = new wxButton( itemDialog1, wxID_CANCEL, _("&Cancel"), wxDefaultPosition, wxDefaultSize, 0 );
itemButton20->SetHelpText(_("Click to cancel changes to the font."));
if (ShowToolTips())
itemButton20->SetToolTip(_("Click to cancel changes to the font."));
itemBoxSizer19->Add(itemButton20, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
wxButton* itemButton21 = new wxButton( itemDialog1, wxID_OK, _("&OK"), wxDefaultPosition, wxDefaultSize, 0 );
itemButton21->SetDefault();
itemButton21->SetHelpText(_("Click to confirm changes to the font."));
if (ShowToolTips())
itemButton21->SetToolTip(_("Click to confirm changes to the font."));
itemBoxSizer19->Add(itemButton21, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
wxFontEnumerator enumerator;
enumerator.EnumerateFacenames();
wxArrayString facenames = enumerator.GetFacenames();
if (facenames)
{
facenames.Add(_("<Any>"));
facenames.Add(_("<Any Roman>"));
facenames.Add(_("<Any Decorative>"));
facenames.Add(_("<Any Modern>"));
facenames.Add(_("<Any Script>"));
facenames.Add(_("<Any Swiss>"));
facenames.Add(_("<Any Teletype>"));
facenames.Sort();
m_facenameCtrl->Append(facenames);
}
InitializeControls();
m_previewCtrl->SetFont(m_dialogFont);
if (m_fontData.GetColour().Ok())
{
m_previewCtrl->SetForegroundColour(m_fontData.GetColour());
}
m_previewCtrl->Refresh();
}
/*!
* wxEVT_COMMAND_SPINCTRL_UPDATED event handler for wxID_FONTDIALOG_FONTSIZE
*/
void wxFontDialog::OnFontdialogFontsizeUpdated( wxSpinEvent& WXUNUSED(event) )
{
ChangeFont();
}
/*!
* wxEVT_COMMAND_TEXT_UPDATED event handler for wxID_FONTDIALOG_FONTSIZE
*/
void wxFontDialog::OnFontdialogFontsizeTextUpdated( wxCommandEvent& WXUNUSED(event) )
{
ChangeFont();
}
/*!
* wxEVT_COMMAND_CHECKBOX_CLICKED event handler for wxID_FONTDIALOG_BOLD
*/
void wxFontDialog::OnFontdialogBoldClick( wxCommandEvent& WXUNUSED(event) )
{
ChangeFont();
}
/*!
* wxEVT_COMMAND_CHECKBOX_CLICKED event handler for wxID_FONTDIALOG_ITALIC
*/
void wxFontDialog::OnFontdialogItalicClick( wxCommandEvent& WXUNUSED(event) )
{
ChangeFont();
}
/*!
* wxEVT_COMMAND_CHECKBOX_CLICKED event handler for wxID_FONTDIALOG_UNDERLINED
*/
void wxFontDialog::OnFontdialogUnderlinedClick( wxCommandEvent& WXUNUSED(event) )
{
ChangeFont();
}
/*!
* wxEVT_COMMAND_BUTTON_CLICKED event handler for wxID_OK
*/
void wxFontDialog::OnOkClick( wxCommandEvent& event )
{
event.Skip();
}
/*!
* wxEVT_COMMAND_LISTBOX_SELECTED event handler for wxID_FONTDIALOG_FACENAME
*/
void wxFontDialog::OnFontdialogFacenameSelected( wxCommandEvent& WXUNUSED(event) )
{
ChangeFont();
}
void wxFontDialog::OnColourChanged(wxCommandEvent & WXUNUSED(event))
{
m_fontData.SetColour(m_colourCtrl->GetColour());
m_previewCtrl->SetForegroundColour(m_colourCtrl->GetColour());
m_previewCtrl->Refresh();
}
/*!
* Should we show tooltips?
*/
bool wxFontDialog::ShowToolTips()
{
return true;
}
void wxFontDialog::InitializeFont()
{
int fontFamily = wxSWISS;
int fontWeight = wxNORMAL;
int fontStyle = wxNORMAL;
int fontSize = 12;
bool fontUnderline = false;
wxString fontName;
if (m_fontData.m_initialFont.Ok())
{
fontFamily = m_fontData.m_initialFont.GetFamily();
fontWeight = m_fontData.m_initialFont.GetWeight();
fontStyle = m_fontData.m_initialFont.GetStyle();
fontSize = m_fontData.m_initialFont.GetPointSize();
fontUnderline = m_fontData.m_initialFont.GetUnderlined();
fontName = m_fontData.m_initialFont.GetFaceName();
}
m_dialogFont = wxFont(fontSize, fontFamily, fontStyle,
fontWeight, fontUnderline, fontName);
if (m_previewCtrl)
m_previewCtrl->SetFont(m_dialogFont);
m_fontData.SetChosenFont(m_dialogFont);
}
/// Set controls according to current font
void wxFontDialog::InitializeControls()
{
m_suppressUpdates = true;
if (m_underlinedCtrl)
m_underlinedCtrl->SetValue(m_dialogFont.GetUnderlined());
m_boldCtrl->SetValue(m_dialogFont.GetWeight() == wxBOLD);
m_italicCtrl->SetValue(m_dialogFont.GetStyle() == wxITALIC);
m_sizeCtrl->SetValue(m_dialogFont.GetPointSize());
wxString facename = m_dialogFont.GetFaceName();
if (facename.empty() || m_facenameCtrl->FindString(facename) == wxNOT_FOUND)
{
facename = FontFamilyIntToString(m_dialogFont.GetFamily());
}
m_facenameCtrl->SetStringSelection(facename);
if (m_colourCtrl && m_fontData.GetColour().Ok())
{
m_colourCtrl->SetColour(m_fontData.GetColour());
m_colourCtrl->Refresh();
}
m_suppressUpdates = false;
}
/// Respond to font change
void wxFontDialog::ChangeFont()
{
if (m_suppressUpdates)
return;
bool underlined = m_underlinedCtrl ? m_underlinedCtrl->GetValue() : false;
bool italic = m_italicCtrl->GetValue();
bool bold = m_boldCtrl->GetValue();
int size = m_sizeCtrl->GetValue();
wxString facename = m_facenameCtrl->GetStringSelection();
int family = FontFamilyStringToInt(facename);
if (family == -1)
family = wxDEFAULT;
else
facename = wxEmptyString;
m_dialogFont = wxFont(size, family, italic ? wxITALIC : wxNORMAL, bold ? wxBOLD : wxNORMAL,
underlined, facename);
m_fontData.SetChosenFont(m_dialogFont);
m_previewCtrl->SetFont(m_dialogFont);
m_previewCtrl->Refresh();
}
void wxFontDialog::SetData(const wxFontData& fontdata)
{
m_fontData = fontdata;
}
bool wxFontDialog::IsShown() const
{
return false;
}
int wxFontDialog::ShowModal()
{
return wxDialog::ShowModal();
}
void wxFontDialog::OnPanelClose()
{
}
const wxChar *FontFamilyIntToString(int family)
{
switch (family)
{
case wxROMAN:
return _("<Any Roman>");
case wxDECORATIVE:
return _("<Any Decorative>");
case wxMODERN:
return _("<Any Modern>");
case wxSCRIPT:
return _("<Any Script>");
case wxTELETYPE:
return _("<Any Teletype>");
case wxSWISS:
default:
return _("<Any Swiss>");
}
}
int FontFamilyStringToInt(const wxChar *family)
{
if (!family)
return wxSWISS;
if (wxStrcmp(family, _("<Any Roman>")) == 0)
return wxROMAN;
else if (wxStrcmp(family, _("<Any Decorative>")) == 0)
return wxDECORATIVE;
else if (wxStrcmp(family, _("<Any Modern>")) == 0)
return wxMODERN;
else if (wxStrcmp(family, _("<Any Script>")) == 0)
return wxSCRIPT;
else if (wxStrcmp(family, _("<Any Teletype>")) == 0)
return wxTELETYPE;
else if (wxStrcmp(family, _("<Any Swiss>")) == 0)
return wxSWISS;
else return -1;
}
#endif // !USE_NATIVE_FONT_DIALOG_FOR_MACOSX
#endif // wxMAC_USE_EXPERIMENTAL_FONTDIALOG
#endif // wxUSE_FONTDLG

View File

@@ -0,0 +1,535 @@
/////////////////////////////////////////////////////////////////////////////
// Name: src/mac/carbon/fontdlgosx.cpp
// Purpose: wxFontDialog class.
// Author: Ryan Norton
// Modified by:
// Created: 2004-10-03
// RCS-ID: $Id$
// Copyright: (c) Ryan Norton
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
#include "wx/wxprec.h"
// ===========================================================================
// declarations
// ===========================================================================
// ---------------------------------------------------------------------------
// headers
// ---------------------------------------------------------------------------
#include "wx/fontdlg.h"
#ifndef WX_PRECOMP
#include "wx/intl.h"
#include "wx/log.h"
#include "wx/cmndata.h"
#endif
#include "wx/fontutil.h"
// ============================================================================
// implementation
// ============================================================================
#include "wx/cocoa/autorelease.h"
#include "wx/cocoa/string.h"
#if wxMAC_USE_EXPERIMENTAL_FONTDIALOG
#import <Foundation/Foundation.h>
#import <AppKit/AppKit.h>
#include "wx/mac/uma.h"
@interface wxMacFontPanelAccView : NSView
{
BOOL m_okPressed ;
BOOL m_shouldClose ;
NSButton* m_cancelButton ;
NSButton* m_okButton ;
}
- (IBAction)cancelPressed:(id)sender;
- (IBAction)okPressed:(id)sender;
- (void)resetFlags;
- (BOOL)closedWithOk;
- (BOOL)shouldCloseCarbon;
- (NSButton*)okButton;
@end
@implementation wxMacFontPanelAccView : NSView
- (id)initWithFrame:(NSRect)rectBox
{
[super initWithFrame:rectBox];
wxCFStringRef cfOkString( wxT("OK"), wxLocale::GetSystemEncoding() );
wxCFStringRef cfCancelString( wxT("Cancel"), wxLocale::GetSystemEncoding() );
NSRect rectCancel = NSMakeRect( 10.0 , 10.0 , 82 , 24 );
NSRect rectOK = NSMakeRect( 100.0 , 10.0 , 82 , 24 );
NSButton* cancelButton = [[NSButton alloc] initWithFrame:rectCancel];
[cancelButton setTitle:(NSString*)wxCFRetain((CFStringRef)cfCancelString)];
[cancelButton setBezelStyle:NSRoundedBezelStyle];
[cancelButton setButtonType:NSMomentaryPushInButton];
[cancelButton setAction:@selector(cancelPressed:)];
[cancelButton setTarget:self];
m_cancelButton = cancelButton ;
NSButton* okButton = [[NSButton alloc] initWithFrame:rectOK];
[okButton setTitle:(NSString*)wxCFRetain((CFStringRef)cfOkString)];
[okButton setBezelStyle:NSRoundedBezelStyle];
[okButton setButtonType:NSMomentaryPushInButton];
[okButton setAction:@selector(okPressed:)];
[okButton setTarget:self];
// doesn't help either, the button is not highlighted after a color dialog has been used
// [okButton setKeyEquivalent:@"\r"];
m_okButton = okButton ;
[self addSubview:cancelButton];
[self addSubview:okButton];
[self resetFlags];
return self;
}
- (void)resetFlags
{
m_okPressed = NO ;
m_shouldClose = NO ;
}
- (IBAction)cancelPressed:(id)sender
{
wxUnusedVar(sender);
m_shouldClose = YES ;
[NSApp stopModal];
}
- (IBAction)okPressed:(id)sender
{
wxUnusedVar(sender);
m_okPressed = YES ;
m_shouldClose = YES ;
[NSApp stopModal];
}
-(BOOL)closedWithOk
{
return m_okPressed ;
}
-(BOOL)shouldCloseCarbon
{
return m_shouldClose ;
}
-(NSButton*)okButton
{
return m_okButton ;
}
@end
extern "C" int RunMixedFontDialog(wxFontDialog* dialog) ;
int RunMixedFontDialog(wxFontDialog* WXUNUSED(dialog))
{
int retval = wxID_CANCEL ;
if ( !NSApplicationLoad() )
{
wxFAIL_MSG("Couldn't load Cocoa in Carbon Environment");
}
wxAutoNSAutoreleasePool pool;
// setting up the ok/cancel buttons
NSFontPanel* fontPanel = [NSFontPanel sharedFontPanel] ;
// adjust modality for carbon environment
WindowRef carbonWindowRef = (WindowRef)[fontPanel windowRef] ;
SetWindowModality(carbonWindowRef, kWindowModalityAppModal , 0) ;
SetWindowGroup(carbonWindowRef , GetWindowGroupOfClass(kMovableModalWindowClass));
[fontPanel setFloatingPanel:NO] ;
[[fontPanel standardWindowButton:NSWindowCloseButton] setEnabled:NO] ;
wxMacFontPanelAccView* accessoryView = (wxMacFontPanelAccView*) [fontPanel accessoryView] ;
if ( accessoryView == nil)
{
NSRect rectBox = NSMakeRect( 0 , 0 , 192 , 40 );
accessoryView = [[wxMacFontPanelAccView alloc] initWithFrame:rectBox];
[fontPanel setAccessoryView:accessoryView];
[fontPanel setDefaultButtonCell:[[accessoryView okButton] cell]] ;
}
[accessoryView resetFlags];
NSModalSession session = [NSApp beginModalSessionForWindow:fontPanel];
[NSApp runModalSession:session];
[NSApp endModalSession:session];
// if we don't reenable it, FPShowHideFontPanel does not work
[[fontPanel standardWindowButton:NSWindowCloseButton] setEnabled:YES] ;
if( FPIsFontPanelVisible())
FPShowHideFontPanel() ;
if ( [accessoryView closedWithOk])
{
retval = wxID_OK ;
}
return retval ;
}
#else
#if USE_NATIVE_FONT_DIALOG_FOR_MACOSX
IMPLEMENT_DYNAMIC_CLASS(wxFontDialog, wxDialog)
// Cocoa headers
#import <AppKit/NSFont.h>
#import <AppKit/NSFontManager.h>
#import <AppKit/NSFontPanel.h>
#import <AppKit/NSColor.h>
#import <AppKit/NSColorPanel.h>
// ---------------------------------------------------------------------------
// wxWCDelegate - Window Closed delegate
// ---------------------------------------------------------------------------
@interface wxWCDelegate : NSObject
{
bool m_bIsClosed;
}
// Delegate methods
- (id)init;
- (BOOL)windowShouldClose:(id)sender;
- (BOOL)isClosed;
@end // interface wxNSFontPanelDelegate : NSObject
@implementation wxWCDelegate : NSObject
- (id)init
{
[super init];
m_bIsClosed = false;
return self;
}
- (BOOL)windowShouldClose:(id)sender
{
m_bIsClosed = true;
[NSApp abortModal];
[NSApp stopModal];
return YES;
}
- (BOOL)isClosed
{
return m_bIsClosed;
}
@end // wxNSFontPanelDelegate
// ---------------------------------------------------------------------------
// wxWCODelegate - Window Closed or Open delegate
// ---------------------------------------------------------------------------
@interface wxWCODelegate : NSObject
{
bool m_bIsClosed;
bool m_bIsOpen;
}
// Delegate methods
- (id)init;
- (BOOL)windowShouldClose:(id)sender;
- (void)windowDidUpdate:(NSNotification *)aNotification;
- (BOOL)isClosed;
- (BOOL)isOpen;
@end // interface wxNSFontPanelDelegate : NSObject
@implementation wxWCODelegate : NSObject
- (id)init
{
[super init];
m_bIsClosed = false;
m_bIsOpen = false;
return self;
}
- (BOOL)windowShouldClose:(id)sender
{
m_bIsClosed = true;
m_bIsOpen = false;
[NSApp abortModal];
[NSApp stopModal];
return YES;
}
- (void)windowDidUpdate:(NSNotification *)aNotification
{
if (m_bIsOpen == NO)
{
m_bIsClosed = false;
m_bIsOpen = true;
[NSApp abortModal];
[NSApp stopModal];
}
}
- (BOOL)isClosed
{
return m_bIsClosed;
}
- (BOOL)isOpen
{
return m_bIsOpen;
}
@end // wxNSFontPanelDelegate
// ---------------------------------------------------------------------------
// wxFontDialog
// ---------------------------------------------------------------------------
wxFontDialog::wxFontDialog()
{
}
wxFontDialog::wxFontDialog(wxWindow *parent, const wxFontData& data)
{
Create(parent, data);
}
wxFontDialog::~wxFontDialog()
{
}
bool wxFontDialog::Create(wxWindow *parent, const wxFontData& data)
{
m_fontData = data;
//
// This is the key call - this initializes
// events and window stuff for cocoa for carbon
// applications.
//
// This is also the only call here that is
// 10.2+ specific (the rest is OSX only),
// which, ironically, the carbon font
// panel requires.
//
bool bOK = NSApplicationLoad();
//autorelease pool - req'd for carbon
NSAutoreleasePool *thePool;
thePool = [[NSAutoreleasePool alloc] init];
//Get the initial wx font
wxFont& thewxfont = m_fontData.m_initialFont;
//if the font is valid set the default (selected) font of the
//NSFontDialog to that font
if (thewxfont.Ok())
{
NSFontTraitMask theMask = 0;
if(thewxfont.GetStyle() == wxFONTSTYLE_ITALIC)
theMask |= NSItalicFontMask;
if(thewxfont.IsFixedWidth())
theMask |= NSFixedPitchFontMask;
NSFont* theDefaultFont =
[[NSFontManager sharedFontManager] fontWithFamily:
wxNSStringWithWxString(thewxfont.GetFaceName())
traits:theMask
weight:thewxfont.GetWeight() == wxBOLD ? 9 :
thewxfont.GetWeight() == wxLIGHT ? 0 : 5
size: (float)(thewxfont.GetPointSize())
];
wxASSERT_MSG(theDefaultFont, wxT("Invalid default font for wxCocoaFontDialog!"));
//Apple docs say to call NSFontManager::setSelectedFont
//However, 10.3 doesn't seem to create the font panel
//is this is done, so create it ourselves
[[NSFontPanel sharedFontPanel] setPanelFont:theDefaultFont isMultiple:NO];
}
if(m_fontData.m_fontColour.Ok())
[[NSColorPanel sharedColorPanel] setColor:
[NSColor colorWithCalibratedRed:m_fontData.m_fontColour.Red() / 255.0
green:m_fontData.m_fontColour.Green() / 255.0
blue:m_fontData.m_fontColour.Blue() / 255.0
alpha:1.0]
];
else
[[NSColorPanel sharedColorPanel] setColor:[NSColor blackColor]];
//We're done - free up the pool
[thePool release];
return bOK;
}
int wxFontDialog::ShowModal()
{
//Start the pool. Required for carbon interaction
//(For those curious, the only thing that happens
//if you don't do this is a bunch of error
//messages about leaks on the console,
//with no windows shown or anything).
NSAutoreleasePool *thePool;
thePool = [[NSAutoreleasePool alloc] init];
//Get the shared color and font panel
NSFontPanel* theFontPanel = [NSFontPanel sharedFontPanel];
NSColorPanel* theColorPanel = [NSColorPanel sharedColorPanel];
//Create and assign the delegates (cocoa event handlers) so
//we can tell if a window has closed/open or not
wxWCDelegate* theFPDelegate = [[wxWCDelegate alloc] init];
[theFontPanel setDelegate:theFPDelegate];
wxWCODelegate* theCPDelegate = [[wxWCODelegate alloc] init];
[theColorPanel setDelegate:theCPDelegate];
//
// Begin the modal loop for the font and color panels
//
// The idea is that we first make the font panel modal,
// but if the color panel is opened, unless we stop the
// modal loop the color panel opens behind the font panel
// with no input acceptable to it - which makes it useless.
//
// So we set up delegates for both the color and font panels,
// and the if the font panel opens the color panel, we
// stop the modal loop, and start a separate modal loop for
// the color panel until the color panel closes, switching
// back to the font panel modal loop once it does close.
//
do
{
//
// Start the font panel modal loop
//
NSModalSession session = [NSApp beginModalSessionForWindow:theFontPanel];
for (;;)
{
[NSApp runModalSession:session];
//If the font panel is closed or the font panel
//opened the color panel, break
if ([theFPDelegate isClosed] || [theCPDelegate isOpen])
break;
}
[NSApp endModalSession:session];
//is the color panel open?
if ([theCPDelegate isOpen])
{
//
// Start the color panel modal loop
//
NSModalSession session = [NSApp beginModalSessionForWindow:theColorPanel];
for (;;)
{
[NSApp runModalSession:session];
//If the color panel is closed, return the font panel modal loop
if ([theCPDelegate isClosed])
break;
}
[NSApp endModalSession:session];
}
//If the font panel is still alive (I.E. we broke
//out of its modal loop because the color panel was
//opened) return the font panel modal loop
}while([theFPDelegate isClosed] == NO);
//free up the memory for the delegates - we don't need them anymore
[theFPDelegate release];
[theCPDelegate release];
//Get the font the user selected
NSFont* theFont = [theFontPanel panelConvertFont:[NSFont userFontOfSize:0]];
//Get more information about the user's chosen font
NSFontTraitMask theTraits = [[NSFontManager sharedFontManager] traitsOfFont:theFont];
int theFontWeight = [[NSFontManager sharedFontManager] weightOfFont:theFont];
int theFontSize = (int) [theFont pointSize];
//Set the wx font to the appropriate data
if(theTraits & NSFixedPitchFontMask)
m_fontData.m_chosenFont.SetFamily(wxTELETYPE);
m_fontData.m_chosenFont.SetFaceName(wxStringWithNSString([theFont familyName]));
m_fontData.m_chosenFont.SetPointSize(theFontSize);
m_fontData.m_chosenFont.SetStyle(theTraits & NSItalicFontMask ? wxFONTSTYLE_ITALIC : 0);
m_fontData.m_chosenFont.SetWeight(theFontWeight < 5 ? wxLIGHT :
theFontWeight >= 9 ? wxBOLD : wxNORMAL);
//Get the shared color panel along with the chosen color and set the chosen color
NSColor* theColor = [[theColorPanel color] colorUsingColorSpaceName:NSCalibratedRGBColorSpace];
m_fontData.m_fontColour.Set((unsigned char) ([theColor redComponent] * 255.0),
(unsigned char) ([theColor greenComponent] * 255.0),
(unsigned char) ([theColor blueComponent] * 255.0));
//Friendly debug stuff
#ifdef FONTDLGDEBUG
wxPrintf(wxT("---Font Panel---\n--NS--\nSize:%f\nWeight:%i\nTraits:%i\n--WX--\nFaceName:%s\nPointSize:%i\nStyle:%i\nWeight:%i\nColor:%i,%i,%i\n---END Font Panel---\n"),
(float) theFontSize,
theFontWeight,
theTraits,
m_fontData.m_chosenFont.GetFaceName().c_str(),
m_fontData.m_chosenFont.GetPointSize(),
m_fontData.m_chosenFont.GetStyle(),
m_fontData.m_chosenFont.GetWeight(),
m_fontData.m_fontColour.Red(),
m_fontData.m_fontColour.Green(),
m_fontData.m_fontColour.Blue() );
#endif
//Release the pool, we're done :)
[thePool release];
//Return ID_OK - there are no "apply" buttons or the like
//on either the font or color panel
return wxID_OK;
}
//old api stuff (REMOVE ME)
bool wxFontDialog::IsShown() const
{
return false;
}
#endif // 10.2+
#endif

123
src/osx/carbon/fontenum.cpp Normal file
View File

@@ -0,0 +1,123 @@
///////////////////////////////////////////////////////////////////////////////
// Name: src/mac/carbon/fontenum.cpp
// Purpose: wxFontEnumerator class for MacOS
// Author: Stefan Csomor
// Modified by:
// Created: 04/01/98
// RCS-ID: $Id$
// Copyright: (c) Stefan Csomor
// Licence: wxWindows licence
///////////////////////////////////////////////////////////////////////////////
// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"
#if wxUSE_FONTENUM
#include "wx/fontenum.h"
#ifndef WX_PRECOMP
#include "wx/font.h"
#include "wx/intl.h"
#endif
#include "wx/fontutil.h"
#include "wx/fontmap.h"
#include "wx/encinfo.h"
#include "wx/mac/private.h"
// ----------------------------------------------------------------------------
// wxFontEnumerator
// ----------------------------------------------------------------------------
bool wxFontEnumerator::EnumerateFacenames(wxFontEncoding encoding,
bool fixedWidthOnly)
{
if ( fixedWidthOnly )
{
wxFAIL_MSG( "enumerating only fixed width fonts not supported" );
return false;
}
wxArrayString fontFamilies ;
#if wxMAC_USE_ATSU_TEXT || wxMAC_USE_CORE_TEXT
//
// From Apple's QA 1471 http://developer.apple.com/qa/qa2006/qa1471.html
//
ATSFontFamilyIterator theFontFamilyIterator = NULL;
ATSFontFamilyRef theATSFontFamilyRef = 0;
OSStatus status = noErr;
// Create the iterator
status = ATSFontFamilyIteratorCreate(kATSFontContextLocal, nil,nil,
kATSOptionFlagsUnRestrictedScope,
&theFontFamilyIterator );
wxUint32 macEncoding = wxMacGetSystemEncFromFontEnc(encoding) ;
while (status == noErr)
{
// Get the next font in the iteration.
status = ATSFontFamilyIteratorNext( theFontFamilyIterator, &theATSFontFamilyRef );
if(status == noErr)
{
#ifndef __LP64__
// TODO CS : Find replacement
// added CS : avoid showing fonts that won't be displayable
FMFontStyle intrinsicStyle = 0 ;
FMFont fontInstance ;
FMFontFamily fmFamily = FMGetFontFamilyFromATSFontFamilyRef( theATSFontFamilyRef );
status = FMGetFontFromFontFamilyInstance( fmFamily , 0 , &fontInstance , &intrinsicStyle);
if ( status != noErr )
{
status = noErr;
continue ;
}
#endif
if ( encoding != wxFONTENCODING_SYSTEM )
{
TextEncoding fontFamiliyEncoding = ATSFontFamilyGetEncoding(theATSFontFamilyRef) ;
if ( fontFamiliyEncoding != macEncoding )
continue ;
}
// TODO: determine fixed widths ...
CFStringRef theName = NULL;
ATSFontFamilyGetName(theATSFontFamilyRef, kATSOptionFlagsDefault, &theName);
wxCFStringRef cfName(theName) ;
fontFamilies.Add(cfName.AsString(wxLocale::GetSystemEncoding()));
}
else if (status == kATSIterationScopeModified) // Make sure the font database hasn<73>t changed.
{
// reset the iterator
status = ATSFontFamilyIteratorReset (kATSFontContextLocal, nil, nil,
kATSOptionFlagsUnRestrictedScope,
&theFontFamilyIterator);
fontFamilies.Clear() ;
}
}
ATSFontFamilyIteratorRelease(&theFontFamilyIterator);
#endif
for ( size_t i = 0 ; i < fontFamilies.Count() ; ++i )
{
if ( OnFacename( fontFamilies[i] ) == false )
break ;
}
return true;
}
bool wxFontEnumerator::EnumerateEncodings(const wxString& WXUNUSED(family))
{
wxFAIL_MSG(wxT("wxFontEnumerator::EnumerateEncodings() not yet implemented"));
return true;
}
#endif // wxUSE_FONTENUM

View File

@@ -0,0 +1,88 @@
///////////////////////////////////////////////////////////////////////////////
// Name: msw/fontutil.cpp
// Purpose: font-related helper functions for wxMSW
// Author: Vadim Zeitlin
// Modified by:
// Created: 05.11.99
// RCS-ID: $Id$
// Copyright: (c) 1999 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
// Licence: wxWindows licence
///////////////////////////////////////////////////////////////////////////////
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#ifndef WX_PRECOMP
#include "wx/string.h"
#include "wx/wxcrtvararg.h"
#include "wx/log.h"
#include "wx/intl.h"
#endif
#include "wx/fontutil.h"
#include "wx/fontmap.h"
#include "wx/encinfo.h"
#include "wx/tokenzr.h"
// convert to/from the string representation:
// format is facename[;charset]
//
bool wxNativeEncodingInfo::FromString( const wxString& s )
{
wxStringTokenizer tokenizer(s, wxT(";"));
facename = tokenizer.GetNextToken();
if ( !facename )
return false;
wxString tmp = tokenizer.GetNextToken();
if ( !tmp )
{
// default charset (don't use DEFAULT_CHARSET though because of subtle
// Windows 9x/NT differences in handling it)
charset = 0;
}
else
{
if ( wxSscanf( tmp, wxT("%u"), &charset ) != 1 )
// should be a number!
return false;
}
return true;
}
wxString wxNativeEncodingInfo::ToString() const
{
wxString s(facename);
if ( charset != 0 )
s << wxT(';') << charset;
return s;
}
// ----------------------------------------------------------------------------
// helper functions
// ----------------------------------------------------------------------------
bool wxGetNativeFontEncoding( wxFontEncoding encoding, wxNativeEncodingInfo *info )
{
wxCHECK_MSG( info, false, wxT("bad pointer in wxGetNativeFontEncoding") );
if ( encoding == wxFONTENCODING_DEFAULT )
encoding = wxFont::GetDefaultEncoding();
info->encoding = encoding;
return true;
}
bool wxTestFontEncoding( const wxNativeEncodingInfo& WXUNUSED(info) )
{
// basically we should be able to support every encoding via the OS
return true;
}

402
src/osx/carbon/frame.cpp Normal file
View File

@@ -0,0 +1,402 @@
/////////////////////////////////////////////////////////////////////////////
// Name: src/mac/carbon/frame.cpp
// Purpose: wxFrame
// Author: Stefan Csomor
// Modified by:
// Created: 1998-01-01
// RCS-ID: $Id$
// Copyright: (c) Stefan Csomor
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
#include "wx/wxprec.h"
#include "wx/frame.h"
#ifndef WX_PRECOMP
#include "wx/app.h"
#include "wx/dcclient.h"
#include "wx/menu.h"
#include "wx/dialog.h"
#include "wx/settings.h"
#include "wx/toolbar.h"
#include "wx/statusbr.h"
#include "wx/menuitem.h"
#endif // WX_PRECOMP
#include "wx/mac/uma.h"
BEGIN_EVENT_TABLE(wxFrame, wxFrameBase)
EVT_ACTIVATE(wxFrame::OnActivate)
// EVT_MENU_HIGHLIGHT_ALL(wxFrame::OnMenuHighlight)
EVT_SYS_COLOUR_CHANGED(wxFrame::OnSysColourChanged)
// EVT_IDLE(wxFrame::OnIdle)
// EVT_CLOSE(wxFrame::OnCloseWindow)
END_EVENT_TABLE()
IMPLEMENT_DYNAMIC_CLASS(wxFrame, wxTopLevelWindow)
#define WX_MAC_STATUSBAR_HEIGHT 18
// ----------------------------------------------------------------------------
// creation/destruction
// ----------------------------------------------------------------------------
void wxFrame::Init()
{
m_winLastFocused = NULL;
}
bool wxFrame::Create(wxWindow *parent,
wxWindowID id,
const wxString& title,
const wxPoint& pos,
const wxSize& size,
long style,
const wxString& name)
{
if ( !wxTopLevelWindow::Create(parent, id, title, pos, size, style, name) )
return false;
return true;
}
wxFrame::~wxFrame()
{
m_isBeingDeleted = true;
DeleteAllBars();
}
// get the origin of the client area in the client coordinates
wxPoint wxFrame::GetClientAreaOrigin() const
{
wxPoint pt = wxTopLevelWindow::GetClientAreaOrigin();
#if wxUSE_TOOLBAR && !defined(__WXUNIVERSAL__)
wxToolBar *toolbar = GetToolBar();
if ( toolbar && toolbar->IsShown() )
{
int w, h;
toolbar->GetSize(&w, &h);
if ( toolbar->GetWindowStyleFlag() & wxTB_VERTICAL )
{
pt.x += w;
}
else
{
#if !wxMAC_USE_NATIVE_TOOLBAR
pt.y += h;
#endif
}
}
#endif
return pt;
}
bool wxFrame::Enable(bool enable)
{
if ( !wxWindow::Enable(enable) )
return false;
if ( m_frameMenuBar && m_frameMenuBar == wxMenuBar::MacGetInstalledMenuBar() )
{
int iMaxMenu = m_frameMenuBar->GetMenuCount();
for ( int i = 0 ; i < iMaxMenu ; ++ i )
{
m_frameMenuBar->EnableTop( i , enable ) ;
}
}
return true;
}
#if wxUSE_STATUSBAR
wxStatusBar *wxFrame::OnCreateStatusBar(int number, long style, wxWindowID id,
const wxString& name)
{
wxStatusBar *statusBar;
statusBar = new wxStatusBar(this, id, style, name);
statusBar->SetSize(100, WX_MAC_STATUSBAR_HEIGHT);
statusBar->SetFieldsCount(number);
return statusBar;
}
void wxFrame::PositionStatusBar()
{
if (m_frameStatusBar && m_frameStatusBar->IsShown() )
{
int w, h;
GetClientSize(&w, &h);
// Since we wish the status bar to be directly under the client area,
// we use the adjusted sizes without using wxSIZE_NO_ADJUSTMENTS.
m_frameStatusBar->SetSize(0, h, w, WX_MAC_STATUSBAR_HEIGHT);
}
}
#endif // wxUSE_STATUSBAR
// Responds to colour changes, and passes event on to children.
void wxFrame::OnSysColourChanged(wxSysColourChangedEvent& event)
{
SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_APPWORKSPACE));
Refresh();
#if wxUSE_STATUSBAR
if ( m_frameStatusBar )
{
wxSysColourChangedEvent event2;
event2.SetEventObject( m_frameStatusBar );
m_frameStatusBar->ProcessEvent(event2);
}
#endif // wxUSE_STATUSBAR
// Propagate the event to the non-top-level children
wxWindow::OnSysColourChanged(event);
}
// Default activation behaviour - set the focus for the first child
// subwindow found.
void wxFrame::OnActivate(wxActivateEvent& event)
{
if ( !event.GetActive() )
{
// remember the last focused child if it is our child
m_winLastFocused = FindFocus();
// so we NULL it out if it's a child from some other frame
wxWindow *win = m_winLastFocused;
while ( win )
{
if ( win->IsTopLevel() )
{
if ( win != this )
m_winLastFocused = NULL;
break;
}
win = win->GetParent();
}
event.Skip();
}
else
{
// restore focus to the child which was last focused
wxWindow *parent = m_winLastFocused
? m_winLastFocused->GetParent()
: NULL;
if (parent == NULL)
parent = this;
wxSetFocusToChild(parent, &m_winLastFocused);
if (m_frameMenuBar != NULL)
{
m_frameMenuBar->MacInstallMenuBar();
}
else
{
wxFrame *tlf = wxDynamicCast( wxTheApp->GetTopWindow(), wxFrame );
if (tlf != NULL)
{
// Trying top-level frame membar
if (tlf->GetMenuBar())
tlf->GetMenuBar()->MacInstallMenuBar();
}
}
}
}
void wxFrame::DetachMenuBar()
{
if ( m_frameMenuBar )
m_frameMenuBar->UnsetInvokingWindow();
wxFrameBase::DetachMenuBar();
}
void wxFrame::AttachMenuBar( wxMenuBar *menuBar )
{
wxFrame* tlf = wxDynamicCast( wxFindWinFromMacWindow( FrontNonFloatingWindow() ) , wxFrame );
bool makeCurrent = false;
// if this is already the current menubar or we are the frontmost window
if ( (tlf == this) || (m_frameMenuBar == wxMenuBar::MacGetInstalledMenuBar()) )
makeCurrent = true;
// or there is an app-level menubar like MDI
else if ( tlf && (tlf->GetMenuBar() == NULL) && (((wxFrame*)wxTheApp->GetTopWindow()) == this) )
makeCurrent = true;
wxFrameBase::AttachMenuBar( menuBar );
if (m_frameMenuBar)
{
m_frameMenuBar->SetInvokingWindow( this );
if (makeCurrent)
m_frameMenuBar->MacInstallMenuBar();
}
}
void wxFrame::DoGetClientSize(int *x, int *y) const
{
wxTopLevelWindow::DoGetClientSize( x , y );
#if wxUSE_STATUSBAR
if ( GetStatusBar() && GetStatusBar()->IsShown() && y )
*y -= WX_MAC_STATUSBAR_HEIGHT;
#endif
#if wxUSE_TOOLBAR
wxToolBar *toolbar = GetToolBar();
if ( toolbar && toolbar->IsShown() )
{
int w, h;
toolbar->GetSize(&w, &h);
if ( toolbar->GetWindowStyleFlag() & wxTB_VERTICAL )
{
if ( x )
*x -= w;
}
else
{
#if !wxMAC_USE_NATIVE_TOOLBAR
if ( y )
*y -= h;
#endif
}
}
#endif
}
bool wxFrame::MacIsChildOfClientArea( const wxWindow* child ) const
{
#if wxUSE_STATUSBAR
if ( child == GetStatusBar() )
return false ;
#endif
#if wxUSE_TOOLBAR
if ( child == GetToolBar() )
return false ;
#endif
return wxFrameBase::MacIsChildOfClientArea( child ) ;
}
void wxFrame::DoSetClientSize(int clientwidth, int clientheight)
{
int currentclientwidth , currentclientheight ;
int currentwidth , currentheight ;
GetClientSize( &currentclientwidth , &currentclientheight ) ;
if ( clientwidth == -1 )
clientwidth = currentclientwidth ;
if ( clientheight == -1 )
clientheight = currentclientheight ;
GetSize( &currentwidth , &currentheight ) ;
// find the current client size
// Find the difference between the entire window (title bar and all) and
// the client area; add this to the new client size to move the window
DoSetSize( -1 , -1 , currentwidth + clientwidth - currentclientwidth ,
currentheight + clientheight - currentclientheight , wxSIZE_USE_EXISTING ) ;
}
#if wxUSE_TOOLBAR
void wxFrame::SetToolBar(wxToolBar *toolbar)
{
if ( m_frameToolBar == toolbar )
return ;
#if wxMAC_USE_NATIVE_TOOLBAR
if ( m_frameToolBar )
m_frameToolBar->MacInstallNativeToolbar( false ) ;
#endif
m_frameToolBar = toolbar ;
#if wxMAC_USE_NATIVE_TOOLBAR
if ( toolbar )
toolbar->MacInstallNativeToolbar( true ) ;
#endif
}
wxToolBar* wxFrame::CreateToolBar(long style, wxWindowID id, const wxString& name)
{
if ( wxFrameBase::CreateToolBar(style, id, name) )
PositionToolBar();
return m_frameToolBar;
}
void wxFrame::PositionToolBar()
{
int cw, ch;
GetSize( &cw , &ch ) ;
int statusX = 0 ;
int statusY = 0 ;
#if wxUSE_STATUSBAR
if (GetStatusBar() && GetStatusBar()->IsShown())
{
GetStatusBar()->GetClientSize(&statusX, &statusY);
ch -= statusY;
}
#endif
if (GetToolBar())
{
int tx, ty, tw, th;
tx = ty = 0 ;
GetToolBar()->GetSize(&tw, &th);
if (GetToolBar()->GetWindowStyleFlag() & wxTB_VERTICAL)
{
// Use the 'real' position. wxSIZE_NO_ADJUSTMENTS
// means, pretend we don't have toolbar/status bar, so we
// have the original client size.
GetToolBar()->SetSize(tx , ty , tw, ch , wxSIZE_NO_ADJUSTMENTS );
}
else if (GetToolBar()->GetWindowStyleFlag() & wxTB_BOTTOM)
{
//FIXME: this positions the tool bar almost correctly, but still it doesn't work right yet,
//as 1) the space for the 'old' top toolbar is still taken up, and 2) the toolbar
//doesn't extend it's width to the width of the frame.
tx = 0;
ty = ch - (th + statusY);
GetToolBar()->SetSize(tx, ty, cw, th, wxSIZE_NO_ADJUSTMENTS );
}
else
{
#if !wxMAC_USE_NATIVE_TOOLBAR
// Use the 'real' position
GetToolBar()->SetSize(tx , ty , cw , th, wxSIZE_NO_ADJUSTMENTS );
#endif
}
}
}
#endif // wxUSE_TOOLBAR
void wxFrame::PositionBars()
{
#if wxUSE_STATUSBAR
PositionStatusBar();
#endif
#if wxUSE_TOOLBAR
PositionToolBar();
#endif
}

128
src/osx/carbon/gauge.cpp Normal file
View File

@@ -0,0 +1,128 @@
/////////////////////////////////////////////////////////////////////////////
// Name: gauge.cpp
// Purpose: wxGauge class
// Author: Stefan Csomor
// Modified by:
// Created: 1998-01-01
// RCS-ID: $Id$
// Copyright: (c) Stefan Csomor
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
#include "wx/wxprec.h"
#if wxUSE_GAUGE
#include "wx/gauge.h"
IMPLEMENT_DYNAMIC_CLASS(wxGauge, wxControl)
#include "wx/mac/uma.h"
bool wxGauge::Create( wxWindow *parent,
wxWindowID id,
int range,
const wxPoint& pos,
const wxSize& s,
long style,
const wxValidator& validator,
const wxString& name )
{
m_macIsUserPane = false;
if ( !wxGaugeBase::Create( parent, id, range, pos, s, style & 0xE0FFFFFF, validator, name ) )
return false;
wxSize size = s;
#if 0
if (size.x == wxDefaultCoord && size.y == wxDefaultCoord)
size = wxSize( 200 , 16 );
#endif
Rect bounds = wxMacGetBoundsForControl( this, pos, size );
m_peer = new wxMacControl( this );
OSStatus err = CreateProgressBarControl(
MAC_WXHWND(parent->MacGetTopLevelWindowRef()), &bounds,
GetValue(), 0, GetRange(), false /* not indeterminate */, m_peer->GetControlRefAddr() );
verify_noerr( err );
if ( GetValue() == 0 )
m_peer->SetData<Boolean>( kControlEntireControl, kControlProgressBarAnimatingTag, (Boolean)false );
MacPostControlCreate( pos, size );
return true;
}
void wxGauge::SetRange(int r)
{
// we are going via the base class in case there is
// some change behind the values by it
wxGaugeBase::SetRange( r ) ;
if ( m_peer && m_peer->Ok() ){
// switch back to determinate mode if not there already
if ( m_peer->GetData<Boolean>( kControlNoPart, kControlProgressBarIndeterminateTag ) != false )
{
m_peer->SetData<Boolean>( kControlNoPart, kControlProgressBarIndeterminateTag, (Boolean)false );
}
m_peer->SetMaximum( GetRange() ) ;
}
}
void wxGauge::SetValue(int pos)
{
// we are going via the base class in case there is
// some change behind the values by it
wxGaugeBase::SetValue( pos ) ;
if ( m_peer && m_peer->Ok() )
{
// switch back to determinate mode if not there already
if ( m_peer->GetData<Boolean>( kControlNoPart, kControlProgressBarIndeterminateTag ) != false )
{
m_peer->SetData<Boolean>( kControlNoPart, kControlProgressBarIndeterminateTag, (Boolean)false );
}
m_peer->SetValue( GetValue() ) ;
// turn off animation in the unnecessary situations as this is consuming a lot of CPU otherwise
Boolean shouldAnimate = ( GetValue() > 0 && GetValue() < GetRange() ) ;
if ( m_peer->GetData<Boolean>( kControlEntireControl, kControlProgressBarAnimatingTag ) != shouldAnimate )
{
m_peer->SetData<Boolean>( kControlEntireControl, kControlProgressBarAnimatingTag, shouldAnimate ) ;
if ( !shouldAnimate )
Refresh() ;
}
}
}
int wxGauge::GetValue() const
{
#if 0
if ( m_peer && m_peer->Ok() )
return m_peer->GetValue() ;
#endif
return m_gaugePos ;
}
void wxGauge::Pulse()
{
if ( m_peer && m_peer->Ok() )
{
if ( m_peer->GetData<Boolean>( kControlNoPart, kControlProgressBarIndeterminateTag ) != true )
{
m_peer->SetData<Boolean>( kControlNoPart, kControlProgressBarIndeterminateTag, true);
}
if ( m_peer->GetData<Boolean>( kControlEntireControl, kControlProgressBarAnimatingTag ) != true )
{
m_peer->SetData<Boolean>( kControlEntireControl, kControlProgressBarAnimatingTag, true ) ;
}
}
}
#endif // wxUSE_GAUGE

75
src/osx/carbon/gdiobj.cpp Normal file
View File

@@ -0,0 +1,75 @@
/////////////////////////////////////////////////////////////////////////////
// Name: src/mac/carbon/gdiobj.cpp
// Purpose: wxGDIObject class
// Author: Stefan Csomor
// Modified by:
// Created: 1998-01-01
// RCS-ID: $Id$
// Copyright: (c) Stefan Csomor
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
#include "wx/wxprec.h"
#include "wx/gdiobj.h"
#ifndef WX_PRECOMP
#include "wx/gdicmn.h"
#include "wx/module.h"
#endif
#include "wx/link.h"
#include "wx/mac/private.h"
// Linker will discard entire object file without this
wxFORCE_LINK_THIS_MODULE(gdiobj)
class wxStockGDIMac: public wxStockGDI, public wxModule
{
public:
virtual const wxFont* GetFont(Item item);
virtual bool OnInit();
virtual void OnExit();
private:
typedef wxStockGDI super;
DECLARE_DYNAMIC_CLASS(wxStockGDIMac)
};
IMPLEMENT_DYNAMIC_CLASS(wxStockGDIMac, wxModule)
bool wxStockGDIMac::OnInit()
{
// Override default instance
ms_instance = this;
return true;
}
void wxStockGDIMac::OnExit()
{
}
const wxFont* wxStockGDIMac::GetFont(Item item)
{
wxFont* font = static_cast<wxFont*>(ms_stockObject[item]);
if (font == NULL)
{
switch (item)
{
case FONT_NORMAL:
font = new wxFont;
font->MacCreateFromThemeFont(kThemeSystemFont);
break;
case FONT_SMALL:
font = new wxFont;
font->MacCreateFromThemeFont(kThemeSmallSystemFont);
break;
default:
font = const_cast<wxFont*>(super::GetFont(item));
break;
}
ms_stockObject[item] = font;
}
return font;
}

499
src/osx/carbon/glcanvas.cpp Normal file
View File

@@ -0,0 +1,499 @@
///////////////////////////////////////////////////////////////////////////////
// Name: src/mac/carbon/glcanvas.cpp
// Purpose: wxGLCanvas, for using OpenGL with wxWidgets under Macintosh
// Author: Stefan Csomor
// Modified by:
// Created: 1998-01-01
// RCS-ID: $Id$
// Copyright: (c) Stefan Csomor
// Licence: wxWindows licence
///////////////////////////////////////////////////////////////////////////////
// ============================================================================
// declarations
// ============================================================================
// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------
#include "wx/wxprec.h"
#if defined(__BORLANDC__)
#pragma hdrstop
#endif
#if wxUSE_GLCANVAS
#include "wx/glcanvas.h"
#ifndef WX_PRECOMP
#include "wx/frame.h"
#include "wx/log.h"
#include "wx/settings.h"
#endif
#include "wx/mac/uma.h"
#include "wx/mac/private.h"
// ----------------------------------------------------------------------------
// helper functions
// ----------------------------------------------------------------------------
static void wxLogAGLError(const char *func)
{
const int err = aglGetError();
wxLogError(_("OpenGL function \"%s\" failed: %s (error %d)"),
func, aglErrorString(err), err);
}
// ============================================================================
// implementation
// ============================================================================
// ----------------------------------------------------------------------------
// wxGLContext
// ----------------------------------------------------------------------------
wxGLContext::wxGLContext(wxGLCanvas *win, const wxGLContext *other)
{
m_aglContext = aglCreateContext(win->GetAGLPixelFormat(),
other ? other->m_aglContext : NULL);
if ( !m_aglContext )
wxLogAGLError("aglCreateContext");
}
wxGLContext::~wxGLContext()
{
if ( m_aglContext )
{
// it's ok to pass the current context to this function
if ( !aglDestroyContext(m_aglContext) )
wxLogAGLError("aglDestroyContext");
}
}
bool wxGLContext::SetCurrent(const wxGLCanvas& win) const
{
if ( !m_aglContext )
return false;
AGLDrawable drawable = (AGLDrawable)GetWindowPort(
MAC_WXHWND(win.MacGetTopLevelWindowRef()));
if ( !aglSetDrawable(m_aglContext, drawable) )
{
wxLogAGLError("aglSetDrawable");
return false;
}
if ( !aglSetCurrentContext(m_aglContext) )
{
wxLogAGLError("aglSetCurrentContext");
return false;
}
wx_const_cast(wxGLCanvas&, win).SetViewport();
return true;
}
// ----------------------------------------------------------------------------
// wxGLCanvas
// ----------------------------------------------------------------------------
IMPLEMENT_CLASS(wxGLCanvas, wxWindow)
BEGIN_EVENT_TABLE(wxGLCanvas, wxWindow)
EVT_SIZE(wxGLCanvas::OnSize)
END_EVENT_TABLE()
wxGLCanvas::wxGLCanvas(wxWindow *parent,
wxWindowID id,
const int *attribList,
const wxPoint& pos,
const wxSize& size,
long style,
const wxString& name,
const wxPalette& palette)
{
Create(parent, id, pos, size, style, name, attribList, palette);
}
#if WXWIN_COMPATIBILITY_2_8
wxGLCanvas::wxGLCanvas(wxWindow *parent,
wxWindowID id,
const wxPoint& pos,
const wxSize& size,
long style,
const wxString& name,
const int *attribList,
const wxPalette& palette)
{
if ( Create(parent, id, pos, size, style, name, attribList, palette) )
m_glContext = new wxGLContext(this);
}
wxGLCanvas::wxGLCanvas(wxWindow *parent,
const wxGLContext *shared,
wxWindowID id,
const wxPoint& pos,
const wxSize& size,
long style,
const wxString& name,
const int *attribList,
const wxPalette& palette)
{
if ( Create(parent, id, pos, size, style, name, attribList, palette) )
m_glContext = new wxGLContext(this, shared);
}
wxGLCanvas::wxGLCanvas(wxWindow *parent,
const wxGLCanvas *shared,
wxWindowID id,
const wxPoint& pos,
const wxSize& size,
long style,
const wxString& name,
const int *attribList,
const wxPalette& palette)
{
if ( Create(parent, id, pos, size, style, name, attribList, palette) )
m_glContext = new wxGLContext(this, shared ? shared->m_glContext : NULL);
}
#endif // WXWIN_COMPATIBILITY_2_8
/* static */
bool wxGLCanvasBase::IsExtensionSupported(const char *extension)
{
// we need a valid context to query for extensions.
const GLint defaultAttribs[] = { AGL_RGBA, AGL_DOUBLEBUFFER, AGL_NONE };
AGLPixelFormat fmt = aglChoosePixelFormat(NULL, 0, defaultAttribs);
AGLContext ctx = aglCreateContext(fmt, NULL);
if ( !ctx )
return false;
wxString extensions = wxString::FromAscii(glGetString(GL_EXTENSIONS));
aglDestroyPixelFormat(fmt);
aglDestroyContext(ctx);
return IsExtensionInList(extensions, extension);
}
/* static */
bool wxGLCanvas::IsAGLMultiSampleAvailable()
{
static int s_isMultiSampleAvailable = -1;
if ( s_isMultiSampleAvailable == -1 )
s_isMultiSampleAvailable = IsExtensionSupported("GL_ARB_multisample");
return s_isMultiSampleAvailable != 0;
}
static AGLPixelFormat ChoosePixelFormat(const int *attribList)
{
GLint data[512];
const GLint defaultAttribs[] =
{
AGL_RGBA,
AGL_DOUBLEBUFFER,
AGL_MINIMUM_POLICY, // never choose less than requested
AGL_DEPTH_SIZE, 1, // use largest available depth buffer
AGL_RED_SIZE, 1,
AGL_GREEN_SIZE, 1,
AGL_BLUE_SIZE, 1,
AGL_ALPHA_SIZE, 0,
AGL_NONE
};
const GLint *attribs;
if ( !attribList )
{
attribs = defaultAttribs;
}
else
{
unsigned p = 0;
data[p++] = AGL_MINIMUM_POLICY; // make _SIZE tags behave more like GLX
for ( unsigned arg = 0; attribList[arg] !=0 && p < WXSIZEOF(data); )
{
switch ( attribList[arg++] )
{
case WX_GL_RGBA:
data[p++] = AGL_RGBA;
break;
case WX_GL_BUFFER_SIZE:
data[p++] = AGL_BUFFER_SIZE;
data[p++] = attribList[arg++];
break;
case WX_GL_LEVEL:
data[p++]=AGL_LEVEL;
data[p++]=attribList[arg++];
break;
case WX_GL_DOUBLEBUFFER:
data[p++] = AGL_DOUBLEBUFFER;
break;
case WX_GL_STEREO:
data[p++] = AGL_STEREO;
break;
case WX_GL_AUX_BUFFERS:
data[p++] = AGL_AUX_BUFFERS;
data[p++] = attribList[arg++];
break;
case WX_GL_MIN_RED:
data[p++] = AGL_RED_SIZE;
data[p++] = attribList[arg++];
break;
case WX_GL_MIN_GREEN:
data[p++] = AGL_GREEN_SIZE;
data[p++] = attribList[arg++];
break;
case WX_GL_MIN_BLUE:
data[p++] = AGL_BLUE_SIZE;
data[p++] = attribList[arg++];
break;
case WX_GL_MIN_ALPHA:
data[p++] = AGL_ALPHA_SIZE;
data[p++] = attribList[arg++];
break;
case WX_GL_DEPTH_SIZE:
data[p++] = AGL_DEPTH_SIZE;
data[p++] = attribList[arg++];
break;
case WX_GL_STENCIL_SIZE:
data[p++] = AGL_STENCIL_SIZE;
data[p++] = attribList[arg++];
break;
case WX_GL_MIN_ACCUM_RED:
data[p++] = AGL_ACCUM_RED_SIZE;
data[p++] = attribList[arg++];
break;
case WX_GL_MIN_ACCUM_GREEN:
data[p++] = AGL_ACCUM_GREEN_SIZE;
data[p++] = attribList[arg++];
break;
case WX_GL_MIN_ACCUM_BLUE:
data[p++] = AGL_ACCUM_BLUE_SIZE;
data[p++] = attribList[arg++];
break;
case WX_GL_MIN_ACCUM_ALPHA:
data[p++] = AGL_ACCUM_ALPHA_SIZE;
data[p++] = attribList[arg++];
break;
case WX_GL_SAMPLE_BUFFERS:
if ( !wxGLCanvas::IsAGLMultiSampleAvailable() )
{
if ( !attribList[arg++] )
break;
return false;
}
data[p++] = AGL_SAMPLE_BUFFERS_ARB;
if ( (data[p++] = attribList[arg++]) == true )
{
// don't use software fallback
data[p++] = AGL_NO_RECOVERY;
}
break;
case WX_GL_SAMPLES:
if ( !wxGLCanvas::IsAGLMultiSampleAvailable() )
{
if ( !attribList[arg++] )
break;
return false;
}
data[p++] = AGL_SAMPLES_ARB;
data[p++] = attribList[arg++];
break;
}
}
data[p] = AGL_NONE;
attribs = data;
}
return aglChoosePixelFormat(NULL, 0, attribs);
}
bool wxGLCanvas::Create(wxWindow *parent,
wxWindowID id,
const wxPoint& pos,
const wxSize& size,
long style,
const wxString& name,
const int *attribList,
const wxPalette& WXUNUSED(palette))
{
m_needsUpdate = false;
m_macCanvasIsShown = false;
m_aglFormat = ChoosePixelFormat(attribList);
if ( !m_aglFormat )
return false;
if ( !wxWindow::Create(parent, id, pos, size, style, name) )
return false;
m_macCanvasIsShown = true;
return true;
}
wxGLCanvas::~wxGLCanvas()
{
if ( m_aglFormat )
aglDestroyPixelFormat(m_aglFormat);
}
/* static */
bool wxGLCanvasBase::IsDisplaySupported(const int *attribList)
{
AGLPixelFormat aglFormat = ChoosePixelFormat(attribList);
if ( !aglFormat )
return false;
aglDestroyPixelFormat(aglFormat);
return true;
}
bool wxGLCanvas::SwapBuffers()
{
AGLContext context = aglGetCurrentContext();
wxCHECK_MSG(context, false, _T("should have current context"));
aglSwapBuffers(context);
return true;
}
void wxGLCanvas::SetViewport()
{
if ( !m_needsUpdate )
return;
m_needsUpdate = false;
AGLContext context = aglGetCurrentContext();
if ( !context )
return;
// viewport is initially set to entire port, adjust it to just this window
int x = 0,
y = 0;
MacClientToRootWindow(&x , &y);
int width, height;
GetClientSize(&width, &height);
Rect bounds;
GetWindowPortBounds(MAC_WXHWND(MacGetTopLevelWindowRef()) , &bounds);
#if 0
// TODO in case we adopt point vs pixel coordinates, this will make the conversion
HIRect hiRect = CGRectMake( x, y, width, height );
HIRectConvert( &hiRect, kHICoordSpace72DPIGlobal, NULL, kHICoordSpaceScreenPixel, NULL);
HIRect hiBounds = CGRectMake( 0, 0, bounds.right - bounds.left , bounds.bottom - bounds.top );
HIRectConvert( &hiBounds, kHICoordSpace72DPIGlobal, NULL, kHICoordSpaceScreenPixel, NULL);
GLint parms[4];
parms[0] = hiRect.origin.x;
parms[1] = hiBounds.size.height - (hiRect.origin.y + hiRect.size.height);
parms[2] = hiRect.size.width;
parms[3] = hiRect.size.height;
#else
GLint parms[4];
parms[0] = x;
parms[1] = bounds.bottom - bounds.top - ( y + height );
parms[2] = width;
parms[3] = height;
#endif
// move the buffer rect out of sight if we're hidden
if ( !m_macCanvasIsShown )
parms[0] += 20000;
if ( !aglSetInteger(context, AGL_BUFFER_RECT, parms) )
wxLogAGLError("aglSetInteger(AGL_BUFFER_RECT)");
if ( !aglEnable(context, AGL_BUFFER_RECT) )
wxLogAGLError("aglEnable(AGL_BUFFER_RECT)");
if ( !aglUpdateContext(context) )
wxLogAGLError("aglUpdateContext");
}
void wxGLCanvas::OnSize(wxSizeEvent& event)
{
MacUpdateView();
event.Skip();
}
void wxGLCanvas::MacUpdateView()
{
m_needsUpdate = true;
Refresh(false);
}
void wxGLCanvas::MacSuperChangedPosition()
{
MacUpdateView();
wxWindow::MacSuperChangedPosition();
}
void wxGLCanvas::MacTopLevelWindowChangedPosition()
{
MacUpdateView();
wxWindow::MacTopLevelWindowChangedPosition();
}
void wxGLCanvas::MacVisibilityChanged()
{
if ( IsShownOnScreen() != m_macCanvasIsShown )
{
m_macCanvasIsShown = !m_macCanvasIsShown;
MacUpdateView();
}
wxWindowMac::MacVisibilityChanged();
}
// ----------------------------------------------------------------------------
// wxGLApp
// ----------------------------------------------------------------------------
bool wxGLApp::InitGLVisual(const int *attribList)
{
AGLPixelFormat fmt = ChoosePixelFormat(attribList);
if ( !fmt )
return false;
aglDestroyPixelFormat(fmt);
return true;
}
#endif // wxUSE_GLCANVAS

2594
src/osx/carbon/graphics.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,80 @@
/////////////////////////////////////////////////////////////////////////////
// Name: helpxxxx.cpp
// Purpose: Help system: native implementation
// Author: Stefan Csomor
// Modified by:
// Created: 1998-01-01
// RCS-ID: $Id$
// Copyright: (c) Stefan Csomor
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
#include "wx/wxprec.h"
#include "wx/stubs/helpxxxx.h"
#include <string.h>
IMPLEMENT_DYNAMIC_CLASS(wxXXXXHelpController, wxHelpControllerBase)
wxXXXXHelpController::wxXXXXHelpController()
{
m_helpFile = "";
}
wxXXXXHelpController::~wxXXXXHelpController()
{
}
bool wxXXXXHelpController::Initialize(const wxString& filename)
{
m_helpFile = filename;
// TODO any other inits
return TRUE;
}
bool wxXXXXHelpController::LoadFile(const wxString& file)
{
m_helpFile = file;
// TODO
return TRUE;
}
bool wxXXXXHelpController::DisplayContents()
{
// TODO
return FALSE;
}
bool wxXXXXHelpController::DisplaySection(int section)
{
// TODO
return FALSE;
}
bool wxXXXXHelpController::DisplayBlock(long block)
{
// TODO
return FALSE;
}
bool wxXXXXHelpController::KeywordSearch(const wxString& k,
wxHelpSearchMode WXUNUSED(mode))
{
if (m_helpFile == "") return FALSE;
// TODO
return FALSE;
}
// Can't close the help window explicitly in WinHelp
bool wxXXXXHelpController::Quit()
{
// TODO
return FALSE;
}
void wxXXXXHelpController::OnQuit()
{
}

317
src/osx/carbon/icon.cpp Normal file
View File

@@ -0,0 +1,317 @@
/////////////////////////////////////////////////////////////////////////////
// Name: src/mac/carbon/icon.cpp
// Purpose: wxIcon class
// Author: Stefan Csomor
// Modified by:
// Created: 1998-01-01
// RCS-ID: $Id$
// Copyright: (c) Stefan Csomor
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
#include "wx/wxprec.h"
#include "wx/icon.h"
#ifndef WX_PRECOMP
#include "wx/image.h"
#endif
#include "wx/mac/private.h"
IMPLEMENT_DYNAMIC_CLASS(wxIcon, wxGDIObject)
#define M_ICONDATA ((wxIconRefData *)m_refData)
class WXDLLEXPORT wxIconRefData : public wxGDIRefData
{
public:
wxIconRefData() { Init(); }
wxIconRefData( WXHICON iconref, int desiredWidth, int desiredHeight );
virtual ~wxIconRefData() { Free(); }
virtual bool IsOk() const { return m_iconRef != NULL; }
virtual void Free();
void SetWidth( int width ) { m_width = width; }
void SetHeight( int height ) { m_height = height; }
int GetWidth() const { return m_width; }
int GetHeight() const { return m_height; }
WXHICON GetHICON() const { return (WXHICON) m_iconRef; }
private:
void Init();
IconRef m_iconRef;
int m_width;
int m_height;
};
wxIconRefData::wxIconRefData( WXHICON icon, int desiredWidth, int desiredHeight )
{
m_iconRef = MAC_WXHICON( icon ) ;
// Standard sizes
SetWidth( desiredWidth == -1 ? 32 : desiredWidth ) ;
SetHeight( desiredHeight == -1 ? 32 : desiredHeight ) ;
}
void wxIconRefData::Init()
{
m_iconRef = NULL ;
m_width =
m_height = 0;
}
void wxIconRefData::Free()
{
if ( m_iconRef )
{
ReleaseIconRef( m_iconRef ) ;
m_iconRef = NULL ;
}
}
//
//
//
wxIcon::wxIcon()
{
}
wxIcon::wxIcon( const char bits[], int width, int height )
{
wxBitmap bmp( bits, width, height ) ;
CopyFromBitmap( bmp ) ;
}
wxIcon::wxIcon(const char* const* bits)
{
wxBitmap bmp( bits ) ;
CopyFromBitmap( bmp ) ;
}
wxIcon::wxIcon(
const wxString& icon_file, int flags,
int desiredWidth, int desiredHeight )
{
LoadFile( icon_file, (wxBitmapType) flags, desiredWidth, desiredHeight );
}
wxIcon::wxIcon(WXHICON icon, const wxSize& size)
: wxGDIObject()
{
// as the icon owns that ref, we have to acquire it as well
if (icon)
AcquireIconRef( (IconRef) icon ) ;
m_refData = new wxIconRefData( icon, size.x, size.y ) ;
}
wxIcon::~wxIcon()
{
}
wxGDIRefData *wxIcon::CreateGDIRefData() const
{
return new wxIconRefData;
}
wxGDIRefData *wxIcon::CloneGDIRefData(const wxGDIRefData *data) const
{
return new wxIconRefData(*wx_static_cast(const wxIconRefData *, data));
}
WXHICON wxIcon::GetHICON() const
{
wxASSERT( Ok() ) ;
return (WXHICON) ((wxIconRefData*)m_refData)->GetHICON() ;
}
int wxIcon::GetWidth() const
{
wxCHECK_MSG( Ok(), -1, wxT("invalid icon") );
return M_ICONDATA->GetWidth();
}
int wxIcon::GetHeight() const
{
wxCHECK_MSG( Ok(), -1, wxT("invalid icon") );
return M_ICONDATA->GetHeight();
}
int wxIcon::GetDepth() const
{
return 32;
}
void wxIcon::SetDepth( int WXUNUSED(depth) )
{
}
void wxIcon::SetWidth( int WXUNUSED(width) )
{
}
void wxIcon::SetHeight( int WXUNUSED(height) )
{
}
bool wxIcon::LoadFile(
const wxString& filename, wxBitmapType type,
int desiredWidth, int desiredHeight )
{
UnRef();
if ( type == wxBITMAP_TYPE_ICON_RESOURCE )
{
OSType theId = 0 ;
if ( filename == wxT("wxICON_INFORMATION") )
{
theId = kAlertNoteIcon ;
}
else if ( filename == wxT("wxICON_QUESTION") )
{
theId = kAlertCautionIcon ;
}
else if ( filename == wxT("wxICON_WARNING") )
{
theId = kAlertCautionIcon ;
}
else if ( filename == wxT("wxICON_ERROR") )
{
theId = kAlertStopIcon ;
}
else if ( filename == wxT("wxICON_FOLDER") )
{
theId = kGenericFolderIcon ;
}
else if ( filename == wxT("wxICON_FOLDER_OPEN") )
{
theId = kOpenFolderIcon ;
}
else if ( filename == wxT("wxICON_NORMAL_FILE") )
{
theId = kGenericDocumentIcon ;
}
else
{
IconRef iconRef = NULL ;
// first look in the resource fork
if ( iconRef == NULL )
{
Str255 theName ;
wxMacStringToPascal( filename , theName ) ;
Handle resHandle = GetNamedResource( 'icns' , theName ) ;
if ( resHandle != 0L )
{
IconFamilyHandle iconFamily = (IconFamilyHandle) resHandle ;
HLock((Handle) iconFamily);
OSStatus err = GetIconRefFromIconFamilyPtr( *iconFamily, GetHandleSize((Handle) iconFamily), &iconRef );
HUnlock((Handle) iconFamily);
if ( err != noErr )
{
wxFAIL_MSG("Error when constructing icon ref");
}
ReleaseResource( resHandle ) ;
}
}
if ( iconRef == NULL )
{
// TODO add other attempts to load it from files etc here
}
if ( iconRef )
{
m_refData = new wxIconRefData( (WXHICON) iconRef, desiredWidth, desiredHeight ) ;
return true ;
}
}
if ( theId != 0 )
{
IconRef iconRef = NULL ;
verify_noerr( GetIconRef( kOnSystemDisk, kSystemIconsCreator, theId, &iconRef ) ) ;
if ( iconRef )
{
m_refData = new wxIconRefData( (WXHICON) iconRef, desiredWidth, desiredHeight ) ;
return true ;
}
}
return false ;
}
else
{
wxBitmapHandler *handler = wxBitmap::FindHandler( type );
if ( handler )
{
wxBitmap bmp ;
if ( handler->LoadFile( &bmp , filename, type, desiredWidth, desiredHeight ))
{
CopyFromBitmap( bmp ) ;
return true ;
}
return false ;
}
else
{
#if wxUSE_IMAGE
wxImage loadimage( filename, type );
if (loadimage.Ok())
{
if ( desiredWidth == -1 )
desiredWidth = loadimage.GetWidth() ;
if ( desiredHeight == -1 )
desiredHeight = loadimage.GetHeight() ;
if ( desiredWidth != loadimage.GetWidth() || desiredHeight != loadimage.GetHeight() )
loadimage.Rescale( desiredWidth , desiredHeight ) ;
wxBitmap bmp( loadimage );
CopyFromBitmap( bmp ) ;
return true;
}
#endif
}
}
return true ;
}
void wxIcon::CopyFromBitmap( const wxBitmap& bmp )
{
UnRef() ;
// as the bitmap owns that ref, we have to acquire it as well
IconRef iconRef = bmp.CreateIconRef() ;
m_refData = new wxIconRefData( (WXHICON) iconRef, bmp.GetWidth(), bmp.GetHeight() ) ;
}
IMPLEMENT_DYNAMIC_CLASS(wxICONResourceHandler, wxBitmapHandler)
bool wxICONResourceHandler::LoadFile(
wxBitmap *bitmap, const wxString& name, long WXUNUSED(flags),
int desiredWidth, int desiredHeight )
{
wxIcon icon ;
icon.LoadFile( name , wxBITMAP_TYPE_ICON_RESOURCE , desiredWidth , desiredHeight ) ;
bitmap->CopyFromIcon( icon ) ;
return bitmap->Ok() ;
}

309
src/osx/carbon/imaglist.cpp Normal file
View File

@@ -0,0 +1,309 @@
/////////////////////////////////////////////////////////////////////////////
// Name: src/mac/carbon/imaglist.cpp
// Purpose:
// Author: Robert Roebling
// RCS_ID: $Id$
// Copyright: (c) 1998 Robert Roebling
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#if wxUSE_IMAGLIST
#include "wx/imaglist.h"
#ifndef WX_PRECOMP
#include "wx/dc.h"
#include "wx/icon.h"
#include "wx/image.h"
#endif
IMPLEMENT_DYNAMIC_CLASS(wxImageList, wxObject)
wxImageList::wxImageList( int width, int height, bool mask, int initialCount )
{
(void)Create(width, height, mask, initialCount);
}
wxImageList::~wxImageList()
{
(void)RemoveAll();
}
int wxImageList::GetImageCount() const
{
return m_images.GetCount();
}
bool wxImageList::Create( int width, int height, bool WXUNUSED(mask), int WXUNUSED(initialCount) )
{
m_width = width;
m_height = height;
return Create();
}
bool wxImageList::Create()
{
return true;
}
int wxImageList::Add( const wxIcon &bitmap )
{
wxASSERT_MSG( (bitmap.GetWidth() == m_width && bitmap.GetHeight() == m_height)
|| (m_width == 0 && m_height == 0),
_T("invalid bitmap size in wxImageList: this might work ")
_T("on this platform but definitely won't under Windows.") );
m_images.Append( new wxIcon( bitmap ) );
if (m_width == 0 && m_height == 0)
{
m_width = bitmap.GetWidth();
m_height = bitmap.GetHeight();
}
return m_images.GetCount() - 1;
}
int wxImageList::Add( const wxBitmap &bitmap )
{
wxASSERT_MSG( (bitmap.GetWidth() >= m_width && bitmap.GetHeight() == m_height)
|| (m_width == 0 && m_height == 0),
_T("invalid bitmap size in wxImageList: this might work ")
_T("on this platform but definitely won't under Windows.") );
// Mimic behavior of Windows ImageList_Add that automatically breaks up the added
// bitmap into sub-images of the correct size
if (m_width > 0 && bitmap.GetWidth() > m_width && bitmap.GetHeight() >= m_height)
{
int numImages = bitmap.GetWidth() / m_width;
for (int subIndex = 0; subIndex < numImages; subIndex++)
{
wxRect rect(m_width * subIndex, 0, m_width, m_height);
wxBitmap tmpBmp = bitmap.GetSubBitmap(rect);
m_images.Append( new wxBitmap(tmpBmp) );
}
}
else
{
m_images.Append( new wxBitmap(bitmap) );
}
if (m_width == 0 && m_height == 0)
{
m_width = bitmap.GetWidth();
m_height = bitmap.GetHeight();
}
return m_images.GetCount() - 1;
}
int wxImageList::Add( const wxBitmap& bitmap, const wxBitmap& mask )
{
wxBitmap bmp( bitmap );
if (mask.Ok())
bmp.SetMask( new wxMask( mask ) );
return Add( bmp );
}
int wxImageList::Add( const wxBitmap& bitmap, const wxColour& maskColour )
{
wxImage img = bitmap.ConvertToImage();
img.SetMaskColour( maskColour.Red(), maskColour.Green(), maskColour.Blue() );
return Add( wxBitmap( img ) );
}
// Get the bitmap
wxBitmap wxImageList::GetBitmap(int index) const
{
wxList::compatibility_iterator node = m_images.Item( index );
wxCHECK_MSG( node, wxNullBitmap , wxT("wrong index in image list") );
wxObject* obj = (wxObject*) node->GetData();
if ( obj == NULL )
return wxNullBitmap ;
else if ( obj->IsKindOf(CLASSINFO(wxIcon)) )
return wxBitmap( *(wx_static_cast(wxIcon*, obj)) ) ;
else
return *(wx_static_cast(wxBitmap*, obj)) ;
}
// Get the icon
wxIcon wxImageList::GetIcon(int index) const
{
wxList::compatibility_iterator node = m_images.Item( index );
wxCHECK_MSG( node, wxNullIcon , wxT("wrong index in image list") );
wxObject* obj = (wxObject*) node->GetData();
if ( obj == NULL )
return wxNullIcon ;
else if ( obj->IsKindOf(CLASSINFO(wxBitmap)) )
{
wxFAIL_MSG( wxT("cannot convert from bitmap to icon") ) ;
return wxNullIcon ;
}
else
return *(wx_static_cast(wxIcon*, obj)) ;
}
bool wxImageList::Replace( int index, const wxBitmap &bitmap )
{
wxList::compatibility_iterator node = m_images.Item( index );
wxCHECK_MSG( node, false, wxT("wrong index in image list") );
wxBitmap* newBitmap = new wxBitmap( bitmap );
if (index == (int) m_images.GetCount() - 1)
{
delete node->GetData();
m_images.Erase( node );
m_images.Append( newBitmap );
}
else
{
wxList::compatibility_iterator next = node->GetNext();
delete node->GetData();
m_images.Erase( node );
m_images.Insert( next, newBitmap );
}
return true;
}
bool wxImageList::Replace( int index, const wxIcon &bitmap )
{
wxList::compatibility_iterator node = m_images.Item( index );
wxCHECK_MSG( node, false, wxT("wrong index in image list") );
wxIcon* newBitmap = new wxIcon( bitmap );
if (index == (int) m_images.GetCount() - 1)
{
delete node->GetData();
m_images.Erase( node );
m_images.Append( newBitmap );
}
else
{
wxList::compatibility_iterator next = node->GetNext();
delete node->GetData();
m_images.Erase( node );
m_images.Insert( next, newBitmap );
}
return true;
}
bool wxImageList::Replace( int index, const wxBitmap &bitmap, const wxBitmap &mask )
{
wxList::compatibility_iterator node = m_images.Item( index );
wxCHECK_MSG( node, false, wxT("wrong index in image list") );
wxBitmap* newBitmap = new wxBitmap(bitmap);
if (index == (int) m_images.GetCount() - 1)
{
delete node->GetData();
m_images.Erase( node );
m_images.Append( newBitmap );
}
else
{
wxList::compatibility_iterator next = node->GetNext();
delete node->GetData();
m_images.Erase( node );
m_images.Insert( next, newBitmap );
}
if (mask.Ok())
newBitmap->SetMask(new wxMask(mask));
return true;
}
bool wxImageList::Remove( int index )
{
wxList::compatibility_iterator node = m_images.Item( index );
wxCHECK_MSG( node, false, wxT("wrong index in image list") );
delete node->GetData();
m_images.Erase( node );
return true;
}
bool wxImageList::RemoveAll()
{
WX_CLEAR_LIST(wxList, m_images);
m_images.Clear();
return true;
}
bool wxImageList::GetSize( int index, int &width, int &height ) const
{
width = 0;
height = 0;
wxList::compatibility_iterator node = m_images.Item( index );
wxCHECK_MSG( node, false, wxT("wrong index in image list") );
wxObject *obj = (wxObject*)node->GetData();
if (obj->IsKindOf(CLASSINFO(wxIcon)))
{
wxIcon *bm = wx_static_cast( wxIcon* , obj ) ;
width = bm->GetWidth();
height = bm->GetHeight();
}
else
{
wxBitmap *bm = wx_static_cast( wxBitmap* , obj ) ;
width = bm->GetWidth();
height = bm->GetHeight();
}
return true;
}
bool wxImageList::Draw(
int index, wxDC &dc, int x, int y,
int flags, bool WXUNUSED(solidBackground) )
{
wxList::compatibility_iterator node = m_images.Item( index );
wxCHECK_MSG( node, false, wxT("wrong index in image list") );
wxObject *obj = (wxObject*)node->GetData();
if (obj->IsKindOf(CLASSINFO(wxIcon)))
{
wxIcon *bm = wx_static_cast( wxIcon* , obj ) ;
dc.DrawIcon( *bm , x, y );
}
else
{
wxBitmap *bm = wx_static_cast( wxBitmap* , obj ) ;
dc.DrawBitmap( *bm, x, y, (flags & wxIMAGELIST_DRAW_TRANSPARENT) > 0 );
}
return true;
}
#endif // wxUSE_IMAGLIST

View File

@@ -0,0 +1 @@
// todo remove

628
src/osx/carbon/listbox.cpp Normal file
View File

@@ -0,0 +1,628 @@
///////////////////////////////////////////////////////////////////////////////
// Name: src/mac/carbon/listbox.cpp
// Purpose: wxListBox
// Author: Stefan Csomor
// Modified by:
// Created: 1998-01-01
// RCS-ID: $Id$
// Copyright: (c) Stefan Csomor
// Licence: wxWindows licence
///////////////////////////////////////////////////////////////////////////////
#include "wx/wxprec.h"
#if wxUSE_LISTBOX
#include "wx/listbox.h"
#ifndef WX_PRECOMP
#include "wx/log.h"
#include "wx/intl.h"
#include "wx/utils.h"
#include "wx/settings.h"
#include "wx/arrstr.h"
#include "wx/dcclient.h"
#endif
IMPLEMENT_DYNAMIC_CLASS(wxListBox, wxControlWithItems)
BEGIN_EVENT_TABLE(wxListBox, wxControl)
END_EVENT_TABLE()
#include "wx/mac/uma.h"
// ============================================================================
// list box control implementation
// ============================================================================
wxListBox::wxListBox()
{
}
bool wxListBox::Create(
wxWindow *parent,
wxWindowID id,
const wxPoint& pos,
const wxSize& size,
const wxArrayString& choices,
long style,
const wxValidator& validator,
const wxString& name )
{
wxCArrayString chs(choices);
return Create(
parent, id, pos, size, chs.GetCount(), chs.GetStrings(),
style, validator, name );
}
wxMacListControl* wxListBox::GetPeer() const
{
wxMacDataBrowserListControl *lb = wxDynamicCast(m_peer,wxMacDataBrowserListControl);
return lb ? wx_static_cast(wxMacListControl*,lb) : 0 ;
}
bool wxListBox::Create(
wxWindow *parent,
wxWindowID id,
const wxPoint& pos,
const wxSize& size,
int n,
const wxString choices[],
long style,
const wxValidator& validator,
const wxString& name )
{
m_blockEvents = false;
m_macIsUserPane = false;
wxASSERT_MSG( !(style & wxLB_MULTIPLE) || !(style & wxLB_EXTENDED),
wxT("only a single listbox selection mode can be specified") );
if ( !wxListBoxBase::Create( parent, id, pos, size, style & ~(wxHSCROLL | wxVSCROLL), validator, name ) )
return false;
wxMacDataBrowserListControl* control = new wxMacDataBrowserListControl( this, pos, size, style );
// TODO CHECK control->SetClientDataType( m_clientDataItemsType );
m_peer = control;
MacPostControlCreate( pos, size );
Append(n, choices);
// Needed because it is a wxControlWithItems
SetInitialSize( size );
return true;
}
wxListBox::~wxListBox()
{
FreeData();
m_peer->SetReference( 0 );
}
void wxListBox::FreeData()
{
GetPeer()->MacClear();
}
void wxListBox::DoSetFirstItem(int n)
{
GetPeer()->MacScrollTo( n );
}
void wxListBox::EnsureVisible(int n)
{
GetPeer()->MacScrollTo( n );
}
void wxListBox::DoDeleteOneItem(unsigned int n)
{
wxCHECK_RET( IsValid(n), wxT("invalid index in wxListBox::Delete") );
m_blockEvents = true;
GetPeer()->MacDelete( n );
m_blockEvents = false;
UpdateOldSelections();
}
int wxListBox::DoInsertItems(const wxArrayStringsAdapter& items,
unsigned int pos,
void **clientData,
wxClientDataType type)
{
InvalidateBestSize();
GetPeer()->MacInsert( pos, items );
const unsigned int count = items.GetCount();
if ( clientData )
{
for (unsigned int i = 0; i < count; ++i)
AssignNewItemClientData( pos + i, clientData, i, type );
}
return pos + count - 1;
UpdateOldSelections();
}
int wxListBox::FindString(const wxString& s, bool bCase) const
{
for ( size_t i = 0; i < GetCount(); ++ i )
{
if (s.IsSameAs( GetString( i ), bCase) )
return (int)i;
}
return wxNOT_FOUND;
}
void wxListBox::DoClear()
{
m_blockEvents = true;
FreeData();
m_blockEvents = false;
UpdateOldSelections();
}
void wxListBox::DoSetSelection(int n, bool select)
{
wxCHECK_RET( n == wxNOT_FOUND || IsValid(n),
wxT("invalid index in wxListBox::SetSelection") );
m_blockEvents = true;
if ( n == wxNOT_FOUND )
GetPeer()->MacDeselectAll();
else
GetPeer()->MacSetSelection( n, select, HasMultipleSelection() );
m_blockEvents = false;
UpdateOldSelections();
}
bool wxListBox::IsSelected(int n) const
{
wxCHECK_MSG( IsValid(n), false, wxT("invalid index in wxListBox::Selected") );
return GetPeer()->MacIsSelected( n );
}
void *wxListBox::DoGetItemClientData(unsigned int n) const
{
wxCHECK_MSG( IsValid(n), NULL, wxT("invalid index in wxListBox::GetClientData"));
return GetPeer()->MacGetClientData( n );
}
void wxListBox::DoSetItemClientData(unsigned int n, void *clientData)
{
wxCHECK_RET( IsValid(n), wxT("invalid index in wxListBox::SetClientData") );
GetPeer()->MacSetClientData( n , clientData);
}
// Return number of selections and an array of selected integers
int wxListBox::GetSelections(wxArrayInt& aSelections) const
{
return GetPeer()->MacGetSelections( aSelections );
}
// Get single selection, for single choice list items
int wxListBox::GetSelection() const
{
return GetPeer()->MacGetSelection();
}
// Find string for position
wxString wxListBox::GetString(unsigned int n) const
{
wxCHECK_MSG( IsValid(n), wxEmptyString, wxT("invalid index in wxListBox::GetString") );
return GetPeer()->MacGetString(n);
}
void wxListBox::SetString(unsigned int n, const wxString& s)
{
GetPeer()->MacSetString( n, s );
}
wxSize wxListBox::DoGetBestSize() const
{
int lbWidth = 100; // some defaults
int lbHeight = 110;
int wLine;
{
wxClientDC dc(const_cast<wxListBox*>(this));
dc.SetFont(GetFont());
// Find the widest line
for (unsigned int i = 0; i < GetCount(); i++)
{
wxString str( GetString( i ) );
wxCoord width, height ;
dc.GetTextExtent( str , &width, &height);
wLine = width ;
lbWidth = wxMax( lbWidth, wLine );
}
// Add room for the scrollbar
lbWidth += wxSystemSettings::GetMetric( wxSYS_VSCROLL_X );
// And just a bit more
int cy = 12;
wxCoord width, height ;
dc.GetTextExtent( wxT("XX") , &width, &height);
int cx = width ;
lbWidth += cx;
// don't make the listbox too tall (limit height to around 10 items)
// but don't make it too small neither
lbHeight = wxMax( (cy + 4) * wxMin( wxMax( GetCount(), 3 ), 10 ), 70 );
}
return wxSize( lbWidth, lbHeight );
}
unsigned int wxListBox::GetCount() const
{
return GetPeer()->MacGetCount();
}
void wxListBox::Refresh(bool eraseBack, const wxRect *rect)
{
wxControl::Refresh( eraseBack, rect );
}
// Some custom controls depend on this
/* static */ wxVisualAttributes
wxListBox::GetClassDefaultAttributes(wxWindowVariant WXUNUSED(variant))
{
wxVisualAttributes attr;
attr.colFg = wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOWTEXT );
attr.colBg = wxSystemSettings::GetColour( wxSYS_COLOUR_LISTBOX );
attr.font.MacCreateFromThemeFont(kThemeViewsFont);
return attr;
}
int wxListBox::DoListHitTest(const wxPoint& inpoint) const
{
OSStatus err;
// There are few reasons why this is complicated:
// 1) There is no native HitTest function for Mac
// 2) GetDataBrowserItemPartBounds only works on visible items
// 3) We can't do it through GetDataBrowserTableView[Item]RowHeight
// because what it returns is basically inaccurate in the context
// of the coordinates we want here, but we use this as a guess
// for where the first visible item lies
wxPoint point = inpoint;
// get column property ID (req. for call to itempartbounds)
DataBrowserTableViewColumnID colId = 0;
err = GetDataBrowserTableViewColumnProperty(m_peer->GetControlRef(), 0, &colId);
wxCHECK_MSG(err == noErr, wxNOT_FOUND, wxT("Unexpected error from GetDataBrowserTableViewColumnProperty"));
// OK, first we need to find the first visible item we have -
// this will be the "low" for our binary search. There is no real
// easy way around this, as we will need to do a SLOW linear search
// until we find a visible item, but we can do a cheap calculation
// via the row height to speed things up a bit
UInt32 scrollx, scrolly;
err = GetDataBrowserScrollPosition(m_peer->GetControlRef(), &scrollx, &scrolly);
wxCHECK_MSG(err == noErr, wxNOT_FOUND, wxT("Unexpected error from GetDataBrowserScrollPosition"));
UInt16 height;
err = GetDataBrowserTableViewRowHeight(m_peer->GetControlRef(), &height);
wxCHECK_MSG(err == noErr, wxNOT_FOUND, wxT("Unexpected error from GetDataBrowserTableViewRowHeight"));
// these indices are 0-based, as usual, so we need to add 1 to them when
// passing them to data browser functions which use 1-based indices
int low = scrolly / height,
high = GetCount() - 1;
// search for the first visible item (note that the scroll guess above
// is the low bounds of where the item might lie so we only use that as a
// starting point - we should reach it within 1 or 2 iterations of the loop)
while ( low <= high )
{
Rect bounds;
err = GetDataBrowserItemPartBounds(
m_peer->GetControlRef(), low + 1, colId,
kDataBrowserPropertyEnclosingPart,
&bounds); // note +1 to translate to Mac ID
if ( err == noErr )
break;
// errDataBrowserItemNotFound is expected as it simply means that the
// item is not currently visible -- but other errors are not
wxCHECK_MSG( err == errDataBrowserItemNotFound, wxNOT_FOUND,
wxT("Unexpected error from GetDataBrowserItemPartBounds") );
low++;
}
// NOW do a binary search for where the item lies, searching low again if
// we hit an item that isn't visible
while ( low <= high )
{
int mid = (low + high) / 2;
Rect bounds;
err = GetDataBrowserItemPartBounds(
m_peer->GetControlRef(), mid + 1, colId,
kDataBrowserPropertyEnclosingPart,
&bounds); //note +1 to trans to mac id
wxCHECK_MSG( err == noErr || err == errDataBrowserItemNotFound,
wxNOT_FOUND,
wxT("Unexpected error from GetDataBrowserItemPartBounds") );
if ( err == errDataBrowserItemNotFound )
{
// item not visible, attempt to find a visible one
// search lower
high = mid - 1;
}
else // visible item, do actual hitttest
{
// if point is within the bounds, return this item (since we assume
// all x coords of items are equal we only test the x coord in
// equality)
if ((point.x >= bounds.left && point.x <= bounds.right) &&
(point.y >= bounds.top && point.y <= bounds.bottom) )
{
// found!
return mid;
}
if ( point.y < bounds.top )
// index(bounds) greater then key(point)
high = mid - 1;
else
// index(bounds) less then key(point)
low = mid + 1;
}
}
return wxNOT_FOUND;
}
// ============================================================================
// data browser based implementation
// ============================================================================
wxMacListBoxItem::wxMacListBoxItem()
:wxMacDataItem()
{
}
wxMacListBoxItem::~wxMacListBoxItem()
{
}
void wxMacListBoxItem::Notification(wxMacDataItemBrowserControl *owner ,
DataBrowserItemNotification message,
DataBrowserItemDataRef WXUNUSED(itemData) ) const
{
wxMacDataBrowserListControl *lb = wxDynamicCast(owner,wxMacDataBrowserListControl);
// we want to depend on as little as possible to make sure tear-down of controls is safe
if ( message == kDataBrowserItemRemoved)
{
if ( lb != NULL && lb->GetClientDataType() == wxClientData_Object )
{
delete (wxClientData*) (m_data);
}
delete this;
return;
}
wxListBox *list = wxDynamicCast( owner->GetPeer() , wxListBox );
wxCHECK_RET( list != NULL , wxT("Listbox expected"));
if (message == kDataBrowserItemDoubleClicked)
{
wxCommandEvent event( wxEVT_COMMAND_LISTBOX_DOUBLECLICKED, list->GetId() );
event.SetEventObject( list );
if ( list->HasClientObjectData() )
event.SetClientObject( (wxClientData*) m_data );
else if ( list->HasClientUntypedData() )
event.SetClientData( m_data );
event.SetString( m_label );
event.SetInt( owner->GetLineFromItem( this ) );
event.SetExtraLong( 1 );
list->HandleWindowEvent(event);
return;
}
}
IMPLEMENT_DYNAMIC_CLASS( wxMacDataBrowserListControl , wxMacDataItemBrowserControl )
wxMacDataBrowserListControl::wxMacDataBrowserListControl( wxWindow *peer, const wxPoint& pos, const wxSize& size, long style)
: wxMacDataItemBrowserControl( peer, pos, size, style )
{
OSStatus err = noErr;
m_clientDataItemsType = wxClientData_None;
if ( style & wxLB_SORT )
m_sortOrder = SortOrder_Text_Ascending;
DataBrowserSelectionFlags options = kDataBrowserDragSelect;
if ( style & wxLB_MULTIPLE )
{
options |= kDataBrowserAlwaysExtendSelection | kDataBrowserCmdTogglesSelection;
}
else if ( style & wxLB_EXTENDED )
{
options |= kDataBrowserCmdTogglesSelection;
}
else
{
options |= kDataBrowserSelectOnlyOne;
}
err = SetSelectionFlags( options );
verify_noerr( err );
DataBrowserListViewColumnDesc columnDesc;
columnDesc.headerBtnDesc.titleOffset = 0;
columnDesc.headerBtnDesc.version = kDataBrowserListViewLatestHeaderDesc;
columnDesc.headerBtnDesc.btnFontStyle.flags =
kControlUseFontMask | kControlUseJustMask;
columnDesc.headerBtnDesc.btnContentInfo.contentType = kControlNoContent;
columnDesc.headerBtnDesc.btnFontStyle.just = teFlushDefault;
columnDesc.headerBtnDesc.btnFontStyle.font = kControlFontViewSystemFont;
columnDesc.headerBtnDesc.btnFontStyle.style = normal;
columnDesc.headerBtnDesc.titleString = NULL;
columnDesc.headerBtnDesc.minimumWidth = 0;
columnDesc.headerBtnDesc.maximumWidth = 10000;
columnDesc.propertyDesc.propertyID = kTextColumnId;
columnDesc.propertyDesc.propertyType = kDataBrowserTextType;
columnDesc.propertyDesc.propertyFlags = kDataBrowserTableViewSelectionColumn;
columnDesc.propertyDesc.propertyFlags |= kDataBrowserListViewTypeSelectColumn;
verify_noerr( AddColumn( &columnDesc, kDataBrowserListViewAppendColumn ) );
columnDesc.headerBtnDesc.minimumWidth = 0;
columnDesc.headerBtnDesc.maximumWidth = 0;
columnDesc.propertyDesc.propertyID = kNumericOrderColumnId;
columnDesc.propertyDesc.propertyType = kDataBrowserPropertyRelevanceRankPart;
columnDesc.propertyDesc.propertyFlags = kDataBrowserTableViewSelectionColumn;
columnDesc.propertyDesc.propertyFlags |= kDataBrowserListViewTypeSelectColumn;
verify_noerr( AddColumn( &columnDesc, kDataBrowserListViewAppendColumn ) );
SetDataBrowserSortProperty( m_controlRef , kTextColumnId);
if ( m_sortOrder == SortOrder_Text_Ascending )
{
SetDataBrowserSortProperty( m_controlRef , kTextColumnId);
SetDataBrowserSortOrder( m_controlRef , kDataBrowserOrderIncreasing);
}
else
{
SetDataBrowserSortProperty( m_controlRef , kNumericOrderColumnId);
SetDataBrowserSortOrder( m_controlRef , kDataBrowserOrderIncreasing);
}
verify_noerr( AutoSizeColumns() );
verify_noerr( SetHiliteStyle(kDataBrowserTableViewFillHilite ) );
verify_noerr( SetHeaderButtonHeight( 0 ) );
err = SetHasScrollBars( (style & wxHSCROLL) != 0 , true );
#if 0
// shouldn't be necessary anymore under 10.2
m_peer->SetData( kControlNoPart, kControlDataBrowserIncludesFrameAndFocusTag, (Boolean)false );
m_peer->SetNeedsFocusRect( true );
#endif
}
wxMacDataBrowserListControl::~wxMacDataBrowserListControl()
{
}
void wxMacDataBrowserListControl::ItemNotification(
const wxMacDataItem* itemID,
DataBrowserItemNotification message,
DataBrowserItemDataRef itemData)
{
wxListBox *list = wxDynamicCast( GetPeer() , wxListBox );
wxCHECK_RET( list != NULL , wxT("Listbox expected"));
if (list->HasMultipleSelection() && (message == kDataBrowserSelectionSetChanged) && (!list->MacGetBlockEvents()))
{
list->CalcAndSendEvent();
return;
}
if ((message == kDataBrowserSelectionSetChanged) && (!list->MacGetBlockEvents()))
{
wxCommandEvent event( wxEVT_COMMAND_LISTBOX_SELECTED, list->GetId() );
int sel = list->GetSelection();
if ((sel < 0) || (sel > list->GetCount())) // OS X can select an item below the last item (why?)
return;
event.SetEventObject( list );
if ( list->HasClientObjectData() )
event.SetClientObject( list->GetClientObject( sel ) );
else if ( list->HasClientUntypedData() )
event.SetClientData( list->GetClientData( sel ) );
event.SetString( list->GetString( sel ) );
event.SetInt( sel );
event.SetExtraLong( 1 );
list->HandleWindowEvent(event);
return;
}
// call super for item level(wxMacDataItem->Notification) callback processing
wxMacDataItemBrowserControl::ItemNotification( itemID, message, itemData);
}
wxWindow * wxMacDataBrowserListControl::GetPeer() const
{
return wxDynamicCast( wxMacControl::GetPeer() , wxWindow );
}
wxMacDataItem* wxMacDataBrowserListControl::CreateItem()
{
return new wxMacListBoxItem();
}
#if 0
// in case we need that one day
// ============================================================================
// HIView owner-draw-based implementation
// ============================================================================
static pascal void ListBoxDrawProc(
ControlRef browser, DataBrowserItemID item, DataBrowserPropertyID property,
DataBrowserItemState itemState, const Rect *itemRect, SInt16 depth, Boolean isColorDevice )
{
CFStringRef cfString;
ThemeDrawingState themeState;
long systemVersion;
GetThemeDrawingState( &themeState );
cfString = CFStringCreateWithFormat( NULL, NULL, CFSTR("Row %d"), item );
// In this sample we handle the "selected" state; all others fall through to our "active" state
if ( itemState == kDataBrowserItemIsSelected )
{
ThemeBrush colorBrushID;
// TODO: switch over to wxSystemSettingsNative::GetColour() when kThemeBrushSecondaryHighlightColor
// is incorporated Panther DB starts using kThemeBrushSecondaryHighlightColor
// for inactive browser highlighting
if ( !IsControlActive( browser ) )
colorBrushID = kThemeBrushSecondaryHighlightColor;
else
colorBrushID = kThemeBrushPrimaryHighlightColor;
// First paint the hilite rect, then the text on top
SetThemePen( colorBrushID, 32, true );
PaintRect( itemRect );
SetThemeDrawingState( themeState, false );
}
DrawThemeTextBox( cfString, kThemeApplicationFont, kThemeStateActive, true, itemRect, teFlushDefault, NULL );
SetThemeDrawingState( themeState, true );
if ( cfString != NULL )
CFRelease( cfString );
}
#endif
#endif // wxUSE_LISTBOX

File diff suppressed because it is too large Load Diff

12
src/osx/carbon/main.cpp Normal file
View File

@@ -0,0 +1,12 @@
/////////////////////////////////////////////////////////////////////////////
// Name: main.cpp
// Purpose: Entry point
// Author: Stefan Csomor
// Modified by:
// Created: 1998-01-01
// RCS-ID: $Id$
// Copyright: (c) Stefan Csomor
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
// We don't put main() in the library any more. GD.

514
src/osx/carbon/mdi.cpp Normal file
View File

@@ -0,0 +1,514 @@
/////////////////////////////////////////////////////////////////////////////
// Name: src/mac/carbon/mdi.cpp
// Purpose: MDI classes
// Author: Stefan Csomor
// Modified by:
// Created: 1998-01-01
// RCS-ID: $Id$
// Copyright: (c) Stefan Csomor
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
#include "wx/wxprec.h"
#if wxUSE_MDI
#include "wx/mdi.h"
#ifndef WX_PRECOMP
#include "wx/log.h"
#include "wx/menu.h"
#include "wx/settings.h"
#include "wx/statusbr.h"
#endif
#include "wx/mac/private.h"
#include "wx/mac/uma.h"
IMPLEMENT_DYNAMIC_CLASS(wxMDIParentFrame, wxFrame)
IMPLEMENT_DYNAMIC_CLASS(wxMDIChildFrame, wxFrame)
IMPLEMENT_DYNAMIC_CLASS(wxMDIClientWindow, wxWindow)
BEGIN_EVENT_TABLE(wxMDIParentFrame, wxFrame)
EVT_ACTIVATE(wxMDIParentFrame::OnActivate)
EVT_SYS_COLOUR_CHANGED(wxMDIParentFrame::OnSysColourChanged)
END_EVENT_TABLE()
BEGIN_EVENT_TABLE(wxMDIClientWindow, wxWindow)
EVT_SCROLL(wxMDIClientWindow::OnScroll)
END_EVENT_TABLE()
#define TRACE_MDI "mdi"
static const int IDM_WINDOWTILEHOR = 4001;
static const int IDM_WINDOWCASCADE = 4002;
static const int IDM_WINDOWICONS = 4003;
static const int IDM_WINDOWNEXT = 4004;
static const int IDM_WINDOWTILEVERT = 4005;
// others
void UMAHighlightAndActivateWindow( WindowRef inWindowRef , bool inActivate )
{
#if 1 // TODO REMOVE
if ( inWindowRef )
{
// bool isHighlighted = IsWindowHighlited( inWindowRef ) ;
// if ( inActivate != isHighlighted )
#ifndef __LP64__
GrafPtr port ;
GetPort( &port ) ;
SetPortWindowPort( inWindowRef ) ;
#endif
HiliteWindow( inWindowRef , inActivate ) ;
ControlRef control = NULL ;
::GetRootControl( inWindowRef , &control ) ;
if ( control )
{
if ( inActivate )
::ActivateControl( control ) ;
else
::DeactivateControl( control ) ;
}
#ifndef __LP64__
SetPort( port ) ;
#endif
}
#endif
}
// ----------------------------------------------------------------------------
// Parent frame
// ----------------------------------------------------------------------------
void wxMDIParentFrame::Init()
{
m_clientWindow = NULL;
m_currentChild = NULL;
m_windowMenu = (wxMenu*) NULL;
m_parentFrameActive = true;
m_shouldBeShown = false;
}
bool wxMDIParentFrame::Create(wxWindow *parent,
wxWindowID id,
const wxString& title,
const wxPoint& pos,
const wxSize& size,
long style,
const wxString& name)
{
// this style can be used to prevent a window from having the standard MDI
// "Window" menu
if ( style & wxFRAME_NO_WINDOW_MENU )
{
m_windowMenu = (wxMenu *)NULL;
style -= wxFRAME_NO_WINDOW_MENU ;
}
else // normal case: we have the window menu, so construct it
{
m_windowMenu = new wxMenu;
m_windowMenu->Append(IDM_WINDOWCASCADE, wxT("&Cascade"));
m_windowMenu->Append(IDM_WINDOWTILEHOR, wxT("Tile &Horizontally"));
m_windowMenu->Append(IDM_WINDOWTILEVERT, wxT("Tile &Vertically"));
m_windowMenu->AppendSeparator();
m_windowMenu->Append(IDM_WINDOWICONS, wxT("&Arrange Icons"));
m_windowMenu->Append(IDM_WINDOWNEXT, wxT("&Next"));
}
if ( !wxFrame::Create( parent , id , title , pos , size , style , name ) )
return false;
m_parentFrameActive = true;
m_clientWindow = OnCreateClient();
return m_clientWindow != NULL;
}
wxMDIParentFrame::~wxMDIParentFrame()
{
DestroyChildren();
// already deleted by DestroyChildren()
m_clientWindow = NULL ;
delete m_windowMenu;
}
void wxMDIParentFrame::SetMenuBar(wxMenuBar *menu_bar)
{
wxFrame::SetMenuBar( menu_bar ) ;
}
void wxMDIParentFrame::GetRectForTopLevelChildren(int *x, int *y, int *w, int *h)
{
if (x)
*x = 0;
if (y)
*y = 0;
wxDisplaySize(w, h);
}
void wxMDIParentFrame::AddChild(wxWindowBase *child)
{
// moved this to front, so that we don't run into unset m_parent problems later
wxFrame::AddChild(child);
if ( !m_currentChild )
{
m_currentChild = wxDynamicCast(child, wxMDIChildFrame);
if ( m_currentChild && IsShown() && !ShouldBeVisible() )
{
// we shouldn't remain visible any more
wxFrame::Show(false);
m_shouldBeShown = true;
}
}
}
void wxMDIParentFrame::RemoveChild(wxWindowBase *child)
{
if ( child == m_currentChild )
{
// the current child isn't active any more, try to find another one
m_currentChild = NULL;
for ( wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
node;
node = node->GetNext() )
{
wxMDIChildFrame *
childCur = wxDynamicCast(node->GetData(), wxMDIChildFrame);
if ( childCur != child )
{
m_currentChild = childCur;
break;
}
}
}
wxFrame::RemoveChild(child);
// if there are no more children left we need to show the frame if we
// hadn't shown it before because there were active children and it was
// useless (note that we have to do it after fully removing the child, i.e.
// after calling the base class RemoveChild() as otherwise we risk to touch
// pointer to the child being deleted)
if ( !m_currentChild && m_shouldBeShown && !IsShown() )
{
// we have to show it, but at least move it out of sight and make it of
// smallest possible size (unfortunately (0, 0) doesn't work so that it
// doesn't appear in expose
SetSize(-10000, -10000, 1, 1);
Show();
}
}
void wxMDIParentFrame::MacActivate(long timestamp, bool activating)
{
wxLogTrace(TRACE_MDI, wxT("MDI PARENT=%p MacActivate(0x%08lx,%s)"), this, timestamp, activating ? wxT("ACTIV") : wxT("deact"));
if (activating)
{
if (s_macDeactivateWindow && s_macDeactivateWindow->GetParent() == this)
{
wxLogTrace(TRACE_MDI, wxT("child had been scheduled for deactivation, rehighlighting"));
UMAHighlightAndActivateWindow((WindowRef)s_macDeactivateWindow->MacGetWindowRef(), true);
wxLogTrace(TRACE_MDI, wxT("finished highliting child"));
s_macDeactivateWindow = NULL;
}
else if (s_macDeactivateWindow == this)
{
wxLogTrace(TRACE_MDI, wxT("Avoided deactivation/activation of this=%p"), this);
s_macDeactivateWindow = NULL;
}
else // window to deactivate is NULL or is not us or one of our kids
{
// activate kid instead
if (m_currentChild)
m_currentChild->MacActivate(timestamp, activating);
else
wxFrame::MacActivate(timestamp, activating);
}
}
else
{
// We were scheduled for deactivation, and now we do it.
if (s_macDeactivateWindow == this)
{
s_macDeactivateWindow = NULL;
if (m_currentChild)
m_currentChild->MacActivate(timestamp, activating);
wxFrame::MacActivate(timestamp, activating);
}
else // schedule ourselves for deactivation
{
if (s_macDeactivateWindow)
wxLogTrace(TRACE_MDI, wxT("window=%p SHOULD have been deactivated, oh well!"), s_macDeactivateWindow);
wxLogTrace(TRACE_MDI, wxT("Scheduling delayed MDI Parent deactivation"));
s_macDeactivateWindow = this;
}
}
}
void wxMDIParentFrame::OnActivate(wxActivateEvent& event)
{
event.Skip();
}
// Returns the active MDI child window
wxMDIChildFrame *wxMDIParentFrame::GetActiveChild() const
{
return m_currentChild ;
}
// Create the client window class (don't Create the window,
// just return a new class)
wxMDIClientWindow *wxMDIParentFrame::OnCreateClient()
{
return new wxMDIClientWindow( this );
}
// Responds to colour changes, and passes event on to children.
void wxMDIParentFrame::OnSysColourChanged(wxSysColourChangedEvent& event)
{
// TODO
// Propagate the event to the non-top-level children
wxFrame::OnSysColourChanged(event);
}
// MDI operations
void wxMDIParentFrame::Cascade()
{
// TODO
}
void wxMDIParentFrame::Tile(wxOrientation WXUNUSED(orient))
{
// TODO
}
void wxMDIParentFrame::ArrangeIcons()
{
// TODO
}
void wxMDIParentFrame::ActivateNext()
{
// TODO
}
void wxMDIParentFrame::ActivatePrevious()
{
// TODO
}
bool wxMDIParentFrame::ShouldBeVisible() const
{
for ( wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
node;
node = node->GetNext() )
{
wxWindow *win = node->GetData();
if ( win->IsShown()
&& !wxDynamicCast(win, wxMDIChildFrame)
#if wxUSE_STATUSBAR
&& win != (wxWindow*) GetStatusBar()
#endif
&& win != GetClientWindow() )
{
// if we have a non-MDI child, do remain visible so that it could
// be used
return true;
}
}
return false;
}
bool wxMDIParentFrame::Show( bool show )
{
m_shouldBeShown = false;
// don't really show the MDI frame unless it has any children other than
// MDI children as it is pretty useless in this case
if ( show )
{
if ( !ShouldBeVisible() && m_currentChild )
{
// don't make the window visible now but remember that we should
// have had done it
m_shouldBeShown = true;
return false;
}
}
return wxFrame::Show(show);
}
// ----------------------------------------------------------------------------
// Child frame
// ----------------------------------------------------------------------------
wxMDIChildFrame::wxMDIChildFrame()
{
Init() ;
}
void wxMDIChildFrame::Init()
{
}
bool wxMDIChildFrame::Create(wxMDIParentFrame *parent,
wxWindowID id,
const wxString& title,
const wxPoint& pos,
const wxSize& size,
long style,
const wxString& name)
{
SetName(name);
if ( id == wxID_ANY )
m_windowId = (int)NewControlId();
else
m_windowId = id;
if (parent)
parent->AddChild(this);
MacCreateRealWindow( pos , size , MacRemoveBordersFromStyle(style) , name ) ;
SetTitle( title );
SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_APPWORKSPACE));
return true;
}
wxMDIChildFrame::~wxMDIChildFrame()
{
DestroyChildren();
}
void wxMDIChildFrame::SetMenuBar(wxMenuBar *menu_bar)
{
return wxFrame::SetMenuBar( menu_bar ) ;
}
void wxMDIChildFrame::MacActivate(long timestamp, bool activating)
{
wxLogTrace(TRACE_MDI, wxT("MDI child=%p MacActivate(0x%08lx,%s)"),this, timestamp, activating ? wxT("ACTIV") : wxT("deact"));
wxMDIParentFrame *mdiparent = wxDynamicCast(m_parent, wxMDIParentFrame);
wxASSERT(mdiparent);
if (activating)
{
if (s_macDeactivateWindow == m_parent)
{
wxLogTrace(TRACE_MDI, wxT("parent had been scheduled for deactivation, rehighlighting"));
UMAHighlightAndActivateWindow((WindowRef)s_macDeactivateWindow->MacGetWindowRef(), true);
wxLogTrace(TRACE_MDI, wxT("finished highliting parent"));
s_macDeactivateWindow = NULL;
}
else if ((mdiparent->m_currentChild == this) || !s_macDeactivateWindow)
mdiparent->wxFrame::MacActivate(timestamp, activating);
if (mdiparent->m_currentChild && mdiparent->m_currentChild != this)
mdiparent->m_currentChild->wxFrame::MacActivate(timestamp, false);
mdiparent->m_currentChild = this;
if (s_macDeactivateWindow == this)
{
wxLogTrace(TRACE_MDI, wxT("Avoided deactivation/activation of this=%p"), this);
s_macDeactivateWindow = NULL;
}
else
wxFrame::MacActivate(timestamp, activating);
}
else
{
// We were scheduled for deactivation, and now we do it.
if (s_macDeactivateWindow == this)
{
s_macDeactivateWindow = NULL;
wxFrame::MacActivate(timestamp, activating);
if (mdiparent->m_currentChild == this)
mdiparent->wxFrame::MacActivate(timestamp, activating);
}
else // schedule ourselves for deactivation
{
if (s_macDeactivateWindow)
wxLogTrace(TRACE_MDI, wxT("window=%p SHOULD have been deactivated, oh well!"), s_macDeactivateWindow);
wxLogTrace(TRACE_MDI, wxT("Scheduling delayed deactivation"));
s_macDeactivateWindow = this;
}
}
}
// MDI operations
void wxMDIChildFrame::Maximize()
{
wxFrame::Maximize() ;
}
void wxMDIChildFrame::Restore()
{
wxFrame::Restore() ;
}
void wxMDIChildFrame::Activate()
{
Raise ();
}
//-----------------------------------------------------------------------------
// wxMDIClientWindow
//-----------------------------------------------------------------------------
wxMDIClientWindow::wxMDIClientWindow()
{
}
wxMDIClientWindow::~wxMDIClientWindow()
{
DestroyChildren();
}
bool wxMDIClientWindow::CreateClient(wxMDIParentFrame *parent, long style)
{
if ( !wxWindow::Create(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, style) )
return false;
return true;
}
// Get size *available for subwindows* i.e. excluding menu bar.
void wxMDIClientWindow::DoGetClientSize(int *x, int *y) const
{
wxDisplaySize( x , y ) ;
}
// Explicitly call default scroll behaviour
void wxMDIClientWindow::OnScroll(wxScrollEvent& WXUNUSED(event))
{
}
#endif // wxUSE_MDI

1243
src/osx/carbon/mediactrl.cpp Normal file

File diff suppressed because it is too large Load Diff

1183
src/osx/carbon/menu.cpp Normal file

File diff suppressed because it is too large Load Diff

289
src/osx/carbon/menuitem.cpp Normal file
View File

@@ -0,0 +1,289 @@
///////////////////////////////////////////////////////////////////////////////
// Name: src/mac/carbon/menuitem.cpp
// Purpose: wxMenuItem implementation
// Author: Stefan Csomor
// Modified by:
// Created: 1998-01-01
// RCS-ID: $Id$
// Copyright: (c) Stefan Csomor
// Licence: wxWindows licence
///////////////////////////////////////////////////////////////////////////////
#include "wx/wxprec.h"
#include "wx/menuitem.h"
#include "wx/stockitem.h"
#ifndef WX_PRECOMP
#include "wx/app.h"
#include "wx/menu.h"
#endif // WX_PRECOMP
#include "wx/mac/uma.h"
IMPLEMENT_DYNAMIC_CLASS(wxMenuItem, wxObject)
wxMenuItem::wxMenuItem(wxMenu *pParentMenu,
int id,
const wxString& text,
const wxString& strHelp,
wxItemKind kind,
wxMenu *pSubMenu)
:wxMenuItemBase(pParentMenu, id, text, strHelp, kind, pSubMenu)
{
wxASSERT_MSG( id != 0 || pSubMenu != NULL , wxT("A MenuItem ID of Zero does not work under Mac") ) ;
// In other languages there is no difference in naming the Exit/Quit menu item between MacOS and Windows guidelines
// therefore these item must not be translated
if ( wxStripMenuCodes(m_text).Upper() == wxT("EXIT") )
m_text = wxT("Quit\tCtrl+Q") ;
m_radioGroup.start = -1;
m_isRadioGroupStart = false;
}
wxMenuItem::~wxMenuItem()
{
}
// change item state
// -----------------
void wxMenuItem::SetBitmap(const wxBitmap& bitmap)
{
m_bitmap = bitmap;
UpdateItemBitmap();
}
void wxMenuItem::UpdateItemBitmap()
{
if ( !m_parentMenu )
return ;
MenuHandle mhandle = MAC_WXHMENU(m_parentMenu->GetHMenu()) ;
MenuItemIndex index = m_parentMenu->MacGetIndexFromItem( this ) ;
DoUpdateItemBitmap( mhandle, index );
}
void wxMenuItem::DoUpdateItemBitmap( WXHMENU menu, wxUint16 index)
{
MenuHandle mhandle = (MenuHandle) menu;
if ( mhandle == NULL || index == 0)
return ;
if ( m_bitmap.Ok() )
{
#if wxUSE_BMPBUTTON
ControlButtonContentInfo info ;
wxMacCreateBitmapButton( &info , m_bitmap ) ;
if ( info.contentType != kControlNoContent )
{
if ( info.contentType == kControlContentIconRef )
SetMenuItemIconHandle( mhandle , index ,
kMenuIconRefType , (Handle) info.u.iconRef ) ;
else if ( info.contentType == kControlContentCGImageRef )
SetMenuItemIconHandle( mhandle , index ,
kMenuCGImageRefType , (Handle) info.u.imageRef ) ;
}
wxMacReleaseBitmapButton( &info ) ;
#endif
}
}
void wxMenuItem::UpdateItemStatus()
{
if ( !m_parentMenu )
return ;
if ( IsSeparator() )
return ;
if ( GetId() == wxApp::s_macPreferencesMenuItemId)
{
if ( !IsEnabled() )
DisableMenuCommand( NULL , kHICommandPreferences ) ;
else
EnableMenuCommand( NULL , kHICommandPreferences ) ;
}
if ( GetId() == wxApp::s_macExitMenuItemId)
{
if ( !IsEnabled() )
DisableMenuCommand( NULL , kHICommandQuit ) ;
else
EnableMenuCommand( NULL , kHICommandQuit ) ;
}
{
MenuHandle mhandle = MAC_WXHMENU(m_parentMenu->GetHMenu()) ;
MenuItemIndex index = m_parentMenu->MacGetIndexFromItem( this ) ;
if ( mhandle == NULL || index == 0)
return ;
UMAEnableMenuItem( mhandle , index , m_isEnabled ) ;
if ( IsCheckable() && IsChecked() )
::SetItemMark( mhandle , index , 0x12 ) ; // checkmark
else
::SetItemMark( mhandle , index , 0 ) ; // no mark
UMASetMenuItemText( mhandle , index , wxStripMenuCodes(m_text) , wxFont::GetDefaultEncoding() ) ;
wxAcceleratorEntry *entry = wxAcceleratorEntry::Create( m_text ) ;
UMASetMenuItemShortcut( mhandle , index , entry ) ;
delete entry ;
}
}
void wxMenuItem::UpdateItemText()
{
if ( !m_parentMenu )
return ;
MenuHandle mhandle = MAC_WXHMENU(m_parentMenu->GetHMenu()) ;
MenuItemIndex index = m_parentMenu->MacGetIndexFromItem( this ) ;
if (mhandle == NULL || index == 0)
return ;
wxString text = m_text;
if (text.IsEmpty() && !IsSeparator())
{
wxASSERT_MSG(wxIsStockID(GetId()), wxT("A non-stock menu item with an empty label?"));
text = wxGetStockLabel(GetId(), wxSTOCK_WITH_ACCELERATOR|wxSTOCK_WITH_MNEMONIC);
}
UMASetMenuItemText( mhandle , index , wxStripMenuCodes(text) , wxFont::GetDefaultEncoding() ) ;
wxAcceleratorEntry *entry = wxAcceleratorEntry::Create( text ) ;
UMASetMenuItemShortcut( mhandle , index , entry ) ;
delete entry ;
}
void wxMenuItem::Enable(bool bDoEnable)
{
if (( m_isEnabled != bDoEnable
// avoid changing menuitem state when menu is disabled
// eg. BeginAppModalStateForWindow() will disable menus and ignore this change
// which in turn causes m_isEnabled to become out of sync with real menuitem state
&& !(m_parentMenu && !IsMenuItemEnabled(MAC_WXHMENU(m_parentMenu->GetHMenu()), 0)) )
// always update builtin menuitems
|| ( GetId() == wxApp::s_macPreferencesMenuItemId
|| GetId() == wxApp::s_macExitMenuItemId
|| GetId() == wxApp::s_macAboutMenuItemId
))
{
wxMenuItemBase::Enable( bDoEnable ) ;
UpdateItemStatus() ;
}
}
void wxMenuItem::UncheckRadio()
{
if ( m_isChecked )
{
wxMenuItemBase::Check( false ) ;
UpdateItemStatus() ;
}
}
void wxMenuItem::Check(bool bDoCheck)
{
wxCHECK_RET( IsCheckable() && !IsSeparator(), wxT("only checkable items may be checked") );
if ( m_isChecked != bDoCheck )
{
if ( GetKind() == wxITEM_RADIO )
{
if ( bDoCheck )
{
wxMenuItemBase::Check( bDoCheck ) ;
UpdateItemStatus() ;
// get the index of this item in the menu
const wxMenuItemList& items = m_parentMenu->GetMenuItems();
int pos = items.IndexOf(this);
wxCHECK_RET( pos != wxNOT_FOUND,
_T("menuitem not found in the menu items list?") );
// get the radio group range
int start, end;
if ( m_isRadioGroupStart )
{
// we already have all information we need
start = pos;
end = m_radioGroup.end;
}
else // next radio group item
{
// get the radio group end from the start item
start = m_radioGroup.start;
end = items.Item(start)->GetData()->m_radioGroup.end;
}
// also uncheck all the other items in this radio group
wxMenuItemList::compatibility_iterator node = items.Item(start);
for ( int n = start; n <= end && node; n++ )
{
if ( n != pos )
((wxMenuItem*)node->GetData())->UncheckRadio();
node = node->GetNext();
}
}
}
else
{
wxMenuItemBase::Check( bDoCheck ) ;
UpdateItemStatus() ;
}
}
}
void wxMenuItem::SetItemLabel(const wxString& text)
{
// don't do anything if label didn't change
if ( m_text == text )
return;
wxMenuItemBase::SetItemLabel(text);
UpdateItemText() ;
}
// radio group stuff
// -----------------
void wxMenuItem::SetAsRadioGroupStart()
{
m_isRadioGroupStart = true;
}
void wxMenuItem::SetRadioGroupStart(int start)
{
wxASSERT_MSG( !m_isRadioGroupStart,
wxT("should only be called for the next radio items") );
m_radioGroup.start = start;
}
void wxMenuItem::SetRadioGroupEnd(int end)
{
wxASSERT_MSG( m_isRadioGroupStart,
wxT("should only be called for the first radio item") );
m_radioGroup.end = end;
}
// ----------------------------------------------------------------------------
// wxMenuItemBase
// ----------------------------------------------------------------------------
wxMenuItem *wxMenuItemBase::New(wxMenu *parentMenu,
int id,
const wxString& name,
const wxString& help,
wxItemKind kind,
wxMenu *subMenu)
{
return new wxMenuItem(parentMenu, id, name, help, kind, subMenu);
}

366
src/osx/carbon/metafile.cpp Normal file
View File

@@ -0,0 +1,366 @@
/////////////////////////////////////////////////////////////////////////////
// Name: src/mac/carbon/metafile.cpp
// Purpose: wxMetaFile, wxMetaFileDC etc. These classes are optional.
// Author: Stefan Csomor
// Modified by:
// Created: 04/01/98
// RCS-ID: $Id$
// Copyright: (c) Stefan Csomor
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
//
// Currently, the only purpose for making a metafile
// is to put it on the clipboard.
#include "wx/wxprec.h"
#if wxUSE_METAFILE
#ifndef WX_PRECOMP
#include "wx/utils.h"
#include "wx/app.h"
#endif
#include "wx/metafile.h"
#include "wx/clipbrd.h"
#include "wx/mac/uma.h"
#include "wx/graphics.h"
#include "wx/mac/carbon/metafile.h"
#include <stdio.h>
#include <string.h>
IMPLEMENT_DYNAMIC_CLASS(wxMetafile, wxObject)
IMPLEMENT_ABSTRACT_CLASS(wxMetafileDC, wxDC)
IMPLEMENT_ABSTRACT_CLASS(wxMetafileDCImpl, wxGCDCImpl)
#define M_METAFILEREFDATA( a ) ((wxMetafileRefData*)(a).GetRefData())
class wxMetafileRefData : public wxGDIRefData
{
public:
// default ctor needed for CreateGDIRefData(), must be initialized later
wxMetafileRefData() { Init(); }
// creates a metafile from memory, assumes ownership
wxMetafileRefData(CFDataRef data);
// prepares a recording metafile
wxMetafileRefData( int width, int height);
// prepares a metafile to be read from a file (if filename is not empty)
wxMetafileRefData( const wxString& filename);
virtual ~wxMetafileRefData();
virtual bool IsOk() const { return m_data != NULL; }
void Init();
int GetWidth() const { return m_width; }
int GetHeight() const { return m_height; }
CGPDFDocumentRef GetPDFDocument() const { return m_pdfDoc; }
void UpdateDocumentFromData() ;
const wxCFDataRef& GetData() const { return m_data; }
CGContextRef GetContext() const { return m_context; }
// ends the recording
void Close();
private:
wxCFDataRef m_data;
wxCFRef<CGPDFDocumentRef> m_pdfDoc;
CGContextRef m_context;
int m_width ;
int m_height ;
};
wxMetafileRefData::wxMetafileRefData(CFDataRef data) :
m_data(data)
{
Init();
UpdateDocumentFromData();
}
wxMetafileRefData::wxMetafileRefData( const wxString& filename )
{
Init();
if ( !filename.empty() )
{
wxCFRef<CFMutableStringRef> cfMutableString(CFStringCreateMutableCopy(NULL, 0, wxCFStringRef(filename)));
CFStringNormalize(cfMutableString,kCFStringNormalizationFormD);
wxCFRef<CFURLRef> url(CFURLCreateWithFileSystemPath(kCFAllocatorDefault, cfMutableString , kCFURLPOSIXPathStyle, false));
m_pdfDoc.reset(CGPDFDocumentCreateWithURL(url));
}
}
wxMetafileRefData::wxMetafileRefData( int width, int height)
{
Init();
m_width = width;
m_height = height;
CGRect r = CGRectMake( 0 , 0 , width , height );
CFMutableDataRef data = CFDataCreateMutable(kCFAllocatorDefault, 0);
m_data.reset(data);
CGDataConsumerRef dataConsumer = wxMacCGDataConsumerCreateWithCFData(data);
m_context = CGPDFContextCreate( dataConsumer, (width != 0 && height != 0) ? &r : NULL , NULL );
CGDataConsumerRelease( dataConsumer );
if ( m_context )
{
CGPDFContextBeginPage(m_context, NULL);
CGColorSpaceRef genericColorSpace = wxMacGetGenericRGBColorSpace();
CGContextSetFillColorSpace( m_context, genericColorSpace );
CGContextSetStrokeColorSpace( m_context, genericColorSpace );
CGContextTranslateCTM( m_context , 0 , height ) ;
CGContextScaleCTM( m_context , 1 , -1 ) ;
}
}
wxMetafileRefData::~wxMetafileRefData()
{
}
void wxMetafileRefData::Init()
{
m_context = NULL;
m_width = -1;
m_height = -1;
}
void wxMetafileRefData::Close()
{
CGPDFContextEndPage(m_context);
CGContextRelease(m_context);
m_context = NULL;
UpdateDocumentFromData();
}
void wxMetafileRefData::UpdateDocumentFromData()
{
wxCFRef<CGDataProviderRef> provider(wxMacCGDataProviderCreateWithCFData(m_data));
m_pdfDoc.reset(CGPDFDocumentCreateWithProvider(provider));
if ( m_pdfDoc != NULL )
{
CGPDFPageRef page = CGPDFDocumentGetPage( m_pdfDoc, 1 );
CGRect rect = CGPDFPageGetBoxRect ( page, kCGPDFMediaBox);
m_width = wx_static_cast(int, rect.size.width);
m_height = wx_static_cast(int, rect.size.height);
}
}
wxMetaFile::wxMetaFile(const wxString& file)
{
m_refData = new wxMetafileRefData(file);
}
wxMetaFile::~wxMetaFile()
{
}
wxGDIRefData *wxMetaFile::CreateGDIRefData() const
{
return new wxMetafileRefData;
}
wxGDIRefData *wxMetaFile::CloneGDIRefData(const wxGDIRefData *data) const
{
return new wxMetafileRefData(*wx_static_cast(const wxMetafileRefData *, data));
}
WXHMETAFILE wxMetaFile::GetHMETAFILE() const
{
return (WXHMETAFILE) (CFDataRef) M_METAFILEDATA->GetData();
}
bool wxMetaFile::SetClipboard(int WXUNUSED(width), int WXUNUSED(height))
{
bool success = true;
#if wxUSE_DRAG_AND_DROP
if (m_refData == NULL)
return false;
bool alreadyOpen = wxTheClipboard->IsOpened();
if (!alreadyOpen)
{
wxTheClipboard->Open();
wxTheClipboard->Clear();
}
wxDataObject *data = new wxMetafileDataObject( *this );
success = wxTheClipboard->SetData( data );
if (!alreadyOpen)
wxTheClipboard->Close();
#endif
return success;
}
void wxMetafile::SetHMETAFILE(WXHMETAFILE mf)
{
UnRef();
m_refData = new wxMetafileRefData((CFDataRef)mf);
}
#ifndef __LP64__
void wxMetafile::SetPICT(void* pictHandle)
{
UnRef();
Handle picHandle = (Handle) pictHandle;
HLock(picHandle);
CFDataRef data = CFDataCreateWithBytesNoCopy( kCFAllocatorDefault, (const UInt8*) *picHandle, GetHandleSize(picHandle), kCFAllocatorNull);
wxCFRef<CGDataProviderRef> provider(wxMacCGDataProviderCreateWithCFData(data));
QDPictRef pictRef = QDPictCreateWithProvider(provider);
CGRect rect = QDPictGetBounds(pictRef);
m_refData = new wxMetafileRefData(wx_static_cast(int, rect.size.width),
wx_static_cast(int, rect.size.height));
QDPictDrawToCGContext( ((wxMetafileRefData*) m_refData)->GetContext(), rect, pictRef );
CFRelease( data );
QDPictRelease( pictRef );
((wxMetafileRefData*) m_refData)->Close();
}
#endif
bool wxMetaFile::Play(wxDC *dc)
{
if (!m_refData)
return false;
if (!dc->IsOk())
return false;
{
wxDCImpl *impl = dc->GetImpl();
wxGCDCImpl *gc_impl = wxDynamicCast(impl, wxGCDCImpl);
if (gc_impl)
{
CGContextRef cg = (CGContextRef) (gc_impl->GetGraphicsContext()->GetNativeContext());
CGPDFDocumentRef doc = M_METAFILEDATA->GetPDFDocument();
CGPDFPageRef page = CGPDFDocumentGetPage( doc, 1 );
wxMacCGContextStateSaver save(cg);
CGContextDrawPDFPage( cg, page );
}
// CGContextTranslateCTM( cg, 0, bounds.size.width );
// CGContextScaleCTM( cg, 1, -1 );
}
return true;
}
wxSize wxMetaFile::GetSize() const
{
wxSize dataSize = wxDefaultSize;
if (Ok())
{
dataSize.x = M_METAFILEDATA->GetWidth();
dataSize.y = M_METAFILEDATA->GetHeight();
}
return dataSize;
}
// Metafile device context
// New constructor that takes origin and extent. If you use this, don't
// give origin/extent arguments to wxMakeMetaFilePlaceable.
wxMetafileDCImpl::wxMetafileDCImpl(
wxDC *owner,
const wxString& filename,
int width, int height,
const wxString& WXUNUSED(description) ) :
wxGCDCImpl( owner )
{
wxASSERT_MSG( width != 0 || height != 0, wxT("no arbitration of metafile size supported") );
wxASSERT_MSG( filename.empty(), wxT("no file based metafile support yet"));
m_metaFile = new wxMetaFile( filename );
wxMetafileRefData* metafiledata = new wxMetafileRefData(width, height);
m_metaFile->UnRef();
m_metaFile->SetRefData( metafiledata );
SetGraphicsContext( wxGraphicsContext::CreateFromNative(metafiledata->GetContext()));
m_ok = (m_graphicContext != NULL) ;
SetMapMode( wxMM_TEXT );
}
wxMetafileDCImpl::~wxMetafileDCImpl()
{
}
void wxMetafileDCImpl::DoGetSize(int *width, int *height) const
{
wxCHECK_RET( m_metaFile, wxT("GetSize() doesn't work without a metafile") );
wxSize sz = m_metaFile->GetSize();
if (width)
(*width) = sz.x;
if (height)
(*height) = sz.y;
}
wxMetaFile *wxMetafileDCImpl::Close()
{
delete m_graphicContext;
m_graphicContext = NULL;
m_ok = false;
M_METAFILEREFDATA(*m_metaFile)->Close();
return m_metaFile;
}
#if wxUSE_DATAOBJ
size_t wxMetafileDataObject::GetDataSize() const
{
CFIndex length = 0;
wxMetafileRefData* refData = M_METAFILEREFDATA(m_metafile);
if ( refData )
length = refData->GetData().GetLength();
return length;
}
bool wxMetafileDataObject::GetDataHere(void *buf) const
{
bool result = false;
wxMetafileRefData* refData = M_METAFILEREFDATA(m_metafile);
if ( refData )
{
CFIndex length = refData->GetData().GetLength();
if ( length > 0 )
{
result = true ;
refData->GetData().GetBytes(CFRangeMake(0,length), (UInt8 *) buf);
}
}
return result;
}
bool wxMetafileDataObject::SetData(size_t len, const void *buf)
{
wxMetafileRefData* metafiledata = new wxMetafileRefData(wxCFRefFromGet(wxCFDataRef((UInt8*)buf, len).get()));
m_metafile.UnRef();
m_metafile.SetRefData( metafiledata );
return true;
}
#endif
#endif

1953
src/osx/carbon/mimetmac.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,20 @@
/////////////////////////////////////////////////////////////////////////////
// Name: minifram.cpp
// Purpose: wxMiniFrame. Optional; identical to wxFrame if not supported.
// Author: Stefan Csomor
// Modified by:
// Created: 1998-01-01
// RCS-ID: $Id$
// Copyright: (c) Stefan Csomor
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
#include "wx/wxprec.h"
#if wxUSE_MINIFRAME
#include "wx/minifram.h"
IMPLEMENT_DYNAMIC_CLASS(wxMiniFrame, wxFrame)
#endif // wxUSE_MINIFRAME

View File

@@ -0,0 +1,685 @@
/*
File: DirectoryCopy.c
Contains: A robust, general purpose directory copy routine.
Version: MoreFiles
Copyright: <09> 1992-2001 by Apple Computer, Inc., all rights reserved.
You may incorporate this sample code into your applications without
restriction, though the sample code has been provided "AS IS" and the
responsibility for its operation is 100% yours. However, what you are
not permitted to do is to redistribute the source as "DSC Sample Code"
after having made changes. If you're going to re-distribute the source,
we require that you make it clear in the source that the code was
descended from Apple Sample Code, but that you've made changes.
File Ownership:
DRI: Apple Macintosh Developer Technical Support
Other Contact: Apple Macintosh Developer Technical Support
<http://developer.apple.com/bugreporter/>
Technology: DTS Sample Code
Writers:
(JL) Jim Luther
Change History (most recent first):
<2> 2/7/01 JL Added standard header. Updated names of includes.
<1> 12/06/99 JL MoreFiles 1.5.
*/
#include <MacTypes.h>
#include <MacErrors.h>
#include <MacMemory.h>
#include <Files.h>
#include <Script.h>
#include <Math64.h>
#define __COMPILINGMOREFILES
#include "MoreFiles.h"
#include "MoreFilesExtras.h"
#include "MoreDesktopMgr.h"
#include "FileCopy.h"
#include "DirectoryCopy.h"
/*****************************************************************************/
/* local constants */
enum
{
dirCopyBigCopyBuffSize = 0x00004000,
dirCopyMinCopyBuffSize = 0x00000200
};
/*****************************************************************************/
/* local data structures */
/* The EnumerateGlobals structure is used to minimize the amount of
** stack space used when recursively calling CopyLevel and to hold
** global information that might be needed at any time. */
#if PRAGMA_STRUCT_ALIGN
#pragma options align=mac68k
#endif
struct EnumerateGlobals
{
Ptr copyBuffer; /* pointer to buffer used for file copy operations */
long bufferSize; /* the size of the copy buffer */
CopyErrProcPtr errorHandler; /* pointer to error handling function */
CopyFilterProcPtr copyFilterProc; /* pointer to filter function */
OSErr error; /* temporary holder of results - saves 2 bytes of stack each level */
Boolean bailout; /* set to true to by error handling function if fatal error */
short destinationVRefNum; /* the destination vRefNum */
Str63 itemName; /* the name of the current item */
CInfoPBRec myCPB; /* the parameter block used for PBGetCatInfo calls */
};
#if PRAGMA_STRUCT_ALIGN
#pragma options align=reset
#endif
typedef struct EnumerateGlobals EnumerateGlobals;
typedef EnumerateGlobals *EnumerateGlobalsPtr;
/* The PreflightGlobals structure is used to minimize the amount of
** stack space used when recursively calling GetLevelSize and to hold
** global information that might be needed at any time. */
#if PRAGMA_STRUCT_ALIGN
#pragma options align=mac68k
#endif
struct PreflightGlobals
{
OSErr result; /* temporary holder of results - saves 2 bytes of stack each level */
Str63 itemName; /* the name of the current item */
CInfoPBRec myCPB; /* the parameter block used for PBGetCatInfo calls */
unsigned long dstBlksPerAllocBlk; /* the number of 512 byte blocks per allocation block on destination */
unsigned long allocBlksNeeded; /* the total number of allocation blocks needed */
unsigned long tempBlocks; /* temporary storage for calculations (save some stack space) */
CopyFilterProcPtr copyFilterProc; /* pointer to filter function */
};
#if PRAGMA_STRUCT_ALIGN
#pragma options align=reset
#endif
typedef struct PreflightGlobals PreflightGlobals;
typedef PreflightGlobals *PreflightGlobalsPtr;
/*****************************************************************************/
/* static prototypes */
static void GetLevelSize(long currentDirID,
PreflightGlobals *theGlobals);
static OSErr PreflightDirectoryCopySpace(short srcVRefNum,
long srcDirID,
short dstVRefNum,
CopyFilterProcPtr copyFilterProc,
Boolean *spaceOK);
static void CopyLevel(long sourceDirID,
long dstDirID,
EnumerateGlobals *theGlobals);
/*****************************************************************************/
static void GetLevelSize(long currentDirID,
PreflightGlobals *theGlobals)
{
short index = 1;
do
{
theGlobals->myCPB.dirInfo.ioFDirIndex = index;
theGlobals->myCPB.dirInfo.ioDrDirID = currentDirID; /* we need to do this every time */
/* through, since GetCatInfo */
/* returns ioFlNum in this field */
theGlobals->result = PBGetCatInfoSync(&theGlobals->myCPB);
if ( theGlobals->result == noErr )
{
if ( (theGlobals->copyFilterProc == NULL) ||
CallCopyFilterProc(theGlobals->copyFilterProc, &theGlobals->myCPB) ) /* filter if filter proc was supplied */
{
/* Either there's no filter proc OR the filter proc says to use this item */
if ( (theGlobals->myCPB.dirInfo.ioFlAttrib & kioFlAttribDirMask) != 0 )
{
/* we have a directory */
GetLevelSize(theGlobals->myCPB.dirInfo.ioDrDirID, theGlobals); /* recurse */
theGlobals->result = noErr; /* clear error return on way back */
}
else
{
/* We have a file - add its allocation blocks to allocBlksNeeded. */
/* Since space on Mac OS disks is always allocated in allocation blocks, */
/* this takes into account rounding up to the end of an allocation block. */
/* get number of 512-byte blocks needed for data fork */
if ( ((unsigned long)theGlobals->myCPB.hFileInfo.ioFlLgLen & 0x000001ff) != 0 )
{
theGlobals->tempBlocks = ((unsigned long)theGlobals->myCPB.hFileInfo.ioFlLgLen >> 9) + 1;
}
else
{
theGlobals->tempBlocks = (unsigned long)theGlobals->myCPB.hFileInfo.ioFlLgLen >> 9;
}
/* now, calculate number of new allocation blocks needed for the data fork and add it to the total */
if ( theGlobals->tempBlocks % theGlobals->dstBlksPerAllocBlk )
{
theGlobals->allocBlksNeeded += (theGlobals->tempBlocks / theGlobals->dstBlksPerAllocBlk) + 1;
}
else
{
theGlobals->allocBlksNeeded += theGlobals->tempBlocks / theGlobals->dstBlksPerAllocBlk;
}
/* get number of 512-byte blocks needed for resource fork */
if ( ((unsigned long)theGlobals->myCPB.hFileInfo.ioFlRLgLen & 0x000001ff) != 0 )
{
theGlobals->tempBlocks = ((unsigned long)theGlobals->myCPB.hFileInfo.ioFlRLgLen >> 9) + 1;
}
else
{
theGlobals->tempBlocks = (unsigned long)theGlobals->myCPB.hFileInfo.ioFlRLgLen >> 9;
}
/* now, calculate number of new allocation blocks needed for the resource fork and add it to the total */
if ( theGlobals->tempBlocks % theGlobals->dstBlksPerAllocBlk )
{
theGlobals->allocBlksNeeded += (theGlobals->tempBlocks / theGlobals->dstBlksPerAllocBlk) + 1;
}
else
{
theGlobals->allocBlksNeeded += theGlobals->tempBlocks / theGlobals->dstBlksPerAllocBlk;
}
}
}
}
++index;
} while ( theGlobals->result == noErr );
}
/*****************************************************************************/
static OSErr PreflightDirectoryCopySpace(short srcVRefNum,
long srcDirID,
short dstVRefNum,
CopyFilterProcPtr copyFilterProc,
Boolean *spaceOK)
{
XVolumeParam pb;
OSErr error;
unsigned long dstFreeBlocks;
PreflightGlobals theGlobals;
error = XGetVolumeInfoNoName(NULL, dstVRefNum, &pb);
if ( error == noErr )
{
/* Convert freeBytes to free disk blocks (512-byte blocks) */
dstFreeBlocks = U32SetU(U64ShiftRight(pb.ioVFreeBytes, 9));
/* get allocation block size (always multiple of 512) and divide by 512
to get number of 512-byte blocks per allocation block */
theGlobals.dstBlksPerAllocBlk = ((unsigned long)pb.ioVAlBlkSiz >> 9);
theGlobals.allocBlksNeeded = 0;
theGlobals.myCPB.dirInfo.ioNamePtr = theGlobals.itemName;
theGlobals.myCPB.dirInfo.ioVRefNum = srcVRefNum;
theGlobals.copyFilterProc = copyFilterProc;
GetLevelSize(srcDirID, &theGlobals);
/* Is there enough room on the destination volume for the source file? */
/* Note: This will work because the largest number of disk blocks supported */
/* on a 2TB volume is 0xffffffff and (allocBlksNeeded * dstBlksPerAllocBlk) */
/* will always be less than 0xffffffff. */
*spaceOK = ((theGlobals.allocBlksNeeded * theGlobals.dstBlksPerAllocBlk) <= dstFreeBlocks);
}
return ( error );
}
/*****************************************************************************/
static void CopyLevel(long sourceDirID,
long dstDirID,
EnumerateGlobals *theGlobals)
{
long currentSrcDirID = 0 ;
long newDirID;
short index = 1;
do
{
/* Get next source item at the current directory level */
theGlobals->myCPB.dirInfo.ioFDirIndex = index;
theGlobals->myCPB.dirInfo.ioDrDirID = sourceDirID;
theGlobals->error = PBGetCatInfoSync(&theGlobals->myCPB);
if ( theGlobals->error == noErr )
{
if ( (theGlobals->copyFilterProc == NULL) ||
CallCopyFilterProc(theGlobals->copyFilterProc, &theGlobals->myCPB) ) /* filter if filter proc was supplied */
{
/* Either there's no filter proc OR the filter proc says to use this item */
/* We have an item. Is it a file or directory? */
if ( (theGlobals->myCPB.hFileInfo.ioFlAttrib & kioFlAttribDirMask) != 0 )
{
/* We have a directory */
/* Create a new directory at the destination. No errors allowed! */
theGlobals->error = DirCreate(theGlobals->destinationVRefNum, dstDirID, theGlobals->itemName, &newDirID);
if ( theGlobals->error == noErr )
{
/* Save the current source directory ID where we can get it when we come back
** from recursion land. */
currentSrcDirID = theGlobals->myCPB.dirInfo.ioDrDirID;
/* Dive again (copy the directory level we just found below this one) */
CopyLevel(theGlobals->myCPB.dirInfo.ioDrDirID, newDirID, theGlobals);
if ( !theGlobals->bailout )
{
/* Copy comment from old to new directory. */
/* Ignore the result because we really don't care if it worked or not. */
(void) DTCopyComment(theGlobals->myCPB.dirInfo.ioVRefNum, currentSrcDirID, NULL, theGlobals->destinationVRefNum, newDirID, NULL);
/* Copy directory attributes (dates, etc.) to newDirID. */
/* No errors allowed */
theGlobals->error = CopyFileMgrAttributes(theGlobals->myCPB.dirInfo.ioVRefNum, currentSrcDirID, NULL, theGlobals->destinationVRefNum, newDirID, NULL, true);
/* handle any errors from CopyFileMgrAttributes */
if ( theGlobals->error != noErr )
{
if ( theGlobals->errorHandler != NULL )
{
theGlobals->bailout = CallCopyErrProc(theGlobals->errorHandler, theGlobals->error, copyDirFMAttributesOp,
theGlobals->myCPB.dirInfo.ioVRefNum, currentSrcDirID, NULL,
theGlobals->destinationVRefNum, newDirID, NULL);
}
else
{
/* If you don't handle the errors with an error handler, */
/* then the copy stops here. */
theGlobals->bailout = true;
}
}
}
}
else /* error handling for DirCreate */
{
/* note that currentSrcDirID has not been initialised when entering this execution path */
if ( theGlobals->errorHandler != NULL )
{
theGlobals->bailout = CallCopyErrProc(theGlobals->errorHandler, theGlobals->error, dirCreateOp,
theGlobals->myCPB.dirInfo.ioVRefNum, currentSrcDirID, NULL,
theGlobals->destinationVRefNum, dstDirID, theGlobals->itemName);
}
else
{
/* If you don't handle the errors with an error handler, */
/* then the copy stops here. */
theGlobals->bailout = true;
}
}
if ( !theGlobals->bailout )
{
/* clear error return on way back if we aren't bailing out */
theGlobals->error = noErr;
}
}
else
{
/* We have a file, so copy it */
theGlobals->error = FileCopy(theGlobals->myCPB.hFileInfo.ioVRefNum,
theGlobals->myCPB.hFileInfo.ioFlParID,
theGlobals->itemName,
theGlobals->destinationVRefNum,
dstDirID,
NULL,
NULL,
theGlobals->copyBuffer,
theGlobals->bufferSize,
false);
/* handle any errors from FileCopy */
if ( theGlobals->error != noErr )
{
if ( theGlobals->errorHandler != NULL )
{
theGlobals->bailout = CallCopyErrProc(theGlobals->errorHandler, theGlobals->error, fileCopyOp,
theGlobals->myCPB.hFileInfo.ioVRefNum, theGlobals->myCPB.hFileInfo.ioFlParID, theGlobals->itemName,
theGlobals->destinationVRefNum, dstDirID, NULL);
if ( !theGlobals->bailout )
{
/* If the CopyErrProc handled the problem, clear the error here */
theGlobals->error = noErr;
}
}
else
{
/* If you don't handle the errors with an error handler, */
/* then the copy stops here. */
theGlobals->bailout = true;
}
}
}
}
}
else
{ /* error handling for PBGetCatInfo */
/* it's normal to get a fnfErr when indexing; that only means you've hit the end of the directory */
if ( theGlobals->error != fnfErr )
{
if ( theGlobals->errorHandler != NULL )
{
theGlobals->bailout = CallCopyErrProc(theGlobals->errorHandler, theGlobals->error, getNextItemOp,
theGlobals->myCPB.dirInfo.ioVRefNum, sourceDirID, NULL, 0, 0, NULL);
if ( !theGlobals->bailout )
{
/* If the CopyErrProc handled the problem, clear the error here */
theGlobals->error = noErr;
}
}
else
{
/* If you don't handle the errors with an error handler, */
/* then the copy stops here. */
theGlobals->bailout = true;
}
}
}
++index; /* prepare to get next item */
} while ( (theGlobals->error == noErr) && (!theGlobals->bailout) ); /* time to fall back a level? */
}
/*****************************************************************************/
pascal OSErr FilteredDirectoryCopy(short srcVRefNum,
long srcDirID,
ConstStr255Param srcName,
short dstVRefNum,
long dstDirID,
ConstStr255Param dstName,
ConstStr255Param copyName,
void *copyBufferPtr,
long copyBufferSize,
Boolean preflight,
CopyErrProcPtr copyErrHandler,
CopyFilterProcPtr copyFilterProc)
{
EnumerateGlobals theGlobals;
Boolean isDirectory;
OSErr error;
Boolean ourCopyBuffer = false;
Str63 srcDirName, oldDiskName;
Boolean spaceOK;
/* Make sure a copy buffer is allocated. */
if ( copyBufferPtr == NULL )
{
/* The caller didn't supply a copy buffer so grab one from the application heap.
** Try to get a big copy buffer, if we can't, try for a 512-byte buffer.
** If 512 bytes aren't available, we're in trouble. */
copyBufferSize = dirCopyBigCopyBuffSize;
copyBufferPtr = NewPtr(copyBufferSize);
if ( copyBufferPtr == NULL )
{
copyBufferSize = dirCopyMinCopyBuffSize;
copyBufferPtr = NewPtr(copyBufferSize);
if ( copyBufferPtr == NULL )
{
return ( memFullErr );
}
}
ourCopyBuffer = true;
}
/* Get the real dirID where we're copying from and make sure it is a directory. */
error = GetDirectoryID(srcVRefNum, srcDirID, srcName, &srcDirID, &isDirectory);
if ( error != noErr )
{
goto ErrorExit;
}
if ( !isDirectory )
{
error = dirNFErr;
goto ErrorExit;
}
/* Special case destination if it is the root parent directory. */
/* Since you can't create the root directory, this is needed if */
/* you want to copy a directory's content to a disk's root directory. */
if ( (dstDirID == fsRtParID) && (dstName == NULL) )
{
dstDirID = fsRtParID;
isDirectory = true;
error = noErr;
}
else
{
/* Get the real dirID where we're going to put the copy and make sure it is a directory. */
error = GetDirectoryID(dstVRefNum, dstDirID, dstName, &dstDirID, &isDirectory);
if ( error != noErr )
{
goto ErrorExit;
}
if ( !isDirectory )
{
error = dirNFErr;
goto ErrorExit;
}
}
/* Get the real vRefNum of both the source and destination */
error = DetermineVRefNum(srcName, srcVRefNum, &srcVRefNum);
if ( error != noErr )
{
goto ErrorExit;
}
error = DetermineVRefNum(dstName, dstVRefNum, &dstVRefNum);
if ( error != noErr )
{
goto ErrorExit;
}
if ( preflight )
{
error = PreflightDirectoryCopySpace(srcVRefNum, srcDirID, dstVRefNum, copyFilterProc, &spaceOK);
if ( error != noErr )
{
goto ErrorExit;
}
if ( !spaceOK )
{
error = dskFulErr; /* not enough room on destination */
goto ErrorExit;
}
}
/* Create the new directory in the destination directory with the */
/* same name as the source directory. */
error = GetDirName(srcVRefNum, srcDirID, srcDirName);
if ( error != noErr )
{
goto ErrorExit;
}
/* Again, special case destination if the destination is the */
/* root parent directory. This time, we'll rename the disk to */
/* the source directory name. */
if ( dstDirID == fsRtParID )
{
/* Get the current name of the destination disk */
error = GetDirName(dstVRefNum, fsRtDirID, oldDiskName);
if ( error == noErr )
{
/* use the copyName as srcDirName if supplied */
if ( copyName != NULL )
{
/* make a copy since copyName is a const input */
BlockMoveData(copyName, srcDirName, sizeof(Str31));
}
/* Shorten the name if it's too long to be the volume name */
TruncPString(srcDirName, srcDirName, 27);
/* Rename the disk */
error = HRename(dstVRefNum, fsRtParID, oldDiskName, srcDirName);
/* and copy to the root directory */
dstDirID = fsRtDirID;
}
}
else
{
/* use the copyName as srcDirName if supplied */
error = DirCreate(dstVRefNum, dstDirID, ((copyName != NULL) ? copyName : srcDirName), &dstDirID);
}
if ( error != noErr )
{
/* handle any errors from DirCreate */
if ( copyErrHandler != NULL )
{
if ( CallCopyErrProc(copyErrHandler, error, dirCreateOp,
srcVRefNum, srcDirID, NULL,
dstVRefNum, dstDirID, srcDirName) )
{
goto ErrorExit;
}
else
{
/* If the CopyErrProc handled the problem, clear the error here */
/* and continue */
error = noErr;
}
}
else
{
/* If you don't handle the errors with an error handler, */
/* then the copy stops here. */
goto ErrorExit;
}
}
/* dstDirID is now the newly created directory! */
/* Set up the globals we need to access from the recursive routine. */
theGlobals.copyBuffer = (Ptr)copyBufferPtr;
theGlobals.bufferSize = copyBufferSize;
theGlobals.destinationVRefNum = dstVRefNum; /* so we can get to it always */
theGlobals.myCPB.hFileInfo.ioNamePtr = (StringPtr)&theGlobals.itemName;
theGlobals.myCPB.hFileInfo.ioVRefNum = srcVRefNum;
theGlobals.errorHandler = copyErrHandler;
theGlobals.bailout = false;
theGlobals.copyFilterProc = copyFilterProc;
/* Here we go into recursion land... */
CopyLevel(srcDirID, dstDirID, &theGlobals);
error = theGlobals.error; /* get the result */
if ( !theGlobals.bailout )
{
/* Copy comment from source to destination directory. */
/* Ignore the result because we really don't care if it worked or not. */
(void) DTCopyComment(srcVRefNum, srcDirID, NULL, dstVRefNum, dstDirID, NULL);
/* Copy the File Manager attributes */
error = CopyFileMgrAttributes(srcVRefNum, srcDirID, NULL,
dstVRefNum, dstDirID, NULL, true);
/* handle any errors from CopyFileMgrAttributes */
if ( (error != noErr) && (copyErrHandler != NULL) )
{
theGlobals.bailout = CallCopyErrProc(copyErrHandler, error, copyDirFMAttributesOp,
srcVRefNum, srcDirID, NULL,
dstVRefNum, dstDirID, NULL);
}
}
ErrorExit:
/* Get rid of the copy buffer if we allocated it. */
if ( ourCopyBuffer )
{
DisposePtr((Ptr)copyBufferPtr);
}
return ( error );
}
/*****************************************************************************/
pascal OSErr DirectoryCopy(short srcVRefNum,
long srcDirID,
ConstStr255Param srcName,
short dstVRefNum,
long dstDirID,
ConstStr255Param dstName,
ConstStr255Param copyName,
void *copyBufferPtr,
long copyBufferSize,
Boolean preflight,
CopyErrProcPtr copyErrHandler)
{
return ( FilteredDirectoryCopy(srcVRefNum, srcDirID, srcName,
dstVRefNum, dstDirID, dstName,
copyName,
copyBufferPtr, copyBufferSize, preflight,
copyErrHandler, NULL) );
}
/*****************************************************************************/
pascal OSErr FSpFilteredDirectoryCopy(const FSSpec *srcSpec,
const FSSpec *dstSpec,
ConstStr255Param copyName,
void *copyBufferPtr,
long copyBufferSize,
Boolean preflight,
CopyErrProcPtr copyErrHandler,
CopyFilterProcPtr copyFilterProc)
{
return ( FilteredDirectoryCopy(srcSpec->vRefNum, srcSpec->parID, srcSpec->name,
dstSpec->vRefNum, dstSpec->parID, dstSpec->name,
copyName,
copyBufferPtr, copyBufferSize, preflight,
copyErrHandler, copyFilterProc) );
}
/*****************************************************************************/
pascal OSErr FSpDirectoryCopy(const FSSpec *srcSpec,
const FSSpec *dstSpec,
ConstStr255Param copyName,
void *copyBufferPtr,
long copyBufferSize,
Boolean preflight,
CopyErrProcPtr copyErrHandler)
{
return ( FilteredDirectoryCopy(srcSpec->vRefNum, srcSpec->parID, srcSpec->name,
dstSpec->vRefNum, dstSpec->parID, dstSpec->name,
copyName,
copyBufferPtr, copyBufferSize, preflight,
copyErrHandler, NULL) );
}
/*****************************************************************************/

View File

@@ -0,0 +1,559 @@
/*
File: DirectoryCopy.h
Contains: A robust, general purpose directory copy routine.
Version: Technology: MoreFiles
Release: 1.5.2
Copyright: <20> 1992-2001 by Apple Computer, Inc., all rights reserved.
Bugs?: For bug reports, consult the following page on
the World Wide Web:
http://developer.apple.com/bugreporter/
*/
/*
You may incorporate this sample code into your applications without
restriction, though the sample code has been provided "AS IS" and the
responsibility for its operation is 100% yours. However, what you are
not permitted to do is to redistribute the source as "DSC Sample Code"
after having made changes. If you're going to re-distribute the source,
we require that you make it clear in the source that the code was
descended from Apple Sample Code, but that you've made changes.
*/
#ifndef __DIRECTORYCOPY__
#define __DIRECTORYCOPY__
#ifndef __MACTYPES__
#include <MacTypes.h>
#endif
#ifndef __FILES__
#include <Files.h>
#endif
#include "Optimization.h"
#if PRAGMA_ONCE
#pragma once
#endif
#ifdef __cplusplus
extern "C" {
#endif
#if PRAGMA_IMPORT
#pragma import on
#endif
#if PRAGMA_STRUCT_ALIGN
#pragma options align=mac68k
#elif PRAGMA_STRUCT_PACKPUSH
#pragma pack(push, 2)
#elif PRAGMA_STRUCT_PACK
#pragma pack(2)
#endif
/*****************************************************************************/
enum {
getNextItemOp = 1, /* couldn't access items in this directory - no access privileges */
copyDirCommentOp = 2, /* couldn't copy directory's Finder comment */
copyDirAccessPrivsOp = 3, /* couldn't copy directory's AFP access privileges */
copyDirFMAttributesOp = 4, /* couldn't copy directory's File Manager attributes */
dirCreateOp = 5, /* couldn't create destination directory */
fileCopyOp = 6 /* couldn't copy file */
};
/*****************************************************************************/
typedef CALLBACK_API( Boolean , CopyErrProcPtr )(OSErr error, short failedOperation, short srcVRefNum, long srcDirID, ConstStr255Param srcName, short dstVRefNum, long dstDirID, ConstStr255Param dstName);
/*
This is the prototype for the CopyErrProc function DirectoryCopy
calls if an error condition is detected sometime during the copy. If
CopyErrProc returns false, then DirectoryCopy attempts to continue with
the directory copy operation. If CopyErrProc returns true, then
DirectoryCopy stops the directory copy operation.
error input: The error result code that caused CopyErrProc to
be called.
failedOperation input: The operation that returned an error to
DirectoryCopy.
srcVRefNum input: Source volume specification.
srcDirID input: Source directory ID.
srcName input: Source file or directory name, or nil if
srcDirID specifies the directory.
dstVRefNum input: Destination volume specification.
dstDirID input: Destination directory ID.
dstName input: Destination file or directory name, or nil if
dstDirID specifies the directory.
__________
Also see: FilteredDirectoryCopy, FSpFilteredDirectoryCopy, DirectoryCopy, FSpDirectoryCopy
*/
#define CallCopyErrProc(userRoutine, error, failedOperation, srcVRefNum, srcDirID, srcName, dstVRefNum, dstDirID, dstName) \
(*(userRoutine))((error), (failedOperation), (srcVRefNum), (srcDirID), (srcName), (dstVRefNum), (dstDirID), (dstName))
/*****************************************************************************/
typedef CALLBACK_API( Boolean , CopyFilterProcPtr )(const CInfoPBRec * cpbPtr);
/*
This is the prototype for the CopyFilterProc function called by
FilteredDirectoryCopy and GetLevelSize. If true is returned,
the file/folder is included in the copy, otherwise it is excluded.
pb input: Points to the CInfoPBRec for the item under consideration.
__________
Also see: FilteredDirectoryCopy, FSpFilteredDirectoryCopy
*/
#define CallCopyFilterProc(userRoutine, cpbPtr) \
(*(userRoutine))((cpbPtr))
/*****************************************************************************/
EXTERN_API( OSErr )
FilteredDirectoryCopy(
short srcVRefNum,
long srcDirID,
ConstStr255Param srcName,
short dstVRefNum,
long dstDirID,
ConstStr255Param dstName,
ConstStr255Param copyName,
void * copyBufferPtr,
long copyBufferSize,
Boolean preflight,
CopyErrProcPtr copyErrHandler,
CopyFilterProcPtr copyFilterProc);
/*
The FilteredDirectoryCopy function makes a copy of a directory
structure in a new location. If copyBufferPtr <> NIL, it points to
a buffer of copyBufferSize that is used to copy files data. The
larger the supplied buffer, the faster the copy. If
copyBufferPtr = NIL, then this routine allocates a buffer in the
application heap. If you pass a copy buffer to this routine, make
its size a multiple of 512 ($200) bytes for optimum performance.
The optional copyFilterProc parameter lets a routine you define
decide what files or directories are copied to the destination.
FilteredDirectoryCopy normally creates a new directory *in* the
specified destination directory and copies the source directory's
content into the new directory. However, if root parent directory
(fsRtParID) is passed as the dstDirID parameter and NULL is
passed as the dstName parameter, DirectoryCopy renames the
destination volume to the source directory's name (truncating
if the name is longer than 27 characters) and copies the source
directory's content into the destination volume's root directory.
This special case is supported by FilteredDirectoryCopy, but
not by FSpFilteredDirectoryCopy since with FSpFilteredDirectoryCopy,
the dstName parameter can not be NULL.
srcVRefNum input: Source volume specification.
srcDirID input: Source directory ID.
srcName input: Source directory name, or nil if
srcDirID specifies the directory.
dstVRefNum input: Destination volume specification.
dstDirID input: Destination directory ID.
dstName input: Destination directory name, or nil if
dstDirID specifies the directory.
copyName input: Points to the new directory name if the directory
is to be renamed or nil if the directory isn't to
be renamed.
copyBufferPtr input: Points to a buffer of copyBufferSize that
is used the i/o buffer for the copy or
nil if you want DirectoryCopy to allocate its
own buffer in the application heap.
copyBufferSize input: The size of the buffer pointed to
by copyBufferPtr.
preflight input: If true, DirectoryCopy makes sure there are
enough allocation blocks on the destination
volume to hold the directory's files before
starting the copy.
copyErrHandler input: A pointer to the routine you want called if an
error condition is detected during the copy, or
nil if you don't want to handle error conditions.
If you don't handle error conditions, the first
error will cause the copy to quit and
DirectoryCopy will return the error.
Error handling is recommended...
copyFilterProc input: A pointer to the filter routine you want called
for each item in the source directory, or NULL
if you don't want to filter.
Result Codes
noErr 0 No error
readErr <20>19 Driver does not respond to read requests
writErr <20>20 Driver does not respond to write requests
badUnitErr <20>21 Driver reference number does not
match unit table
unitEmptyErr <20>22 Driver reference number specifies a
nil handle in unit table
abortErr <20>27 Request aborted by KillIO
notOpenErr <20>28 Driver not open
dskFulErr -34 Destination volume is full
nsvErr -35 No such volume
ioErr -36 I/O error
bdNamErr -37 Bad filename
tmfoErr -42 Too many files open
fnfErr -43 Source file not found, or destination
directory does not exist
wPrErr -44 Volume locked by hardware
fLckdErr -45 File is locked
vLckdErr -46 Destination volume is read-only
fBsyErr -47 The source or destination file could
not be opened with the correct access
modes
dupFNErr -48 Destination file already exists
opWrErr -49 File already open for writing
paramErr -50 No default volume or function not
supported by volume
permErr -54 File is already open and cannot be opened using specified deny modes
memFullErr -108 Copy buffer could not be allocated
dirNFErr -120 Directory not found or incomplete pathname
wrgVolTypErr -123 Function not supported by volume
afpAccessDenied -5000 User does not have the correct access
afpDenyConflict -5006 The source or destination file could
not be opened with the correct access
modes
afpObjectTypeErr -5025 Source is a directory, directory not found
or incomplete pathname
__________
Also see: CopyErrProcPtr, CopyFilterProcPtr, FSpFilteredDirectoryCopy,
DirectoryCopy, FSpDirectoryCopy, FileCopy, FSpFileCopy
*/
/*****************************************************************************/
EXTERN_API( OSErr )
FSpFilteredDirectoryCopy(
const FSSpec * srcSpec,
const FSSpec * dstSpec,
ConstStr255Param copyName,
void * copyBufferPtr,
long copyBufferSize,
Boolean preflight,
CopyErrProcPtr copyErrHandler,
CopyFilterProcPtr copyFilterProc);
/*
The FSpFilteredDirectoryCopy function makes a copy of a directory
structure in a new location. If copyBufferPtr <> NIL, it points to
a buffer of copyBufferSize that is used to copy files data. The
larger the supplied buffer, the faster the copy. If
copyBufferPtr = NIL, then this routine allocates a buffer in the
application heap. If you pass a copy buffer to this routine, make
its size a multiple of 512 ($200) bytes for optimum performance.
The optional copyFilterProc parameter lets a routine you define
decide what files or directories are copied to the destination.
srcSpec input: An FSSpec record specifying the directory to copy.
dstSpec input: An FSSpec record specifying destination directory
of the copy.
copyName input: Points to the new directory name if the directory
is to be renamed or nil if the directory isn't to
be renamed.
copyBufferPtr input: Points to a buffer of copyBufferSize that
is used the i/o buffer for the copy or
nil if you want DirectoryCopy to allocate its
own buffer in the application heap.
copyBufferSize input: The size of the buffer pointed to
by copyBufferPtr.
preflight input: If true, FSpDirectoryCopy makes sure there are
enough allocation blocks on the destination
volume to hold the directory's files before
starting the copy.
copyErrHandler input: A pointer to the routine you want called if an
error condition is detected during the copy, or
nil if you don't want to handle error conditions.
If you don't handle error conditions, the first
error will cause the copy to quit and
DirectoryCopy will return the error.
Error handling is recommended...
copyFilterProc input: A pointer to the filter routine you want called
for each item in the source directory, or NULL
if you don't want to filter.
Result Codes
noErr 0 No error
readErr <20>19 Driver does not respond to read requests
writErr <20>20 Driver does not respond to write requests
badUnitErr <20>21 Driver reference number does not
match unit table
unitEmptyErr <20>22 Driver reference number specifies a
nil handle in unit table
abortErr <20>27 Request aborted by KillIO
notOpenErr <20>28 Driver not open
dskFulErr -34 Destination volume is full
nsvErr -35 No such volume
ioErr -36 I/O error
bdNamErr -37 Bad filename
tmfoErr -42 Too many files open
fnfErr -43 Source file not found, or destination
directory does not exist
wPrErr -44 Volume locked by hardware
fLckdErr -45 File is locked
vLckdErr -46 Destination volume is read-only
fBsyErr -47 The source or destination file could
not be opened with the correct access
modes
dupFNErr -48 Destination file already exists
opWrErr -49 File already open for writing
paramErr -50 No default volume or function not
supported by volume
permErr -54 File is already open and cannot be opened using specified deny modes
memFullErr -108 Copy buffer could not be allocated
dirNFErr -120 Directory not found or incomplete pathname
wrgVolTypErr -123 Function not supported by volume
afpAccessDenied -5000 User does not have the correct access
afpDenyConflict -5006 The source or destination file could
not be opened with the correct access
modes
afpObjectTypeErr -5025 Source is a directory, directory not found
or incomplete pathname
__________
Also see: CopyErrProcPtr, CopyFilterProcPtr, FilteredDirectoryCopy,
DirectoryCopy, FSpDirectoryCopy, FileCopy, FSpFileCopy
*/
/*****************************************************************************/
EXTERN_API( OSErr )
DirectoryCopy(
short srcVRefNum,
long srcDirID,
ConstStr255Param srcName,
short dstVRefNum,
long dstDirID,
ConstStr255Param dstName,
ConstStr255Param copyName,
void * copyBufferPtr,
long copyBufferSize,
Boolean preflight,
CopyErrProcPtr copyErrHandler);
/*
The DirectoryCopy function makes a copy of a directory structure in a
new location. If copyBufferPtr <> NIL, it points to a buffer of
copyBufferSize that is used to copy files data. The larger the
supplied buffer, the faster the copy. If copyBufferPtr = NIL, then this
routine allocates a buffer in the application heap. If you pass a
copy buffer to this routine, make its size a multiple of 512
($200) bytes for optimum performance.
DirectoryCopy normally creates a new directory *in* the specified
destination directory and copies the source directory's content into
the new directory. However, if root parent directory (fsRtParID)
is passed as the dstDirID parameter and NULL is passed as the
dstName parameter, DirectoryCopy renames the destination volume to
the source directory's name (truncating if the name is longer than
27 characters) and copies the source directory's content into the
destination volume's root directory. This special case is supported
by DirectoryCopy, but not by FSpDirectoryCopy since with
FSpDirectoryCopy, the dstName parameter can not be NULL.
srcVRefNum input: Source volume specification.
srcDirID input: Source directory ID.
srcName input: Source directory name, or nil if
srcDirID specifies the directory.
dstVRefNum input: Destination volume specification.
dstDirID input: Destination directory ID.
dstName input: Destination directory name, or nil if
dstDirID specifies the directory.
copyName input: Points to the new directory name if the directory
is to be renamed or nil if the directory isn't to
be renamed.
copyBufferPtr input: Points to a buffer of copyBufferSize that
is used the i/o buffer for the copy or
nil if you want DirectoryCopy to allocate its
own buffer in the application heap.
copyBufferSize input: The size of the buffer pointed to
by copyBufferPtr.
preflight input: If true, DirectoryCopy makes sure there are
enough allocation blocks on the destination
volume to hold the directory's files before
starting the copy.
copyErrHandler input: A pointer to the routine you want called if an
error condition is detected during the copy, or
nil if you don't want to handle error conditions.
If you don't handle error conditions, the first
error will cause the copy to quit and
DirectoryCopy will return the error.
Error handling is recommended...
Result Codes
noErr 0 No error
readErr <20>19 Driver does not respond to read requests
writErr <20>20 Driver does not respond to write requests
badUnitErr <20>21 Driver reference number does not
match unit table
unitEmptyErr <20>22 Driver reference number specifies a
nil handle in unit table
abortErr <20>27 Request aborted by KillIO
notOpenErr <20>28 Driver not open
dskFulErr -34 Destination volume is full
nsvErr -35 No such volume
ioErr -36 I/O error
bdNamErr -37 Bad filename
tmfoErr -42 Too many files open
fnfErr -43 Source file not found, or destination
directory does not exist
wPrErr -44 Volume locked by hardware
fLckdErr -45 File is locked
vLckdErr -46 Destination volume is read-only
fBsyErr -47 The source or destination file could
not be opened with the correct access
modes
dupFNErr -48 Destination file already exists
opWrErr -49 File already open for writing
paramErr -50 No default volume or function not
supported by volume
permErr -54 File is already open and cannot be opened using specified deny modes
memFullErr -108 Copy buffer could not be allocated
dirNFErr -120 Directory not found or incomplete pathname
wrgVolTypErr -123 Function not supported by volume
afpAccessDenied -5000 User does not have the correct access
afpDenyConflict -5006 The source or destination file could
not be opened with the correct access
modes
afpObjectTypeErr -5025 Source is a directory, directory not found
or incomplete pathname
__________
Also see: CopyErrProcPtr, FSpDirectoryCopy, FilteredDirectoryCopy,
FSpFilteredDirectoryCopy, FileCopy, FSpFileCopy
*/
/*****************************************************************************/
EXTERN_API( OSErr )
FSpDirectoryCopy(
const FSSpec * srcSpec,
const FSSpec * dstSpec,
ConstStr255Param copyName,
void * copyBufferPtr,
long copyBufferSize,
Boolean preflight,
CopyErrProcPtr copyErrHandler);
/*
The FSpDirectoryCopy function makes a copy of a directory structure in a
new location. If copyBufferPtr <> NIL, it points to a buffer of
copyBufferSize that is used to copy files data. The larger the
supplied buffer, the faster the copy. If copyBufferPtr = NIL, then this
routine allocates a buffer in the application heap. If you pass a
copy buffer to this routine, make its size a multiple of 512
($200) bytes for optimum performance.
srcSpec input: An FSSpec record specifying the directory to copy.
dstSpec input: An FSSpec record specifying destination directory
of the copy.
copyName input: Points to the new directory name if the directory
is to be renamed or nil if the directory isn't to
be renamed.
copyBufferPtr input: Points to a buffer of copyBufferSize that
is used the i/o buffer for the copy or
nil if you want DirectoryCopy to allocate its
own buffer in the application heap.
copyBufferSize input: The size of the buffer pointed to
by copyBufferPtr.
preflight input: If true, FSpDirectoryCopy makes sure there are
enough allocation blocks on the destination
volume to hold the directory's files before
starting the copy.
copyErrHandler input: A pointer to the routine you want called if an
error condition is detected during the copy, or
nil if you don't want to handle error conditions.
If you don't handle error conditions, the first
error will cause the copy to quit and
DirectoryCopy will return the error.
Error handling is recommended...
Result Codes
noErr 0 No error
readErr <20>19 Driver does not respond to read requests
writErr <20>20 Driver does not respond to write requests
badUnitErr <20>21 Driver reference number does not
match unit table
unitEmptyErr <20>22 Driver reference number specifies a
nil handle in unit table
abortErr <20>27 Request aborted by KillIO
notOpenErr <20>28 Driver not open
dskFulErr -34 Destination volume is full
nsvErr -35 No such volume
ioErr -36 I/O error
bdNamErr -37 Bad filename
tmfoErr -42 Too many files open
fnfErr -43 Source file not found, or destination
directory does not exist
wPrErr -44 Volume locked by hardware
fLckdErr -45 File is locked
vLckdErr -46 Destination volume is read-only
fBsyErr -47 The source or destination file could
not be opened with the correct access
modes
dupFNErr -48 Destination file already exists
opWrErr -49 File already open for writing
paramErr -50 No default volume or function not
supported by volume
permErr -54 File is already open and cannot be opened using specified deny modes
memFullErr -108 Copy buffer could not be allocated
dirNFErr -120 Directory not found or incomplete pathname
wrgVolTypErr -123 Function not supported by volume
afpAccessDenied -5000 User does not have the correct access
afpDenyConflict -5006 The source or destination file could
not be opened with the correct access
modes
afpObjectTypeErr -5025 Source is a directory, directory not found
or incomplete pathname
__________
Also see: CopyErrProcPtr, DirectoryCopy, FilteredDirectoryCopy,
FSpFilteredDirectoryCopy, FileCopy, FSpFileCopy
*/
/*****************************************************************************/
#include "OptimizationEnd.h"
#if PRAGMA_STRUCT_ALIGN
#pragma options align=reset
#elif PRAGMA_STRUCT_PACKPUSH
#pragma pack(pop)
#elif PRAGMA_STRUCT_PACK
#pragma pack()
#endif
#ifdef PRAGMA_IMPORT_OFF
#pragma import off
#elif PRAGMA_IMPORT
#pragma import reset
#endif
#ifdef __cplusplus
}
#endif
#endif /* __DIRECTORYCOPY__ */

View File

@@ -0,0 +1,946 @@
/*
File: FSpCompat.c
Contains: FSSpec compatibility functions.
Version: MoreFiles
Copyright: <09> 1992-2001 by Apple Computer, Inc., all rights reserved.
You may incorporate this sample code into your applications without
restriction, though the sample code has been provided "AS IS" and the
responsibility for its operation is 100% yours. However, what you are
not permitted to do is to redistribute the source as "DSC Sample Code"
after having made changes. If you're going to re-distribute the source,
we require that you make it clear in the source that the code was
descended from Apple Sample Code, but that you've made changes.
File Ownership:
DRI: Apple Macintosh Developer Technical Support
Other Contact: Apple Macintosh Developer Technical Support
<http://developer.apple.com/bugreporter/>
Technology: DTS Sample Code
Writers:
(JL) Jim Luther
Change History (most recent first):
<2> 2/7/01 JL Added standard header. Updated names of includes. Updated
various routines to use new calling convention of the
MoreFilesExtras accessor functions.
<1> 12/06/99 JL MoreFiles 1.5.
*/
/*
** If building application 68K code, set GENERATENODATA to 0 for faster code.
** If building stand-alone 68K code, set GENERATENODATA to 1 so globals
** (static variables) are not used.
*/
#ifndef GENERATENODATA
#define GENERATENODATA 0
#endif
#include <MacTypes.h>
#include <MacErrors.h>
#include <Files.h>
#include <LowMem.h>
#include <Gestalt.h>
#include <Resources.h>
#include <Script.h>
#define __COMPILINGMOREFILES
#include "MoreFilesExtras.h"
#include "FSpCompat.h"
/*****************************************************************************/
/* local constants */
enum {
gestaltBugFixAttrsTwo = 'bugy',
gestaltFSpExchangeFilesCompatibilityFix = 26,
gestaltBugFixAttrsThree = 'bugx',
gestaltFSpCreateScriptSupportFix = 1
};
/*****************************************************************************/
/* static prototypes */
#if !__MACOSSEVENORLATER
static Boolean FSHasFSSpecCalls(void);
static Boolean QTHasFSSpecCalls(void);
#endif /* !__MACOSSEVENORLATER */
#if !__MACOSSEVENFIVEORLATER
static Boolean HasFSpExchangeFilesCompatibilityFix(void);
static OSErr GenerateUniqueName(short volume,
long *startSeed,
long dir1,
long dir2,
StringPtr uniqueName);
#endif /* !__MACOSSEVENFIVEORLATER */
#if !__MACOSSEVENFIVEONEORLATER
static Boolean HasFSpCreateScriptSupportFix(void);
#endif /* !__MACOSSEVENFIVEONEORLATER */
/*****************************************************************************/
/* FSHasFSSpecCalls returns true if the file system provides FSSpec calls. */
#if !__MACOSSEVENORLATER
static Boolean FSHasFSSpecCalls(void)
{
long response;
#if !GENERATENODATA
static Boolean tested = false;
static Boolean result = false;
#else
Boolean result = false;
#endif
#if !GENERATENODATA
if ( !tested )
{
tested = true;
#endif
if ( Gestalt(gestaltFSAttr, &response) == noErr )
{
result = ((response & (1L << gestaltHasFSSpecCalls)) != 0);
}
#if !GENERATENODATA
}
#endif
return ( result );
}
#endif /* !__MACOSSEVENORLATER */
/*****************************************************************************/
/* QTHasFSSpecCalls returns true if QuickTime provides FSSpec calls */
/* except for FSpExchangeFiles. */
#if !__MACOSSEVENORLATER
static Boolean QTHasFSSpecCalls(void)
{
long response;
#if !GENERATENODATA
static Boolean tested = false;
static Boolean result = false;
#else
Boolean result = false;
#endif
#if !GENERATENODATA
if ( !tested )
{
tested = true;
#endif
result = (Gestalt(gestaltQuickTimeVersion, &response) == noErr);
#if !GENERATENODATA
}
#endif
return ( result );
}
#endif /* !__MACOSSEVENORLATER */
/*****************************************************************************/
/* HasFSpExchangeFilesCompatibilityFix returns true if FSpExchangeFiles */
/* compatibility code has been fixed in system software. */
/* This was fixed by System Update 3.0, so if SystemSevenFiveOrLater */
/* is true, then we know the fix is in. */
#if !__MACOSSEVENFIVEORLATER
static Boolean HasFSpExchangeFilesCompatibilityFix(void)
{
long response;
#if !GENERATENODATA
static Boolean tested = false;
static Boolean result = false;
#else /* !GENERATENODATA */
Boolean result = false;
#endif /* !GENERATENODATA */
#if !GENERATENODATA
if ( !tested )
{
tested = true;
#endif /* !GENERATENODATA */
if ( Gestalt(gestaltBugFixAttrsTwo, &response) == noErr )
{
result = ((response & (1L << gestaltFSpExchangeFilesCompatibilityFix)) != 0);
}
#if !GENERATENODATA
}
#endif /* !GENERATENODATA */
return ( result );
}
#endif /* !__MACOSSEVENFIVEORLATER */
/*****************************************************************************/
/* HasFSpCreateScriptSupportFix returns true if FSpCreate and */
/* FSpCreateResFile have been fixed in system software to correctly set */
/* the scriptCode in the volume's catalog. */
/* This was fixed by System 7.5 Update 1.0 */
#if !__MACOSSEVENFIVEONEORLATER
static Boolean HasFSpCreateScriptSupportFix(void)
{
long response;
#if !GENERATENODATA
static Boolean tested = false;
static Boolean result = false;
#else
Boolean result = false;
#endif /* !GENERATENODATA */
#if !GENERATENODATA
if ( !tested )
{
tested = true;
#endif /* !GENERATENODATA */
if ( Gestalt(gestaltBugFixAttrsThree, &response) == noErr )
{
result = ((response & (1L << gestaltFSpCreateScriptSupportFix)) != 0);
}
#if !GENERATENODATA
}
#endif /* !GENERATENODATA */
return ( result );
}
#endif /* !__MACOSSEVENFIVEONEORLATER */
/*****************************************************************************/
/*
** File Manager FSp calls
*/
/*****************************************************************************/
pascal OSErr FSMakeFSSpecCompat(short vRefNum,
long dirID,
ConstStr255Param fileName,
FSSpec *spec)
{
OSErr result;
#if !__MACOSSEVENORLATER
if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
{
Boolean isDirectory;
result = GetObjectLocation(vRefNum, dirID, fileName,
&(spec->vRefNum), &(spec->parID), spec->name,
&isDirectory);
}
else
#endif /* !__MACOSSEVENORLATER */
{
/* Let the file system create the FSSpec if it can since it does the job */
/* much more efficiently than I can. */
result = FSMakeFSSpec(vRefNum, dirID, fileName, spec);
/* Fix a bug in Macintosh PC Exchange's MakeFSSpec code where 0 is */
/* returned in the parID field when making an FSSpec to the volume's */
/* root directory by passing a full pathname in MakeFSSpec's */
/* fileName parameter. Fixed in Mac OS 8.1 */
if ( (result == noErr) && (spec->parID == 0) )
spec->parID = fsRtParID;
}
return ( result );
}
/*****************************************************************************/
pascal OSErr FSpOpenDFCompat(const FSSpec *spec,
char permission,
short *refNum)
{
#if !__MACOSSEVENORLATER
if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
{
OSErr result;
HParamBlockRec pb;
pb.ioParam.ioVRefNum = spec->vRefNum;
pb.fileParam.ioDirID = spec->parID;
pb.ioParam.ioNamePtr = (StringPtr) &(spec->name);
pb.ioParam.ioVersNum = 0;
pb.ioParam.ioPermssn = permission;
pb.ioParam.ioMisc = NULL;
result = PBHOpenSync(&pb); /* OpenDF not supported by System 6, so use Open */
*refNum = pb.ioParam.ioRefNum;
return ( result );
}
else
#endif /* !__MACOSSEVENORLATER */
{
return ( FSpOpenDF(spec, permission, refNum) );
}
}
/*****************************************************************************/
pascal OSErr FSpOpenRFCompat(const FSSpec *spec,
char permission,
short *refNum)
{
#if !__MACOSSEVENORLATER
if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
{
OSErr result;
HParamBlockRec pb;
pb.ioParam.ioVRefNum = spec->vRefNum;
pb.fileParam.ioDirID = spec->parID;
pb.ioParam.ioNamePtr = (StringPtr) &(spec->name);
pb.ioParam.ioVersNum = 0;
pb.ioParam.ioPermssn = permission;
pb.ioParam.ioMisc = NULL;
result = PBHOpenRFSync(&pb);
*refNum = pb.ioParam.ioRefNum;
return ( result );
}
else
#endif /* !__MACOSSEVENORLATER */
{
return ( FSpOpenRF(spec, permission, refNum) );
}
}
/*****************************************************************************/
pascal OSErr FSpCreateCompat(const FSSpec *spec,
OSType creator,
OSType fileType,
ScriptCode scriptTag)
{
#if !__MACOSSEVENFIVEONEORLATER
OSErr result;
UniversalFMPB pb;
if (
#if !__MACOSSEVENORLATER
(!FSHasFSSpecCalls() && !QTHasFSSpecCalls()) ||
#endif /* !__MACOSSEVENORLATER */
!HasFSpCreateScriptSupportFix() )
{
/* If FSpCreate isn't called, this code will be executed */
pb.hPB.fileParam.ioVRefNum = spec->vRefNum;
pb.hPB.fileParam.ioDirID = spec->parID;
pb.hPB.fileParam.ioNamePtr = (StringPtr) &(spec->name);
pb.hPB.fileParam.ioFVersNum = 0;
result = PBHCreateSync(&(pb.hPB));
if ( result == noErr )
{
/* get info on created item */
pb.ciPB.hFileInfo.ioFDirIndex = 0;
result = PBGetCatInfoSync(&(pb.ciPB));
if ( result == noErr )
{
/* Set fdScript in FXInfo */
/* The negative script constants (smSystemScript, smCurrentScript, and smAllScripts) */
/* don't make sense on disk, so only use scriptTag if scriptTag >= smRoman */
/* (smRoman is 0). fdScript is valid if high bit is set (see IM-6, page 9-38) */
pb.ciPB.hFileInfo.ioFlXFndrInfo.fdScript = (scriptTag >= smRoman) ?
((char)scriptTag | (char)0x80) :
(smRoman);
/* Set creator/fileType */
pb.ciPB.hFileInfo.ioFlFndrInfo.fdCreator = creator;
pb.ciPB.hFileInfo.ioFlFndrInfo.fdType = fileType;
/* Restore ioDirID field in pb which was changed by PBGetCatInfo */
pb.ciPB.hFileInfo.ioDirID = spec->parID;
result = PBSetCatInfoSync(&(pb.ciPB));
}
}
return ( result );
}
else
#endif /* !__MACOSSEVENFIVEONEORLATER */
{
return ( FSpCreate(spec, creator, fileType, scriptTag) );
}
}
/*****************************************************************************/
pascal OSErr FSpDirCreateCompat(const FSSpec *spec,
ScriptCode scriptTag,
long *createdDirID)
{
#if !__MACOSSEVENORLATER
if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
{
OSErr result;
UniversalFMPB pb;
pb.hPB.fileParam.ioVRefNum = spec->vRefNum;
pb.hPB.fileParam.ioDirID = spec->parID;
pb.hPB.fileParam.ioNamePtr = (StringPtr) &(spec->name);
result = PBDirCreateSync(&(pb.hPB));
*createdDirID = pb.hPB.fileParam.ioDirID;
if ( result == noErr )
{
/* get info on created item */
pb.ciPB.dirInfo.ioFDirIndex = 0;
pb.ciPB.dirInfo.ioDrDirID = spec->parID;
result = PBGetCatInfoSync(&(pb.ciPB));
if ( result == noErr )
{
/* Set frScript in DXInfo */
/* The negative script constants (smSystemScript, smCurrentScript, and smAllScripts) */
/* don't make sense on disk, so only use scriptTag if scriptTag >= smRoman */
/* (smRoman is 0). frScript is valid if high bit is set (see IM-6, page 9-38) */
pb.ciPB.dirInfo.ioDrFndrInfo.frScript = (scriptTag >= smRoman) ?
((char)scriptTag | (char)0x80) :
(smRoman);
/* Restore ioDirID field in pb which was changed by PBGetCatInfo */
pb.ciPB.dirInfo.ioDrDirID = spec->parID;
result = PBSetCatInfoSync(&(pb.ciPB));
}
}
return ( result );
}
else
#endif /* !__MACOSSEVENORLATER */
{
return ( FSpDirCreate(spec, scriptTag, createdDirID) );
}
}
/*****************************************************************************/
pascal OSErr FSpDeleteCompat(const FSSpec *spec)
{
#if !__MACOSSEVENORLATER
if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
{
HParamBlockRec pb;
pb.ioParam.ioVRefNum = spec->vRefNum;
pb.fileParam.ioDirID = spec->parID;
pb.ioParam.ioNamePtr = (StringPtr) &(spec->name);
pb.ioParam.ioVersNum = 0;
return ( PBHDeleteSync(&pb) );
}
else
#endif /* !__MACOSSEVENORLATER */
{
return ( FSpDelete(spec) );
}
}
/*****************************************************************************/
pascal OSErr FSpGetFInfoCompat(const FSSpec *spec,
FInfo *fndrInfo)
{
#if !__MACOSSEVENORLATER
if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
{
OSErr result;
HParamBlockRec pb;
pb.fileParam.ioVRefNum = spec->vRefNum;
pb.fileParam.ioDirID = spec->parID;
pb.fileParam.ioNamePtr = (StringPtr) &(spec->name);
pb.fileParam.ioFVersNum = 0;
pb.fileParam.ioFDirIndex = 0;
result = PBHGetFInfoSync(&pb);
*fndrInfo = pb.fileParam.ioFlFndrInfo;
return ( result );
}
else
#endif /* !__MACOSSEVENORLATER */
{
return ( FSpGetFInfo(spec, fndrInfo) );
}
}
/*****************************************************************************/
pascal OSErr FSpSetFInfoCompat(const FSSpec *spec,
const FInfo *fndrInfo)
{
#if !__MACOSSEVENORLATER
if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
{
OSErr result;
HParamBlockRec pb;
pb.fileParam.ioVRefNum = spec->vRefNum;
pb.fileParam.ioDirID = spec->parID;
pb.fileParam.ioNamePtr = (StringPtr) &(spec->name);
pb.fileParam.ioFVersNum = 0;
pb.fileParam.ioFDirIndex = 0;
result = PBHGetFInfoSync(&pb);
if ( result == noErr )
{
pb.fileParam.ioFlFndrInfo = *fndrInfo;
pb.fileParam.ioDirID = spec->parID;
result = PBHSetFInfoSync(&pb);
}
return ( result );
}
else
#endif /* !__MACOSSEVENORLATER */
{
return ( FSpSetFInfo(spec, fndrInfo) );
}
}
/*****************************************************************************/
pascal OSErr FSpSetFLockCompat(const FSSpec *spec)
{
#if !__MACOSSEVENORLATER
if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
{
HParamBlockRec pb;
pb.fileParam.ioVRefNum = spec->vRefNum;
pb.fileParam.ioDirID = spec->parID;
pb.fileParam.ioNamePtr = (StringPtr) &(spec->name);
pb.fileParam.ioFVersNum = 0;
return ( PBHSetFLockSync(&pb) );
}
else
#endif /* !__MACOSSEVENORLATER */
{
return ( FSpSetFLock(spec) );
}
}
/*****************************************************************************/
pascal OSErr FSpRstFLockCompat(const FSSpec *spec)
{
#if !__MACOSSEVENORLATER
if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
{
HParamBlockRec pb;
pb.fileParam.ioVRefNum = spec->vRefNum;
pb.fileParam.ioDirID = spec->parID;
pb.fileParam.ioNamePtr = (StringPtr) &(spec->name);
pb.fileParam.ioFVersNum = 0;
return ( PBHRstFLockSync(&pb) );
}
else
#endif /* !__MACOSSEVENORLATER */
{
return ( FSpRstFLock(spec) );
}
}
/*****************************************************************************/
pascal OSErr FSpRenameCompat(const FSSpec *spec,
ConstStr255Param newName)
{
#if !__MACOSSEVENORLATER
if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
{
HParamBlockRec pb;
pb.ioParam.ioVRefNum = spec->vRefNum;
pb.fileParam.ioDirID = spec->parID;
pb.ioParam.ioNamePtr = (StringPtr) &(spec->name);
pb.ioParam.ioVersNum = 0;
pb.ioParam.ioMisc = (Ptr) newName;
return ( PBHRenameSync(&pb) );
}
else
#endif /* !__MACOSSEVENORLATER */
{
return ( FSpRename(spec, newName) );
}
}
/*****************************************************************************/
pascal OSErr FSpCatMoveCompat(const FSSpec *source,
const FSSpec *dest)
{
#if !__MACOSSEVENORLATER
if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
{
CMovePBRec pb;
/* source and destination volume must be the same */
if ( source->vRefNum != dest->vRefNum )
return ( paramErr );
pb.ioNamePtr = (StringPtr) &(source->name);
pb.ioVRefNum = source->vRefNum;
pb.ioDirID = source->parID;
pb.ioNewDirID = dest->parID;
pb.ioNewName = (StringPtr) &(dest->name);
return ( PBCatMoveSync(&pb) );
}
else
#endif /* !__MACOSSEVENORLATER */
{
return ( FSpCatMove(source, dest) );
}
}
/*****************************************************************************/
/* GenerateUniqueName generates a name that is unique in both dir1 and dir2 */
/* on the specified volume. Ripped off from Feldman's code. */
#if !__MACOSSEVENFIVEORLATER
static OSErr GenerateUniqueName(short volume,
long *startSeed,
long dir1,
long dir2,
StringPtr uniqueName)
{
OSErr error = noErr;
long i;
CInfoPBRec cinfo;
unsigned char hexStr[16];
for ( i = 0; i < 16; ++i )
{
if ( i < 10 )
{
hexStr[i] = 0x30 + i;
}
else
{
hexStr[i] = 0x37 + i;
}
}
cinfo.hFileInfo.ioVRefNum = volume;
cinfo.hFileInfo.ioFDirIndex = 0;
cinfo.hFileInfo.ioNamePtr = uniqueName;
while ( error != fnfErr )
{
(*startSeed)++;
cinfo.hFileInfo.ioNamePtr[0] = 8;
for ( i = 1; i <= 8; i++ )
{
cinfo.hFileInfo.ioNamePtr[i] = hexStr[((*startSeed >> ((8-i)*4)) & 0xf)];
}
cinfo.hFileInfo.ioDirID = dir1;
error = fnfErr;
for ( i = 1; i <= 2; i++ )
{
error = error & PBGetCatInfoSync(&cinfo);
cinfo.hFileInfo.ioDirID = dir2;
if ( (error != fnfErr) && (error != noErr) )
{
return ( error );
}
}
}
return ( noErr );
}
#endif /* !__MACOSSEVENFIVEORLATER */
/*****************************************************************************/
pascal OSErr FSpExchangeFilesCompat(const FSSpec *source,
const FSSpec *dest)
{
#if !__MACOSSEVENFIVEORLATER
if (
#if !__MACOSSEVENORLATER
!FSHasFSSpecCalls() ||
#endif /* !__MACOSSEVENORLATER */
!HasFSpExchangeFilesCompatibilityFix() )
{
HParamBlockRec pb;
CInfoPBRec catInfoSource, catInfoDest;
OSErr result, result2;
Str31 unique1, unique2;
StringPtr unique1Ptr, unique2Ptr, swapola;
GetVolParmsInfoBuffer volInfo;
long theSeed, temp;
/* Make sure the source and destination are on the same volume */
if ( source->vRefNum != dest->vRefNum )
{
result = diffVolErr;
goto errorExit3;
}
/* Try PBExchangeFiles first since it preserves the file ID reference */
pb.fidParam.ioNamePtr = (StringPtr) &(source->name);
pb.fidParam.ioVRefNum = source->vRefNum;
pb.fidParam.ioDestNamePtr = (StringPtr) &(dest->name);
pb.fidParam.ioDestDirID = dest->parID;
pb.fidParam.ioSrcDirID = source->parID;
result = PBExchangeFilesSync(&pb);
/* Note: The compatibility case won't work for files with *Btree control blocks. */
/* Right now the only *Btree files are created by the system. */
if ( result != noErr )
{
pb.ioParam.ioNamePtr = NULL;
pb.ioParam.ioBuffer = (Ptr) &volInfo;
pb.ioParam.ioReqCount = sizeof(volInfo);
result2 = PBHGetVolParmsSync(&pb);
/* continue if volume has no fileID support (or no GetVolParms support) */
if ( (result2 == noErr) && hasFileIDs(&volInfo) )
{
goto errorExit3;
}
/* Get the catalog information for each file */
/* and make sure both files are *really* files */
catInfoSource.hFileInfo.ioVRefNum = source->vRefNum;
catInfoSource.hFileInfo.ioFDirIndex = 0;
catInfoSource.hFileInfo.ioNamePtr = (StringPtr) &(source->name);
catInfoSource.hFileInfo.ioDirID = source->parID;
catInfoSource.hFileInfo.ioACUser = 0; /* ioACUser used to be filler2 */
result = PBGetCatInfoSync(&catInfoSource);
if ( result != noErr )
{
goto errorExit3;
}
if ( (catInfoSource.hFileInfo.ioFlAttrib & kioFlAttribDirMask) != 0 )
{
result = notAFileErr;
goto errorExit3;
}
catInfoDest.hFileInfo.ioVRefNum = dest->vRefNum;
catInfoDest.hFileInfo.ioFDirIndex = 0;
catInfoDest.hFileInfo.ioNamePtr = (StringPtr) &(dest->name);
catInfoDest.hFileInfo.ioDirID = dest->parID;
catInfoDest.hFileInfo.ioACUser = 0; /* ioACUser used to be filler2 */
result = PBGetCatInfoSync(&catInfoDest);
if ( result != noErr )
{
goto errorExit3;
}
if ( (catInfoDest.hFileInfo.ioFlAttrib & kioFlAttribDirMask) != 0 )
{
result = notAFileErr;
goto errorExit3;
}
/* generate 2 filenames that are unique in both directories */
theSeed = 0x64666A6C; /* a fine unlikely filename */
unique1Ptr = (StringPtr)&unique1;
unique2Ptr = (StringPtr)&unique2;
result = GenerateUniqueName(source->vRefNum, &theSeed, source->parID, dest->parID, unique1Ptr);
if ( result != noErr )
{
goto errorExit3;
}
GenerateUniqueName(source->vRefNum, &theSeed, source->parID, dest->parID, unique2Ptr);
if ( result != noErr )
{
goto errorExit3;
}
/* rename source to unique1 */
pb.fileParam.ioNamePtr = (StringPtr) &(source->name);
pb.ioParam.ioMisc = (Ptr) unique1Ptr;
pb.ioParam.ioVersNum = 0;
result = PBHRenameSync(&pb);
if ( result != noErr )
{
goto errorExit3;
}
/* rename dest to unique2 */
pb.ioParam.ioMisc = (Ptr) unique2Ptr;
pb.ioParam.ioVersNum = 0;
pb.fileParam.ioNamePtr = (StringPtr) &(dest->name);
pb.fileParam.ioDirID = dest->parID;
result = PBHRenameSync(&pb);
if ( result != noErr )
{
goto errorExit2; /* back out gracefully by renaming unique1 back to source */
}
/* If files are not in same directory, swap their locations */
if ( source->parID != dest->parID )
{
/* move source file to dest directory */
pb.copyParam.ioNamePtr = unique1Ptr;
pb.copyParam.ioNewName = NULL;
pb.copyParam.ioNewDirID = dest->parID;
pb.copyParam.ioDirID = source->parID;
result = PBCatMoveSync((CMovePBPtr) &pb);
if ( result != noErr )
{
goto errorExit1; /* back out gracefully by renaming both files to original names */
}
/* move dest file to source directory */
pb.copyParam.ioNamePtr = unique2Ptr;
pb.copyParam.ioNewDirID = source->parID;
pb.copyParam.ioDirID = dest->parID;
result = PBCatMoveSync((CMovePBPtr) &pb);
if ( result != noErr)
{
/* life is very bad. We'll at least try to move source back */
pb.copyParam.ioNamePtr = unique1Ptr;
pb.copyParam.ioNewName = NULL;
pb.copyParam.ioNewDirID = source->parID;
pb.copyParam.ioDirID = dest->parID;
(void) PBCatMoveSync((CMovePBPtr) &pb); /* ignore errors */
goto errorExit1; /* back out gracefully by renaming both files to original names */
}
}
/* Make unique1Ptr point to file in source->parID */
/* and unique2Ptr point to file in dest->parID */
/* This lets us fall through to the rename code below */
swapola = unique1Ptr;
unique1Ptr = unique2Ptr;
unique2Ptr = swapola;
/* At this point, the files are in their new locations (if they were moved) */
/* Source is named Unique1 (name pointed to by unique2Ptr) and is in dest->parID */
/* Dest is named Unique2 (name pointed to by unique1Ptr) and is in source->parID */
/* Need to swap attributes except mod date and swap names */
/* swap the catalog info by re-aiming the CInfoPB's */
catInfoSource.hFileInfo.ioNamePtr = unique1Ptr;
catInfoDest.hFileInfo.ioNamePtr = unique2Ptr;
catInfoSource.hFileInfo.ioDirID = source->parID;
catInfoDest.hFileInfo.ioDirID = dest->parID;
/* Swap the original mod dates with each file */
temp = catInfoSource.hFileInfo.ioFlMdDat;
catInfoSource.hFileInfo.ioFlMdDat = catInfoDest.hFileInfo.ioFlMdDat;
catInfoDest.hFileInfo.ioFlMdDat = temp;
/* Here's the swap (ignore errors) */
(void) PBSetCatInfoSync(&catInfoSource);
(void) PBSetCatInfoSync(&catInfoDest);
/* rename unique2 back to dest */
errorExit1:
pb.ioParam.ioMisc = (Ptr) &(dest->name);
pb.ioParam.ioVersNum = 0;
pb.fileParam.ioNamePtr = unique2Ptr;
pb.fileParam.ioDirID = dest->parID;
(void) PBHRenameSync(&pb); /* ignore errors */
/* rename unique1 back to source */
errorExit2:
pb.ioParam.ioMisc = (Ptr) &(source->name);
pb.ioParam.ioVersNum = 0;
pb.fileParam.ioNamePtr = unique1Ptr;
pb.fileParam.ioDirID = source->parID;
(void) PBHRenameSync(&pb); /* ignore errors */
}
errorExit3: { /* null statement */ }
return ( result );
}
else
#endif /* !__MACOSSEVENFIVEORLATER */
{
return ( FSpExchangeFiles(source, dest) );
}
}
/*****************************************************************************/
/*
** Resource Manager FSp calls
*/
/*****************************************************************************/
pascal short FSpOpenResFileCompat(const FSSpec *spec,
SignedByte permission)
{
#if !__MACOSSEVENORLATER
if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
{
return ( HOpenResFile(spec->vRefNum, spec->parID, spec->name, permission) );
}
else
#endif /* !__MACOSSEVENORLATER */
{
return ( FSpOpenResFile(spec, permission) );
}
}
/*****************************************************************************/
pascal void FSpCreateResFileCompat(const FSSpec *spec,
OSType creator,
OSType fileType,
ScriptCode scriptTag)
{
#if !__MACOSSEVENFIVEONEORLATER
if (
#if !__MACOSSEVENORLATER
(!FSHasFSSpecCalls() && !QTHasFSSpecCalls()) ||
#endif /* !__MACOSSEVENORLATER */
!HasFSpCreateScriptSupportFix() )
{
OSErr result;
CInfoPBRec pb;
HCreateResFile(spec->vRefNum, spec->parID, spec->name);
if ( ResError() == noErr )
{
/* get info on created item */
pb.hFileInfo.ioVRefNum = spec->vRefNum;
pb.hFileInfo.ioDirID = spec->parID;
pb.hFileInfo.ioNamePtr = (StringPtr) &(spec->name);
pb.hFileInfo.ioFDirIndex = 0;
result = PBGetCatInfoSync(&pb);
if ( result == noErr )
{
/* Set fdScript in FXInfo */
/* The negative script constants (smSystemScript, smCurrentScript, and smAllScripts) */
/* don't make sense on disk, so only use scriptTag if scriptTag >= smRoman */
/* (smRoman is 0). fdScript is valid if high bit is set (see IM-6, page 9-38) */
pb.hFileInfo.ioFlXFndrInfo.fdScript = (scriptTag >= smRoman) ?
((char)scriptTag | (char)0x80) :
(smRoman);
/* Set creator/fileType */
pb.hFileInfo.ioFlFndrInfo.fdCreator = creator;
pb.hFileInfo.ioFlFndrInfo.fdType = fileType;
/* Restore ioDirID field in pb which was changed by PBGetCatInfo */
pb.hFileInfo.ioDirID = spec->parID;
result = PBSetCatInfoSync(&pb);
}
/* Set ResErr low memory global to result */
LMSetResErr(result);
}
return;
}
else
#endif /* !__MACOSSEVENFIVEONEORLATER */
{
FSpCreateResFile(spec, creator, fileType, scriptTag);
return;
}
}
/*****************************************************************************/

View File

@@ -0,0 +1,586 @@
/*
File: FSpCompat.h
Contains: FSSpec compatibility functions.
Version: Technology: MoreFiles
Release: 1.5.2
Copyright: <20> 1992-2001 by Apple Computer, Inc., all rights reserved.
Bugs?: For bug reports, consult the following page on
the World Wide Web:
http://developer.apple.com/bugreporter/
*/
/*
You may incorporate this sample code into your applications without
restriction, though the sample code has been provided "AS IS" and the
responsibility for its operation is 100% yours. However, what you are
not permitted to do is to redistribute the source as "DSC Sample Code"
after having made changes. If you're going to re-distribute the source,
we require that you make it clear in the source that the code was
descended from Apple Sample Code, but that you've made changes.
*/
#ifndef __FSPCOMPAT__
#define __FSPCOMPAT__
#ifndef __MACTYPES__
#include <MacTypes.h>
#endif
#ifndef __FILES__
#include <Files.h>
#endif
#include "Optimization.h"
#if PRAGMA_ONCE
#pragma once
#endif
#ifdef __cplusplus
extern "C" {
#endif
#if PRAGMA_IMPORT
#pragma import on
#endif
#if PRAGMA_STRUCT_ALIGN
#pragma options align=mac68k
#elif PRAGMA_STRUCT_PACKPUSH
#pragma pack(push, 2)
#elif PRAGMA_STRUCT_PACK
#pragma pack(2)
#endif
/*****************************************************************************/
EXTERN_API( OSErr )
FSMakeFSSpecCompat(
short vRefNum,
long dirID,
ConstStr255Param fileName,
FSSpec * spec);
/*
The FSMakeFSSpecCompat function fills in the fields of an FSSpec record.
If the file system can't create the FSSpec, then the compatibility code
creates a FSSpec that is exactly like an FSSpec except that spec.name
for a file may not have the same capitalization as the file's catalog
entry on the disk volume. That is because fileName is parsed to get the
name instead of getting the name back from the file system. This works
fine with System 6 where FSMakeSpec isn't available.
vRefNum input: Volume specification.
dirID input: Directory ID.
fileName input: Pointer to object name, or nil when dirID specifies
a directory that's the object.
spec output: A file system specification to be filled in by
FSMakeFSSpecCompat.
Result Codes
noErr 0 No error
nsvErr -35 Volume doesn<73>t exist
fnfErr -43 File or directory does not exist
(FSSpec is still valid)
*/
/*****************************************************************************/
EXTERN_API( OSErr )
FSpOpenDFCompat(
const FSSpec * spec,
char permission,
short * refNum);
/*
The FSpOpenDFCompat function opens the data fork of the file specified
by spec.
Differences from FSpOpenDF: If FSpOpenDF isn't available,
FSpOpenDFCompat uses PHBOpen because System 6 doesn't support PBHOpenDF.
This means FSpOpenDFCompat could accidentally open a driver if the
spec->name begins with a period.
spec input: An FSSpec record specifying the file whose data
fork is to be opened.
permission input: A constant indicating the desired file access
permissions.
refNum output: A reference number of an access path to the file's
data fork.
Result Codes
noErr 0 No error
nsvErr -35 No such volume
ioErr -36 I/O error
bdNamErr -37 Bad filename
tmfoErr -42 Too many files open
fnfErr -43 File not found
opWrErr -49 File already open for writing
permErr -54 Attempt to open locked file for writing
dirNFErr -120 Directory not found or incomplete pathname
afpAccessDenied -5000 User does not have the correct access to
the file
__________
See also: FSpOpenAware
*/
/*****************************************************************************/
EXTERN_API( OSErr )
FSpOpenRFCompat(
const FSSpec * spec,
char permission,
short * refNum);
/*
The FSpOpenRFCompat function opens the resource fork of the file
specified by spec.
spec input: An FSSpec record specifying the file whose resource
fork is to be opened.
permission input: A constant indicating the desired file access
permissions.
refNum output: A reference number of an access path to the file's
resource fork.
Result Codes
noErr 0 No error
nsvErr -35 No such volume
ioErr -36 I/O error
bdNamErr -37 Bad filename
tmfoErr -42 Too many files open
fnfErr -43 File not found
opWrErr -49 File already open for writing
permErr -54 Attempt to open locked file for writing
dirNFErr -120 Directory not found or incomplete pathname
afpAccessDenied -5000 User does not have the correct access to
the file
__________
See also: FSpOpenRFAware
*/
/*****************************************************************************/
EXTERN_API( OSErr )
FSpCreateCompat(
const FSSpec * spec,
OSType creator,
OSType fileType,
ScriptCode scriptTag);
/*
The FSpCreateCompat function creates a new file with the specified
type, creator, and script code.
Differences from FSpCreate: FSpCreateCompat correctly sets the
fdScript in the file's FXInfo record to scriptTag if the problem
isn't fixed in the File Manager code.
spec input: An FSSpec record specifying the file to create.
creator input: The creator of the new file.
fileType input The file type of the new file.
scriptCode input: The code of the script system in which the file
name is to be displayed.
Result Codes
noErr 0 No error
dirFulErr -33 File directory full
dskFulErr -34 Disk is full
nsvErr -35 No such volume
ioErr -36 I/O error
bdNamErr -37 Bad filename
fnfErr -43 Directory not found or incomplete pathname
wPrErr -44 Hardware volume lock
vLckdErr -46 Software volume lock
dupFNErr -48 Duplicate filename and version
dirNFErrdirNFErr -120 Directory not found or incomplete pathname
afpAccessDenied -5000 User does not have the correct access
afpObjectTypeErr -5025 A directory exists with that name
*/
/*****************************************************************************/
EXTERN_API( OSErr )
FSpDirCreateCompat(
const FSSpec * spec,
ScriptCode scriptTag,
long * createdDirID);
/*
The FSpDirCreateCompat function creates a new directory and returns the
directory ID of the newDirectory.
spec input: An FSSpec record specifying the directory to
create.
scriptCode input: The code of the script system in which the
directory name is to be displayed.
createdDirID output: The directory ID of the directory that was
created.
Result Codes
noErr 0 No error
dirFulErr -33 File directory full
dskFulErr -34 Disk is full
nsvErr -35 No such volume
ioErr -36 I/O error
bdNamErr -37 Bad filename
fnfErr -43 Directory not found or incomplete pathname
wPrErr -44 Hardware volume lock
vLckdErr -46 Software volume lock
dupFNErr -48 Duplicate filename and version
dirNFErrdirNFErr -120 Directory not found or incomplete pathname
wrgVolTypErr -123 Not an HFS volume
afpAccessDenied -5000 User does not have the correct access
*/
/*****************************************************************************/
EXTERN_API( OSErr )
FSpDeleteCompat(const FSSpec * spec);
/*
The FSpDeleteCompat function deletes a file or directory.
spec input: An FSSpec record specifying the file or
directory to delete.
Result Codes
noErr 0 No error
nsvErr -35 No such volume
ioErr -36 I/O error
bdNamErr -37 Bad filename
fnfErr -43 File not found
wPrErr -44 Hardware volume lock
fLckdErr -45 File is locked
vLckdErr -46 Software volume lock
fBsyErr -47 File busy, directory not empty, or
working directory control block open
dirNFErrdirNFErr -120 Directory not found or incomplete pathname
afpAccessDenied -5000 User does not have the correct access
*/
/*****************************************************************************/
EXTERN_API( OSErr )
FSpGetFInfoCompat(
const FSSpec * spec,
FInfo * fndrInfo);
/*
The FSpGetFInfoCompat function gets the finder information for a file.
spec input: An FSSpec record specifying the file.
fndrInfo output: If the object is a file, then its FInfo.
Result Codes
noErr 0 No error
nsvErr -35 No such volume
ioErr -36 I/O error
bdNamErr -37 Bad filename
fnfErr -43 File not found
paramErr -50 No default volume
dirNFErrdirNFErr -120 Directory not found or incomplete pathname
afpAccessDenied -5000 User does not have the correct access
afpObjectTypeErr -5025 Directory not found or incomplete pathname
__________
Also see: FSpGetDInfo
*/
/*****************************************************************************/
EXTERN_API( OSErr )
FSpSetFInfoCompat(
const FSSpec * spec,
const FInfo * fndrInfo);
/*
The FSpSetFInfoCompat function sets the finder information for a file.
spec input: An FSSpec record specifying the file.
fndrInfo input: The FInfo.
Result Codes
noErr 0 No error
nsvErr -35 No such volume
ioErr -36 I/O error
bdNamErr -37 Bad filename
fnfErr -43 File not found
wPrErr -44 Hardware volume lock
fLckdErr -45 File is locked
vLckdErr -46 Software volume lock
dirNFErrdirNFErr -120 Directory not found or incomplete pathname
afpAccessDenied -5000 User does not have the correct access
afpObjectTypeErr -5025 Object was a directory
__________
Also see: FSpSetDInfo
*/
/*****************************************************************************/
EXTERN_API( OSErr )
FSpSetFLockCompat(const FSSpec * spec);
/*
The FSpSetFLockCompat function locks a file.
spec input: An FSSpec record specifying the file.
Result Codes
noErr 0 No error
nsvErr -35 No such volume
ioErr -36 I/O error
fnfErr -43 File not found
wPrErr -44 Hardware volume lock
vLckdErr -46 Software volume lock
dirNFErrdirNFErr -120 Directory not found or incomplete pathname
afpAccessDenied -5000 User does not have the correct access to
the file
afpObjectTypeErr -5025 Folder locking not supported by volume
*/
/*****************************************************************************/
EXTERN_API( OSErr )
FSpRstFLockCompat(const FSSpec * spec);
/*
The FSpRstFLockCompat function unlocks a file.
spec input: An FSSpec record specifying the file.
Result Codes
noErr 0 No error
nsvErr -35 No such volume
ioErr -36 I/O error
fnfErr -43 File not found
wPrErr -44 Hardware volume lock
vLckdErr -46 Software volume lock
dirNFErrdirNFErr -120 Directory not found or incomplete pathname
afpAccessDenied -5000 User does not have the correct access to
the file
afpObjectTypeErr -5025 Folder locking not supported by volume
*/
/*****************************************************************************/
EXTERN_API( OSErr )
FSpRenameCompat(
const FSSpec * spec,
ConstStr255Param newName);
/*
The FSpRenameCompat function renames a file or directory.
spec input: An FSSpec record specifying the file.
newName input: The new name of the file or directory.
Result Codes
noErr 0 No error
dirFulErr -33 File directory full
dskFulErr -34 Volume is full
nsvErr -35 No such volume
ioErr -36 I/O error
bdNamErr -37 Bad filename
fnfErr -43 File not found
wPrErr -44 Hardware volume lock
fLckdErr -45 File is locked
vLckdErr -46 Software volume lock
dupFNErr -48 Duplicate filename and version
paramErr -50 No default volume
fsRnErr -59 Problem during rename
dirNFErrdirNFErr -120 Directory not found or incomplete pathname
afpAccessDenied -5000 User does not have the correct access to
the file
*/
/*****************************************************************************/
EXTERN_API( OSErr )
FSpCatMoveCompat(
const FSSpec * source,
const FSSpec * dest);
/*
The FSpCatMoveCompat function moves a file or directory to a different
location on on the same volume.
source input: An FSSpec record specifying the file or directory.
dest input: An FSSpec record specifying the name and location
of the directory into which the source file or
directory is to be moved.
Result Codes
noErr 0 No error
nsvErr -35 No such volume
ioErr -36 I/O error
bdNamErr -37 Bad filename or attempt to move into
a file
fnfErr -43 File not found
wPrErr -44 Hardware volume lock
fLckdErr -45 Target directory is locked
vLckdErr -46 Software volume lock
dupFNErr -48 Duplicate filename and version
paramErr -50 No default volume
badMovErr -122 Attempt to move into offspring
wrgVolTypErr -123 Not an HFS volume
afpAccessDenied -5000 User does not have the correct access to
the file
*/
/*****************************************************************************/
EXTERN_API( OSErr )
FSpExchangeFilesCompat(
const FSSpec * source,
const FSSpec * dest);
/*
The FSpExchangeFilesCompat function swaps the data in two files by
changing the information in the volume's catalog and, if the files
are open, in the file control blocks.
Differences from FSpExchangeFiles: Correctly exchanges files on volumes
that don't support PBExchangeFiles. FSpExchangeFiles attempts to support
volumes that don't support PBExchangeFiles, but in System 7, 7.0.1, 7.1,
and 7 Pro, the compatibility code just doesn't work on volumes that
don't support PBExchangeFiles (even though you may get a noErr result).
System Update 3.0 and System 7.5 and later have the problems in
FSpExchangeFiles corrected.
Result Codes
noErr 0 No error
nsvErr -35 Volume not found
ioErr -36 I/O error
fnfErr -43 File not found
fLckdErr -45 File is locked
vLckdErr -46 Volume is locked or read-only
paramErr -50 Function not supported by volume
volOfflinErr -53 Volume is offline
wrgVolTypErr -123 Not an HFS volume
diffVolErr -1303 Files on different volumes
afpAccessDenied -5000 User does not have the correct access
afpObjectTypeErr -5025 Object is a directory, not a file
afpSameObjectErr -5038 Source and destination files are the same
*/
/*****************************************************************************/
EXTERN_API( short )
FSpOpenResFileCompat(
const FSSpec * spec,
SignedByte permission);
/*
The FSpOpenResFileCompat function opens the resource file specified
by spec.
spec input: An FSSpec record specifying the file whose
resource file is to be opened.
permission input: A constant indicating the desired file access
permissions.
function result output: A resource file reference number, or if there's
an error -1.
Result Codes
noErr 0 No error
nsvErr <20>35 No such volume
ioErr <20>36 I/O error
bdNamErr <20>37 Bad filename or volume name (perhaps zero
length)
eofErr <20>39 End of file
tmfoErr <20>42 Too many files open
fnfErr <20>43 File not found
opWrErr <20>49 File already open with write permission
permErr <20>54 Permissions error (on file open)
extFSErr <20>58 Volume belongs to an external file system
memFullErr <20>108 Not enough room in heap zone
dirNFErr <20>120 Directory not found
mapReadErr <20>199 Map inconsistent with operation
*/
/*****************************************************************************/
EXTERN_API( void )
FSpCreateResFileCompat(
const FSSpec * spec,
OSType creator,
OSType fileType,
ScriptCode scriptTag);
/*
The FSpCreateResFileCompat function creates a new resource file with
the specified type, creator, and script code.
Differences from FSpCreateResFile: FSpCreateResFileCompat correctly
sets the fdScript in the file's FXInfo record to scriptTag if the
problem isn't fixed in the File Manager code.
spec input: An FSSpec record specifying the resource file to create.
creator input: The creator of the new file.
fileType input The file type of the new file.
scriptCode input: The code of the script system in which the file
name is to be displayed.
Result Codes
noErr 0 No error
dirFulErr <20>33 Directory full
dskFulErr <20>34 Disk full
nsvErr <20>35 No such volume
ioErr <20>36 I/O error
bdNamErr <20>37 Bad filename or volume name (perhaps zero
length)
tmfoErr <20>42 Too many files open
wPrErrw <20>44 Disk is write-protected
fLckdErr <20>45 File is locked
*/
/*****************************************************************************/
#include "OptimizationEnd.h"
#if PRAGMA_STRUCT_ALIGN
#pragma options align=reset
#elif PRAGMA_STRUCT_PACKPUSH
#pragma pack(pop)
#elif PRAGMA_STRUCT_PACK
#pragma pack()
#endif
#ifdef PRAGMA_IMPORT_OFF
#pragma import off
#elif PRAGMA_IMPORT
#pragma import reset
#endif
#ifdef __cplusplus
}
#endif
#endif /* __FSPCOMPAT__ */

View File

@@ -0,0 +1,611 @@
/*
File: FileCopy.c
Contains: A robust, general purpose file copy routine.
Version: MoreFiles
Copyright: <09> 1992-2001 by Apple Computer, Inc., all rights reserved.
You may incorporate this sample code into your applications without
restriction, though the sample code has been provided "AS IS" and the
responsibility for its operation is 100% yours. However, what you are
not permitted to do is to redistribute the source as "DSC Sample Code"
after having made changes. If you're going to re-distribute the source,
we require that you make it clear in the source that the code was
descended from Apple Sample Code, but that you've made changes.
File Ownership:
DRI: Apple Macintosh Developer Technical Support
Other Contact: Apple Macintosh Developer Technical Support
<http://developer.apple.com/bugreporter/>
Technology: DTS Sample Code
Writers:
(JL) Jim Luther
Change History (most recent first):
<2> 2/7/01 JL Added standard header. Updated names of includes. Updated
various routines to use new calling convention of the
MoreFilesExtras accessor functions.
<1> 12/06/99 JL MoreFiles 1.5.
*/
#include <MacTypes.h>
#include <MacErrors.h>
#include <MacMemory.h>
#include <Files.h>
#include <Math64.h>
#define __COMPILINGMOREFILES
#include "MoreFiles.h"
#include "MoreFilesExtras.h"
#include "MoreDesktopMgr.h"
#include "FileCopy.h"
/*****************************************************************************/
/* local constants */
/* The deny-mode privileges to use when opening the source and destination files. */
enum
{
srcCopyMode = dmRdDenyWr,
dstCopyMode = dmWrDenyRdWr
};
/* The largest (16K) and smallest (.5K) copy buffer to use if the caller doesn't supply
** their own copy buffer. */
enum
{
bigCopyBuffSize = 0x00004000,
minCopyBuffSize = 0x00000200
};
/*****************************************************************************/
/* static prototypes */
static OSErr GetDestinationDirInfo(short vRefNum,
long dirID,
ConstStr255Param name,
long *theDirID,
Boolean *isDirectory,
Boolean *isDropBox);
/* GetDestinationDirInfo tells us if the destination is a directory, it's
directory ID, and if it's an AppleShare drop box (write privileges only --
no read or search privileges).
vRefNum input: Volume specification.
dirID input: Directory ID.
name input: Pointer to object name, or nil when dirID
specifies a directory that's the object.
theDirID output: If the object is a file, then its parent directory
ID. If the object is a directory, then its ID.
isDirectory output: True if object is a directory; false if
object is a file.
isDropBox output: True if directory is an AppleShare drop box.
*/
static OSErr CheckForForks(short vRefNum,
long dirID,
ConstStr255Param name,
Boolean *hasDataFork,
Boolean *hasResourceFork);
/* CheckForForks tells us if there is a data or resource fork to copy.
vRefNum input: Volume specification of the file's current
location.
dirID input: Directory ID of the file's current location.
name input: The name of the file.
*/
static OSErr PreflightFileCopySpace(short srcVRefNum,
long srcDirID,
ConstStr255Param srcName,
ConstStr255Param dstVolName,
short dstVRefNum,
Boolean *spaceOK);
/* PreflightFileCopySpace determines if there's enough space on a
volume to copy the specified file to that volume.
Note: The results of this routine are not perfect. For example if the
volume's catalog or extents overflow file grows when the new file is
created, more allocation blocks may be needed beyond those needed for
the file's data and resource forks.
srcVRefNum input: Volume specification of the file's current
location.
srcDirID input: Directory ID of the file's current location.
srcName input: The name of the file.
dstVolName input: A pointer to the name of the volume where
the file will be copied or NULL.
dstVRefNum input: Volume specification indicating the volume
where the file will be copied.
spaceOK output: true if there's enough space on the volume for
the file's data and resource forks.
*/
/*****************************************************************************/
static OSErr GetDestinationDirInfo(short vRefNum,
long dirID,
ConstStr255Param name,
long *theDirID,
Boolean *isDirectory,
Boolean *isDropBox)
{
CInfoPBRec pb;
OSErr error;
pb.dirInfo.ioACUser = 0; /* ioACUser used to be filler2, clear it before calling GetCatInfo */
error = GetCatInfoNoName(vRefNum, dirID, name, &pb);
*theDirID = pb.dirInfo.ioDrDirID;
*isDirectory = (pb.dirInfo.ioFlAttrib & kioFlAttribDirMask) != 0;
/* see if access priviledges are make changes, not see folder, and not see files (drop box) */
*isDropBox = userHasDropBoxAccess(pb.dirInfo.ioACUser);
return ( error );
}
/*****************************************************************************/
static OSErr CheckForForks(short vRefNum,
long dirID,
ConstStr255Param name,
Boolean *hasDataFork,
Boolean *hasResourceFork)
{
HParamBlockRec pb;
OSErr error;
pb.fileParam.ioNamePtr = (StringPtr)name;
pb.fileParam.ioVRefNum = vRefNum;
pb.fileParam.ioFVersNum = 0;
pb.fileParam.ioDirID = dirID;
pb.fileParam.ioFDirIndex = 0;
error = PBHGetFInfoSync(&pb);
*hasDataFork = (pb.fileParam.ioFlLgLen != 0);
*hasResourceFork = (pb.fileParam.ioFlRLgLen != 0);
return ( error );
}
/*****************************************************************************/
static OSErr PreflightFileCopySpace(short srcVRefNum,
long srcDirID,
ConstStr255Param srcName,
ConstStr255Param dstVolName,
short dstVRefNum,
Boolean *spaceOK)
{
UniversalFMPB pb;
OSErr error;
unsigned long dstFreeBlocks;
unsigned long dstBlksPerAllocBlk;
unsigned long srcDataBlks;
unsigned long srcResourceBlks;
error = XGetVolumeInfoNoName(dstVolName, dstVRefNum, &pb.xPB);
if ( error == noErr )
{
/* get allocation block size (always multiple of 512) and divide by 512
to get number of 512-byte blocks per allocation block */
dstBlksPerAllocBlk = ((unsigned long)pb.xPB.ioVAlBlkSiz >> 9);
/* Convert freeBytes to free disk blocks (512-byte blocks) */
dstFreeBlocks = U32SetU(U64ShiftRight(pb.xPB.ioVFreeBytes, 9));
/* Now, get the size of the file's data resource forks */
pb.hPB.fileParam.ioNamePtr = (StringPtr)srcName;
pb.hPB.fileParam.ioVRefNum = srcVRefNum;
pb.hPB.fileParam.ioFVersNum = 0;
pb.hPB.fileParam.ioDirID = srcDirID;
pb.hPB.fileParam.ioFDirIndex = 0;
error = PBHGetFInfoSync(&pb.hPB);
if ( error == noErr )
{
/* Since space on Mac OS disks is always allocated in allocation blocks, */
/* this code takes into account rounding up to the end of an allocation block. */
/* get number of 512-byte blocks needed for data fork */
if ( ((unsigned long)pb.hPB.fileParam.ioFlLgLen & 0x000001ff) != 0 )
{
srcDataBlks = ((unsigned long)pb.hPB.fileParam.ioFlLgLen >> 9) + 1;
}
else
{
srcDataBlks = (unsigned long)pb.hPB.fileParam.ioFlLgLen >> 9;
}
/* now, calculate number of new allocation blocks needed */
if ( srcDataBlks % dstBlksPerAllocBlk )
{
srcDataBlks = (srcDataBlks / dstBlksPerAllocBlk) + 1;
}
else
{
srcDataBlks /= dstBlksPerAllocBlk;
}
/* get number of 512-byte blocks needed for resource fork */
if ( ((unsigned long)pb.hPB.fileParam.ioFlRLgLen & 0x000001ff) != 0 )
{
srcResourceBlks = ((unsigned long)pb.hPB.fileParam.ioFlRLgLen >> 9) + 1;
}
else
{
srcResourceBlks = (unsigned long)pb.hPB.fileParam.ioFlRLgLen >> 9;
}
/* now, calculate number of new allocation blocks needed */
if ( srcResourceBlks % dstBlksPerAllocBlk )
{
srcResourceBlks = (srcResourceBlks / dstBlksPerAllocBlk) + 1;
}
else
{
srcResourceBlks /= dstBlksPerAllocBlk;
}
/* Is there enough room on the destination volume for the source file? */
*spaceOK = ( ((srcDataBlks + srcResourceBlks) * dstBlksPerAllocBlk) <= dstFreeBlocks );
}
}
return ( error );
}
/*****************************************************************************/
pascal OSErr FileCopy(short srcVRefNum,
long srcDirID,
ConstStr255Param srcName,
short dstVRefNum,
long dstDirID,
ConstStr255Param dstPathname,
ConstStr255Param copyName,
void *copyBufferPtr,
long copyBufferSize,
Boolean preflight)
{
OSErr err;
short srcRefNum = 0, /* 0 when source data and resource fork are closed */
dstDataRefNum = 0, /* 0 when destination data fork is closed */
dstRsrcRefNum = 0; /* 0 when destination resource fork is closed */
Str63 dstName; /* The filename of the destination. It might be the
** source filename, it might be a new name... */
GetVolParmsInfoBuffer infoBuffer; /* Where PBGetVolParms dumps its info */
long srcServerAdr; /* AppleTalk server address of source (if any) */
Boolean dstCreated = false, /* true when destination file has been created */
ourCopyBuffer = false, /* true if we had to allocate the copy buffer */
isDirectory, /* true if destination is really a directory */
isDropBox; /* true if destination is an AppleShare drop box */
long tempLong;
short tempInt;
Boolean spaceOK; /* true if there's enough room to copy the file to the destination volume */
Boolean hasDataFork;
Boolean hasResourceFork;
/* Preflight for size */
if ( preflight )
{
err = PreflightFileCopySpace(srcVRefNum, srcDirID, srcName,
dstPathname, dstVRefNum, &spaceOK);
if ( err != noErr )
{
return ( err );
}
if ( !spaceOK )
{
return ( dskFulErr );
}
}
/* get the destination's real dirID and make sure it really is a directory */
err = GetDestinationDirInfo(dstVRefNum, dstDirID, dstPathname,
&dstDirID, &isDirectory, &isDropBox);
if ( err != noErr )
{
goto ErrorExit;
}
if ( !isDirectory )
{
return ( dirNFErr );
}
/* get the destination's real vRefNum */
err = DetermineVRefNum(dstPathname, dstVRefNum, &dstVRefNum);
if ( err != noErr )
{
goto ErrorExit;
}
/* See if PBHCopyFile can be used. Using PBHCopyFile saves time by letting the file server
** copy the file if the source and destination locations are on the same file server. */
tempLong = sizeof(infoBuffer);
err = HGetVolParms(srcName, srcVRefNum, &infoBuffer, &tempLong);
if ( (err != noErr) && (err != paramErr) )
{
return ( err );
}
if ( (err != paramErr) && hasCopyFile(&infoBuffer) )
{
/* The source volume supports PBHCopyFile. */
srcServerAdr = infoBuffer.vMServerAdr;
/* Now, see if the destination volume is on the same file server. */
tempLong = sizeof(infoBuffer);
err = HGetVolParms(NULL, dstVRefNum, &infoBuffer, &tempLong);
if ( (err != noErr) && (err != paramErr) )
{
return ( err );
}
if ( (err != paramErr) && (srcServerAdr == infoBuffer.vMServerAdr) )
{
/* Source and Dest are on same server and PBHCopyFile is supported. Copy with CopyFile. */
err = HCopyFile(srcVRefNum, srcDirID, srcName, dstVRefNum, dstDirID, NULL, copyName);
if ( err != noErr )
{
return ( err );
}
/* AppleShare's CopyFile clears the isAlias bit, so I still need to attempt to copy
the File's attributes to attempt to get things right. */
if ( copyName != NULL ) /* Did caller supply copy file name? */
{
/* Yes, use the caller supplied copy file name. */
(void) CopyFileMgrAttributes(srcVRefNum, srcDirID, srcName,
dstVRefNum, dstDirID, copyName, true);
}
else
{
/* They didn't, so get the source file name and use it. */
if ( GetFilenameFromPathname(srcName, dstName) == noErr )
{
/* */
(void) CopyFileMgrAttributes(srcVRefNum, srcDirID, srcName,
dstVRefNum, dstDirID, dstName, true);
}
}
return ( err );
}
}
/* If we're here, then PBHCopyFile couldn't be used so we have to copy the file by hand. */
/* Make sure a copy buffer is allocated. */
if ( copyBufferPtr == NULL )
{
/* The caller didn't supply a copy buffer so grab one from the application heap.
** Try to get a big copy buffer, if we can't, try for a 512-byte buffer.
** If 512 bytes aren't available, we're in trouble. */
copyBufferSize = bigCopyBuffSize;
copyBufferPtr = NewPtr(copyBufferSize);
if ( copyBufferPtr == NULL )
{
copyBufferSize = minCopyBuffSize;
copyBufferPtr = NewPtr(copyBufferSize);
if ( copyBufferPtr == NULL )
{
return ( memFullErr );
}
}
ourCopyBuffer = true;
}
/* Open the source data fork. */
err = HOpenAware(srcVRefNum, srcDirID, srcName, srcCopyMode, &srcRefNum);
if ( err != noErr )
return ( err );
/* Once a file is opened, we have to exit via ErrorExit to make sure things are cleaned up */
/* See if the copy will be renamed. */
if ( copyName != NULL ) /* Did caller supply copy file name? */
BlockMoveData(copyName, dstName, copyName[0] + 1); /* Yes, use the caller supplied copy file name. */
else
{ /* They didn't, so get the source file name and use it. */
err = GetFileLocation(srcRefNum, &tempInt, &tempLong, dstName);
if ( err != noErr )
{
goto ErrorExit;
}
}
/* Create the destination file. */
err = HCreateMinimum(dstVRefNum, dstDirID, dstName);
if ( err != noErr )
{
goto ErrorExit;
}
dstCreated = true; /* After creating the destination file, any
** error conditions should delete the destination file */
/* An AppleShare dropbox folder is a folder for which the user has the Make Changes
** privilege (write access), but not See Files (read access) and See Folders (search access).
** Copying a file into an AppleShare dropbox presents some special problems. Here are the
** rules we have to follow to copy a file into a dropbox:
** <20> File attributes can be changed only when both forks of a file are empty.
** <20> DeskTop Manager comments can be added to a file only when both forks of a file
** are empty.
** <20> A fork can be opened for write access only when both forks of a file are empty.
** So, with those rules to live with, we'll do those operations now while both forks
** are empty. */
if ( isDropBox )
{
/* We only set the file attributes now if the file is being copied into a
** drop box. In all other cases, it is better to set the attributes last
** so that if FileCopy is modified to give up time to other processes
** periodicly, the Finder won't try to read any bundle information (because
** the bundle-bit will still be clear) from a partially copied file. If the
** copy is into a drop box, we have to set the attributes now, but since the
** destination forks are opened with write/deny-read/deny-write permissions,
** any Finder that might see the file in the drop box won't be able to open
** its resource fork until the resource fork is closed.
**
** Note: if you do modify FileCopy to give up time to other processes, don't
** give up time between the time the destination file is created (above) and
** the time both forks are opened (below). That way, you stand the best chance
** of making sure the Finder doesn't read a partially copied resource fork.
*/
/* Copy attributes but don't lock the destination. */
err = CopyFileMgrAttributes(srcVRefNum, srcDirID, srcName,
dstVRefNum, dstDirID, dstName, false);
if ( err != noErr )
{
goto ErrorExit;
}
}
/* Attempt to copy the comments while both forks are empty.
** Ignore the result because we really don't care if it worked or not. */
(void) DTCopyComment(srcVRefNum, srcDirID, srcName, dstVRefNum, dstDirID, dstName);
/* See which forks we need to copy. By doing this, we won't create a data or resource fork
** for the destination unless it's really needed (some foreign file systems such as
** the ProDOS File System and Macintosh PC Exchange have to create additional disk
** structures to support resource forks). */
err = CheckForForks(srcVRefNum, srcDirID, srcName, &hasDataFork, &hasResourceFork);
if ( err != noErr )
{
goto ErrorExit;
}
if ( hasDataFork )
{
/* Open the destination data fork. */
err = HOpenAware(dstVRefNum, dstDirID, dstName, dstCopyMode, &dstDataRefNum);
if ( err != noErr )
{
goto ErrorExit;
}
}
if ( hasResourceFork )
{
/* Open the destination resource fork. */
err = HOpenRFAware(dstVRefNum, dstDirID, dstName, dstCopyMode, &dstRsrcRefNum);
if ( err != noErr )
{
goto ErrorExit;
}
}
if ( hasDataFork )
{
/* Copy the data fork. */
err = CopyFork(srcRefNum, dstDataRefNum, copyBufferPtr, copyBufferSize);
if ( err != noErr )
{
goto ErrorExit;
}
/* Close both data forks and clear reference numbers. */
(void) FSClose(srcRefNum);
(void) FSClose(dstDataRefNum);
srcRefNum = dstDataRefNum = 0;
}
else
{
/* Close the source data fork since it was opened earlier */
(void) FSClose(srcRefNum);
srcRefNum = 0;
}
if ( hasResourceFork )
{
/* Open the source resource fork. */
err = HOpenRFAware(srcVRefNum, srcDirID, srcName, srcCopyMode, &srcRefNum);
if ( err != noErr )
{
goto ErrorExit;
}
/* Copy the resource fork. */
err = CopyFork(srcRefNum, dstRsrcRefNum, copyBufferPtr, copyBufferSize);
if ( err != noErr )
{
goto ErrorExit;
}
/* Close both resource forks and clear reference numbers. */
(void) FSClose(srcRefNum);
(void) FSClose(dstRsrcRefNum);
srcRefNum = dstRsrcRefNum = 0;
}
/* Get rid of the copy buffer if we allocated it. */
if ( ourCopyBuffer )
{
DisposePtr((Ptr)copyBufferPtr);
}
/* Attempt to copy attributes again to set mod date. Copy lock condition this time
** since we're done with the copy operation. This operation will fail if we're copying
** into an AppleShare dropbox, so we don't check for error conditions. */
CopyFileMgrAttributes(srcVRefNum, srcDirID, srcName,
dstVRefNum, dstDirID, dstName, true);
/* Hey, we did it! */
return ( noErr );
ErrorExit:
if ( srcRefNum != 0 )
{
(void) FSClose(srcRefNum); /* Close the source file */
}
if ( dstDataRefNum != 0 )
{
(void) FSClose(dstDataRefNum); /* Close the destination file data fork */
}
if ( dstRsrcRefNum != 0 )
{
(void) FSClose(dstRsrcRefNum); /* Close the destination file resource fork */
}
if ( dstCreated )
{
(void) HDelete(dstVRefNum, dstDirID, dstName); /* Delete dest file. This may fail if the file
is in a "drop folder" */
}
if ( ourCopyBuffer ) /* dispose of any memory we allocated */
{
DisposePtr((Ptr)copyBufferPtr);
}
return ( err );
}
/*****************************************************************************/
pascal OSErr FSpFileCopy(const FSSpec *srcSpec,
const FSSpec *dstSpec,
ConstStr255Param copyName,
void *copyBufferPtr,
long copyBufferSize,
Boolean preflight)
{
return ( FileCopy(srcSpec->vRefNum, srcSpec->parID, srcSpec->name,
dstSpec->vRefNum, dstSpec->parID, dstSpec->name,
copyName, copyBufferPtr, copyBufferSize, preflight) );
}
/*****************************************************************************/

View File

@@ -0,0 +1,271 @@
/*
File: FileCopy.h
Contains: A robust, general purpose file copy routine.
Version: Technology: MoreFiles
Release: 1.5.2
Copyright: <20> 1992-2001 by Apple Computer, Inc., all rights reserved.
Bugs?: For bug reports, consult the following page on
the World Wide Web:
http://developer.apple.com/bugreporter/
*/
/*
You may incorporate this sample code into your applications without
restriction, though the sample code has been provided "AS IS" and the
responsibility for its operation is 100% yours. However, what you are
not permitted to do is to redistribute the source as "DSC Sample Code"
after having made changes. If you're going to re-distribute the source,
we require that you make it clear in the source that the code was
descended from Apple Sample Code, but that you've made changes.
*/
#ifndef __FILECOPY__
#define __FILECOPY__
#ifndef __MACTYPES__
#include <MacTypes.h>
#endif
#ifndef __FILES__
#include <Files.h>
#endif
#include "Optimization.h"
#if PRAGMA_ONCE
#pragma once
#endif
#ifdef __cplusplus
extern "C" {
#endif
#if PRAGMA_IMPORT
#pragma import on
#endif
#if PRAGMA_STRUCT_ALIGN
#pragma options align=mac68k
#elif PRAGMA_STRUCT_PACKPUSH
#pragma pack(push, 2)
#elif PRAGMA_STRUCT_PACK
#pragma pack(2)
#endif
/*****************************************************************************/
EXTERN_API( OSErr )
FileCopy(
short srcVRefNum,
long srcDirID,
ConstStr255Param srcName,
short dstVRefNum,
long dstDirID,
ConstStr255Param dstPathname,
ConstStr255Param copyName,
void * copyBufferPtr,
long copyBufferSize,
Boolean preflight);
/*
The FileCopy function duplicates a file and optionally renames it.
Since the PBHCopyFile routine is only available on some
AFP server volumes under specific conditions, this routine
either uses PBHCopyFile, or does all of the work PBHCopyFile
does. The srcVRefNum, srcDirID and srcName are used to
determine the location of the file to copy. The dstVRefNum
dstDirID and dstPathname are used to determine the location of
the destination directory. If copyName <> NIL, then it points
to the name of the new file. If copyBufferPtr <> NIL, it
points to a buffer of copyBufferSize that is used to copy
the file's data. The larger the supplied buffer, the
faster the copy. If copyBufferPtr = NIL, then this routine
allocates a buffer in the application heap. If you pass a
copy buffer to this routine, make its size a multiple of 512
($200) bytes for optimum performance.
srcVRefNum input: Source volume specification.
srcDirID input: Source directory ID.
srcName input: Source file name.
dstVRefNum input: Destination volume specification.
dstDirID input: Destination directory ID.
dstPathname input: Pointer to destination directory name, or
nil when dstDirID specifies a directory.
copyName input: Points to the new file name if the file is
to be renamed or nil if the file isn't to
be renamed.
copyBufferPtr input: Points to a buffer of copyBufferSize that
is used the i/o buffer for the copy or
nil if you want FileCopy to allocate its
own buffer in the application heap.
copyBufferSize input: The size of the buffer pointed to
by copyBufferPtr.
preflight input: If true, FileCopy makes sure there are enough
allocation blocks on the destination volume to
hold both the data and resource forks before
starting the copy.
Result Codes
noErr 0 No error
readErr <20>19 Driver does not respond to read requests
writErr <20>20 Driver does not respond to write requests
badUnitErr <20>21 Driver reference number does not
match unit table
unitEmptyErr <20>22 Driver reference number specifies a
nil handle in unit table
abortErr <20>27 Request aborted by KillIO
notOpenErr <20>28 Driver not open
dskFulErr -34 Destination volume is full
nsvErr -35 No such volume
ioErr -36 I/O error
bdNamErr -37 Bad filename
tmfoErr -42 Too many files open
fnfErr -43 Source file not found, or destination
directory does not exist
wPrErr -44 Volume locked by hardware
fLckdErr -45 File is locked
vLckdErr -46 Destination volume is read-only
fBsyErr -47 The source or destination file could
not be opened with the correct access
modes
dupFNErr -48 Destination file already exists
opWrErr -49 File already open for writing
paramErr -50 No default volume or function not
supported by volume
permErr -54 File is already open and cannot be opened using specified deny modes
memFullErr -108 Copy buffer could not be allocated
dirNFErr -120 Directory not found or incomplete pathname
wrgVolTypErr -123 Function not supported by volume
afpAccessDenied -5000 User does not have the correct access
afpDenyConflict -5006 The source or destination file could
not be opened with the correct access
modes
afpObjectTypeErr -5025 Source is a directory, directory not found
or incomplete pathname
__________
Also see: FSpFileCopy, DirectoryCopy, FSpDirectoryCopy
*/
/*****************************************************************************/
EXTERN_API( OSErr )
FSpFileCopy(
const FSSpec * srcSpec,
const FSSpec * dstSpec,
ConstStr255Param copyName,
void * copyBufferPtr,
long copyBufferSize,
Boolean preflight);
/*
The FSpFileCopy function duplicates a file and optionally renames it.
Since the PBHCopyFile routine is only available on some
AFP server volumes under specific conditions, this routine
either uses PBHCopyFile, or does all of the work PBHCopyFile
does. The srcSpec is used to
determine the location of the file to copy. The dstSpec is
used to determine the location of the
destination directory. If copyName <> NIL, then it points
to the name of the new file. If copyBufferPtr <> NIL, it
points to a buffer of copyBufferSize that is used to copy
the file's data. The larger the supplied buffer, the
faster the copy. If copyBufferPtr = NIL, then this routine
allocates a buffer in the application heap. If you pass a
copy buffer to this routine, make its size a multiple of 512
($200) bytes for optimum performance.
srcSpec input: An FSSpec record specifying the source file.
dstSpec input: An FSSpec record specifying the destination
directory.
copyName input: Points to the new file name if the file is
to be renamed or nil if the file isn't to
be renamed.
copyBufferPtr input: Points to a buffer of copyBufferSize that
is used the i/o buffer for the copy or
nil if you want FileCopy to allocate its
own buffer in the application heap.
copyBufferSize input: The size of the buffer pointed to
by copyBufferPtr.
preflight input: If true, FSpFileCopy makes sure there are
enough allocation blocks on the destination
volume to hold both the data and resource forks
before starting the copy.
Result Codes
noErr 0 No error
readErr <20>19 Driver does not respond to read requests
writErr <20>20 Driver does not respond to write requests
badUnitErr <20>21 Driver reference number does not
match unit table
unitEmptyErr <20>22 Driver reference number specifies a
nil handle in unit table
abortErr <20>27 Request aborted by KillIO
notOpenErr <20>28 Driver not open
dskFulErr -34 Destination volume is full
nsvErr -35 No such volume
ioErr -36 I/O error
bdNamErr -37 Bad filename
tmfoErr -42 Too many files open
fnfErr -43 Source file not found, or destination
directory does not exist
wPrErr -44 Volume locked by hardware
fLckdErr -45 File is locked
vLckdErr -46 Destination volume is read-only
fBsyErr -47 The source or destination file could
not be opened with the correct access
modes
dupFNErr -48 Destination file already exists
opWrErr -49 File already open for writing
paramErr -50 No default volume or function not
supported by volume
permErr -54 File is already open and cannot be opened using specified deny modes
memFullErr -108 Copy buffer could not be allocated
dirNFErr -120 Directory not found or incomplete pathname
wrgVolTypErr -123 Function not supported by volume
afpAccessDenied -5000 User does not have the correct access
afpDenyConflict -5006 The source or destination file could
not be opened with the correct access
modes
afpObjectTypeErr -5025 Source is a directory, directory not found
or incomplete pathname
__________
Also see: FileCopy, DirectoryCopy, FSpDirectoryCopy
*/
/*****************************************************************************/
#include "OptimizationEnd.h"
#if PRAGMA_STRUCT_ALIGN
#pragma options align=reset
#elif PRAGMA_STRUCT_PACKPUSH
#pragma pack(pop)
#elif PRAGMA_STRUCT_PACK
#pragma pack()
#endif
#ifdef PRAGMA_IMPORT_OFF
#pragma import off
#elif PRAGMA_IMPORT
#pragma import reset
#endif
#ifdef __cplusplus
}
#endif
#endif /* __FILECOPY__ */

View File

@@ -0,0 +1,282 @@
/*
File: FullPath.c
Contains: Routines for dealing with full pathnames... if you really must.
Version: MoreFiles
Copyright: <09> 1995-2001 by Apple Computer, Inc., all rights reserved.
You may incorporate this sample code into your applications without
restriction, though the sample code has been provided "AS IS" and the
responsibility for its operation is 100% yours. However, what you are
not permitted to do is to redistribute the source as "DSC Sample Code"
after having made changes. If you're going to re-distribute the source,
we require that you make it clear in the source that the code was
descended from Apple Sample Code, but that you've made changes.
File Ownership:
DRI: Apple Macintosh Developer Technical Support
Other Contact: Apple Macintosh Developer Technical Support
<http://developer.apple.com/bugreporter/>
Technology: DTS Sample Code
Writers:
(JL) Jim Luther
Change History (most recent first):
<2> 2/7/01 JL Added standard header. Updated names of includes.
<1> 12/06/99 JL MoreFiles 1.5.
*/
#include <MacTypes.h>
#include <MacErrors.h>
#include <MacMemory.h>
#include <Files.h>
#include <TextUtils.h>
#include <Aliases.h>
#define __COMPILINGMOREFILES
#include "FSpCompat.h"
#include "FullPath.h"
/*
IMPORTANT NOTE:
The use of full pathnames is strongly discouraged. Full pathnames are
particularly unreliable as a means of identifying files, directories
or volumes within your application, for two primary reasons:
<09> The user can change the name of any element in the path at virtually
any time.
<09> Volume names on the Macintosh are *not* unique. Multiple
mounted volumes can have the same name. For this reason, the use of
a full pathname to identify a specific volume may not produce the
results you expect. If more than one volume has the same name and
a full pathname is used, the File Manager currently uses the first
mounted volume it finds with a matching name in the volume queue.
In general, you should use a file<6C>s name, parent directory ID, and
volume reference number to identify a file you want to open, delete,
or otherwise manipulate.
If you need to remember the location of a particular file across
subsequent system boots, use the Alias Manager to create an alias record
describing the file. If the Alias Manager is not available, you can save
the file<6C>s name, its parent directory ID, and the name of the volume on
which it<69>s located. Although none of these methods is foolproof, they are
much more reliable than using full pathnames to identify files.
Nonetheless, it is sometimes useful to display a file<6C>s full pathname to
the user. For example, a backup utility might display a list of full
pathnames of files as it copies them onto the backup medium. Or, a
utility might want to display a dialog box showing the full pathname of
a file when it needs the user<65>s confirmation to delete the file. No
matter how unreliable full pathnames may be from a file-specification
viewpoint, users understand them more readily than volume reference
numbers or directory IDs. (Hint: Use the TruncString function from
TextUtils.h with truncMiddle as the truncWhere argument to shorten
full pathnames to a displayable length.)
The following technique for constructing the full pathname of a file is
intended for display purposes only. Applications that depend on any
particular structure of a full pathname are likely to fail on alternate
foreign file systems or under future system software versions.
*/
/*****************************************************************************/
pascal OSErr GetFullPath(short vRefNum,
long dirID,
ConstStr255Param name,
short *fullPathLength,
Handle *fullPath)
{
OSErr result;
FSSpec spec;
*fullPathLength = 0;
*fullPath = NULL;
result = FSMakeFSSpecCompat(vRefNum, dirID, name, &spec);
if ( (result == noErr) || (result == fnfErr) )
{
result = FSpGetFullPath(&spec, fullPathLength, fullPath);
}
return ( result );
}
/*****************************************************************************/
pascal OSErr FSpGetFullPath(const FSSpec *spec,
short *fullPathLength,
Handle *fullPath)
{
OSErr result;
OSErr realResult;
FSSpec tempSpec;
CInfoPBRec pb;
*fullPathLength = 0;
*fullPath = NULL;
/* Default to noErr */
realResult = result = noErr;
/* work around Nav Services "bug" (it returns invalid FSSpecs with empty names) */
if ( spec->name[0] == 0 )
{
result = FSMakeFSSpecCompat(spec->vRefNum, spec->parID, spec->name, &tempSpec);
}
else
{
/* Make a copy of the input FSSpec that can be modified */
BlockMoveData(spec, &tempSpec, sizeof(FSSpec));
}
if ( result == noErr )
{
if ( tempSpec.parID == fsRtParID )
{
/* The object is a volume */
/* Add a colon to make it a full pathname */
++tempSpec.name[0];
tempSpec.name[tempSpec.name[0]] = ':';
/* We're done */
result = PtrToHand(&tempSpec.name[1], fullPath, tempSpec.name[0]);
}
else
{
/* The object isn't a volume */
/* Is the object a file or a directory? */
pb.dirInfo.ioNamePtr = tempSpec.name;
pb.dirInfo.ioVRefNum = tempSpec.vRefNum;
pb.dirInfo.ioDrDirID = tempSpec.parID;
pb.dirInfo.ioFDirIndex = 0;
result = PBGetCatInfoSync(&pb);
// Allow file/directory name at end of path to not exist.
realResult = result;
if ( (result == noErr) || (result == fnfErr) )
{
/* if the object is a directory, append a colon so full pathname ends with colon */
if ( (result == noErr) && (pb.hFileInfo.ioFlAttrib & kioFlAttribDirMask) != 0 )
{
++tempSpec.name[0];
tempSpec.name[tempSpec.name[0]] = ':';
}
/* Put the object name in first */
result = PtrToHand(&tempSpec.name[1], fullPath, tempSpec.name[0]);
if ( result == noErr )
{
/* Get the ancestor directory names */
pb.dirInfo.ioNamePtr = tempSpec.name;
pb.dirInfo.ioVRefNum = tempSpec.vRefNum;
pb.dirInfo.ioDrParID = tempSpec.parID;
do /* loop until we have an error or find the root directory */
{
pb.dirInfo.ioFDirIndex = -1;
pb.dirInfo.ioDrDirID = pb.dirInfo.ioDrParID;
result = PBGetCatInfoSync(&pb);
if ( result == noErr )
{
/* Append colon to directory name */
++tempSpec.name[0];
tempSpec.name[tempSpec.name[0]] = ':';
/* Add directory name to beginning of fullPath */
(void) Munger(*fullPath, 0, NULL, 0, &tempSpec.name[1], tempSpec.name[0]);
result = MemError();
}
} while ( (result == noErr) && (pb.dirInfo.ioDrDirID != fsRtDirID) );
}
}
}
}
if ( result == noErr )
{
/* Return the length */
*fullPathLength = GetHandleSize(*fullPath);
result = realResult; // return realResult in case it was fnfErr
}
else
{
/* Dispose of the handle and return NULL and zero length */
if ( *fullPath != NULL )
{
DisposeHandle(*fullPath);
}
*fullPath = NULL;
*fullPathLength = 0;
}
return ( result );
}
/*****************************************************************************/
pascal OSErr FSpLocationFromFullPath(short fullPathLength,
const void *fullPath,
FSSpec *spec)
{
AliasHandle alias;
OSErr result;
Boolean wasChanged;
Str32 nullString;
/* Create a minimal alias from the full pathname */
nullString[0] = 0; /* null string to indicate no zone or server name */
result = NewAliasMinimalFromFullPath(fullPathLength, fullPath, nullString, nullString, &alias);
if ( result == noErr )
{
/* Let the Alias Manager resolve the alias. */
result = ResolveAlias(NULL, alias, spec, &wasChanged);
/* work around Alias Mgr sloppy volume matching bug */
if ( spec->vRefNum == 0 )
{
/* invalidate wrong FSSpec */
spec->parID = 0;
spec->name[0] = 0;
result = nsvErr;
}
DisposeHandle((Handle)alias); /* Free up memory used */
}
return ( result );
}
/*****************************************************************************/
pascal OSErr LocationFromFullPath(short fullPathLength,
const void *fullPath,
short *vRefNum,
long *parID,
Str31 name)
{
OSErr result;
FSSpec spec;
result = FSpLocationFromFullPath(fullPathLength, fullPath, &spec);
if ( result == noErr )
{
*vRefNum = spec.vRefNum;
*parID = spec.parID;
BlockMoveData(&spec.name[0], &name[0], spec.name[0] + 1);
}
return ( result );
}
/*****************************************************************************/

View File

@@ -0,0 +1,311 @@
/*
File: FullPath.h
Contains: Routines for dealing with full pathnames... if you really must.
Version: Technology: MoreFiles
Release: 1.5.2
Copyright: <20> 1995-2001 by Apple Computer, Inc., all rights reserved.
Bugs?: For bug reports, consult the following page on
the World Wide Web:
http://developer.apple.com/bugreporter/
*/
/*
You may incorporate this sample code into your applications without
restriction, though the sample code has been provided "AS IS" and the
responsibility for its operation is 100% yours. However, what you are
not permitted to do is to redistribute the source as "DSC Sample Code"
after having made changes. If you're going to re-distribute the source,
we require that you make it clear in the source that the code was
descended from Apple Sample Code, but that you've made changes.
*/
/*
IMPORTANT NOTE:
The use of full pathnames is strongly discouraged. Full pathnames are
particularly unreliable as a means of identifying files, directories
or volumes within your application, for two primary reasons:
<20> The user can change the name of any element in the path at
virtually any time.
<20> Volume names on the Macintosh are *not* unique. Multiple
mounted volumes can have the same name. For this reason, the use of
a full pathname to identify a specific volume may not produce the
results you expect. If more than one volume has the same name and
a full pathname is used, the File Manager currently uses the first
mounted volume it finds with a matching name in the volume queue.
In general, you should use a file<6C>s name, parent directory ID, and
volume reference number to identify a file you want to open, delete,
or otherwise manipulate.
If you need to remember the location of a particular file across
subsequent system boots, use the Alias Manager to create an alias
record describing the file. If the Alias Manager is not available, you
can save the file<6C>s name, its parent directory ID, and the name of the
volume on which it<69>s located. Although none of these methods is
foolproof, they are much more reliable than using full pathnames to
identify files.
Nonetheless, it is sometimes useful to display a file<6C>s full pathname
to the user. For example, a backup utility might display a list of full
pathnames of files as it copies them onto the backup medium. Or, a
utility might want to display a dialog box showing the full pathname of
a file when it needs the user<65>s confirmation to delete the file. No
matter how unreliable full pathnames may be from a file-specification
viewpoint, users understand them more readily than volume reference
numbers or directory IDs. (Hint: Use the TruncString function from
TextUtils.h with truncMiddle as the truncWhere argument to shorten
full pathnames to a displayable length.)
The following technique for constructing the full pathname of a file is
intended for display purposes only. Applications that depend on any
particular structure of a full pathname are likely to fail on alternate
foreign file systems or under future system software versions.
*/
#ifndef __FULLPATH__
#define __FULLPATH__
#ifndef __MACTYPES__
#include <MacTypes.h>
#endif
#ifndef __FILES__
#include <Files.h>
#endif
#include "Optimization.h"
#if PRAGMA_ONCE
#pragma once
#endif
#ifdef __cplusplus
extern "C" {
#endif
#if PRAGMA_IMPORT
#pragma import on
#endif
#if PRAGMA_STRUCT_ALIGN
#pragma options align=mac68k
#elif PRAGMA_STRUCT_PACKPUSH
#pragma pack(push, 2)
#elif PRAGMA_STRUCT_PACK
#pragma pack(2)
#endif
/*****************************************************************************/
EXTERN_API( OSErr )
GetFullPath(
short vRefNum,
long dirID,
ConstStr255Param name,
short * fullPathLength,
Handle * fullPath);
/*
The GetFullPath function builds a full pathname to the specified
object. The full pathname is returned in the newly created handle
fullPath and the length of the full pathname is returned in
fullPathLength. Your program is responsible for disposing of the
fullPath handle.
Note that a full pathname can be made to a file/directory that does not
yet exist if all directories up to that file/directory exist. In this case,
GetFullPath will return a fnfErr.
vRefNum input: Volume specification.
dirID input: Directory ID.
name input: Pointer to object name, or nil when dirID
specifies a directory that's the object.
fullPathLength output: The number of characters in the full pathname.
If the function fails to create a full
pathname, it sets fullPathLength to 0.
fullPath output: A handle to the newly created full pathname
buffer. If the function fails to create a
full pathname, it sets fullPath to NULL.
Result Codes
noErr 0 No error
nsvErr -35 No such volume
ioErr -36 I/O error
bdNamErr -37 Bad filename
fnfErr -43 File or directory does not exist (fullPath
and fullPathLength are still valid)
paramErr -50 No default volume
memFullErr -108 Not enough memory
dirNFErr -120 Directory not found or incomplete pathname
afpAccessDenied -5000 User does not have the correct access
afpObjectTypeErr -5025 Directory not found or incomplete pathname
__________
See also: FSpGetFullPath
*/
/*****************************************************************************/
EXTERN_API( OSErr )
FSpGetFullPath(
const FSSpec * spec,
short * fullPathLength,
Handle * fullPath);
/*
The GetFullPath function builds a full pathname to the specified
object. The full pathname is returned in the newly created handle
fullPath and the length of the full pathname is returned in
fullPathLength. Your program is responsible for disposing of the
fullPath handle.
Note that a full pathname can be made to a file/directory that does not
yet exist if all directories up to that file/directory exist. In this case,
FSpGetFullPath will return a fnfErr.
IMPORTANT: The definition of a FSSpec is a volume reference number (not a
drive number, working directory number, or 0), a parent directory ID (not 0),
and the name of a file or folder (not an empty name, a full pathname, or
a partial pathname containing one or more colon (:) characters).
FSpGetFullPath assumes it is getting a FSSpec that matches the rules.
If you have an FSSpec record that wasn't created by FSMakeFSSpec (or
FSMakeFSSpecCompat from FSpCompat in MoreFiles which correctly builds
FSSpecs), you should call GetFullPath instead of FSpGetFullPath.
spec input: An FSSpec record specifying the object.
fullPathLength output: The number of characters in the full pathname.
If the function fails to create a full pathname,
it sets fullPathLength to 0.
fullPath output: A handle to the newly created full pathname
buffer. If the function fails to create a
full pathname, it sets fullPath to NULL.
Result Codes
noErr 0 No error
nsvErr -35 No such volume
ioErr -36 I/O error
bdNamErr -37 Bad filename
fnfErr -43 File or directory does not exist (fullPath
and fullPathLength are still valid)
paramErr -50 No default volume
memFullErr -108 Not enough memory
dirNFErr -120 Directory not found or incomplete pathname
afpAccessDenied -5000 User does not have the correct access
afpObjectTypeErr -5025 Directory not found or incomplete pathname
__________
See also: GetFullPath
*/
/*****************************************************************************/
EXTERN_API( OSErr )
FSpLocationFromFullPath(
short fullPathLength,
const void * fullPath,
FSSpec * spec);
/*
The FSpLocationFromFullPath function returns a FSSpec to the object
specified by full pathname. This function requires the Alias Manager.
fullPathLength input: The number of characters in the full pathname
of the target.
fullPath input: A pointer to a buffer that contains the full
pathname of the target. The full pathname
starts with the name of the volume, includes
all of the directory names in the path to the
target, and ends with the target name.
spec output: An FSSpec record specifying the object.
Result Codes
noErr 0 No error
nsvErr -35 The volume is not mounted
fnfErr -43 Target not found, but volume and parent
directory found
paramErr -50 Parameter error
usrCanceledErr -128 The user canceled the operation
__________
See also: LocationFromFullPath
*/
/*****************************************************************************/
EXTERN_API( OSErr )
LocationFromFullPath(
short fullPathLength,
const void * fullPath,
short * vRefNum,
long * parID,
Str31 name);
/*
The LocationFromFullPath function returns the volume reference number,
parent directory ID and name of the object specified by full pathname.
This function requires the Alias Manager.
fullPathLength input: The number of characters in the full pathname
of the target.
fullPath input: A pointer to a buffer that contains the full
pathname of the target. The full pathname starts
with the name of the volume, includes all of
the directory names in the path to the target,
and ends with the target name.
vRefNum output: The volume reference number.
parID output: The parent directory ID of the specified object.
name output: The name of the specified object.
Result Codes
noErr 0 No error
nsvErr -35 The volume is not mounted
fnfErr -43 Target not found, but volume and parent
directory found
paramErr -50 Parameter error
usrCanceledErr -128 The user canceled the operation
__________
See also: FSpLocationFromFullPath
*/
/*****************************************************************************/
#include "OptimizationEnd.h"
#if PRAGMA_STRUCT_ALIGN
#pragma options align=reset
#elif PRAGMA_STRUCT_PACKPUSH
#pragma pack(pop)
#elif PRAGMA_STRUCT_PACK
#pragma pack()
#endif
#ifdef PRAGMA_IMPORT_OFF
#pragma import off
#elif PRAGMA_IMPORT
#pragma import reset
#endif
#ifdef __cplusplus
}
#endif
#endif /* __FULLPATH__ */

View File

@@ -0,0 +1,207 @@
/*
File: IterateDirectory.c
Contains: File Manager directory iterator routines.
Version: MoreFiles
Copyright: <09> 1995-2001 by Jim Luther and Apple Computer, Inc., all rights reserved.
You may incorporate this sample code into your applications without
restriction, though the sample code has been provided "AS IS" and the
responsibility for its operation is 100% yours. However, what you are
not permitted to do is to redistribute the source as "DSC Sample Code"
after having made changes. If you're going to re-distribute the source,
we require that you make it clear in the source that the code was
descended from Apple Sample Code, but that you've made changes.
File Ownership:
DRI: Apple Macintosh Developer Technical Support
Other Contact: Apple Macintosh Developer Technical Support
<http://developer.apple.com/bugreporter/>
Technology: DTS Sample Code
Writers:
(JL) Jim Luther
Change History (most recent first):
<2> 2/7/01 JL Added standard header. Updated names of includes.
<1> 12/06/99 JL MoreFiles 1.5.
*/
#include <MacTypes.h>
#include <MacErrors.h>
#include <Files.h>
#define __COMPILINGMOREFILES
#include "MoreFilesExtras.h"
#include "IterateDirectory.h"
/*
** Type definitions
*/
/* The IterateGlobals structure is used to minimize the amount of
** stack space used when recursively calling IterateDirectoryLevel
** and to hold global information that might be needed at any time.
*/
#if PRAGMA_STRUCT_ALIGN
#pragma options align=mac68k
#endif
struct IterateGlobals
{
IterateFilterProcPtr iterateFilter; /* pointer to IterateFilterProc */
CInfoPBRec cPB; /* the parameter block used for PBGetCatInfo calls */
Str63 itemName; /* the name of the current item */
OSErr result; /* temporary holder of results - saves 2 bytes of stack each level */
Boolean quitFlag; /* set to true if filter wants to kill interation */
unsigned short maxLevels; /* Maximum levels to iterate through */
unsigned short currentLevel; /* The current level IterateLevel is on */
void *yourDataPtr; /* A pointer to caller data the filter may need to access */
};
#if PRAGMA_STRUCT_ALIGN
#pragma options align=reset
#endif
typedef struct IterateGlobals IterateGlobals;
typedef IterateGlobals *IterateGlobalsPtr;
/*****************************************************************************/
/* Static Prototype */
static void IterateDirectoryLevel(long dirID,
IterateGlobals *theGlobals);
/*****************************************************************************/
/*
** Functions
*/
static void IterateDirectoryLevel(long dirID,
IterateGlobals *theGlobals)
{
if ( (theGlobals->maxLevels == 0) || /* if maxLevels is zero, we aren't checking levels */
(theGlobals->currentLevel < theGlobals->maxLevels) ) /* if currentLevel < maxLevels, look at this level */
{
short index = 1;
++theGlobals->currentLevel; /* go to next level */
do
{ /* Isn't C great... What I'd give for a "WITH theGlobals DO" about now... */
/* Get next source item at the current directory level */
theGlobals->cPB.dirInfo.ioFDirIndex = index;
theGlobals->cPB.dirInfo.ioDrDirID = dirID;
theGlobals->result = PBGetCatInfoSync((CInfoPBPtr)&theGlobals->cPB);
if ( theGlobals->result == noErr )
{
/* Call the IterateFilterProc */
CallIterateFilterProc(theGlobals->iterateFilter, &theGlobals->cPB, &theGlobals->quitFlag, theGlobals->yourDataPtr);
/* Is it a directory? */
if ( (theGlobals->cPB.hFileInfo.ioFlAttrib & kioFlAttribDirMask) != 0 )
{
/* We have a directory */
if ( !theGlobals->quitFlag )
{
/* Dive again if the IterateFilterProc didn't say "quit" */
IterateDirectoryLevel(theGlobals->cPB.dirInfo.ioDrDirID, theGlobals);
}
}
}
++index; /* prepare to get next item */
} while ( (theGlobals->result == noErr) && (!theGlobals->quitFlag) ); /* time to fall back a level? */
if ( (theGlobals->result == fnfErr) || /* fnfErr is OK - it only means we hit the end of this level */
(theGlobals->result == afpAccessDenied) ) /* afpAccessDenied is OK, too - it only means we cannot see inside a directory */
{
theGlobals->result = noErr;
}
--theGlobals->currentLevel; /* return to previous level as we leave */
}
}
/*****************************************************************************/
pascal OSErr IterateDirectory(short vRefNum,
long dirID,
ConstStr255Param name,
unsigned short maxLevels,
IterateFilterProcPtr iterateFilter,
void *yourDataPtr)
{
IterateGlobals theGlobals;
OSErr result;
long theDirID;
short theVRefNum;
Boolean isDirectory;
/* Make sure there is a IterateFilter */
if ( iterateFilter != NULL )
{
/* Get the real directory ID and make sure it is a directory */
result = GetDirectoryID(vRefNum, dirID, name, &theDirID, &isDirectory);
if ( result == noErr )
{
if ( isDirectory == true )
{
/* Get the real vRefNum */
result = DetermineVRefNum(name, vRefNum, &theVRefNum);
if ( result == noErr )
{
/* Set up the globals we need to access from the recursive routine. */
theGlobals.iterateFilter = iterateFilter;
theGlobals.cPB.hFileInfo.ioNamePtr = (StringPtr)&theGlobals.itemName;
theGlobals.cPB.hFileInfo.ioVRefNum = theVRefNum;
theGlobals.itemName[0] = 0;
theGlobals.result = noErr;
theGlobals.quitFlag = false;
theGlobals.maxLevels = maxLevels;
theGlobals.currentLevel = 0; /* start at level 0 */
theGlobals.yourDataPtr = yourDataPtr;
/* Here we go into recursion land... */
IterateDirectoryLevel(theDirID, &theGlobals);
result = theGlobals.result; /* set the result */
}
}
else
{
result = dirNFErr; /* a file was passed instead of a directory */
}
}
}
else
{
result = paramErr; /* iterateFilter was NULL */
}
return ( result );
}
/*****************************************************************************/
pascal OSErr FSpIterateDirectory(const FSSpec *spec,
unsigned short maxLevels,
IterateFilterProcPtr iterateFilter,
void *yourDataPtr)
{
return ( IterateDirectory(spec->vRefNum, spec->parID, spec->name,
maxLevels, iterateFilter, yourDataPtr) );
}
/*****************************************************************************/

View File

@@ -0,0 +1,222 @@
/*
File: IterateDirectory.h
Contains: File Manager directory iterator routines.
Version: Technology: MoreFiles
Release: 1.5.2
Copyright: <20> 1995-2001 by Jim Luther and Apple Computer, Inc., all rights reserved.
Bugs?: For bug reports, consult the following page on
the World Wide Web:
http://developer.apple.com/bugreporter/
*/
/*
You may incorporate this sample code into your applications without
restriction, though the sample code has been provided "AS IS" and the
responsibility for its operation is 100% yours. However, what you are
not permitted to do is to redistribute the source as "DSC Sample Code"
after having made changes. If you're going to re-distribute the source,
we require that you make it clear in the source that the code was
descended from Apple Sample Code, but that you've made changes.
*/
#ifndef __ITERATEDIRECTORY__
#define __ITERATEDIRECTORY__
#ifndef __MACTYPES__
#include <MacTypes.h>
#endif
#ifndef __FILES__
#include <Files.h>
#endif
#include "Optimization.h"
#if PRAGMA_ONCE
#pragma once
#endif
#ifdef __cplusplus
extern "C" {
#endif
#if PRAGMA_IMPORT
#pragma import on
#endif
#if PRAGMA_STRUCT_ALIGN
#pragma options align=mac68k
#elif PRAGMA_STRUCT_PACKPUSH
#pragma pack(push, 2)
#elif PRAGMA_STRUCT_PACK
#pragma pack(2)
#endif
/*****************************************************************************/
typedef CALLBACK_API( void , IterateFilterProcPtr )(const CInfoPBRec *cpbPtr, Boolean *quitFlag, void *yourDataPtr);
/*
This is the prototype for the IterateFilterProc function which is
called once for each file and directory found by IterateDirectory. The
IterateFilterProc gets a pointer to the CInfoPBRec that IterateDirectory
used to call PBGetCatInfo. The IterateFilterProc can use the read-only
data in the CInfoPBRec for whatever it wants.
If the IterateFilterProc wants to stop IterateDirectory, it can set
quitFlag to true (quitFlag will be passed to the IterateFilterProc
false).
The yourDataPtr parameter can point to whatever data structure you might
want to access from within the IterateFilterProc.
cpbPtr input: A pointer to the CInfoPBRec that IterateDirectory
used to call PBGetCatInfo. The CInfoPBRec and the
data it points to must not be changed by your
IterateFilterProc.
quitFlag output: Your IterateFilterProc can set quitFlag to true
if it wants to stop IterateDirectory.
yourDataPtr input: A pointer to whatever data structure you might
want to access from within the IterateFilterProc.
__________
Also see: IterateDirectory, FSpIterateDirectory
*/
#define CallIterateFilterProc(userRoutine, cpbPtr, quitFlag, yourDataPtr) \
(*(userRoutine))((cpbPtr), (quitFlag), (yourDataPtr))
/*****************************************************************************/
EXTERN_API( OSErr )
IterateDirectory(
short vRefNum,
long dirID,
ConstStr255Param name,
unsigned short maxLevels,
IterateFilterProcPtr iterateFilter,
void * yourDataPtr);
/*
The IterateDirectory function performs a recursive iteration (scan) of
the specified directory and calls your IterateFilterProc function once
for each file and directory found.
The maxLevels parameter lets you control how deep the recursion goes.
If maxLevels is 1, IterateDirectory only scans the specified directory;
if maxLevels is 2, IterateDirectory scans the specified directory and
one subdirectory below the specified directory; etc. Set maxLevels to
zero to scan all levels.
The yourDataPtr parameter can point to whatever data structure you might
want to access from within the IterateFilterProc.
vRefNum input: Volume specification.
dirID input: Directory ID.
name input: Pointer to object name, or nil when dirID
specifies a directory that's the object.
maxLevels input: Maximum number of directory levels to scan or
zero to scan all directory levels.
iterateFilter input: A pointer to the routine you want called once
for each file and directory found by
IterateDirectory.
yourDataPtr input: A pointer to whatever data structure you might
want to access from within the IterateFilterProc.
Result Codes
noErr 0 No error
nsvErr -35 No such volume
ioErr -36 I/O error
bdNamErr -37 Bad filename
fnfErr -43 File not found
paramErr -50 No default volume or iterateFilter was NULL
dirNFErr -120 Directory not found or incomplete pathname
or a file was passed instead of a directory
afpAccessDenied -5000 User does not have the correct access
afpObjectTypeErr -5025 Directory not found or incomplete pathname
__________
See also: IterateFilterProcPtr, FSpIterateDirectory
*/
/*****************************************************************************/
EXTERN_API( OSErr )
FSpIterateDirectory(
const FSSpec * spec,
unsigned short maxLevels,
IterateFilterProcPtr iterateFilter,
void * yourDataPtr);
/*
The FSpIterateDirectory function performs a recursive iteration (scan)
of the specified directory and calls your IterateFilterProc function once
for each file and directory found.
The maxLevels parameter lets you control how deep the recursion goes.
If maxLevels is 1, FSpIterateDirectory only scans the specified directory;
if maxLevels is 2, FSpIterateDirectory scans the specified directory and
one subdirectory below the specified directory; etc. Set maxLevels to
zero to scan all levels.
The yourDataPtr parameter can point to whatever data structure you might
want to access from within the IterateFilterProc.
spec input: An FSSpec record specifying the directory to scan.
maxLevels input: Maximum number of directory levels to scan or
zero to scan all directory levels.
iterateFilter input: A pointer to the routine you want called once
for each file and directory found by
FSpIterateDirectory.
yourDataPtr input: A pointer to whatever data structure you might
want to access from within the IterateFilterProc.
Result Codes
noErr 0 No error
nsvErr -35 No such volume
ioErr -36 I/O error
bdNamErr -37 Bad filename
fnfErr -43 File not found
paramErr -50 No default volume or iterateFilter was NULL
dirNFErr -120 Directory not found or incomplete pathname
afpAccessDenied -5000 User does not have the correct access
afpObjectTypeErr -5025 Directory not found or incomplete pathname
__________
See also: IterateFilterProcPtr, IterateDirectory
*/
/*****************************************************************************/
#include "OptimizationEnd.h"
#if PRAGMA_STRUCT_ALIGN
#pragma options align=reset
#elif PRAGMA_STRUCT_PACKPUSH
#pragma pack(pop)
#elif PRAGMA_STRUCT_PACK
#pragma pack()
#endif
#ifdef PRAGMA_IMPORT_OFF
#pragma import off
#elif PRAGMA_IMPORT
#pragma import reset
#endif
#ifdef __cplusplus
}
#endif
#endif /* __ITERATEDIRECTORY__ */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,628 @@
/*
File: MoreDesktopMgr.h
Contains: A collection of useful high-level Desktop Manager routines. If the Desktop Manager is not available, use the Desktop file for 'read' operations.
Version: Technology: MoreFiles
Release: 1.5.2
Copyright: <20> 1992-2001 by Apple Computer, Inc., all rights reserved.
Bugs?: For bug reports, consult the following page on
the World Wide Web:
http://developer.apple.com/bugreporter/
*/
/*
You may incorporate this sample code into your applications without
restriction, though the sample code has been provided "AS IS" and the
responsibility for its operation is 100% yours. However, what you are
not permitted to do is to redistribute the source as "DSC Sample Code"
after having made changes. If you're going to re-distribute the source,
we require that you make it clear in the source that the code was
descended from Apple Sample Code, but that you've made changes.
*/
#ifndef __MOREDESKTOPMGR__
#define __MOREDESKTOPMGR__
#ifndef __MACTYPES__
#include <MacTypes.h>
#endif
#ifndef __FILES__
#include <Files.h>
#endif
#include "Optimization.h"
#if PRAGMA_ONCE
#pragma once
#endif
#ifdef __cplusplus
extern "C" {
#endif
#if PRAGMA_IMPORT
#pragma import on
#endif
#if PRAGMA_STRUCT_ALIGN
#pragma options align=mac68k
#elif PRAGMA_STRUCT_PACKPUSH
#pragma pack(push, 2)
#elif PRAGMA_STRUCT_PACK
#pragma pack(2)
#endif
/*****************************************************************************/
EXTERN_API( OSErr )
DTOpen(
ConstStr255Param volName,
short vRefNum,
short * dtRefNum,
Boolean * newDTDatabase);
/*
The DTOpen function opens a volume's desktop database. It returns
the reference number of the desktop database and indicates if the
desktop database was created as a result of this call (if it was created,
then it is empty).
volName input: A pointer to the name of a mounted volume
or nil.
vRefNum input: Volume specification.
dtRefNum output: The reference number of Desktop Manager's
desktop database on the specified volume.
newDTDatabase output: true if the desktop database was created as a
result of this call and thus empty.
false if the desktop database was already created,
or if it could not be determined if it was already
created.
Result Codes
noErr 0 No error
nsvErr -35 Volume not found
ioErr -36 I/O error
paramErr -50 Volume doesn't support this function
extFSErr -58 External file system error - no file
system claimed this call.
desktopDamagedErr -1305 The desktop database has become corrupted -
the Finder will fix this, but if your
application is not running with the
Finder, use PBDTReset or PBDTDelete
*/
/*****************************************************************************/
EXTERN_API( OSErr )
DTXGetAPPL(
ConstStr255Param volName,
short vRefNum,
OSType creator,
Boolean searchCatalog,
short * applVRefNum,
long * applParID,
Str255 applName);
/*
The DTXGetAPPL function finds an application (file type 'APPL') with
the specified creator on the specified volume. It first tries to get
the application mapping from the desktop database. If that fails,
then it tries to find an application in the Desktop file. If that
fails and searchCatalog is true, then it tries to find an application
with the specified creator using the File Manager's CatSearch routine.
volName input: A pointer to the name of a mounted volume
or nil.
vRefNum input: Volume specification.
creator input: The file's creator type.
searchCatalog input: If true, search the catalog for the application
if it isn't found in the desktop database.
applVRefNum output: The volume reference number of the volume the
application is on.
applParID output: The parent directory ID of the application.
applName output: The name of the application.
Result Codes
noErr 0 No error
nsvErr -35 Volume not found
ioErr -36 I/O error
paramErr -50 No default volume
rfNumErr -51 Reference number invalid
extFSErr -58 External file system error - no file
system claimed this call
desktopDamagedErr -1305 The desktop database has become corrupted -
the Finder will fix this, but if your
application is not running with the
Finder, use PBDTReset or PBDTDelete
afpItemNotFound -5012 Information not found
__________
Also see: FSpDTGetAPPL
*/
/*****************************************************************************/
EXTERN_API( OSErr )
FSpDTXGetAPPL(
ConstStr255Param volName,
short vRefNum,
OSType creator,
Boolean searchCatalog,
FSSpec * spec);
/*
The FSpDTXGetAPPL function finds an application (file type 'APPL') with
the specified creator on the specified volume. It first tries to get
the application mapping from the desktop database. If that fails,
then it tries to find an application in the Desktop file. If that
fails and searchCatalog is true, then it tries to find an application
with the specified creator using the File Manager's CatSearch routine.
volName input: A pointer to the name of a mounted volume
or nil.
vRefNum input: Volume specification.
creator input: The file's creator type.
searchCatalog input: If true, search the catalog for the application
if it isn't found in the desktop database.
spec output: FSSpec record containing the application name and
location.
Result Codes
noErr 0 No error
nsvErr -35 Volume not found
ioErr -36 I/O error
paramErr -50 No default volume
rfNumErr -51 Reference number invalid
extFSErr -58 External file system error - no file
system claimed this call
desktopDamagedErr -1305 The desktop database has become corrupted -
the Finder will fix this, but if your
application is not running with the
Finder, use PBDTReset or PBDTDelete
afpItemNotFound -5012 Information not found
__________
Also see: FSpDTGetAPPL
*/
/*****************************************************************************/
EXTERN_API( OSErr )
DTGetAPPL(
ConstStr255Param volName,
short vRefNum,
OSType creator,
short * applVRefNum,
long * applParID,
Str255 applName);
/*
The DTGetAPPL function finds an application (file type 'APPL') with
the specified creator on the specified volume. It first tries to get
the application mapping from the desktop database. If that fails,
then it tries to find an application in the Desktop file. If that
fails, then it tries to find an application with the specified creator
using the File Manager's CatSearch routine.
volName input: A pointer to the name of a mounted volume
or nil.
vRefNum input: Volume specification.
creator input: The file's creator type.
applVRefNum output: The volume reference number of the volume the
application is on.
applParID output: The parent directory ID of the application.
applName output: The name of the application.
Result Codes
noErr 0 No error
nsvErr -35 Volume not found
ioErr -36 I/O error
paramErr -50 No default volume
rfNumErr -51 Reference number invalid
extFSErr -58 External file system error - no file
system claimed this call
desktopDamagedErr -1305 The desktop database has become corrupted -
the Finder will fix this, but if your
application is not running with the
Finder, use PBDTReset or PBDTDelete
afpItemNotFound -5012 Information not found
__________
Also see: FSpDTGetAPPL
*/
/*****************************************************************************/
EXTERN_API( OSErr )
FSpDTGetAPPL(
ConstStr255Param volName,
short vRefNum,
OSType creator,
FSSpec * spec);
/*
The FSpDTGetAPPL function finds an application (file type 'APPL') with
the specified creator on the specified volume. It first tries to get
the application mapping from the desktop database. If that fails,
then it tries to find an application in the Desktop file. If that
fails, then it tries to find an application with the specified creator
using the File Manager's CatSearch routine.
volName input: A pointer to the name of a mounted volume
or nil.
vRefNum input: Volume specification.
creator input: The file's creator type.
spec output: FSSpec record containing the application name and
location.
Result Codes
noErr 0 No error
nsvErr -35 Volume not found
ioErr -36 I/O error
paramErr -50 No default volume
rfNumErr -51 Reference number invalid
extFSErr -58 External file system error - no file
system claimed this call
desktopDamagedErr -1305 The desktop database has become corrupted -
the Finder will fix this, but if your
application is not running with the
Finder, use PBDTReset or PBDTDelete
afpItemNotFound -5012 Information not found
__________
Also see: DTGetAPPL
*/
/*****************************************************************************/
EXTERN_API( OSErr )
DTGetIcon(
ConstStr255Param volName,
short vRefNum,
short iconType,
OSType fileCreator,
OSType fileType,
Handle * iconHandle);
/*
The DTGetIcon function retrieves the specified icon and returns it in
a newly created handle. The icon is retrieves from the Desktop Manager
or if the Desktop Manager is not available, from the Finder's Desktop
file. Your program is responsible for disposing of the handle when it is
done using the icon.
volName input: A pointer to the name of a mounted volume
or nil.
vRefNum input: Volume specification.
iconType input: The icon type as defined in Files.h. Valid values are:
kLargeIcon
kLarge4BitIcon
kLarge8BitIcon
kSmallIcon
kSmall4BitIcon
kSmall8BitIcon
fileCreator input: The icon's creator type.
fileType input: The icon's file type.
iconHandle output: A Handle containing the newly created icon.
Result Codes
noErr 0 No error
nsvErr -35 Volume not found
ioErr -36 I/O error
paramErr -50 Volume doesn't support this function
rfNumErr -51 Reference number invalid
extFSErr -58 External file system error - no file
system claimed this call
memFullErr -108 iconHandle could not be allocated
desktopDamagedErr -1305 The desktop database has become corrupted -
the Finder will fix this, but if your
application is not running with the
Finder, use PBDTReset or PBDTDelete
afpItemNotFound -5012 Information not found
*/
/*****************************************************************************/
EXTERN_API( OSErr )
DTSetComment(
short vRefNum,
long dirID,
ConstStr255Param name,
ConstStr255Param comment);
/*
The DTSetComment function sets a file or directory's Finder comment
field. The volume must support the Desktop Manager because you only
have read access to the Desktop file.
vRefNum input: Volume specification.
dirID input: Directory ID.
name input: Pointer to object name, or nil when dirID
specifies a directory that's the object.
comment input: The comment to add. Comments are limited to 200 characters;
longer comments are truncated.
Result Codes
noErr 0 No error
nsvErr -35 Volume not found
ioErr -36 I/O error
fnfErr <20>43 File or directory doesn<73>t exist
paramErr -50 Volume doesn't support this function
wPrErr <20>44 Volume is locked through hardware
vLckdErr <20>46 Volume is locked through software
rfNumErr <20>51 Reference number invalid
extFSErr -58 External file system error - no file
system claimed this call.
desktopDamagedErr -1305 The desktop database has become corrupted -
the Finder will fix this, but if your
application is not running with the
Finder, use PBDTReset or PBDTDelete
__________
Also see: DTCopyComment, FSpDTCopyComment, FSpDTSetComment, DTGetComment,
FSpDTGetComment
*/
/*****************************************************************************/
EXTERN_API( OSErr )
FSpDTSetComment(
const FSSpec * spec,
ConstStr255Param comment);
/*
The FSpDTSetComment function sets a file or directory's Finder comment
field. The volume must support the Desktop Manager because you only
have read access to the Desktop file.
spec input: An FSSpec record specifying the file or directory.
comment input: The comment to add. Comments are limited to 200 characters;
longer comments are truncated.
Result Codes
noErr 0 No error
nsvErr -35 Volume not found
ioErr -36 I/O error
fnfErr <20>43 File or directory doesn<73>t exist
wPrErr <20>44 Volume is locked through hardware
vLckdErr <20>46 Volume is locked through software
rfNumErr <20>51 Reference number invalid
paramErr -50 Volume doesn't support this function
extFSErr -58 External file system error - no file
system claimed this call.
desktopDamagedErr -1305 The desktop database has become corrupted -
the Finder will fix this, but if your
application is not running with the
Finder, use PBDTReset or PBDTDelete
__________
Also see: DTCopyComment, FSpDTCopyComment, DTSetComment, DTGetComment,
FSpDTGetComment
*/
/*****************************************************************************/
EXTERN_API( OSErr )
DTGetComment(
short vRefNum,
long dirID,
ConstStr255Param name,
Str255 comment);
/*
The DTGetComment function gets a file or directory's Finder comment
field (if any) from the Desktop Manager or if the Desktop Manager is
not available, from the Finder's Desktop file.
IMPORTANT NOTE: Inside Macintosh says that comments are up to
200 characters. While that may be correct for the HFS file system's
Desktop Manager, other file systems (such as Apple Photo Access) return
up to 255 characters. Make sure the comment buffer is a Str255 or you'll
regret it.
vRefNum input: Volume specification.
dirID input: Directory ID.
name input: Pointer to object name, or nil when dirID
specifies a directory that's the object.
comment output: A Str255 where the comment is to be returned.
Result Codes
noErr 0 No error
nsvErr -35 Volume not found
ioErr -36 I/O error
fnfErr -43 File not found
paramErr -50 Volume doesn't support this function
rfNumErr <20>51 Reference number invalid
extFSErr -58 External file system error - no file
system claimed this call.
desktopDamagedErr -1305 The desktop database has become corrupted -
the Finder will fix this, but if your
application is not running with the
Finder, use PBDTReset or PBDTDelete
afpItemNotFound -5012 Information not found
__________
Also see: DTCopyComment, FSpDTCopyComment, DTSetComment, FSpDTSetComment,
FSpDTGetComment
*/
/*****************************************************************************/
EXTERN_API( OSErr )
FSpDTGetComment(
const FSSpec * spec,
Str255 comment);
/*
The FSpDTGetComment function gets a file or directory's Finder comment
field (if any) from the Desktop Manager or if the Desktop Manager is
not available, from the Finder's Desktop file.
IMPORTANT NOTE: Inside Macintosh says that comments are up to
200 characters. While that may be correct for the HFS file system's
Desktop Manager, other file systems (such as Apple Photo Access) return
up to 255 characters. Make sure the comment buffer is a Str255 or you'll
regret it.
spec input: An FSSpec record specifying the file or directory.
comment output: A Str255 where the comment is to be returned.
Result Codes
noErr 0 No error
nsvErr -35 Volume not found
ioErr -36 I/O error
fnfErr -43 File not found
paramErr -50 Volume doesn't support this function
rfNumErr <20>51 Reference number invalid
extFSErr -58 External file system error - no file
system claimed this call.
desktopDamagedErr -1305 The desktop database has become corrupted -
the Finder will fix this, but if your
application is not running with the
Finder, use PBDTReset or PBDTDelete
afpItemNotFound -5012 Information not found
__________
Also see: DTCopyComment, FSpDTCopyComment, DTSetComment, FSpDTSetComment,
DTGetComment
*/
/*****************************************************************************/
EXTERN_API( OSErr )
DTCopyComment(
short srcVRefNum,
long srcDirID,
ConstStr255Param srcName,
short dstVRefNum,
long dstDirID,
ConstStr255Param dstName);
/*
The DTCopyComment function copies the file or folder comment from the
source to the destination object. The destination volume must support
the Desktop Manager because you only have read access to the Desktop file.
srcVRefNum input: Source volume specification.
srcDirID input: Source directory ID.
srcName input: Pointer to source object name, or nil when srcDirID
specifies a directory that's the object.
dstVRefNum input: Destination volume specification.
dstDirID input: Destination directory ID.
dstName input: Pointer to destination object name, or nil when
dstDirID specifies a directory that's the object.
Result Codes
noErr 0 No error
nsvErr -35 Volume not found
ioErr -36 I/O error
fnfErr <20>43 File or directory doesn<73>t exist
wPrErr <20>44 Volume is locked through hardware
vLckdErr <20>46 Volume is locked through software
paramErr -50 Volume doesn't support this function
rfNumErr <20>51 Reference number invalid
paramErr -50 Volume doesn't support this function
extFSErr -58 External file system error - no file
system claimed this call.
desktopDamagedErr -1305 The desktop database has become corrupted -
the Finder will fix this, but if your
application is not running with the
Finder, use PBDTReset or PBDTDelete
afpItemNotFound -5012 Information not found
__________
Also see: FSpDTCopyComment, DTSetComment, FSpDTSetComment, DTGetComment,
FSpDTGetComment
*/
/*****************************************************************************/
EXTERN_API( OSErr )
FSpDTCopyComment(
const FSSpec * srcSpec,
const FSSpec * dstSpec);
/*
The FSpDTCopyComment function copies the desktop database comment from
the source to the destination object. Both the source and the
destination volumes must support the Desktop Manager.
srcSpec input: An FSSpec record specifying the source object.
dstSpec input: An FSSpec record specifying the destination object.
Result Codes
noErr 0 No error
nsvErr -35 Volume not found
ioErr -36 I/O error
fnfErr <20>43 File or directory doesn<73>t exist
wPrErr <20>44 Volume is locked through hardware
vLckdErr <20>46 Volume is locked through software
paramErr -50 Volume doesn't support this function
rfNumErr <20>51 Reference number invalid
paramErr -50 Volume doesn't support this function
extFSErr -58 External file system error - no file
system claimed this call.
desktopDamagedErr -1305 The desktop database has become corrupted -
the Finder will fix this, but if your
application is not running with the
Finder, use PBDTReset or PBDTDelete
afpItemNotFound -5012 Information not found
__________
Also see: DTCopyComment, DTSetComment, FSpDTSetComment, DTGetComment,
FSpDTGetComment
*/
/*****************************************************************************/
#include "OptimizationEnd.h"
#if PRAGMA_STRUCT_ALIGN
#pragma options align=reset
#elif PRAGMA_STRUCT_PACKPUSH
#pragma pack(pop)
#elif PRAGMA_STRUCT_PACK
#pragma pack()
#endif
#ifdef PRAGMA_IMPORT_OFF
#pragma import off
#elif PRAGMA_IMPORT
#pragma import reset
#endif
#ifdef __cplusplus
}
#endif
#endif /* __MOREDESKTOPMGR__ */

View File

@@ -0,0 +1,643 @@
/*
File: MoreFiles.c
Contains: The long lost high-level and FSSpec File Manager functions.
Version: MoreFiles
Copyright: <09> 1992-2001 by Apple Computer, Inc., all rights reserved.
You may incorporate this sample code into your applications without
restriction, though the sample code has been provided "AS IS" and the
responsibility for its operation is 100% yours. However, what you are
not permitted to do is to redistribute the source as "DSC Sample Code"
after having made changes. If you're going to re-distribute the source,
we require that you make it clear in the source that the code was
descended from Apple Sample Code, but that you've made changes.
File Ownership:
DRI: Apple Macintosh Developer Technical Support
Other Contact: Apple Macintosh Developer Technical Support
<http://developer.apple.com/bugreporter/>
Technology: DTS Sample Code
Writers:
(JL) Jim Luther
Change History (most recent first):
<2> 2/7/01 JL Added standard header. Updated names of includes.
<1> 12/06/99 JL MoreFiles 1.5.
*/
#include <MacTypes.h>
#include <MacErrors.h>
#include <Files.h>
#define __COMPILINGMOREFILES
#include "MoreFiles.h"
#include "MoreFilesExtras.h"
/*****************************************************************************/
pascal OSErr HGetVolParms(ConstStr255Param volName,
short vRefNum,
GetVolParmsInfoBuffer *volParmsInfo,
long *infoSize)
{
HParamBlockRec pb;
OSErr error;
pb.ioParam.ioNamePtr = (StringPtr)volName;
pb.ioParam.ioVRefNum = vRefNum;
pb.ioParam.ioBuffer = (Ptr)volParmsInfo;
pb.ioParam.ioReqCount = *infoSize;
error = PBHGetVolParmsSync(&pb);
if ( error == noErr )
{
*infoSize = pb.ioParam.ioActCount;
}
return ( error );
}
/*****************************************************************************/
pascal OSErr HCreateMinimum(short vRefNum,
long dirID,
ConstStr255Param fileName)
{
HParamBlockRec pb;
pb.fileParam.ioNamePtr = (StringPtr)fileName;
pb.fileParam.ioVRefNum = vRefNum;
pb.ioParam.ioVersNum = 0;
pb.fileParam.ioDirID = dirID;
return ( PBHCreateSync(&pb) );
}
/*****************************************************************************/
pascal OSErr FSpCreateMinimum(const FSSpec *spec)
{
return ( HCreateMinimum(spec->vRefNum, spec->parID, spec->name) );
}
/*****************************************************************************/
pascal OSErr ExchangeFiles(short vRefNum,
long srcDirID,
ConstStr255Param srcName,
long dstDirID,
ConstStr255Param dstName)
{
HParamBlockRec pb;
pb.fidParam.ioVRefNum = vRefNum;
pb.fidParam.ioSrcDirID = srcDirID;
pb.fidParam.ioNamePtr = (StringPtr)srcName;
pb.fidParam.ioDestDirID = dstDirID;
pb.fidParam.ioDestNamePtr = (StringPtr)dstName;
return ( PBExchangeFilesSync(&pb) );
}
/*****************************************************************************/
pascal OSErr ResolveFileIDRef(ConstStr255Param volName,
short vRefNum,
long fileID,
long *parID,
StringPtr fileName)
{
HParamBlockRec pb;
OSErr error;
Str255 tempStr;
tempStr[0] = 0;
if ( volName != NULL )
{
BlockMoveData(volName, tempStr, volName[0] + 1);
}
pb.fidParam.ioNamePtr = (StringPtr)tempStr;
pb.fidParam.ioVRefNum = vRefNum;
pb.fidParam.ioFileID = fileID;
error = PBResolveFileIDRefSync(&pb);
if ( error == noErr )
{
*parID = pb.fidParam.ioSrcDirID;
if ( fileName != NULL )
{
BlockMoveData(tempStr, fileName, tempStr[0] + 1);
}
}
return ( error );
}
/*****************************************************************************/
pascal OSErr FSpResolveFileIDRef(ConstStr255Param volName,
short vRefNum,
long fileID,
FSSpec *spec)
{
OSErr error;
error = DetermineVRefNum(volName, vRefNum, &(spec->vRefNum));
if ( error == noErr )
{
error = ResolveFileIDRef(volName, vRefNum, fileID, &(spec->parID), spec->name);
}
return ( error );
}
/*****************************************************************************/
pascal OSErr CreateFileIDRef(short vRefNum,
long parID,
ConstStr255Param fileName,
long *fileID)
{
HParamBlockRec pb;
OSErr error;
pb.fidParam.ioNamePtr = (StringPtr)fileName;
pb.fidParam.ioVRefNum = vRefNum;
pb.fidParam.ioSrcDirID = parID;
error = PBCreateFileIDRefSync(&pb);
if ( (error == noErr) || (error == fidExists) || (error == afpIDExists) )
{
*fileID = pb.fidParam.ioFileID;
}
return ( error );
}
/*****************************************************************************/
pascal OSErr FSpCreateFileIDRef(const FSSpec *spec,
long *fileID)
{
return ( CreateFileIDRef(spec->vRefNum, spec->parID, spec->name, fileID) );
}
/*****************************************************************************/
pascal OSErr DeleteFileIDRef(ConstStr255Param volName,
short vRefNum,
long fileID)
{
HParamBlockRec pb;
pb.fidParam.ioNamePtr = (StringPtr)volName;
pb.fidParam.ioVRefNum = vRefNum;
pb.fidParam.ioFileID = fileID;
return ( PBDeleteFileIDRefSync(&pb) );
}
/*****************************************************************************/
pascal OSErr FlushFile(short refNum)
{
ParamBlockRec pb;
pb.ioParam.ioRefNum = refNum;
return ( PBFlushFileSync(&pb) );
}
/*****************************************************************************/
pascal OSErr LockRange(short refNum,
long rangeLength,
long rangeStart)
{
ParamBlockRec pb;
pb.ioParam.ioRefNum = refNum;
pb.ioParam.ioReqCount = rangeLength;
pb.ioParam.ioPosMode = fsFromStart;
pb.ioParam.ioPosOffset = rangeStart;
return ( PBLockRangeSync(&pb) );
}
/*****************************************************************************/
pascal OSErr UnlockRange(short refNum,
long rangeLength,
long rangeStart)
{
ParamBlockRec pb;
pb.ioParam.ioRefNum = refNum;
pb.ioParam.ioReqCount = rangeLength;
pb.ioParam.ioPosMode = fsFromStart;
pb.ioParam.ioPosOffset = rangeStart;
return ( PBUnlockRangeSync(&pb) );
}
/*****************************************************************************/
pascal OSErr GetForeignPrivs(short vRefNum,
long dirID,
ConstStr255Param name,
void *foreignPrivBuffer,
long *foreignPrivSize,
long *foreignPrivInfo1,
long *foreignPrivInfo2,
long *foreignPrivInfo3,
long *foreignPrivInfo4)
{
HParamBlockRec pb;
OSErr error;
pb.foreignPrivParam.ioNamePtr = (StringPtr)name;
pb.foreignPrivParam.ioVRefNum = vRefNum;
pb.foreignPrivParam.ioForeignPrivDirID = dirID;
pb.foreignPrivParam.ioForeignPrivBuffer = (Ptr)foreignPrivBuffer;
pb.foreignPrivParam.ioForeignPrivReqCount = *foreignPrivSize;
error = PBGetForeignPrivsSync(&pb);
*foreignPrivSize = pb.foreignPrivParam.ioForeignPrivActCount;
*foreignPrivInfo1 = pb.foreignPrivParam.ioForeignPrivInfo1;
*foreignPrivInfo2 = pb.foreignPrivParam.ioForeignPrivInfo2;
*foreignPrivInfo3 = pb.foreignPrivParam.ioForeignPrivInfo3;
*foreignPrivInfo4 = pb.foreignPrivParam.ioForeignPrivInfo4;
return ( error );
}
/*****************************************************************************/
pascal OSErr FSpGetForeignPrivs(const FSSpec *spec,
void *foreignPrivBuffer,
long *foreignPrivSize,
long *foreignPrivInfo1,
long *foreignPrivInfo2,
long *foreignPrivInfo3,
long *foreignPrivInfo4)
{
return ( GetForeignPrivs(spec->vRefNum, spec->parID, spec->name,
foreignPrivBuffer, foreignPrivSize,
foreignPrivInfo1, foreignPrivInfo2,
foreignPrivInfo3, foreignPrivInfo4) );
}
/*****************************************************************************/
pascal OSErr SetForeignPrivs(short vRefNum,
long dirID,
ConstStr255Param name,
const void *foreignPrivBuffer,
long *foreignPrivSize,
long foreignPrivInfo1,
long foreignPrivInfo2,
long foreignPrivInfo3,
long foreignPrivInfo4)
{
HParamBlockRec pb;
OSErr error;
pb.foreignPrivParam.ioNamePtr = (StringPtr)name;
pb.foreignPrivParam.ioVRefNum = vRefNum;
pb.foreignPrivParam.ioForeignPrivDirID = dirID;
pb.foreignPrivParam.ioForeignPrivBuffer = (Ptr)foreignPrivBuffer;
pb.foreignPrivParam.ioForeignPrivReqCount = *foreignPrivSize;
pb.foreignPrivParam.ioForeignPrivInfo1 = foreignPrivInfo1;
pb.foreignPrivParam.ioForeignPrivInfo2 = foreignPrivInfo2;
pb.foreignPrivParam.ioForeignPrivInfo3 = foreignPrivInfo3;
pb.foreignPrivParam.ioForeignPrivInfo4 = foreignPrivInfo4;
error = PBSetForeignPrivsSync(&pb);
if ( error == noErr )
{
*foreignPrivSize = pb.foreignPrivParam.ioForeignPrivActCount;
}
return ( error );
}
/*****************************************************************************/
pascal OSErr FSpSetForeignPrivs(const FSSpec *spec,
const void *foreignPrivBuffer,
long *foreignPrivSize,
long foreignPrivInfo1,
long foreignPrivInfo2,
long foreignPrivInfo3,
long foreignPrivInfo4)
{
return ( SetForeignPrivs(spec->vRefNum, spec->parID, spec->name,
foreignPrivBuffer, foreignPrivSize,
foreignPrivInfo1, foreignPrivInfo2,
foreignPrivInfo3, foreignPrivInfo4) );
}
/*****************************************************************************/
pascal OSErr HGetLogInInfo(ConstStr255Param volName,
short vRefNum,
short *loginMethod,
StringPtr userName)
{
HParamBlockRec pb;
OSErr error;
pb.objParam.ioNamePtr = (StringPtr)volName;
pb.objParam.ioVRefNum = vRefNum;
pb.objParam.ioObjNamePtr = userName;
error = PBHGetLogInInfoSync(&pb);
if ( error == noErr )
{
*loginMethod = pb.objParam.ioObjType;
}
return ( error );
}
/*****************************************************************************/
pascal OSErr HGetDirAccess(short vRefNum,
long dirID,
ConstStr255Param name,
long *ownerID,
long *groupID,
long *accessRights)
{
HParamBlockRec pb;
OSErr error;
pb.accessParam.ioNamePtr = (StringPtr)name;
pb.accessParam.ioVRefNum = vRefNum;
pb.fileParam.ioDirID = dirID;
error = PBHGetDirAccessSync(&pb);
if ( error == noErr )
{
*ownerID = pb.accessParam.ioACOwnerID;
*groupID = pb.accessParam.ioACGroupID;
*accessRights = pb.accessParam.ioACAccess;
}
return ( error );
}
/*****************************************************************************/
pascal OSErr FSpGetDirAccess(const FSSpec *spec,
long *ownerID,
long *groupID,
long *accessRights)
{
return ( HGetDirAccess(spec->vRefNum, spec->parID, spec->name,
ownerID, groupID, accessRights) );
}
/*****************************************************************************/
pascal OSErr HSetDirAccess(short vRefNum,
long dirID,
ConstStr255Param name,
long ownerID,
long groupID,
long accessRights)
{
HParamBlockRec pb;
pb.accessParam.ioNamePtr = (StringPtr)name;
pb.accessParam.ioVRefNum = vRefNum;
pb.fileParam.ioDirID = dirID;
pb.accessParam.ioACOwnerID = ownerID;
pb.accessParam.ioACGroupID = groupID;
pb.accessParam.ioACAccess = accessRights;
return ( PBHSetDirAccessSync(&pb) );
}
/*****************************************************************************/
pascal OSErr FSpSetDirAccess(const FSSpec *spec,
long ownerID,
long groupID,
long accessRights)
{
return ( HSetDirAccess(spec->vRefNum, spec->parID, spec->name,
ownerID, groupID, accessRights) );
}
/*****************************************************************************/
pascal OSErr HMapID(ConstStr255Param volName,
short vRefNum,
long ugID,
short objType,
StringPtr name)
{
HParamBlockRec pb;
pb.objParam.ioNamePtr = (StringPtr)volName;
pb.objParam.ioVRefNum = vRefNum;
pb.objParam.ioObjType = objType;
pb.objParam.ioObjNamePtr = name;
pb.objParam.ioObjID = ugID;
return ( PBHMapIDSync(&pb) );
}
/*****************************************************************************/
pascal OSErr HMapName(ConstStr255Param volName,
short vRefNum,
ConstStr255Param name,
short objType,
long *ugID)
{
HParamBlockRec pb;
OSErr error;
pb.objParam.ioNamePtr = (StringPtr)volName;
pb.objParam.ioVRefNum = vRefNum;
pb.objParam.ioObjType = objType;
pb.objParam.ioObjNamePtr = (StringPtr)name;
error = PBHMapNameSync(&pb);
if ( error == noErr )
{
*ugID = pb.objParam.ioObjID;
}
return ( error );
}
/*****************************************************************************/
pascal OSErr HCopyFile(short srcVRefNum,
long srcDirID,
ConstStr255Param srcName,
short dstVRefNum,
long dstDirID,
ConstStr255Param dstPathname,
ConstStr255Param copyName)
{
HParamBlockRec pb;
pb.copyParam.ioVRefNum = srcVRefNum;
pb.copyParam.ioDirID = srcDirID;
pb.copyParam.ioNamePtr = (StringPtr)srcName;
pb.copyParam.ioDstVRefNum = dstVRefNum;
pb.copyParam.ioNewDirID = dstDirID;
pb.copyParam.ioNewName = (StringPtr)dstPathname;
pb.copyParam.ioCopyName = (StringPtr)copyName;
return ( PBHCopyFileSync(&pb) );
}
/*****************************************************************************/
pascal OSErr FSpCopyFile(const FSSpec *srcSpec,
const FSSpec *dstSpec,
ConstStr255Param copyName)
{
return ( HCopyFile(srcSpec->vRefNum, srcSpec->parID, srcSpec->name,
dstSpec->vRefNum, dstSpec->parID,
dstSpec->name, copyName) );
}
/*****************************************************************************/
pascal OSErr HMoveRename(short vRefNum,
long srcDirID,
ConstStr255Param srcName,
long dstDirID,
ConstStr255Param dstpathName,
ConstStr255Param copyName)
{
HParamBlockRec pb;
pb.copyParam.ioVRefNum = vRefNum;
pb.copyParam.ioDirID = srcDirID;
pb.copyParam.ioNamePtr = (StringPtr)srcName;
pb.copyParam.ioNewDirID = dstDirID;
pb.copyParam.ioNewName = (StringPtr)dstpathName;
pb.copyParam.ioCopyName = (StringPtr)copyName;
return ( PBHMoveRenameSync(&pb) );
}
/*****************************************************************************/
pascal OSErr FSpMoveRename(const FSSpec *srcSpec,
const FSSpec *dstSpec,
ConstStr255Param copyName)
{
OSErr error;
/* make sure the FSSpecs refer to the same volume */
if ( srcSpec->vRefNum != dstSpec->vRefNum )
{
error = diffVolErr;
}
else
{
error = HMoveRename(srcSpec->vRefNum, srcSpec->parID, srcSpec->name,
dstSpec->parID, dstSpec->name, copyName);
}
return ( error );
}
/*****************************************************************************/
pascal OSErr GetVolMountInfoSize(ConstStr255Param volName,
short vRefNum,
short *size)
{
ParamBlockRec pb;
pb.ioParam.ioNamePtr = (StringPtr)volName;
pb.ioParam.ioVRefNum = vRefNum;
pb.ioParam.ioBuffer = (Ptr)size;
return ( PBGetVolMountInfoSize(&pb) );
}
/*****************************************************************************/
pascal OSErr GetVolMountInfo(ConstStr255Param volName,
short vRefNum,
void *volMountInfo)
{
ParamBlockRec pb;
pb.ioParam.ioNamePtr = (StringPtr)volName;
pb.ioParam.ioVRefNum = vRefNum;
pb.ioParam.ioBuffer = (Ptr)volMountInfo;
return ( PBGetVolMountInfo(&pb) );
}
/*****************************************************************************/
pascal OSErr VolumeMount(const void *volMountInfo,
short *vRefNum)
{
ParamBlockRec pb;
OSErr error;
pb.ioParam.ioBuffer = (Ptr)volMountInfo;
error = PBVolumeMount(&pb);
if ( error == noErr )
{
*vRefNum = pb.ioParam.ioVRefNum;
}
return ( error );
}
/*****************************************************************************/
pascal OSErr Share(short vRefNum,
long dirID,
ConstStr255Param name)
{
HParamBlockRec pb;
pb.fileParam.ioNamePtr = (StringPtr)name;
pb.fileParam.ioVRefNum = vRefNum;
pb.fileParam.ioDirID = dirID;
return ( PBShareSync(&pb) );
}
/*****************************************************************************/
pascal OSErr FSpShare(const FSSpec *spec)
{
return ( Share(spec->vRefNum, spec->parID, spec->name) );
}
/*****************************************************************************/
pascal OSErr Unshare(short vRefNum,
long dirID,
ConstStr255Param name)
{
HParamBlockRec pb;
pb.fileParam.ioNamePtr = (StringPtr)name;
pb.fileParam.ioVRefNum = vRefNum;
pb.fileParam.ioDirID = dirID;
return ( PBUnshareSync(&pb) );
}
/*****************************************************************************/
pascal OSErr FSpUnshare(const FSSpec *spec)
{
return ( Unshare(spec->vRefNum, spec->parID, spec->name) );
}
/*****************************************************************************/
pascal OSErr GetUGEntry(short objType,
StringPtr objName,
long *objID)
{
HParamBlockRec pb;
OSErr error;
pb.objParam.ioObjType = objType;
pb.objParam.ioObjNamePtr = objName;
pb.objParam.ioObjID = *objID;
error = PBGetUGEntrySync(&pb);
if ( error == noErr )
{
*objID = pb.objParam.ioObjID;
}
return ( error );
}
/*****************************************************************************/

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,109 @@
/*
File: Optimization.h
Contains: Defines that let you make MoreFiles code more efficient.
Version: MoreFiles
Copyright: <09> 1992-2001 by Apple Computer, Inc., all rights reserved.
You may incorporate this sample code into your applications without
restriction, though the sample code has been provided "AS IS" and the
responsibility for its operation is 100% yours. However, what you are
not permitted to do is to redistribute the source as "DSC Sample Code"
after having made changes. If you're going to re-distribute the source,
we require that you make it clear in the source that the code was
descended from Apple Sample Code, but that you've made changes.
File Ownership:
DRI: Apple Macintosh Developer Technical Support
Other Contact: Apple Macintosh Developer Technical Support
<http://developer.apple.com/bugreporter/>
Technology: DTS Sample Code
Writers:
(JL) Jim Luther
Change History (most recent first):
<1> 2/7/01 JL first checked in
*/
/*
The Optimization changes to MoreFiles source and header files, along with
this file and OptimizationEnd.h, let you optimize the code produced
by MoreFiles in several ways.
1 -- MoreFiles contains extra code so that many routines can run under
Mac OS systems back to System 6. If your program requires a specific
version of Mac OS and your program checks for that version before
calling MoreFiles routines, then you can remove a lot of compatibility
code by defining one of the following to 1:
__MACOSSEVENFIVEONEORLATER // assume Mac OS 7.5.1 or later
__MACOSSEVENFIVEORLATER // assume Mac OS 7.5 or later
__MACOSSEVENORLATER // assume Mac OS 7.0 or later
If you're compiling 68K code, the default is to include all compatibility code.
If you're compiling PowerPC code (TARGET_RT_MAC_CFM), the default is __MACOSSEVENORLATER
If you're compiling for Carbon code (TARGET_API_MAC_CARBON), the default is __MACOSSEVENFIVEONEORLATER
2 -- You may disable Pascal calling conventions in all MoreFiles routines
except for system callbacks that require Pascal calling conventions.
This will make 68K C programs both smaller and faster.
(PowerPC compilers ignore pascal calling conventions.)
Just define __WANTPASCALELIMINATION to be 1 to turn this optimization on
when building MoreFiles for use from C programs (you'll need to keep
Pascal calling conventions when linking MoreFiles routines with Pascal
programs).
3 -- If Metrowerks compiler is used, "#pragma internal on" may help produce
better code. However, this option can also cause problems if you're
trying to build MoreFiles as a shared library, so it is by default not used.
Just define __USEPRAGMAINTERNAL to be 1 to turn this optimization on.
Original changes supplied by Fabrizio Oddone
*/
#include <ConditionalMacros.h>
// if we're compiling for Carbon, then we're running on Mac OS 8.1 or later
#ifndef __MACOSSEVENFIVEONEORLATER
#define __MACOSSEVENFIVEONEORLATER TARGET_API_MAC_CARBON
#endif
#ifndef __MACOSSEVENFIVEORLATER
#define __MACOSSEVENFIVEORLATER __MACOSSEVENFIVEONEORLATER
#endif
#ifndef __MACOSSEVENORLATER
#if TARGET_RT_MAC_CFM
#define __MACOSSEVENORLATER 1
#else
#define __MACOSSEVENORLATER __MACOSSEVENFIVEORLATER
#endif
#endif
#ifndef __WANTPASCALELIMINATION
#define __WANTPASCALELIMINATION 0
#endif
#if __WANTPASCALELIMINATION
#define pascal
#endif
#ifndef __USEPRAGMAINTERNAL
#define __USEPRAGMAINTERNAL 0
#endif
#if __USEPRAGMAINTERNAL
#if defined(__MWERKS__)
#pragma internal on
#endif
#endif

View File

@@ -0,0 +1,56 @@
/*
File: OptimizationEnd.h
Contains: Defines that let you make MoreFiles code more efficient.
Version: MoreFiles
Copyright: <09> 1992-2001 by Apple Computer, Inc., all rights reserved.
You may incorporate this sample code into your applications without
restriction, though the sample code has been provided "AS IS" and the
responsibility for its operation is 100% yours. However, what you are
not permitted to do is to redistribute the source as "DSC Sample Code"
after having made changes. If you're going to re-distribute the source,
we require that you make it clear in the source that the code was
descended from Apple Sample Code, but that you've made changes.
File Ownership:
DRI: Apple Macintosh Developer Technical Support
Other Contact: Apple Macintosh Developer Technical Support
<http://developer.apple.com/bugreporter/>
Technology: DTS Sample Code
Writers:
(JL) Jim Luther
Change History (most recent first):
<1> 2/7/01 JL first checked in
*/
/*
The Optimization changes to MoreFiles source and header files, along with
this file and Optimization.h, let you optimize the code produced by MoreFiles
in several ways.
Original changes supplied by Fabrizio Oddone
*/
#if __USEPRAGMAINTERNAL
#if defined(__MWERKS__)
#pragma internal reset
#endif
#endif
#if __WANTPASCALELIMINATION
#ifndef __COMPILINGMOREFILES
#undef pascal
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,304 @@
/*
File: Search.h
Contains: IndexedSearch and the PBCatSearch compatibility function.
Version: Technology: MoreFiles
Release: 1.5.2
Copyright: <20> 1992-2001 by Apple Computer, Inc., all rights reserved.
Bugs?: For bug reports, consult the following page on
the World Wide Web:
http://developer.apple.com/bugreporter/
*/
/*
You may incorporate this sample code into your applications without
restriction, though the sample code has been provided "AS IS" and the
responsibility for its operation is 100% yours. However, what you are
not permitted to do is to redistribute the source as "DSC Sample Code"
after having made changes. If you're going to re-distribute the source,
we require that you make it clear in the source that the code was
descended from Apple Sample Code, but that you've made changes.
*/
#ifndef __SEARCH__
#define __SEARCH__
#ifndef __MACTYPES__
#include <MacTypes.h>
#endif
#ifndef __FILES__
#include <Files.h>
#endif
#include "Optimization.h"
#if PRAGMA_ONCE
#pragma once
#endif
#ifdef __cplusplus
extern "C" {
#endif
#if PRAGMA_IMPORT
#pragma import on
#endif
#if PRAGMA_STRUCT_ALIGN
#pragma options align=mac68k
#elif PRAGMA_STRUCT_PACKPUSH
#pragma pack(push, 2)
#elif PRAGMA_STRUCT_PACK
#pragma pack(2)
#endif
/*****************************************************************************/
EXTERN_API( OSErr )
IndexedSearch(
CSParamPtr pb,
long dirID);
/*
The IndexedSearch function performs an indexed search in and below the
specified directory using the same parameters (in pb) as is passed to
PBCatSearch. See Inside Macintosh: Files for a description of the
parameter block.
pb input: A CSParamPtr record specifying the volume to search
and the search criteria.
output: Fields in the parameter block are returned indicating
the number of matches found, the matches, and if the
search ended with noErr, the CatPosition record that
lets you resume a search where the last search left
off.
dirID input: The directory to search. If fsRtDirID is passed,
the entire volume is searched.
Note: If you use a high-level debugger and use ioSearchTime to limit
the length of time to run the search, you'll want to step over
calls to IndexedSearch because it installs a Time Manager task.
Most high-level debuggers don't deal gracefully with interrupt
driven code.
Result Codes
noErr 0 No error
nsvErr -35 Volume not found
ioErr -36 I/O error
eofErr -39 End of catalog found (this is normal!)
paramErr -50 Parameter block has invalid parameters
(see source for VerifyUserPB) or
invalid catPosition record was passed
extFSErr -58 External file system error - no file
system claimed this call.
memFullErr -108 Memory could not be allocated in heap
catChangedErr -1304 Catalog has changed and catalog position
record may be invalid
__________
See also: PBCatSearch, PBCatSearchSyncCompat
*/
/*****************************************************************************/
EXTERN_API( OSErr )
PBCatSearchSyncCompat(CSParamPtr paramBlock);
/*
The PBCatSearchSyncCompat function uses PBCatSearch (if available) or
IndexedSearch (if PBCatSearch is not available) to search a volume
using a set of search criteria that you specify. It builds a list of all
files or directories that meet your specifications.
pb input: A CSParamPtr record specifying the volume to search
and the search criteria.
output: Fields in the parameter block are returned indicating
the number of matches found, the matches, and if the
search ended with noErr, the CatPosition record that
lets you resume a search where the last search left
off.
Note: If you use a high-level debugger and use ioSearchTime to limit
the length of time to run the search, you'll want to step over
calls to PBCatSearchSyncCompat because it calls IndexedSearch
which installs a Time Manager task. Most high-level debuggers
don't deal gracefully with interrupt driven code.
Result Codes
noErr 0 No error
nsvErr -35 Volume not found
ioErr -36 I/O error
eofErr -39 End of catalog found (this is normal!)
paramErr -50 Parameter block has invalid parameters
(see source for VerifyUserPB) or
invalid catPosition record was passed
extFSErr -58 External file system error - no file
system claimed this call.
memFullErr -108 Memory could not be allocated in heap
catChangedErr -1304 Catalog has changed and catalog position
record may be invalid
afpCatalogChanged -5037 Catalog has changed and search cannot
be resumed
__________
See also: PBCatSearch, IndexedSearch
*/
/*****************************************************************************/
EXTERN_API( OSErr )
NameFileSearch(
ConstStr255Param volName,
short vRefNum,
ConstStr255Param fileName,
FSSpecPtr matches,
long reqMatchCount,
long * actMatchCount,
Boolean newSearch,
Boolean partial);
/*
The NameFileSearch function searches for files with a specific file
name on a volume that supports PBCatSearch.
Note: A result of catChangedErr means the catalog has changed between
searches, but the search can be continued with the possiblity that you
may miss some matches or get duplicate matches. For all other results
(except for noErr), the search cannot be continued.
volName input: A pointer to the name of a mounted volume
or nil.
vRefNum input: Volume specification.
fileName input: The name of the file to search for.
matches input: Pointer to array of FSSpec where the match list is
returned.
reqMatchCount input: Maximum number of matches to return (the number of
elements in the matches array).
actMatchCount output: The number of matches actually returned.
newSearch input: If true, start a new search. If false and if
vRefNum is the same as the last call to
NameFileSearch, then start searching at the
position where the last search left off.
partial input: If the partial parameter is false, then only files
that exactly match fileName will be found. If the
partial parameter is true, then all file names that
contain fileName will be found.
Result Codes
noErr 0 No error
nsvErr -35 Volume not found
ioErr -36 I/O error
eofErr -39 End of catalog found (this is normal!)
paramErr -50 Parameter block has invalid parameters
(see source for VerifyUserPB) or
invalid catPosition record was passed
extFSErr -58 External file system error - no file
system claimed this call.
memFullErr -108 Memory could not be allocated in heap
catChangedErr -1304 Catalog has changed and catalog position
record may be invalid
afpCatalogChanged -5037 Catalog has changed and search cannot
be resumed
__________
Also see: CreatorTypeFileSearch
*/
/*****************************************************************************/
EXTERN_API( OSErr )
CreatorTypeFileSearch(
ConstStr255Param volName,
short vRefNum,
OSType creator,
OSType fileType,
FSSpecPtr matches,
long reqMatchCount,
long * actMatchCount,
Boolean newSearch);
/*
The CreatorTypeFileSearch function searches for files with a specific
creator or fileType on a volume that supports PBCatSearch.
Note: A result of catChangedErr means the catalog has changed between
searches, but the search can be continued with the possiblity that you
may miss some matches or get duplicate matches. For all other results
(except for noErr), the search cannot be continued.
volName input: A pointer to the name of a mounted volume
or nil.
vRefNum input: Volume specification.
creator input: The creator type of the file to search for.
To ignore the creator type, pass 0x00000000 in
this field.
fileType input: The file type of the file to search for.
To ignore the file type, pass 0x00000000 in
this field.
matches input: Pointer to array of FSSpec where the match list is
returned.
reqMatchCount input: Maximum number of matches to return (the number of
elements in the matches array).
actMatchCount output: The number of matches actually returned.
newSearch input: If true, start a new search. If false and if
vRefNum is the same as the last call to
CreatorTypeFileSearch, then start searching at the
position where the last search left off.
Result Codes
noErr 0 No error
nsvErr -35 Volume not found
ioErr -36 I/O error
eofErr -39 End of catalog found (this is normal!)
paramErr -50 Parameter block has invalid parameters
(see source for VerifyUserPB) or
invalid catPosition record was passed
extFSErr -58 External file system error - no file
system claimed this call.
memFullErr -108 Memory could not be allocated in heap
catChangedErr -1304 Catalog has changed and catalog position
record may be invalid
afpCatalogChanged -5037 Catalog has changed and search cannot
be resumed
__________
Also see: NameFileSearch
*/
/*****************************************************************************/
#include "OptimizationEnd.h"
#if PRAGMA_STRUCT_ALIGN
#pragma options align=reset
#elif PRAGMA_STRUCT_PACKPUSH
#pragma pack(pop)
#elif PRAGMA_STRUCT_PACK
#pragma pack()
#endif
#ifdef PRAGMA_IMPORT_OFF
#pragma import off
#elif PRAGMA_IMPORT
#pragma import reset
#endif
#ifdef __cplusplus
}
#endif
#endif /* __SEARCH__ */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,125 @@
MoreFilesX
Copyright (c) 1992-2002 Apple Computer, Inc.
All rights reserved.
________________________________________________________________________________
About MoreFilesX
MoreFilesX is a collection of useful high-level File Manager routines that use the HFS Plus APIs introduced in Mac OS 9.0 wherever possible.
While many of the routines in MoreFilesX are based on the older MoreFiles sample code (which used the older File Manager APIs), by using the HFS Plus APIs, the routines in MoreFilesX have several advantages over the older MoreFiles code:
<EFBFBD> The routines are simpler to understand because the high-level HFS Plus APIs are more powerful.
<EFBFBD> The routines support the features of the HFS Plus volume format such as long Unicode filenames and files larger than 2GB.
<EFBFBD> In many cases, the routines execute more efficiently than code that uses the older File Manager APIs -- especially on non-HFS volumes.
<EFBFBD> The routines use Apple's standard exception and assertion macros (the require, check, and verify macros) which improves readability and error handling, and which provides easy debug builds -- just add #define DEBUG 1 and every exception causes an assertion.
<EFBFBD> The routines are thread safe. There are no global or static variables so multiple program threads can use MoreFilesX routines safely.
If you are writing new Carbon applications for Mac OS X that call the File Manager, you should use MoreFilesX -- not MoreFiles. If you're porting existing applications to Mac OS X and those applications use routines from MoreFiles, you should consider switching to the routines in MoreFilesX.
The routines were designed for applications running in the Mac OS X Carbon environment. All of the routines will work under Mac OS 9 if you define BuildingMoreFilesXForMacOS9 to 1. Doing that removes code that calls Mac OS X only APIs. MoreFilesX cannot be used in pre-Mac OS 9 system releases.
The routines in MoreFilesX have been tested (but not stress-tested) and are fully documented.
________________________________________________________________________________
Files in the MoreFilesX Package
MoreFilesX.c - the source code for MoreFilesX.
MoreFilesX.h - the header files and complete documentation for the routines included in MoreFilesX.
________________________________________________________________________________
How to use MoreFilesX
You can compile the code and link it into your programs. You can cut and paste portions of it into your programs. You can use it as an example. Since MoreFilesX is sample code, many routines are there simply to show you how to use the File Manager APIs. If a routine does more or less than what you want, you can have the source so you can modify it to do exactly you want it to do. Feel free to rip MoreFilesX off and modify its code in whatever ways you find work best for you.
You'll also notice that all routines that make other File Manager calls return an OSErr or OSStatus result. I always check for error results and you should too.
________________________________________________________________________________
Documentation
The documentation for the routines can be found in the header files. There, you'll find function prototypes, and a description of each call that includes a complete listing of all input and output parameters. For example, here's the function prototype and documentation for one of the routines, FSPathMakeFSSpec.
OSStatus
FSPathMakeFSSpec(
UInt8 *path,
FSSpec *spec,
Boolean *isDirectory); /* can be NULL */
/*
The FSPathMakeFSSpec function converts a pathname to an FSSpec.
path --> A pointer to a C String that is the pathname. The
format of the pathname you must supply can be
determined with the Gestalt selector gestaltFSAttr's
gestaltFSUsesPOSIXPathsForConversion bit.
If the gestaltFSUsesPOSIXPathsForConversion bit is
clear, the pathname must be a Mac OS File Manager
full pathname in a C string. If the
gestaltFSUsesPOSIXPathsForConversion bit is set,
the pathname must be a UTF8 encoded POSIX absolute
pathname in a C string. In either case, the pathname
returned by FSMakePath can be passed to
FSPathMakeFSSpec.
spec <-- The FSSpec.
isDirectory <** An optional pointer to a Boolean.
If not NULL, true will be returned in the Boolean
if the specified path is a directory or false will
be returned in the Boolean if the specified path is
a file.
*/
What do those arrows in the documentation for each routine mean?
--> The parameter is an input
<-- The parameter is an output. The pointer to the variable
where the output will be returned (must not be NULL).
<** The parameter is an optional output. If it is not a
NULL pointer, it points to the variable where the output
will be returned. If it is a NULL pointer, the output will
not be returned and will possibly let the routine and the
File Manager do less work. If you don't need an optional output,
don't ask for it.
**> The parameter is an optional input. If it is not a
NULL pointer, it points to the variable containing the
input data. If it is a NULL pointer, the input is not used
and will possibly let the routine and the File Manager
do less work.
While most of the routines in MoreFilesX have plenty of comments to clarify what the code is doing, a few have very few comments in their code because they simply make a single File Manager call. For those routines, the routine description is the comment. If something isn't clear, take a look at File Manager documentation online at <http://developer.apple.com/techpubs/macosx/Carbon/Files/FileManager/File_Manager/index.html>.
The methodology behind Apple's standard exception and assertion macros is clearly explained in Sean Parent's article "Living in an Exceptional World" develop, The Apple Technical Journal, August 1992 <http://developer.apple.com/dev/techsupport/develop/issue11toc.shtml>. Don't let the fact that this article is 10 years old fool you -- this is highly recommended reading.
________________________________________________________________________________
Release Notes
v1.0 Jan 25, 2002
First Release.
v1.0.1 Aug 23, 2002
[2850624] Fixed C++ compile errors and Project Builder warnings.
[2853901] Updated standard disclaimer.
[2853905] Fixed #if test around header includes.
[3016251] Changed FSMoveRenameObjectUnicode to not use the Temporary folder because it isn't available on NFS volumes.
________________________________________________________________________________
Bug Reports and Enhancement Requests
To file bug reports and enhancement requests, please go to <http://developer.apple.com/bugreporter/> and include "MoreFilesX Sample Code" in the title of your message.
Yes, we know that some of the routines available in MoreFiles still aren't in MoreFilesX. They were omitted due to time constraints.
________________________________________________________________________________

284
src/osx/carbon/msgdlg.cpp Normal file
View File

@@ -0,0 +1,284 @@
/////////////////////////////////////////////////////////////////////////////
// Name: src/mac/carbon/msgdlg.cpp
// Purpose: wxMessageDialog
// Author: Stefan Csomor
// Modified by:
// Created: 04/01/98
// RCS-ID: $Id$
// Copyright: (c) Stefan Csomor
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
#include "wx/wxprec.h"
#include "wx/msgdlg.h"
#ifndef WX_PRECOMP
#include "wx/intl.h"
#include "wx/app.h"
#endif
#include "wx/thread.h"
#include "wx/mac/uma.h"
IMPLEMENT_CLASS(wxMessageDialog, wxDialog)
wxMessageDialog::wxMessageDialog(wxWindow *parent,
const wxString& message,
const wxString& caption,
long style,
const wxPoint& WXUNUSED(pos))
: wxMessageDialogBase(parent, message, caption, style)
{
m_yes = _("Yes");
m_no = _("No");
m_ok = _("OK");
m_cancel = _("Cancel");
}
bool wxMessageDialog::SetYesNoLabels(const wxString& yes,const wxString& no)
{
m_yes = yes;
m_no = no;
return true;
}
bool wxMessageDialog::SetYesNoCancelLabels(const wxString& yes, const wxString& no, const wxString& cancel)
{
m_yes = yes;
m_no = no;
m_cancel = cancel;
return true;
}
bool wxMessageDialog::SetOKLabel(const wxString& ok)
{
m_ok = ok;
return true;
}
bool wxMessageDialog::SetOKCancelLabels(const wxString& ok, const wxString& cancel)
{
m_ok = ok;
m_cancel = cancel;
return true;
}
int wxMessageDialog::ShowModal()
{
int resultbutton = wxID_CANCEL;
const long style = GetMessageDialogStyle();
wxASSERT_MSG( (style & 0x3F) != wxYES, wxT("this style is not supported on Mac") );
AlertType alertType = kAlertPlainAlert;
if (style & wxICON_EXCLAMATION)
alertType = kAlertCautionAlert;
else if (style & wxICON_HAND)
alertType = kAlertStopAlert;
else if (style & wxICON_INFORMATION)
alertType = kAlertNoteAlert;
else if (style & wxICON_QUESTION)
alertType = kAlertNoteAlert;
// work out what to display
// if the extended text is empty then we use the caption as the title
// and the message as the text (for backwards compatibility)
// but if the extended message is not empty then we use the message as the title
// and the extended message as the text because that makes more sense
wxString msgtitle,msgtext;
if(m_extendedMessage.IsEmpty())
{
msgtitle = m_caption;
msgtext = m_message;
}
else
{
msgtitle = m_message;
msgtext = m_extendedMessage;
}
if ( !wxIsMainThread() )
{
CFStringRef defaultButtonTitle = NULL;
CFStringRef alternateButtonTitle = NULL;
CFStringRef otherButtonTitle = NULL;
wxCFStringRef cfTitle( msgtitle, GetFont().GetEncoding() );
wxCFStringRef cfText( msgtext, GetFont().GetEncoding() );
wxCFStringRef cfNoString( m_no.c_str(), GetFont().GetEncoding() );
wxCFStringRef cfYesString( m_yes.c_str(), GetFont().GetEncoding() );
wxCFStringRef cfOKString( m_ok.c_str() , GetFont().GetEncoding()) ;
wxCFStringRef cfCancelString( m_cancel.c_str(), GetFont().GetEncoding() );
int buttonId[4] = { 0, 0, 0, wxID_CANCEL /* time-out */ };
if (style & wxYES_NO)
{
if ( style & wxNO_DEFAULT )
{
defaultButtonTitle = cfNoString;
alternateButtonTitle = cfYesString;
buttonId[0] = wxID_NO;
buttonId[1] = wxID_YES;
}
else
{
defaultButtonTitle = cfYesString;
alternateButtonTitle = cfNoString;
buttonId[0] = wxID_YES;
buttonId[1] = wxID_NO;
}
if (style & wxCANCEL)
{
otherButtonTitle = cfCancelString;
buttonId[2] = wxID_CANCEL;
}
}
else
{
// the MSW implementation even shows an OK button if it is not specified, we'll do the same
buttonId[0] = wxID_OK;
// using null as default title does not work on earlier systems
defaultButtonTitle = cfOKString;
if (style & wxCANCEL)
{
alternateButtonTitle = cfCancelString;
buttonId[1] = wxID_CANCEL;
}
}
CFOptionFlags exitButton;
OSStatus err = CFUserNotificationDisplayAlert(
0, alertType, NULL, NULL, NULL, cfTitle, cfText,
defaultButtonTitle, alternateButtonTitle, otherButtonTitle, &exitButton );
if (err == noErr)
resultbutton = buttonId[exitButton];
}
else
{
short result;
AlertStdCFStringAlertParamRec param;
wxCFStringRef cfNoString( m_no.c_str(), GetFont().GetEncoding() );
wxCFStringRef cfYesString( m_yes.c_str(), GetFont().GetEncoding() );
wxCFStringRef cfOKString( m_ok.c_str(), GetFont().GetEncoding() );
wxCFStringRef cfCancelString( m_cancel.c_str(), GetFont().GetEncoding() );
wxCFStringRef cfTitle( msgtitle, GetFont().GetEncoding() );
wxCFStringRef cfText( msgtext, GetFont().GetEncoding() );
param.movable = true;
param.flags = 0;
param.version = kStdCFStringAlertVersionOne;
bool skipDialog = false;
if (style & wxYES_NO)
{
if (style & wxCANCEL)
{
param.defaultText = cfYesString;
param.cancelText = cfCancelString;
param.otherText = cfNoString;
param.helpButton = false;
param.defaultButton = style & wxNO_DEFAULT ? kAlertStdAlertOtherButton : kAlertStdAlertOKButton;
param.cancelButton = kAlertStdAlertCancelButton;
}
else
{
param.defaultText = cfYesString;
param.cancelText = NULL;
param.otherText = cfNoString;
param.helpButton = false;
param.defaultButton = style & wxNO_DEFAULT ? kAlertStdAlertOtherButton : kAlertStdAlertOKButton;
param.cancelButton = 0;
}
}
// the MSW implementation even shows an OK button if it is not specified, we'll do the same
else
{
if (style & wxCANCEL)
{
// that's a cancel missing
param.defaultText = cfOKString;
param.cancelText = cfCancelString;
param.otherText = NULL;
param.helpButton = false;
param.defaultButton = kAlertStdAlertOKButton;
param.cancelButton = 0;
}
else
{
param.defaultText = cfOKString;
param.cancelText = NULL;
param.otherText = NULL;
param.helpButton = false;
param.defaultButton = kAlertStdAlertOKButton;
param.cancelButton = 0;
}
}
param.position = kWindowDefaultPosition;
if ( !skipDialog )
{
DialogRef alertRef;
CreateStandardAlert( alertType, cfTitle, cfText, &param, &alertRef );
RunStandardAlert( alertRef, NULL, &result );
}
else
{
return wxID_CANCEL;
}
if (style & wxOK)
{
switch ( result )
{
case 1:
resultbutton = wxID_OK;
break;
case 2:
// TODO: add Cancel button
// if (style & wxCANCEL)
// resultbutton = wxID_CANCEL;
break;
case 3:
default:
break;
}
}
else if (style & wxYES_NO)
{
switch ( result )
{
case 1:
resultbutton = wxID_YES;
break;
case 2:
if (!(style & wxCANCEL))
resultbutton = wxID_CANCEL;
break;
case 3:
resultbutton = wxID_NO;
break;
default:
break;
}
}
}
return resultbutton;
}

File diff suppressed because it is too large Load Diff

621
src/osx/carbon/notebmac.cpp Normal file
View File

@@ -0,0 +1,621 @@
///////////////////////////////////////////////////////////////////////////////
// Name: src/mac/carbon/notebmac.cpp
// Purpose: implementation of wxNotebook
// Author: Stefan Csomor
// Modified by:
// Created: 1998-01-01
// RCS-ID: $Id$
// Copyright: (c) Stefan Csomor
// Licence: wxWindows licence
///////////////////////////////////////////////////////////////////////////////
#include "wx/wxprec.h"
#if wxUSE_NOTEBOOK
#include "wx/notebook.h"
#ifndef WX_PRECOMP
#include "wx/string.h"
#include "wx/log.h"
#include "wx/app.h"
#include "wx/image.h"
#endif
#include "wx/string.h"
#include "wx/imaglist.h"
#include "wx/mac/uma.h"
// check that the page index is valid
#define IS_VALID_PAGE(nPage) ((nPage) < GetPageCount())
DEFINE_EVENT_TYPE(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED)
DEFINE_EVENT_TYPE(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGING)
BEGIN_EVENT_TABLE(wxNotebook, wxBookCtrlBase)
EVT_NOTEBOOK_PAGE_CHANGED(wxID_ANY, wxNotebook::OnSelChange)
EVT_SIZE(wxNotebook::OnSize)
EVT_SET_FOCUS(wxNotebook::OnSetFocus)
EVT_NAVIGATION_KEY(wxNotebook::OnNavigationKey)
END_EVENT_TABLE()
IMPLEMENT_DYNAMIC_CLASS(wxNotebook, wxBookCtrlBase)
IMPLEMENT_DYNAMIC_CLASS(wxNotebookEvent, wxCommandEvent)
// common part of all ctors
void wxNotebook::Init()
{
m_nSelection = -1;
}
// default for dynamic class
wxNotebook::wxNotebook()
{
Init();
}
// the same arguments as for wxControl
wxNotebook::wxNotebook( wxWindow *parent,
wxWindowID id,
const wxPoint& pos,
const wxSize& size,
long style,
const wxString& name )
{
Init();
Create( parent, id, pos, size, style, name );
}
bool wxNotebook::Create( wxWindow *parent,
wxWindowID id,
const wxPoint& pos,
const wxSize& size,
long style,
const wxString& name )
{
m_macIsUserPane = false ;
if (! (style & wxBK_ALIGN_MASK))
style |= wxBK_TOP;
if ( !wxNotebookBase::Create( parent, id, pos, size, style, name ) )
return false;
Rect bounds = wxMacGetBoundsForControl( this, pos, size );
if ( bounds.right <= bounds.left )
bounds.right = bounds.left + 100;
if ( bounds.bottom <= bounds.top )
bounds.bottom = bounds.top + 100;
UInt16 tabstyle = kControlTabDirectionNorth;
if ( HasFlag(wxBK_LEFT) )
tabstyle = kControlTabDirectionWest;
else if ( HasFlag( wxBK_RIGHT ) )
tabstyle = kControlTabDirectionEast;
else if ( HasFlag( wxBK_BOTTOM ) )
tabstyle = kControlTabDirectionSouth;
ControlTabSize tabsize;
switch (GetWindowVariant())
{
case wxWINDOW_VARIANT_MINI:
tabsize = 3 ;
break;
case wxWINDOW_VARIANT_SMALL:
tabsize = kControlTabSizeSmall;
break;
default:
tabsize = kControlTabSizeLarge;
break;
}
m_peer = new wxMacControl( this );
OSStatus err = CreateTabsControl(
MAC_WXHWND(parent->MacGetTopLevelWindowRef()), &bounds,
tabsize, tabstyle, 0, NULL, m_peer->GetControlRefAddr() );
verify_noerr( err );
MacPostControlCreate( pos, size );
return true ;
}
// dtor
wxNotebook::~wxNotebook()
{
}
// ----------------------------------------------------------------------------
// wxNotebook accessors
// ----------------------------------------------------------------------------
void wxNotebook::SetPadding(const wxSize& WXUNUSED(padding))
{
// unsupported by OS
}
void wxNotebook::SetTabSize(const wxSize& WXUNUSED(sz))
{
// unsupported by OS
}
void wxNotebook::SetPageSize(const wxSize& size)
{
SetSize( CalcSizeFromPage( size ) );
}
wxSize wxNotebook::CalcSizeFromPage(const wxSize& sizePage) const
{
return DoGetSizeFromClientSize( sizePage );
}
int wxNotebook::DoSetSelection(size_t nPage, int flags)
{
wxCHECK_MSG( IS_VALID_PAGE(nPage), wxNOT_FOUND, wxT("DoSetSelection: invalid notebook page") );
if ( m_nSelection == wxNOT_FOUND || nPage != (size_t)m_nSelection )
{
if ( flags & SetSelection_SendEvent )
{
if ( !SendPageChangingEvent(nPage) )
{
// vetoed by program
return m_nSelection;
}
//else: program allows the page change
SendPageChangedEvent(m_nSelection, nPage);
}
ChangePage(m_nSelection, nPage);
}
//else: no change
return m_nSelection;
}
bool wxNotebook::SetPageText(size_t nPage, const wxString& strText)
{
wxCHECK_MSG( IS_VALID_PAGE(nPage), false, wxT("SetPageText: invalid notebook page") );
wxNotebookPage *page = m_pages[nPage];
page->SetLabel(wxStripMenuCodes(strText));
MacSetupTabs();
return true;
}
wxString wxNotebook::GetPageText(size_t nPage) const
{
wxCHECK_MSG( IS_VALID_PAGE(nPage), wxEmptyString, wxT("GetPageText: invalid notebook page") );
wxNotebookPage *page = m_pages[nPage];
return page->GetLabel();
}
int wxNotebook::GetPageImage(size_t nPage) const
{
wxCHECK_MSG( IS_VALID_PAGE(nPage), wxNOT_FOUND, wxT("GetPageImage: invalid notebook page") );
return m_images[nPage];
}
bool wxNotebook::SetPageImage(size_t nPage, int nImage)
{
wxCHECK_MSG( IS_VALID_PAGE(nPage), false,
wxT("SetPageImage: invalid notebook page") );
wxCHECK_MSG( m_imageList && nImage < m_imageList->GetImageCount(), false,
wxT("SetPageImage: invalid image index") );
if ( nImage != m_images[nPage] )
{
// if the item didn't have an icon before or, on the contrary, did have
// it but has lost it now, its size will change - but if the icon just
// changes, it won't
m_images[nPage] = nImage;
MacSetupTabs() ;
}
return true;
}
// ----------------------------------------------------------------------------
// wxNotebook operations
// ----------------------------------------------------------------------------
// remove one page from the notebook, without deleting the window
wxNotebookPage* wxNotebook::DoRemovePage(size_t nPage)
{
wxCHECK_MSG( IS_VALID_PAGE(nPage), NULL,
wxT("DoRemovePage: invalid notebook page") );
wxNotebookPage* page = m_pages[nPage] ;
m_pages.RemoveAt(nPage);
MacSetupTabs();
if (m_nSelection >= (int)GetPageCount())
m_nSelection = GetPageCount() - 1;
if (m_nSelection >= 0)
m_pages[m_nSelection]->Show(true);
InvalidateBestSize();
return page;
}
// remove all pages
bool wxNotebook::DeleteAllPages()
{
WX_CLEAR_ARRAY(m_pages) ;
MacSetupTabs();
m_nSelection = -1 ;
InvalidateBestSize();
return true;
}
// same as AddPage() but does it at given position
bool wxNotebook::InsertPage(size_t nPage,
wxNotebookPage *pPage,
const wxString& strText,
bool bSelect,
int imageId )
{
if ( !wxNotebookBase::InsertPage( nPage, pPage, strText, bSelect, imageId ) )
return false;
wxASSERT_MSG( pPage->GetParent() == this, wxT("notebook pages must have notebook as parent") );
// don't show pages by default (we'll need to adjust their size first)
pPage->Show( false ) ;
pPage->SetLabel( wxStripMenuCodes(strText) );
m_images.Insert( imageId, nPage );
MacSetupTabs();
wxRect rect = GetPageRect() ;
pPage->SetSize( rect );
if ( pPage->GetAutoLayout() )
pPage->Layout();
// now deal with the selection
// ---------------------------
// if the inserted page is before the selected one, we must update the
// index of the selected page
if ( int(nPage) <= m_nSelection )
{
m_nSelection++;
// while this still is the same page showing, we need to update the tabs
m_peer->SetValue( m_nSelection + 1 ) ;
}
// some page should be selected: either this one or the first one if there
// is still no selection
int selNew = -1;
if ( bSelect )
selNew = nPage;
else if ( m_nSelection == -1 )
selNew = 0;
if ( selNew != -1 )
SetSelection( selNew );
InvalidateBestSize();
return true;
}
int wxNotebook::HitTest(const wxPoint& pt, long * flags) const
{
int resultV = wxNOT_FOUND;
const int countPages = GetPageCount();
// we have to convert from Client to Window relative coordinates
wxPoint adjustedPt = pt + GetClientAreaOrigin();
// and now to HIView native ones
adjustedPt.x -= MacGetLeftBorderSize() ;
adjustedPt.y -= MacGetTopBorderSize() ;
HIPoint hipoint= { adjustedPt.x , adjustedPt.y } ;
HIViewPartCode outPart = 0 ;
OSStatus err = HIViewGetPartHit( m_peer->GetControlRef(), &hipoint, &outPart );
int max = m_peer->GetMaximum() ;
if ( outPart == 0 && max > 0 )
{
// this is a hack, as unfortunately a hit on an already selected tab returns 0,
// so we have to go some extra miles to make sure we select something different
// and try again ..
int val = m_peer->GetValue() ;
int maxval = max ;
if ( max == 1 )
{
m_peer->SetMaximum( 2 ) ;
maxval = 2 ;
}
if ( val == 1 )
m_peer->SetValue( maxval ) ;
else
m_peer->SetValue( 1 ) ;
err = HIViewGetPartHit( m_peer->GetControlRef(), &hipoint, &outPart );
m_peer->SetValue( val ) ;
if ( max == 1 )
m_peer->SetMaximum( 1 ) ;
}
if ( outPart >= 1 && outPart <= countPages )
resultV = outPart - 1 ;
if (flags != NULL)
{
*flags = 0;
// we cannot differentiate better
if (resultV >= 0)
*flags |= wxBK_HITTEST_ONLABEL;
else
*flags |= wxBK_HITTEST_NOWHERE;
}
return resultV;
}
// Added by Mark Newsam
// When a page is added or deleted to the notebook this function updates
// information held in the control so that it matches the order
// the user would expect.
//
void wxNotebook::MacSetupTabs()
{
m_peer->SetMaximum( GetPageCount() ) ;
wxNotebookPage *page;
ControlTabInfoRecV1 info;
const size_t countPages = GetPageCount();
for (size_t ii = 0; ii < countPages; ii++)
{
page = m_pages[ii];
info.version = kControlTabInfoVersionOne;
info.iconSuiteID = 0;
wxCFStringRef cflabel( page->GetLabel(), GetFont().GetEncoding() ) ;
info.name = cflabel ;
m_peer->SetData<ControlTabInfoRecV1>( ii + 1, kControlTabInfoTag, &info ) ;
if ( GetImageList() && GetPageImage(ii) >= 0 )
{
const wxBitmap bmap = GetImageList()->GetBitmap( GetPageImage( ii ) ) ;
if ( bmap.Ok() )
{
ControlButtonContentInfo info ;
wxMacCreateBitmapButton( &info, bmap ) ;
OSStatus err = m_peer->SetData<ControlButtonContentInfo>( ii + 1, kControlTabImageContentTag, &info );
if ( err != noErr )
{
wxFAIL_MSG("Error when setting icon on tab");
}
wxMacReleaseBitmapButton( &info ) ;
}
}
m_peer->SetTabEnabled( ii + 1, true ) ;
}
Refresh();
}
wxRect wxNotebook::GetPageRect() const
{
wxSize size = GetClientSize() ;
return wxRect( 0 , 0 , size.x , size.y ) ;
}
// ----------------------------------------------------------------------------
// wxNotebook callbacks
// ----------------------------------------------------------------------------
// @@@ OnSize() is used for setting the font when it's called for the first
// time because doing it in ::Create() doesn't work (for unknown reasons)
void wxNotebook::OnSize(wxSizeEvent& event)
{
unsigned int nCount = m_pages.Count();
wxRect rect = GetPageRect() ;
for ( unsigned int nPage = 0; nPage < nCount; nPage++ )
{
wxNotebookPage *pPage = m_pages[nPage];
pPage->SetSize(rect);
if ( pPage->GetAutoLayout() )
pPage->Layout();
}
// Processing continues to next OnSize
event.Skip();
}
void wxNotebook::OnSelChange(wxNotebookEvent& event)
{
// is it our tab control?
if ( event.GetEventObject() == this )
ChangePage(event.GetOldSelection(), event.GetSelection());
// we want to give others a chance to process this message as well
event.Skip();
}
void wxNotebook::OnSetFocus(wxFocusEvent& event)
{
// set focus to the currently selected page if any
if ( m_nSelection != -1 )
m_pages[m_nSelection]->SetFocus();
event.Skip();
}
void wxNotebook::OnNavigationKey(wxNavigationKeyEvent& event)
{
if ( event.IsWindowChange() )
{
// change pages
AdvanceSelection( event.GetDirection() );
}
else
{
// we get this event in 2 cases
//
// a) one of our pages might have generated it because the user TABbed
// out from it in which case we should propagate the event upwards and
// our parent will take care of setting the focus to prev/next sibling
//
// or
//
// b) the parent panel wants to give the focus to us so that we
// forward it to our selected page. We can't deal with this in
// OnSetFocus() because we don't know which direction the focus came
// from in this case and so can't choose between setting the focus to
// first or last panel child
wxWindow *parent = GetParent();
// the cast is here to fix a GCC ICE
if ( ((wxWindow*)event.GetEventObject()) == parent )
{
// no, it doesn't come from child, case (b): forward to a page
if ( m_nSelection != -1 )
{
// so that the page knows that the event comes from it's parent
// and is being propagated downwards
event.SetEventObject( this );
wxWindow *page = m_pages[m_nSelection];
if ( !page->HandleWindowEvent( event ) )
{
page->SetFocus();
}
//else: page manages focus inside it itself
}
else
{
// we have no pages - still have to give focus to _something_
SetFocus();
}
}
else
{
// it comes from our child, case (a), pass to the parent
if ( parent )
{
event.SetCurrentFocus( this );
parent->HandleWindowEvent( event );
}
}
}
}
// ----------------------------------------------------------------------------
// wxNotebook base class virtuals
// ----------------------------------------------------------------------------
#if wxUSE_CONSTRAINTS
// override these 2 functions to do nothing: everything is done in OnSize
void wxNotebook::SetConstraintSizes(bool WXUNUSED(recurse))
{
// don't set the sizes of the pages - their correct size is not yet known
wxControl::SetConstraintSizes( false );
}
bool wxNotebook::DoPhase(int WXUNUSED(nPhase))
{
return true;
}
#endif // wxUSE_CONSTRAINTS
void wxNotebook::Command(wxCommandEvent& WXUNUSED(event))
{
wxFAIL_MSG(wxT("wxNotebook::Command not implemented"));
}
// ----------------------------------------------------------------------------
// wxNotebook helper functions
// ----------------------------------------------------------------------------
// hide the currently active panel and show the new one
void wxNotebook::ChangePage(int nOldSel, int nSel)
{
if (nOldSel == nSel)
return;
if ( nOldSel != -1 )
m_pages[nOldSel]->Show( false );
if ( nSel != -1 )
{
wxNotebookPage *pPage = m_pages[nSel];
pPage->Show( true );
pPage->SetFocus();
}
m_nSelection = nSel;
m_peer->SetValue( m_nSelection + 1 ) ;
}
wxInt32 wxNotebook::MacControlHit(WXEVENTHANDLERREF WXUNUSED(handler) , WXEVENTREF WXUNUSED(event) )
{
OSStatus status = eventNotHandledErr ;
SInt32 newSel = m_peer->GetValue() - 1 ;
if ( newSel != m_nSelection )
{
wxNotebookEvent changing(
wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGING, m_windowId,
newSel , m_nSelection );
changing.SetEventObject( this );
HandleWindowEvent( changing );
if ( changing.IsAllowed() )
{
wxNotebookEvent event(
wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED, m_windowId,
newSel, m_nSelection );
event.SetEventObject( this );
HandleWindowEvent( event );
}
else
{
m_peer->SetValue( m_nSelection + 1 ) ;
}
status = noErr ;
}
return (wxInt32)status ;
}
#endif

185
src/osx/carbon/overlay.cpp Normal file
View File

@@ -0,0 +1,185 @@
/////////////////////////////////////////////////////////////////////////////
// Name: src/mac/carbon/overlay.cpp
// Purpose: common wxOverlay code
// Author: Stefan Csomor
// Modified by:
// Created: 2006-10-20
// RCS-ID: $Id$
// Copyright: (c) wxWidgets team
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
// ============================================================================
// declarations
// ============================================================================
// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------
// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#include "wx/overlay.h"
#ifndef WX_PRECOMP
#include "wx/dcclient.h"
#endif
#include "wx/private/overlay.h"
#ifdef wxHAS_NATIVE_OVERLAY
// ============================================================================
// implementation
// ============================================================================
wxOverlayImpl::wxOverlayImpl()
{
m_window = NULL ;
m_overlayContext = NULL ;
m_overlayWindow = NULL ;
}
wxOverlayImpl::~wxOverlayImpl()
{
Reset();
}
bool wxOverlayImpl::IsOk()
{
return m_overlayWindow != NULL ;
}
void wxOverlayImpl::MacGetBounds( Rect *bounds )
{
int x, y;
x=y=0;
m_window->MacWindowToRootWindow( &x , &y ) ;
WindowRef window = (WindowRef) m_window->MacGetTopLevelWindowRef() ;
Point localwhere = { y, x };
wxMacLocalToGlobal( window, &localwhere ) ;
bounds->top = localwhere.v+m_y;
bounds->left = localwhere.h+m_x;
bounds->bottom = localwhere.v+m_y+m_height;
bounds->right = localwhere.h+m_x+m_width;
}
OSStatus wxOverlayImpl::CreateOverlayWindow()
{
OSStatus err;
WindowAttributes overlayAttributes = kWindowIgnoreClicksAttribute;
if ( m_window )
{
m_overlayParentWindow =(WindowRef) m_window->MacGetTopLevelWindowRef();
Rect bounds ;
MacGetBounds(&bounds);
err = CreateNewWindow( kOverlayWindowClass, overlayAttributes, &bounds, &m_overlayWindow );
if ( err == noErr )
{
SetWindowGroup( m_overlayWindow, GetWindowGroup(m_overlayParentWindow)); // Put them in the same group so that their window layers are consistent
}
}
else
{
m_overlayParentWindow = NULL ;
CGRect cgbounds ;
cgbounds = CGDisplayBounds(CGMainDisplayID());
Rect bounds;
bounds.top = (short)cgbounds.origin.y;
bounds.left = (short)cgbounds.origin.x;
bounds.bottom = (short)(bounds.top + cgbounds.size.height);
bounds.right = (short)(bounds.left + cgbounds.size.width);
err = CreateNewWindow( kOverlayWindowClass, overlayAttributes, &bounds, &m_overlayWindow );
}
ShowWindow(m_overlayWindow);
return err;
}
void wxOverlayImpl::Init( wxDC* dc, int x , int y , int width , int height )
{
wxASSERT_MSG( !IsOk() , _("You cannot Init an overlay twice") );
m_window = dc->GetWindow();
m_x = x ;
m_y = y ;
if ( dc->IsKindOf( CLASSINFO( wxClientDC ) ))
{
wxPoint origin = m_window->GetClientAreaOrigin();
m_x += origin.x;
m_y += origin.y;
}
m_width = width ;
m_height = height ;
OSStatus err = CreateOverlayWindow();
wxASSERT_MSG( err == noErr , _("Couldn't create the overlay window") );
#ifndef __LP64__
err = QDBeginCGContext(GetWindowPort(m_overlayWindow), &m_overlayContext);
#endif
CGContextTranslateCTM( m_overlayContext, 0, m_height );
CGContextScaleCTM( m_overlayContext, 1, -1 );
CGContextTranslateCTM( m_overlayContext, -m_x , -m_y );
wxASSERT_MSG( err == noErr , _("Couldn't init the context on the overlay window") );
}
void wxOverlayImpl::BeginDrawing( wxDC* dc)
{
wxDCImpl *impl = dc->GetImpl();
wxGCDCImpl *win_impl = wxDynamicCast(impl,wxGCDCImpl);
if (win_impl)
{
win_impl->SetGraphicsContext( wxGraphicsContext::CreateFromNative( m_overlayContext ) );
dc->SetClippingRegion( m_x , m_y , m_width , m_height ) ;
}
}
void wxOverlayImpl::EndDrawing( wxDC* dc)
{
wxDCImpl *impl = dc->GetImpl();
wxGCDCImpl *win_impl = wxDynamicCast(impl,wxGCDCImpl);
if (win_impl)
win_impl->SetGraphicsContext(NULL);
CGContextFlush( m_overlayContext );
}
void wxOverlayImpl::Clear(wxDC* WXUNUSED(dc))
{
wxASSERT_MSG( IsOk() , _("You cannot Clear an overlay that is not inited") );
CGRect box = CGRectMake( m_x - 1, m_y - 1 , m_width + 2 , m_height + 2 );
CGContextClearRect( m_overlayContext, box );
}
void wxOverlayImpl::Reset()
{
if ( m_overlayContext )
{
#ifndef __LP64__
OSStatus err = QDEndCGContext(GetWindowPort(m_overlayWindow), &m_overlayContext);
if ( err != noErr )
{
wxFAIL_MSG("Couldn't end the context on the overlay window");
}
#endif
m_overlayContext = NULL ;
}
// todo : don't dispose, only hide and reposition on next run
if (m_overlayWindow)
{
DisposeWindow(m_overlayWindow);
m_overlayWindow = NULL ;
}
}
#endif // wxHAS_NATIVE_OVERLAY

155
src/osx/carbon/palette.cpp Normal file
View File

@@ -0,0 +1,155 @@
/////////////////////////////////////////////////////////////////////////////
// Name: src/mac/carbon/palette.cpp
// Purpose: wxPalette
// Author: Stefan Csomor
// Modified by:
// Created: 1998-01-01
// RCS-ID: $Id$
// Copyright: (c) Stefan Csomor
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
#include "wx/wxprec.h"
#if wxUSE_PALETTE
#include "wx/palette.h"
#include "wx/colour.h"
IMPLEMENT_DYNAMIC_CLASS(wxPalette, wxGDIObject)
// ============================================================================
// wxPaletteRefData
// ============================================================================
class WXDLLEXPORT wxPaletteRefData: public wxGDIRefData
{
public:
wxPaletteRefData();
wxPaletteRefData(const wxPaletteRefData& data);
virtual ~wxPaletteRefData();
virtual bool IsOk() const { return m_count > 0; }
protected:
wxColour* m_palette;
wxInt32 m_count;
friend class WXDLLIMPEXP_FWD_CORE wxPalette;
DECLARE_NO_ASSIGN_CLASS(wxPaletteRefData)
};
wxPaletteRefData::wxPaletteRefData()
{
m_palette = NULL;
m_count = 0;
}
wxPaletteRefData::wxPaletteRefData(const wxPaletteRefData& data)
{
m_count = data.m_count;
m_palette = new wxColour[m_count];
for ( wxInt32 i = 0; i < m_count; i++ )
m_palette[i] = data.m_palette[i];
}
wxPaletteRefData::~wxPaletteRefData()
{
delete[] m_palette;
}
// ============================================================================
// wxPalette
// ============================================================================
wxPalette::wxPalette()
{
}
wxPalette::wxPalette(int n, const unsigned char *red, const unsigned char *green, const unsigned char *blue)
{
Create(n, red, green, blue);
}
wxPalette::~wxPalette()
{
}
bool wxPalette::Create(int n, const unsigned char *red, const unsigned char *green, const unsigned char *blue)
{
UnRef();
m_refData = new wxPaletteRefData;
M_PALETTEDATA->m_count = n ;
M_PALETTEDATA->m_palette = new wxColour[n] ;
for ( int i = 0 ; i < n ; ++i)
{
M_PALETTEDATA->m_palette[i].Set( red[i] , green[i] , blue[i] ) ;
}
return false;
}
int wxPalette::GetPixel(unsigned char red, unsigned char green, unsigned char blue) const
{
if ( !m_refData )
return wxNOT_FOUND;
long bestdiff = 3 * 256 ;
long bestpos = 0 ;
long currentdiff ;
for ( int i = 0 ; i < M_PALETTEDATA->m_count ; ++i )
{
const wxColour& col = M_PALETTEDATA->m_palette[i] ;
currentdiff = abs ( col.Red() - red ) + abs( col.Green() - green ) + abs ( col.Blue() - blue ) ;
if ( currentdiff < bestdiff )
{
bestdiff = currentdiff ;
bestpos = i ;
if ( bestdiff == 0 )
break ;
}
}
return bestpos;
}
bool wxPalette::GetRGB(int index, unsigned char *red, unsigned char *green, unsigned char *blue) const
{
if ( !m_refData )
return false;
if (index < 0 || index >= M_PALETTEDATA->m_count)
return false;
const wxColour& col = M_PALETTEDATA->m_palette[index] ;
*red = col.Red() ;
*green = col.Green() ;
*blue = col.Blue() ;
return true;
}
int wxPalette::GetColoursCount() const
{
if (m_refData)
return M_PALETTEDATA->m_count;
return 0;
}
wxGDIRefData *wxPalette::CreateGDIRefData() const
{
return new wxPaletteRefData;
}
wxGDIRefData *wxPalette::CloneGDIRefData(const wxGDIRefData *data) const
{
return new wxPaletteRefData(*wx_static_cast(const wxPaletteRefData *, data));
}
#endif // wxUSE_PALETTE

308
src/osx/carbon/pen.cpp Normal file
View File

@@ -0,0 +1,308 @@
/////////////////////////////////////////////////////////////////////////////
// Name: src/mac/carbon/pen.cpp
// Purpose: wxPen
// Author: Stefan Csomor
// Modified by:
// Created: 1998-01-01
// RCS-ID: $Id$
// Copyright: (c) Stefan Csomor
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
#include "wx/wxprec.h"
#include "wx/pen.h"
#ifndef WX_PRECOMP
#include "wx/utils.h"
#endif
IMPLEMENT_DYNAMIC_CLASS(wxPen, wxGDIObject)
class WXDLLEXPORT wxPenRefData : public wxGDIRefData
{
public:
wxPenRefData();
wxPenRefData(const wxPenRefData& data);
virtual ~wxPenRefData();
wxPenRefData& operator=(const wxPenRefData& data);
bool operator==(const wxPenRefData& data) const
{
// we intentionally don't compare m_hPen fields here
return m_style == data.m_style &&
m_width == data.m_width &&
m_join == data.m_join &&
m_cap == data.m_cap &&
m_colour == data.m_colour &&
(m_style != wxPENSTYLE_STIPPLE || m_stipple.IsSameAs(data.m_stipple)) &&
(m_style != wxPENSTYLE_USER_DASH ||
(m_nbDash == data.m_nbDash &&
memcmp(m_dash, data.m_dash, m_nbDash*sizeof(wxDash)) == 0));
}
protected:
int m_width;
wxPenStyle m_style;
wxPenJoin m_join ;
wxPenCap m_cap ;
wxBitmap m_stipple ;
int m_nbDash ;
wxDash * m_dash ;
wxColour m_colour;
/* TODO: implementation
WXHPEN m_hPen;
*/
friend class WXDLLIMPEXP_FWD_CORE wxPen;
};
wxPenRefData::wxPenRefData()
{
m_style = wxPENSTYLE_SOLID;
m_width = 1;
m_join = wxJOIN_ROUND ;
m_cap = wxCAP_ROUND ;
m_nbDash = 0 ;
m_dash = 0 ;
}
wxPenRefData::wxPenRefData(const wxPenRefData& data)
: wxGDIRefData()
{
m_style = data.m_style;
m_width = data.m_width;
m_join = data.m_join;
m_cap = data.m_cap;
m_nbDash = data.m_nbDash;
m_dash = data.m_dash;
m_colour = data.m_colour;
}
wxPenRefData::~wxPenRefData()
{
}
// Pens
#define M_PENDATA ((wxPenRefData *)m_refData)
wxPen::wxPen()
{
}
wxPen::~wxPen()
{
}
// Should implement Create
wxPen::wxPen(const wxColour& col, int Width, wxPenStyle Style)
{
m_refData = new wxPenRefData;
M_PENDATA->m_colour = col;
M_PENDATA->m_width = Width;
M_PENDATA->m_style = Style;
M_PENDATA->m_join = wxJOIN_ROUND ;
M_PENDATA->m_cap = wxCAP_ROUND ;
M_PENDATA->m_nbDash = 0 ;
M_PENDATA->m_dash = 0 ;
RealizeResource();
}
#if FUTURE_WXWIN_COMPATIBILITY_3_0
wxPen::wxPen(const wxColour& col, int Width, int Style)
{
m_refData = new wxPenRefData;
M_PENDATA->m_colour = col;
M_PENDATA->m_width = Width;
M_PENDATA->m_style = (wxPenStyle)Style;
M_PENDATA->m_join = wxJOIN_ROUND ;
M_PENDATA->m_cap = wxCAP_ROUND ;
M_PENDATA->m_nbDash = 0 ;
M_PENDATA->m_dash = 0 ;
RealizeResource();
}
#endif
wxPen::wxPen(const wxBitmap& stipple, int Width)
{
m_refData = new wxPenRefData;
M_PENDATA->m_stipple = stipple;
M_PENDATA->m_width = Width;
M_PENDATA->m_style = wxPENSTYLE_STIPPLE;
M_PENDATA->m_join = wxJOIN_ROUND ;
M_PENDATA->m_cap = wxCAP_ROUND ;
M_PENDATA->m_nbDash = 0 ;
M_PENDATA->m_dash = 0 ;
RealizeResource();
}
wxGDIRefData *wxPen::CreateGDIRefData() const
{
return new wxPenRefData;
}
wxGDIRefData *wxPen::CloneGDIRefData(const wxGDIRefData *data) const
{
return new wxPenRefData(*wx_static_cast(const wxPenRefData *, data));
}
bool wxPen::operator==(const wxPen& pen) const
{
const wxPenRefData *penData = (wxPenRefData *)pen.m_refData;
// an invalid pen is only equal to another invalid pen
return m_refData ? penData && *M_PENDATA == *penData : !penData;
}
wxColour wxPen::GetColour() const
{
wxCHECK_MSG( Ok(), wxNullColour, wxT("invalid pen") );
return M_PENDATA->m_colour;
}
int wxPen::GetWidth() const
{
wxCHECK_MSG( Ok(), -1, wxT("invalid pen") );
return M_PENDATA->m_width;
}
wxPenStyle wxPen::GetStyle() const
{
wxCHECK_MSG( Ok(), wxPENSTYLE_INVALID, wxT("invalid pen") );
return M_PENDATA->m_style;
}
wxPenJoin wxPen::GetJoin() const
{
wxCHECK_MSG( Ok(), wxJOIN_INVALID, wxT("invalid pen") );
return M_PENDATA->m_join;
}
wxPenCap wxPen::GetCap() const
{
wxCHECK_MSG( Ok(), wxCAP_INVALID, wxT("invalid pen") );
return M_PENDATA->m_cap;
}
int wxPen::GetDashes(wxDash **ptr) const
{
wxCHECK_MSG( Ok(), -1, wxT("invalid pen") );
*ptr = M_PENDATA->m_dash;
return M_PENDATA->m_nbDash;
}
wxBitmap *wxPen::GetStipple() const
{
wxCHECK_MSG( Ok(), NULL, wxT("invalid pen") );
return &M_PENDATA->m_stipple;
}
void wxPen::Unshare()
{
// Don't change shared data
if (!m_refData)
{
m_refData = new wxPenRefData();
}
else
{
wxPenRefData* ref = new wxPenRefData(*(wxPenRefData*)m_refData);
UnRef();
m_refData = ref;
}
}
void wxPen::SetColour(const wxColour& col)
{
Unshare();
M_PENDATA->m_colour = col;
RealizeResource();
}
void wxPen::SetColour(unsigned char r, unsigned char g, unsigned char b)
{
Unshare();
M_PENDATA->m_colour.Set(r, g, b);
RealizeResource();
}
void wxPen::SetWidth(int Width)
{
Unshare();
M_PENDATA->m_width = Width;
RealizeResource();
}
void wxPen::SetStyle(wxPenStyle Style)
{
Unshare();
M_PENDATA->m_style = Style;
RealizeResource();
}
void wxPen::SetStipple(const wxBitmap& Stipple)
{
Unshare();
M_PENDATA->m_stipple = Stipple;
M_PENDATA->m_style = wxPENSTYLE_STIPPLE;
RealizeResource();
}
void wxPen::SetDashes(int nb_dashes, const wxDash *Dash)
{
Unshare();
M_PENDATA->m_nbDash = nb_dashes;
M_PENDATA->m_dash = (wxDash *)Dash;
RealizeResource();
}
void wxPen::SetJoin(wxPenJoin Join)
{
Unshare();
M_PENDATA->m_join = Join;
RealizeResource();
}
void wxPen::SetCap(wxPenCap Cap)
{
Unshare();
M_PENDATA->m_cap = Cap;
RealizeResource();
}
bool wxPen::RealizeResource()
{
// nothing to do here for mac
return true;
}

View File

@@ -0,0 +1,59 @@
///////////////////////////////////////////////////////////////////////////////
// Name: src/mac/popupwin.cpp
// Purpose: implements wxPopupWindow for wxMac
// Author: Stefan Csomor
// Modified by:
// Created:
// RCS-ID: $Id$
// Copyright: (c) 2006 Stefan Csomor
// License: wxWindows licence
///////////////////////////////////////////////////////////////////////////////
// ============================================================================
// declarations
// ============================================================================
// CAUTION : This is only experimental stuff right now
// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------
// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#if wxUSE_POPUPWIN
#ifndef WX_PRECOMP
#endif //WX_PRECOMP
#include "wx/popupwin.h"
#include "wx/tooltip.h"
#include "wx/mac/private.h"
// ============================================================================
// implementation
// ============================================================================
wxPopupWindow::~wxPopupWindow()
{
}
bool wxPopupWindow::Create(wxWindow *parent, int flags)
{
// popup windows are created hidden by default
Hide();
return wxPopupWindowBase::Create(parent) &&
wxNonOwnedWindow::Create(parent, wxID_ANY,
wxDefaultPosition, wxDefaultSize,
flags | wxPOPUP_WINDOW);
}
#endif // #if wxUSE_POPUPWIN

292
src/osx/carbon/printdlg.cpp Normal file
View File

@@ -0,0 +1,292 @@
/////////////////////////////////////////////////////////////////////////////
// Name: src/mac/carbon/printdlg.cpp
// Purpose: wxPrintDialog, wxPageSetupDialog
// Author: Stefan Csomor
// Modified by:
// Created: 1998-01-01
// RCS-ID: $Id$
// Copyright: (c) Stefan Csomor
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
#include "wx/wxprec.h"
#if wxUSE_PRINTING_ARCHITECTURE
#include "wx/printdlg.h"
#ifndef WX_PRECOMP
#include "wx/object.h"
#include "wx/dcprint.h"
#include "wx/msgdlg.h"
#include "wx/textctrl.h"
#include "wx/sizer.h"
#include "wx/stattext.h"
#endif
#include "wx/mac/printdlg.h"
#include "wx/mac/private/print.h"
#include "wx/mac/private.h"
#include "wx/statline.h"
// Use generic page setup dialog: use your own native one if one exists.
IMPLEMENT_DYNAMIC_CLASS(wxMacPrintDialog, wxPrintDialogBase)
wxMacPrintDialog::wxMacPrintDialog()
{
m_dialogParent = NULL;
m_printerDC = NULL;
m_destroyDC = true;
}
wxMacPrintDialog::wxMacPrintDialog( wxWindow *p, wxPrintDialogData *data )
{
Create( p, data );
}
wxMacPrintDialog::wxMacPrintDialog( wxWindow *p, wxPrintData *data )
{
wxPrintDialogData data2;
if (data != NULL)
data2 = *data;
Create( p, &data2 );
}
bool wxMacPrintDialog::Create( wxWindow *p, wxPrintDialogData *data )
{
m_dialogParent = p;
m_printerDC = NULL;
m_destroyDC = true;
if (data != NULL)
m_printDialogData = *data;
return true;
}
wxMacPrintDialog::~wxMacPrintDialog()
{
if (m_destroyDC && m_printerDC)
{
delete m_printerDC;
m_printerDC = NULL;
}
}
int wxMacPrintDialog::ShowModal()
{
m_printDialogData.GetPrintData().ConvertToNative();
((wxMacCarbonPrintData*)m_printDialogData.GetPrintData().GetNativeData())->TransferFrom( &m_printDialogData );
int result = wxID_CANCEL;
#ifdef __LP64__
// TODO use NSPrintPanel
#else
OSErr err = noErr;
Boolean accepted;
err = PMSessionPrintDialog(
((wxMacCarbonPrintData*)m_printDialogData.GetPrintData().GetNativeData())->m_macPrintSession,
((wxMacCarbonPrintData*)m_printDialogData.GetPrintData().GetNativeData())->m_macPrintSettings,
((wxMacCarbonPrintData*)m_printDialogData.GetPrintData().GetNativeData())->m_macPageFormat,
&accepted );
if ((err == noErr) && !accepted)
{
// user clicked Cancel button
err = kPMCancel;
}
if (err == noErr)
{
result = wxID_OK;
}
if ((err != noErr) && (err != kPMCancel))
{
wxString message;
message.Printf( wxT("Print Error %d"), err );
wxMessageDialog dialog( NULL, message, wxEmptyString, wxICON_HAND | wxOK );
dialog.ShowModal();
}
if (result == wxID_OK)
{
m_printDialogData.GetPrintData().ConvertFromNative();
((wxMacCarbonPrintData*)m_printDialogData.GetPrintData().GetNativeData())->TransferTo( &m_printDialogData );
}
#endif
return result;
}
wxDC *wxMacPrintDialog::GetPrintDC()
{
return new wxPrinterDC( m_printDialogData.GetPrintData() );
}
IMPLEMENT_CLASS(wxMacPageSetupDialog, wxPageSetupDialogBase)
wxMacPageSetupDialog::wxMacPageSetupDialog( wxWindow *p, wxPageSetupData *data )
: wxPageSetupDialogBase()
{
Create( p, data );
}
bool wxMacPageSetupDialog::Create( wxWindow *p, wxPageSetupData *data )
{
m_dialogParent = p;
if (data != NULL)
m_pageSetupData = (*data);
return true;
}
wxMacPageSetupDialog::~wxMacPageSetupDialog()
{
}
wxPageSetupData& wxMacPageSetupDialog::GetPageSetupDialogData()
{
return m_pageSetupData;
}
int wxMacPageSetupDialog::ShowModal()
{
m_pageSetupData.GetPrintData().ConvertToNative();
((wxMacCarbonPrintData*)m_pageSetupData.GetPrintData().GetNativeData())->TransferFrom( &m_pageSetupData );
int result = wxID_CANCEL;
#ifdef __LP64__
#else
OSErr err = noErr;
Boolean accepted;
err = PMSessionPageSetupDialog(
((wxMacCarbonPrintData*)m_pageSetupData.GetPrintData().GetNativeData())->m_macPrintSession,
((wxMacCarbonPrintData*)m_pageSetupData.GetPrintData().GetNativeData())->m_macPageFormat,
&accepted );
if ((err == noErr) && !accepted)
{
// user clicked Cancel button
err = kPMCancel;
}
// If the user did not cancel, flatten and save the PageFormat object
// with our document.
if (err == noErr)
{
result = wxID_OK;
}
if ((err != noErr) && (err != kPMCancel))
{
wxString message;
message.Printf( wxT("Print Error %d"), err );
wxMessageDialog dialog( NULL, message, wxEmptyString, wxICON_HAND | wxOK );
dialog.ShowModal();
}
if (result == wxID_OK)
{
m_pageSetupData.GetPrintData().ConvertFromNative();
m_pageSetupData.SetPaperSize( m_pageSetupData.GetPrintData().GetPaperSize() );
((wxMacCarbonPrintData*)m_pageSetupData.GetPrintData().GetNativeData())->TransferTo( &m_pageSetupData );
}
#endif
return result;
}
IMPLEMENT_CLASS(wxMacPageMarginsDialog, wxDialog)
wxMacPageMarginsDialog::wxMacPageMarginsDialog(wxFrame *parent, wxPageSetupData *data) :
wxDialog(parent, wxID_ANY, wxString(wxT("Page Margins"))),
m_pageSetupDialogData(data)
{
GetMinMargins();
wxBoxSizer *colSizer = new wxBoxSizer(wxVERTICAL);
wxFlexGridSizer *gridSizer = new wxFlexGridSizer(4, 5, 5);
colSizer->Add(gridSizer, wxSizerFlags().Border(wxALL, 5));
gridSizer->Add(new wxStaticText(this, wxID_ANY, wxT("Left (mm):")), wxSizerFlags().Right());
gridSizer->Add(m_LeftMargin = new wxTextCtrl(this, wxID_ANY), wxSizerFlags().Left());
gridSizer->Add(new wxStaticText(this, wxID_ANY, wxT("Top (mm):")), wxSizerFlags().Right());
gridSizer->Add(m_TopMargin = new wxTextCtrl(this, wxID_ANY), wxSizerFlags().Left());
gridSizer->Add(new wxStaticText(this, wxID_ANY, wxT("Right (mm):")), wxSizerFlags().Right());
gridSizer->Add(m_RightMargin = new wxTextCtrl(this, wxID_ANY), wxSizerFlags().Left());
gridSizer->Add(new wxStaticText(this, wxID_ANY, wxT("Bottom (mm):")), wxSizerFlags().Right());
gridSizer->Add(m_BottomMargin = new wxTextCtrl(this, wxID_ANY), wxSizerFlags().Left());
colSizer->Add(new wxStaticLine(this), wxSizerFlags().Expand().Border(wxTOP|wxBOTTOM, 5));
colSizer->Add(CreateButtonSizer(wxOK | wxCANCEL), wxSizerFlags().Expand().Border(wxALL, 5));
TransferToWindow();
SetSizerAndFit(colSizer);
Center(wxBOTH);
}
bool wxMacPageMarginsDialog::TransferToWindow()
{
wxASSERT(m_pageSetupDialogData);
wxPoint topLeft = m_pageSetupDialogData->GetMarginTopLeft();
wxPoint bottomRight = m_pageSetupDialogData->GetMarginBottomRight();
wxPoint minTopLeft = m_pageSetupDialogData->GetMinMarginTopLeft();
wxPoint minBottomRight = m_pageSetupDialogData->GetMinMarginBottomRight();
m_LeftMargin->SetValue(wxString::Format(wxT("%d"), wxMax(topLeft.x, minTopLeft.x)));
m_LeftMargin->SetSelection(-1, -1);
m_TopMargin->SetValue(wxString::Format(wxT("%d"), wxMax(topLeft.y, minTopLeft.y)));
m_TopMargin->SetSelection(-1, -1);
m_RightMargin->SetValue(wxString::Format(wxT("%d"), wxMax(bottomRight.x, minBottomRight.x)));
m_RightMargin->SetSelection(-1, -1);
m_BottomMargin->SetValue(wxString::Format(wxT("%d"), wxMax(bottomRight.y, minBottomRight.y)));
m_BottomMargin->SetSelection(-1, -1);
m_LeftMargin->SetFocus();
return true;
}
bool wxMacPageMarginsDialog::TransferDataFromWindow()
{
wxPoint topLeft, bottomRight;
if (!CheckValue(m_LeftMargin, &topLeft.x, m_MinMarginTopLeft.x, wxT("left margin"))) return false;
if (!CheckValue(m_TopMargin, &topLeft.y, m_MinMarginTopLeft.y, wxT("top margin"))) return false;
if (!CheckValue(m_RightMargin, &bottomRight.x, m_MinMarginBottomRight.x, wxT("right margin"))) return false;
if (!CheckValue(m_BottomMargin, &bottomRight.y, m_MinMarginBottomRight.y, wxT("bottom margin"))) return false;
m_pageSetupDialogData->SetMarginTopLeft(topLeft);
m_pageSetupDialogData->SetMarginBottomRight(bottomRight);
return true;
}
bool wxMacPageMarginsDialog::CheckValue(wxTextCtrl* textCtrl, int *value, int minValue, const wxString& name)
{
long lvalue;
if (!textCtrl->GetValue().ToLong(&lvalue))
{
wxMessageBox(wxString::Format(wxT("Sorry, \"%s\" is not a valid numerical value for the %s"), textCtrl->GetValue().c_str(), name.c_str()), wxT("Page Margin Error"));
return false;
}
if (lvalue < minValue)
{
wxMessageBox(wxString::Format(wxT("Sorry, \"%s\" is not a valid value for the %s, which must be >= %d"), textCtrl->GetValue().c_str(), name.c_str(), minValue), wxT("Page Margin Error"));
textCtrl->SetValue(wxString::Format(wxT("%d"), minValue));
textCtrl->SetSelection(-1, -1);
textCtrl->SetFocus();
return false;
}
*value = int(lvalue);
return true;
}
void wxMacPageMarginsDialog::GetMinMargins()
{
m_MinMarginTopLeft = m_pageSetupDialogData->GetMinMarginTopLeft();
m_MinMarginBottomRight = m_pageSetupDialogData->GetMinMarginBottomRight();
}
#endif

620
src/osx/carbon/printmac.cpp Normal file
View File

@@ -0,0 +1,620 @@
/////////////////////////////////////////////////////////////////////////////
// Name: src/mac/carbon/printwin.cpp
// Purpose: wxMacPrinter framework
// Author: Julian Smart
// Modified by:
// Created: 04/01/98
// RCS-ID: $Id$
// Copyright: (c) Julian Smart
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"
#if wxUSE_PRINTING_ARCHITECTURE
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#ifndef WX_PRECOMP
#include "wx/utils.h"
#include "wx/dc.h"
#include "wx/app.h"
#include "wx/msgdlg.h"
#include "wx/dcprint.h"
#include "wx/math.h"
#endif
#include "wx/mac/uma.h"
#include "wx/mac/printmac.h"
#include "wx/mac/private/print.h"
#include "wx/printdlg.h"
#include "wx/paper.h"
#include "wx/mac/printdlg.h"
#include <stdlib.h>
IMPLEMENT_DYNAMIC_CLASS(wxMacCarbonPrintData, wxPrintNativeDataBase)
IMPLEMENT_DYNAMIC_CLASS(wxMacPrinter, wxPrinterBase)
IMPLEMENT_CLASS(wxMacPrintPreview, wxPrintPreviewBase)
bool wxMacCarbonPrintData::IsOk() const
{
return (m_macPageFormat != kPMNoPageFormat) && (m_macPrintSettings != kPMNoPrintSettings) && (m_macPrintSession != kPMNoReference);
}
wxMacCarbonPrintData::wxMacCarbonPrintData()
{
m_macPageFormat = kPMNoPageFormat;
m_macPrintSettings = kPMNoPrintSettings;
m_macPrintSession = kPMNoReference ;
ValidateOrCreate() ;
}
wxMacCarbonPrintData::~wxMacCarbonPrintData()
{
if (m_macPageFormat != kPMNoPageFormat)
{
(void)PMRelease(m_macPageFormat);
m_macPageFormat = kPMNoPageFormat;
}
if (m_macPrintSettings != kPMNoPrintSettings)
{
(void)PMRelease(m_macPrintSettings);
m_macPrintSettings = kPMNoPrintSettings;
}
if ( m_macPrintSession != kPMNoReference )
{
(void)PMRelease(m_macPrintSession);
m_macPrintSession = kPMNoReference;
}
}
void wxMacCarbonPrintData::ValidateOrCreate()
{
OSStatus err = noErr ;
if ( m_macPrintSession == kPMNoReference )
{
err = PMCreateSession( &m_macPrintSession ) ;
}
// Set up a valid PageFormat object.
if ( m_macPageFormat == kPMNoPageFormat)
{
err = PMCreatePageFormat(&m_macPageFormat);
// Note that PMPageFormat is not session-specific, but calling
// PMSessionDefaultPageFormat assigns values specific to the printer
// associated with the current printing session.
if ((err == noErr) &&
( m_macPageFormat != kPMNoPageFormat))
{
err = PMSessionDefaultPageFormat(m_macPrintSession,
m_macPageFormat);
}
}
else
{
err = PMSessionValidatePageFormat(m_macPrintSession,
m_macPageFormat,
kPMDontWantBoolean);
}
// Set up a valid PrintSettings object.
if ( m_macPrintSettings == kPMNoPrintSettings)
{
err = PMCreatePrintSettings( &m_macPrintSettings);
// Note that PMPrintSettings is not session-specific, but calling
// PMSessionDefaultPrintSettings assigns values specific to the printer
// associated with the current printing session.
if ((err == noErr) &&
( m_macPrintSettings != kPMNoPrintSettings))
{
err = PMSessionDefaultPrintSettings(m_macPrintSession,
m_macPrintSettings);
}
}
else
{
err = PMSessionValidatePrintSettings( m_macPrintSession,
m_macPrintSettings,
kPMDontWantBoolean);
}
}
bool wxMacCarbonPrintData::TransferFrom( const wxPrintData &data )
{
ValidateOrCreate() ;
PMSetCopies( (PMPrintSettings) m_macPrintSettings , data.GetNoCopies() , false ) ;
if ( data.IsOrientationReversed() )
PMSetOrientation( (PMPageFormat) m_macPageFormat , ( data.GetOrientation() == wxLANDSCAPE ) ?
kPMReverseLandscape : kPMReversePortrait , false ) ;
else
PMSetOrientation( (PMPageFormat) m_macPageFormat , ( data.GetOrientation() == wxLANDSCAPE ) ?
kPMLandscape : kPMPortrait , false ) ;
// collate cannot be set
#if 0 // not yet tested
if ( !m_printerName.empty() )
PMSessionSetCurrentPrinter( (PMPrintSession) m_macPrintSession , wxCFStringRef( m_printerName , wxFont::GetDefaultEncoding() ) ) ;
#endif
#ifndef __LP64__
PMColorMode color ;
PMGetColorMode( (PMPrintSettings) m_macPrintSettings, &color ) ;
if ( data.GetColour() )
{
if ( color == kPMBlackAndWhite )
PMSetColorMode( (PMPrintSettings) m_macPrintSettings, kPMColor ) ;
}
else
PMSetColorMode( (PMPrintSettings) m_macPrintSettings, kPMBlackAndWhite ) ;
#endif
PMDuplexMode mode = 0 ;
switch( data.GetDuplex() )
{
case wxDUPLEX_HORIZONTAL :
mode = kPMDuplexNoTumble ;
break ;
case wxDUPLEX_VERTICAL :
mode = kPMDuplexTumble ;
break ;
case wxDUPLEX_SIMPLEX :
default :
mode = kPMDuplexNone ;
break ;
}
PMSetDuplex( (PMPrintSettings) m_macPrintSettings, mode ) ;
// PMQualityMode not yet accessible via API
// todo paperSize
PMResolution res;
PMPrinter printer;
PMSessionGetCurrentPrinter(m_macPrintSession, &printer);
#if 0 // MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5
PMPrinterGetOutputResolution( printer,
(PMPrintSettings) m_macPrintSettings, &res) ;
// TODO transfer ? into page format ?
// may fail !
#else
PMTag tag = kPMMaxSquareResolution;
PMPrinterGetPrinterResolution(printer, tag, &res);
PMSetResolution((PMPageFormat) m_macPageFormat, &res);
#endif
// after setting the new resolution the format has to be updated, otherwise the page rect remains
// at the 'old' scaling
PMSessionValidatePageFormat((PMPrintSession) m_macPrintSession,
(PMPageFormat) m_macPageFormat,
kPMDontWantBoolean) ;
return true ;
}
bool wxMacCarbonPrintData::TransferTo( wxPrintData &data )
{
OSStatus err = noErr ;
UInt32 copies ;
err = PMGetCopies( m_macPrintSettings , &copies ) ;
if ( err == noErr )
data.SetNoCopies( copies ) ;
PMOrientation orientation ;
err = PMGetOrientation( m_macPageFormat , &orientation ) ;
if ( err == noErr )
{
if ( orientation == kPMPortrait || orientation == kPMReversePortrait )
{
data.SetOrientation( wxPORTRAIT );
data.SetOrientationReversed( orientation == kPMReversePortrait );
}
else
{
data.SetOrientation( wxLANDSCAPE );
data.SetOrientationReversed( orientation == kPMReverseLandscape );
}
}
// collate cannot be set
#if 0
{
wxCFStringRef name ;
PMPrinter printer ;
PMSessionGetCurrentPrinter( m_macPrintSession ,
&printer ) ;
m_printerName = name.AsString() ;
}
#endif
#ifndef __LP64__
PMColorMode color ;
err = PMGetColorMode( m_macPrintSettings, &color ) ;
if ( err == noErr )
data.SetColour( !(color == kPMBlackAndWhite) ) ;
#endif
PMDuplexMode mode = 0 ;
PMGetDuplex( (PMPrintSettings) m_macPrintSettings, &mode ) ;
switch( mode )
{
case kPMDuplexNoTumble :
data.SetDuplex(wxDUPLEX_HORIZONTAL);
break ;
case kPMDuplexTumble :
data.SetDuplex(wxDUPLEX_VERTICAL);
break ;
case kPMDuplexNone :
default :
data.SetDuplex(wxDUPLEX_SIMPLEX);
break ;
}
// PMQualityMode not yet accessible via API
PMPaper paper ;
PMGetPageFormatPaper( m_macPageFormat, &paper );
PMRect rPaper;
err = PMGetUnadjustedPaperRect( m_macPageFormat, &rPaper);
if ( err == noErr )
{
wxSize sz((int)(( rPaper.right - rPaper.left ) * pt2mm + 0.5 ) ,
(int)(( rPaper.bottom - rPaper.top ) * pt2mm + 0.5 ));
data.SetPaperSize(sz);
wxPaperSize id = wxThePrintPaperDatabase->GetSize(wxSize(sz.x* 10, sz.y * 10));
if (id != wxPAPER_NONE)
{
data.SetPaperId(id);
}
}
return true ;
}
void wxMacCarbonPrintData::TransferFrom( wxPageSetupData *WXUNUSED(data) )
{
// should we setup the page rect here ?
// since MacOS sometimes has two same paper rects with different
// page rects we could make it roundtrip safe perhaps
}
void wxMacCarbonPrintData::TransferTo( wxPageSetupData* data )
{
PMRect rPaper;
OSStatus err = PMGetUnadjustedPaperRect(m_macPageFormat, &rPaper);
if ( err == noErr )
{
wxSize sz((int)(( rPaper.right - rPaper.left ) * pt2mm + 0.5 ) ,
(int)(( rPaper.bottom - rPaper.top ) * pt2mm + 0.5 ));
data->SetPaperSize(sz);
PMRect rPage ;
err = PMGetUnadjustedPageRect(m_macPageFormat , &rPage ) ;
if ( err == noErr )
{
data->SetMinMarginTopLeft( wxPoint (
(int)(((double) rPage.left - rPaper.left ) * pt2mm) ,
(int)(((double) rPage.top - rPaper.top ) * pt2mm) ) ) ;
data->SetMinMarginBottomRight( wxPoint (
(wxCoord)(((double) rPaper.right - rPage.right ) * pt2mm),
(wxCoord)(((double) rPaper.bottom - rPage.bottom ) * pt2mm)) ) ;
if ( data->GetMarginTopLeft().x < data->GetMinMarginTopLeft().x )
data->SetMarginTopLeft( wxPoint( data->GetMinMarginTopLeft().x ,
data->GetMarginTopLeft().y ) ) ;
if ( data->GetMarginBottomRight().x < data->GetMinMarginBottomRight().x )
data->SetMarginBottomRight( wxPoint( data->GetMinMarginBottomRight().x ,
data->GetMarginBottomRight().y ) );
if ( data->GetMarginTopLeft().y < data->GetMinMarginTopLeft().y )
data->SetMarginTopLeft( wxPoint( data->GetMarginTopLeft().x , data->GetMinMarginTopLeft().y ) );
if ( data->GetMarginBottomRight().y < data->GetMinMarginBottomRight().y )
data->SetMarginBottomRight( wxPoint( data->GetMarginBottomRight().x ,
data->GetMinMarginBottomRight().y) );
}
}
}
void wxMacCarbonPrintData::TransferTo( wxPrintDialogData* data )
{
UInt32 minPage , maxPage ;
PMGetPageRange( m_macPrintSettings , &minPage , &maxPage ) ;
data->SetMinPage( minPage ) ;
data->SetMaxPage( maxPage ) ;
UInt32 copies ;
PMGetCopies( m_macPrintSettings , &copies ) ;
data->SetNoCopies( copies ) ;
UInt32 from , to ;
PMGetFirstPage( m_macPrintSettings , &from ) ;
PMGetLastPage( m_macPrintSettings , &to ) ;
if ( to >= 0x7FFFFFFF ) // due to an OS Bug we don't get back kPMPrintAllPages
{
data->SetAllPages( true ) ;
// This means all pages, more or less
data->SetFromPage(1);
data->SetToPage(32000);
}
else
{
data->SetFromPage( from ) ;
data->SetToPage( to ) ;
data->SetAllPages( false );
}
}
void wxMacCarbonPrintData::TransferFrom( wxPrintDialogData* data )
{
// Respect the value of m_printAllPages
if ( data->GetAllPages() )
PMSetPageRange( m_macPrintSettings , data->GetMinPage() , (UInt32) kPMPrintAllPages ) ;
else
PMSetPageRange( m_macPrintSettings , data->GetMinPage() , data->GetMaxPage() ) ;
PMSetCopies( m_macPrintSettings , data->GetNoCopies() , false ) ;
PMSetFirstPage( m_macPrintSettings , data->GetFromPage() , false ) ;
if (data->GetAllPages() || data->GetFromPage() == 0)
PMSetLastPage( m_macPrintSettings , (UInt32) kPMPrintAllPages, true ) ;
else
PMSetLastPage( m_macPrintSettings , (UInt32) data->GetToPage() , false ) ;
}
/*
* Printer
*/
wxMacPrinter::wxMacPrinter(wxPrintDialogData *data):
wxPrinterBase(data)
{
}
wxMacPrinter::~wxMacPrinter(void)
{
}
bool wxMacPrinter::Print(wxWindow *parent, wxPrintout *printout, bool prompt)
{
sm_abortIt = false;
sm_abortWindow = NULL;
if (!printout)
return false;
printout->SetIsPreview(false);
if (m_printDialogData.GetMinPage() < 1)
m_printDialogData.SetMinPage(1);
if (m_printDialogData.GetMaxPage() < 1)
m_printDialogData.SetMaxPage(9999);
// Create a suitable device context
wxPrinterDC *dc = NULL;
if (prompt)
{
wxMacPrintDialog dialog(parent, & m_printDialogData);
if (dialog.ShowModal() == wxID_OK)
{
dc = wxDynamicCast(dialog.GetPrintDC(), wxPrinterDC);
wxASSERT(dc);
m_printDialogData = dialog.GetPrintDialogData();
}
}
else
{
dc = new wxPrinterDC( m_printDialogData.GetPrintData() ) ;
}
// May have pressed cancel.
if (!dc || !dc->IsOk())
{
if (dc)
delete dc;
return false;
}
// on the mac we have always pixels as addressing mode with 72 dpi
printout->SetPPIScreen(72, 72);
PMResolution res;
wxMacCarbonPrintData* nativeData = (wxMacCarbonPrintData*)
(m_printDialogData.GetPrintData().GetNativeData());
#if 0 // MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5
PMPrinter printer;
PMSessionGetCurrentPrinter(nativeData->m_macPrintSession, &printer);
PMPrinterGetOutputResolution( printer, nativeData->m_macPrintSettings, &res) ;
#else
PMGetResolution((PMPageFormat) (nativeData->m_macPageFormat), &res);
#endif
printout->SetPPIPrinter(int(res.hRes), int(res.vRes));
// Set printout parameters
printout->SetDC(dc);
int w, h;
dc->GetSize(&w, &h);
printout->SetPageSizePixels((int)w, (int)h);
printout->SetPaperRectPixels(dc->GetPaperRect());
wxCoord mw, mh;
dc->GetSizeMM(&mw, &mh);
printout->SetPageSizeMM((int)mw, (int)mh);
// Create an abort window
wxBeginBusyCursor();
printout->OnPreparePrinting();
// Get some parameters from the printout, if defined
int fromPage, toPage;
int minPage, maxPage;
printout->GetPageInfo(&minPage, &maxPage, &fromPage, &toPage);
if (maxPage == 0)
{
wxEndBusyCursor();
return false;
}
// Only set min and max, because from and to have been
// set by the user
m_printDialogData.SetMinPage(minPage);
m_printDialogData.SetMaxPage(maxPage);
printout->OnBeginPrinting();
bool keepGoing = true;
if (!printout->OnBeginDocument(m_printDialogData.GetFromPage(), m_printDialogData.GetToPage()))
{
wxEndBusyCursor();
wxMessageBox(wxT("Could not start printing."), wxT("Print Error"), wxOK, parent);
}
int pn;
for (pn = m_printDialogData.GetFromPage();
keepGoing && (pn <= m_printDialogData.GetToPage()) && printout->HasPage(pn);
pn++)
{
if (sm_abortIt)
{
keepGoing = false;
break;
}
else
{
dc->StartPage();
keepGoing = printout->OnPrintPage(pn);
dc->EndPage();
}
}
printout->OnEndDocument();
printout->OnEndPrinting();
if (sm_abortWindow)
{
sm_abortWindow->Show(false);
delete sm_abortWindow;
sm_abortWindow = NULL;
}
wxEndBusyCursor();
delete dc;
return true;
}
wxDC* wxMacPrinter::PrintDialog(wxWindow *parent)
{
wxDC* dc = (wxDC*) NULL;
wxPrintDialog dialog(parent, & m_printDialogData);
int ret = dialog.ShowModal();
if (ret == wxID_OK)
{
dc = dialog.GetPrintDC();
m_printDialogData = dialog.GetPrintDialogData();
}
return dc;
}
bool wxMacPrinter::Setup(wxWindow *WXUNUSED(parent))
{
#if 0
wxPrintDialog dialog(parent, & m_printDialogData);
dialog.GetPrintDialogData().SetSetupDialog(true);
int ret = dialog.ShowModal();
if (ret == wxID_OK)
m_printDialogData = dialog.GetPrintDialogData();
return (ret == wxID_OK);
#endif
return wxID_CANCEL;
}
/*
* Print preview
*/
wxMacPrintPreview::wxMacPrintPreview(wxPrintout *printout,
wxPrintout *printoutForPrinting,
wxPrintDialogData *data)
: wxPrintPreviewBase(printout, printoutForPrinting, data)
{
DetermineScaling();
}
wxMacPrintPreview::wxMacPrintPreview(wxPrintout *printout, wxPrintout *printoutForPrinting, wxPrintData *data):
wxPrintPreviewBase(printout, printoutForPrinting, data)
{
DetermineScaling();
}
wxMacPrintPreview::~wxMacPrintPreview(void)
{
}
bool wxMacPrintPreview::Print(bool interactive)
{
if (!m_printPrintout)
return false;
wxMacPrinter printer(&m_printDialogData);
return printer.Print(m_previewFrame, m_printPrintout, interactive);
}
void wxMacPrintPreview::DetermineScaling(void)
{
int screenWidth , screenHeight ;
wxDisplaySize( &screenWidth , &screenHeight ) ;
wxSize ppiScreen( 72 , 72 ) ;
wxSize ppiPrinter( 72 , 72 ) ;
// Note that with Leopard, screen dpi=72 is no longer a given
m_previewPrintout->SetPPIScreen( ppiScreen.x , ppiScreen.y ) ;
wxCoord w , h ;
wxCoord ww, hh;
wxRect paperRect;
// Get a device context for the currently selected printer
wxPrinterDC printerDC(m_printDialogData.GetPrintData());
if (printerDC.IsOk())
{
printerDC.GetSizeMM(&ww, &hh);
printerDC.GetSize( &w , &h ) ;
ppiPrinter = printerDC.GetPPI() ;
paperRect = printerDC.GetPaperRect();
m_isOk = true ;
}
else
{
// use some defaults
w = 8 * 72 ;
h = 11 * 72 ;
ww = (wxCoord) (w * 25.4 / ppiPrinter.x) ;
hh = (wxCoord) (h * 25.4 / ppiPrinter.y) ;
paperRect = wxRect(0, 0, w, h);
m_isOk = false ;
}
m_pageWidth = w;
m_pageHeight = h;
m_previewPrintout->SetPageSizePixels(w , h) ;
m_previewPrintout->SetPageSizeMM(ww, hh);
m_previewPrintout->SetPaperRectPixels(paperRect);
m_previewPrintout->SetPPIPrinter( ppiPrinter.x , ppiPrinter.y ) ;
m_previewScaleX = float(ppiScreen.x) / ppiPrinter.x;
m_previewScaleY = float(ppiScreen.y) / ppiPrinter.y;
}
#endif

527
src/osx/carbon/radiobox.cpp Normal file
View File

@@ -0,0 +1,527 @@
/////////////////////////////////////////////////////////////////////////////
// Name: src/mac/carbon/radiobox.cpp
// Purpose: wxRadioBox
// Author: Stefan Csomor
// Modified by: JS Lair (99/11/15) first implementation
// Created: 1998-01-01
// RCS-ID: $Id$
// Copyright: (c) Stefan Csomor
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
#include "wx/wxprec.h"
#if wxUSE_RADIOBOX
#include "wx/radiobox.h"
#ifndef WX_PRECOMP
#include "wx/radiobut.h"
#include "wx/arrstr.h"
#endif
#include "wx/mac/uma.h"
IMPLEMENT_DYNAMIC_CLASS(wxRadioBox, wxControl)
BEGIN_EVENT_TABLE(wxRadioBox, wxControl)
EVT_RADIOBUTTON( wxID_ANY , wxRadioBox::OnRadioButton )
END_EVENT_TABLE()
void wxRadioBox::OnRadioButton( wxCommandEvent &outer )
{
if ( outer.IsChecked() )
{
wxCommandEvent event( wxEVT_COMMAND_RADIOBOX_SELECTED, m_windowId );
int i = GetSelection() ;
event.SetInt(i);
event.SetString(GetString(i));
event.SetEventObject( this );
ProcessCommand(event);
}
}
wxRadioBox::wxRadioBox()
{
m_noItems = 0;
m_noRowsOrCols = 0;
m_radioButtonCycle = NULL;
}
wxRadioBox::~wxRadioBox()
{
m_isBeingDeleted = true;
wxRadioButton *next, *current;
current = m_radioButtonCycle->NextInCycle();
if (current != NULL)
{
while (current != m_radioButtonCycle)
{
next = current->NextInCycle();
delete current;
current = next;
}
delete current;
}
}
// Create the radiobox for two-step construction
bool wxRadioBox::Create( wxWindow *parent,
wxWindowID id, const wxString& label,
const wxPoint& pos, const wxSize& size,
const wxArrayString& choices,
int majorDim, long style,
const wxValidator& val, const wxString& name )
{
wxCArrayString chs(choices);
return Create(
parent, id, label, pos, size, chs.GetCount(),
chs.GetStrings(), majorDim, style, val, name);
}
bool wxRadioBox::Create( wxWindow *parent,
wxWindowID id, const wxString& label,
const wxPoint& pos, const wxSize& size,
int n, const wxString choices[],
int majorDim, long style,
const wxValidator& val, const wxString& name )
{
m_macIsUserPane = false ;
if ( !wxControl::Create( parent, id, pos, size, style, val, name ) )
return false;
int i;
m_noItems = (unsigned int)n;
m_noRowsOrCols = majorDim;
m_radioButtonCycle = NULL;
SetMajorDim( majorDim == 0 ? n : majorDim, style );
m_labelOrig = m_label = label;
Rect bounds = wxMacGetBoundsForControl( this, pos, size );
if ( bounds.right <= bounds.left )
bounds.right = bounds.left + 100;
if ( bounds.bottom <= bounds.top )
bounds.bottom = bounds.top + 100;
m_peer = new wxMacControl( this );
OSStatus err = CreateGroupBoxControl(
MAC_WXHWND(parent->MacGetTopLevelWindowRef()),
&bounds, CFSTR("") , true /*primary*/,
m_peer->GetControlRefAddr() );
verify_noerr( err );
for (i = 0; i < n; i++)
{
wxRadioButton *radBtn = new wxRadioButton(
this,
wxID_ANY,
GetLabelText(choices[i]),
wxPoint( 5, 20 * i + 10 ),
wxDefaultSize,
i == 0 ? wxRB_GROUP : 0 );
if ( i == 0 )
m_radioButtonCycle = radBtn;
// m_radioButtonCycle = radBtn->AddInCycle( m_radioButtonCycle );
}
SetSelection( 0 );
MacPostControlCreate( pos, size );
return true;
}
// Enables or disables the entire radiobox
//
bool wxRadioBox::Enable(bool enable)
{
wxRadioButton *current;
if (!wxControl::Enable( enable ))
return false;
current = m_radioButtonCycle;
for (unsigned int i = 0; i < m_noItems; i++)
{
current->Enable( enable );
current = current->NextInCycle();
}
return true;
}
// Enables or disables an given button
//
bool wxRadioBox::Enable(unsigned int item, bool enable)
{
if (!IsValid( item ))
return false;
unsigned int i = 0;
wxRadioButton *current = m_radioButtonCycle;
while (i != item)
{
i++;
current = current->NextInCycle();
}
return current->Enable( enable );
}
bool wxRadioBox::IsItemEnabled(unsigned int item) const
{
if (!IsValid( item ))
return false;
unsigned int i = 0;
wxRadioButton *current = m_radioButtonCycle;
while (i != item)
{
i++;
current = current->NextInCycle();
}
return current->IsEnabled();
}
// Returns the radiobox label
//
wxString wxRadioBox::GetLabel() const
{
return wxControl::GetLabel();
}
// Returns the label for the given button
//
wxString wxRadioBox::GetString(unsigned int item) const
{
wxRadioButton *current;
if (!IsValid( item ))
return wxEmptyString;
unsigned int i = 0;
current = m_radioButtonCycle;
while (i != item)
{
i++;
current = current->NextInCycle();
}
return current->GetLabel();
}
// Returns the zero-based position of the selected button
//
int wxRadioBox::GetSelection() const
{
int i;
wxRadioButton *current;
i = 0;
current = m_radioButtonCycle;
while (!current->GetValue())
{
i++;
current = current->NextInCycle();
}
return i;
}
// Sets the radiobox label
//
void wxRadioBox::SetLabel(const wxString& label)
{
return wxControl::SetLabel( label );
}
// Sets the label of a given button
//
void wxRadioBox::SetString(unsigned int item,const wxString& label)
{
if (!IsValid( item ))
return;
unsigned int i = 0;
wxRadioButton *current = m_radioButtonCycle;
while (i != item)
{
i++;
current = current->NextInCycle();
}
return current->SetLabel( label );
}
// Sets a button by passing the desired position. This does not cause
// wxEVT_COMMAND_RADIOBOX_SELECTED event to get emitted
//
void wxRadioBox::SetSelection(int item)
{
int i;
wxRadioButton *current;
if (!IsValid( item ))
return;
i = 0;
current = m_radioButtonCycle;
while (i != item)
{
i++;
current = current->NextInCycle();
}
current->SetValue( true );
}
// Shows or hides the entire radiobox
//
bool wxRadioBox::Show(bool show)
{
wxRadioButton *current;
current = m_radioButtonCycle;
for (unsigned int i=0; i<m_noItems; i++)
{
current->Show( show );
current = current->NextInCycle();
}
wxControl::Show( show );
return true;
}
// Shows or hides the given button
//
bool wxRadioBox::Show(unsigned int item, bool show)
{
if (!IsValid( item ))
return false;
unsigned int i = 0;
wxRadioButton *current = m_radioButtonCycle;
while (i != item)
{
i++;
current = current->NextInCycle();
}
return current->Show( show );
}
bool wxRadioBox::IsItemShown(unsigned int item) const
{
if (!IsValid( item ))
return false;
unsigned int i = 0;
wxRadioButton *current = m_radioButtonCycle;
while (i != item)
{
i++;
current = current->NextInCycle();
}
return current->IsShown();
}
// Simulates the effect of the user issuing a command to the item
//
void wxRadioBox::Command( wxCommandEvent& event )
{
SetSelection( event.GetInt() );
ProcessCommand( event );
}
// Sets the selected button to receive keyboard input
//
void wxRadioBox::SetFocus()
{
wxRadioButton *current;
current = m_radioButtonCycle;
while (!current->GetValue())
{
current = current->NextInCycle();
}
current->SetFocus();
}
// Simulates the effect of the user issuing a command to the item
//
#define RADIO_SIZE 20
void wxRadioBox::DoSetSize(int x, int y, int width, int height, int sizeFlags)
{
int i;
wxRadioButton *current;
// define the position
int x_current, y_current;
int x_offset, y_offset;
int widthOld, heightOld;
GetSize( &widthOld, &heightOld );
GetPosition( &x_current, &y_current );
x_offset = x;
y_offset = y;
if (!(sizeFlags & wxSIZE_ALLOW_MINUS_ONE))
{
if (x == wxDefaultCoord)
x_offset = x_current;
if (y == wxDefaultCoord)
y_offset = y_current;
}
// define size
int charWidth, charHeight;
int maxWidth, maxHeight;
int eachWidth[128], eachHeight[128];
int totWidth, totHeight;
GetTextExtent(
wxT("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"),
&charWidth, &charHeight );
charWidth /= 52;
maxWidth = -1;
maxHeight = -1;
for (unsigned int i = 0 ; i < m_noItems; i++)
{
GetTextExtent(GetString(i), &eachWidth[i], &eachHeight[i] );
eachWidth[i] = (int)(eachWidth[i] + RADIO_SIZE);
eachHeight[i] = (int)((3 * eachHeight[i]) / 2);
if (maxWidth < eachWidth[i])
maxWidth = eachWidth[i];
if (maxHeight < eachHeight[i])
maxHeight = eachHeight[i];
}
totHeight = GetRowCount() * maxHeight;
totWidth = GetColumnCount() * (maxWidth + charWidth);
wxSize sz = DoGetSizeFromClientSize( wxSize( totWidth, totHeight ) ) ;
// change the width / height only when specified
if ( width == wxDefaultCoord )
{
if ( sizeFlags & wxSIZE_AUTO_WIDTH )
width = sz.x;
else
width = widthOld;
}
if ( height == wxDefaultCoord )
{
if ( sizeFlags & wxSIZE_AUTO_HEIGHT )
height = sz.y;
else
height = heightOld;
}
wxControl::DoSetSize( x_offset, y_offset, width, height, wxSIZE_AUTO );
// arrange radio buttons
int x_start, y_start;
x_start = 0;
y_start = 0;
x_offset = x_start;
y_offset = y_start;
current = m_radioButtonCycle;
for (i = 0 ; i < (int)m_noItems; i++)
{
// not to do for the zero button!
if ((i > 0) && ((i % GetMajorDim()) == 0))
{
if (m_windowStyle & wxRA_SPECIFY_ROWS)
{
x_offset += maxWidth + charWidth;
y_offset = y_start;
}
else
{
x_offset = x_start;
y_offset += maxHeight ; //+ charHeight / 2
}
}
current->SetSize( x_offset, y_offset, eachWidth[i], eachHeight[i]);
current = current->NextInCycle();
if (m_windowStyle & wxRA_SPECIFY_ROWS)
y_offset += maxHeight ; // + charHeight / 2
else
x_offset += maxWidth + charWidth;
}
}
wxSize wxRadioBox::DoGetBestSize() const
{
int charWidth, charHeight;
int maxWidth, maxHeight;
int eachWidth, eachHeight;
int totWidth, totHeight;
wxFont font = GetFont(); // GetParent()->GetFont()
GetTextExtent(
wxT("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"),
&charWidth, &charHeight, NULL, NULL, &font );
charWidth /= 52;
maxWidth = -1;
maxHeight = -1;
for (unsigned int i = 0 ; i < m_noItems; i++)
{
GetTextExtent(GetString(i), &eachWidth, &eachHeight, NULL, NULL, &font );
eachWidth = (int)(eachWidth + RADIO_SIZE);
eachHeight = (int)((3 * eachHeight) / 2);
if (maxWidth < eachWidth)
maxWidth = eachWidth;
if (maxHeight < eachHeight)
maxHeight = eachHeight;
}
totHeight = GetRowCount() * maxHeight;
totWidth = GetColumnCount() * (maxWidth + charWidth);
wxSize sz = DoGetSizeFromClientSize( wxSize( totWidth, totHeight ) );
totWidth = sz.x;
totHeight = sz.y;
// handle radio box title as well
GetTextExtent( GetLabel(), &eachWidth, NULL );
eachWidth = (int)(eachWidth + RADIO_SIZE) + 3 * charWidth;
if (totWidth < eachWidth)
totWidth = eachWidth;
return wxSize( totWidth, totHeight );
}
#endif // wxUSE_RADIOBOX

178
src/osx/carbon/radiobut.cpp Normal file
View File

@@ -0,0 +1,178 @@
/////////////////////////////////////////////////////////////////////////////
// Name: radiobut.cpp
// Purpose: wxRadioButton
// Author: AUTHOR
// Modified by: JS Lair (99/11/15) adding the cyclic group notion for radiobox
// Created: ??/??/98
// RCS-ID: $Id$
// Copyright: (c) AUTHOR
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
#include "wx/wxprec.h"
#if wxUSE_RADIOBTN
#include "wx/radiobut.h"
#include "wx/mac/uma.h"
IMPLEMENT_DYNAMIC_CLASS(wxRadioButton, wxControl)
bool wxRadioButton::Create( wxWindow *parent,
wxWindowID id,
const wxString& label,
const wxPoint& pos,
const wxSize& size,
long style,
const wxValidator& validator,
const wxString& name )
{
m_macIsUserPane = false;
if ( !wxControl::Create( parent, id, pos, size, style, validator, name ) )
return false;
m_labelOrig = m_label = label;
Rect bounds = wxMacGetBoundsForControl( this, pos, size );
m_peer = new wxMacControl( this );
OSStatus err = CreateRadioButtonControl(
MAC_WXHWND(parent->MacGetTopLevelWindowRef()), &bounds, CFSTR(""),
0, false /* no autotoggle */, m_peer->GetControlRefAddr() );
verify_noerr( err );
MacPostControlCreate( pos, size );
m_cycle = this;
if (HasFlag( wxRB_GROUP ))
{
AddInCycle( NULL );
}
else
{
// search backward for last group start
wxRadioButton *chief = NULL;
wxWindowList::compatibility_iterator node = parent->GetChildren().GetLast();
while (node)
{
wxWindow *child = node->GetData();
if (child->IsKindOf( CLASSINFO( wxRadioButton ) ))
{
chief = (wxRadioButton*)child;
if (child->HasFlag( wxRB_GROUP ))
break;
}
node = node->GetPrevious();
}
AddInCycle( chief );
}
return true;
}
wxRadioButton::~wxRadioButton()
{
RemoveFromCycle();
}
void wxRadioButton::SetValue(bool val)
{
wxRadioButton *cycle;
if (m_peer->GetValue() == val)
return;
m_peer->SetValue( val );
if (val)
{
cycle = this->NextInCycle();
if (cycle != NULL)
{
while (cycle != this)
{
cycle->SetValue( false );
cycle = cycle->NextInCycle();
}
}
}
}
bool wxRadioButton::GetValue() const
{
return m_peer->GetValue();
}
void wxRadioButton::Command(wxCommandEvent& event)
{
SetValue( (event.GetInt() != 0) );
ProcessCommand( event );
}
wxInt32 wxRadioButton::MacControlHit( WXEVENTHANDLERREF WXUNUSED(handler), WXEVENTREF WXUNUSED(event) )
{
// if already set -> no action
if (GetValue())
return noErr;
wxRadioButton *cycle;
cycle = this->NextInCycle();
if (cycle != NULL)
{
while (cycle != this)
{
if (cycle->GetValue())
cycle->SetValue( false );
cycle = cycle->NextInCycle();
}
}
SetValue( true );
wxCommandEvent event2( wxEVT_COMMAND_RADIOBUTTON_SELECTED, m_windowId );
event2.SetEventObject( this );
event2.SetInt( true );
ProcessCommand( event2 );
return noErr;
}
wxRadioButton *wxRadioButton::AddInCycle(wxRadioButton *cycle)
{
wxRadioButton *current;
if (cycle == NULL)
{
m_cycle = this;
}
else
{
current = cycle;
while (current->m_cycle != cycle)
current = current->m_cycle;
m_cycle = cycle;
current->m_cycle = this;
}
return m_cycle;
}
void wxRadioButton::RemoveFromCycle()
{
if ((m_cycle == NULL) || (m_cycle == this))
return;
// Find the previous one and make it point to the next one
wxRadioButton* prev = this;
while (prev->m_cycle != this)
prev = prev->m_cycle;
prev->m_cycle = m_cycle;
}
#endif

Some files were not shown because too many files have changed in this diff Show More