1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <tools/urlobj.hxx>
22 #include <svl/urihelper.hxx>
25 #include <poolfmt.hxx>
26 #include <shellio.hxx>
28 #include <fmtanchr.hxx>
31 #include <IDocumentStylePoolAccess.hxx>
33 #include <frameformats.hxx>
34 #include "ww8glsy.hxx"
37 WW8Glossary::WW8Glossary(tools::SvRef
<SotStorageStream
> &refStrm
, sal_uInt8 nVersion
, SotStorage
*pStg
)
42 refStrm
->SetEndian(SvStreamEndian::LITTLE
);
43 WW8Fib
aWwFib(*refStrm
, nVersion
);
45 if (aWwFib
.m_nFibBack
>= 0x6A) //Word97
47 xTableStream
= pStg
->OpenSotStream(
48 aWwFib
.m_fWhichTableStm
? SL::a1Table
: SL::a0Table
, StreamMode::STD_READ
);
50 if (xTableStream
.is() && ERRCODE_NONE
== xTableStream
->GetError())
52 xTableStream
->SetEndian(SvStreamEndian::LITTLE
);
53 xGlossary
= std::make_shared
<WW8GlossaryFib
>(*refStrm
, nVersion
, aWwFib
);
58 bool WW8Glossary::HasBareGraphicEnd(SwDoc
*pDoc
,SwNodeIndex
const &rIdx
)
61 for( sal_uInt16 nCnt
= pDoc
->GetSpzFrameFormats()->size(); nCnt
; )
63 const SwFrameFormat
* pFrameFormat
= (*pDoc
->GetSpzFrameFormats())[ --nCnt
];
64 if ( RES_FLYFRMFMT
!= pFrameFormat
->Which() &&
65 RES_DRAWFRMFMT
!= pFrameFormat
->Which() )
67 const SwFormatAnchor
& rAnchor
= pFrameFormat
->GetAnchor();
68 SwPosition
const*const pAPos
= rAnchor
.GetContentAnchor();
70 ((RndStdIds::FLY_AT_PARA
== rAnchor
.GetAnchorId()) ||
71 (RndStdIds::FLY_AT_CHAR
== rAnchor
.GetAnchorId())) &&
72 rIdx
== pAPos
->nNode
.GetIndex() )
81 bool WW8Glossary::MakeEntries(SwDoc
*pD
, SwTextBlocks
&rBlocks
,
82 bool bSaveRelFile
, const std::vector
<OUString
>& rStrings
,
83 const std::vector
<ww::bytes
>& rExtra
)
85 // this code will be called after reading all text into the
87 const OUString
aOldURL( rBlocks
.GetBaseURL() );
92 URIHelper::SmartRel2Abs(
93 INetURLObject(), rBlocks
.GetFileName(),
94 URIHelper::GetMaybeFileHdl()));
97 rBlocks
.SetBaseURL( OUString() );
99 SwNodeIndex
aDocEnd( pD
->GetNodes().GetEndOfContent() );
100 SwNodeIndex
aStart( *aDocEnd
.GetNode().StartOfSectionNode(), 1 );
102 // search the first NormalStartNode
103 while( !( aStart
.GetNode().IsStartNode() && SwNormalStartNode
==
104 aStart
.GetNode().GetStartNode()->GetStartNodeType()) &&
108 if( aStart
< aDocEnd
)
110 SwTextFormatColl
* pColl
= pD
->getIDocumentStylePoolAccess().GetTextCollFromPool
111 (RES_POOLCOLL_STANDARD
, false);
112 sal_uInt16 nGlosEntry
= 0;
113 SwContentNode
* pCNd
= nullptr;
115 SwPaM
aPam( aStart
);
117 SwNodeIndex
& rIdx
= aPam
.GetPoint()->nNode
;
119 pCNd
= rIdx
.GetNode().GetTextNode();
120 if( nullptr == pCNd
)
122 pCNd
= pD
->GetNodes().MakeTextNode( rIdx
, pColl
);
126 aPam
.GetPoint()->nContent
.Assign( pCNd
, 0 );
129 SwNodeIndex
& rIdx
= aPam
.GetPoint()->nNode
;
130 rIdx
= aStart
.GetNode().EndOfSectionIndex() - 1;
131 if(( nullptr == ( pCNd
= rIdx
.GetNode().GetContentNode() ) )
132 || HasBareGraphicEnd(pD
,rIdx
))
135 pCNd
= pD
->GetNodes().MakeTextNode( rIdx
, pColl
);
139 aPam
.GetPoint()->nContent
.Assign( pCNd
, pCNd
->Len() );
141 // now we have the right selection for one entry. Copy this to
142 // the defined TextBlock, but only if it is not an autocorrection
143 // entry (== -1) otherwise the group indicates the group in the
144 // sttbfglsystyle list that this entry belongs to. Unused at the
146 const ww::bytes
&rData
= rExtra
[nGlosEntry
];
147 sal_uInt16 n
= SVBT16ToUInt16( &(rData
[2]) );
151 const OUString
&rLNm
= rStrings
[nGlosEntry
];
153 OUString sShortcut
= rLNm
;
155 // Need to check make sure the shortcut is not already being used
156 sal_Int32 nStart
= 0;
157 sal_uInt16 nCurPos
= rBlocks
.GetIndex( sShortcut
);
158 while( sal_uInt16(-1) != nCurPos
)
160 sShortcut
= rLNm
+ OUString::number(++nStart
); // add a Number to it
161 nCurPos
= rBlocks
.GetIndex( sShortcut
);
164 if( rBlocks
.BeginPutDoc( sShortcut
, sShortcut
)) // Make the shortcut and the name the same
167 SwDoc
* pGlDoc
= rBlocks
.GetDoc();
168 SwNodeIndex
aIdx( pGlDoc
->GetNodes().GetEndOfContent(),
170 pCNd
= aIdx
.GetNode().GetContentNode();
171 SwPosition
aPos(aIdx
, SwIndex(pCNd
, pCNd
? pCNd
->Len() : 0));
172 pD
->getIDocumentContentOperations().CopyRange(aPam
, aPos
, SwCopyFlags::CheckPosInFly
);
176 aStart
= aStart
.GetNode().EndOfSectionIndex() + 1;
178 } while( aStart
.GetNode().IsStartNode() &&
179 SwNormalStartNode
== aStart
.GetNode().
180 GetStartNode()->GetStartNodeType());
184 // this code will be called after reading all text into the empty sections
186 rBlocks
.SetBaseURL( aOldURL
);
190 bool WW8Glossary::Load( SwTextBlocks
&rBlocks
, bool bSaveRelFile
)
193 if (xGlossary
&& xGlossary
->IsGlossaryFib() && rBlocks
.StartPutMuchBlockEntries())
195 //read the names of the autotext entries
196 std::vector
<OUString
> aStrings
;
197 std::vector
<ww::bytes
> aData
;
199 rtl_TextEncoding eStructCharSet
=
200 WW8Fib::GetFIBCharset(xGlossary
->m_chseTables
, xGlossary
->m_lid
);
202 WW8ReadSTTBF(true, *xTableStream
, xGlossary
->m_fcSttbfglsy
,
203 xGlossary
->m_lcbSttbfglsy
, 0, eStructCharSet
, aStrings
, &aData
);
207 nStrings
= static_cast< sal_uInt16
>(aStrings
.size());
210 SfxObjectShellLock
xDocSh(new SwDocShell(SfxObjectCreateMode::INTERNAL
));
211 if (xDocSh
->DoInitNew())
213 SwDoc
*pD
= static_cast<SwDocShell
*>((&xDocSh
))->GetDoc();
216 *pD
->GetNodes().GetEndOfContent().StartOfSectionNode(), 1);
217 if( !aIdx
.GetNode().IsTextNode() )
219 OSL_ENSURE( false, "Where is the TextNode?" );
220 pD
->GetNodes().GoNext( &aIdx
);
223 aPamo
.GetPoint()->nContent
.Assign(aIdx
.GetNode().GetContentNode(),
225 std::unique_ptr
<SwWW8ImplReader
> xRdr(new SwWW8ImplReader(
226 xGlossary
->m_nVersion
, xStg
.get(), rStrm
.get(), *pD
, rBlocks
.GetBaseURL(),
227 true, false, *aPamo
.GetPoint()));
229 bRet
= MakeEntries(pD
, rBlocks
, bSaveRelFile
, aStrings
, aData
);
232 rBlocks
.EndPutMuchBlockEntries();
238 sal_uInt32
WW8GlossaryFib::FindGlossaryFibOffset(const WW8Fib
&rFib
)
240 sal_uInt32 nGlossaryFibOffset
= 0;
241 if ( rFib
.m_fDot
) // it's a template
244 nGlossaryFibOffset
= ( rFib
.m_pnNext
* 512 );
246 return nGlossaryFibOffset
;
249 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */