/**************************************************************
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
 *************************************************************/



// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sfx2.hxx"

#include <com/sun/star/uno/Reference.hxx>

#include <com/sun/star/document/XDocumentProperties.hpp>
#include <com/sun/star/document/UpdateDocMode.hpp>
#include <com/sun/star/frame/XLayoutManager.hpp>
#include <com/sun/star/embed/ElementModes.hpp>
#include <com/sun/star/document/XStandaloneDocumentInfo.hpp>
#include <com/sun/star/beans/XFastPropertySet.hpp>
#include <tools/cachestr.hxx>
#include <vcl/msgbox.hxx>
#include <svl/style.hxx>
#include <vcl/wrkwin.hxx>

#include <svl/stritem.hxx>
#include <svl/intitem.hxx>
#include <svl/rectitem.hxx>
#include <svl/eitem.hxx>
#include <svl/urihelper.hxx>
#include <svl/ctloptions.hxx>
#include <comphelper/storagehelper.hxx>
#include <comphelper/processfactory.hxx>
#include <unotools/securityoptions.hxx>
#include <svtools/sfxecode.hxx>
#include <svtools/ehdl.hxx>
#include <tools/datetime.hxx>
#include <math.h>

#include <unotools/saveopt.hxx>
#include <unotools/useroptions.hxx>
#include <unotools/localfilehelper.hxx>
#include <vcl/virdev.hxx>
#include <vcl/oldprintadaptor.hxx>

#include <sfx2/app.hxx>
#include "sfx2/sfxresid.hxx"
#include "appdata.hxx"
#include <sfx2/dinfdlg.hxx>
#include "fltfnc.hxx"
#include <sfx2/docfac.hxx>
#include <sfx2/viewsh.hxx>
#include <sfx2/objsh.hxx>
#include "objshimp.hxx"
#include <sfx2/evntconf.hxx>
#include "sfx2/sfxhelp.hxx"
#include <sfx2/dispatch.hxx>
#include <sfx2/printer.hxx>
#include "sfx2/basmgr.hxx"
#include <sfx2/viewfrm.hxx>
#include <sfx2/doctempl.hxx>
#include "doc.hrc"
#include <sfx2/sfxbasemodel.hxx>
#include <sfx2/docfile.hxx>
#include <sfx2/request.hxx>
#include "openflag.hxx"
#include "querytemplate.hxx"

using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;

//====================================================================

//====================================================================

static
bool operator> (const util::DateTime& i_rLeft, const util::DateTime& i_rRight)
{
    if ( i_rLeft.Year != i_rRight.Year )
        return i_rLeft.Year > i_rRight.Year;

    if ( i_rLeft.Month != i_rRight.Month )
        return i_rLeft.Month > i_rRight.Month;

    if ( i_rLeft.Day != i_rRight.Day )
        return i_rLeft.Day > i_rRight.Day;

    if ( i_rLeft.Hours != i_rRight.Hours )
        return i_rLeft.Hours > i_rRight.Hours;

    if ( i_rLeft.Minutes != i_rRight.Minutes )
        return i_rLeft.Minutes > i_rRight.Minutes;

    if ( i_rLeft.Seconds != i_rRight.Seconds )
        return i_rLeft.Seconds > i_rRight.Seconds;

    if ( i_rLeft.HundredthSeconds != i_rRight.HundredthSeconds )
        return i_rLeft.HundredthSeconds > i_rRight.HundredthSeconds;

    return sal_False;
}


::boost::shared_ptr<GDIMetaFile>
SfxObjectShell::GetPreviewMetaFile( sal_Bool bFullContent ) const
{
	return CreatePreviewMetaFile_Impl( bFullContent, sal_False );
}


::boost::shared_ptr<GDIMetaFile>
SfxObjectShell::CreatePreviewMetaFile_Impl( sal_Bool bFullContent, sal_Bool bHighContrast ) const
{
	// Nur wenn gerade nicht gedruckt wird, darf DoDraw aufgerufen
	// werden, sonst wird u.U. der Printer abgeschossen !
	SfxViewFrame *pFrame = SfxViewFrame::GetFirst( this );
	if ( pFrame && pFrame->GetViewShell() &&
		 pFrame->GetViewShell()->GetPrinter() &&
		 pFrame->GetViewShell()->GetPrinter()->IsPrinting() )
		 return ::boost::shared_ptr<GDIMetaFile>();

    ::boost::shared_ptr<GDIMetaFile> pFile(new GDIMetaFile);

	VirtualDevice aDevice;
	aDevice.EnableOutput( sal_False );

	// adjust the output device if HC-metafile is requested
	if ( bHighContrast )
		aDevice.SetDrawMode( aDevice.GetDrawMode() | DRAWMODE_SETTINGSLINE | DRAWMODE_SETTINGSFILL | DRAWMODE_SETTINGSTEXT | DRAWMODE_SETTINGSGRADIENT );

    MapMode aMode( ((SfxObjectShell*)this)->GetMapUnit() );
    aDevice.SetMapMode( aMode );
    pFile->SetPrefMapMode( aMode );

    Size aTmpSize;
    sal_Int8 nAspect;
    if ( bFullContent )
    {
        nAspect = ASPECT_CONTENT;
        aTmpSize = GetVisArea( nAspect ).GetSize();
    }
    else
    {
        nAspect = ASPECT_THUMBNAIL;
        aTmpSize = ((SfxObjectShell*)this)->GetFirstPageSize();
    }

    pFile->SetPrefSize( aTmpSize );
    DBG_ASSERT( aTmpSize.Height()*aTmpSize.Width(),
                "size of first page is 0, overload GetFirstPageSize or set vis-area!" );

    pFile->Record( &aDevice );

    LanguageType eLang;
    // #120038# use local incarnation, so deletion cannot be forgotten
    const SvtCTLOptions aCTLOptions;

    if ( SvtCTLOptions::NUMERALS_HINDI == aCTLOptions.GetCTLTextNumerals() )
        eLang = LANGUAGE_ARABIC_SAUDI_ARABIA;
    else if ( SvtCTLOptions::NUMERALS_ARABIC == aCTLOptions.GetCTLTextNumerals() )
        eLang = LANGUAGE_ENGLISH;
    else
        eLang = (LanguageType) Application::GetSettings().GetLanguage();

    aDevice.SetDigitLanguage( eLang );

    ((SfxObjectShell*)this)->DoDraw( &aDevice, Point(0,0), aTmpSize, JobSetup(), nAspect );
    pFile->Stop();

	return pFile;
}

