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>
23 #include <osl/diagnose.h>
26 #include <poolfmt.hxx>
27 #include <shellio.hxx>
29 #include <fmtanchr.hxx>
32 #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 m_xTableStream
= pStg
->OpenSotStream(
48 aWwFib
.m_fWhichTableStm
? OUString(SL::a1Table
) : OUString(SL::a0Table
),
49 StreamMode::STD_READ
);
51 if (m_xTableStream
.is() && ERRCODE_NONE
== m_xTableStream
->GetError())
53 m_xTableStream
->SetEndian(SvStreamEndian::LITTLE
);
54 m_xGlossary
= std::make_shared
<WW8GlossaryFib
>(*refStrm
, nVersion
, aWwFib
);
59 bool WW8Glossary::HasBareGraphicEnd(SwDoc
*pDoc
, SwNode
const &rIdx
)
62 for( sal_uInt16 nCnt
= pDoc
->GetSpzFrameFormats()->size(); nCnt
; )
64 const SwFrameFormat
* pFrameFormat
= (*pDoc
->GetSpzFrameFormats())[ --nCnt
];
65 if ( RES_FLYFRMFMT
!= pFrameFormat
->Which() &&
66 RES_DRAWFRMFMT
!= pFrameFormat
->Which() )
68 const SwFormatAnchor
& rAnchor
= pFrameFormat
->GetAnchor();
69 SwNode
const*const pAnchorNode
= rAnchor
.GetAnchorNode();
71 ((RndStdIds::FLY_AT_PARA
== rAnchor
.GetAnchorId()) ||
72 (RndStdIds::FLY_AT_CHAR
== rAnchor
.GetAnchorId())) &&
73 rIdx
== *pAnchorNode
)
82 bool WW8Glossary::MakeEntries(SwDoc
*pD
, SwTextBlocks
&rBlocks
,
83 bool bSaveRelFile
, const std::vector
<OUString
>& rStrings
,
84 const std::vector
<ww::bytes
>& rExtra
)
86 // this code will be called after reading all text into the
88 const OUString
aOldURL( rBlocks
.GetBaseURL() );
93 URIHelper::SmartRel2Abs(
94 INetURLObject(), rBlocks
.GetFileName(),
95 URIHelper::GetMaybeFileHdl()));
98 rBlocks
.SetBaseURL( OUString() );
100 SwNodeIndex
aDocEnd( pD
->GetNodes().GetEndOfContent() );
101 SwNodeIndex
aStart( *aDocEnd
.GetNode().StartOfSectionNode(), 1 );
103 // search the first NormalStartNode
104 while( !( aStart
.GetNode().IsStartNode() && SwNormalStartNode
==
105 aStart
.GetNode().GetStartNode()->GetStartNodeType()) &&
109 if( aStart
< aDocEnd
)
111 SwTextFormatColl
* pColl
= pD
->getIDocumentStylePoolAccess().GetTextCollFromPool
112 (RES_POOLCOLL_STANDARD
, false);
113 sal_uInt16 nGlosEntry
= 0;
114 SwContentNode
* pCNd
= nullptr;
116 SwPaM
aPam( aStart
);
118 SwPosition
& rPos
= *aPam
.GetPoint();
119 rPos
.Adjust(SwNodeOffset(1));
120 pCNd
= rPos
.GetNode().GetTextNode();
121 if( nullptr == pCNd
)
123 pCNd
= pD
->GetNodes().MakeTextNode( rPos
.GetNode(), pColl
);
129 SwPosition
& rPos
= *aPam
.GetPoint();
130 rPos
.Assign(aStart
.GetNode().EndOfSectionIndex() - 1);
131 if(( nullptr == ( pCNd
= rPos
.GetNode().GetContentNode() ) )
132 || HasBareGraphicEnd(pD
,rPos
.GetNode()))
134 rPos
.Adjust(SwNodeOffset(1));
135 pCNd
= pD
->GetNodes().MakeTextNode( rPos
.GetNode(), pColl
);
139 aPam
.GetPoint()->SetContent( 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
, 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 (m_xGlossary
&& m_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(m_xGlossary
->m_chseTables
, m_xGlossary
->m_lid
);
202 WW8ReadSTTBF(true, *m_xTableStream
, m_xGlossary
->m_fcSttbfglsy
,
203 m_xGlossary
->m_lcbSttbfglsy
, 0, eStructCharSet
, aStrings
, &aData
);
207 m_nStrings
= static_cast< sal_uInt16
>(aStrings
.size());
208 if ( 0 != m_nStrings
)
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 std::unique_ptr
<SwWW8ImplReader
> xRdr(new SwWW8ImplReader(
224 m_xGlossary
->m_nVersion
, m_xStg
.get(), m_rStrm
.get(), *pD
, rBlocks
.GetBaseURL(),
225 true, false, *aPamo
.GetPoint()));
227 bRet
= MakeEntries(pD
, rBlocks
, bSaveRelFile
, aStrings
, aData
);
230 rBlocks
.EndPutMuchBlockEntries();
236 sal_uInt32
WW8GlossaryFib::FindGlossaryFibOffset(const WW8Fib
&rFib
)
238 sal_uInt32 nGlossaryFibOffset
= 0;
239 if ( rFib
.m_fDot
) // it's a template
242 nGlossaryFibOffset
= ( rFib
.m_pnNext
* 512 );
244 return nGlossaryFibOffset
;
247 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */