summaryrefslogtreecommitdiff
path: root/vcl
diff options
context:
space:
mode:
Diffstat (limited to 'vcl')
-rw-r--r--vcl/aqua/inc/salobj.h1
-rwxr-xr-xvcl/aqua/source/gdi/salatslayout.cxx5
-rw-r--r--vcl/aqua/source/window/salobj.cxx6
-rw-r--r--vcl/inc/vcl/arrange.hxx56
-rw-r--r--vcl/inc/vcl/pdfwriter.hxx87
-rw-r--r--vcl/inc/vcl/prndlg.hxx10
-rw-r--r--vcl/inc/vcl/salframe.hxx1
-rw-r--r--vcl/inc/vcl/salobj.hxx2
-rw-r--r--vcl/inc/vcl/svdata.hxx2
-rw-r--r--vcl/inc/vcl/window.h9
-rwxr-xr-x[-rw-r--r--]vcl/inc/vcl/window.hxx72
-rw-r--r--vcl/inc/vcl/wpropset.hxx66
-rw-r--r--vcl/os2/inc/salobj.h1
-rw-r--r--vcl/os2/source/window/salobj.cxx6
-rw-r--r--vcl/prj/d.lst4
-rw-r--r--[-rwxr-xr-x]vcl/source/app/settings.cxx0
-rw-r--r--vcl/source/app/svdata.cxx3
-rw-r--r--vcl/source/gdi/metaact.cxx40
-rw-r--r--vcl/source/gdi/pdfwriter.cxx24
-rw-r--r--vcl/source/gdi/pdfwriter_impl.cxx610
-rw-r--r--vcl/source/gdi/pdfwriter_impl.hxx172
-rw-r--r--vcl/source/gdi/pdfwriter_impl2.cxx507
-rw-r--r--vcl/source/gdi/pngread.cxx28
-rw-r--r--vcl/source/gdi/print2.cxx1
-rw-r--r--vcl/source/window/arrange.cxx234
-rw-r--r--vcl/source/window/makefile.mk2
-rw-r--r--vcl/source/window/printdlg.cxx191
-rwxr-xr-xvcl/source/window/window.cxx14
-rw-r--r--vcl/source/window/window4.cxx224
-rw-r--r--vcl/source/window/wpropset.cxx346
-rw-r--r--vcl/unx/gtk/window/gtkobject.cxx5
-rw-r--r--vcl/unx/headless/svpdummies.cxx1
-rw-r--r--vcl/unx/headless/svpdummies.hxx2
-rw-r--r--vcl/unx/inc/plugins/gtk/gtkobject.hxx1
-rw-r--r--vcl/unx/inc/salobj.h1
-rw-r--r--vcl/unx/source/gdi/salprnpsp.cxx11
-rw-r--r--vcl/unx/source/window/salobj.cxx7
-rw-r--r--vcl/win/inc/saldata.hxx1
-rw-r--r--vcl/win/inc/salobj.h2
-rw-r--r--vcl/win/source/app/salinst.cxx15
-rw-r--r--vcl/win/source/gdi/salprn.cxx15
-rw-r--r--vcl/win/source/window/salobj.cxx50
42 files changed, 2019 insertions, 816 deletions
diff --git a/vcl/aqua/inc/salobj.h b/vcl/aqua/inc/salobj.h
index 0041b22c16a0..56b07cea4262 100644
--- a/vcl/aqua/inc/salobj.h
+++ b/vcl/aqua/inc/salobj.h
@@ -81,6 +81,7 @@ public:
virtual void SetBackground();
virtual void SetBackground( SalColor nSalColor );
virtual const SystemEnvData* GetSystemData() const;
+ virtual void InterceptChildWindowKeyDown( sal_Bool bIntercept );
};
#endif // _SV_SALOBJ_H
diff --git a/vcl/aqua/source/gdi/salatslayout.cxx b/vcl/aqua/source/gdi/salatslayout.cxx
index 335505de85ac..a355ff86d00e 100755
--- a/vcl/aqua/source/gdi/salatslayout.cxx
+++ b/vcl/aqua/source/gdi/salatslayout.cxx
@@ -754,9 +754,10 @@ int ATSLayout::GetTextBreak( long nMaxWidth, long nCharExtra, int nFactor ) cons
// initial measurement of text break position
UniCharArrayOffset nBreakPos = mnMinCharPos;
const ATSUTextMeasurement nATSUMaxWidth = Vcl2Fixed( nPixelWidth );
+ if( nATSUMaxWidth <= 0xFFFF ) // #i108584# avoid ATSU rejecting the parameter
+ return mnMinCharPos; // or do ATSUMaxWidth=0x10000;
OSStatus eStatus = ATSUBreakLine( maATSULayout, mnMinCharPos,
nATSUMaxWidth, false, &nBreakPos );
-
if( (eStatus != noErr) && (eStatus != kATSULineBreakInWord) )
return STRING_LEN;
@@ -781,7 +782,7 @@ int ATSLayout::GetTextBreak( long nMaxWidth, long nCharExtra, int nFactor ) cons
if( eStatus != noErr )
return nBreakPos;
const ATSUTextMeasurement nATSURemWidth = nATSUMaxWidth - (nRight - nLeft);
- if( nATSURemWidth <= 0 )
+ if( nATSURemWidth <= 0xFFFF ) // #i108584# avoid ATSU rejecting the parameter
return nBreakPos;
UniCharArrayOffset nBreakPosInWord = nBreakPos;
eStatus = ATSUBreakLine( maATSULayout, nBreakPos, nATSURemWidth, false, &nBreakPosInWord );
diff --git a/vcl/aqua/source/window/salobj.cxx b/vcl/aqua/source/window/salobj.cxx
index 07d337dcc81a..f300929f04fe 100644
--- a/vcl/aqua/source/window/salobj.cxx
+++ b/vcl/aqua/source/window/salobj.cxx
@@ -237,3 +237,9 @@ const SystemEnvData* AquaSalObject::GetSystemData() const
return &maSysData;
}
+// -----------------------------------------------------------------------
+
+void AquaSalObject::InterceptChildWindowKeyDown( sal_Bool /*bIntercept*/ )
+{
+}
+
diff --git a/vcl/inc/vcl/arrange.hxx b/vcl/inc/vcl/arrange.hxx
index f98197231be9..327494b216e4 100644
--- a/vcl/inc/vcl/arrange.hxx
+++ b/vcl/inc/vcl/arrange.hxx
@@ -76,11 +76,13 @@ namespace vcl
Element( Window* i_pWin,
boost::shared_ptr<WindowArranger> const & i_pChild = boost::shared_ptr<WindowArranger>(),
- sal_Int32 i_nExpandPriority = 0
+ sal_Int32 i_nExpandPriority = 0,
+ const Size& i_rMinSize = Size()
)
: m_pElement( i_pWin )
, m_pChild( i_pChild )
, m_nExpandPriority( i_nExpandPriority )
+ , m_aMinSize( i_rMinSize )
, m_bHidden( false )
, m_nLeftBorder( 0 )
, m_nTopBorder( 0 )
@@ -101,12 +103,19 @@ namespace vcl
Rectangle m_aManagedArea;
long m_nOuterBorder;
+ rtl::OUString m_aIdentifier;
+
virtual Element* getElement( size_t i_nIndex ) = 0;
const Element* getConstElement( size_t i_nIndex ) const
{ return const_cast<WindowArranger*>(this)->getElement( i_nIndex ); }
public:
+ static long getDefaultBorder();
+
+ static long getBorderValue( long nBorder )
+ { return nBorder >= 0 ? nBorder : -nBorder * getDefaultBorder(); }
+
WindowArranger( WindowArranger* i_pParent = NULL )
: m_pParentWindow( i_pParent ? i_pParent->m_pParentWindow : NULL )
, m_pParentArranger( i_pParent )
@@ -141,6 +150,9 @@ namespace vcl
virtual bool isVisible() const; // true if any element is visible
+ virtual com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValue > getProperties() const;
+ virtual void setProperties( const com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValue >& );
+
sal_Int32 getExpandPriority( size_t i_nIndex ) const
{
const Element* pEle = getConstElement( i_nIndex );
@@ -173,6 +185,19 @@ namespace vcl
}
}
+ void getBorders( size_t i_nIndex, long* i_pLeft = NULL, long* i_pTop = NULL, long* i_pRight = NULL, long* i_pBottom = NULL ) const
+ {
+ const Element* pEle = getConstElement( i_nIndex );
+ if( pEle )
+ {
+ if( i_pLeft ) *i_pLeft = pEle->m_nLeftBorder;
+ if( i_pTop ) *i_pTop = pEle->m_nTopBorder;
+ if( i_pRight ) *i_pRight = pEle->m_nRightBorder;
+ if( i_pBottom ) *i_pBottom = pEle->m_nBottomBorder;
+ }
+ }
+
+
void show( bool i_bShow = true, bool i_bImmediateUpdate = true );
void setManagedArea( const Rectangle& i_rArea )
@@ -187,6 +212,12 @@ namespace vcl
m_nOuterBorder = i_nBorder;
resize();
}
+
+ const rtl::OUString getIdentifier() const
+ { return m_aIdentifier; }
+
+ void setIdentifier( const rtl::OUString& i_rId )
+ { m_aIdentifier = i_rId; }
};
class VCL_DLLPUBLIC RowOrColumn : public WindowArranger
@@ -204,7 +235,7 @@ namespace vcl
public:
RowOrColumn( WindowArranger* i_pParent = NULL,
- bool bColumn = true, long i_nBorderWidth = 5 )
+ bool bColumn = true, long i_nBorderWidth = -1 )
: WindowArranger( i_pParent )
, m_nBorderWidth( i_nBorderWidth )
, m_bColumn( bColumn )
@@ -218,7 +249,7 @@ namespace vcl
// add a managed window at the given index
// an index smaller than zero means add the window at the end
- size_t addWindow( Window*, sal_Int32 i_nExpandPrio = 0, size_t i_nIndex = ~0 );
+ size_t addWindow( Window*, sal_Int32 i_nExpandPrio = 0, const Size& i_rMinSize = Size(), size_t i_nIndex = ~0 );
void remove( Window* );
size_t addChild( boost::shared_ptr<WindowArranger> const &, sal_Int32 i_nExpandPrio = 0, size_t i_nIndex = ~0 );
@@ -248,7 +279,7 @@ namespace vcl
}
public:
- LabeledElement( WindowArranger* i_pParent = NULL, int i_nLabelStyle = 0, long i_nDistance = 5 )
+ LabeledElement( WindowArranger* i_pParent = NULL, int i_nLabelStyle = 0, long i_nDistance = -1 )
: WindowArranger( i_pParent )
, m_nDistance( i_nDistance )
, m_nLabelColumnWidth( 0 )
@@ -278,7 +309,7 @@ namespace vcl
{
long getLabelWidth() const;
public:
- LabelColumn( WindowArranger* i_pParent = NULL, long i_nBorderWidth = 5 )
+ LabelColumn( WindowArranger* i_pParent = NULL, long i_nBorderWidth = -1 )
: RowOrColumn( i_pParent, true, i_nBorderWidth )
{}
virtual ~LabelColumn();
@@ -288,7 +319,7 @@ namespace vcl
// returns the index of the added label
size_t addRow( Window* i_pLabel, boost::shared_ptr<WindowArranger> const& i_rElement, long i_nIndent = 0 );
- size_t addRow( Window* i_pLabel, Window* i_pElement, long i_nIndent = 0 );
+ size_t addRow( Window* i_pLabel, Window* i_pElement, long i_nIndent = 0, const Size& i_rElementMinSize = Size() );
};
class VCL_DLLPUBLIC Indenter : public WindowArranger
@@ -301,7 +332,7 @@ namespace vcl
{ return i_nIndex == 0 ? &m_aElement : NULL; }
public:
- Indenter( WindowArranger* i_pParent = NULL, long i_nIndent = 15 )
+ Indenter( WindowArranger* i_pParent = NULL, long i_nIndent = 3*getDefaultBorder() )
: WindowArranger( i_pParent )
, m_nIndent( i_nIndent )
{}
@@ -370,9 +401,10 @@ namespace vcl
MatrixElement( Window* i_pWin,
sal_uInt32 i_nX, sal_uInt32 i_nY,
boost::shared_ptr<WindowArranger> const & i_pChild = boost::shared_ptr<WindowArranger>(),
- sal_Int32 i_nExpandPriority = 0
+ sal_Int32 i_nExpandPriority = 0,
+ const Size& i_rMinSize = Size()
)
- : WindowArranger::Element( i_pWin, i_pChild, i_nExpandPriority )
+ : WindowArranger::Element( i_pWin, i_pChild, i_nExpandPriority, i_rMinSize )
, m_nX( i_nX )
, m_nY( i_nY )
{
@@ -397,8 +429,8 @@ namespace vcl
public:
MatrixArranger( WindowArranger* i_pParent = NULL,
- long i_nBorderX = 5,
- long i_nBorderY = 5 )
+ long i_nBorderX = -1,
+ long i_nBorderY = -1 )
: WindowArranger( i_pParent )
, m_nBorderX( i_nBorderX )
, m_nBorderY( i_nBorderY )
@@ -411,7 +443,7 @@ namespace vcl
virtual size_t countElements() const { return m_aElements.size(); }
// add a managed window at the given matrix position
- size_t addWindow( Window*, sal_uInt32 i_nX, sal_uInt32 i_nY, sal_Int32 i_nExpandPrio = 0 );
+ size_t addWindow( Window*, sal_uInt32 i_nX, sal_uInt32 i_nY, sal_Int32 i_nExpandPrio = 0, const Size& i_rMinSize = Size() );
void remove( Window* );
size_t addChild( boost::shared_ptr<WindowArranger> const &, sal_uInt32 i_nX, sal_uInt32 i_nY, sal_Int32 i_nExpandPrio = 0 );
diff --git a/vcl/inc/vcl/pdfwriter.hxx b/vcl/inc/vcl/pdfwriter.hxx
index 27dbbfc80c72..52e4b5014120 100644
--- a/vcl/inc/vcl/pdfwriter.hxx
+++ b/vcl/inc/vcl/pdfwriter.hxx
@@ -38,7 +38,8 @@
#include <vcl/font.hxx>
#include <vcl/graphictools.hxx>
-#include <com/sun/star/io/XOutputStream.hpp>
+#include "com/sun/star/io/XOutputStream.hpp"
+#include "com/sun/star/beans/XMaterialHolder.hpp"
#include <list>
#include <vector>
@@ -64,16 +65,6 @@ namespace vcl
class PDFExtOutDevData;
-struct PDFDocInfo
-{
- String Title; // document title
- String Author; // document author
- String Subject; // subject
- String Keywords; // keywords
- String Creator; // application that created the original document
- String Producer; // OpenOffice
-};
-
struct PDFNote
{
String Title; // optional title for the popup containing the note
@@ -471,7 +462,7 @@ public:
FitVisible,
ActionZoom
};
-// These emuns are treated as integer while reading/writing to configuration
+// These enums are treated as integer while reading/writing to configuration
enum PDFPageLayout
{
DefaultLayout,
@@ -492,20 +483,35 @@ public:
/*
The following structure describes the permissions used in PDF security
*/
- struct PDFSecPermissions
+ struct PDFEncryptionProperties
{
-//for both 40 and 128 bit security, see 3.5.2 PDF v 1.4 table 3.15, v 1.5 and v 1.6 table 3.20.
- bool CanPrintTheDocument;
+
+ bool Security128bit; // true to select 128 bit encryption, false for 40 bit
+ //for both 40 and 128 bit security, see 3.5.2 PDF v 1.4 table 3.15, v 1.5 and v 1.6 table 3.20.
+ bool CanPrintTheDocument;
bool CanModifyTheContent;
bool CanCopyOrExtract;
bool CanAddOrModify;
-//for revision 3 (bit 128 security) only
+ //for revision 3 (bit 128 security) only
bool CanFillInteractive;
bool CanExtractForAccessibility;
bool CanAssemble;
bool CanPrintFull;
-//permission default set for 128 bit, accessibility only
- PDFSecPermissions() :
+
+ // encryption will only happen if EncryptionKey is not empty
+ // EncryptionKey is actually a construct out of OValue, UValue and DocumentIdentifier
+ // if these do not match, behavior is undefined, most likely an invalid PDF will be produced
+ // OValue, UValue, EncryptionKey and DocumentIdentifier can be computed from
+ // PDFDocInfo, Owner password and User password used the InitEncryption method which
+ // implements the algorithms described in the PDF reference chapter 3.5: Encryption
+ std::vector<sal_uInt8> OValue;
+ std::vector<sal_uInt8> UValue;
+ std::vector<sal_uInt8> EncryptionKey;
+ std::vector<sal_uInt8> DocumentIdentifier;
+
+ //permission default set for 128 bit, accessibility only
+ PDFEncryptionProperties() :
+ Security128bit ( true ),
CanPrintTheDocument ( false ),
CanModifyTheContent ( false ),
CanCopyOrExtract ( false ),
@@ -515,6 +521,20 @@ The following structure describes the permissions used in PDF security
CanAssemble ( false ),
CanPrintFull ( false )
{}
+
+
+ bool Encrypt() const
+ { return ! OValue.empty() && ! UValue.empty() && ! DocumentIdentifier.empty(); }
+ };
+
+ struct PDFDocInfo
+ {
+ String Title; // document title
+ String Author; // document author
+ String Subject; // subject
+ String Keywords; // keywords
+ String Creator; // application that created the original document
+ String Producer; // OpenOffice
};
struct PDFWriterContext
@@ -573,12 +593,8 @@ The following structure describes the permissions used in PDF security
sal_Int32 InitialPage;
sal_Int32 OpenBookmarkLevels; // -1 means all levels
- struct PDFSecPermissions AccessPermissions;
-
- bool Encrypt; // main encryption flag, must be true to encript
- bool Security128bit; // true to select 128 bit encryption, false for 40 bit
- rtl::OUString OwnerPassword; // owner password for PDF, in clear text
- rtl::OUString UserPassword; // user password for PDF, in clear text
+ PDFWriter::PDFEncryptionProperties Encryption;
+ PDFWriter::PDFDocInfo DocumentInfo;
com::sun::star::lang::Locale DocumentLocale; // defines the document default language
sal_uInt32 DPIx, DPIy; // how to handle MapMode( MAP_PIXEL )
@@ -609,15 +625,13 @@ The following structure describes the permissions used in PDF security
FirstPageLeft( false ),
InitialPage( 1 ),
OpenBookmarkLevels( -1 ),
- AccessPermissions( ),
- Encrypt( false ),
- Security128bit( true ),
+ Encryption(),
DPIx( 0 ),
DPIy( 0 )
{}
};
- PDFWriter( const PDFWriterContext& rContext );
+ PDFWriter( const PDFWriterContext& rContext, const com::sun::star::uno::Reference< com::sun::star::beans::XMaterialHolder >& );
~PDFWriter();
/** Returns an OutputDevice for formatting
@@ -661,17 +675,6 @@ The following structure describes the permissions used in PDF security
};
void PlayMetafile( const GDIMetaFile&, const PlayMetafileContext&, vcl::PDFExtOutDevData* pDevDat = NULL );
- /*
- * set document info; due to the use of document information in building the PDF document ID, must be called before
- * emitting anything.
- */
- void SetDocInfo( const PDFDocInfo& rInfo );
-
- /*
- * get currently set document info
- */
- const PDFDocInfo& GetDocInfo() const;
-
/* sets the document locale originally passed with the context to a new value
* only affects the output if used before calling <code>Emit/code>.
*/
@@ -689,6 +692,12 @@ The following structure describes the permissions used in PDF security
PDFVersion GetVersion() const;
+ static com::sun::star::uno::Reference< com::sun::star::beans::XMaterialHolder >
+ InitEncryption( const rtl::OUString& i_rOwnerPassword,
+ const rtl::OUString& i_rUserPassword,
+ bool b128Bit
+ );
+
/* functions for graphics state */
/* flag values: see vcl/outdev.hxx */
void Push( USHORT nFlags = 0xffff );
diff --git a/vcl/inc/vcl/prndlg.hxx b/vcl/inc/vcl/prndlg.hxx
index d53354c40b4a..1d16a2241485 100644
--- a/vcl/inc/vcl/prndlg.hxx
+++ b/vcl/inc/vcl/prndlg.hxx
@@ -128,7 +128,6 @@ namespace vcl
// border around each page
CheckBox maBorderCB;
- vcl::RowOrColumn maLayout;
boost::shared_ptr< vcl::RowOrColumn > mxBrochureDep;
boost::shared_ptr< vcl::LabeledElement >mxPagesBtnLabel;
@@ -144,7 +143,7 @@ namespace vcl
void showAdvancedControls( bool );
- virtual void Resize();
+ // virtual void Resize();
};
class JobTabPage : public TabPage
@@ -176,7 +175,6 @@ namespace vcl
long mnCollateUIMode;
- vcl::RowOrColumn maLayout;
boost::shared_ptr<vcl::RowOrColumn> mxPrintRange;
boost::shared_ptr<vcl::WindowArranger> mxDetails;
@@ -186,7 +184,7 @@ namespace vcl
void readFromSettings();
void storeToSettings();
- virtual void Resize();
+ // virtual void Resize();
void setupLayout();
};
@@ -199,7 +197,6 @@ namespace vcl
CheckBox maCollateSingleJobsBox;
CheckBox maReverseOrderBox;
- vcl::RowOrColumn maLayout;
boost::shared_ptr<vcl::RowOrColumn> mxOptGroup;
OutputOptPage( Window*, const ResId& );
@@ -208,7 +205,7 @@ namespace vcl
void readFromSettings();
void storeToSettings();
- virtual void Resize();
+ // virtual void Resize();
void setupLayout();
};
@@ -253,7 +250,6 @@ namespace vcl
rtl::OUString maPrintText;
rtl::OUString maDefPrtText;
- vcl::RowOrColumn maLayout;
boost::shared_ptr<vcl::RowOrColumn> mxPreviewCtrls;
Size maDetailsCollapsedSize;
diff --git a/vcl/inc/vcl/salframe.hxx b/vcl/inc/vcl/salframe.hxx
index 08548d7dda40..d82a2099f315 100644
--- a/vcl/inc/vcl/salframe.hxx
+++ b/vcl/inc/vcl/salframe.hxx
@@ -270,7 +270,6 @@ public:
// done setting up the clipregion
virtual void EndSetClipRegion() = 0;
-
// Callbacks (indepent part in vcl/source/window/winproc.cxx)
// for default message handling return 0
void SetCallback( Window* pWindow, SALFRAMEPROC pProc )
diff --git a/vcl/inc/vcl/salobj.hxx b/vcl/inc/vcl/salobj.hxx
index e453bf5c6f87..adf0e0a3d45d 100644
--- a/vcl/inc/vcl/salobj.hxx
+++ b/vcl/inc/vcl/salobj.hxx
@@ -73,6 +73,8 @@ public:
virtual const SystemEnvData* GetSystemData() const = 0;
+ virtual void InterceptChildWindowKeyDown( sal_Bool bIntercept ) = 0;
+
void SetCallback( void* pInst, SALOBJECTPROC pProc )
{ m_pInst = pInst; m_pCallback = pProc; }
long CallCallback( USHORT nEvent, const void* pEvent )
diff --git a/vcl/inc/vcl/svdata.hxx b/vcl/inc/vcl/svdata.hxx
index a4ce806a7e8a..67aa6806be49 100644
--- a/vcl/inc/vcl/svdata.hxx
+++ b/vcl/inc/vcl/svdata.hxx
@@ -167,6 +167,8 @@ struct ImplSVAppData
BOOL mbDialogCancel; // TRUE: Alle Dialog::Execute()-Aufrufe werden mit return FALSE sofort beendet
BOOL mbNoYield; // Application::Yield will not wait for events if the queue is empty
// essentially that makes it the same as Application::Reschedule
+ long mnDefaultLayoutBorder; // default value in pixel for layout distances used
+ // in window arrangers
/** Controls whether showing any IME status window is toggled on or off.
diff --git a/vcl/inc/vcl/window.h b/vcl/inc/vcl/window.h
index ff76874de11a..73b6f1078ca9 100644
--- a/vcl/inc/vcl/window.h
+++ b/vcl/inc/vcl/window.h
@@ -99,7 +99,10 @@ namespace dnd {
class XDropTarget;
} } } } }
-namespace vcl { struct ControlLayoutData; }
+namespace vcl {
+ struct ControlLayoutData;
+ struct ExtWindowImpl;
+}
@@ -237,6 +240,7 @@ public:
ImplDelData* mpFirstDel;
void* mpUserData;
+ vcl::ExtWindowImpl* mpExtImpl;
Cursor* mpCursor;
Pointer maPointer;
Fraction maZoom;
@@ -353,7 +357,8 @@ public:
mbDisableAccessibleLabelForRelation:1,
mbDisableAccessibleLabeledByRelation:1,
mbHelpTextDynamic:1,
- mbFakeFocusSet:1;
+ mbFakeFocusSet:1,
+ mbInterceptChildWindowKeyDown:1;
::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > mxDNDListenerContainer;
};
diff --git a/vcl/inc/vcl/window.hxx b/vcl/inc/vcl/window.hxx
index d209becfb4ae..fa136f6d514d 100644..100755
--- a/vcl/inc/vcl/window.hxx
+++ b/vcl/inc/vcl/window.hxx
@@ -50,6 +50,7 @@
#include <rtl/ustring.hxx>
#include <cppuhelper/weakref.hxx>
#include <com/sun/star/uno/Reference.hxx>
+#include <boost/shared_ptr.hpp>
class VirtualDevice;
struct ImplDelData;
@@ -94,6 +95,13 @@ namespace accessibility {
namespace com {
namespace sun {
namespace star {
+namespace beans {
+ struct PropertyValue;
+}}}}
+
+namespace com {
+namespace sun {
+namespace star {
namespace rendering {
class XCanvas;
class XSpriteCanvas;
@@ -121,7 +129,11 @@ namespace dnd {
class XDropTarget;
} } } } }
-namespace vcl { struct ControlLayoutData; }
+namespace vcl {
+ struct ControlLayoutData;
+ class WindowArranger;
+ struct ExtWindowImpl;
+}
namespace svt { class PopupWindowControllerImpl; }
@@ -475,6 +487,10 @@ public:
SAL_DLLPRIVATE BOOL ImplUpdatePos();
SAL_DLLPRIVATE void ImplUpdateSysObjPos();
SAL_DLLPRIVATE WindowImpl* ImplGetWindowImpl() const { return mpWindowImpl; }
+ SAL_DLLPRIVATE void ImplFreeExtWindowImpl();
+ // creates ExtWindowImpl on demand, but may return NULL (e.g. if mbInDtor)
+ SAL_DLLPRIVATE vcl::ExtWindowImpl* ImplGetExtWindowImpl() const;
+ SAL_DLLPRIVATE void ImplDeleteOwnedChildren();
/** check whether a font is suitable for UI
The font to be tested will be checked whether it could display a
@@ -540,6 +556,7 @@ public:
SAL_DLLPRIVATE BOOL ImplRegisterAccessibleNativeFrame();
SAL_DLLPRIVATE void ImplRevokeAccessibleNativeFrame();
SAL_DLLPRIVATE void ImplCallResize();
+ SAL_DLLPRIVATE void ImplExtResize();
SAL_DLLPRIVATE void ImplCallMove();
SAL_DLLPRIVATE Rectangle ImplOutputToUnmirroredAbsoluteScreenPixel( const Rectangle& rRect ) const;
SAL_DLLPRIVATE void ImplMirrorFramePos( Point &pt ) const;
@@ -1097,8 +1114,61 @@ public:
*/
void doLazyDelete();
+ // let the window intercept the KeyDown messages of the system children
+ void InterceptChildWindowKeyDown( sal_Bool bIntercept );
+
virtual XubString GetSurroundingText() const;
virtual Selection GetSurroundingTextSelection() const;
+
+ // ExtImpl
+
+ // layouting
+ boost::shared_ptr< vcl::WindowArranger > getLayout();
+
+ /* add a child Window
+ addWindow will do the following things
+ - insert the passed window into the child list (equivalent to i_pWin->SetParent( this ))
+ - mark the window as "owned", meaning that the added Window will be destroyed by
+ the parent's desctructor.
+ This means: do not pass in member windows or stack objects here. Do not cause
+ the destructor of the added window to be called in any way.
+
+ to avoid ownership pass i_bTakeOwnership as "false"
+ */
+ void addWindow( Window* i_pWin, bool i_bTakeOwnership = true );
+
+ /* remove a child Window
+ the remove window functions will
+ - reparent the searched window (equivalent to i_pWin->SetParent( i_pNewParent ))
+ - return a pointer to the removed window or NULL if i_pWin was not found
+ caution: ownership passes to the new parent or the caller, if the new parent was NULL
+ */
+ Window* removeWindow( Window* i_pWin, Window* i_pNewParent = NULL );
+
+ /* return the identifier of this window
+ */
+ const rtl::OUString& getIdentifier() const;
+ /* set an identifier
+ identifiers have only loosely defined rules per se
+ in context of Window they must be unique over the window
+ hierarchy you'd like to find them again using the findWindow method
+ */
+ void setIdentifier( const rtl::OUString& );
+
+ /* returns the first found descendant that matches
+ the passed identifier or NULL
+ */
+ Window* findWindow( const rtl::OUString& ) const;
+
+ /* get/set properties
+ this will contain window properties (like visible, enabled)
+ as well as properties of derived classes (e.g. text of Edit fields)
+ */
+ virtual com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValue > getProperties() const;
+ /*
+ */
+ virtual void setProperties( const com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValue >& );
+
};
diff --git a/vcl/inc/vcl/wpropset.hxx b/vcl/inc/vcl/wpropset.hxx
new file mode 100644
index 000000000000..409b629496e6
--- /dev/null
+++ b/vcl/inc/vcl/wpropset.hxx
@@ -0,0 +1,66 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef VCL_WPROPSET_HXX
+#define VCL_WPROPSET_HXX
+
+#include "vcl/dllapi.h"
+
+#include "tools/link.hxx"
+#include "vcl/arrange.hxx"
+
+#include "com/sun/star/beans/XPropertySet.hpp"
+
+class VclWindowEvent;
+
+namespace vcl
+{
+ class WindowPropertySetData;
+ class WindowPropertySetListener;
+
+ class VCL_DLLPUBLIC WindowPropertySet
+ {
+ WindowPropertySetData* mpImpl;
+
+ void addWindowToSet( Window* );
+ void addLayoutToSet( const boost::shared_ptr<WindowArranger>& );
+ void setupProperties();
+
+ DECL_LINK( ChildEventListener, VclWindowEvent* );
+
+ void propertyChange( const com::sun::star::beans::PropertyChangeEvent& );
+ friend class vcl::WindowPropertySetListener;
+
+ public:
+ WindowPropertySet( Window* i_pTopWindow, bool i_bTakeOwnership );
+ ~WindowPropertySet();
+
+ com::sun::star::uno::Reference< com::sun::star::beans::XPropertySet > getPropertySet() const;
+ };
+}
+
+#endif
diff --git a/vcl/os2/inc/salobj.h b/vcl/os2/inc/salobj.h
index 5b4ac21ccdd6..04fdef90bf67 100644
--- a/vcl/os2/inc/salobj.h
+++ b/vcl/os2/inc/salobj.h
@@ -64,6 +64,7 @@ public:
virtual void SetBackground();
virtual void SetBackground( SalColor nSalColor );
virtual const SystemEnvData* GetSystemData() const;
+ virtual void InterceptChildWindowKeyDown( sal_Bool bIntercept );
};
#endif // _SV_SALOBJ_H
diff --git a/vcl/os2/source/window/salobj.cxx b/vcl/os2/source/window/salobj.cxx
index 85ed1a606d08..e55ce448f7d0 100644
--- a/vcl/os2/source/window/salobj.cxx
+++ b/vcl/os2/source/window/salobj.cxx
@@ -566,3 +566,9 @@ void Os2SalObject::SetCallback( void* pInst, SALOBJECTPROC pProc )
}
#endif
+// -----------------------------------------------------------------------
+
+void Os2SalObject::InterceptChildWindowKeyDown( sal_Bool /*bIntercept*/ )
+{
+}
+
diff --git a/vcl/prj/d.lst b/vcl/prj/d.lst
index 9e6d39d925c0..196bdeb19c0e 100644
--- a/vcl/prj/d.lst
+++ b/vcl/prj/d.lst
@@ -23,7 +23,6 @@ mkdir: %_DEST%\inc%_EXT%\vcl
..\inc\vcl\bmpacc.hxx %_DEST%\inc%_EXT%\vcl\bmpacc.hxx
..\inc\vcl\btndlg.hxx %_DEST%\inc%_EXT%\vcl\btndlg.hxx
..\inc\vcl\button.hxx %_DEST%\inc%_EXT%\vcl\button.hxx
-..\inc\vcl\button.hxx %_DEST%\inc%_EXT%\vcl\imagebtn.hxx
..\inc\vcl\cmdevt.h %_DEST%\inc%_EXT%\vcl\cmdevt.h
..\inc\vcl\cmdevt.hxx %_DEST%\inc%_EXT%\vcl\cmdevt.hxx
..\inc\vcl\combobox.h %_DEST%\inc%_EXT%\vcl\combobox.h
@@ -154,4 +153,7 @@ mkdir: %_DEST%\inc%_EXT%\vcl
..\inc\vcl\helper.hxx %_DEST%\inc%_EXT%\vcl\helper.hxx
..\inc\vcl\strhelper.hxx %_DEST%\inc%_EXT%\vcl\strhelper.hxx
..\inc\vcl\lazydelete.hxx %_DEST%\inc%_EXT%\vcl\lazydelete.hxx
+..\inc\vcl\arrange.hxx %_DEST%\inc%_EXT%\vcl\arrange.hxx
+..\inc\vcl\wpropset.hxx %_DEST%\inc%_EXT%\vcl\wpropset.hxx
..\%__SRC%\misc\vcl.component %_DEST%\xml%_EXT%\vcl.component
+
diff --git a/vcl/source/app/settings.cxx b/vcl/source/app/settings.cxx
index b91afbbae9fe..b91afbbae9fe 100755..100644
--- a/vcl/source/app/settings.cxx
+++ b/vcl/source/app/settings.cxx
diff --git a/vcl/source/app/svdata.cxx b/vcl/source/app/svdata.cxx
index 03b0365cff63..935d2c1894ea 100644
--- a/vcl/source/app/svdata.cxx
+++ b/vcl/source/app/svdata.cxx
@@ -129,6 +129,9 @@ void ImplInitSVData()
break;
}
}
+
+ // mark default layout border as unitialized
+ pImplSVData->maAppData.mnDefaultLayoutBorder = -1;
}
// -----------------------------------------------------------------------
diff --git a/vcl/source/gdi/metaact.cxx b/vcl/source/gdi/metaact.cxx
index 8c1545758c3b..f398888a33b6 100644
--- a/vcl/source/gdi/metaact.cxx
+++ b/vcl/source/gdi/metaact.cxx
@@ -1441,19 +1441,35 @@ void MetaTextArrayAction::Read( SvStream& rIStm, ImplMetaReadData* pData )
rIStm >> mnLen;
rIStm >> nAryLen;
+ if ( mnIndex + mnLen > maStr.Len() )
+ {
+ mnIndex = 0;
+ mpDXAry = 0;
+ return;
+ }
+
if( nAryLen )
{
// #i9762#, #106172# Ensure that DX array is at least mnLen entries long
- const ULONG nIntAryLen( Max(nAryLen, static_cast<sal_uInt32>(mnLen)) );
- mpDXAry = new sal_Int32[ nIntAryLen ];
-
- ULONG i;
- for( i = 0UL; i < nAryLen; i++ )
- rIStm >> mpDXAry[ i ];
+ if ( mnLen >= nAryLen )
+ {
+ mpDXAry = new (std::nothrow)sal_Int32[ mnLen ];
+ if ( mpDXAry )
+ {
+ ULONG i;
+ for( i = 0UL; i < nAryLen; i++ )
+ rIStm >> mpDXAry[ i ];
- // #106172# setup remainder
- for( ; i < nIntAryLen; i++ )
- mpDXAry[ i ] = 0;
+ // #106172# setup remainder
+ for( ; i < mnLen; i++ )
+ mpDXAry[ i ] = 0;
+ }
+ }
+ else
+ {
+ mpDXAry = NULL;
+ return;
+ }
}
else
mpDXAry = NULL;
@@ -1465,6 +1481,12 @@ void MetaTextArrayAction::Read( SvStream& rIStm, ImplMetaReadData* pData )
sal_Unicode* pBuffer = maStr.AllocBuffer( nLen );
while ( nLen-- )
rIStm >> *pBuffer++;
+
+ if ( mnIndex + mnLen > maStr.Len() )
+ {
+ mnIndex = 0;
+ delete[] mpDXAry, mpDXAry = NULL;
+ }
}
}
diff --git a/vcl/source/gdi/pdfwriter.cxx b/vcl/source/gdi/pdfwriter.cxx
index 969bc51b3cac..23ce1dfa6169 100644
--- a/vcl/source/gdi/pdfwriter.cxx
+++ b/vcl/source/gdi/pdfwriter.cxx
@@ -38,9 +38,9 @@ PDFWriter::AnyWidget::~AnyWidget()
{
}
-PDFWriter::PDFWriter( const PDFWriter::PDFWriterContext& rContext )
+PDFWriter::PDFWriter( const PDFWriter::PDFWriterContext& rContext, const com::sun::star::uno::Reference< com::sun::star::beans::XMaterialHolder >& xEnc )
:
- pImplementation( new PDFWriterImpl( rContext, *this ) )
+ pImplementation( new PDFWriterImpl( rContext, xEnc, *this ) )
{
}
@@ -69,16 +69,6 @@ PDFWriter::PDFVersion PDFWriter::GetVersion() const
return ((PDFWriterImpl*)pImplementation)->getVersion();
}
-void PDFWriter::SetDocInfo( const PDFDocInfo& rInfo )
-{
- ((PDFWriterImpl*)pImplementation)->setDocInfo( rInfo );
-}
-
-const PDFDocInfo& PDFWriter::GetDocInfo() const
-{
- return ((PDFWriterImpl*)pImplementation)->getDocInfo();
-}
-
void PDFWriter::SetDocumentLocale( const com::sun::star::lang::Locale& rLoc )
{
((PDFWriterImpl*)pImplementation)->setDocumentLocale( rLoc );
@@ -570,7 +560,17 @@ std::set< PDFWriter::ErrorCode > PDFWriter::GetErrors()
return ((PDFWriterImpl*)pImplementation)->getErrors();
}
+com::sun::star::uno::Reference< com::sun::star::beans::XMaterialHolder >
+PDFWriter::InitEncryption( const rtl::OUString& i_rOwnerPassword,
+ const rtl::OUString& i_rUserPassword,
+ bool b128Bit
+ )
+{
+ return PDFWriterImpl::initEncryption( i_rOwnerPassword, i_rUserPassword, b128Bit );
+}
+
void PDFWriter::PlayMetafile( const GDIMetaFile& i_rMTF, const vcl::PDFWriter::PlayMetafileContext& i_rPlayContext, PDFExtOutDevData* i_pData )
{
((PDFWriterImpl*)pImplementation)->playMetafile( i_rMTF, i_pData, i_rPlayContext, NULL);
}
+
diff --git a/vcl/source/gdi/pdfwriter_impl.cxx b/vcl/source/gdi/pdfwriter_impl.cxx
index 5d75c829da8a..325ccef1c3a6 100644
--- a/vcl/source/gdi/pdfwriter_impl.cxx
+++ b/vcl/source/gdi/pdfwriter_impl.cxx
@@ -113,12 +113,10 @@ void doTestCode()
aContext.Version = PDFWriter::PDF_1_4;
aContext.Tagged = true;
aContext.InitialPage = 2;
+ aContext.DocumentInfo.Title = OUString( RTL_CONSTASCII_USTRINGPARAM( "PDF export test document" ) );
+ aContext.DocumentInfo.Producer = OUString( RTL_CONSTASCII_USTRINGPARAM( "VCL" ) );
PDFWriter aWriter( aContext );
- PDFDocInfo aDocInfo;
- aDocInfo.Title = OUString( RTL_CONSTASCII_USTRINGPARAM( "PDF export test document" ) );
- aDocInfo.Producer = OUString( RTL_CONSTASCII_USTRINGPARAM( "VCL" ) );
- aWriter.SetDocInfo( aDocInfo );
aWriter.NewPage( 595, 842 );
aWriter.BeginStructureElement( PDFWriter::Document );
// set duration of 3 sec for first page
@@ -496,6 +494,12 @@ static inline double pixelToPoint( sal_Int32 px ) { return double(px)/fDivisor;
static inline double pixelToPoint( double px ) { return px/fDivisor; }
static inline sal_Int32 pointToPixel( double pt ) { return sal_Int32(pt*fDivisor); }
+const sal_uInt8 PDFWriterImpl::s_nPadString[32] =
+{
+ 0x28, 0xBF, 0x4E, 0x5E, 0x4E, 0x75, 0x8A, 0x41, 0x64, 0x00, 0x4E, 0x56, 0xFF, 0xFA, 0x01, 0x08,
+ 0x2E, 0x2E, 0x00, 0xB6, 0xD0, 0x68, 0x3E, 0x80, 0x2F, 0x0C, 0xA9, 0xFE, 0x64, 0x53, 0x69, 0x7A
+};
+
static void appendHex( sal_Int8 nInt, OStringBuffer& rBuffer )
{
static const sal_Char pHexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7',
@@ -1693,7 +1697,9 @@ void PDFWriterImpl::PDFPage::appendWaveLine( sal_Int32 nWidth, sal_Int32 nY, sal
* class PDFWriterImpl
*/
-PDFWriterImpl::PDFWriterImpl( const PDFWriter::PDFWriterContext& rContext, PDFWriter& i_rOuterFace )
+ PDFWriterImpl::PDFWriterImpl( const PDFWriter::PDFWriterContext& rContext,
+ const com::sun::star::uno::Reference< com::sun::star::beans::XMaterialHolder >& xEnc,
+ PDFWriter& i_rOuterFace)
:
m_pReferenceDevice( NULL ),
m_aMapMode( MAP_POINT, Point(), Fraction( 1L, pointToPixel(1) ), Fraction( 1L, pointToPixel(1) ) ),
@@ -1714,9 +1720,6 @@ PDFWriterImpl::PDFWriterImpl( const PDFWriter::PDFWriterContext& rContext, PDFWr
m_aCipher( (rtlCipher)NULL ),
m_aDigest( NULL ),
m_bEncryptThisStream( false ),
- m_aDocID( 32 ),
- m_aCreationDateString( 64 ),
- m_aCreationMetaDateString( 64 ),
m_pEncryptionBuffer( NULL ),
m_nEncryptionBufferSize( 0 ),
m_bIsPDF_A1( false ),
@@ -1759,14 +1762,37 @@ PDFWriterImpl::PDFWriterImpl( const PDFWriter::PDFWriterContext& rContext, PDFWr
m_bOpen = true;
-/* prepare the cypher engine, can be done in CTOR, free in DTOR */
+ // setup DocInfo
+ setupDocInfo();
+ /* prepare the cypher engine, can be done in CTOR, free in DTOR */
m_aCipher = rtl_cipher_createARCFOUR( rtl_Cipher_ModeStream );
m_aDigest = rtl_digest_createMD5();
-/* the size of the Codec default maximum */
+ /* the size of the Codec default maximum */
checkEncryptionBufferSize( 0x4000 );
+ if( xEnc.is() )
+ prepareEncryption( xEnc );
+
+ if( m_aContext.Encryption.Encrypt() )
+ {
+ // sanity check
+ if( m_aContext.Encryption.OValue.size() != ENCRYPTED_PWD_SIZE ||
+ m_aContext.Encryption.UValue.size() != ENCRYPTED_PWD_SIZE ||
+ m_aContext.Encryption.EncryptionKey.size() != MAXIMUM_RC4_KEY_LENGTH
+ )
+ {
+ // the field lengths are invalid ? This was not setup by initEncryption.
+ // do not encrypt after all
+ m_aContext.Encryption.OValue.clear();
+ m_aContext.Encryption.UValue.clear();
+ OSL_ENSURE( 0, "encryption data failed sanity check, encryption disabled" );
+ }
+ else // setup key lengths
+ m_nAccessPermissions = computeAccessPermissions( m_aContext.Encryption, m_nKeyLength, m_nRC4KeyLength );
+ }
+
// write header
OStringBuffer aBuffer( 20 );
aBuffer.append( "%PDF-" );
@@ -1812,139 +1838,138 @@ PDFWriterImpl::~PDFWriterImpl()
rtl_freeMemory( m_pEncryptionBuffer );
}
-void PDFWriterImpl::setDocInfo( const PDFDocInfo& rInfo )
+void PDFWriterImpl::setupDocInfo()
{
- m_aDocInfo.Title = rInfo.Title;
- m_aDocInfo.Author = rInfo.Author;
- m_aDocInfo.Subject = rInfo.Subject;
- m_aDocInfo.Keywords = rInfo.Keywords;
- m_aDocInfo.Creator = rInfo.Creator;
- m_aDocInfo.Producer = rInfo.Producer;
+ std::vector< sal_uInt8 > aId;
+ computeDocumentIdentifier( aId, m_aContext.DocumentInfo, m_aCreationDateString, m_aCreationMetaDateString );
+ if( m_aContext.Encryption.DocumentIdentifier.empty() )
+ m_aContext.Encryption.DocumentIdentifier = aId;
+}
-//build the document id
+void PDFWriterImpl::computeDocumentIdentifier( std::vector< sal_uInt8 >& o_rIdentifier,
+ const vcl::PDFWriter::PDFDocInfo& i_rDocInfo,
+ rtl::OString& o_rCString1,
+ rtl::OString& o_rCString2
+ )
+{
+ o_rIdentifier.clear();
+
+ //build the document id
rtl::OString aInfoValuesOut;
OStringBuffer aID( 1024 );
- if( m_aDocInfo.Title.Len() )
- appendUnicodeTextString( m_aDocInfo.Title, aID );
- if( m_aDocInfo.Author.Len() )
- appendUnicodeTextString( m_aDocInfo.Author, aID );
- if( m_aDocInfo.Subject.Len() )
- appendUnicodeTextString( m_aDocInfo.Subject, aID );
- if( m_aDocInfo.Keywords.Len() )
- appendUnicodeTextString( m_aDocInfo.Keywords, aID );
- if( m_aDocInfo.Creator.Len() )
- appendUnicodeTextString( m_aDocInfo.Creator, aID );
- if( m_aDocInfo.Producer.Len() )
- appendUnicodeTextString( m_aDocInfo.Producer, aID );
+ if( i_rDocInfo.Title.Len() )
+ appendUnicodeTextString( i_rDocInfo.Title, aID );
+ if( i_rDocInfo.Author.Len() )
+ appendUnicodeTextString( i_rDocInfo.Author, aID );
+ if( i_rDocInfo.Subject.Len() )
+ appendUnicodeTextString( i_rDocInfo.Subject, aID );
+ if( i_rDocInfo.Keywords.Len() )
+ appendUnicodeTextString( i_rDocInfo.Keywords, aID );
+ if( i_rDocInfo.Creator.Len() )
+ appendUnicodeTextString( i_rDocInfo.Creator, aID );
+ if( i_rDocInfo.Producer.Len() )
+ appendUnicodeTextString( i_rDocInfo.Producer, aID );
TimeValue aTVal, aGMT;
oslDateTime aDT;
osl_getSystemTime( &aGMT );
osl_getLocalTimeFromSystemTime( &aGMT, &aTVal );
osl_getDateTimeFromTimeValue( &aTVal, &aDT );
- m_aCreationDateString.append( "D:" );
- m_aCreationDateString.append( (sal_Char)('0' + ((aDT.Year/1000)%10)) );
- m_aCreationDateString.append( (sal_Char)('0' + ((aDT.Year/100)%10)) );
- m_aCreationDateString.append( (sal_Char)('0' + ((aDT.Year/10)%10)) );
- m_aCreationDateString.append( (sal_Char)('0' + ((aDT.Year)%10)) );
- m_aCreationDateString.append( (sal_Char)('0' + ((aDT.Month/10)%10)) );
- m_aCreationDateString.append( (sal_Char)('0' + ((aDT.Month)%10)) );
- m_aCreationDateString.append( (sal_Char)('0' + ((aDT.Day/10)%10)) );
- m_aCreationDateString.append( (sal_Char)('0' + ((aDT.Day)%10)) );
- m_aCreationDateString.append( (sal_Char)('0' + ((aDT.Hours/10)%10)) );
- m_aCreationDateString.append( (sal_Char)('0' + ((aDT.Hours)%10)) );
- m_aCreationDateString.append( (sal_Char)('0' + ((aDT.Minutes/10)%10)) );
- m_aCreationDateString.append( (sal_Char)('0' + ((aDT.Minutes)%10)) );
- m_aCreationDateString.append( (sal_Char)('0' + ((aDT.Seconds/10)%10)) );
- m_aCreationDateString.append( (sal_Char)('0' + ((aDT.Seconds)%10)) );
-//--> i59651, we fill the Metadata date string as well, if PDF/A is requested
- if( m_bIsPDF_A1 )
- {
-// according to ISO 19005-1:2005 6.7.3 the date is corrected for
-// local time zone offset UTC only, whereas Acrobat 8 seems
-// to use the localtime notation only
-// according to a raccomandation in XMP Specification (Jan 2004, page 75)
-// the Acrobat way seems the right approach
- m_aCreationMetaDateString.append( (sal_Char)('0' + ((aDT.Year/1000)%10)) );
- m_aCreationMetaDateString.append( (sal_Char)('0' + ((aDT.Year/100)%10)) );
- m_aCreationMetaDateString.append( (sal_Char)('0' + ((aDT.Year/10)%10)) );
- m_aCreationMetaDateString.append( (sal_Char)('0' + ((aDT.Year)%10)) );
- m_aCreationMetaDateString.append( "-" );
- m_aCreationMetaDateString.append( (sal_Char)('0' + ((aDT.Month/10)%10)) );
- m_aCreationMetaDateString.append( (sal_Char)('0' + ((aDT.Month)%10)) );
- m_aCreationMetaDateString.append( "-" );
- m_aCreationMetaDateString.append( (sal_Char)('0' + ((aDT.Day/10)%10)) );
- m_aCreationMetaDateString.append( (sal_Char)('0' + ((aDT.Day)%10)) );
- m_aCreationMetaDateString.append( "T" );
- m_aCreationMetaDateString.append( (sal_Char)('0' + ((aDT.Hours/10)%10)) );
- m_aCreationMetaDateString.append( (sal_Char)('0' + ((aDT.Hours)%10)) );
- m_aCreationMetaDateString.append( ":" );
- m_aCreationMetaDateString.append( (sal_Char)('0' + ((aDT.Minutes/10)%10)) );
- m_aCreationMetaDateString.append( (sal_Char)('0' + ((aDT.Minutes)%10)) );
- m_aCreationMetaDateString.append( ":" );
- m_aCreationMetaDateString.append( (sal_Char)('0' + ((aDT.Seconds/10)%10)) );
- m_aCreationMetaDateString.append( (sal_Char)('0' + ((aDT.Seconds)%10)) );
- }
+ rtl::OStringBuffer aCreationDateString(64), aCreationMetaDateString(64);
+ aCreationDateString.append( "D:" );
+ aCreationDateString.append( (sal_Char)('0' + ((aDT.Year/1000)%10)) );
+ aCreationDateString.append( (sal_Char)('0' + ((aDT.Year/100)%10)) );
+ aCreationDateString.append( (sal_Char)('0' + ((aDT.Year/10)%10)) );
+ aCreationDateString.append( (sal_Char)('0' + ((aDT.Year)%10)) );
+ aCreationDateString.append( (sal_Char)('0' + ((aDT.Month/10)%10)) );
+ aCreationDateString.append( (sal_Char)('0' + ((aDT.Month)%10)) );
+ aCreationDateString.append( (sal_Char)('0' + ((aDT.Day/10)%10)) );
+ aCreationDateString.append( (sal_Char)('0' + ((aDT.Day)%10)) );
+ aCreationDateString.append( (sal_Char)('0' + ((aDT.Hours/10)%10)) );
+ aCreationDateString.append( (sal_Char)('0' + ((aDT.Hours)%10)) );
+ aCreationDateString.append( (sal_Char)('0' + ((aDT.Minutes/10)%10)) );
+ aCreationDateString.append( (sal_Char)('0' + ((aDT.Minutes)%10)) );
+ aCreationDateString.append( (sal_Char)('0' + ((aDT.Seconds/10)%10)) );
+ aCreationDateString.append( (sal_Char)('0' + ((aDT.Seconds)%10)) );
+
+ //--> i59651, we fill the Metadata date string as well, if PDF/A is requested
+ // according to ISO 19005-1:2005 6.7.3 the date is corrected for
+ // local time zone offset UTC only, whereas Acrobat 8 seems
+ // to use the localtime notation only
+ // according to a raccomandation in XMP Specification (Jan 2004, page 75)
+ // the Acrobat way seems the right approach
+ aCreationMetaDateString.append( (sal_Char)('0' + ((aDT.Year/1000)%10)) );
+ aCreationMetaDateString.append( (sal_Char)('0' + ((aDT.Year/100)%10)) );
+ aCreationMetaDateString.append( (sal_Char)('0' + ((aDT.Year/10)%10)) );
+ aCreationMetaDateString.append( (sal_Char)('0' + ((aDT.Year)%10)) );
+ aCreationMetaDateString.append( "-" );
+ aCreationMetaDateString.append( (sal_Char)('0' + ((aDT.Month/10)%10)) );
+ aCreationMetaDateString.append( (sal_Char)('0' + ((aDT.Month)%10)) );
+ aCreationMetaDateString.append( "-" );
+ aCreationMetaDateString.append( (sal_Char)('0' + ((aDT.Day/10)%10)) );
+ aCreationMetaDateString.append( (sal_Char)('0' + ((aDT.Day)%10)) );
+ aCreationMetaDateString.append( "T" );
+ aCreationMetaDateString.append( (sal_Char)('0' + ((aDT.Hours/10)%10)) );
+ aCreationMetaDateString.append( (sal_Char)('0' + ((aDT.Hours)%10)) );
+ aCreationMetaDateString.append( ":" );
+ aCreationMetaDateString.append( (sal_Char)('0' + ((aDT.Minutes/10)%10)) );
+ aCreationMetaDateString.append( (sal_Char)('0' + ((aDT.Minutes)%10)) );
+ aCreationMetaDateString.append( ":" );
+ aCreationMetaDateString.append( (sal_Char)('0' + ((aDT.Seconds/10)%10)) );
+ aCreationMetaDateString.append( (sal_Char)('0' + ((aDT.Seconds)%10)) );
+
sal_uInt32 nDelta = 0;
if( aGMT.Seconds > aTVal.Seconds )
{
- m_aCreationDateString.append( "-" );
+ aCreationDateString.append( "-" );
nDelta = aGMT.Seconds-aTVal.Seconds;
- if( m_bIsPDF_A1 )
- m_aCreationMetaDateString.append( "-" );
+ aCreationMetaDateString.append( "-" );
}
else if( aGMT.Seconds < aTVal.Seconds )
{
- m_aCreationDateString.append( "+" );
+ aCreationDateString.append( "+" );
nDelta = aTVal.Seconds-aGMT.Seconds;
- if( m_bIsPDF_A1 )
- m_aCreationMetaDateString.append( "+" );
+ aCreationMetaDateString.append( "+" );
}
else
{
- m_aCreationDateString.append( "Z" );
- if( m_bIsPDF_A1 )
- m_aCreationMetaDateString.append( "Z" );
+ aCreationDateString.append( "Z" );
+ aCreationMetaDateString.append( "Z" );
}
if( nDelta )
{
- m_aCreationDateString.append( (sal_Char)('0' + ((nDelta/36000)%10)) );
- m_aCreationDateString.append( (sal_Char)('0' + ((nDelta/3600)%10)) );
- m_aCreationDateString.append( "'" );
- m_aCreationDateString.append( (sal_Char)('0' + ((nDelta/600)%6)) );
- m_aCreationDateString.append( (sal_Char)('0' + ((nDelta/60)%10)) );
- if( m_bIsPDF_A1 )
- {
- m_aCreationMetaDateString.append( (sal_Char)('0' + ((nDelta/36000)%10)) );
- m_aCreationMetaDateString.append( (sal_Char)('0' + ((nDelta/3600)%10)) );
- m_aCreationMetaDateString.append( ":" );
- m_aCreationMetaDateString.append( (sal_Char)('0' + ((nDelta/600)%6)) );
- m_aCreationMetaDateString.append( (sal_Char)('0' + ((nDelta/60)%10)) );
- }
+ aCreationDateString.append( (sal_Char)('0' + ((nDelta/36000)%10)) );
+ aCreationDateString.append( (sal_Char)('0' + ((nDelta/3600)%10)) );
+ aCreationDateString.append( "'" );
+ aCreationDateString.append( (sal_Char)('0' + ((nDelta/600)%6)) );
+ aCreationDateString.append( (sal_Char)('0' + ((nDelta/60)%10)) );
+
+ aCreationMetaDateString.append( (sal_Char)('0' + ((nDelta/36000)%10)) );
+ aCreationMetaDateString.append( (sal_Char)('0' + ((nDelta/3600)%10)) );
+ aCreationMetaDateString.append( ":" );
+ aCreationMetaDateString.append( (sal_Char)('0' + ((nDelta/600)%6)) );
+ aCreationMetaDateString.append( (sal_Char)('0' + ((nDelta/60)%10)) );
}
- m_aCreationDateString.append( "'" );
- aID.append( m_aCreationDateString.getStr(), m_aCreationDateString.getLength() );
+ aCreationDateString.append( "'" );
+ aID.append( aCreationDateString.getStr(), aCreationDateString.getLength() );
aInfoValuesOut = aID.makeStringAndClear();
+ o_rCString1 = aCreationDateString.makeStringAndClear();
+ o_rCString2 = aCreationMetaDateString.makeStringAndClear();
- DBG_ASSERT( m_aDigest != NULL, "PDFWrite_Impl::setDocInfo: cannot obtain a digest object !" );
-
- m_aDocID.setLength( 0 );
- if( m_aDigest )
+ rtlDigest aDigest = rtl_digest_createMD5();
+ OSL_ENSURE( aDigest != NULL, "PDFWriterImpl::computeDocumentIdentifier: cannot obtain a digest object !" );
+ if( aDigest )
{
- osl_getSystemTime( &aGMT );
- rtlDigestError nError = rtl_digest_updateMD5( m_aDigest, &aGMT, sizeof( aGMT ) );
- if( nError == rtl_Digest_E_None )
- nError = rtl_digest_updateMD5( m_aDigest, m_aContext.URL.getStr(), m_aContext.URL.getLength()*sizeof(sal_Unicode) );
+ rtlDigestError nError = rtl_digest_updateMD5( aDigest, &aGMT, sizeof( aGMT ) );
if( nError == rtl_Digest_E_None )
- nError = rtl_digest_updateMD5( m_aDigest, aInfoValuesOut.getStr(), aInfoValuesOut.getLength() );
+ nError = rtl_digest_updateMD5( aDigest, aInfoValuesOut.getStr(), aInfoValuesOut.getLength() );
if( nError == rtl_Digest_E_None )
{
-//the binary form of the doc id is needed for encryption stuff
- rtl_digest_getMD5( m_aDigest, m_nDocID, 16 );
- for( unsigned int i = 0; i < 16; i++ )
- appendHex( m_nDocID[i], m_aDocID );
+ o_rIdentifier = std::vector< sal_uInt8 >( 16, 0 );
+ //the binary form of the doc id is needed for encryption stuff
+ rtl_digest_getMD5( aDigest, &o_rIdentifier[0], 16 );
}
}
}
@@ -1957,7 +1982,7 @@ append the string as unicode hex, encrypted if needed
inline void PDFWriterImpl::appendUnicodeTextStringEncrypt( const rtl::OUString& rInString, const sal_Int32 nInObjectNumber, OStringBuffer& rOutBuffer )
{
rOutBuffer.append( "<" );
- if( m_aContext.Encrypt )
+ if( m_aContext.Encryption.Encrypt() )
{
const sal_Unicode* pStr = rInString.getStr();
sal_Int32 nLen = rInString.getLength();
@@ -1994,7 +2019,7 @@ inline void PDFWriterImpl::appendLiteralStringEncrypt( rtl::OStringBuffer& rInSt
rOutBuffer.append( "(" );
sal_Int32 nChars = rInString.getLength();
//check for encryption, if ok, encrypt the string, then convert with appndLiteralString
- if( m_aContext.Encrypt && checkEncryptionBufferSize( nChars ) )
+ if( m_aContext.Encryption.Encrypt() && checkEncryptionBufferSize( nChars ) )
{
//encrypt the string in a buffer, then append it
enableStringEncryption( nInObjectNumber );
@@ -2384,9 +2409,6 @@ SalLayout* PDFWriterImpl::GetTextLayout( ImplLayoutArgs& rArgs, ImplFontSelectDa
sal_Int32 PDFWriterImpl::newPage( sal_Int32 nPageWidth, sal_Int32 nPageHeight, PDFWriter::Orientation eOrientation )
{
- if( m_aContext.Encrypt && m_aPages.empty() )
- initEncryption();
-
endPage();
m_nCurrentPage = m_aPages.size();
m_aPages.push_back( PDFPage(this, nPageWidth, nPageHeight, eOrientation ) );
@@ -5881,7 +5903,7 @@ bool PDFWriterImpl::emitCatalog()
}
// viewer preferences, if we had some, then emit
if( m_aContext.HideViewerToolbar ||
- ( m_aContext.Version > PDFWriter::PDF_1_3 && m_aDocInfo.Title.Len() && m_aContext.DisplayPDFDocumentTitle ) ||
+ ( m_aContext.Version > PDFWriter::PDF_1_3 && m_aContext.DocumentInfo.Title.Len() && m_aContext.DisplayPDFDocumentTitle ) ||
m_aContext.HideViewerMenubar ||
m_aContext.HideViewerWindowControls || m_aContext.FitWindow ||
m_aContext.CenterWindow || (m_aContext.FirstPageLeft && m_aContext.PageLayout == PDFWriter::ContinuousFacing ) ||
@@ -5898,7 +5920,7 @@ bool PDFWriterImpl::emitCatalog()
aLine.append( "/FitWindow true\n" );
if( m_aContext.CenterWindow )
aLine.append( "/CenterWindow true\n" );
- if( m_aContext.Version > PDFWriter::PDF_1_3 && m_aDocInfo.Title.Len() && m_aContext.DisplayPDFDocumentTitle )
+ if( m_aContext.Version > PDFWriter::PDF_1_3 && m_aContext.DocumentInfo.Title.Len() && m_aContext.DisplayPDFDocumentTitle )
aLine.append( "/DisplayDocTitle true\n" );
if( m_aContext.FirstPageLeft && m_aContext.PageLayout == PDFWriter::ContinuousFacing )
aLine.append( "/Direction/R2L\n" );
@@ -6002,40 +6024,40 @@ sal_Int32 PDFWriterImpl::emitInfoDict( )
aLine.append( nObject );
aLine.append( " 0 obj\n"
"<<" );
- if( m_aDocInfo.Title.Len() )
+ if( m_aContext.DocumentInfo.Title.Len() )
{
aLine.append( "/Title" );
- appendUnicodeTextStringEncrypt( m_aDocInfo.Title, nObject, aLine );
+ appendUnicodeTextStringEncrypt( m_aContext.DocumentInfo.Title, nObject, aLine );
aLine.append( "\n" );
}
- if( m_aDocInfo.Author.Len() )
+ if( m_aContext.DocumentInfo.Author.Len() )
{
aLine.append( "/Author" );
- appendUnicodeTextStringEncrypt( m_aDocInfo.Author, nObject, aLine );
+ appendUnicodeTextStringEncrypt( m_aContext.DocumentInfo.Author, nObject, aLine );
aLine.append( "\n" );
}
- if( m_aDocInfo.Subject.Len() )
+ if( m_aContext.DocumentInfo.Subject.Len() )
{
aLine.append( "/Subject" );
- appendUnicodeTextStringEncrypt( m_aDocInfo.Subject, nObject, aLine );
+ appendUnicodeTextStringEncrypt( m_aContext.DocumentInfo.Subject, nObject, aLine );
aLine.append( "\n" );
}
- if( m_aDocInfo.Keywords.Len() )
+ if( m_aContext.DocumentInfo.Keywords.Len() )
{
aLine.append( "/Keywords" );
- appendUnicodeTextStringEncrypt( m_aDocInfo.Keywords, nObject, aLine );
+ appendUnicodeTextStringEncrypt( m_aContext.DocumentInfo.Keywords, nObject, aLine );
aLine.append( "\n" );
}
- if( m_aDocInfo.Creator.Len() )
+ if( m_aContext.DocumentInfo.Creator.Len() )
{
aLine.append( "/Creator" );
- appendUnicodeTextStringEncrypt( m_aDocInfo.Creator, nObject, aLine );
+ appendUnicodeTextStringEncrypt( m_aContext.DocumentInfo.Creator, nObject, aLine );
aLine.append( "\n" );
}
- if( m_aDocInfo.Producer.Len() )
+ if( m_aContext.DocumentInfo.Producer.Len() )
{
aLine.append( "/Producer" );
- appendUnicodeTextStringEncrypt( m_aDocInfo.Producer, nObject, aLine );
+ appendUnicodeTextStringEncrypt( m_aContext.DocumentInfo.Producer, nObject, aLine );
aLine.append( "\n" );
}
@@ -6281,45 +6303,45 @@ sal_Int32 PDFWriterImpl::emitDocumentMetadata()
aMetadataStream.append( " <pdfaid:conformance>A</pdfaid:conformance>\n" );
aMetadataStream.append( " </rdf:Description>\n" );
//... Dublin Core properties go here
- if( m_aDocInfo.Title.Len() ||
- m_aDocInfo.Author.Len() ||
- m_aDocInfo.Subject.Len() )
+ if( m_aContext.DocumentInfo.Title.Len() ||
+ m_aContext.DocumentInfo.Author.Len() ||
+ m_aContext.DocumentInfo.Subject.Len() )
{
aMetadataStream.append( " <rdf:Description rdf:about=\"\"\n" );
aMetadataStream.append( " xmlns:dc=\"http://purl.org/dc/elements/1.1/\">\n" );
- if( m_aDocInfo.Title.Len() )
+ if( m_aContext.DocumentInfo.Title.Len() )
{
// this is according to PDF/A-1, technical corrigendum 1 (2007-04-01)
aMetadataStream.append( " <dc:title>\n" );
aMetadataStream.append( " <rdf:Alt>\n" );
aMetadataStream.append( " <rdf:li xml:lang=\"x-default\">" );
rtl::OUString aTitle;
- escapeStringXML( m_aDocInfo.Title, aTitle );
+ escapeStringXML( m_aContext.DocumentInfo.Title, aTitle );
aMetadataStream.append( OUStringToOString( aTitle, RTL_TEXTENCODING_UTF8 ) );
aMetadataStream.append( "</rdf:li>\n" );
aMetadataStream.append( " </rdf:Alt>\n" );
aMetadataStream.append( " </dc:title>\n" );
}
- if( m_aDocInfo.Author.Len() )
+ if( m_aContext.DocumentInfo.Author.Len() )
{
aMetadataStream.append( " <dc:creator>\n" );
aMetadataStream.append( " <rdf:Seq>\n" );
aMetadataStream.append( " <rdf:li>" );
rtl::OUString aAuthor;
- escapeStringXML( m_aDocInfo.Author, aAuthor );
+ escapeStringXML( m_aContext.DocumentInfo.Author, aAuthor );
aMetadataStream.append( OUStringToOString( aAuthor , RTL_TEXTENCODING_UTF8 ) );
aMetadataStream.append( "</rdf:li>\n" );
aMetadataStream.append( " </rdf:Seq>\n" );
aMetadataStream.append( " </dc:creator>\n" );
}
- if( m_aDocInfo.Subject.Len() )
+ if( m_aContext.DocumentInfo.Subject.Len() )
{
// this is according to PDF/A-1, technical corrigendum 1 (2007-04-01)
aMetadataStream.append( " <dc:description>\n" );
aMetadataStream.append( " <rdf:Alt>\n" );
aMetadataStream.append( " <rdf:li xml:lang=\"x-default\">" );
rtl::OUString aSubject;
- escapeStringXML( m_aDocInfo.Subject, aSubject );
+ escapeStringXML( m_aContext.DocumentInfo.Subject, aSubject );
aMetadataStream.append( OUStringToOString( aSubject , RTL_TEXTENCODING_UTF8 ) );
aMetadataStream.append( "</rdf:li>\n" );
aMetadataStream.append( " </rdf:Alt>\n" );
@@ -6329,24 +6351,24 @@ sal_Int32 PDFWriterImpl::emitDocumentMetadata()
}
//... PDF properties go here
- if( m_aDocInfo.Producer.Len() ||
- m_aDocInfo.Keywords.Len() )
+ if( m_aContext.DocumentInfo.Producer.Len() ||
+ m_aContext.DocumentInfo.Keywords.Len() )
{
aMetadataStream.append( " <rdf:Description rdf:about=\"\"\n" );
aMetadataStream.append( " xmlns:pdf=\"http://ns.adobe.com/pdf/1.3/\">\n" );
- if( m_aDocInfo.Producer.Len() )
+ if( m_aContext.DocumentInfo.Producer.Len() )
{
aMetadataStream.append( " <pdf:Producer>" );
rtl::OUString aProducer;
- escapeStringXML( m_aDocInfo.Producer, aProducer );
+ escapeStringXML( m_aContext.DocumentInfo.Producer, aProducer );
aMetadataStream.append( OUStringToOString( aProducer , RTL_TEXTENCODING_UTF8 ) );
aMetadataStream.append( "</pdf:Producer>\n" );
}
- if( m_aDocInfo.Keywords.Len() )
+ if( m_aContext.DocumentInfo.Keywords.Len() )
{
aMetadataStream.append( " <pdf:Keywords>" );
rtl::OUString aKeywords;
- escapeStringXML( m_aDocInfo.Keywords, aKeywords );
+ escapeStringXML( m_aContext.DocumentInfo.Keywords, aKeywords );
aMetadataStream.append( OUStringToOString( aKeywords , RTL_TEXTENCODING_UTF8 ) );
aMetadataStream.append( "</pdf:Keywords>\n" );
}
@@ -6355,11 +6377,11 @@ sal_Int32 PDFWriterImpl::emitDocumentMetadata()
aMetadataStream.append( " <rdf:Description rdf:about=\"\"\n" );
aMetadataStream.append( " xmlns:xmp=\"http://ns.adobe.com/xap/1.0/\">\n" );
- if( m_aDocInfo.Creator.Len() )
+ if( m_aContext.DocumentInfo.Creator.Len() )
{
aMetadataStream.append( " <xmp:CreatorTool>" );
rtl::OUString aCreator;
- escapeStringXML( m_aDocInfo.Creator, aCreator );
+ escapeStringXML( m_aContext.DocumentInfo.Creator, aCreator );
aMetadataStream.append( OUStringToOString( aCreator , RTL_TEXTENCODING_UTF8 ) );
aMetadataStream.append( "</xmp:CreatorTool>\n" );
}
@@ -6415,7 +6437,7 @@ bool PDFWriterImpl::emitTrailer()
sal_Int32 nSecObject = 0;
- if( m_aContext.Encrypt == true )
+ if( m_aContext.Encryption.Encrypt() )
{
//emit the security information
//must be emitted as indirect dictionary object, since
@@ -6429,16 +6451,16 @@ bool PDFWriterImpl::emitTrailer()
aLineS.append( " 0 obj\n"
"<</Filter/Standard/V " );
// check the version
- if( m_aContext.Security128bit == true )
+ if( m_aContext.Encryption.Security128bit )
aLineS.append( "2/Length 128/R 3" );
else
aLineS.append( "1/R 2" );
// emit the owner password, must not be encrypted
aLineS.append( "/O(" );
- appendLiteralString( (const sal_Char*)m_nEncryptedOwnerPassword, 32, aLineS );
+ appendLiteralString( (const sal_Char*)&m_aContext.Encryption.OValue[0], sal_Int32(m_aContext.Encryption.OValue.size()), aLineS );
aLineS.append( ")/U(" );
- appendLiteralString( (const sal_Char*)m_nEncryptedUserPassword, 32, aLineS );
+ appendLiteralString( (const sal_Char*)&m_aContext.Encryption.UValue[0], sal_Int32(m_aContext.Encryption.UValue.size()), aLineS );
aLineS.append( ")/P " );// the permission set
aLineS.append( m_nAccessPermissions );
aLineS.append( ">>\nendobj\n\n" );
@@ -6504,13 +6526,21 @@ bool PDFWriterImpl::emitTrailer()
aLine.append( nDocInfoObject );
aLine.append( " 0 R\n" );
}
- if( m_aDocID.getLength() )
+ if( ! m_aContext.Encryption.DocumentIdentifier.empty() )
{
aLine.append( "/ID [ <" );
- aLine.append( m_aDocID.getStr(), m_aDocID.getLength() );
+ for( std::vector< sal_uInt8 >::const_iterator it = m_aContext.Encryption.DocumentIdentifier.begin();
+ it != m_aContext.Encryption.DocumentIdentifier.end(); ++it )
+ {
+ appendHex( sal_Int8(*it), aLine );
+ }
aLine.append( ">\n"
"<" );
- aLine.append( m_aDocID.getStr(), m_aDocID.getLength() );
+ for( std::vector< sal_uInt8 >::const_iterator it = m_aContext.Encryption.DocumentIdentifier.begin();
+ it != m_aContext.Encryption.DocumentIdentifier.end(); ++it )
+ {
+ appendHex( sal_Int8(*it), aLine );
+ }
aLine.append( "> ]\n" );
}
if( aDocChecksum.getLength() )
@@ -7403,7 +7433,14 @@ void PDFWriterImpl::drawLayout( SalLayout& rLayout, const String& rText, bool bT
// try to handle ligatures and such
if( i < nGlyphs-1 )
{
- pUnicodesPerGlyph[i] = nChars = pCharPosAry[i+1] - pCharPosAry[i];
+ nChars = pCharPosAry[i+1] - pCharPosAry[i];
+ // #i115618# fix for simple RTL+CTL cases
+ // TODO: sanitize for RTL ligatures, more complex CTL, etc.
+ if( nChars < 0 )
+ nChars = -nChars;
+ else if( nChars == 0 )
+ nChars = 1;
+ pUnicodesPerGlyph[i] = nChars;
for( int n = 1; n < nChars; n++ )
aUnicodes.push_back( rText.GetChar( sal::static_int_cast<xub_StrLen>(pCharPosAry[i]+n) ) );
}
@@ -9661,7 +9698,7 @@ bool PDFWriterImpl::writeBitmapObject( BitmapEmit& rObject, bool bMask )
aLine.append( "[ /Indexed/DeviceRGB " );
aLine.append( (sal_Int32)(pAccess->GetPaletteEntryCount()-1) );
aLine.append( "\n<" );
- if( m_aContext.Encrypt )
+ if( m_aContext.Encryption.Encrypt() )
{
enableStringEncryption( rObject.m_nObject );
//check encryption buffer size
@@ -12047,268 +12084,5 @@ void PDFWriterImpl::addStream( const String& rMimeType, PDFOutputStream* pStream
}
}
-/*************************************************************
-begin i12626 methods
-
-Implements Algorithm 3.2, step 1 only
-*/
-void PDFWriterImpl::padPassword( rtl::OUString aPassword, sal_uInt8 *paPasswordTarget )
-{
-// get ansi-1252 version of the password string CHECKIT ! i12626
- rtl::OString aString = rtl::OUStringToOString( aPassword, RTL_TEXTENCODING_MS_1252 );
-
-//copy the string to the target
- sal_Int32 nToCopy = ( aString.getLength() < 32 ) ? aString.getLength() : 32;
- sal_Int32 nCurrentChar;
-
- for( nCurrentChar = 0; nCurrentChar < nToCopy; nCurrentChar++ )
- paPasswordTarget[nCurrentChar] = (sal_uInt8)( aString.getStr()[nCurrentChar] );
-
-//pad it
- if( nCurrentChar < 32 )
- {//fill with standard byte string
- sal_Int32 i,y;
- for( i = nCurrentChar, y = 0 ; i < 32; i++, y++ )
- paPasswordTarget[i] = m_nPadString[y];
- }
-}
-
-/**********************************
-Algorithm 3.2 Compute the encryption key used
-
-step 1 should already be done before calling, the paThePaddedPassword parameter should contain
-the padded password and must be 32 byte long, the encryption key is returned into the paEncryptionKey parameter,
-it will be 16 byte long for 128 bit security; for 40 bit security only the first 5 bytes are used
-
-TODO: in pdf ver 1.5 and 1.6 the step 6 is different, should be implemented. See spec.
-
-*/
-void PDFWriterImpl::computeEncryptionKey(sal_uInt8 *paThePaddedPassword, sal_uInt8 *paEncryptionKey )
-{
-//step 2
- if( m_aDigest )
- {
- rtlDigestError nError = rtl_digest_updateMD5( m_aDigest, paThePaddedPassword, ENCRYPTED_PWD_SIZE );
-//step 3
- if( nError == rtl_Digest_E_None )
- nError = rtl_digest_updateMD5( m_aDigest, m_nEncryptedOwnerPassword , sizeof( m_nEncryptedOwnerPassword ) );
-//Step 4
- sal_uInt8 nPerm[4];
-
- nPerm[0] = (sal_uInt8)m_nAccessPermissions;
- nPerm[1] = (sal_uInt8)( m_nAccessPermissions >> 8 );
- nPerm[2] = (sal_uInt8)( m_nAccessPermissions >> 16 );
- nPerm[3] = (sal_uInt8)( m_nAccessPermissions >> 24 );
-
- if( nError == rtl_Digest_E_None )
- nError = rtl_digest_updateMD5( m_aDigest, nPerm , sizeof( nPerm ) );
-
-//step 5, get the document ID, binary form
- if( nError == rtl_Digest_E_None )
- nError = rtl_digest_updateMD5( m_aDigest, m_nDocID , sizeof( m_nDocID ) );
-//get the digest
- sal_uInt8 nMD5Sum[ RTL_DIGEST_LENGTH_MD5 ];
- if( nError == rtl_Digest_E_None )
- {
- rtl_digest_getMD5( m_aDigest, nMD5Sum, sizeof( nMD5Sum ) );
-
-//step 6, only if 128 bit
- if( m_aContext.Security128bit )
- {
- for( sal_Int32 i = 0; i < 50; i++ )
- {
- nError = rtl_digest_updateMD5( m_aDigest, &nMD5Sum, sizeof( nMD5Sum ) );
- if( nError != rtl_Digest_E_None )
- break;
- rtl_digest_getMD5( m_aDigest, nMD5Sum, sizeof( nMD5Sum ) );
- }
- }
- }
-//Step 7
- for( sal_Int32 i = 0; i < MD5_DIGEST_SIZE; i++ )
- paEncryptionKey[i] = nMD5Sum[i];
- }
-}
-
-/**********************************
-Algorithm 3.3 Compute the encryption dictionary /O value, save into the class data member
-the step numbers down here correspond to the ones in PDF v.1.4 specfication
-*/
-void PDFWriterImpl::computeODictionaryValue()
-{
-//step 1 already done, data is in m_nPaddedOwnerPassword
-//step 2
- if( m_aDigest )
- {
- rtlDigestError nError = rtl_digest_updateMD5( m_aDigest, &m_nPaddedOwnerPassword, sizeof( m_nPaddedOwnerPassword ) );
- if( nError == rtl_Digest_E_None )
- {
- sal_uInt8 nMD5Sum[ RTL_DIGEST_LENGTH_MD5 ];
-
- rtl_digest_getMD5( m_aDigest, nMD5Sum, sizeof(nMD5Sum) );
-//step 3, only if 128 bit
- if( m_aContext.Security128bit )
- {
- sal_Int32 i;
- for( i = 0; i < 50; i++ )
- {
- nError = rtl_digest_updateMD5( m_aDigest, nMD5Sum, sizeof( nMD5Sum ) );
- if( nError != rtl_Digest_E_None )
- break;
- rtl_digest_getMD5( m_aDigest, nMD5Sum, sizeof( nMD5Sum ) );
- }
- }
-//Step 4, the key is in nMD5Sum
-//step 5 already done, data is in m_nPaddedUserPassword
-//step 6
- rtl_cipher_initARCFOUR( m_aCipher, rtl_Cipher_DirectionEncode,
- nMD5Sum, m_nKeyLength , NULL, 0 );
-// encrypt the user password using the key set above
- rtl_cipher_encodeARCFOUR( m_aCipher, m_nPaddedUserPassword, sizeof( m_nPaddedUserPassword ), // the data to be encrypted
- m_nEncryptedOwnerPassword, sizeof( m_nEncryptedOwnerPassword ) ); //encrypted data, stored in class data member
-//Step 7, only if 128 bit
- if( m_aContext.Security128bit )
- {
- sal_uInt32 i, y;
- sal_uInt8 nLocalKey[ SECUR_128BIT_KEY ]; // 16 = 128 bit key
- for( i = 1; i <= 19; i++ ) // do it 19 times, start with 1
- {
- for( y = 0; y < sizeof( nLocalKey ); y++ )
- nLocalKey[y] = (sal_uInt8)( nMD5Sum[y] ^ i );
-
- rtl_cipher_initARCFOUR( m_aCipher, rtl_Cipher_DirectionEncode,
- nLocalKey, SECUR_128BIT_KEY, NULL, 0 ); //destination data area, on init can be NULL
- rtl_cipher_encodeARCFOUR( m_aCipher, m_nEncryptedOwnerPassword, sizeof( m_nEncryptedOwnerPassword ), // the data to be encrypted
- m_nEncryptedOwnerPassword, sizeof( m_nEncryptedOwnerPassword ) ); // encrypted data, can be the same as the input, encrypt "in place"
-//step 8, store in class data member
- }
- }
- }
- }
-}
-
-/**********************************
-Algorithms 3.4 and 3.5 Compute the encryption dictionary /U value, save into the class data member, revision 2 (40 bit) or 3 (128 bit)
-*/
-void PDFWriterImpl::computeUDictionaryValue()
-{
-//step 1, common to both 3.4 and 3.5
- computeEncryptionKey( m_nPaddedUserPassword , m_nEncryptionKey );
-
- if( m_aContext.Security128bit == false )
- {
-//3.4
-//step 2 and 3
- rtl_cipher_initARCFOUR( m_aCipher, rtl_Cipher_DirectionEncode,
- m_nEncryptionKey, 5 , // key and key length
- NULL, 0 ); //destination data area
-// encrypt the user password using the key set above, save for later use
- rtl_cipher_encodeARCFOUR( m_aCipher, m_nPadString, sizeof( m_nPadString ), // the data to be encrypted
- m_nEncryptedUserPassword, sizeof( m_nEncryptedUserPassword ) ); //encrypted data, stored in class data member
- }
- else
- {
-//or 3.5, for 128 bit security
-//step6, initilize the last 16 bytes of the encrypted user password to 0
- for(sal_uInt32 i = MD5_DIGEST_SIZE; i < sizeof( m_nEncryptedUserPassword ); i++)
- m_nEncryptedUserPassword[i] = 0;
-//step 2
- if( m_aDigest )
- {
- rtlDigestError nError = rtl_digest_updateMD5( m_aDigest, m_nPadString, sizeof( m_nPadString ) );
-//step 3
- if( nError == rtl_Digest_E_None )
- nError = rtl_digest_updateMD5( m_aDigest, m_nDocID , sizeof(m_nDocID) );
-
- sal_uInt8 nMD5Sum[ RTL_DIGEST_LENGTH_MD5 ];
- rtl_digest_getMD5( m_aDigest, nMD5Sum, sizeof(nMD5Sum) );
-//Step 4
- rtl_cipher_initARCFOUR( m_aCipher, rtl_Cipher_DirectionEncode,
- m_nEncryptionKey, SECUR_128BIT_KEY, NULL, 0 ); //destination data area
- rtl_cipher_encodeARCFOUR( m_aCipher, nMD5Sum, sizeof( nMD5Sum ), // the data to be encrypted
- m_nEncryptedUserPassword, sizeof( nMD5Sum ) ); //encrypted data, stored in class data member
-//step 5
- sal_uInt32 i, y;
- sal_uInt8 nLocalKey[SECUR_128BIT_KEY];
-
- for( i = 1; i <= 19; i++ ) // do it 19 times, start with 1
- {
- for( y = 0; y < sizeof( nLocalKey ) ; y++ )
- nLocalKey[y] = (sal_uInt8)( m_nEncryptionKey[y] ^ i );
-
- rtl_cipher_initARCFOUR( m_aCipher, rtl_Cipher_DirectionEncode,
- nLocalKey, SECUR_128BIT_KEY, // key and key length
- NULL, 0 ); //destination data area, on init can be NULL
- rtl_cipher_encodeARCFOUR( m_aCipher, m_nEncryptedUserPassword, SECUR_128BIT_KEY, // the data to be encrypted
- m_nEncryptedUserPassword, SECUR_128BIT_KEY ); // encrypted data, can be the same as the input, encrypt "in place"
- }
- }
- }
-}
-
-/* init the encryption engine
-1. init the document id, used both for building the document id and for building the encryption key(s)
-2. build the encryption key following algorithms described in the PDF specification
- */
-void PDFWriterImpl::initEncryption()
-{
- m_aOwnerPassword = m_aContext.OwnerPassword;
- m_aUserPassword = m_aContext.UserPassword;
-/* password stuff computing, before sending out anything */
- DBG_ASSERT( m_aCipher != NULL, "PDFWriterImpl::initEncryption: a cipher (ARCFOUR) object is not available !" );
- DBG_ASSERT( m_aDigest != NULL, "PDFWriterImpl::initEncryption: a digest (MD5) object is not available !" );
-
- if( m_aCipher && m_aDigest )
- {
-//if there is no owner password, force it to the user password
- if( m_aOwnerPassword.getLength() == 0 )
- m_aOwnerPassword = m_aUserPassword;
-
- initPadString();
-/*
-1) pad passwords
-*/
- padPassword( m_aOwnerPassword, m_nPaddedOwnerPassword );
- padPassword( m_aUserPassword, m_nPaddedUserPassword );
-/*
-2) compute the access permissions, in numerical form
-
-the default value depends on the revision 2 (40 bit) or 3 (128 bit security):
-- for 40 bit security the unused bit must be set to 1, since they are not used
-- for 128 bit security the same bit must be preset to 0 and set later if needed
-according to the table 3.15, pdf v 1.4 */
- m_nAccessPermissions = ( m_aContext.Security128bit ) ? 0xfffff0c0 : 0xffffffc0 ;
-
-/* check permissions for 40 bit security case */
- m_nAccessPermissions |= ( m_aContext.AccessPermissions.CanPrintTheDocument ) ? 1 << 2 : 0;
- m_nAccessPermissions |= ( m_aContext.AccessPermissions.CanModifyTheContent ) ? 1 << 3 : 0;
- m_nAccessPermissions |= ( m_aContext.AccessPermissions.CanCopyOrExtract ) ? 1 << 4 : 0;
- m_nAccessPermissions |= ( m_aContext.AccessPermissions.CanAddOrModify ) ? 1 << 5 : 0;
- m_nKeyLength = SECUR_40BIT_KEY;
- m_nRC4KeyLength = SECUR_40BIT_KEY+5; // for this value see PDF spec v 1.4, algorithm 3.1 step 4, where n is 5
-
- if( m_aContext.Security128bit )
- {
- m_nKeyLength = SECUR_128BIT_KEY;
- m_nRC4KeyLength = 16; // for this value see PDF spec v 1.4, algorithm 3.1 step 4, where n is 16, thus maximum
- // permitted value is 16
- m_nAccessPermissions |= ( m_aContext.AccessPermissions.CanFillInteractive ) ? 1 << 8 : 0;
- m_nAccessPermissions |= ( m_aContext.AccessPermissions.CanExtractForAccessibility ) ? 1 << 9 : 0;
- m_nAccessPermissions |= ( m_aContext.AccessPermissions.CanAssemble ) ? 1 << 10 : 0;
- m_nAccessPermissions |= ( m_aContext.AccessPermissions.CanPrintFull ) ? 1 << 11 : 0;
- }
- computeODictionaryValue();
- computeUDictionaryValue();
-
-//clear out exceding key values, prepares for generation number default to 0 as well
-// see checkAndEnableStreamEncryption in pdfwriter_impl.hxx
- sal_Int32 i, y;
- for( i = m_nKeyLength, y = 0; y < 5 ; y++ )
- m_nEncryptionKey[i++] = 0;
- }
- else //either no cipher or no digest or both, something is wrong with memory or something else
- m_aContext.Encrypt = false; //then turn the encryption off
-}
-/* end i12626 methods */
diff --git a/vcl/source/gdi/pdfwriter_impl.hxx b/vcl/source/gdi/pdfwriter_impl.hxx
index 9457aea5f0c2..5702bee23ea5 100644
--- a/vcl/source/gdi/pdfwriter_impl.hxx
+++ b/vcl/source/gdi/pdfwriter_impl.hxx
@@ -58,6 +58,7 @@ class ImplFontSelectData;
class ImplFontMetricData;
class FontSubsetInfo;
class ZCodec;
+class EncHashTransporter;
// the maximum password length
#define ENCRYPTED_PWD_SIZE 32
@@ -595,7 +596,6 @@ private:
MapMode m_aMapMode; // PDFWriterImpl scaled units
std::vector< PDFPage > m_aPages;
- PDFDocInfo m_aDocInfo;
/* maps object numbers to file offsets (needed for xref) */
std::vector< sal_uInt64 > m_aObjects;
/* contains Bitmaps until they are written to the
@@ -796,116 +796,37 @@ i12626
/* used to cipher the stream data and for password management */
rtlCipher m_aCipher;
rtlDigest m_aDigest;
-/* pad string used for password in Standard security handler */
- sal_uInt8 m_nPadString[ENCRYPTED_PWD_SIZE];
-/* the owner password, in clear text */
- rtl::OUString m_aOwnerPassword;
-/* the padded owner password */
- sal_uInt8 m_nPaddedOwnerPassword[ENCRYPTED_PWD_SIZE];
-/* the encryption dictionary owner password, according to algorithm 3.3 */
- sal_uInt8 m_nEncryptedOwnerPassword[ENCRYPTED_PWD_SIZE];
-/* the user password, in clear text */
- rtl::OUString m_aUserPassword;
-/* the padded user password */
- sal_uInt8 m_nPaddedUserPassword[ENCRYPTED_PWD_SIZE];
-/* the encryption dictionary user password, according to algorithm 3.4 or 3.5 depending on the
- security handler revision */
- sal_uInt8 m_nEncryptedUserPassword[ENCRYPTED_PWD_SIZE];
-
-/* the encryption key, formed with the user password according to algorithm 3.2, maximum length is 16 bytes + 3 + 2
- for 128 bit security */
- sal_uInt8 m_nEncryptionKey[MAXIMUM_RC4_KEY_LENGTH];
+ /* pad string used for password in Standard security handler */
+ static const sal_uInt8 s_nPadString[ENCRYPTED_PWD_SIZE];
+
+ /* the encryption key, formed with the user password according to algorithm 3.2, maximum length is 16 bytes + 3 + 2
+ for 128 bit security */
sal_Int32 m_nKeyLength; // key length, 16 or 5
sal_Int32 m_nRC4KeyLength; // key length, 16 or 10, to be input to the algorith 3.1
-/* set to true if the following stream must be encrypted, used inside writeBuffer() */
+ /* set to true if the following stream must be encrypted, used inside writeBuffer() */
sal_Bool m_bEncryptThisStream;
-/* the numerical value of the access permissions, according to PDF spec, must be signed */
+ /* the numerical value of the access permissions, according to PDF spec, must be signed */
sal_Int32 m_nAccessPermissions;
-/* the document ID, the raw MD5 hash */
- sal_uInt8 m_nDocID[MD5_DIGEST_SIZE];
-/* string buffer to hold document ID, this is the output string */
- rtl::OStringBuffer m_aDocID;
-/* string to hold the PDF creation date */
- rtl::OStringBuffer m_aCreationDateString;
-/* string to hold the PDF creation date, for PDF/A metadata */
- rtl::OStringBuffer m_aCreationMetaDateString;
-/* the buffer where the data are encrypted, dynamically allocated */
+ /* string to hold the PDF creation date */
+ rtl::OString m_aCreationDateString;
+ /* string to hold the PDF creation date, for PDF/A metadata */
+ rtl::OString m_aCreationMetaDateString;
+ /* the buffer where the data are encrypted, dynamically allocated */
sal_uInt8 *m_pEncryptionBuffer;
-/* size of the buffer */
+ /* size of the buffer */
sal_Int32 m_nEncryptionBufferSize;
-/* check and reallocate the buffer for encryption */
- sal_Bool checkEncryptionBufferSize( register sal_Int32 newSize )
- {
- if( m_nEncryptionBufferSize < newSize )
- {
-/* reallocate the buffer, the used function allocate as rtl_allocateMemory
- if the pointer parameter is NULL */
- m_pEncryptionBuffer = (sal_uInt8*)rtl_reallocateMemory( m_pEncryptionBuffer, newSize );
- if( m_pEncryptionBuffer )
- m_nEncryptionBufferSize = newSize;
- else
- m_nEncryptionBufferSize = 0;
- }
- return ( m_nEncryptionBufferSize != 0 );
- }
-/* init the internal pad string */
- void initPadString()
- {
- static const sal_uInt8 nPadString[32] =
- {
- 0x28, 0xBF, 0x4E, 0x5E, 0x4E, 0x75, 0x8A, 0x41, 0x64, 0x00, 0x4E, 0x56, 0xFF, 0xFA, 0x01, 0x08,
- 0x2E, 0x2E, 0x00, 0xB6, 0xD0, 0x68, 0x3E, 0x80, 0x2F, 0x0C, 0xA9, 0xFE, 0x64, 0x53, 0x69, 0x7A
- };
-
- for(sal_uInt32 i = 0; i < sizeof( nPadString ); i++ )
- m_nPadString[i] = nPadString[i];
-
- };
-/* initialize the encryption engine */
- void initEncryption();
-
-/* this function implements part of the PDF spec algorithm 3.1 in encryption, the rest (the actual encryption) is in PDFWriterImpl::writeBuffer */
- void checkAndEnableStreamEncryption( register sal_Int32 nObject )
- {
- if( m_aContext.Encrypt )
- {
- m_bEncryptThisStream = true;
- register sal_Int32 i = m_nKeyLength;
- m_nEncryptionKey[i++] = (sal_uInt8)nObject;
- m_nEncryptionKey[i++] = (sal_uInt8)( nObject >> 8 );
- m_nEncryptionKey[i++] = (sal_uInt8)( nObject >> 16 );
-//the other location of m_nEncryptionKey are already set to 0, our fixed generation number
-// do the MD5 hash
- sal_uInt8 nMD5Sum[ RTL_DIGEST_LENGTH_MD5 ];
- // the i+2 to take into account the generation number, always zero
- rtl_digest_MD5( &m_nEncryptionKey, i+2, nMD5Sum, sizeof(nMD5Sum) );
-// initialize the RC4 with the key
-// key legth: see algoritm 3.1, step 4: (N+5) max 16
- rtl_cipher_initARCFOUR( m_aCipher, rtl_Cipher_DirectionEncode, nMD5Sum, m_nRC4KeyLength, NULL, 0 );
- }
- };
+ /* check and reallocate the buffer for encryption */
+ sal_Bool checkEncryptionBufferSize( register sal_Int32 newSize );
+ /* this function implements part of the PDF spec algorithm 3.1 in encryption, the rest (the actual encryption) is in PDFWriterImpl::writeBuffer */
+ void checkAndEnableStreamEncryption( register sal_Int32 nObject );
void disableStreamEncryption() { m_bEncryptThisStream = false; };
-/* */
- void enableStringEncryption( register sal_Int32 nObject )
- {
- register sal_Int32 i = m_nKeyLength;
- m_nEncryptionKey[i++] = (sal_uInt8)nObject;
- m_nEncryptionKey[i++] = (sal_uInt8)( nObject >> 8 );
- m_nEncryptionKey[i++] = (sal_uInt8)( nObject >> 16 );
-//the other location of m_nEncryptionKey are already set to 0, our fixed generation number
-// do the MD5 hash
- sal_uInt8 nMD5Sum[ RTL_DIGEST_LENGTH_MD5 ];
- // the i+2 to take into account the generation number, always zero
- rtl_digest_MD5( &m_nEncryptionKey, i+2, nMD5Sum, sizeof(nMD5Sum) );
-// initialize the RC4 with the key
-// key legth: see algoritm 3.1, step 4: (N+5) max 16
- rtl_cipher_initARCFOUR( m_aCipher, rtl_Cipher_DirectionEncode, nMD5Sum, m_nRC4KeyLength, NULL, 0 );
- };
+ /* */
+ void enableStringEncryption( register sal_Int32 nObject );
// test if the encryption is active, if yes than encrypt the unicode string and add to the OStringBuffer parameter
void appendUnicodeTextStringEncrypt( const rtl::OUString& rInString, const sal_Int32 nInObjectNumber, rtl::OStringBuffer& rOutBuffer );
@@ -1097,18 +1018,38 @@ i12626
sal_Bool m_bIsPDF_A1;
PDFWriter& m_rOuterFace;
-/*
-i12626
-methods for PDF security
-
- pad a password according algorithm 3.2, step 1 */
- void padPassword( const rtl::OUString aPassword, sal_uInt8 *paPasswordTarget );
-/* algorithm 3.2: compute an encryption key */
- void computeEncryptionKey( sal_uInt8 *paThePaddedPassword, sal_uInt8 *paEncryptionKey );
-/* algorithm 3.3: computing the encryption dictionary'ss owner password value ( /O ) */
- void computeODictionaryValue();
-/* algorithm 3.4 or 3.5: computing the encryption dictionary's user password value ( /U ) revision 2 or 3 of the standard security handler */
- void computeUDictionaryValue();
+ /*
+ i12626
+ methods for PDF security
+
+ pad a password according algorithm 3.2, step 1 */
+ static void padPassword( const rtl::OUString& i_rPassword, sal_uInt8* o_pPaddedPW );
+ /* algorithm 3.2: compute an encryption key */
+ static bool computeEncryptionKey( EncHashTransporter*,
+ vcl::PDFWriter::PDFEncryptionProperties& io_rProperties,
+ sal_Int32 i_nAccessPermissions
+ );
+ /* algorithm 3.3: computing the encryption dictionary'ss owner password value ( /O ) */
+ static bool computeODictionaryValue( const sal_uInt8* i_pPaddedOwnerPassword, const sal_uInt8* i_pPaddedUserPassword,
+ std::vector< sal_uInt8 >& io_rOValue,
+ sal_Int32 i_nKeyLength
+ );
+ /* algorithm 3.4 or 3.5: computing the encryption dictionary's user password value ( /U ) revision 2 or 3 of the standard security handler */
+ static bool computeUDictionaryValue( EncHashTransporter* i_pTransporter,
+ vcl::PDFWriter::PDFEncryptionProperties& io_rProperties,
+ sal_Int32 i_nKeyLength,
+ sal_Int32 i_nAccessPermissions
+ );
+
+ static void computeDocumentIdentifier( std::vector< sal_uInt8 >& o_rIdentifier,
+ const vcl::PDFWriter::PDFDocInfo& i_rDocInfo,
+ rtl::OString& o_rCString1,
+ rtl::OString& o_rCString2
+ );
+ static sal_Int32 computeAccessPermissions( const vcl::PDFWriter::PDFEncryptionProperties& i_rProperties,
+ sal_Int32& o_rKeyLength, sal_Int32& o_rRC4KeyLength );
+ void setupDocInfo();
+ bool prepareEncryption( const com::sun::star::uno::Reference< com::sun::star::beans::XMaterialHolder >& );
// helper for playMetafile
void implWriteGradient( const PolyPolygon& rPolyPoly, const Gradient& rGradient,
@@ -1117,9 +1058,14 @@ methods for PDF security
VirtualDevice* pDummyVDev, const vcl::PDFWriter::PlayMetafileContext& );
public:
- PDFWriterImpl( const PDFWriter::PDFWriterContext& rContext, PDFWriter& );
+ PDFWriterImpl( const PDFWriter::PDFWriterContext& rContext, const com::sun::star::uno::Reference< com::sun::star::beans::XMaterialHolder >&, PDFWriter& );
~PDFWriterImpl();
+ static com::sun::star::uno::Reference< com::sun::star::beans::XMaterialHolder >
+ initEncryption( const rtl::OUString& i_rOwnerPassword,
+ const rtl::OUString& i_rUserPassword,
+ bool b128Bit );
+
/* for OutputDevice so the reference device can have a list
* that contains only suitable fonts (subsettable or builtin)
* produces a new font list
@@ -1152,8 +1098,6 @@ public:
}
PDFWriter::PDFVersion getVersion() const { return m_aContext.Version; }
- void setDocInfo( const PDFDocInfo& rInfo );
- const PDFDocInfo& getDocInfo() const { return m_aDocInfo; }
void setDocumentLocale( const com::sun::star::lang::Locale& rLoc )
{ m_aContext.DocumentLocale = rLoc; }
diff --git a/vcl/source/gdi/pdfwriter_impl2.cxx b/vcl/source/gdi/pdfwriter_impl2.cxx
index c01b8a9771d8..ee1fe1cc6bc5 100644
--- a/vcl/source/gdi/pdfwriter_impl2.cxx
+++ b/vcl/source/gdi/pdfwriter_impl2.cxx
@@ -28,6 +28,7 @@
#include "precompiled_vcl.hxx"
#include "pdfwriter_impl.hxx"
+
#include "vcl/pdfextoutdevdata.hxx"
#include "vcl/virdev.hxx"
#include "vcl/gdimtf.hxx"
@@ -36,12 +37,16 @@
#include "vcl/svdata.hxx"
#include "unotools/streamwrap.hxx"
#include "unotools/processfactory.hxx"
-
#include "comphelper/processfactory.hxx"
+
#include "com/sun/star/beans/PropertyValue.hpp"
#include "com/sun/star/io/XSeekable.hpp"
#include "com/sun/star/graphic/XGraphicProvider.hpp"
+#include "cppuhelper/implbase1.hxx"
+
+#include <rtl/digest.h>
+
using namespace vcl;
using namespace rtl;
using namespace com::sun::star;
@@ -1032,4 +1037,504 @@ void PDFWriterImpl::playMetafile( const GDIMetaFile& i_rMtf, vcl::PDFExtOutDevDa
delete pPrivateDevice;
}
+// Encryption methods
+
+/* a crutch to transport an rtlDigest safely though UNO API
+ this is needed for the PDF export dialog, which otherwise would have to pass
+ clear text passwords down till they can be used in PDFWriter. Unfortunately
+ the MD5 sum of the password (which is needed to create the PDF encryption key)
+ is not sufficient, since an rtl MD5 digest cannot be created in an arbitrary state
+ which would be needed in PDFWriterImpl::computeEncryptionKey.
+*/
+class EncHashTransporter : public cppu::WeakImplHelper1 < com::sun::star::beans::XMaterialHolder >
+{
+ rtlDigest maUDigest;
+ sal_IntPtr maID;
+ std::vector< sal_uInt8 > maOValue;
+
+ static std::map< sal_IntPtr, EncHashTransporter* > sTransporters;
+public:
+ EncHashTransporter()
+ : maUDigest( rtl_digest_createMD5() )
+ {
+ maID = reinterpret_cast< sal_IntPtr >(this);
+ while( sTransporters.find( maID ) != sTransporters.end() ) // paranoia mode
+ maID++;
+ sTransporters[ maID ] = this;
+ }
+
+ virtual ~EncHashTransporter()
+ {
+ sTransporters.erase( maID );
+ if( maUDigest )
+ rtl_digest_destroyMD5( maUDigest );
+ OSL_TRACE( "EncHashTransporter freed\n" );
+ }
+
+ rtlDigest getUDigest() const { return maUDigest; };
+ std::vector< sal_uInt8 >& getOValue() { return maOValue; }
+ void invalidate()
+ {
+ if( maUDigest )
+ {
+ rtl_digest_destroyMD5( maUDigest );
+ maUDigest = NULL;
+ }
+ }
+
+ // XMaterialHolder
+ virtual uno::Any SAL_CALL getMaterial() throw()
+ {
+ return uno::makeAny( sal_Int64(maID) );
+ }
+
+ static EncHashTransporter* getEncHashTransporter( const uno::Reference< beans::XMaterialHolder >& );
+
+};
+
+std::map< sal_IntPtr, EncHashTransporter* > EncHashTransporter::sTransporters;
+
+EncHashTransporter* EncHashTransporter::getEncHashTransporter( const uno::Reference< beans::XMaterialHolder >& xRef )
+{
+ EncHashTransporter* pResult = NULL;
+ if( xRef.is() )
+ {
+ uno::Any aMat( xRef->getMaterial() );
+ sal_Int64 nMat = 0;
+ if( aMat >>= nMat )
+ {
+ std::map< sal_IntPtr, EncHashTransporter* >::iterator it = sTransporters.find( static_cast<sal_IntPtr>(nMat) );
+ if( it != sTransporters.end() )
+ pResult = it->second;
+ }
+ }
+ return pResult;
+}
+
+sal_Bool PDFWriterImpl::checkEncryptionBufferSize( register sal_Int32 newSize )
+{
+ if( m_nEncryptionBufferSize < newSize )
+ {
+ /* reallocate the buffer, the used function allocate as rtl_allocateMemory
+ if the pointer parameter is NULL */
+ m_pEncryptionBuffer = (sal_uInt8*)rtl_reallocateMemory( m_pEncryptionBuffer, newSize );
+ if( m_pEncryptionBuffer )
+ m_nEncryptionBufferSize = newSize;
+ else
+ m_nEncryptionBufferSize = 0;
+ }
+ return ( m_nEncryptionBufferSize != 0 );
+}
+
+void PDFWriterImpl::checkAndEnableStreamEncryption( register sal_Int32 nObject )
+{
+ if( m_aContext.Encryption.Encrypt() )
+ {
+ m_bEncryptThisStream = true;
+ sal_Int32 i = m_nKeyLength;
+ m_aContext.Encryption.EncryptionKey[i++] = (sal_uInt8)nObject;
+ m_aContext.Encryption.EncryptionKey[i++] = (sal_uInt8)( nObject >> 8 );
+ m_aContext.Encryption.EncryptionKey[i++] = (sal_uInt8)( nObject >> 16 );
+ //the other location of m_nEncryptionKey are already set to 0, our fixed generation number
+ // do the MD5 hash
+ sal_uInt8 nMD5Sum[ RTL_DIGEST_LENGTH_MD5 ];
+ // the i+2 to take into account the generation number, always zero
+ rtl_digest_MD5( &m_aContext.Encryption.EncryptionKey[0], i+2, nMD5Sum, sizeof(nMD5Sum) );
+ // initialize the RC4 with the key
+ // key legth: see algoritm 3.1, step 4: (N+5) max 16
+ rtl_cipher_initARCFOUR( m_aCipher, rtl_Cipher_DirectionEncode, nMD5Sum, m_nRC4KeyLength, NULL, 0 );
+ }
+}
+
+void PDFWriterImpl::enableStringEncryption( register sal_Int32 nObject )
+{
+ if( m_aContext.Encryption.Encrypt() )
+ {
+ sal_Int32 i = m_nKeyLength;
+ m_aContext.Encryption.EncryptionKey[i++] = (sal_uInt8)nObject;
+ m_aContext.Encryption.EncryptionKey[i++] = (sal_uInt8)( nObject >> 8 );
+ m_aContext.Encryption.EncryptionKey[i++] = (sal_uInt8)( nObject >> 16 );
+ //the other location of m_nEncryptionKey are already set to 0, our fixed generation number
+ // do the MD5 hash
+ sal_uInt8 nMD5Sum[ RTL_DIGEST_LENGTH_MD5 ];
+ // the i+2 to take into account the generation number, always zero
+ rtl_digest_MD5( &m_aContext.Encryption.EncryptionKey[0], i+2, nMD5Sum, sizeof(nMD5Sum) );
+ // initialize the RC4 with the key
+ // key legth: see algoritm 3.1, step 4: (N+5) max 16
+ rtl_cipher_initARCFOUR( m_aCipher, rtl_Cipher_DirectionEncode, nMD5Sum, m_nRC4KeyLength, NULL, 0 );
+ }
+}
+
+/* init the encryption engine
+1. init the document id, used both for building the document id and for building the encryption key(s)
+2. build the encryption key following algorithms described in the PDF specification
+ */
+uno::Reference< beans::XMaterialHolder > PDFWriterImpl::initEncryption( const rtl::OUString& i_rOwnerPassword,
+ const rtl::OUString& i_rUserPassword,
+ bool b128Bit
+ )
+{
+ uno::Reference< beans::XMaterialHolder > xResult;
+ if( i_rOwnerPassword.getLength() || i_rUserPassword.getLength() )
+ {
+ EncHashTransporter* pTransporter = new EncHashTransporter;
+ xResult = pTransporter;
+
+ // get padded passwords
+ sal_uInt8 aPadUPW[ENCRYPTED_PWD_SIZE], aPadOPW[ENCRYPTED_PWD_SIZE];
+ padPassword( i_rOwnerPassword.getLength() ? i_rOwnerPassword : i_rUserPassword, aPadOPW );
+ padPassword( i_rUserPassword, aPadUPW );
+ sal_Int32 nKeyLength = SECUR_40BIT_KEY;
+ if( b128Bit )
+ nKeyLength = SECUR_128BIT_KEY;
+
+ if( computeODictionaryValue( aPadOPW, aPadUPW, pTransporter->getOValue(), nKeyLength ) )
+ {
+ rtlDigest aDig = pTransporter->getUDigest();
+ if( rtl_digest_updateMD5( aDig, aPadUPW, ENCRYPTED_PWD_SIZE ) != rtl_Digest_E_None )
+ xResult.clear();
+ }
+ else
+ xResult.clear();
+
+ // trash temporary padded cleartext PWDs
+ rtl_zeroMemory( aPadOPW, sizeof(aPadOPW) );
+ rtl_zeroMemory( aPadUPW, sizeof(aPadUPW) );
+
+ }
+ return xResult;
+}
+
+bool PDFWriterImpl::prepareEncryption( const uno::Reference< beans::XMaterialHolder >& xEnc )
+{
+ bool bSuccess = false;
+ EncHashTransporter* pTransporter = EncHashTransporter::getEncHashTransporter( xEnc );
+ if( pTransporter )
+ {
+ sal_Int32 nKeyLength = 0, nRC4KeyLength = 0;
+ sal_Int32 nAccessPermissions = computeAccessPermissions( m_aContext.Encryption, nKeyLength, nRC4KeyLength );
+ m_aContext.Encryption.OValue = pTransporter->getOValue();
+ bSuccess = computeUDictionaryValue( pTransporter, m_aContext.Encryption, nKeyLength, nAccessPermissions );
+ }
+ if( ! bSuccess )
+ {
+ m_aContext.Encryption.OValue.clear();
+ m_aContext.Encryption.UValue.clear();
+ m_aContext.Encryption.EncryptionKey.clear();
+ }
+ return bSuccess;
+}
+
+sal_Int32 PDFWriterImpl::computeAccessPermissions( const vcl::PDFWriter::PDFEncryptionProperties& i_rProperties,
+ sal_Int32& o_rKeyLength, sal_Int32& o_rRC4KeyLength )
+{
+ /*
+ 2) compute the access permissions, in numerical form
+
+ the default value depends on the revision 2 (40 bit) or 3 (128 bit security):
+ - for 40 bit security the unused bit must be set to 1, since they are not used
+ - for 128 bit security the same bit must be preset to 0 and set later if needed
+ according to the table 3.15, pdf v 1.4 */
+ sal_Int32 nAccessPermissions = ( i_rProperties.Security128bit ) ? 0xfffff0c0 : 0xffffffc0 ;
+
+ /* check permissions for 40 bit security case */
+ nAccessPermissions |= ( i_rProperties.CanPrintTheDocument ) ? 1 << 2 : 0;
+ nAccessPermissions |= ( i_rProperties.CanModifyTheContent ) ? 1 << 3 : 0;
+ nAccessPermissions |= ( i_rProperties.CanCopyOrExtract ) ? 1 << 4 : 0;
+ nAccessPermissions |= ( i_rProperties.CanAddOrModify ) ? 1 << 5 : 0;
+ o_rKeyLength = SECUR_40BIT_KEY;
+ o_rRC4KeyLength = SECUR_40BIT_KEY+5; // for this value see PDF spec v 1.4, algorithm 3.1 step 4, where n is 5
+
+ if( i_rProperties.Security128bit )
+ {
+ o_rKeyLength = SECUR_128BIT_KEY;
+ o_rRC4KeyLength = 16; // for this value see PDF spec v 1.4, algorithm 3.1 step 4, where n is 16, thus maximum
+ // permitted value is 16
+ nAccessPermissions |= ( i_rProperties.CanFillInteractive ) ? 1 << 8 : 0;
+ nAccessPermissions |= ( i_rProperties.CanExtractForAccessibility ) ? 1 << 9 : 0;
+ nAccessPermissions |= ( i_rProperties.CanAssemble ) ? 1 << 10 : 0;
+ nAccessPermissions |= ( i_rProperties.CanPrintFull ) ? 1 << 11 : 0;
+ }
+ return nAccessPermissions;
+}
+
+/*************************************************************
+begin i12626 methods
+
+Implements Algorithm 3.2, step 1 only
+*/
+void PDFWriterImpl::padPassword( const rtl::OUString& i_rPassword, sal_uInt8* o_pPaddedPW )
+{
+ // get ansi-1252 version of the password string CHECKIT ! i12626
+ rtl::OString aString( rtl::OUStringToOString( i_rPassword, RTL_TEXTENCODING_MS_1252 ) );
+
+ //copy the string to the target
+ sal_Int32 nToCopy = ( aString.getLength() < ENCRYPTED_PWD_SIZE ) ? aString.getLength() : ENCRYPTED_PWD_SIZE;
+ sal_Int32 nCurrentChar;
+
+ for( nCurrentChar = 0; nCurrentChar < nToCopy; nCurrentChar++ )
+ o_pPaddedPW[nCurrentChar] = (sal_uInt8)( aString.getStr()[nCurrentChar] );
+
+ //pad it with standard byte string
+ sal_Int32 i,y;
+ for( i = nCurrentChar, y = 0 ; i < ENCRYPTED_PWD_SIZE; i++, y++ )
+ o_pPaddedPW[i] = s_nPadString[y];
+
+ // trash memory of temporary clear text password
+ rtl_zeroMemory( (sal_Char*)aString.getStr(), aString.getLength() );
+}
+
+/**********************************
+Algorithm 3.2 Compute the encryption key used
+
+step 1 should already be done before calling, the paThePaddedPassword parameter should contain
+the padded password and must be 32 byte long, the encryption key is returned into the paEncryptionKey parameter,
+it will be 16 byte long for 128 bit security; for 40 bit security only the first 5 bytes are used
+
+TODO: in pdf ver 1.5 and 1.6 the step 6 is different, should be implemented. See spec.
+
+*/
+bool PDFWriterImpl::computeEncryptionKey( EncHashTransporter* i_pTransporter, vcl::PDFWriter::PDFEncryptionProperties& io_rProperties, sal_Int32 i_nAccessPermissions )
+{
+ bool bSuccess = true;
+ sal_uInt8 nMD5Sum[ RTL_DIGEST_LENGTH_MD5 ];
+
+ // transporter contains an MD5 digest with the padded user password already
+ rtlDigest aDigest = i_pTransporter->getUDigest();
+ rtlDigestError nError = rtl_Digest_E_None;
+ if( aDigest )
+ {
+ //step 3
+ if( ! io_rProperties.OValue.empty() )
+ nError = rtl_digest_updateMD5( aDigest, &io_rProperties.OValue[0] , sal_Int32(io_rProperties.OValue.size()) );
+ else
+ bSuccess = false;
+ //Step 4
+ sal_uInt8 nPerm[4];
+
+ nPerm[0] = (sal_uInt8)i_nAccessPermissions;
+ nPerm[1] = (sal_uInt8)( i_nAccessPermissions >> 8 );
+ nPerm[2] = (sal_uInt8)( i_nAccessPermissions >> 16 );
+ nPerm[3] = (sal_uInt8)( i_nAccessPermissions >> 24 );
+
+ if( nError == rtl_Digest_E_None )
+ nError = rtl_digest_updateMD5( aDigest, nPerm , sizeof( nPerm ) );
+
+ //step 5, get the document ID, binary form
+ if( nError == rtl_Digest_E_None )
+ nError = rtl_digest_updateMD5( aDigest, &io_rProperties.DocumentIdentifier[0], sal_Int32(io_rProperties.DocumentIdentifier.size()) );
+ //get the digest
+ if( nError == rtl_Digest_E_None )
+ {
+ rtl_digest_getMD5( aDigest, nMD5Sum, sizeof( nMD5Sum ) );
+
+ //step 6, only if 128 bit
+ if( io_rProperties.Security128bit )
+ {
+ for( sal_Int32 i = 0; i < 50; i++ )
+ {
+ nError = rtl_digest_updateMD5( aDigest, &nMD5Sum, sizeof( nMD5Sum ) );
+ if( nError != rtl_Digest_E_None )
+ {
+ bSuccess = false;
+ break;
+ }
+ rtl_digest_getMD5( aDigest, nMD5Sum, sizeof( nMD5Sum ) );
+ }
+ }
+ }
+ }
+ else
+ bSuccess = false;
+
+ i_pTransporter->invalidate();
+
+ //Step 7
+ if( bSuccess )
+ {
+ io_rProperties.EncryptionKey.resize( MAXIMUM_RC4_KEY_LENGTH );
+ for( sal_Int32 i = 0; i < MD5_DIGEST_SIZE; i++ )
+ io_rProperties.EncryptionKey[i] = nMD5Sum[i];
+ }
+ else
+ io_rProperties.EncryptionKey.clear();
+
+ return bSuccess;
+}
+
+/**********************************
+Algorithm 3.3 Compute the encryption dictionary /O value, save into the class data member
+the step numbers down here correspond to the ones in PDF v.1.4 specfication
+*/
+bool PDFWriterImpl::computeODictionaryValue( const sal_uInt8* i_pPaddedOwnerPassword,
+ const sal_uInt8* i_pPaddedUserPassword,
+ std::vector< sal_uInt8 >& io_rOValue,
+ sal_Int32 i_nKeyLength
+ )
+{
+ bool bSuccess = true;
+
+ io_rOValue.resize( ENCRYPTED_PWD_SIZE );
+
+ rtlDigest aDigest = rtl_digest_createMD5();
+ rtlCipher aCipher = rtl_cipher_createARCFOUR( rtl_Cipher_ModeStream );
+ if( aDigest && aCipher)
+ {
+ //step 1 already done, data is in i_pPaddedOwnerPassword
+ //step 2
+
+ rtlDigestError nError = rtl_digest_updateMD5( aDigest, i_pPaddedOwnerPassword, ENCRYPTED_PWD_SIZE );
+ if( nError == rtl_Digest_E_None )
+ {
+ sal_uInt8 nMD5Sum[ RTL_DIGEST_LENGTH_MD5 ];
+
+ rtl_digest_getMD5( aDigest, nMD5Sum, sizeof(nMD5Sum) );
+//step 3, only if 128 bit
+ if( i_nKeyLength == SECUR_128BIT_KEY )
+ {
+ sal_Int32 i;
+ for( i = 0; i < 50; i++ )
+ {
+ nError = rtl_digest_updateMD5( aDigest, nMD5Sum, sizeof( nMD5Sum ) );
+ if( nError != rtl_Digest_E_None )
+ {
+ bSuccess = false;
+ break;
+ }
+ rtl_digest_getMD5( aDigest, nMD5Sum, sizeof( nMD5Sum ) );
+ }
+ }
+ //Step 4, the key is in nMD5Sum
+ //step 5 already done, data is in i_pPaddedUserPassword
+ //step 6
+ rtl_cipher_initARCFOUR( aCipher, rtl_Cipher_DirectionEncode,
+ nMD5Sum, i_nKeyLength , NULL, 0 );
+ // encrypt the user password using the key set above
+ rtl_cipher_encodeARCFOUR( aCipher, i_pPaddedUserPassword, ENCRYPTED_PWD_SIZE, // the data to be encrypted
+ &io_rOValue[0], sal_Int32(io_rOValue.size()) ); //encrypted data
+ //Step 7, only if 128 bit
+ if( i_nKeyLength == SECUR_128BIT_KEY )
+ {
+ sal_uInt32 i, y;
+ sal_uInt8 nLocalKey[ SECUR_128BIT_KEY ]; // 16 = 128 bit key
+
+ for( i = 1; i <= 19; i++ ) // do it 19 times, start with 1
+ {
+ for( y = 0; y < sizeof( nLocalKey ); y++ )
+ nLocalKey[y] = (sal_uInt8)( nMD5Sum[y] ^ i );
+
+ rtl_cipher_initARCFOUR( aCipher, rtl_Cipher_DirectionEncode,
+ nLocalKey, SECUR_128BIT_KEY, NULL, 0 ); //destination data area, on init can be NULL
+ rtl_cipher_encodeARCFOUR( aCipher, &io_rOValue[0], sal_Int32(io_rOValue.size()), // the data to be encrypted
+ &io_rOValue[0], sal_Int32(io_rOValue.size()) ); // encrypted data, can be the same as the input, encrypt "in place"
+ //step 8, store in class data member
+ }
+ }
+ }
+ else
+ bSuccess = false;
+ }
+ else
+ bSuccess = false;
+
+ if( aDigest )
+ rtl_digest_destroyMD5( aDigest );
+ if( aCipher )
+ rtl_cipher_destroyARCFOUR( aCipher );
+
+ if( ! bSuccess )
+ io_rOValue.clear();
+ return bSuccess;
+}
+
+/**********************************
+Algorithms 3.4 and 3.5 Compute the encryption dictionary /U value, save into the class data member, revision 2 (40 bit) or 3 (128 bit)
+*/
+bool PDFWriterImpl::computeUDictionaryValue( EncHashTransporter* i_pTransporter,
+ vcl::PDFWriter::PDFEncryptionProperties& io_rProperties,
+ sal_Int32 i_nKeyLength,
+ sal_Int32 i_nAccessPermissions
+ )
+{
+ bool bSuccess = true;
+
+ io_rProperties.UValue.resize( ENCRYPTED_PWD_SIZE );
+
+ rtlDigest aDigest = rtl_digest_createMD5();
+ rtlCipher aCipher = rtl_cipher_createARCFOUR( rtl_Cipher_ModeStream );
+ if( aDigest && aCipher )
+ {
+ //step 1, common to both 3.4 and 3.5
+ if( computeEncryptionKey( i_pTransporter, io_rProperties, i_nAccessPermissions ) )
+ {
+ // prepare encryption key for object
+ for( sal_Int32 i = i_nKeyLength, y = 0; y < 5 ; y++ )
+ io_rProperties.EncryptionKey[i++] = 0;
+
+ if( io_rProperties.Security128bit == false )
+ {
+ //3.4
+ //step 2 and 3
+ rtl_cipher_initARCFOUR( aCipher, rtl_Cipher_DirectionEncode,
+ &io_rProperties.EncryptionKey[0], 5 , // key and key length
+ NULL, 0 ); //destination data area
+ // encrypt the user password using the key set above, save for later use
+ rtl_cipher_encodeARCFOUR( aCipher, s_nPadString, sizeof( s_nPadString ), // the data to be encrypted
+ &io_rProperties.UValue[0], sal_Int32(io_rProperties.UValue.size()) ); //encrypted data, stored in class data member
+ }
+ else
+ {
+ //or 3.5, for 128 bit security
+ //step6, initilize the last 16 bytes of the encrypted user password to 0
+ for(sal_uInt32 i = MD5_DIGEST_SIZE; i < sal_uInt32(io_rProperties.UValue.size()); i++)
+ io_rProperties.UValue[i] = 0;
+ //step 2
+ rtlDigestError nError = rtl_digest_updateMD5( aDigest, s_nPadString, sizeof( s_nPadString ) );
+ //step 3
+ if( nError == rtl_Digest_E_None )
+ nError = rtl_digest_updateMD5( aDigest, &io_rProperties.DocumentIdentifier[0], sal_Int32(io_rProperties.DocumentIdentifier.size()) );
+ else
+ bSuccess = false;
+
+ sal_uInt8 nMD5Sum[ RTL_DIGEST_LENGTH_MD5 ];
+ rtl_digest_getMD5( aDigest, nMD5Sum, sizeof(nMD5Sum) );
+ //Step 4
+ rtl_cipher_initARCFOUR( aCipher, rtl_Cipher_DirectionEncode,
+ &io_rProperties.EncryptionKey[0], SECUR_128BIT_KEY, NULL, 0 ); //destination data area
+ rtl_cipher_encodeARCFOUR( aCipher, nMD5Sum, sizeof( nMD5Sum ), // the data to be encrypted
+ &io_rProperties.UValue[0], sizeof( nMD5Sum ) ); //encrypted data, stored in class data member
+ //step 5
+ sal_uInt32 i, y;
+ sal_uInt8 nLocalKey[SECUR_128BIT_KEY];
+
+ for( i = 1; i <= 19; i++ ) // do it 19 times, start with 1
+ {
+ for( y = 0; y < sizeof( nLocalKey ) ; y++ )
+ nLocalKey[y] = (sal_uInt8)( io_rProperties.EncryptionKey[y] ^ i );
+
+ rtl_cipher_initARCFOUR( aCipher, rtl_Cipher_DirectionEncode,
+ nLocalKey, SECUR_128BIT_KEY, // key and key length
+ NULL, 0 ); //destination data area, on init can be NULL
+ rtl_cipher_encodeARCFOUR( aCipher, &io_rProperties.UValue[0], SECUR_128BIT_KEY, // the data to be encrypted
+ &io_rProperties.UValue[0], SECUR_128BIT_KEY ); // encrypted data, can be the same as the input, encrypt "in place"
+ }
+ }
+ }
+ else
+ bSuccess = false;
+ }
+ else
+ bSuccess = false;
+
+ if( aDigest )
+ rtl_digest_destroyMD5( aDigest );
+ if( aCipher )
+ rtl_cipher_destroyARCFOUR( aCipher );
+
+ if( ! bSuccess )
+ io_rProperties.UValue.clear();
+ return bSuccess;
+}
+
+/* end i12626 methods */
diff --git a/vcl/source/gdi/pngread.cxx b/vcl/source/gdi/pngread.cxx
index 11971db34378..df67c4974d47 100644
--- a/vcl/source/gdi/pngread.cxx
+++ b/vcl/source/gdi/pngread.cxx
@@ -411,7 +411,9 @@ BitmapEx PNGReaderImpl::GetBitmapEx( const Size& rPreviewSizeHint )
case PNGCHUNK_IDAT :
{
- if ( !mbIDAT ) // the gfx is finished, but there may be left a zlibCRC of about 4Bytes
+ if ( !mpInflateInBuf ) // taking care that the header has properly been read
+ mbStatus = FALSE;
+ else if ( !mbIDAT ) // the gfx is finished, but there may be left a zlibCRC of about 4Bytes
ImplReadIDAT();
}
break;
@@ -527,7 +529,7 @@ BOOL PNGReaderImpl::ImplReadHeader( const Size& rPreviewSizeHint )
mbIDAT = mbAlphaChannel = mbTransparent = FALSE;
mbGrayScale = mbRGBTriple = FALSE;
mnTargetDepth = mnPngDepth;
- mnScansize = ( ( maOrigSize.Width() * mnPngDepth ) + 7 ) >> 3;
+ sal_uInt64 nScansize64 = ( ( static_cast< sal_uInt64 >( maOrigSize.Width() ) * mnPngDepth ) + 7 ) >> 3;
// valid color types are 0,2,3,4 & 6
switch ( mnColorType )
@@ -557,7 +559,7 @@ BOOL PNGReaderImpl::ImplReadHeader( const Size& rPreviewSizeHint )
case 2 : // each pixel is an RGB triple
{
mbRGBTriple = TRUE;
- mnScansize *= 3;
+ nScansize64 *= 3;
switch ( mnPngDepth )
{
case 16 : // we have to reduce the bitmap
@@ -590,7 +592,7 @@ BOOL PNGReaderImpl::ImplReadHeader( const Size& rPreviewSizeHint )
case 4 : // each pixel is a grayscale sample followed by an alpha sample
{
- mnScansize *= 2;
+ nScansize64 *= 2;
mbAlphaChannel = TRUE;
switch ( mnPngDepth )
{
@@ -608,7 +610,7 @@ BOOL PNGReaderImpl::ImplReadHeader( const Size& rPreviewSizeHint )
case 6 : // each pixel is an RGB triple followed by an alpha sample
{
mbRGBTriple = TRUE;
- mnScansize *= 4;
+ nScansize64 *= 4;
mbAlphaChannel = TRUE;
switch (mnPngDepth )
{
@@ -626,16 +628,24 @@ BOOL PNGReaderImpl::ImplReadHeader( const Size& rPreviewSizeHint )
return FALSE;
}
- mnBPP = mnScansize / maOrigSize.Width();
+ mnBPP = static_cast< sal_uInt32 >( nScansize64 / maOrigSize.Width() );
if ( !mnBPP )
mnBPP = 1;
- mnScansize++; // each scanline includes one filterbyte
+ nScansize64++; // each scanline includes one filterbyte
+
+ if ( nScansize64 > SAL_MAX_UINT32 )
+ return FALSE;
+
+ mnScansize = static_cast< sal_uInt32 >( nScansize64 );
// TODO: switch between both scanlines instead of copying
- mpInflateInBuf = new BYTE[ mnScansize ];
+ mpInflateInBuf = new (std::nothrow) BYTE[ mnScansize ];
mpScanCurrent = mpInflateInBuf;
- mpScanPrior = new BYTE[ mnScansize ];
+ mpScanPrior = new (std::nothrow) BYTE[ mnScansize ];
+
+ if ( !mpInflateInBuf || !mpScanPrior )
+ return FALSE;
// calculate target size from original size and the preview hint
if( rPreviewSizeHint.Width() || rPreviewSizeHint.Height() )
diff --git a/vcl/source/gdi/print2.cxx b/vcl/source/gdi/print2.cxx
index 25ba80003fd7..5c2a742a10ba 100644
--- a/vcl/source/gdi/print2.cxx
+++ b/vcl/source/gdi/print2.cxx
@@ -407,6 +407,7 @@ static Rectangle ImplCalcActionBounds( const MetaAction& rAct, const OutputDevic
{
const MetaLineAction& rMetaLineAction = static_cast<const MetaLineAction&>(rAct);
aActionBounds = Rectangle( rMetaLineAction.GetStartPoint(), rMetaLineAction.GetEndPoint() );
+ aActionBounds.Justify();
const long nLineWidth(rMetaLineAction.GetLineInfo().GetWidth());
if(nLineWidth)
{
diff --git a/vcl/source/window/arrange.cxx b/vcl/source/window/arrange.cxx
index 9749299d4d6b..f016ef2c053b 100644
--- a/vcl/source/window/arrange.cxx
+++ b/vcl/source/window/arrange.cxx
@@ -29,15 +29,37 @@
#include "vcl/arrange.hxx"
#include "vcl/edit.hxx"
+#include "vcl/svdata.hxx"
+#include "vcl/svapp.hxx"
+
+#include "com/sun/star/beans/PropertyValue.hpp"
+#include "com/sun/star/awt/Rectangle.hpp"
#include "osl/diagnose.h"
using namespace vcl;
+using namespace com::sun::star;
// ----------------------------------------
// vcl::WindowArranger
//-----------------------------------------
+long WindowArranger::getDefaultBorder()
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ long nResult = pSVData->maAppData.mnDefaultLayoutBorder;
+ if( nResult < 0 )
+ {
+ OutputDevice* pDefDev = Application::GetDefaultDevice();
+ if( pDefDev )
+ {
+ Size aBorder( pDefDev->LogicToPixel( Size( 3, 3 ), MapMode( MAP_APPFONT ) ) );
+ nResult = pSVData->maAppData.mnDefaultLayoutBorder = aBorder.Height();
+ }
+ }
+ return nResult > 0 ? nResult : 0;
+}
+
WindowArranger::~WindowArranger()
{}
@@ -156,16 +178,26 @@ Size WindowArranger::Element::getOptimalSize( WindowSizeType i_eType ) const
Size aResult;
if( ! m_bHidden )
{
+ bool bVisible = false;
if( m_pElement && m_pElement->IsVisible() )
+ {
aResult = m_pElement->GetOptimalSize( i_eType );
- else if( m_pChild )
+ bVisible = true;
+ }
+ else if( m_pChild && m_pChild->isVisible() )
+ {
aResult = m_pChild->getOptimalSize( i_eType );
- if( aResult.Width() < m_aMinSize.Width() )
- aResult.Width() = m_aMinSize.Width();
- if( aResult.Height() < m_aMinSize.Height() )
- aResult.Height() = m_aMinSize.Height();
- aResult.Width() += m_nLeftBorder + m_nRightBorder;
- aResult.Height() += m_nTopBorder + m_nBottomBorder;
+ bVisible = true;
+ }
+ if( bVisible )
+ {
+ if( aResult.Width() < m_aMinSize.Width() )
+ aResult.Width() = m_aMinSize.Width();
+ if( aResult.Height() < m_aMinSize.Height() )
+ aResult.Height() = m_aMinSize.Height();
+ aResult.Width() += getBorderValue( m_nLeftBorder ) + getBorderValue( m_nRightBorder );
+ aResult.Height() += getBorderValue( m_nTopBorder ) + getBorderValue( m_nBottomBorder );
+ }
}
return aResult;
@@ -175,16 +207,74 @@ void WindowArranger::Element::setPosSize( const Point& i_rPos, const Size& i_rSi
{
Point aPoint( i_rPos );
Size aSize( i_rSize );
- aPoint.X() += m_nLeftBorder;
- aPoint.Y() += m_nTopBorder;
- aSize.Width() -= m_nLeftBorder + m_nRightBorder;
- aSize.Height() -= m_nTopBorder + m_nBottomBorder;
+ aPoint.X() += getBorderValue( m_nLeftBorder );
+ aPoint.Y() += getBorderValue( m_nTopBorder );
+ aSize.Width() -= getBorderValue( m_nLeftBorder ) + getBorderValue( m_nRightBorder );
+ aSize.Height() -= getBorderValue( m_nTopBorder ) + getBorderValue( m_nBottomBorder );
if( m_pElement )
m_pElement->SetPosSizePixel( aPoint, aSize );
else if( m_pChild )
m_pChild->setManagedArea( Rectangle( aPoint, aSize ) );
}
+uno::Sequence< beans::PropertyValue > WindowArranger::getProperties() const
+{
+ uno::Sequence< beans::PropertyValue > aRet( 3 );
+ aRet[0].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "OuterBorder" ) );
+ aRet[0].Value = uno::makeAny( sal_Int32( getBorderValue( m_nOuterBorder ) ) );
+ aRet[1].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ManagedArea" ) );
+ awt::Rectangle aArea( m_aManagedArea.getX(), m_aManagedArea.getY(), m_aManagedArea.getWidth(), m_aManagedArea.getHeight() );
+ aRet[1].Value = uno::makeAny( aArea );
+ aRet[2].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Visible" ) );
+ aRet[2].Value = uno::makeAny( sal_Bool( isVisible() ) );
+ return aRet;
+}
+
+void WindowArranger::setProperties( const uno::Sequence< beans::PropertyValue >& i_rProps )
+{
+ const beans::PropertyValue* pProps = i_rProps.getConstArray();
+ bool bResize = false;
+ for( sal_Int32 i = 0; i < i_rProps.getLength(); i++ )
+ {
+ if( pProps[i].Name.equalsAscii( "OuterBorder" ) )
+ {
+ sal_Int32 nVal = 0;
+ if( pProps[i].Value >>= nVal )
+ {
+ if( getBorderValue( m_nOuterBorder ) != nVal )
+ {
+ m_nOuterBorder = nVal;
+ bResize = true;
+ }
+ }
+ }
+ else if( pProps[i].Name.equalsAscii( "ManagedArea" ) )
+ {
+ awt::Rectangle aArea( 0, 0, 0, 0 );
+ if( pProps[i].Value >>= aArea )
+ {
+ m_aManagedArea.setX( aArea.X );
+ m_aManagedArea.setY( aArea.Y );
+ m_aManagedArea.setWidth( aArea.Width );
+ m_aManagedArea.setHeight( aArea.Height );
+ bResize = true;
+ }
+ }
+ else if( pProps[i].Name.equalsAscii( "Visible" ) )
+ {
+ sal_Bool bVal = sal_False;
+ if( pProps[i].Value >>= bVal )
+ {
+ show( bVal, false );
+ bResize = true;
+ }
+ }
+ }
+ if( bResize )
+ resize();
+}
+
+
// ----------------------------------------
// vcl::RowOrColumn
//-----------------------------------------
@@ -201,6 +291,7 @@ RowOrColumn::~RowOrColumn()
Size RowOrColumn::getOptimalSize( WindowSizeType i_eType ) const
{
Size aRet( 0, 0 );
+ long nDistance = getBorderValue( m_nBorderWidth );
for( std::vector< WindowArranger::Element >::const_iterator it = m_aElements.begin();
it != m_aElements.end(); ++it )
{
@@ -211,7 +302,7 @@ Size RowOrColumn::getOptimalSize( WindowSizeType i_eType ) const
if( m_bColumn )
{
// add the distance between elements
- aRet.Height() += m_nBorderWidth;
+ aRet.Height() += nDistance;
// check if the width needs adjustment
if( aRet.Width() < aElementSize.Width() )
aRet.Width() = aElementSize.Width();
@@ -220,7 +311,7 @@ Size RowOrColumn::getOptimalSize( WindowSizeType i_eType ) const
else
{
// add the distance between elements
- aRet.Width() += m_nBorderWidth;
+ aRet.Width() += nDistance;
// check if the height needs adjustment
if( aRet.Height() < aElementSize.Height() )
aRet.Height() = aElementSize.Height();
@@ -233,13 +324,14 @@ Size RowOrColumn::getOptimalSize( WindowSizeType i_eType ) const
{
// subtract the border for the first element
if( m_bColumn )
- aRet.Height() -= m_nBorderWidth;
+ aRet.Height() -= nDistance;
else
- aRet.Width() -= m_nBorderWidth;
+ aRet.Width() -= nDistance;
// add the outer border
- aRet.Width() += 2*m_nOuterBorder;
- aRet.Height() += 2*m_nOuterBorder;
+ long nOuterBorder = getBorderValue( m_nOuterBorder );
+ aRet.Width() += 2*nOuterBorder;
+ aRet.Height() += 2*nOuterBorder;
}
return aRet;
@@ -344,7 +436,9 @@ void RowOrColumn::resize()
size_t nElements = m_aElements.size();
// get all element sizes for sizing
std::vector<Size> aElementSizes( nElements );
- long nUsedWidth = 2*m_nOuterBorder - (nElements ? m_nBorderWidth : 0);
+ long nDistance = getBorderValue( m_nBorderWidth );
+ long nOuterBorder = getBorderValue( m_nOuterBorder );
+ long nUsedWidth = 2*nOuterBorder - (nElements ? nDistance : 0);
for( size_t i = 0; i < nElements; i++ )
{
if( m_aElements[i].isVisible() )
@@ -352,13 +446,13 @@ void RowOrColumn::resize()
aElementSizes[i] = m_aElements[i].getOptimalSize( eType );
if( m_bColumn )
{
- aElementSizes[i].Width() = m_aManagedArea.GetWidth() - 2* m_nOuterBorder;
- nUsedWidth += aElementSizes[i].Height() + m_nBorderWidth;
+ aElementSizes[i].Width() = m_aManagedArea.GetWidth() - 2 * nOuterBorder;
+ nUsedWidth += aElementSizes[i].Height() + nDistance;
}
else
{
- aElementSizes[i].Height() = m_aManagedArea.GetHeight() - 2* m_nOuterBorder;
- nUsedWidth += aElementSizes[i].Width() + m_nBorderWidth;
+ aElementSizes[i].Height() = m_aManagedArea.GetHeight() - 2 * nOuterBorder;
+ nUsedWidth += aElementSizes[i].Width() + nDistance;
}
}
}
@@ -375,8 +469,8 @@ void RowOrColumn::resize()
// get starting position
Point aElementPos( m_aManagedArea.TopLeft() );
// outer border
- aElementPos.X() += m_nOuterBorder;
- aElementPos.Y() += m_nOuterBorder;
+ aElementPos.X() += nOuterBorder;
+ aElementPos.Y() += nOuterBorder;
// position managed windows
for( size_t i = 0; i < nElements; i++ )
@@ -386,27 +480,27 @@ void RowOrColumn::resize()
{
m_aElements[i].setPosSize( aElementPos, aElementSizes[i] );
if( m_bColumn )
- aElementPos.Y() += m_nBorderWidth + aElementSizes[i].Height();
+ aElementPos.Y() += nDistance + aElementSizes[i].Height();
else
- aElementPos.X() += m_nBorderWidth + aElementSizes[i].Width();
+ aElementPos.X() += nDistance + aElementSizes[i].Width();
}
}
}
-size_t RowOrColumn::addWindow( Window* i_pWindow, sal_Int32 i_nExpandPrio, size_t i_nIndex )
+size_t RowOrColumn::addWindow( Window* i_pWindow, sal_Int32 i_nExpandPrio, const Size& i_rMinSize, size_t i_nIndex )
{
size_t nIndex = i_nIndex;
if( i_nIndex >= m_aElements.size() )
{
nIndex = m_aElements.size();
- m_aElements.push_back( WindowArranger::Element( i_pWindow, boost::shared_ptr<WindowArranger>(), i_nExpandPrio ) );
+ m_aElements.push_back( WindowArranger::Element( i_pWindow, boost::shared_ptr<WindowArranger>(), i_nExpandPrio, i_rMinSize ) );
}
else
{
std::vector< WindowArranger::Element >::iterator it = m_aElements.begin();
while( i_nIndex-- )
++it;
- m_aElements.insert( it, WindowArranger::Element( i_pWindow, boost::shared_ptr<WindowArranger>(), i_nExpandPrio ) );
+ m_aElements.insert( it, WindowArranger::Element( i_pWindow, boost::shared_ptr<WindowArranger>(), i_nExpandPrio, i_rMinSize ) );
}
return nIndex;
}
@@ -479,14 +573,14 @@ Size LabeledElement::getOptimalSize( WindowSizeType i_eType ) const
if( m_nLabelColumnWidth != 0 )
aRet.Width() = m_nLabelColumnWidth;
else
- aRet.Width() += m_nDistance;
+ aRet.Width() += getBorderValue( m_nDistance );
}
Size aElementSize( m_aElement.getOptimalSize( i_eType ) );
aRet.Width() += aElementSize.Width();
if( aElementSize.Height() > aRet.Height() )
aRet.Height() = aElementSize.Height();
if( aRet.Height() != 0 )
- aRet.Height() += 2*m_nOuterBorder;
+ aRet.Height() += 2 * getBorderValue( m_nOuterBorder );
return aRet;
}
@@ -495,23 +589,25 @@ void LabeledElement::resize()
{
Size aLabelSize( m_aLabel.getOptimalSize( WINDOWSIZE_MINIMUM ) );
Size aElementSize( m_aElement.getOptimalSize( WINDOWSIZE_PREFERRED ) );
- if( m_nDistance + aLabelSize.Width() + aElementSize.Width() > m_aManagedArea.GetWidth() )
+ long nDistance = getBorderValue( m_nDistance );
+ long nOuterBorder = getBorderValue( m_nOuterBorder );
+ if( nDistance + aLabelSize.Width() + aElementSize.Width() > m_aManagedArea.GetWidth() )
aElementSize = m_aElement.getOptimalSize( WINDOWSIZE_MINIMUM );
// align label and element vertically in LabeledElement
- long nYOff = (m_aManagedArea.GetHeight() - 2*m_nOuterBorder - aLabelSize.Height()) / 2;
+ long nYOff = (m_aManagedArea.GetHeight() - 2*nOuterBorder - aLabelSize.Height()) / 2;
Point aPos( m_aManagedArea.Left(),
- m_aManagedArea.Top() + m_nOuterBorder + nYOff );
+ m_aManagedArea.Top() + nOuterBorder + nYOff );
Size aSize( aLabelSize );
if( m_nLabelColumnWidth != 0 )
aSize.Width() = m_nLabelColumnWidth;
m_aLabel.setPosSize( aPos, aSize );
- aPos.X() += aSize.Width() + m_nDistance;
- nYOff = (m_aManagedArea.GetHeight() - 2*m_nOuterBorder - aElementSize.Height()) / 2;
- aPos.Y() = m_aManagedArea.Top() + m_nOuterBorder + nYOff;
+ aPos.X() += aSize.Width() + nDistance;
+ nYOff = (m_aManagedArea.GetHeight() - 2*nOuterBorder - aElementSize.Height()) / 2;
+ aPos.Y() = m_aManagedArea.Top() + nOuterBorder + nYOff;
aSize.Width() = aElementSize.Width();
- aSize.Height() = m_aManagedArea.GetHeight() - 2*m_nOuterBorder;
+ aSize.Height() = m_aManagedArea.GetHeight() - 2*nOuterBorder;
// label style
// 0: position left and right
@@ -578,18 +674,22 @@ long LabelColumn::getLabelWidth() const
if( pLW )
{
Size aLabSize( pLW->GetOptimalSize( WINDOWSIZE_MINIMUM ) );
+ long nLB = 0;
+ pLabel->getBorders(0, &nLB);
+ aLabSize.Width() += getBorderValue( nLB );
if( aLabSize.Width() > nWidth )
nWidth = aLabSize.Width();
}
}
}
}
- return nWidth + getBorderWidth();
+ return nWidth + getBorderValue( getBorderWidth() );
}
Size LabelColumn::getOptimalSize( WindowSizeType i_eType ) const
{
long nWidth = getLabelWidth();
+ long nOuterBorder = getBorderValue( m_nOuterBorder );
Size aColumnSize;
// every child is a LabeledElement
@@ -622,19 +722,19 @@ Size LabelColumn::getOptimalSize( WindowSizeType i_eType ) const
}
if( aElementSize.Width() )
{
- aElementSize.Width() += 2*m_nOuterBorder;
+ aElementSize.Width() += 2*nOuterBorder;
if( aElementSize.Width() > aColumnSize.Width() )
aColumnSize.Width() = aElementSize.Width();
}
if( aElementSize.Height() )
{
- aColumnSize.Height() += getBorderWidth() + aElementSize.Height();
+ aColumnSize.Height() += getBorderValue( getBorderWidth() ) + aElementSize.Height();
}
}
if( nEle > 0 && aColumnSize.Height() )
{
- aColumnSize.Height() -= getBorderWidth(); // for the first element
- aColumnSize.Height() += 2*m_nOuterBorder;
+ aColumnSize.Height() -= getBorderValue( getBorderWidth() ); // for the first element
+ aColumnSize.Height() += 2*nOuterBorder;
}
return aColumnSize;
}
@@ -667,12 +767,13 @@ size_t LabelColumn::addRow( Window* i_pLabel, boost::shared_ptr<WindowArranger>
return nIndex;
}
-size_t LabelColumn::addRow( Window* i_pLabel, Window* i_pElement, long i_nIndent )
+size_t LabelColumn::addRow( Window* i_pLabel, Window* i_pElement, long i_nIndent, const Size& i_rElementMinSize )
{
boost::shared_ptr< LabeledElement > xLabel( new LabeledElement( this, 1 ) );
xLabel->setLabel( i_pLabel );
xLabel->setBorders( 0, i_nIndent, 0, 0, 0 );
xLabel->setElement( i_pElement );
+ xLabel->setMinimumSize( 1, i_rElementMinSize );
size_t nIndex = addChild( xLabel );
resize();
return nIndex;
@@ -690,19 +791,23 @@ Indenter::~Indenter()
Size Indenter::getOptimalSize( WindowSizeType i_eType ) const
{
Size aSize( m_aElement.getOptimalSize( i_eType ) );
- aSize.Width() += 2*m_nOuterBorder + m_nIndent;
- aSize.Height() += 2*m_nOuterBorder;
+ long nOuterBorder = getBorderValue( m_nOuterBorder );
+ long nIndent = getBorderValue( m_nIndent );
+ aSize.Width() += 2*nOuterBorder + nIndent;
+ aSize.Height() += 2*nOuterBorder;
return aSize;
}
void Indenter::resize()
{
+ long nOuterBorder = getBorderValue( m_nOuterBorder );
+ long nIndent = getBorderValue( m_nIndent );
Point aPt( m_aManagedArea.TopLeft() );
- aPt.X() += m_nOuterBorder + m_nIndent;
- aPt.Y() += m_nOuterBorder;
+ aPt.X() += nOuterBorder + nIndent;
+ aPt.Y() += nOuterBorder;
Size aSz( m_aManagedArea.GetSize() );
- aSz.Width() -= 2*m_nOuterBorder + m_nIndent;
- aSz.Height() -= 2*m_nOuterBorder;
+ aSz.Width() -= 2*nOuterBorder + nIndent;
+ aSz.Height() -= 2*nOuterBorder;
m_aElement.setPosSize( aPt, aSz );
}
@@ -733,7 +838,8 @@ Size MatrixArranger::getOptimalSize( WindowSizeType i_eType,
std::vector<sal_Int32>& o_rColumnPrio, std::vector<sal_Int32>& o_rRowPrio
) const
{
- Size aMatrixSize( 2*m_nOuterBorder, 2*m_nOuterBorder );
+ long nOuterBorder = getBorderValue( m_nOuterBorder );
+ Size aMatrixSize( 2*nOuterBorder, 2*nOuterBorder );
// first find out the current number of rows and columns
sal_uInt32 nRows = 0, nColumns = 0;
@@ -768,15 +874,17 @@ Size MatrixArranger::getOptimalSize( WindowSizeType i_eType,
}
// add up sizes
+ long nDistanceX = getBorderValue( m_nBorderX );
+ long nDistanceY = getBorderValue( m_nBorderY );
for( sal_uInt32 i = 0; i < nColumns; i++ )
- aMatrixSize.Width() += o_rColumnWidths[i] + m_nBorderX;
+ aMatrixSize.Width() += o_rColumnWidths[i] + nDistanceX;
if( nColumns > 0 )
- aMatrixSize.Width() -= m_nBorderX;
+ aMatrixSize.Width() -= nDistanceX;
for( sal_uInt32 i = 0; i < nRows; i++ )
- aMatrixSize.Height() += o_rRowHeights[i] + m_nBorderY;
+ aMatrixSize.Height() += o_rRowHeights[i] + nDistanceY;
if( nRows > 0 )
- aMatrixSize.Height() -= m_nBorderY;
+ aMatrixSize.Height() -= nDistanceY;
return aMatrixSize;
}
@@ -860,15 +968,18 @@ void MatrixArranger::resize()
distributeExtraSize( aRowHeights, aRowPrio, nExtraSize );
// prepare offsets
+ long nDistanceX = getBorderValue( m_nBorderX );
+ long nDistanceY = getBorderValue( m_nBorderY );
+ long nOuterBorder = getBorderValue( m_nOuterBorder );
std::vector<long> aColumnX( aColumnWidths.size() );
- aColumnX[0] = m_aManagedArea.Left() + m_nOuterBorder;
+ aColumnX[0] = m_aManagedArea.Left() + nOuterBorder;
for( size_t i = 1; i < aColumnX.size(); i++ )
- aColumnX[i] = aColumnX[i-1] + aColumnWidths[i-1] + m_nBorderX;
+ aColumnX[i] = aColumnX[i-1] + aColumnWidths[i-1] + nDistanceX;
std::vector<long> aRowY( aRowHeights.size() );
- aRowY[0] = m_aManagedArea.Top() + m_nOuterBorder;
+ aRowY[0] = m_aManagedArea.Top() + nOuterBorder;
for( size_t i = 1; i < aRowY.size(); i++ )
- aRowY[i] = aRowY[i-1] + aRowHeights[i-1] + m_nBorderY;
+ aRowY[i] = aRowY[i-1] + aRowHeights[i-1] + nDistanceY;
// now iterate over the elements and assign their positions
for( std::vector< MatrixElement >::iterator it = m_aElements.begin();
@@ -880,7 +991,7 @@ void MatrixArranger::resize()
}
}
-size_t MatrixArranger::addWindow( Window* i_pWindow, sal_uInt32 i_nX, sal_uInt32 i_nY, sal_Int32 i_nExpandPrio )
+size_t MatrixArranger::addWindow( Window* i_pWindow, sal_uInt32 i_nX, sal_uInt32 i_nY, sal_Int32 i_nExpandPrio, const Size& i_rMinSize )
{
sal_uInt64 nMapValue = getMap( i_nX, i_nY );
std::map< sal_uInt64, size_t >::const_iterator it = m_aMatrixMap.find( nMapValue );
@@ -888,7 +999,7 @@ size_t MatrixArranger::addWindow( Window* i_pWindow, sal_uInt32 i_nX, sal_uInt32
if( it == m_aMatrixMap.end() )
{
m_aMatrixMap[ nMapValue ] = nIndex = m_aElements.size();
- m_aElements.push_back( MatrixElement( i_pWindow, i_nX, i_nY, boost::shared_ptr<WindowArranger>(), i_nExpandPrio ) );
+ m_aElements.push_back( MatrixElement( i_pWindow, i_nX, i_nY, boost::shared_ptr<WindowArranger>(), i_nExpandPrio, i_rMinSize ) );
}
else
{
@@ -896,6 +1007,7 @@ size_t MatrixArranger::addWindow( Window* i_pWindow, sal_uInt32 i_nX, sal_uInt32
rEle.m_pElement = i_pWindow;
rEle.m_pChild.reset();
rEle.m_nExpandPriority = i_nExpandPrio;
+ rEle.m_aMinSize = i_rMinSize;
rEle.m_nX = i_nX;
rEle.m_nY = i_nY;
nIndex = it->second;
diff --git a/vcl/source/window/makefile.mk b/vcl/source/window/makefile.mk
index 82ce26f8e78e..1c63376dfda5 100644
--- a/vcl/source/window/makefile.mk
+++ b/vcl/source/window/makefile.mk
@@ -85,6 +85,8 @@ SLOFILES= \
$(SLO)$/winproc.obj \
$(SLO)$/window2.obj \
$(SLO)$/window3.obj \
+ $(SLO)$/window4.obj \
+ $(SLO)$/wpropset.obj \
$(SLO)$/wrkwin.obj
# --- Targets ------------------------------------------------------
diff --git a/vcl/source/window/printdlg.cxx b/vcl/source/window/printdlg.cxx
index 5e4e0d59ccc6..73420e6ef8b5 100644
--- a/vcl/source/window/printdlg.cxx
+++ b/vcl/source/window/printdlg.cxx
@@ -533,22 +533,21 @@ void PrintDialog::NUpTabPage::showAdvancedControls( bool i_bShow )
maSheetMarginTxt2.Show( i_bShow );
maNupOrientationTxt.Show( i_bShow );
maNupOrientationBox.Show( i_bShow );
- maLayout.resize();
+ getLayout()->resize();
}
void PrintDialog::NUpTabPage::setupLayout()
{
+ boost::shared_ptr<vcl::RowOrColumn> xLayout =
+ boost::dynamic_pointer_cast<vcl::RowOrColumn>( getLayout() );
Size aBorder( LogicToPixel( Size( 6, 6 ), MapMode( MAP_APPFONT ) ) );
/* According to OOo style guide, the horizontal indentation of child
elements to their parent element should always be 6 map units. */
long nIndent = aBorder.Width();
- maLayout.setParentWindow( this );
- maLayout.setOuterBorder( aBorder.Width() );
-
- maLayout.addWindow( &maNupLine );
- boost::shared_ptr< vcl::RowOrColumn > xRow( new vcl::RowOrColumn( &maLayout, false ) );
- maLayout.addChild( xRow );
+ xLayout->addWindow( &maNupLine );
+ boost::shared_ptr< vcl::RowOrColumn > xRow( new vcl::RowOrColumn( xLayout.get(), false ) );
+ xLayout->addChild( xRow );
boost::shared_ptr< vcl::Indenter > xIndent( new vcl::Indenter( xRow.get() ) );
xRow->addChild( xIndent );
@@ -584,7 +583,7 @@ void PrintDialog::NUpTabPage::setupLayout()
xMainCol->addRow( &maNupOrderTxt, &maNupOrderBox, nIndent );
xMainCol->setBorders( xMainCol->addWindow( &maBorderCB ), nIndent, 0, 0, 0 );
- xSpacer.reset( new vcl::Spacer( xMainCol.get(), 0, Size( 10, aBorder.Width() ) ) );
+ xSpacer.reset( new vcl::Spacer( xMainCol.get(), 0, Size( 10, WindowArranger::getDefaultBorder() ) ) );
xMainCol->addChild( xSpacer );
xRow.reset( new vcl::RowOrColumn( xMainCol.get(), false ) );
@@ -596,11 +595,6 @@ void PrintDialog::NUpTabPage::setupLayout()
showAdvancedControls( false );
}
-void PrintDialog::NUpTabPage::Resize()
-{
- maLayout.setManagedArea( Rectangle( Point( 0, 0 ), GetOutputSizePixel() ) );
-}
-
void PrintDialog::NUpTabPage::initFromMultiPageSetup( const vcl::PrinterController::MultiPageSetup& i_rMPS )
{
maSheetMarginEdt.SetValue( maSheetMarginEdt.Normalize( i_rMPS.nLeftMargin ), FUNIT_100TH_MM );
@@ -641,7 +635,6 @@ PrintDialog::JobTabPage::JobTabPage( Window* i_pParent, const ResId& rResId )
, maNoCollateImg( VclResId( SV_PRINT_NOCOLLATE_IMG ) )
, maNoCollateHCImg( VclResId( SV_PRINT_NOCOLLATE_HC_IMG ) )
, mnCollateUIMode( 0 )
- , maLayout( NULL, true )
{
FreeResource();
@@ -681,39 +674,37 @@ void PrintDialog::JobTabPage::setupLayout()
// sets the results of GetOptimalSize in a normal ListBox
maPrinters.SetDropDownLineCount( 4 );
- Size aBorder( LogicToPixel( Size( 5, 5 ), MapMode( MAP_APPFONT ) ) );
-
- maLayout.setParentWindow( this );
- maLayout.setOuterBorder( aBorder.Width() );
+ boost::shared_ptr<vcl::RowOrColumn> xLayout =
+ boost::dynamic_pointer_cast<vcl::RowOrColumn>( getLayout() );
// add printer fixed line
- maLayout.addWindow( &maPrinterFL );
+ xLayout->addWindow( &maPrinterFL );
// add print LB
- maLayout.addWindow( &maPrinters, 3 );
+ xLayout->addWindow( &maPrinters, 3 );
// create a row for details button/text and properties button
- boost::shared_ptr< vcl::RowOrColumn > xDetRow( new vcl::RowOrColumn( &maLayout, false ) );
- maLayout.addChild( xDetRow );
+ boost::shared_ptr< vcl::RowOrColumn > xDetRow( new vcl::RowOrColumn( xLayout.get(), false ) );
+ xLayout->addChild( xDetRow );
xDetRow->addWindow( &maDetailsBtn );
xDetRow->addChild( new vcl::Spacer( xDetRow.get(), 2 ) );
xDetRow->addWindow( &maSetupButton );
// create an indent for details
- boost::shared_ptr< vcl::Indenter > xIndent( new vcl::Indenter( &maLayout ) );
- maLayout.addChild( xIndent );
+ boost::shared_ptr< vcl::Indenter > xIndent( new vcl::Indenter( xLayout.get() ) );
+ xLayout->addChild( xIndent );
// remember details controls
mxDetails = xIndent;
// create a column for the details
- boost::shared_ptr< vcl::LabelColumn > xLabelCol( new vcl::LabelColumn( xIndent.get(), aBorder.Height() ) );
+ boost::shared_ptr< vcl::LabelColumn > xLabelCol( new vcl::LabelColumn( xIndent.get() ) );
xIndent->setChild( xLabelCol );
xLabelCol->addRow( &maStatusLabel, &maStatusTxt );
xLabelCol->addRow( &maLocationLabel, &maLocationTxt );
xLabelCol->addRow( &maCommentLabel, &maCommentTxt );
// add print range and copies columns
- maLayout.addWindow( &maCopies );
- boost::shared_ptr< vcl::RowOrColumn > xRangeRow( new vcl::RowOrColumn( &maLayout, false, aBorder.Width() ) );
- maLayout.addChild( xRangeRow );
+ xLayout->addWindow( &maCopies );
+ boost::shared_ptr< vcl::RowOrColumn > xRangeRow( new vcl::RowOrColumn( xLayout.get(), false ) );
+ xLayout->addChild( xRangeRow );
// create print range and add to range row
mxPrintRange.reset( new vcl::RowOrColumn( xRangeRow.get() ) );
@@ -780,11 +771,6 @@ void PrintDialog::JobTabPage::storeToSettings()
rtl::OUString::createFromAscii( maCollateBox.IsChecked() ? "true" : "false" ) );
}
-void PrintDialog::JobTabPage::Resize()
-{
- maLayout.setManagedArea( Rectangle( Point( 0, 0 ), GetSizePixel() ) );
-}
-
PrintDialog::OutputOptPage::OutputOptPage( Window* i_pParent, const ResId& i_rResId )
: TabPage( i_pParent, i_rResId )
, maOptionsLine( this, VclResId( SV_PRINT_OPT_PRINT_FL ) )
@@ -808,15 +794,13 @@ PrintDialog::OutputOptPage::~OutputOptPage()
void PrintDialog::OutputOptPage::setupLayout()
{
- Size aBorder( LogicToPixel( Size( 5, 5 ), MapMode( MAP_APPFONT ) ) );
+ boost::shared_ptr<vcl::RowOrColumn> xLayout =
+ boost::dynamic_pointer_cast<vcl::RowOrColumn>( getLayout() );
- maLayout.setParentWindow( this );
- maLayout.setOuterBorder( aBorder.Width() );
-
- maLayout.addWindow( &maOptionsLine );
- boost::shared_ptr<vcl::Indenter> xIndent( new vcl::Indenter( &maLayout, aBorder.Width() ) );
- maLayout.addChild( xIndent );
- boost::shared_ptr<vcl::RowOrColumn> xCol( new vcl::RowOrColumn( xIndent.get(), aBorder.Height() ) );
+ xLayout->addWindow( &maOptionsLine );
+ boost::shared_ptr<vcl::Indenter> xIndent( new vcl::Indenter( xLayout.get(), -1 ) );
+ xLayout->addChild( xIndent );
+ boost::shared_ptr<vcl::RowOrColumn> xCol( new vcl::RowOrColumn( xIndent.get() ) );
xIndent->setChild( xCol );
mxOptGroup = xCol;
xCol->addWindow( &maToFileBox );
@@ -844,12 +828,6 @@ void PrintDialog::OutputOptPage::storeToSettings()
rtl::OUString::createFromAscii( maToFileBox.IsChecked() ? "true" : "false" ) );
}
-void PrintDialog::OutputOptPage::Resize()
-{
- maLayout.setManagedArea( Rectangle( Point( 0, 0 ), GetSizePixel() ) );
-}
-
-
PrintDialog::PrintDialog( Window* i_pParent, const boost::shared_ptr<PrinterController>& i_rController )
: ModalDialog( i_pParent, VclResId( SV_DLG_PRINT ) )
, maOKButton( this, VclResId( SV_PRINT_OK ) )
@@ -1057,13 +1035,14 @@ PrintDialog::~PrintDialog()
void PrintDialog::setupLayout()
{
- Size aBorder( LogicToPixel( Size( 5, 5 ), MapMode( MAP_APPFONT ) ) );
+ boost::shared_ptr<vcl::RowOrColumn> xLayout =
+ boost::dynamic_pointer_cast<vcl::RowOrColumn>( getLayout() );
+ xLayout->setOuterBorder( 0 );
- maLayout.setParentWindow( this );
- boost::shared_ptr< vcl::RowOrColumn > xPreviewAndTab( new vcl::RowOrColumn( &maLayout, false ) );
- size_t nIndex = maLayout.addChild( xPreviewAndTab, 5 );
- maLayout.setBorders( nIndex, aBorder.Width(), aBorder.Width(), aBorder.Width(), 0 );
+ boost::shared_ptr< vcl::RowOrColumn > xPreviewAndTab( new vcl::RowOrColumn( xLayout.get(), false ) );
+ size_t nIndex = xLayout->addChild( xPreviewAndTab, 5 );
+ xLayout->setBorders( nIndex, -1, -1, -1, 0 );
// setup column for preview and sub controls
boost::shared_ptr< vcl::RowOrColumn > xPreview( new vcl::RowOrColumn( xPreviewAndTab.get() ) );
@@ -1087,12 +1066,12 @@ void PrintDialog::setupLayout()
xPreviewAndTab->addWindow( &maTabCtrl );
// add the button line
- maLayout.addWindow( &maButtonLine );
+ xLayout->addWindow( &maButtonLine );
// add the row for the buttons
- boost::shared_ptr< vcl::RowOrColumn > xButtons( new vcl::RowOrColumn( &maLayout, false ) );
- nIndex = maLayout.addChild( xButtons );
- maLayout.setBorders( nIndex, aBorder.Width(), 0, aBorder.Width(), aBorder.Width() );
+ boost::shared_ptr< vcl::RowOrColumn > xButtons( new vcl::RowOrColumn( xLayout.get(), false ) );
+ nIndex = xLayout->addChild( xButtons );
+ xLayout->setBorders( nIndex, -1, 0, -1, -1 );
Size aMinSize( maCancelButton.GetSizePixel() );
// insert help button
@@ -1210,17 +1189,15 @@ void updateMaxSize( const Size& i_rCheckSize, Size& o_rMaxSize )
void PrintDialog::setupOptionalUI()
{
- Size aBorder( LogicToPixel( Size( 5, 5 ), MapMode( MAP_APPFONT ) ) );
-
- std::vector<vcl::RowOrColumn*> aDynamicColumns;
- vcl::RowOrColumn* pCurColumn = 0;
+ std::vector< boost::shared_ptr<vcl::RowOrColumn> > aDynamicColumns;
+ boost::shared_ptr< vcl::RowOrColumn > pCurColumn;
Window* pCurParent = 0, *pDynamicPageParent = 0;
USHORT nOptPageId = 9, nCurSubGroup = 0;
bool bOnStaticPage = false;
bool bSubgroupOnStaticPage = false;
- std::multimap< rtl::OUString, vcl::RowOrColumn* > aPropertyToDependencyRowMap;
+ std::multimap< rtl::OUString, boost::shared_ptr<vcl::RowOrColumn> > aPropertyToDependencyRowMap;
const Sequence< PropertyValue >& rOptions( maPController->getUIOptions() );
for( int i = 0; i < rOptions.getLength(); i++ )
@@ -1331,37 +1308,40 @@ void PrintDialog::setupOptionalUI()
{
// restore to dynamic
pCurParent = pDynamicPageParent;
- pCurColumn = aDynamicColumns.empty() ? NULL : aDynamicColumns.back();
+ if( ! aDynamicColumns.empty() )
+ pCurColumn = aDynamicColumns.back();
+ else
+ pCurColumn.reset();
bOnStaticPage = false;
bSubgroupOnStaticPage = false;
if( aGroupingHint.equalsAscii( "PrintRange" ) )
{
- pCurColumn = maJobPage.mxPrintRange.get();
+ pCurColumn = maJobPage.mxPrintRange;
pCurParent = &maJobPage; // set job page as current parent
bOnStaticPage = true;
}
else if( aGroupingHint.equalsAscii( "OptionsPage" ) )
{
- pCurColumn = &maOptionsPage.maLayout;
+ pCurColumn = boost::dynamic_pointer_cast<vcl::RowOrColumn>(maOptionsPage.getLayout());
pCurParent = &maOptionsPage; // set options page as current parent
bOnStaticPage = true;
}
else if( aGroupingHint.equalsAscii( "OptionsPageOptGroup" ) )
{
- pCurColumn = maOptionsPage.mxOptGroup.get();
+ pCurColumn = maOptionsPage.mxOptGroup;
pCurParent = &maOptionsPage; // set options page as current parent
bOnStaticPage = true;
}
else if( aGroupingHint.equalsAscii( "LayoutPage" ) )
{
- pCurColumn = &maNUpPage.maLayout;
+ pCurColumn = boost::dynamic_pointer_cast<vcl::RowOrColumn>(maNUpPage.getLayout());
pCurParent = &maNUpPage; // set layout page as current parent
bOnStaticPage = true;
}
else if( aGroupingHint.getLength() )
{
- pCurColumn = &maJobPage.maLayout;
+ pCurColumn = boost::dynamic_pointer_cast<vcl::RowOrColumn>(maJobPage.getLayout());
pCurParent = &maJobPage; // set job page as current parent
bOnStaticPage = true;
}
@@ -1386,10 +1366,9 @@ void PrintDialog::setupOptionalUI()
// reset subgroup counter
nCurSubGroup = 0;
- aDynamicColumns.push_back( new vcl::RowOrColumn( NULL, true, aBorder.Width() ) );
+ aDynamicColumns.push_back( boost::dynamic_pointer_cast<vcl::RowOrColumn>(pNewGroup->getLayout()) );
pCurColumn = aDynamicColumns.back();
pCurColumn->setParentWindow( pNewGroup );
- pCurColumn->setOuterBorder( aBorder.Width() );
bSubgroupOnStaticPage = false;
bOnStaticPage = false;
}
@@ -1419,10 +1398,10 @@ void PrintDialog::setupOptionalUI()
}
// add an indent to the current column
- vcl::Indenter* pIndent = new vcl::Indenter( pCurColumn, aBorder.Width() );
+ vcl::Indenter* pIndent = new vcl::Indenter( pCurColumn.get(), -1 );
pCurColumn->addChild( pIndent );
// and create a column inside the indent
- pCurColumn = new vcl::RowOrColumn( pIndent );
+ pCurColumn.reset( new vcl::RowOrColumn( pIndent ) );
pIndent->setChild( pCurColumn );
}
// EVIL
@@ -1446,17 +1425,17 @@ void PrintDialog::setupOptionalUI()
maPropertyToWindowMap[ aPropertyName ].push_back( &maNUpPage.maBrochureBtn );
maControlToPropertyMap[&maNUpPage.maBrochureBtn] = aPropertyName;
- aPropertyToDependencyRowMap.insert( std::pair< rtl::OUString, vcl::RowOrColumn* >( aPropertyName, maNUpPage.mxBrochureDep.get() ) );
+ aPropertyToDependencyRowMap.insert( std::pair< rtl::OUString, boost::shared_ptr<vcl::RowOrColumn> >( aPropertyName, maNUpPage.mxBrochureDep ) );
}
else
{
- vcl::RowOrColumn* pSaveCurColumn = pCurColumn;
+ boost::shared_ptr<vcl::RowOrColumn> pSaveCurColumn( pCurColumn );
if( bUseDependencyRow )
{
// find the correct dependency row (if any)
- std::pair< std::multimap< rtl::OUString, vcl::RowOrColumn* >::iterator,
- std::multimap< rtl::OUString, vcl::RowOrColumn* >::iterator > aDepRange;
+ std::pair< std::multimap< rtl::OUString, boost::shared_ptr<vcl::RowOrColumn> >::iterator,
+ std::multimap< rtl::OUString, boost::shared_ptr<vcl::RowOrColumn> >::iterator > aDepRange;
aDepRange = aPropertyToDependencyRowMap.equal_range( aDependsOnName );
if( aDepRange.first != aDepRange.second )
{
@@ -1495,16 +1474,16 @@ void PrintDialog::setupOptionalUI()
// set help text
setHelpText( pNewBox, aHelpTexts, 0 );
- vcl::RowOrColumn* pDependencyRow = new vcl::RowOrColumn( pCurColumn, false );
+ boost::shared_ptr<vcl::RowOrColumn> pDependencyRow( new vcl::RowOrColumn( pCurColumn.get(), false ) );
pCurColumn->addChild( pDependencyRow );
- aPropertyToDependencyRowMap.insert( std::pair< rtl::OUString, vcl::RowOrColumn* >( aPropertyName, pDependencyRow ) );
+ aPropertyToDependencyRowMap.insert( std::pair< rtl::OUString, boost::shared_ptr<vcl::RowOrColumn> >( aPropertyName, pDependencyRow ) );
// add checkbox to current column
pDependencyRow->addWindow( pNewBox );
}
else if( aCtrlType.equalsAscii( "Radio" ) && pCurParent )
{
- vcl::RowOrColumn* pRadioColumn = pCurColumn;
+ boost::shared_ptr<vcl::RowOrColumn> pRadioColumn( pCurColumn );
if( aText.getLength() )
{
// add a FixedText:
@@ -1520,10 +1499,10 @@ void PrintDialog::setupOptionalUI()
// add fixed text to current column
pCurColumn->addWindow( pHeading );
// add an indent to the current column
- vcl::Indenter* pIndent = new vcl::Indenter( pCurColumn, 15 );
+ vcl::Indenter* pIndent = new vcl::Indenter( pCurColumn.get(), 15 );
pCurColumn->addChild( pIndent );
// and create a column inside the indent
- pRadioColumn = new vcl::RowOrColumn( pIndent );
+ pRadioColumn.reset( new vcl::RowOrColumn( pIndent ) );
pIndent->setChild( pRadioColumn );
}
// iterate options
@@ -1533,11 +1512,11 @@ void PrintDialog::setupOptionalUI()
pVal->Value >>= nSelectVal;
for( sal_Int32 m = 0; m < aChoices.getLength(); m++ )
{
- boost::shared_ptr<vcl::LabeledElement> pLabel( new vcl::LabeledElement( pRadioColumn, 1 ) );
+ boost::shared_ptr<vcl::LabeledElement> pLabel( new vcl::LabeledElement( pRadioColumn.get(), 1 ) );
pRadioColumn->addChild( pLabel );
boost::shared_ptr<vcl::RowOrColumn> pDependencyRow( new vcl::RowOrColumn( pLabel.get(), false ) );
pLabel->setElement( pDependencyRow );
- aPropertyToDependencyRowMap.insert( std::pair< rtl::OUString, vcl::RowOrColumn* >( aPropertyName, pDependencyRow.get() ) );
+ aPropertyToDependencyRowMap.insert( std::pair< rtl::OUString, boost::shared_ptr<vcl::RowOrColumn> >( aPropertyName, pDependencyRow ) );
RadioButton* pBtn = new RadioButton( pCurParent, m == 0 ? WB_GROUP : 0 );
maControls.push_front( pBtn );
@@ -1565,9 +1544,9 @@ void PrintDialog::setupOptionalUI()
) && pCurParent )
{
// create a row in the current column
- vcl::RowOrColumn* pFieldColumn = new vcl::RowOrColumn( pCurColumn, false );
+ boost::shared_ptr<vcl::RowOrColumn> pFieldColumn( new vcl::RowOrColumn( pCurColumn.get(), false ) );
pCurColumn->addChild( pFieldColumn );
- aPropertyToDependencyRowMap.insert( std::pair< rtl::OUString, vcl::RowOrColumn* >( aPropertyName, pFieldColumn ) );
+ aPropertyToDependencyRowMap.insert( std::pair< rtl::OUString, boost::shared_ptr<vcl::RowOrColumn> >( aPropertyName, pFieldColumn ) );
vcl::LabeledElement* pLabel = NULL;
if( aText.getLength() )
@@ -1582,7 +1561,7 @@ void PrintDialog::setupOptionalUI()
setSmartId( pHeading, "FixedText", -1, aPropertyName );
// add to row
- pLabel = new vcl::LabeledElement( pFieldColumn, 2 );
+ pLabel = new vcl::LabeledElement( pFieldColumn.get(), 2 );
pFieldColumn->addChild( pLabel );
pLabel->setLabel( pHeading );
}
@@ -1717,11 +1696,11 @@ void PrintDialog::setupOptionalUI()
// FIXME: the GetNativeControlRegion call on Windows has some issues
// (which skew the results of GetOptimalSize())
// however fixing this thoroughly needs to take interaction with paint into
- // acoount, making the right fix less simple. Fix this the right way
+ // account, making the right fix less simple. Fix this the right way
// at some point. For now simply add some space at the lowest element
- size_t nIndex = maJobPage.maLayout.countElements();
+ size_t nIndex = maJobPage.getLayout()->countElements();
if( nIndex > 0 ) // sanity check
- maJobPage.maLayout.setBorders( nIndex-1, 0, 0, 0, aBorder.Width() );
+ maJobPage.getLayout()->setBorders( nIndex-1, 0, 0, 0, -1 );
#endif
// create auto mnemomnics now so they can be calculated in layout
@@ -1731,13 +1710,13 @@ void PrintDialog::setupOptionalUI()
ImplWindowAutoMnemonic( this );
// calculate job page
- Size aMaxSize = maJobPage.maLayout.getOptimalSize( WINDOWSIZE_PREFERRED );
+ Size aMaxSize = maJobPage.getLayout()->getOptimalSize( WINDOWSIZE_PREFERRED );
// and layout page
- updateMaxSize( maNUpPage.maLayout.getOptimalSize( WINDOWSIZE_PREFERRED ), aMaxSize );
+ updateMaxSize( maNUpPage.getLayout()->getOptimalSize( WINDOWSIZE_PREFERRED ), aMaxSize );
// and options page
- updateMaxSize( maOptionsPage.maLayout.getOptimalSize( WINDOWSIZE_PREFERRED ), aMaxSize );
+ updateMaxSize( maOptionsPage.getLayout()->getOptimalSize( WINDOWSIZE_PREFERRED ), aMaxSize );
- for( std::vector< vcl::RowOrColumn* >::iterator it = aDynamicColumns.begin();
+ for( std::vector< boost::shared_ptr<vcl::RowOrColumn> >::iterator it = aDynamicColumns.begin();
it != aDynamicColumns.end(); ++it )
{
Size aPageSize( (*it)->getOptimalSize( WINDOWSIZE_PREFERRED ) );
@@ -1765,19 +1744,7 @@ void PrintDialog::setupOptionalUI()
maTabCtrl.SetMinimumSizePixel( maTabCtrl.GetSizePixel() );
}
- // and finally arrange controls
- for( std::vector< vcl::RowOrColumn* >::iterator it = aDynamicColumns.begin();
- it != aDynamicColumns.end(); ++it )
- {
- (*it)->setManagedArea( Rectangle( Point(), aTabSize ) );
- delete *it;
- *it = NULL;
- }
- maJobPage.Resize();
- maNUpPage.Resize();
- maOptionsPage.Resize();
-
- Size aSz = maLayout.getOptimalSize( WINDOWSIZE_PREFERRED );
+ Size aSz = getLayout()->getOptimalSize( WINDOWSIZE_PREFERRED );
SetOutputSizePixel( aSz );
}
@@ -1812,7 +1779,7 @@ void PrintDialog::checkControlDependencies()
maJobPage.maCollateImage.SetSizePixel( aImgSize );
maJobPage.maCollateImage.SetImage( bHC ? aHCImg : aImg );
maJobPage.maCollateImage.SetModeImage( aHCImg, BMP_COLOR_HIGHCONTRAST );
- maJobPage.maLayout.resize();
+ maJobPage.getLayout()->resize();
// enable setup button only for printers that can be setup
bool bHaveSetup = maPController->getPrinter()->HasSupport( SUPPORT_SETUPDIALOG );
@@ -1827,7 +1794,7 @@ void PrintDialog::checkControlDependencies()
aPrinterSize.Width() = aSetupPos.X() - aPrinterPos.X() - LogicToPixel( Size( 5, 5 ), MapMode( MAP_APPFONT ) ).Width();
maJobPage.maPrinters.SetSizePixel( aPrinterSize );
maJobPage.maSetupButton.Show();
- maLayout.resize();
+ getLayout()->resize();
}
}
else
@@ -1841,7 +1808,7 @@ void PrintDialog::checkControlDependencies()
aPrinterSize.Width() = aSetupPos.X() + aSetupSize.Width() - aPrinterPos.X();
maJobPage.maPrinters.SetSizePixel( aPrinterSize );
maJobPage.maSetupButton.Hide();
- maLayout.resize();
+ getLayout()->resize();
}
}
}
@@ -2082,7 +2049,7 @@ void PrintDialog::updateNupFromPages()
if( bCustom )
{
// see if we have to enlarge the dialog to make the tab page fit
- Size aCurSize( maNUpPage.maLayout.getOptimalSize( WINDOWSIZE_PREFERRED ) );
+ Size aCurSize( maNUpPage.getLayout()->getOptimalSize( WINDOWSIZE_PREFERRED ) );
Size aTabSize( maTabCtrl.GetTabPageSizePixel() );
if( aTabSize.Height() < aCurSize.Height() )
{
@@ -2205,7 +2172,7 @@ IMPL_LINK( PrintDialog, ClickHdl, Button*, pButton )
else if( pButton == &maOptionsPage.maToFileBox )
{
maOKButton.SetText( maOptionsPage.maToFileBox.IsChecked() ? maPrintToFileText : maPrintText );
- maLayout.resize();
+ getLayout()->resize();
}
else if( pButton == &maNUpPage.maBrochureBtn )
{
@@ -2241,7 +2208,7 @@ IMPL_LINK( PrintDialog, ClickHdl, Button*, pButton )
{
maDetailsCollapsedSize = GetOutputSizePixel();
// enlarge dialog if necessary
- Size aMinSize( maJobPage.maLayout.getOptimalSize( WINDOWSIZE_MINIMUM ) );
+ Size aMinSize( maJobPage.getLayout()->getOptimalSize( WINDOWSIZE_MINIMUM ) );
Size aCurSize( maJobPage.GetSizePixel() );
if( aCurSize.Height() < aMinSize.Height() )
{
@@ -2515,7 +2482,7 @@ void PrintDialog::Command( const CommandEvent& rEvt )
void PrintDialog::Resize()
{
- maLayout.setManagedArea( Rectangle( Point( 0, 0 ), GetSizePixel() ) );
+ // maLayout.setManagedArea( Rectangle( Point( 0, 0 ), GetSizePixel() ) );
// and do the preview; however the metafile does not need to be gotten anew
preparePreview( false );
diff --git a/vcl/source/window/window.cxx b/vcl/source/window/window.cxx
index 77da205131ea..fe2af486c53a 100755
--- a/vcl/source/window/window.cxx
+++ b/vcl/source/window/window.cxx
@@ -295,6 +295,8 @@ void Window::ImplUpdateGlobalSettings( AllSettings& rSettings, BOOL bCallHdl )
aTmpSt.SetHighContrastMode( FALSE );
rSettings.SetStyleSettings( aTmpSt );
ImplGetFrame()->UpdateSettings( rSettings );
+ // reset default border width for layouters
+ ImplGetSVData()->maAppData.mnDefaultLayoutBorder = -1;
// Verify availability of the configured UI font, otherwise choose "Andale Sans UI"
String aUserInterfaceFont;
@@ -599,6 +601,7 @@ void Window::ImplInitWindowData( WindowType nType )
mpWindowImpl->mpDlgCtrlDownWindow = NULL; // window for dialog control
mpWindowImpl->mpFirstDel = NULL; // Dtor notification list
mpWindowImpl->mpUserData = NULL; // user data
+ mpWindowImpl->mpExtImpl = NULL; // extended implementation data
mpWindowImpl->mpCursor = NULL; // cursor
mpWindowImpl->mpControlFont = NULL; // font propertie
mpWindowImpl->mpVCLXWindow = NULL;
@@ -1129,6 +1132,8 @@ void Window::ImplCallResize()
// #88419# Most classes don't call the base class in Resize() and Move(),
// => Call ImpleResize/Move instead of Resize/Move directly...
ImplCallEventListeners( VCLEVENT_WINDOW_RESIZE );
+
+ ImplExtResize();
}
// -----------------------------------------------------------------------
@@ -4342,6 +4347,8 @@ namespace
Window::~Window()
{
+ ImplFreeExtWindowImpl();
+
vcl::LazyDeletor<Window>::Undelete( this );
DBG_DTOR( Window, ImplDbgCheckWindow );
@@ -4779,6 +4786,13 @@ void Window::doLazyDelete()
}
// -----------------------------------------------------------------------
+void Window::InterceptChildWindowKeyDown( sal_Bool bIntercept )
+{
+ if( mpWindowImpl->mpSysObj )
+ mpWindowImpl->mpSysObj->InterceptChildWindowKeyDown( bIntercept );
+}
+
+// -----------------------------------------------------------------------
void Window::MouseMove( const MouseEvent& rMEvt )
{
diff --git a/vcl/source/window/window4.cxx b/vcl/source/window/window4.cxx
new file mode 100644
index 000000000000..577a573c2015
--- /dev/null
+++ b/vcl/source/window/window4.cxx
@@ -0,0 +1,224 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "precompiled_vcl.hxx"
+
+#include "vcl/window.hxx"
+#include "vcl/window.h"
+#include "vcl/svdata.hxx"
+#include "vcl/arrange.hxx"
+
+#include "com/sun/star/beans/PropertyValue.hpp"
+
+#include <map>
+#include <vector>
+
+using namespace com::sun::star;
+
+namespace vcl
+{
+ struct ExtWindowImpl
+ {
+ ExtWindowImpl()
+ : mbOwnedByParent( false )
+ {}
+ ~ExtWindowImpl()
+ {}
+
+ boost::shared_ptr< WindowArranger > mxLayout;
+ bool mbOwnedByParent;
+ rtl::OUString maIdentifier;
+ };
+}
+
+void Window::ImplDeleteOwnedChildren()
+{
+ Window* pChild = mpWindowImpl->mpFirstChild;
+ while ( pChild )
+ {
+ Window* pDeleteCandidate = pChild;
+ pChild = pChild->mpWindowImpl->mpNext;
+ vcl::ExtWindowImpl* pDelImpl = pDeleteCandidate->ImplGetExtWindowImpl();
+ if( pDelImpl && pDelImpl->mbOwnedByParent )
+ delete pDeleteCandidate;
+ }
+}
+
+void Window::ImplFreeExtWindowImpl()
+{
+ ImplDeleteOwnedChildren();
+ if( mpWindowImpl )
+ {
+ delete mpWindowImpl->mpExtImpl;
+ mpWindowImpl->mpExtImpl = NULL;
+ }
+}
+
+vcl::ExtWindowImpl* Window::ImplGetExtWindowImpl() const
+{
+ vcl::ExtWindowImpl* pImpl = NULL;
+ if( mpWindowImpl )
+ {
+ if( ! mpWindowImpl->mpExtImpl && ! mpWindowImpl->mbInDtor )
+ mpWindowImpl->mpExtImpl = new vcl::ExtWindowImpl();
+ pImpl = mpWindowImpl->mpExtImpl;
+ }
+ return pImpl;
+}
+
+void Window::ImplExtResize()
+{
+ if( mpWindowImpl && mpWindowImpl->mpExtImpl )
+ {
+ if( mpWindowImpl->mpExtImpl->mxLayout.get() )
+ mpWindowImpl->mpExtImpl->mxLayout->setManagedArea( Rectangle( Point( 0, 0 ), GetSizePixel() ) );
+ }
+}
+
+boost::shared_ptr< vcl::WindowArranger > Window::getLayout()
+{
+ boost::shared_ptr< vcl::WindowArranger > xRet;
+ vcl::ExtWindowImpl* pImpl = ImplGetExtWindowImpl();
+ if( pImpl )
+ {
+ if( ! pImpl->mxLayout.get() )
+ {
+ pImpl->mxLayout.reset( new vcl::LabelColumn() );
+ pImpl->mxLayout->setParentWindow( this );
+ pImpl->mxLayout->setOuterBorder( -1 );
+ }
+ xRet = pImpl->mxLayout;
+ }
+
+ return xRet;
+}
+
+void Window::addWindow( Window* i_pWin, bool i_bTakeOwnership )
+{
+ vcl::ExtWindowImpl* pImpl = ImplGetExtWindowImpl();
+ if( pImpl && i_pWin )
+ {
+ vcl::ExtWindowImpl* pChildImpl = i_pWin->ImplGetExtWindowImpl();
+ if( pChildImpl )
+ {
+ i_pWin->SetParent( this );
+ pChildImpl->mbOwnedByParent = i_bTakeOwnership;
+ }
+ }
+}
+
+Window* Window::removeWindow( Window* i_pWin, Window* i_pNewParent )
+{
+ Window* pRet = NULL;
+ if( i_pWin )
+ {
+ vcl::ExtWindowImpl* pImpl = ImplGetExtWindowImpl();
+ if( pImpl )
+ {
+ vcl::ExtWindowImpl* pChildImpl = i_pWin->ImplGetExtWindowImpl();
+ if( pChildImpl )
+ {
+ if( ! i_pNewParent )
+ pChildImpl->mbOwnedByParent = false;
+ i_pWin->SetParent( i_pNewParent );
+ pRet = i_pWin;
+ }
+ }
+ }
+ return pRet;
+}
+
+Window* Window::findWindow( const rtl::OUString& i_rIdentifier ) const
+{
+ if( getIdentifier() == i_rIdentifier )
+ return const_cast<Window*>(this);
+
+ Window* pChild = mpWindowImpl->mpFirstChild;
+ while ( pChild )
+ {
+ Window* pResult = pChild->findWindow( i_rIdentifier );
+ if( pResult )
+ return pResult;
+ pChild = pChild->mpWindowImpl->mpNext;
+ }
+
+ return NULL;
+}
+
+const rtl::OUString& Window::getIdentifier() const
+{
+ static rtl::OUString aEmptyStr;
+
+ return (mpWindowImpl && mpWindowImpl->mpExtImpl) ? mpWindowImpl->mpExtImpl->maIdentifier : aEmptyStr;
+}
+
+void Window::setIdentifier( const rtl::OUString& i_rIdentifier )
+{
+ vcl::ExtWindowImpl* pImpl = ImplGetExtWindowImpl();
+ if( pImpl )
+ pImpl->maIdentifier = i_rIdentifier;
+}
+
+void Window::setProperties( const uno::Sequence< beans::PropertyValue >& i_rProps )
+{
+ const beans::PropertyValue* pVals = i_rProps.getConstArray();
+ for( sal_Int32 i = 0; i < i_rProps.getLength(); i++ )
+ {
+ if( pVals[i].Name.equalsAscii( "Enabled" ) )
+ {
+ sal_Bool bVal = sal_True;
+ if( pVals[i].Value >>= bVal )
+ Enable( bVal );
+ }
+ else if( pVals[i].Name.equalsAscii( "Visible" ) )
+ {
+ sal_Bool bVal = sal_True;
+ if( pVals[i].Value >>= bVal )
+ Show( bVal );
+ }
+ else if( pVals[i].Name.equalsAscii( "Text" ) )
+ {
+ rtl::OUString aText;
+ if( pVals[i].Value >>= aText )
+ SetText( aText );
+ }
+ }
+}
+
+uno::Sequence< beans::PropertyValue > Window::getProperties() const
+{
+ uno::Sequence< beans::PropertyValue > aProps( 3 );
+ aProps[0].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Enabled" ) );
+ aProps[0].Value = uno::makeAny( sal_Bool( IsEnabled() ) );
+ aProps[1].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Visible" ) );
+ aProps[1].Value = uno::makeAny( sal_Bool( IsVisible() ) );
+ aProps[2].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Text" ) );
+ aProps[2].Value = uno::makeAny( rtl::OUString( GetText() ) );
+
+ return aProps;
+}
+
diff --git a/vcl/source/window/wpropset.cxx b/vcl/source/window/wpropset.cxx
new file mode 100644
index 000000000000..4aaa3f987b77
--- /dev/null
+++ b/vcl/source/window/wpropset.cxx
@@ -0,0 +1,346 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "precompiled_vcl.hxx"
+
+#include "vcl/wpropset.hxx"
+#include "vcl/window.hxx"
+#include "vcl/vclevent.hxx"
+#include "vcl/svdata.hxx"
+
+#include "com/sun/star/lang/XMultiServiceFactory.hpp"
+#include "com/sun/star/beans/PropertyValue.hpp"
+#include "com/sun/star/beans/PropertyAttribute.hpp"
+#include "com/sun/star/beans/XPropertySet.hpp"
+#include "com/sun/star/beans/XPropertyContainer.hpp"
+#include "com/sun/star/beans/XPropertyAccess.hpp"
+
+#include "cppuhelper/basemutex.hxx"
+#include "cppuhelper/compbase1.hxx"
+
+#include <map>
+
+using namespace vcl;
+using namespace com::sun::star;
+
+/*
+
+TODO:
+- release solarmutex during outside UNO calls
+- in ChildEventListener protect against reentry by using PostUserEvent
+
+*/
+
+class vcl::WindowPropertySetListener :
+ public cppu::BaseMutex,
+ public cppu::WeakComponentImplHelper1< com::sun::star::beans::XPropertyChangeListener >,
+ private boost::noncopyable
+{
+ WindowPropertySet* mpParent;
+ bool mbSuspended;
+public:
+ WindowPropertySetListener( WindowPropertySet* pParent )
+ : cppu::WeakComponentImplHelper1< com::sun::star::beans::XPropertyChangeListener >( m_aMutex )
+ , mpParent( pParent )
+ , mbSuspended( false )
+ {}
+
+ virtual ~WindowPropertySetListener()
+ {
+ }
+
+ using cppu::WeakComponentImplHelperBase::disposing;
+ virtual void SAL_CALL disposing( const lang::EventObject& ) throw()
+ {
+ }
+
+ virtual void SAL_CALL propertyChange( const beans::PropertyChangeEvent& i_rEvent ) throw()
+ {
+ if( ! mbSuspended )
+ mpParent->propertyChange( i_rEvent );
+ }
+
+ void suspend( bool i_bSuspended )
+ {
+ mbSuspended = i_bSuspended;
+ }
+};
+
+class vcl::WindowPropertySetData
+{
+public:
+
+ struct PropertyMapEntry
+ {
+ Window* mpWindow;
+ boost::shared_ptr<WindowArranger> mpLayout;
+ uno::Sequence< beans::PropertyValue > maSavedValues;
+
+ PropertyMapEntry( Window* i_pWindow = NULL,
+ const boost::shared_ptr<WindowArranger>& i_pLayout = boost::shared_ptr<WindowArranger>() )
+ : mpWindow( i_pWindow )
+ , mpLayout( i_pLayout )
+ {}
+
+ uno::Sequence< beans::PropertyValue > getProperties() const
+ {
+ if( mpWindow )
+ return mpWindow->getProperties();
+ else if( mpLayout.get() )
+ return mpLayout->getProperties();
+ return uno::Sequence< beans::PropertyValue >();
+ }
+
+ void setProperties( const uno::Sequence< beans::PropertyValue >& i_rProps ) const
+ {
+ if( mpWindow )
+ mpWindow->setProperties( i_rProps );
+ else if( mpLayout.get() )
+ mpLayout->setProperties( i_rProps );
+ }
+ };
+
+ Window* mpTopWindow;
+ bool mbOwner;
+ std::map< rtl::OUString, PropertyMapEntry > maProperties;
+ uno::Reference< beans::XPropertySet > mxPropSet;
+ uno::Reference< beans::XPropertyAccess > mxPropSetAccess;
+ uno::Reference< beans::XPropertyChangeListener > mxListener;
+ vcl::WindowPropertySetListener* mpListener;
+
+ WindowPropertySetData()
+ : mpTopWindow( NULL )
+ , mbOwner( false )
+ , mpListener( NULL )
+ {}
+
+ ~WindowPropertySetData()
+ {
+ // release layouters, possibly interface properties before destroying
+ // the involved parent to be on the safe side
+ maProperties.clear();
+ if( mbOwner )
+ delete mpTopWindow;
+ }
+};
+
+static rtl::OUString getIdentifiedPropertyName( const rtl::OUString& i_rIdentifier, const rtl::OUString& i_rName )
+{
+ rtl::OUStringBuffer aBuf( i_rIdentifier.getLength() + 1 + i_rName.getLength() );
+ aBuf.append( i_rIdentifier );
+ aBuf.append( sal_Unicode( '#' ) );
+ aBuf.append( i_rName );
+ return aBuf.makeStringAndClear();
+}
+
+static void spliceIdentifiedPropertyName( const rtl::OUString& i_rIdentifiedPropName,
+ rtl::OUString& o_rIdentifier,
+ rtl::OUString& o_rPropName )
+{
+ sal_Int32 nIndex = 0;
+ o_rIdentifier = i_rIdentifiedPropName.getToken( 0, sal_Unicode( '#' ), nIndex );
+ if( nIndex != -1 )
+ o_rPropName = i_rIdentifiedPropName.copy( nIndex );
+ else
+ o_rPropName = rtl::OUString();
+}
+
+WindowPropertySet::WindowPropertySet( Window* i_pTopWindow, bool i_bTakeOwnership )
+: mpImpl( new vcl::WindowPropertySetData )
+{
+ mpImpl->mpTopWindow = i_pTopWindow;
+ mpImpl->mbOwner = i_bTakeOwnership;
+
+ mpImpl->mpTopWindow->AddChildEventListener( LINK( this, WindowPropertySet, ChildEventListener ) );
+
+ mpImpl->mxPropSet = uno::Reference< beans::XPropertySet >(
+ ImplGetSVData()->maAppData.mxMSF->createInstance( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.beans.PropertyBag" ) ) ),
+ uno::UNO_QUERY );
+ OSL_ENSURE( mpImpl->mxPropSet.is(), "could not create instance of com.sun.star.beans.PropertyBag" );
+ mpImpl->mxPropSetAccess = uno::Reference< beans::XPropertyAccess >( mpImpl->mxPropSet, uno::UNO_QUERY );
+ OSL_ENSURE( mpImpl->mxPropSet.is(), "could not query XPropertyAccess interface" );
+ if( ! mpImpl->mxPropSetAccess.is() )
+ mpImpl->mxPropSet.clear();
+
+ addWindowToSet( i_pTopWindow );
+
+ setupProperties();
+
+ if( mpImpl->mxPropSet.is() )
+ {
+ mpImpl->mxListener.set( mpImpl->mpListener = new WindowPropertySetListener( this ) );
+ }
+}
+
+WindowPropertySet::~WindowPropertySet()
+{
+ mpImpl->mpTopWindow->RemoveChildEventListener( LINK( this, WindowPropertySet, ChildEventListener ) );
+
+ delete mpImpl;
+ mpImpl = NULL;
+}
+
+uno::Reference< beans::XPropertySet > WindowPropertySet::getPropertySet() const
+{
+ return mpImpl->mxPropSet;
+}
+
+void WindowPropertySet::addLayoutToSet( const boost::shared_ptr< WindowArranger >& i_pLayout )
+{
+ if( i_pLayout.get() )
+ {
+ if( i_pLayout->getIdentifier().getLength() )
+ {
+ WindowPropertySetData::PropertyMapEntry& rEntry = mpImpl->maProperties[ i_pLayout->getIdentifier() ];
+ OSL_ENSURE( rEntry.mpWindow == 0 && rEntry.mpLayout.get() == 0, "inserted layout has duplicate name" );
+ rEntry.mpWindow = NULL;
+ rEntry.mpLayout = i_pLayout;
+ rEntry.maSavedValues = i_pLayout->getProperties();
+ }
+ // insert child layouts
+ size_t nChildren = i_pLayout->countElements();
+ for( size_t i = 0; i < nChildren; i++ )
+ addLayoutToSet( i_pLayout->getChild( i ) );
+ }
+}
+
+void WindowPropertySet::addWindowToSet( Window* i_pWindow )
+{
+ if( i_pWindow->getIdentifier().getLength() ) // no name, no properties
+ {
+ WindowPropertySetData::PropertyMapEntry& rEntry = mpImpl->maProperties[ i_pWindow->getIdentifier() ];
+ OSL_ENSURE( rEntry.mpWindow == 0 && rEntry.mpLayout.get() == 0, "inserted window has duplicate name" );
+ rEntry.mpWindow = i_pWindow;
+ rEntry.mpLayout.reset();
+ rEntry.maSavedValues = i_pWindow->getProperties();
+ }
+ addLayoutToSet( i_pWindow->getLayout() );
+
+ Window* pWin = i_pWindow->GetWindow( WINDOW_FIRSTCHILD );
+ while( pWin )
+ {
+ addWindowToSet( pWin );
+ pWin = pWin->GetWindow( WINDOW_NEXT );
+ }
+}
+
+void WindowPropertySet::setupProperties()
+{
+ uno::Reference< beans::XPropertyContainer > xCont( mpImpl->mxPropSet, uno::UNO_QUERY );
+ OSL_ENSURE( xCont.is(), "could not get XPropertyContainer interface" );
+ if( ! xCont.is() )
+ return;
+
+ for( std::map< rtl::OUString, WindowPropertySetData::PropertyMapEntry >::iterator it
+ = mpImpl->maProperties.begin(); it != mpImpl->maProperties.end(); ++it )
+ {
+ uno::Sequence< beans::PropertyValue > aOutsideValues( it->second.maSavedValues );
+ beans::PropertyValue* pVal = aOutsideValues.getArray();
+ for( sal_Int32 i = 0; i < aOutsideValues.getLength(); i++ )
+ {
+ pVal[i].Name = getIdentifiedPropertyName( it->first, pVal[i].Name );
+ xCont->addProperty( pVal[i].Name,
+ beans::PropertyAttribute::BOUND | beans:: PropertyAttribute::CONSTRAINED,
+ pVal[i].Value
+ );
+ }
+ }
+}
+
+void WindowPropertySet::propertyChange( const beans::PropertyChangeEvent& i_rEvent )
+{
+ rtl::OUString aIdentifier, aProperty;
+ spliceIdentifiedPropertyName( i_rEvent.PropertyName, aIdentifier, aProperty );
+ std::map< rtl::OUString, WindowPropertySetData::PropertyMapEntry >::iterator it =
+ mpImpl->maProperties.find( aIdentifier );
+ if( it != mpImpl->maProperties.end() )
+ {
+ uno::Sequence< beans::PropertyValue > aSet( 1 );
+ aSet[0].Name = aProperty;
+ aSet[0].Value = i_rEvent.NewValue;
+ it->second.setProperties( aSet );
+ }
+}
+
+IMPL_LINK( vcl::WindowPropertySet, ChildEventListener, VclWindowEvent*, pEvent )
+{
+ // find window in our properties
+ std::map< rtl::OUString, WindowPropertySetData::PropertyMapEntry >::iterator it
+ = mpImpl->maProperties.find( pEvent->GetWindow()->getIdentifier() );
+ if( it != mpImpl->maProperties.end() ) // this is valid, some unnamed child may have sent an event
+ {
+ ULONG nId = pEvent->GetId();
+ // check if anything interesting happened
+ if(
+ // general windowy things
+ nId == VCLEVENT_WINDOW_SHOW ||
+ nId == VCLEVENT_WINDOW_HIDE ||
+ nId == VCLEVENT_WINDOW_ENABLED ||
+ nId == VCLEVENT_WINDOW_DISABLED ||
+ // button thingies
+ nId == VCLEVENT_BUTTON_CLICK ||
+ nId == VCLEVENT_PUSHBUTTON_TOGGLE ||
+ nId == VCLEVENT_RADIOBUTTON_TOGGLE ||
+ nId == VCLEVENT_CHECKBOX_TOGGLE ||
+ // listbox
+ nId == VCLEVENT_LISTBOX_SELECT ||
+ // edit
+ nId == VCLEVENT_EDIT_MODIFY
+ )
+ {
+ WindowPropertySetData::PropertyMapEntry& rEntry = it->second;
+ // collect changes
+ uno::Sequence< beans::PropertyValue > aNewProps( rEntry.getProperties() );
+ uno::Sequence< beans::PropertyValue > aNewPropsOut( aNewProps );
+
+ // translate to identified properties
+ beans::PropertyValue* pValues = aNewPropsOut.getArray();
+ for( sal_Int32 i = 0; i < aNewPropsOut.getLength(); i++ )
+ pValues[i].Name = getIdentifiedPropertyName( it->first, pValues[i].Name );
+
+ // broadcast changes
+ bool bWasVeto = false;
+ mpImpl->mpListener->suspend( true );
+ try
+ {
+ mpImpl->mxPropSetAccess->setPropertyValues( aNewPropsOut );
+ }
+ catch( beans::PropertyVetoException& )
+ {
+ bWasVeto = true;
+ }
+ mpImpl->mpListener->suspend( false );
+
+ if( ! bWasVeto ) // changes accepted ?
+ rEntry.maSavedValues = rEntry.getProperties();
+ else // no, reset
+ rEntry.setProperties( rEntry.maSavedValues );
+ }
+ }
+
+ return 0;
+}
diff --git a/vcl/unx/gtk/window/gtkobject.cxx b/vcl/unx/gtk/window/gtkobject.cxx
index 2a2bbe78078a..c5f5a168f653 100644
--- a/vcl/unx/gtk/window/gtkobject.cxx
+++ b/vcl/unx/gtk/window/gtkobject.cxx
@@ -209,3 +209,8 @@ void GtkSalObject::signalDestroy( GtkObject* pObj, gpointer object )
pThis->m_pSocket = NULL;
}
}
+
+void GtkSalObject::InterceptChildWindowKeyDown( sal_Bool /*bIntercept*/ )
+{
+}
+
diff --git a/vcl/unx/headless/svpdummies.cxx b/vcl/unx/headless/svpdummies.cxx
index 5983ff18c34f..0a67b147804a 100644
--- a/vcl/unx/headless/svpdummies.cxx
+++ b/vcl/unx/headless/svpdummies.cxx
@@ -61,6 +61,7 @@ void SvpSalObject::GrabFocus() {}
void SvpSalObject::SetBackground() {}
void SvpSalObject::SetBackground( SalColor ) {}
const SystemEnvData* SvpSalObject::GetSystemData() const { return &m_aSystemChildData; }
+void SvpSalObject::InterceptChildWindowKeyDown( sal_Bool ) {}
// SalI18NImeStatus
SvpImeStatus::~SvpImeStatus() {}
diff --git a/vcl/unx/headless/svpdummies.hxx b/vcl/unx/headless/svpdummies.hxx
index febf7eef6bbe..ea7667ce51ca 100644
--- a/vcl/unx/headless/svpdummies.hxx
+++ b/vcl/unx/headless/svpdummies.hxx
@@ -58,6 +58,8 @@ public:
virtual void SetBackground( SalColor nSalColor );
virtual const SystemEnvData* GetSystemData() const;
+
+ virtual void InterceptChildWindowKeyDown( sal_Bool bIntercept );
};
class SvpImeStatus : public SalI18NImeStatus
diff --git a/vcl/unx/inc/plugins/gtk/gtkobject.hxx b/vcl/unx/inc/plugins/gtk/gtkobject.hxx
index ea740249f1c6..9d3f235b8894 100644
--- a/vcl/unx/inc/plugins/gtk/gtkobject.hxx
+++ b/vcl/unx/inc/plugins/gtk/gtkobject.hxx
@@ -64,6 +64,7 @@ public:
virtual const SystemEnvData* GetSystemData() const;
+ virtual void InterceptChildWindowKeyDown( sal_Bool bIntercept );
};
#endif // _SV_SALOBJ_H
diff --git a/vcl/unx/inc/salobj.h b/vcl/unx/inc/salobj.h
index fa9f1309c8ca..d7d9334f281b 100644
--- a/vcl/unx/inc/salobj.h
+++ b/vcl/unx/inc/salobj.h
@@ -98,6 +98,7 @@ public:
virtual const SystemEnvData* GetSystemData() const;
+ virtual void InterceptChildWindowKeyDown( sal_Bool bIntercept );
};
#endif // _SV_SALOBJ_H
diff --git a/vcl/unx/source/gdi/salprnpsp.cxx b/vcl/unx/source/gdi/salprnpsp.cxx
index 417704eb3b69..ece724d717cb 100644
--- a/vcl/unx/source/gdi/salprnpsp.cxx
+++ b/vcl/unx/source/gdi/salprnpsp.cxx
@@ -1187,14 +1187,12 @@ BOOL PspSalPrinter::StartJob( const String* i_pFileName, const String& i_rJobNam
aContext.Version = vcl::PDFWriter::PDF_1_4;
aContext.Tagged = false;
aContext.EmbedStandardFonts = true;
- aContext.Encrypt = false;
aContext.DocumentLocale = Application::GetSettings().GetLocale();
// prepare doc info
- vcl::PDFDocInfo aDocInfo;
- aDocInfo.Title = i_rJobName;
- aDocInfo.Creator = i_rAppName;
- aDocInfo.Producer = i_rAppName;
+ aContext.DocumentInfo.Title = i_rJobName;
+ aContext.DocumentInfo.Creator = i_rAppName;
+ aContext.DocumentInfo.Producer = i_rAppName;
// define how we handle metafiles in PDFWriter
vcl::PDFWriter::PlayMetafileContext aMtfContext;
@@ -1271,11 +1269,10 @@ BOOL PspSalPrinter::StartJob( const String* i_pFileName, const String& i_rJobNam
#if defined __SUNPRO_CC
#pragma disable_warn
#endif
- pWriter.reset( new vcl::PDFWriter( aContext ) );
+ pWriter.reset( new vcl::PDFWriter( aContext, uno::Reference< beans::XMaterialHolder >() ) );
#if defined __SUNPRO_CC
#pragma enable_warn
#endif
- pWriter->SetDocInfo( aDocInfo );
}
pWriter->NewPage( TenMuToPt( aNewParm.maPageSize.Width() ),
diff --git a/vcl/unx/source/window/salobj.cxx b/vcl/unx/source/window/salobj.cxx
index 647b95ae032c..2ff6d05c35c6 100644
--- a/vcl/unx/source/window/salobj.cxx
+++ b/vcl/unx/source/window/salobj.cxx
@@ -559,3 +559,10 @@ long X11SalObject::Dispatch( XEvent* pEvent )
}
return 0;
}
+
+// -----------------------------------------------------------------------
+
+void X11SalObject::InterceptChildWindowKeyDown( sal_Bool /*bIntercept*/ )
+{
+}
+
diff --git a/vcl/win/inc/saldata.hxx b/vcl/win/inc/saldata.hxx
index ec67272ed07f..f95f1e0ca96b 100644
--- a/vcl/win/inc/saldata.hxx
+++ b/vcl/win/inc/saldata.hxx
@@ -213,6 +213,7 @@ void ImplSalYieldMutexAcquire();
void ImplSalYieldMutexRelease();
ULONG ImplSalReleaseYieldMutex();
void ImplSalAcquireYieldMutex( ULONG nCount );
+sal_Bool ImplInterceptChildWindowKeyDown( MSG& rMsg );
// \\WIN\SOURCE\WINDOW\SALFRAME.CXX
LRESULT CALLBACK SalFrameWndProcA( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam );
diff --git a/vcl/win/inc/salobj.h b/vcl/win/inc/salobj.h
index 11ae96931321..ae7ea5271800 100644
--- a/vcl/win/inc/salobj.h
+++ b/vcl/win/inc/salobj.h
@@ -46,6 +46,7 @@ public:
RGNDATA* mpStdClipRgnData; // Cache Standard-ClipRegion-Data
RECT* mpNextClipRect; // Naechstes ClipRegion-Rect
BOOL mbFirstClipRect; // Flag for first cliprect to insert
+ sal_Bool mbInterceptChildWindowKeyDown; // Intercept the KeyDown event sent to system child window
WinSalObject* mpNextObject; // pointer to next object
@@ -64,6 +65,7 @@ public:
virtual void SetBackground();
virtual void SetBackground( SalColor nSalColor );
virtual const SystemEnvData* GetSystemData() const;
+ virtual void InterceptChildWindowKeyDown( sal_Bool bIntercept );
};
#endif // _SV_SALOBJ_H
diff --git a/vcl/win/source/app/salinst.cxx b/vcl/win/source/app/salinst.cxx
index 419723ee6442..a05d2d0b6502 100644
--- a/vcl/win/source/app/salinst.cxx
+++ b/vcl/win/source/app/salinst.cxx
@@ -719,8 +719,12 @@ void ImplSalYield( BOOL bWait, BOOL bHandleAllCurrentEvents )
{
if ( ImplPeekMessage( &aMsg, 0, 0, 0, PM_REMOVE ) )
{
- TranslateMessage( &aMsg );
- ImplSalDispatchMessage( &aMsg );
+ if ( !ImplInterceptChildWindowKeyDown( aMsg ) )
+ {
+ TranslateMessage( &aMsg );
+ ImplSalDispatchMessage( &aMsg );
+ }
+
bOneEvent = bWasMsg = true;
}
else
@@ -731,8 +735,11 @@ void ImplSalYield( BOOL bWait, BOOL bHandleAllCurrentEvents )
{
if ( ImplGetMessage( &aMsg, 0, 0, 0 ) )
{
- TranslateMessage( &aMsg );
- ImplSalDispatchMessage( &aMsg );
+ if ( !ImplInterceptChildWindowKeyDown( aMsg ) )
+ {
+ TranslateMessage( &aMsg );
+ ImplSalDispatchMessage( &aMsg );
+ }
}
}
}
diff --git a/vcl/win/source/gdi/salprn.cxx b/vcl/win/source/gdi/salprn.cxx
index 9d8d41723f64..702ff639ed84 100644
--- a/vcl/win/source/gdi/salprn.cxx
+++ b/vcl/win/source/gdi/salprn.cxx
@@ -1798,8 +1798,11 @@ WIN_BOOL CALLBACK SalPrintAbortProc( HDC hPrnDC, int /* nError */ )
MSG aMsg;
if ( ImplPeekMessage( &aMsg, 0, 0, 0, PM_REMOVE ) )
{
- TranslateMessage( &aMsg );
- ImplDispatchMessage( &aMsg );
+ if ( !ImplInterceptChildWindowKeyDown( aMsg ) )
+ {
+ TranslateMessage( &aMsg );
+ ImplDispatchMessage( &aMsg );
+ }
i++;
if ( i > 15 )
bWhile = FALSE;
@@ -2060,8 +2063,12 @@ BOOL WinSalPrinter::StartJob( const XubString* pFileName,
MSG aMsg;
if ( ImplPeekMessage( &aMsg, 0, 0, 0, PM_REMOVE ) )
{
- TranslateMessage( &aMsg );
- ImplDispatchMessage( &aMsg );
+ if ( !ImplInterceptChildWindowKeyDown( aMsg ) )
+ {
+ TranslateMessage( &aMsg );
+ ImplDispatchMessage( &aMsg );
+ }
+
i++;
if ( i > 15 )
bWhile = FALSE;
diff --git a/vcl/win/source/window/salobj.cxx b/vcl/win/source/window/salobj.cxx
index 2f657968284f..6d00242ef313 100644
--- a/vcl/win/source/window/salobj.cxx
+++ b/vcl/win/source/window/salobj.cxx
@@ -39,6 +39,7 @@
#include <salframe.h>
#include <salobj.h>
#include <tools/debug.hxx>
+#include <vcl/svapp.hxx>
// =======================================================================
@@ -103,6 +104,46 @@ WinSalFrame* ImplFindSalObjectFrame( HWND hWnd )
// -----------------------------------------------------------------------
+sal_Bool ImplInterceptChildWindowKeyDown( MSG& rMsg )
+{
+ sal_Bool bResult = sal_False;
+ if ( rMsg.message == WM_KEYDOWN )
+ {
+ wchar_t pClassName[10];
+ sal_Int32 nLen = GetClassNameW( rMsg.hwnd, pClassName, 10 );
+ if ( !( nLen == 9 && wcsncmp( pClassName, SAL_OBJECT_CLASSNAMEW, nLen ) == 0 ) )
+ {
+ // look for the first SalObject in the parent hierarchy
+ HWND hWin = rMsg.hwnd;
+ HWND hLastOLEWindow = hWin;
+ WinSalObject* pSalObj = NULL;
+ do
+ {
+ hLastOLEWindow = hWin;
+ hWin = ::GetParent( hWin );
+ if ( hWin )
+ {
+ nLen = GetClassNameW( hWin, pClassName, 10 );
+ if ( nLen == 9 && wcsncmp( pClassName, SAL_OBJECT_CLASSNAMEW, nLen ) == 0 )
+ pSalObj = GetSalObjWindowPtr( hWin );
+ }
+ } while( hWin && !pSalObj );
+
+ if ( pSalObj && pSalObj->mbInterceptChildWindowKeyDown && pSalObj->maSysData.hWnd )
+ {
+ bResult = ( 1 == ImplSendMessage( pSalObj->maSysData.hWnd, rMsg.message, rMsg.wParam, rMsg.lParam ) );
+ }
+ }
+ }
+
+ return bResult;
+}
+
+// -----------------------------------------------------------------------
+
+
+// -----------------------------------------------------------------------
+
LRESULT CALLBACK SalSysMsgProc( int nCode, WPARAM wParam, LPARAM lParam )
{
// Used for Unicode and none Unicode
@@ -623,6 +664,7 @@ WinSalObject::WinSalObject()
mhLastFocusWnd = 0;
maSysData.nSize = sizeof( SystemEnvData );
mpStdClipRgnData = NULL;
+ mbInterceptChildWindowKeyDown = sal_False;
// Insert object in objectlist
mpNextObject = pSalData->mpFirstObject;
@@ -836,3 +878,11 @@ const SystemEnvData* WinSalObject::GetSystemData() const
{
return &maSysData;
}
+
+// -----------------------------------------------------------------------
+
+void WinSalObject::InterceptChildWindowKeyDown( sal_Bool bIntercept )
+{
+ mbInterceptChildWindowKeyDown = bIntercept;
+}
+