1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sw.hxx"
26
27 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil -*- */
28 #include <tools/urlobj.hxx>
29 #include <svl/urihelper.hxx>
30 #include <rtl/tencinfo.h>
31 #include <swerror.h>
32 #include <ndtxt.hxx>
33 #include <pam.hxx>
34 #include <shellio.hxx>
35 #include <docsh.hxx>
36 #include <fmtanchr.hxx>
37 #include <frmfmt.hxx>
38 #include <doc.hxx>
39 #include <docary.hxx>
40 #include "ww8glsy.hxx"
41 #include "ww8par.hxx"
42
43
WW8Glossary(SvStorageStreamRef & refStrm,sal_uInt8 nVersion,SvStorage * pStg)44 WW8Glossary::WW8Glossary(SvStorageStreamRef &refStrm, sal_uInt8 nVersion,
45 SvStorage *pStg)
46 : pGlossary(0), rStrm(refStrm), xStg(pStg), nStrings(0)
47 {
48 refStrm->SetNumberFormatInt(NUMBERFORMAT_INT_LITTLEENDIAN);
49 WW8Fib aWwFib(*refStrm, nVersion);
50
51 if (aWwFib.nFibBack >= 0x6A) //Word97
52 {
53 xTableStream = pStg->OpenSotStream(String::CreateFromAscii(
54 aWwFib.fWhichTblStm ? SL::a1Table : SL::a0Table), STREAM_STD_READ);
55
56 if (xTableStream.Is() && SVSTREAM_OK == xTableStream->GetError())
57 {
58 xTableStream->SetNumberFormatInt(NUMBERFORMAT_INT_LITTLEENDIAN);
59 pGlossary =
60 new WW8GlossaryFib(*refStrm, nVersion, *xTableStream, aWwFib);
61 }
62 }
63 }
64
HasBareGraphicEnd(SwDoc * pDoc,SwNodeIndex & rIdx)65 bool WW8Glossary::HasBareGraphicEnd(SwDoc *pDoc,SwNodeIndex &rIdx)
66 {
67 bool bRet=false;
68 for( sal_uInt16 nCnt = pDoc->GetSpzFrmFmts()->Count(); nCnt; )
69 {
70 SwFrmFmt* pFrmFmt = (*pDoc->GetSpzFrmFmts())[ --nCnt ];
71 if ( RES_FLYFRMFMT != pFrmFmt->Which() &&
72 RES_DRAWFRMFMT != pFrmFmt->Which() )
73 continue;
74 const SwFmtAnchor& rAnchor = pFrmFmt->GetAnchor();
75 SwPosition const*const pAPos = rAnchor.GetCntntAnchor();
76 if (pAPos &&
77 ((FLY_AT_PARA == rAnchor.GetAnchorId()) ||
78 (FLY_AT_CHAR == rAnchor.GetAnchorId())) &&
79 rIdx == pAPos->nNode.GetIndex() )
80 {
81 bRet=true;
82 break;
83 }
84 }
85 return bRet;
86 }
87
MakeEntries(SwDoc * pD,SwTextBlocks & rBlocks,bool bSaveRelFile,const std::vector<String> & rStrings,const std::vector<ww::bytes> & rExtra)88 bool WW8Glossary::MakeEntries(SwDoc *pD, SwTextBlocks &rBlocks,
89 bool bSaveRelFile, const std::vector<String>& rStrings,
90 const std::vector<ww::bytes>& rExtra)
91 {
92 // this code will be called after reading all text into the
93 // empty sections
94 const String aOldURL( rBlocks.GetBaseURL() );
95 bool bRet=false;
96 if( bSaveRelFile )
97 {
98 rBlocks.SetBaseURL(
99 URIHelper::SmartRel2Abs(
100 INetURLObject(), rBlocks.GetFileName(),
101 URIHelper::GetMaybeFileHdl()));
102 }
103 else
104 rBlocks.SetBaseURL( aEmptyStr );
105
106 SwNodeIndex aDocEnd( pD->GetNodes().GetEndOfContent() );
107 SwNodeIndex aStart( *aDocEnd.GetNode().StartOfSectionNode(), 1 );
108
109 // search the first NormalStartNode
110 while( !( aStart.GetNode().IsStartNode() && SwNormalStartNode ==
111 aStart.GetNode().GetStartNode()->GetStartNodeType()) &&
112 aStart < aDocEnd )
113 aStart++;
114
115 if( aStart < aDocEnd )
116 {
117 SwTxtFmtColl* pColl = pD->GetTxtCollFromPool
118 (RES_POOLCOLL_STANDARD, false);
119 sal_uInt16 nGlosEntry = 0;
120 SwCntntNode* pCNd = 0;
121 do {
122 SwPaM aPam( aStart );
123 {
124 SwNodeIndex& rIdx = aPam.GetPoint()->nNode;
125 rIdx++;
126 if( 0 == ( pCNd = rIdx.GetNode().GetTxtNode() ) )
127 {
128 pCNd = pD->GetNodes().MakeTxtNode( rIdx, pColl );
129 rIdx = *pCNd;
130 }
131 }
132 aPam.GetPoint()->nContent.Assign( pCNd, 0 );
133 aPam.SetMark();
134 {
135 SwNodeIndex& rIdx = aPam.GetPoint()->nNode;
136 rIdx = aStart.GetNode().EndOfSectionIndex() - 1;
137 if(( 0 == ( pCNd = rIdx.GetNode().GetCntntNode() ) )
138 || HasBareGraphicEnd(pD,rIdx))
139 {
140 rIdx++;
141 pCNd = pD->GetNodes().MakeTxtNode( rIdx, pColl );
142 rIdx = *pCNd;
143 }
144 }
145 aPam.GetPoint()->nContent.Assign( pCNd, pCNd->Len() );
146
147 // now we have the right selection for one entry. Copy this to
148 // the definied TextBlock, but only if it is not an autocorrection
149 // entry (== -1) otherwise the group indicates the group in the
150 // sttbfglsystyle list that this entry belongs to. Unused at the
151 // moment
152 const ww::bytes &rData = rExtra[nGlosEntry];
153 sal_uInt16 n = SVBT16ToShort( &(rData[2]) );
154 if(n != 0xFFFF)
155 {
156 rBlocks.ClearDoc();
157 const String &rLNm = rStrings[nGlosEntry];
158
159 String sShortcut = rLNm;
160
161 // Need to check make sure the shortcut is not already being used
162 xub_StrLen nStart = 0;
163 sal_uInt16 nCurPos = rBlocks.GetIndex( sShortcut );
164 xub_StrLen nLen = sShortcut.Len();
165 while( (sal_uInt16)-1 != nCurPos )
166 {
167 sShortcut.Erase( nLen ) +=
168 String::CreateFromInt32( ++nStart ); // add an Number to it
169 nCurPos = rBlocks.GetIndex( sShortcut );
170 }
171
172 if( rBlocks.BeginPutDoc( sShortcut, sShortcut )) // Make the shortcut and the name the same
173
174 {
175 SwDoc* pGlDoc = rBlocks.GetDoc();
176 SwNodeIndex aIdx( pGlDoc->GetNodes().GetEndOfContent(),
177 -1 );
178 pCNd = aIdx.GetNode().GetCntntNode();
179 SwPosition aPos( aIdx, SwIndex( pCNd, pCNd->Len() ));
180 pD->CopyRange( aPam, aPos, false );
181 rBlocks.PutDoc();
182 }
183 }
184 aStart = aStart.GetNode().EndOfSectionIndex() + 1;
185 ++nGlosEntry;
186 } while( aStart.GetNode().IsStartNode() &&
187 SwNormalStartNode == aStart.GetNode().
188 GetStartNode()->GetStartNodeType());
189 bRet=true;
190 }
191
192 // this code will be called after reading all text into the empty sections
193
194 rBlocks.SetBaseURL( aOldURL );
195 return bRet;
196 }
197
198
Load(SwTextBlocks & rBlocks,bool bSaveRelFile)199 bool WW8Glossary::Load( SwTextBlocks &rBlocks, bool bSaveRelFile )
200 {
201 bool bRet=false;
202 if (pGlossary && pGlossary->IsGlossaryFib() && rBlocks.StartPutMuchBlockEntries())
203 {
204 //read the names of the autotext entries
205 std::vector<String> aStrings;
206 std::vector<ww::bytes> aData;
207
208 rtl_TextEncoding eStructCharSet =
209 WW8Fib::GetFIBCharset(pGlossary->chseTables);
210
211 WW8ReadSTTBF(true, *xTableStream, pGlossary->fcSttbfglsy,
212 pGlossary->lcbSttbfglsy, 0, eStructCharSet, aStrings, &aData );
213
214 rStrm->Seek(0);
215
216 if ( 0 != (nStrings = static_cast< sal_uInt16 >(aStrings.size())))
217 {
218 SfxObjectShellLock xDocSh(new SwDocShell(SFX_CREATE_MODE_INTERNAL));
219 if (xDocSh->DoInitNew(0))
220 {
221 SwDoc *pD = ((SwDocShell*)(&xDocSh))->GetDoc();
222 SwWW8ImplReader* pRdr = new SwWW8ImplReader(pGlossary->nVersion,
223 xStg, &rStrm, *pD, rBlocks.GetBaseURL(), true);
224
225 SwNodeIndex aIdx(
226 *pD->GetNodes().GetEndOfContent().StartOfSectionNode(), 1);
227 if( !aIdx.GetNode().IsTxtNode() )
228 {
229 ASSERT( sal_False, "where is the TextNode?" );
230 pD->GetNodes().GoNext( &aIdx );
231 }
232 SwPaM aPamo( aIdx );
233 aPamo.GetPoint()->nContent.Assign(aIdx.GetNode().GetCntntNode(),
234 0);
235 pRdr->LoadDoc(aPamo,this);
236
237 bRet = MakeEntries(pD, rBlocks, bSaveRelFile, aStrings, aData);
238
239 delete pRdr;
240 }
241 xDocSh->DoClose();
242 rBlocks.EndPutMuchBlockEntries();
243 }
244 }
245 return bRet;
246 }
247
248
IsGlossaryFib()249 bool WW8GlossaryFib::IsGlossaryFib()
250 {
251 // fGlsy will indicate whether this has AutoText or not
252 return fGlsy;
253 }
254
FindGlossaryFibOffset(SvStream &,SvStream &,const WW8Fib & rFib)255 sal_uInt32 WW8GlossaryFib::FindGlossaryFibOffset(SvStream & /* rTableStrm */,
256 SvStream & /* rStrm */,
257 const WW8Fib &rFib)
258 {
259 sal_uInt32 nGlossaryFibOffset = 0;
260 if ( rFib.fDot ) // its a template
261 {
262 if ( rFib.pnNext )
263 nGlossaryFibOffset = ( rFib.pnNext * 512 );
264 }
265 return nGlossaryFibOffset;
266 }
267
268 /* vi:set tabstop=4 shiftwidth=4 expandtab: */
269