1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: bookmrk.cxx,v $
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>
42 #include <svx/linkmgr.hxx>
43 #include <swtypes.hxx>
46 #include <rtl/random.h>
49 SV_IMPL_REF( SwServerObject
)
51 using namespace ::sw::mark
;
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)
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())
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
,
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
);
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
)
106 , m_pPos1(new SwPosition(*(aPaM
.GetPoint())))
109 lcl_FixPosition(*m_pPos1
);
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
)
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();
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
))
184 void DdeBookmark::SetRefObject(SwServerObject
* pObj
)
189 const ::rtl::OUString
DdeBookmark::our_sNamePrefix
= ::rtl::OUString::createFromAscii("__DdeLink__");
191 void DdeBookmark::DeregisterFromDoc(SwDoc
* const pDoc
)
194 pDoc
->GetLinkManager().RemoveServer(m_aRefObj
);
197 DdeBookmark::~DdeBookmark()
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
)
215 , ::sfx2::Metadatable()
217 , m_sShortName(rShortName
)
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
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
) ) );
266 SwXBookmark
*const pBookmark( dynamic_cast<SwXBookmark
*>(pClient
) );
267 if (pBookmark
&& pBookmark
->GetCoreObject() == this) {
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
))
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
);
319 m_params
.push_back( ParamPair_t( paramName
, paramValue
) );
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
> ¶ms
)
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 )
365 return ParamPair_t( rtl::OUString( ),
367 rtl::OUString::createFromAscii( defaultValue
) :
368 rtl::OUString( ) ) );
371 void Fieldmark::invalidate( )
373 SwPaM
aPaM( this->GetMarkPos(), this->GetOtherMarkPos() );
377 const ::rtl::OUString
Fieldmark::our_sNamePrefix
= ::rtl::OUString::createFromAscii("__Fieldmark__");
379 TextFieldmark::TextFieldmark(const SwPaM
& 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
)
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
; }