//====================================================================

void SfxObjectShell::UpdateDocInfoForSave()
{
    uno::Reference<document::XDocumentProperties> xDocProps(getDocProperties());

	// clear user data if recommend (see 'Tools - Options - Open/StarOffice - Security')
	if ( SvtSecurityOptions().IsOptionSet(
            SvtSecurityOptions::E_DOCWARN_REMOVEPERSONALINFO ) )
    {
		xDocProps->resetUserData( ::rtl::OUString() );
    }
	else if ( IsModified() )
	{
		String aUserName = SvtUserOptions().GetFullName();
		if ( !IsUseUserData() )
        {
			// remove all data pointing to the current user
            if (xDocProps->getAuthor().equals(aUserName)) {
                xDocProps->setAuthor( ::rtl::OUString() );
            }
            xDocProps->setModifiedBy( ::rtl::OUString() );
            if (xDocProps->getPrintedBy().equals(aUserName)) {
                xDocProps->setPrintedBy( ::rtl::OUString() );
            }
        }
		else
		{
			// update ModificationAuthor, revision and editing time
            ::DateTime now;
            xDocProps->setModificationDate( util::DateTime(
                now.Get100Sec(), now.GetSec(), now.GetMin(),
                now.GetHour(), now.GetDay(), now.GetMonth(),
                now.GetYear() ) );
            xDocProps->setModifiedBy( aUserName );
			if ( !HasName() || pImp->bIsSaving )
				// QUESTION: not in case of "real" SaveAs as this is meant to create a new document
				UpdateTime_Impl( xDocProps );
		}
	}
}

//--------------------------------------------------------------------

static void
lcl_add(util::Duration & rDur, Time const& rTime)
{
    // here we don't care about overflow: rDur is converted back to seconds
    // anyway, and Time cannot store more than ~4000 hours
    rDur.Hours   += rTime.GetHour();
    rDur.Minutes += rTime.GetMin();
    rDur.Seconds += rTime.GetSec();
}

// Bearbeitungszeit aktualisieren
void SfxObjectShell::UpdateTime_Impl(
    const uno::Reference<document::XDocumentProperties> & i_xDocProps)
{
	// Get old time from documentinfo
    const sal_Int32 secs = i_xDocProps->getEditingDuration();
    util::Duration editDuration(sal_False, 0, 0, 0,
            secs/3600, (secs%3600)/60, secs%60, 0);

	// Initialize some local member! Its necessary for wollow operations!
	DateTime	aNow					;	// Date and time at current moment
	Time		n24Time		(24,0,0,0)	;	// Time-value for 24 hours - see follow calculation
	sal_uIntPtr		nDays		= 0			;	// Count of days between now and last editing
	Time		nAddTime	(0)			;	// Value to add on aOldTime

	// Safe impossible cases!
	// User has changed time to the past between last editing and now ... its not possible!!!
	DBG_ASSERT( !(aNow.GetDate()<pImp->nTime.GetDate()), "Timestamp of last change is in the past ?!..." );

	// Do the follow only, if user has NOT changed time to the past.
	// Else add a time of 0 to aOldTime ... !!!
	if (aNow.GetDate()>=pImp->nTime.GetDate())
	{
		// Get count of days last editing.
		nDays = aNow.GetSecFromDateTime(pImp->nTime.GetDate())/86400 ;

		if (nDays==0)
		{
			// If no day between now and last editing - calculate time directly.
            nAddTime    =   (const Time&)aNow - (const Time&)pImp->nTime ;
		}
		else
		// If time of working without save greater then 1 month (!) ....
		// we add 0 to aOldTime!
		if (nDays<=31)
		{
			// If 1 or up to 31 days between now and last editing - calculate time indirectly.
			// nAddTime = (24h - nTime) + (nDays * 24h) + aNow
			--nDays;
 			nAddTime	 =	nDays*n24Time.GetTime()	;
			nAddTime	+=	n24Time-(const Time&)pImp->nTime		;
			nAddTime	+=	aNow					;
		}

        lcl_add(editDuration, nAddTime);
	}

	pImp->nTime = aNow;
    try {
        const sal_Int32 newSecs( (editDuration.Hours*3600)
            + (editDuration.Minutes*60) + editDuration.Seconds);
        i_xDocProps->setEditingDuration(newSecs);
        i_xDocProps->setEditingCycles(i_xDocProps->getEditingCycles() + 1);
    }
    catch (lang::IllegalArgumentException &)
    {
        // ignore overflow
    }
}

//--------------------------------------------------------------------

SfxDocumentInfoDialog* SfxObjectShell::CreateDocumentInfoDialog
(
	Window*             pParent,
	const SfxItemSet&   rSet
)
{
	return new SfxDocumentInfoDialog(pParent, rSet);
}

//--------------------------------------------------------------------

