renaming
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@54119 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
36
src/osx/carbon/Info.plist.in
Normal file
36
src/osx/carbon/Info.plist.in
Normal 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>
|
||||
92
src/osx/carbon/aboutdlg.cpp
Normal file
92
src/osx/carbon/aboutdlg.cpp
Normal 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
109
src/osx/carbon/accel.cpp
Normal 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
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
1
src/osx/carbon/apprsrc.h
Normal file
@@ -0,0 +1 @@
|
||||
// TODO REMOVE
|
||||
1
src/osx/carbon/apprsrc.r
Normal file
1
src/osx/carbon/apprsrc.r
Normal file
@@ -0,0 +1 @@
|
||||
/* not needed anymore */
|
||||
108
src/osx/carbon/artmac.cpp
Normal file
108
src/osx/carbon/artmac.cpp
Normal 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
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
189
src/osx/carbon/bmpbuttn.cpp
Normal 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
192
src/osx/carbon/brush.cpp
Normal 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
273
src/osx/carbon/button.cpp
Normal 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);
|
||||
}
|
||||
|
||||
|
||||
7
src/osx/carbon/carbrsrc.r
Normal file
7
src/osx/carbon/carbrsrc.r
Normal 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
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
186
src/osx/carbon/checkbox.cpp
Normal 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
273
src/osx/carbon/checklst.cpp
Normal 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
308
src/osx/carbon/choice.cpp
Normal 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
209
src/osx/carbon/clipbrd.cpp
Normal 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
|
||||
75
src/osx/carbon/colordlg.cpp
Normal file
75
src/osx/carbon/colordlg.cpp
Normal 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
|
||||
193
src/osx/carbon/colordlgosx.mm
Normal file
193
src/osx/carbon/colordlgosx.mm
Normal 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
147
src/osx/carbon/colour.cpp
Normal 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
668
src/osx/carbon/combobox.cpp
Normal 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( ¤tX, ¤tY );
|
||||
|
||||
int currentW, currentH;
|
||||
GetSize( ¤tW, ¤tH );
|
||||
|
||||
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
793
src/osx/carbon/combobxc.cpp
Normal 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( ¤tX, ¤tY );
|
||||
|
||||
int currentW, currentH;
|
||||
GetSize( ¤tW, ¤tH );
|
||||
|
||||
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;
|
||||
}
|
||||
97
src/osx/carbon/control.cpp
Normal file
97
src/osx/carbon/control.cpp
Normal 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
159
src/osx/carbon/corersrc.r
Normal 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
697
src/osx/carbon/cursor.cpp
Normal 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
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
753
src/osx/carbon/dataobj.cpp
Normal 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
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
194
src/osx/carbon/dcclient.cpp
Normal 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
116
src/osx/carbon/dcmemory.cpp
Normal 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
393
src/osx/carbon/dcprint.cpp
Normal 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
|
||||
59
src/osx/carbon/dcscreen.cpp
Normal file
59
src/osx/carbon/dcscreen.cpp
Normal 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
185
src/osx/carbon/dialog.cpp
Normal 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
145
src/osx/carbon/dirdlg.cpp
Normal 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
269
src/osx/carbon/dirmac.cpp
Normal 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
255
src/osx/carbon/display.cpp
Normal 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
562
src/osx/carbon/dnd.cpp
Normal 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
199
src/osx/carbon/drawer.cpp
Normal 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
0
src/osx/carbon/dummy.txt
Normal file
109
src/osx/carbon/evtloop.cpp
Normal file
109
src/osx/carbon/evtloop.cpp
Normal 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
436
src/osx/carbon/filedlg.cpp
Normal 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
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
828
src/osx/carbon/fontdlg.cpp
Normal 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
|
||||
535
src/osx/carbon/fontdlgosx.mm
Normal file
535
src/osx/carbon/fontdlgosx.mm
Normal 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
123
src/osx/carbon/fontenum.cpp
Normal 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
|
||||
88
src/osx/carbon/fontutil.cpp
Normal file
88
src/osx/carbon/fontutil.cpp
Normal 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
402
src/osx/carbon/frame.cpp
Normal 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( ¤tclientwidth , ¤tclientheight ) ;
|
||||
if ( clientwidth == -1 )
|
||||
clientwidth = currentclientwidth ;
|
||||
if ( clientheight == -1 )
|
||||
clientheight = currentclientheight ;
|
||||
GetSize( ¤twidth , ¤theight ) ;
|
||||
|
||||
// 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
128
src/osx/carbon/gauge.cpp
Normal 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
75
src/osx/carbon/gdiobj.cpp
Normal 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
499
src/osx/carbon/glcanvas.cpp
Normal 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
2594
src/osx/carbon/graphics.cpp
Normal file
File diff suppressed because it is too large
Load Diff
80
src/osx/carbon/helpxxxx.cpp
Normal file
80
src/osx/carbon/helpxxxx.cpp
Normal 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
317
src/osx/carbon/icon.cpp
Normal 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
309
src/osx/carbon/imaglist.cpp
Normal 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
|
||||
1
src/osx/carbon/joystick.cpp
Normal file
1
src/osx/carbon/joystick.cpp
Normal file
@@ -0,0 +1 @@
|
||||
// todo remove
|
||||
628
src/osx/carbon/listbox.cpp
Normal file
628
src/osx/carbon/listbox.cpp
Normal 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
|
||||
3382
src/osx/carbon/listctrl_mac.cpp
Normal file
3382
src/osx/carbon/listctrl_mac.cpp
Normal file
File diff suppressed because it is too large
Load Diff
12
src/osx/carbon/main.cpp
Normal file
12
src/osx/carbon/main.cpp
Normal 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
514
src/osx/carbon/mdi.cpp
Normal 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
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
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
289
src/osx/carbon/menuitem.cpp
Normal 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
366
src/osx/carbon/metafile.cpp
Normal 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
1953
src/osx/carbon/mimetmac.cpp
Normal file
File diff suppressed because it is too large
Load Diff
20
src/osx/carbon/minifram.cpp
Normal file
20
src/osx/carbon/minifram.cpp
Normal 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
|
||||
685
src/osx/carbon/morefile/DirectoryCopy.c
Normal file
685
src/osx/carbon/morefile/DirectoryCopy.c
Normal 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) );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
559
src/osx/carbon/morefile/DirectoryCopy.h
Normal file
559
src/osx/carbon/morefile/DirectoryCopy.h
Normal 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__ */
|
||||
|
||||
946
src/osx/carbon/morefile/FSpCompat.c
Normal file
946
src/osx/carbon/morefile/FSpCompat.c
Normal 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;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
586
src/osx/carbon/morefile/FSpCompat.h
Normal file
586
src/osx/carbon/morefile/FSpCompat.h
Normal 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__ */
|
||||
|
||||
611
src/osx/carbon/morefile/FileCopy.c
Normal file
611
src/osx/carbon/morefile/FileCopy.c
Normal 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) );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
271
src/osx/carbon/morefile/FileCopy.h
Normal file
271
src/osx/carbon/morefile/FileCopy.h
Normal 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__ */
|
||||
|
||||
282
src/osx/carbon/morefile/FullPath.c
Normal file
282
src/osx/carbon/morefile/FullPath.c
Normal 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 );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
311
src/osx/carbon/morefile/FullPath.h
Normal file
311
src/osx/carbon/morefile/FullPath.h
Normal 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__ */
|
||||
|
||||
207
src/osx/carbon/morefile/IterateDirectory.c
Normal file
207
src/osx/carbon/morefile/IterateDirectory.c
Normal 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) );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
222
src/osx/carbon/morefile/IterateDirectory.h
Normal file
222
src/osx/carbon/morefile/IterateDirectory.h
Normal 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__ */
|
||||
|
||||
1270
src/osx/carbon/morefile/MoreDesktopMgr.c
Normal file
1270
src/osx/carbon/morefile/MoreDesktopMgr.c
Normal file
File diff suppressed because it is too large
Load Diff
628
src/osx/carbon/morefile/MoreDesktopMgr.h
Normal file
628
src/osx/carbon/morefile/MoreDesktopMgr.h
Normal 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__ */
|
||||
|
||||
643
src/osx/carbon/morefile/MoreFiles.c
Normal file
643
src/osx/carbon/morefile/MoreFiles.c
Normal 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 );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
1420
src/osx/carbon/morefile/MoreFiles.h
Normal file
1420
src/osx/carbon/morefile/MoreFiles.h
Normal file
File diff suppressed because it is too large
Load Diff
3632
src/osx/carbon/morefile/MoreFilesExtras.c
Normal file
3632
src/osx/carbon/morefile/MoreFilesExtras.c
Normal file
File diff suppressed because it is too large
Load Diff
3597
src/osx/carbon/morefile/MoreFilesExtras.h
Normal file
3597
src/osx/carbon/morefile/MoreFilesExtras.h
Normal file
File diff suppressed because it is too large
Load Diff
109
src/osx/carbon/morefile/Optimization.h
Normal file
109
src/osx/carbon/morefile/Optimization.h
Normal 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
|
||||
56
src/osx/carbon/morefile/OptimizationEnd.h
Normal file
56
src/osx/carbon/morefile/OptimizationEnd.h
Normal 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
|
||||
1300
src/osx/carbon/morefile/Search.c
Normal file
1300
src/osx/carbon/morefile/Search.c
Normal file
File diff suppressed because it is too large
Load Diff
304
src/osx/carbon/morefile/Search.h
Normal file
304
src/osx/carbon/morefile/Search.h
Normal 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__ */
|
||||
|
||||
2782
src/osx/carbon/morefilex/MoreFilesX.c
Normal file
2782
src/osx/carbon/morefilex/MoreFilesX.c
Normal file
File diff suppressed because it is too large
Load Diff
2772
src/osx/carbon/morefilex/MoreFilesX.cpp
Normal file
2772
src/osx/carbon/morefilex/MoreFilesX.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1825
src/osx/carbon/morefilex/MoreFilesX.h
Normal file
1825
src/osx/carbon/morefilex/MoreFilesX.h
Normal file
File diff suppressed because it is too large
Load Diff
125
src/osx/carbon/morefilex/MoreFilesXReadMe.txt
Normal file
125
src/osx/carbon/morefilex/MoreFilesXReadMe.txt
Normal 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
284
src/osx/carbon/msgdlg.cpp
Normal 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, ¶m, &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;
|
||||
}
|
||||
1689
src/osx/carbon/nonownedwnd.cpp
Normal file
1689
src/osx/carbon/nonownedwnd.cpp
Normal file
File diff suppressed because it is too large
Load Diff
621
src/osx/carbon/notebmac.cpp
Normal file
621
src/osx/carbon/notebmac.cpp
Normal 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
185
src/osx/carbon/overlay.cpp
Normal 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
155
src/osx/carbon/palette.cpp
Normal 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
308
src/osx/carbon/pen.cpp
Normal 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;
|
||||
}
|
||||
59
src/osx/carbon/popupwin.cpp
Normal file
59
src/osx/carbon/popupwin.cpp
Normal 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
292
src/osx/carbon/printdlg.cpp
Normal 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
620
src/osx/carbon/printmac.cpp
Normal 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
527
src/osx/carbon/radiobox.cpp
Normal 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
178
src/osx/carbon/radiobut.cpp
Normal 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
Reference in New Issue
Block a user