merge the formfield patch from ooo-build
[ooovba.git] / sw / source / core / crsr / bookmrk.cxx
blobeaee9a5a764d5823192bcc77ecfbc18189492307
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: bookmrk.cxx,v $
10 * $Revision: 1.11 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
35 #include <bookmrk.hxx>
36 #include <IDocumentMarkAccess.hxx>
37 #include <doc.hxx>
38 #include <errhdl.hxx>
39 #include <ndtxt.hxx>
40 #include <pam.hxx>
41 #include <swserv.hxx>
42 #include <svx/linkmgr.hxx>
43 #include <swtypes.hxx>
44 #include <undobj.hxx>
45 #include <unoobj.hxx>
46 #include <rtl/random.h>
49 SV_IMPL_REF( SwServerObject )
51 using namespace ::sw::mark;
53 namespace
55 static void lcl_FixPosition(SwPosition& rPos)
57 // make sure the position has 1) the proper node, and 2) a proper index
58 SwTxtNode* pTxtNode = rPos.nNode.GetNode().GetTxtNode();
59 if(pTxtNode == NULL && rPos.nContent.GetIndex() > 0)
61 OSL_TRACE(
62 "bookmrk.cxx::lcl_FixPosition"
63 " - illegal position: %d without proper TxtNode", rPos.nContent.GetIndex());
64 rPos.nContent.Assign(NULL, 0);
66 else if(pTxtNode != NULL && rPos.nContent.GetIndex() > pTxtNode->Len())
68 OSL_TRACE(
69 "bookmrk.cxx::lcl_FixPosition"
70 " - illegal position: %d is beyond %d", rPos.nContent.GetIndex(), pTxtNode->Len());
71 rPos.nContent.Assign(pTxtNode, pTxtNode->Len());
75 static void lcl_AssureFieldMarksSet(Fieldmark* const pField,
76 SwDoc* const io_pDoc,
77 const sal_Unicode aStartMark,
78 const sal_Unicode aEndMark)
80 SwPosition& rStart = pField->GetMarkStart();
81 SwPosition& rEnd = pField->GetMarkEnd();
82 SwTxtNode const * const pStartTxtNode = io_pDoc->GetNodes()[rStart.nNode]->GetTxtNode();
83 SwTxtNode const * const pEndTxtNode = io_pDoc->GetNodes()[rEnd.nNode]->GetTxtNode();
84 const sal_Unicode ch_start=pStartTxtNode->GetTxt().GetChar(rStart.nContent.GetIndex());
85 const sal_Unicode ch_end=pEndTxtNode->GetTxt().GetChar(rEnd.nContent.GetIndex()-1);
86 SwPaM aStartPaM(rStart);
87 SwPaM aEndPaM(rEnd);
88 io_pDoc->StartUndo(UNDO_UI_REPLACE, NULL);
89 if(ch_start != aStartMark)
91 io_pDoc->InsertString(aStartPaM, aStartMark);
93 if ( aEndMark && ( ch_end != aEndMark ) && ( rStart != rEnd ) )
95 io_pDoc->InsertString(aEndPaM, aEndMark);
97 io_pDoc->EndUndo(UNDO_UI_REPLACE, NULL);
101 namespace sw { namespace mark
103 MarkBase::MarkBase(const SwPaM& aPaM,
104 const ::rtl::OUString& rName)
105 : SwModify(0)
106 , m_pPos1(new SwPosition(*(aPaM.GetPoint())))
107 , m_aName(rName)
109 lcl_FixPosition(*m_pPos1);
110 if(aPaM.HasMark())
112 MarkBase::SetOtherMarkPos(*(aPaM.GetMark()));
113 lcl_FixPosition(*m_pPos2);
117 bool MarkBase::IsCoveringPosition(const SwPosition& rPos) const
119 return GetMarkStart() <= rPos && rPos <= GetMarkEnd();
122 void MarkBase::SetMarkPos(const SwPosition& rNewPos)
124 ::boost::scoped_ptr<SwPosition>(new SwPosition(rNewPos)).swap(m_pPos1);
125 //lcl_FixPosition(*m_pPos1);
128 void MarkBase::SetOtherMarkPos(const SwPosition& rNewPos)
130 ::boost::scoped_ptr<SwPosition>(new SwPosition(rNewPos)).swap(m_pPos2);
131 //lcl_FixPosition(*m_pPos2);
134 rtl::OUString MarkBase::toString( ) const
136 rtl::OUStringBuffer buf;
137 buf.appendAscii( "Mark: ( Name, [ Node1, Index1 ] ): ( " );
138 buf.append( m_aName ).appendAscii( ", [ " );
139 buf.append( sal_Int32( GetMarkPos().nNode.GetIndex( ) ) ).appendAscii( ", " );
140 buf.append( sal_Int32( GetMarkPos().nContent.GetIndex( ) ) ).appendAscii( " ] )" );
142 return buf.makeStringAndClear( );
145 MarkBase::~MarkBase()
148 ::rtl::OUString MarkBase::GenerateNewName(const ::rtl::OUString& rPrefix)
150 static rtlRandomPool aPool = rtl_random_createPool();
151 static ::rtl::OUString sUniquePostfix;
152 static sal_Int32 nCount = SAL_MAX_INT32;
153 ::rtl::OUStringBuffer aResult(rPrefix);
154 if(nCount == SAL_MAX_INT32)
156 sal_Int32 nRandom;
157 ::rtl::OUStringBuffer sUniquePostfixBuffer;
158 rtl_random_getBytes(aPool, &nRandom, sizeof(nRandom));
159 sUniquePostfix = ::rtl::OUStringBuffer(13).appendAscii("_").append(static_cast<sal_Int32>(abs(nRandom))).makeStringAndClear();
160 nCount = 0;
162 // putting the counter in front of the random parts will speed up string comparisons
163 return aResult.append(nCount++).append(sUniquePostfix).makeStringAndClear();
167 NavigatorReminder::NavigatorReminder(const SwPaM& rPaM)
168 : MarkBase(rPaM, our_sNamePrefix)
171 const ::rtl::OUString NavigatorReminder::our_sNamePrefix = ::rtl::OUString::createFromAscii("__NavigatorReminder__");
173 UnoMark::UnoMark(const SwPaM& aPaM)
174 : MarkBase(aPaM, MarkBase::GenerateNewName(our_sNamePrefix))
177 const ::rtl::OUString UnoMark::our_sNamePrefix = ::rtl::OUString::createFromAscii("__UnoMark__");
179 DdeBookmark::DdeBookmark(const SwPaM& aPaM)
180 : MarkBase(aPaM, MarkBase::GenerateNewName(our_sNamePrefix))
181 , m_aRefObj(NULL)
184 void DdeBookmark::SetRefObject(SwServerObject* pObj)
186 m_aRefObj = pObj;
189 const ::rtl::OUString DdeBookmark::our_sNamePrefix = ::rtl::OUString::createFromAscii("__DdeLink__");
191 void DdeBookmark::DeregisterFromDoc(SwDoc* const pDoc)
193 if(m_aRefObj.Is())
194 pDoc->GetLinkManager().RemoveServer(m_aRefObj);
197 DdeBookmark::~DdeBookmark()
199 if( m_aRefObj.Is() )
201 if(m_aRefObj->HasDataLinks())
203 ::sfx2::SvLinkSource* p = &m_aRefObj;
204 p->SendDataChanged();
206 m_aRefObj->SetNoServer();
210 Bookmark::Bookmark(const SwPaM& aPaM,
211 const KeyCode& rCode,
212 const ::rtl::OUString& rName,
213 const ::rtl::OUString& rShortName)
214 : DdeBookmark(aPaM)
215 , ::sfx2::Metadatable()
216 , m_aCode(rCode)
217 , m_sShortName(rShortName)
219 m_aName = rName;
222 void Bookmark::InitDoc(SwDoc* const io_pDoc)
224 if(io_pDoc->DoesUndo())
226 io_pDoc->ClearRedo();
227 io_pDoc->AppendUndo(new SwUndoInsBookmark(*this));
229 io_pDoc->SetModified();
232 // ::sfx2::Metadatable
233 ::sfx2::IXmlIdRegistry& Bookmark::GetRegistry()
235 SwDoc *const pDoc( GetMarkPos().GetDoc() );
236 OSL_ENSURE(pDoc, "Bookmark::MakeUnoObject: no doc?");
237 return pDoc->GetXmlIdRegistry();
240 bool Bookmark::IsInClipboard() const
242 SwDoc *const pDoc( GetMarkPos().GetDoc() );
243 OSL_ENSURE(pDoc, "Bookmark::IsInClipboard: no doc?");
244 return pDoc->IsClipBoard();
247 bool Bookmark::IsInUndo() const
249 return false;
252 bool Bookmark::IsInContent() const
254 SwDoc *const pDoc( GetMarkPos().GetDoc() );
255 OSL_ENSURE(pDoc, "Bookmark::IsInContent: no doc?");
256 return !pDoc->IsInHeaderFooter( SwNodeIndex(GetMarkPos().nNode) );
259 ::com::sun::star::uno::Reference< ::com::sun::star::rdf::XMetadatable >
260 Bookmark::MakeUnoObject()
262 // re-use existing SwXBookmark
263 SwClientIter iter( *this );
264 SwClient * pClient( iter.First( TYPE( SwXBookmark ) ) );
265 while (pClient) {
266 SwXBookmark *const pBookmark( dynamic_cast<SwXBookmark*>(pClient) );
267 if (pBookmark && pBookmark->GetCoreObject() == this) {
268 return pBookmark;
270 pClient = iter.Next();
273 // create new SwXBookmark
274 SwDoc *const pDoc( GetMarkPos().GetDoc() );
275 OSL_ENSURE(pDoc, "Bookmark::MakeUnoObject: no doc?");
276 return new SwXBookmark(this, pDoc);
280 Fieldmark::Fieldmark(const SwPaM& rPaM)
281 : MarkBase(rPaM, MarkBase::GenerateNewName(our_sNamePrefix))
283 if(!IsExpanded())
284 SetOtherMarkPos(GetMarkPos());
287 rtl::OUString Fieldmark::toString( ) const
289 rtl::OUStringBuffer buf;
290 buf.appendAscii( "Fieldmark: ( Name, Type, [ Nd1, Id1 ], [ Nd2, Id2 ] ): ( " );
291 buf.append( m_aName ).appendAscii( ", " );
292 buf.append( m_aFieldname ).appendAscii( ", [ " );
293 buf.append( sal_Int32( GetMarkPos().nNode.GetIndex( ) ) ).appendAscii( ", " );
294 buf.append( sal_Int32( GetMarkPos( ).nContent.GetIndex( ) ) ).appendAscii( " ], [" );
295 buf.append( sal_Int32( GetOtherMarkPos().nNode.GetIndex( ) ) ).appendAscii( ", " );
296 buf.append( sal_Int32( GetOtherMarkPos( ).nContent.GetIndex( ) ) ).appendAscii( " ] ) " );
298 return buf.makeStringAndClear( );
301 void Fieldmark::addParam( ::rtl::OUString paramName,
302 ::rtl::OUString paramValue,
303 bool replaceExisting )
305 if ( replaceExisting )
307 bool replaced = false;
308 const int len = m_params.size( );
309 for ( int i = 0; i < len; i++ )
311 if ( m_params[i].first.compareTo( paramName ) == 0 )
313 m_params[i] = ParamPair_t( paramName, paramValue );
314 replaced = true;
317 if ( !replaced )
319 m_params.push_back( ParamPair_t( paramName, paramValue ) );
322 else
324 m_params.push_back( ParamPair_t( paramName, paramValue ) );
328 void Fieldmark::addParam( const char *paramName, int value )
330 rtl::OUString sName = rtl::OUString::createFromAscii( paramName );
331 rtl::OUString sValue =::rtl::OUString::valueOf( ( sal_Int32 ) value );
332 addParam( sName, sValue );
335 void Fieldmark::addParams( std::vector < ParamPair_t > &params )
337 for ( std::vector < ParamPair_t >::iterator i = params.begin( );
338 i != params.end( ); i++ )
340 m_params.push_back( *i );
344 int Fieldmark::getNumOfParams( ) const
346 return m_params.size( );
349 Fieldmark::ParamPair_t Fieldmark::getParam( int pos ) const
351 return m_params[pos];
354 Fieldmark::ParamPair_t Fieldmark::getParam( const char *name,
355 const char *defaultValue ) const
357 for ( std::vector < ParamPair_t >::iterator i = const_cast< Fieldmark* >( this )->m_params.begin( );
358 i != m_params.end( ); i++ )
360 if ( i->first.compareToAscii( name ) == 0 )
362 return *i;
365 return ParamPair_t( rtl::OUString( ),
366 ( defaultValue ?
367 rtl::OUString::createFromAscii( defaultValue ) :
368 rtl::OUString( ) ) );
371 void Fieldmark::invalidate( )
373 SwPaM aPaM( this->GetMarkPos(), this->GetOtherMarkPos() );
374 aPaM.Invalidate();
377 const ::rtl::OUString Fieldmark::our_sNamePrefix = ::rtl::OUString::createFromAscii("__Fieldmark__");
379 TextFieldmark::TextFieldmark(const SwPaM& rPaM)
380 : Fieldmark(rPaM)
383 void TextFieldmark::InitDoc(SwDoc* const io_pDoc)
385 lcl_AssureFieldMarksSet(this, io_pDoc, CH_TXT_ATR_FIELDSTART, CH_TXT_ATR_FIELDEND);
388 CheckboxFieldmark::CheckboxFieldmark(const SwPaM& rPaM)
389 : Fieldmark(rPaM)
392 void CheckboxFieldmark::InitDoc(SwDoc* const io_pDoc)
394 lcl_AssureFieldMarksSet(this, io_pDoc, CH_TXT_ATR_FORMELEMENT, CH_TXT_ATR_FIELDEND);
396 // For some reason the end mark is moved from 1 by the Insert: we don't
397 // want this for checkboxes
398 this->GetMarkEnd( ).nContent--;
401 void CheckboxFieldmark::SetChecked(bool checked)
402 { m_isChecked = checked; }
404 bool CheckboxFieldmark::IsChecked() const
405 { return m_isChecked; }