SfxStyleSheetBasePool* SfxObjectShell::GetStyleSheetPool()
{
	return 0;
}

void SfxObjectShell::SetOrganizerSearchMask(
	SfxStyleSheetBasePool* pStylePool) const
{
	pStylePool->SetSearchMask(
        SFX_STYLE_FAMILY_ALL,
		SFXSTYLEBIT_USERDEF | SFXSTYLEBIT_USED);
}

//--------------------------------------------------------------------

sal_uInt16 SfxObjectShell::GetContentCount(
    sal_uInt16 nIdx1,
    sal_uInt16 /*nIdx2*/)
{
	switch(nIdx1)
	{
		case INDEX_IGNORE:
			return DEF_CONTENT_COUNT;
		case CONTENT_STYLE:
		{
			SfxStyleSheetBasePool *pStylePool = GetStyleSheetPool();
			if(!pStylePool)
				return 0;
			SetOrganizerSearchMask(pStylePool);
			return pStylePool->Count();
		}
		case CONTENT_MACRO:
			break;
/*
		case CONTENT_CONFIG:
			return ( GetConfigManager() ) ?
						GetConfigManager()->GetItemCount() : 0;
			break;
 */
	}
	return 0;
}


//--------------------------------------------------------------------
//TODO/CLEANUP: remove this method (it's virtual)
void  SfxObjectShell::TriggerHelpPI(sal_uInt16 nIdx1, sal_uInt16 nIdx2, sal_uInt16)
{
	if(nIdx1==CONTENT_STYLE && nIdx2 != INDEX_IGNORE) //StyleSheets
	{
		SfxStyleSheetBasePool *pStylePool = GetStyleSheetPool();
		SetOrganizerSearchMask(pStylePool);
	}
}

sal_Bool   SfxObjectShell::CanHaveChilds(sal_uInt16 nIdx1,
									   sal_uInt16 nIdx2)
{
	switch(nIdx1) {
	case INDEX_IGNORE:
		return sal_True;
	case CONTENT_STYLE:
		return INDEX_IGNORE == nIdx2 || !GetStyleSheetPool()? sal_False: sal_True;
	case CONTENT_MACRO:
//!!    return INDEX_IGNORE == nIdx2? sal_False: sal_True;
		return sal_False;
/*
	case CONTENT_CONFIG:
		return INDEX_IGNORE == nIdx2 ? sal_False : sal_True;
 */
	}
	return sal_False;
}

//--------------------------------------------------------------------

void SfxObjectShell::GetContent(String &rText,
								Bitmap &rClosedBitmap,
								Bitmap &rOpenedBitmap,
								sal_Bool &bCanDel,
								sal_uInt16 i,
								sal_uInt16 nIdx1,
								sal_uInt16 nIdx2 )
{
	DBG_ERRORFILE( "Non high contrast method called. Please update calling code!" );
	SfxObjectShell::GetContent( rText, rClosedBitmap, rOpenedBitmap, BMP_COLOR_NORMAL, bCanDel, i, nIdx1, nIdx2 );
}

//--------------------------------------------------------------------

void   SfxObjectShell::GetContent(String &rText,
								  Bitmap &rClosedBitmap,
								  Bitmap &rOpenedBitmap,
								  BmpColorMode eColorMode,
								  sal_Bool &bCanDel,
								  sal_uInt16 i,
								  sal_uInt16 nIdx1,
								  sal_uInt16 /*nIdx2*/ )
{
	bCanDel=sal_True;

	switch(nIdx1)
	{
		case INDEX_IGNORE:
		{
			sal_uInt16 nTextResId = 0;
			sal_uInt16 nClosedBitmapResId = 0; // evtl. sp"ater mal unterschiedliche
			sal_uInt16 nOpenedBitmapResId = 0; // "     "       "   "
			switch(i)
			{
				case CONTENT_STYLE:
					nTextResId = STR_STYLES;
					if ( eColorMode == BMP_COLOR_NORMAL )
					{
						nClosedBitmapResId= BMP_STYLES_CLOSED;
						nOpenedBitmapResId= BMP_STYLES_OPENED;
					}
					else
					{
						nClosedBitmapResId= BMP_STYLES_CLOSED_HC;
						nOpenedBitmapResId= BMP_STYLES_OPENED_HC;
					}
					break;
				case CONTENT_MACRO:
					nTextResId = STR_MACROS;
					if ( eColorMode == BMP_COLOR_NORMAL )
					{
						nClosedBitmapResId= BMP_STYLES_CLOSED;
						nOpenedBitmapResId= BMP_STYLES_OPENED;
					}
					else
					{
						nClosedBitmapResId= BMP_STYLES_CLOSED_HC;
						nOpenedBitmapResId= BMP_STYLES_OPENED_HC;
					}
					break;
/*
				case CONTENT_CONFIG:
					nTextResId = STR_CONFIG;
					nClosedBitmapResId= BMP_STYLES_CLOSED;
					nOpenedBitmapResId= BMP_STYLES_OPENED;
					break;
 */
			}

			if ( nTextResId )
			{
				rText  = String(SfxResId(nTextResId));
				rClosedBitmap = Bitmap(SfxResId(nClosedBitmapResId));
				rOpenedBitmap = Bitmap(SfxResId(nOpenedBitmapResId));
			}
			break;
		}

		case CONTENT_STYLE:
		{
			SfxStyleSheetBasePool *pStylePool = GetStyleSheetPool();
			SetOrganizerSearchMask(pStylePool);
			SfxStyleSheetBase *pStyle = (*pStylePool)[i];
			rText = pStyle->GetName();
			bCanDel=((pStyle->GetMask() & SFXSTYLEBIT_USERDEF)
					 == SFXSTYLEBIT_USERDEF);
			rClosedBitmap = rOpenedBitmap =
				GetStyleFamilyBitmap(pStyle->GetFamily(), eColorMode );
		}
			break;
		case CONTENT_MACRO:
			break;
/*
		case CONTENT_CONFIG:
			if ( GetConfigManager() )
			{
				rText = GetConfigManager()->GetItem(i);
				bCanDel = GetConfigManager()->CanDelete(i);
			}
			else
				rText = String();
			rClosedBitmap = Bitmap(SfxResId(BMP_STYLES_CLOSED));
			rOpenedBitmap = Bitmap(SfxResId(BMP_STYLES_OPENED));
			break;
*/
	}
}

//--------------------------------------------------------------------
Bitmap SfxObjectShell::GetStyleFamilyBitmap( SfxStyleFamily eFamily )
{
	DBG_ERRORFILE( "Non high contrast method called. Please update calling code!" );
	return SfxObjectShell::GetStyleFamilyBitmap( eFamily, BMP_COLOR_NORMAL );
}

//--------------------------------------------------------------------

Bitmap SfxObjectShell::GetStyleFamilyBitmap(SfxStyleFamily eFamily, BmpColorMode eColorMode )
{
	sal_uInt16 nResId = 0;
	switch(eFamily)
	{
		case SFX_STYLE_FAMILY_CHAR:
			nResId = ( eColorMode == BMP_COLOR_NORMAL ) ? BMP_STYLES_FAMILY1 : BMP_STYLES_FAMILY1_HC;
			break;
		case SFX_STYLE_FAMILY_PARA:
			nResId = ( eColorMode == BMP_COLOR_NORMAL ) ? BMP_STYLES_FAMILY2 : BMP_STYLES_FAMILY2_HC;
			break;
		case SFX_STYLE_FAMILY_FRAME:
			nResId = ( eColorMode == BMP_COLOR_NORMAL ) ? BMP_STYLES_FAMILY3 : BMP_STYLES_FAMILY3_HC;
			break;
		case SFX_STYLE_FAMILY_PAGE :
			nResId = ( eColorMode == BMP_COLOR_NORMAL ) ? BMP_STYLES_FAMILY4 : BMP_STYLES_FAMILY4_HC;
			break;
		case SFX_STYLE_FAMILY_PSEUDO:
		case SFX_STYLE_FAMILY_ALL:
			break;
	}

	if ( nResId )
		return Bitmap(SfxResId(nResId));
	else
		return Bitmap();
}


//--------------------------------------------------------------------

sal_Bool SfxObjectShell::Insert(SfxObjectShell &rSource,
							  sal_uInt16 nSourceIdx1,
							  sal_uInt16 nSourceIdx2,
							  sal_uInt16 /*nSourceIdx3*/,
							  sal_uInt16 &nIdx1,
							  sal_uInt16 &nIdx2,
							  sal_uInt16 &/*nIdx3*/,
							  sal_uInt16 &/*nDeleted*/)
{
	sal_Bool bRet = sal_False;

	if (INDEX_IGNORE == nIdx1 && CONTENT_STYLE == nSourceIdx1)
		nIdx1 = CONTENT_STYLE;

	if (CONTENT_STYLE == nSourceIdx1 && CONTENT_STYLE == nIdx1)
	{
		SfxStyleSheetBasePool* pHisPool  = rSource.GetStyleSheetPool();
		SfxStyleSheetBasePool* pMyPool   = GetStyleSheetPool();
		SetOrganizerSearchMask(pHisPool);
		SetOrganizerSearchMask(pMyPool);
        SfxStyleSheetBase* pHisSheet = NULL;

        if ( pHisPool && pHisPool->Count() > nSourceIdx2 )
            pHisSheet = (*pHisPool)[nSourceIdx2];

		// Einfuegen ist nur dann noetig, wenn ein StyleSheet
		// zwischen unterschiedlichen(!) Pools bewegt wird

        if ( pHisSheet && pMyPool != pHisPool )
		{
			if (INDEX_IGNORE == nIdx2)
			{
				nIdx2 = pMyPool->Count();
			}

			// wenn so eine Vorlage schon existiert: loeschen!
			String aOldName(pHisSheet->GetName());
			SfxStyleFamily eOldFamily = pHisSheet->GetFamily();

			SfxStyleSheetBase* pExist = pMyPool->Find(aOldName, eOldFamily);
			// sal_uInt16 nOldHelpId = pExist->GetHelpId(??? VB ueberlegt sich was);
			sal_Bool bUsedOrUserDefined;
			if( pExist )
			{
				bUsedOrUserDefined =
					pExist->IsUsed() || pExist->IsUserDefined();
				if( ErrorHandler::HandleError(
					*new MessageInfo( ERRCODE_SFXMSG_STYLEREPLACE, aOldName ) )
					!= ERRCODE_BUTTON_OK )
					return sal_False;
				else
				{
					pMyPool->Replace( *pHisSheet, *pExist );
					SetModified( sal_True );
					nIdx2 = nIdx1 = INDEX_IGNORE;
					return sal_True;
				}
			}

			SfxStyleSheetBase& rNewSheet = pMyPool->Make(
				aOldName, eOldFamily,
				pHisSheet->GetMask(), nIdx2);

			// ItemSet der neuen Vorlage fuellen
			rNewSheet.GetItemSet().Set(pHisSheet->GetItemSet());

			// wer bekommt den Neuen als Parent? wer benutzt den Neuen als Follow?
			SfxStyleSheetBase* pTestSheet = pMyPool->First();
			while (pTestSheet)
			{
				if (pTestSheet->GetFamily() == eOldFamily &&
					pTestSheet->HasParentSupport() &&
					pTestSheet->GetParent() == aOldName)
				{
					pTestSheet->SetParent(aOldName);
					// Verknuepfung neu aufbauen
				}

				if (pTestSheet->GetFamily() == eOldFamily &&
					pTestSheet->HasFollowSupport() &&
					pTestSheet->GetFollow() == aOldName)
				{
					pTestSheet->SetFollow(aOldName);
					// Verknuepfung neu aufbauen
				}

				pTestSheet = pMyPool->Next();
			}
			bUsedOrUserDefined =
				rNewSheet.IsUsed() || rNewSheet.IsUserDefined();


			// hat der Neue einen Parent? wenn ja, mit gleichem Namen bei uns suchen
			if (pHisSheet->HasParentSupport())
			{
				const String& rParentName = pHisSheet->GetParent();
				if (0 != rParentName.Len())
				{
					SfxStyleSheetBase* pParentOfNew =
						pMyPool->Find(rParentName, eOldFamily);
					if (pParentOfNew)
						rNewSheet.SetParent(rParentName);
				}
			}

			// hat der Neue einen Follow? wenn ja, mit gleichem
			// Namen bei uns suchen
			if (pHisSheet->HasFollowSupport())
			{
				const String& rFollowName = pHisSheet->GetFollow();
				if (0 != rFollowName.Len())
				{
					SfxStyleSheetBase* pFollowOfNew =
						pMyPool->Find(rFollowName, eOldFamily);
					if (pFollowOfNew)
						rNewSheet.SetFollow(rFollowName);
				}
			}

			SetModified( sal_True );
			if( !bUsedOrUserDefined ) nIdx2 = nIdx1 = INDEX_IGNORE;

			bRet = sal_True;
		}
		else
			bRet = sal_False;
	}
/*
	else if (nSourceIdx1 == CONTENT_CONFIG)
	{
		nIdx1 = CONTENT_CONFIG;

		SfxConfigManager *pCfgMgr = SFX_CFGMANAGER();
		if ( !GetConfigManager() )
		{
			SetConfigManager(new SfxConfigManager(0, pCfgMgr));
			SetTemplateConfig(sal_False);
			if (this == Current())
				GetConfigManager()->Activate(pCfgMgr);
		}

		if (GetConfigManager()->CopyItem(
			nSourceIdx2, nIdx2, rSource.GetConfigManager()))
		{
			SetModified(sal_True);
			bRet = sal_True;
            SFX_APP()->GetDispatcher_Impl()->Update_Impl(sal_True);
		}
	}
*/
	return bRet;
}

//--------------------------------------------------------------------

sal_Bool SfxObjectShell::Remove
(
	sal_uInt16 nIdx1,
	sal_uInt16 nIdx2,
	sal_uInt16 /*nIdx3*/
)
{
	sal_Bool bRet = sal_False;

	if (CONTENT_STYLE == nIdx1)
	{
		SfxStyleSheetBasePool* pMyPool  = GetStyleSheetPool();

		SetOrganizerSearchMask(pMyPool);

		SfxStyleSheetBase* pMySheet =  (*pMyPool)[nIdx2];
		String aName(pMySheet->GetName());
		String aEmpty;
		SfxStyleFamily  eFamily = pMySheet->GetFamily();
		pMyPool->Remove(pMySheet);
		bRet = sal_True;

		SfxStyleSheetBase* pTestSheet = pMyPool->First();
		while (pTestSheet)
		{
			if (pTestSheet->GetFamily() == eFamily &&
				pTestSheet->HasParentSupport() &&
				pTestSheet->GetParent() == aName)
			{
				pTestSheet->SetParent(aEmpty); // Verknuepfung aufloesen
			}

			if (pTestSheet->GetFamily() == eFamily &&
				pTestSheet->HasFollowSupport() &&
				pTestSheet->GetFollow() == aName)
			{
				pTestSheet->SetFollow(aEmpty); // Verknuepfung aufloesen
			}

			pTestSheet = pMyPool->Next();
		}

		SetModified( sal_True );
	}

	return bRet;
}

//--------------------------------------------------------------------

sal_Bool SfxObjectShell::Print
(
	Printer&        rPrt,
	sal_uInt16          nIdx1,
	sal_uInt16          /*nIdx2*/,
	sal_uInt16          /*nIdx3*/,
	const String*   pObjectName
)

/*  [Beschreibung]
*/

{
	switch(nIdx1)
	{
	  case CONTENT_STYLE:
		{
			SfxStyleSheetBasePool *pStylePool = GetStyleSheetPool();
			SetOrganizerSearchMask(pStylePool);
			SfxStyleSheetIteratorPtr pIter = pStylePool->CreateIterator( pStylePool->GetSearchFamily(), pStylePool->GetSearchMask() );
			sal_uInt16 nStyles = pIter->Count();
			SfxStyleSheetBase *pStyle = pIter->First();
			if ( !pStyle )
				return sal_True;

            // pepare adaptor for old style StartPage/EndPage printing
            boost::shared_ptr< Printer > pPrinter( new Printer( rPrt.GetJobSetup() ) );
            vcl::OldStylePrintAdaptor* pAdaptor = new vcl::OldStylePrintAdaptor( pPrinter );
            boost::shared_ptr< vcl::PrinterController > pController( pAdaptor );

            pAdaptor->StartPage();

            pPrinter->SetMapMode(MapMode(MAP_10TH_MM));
			Font aFont( DEFINE_CONST_UNICODE( "Arial" ), Size(0, 64));   // 18pt
			aFont.SetWeight(WEIGHT_BOLD);
			pPrinter->SetFont(aFont);
			const Size aPageSize(pPrinter->GetOutputSize());
			const sal_uInt16 nXIndent = 200;
			sal_uInt16 nYIndent = 200;
			Point aOutPos(nXIndent, nYIndent);
			String aHeader(SfxResId(STR_PRINT_STYLES_HEADER));
			if ( pObjectName )
				aHeader += *pObjectName;
			else
				aHeader += GetTitle();
            long nTextHeight( pPrinter->GetTextHeight() );
			pPrinter->DrawText(aOutPos, aHeader);
			aOutPos.Y() += nTextHeight;
			aOutPos.Y() += nTextHeight/2;
			aFont.SetSize(Size(0, 35)); // 10pt
			nStyles = 1;
			while(pStyle)
			{
				// print template name
				String aStr(pStyle->GetName());
				aFont.SetWeight(WEIGHT_BOLD);
				pPrinter->SetFont(aFont);
				nTextHeight = pPrinter->GetTextHeight();
				// check for new page
				if ( aOutPos.Y() + nTextHeight*2 >
                    aPageSize.Height() - (long) nYIndent )
				{
					pAdaptor->EndPage();
					pAdaptor->StartPage();
					aOutPos.Y() = nYIndent;
				}
				pPrinter->DrawText(aOutPos, aStr);
				aOutPos.Y() += nTextHeight;

				// print template description
				aFont.SetWeight(WEIGHT_NORMAL);
				pPrinter->SetFont(aFont);
				aStr = pStyle->GetDescription();
				const char cDelim = ' ';
				sal_uInt16 nStart = 0, nIdx = 0;

				nTextHeight = pPrinter->GetTextHeight();
				// break text into lines
				while(nIdx < aStr.Len())
				{
					sal_uInt16	nOld = nIdx;
                    long nTextWidth;
					nIdx = aStr.Search(cDelim, nStart);
					nTextWidth = pPrinter->GetTextWidth(aStr, nStart, nIdx-nStart);
					while(nIdx != STRING_NOTFOUND &&
						  aOutPos.X() + nTextWidth <
                          aPageSize.Width() - (long) nXIndent)
					{
						nOld = nIdx;
						nIdx = aStr.Search(cDelim, nIdx+1);
						nTextWidth = pPrinter->GetTextWidth(aStr, nStart, nIdx-nStart);
					}
					String aTmp(aStr, nStart, nIdx == STRING_NOTFOUND?
								STRING_LEN :
								nOld-nStart);
					if ( aTmp.Len() )
					{
						nStart = nOld+1;    // trailing space
					}
					else
					{
						sal_uInt16 nChar = 1;
						while(
							nStart + nChar < aStr.Len() &&
							aOutPos.X() + pPrinter->GetTextWidth(
								aStr, nStart, nChar) <
							aPageSize.Width() - nXIndent)
							++nChar;
						aTmp = String(aStr, nStart, nChar-1);
						nIdx = nStart + nChar;
						nStart = nIdx;
					}
					if ( aOutPos.Y() + nTextHeight*2 >
						aPageSize.Height() - nYIndent )
					{
						pAdaptor->EndPage();
						pAdaptor->StartPage();
						aOutPos.Y() = nYIndent;
					}
					pPrinter->DrawText(aOutPos, aTmp);
					aOutPos.Y() += pPrinter->GetTextHeight();
				}
				pStyle = pIter->Next();
			}
			pAdaptor->EndPage();

            Printer::PrintJob( pController, rPrt.GetJobSetup() );

			break;
		}
	  default:
		  return sal_False;
	}
	return sal_True;
}

//--------------------------------------------------------------------

void SfxObjectShell::LoadStyles
(
	SfxObjectShell &rSource         /*  die Dokument-Vorlage, aus der
											die Styles geladen werden sollen */
)

/*  [Beschreibung]

	Diese Methode wird vom SFx gerufen, wenn aus einer Dokument-Vorlage
	Styles nachgeladen werden sollen. Bestehende Styles soll dabei
	"uberschrieben werden. Das Dokument mu"s daher neu formatiert werden.
	Daher werden die Applikationen in der Regel diese Methode "uberladen
	und in ihrer Implementierung die Implementierung der Basisklasse
	rufen.
*/

{
	struct Styles_Impl
	{
		SfxStyleSheetBase *pSource;
		SfxStyleSheetBase *pDest;
//      Styles_Impl () : pSource(0), pDest(0) {}
	};

	SfxStyleSheetBasePool *pSourcePool = rSource.GetStyleSheetPool();
	DBG_ASSERT(pSourcePool, "Source-DocumentShell ohne StyleSheetPool");
	SfxStyleSheetBasePool *pMyPool = GetStyleSheetPool();
	DBG_ASSERT(pMyPool, "Dest-DocumentShell ohne StyleSheetPool");
	pSourcePool->SetSearchMask(SFX_STYLE_FAMILY_ALL, 0xffff);
	Styles_Impl *pFound = new Styles_Impl[pSourcePool->Count()];
	sal_uInt16 nFound = 0;

	SfxStyleSheetBase *pSource = pSourcePool->First();
	while ( pSource )
	{
		SfxStyleSheetBase *pDest =
			pMyPool->Find( pSource->GetName(), pSource->GetFamily() );
		if ( !pDest )
		{
			pDest = &pMyPool->Make( pSource->GetName(),
					pSource->GetFamily(), pSource->GetMask());
			// Setzen des Parents, der Folgevorlage
		}
		pFound[nFound].pSource = pSource;
		pFound[nFound].pDest = pDest;
		++nFound;
		pSource = pSourcePool->Next();
	}

	for ( sal_uInt16 i = 0; i < nFound; ++i )
	{
		pFound[i].pDest->GetItemSet().PutExtended(pFound[i].pSource->GetItemSet(), SFX_ITEM_DONTCARE, SFX_ITEM_DEFAULT);
//      pFound[i].pDest->SetHelpId(pFound[i].pSource->GetHelpId());
		if(pFound[i].pSource->HasParentSupport())
			pFound[i].pDest->SetParent(pFound[i].pSource->GetParent());
		if(pFound[i].pSource->HasFollowSupport())
			pFound[i].pDest->SetFollow(pFound[i].pSource->GetParent());
	}
	delete [] pFound;
}

//--------------------------------------------------------------------

void SfxObjectShell::UpdateFromTemplate_Impl(  )

/*  [Beschreibung]

	Diese interne Methode pr"uft, ob das Dokument aus einem Template
	erzeugt wurde, und ob dieses neuer ist als das Dokument. Ist dies
	der Fall, wird der Benutzer gefragt, ob die Vorlagen (StyleSheets)
	updated werden sollen. Wird dies positiv beantwortet, werden die
	StyleSheets updated.
*/

{
	// Storage-medium?
	SfxMedium *pFile = GetMedium();
	DBG_ASSERT( pFile, "cannot UpdateFromTemplate without medium" );
	if ( !pFile )
		return;

	if ( !::utl::LocalFileHelper::IsLocalFile( pFile->GetName() ) )
		// update only for documents loaded from the local file system
		return;

    // only for own storage formats
	uno::Reference< embed::XStorage > xDocStor = pFile->GetStorage();
    if ( !pFile->GetFilter() || !pFile->GetFilter()->IsOwnFormat() )
		return;

	SFX_ITEMSET_ARG( pFile->GetItemSet(), pUpdateDocItem, SfxUInt16Item, SID_UPDATEDOCMODE, sal_False);
	sal_Int16 bCanUpdateFromTemplate = pUpdateDocItem ? pUpdateDocItem->GetValue() : document::UpdateDocMode::NO_UPDATE;

    // created from template?
    uno::Reference<document::XDocumentProperties> xDocProps(getDocProperties());
    ::rtl::OUString aTemplName( xDocProps->getTemplateName() );
    ::rtl::OUString aTemplURL( xDocProps->getTemplateURL() );
    String aFoundName;

    if ( aTemplName.getLength() || (aTemplURL.getLength() && !IsReadOnly()) )
	{
        // try to locate template, first using filename
        // this must be done because writer global document uses this "great" idea to manage the templates of all parts
        // in the master document
        // but it is NOT an error if the template filename points not to a valid file
        SfxDocumentTemplates aTempl;
        aTempl.Construct();
        if ( aTemplURL.getLength() )
        {
            String aURL;
            if( ::utl::LocalFileHelper::ConvertSystemPathToURL( aTemplURL, GetMedium()->GetName(), aURL ) )
                aFoundName = aURL;
        }

        if( !aFoundName.Len() && aTemplName.getLength() )
            // if the template filename did not lead to success, try to get a file name for the logical template name
            aTempl.GetFull( String(), aTemplName, aFoundName );
	}

    if ( aFoundName.Len() )
	{
        // check existence of template storage
        aTemplURL = aFoundName;
		sal_Bool bLoad = sal_False;

        // should the document checked against changes in the template ?
        if ( IsQueryLoadTemplate() )
		{
            // load document info of template
            sal_Bool bOK = sal_False;
			util::DateTime aTemplDate;
            try
            {
                Reference < document::XStandaloneDocumentInfo > xDocInfo (
                    ::comphelper::getProcessServiceFactory()->createInstance(
                        ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
                            "com.sun.star.document.StandaloneDocumentInfo") ) ),
                    UNO_QUERY_THROW );
                Reference < beans::XFastPropertySet > xSet( xDocInfo,
                    UNO_QUERY_THROW );
                xDocInfo->loadFromURL( aTemplURL );
                Any aAny = xSet->getFastPropertyValue( WID_DATE_MODIFIED );
                ::com::sun::star::util::DateTime aTmp;
                if ( aAny >>= aTemplDate )
                {
                    // get modify date from document info
                    bOK = sal_True;
                }
            }
            catch ( Exception& )
            {
            }

            // if modify date was read successfully
            if ( bOK )
			{
                // compare modify data of template with the last check date of the document
                const util::DateTime aInfoDate( xDocProps->getTemplateDate() );
				if ( aTemplDate > aInfoDate )
				{
                    // ask user
                	if( bCanUpdateFromTemplate == document::UpdateDocMode::QUIET_UPDATE
                	|| bCanUpdateFromTemplate == document::UpdateDocMode::FULL_UPDATE )
						bLoad = sal_True;
					else if ( bCanUpdateFromTemplate == document::UpdateDocMode::ACCORDING_TO_CONFIG )
					{
                        String sMessage( SfxResId( STR_QRYTEMPL_MESSAGE ) );
                        sMessage.SearchAndReplace( String::CreateFromAscii("$(ARG1)"), aTemplName );
                        sfx2::QueryTemplateBox aBox( GetDialogParent(), sMessage );
						if ( RET_YES == aBox.Execute() )
							bLoad = sal_True;
					}

					if( !bLoad )
					{
                        // user refuses, so don't ask again for this document
						SetQueryLoadTemplate(sal_False);
						SetModified( sal_True );
					}
				}
			}

			if ( bLoad )
			{
                // styles should be updated, create document in organizer mode to read in the styles
                //TODO: testen!
                SfxObjectShellLock xTemplDoc = CreateObjectByFactoryName( GetFactory().GetFactoryName(), SFX_CREATE_MODE_ORGANIZER );
				xTemplDoc->DoInitNew(0);

                // TODO/MBA: do we need a BaseURL? Then LoadFrom must be extended!
                //xTemplDoc->SetBaseURL( aFoundName );

                // TODO/LATER: make sure that we don't use binary templates!
                SfxMedium aMedium( aFoundName, STREAM_STD_READ );
                if ( xTemplDoc->LoadFrom( aMedium ) )
				{
                    // transfer styles from xTemplDoc to this document
                    // TODO/MBA: make sure that no BaseURL is needed in *this* document
					LoadStyles(*xTemplDoc);

                    // remember date/time of check
                    xDocProps->setTemplateDate(aTemplDate);
                    // TODO/LATER: new functionality to store document info is required ( didn't work for SO7 XML format )
//REPLACE					pInfo->Save(xDocStor);
				}
			}
		}
	}
}

sal_Bool SfxObjectShell::IsHelpDocument() const
{
    const SfxFilter* pFilter = GetMedium()->GetFilter();
    return ( pFilter && pFilter->GetFilterName().CompareToAscii("writer_web_HTML_help") == COMPARE_EQUAL );
}

void SfxObjectShell::ResetFromTemplate( const String& rTemplateName, const String& rFileName )
{
    // only care about reseting this data for openoffice formats otherwise
    if ( IsOwnStorageFormat_Impl( *GetMedium())  )
    {
        uno::Reference<document::XDocumentProperties> xDocProps(getDocProperties());
        xDocProps->setTemplateURL( ::rtl::OUString() );
        xDocProps->setTemplateName( ::rtl::OUString() );
        xDocProps->setTemplateDate( util::DateTime() );
        xDocProps->resetUserData( ::rtl::OUString() );

    	// TODO/REFACTOR:
    	// Title?

        if( ::utl::LocalFileHelper::IsLocalFile( rFileName ) )
    	{
            String aFoundName;
            if( SFX_APP()->Get_Impl()->GetDocumentTemplates()->GetFull( String(), rTemplateName, aFoundName ) )
            {
                INetURLObject aObj( rFileName );
                xDocProps->setTemplateURL( aObj.GetMainURL(INetURLObject::DECODE_TO_IURI) );
                xDocProps->setTemplateName( rTemplateName );

                ::DateTime now;
                xDocProps->setTemplateDate( util::DateTime(
                    now.Get100Sec(), now.GetSec(), now.GetMin(),
                    now.GetHour(), now.GetDay(), now.GetMonth(),
                    now.GetYear() ) );

    			SetQueryLoadTemplate( sal_True );
            }
        }
    }
}

sal_Bool SfxObjectShell::IsQueryLoadTemplate() const
{
	return pImp->bQueryLoadTemplate;
}

sal_Bool SfxObjectShell::IsUseUserData() const
{
	return pImp->bUseUserData;
}

void SfxObjectShell::SetQueryLoadTemplate( sal_Bool bNew )
{
	if ( pImp->bQueryLoadTemplate != bNew )
		SetModified( sal_True );
	pImp->bQueryLoadTemplate = bNew;
}

void SfxObjectShell::SetUseUserData( sal_Bool bNew )
{
	if ( pImp->bUseUserData != bNew )
		SetModified( sal_True );
	pImp->bUseUserData = bNew;
}

sal_Bool SfxObjectShell::IsLoadReadonly() const
{
	return pImp->bLoadReadonly;
}

sal_Bool SfxObjectShell::IsSaveVersionOnClose() const
{
	return pImp->bSaveVersionOnClose;
}

void SfxObjectShell::SetLoadReadonly( sal_Bool bNew )
{
	if ( pImp->bLoadReadonly != bNew )
		SetModified( sal_True );
	pImp->bLoadReadonly = bNew;
}

void SfxObjectShell::SetSaveVersionOnClose( sal_Bool bNew )
{
	if ( pImp->bSaveVersionOnClose != bNew )
		SetModified( sal_True );
	pImp->bSaveVersionOnClose = bNew;
}

sal_uInt32 SfxObjectShell::GetModifyPasswordHash() const
{
    return pImp->m_nModifyPasswordHash;
}

sal_Bool SfxObjectShell::SetModifyPasswordHash( sal_uInt32 nHash )
{
    if ( ( !IsReadOnly() && !IsReadOnlyUI() )
      || !(pImp->nFlagsInProgress & SFX_LOADED_MAINDOCUMENT ) )
    {
        // the hash can be changed only in editable documents,
        // or during loading of document
        pImp->m_nModifyPasswordHash = nHash;
        return sal_True;
    }

    return sal_False;
}

uno::Sequence< beans::PropertyValue > SfxObjectShell::GetModifyPasswordInfo() const
{
    return pImp->m_aModifyPasswordInfo;
}

sal_Bool SfxObjectShell::SetModifyPasswordInfo( const uno::Sequence< beans::PropertyValue >& aInfo )
{
    if ( ( !IsReadOnly() && !IsReadOnlyUI() )
      || !(pImp->nFlagsInProgress & SFX_LOADED_MAINDOCUMENT ) )
    {
        // the hash can be changed only in editable documents,
        // or during loading of document
        pImp->m_aModifyPasswordInfo = aInfo;
        return sal_True;
    }

    return sal_False;
}

void SfxObjectShell::SetModifyPasswordEntered( sal_Bool bEntered )
{
    pImp->m_bModifyPasswordEntered = bEntered;
}

sal_Bool SfxObjectShell::IsModifyPasswordEntered()
{
    return pImp->m_bModifyPasswordEntered;
}
