/src/libreoffice/sw/source/uibase/uiview/srcview.cxx
Line | Count | Source |
1 | | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 | | /* |
3 | | * This file is part of the LibreOffice project. |
4 | | * |
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/. |
8 | | * |
9 | | * This file incorporates work covered by the following license notice: |
10 | | * |
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 . |
18 | | */ |
19 | | |
20 | | #include <rtl/tencinfo.h> |
21 | | #include <osl/diagnose.h> |
22 | | #include <com/sun/star/frame/XModel.hpp> |
23 | | #include <com/sun/star/frame/XModel3.hpp> |
24 | | #include <com/sun/star/ui/dialogs/TemplateDescription.hpp> |
25 | | #include <unotools/tempfile.hxx> |
26 | | #include <tools/urlobj.hxx> |
27 | | #include <vcl/errinf.hxx> |
28 | | #include <vcl/textview.hxx> |
29 | | #include <vcl/svapp.hxx> |
30 | | #include <vcl/weld/Builder.hxx> |
31 | | #include <vcl/weld/MessageDialog.hxx> |
32 | | #include <svl/intitem.hxx> |
33 | | #include <svl/stritem.hxx> |
34 | | #include <svl/undo.hxx> |
35 | | #include <svl/eitem.hxx> |
36 | | #include <svl/whiter.hxx> |
37 | | #include <svl/itemiter.hxx> |
38 | | #include <vcl/transfer.hxx> |
39 | | #include <svtools/strings.hrc> |
40 | | #include <svtools/svtresid.hxx> |
41 | | #include <svtools/htmlcfg.hxx> |
42 | | #include <sfx2/app.hxx> |
43 | | #include <sfx2/objface.hxx> |
44 | | #include <sfx2/toolbarids.hxx> |
45 | | #include <sfx2/viewfrm.hxx> |
46 | | #include <sfx2/bindings.hxx> |
47 | | #include <sfx2/docfilt.hxx> |
48 | | #include <sfx2/fcontnr.hxx> |
49 | | #include <sfx2/request.hxx> |
50 | | #include <sfx2/docfile.hxx> |
51 | | #include <svx/srchdlg.hxx> |
52 | | #include <svx/statusitem.hxx> |
53 | | #include <svl/srchitem.hxx> |
54 | | #include <sfx2/sfxhtml.hxx> |
55 | | #include <swtypes.hxx> |
56 | | #include <docsh.hxx> |
57 | | #include <wdocsh.hxx> |
58 | | #include <srcview.hxx> |
59 | | #include "viewfunc.hxx" |
60 | | #include <doc.hxx> |
61 | | #include <IDocumentDeviceAccess.hxx> |
62 | | #include <IDocumentState.hxx> |
63 | | #include <sfx2/msg.hxx> |
64 | | #include <shellio.hxx> |
65 | | |
66 | | #include <cmdid.h> |
67 | | #include <strings.hrc> |
68 | | #include <com/sun/star/ui/dialogs/XFilePicker3.hpp> |
69 | | #include <sfx2/filedlghelper.hxx> |
70 | | #define ShellClass_SwSrcView |
71 | | #include <swslots.hxx> |
72 | | |
73 | | #include <com/sun/star/document/XDocumentProperties.hpp> |
74 | | #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp> |
75 | | |
76 | | using namespace ::com::sun::star; |
77 | | using namespace ::com::sun::star::i18n; |
78 | | using namespace ::com::sun::star::lang; |
79 | | using namespace ::com::sun::star::uno; |
80 | | using namespace ::com::sun::star::ui::dialogs; |
81 | | using namespace ::sfx2; |
82 | | |
83 | 0 | #define SWSRCVIEWFLAGS SfxViewShellFlags::NO_NEWWINDOW |
84 | | |
85 | 0 | #define SRC_SEARCHOPTIONS (SearchOptionFlags::ALL & ~SearchOptionFlags(SearchOptionFlags::FORMAT|SearchOptionFlags::FAMILIES|SearchOptionFlags::SEARCHALL)) |
86 | | |
87 | | // Printing margins -> like Basic - Ide |
88 | 0 | #define LMARGPRN 1700 |
89 | 0 | #define RMARGPRN 900 |
90 | 0 | #define TMARGPRN 2000 |
91 | 0 | #define BMARGPRN 1000 |
92 | 0 | #define BORDERPRN 300 |
93 | | |
94 | 0 | SFX_IMPL_NAMED_VIEWFACTORY(SwSrcView, "SourceView") |
95 | 0 | { |
96 | 0 | SFX_VIEW_REGISTRATION(SwWebDocShell); |
97 | 0 | } |
98 | | |
99 | | SFX_IMPL_SUPERCLASS_INTERFACE(SwSrcView, SfxViewShell) |
100 | | |
101 | | void SwSrcView::InitInterface_Impl() |
102 | 9 | { |
103 | 9 | GetStaticInterface()->RegisterPopupMenu(u"source"_ustr); |
104 | | |
105 | 9 | GetStaticInterface()->RegisterObjectBar(SFX_OBJECTBAR_TOOLS, |
106 | 9 | SfxVisibilityFlags::Standard|SfxVisibilityFlags::Server, |
107 | 9 | ToolbarId::Webtools_Toolbox); |
108 | | |
109 | 9 | GetStaticInterface()->RegisterChildWindow(SvxSearchDialogWrapper::GetChildWindowId()); |
110 | 9 | } |
111 | | |
112 | | |
113 | | static void lcl_PrintHeader( vcl::RenderContext &rOutDev, sal_Int32 nPages, sal_Int32 nCurPage, const OUString& rTitle ) |
114 | 0 | { |
115 | 0 | short nLeftMargin = LMARGPRN; |
116 | 0 | Size aSz = rOutDev.GetOutputSize(); |
117 | 0 | short nBorder = BORDERPRN; |
118 | |
|
119 | 0 | Color aOldFillColor( rOutDev.GetFillColor() ); |
120 | 0 | vcl::Font aOldFont( rOutDev.GetFont() ); |
121 | |
|
122 | 0 | rOutDev.SetFillColor( COL_TRANSPARENT ); |
123 | |
|
124 | 0 | vcl::Font aFont( aOldFont ); |
125 | 0 | aFont.SetWeight( WEIGHT_BOLD ); |
126 | 0 | aFont.SetAlignment( ALIGN_BOTTOM ); |
127 | 0 | rOutDev.SetFont( aFont ); |
128 | |
|
129 | 0 | tools::Long nFontHeight = rOutDev.GetTextHeight(); |
130 | | |
131 | | // 1.Border => Line, 2+3 Border = Space. |
132 | 0 | tools::Long nYTop = TMARGPRN-3*nBorder-nFontHeight; |
133 | |
|
134 | 0 | tools::Long nXLeft = nLeftMargin-nBorder; |
135 | 0 | tools::Long nXRight = aSz.Width()-RMARGPRN+nBorder; |
136 | |
|
137 | 0 | rOutDev.DrawRect( tools::Rectangle( |
138 | 0 | Point( nXLeft, nYTop ), |
139 | 0 | Size( nXRight-nXLeft, aSz.Height() - nYTop - BMARGPRN + nBorder ) ) ); |
140 | |
|
141 | 0 | tools::Long nY = TMARGPRN-2*nBorder; |
142 | 0 | Point aPos( nLeftMargin, nY ); |
143 | 0 | rOutDev.DrawText( aPos, rTitle ); |
144 | 0 | if ( nPages != 1 ) |
145 | 0 | { |
146 | 0 | aFont.SetWeight( WEIGHT_NORMAL ); |
147 | 0 | rOutDev.SetFont( aFont ); |
148 | 0 | OUString aPageStr = " [" + SwResId( STR_PAGE ) + " " + OUString::number( nCurPage ) + "]"; |
149 | 0 | aPos.AdjustX(rOutDev.GetTextWidth( rTitle ) ); |
150 | 0 | rOutDev.DrawText( aPos, aPageStr ); |
151 | 0 | } |
152 | |
|
153 | 0 | nY = TMARGPRN-nBorder; |
154 | |
|
155 | 0 | rOutDev.DrawLine( Point( nXLeft, nY ), Point( nXRight, nY ) ); |
156 | |
|
157 | 0 | rOutDev.SetFont( aOldFont ); |
158 | 0 | rOutDev.SetFillColor( aOldFillColor ); |
159 | 0 | } |
160 | | |
161 | | static rtl_TextEncoding lcl_GetStreamCharSet(rtl_TextEncoding eLoadEncoding) |
162 | 0 | { |
163 | 0 | rtl_TextEncoding eRet = eLoadEncoding; |
164 | 0 | if(RTL_TEXTENCODING_DONTKNOW == eRet) |
165 | 0 | { |
166 | 0 | eRet = RTL_TEXTENCODING_UTF8; |
167 | 0 | } |
168 | 0 | return eRet; |
169 | 0 | } |
170 | | |
171 | | static OUString lcl_ConvertTabsToSpaces( const OUString& sLine ) |
172 | 0 | { |
173 | 0 | if (sLine.isEmpty()) |
174 | 0 | return sLine; |
175 | | |
176 | 0 | OUString aRet = sLine; |
177 | 0 | const sal_Unicode aPadSpaces[4] = {' ', ' ', ' ', ' '}; |
178 | 0 | sal_Int32 nPos = 0; |
179 | 0 | for (;;) |
180 | 0 | { |
181 | 0 | nPos = aRet.indexOf('\t', nPos); |
182 | 0 | if (nPos<0) |
183 | 0 | { |
184 | 0 | break; |
185 | 0 | } |
186 | | // Not 4 blanks, but on 4th TabPos: |
187 | 0 | const sal_Int32 nPadLen = 4 - (nPos % 4); |
188 | 0 | aRet = aRet.replaceAt(nPos, 1, std::u16string_view{aPadSpaces, static_cast<size_t>(nPadLen)}); |
189 | 0 | nPos += nPadLen; |
190 | 0 | } |
191 | 0 | return aRet; |
192 | 0 | } |
193 | | |
194 | | SwSrcView::SwSrcView(SfxViewFrame& rViewFrame, SfxViewShell*) : |
195 | 0 | SfxViewShell( rViewFrame, SWSRCVIEWFLAGS ), |
196 | 0 | m_aEditWin( VclPtr<SwSrcEditWindow>::Create( &rViewFrame.GetWindow(), this ) ), |
197 | 0 | m_bSourceSaved(false), |
198 | 0 | m_eLoadEncoding(RTL_TEXTENCODING_DONTKNOW) |
199 | 0 | { |
200 | 0 | Init(); |
201 | 0 | } |
202 | | |
203 | | SwSrcView::~SwSrcView() |
204 | 0 | { |
205 | 0 | SwDocShell* pDocShell = GetDocShell(); |
206 | 0 | assert(dynamic_cast<SwWebDocShell*>( pDocShell) && "Why no WebDocShell?" ); |
207 | 0 | const TextSelection& rSel = m_aEditWin->GetTextView()->GetSelection(); |
208 | 0 | static_cast<SwWebDocShell*>(pDocShell)->SetSourcePara( static_cast< sal_uInt16 >( rSel.GetStart().GetPara() ) ); |
209 | |
|
210 | 0 | uno::Reference<document::XDocumentPropertiesSupplier> xDPS( |
211 | 0 | pDocShell->GetModel(), uno::UNO_QUERY_THROW); |
212 | 0 | uno::Reference<document::XDocumentProperties> xDocProps |
213 | 0 | = xDPS->getDocumentProperties(); |
214 | 0 | OUString url = xDocProps->getAutoloadURL(); |
215 | 0 | sal_Int32 delay = xDocProps->getAutoloadSecs(); |
216 | 0 | pDocShell->SetAutoLoad(INetURLObject(url), delay, |
217 | 0 | (delay != 0) || !url.isEmpty()); |
218 | 0 | EndListening(*pDocShell); |
219 | 0 | m_pSearchItem.reset(); |
220 | |
|
221 | 0 | m_aEditWin.disposeAndClear(); |
222 | 0 | } |
223 | | |
224 | | void SwSrcView::SaveContentTo(SfxMedium& rMed) |
225 | 0 | { |
226 | 0 | SvStream* pOutStream = rMed.GetOutStream(); |
227 | 0 | pOutStream->SetStreamEncoding(lcl_GetStreamCharSet(m_eLoadEncoding)); |
228 | 0 | m_aEditWin->Write( *pOutStream ); |
229 | 0 | } |
230 | | |
231 | | void SwSrcView::Init() |
232 | 0 | { |
233 | 0 | SetName(u"Source"_ustr); |
234 | 0 | SetWindow( m_aEditWin.get() ); |
235 | 0 | SwDocShell* pDocShell = GetDocShell(); |
236 | | // If the doc is still loading, then the DocShell must fire up |
237 | | // the Load if the loading is completed. |
238 | 0 | if(!pDocShell->IsLoading()) |
239 | 0 | Load(pDocShell); |
240 | 0 | else |
241 | 0 | { |
242 | 0 | m_aEditWin->SetReadonly(true); |
243 | 0 | } |
244 | |
|
245 | 0 | SetNewWindowAllowed( false ); |
246 | 0 | StartListening(*pDocShell, DuplicateHandling::Prevent); |
247 | 0 | } |
248 | | |
249 | | SwDocShell* SwSrcView::GetDocShell() |
250 | 0 | { |
251 | 0 | SfxObjectShell* pObjShell = GetViewFrame().GetObjectShell(); |
252 | 0 | return dynamic_cast<SwDocShell*>( pObjShell ); |
253 | 0 | } |
254 | | |
255 | | void SwSrcView::SaveContent(const OUString& rTmpFile) |
256 | 0 | { |
257 | 0 | SfxMedium aMedium( rTmpFile, StreamMode::WRITE); |
258 | 0 | SvStream* pOutStream = aMedium.GetOutStream(); |
259 | 0 | pOutStream->SetStreamEncoding( lcl_GetStreamCharSet(m_eLoadEncoding) ); |
260 | 0 | m_aEditWin->Write(*pOutStream); |
261 | 0 | aMedium.Commit(); |
262 | 0 | } |
263 | | |
264 | | void SwSrcView::Execute(SfxRequest& rReq) |
265 | 0 | { |
266 | 0 | TextView* pTextView = m_aEditWin->GetTextView(); |
267 | 0 | switch( rReq.GetSlot() ) |
268 | 0 | { |
269 | 0 | case SID_SAVEACOPY: |
270 | 0 | case SID_SAVEASDOC: |
271 | 0 | { |
272 | | // filesave dialog with autoextension |
273 | 0 | FileDialogHelper aDlgHelper( |
274 | 0 | TemplateDescription::FILESAVE_AUTOEXTENSION, |
275 | 0 | FileDialogFlags::NONE, m_aEditWin->GetFrameWeld()); |
276 | 0 | uno::Reference < XFilePicker3 > xFP = aDlgHelper.GetFilePicker(); |
277 | | |
278 | | // search for an html filter for export |
279 | 0 | SfxFilterContainer* pFilterCont = GetObjectShell()->GetFactory().GetFilterContainer(); |
280 | 0 | std::shared_ptr<const SfxFilter> pFilter = |
281 | 0 | pFilterCont->GetFilter4Extension( u"html"_ustr, SfxFilterFlags::EXPORT ); |
282 | 0 | if ( pFilter ) |
283 | 0 | { |
284 | | // filter found -> use its uiname and wildcard |
285 | 0 | const OUString& rUIName = pFilter->GetUIName(); |
286 | 0 | const WildCard& rCard = pFilter->GetWildcard(); |
287 | 0 | xFP->appendFilter( rUIName, rCard.getGlob() ); |
288 | 0 | xFP->setCurrentFilter( rUIName ) ; |
289 | 0 | } |
290 | 0 | else |
291 | 0 | { |
292 | | // filter not found |
293 | 0 | OUString sHtml(u"HTML"_ustr); |
294 | 0 | xFP->appendFilter( sHtml, u"*.html;*.htm"_ustr ); |
295 | 0 | xFP->setCurrentFilter( sHtml ) ; |
296 | 0 | } |
297 | |
|
298 | 0 | if( aDlgHelper.Execute() == ERRCODE_NONE) |
299 | 0 | { |
300 | 0 | SfxMedium aMedium( xFP->getSelectedFiles().getConstArray()[0], |
301 | 0 | StreamMode::WRITE | StreamMode::SHARE_DENYNONE ); |
302 | 0 | SvStream* pOutStream = aMedium.GetOutStream(); |
303 | 0 | pOutStream->SetStreamEncoding(lcl_GetStreamCharSet(m_eLoadEncoding)); |
304 | 0 | m_aEditWin->Write( *pOutStream ); |
305 | 0 | aMedium.Commit(); |
306 | 0 | } |
307 | 0 | } |
308 | 0 | break; |
309 | 0 | case SID_SAVEDOC: |
310 | 0 | { |
311 | 0 | SwDocShell* pDocShell = GetDocShell(); |
312 | 0 | assert(pDocShell); |
313 | 0 | SfxMedium* pMed = nullptr; |
314 | 0 | if(pDocShell->HasName()) |
315 | 0 | pMed = pDocShell->GetMedium(); |
316 | 0 | else |
317 | 0 | { |
318 | 0 | const SfxPoolItemHolder& rResult(pDocShell->ExecuteSlot(rReq, pDocShell->GetInterface())); |
319 | 0 | const SfxBoolItem* pItem(static_cast<const SfxBoolItem*>(rResult.getItem())); |
320 | 0 | if(pItem && pItem->GetValue()) |
321 | 0 | pMed = pDocShell->GetMedium(); |
322 | 0 | } |
323 | 0 | if(pMed) |
324 | 0 | { |
325 | 0 | SvStream* pOutStream = pMed->GetOutStream(); |
326 | 0 | pOutStream->Seek(0); |
327 | 0 | pOutStream->SetStreamSize(0); |
328 | 0 | pOutStream->SetStreamEncoding(lcl_GetStreamCharSet(m_eLoadEncoding)); |
329 | 0 | m_aEditWin->Write( *pOutStream ); |
330 | 0 | pMed->CloseOutStream(); |
331 | 0 | pMed->Commit(); |
332 | 0 | pDocShell->GetDoc()->getIDocumentState().ResetModified(); |
333 | 0 | m_bSourceSaved = true; |
334 | 0 | m_aEditWin->ClearModifyFlag(); |
335 | 0 | } |
336 | 0 | } |
337 | 0 | break; |
338 | 0 | case FID_SEARCH_NOW: |
339 | 0 | { |
340 | 0 | const SfxItemSet* pTmpArgs(rReq.GetArgs()); |
341 | 0 | SfxItemIter aIter(*pTmpArgs); |
342 | 0 | OSL_ENSURE( aIter.GetCurItem(), "no SearchItem ?" ); |
343 | 0 | const SvxSearchItem& rItem(static_cast<const SvxSearchItem&>(*aIter.GetCurItem())); |
344 | 0 | SetSearchItem(rItem); |
345 | 0 | StartSearchAndReplace(rItem, rReq.IsAPI() ); |
346 | 0 | if(m_aEditWin->IsModified()) |
347 | 0 | { |
348 | 0 | SwDocShell* pDocShell = GetDocShell(); |
349 | 0 | assert(pDocShell); |
350 | 0 | pDocShell->GetDoc()->getIDocumentState().SetModified(); |
351 | 0 | } |
352 | 0 | } |
353 | 0 | break; |
354 | 0 | case FN_REPEAT_SEARCH: |
355 | 0 | { |
356 | 0 | SvxSearchItem* pSrchItem = GetSearchItem(); |
357 | 0 | if(pSrchItem) |
358 | 0 | { |
359 | 0 | StartSearchAndReplace( *pSrchItem, rReq.IsAPI() ); |
360 | 0 | if(m_aEditWin->IsModified()) |
361 | 0 | GetDocShell()->GetDoc()->getIDocumentState().SetModified(); |
362 | 0 | } |
363 | 0 | } |
364 | 0 | break; |
365 | 0 | case SID_PRINTDOC: |
366 | 0 | case SID_PRINTDOCDIRECT: |
367 | 0 | { |
368 | 0 | SfxViewShell::ExecuteSlot( rReq, SfxViewShell::GetInterface() ); |
369 | 0 | } |
370 | 0 | break; |
371 | 0 | case SID_UNDO: |
372 | 0 | pTextView->Undo(); |
373 | 0 | GetViewFrame().GetBindings().InvalidateAll(false); |
374 | 0 | break; |
375 | 0 | case SID_REDO: |
376 | 0 | pTextView->Redo(); |
377 | 0 | GetViewFrame().GetBindings().InvalidateAll(false); |
378 | 0 | break; |
379 | 0 | case SID_REPEAT: |
380 | 0 | break; |
381 | 0 | case SID_CUT: |
382 | 0 | if(pTextView->HasSelection()) |
383 | 0 | pTextView->Cut(); |
384 | 0 | break; |
385 | 0 | case SID_COPY: |
386 | 0 | if(pTextView->HasSelection()) |
387 | 0 | pTextView->Copy(); |
388 | 0 | break; |
389 | 0 | case SID_PASTE: |
390 | 0 | pTextView->Paste(); |
391 | 0 | break; |
392 | 0 | case SID_SELECTALL: |
393 | 0 | pTextView->SetSelection( TextSelection( TextPaM( 0, 0 ), TextPaM( TEXT_PARA_ALL, TEXT_INDEX_ALL ) ) ); |
394 | 0 | break; |
395 | 0 | } |
396 | 0 | m_aEditWin->Invalidate(); |
397 | 0 | } |
398 | | |
399 | | void SwSrcView::GetState(SfxItemSet& rSet) |
400 | 0 | { |
401 | 0 | SfxWhichIter aIter(rSet); |
402 | 0 | sal_uInt16 nWhich = aIter.FirstWhich(); |
403 | 0 | TextView* pTextView = m_aEditWin->GetTextView(); |
404 | |
|
405 | 0 | while(nWhich) |
406 | 0 | { |
407 | 0 | switch(nWhich) |
408 | 0 | { |
409 | 0 | case SID_SAVEASDOC: |
410 | 0 | rSet.Put(SfxStringItem(nWhich, SwResId(STR_SAVEAS_SRC))); |
411 | 0 | break; |
412 | 0 | case SID_SAVEACOPY: |
413 | 0 | rSet.Put(SfxStringItem(nWhich, SwResId(STR_SAVEACOPY_SRC))); |
414 | 0 | break; |
415 | 0 | case SID_SAVEDOC: |
416 | 0 | { |
417 | 0 | SwDocShell* pDocShell = GetDocShell(); |
418 | 0 | assert(pDocShell); |
419 | 0 | if(!pDocShell->IsModified()) |
420 | 0 | rSet.DisableItem(nWhich); |
421 | 0 | } |
422 | 0 | break; |
423 | 0 | case SID_PRINTDOC: |
424 | 0 | case SID_PRINTDOCDIRECT: |
425 | 0 | break; |
426 | 0 | case SID_TABLE_CELL: |
427 | 0 | { |
428 | 0 | TextSelection aSel = pTextView->GetSelection(); |
429 | 0 | OUString aPos = |
430 | 0 | SwResId(STR_SRCVIEW_ROW) |
431 | 0 | + OUString::number( aSel.GetEnd().GetPara()+1 ) |
432 | 0 | + " : " |
433 | 0 | + SwResId(STR_SRCVIEW_COL) |
434 | 0 | + OUString::number( aSel.GetEnd().GetIndex()+1 ); |
435 | 0 | SvxStatusItem aItem( SID_TABLE_CELL, aPos, StatusCategory::RowColumn ); |
436 | 0 | rSet.Put( aItem ); |
437 | 0 | } |
438 | 0 | break; |
439 | 0 | case SID_SEARCH_OPTIONS: |
440 | 0 | { |
441 | 0 | SearchOptionFlags nOpt = SRC_SEARCHOPTIONS; |
442 | 0 | SwDocShell* pDocShell = GetDocShell(); |
443 | 0 | assert(pDocShell); |
444 | 0 | if (pDocShell->IsReadOnly() || SfxViewShell::IsCurrentLokViewReadOnly()) |
445 | 0 | nOpt &= ~SearchOptionFlags(SearchOptionFlags::REPLACE|SearchOptionFlags::REPLACE_ALL); |
446 | |
|
447 | 0 | rSet.Put( SfxUInt16Item( SID_SEARCH_OPTIONS, static_cast<sal_uInt16>(nOpt) ) ); |
448 | 0 | } |
449 | 0 | break; |
450 | 0 | case SID_SEARCH_ITEM: |
451 | 0 | { |
452 | 0 | OUString sSelected; |
453 | 0 | if ( !pTextView->HasSelection() ) |
454 | 0 | { |
455 | 0 | const TextSelection& rSel = pTextView->GetSelection(); |
456 | 0 | sSelected = m_aEditWin->GetTextEngine()->GetWord( rSel.GetStart()); |
457 | 0 | } |
458 | 0 | else |
459 | 0 | { |
460 | 0 | sSelected = pTextView->GetSelected(); |
461 | 0 | } |
462 | 0 | SvxSearchItem * pSrchItem = GetSearchItem(); |
463 | 0 | pSrchItem->SetSearchString( sSelected ); |
464 | 0 | rSet.Put( *pSrchItem ); |
465 | 0 | } |
466 | 0 | break; |
467 | 0 | case FN_REPEAT_SEARCH: |
468 | 0 | { |
469 | 0 | if(!GetSearchItem()) |
470 | 0 | rSet.DisableItem(nWhich); |
471 | 0 | } |
472 | 0 | break; |
473 | 0 | case SID_UNDO: |
474 | 0 | case SID_REDO: |
475 | 0 | { |
476 | 0 | SfxUndoManager& rMgr = pTextView->GetTextEngine()->GetUndoManager(); |
477 | 0 | sal_uInt16 nCount = 0; |
478 | 0 | if(nWhich == SID_UNDO) |
479 | 0 | { |
480 | 0 | nCount = rMgr.GetUndoActionCount(); |
481 | 0 | if(nCount) |
482 | 0 | { |
483 | 0 | OUString aStr = SvtResId( STR_UNDO) + rMgr.GetUndoActionComment(--nCount); |
484 | 0 | rSet.Put(SfxStringItem(nWhich, aStr)); |
485 | 0 | } |
486 | 0 | else |
487 | 0 | rSet.DisableItem(nWhich); |
488 | 0 | } |
489 | 0 | else |
490 | 0 | { |
491 | 0 | nCount = rMgr.GetRedoActionCount(); |
492 | 0 | if(nCount) |
493 | 0 | { |
494 | 0 | OUString aStr = SvtResId( STR_REDO) + rMgr.GetRedoActionComment(--nCount); |
495 | 0 | rSet.Put(SfxStringItem(nWhich,aStr)); |
496 | 0 | } |
497 | 0 | else |
498 | 0 | rSet.DisableItem(nWhich); |
499 | 0 | } |
500 | 0 | } |
501 | 0 | break; |
502 | 0 | case SID_MAIL_SENDDOCASPDF: |
503 | 0 | case SID_MAIL_SENDDOC : |
504 | 0 | case SID_EXPORTDOCASPDF: |
505 | 0 | case SID_DIRECTEXPORTDOCASPDF: |
506 | 0 | case SID_EXPORTDOC: |
507 | 0 | case SID_REPEAT: |
508 | 0 | case SID_BROWSER_MODE: |
509 | 0 | case FN_PRINT_LAYOUT: |
510 | 0 | case FN_DRAFT_VIEW: |
511 | 0 | case FN_SINGLE_PAGE_PER_ROW: |
512 | 0 | case FN_MULTIPLE_PAGES_PER_ROW: |
513 | 0 | case FN_BOOKVIEW: |
514 | 0 | rSet.DisableItem(nWhich); |
515 | 0 | break; |
516 | 0 | case SID_CUT: |
517 | 0 | case SID_COPY: |
518 | 0 | if(!pTextView->HasSelection()) |
519 | 0 | rSet.DisableItem(nWhich); |
520 | 0 | break; |
521 | 0 | case SID_PASTE: |
522 | 0 | { |
523 | 0 | TransferableDataHelper aDataHelper( |
524 | 0 | TransferableDataHelper::CreateFromSystemClipboard( |
525 | 0 | m_aEditWin.get()) ); |
526 | 0 | bool bDisable = !aDataHelper.GetXTransferable().is() || |
527 | 0 | 0 == aDataHelper.GetFormatCount(); |
528 | 0 | if( bDisable ) |
529 | 0 | rSet.DisableItem(nWhich); |
530 | 0 | } |
531 | 0 | break; |
532 | 0 | } |
533 | 0 | nWhich = aIter.NextWhich(); |
534 | 0 | } |
535 | 0 | } |
536 | | |
537 | | SvxSearchItem* SwSrcView::GetSearchItem() |
538 | 0 | { |
539 | 0 | if(!m_pSearchItem) |
540 | 0 | { |
541 | 0 | m_pSearchItem.reset(new SvxSearchItem(SID_SEARCH_ITEM)); |
542 | 0 | } |
543 | 0 | return m_pSearchItem.get(); |
544 | 0 | } |
545 | | |
546 | | void SwSrcView::SetSearchItem( const SvxSearchItem& rItem ) |
547 | 0 | { |
548 | 0 | m_pSearchItem.reset(rItem.Clone()); |
549 | 0 | } |
550 | | |
551 | | void SwSrcView::StartSearchAndReplace(const SvxSearchItem& rSearchItem, |
552 | | bool bApi, |
553 | | bool bRecursive) |
554 | 0 | { |
555 | 0 | TextView* pTextView = m_aEditWin->GetTextView(); |
556 | 0 | TextPaM aPaM; |
557 | |
|
558 | 0 | bool bForward = !rSearchItem.GetBackward(); |
559 | 0 | bool bAtStart = pTextView->GetSelection() == TextSelection( aPaM, aPaM ); |
560 | |
|
561 | 0 | if( !bForward ) |
562 | 0 | aPaM = TextPaM( TEXT_PARA_ALL, TEXT_INDEX_ALL ); |
563 | |
|
564 | 0 | i18nutil::SearchOptions2 aSearchOpt( rSearchItem.GetSearchOptions() ); |
565 | 0 | aSearchOpt.Locale = GetAppLanguageTag().getLocale(); |
566 | |
|
567 | 0 | sal_uInt16 nFound; |
568 | 0 | bool bAll = false; |
569 | 0 | switch( rSearchItem.GetCommand() ) |
570 | 0 | { |
571 | 0 | case SvxSearchCmd::FIND: |
572 | 0 | case SvxSearchCmd::FIND_ALL: |
573 | 0 | nFound = pTextView->Search( aSearchOpt, bForward ) ? 1 : 0; |
574 | 0 | break; |
575 | | |
576 | 0 | case SvxSearchCmd::REPLACE_ALL: bAll = true; |
577 | 0 | [[fallthrough]]; |
578 | 0 | case SvxSearchCmd::REPLACE: |
579 | 0 | nFound = pTextView->Replace( aSearchOpt, bAll, bForward ); |
580 | 0 | break; |
581 | | |
582 | 0 | default: |
583 | 0 | nFound = 0; |
584 | 0 | } |
585 | | |
586 | 0 | if( nFound ) |
587 | 0 | return; |
588 | | |
589 | 0 | bool bNotFoundMessage = false; |
590 | 0 | if(!bRecursive) |
591 | 0 | { |
592 | 0 | bNotFoundMessage = bAtStart; |
593 | 0 | } |
594 | 0 | else if(bAtStart) |
595 | 0 | { |
596 | 0 | bNotFoundMessage = true; |
597 | 0 | } |
598 | |
|
599 | 0 | if(bApi) |
600 | 0 | return; |
601 | | |
602 | 0 | if(bNotFoundMessage) |
603 | 0 | { |
604 | 0 | std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(nullptr, u"modules/swriter/ui/infonotfounddialog.ui"_ustr)); |
605 | 0 | std::unique_ptr<weld::MessageDialog> xInfoBox(xBuilder->weld_message_dialog(u"InfoNotFoundDialog"_ustr)); |
606 | 0 | xInfoBox->run(); |
607 | 0 | } |
608 | 0 | else if(!bRecursive) |
609 | 0 | { |
610 | 0 | int nRet; |
611 | |
|
612 | 0 | if (!bForward) |
613 | 0 | { |
614 | 0 | std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(nullptr, u"modules/swriter/ui/querycontinueenddialog.ui"_ustr)); |
615 | 0 | std::unique_ptr<weld::MessageDialog> xQueryBox(xBuilder->weld_message_dialog(u"QueryContinueEndDialog"_ustr)); |
616 | 0 | nRet = xQueryBox->run(); |
617 | 0 | } |
618 | 0 | else |
619 | 0 | { |
620 | 0 | std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(nullptr, u"modules/swriter/ui/querycontinuebegindialog.ui"_ustr)); |
621 | 0 | std::unique_ptr<weld::MessageDialog> xQueryBox(xBuilder->weld_message_dialog(u"QueryContinueBeginDialog"_ustr)); |
622 | 0 | nRet = xQueryBox->run(); |
623 | 0 | } |
624 | |
|
625 | 0 | if (nRet == RET_YES) |
626 | 0 | { |
627 | 0 | pTextView->SetSelection( TextSelection( aPaM, aPaM ) ); |
628 | 0 | StartSearchAndReplace( rSearchItem, false, true ); |
629 | 0 | } |
630 | 0 | } |
631 | 0 | } |
632 | | |
633 | | sal_uInt16 SwSrcView::SetPrinter(SfxPrinter* pNew, SfxPrinterChangeFlags nDiffFlags ) |
634 | 0 | { |
635 | 0 | SwDocShell* pDocSh = GetDocShell(); |
636 | 0 | assert(pDocSh); |
637 | 0 | if ( (SfxPrinterChangeFlags::JOBSETUP | SfxPrinterChangeFlags::PRINTER) & nDiffFlags ) |
638 | 0 | { |
639 | 0 | pDocSh->GetDoc()->getIDocumentDeviceAccess().setPrinter( pNew, true, true ); |
640 | 0 | if ( nDiffFlags & SfxPrinterChangeFlags::PRINTER ) |
641 | 0 | pDocSh->SetModified(); |
642 | 0 | } |
643 | 0 | if ( nDiffFlags & SfxPrinterChangeFlags::OPTIONS ) |
644 | 0 | ::SetPrinter( &pDocSh->getIDocumentDeviceAccess(), pNew, true ); |
645 | |
|
646 | 0 | const bool bChgOri = bool(nDiffFlags & SfxPrinterChangeFlags::CHG_ORIENTATION); |
647 | 0 | const bool bChgSize = bool(nDiffFlags & SfxPrinterChangeFlags::CHG_SIZE); |
648 | 0 | if ( bChgOri || bChgSize ) |
649 | 0 | { |
650 | 0 | pDocSh->SetModified(); |
651 | 0 | } |
652 | 0 | return 0; |
653 | 0 | } |
654 | | |
655 | | SfxPrinter* SwSrcView::GetPrinter( bool bCreate ) |
656 | 0 | { |
657 | 0 | SwDocShell* pDocSh = GetDocShell(); |
658 | 0 | assert(pDocSh); |
659 | 0 | return pDocSh->GetDoc()->getIDocumentDeviceAccess().getPrinter(bCreate); |
660 | 0 | } |
661 | | |
662 | | sal_Int32 SwSrcView::PrintSource( |
663 | | OutputDevice *pOutDev, |
664 | | sal_Int32 nPage, |
665 | | bool bCalcNumPagesOnly ) |
666 | 0 | { |
667 | 0 | if (!pOutDev || nPage <= 0) |
668 | 0 | return 0; |
669 | | |
670 | | //! This algorithm for printing the n-th page is very poor since it |
671 | | //! needs to go over the text of all previous pages to get to the correct one. |
672 | | //! But since HTML source code is expected to be just a small number of pages |
673 | | //! even this poor algorithm should be enough... |
674 | | |
675 | 0 | auto popIt = pOutDev->ScopedPush(); |
676 | |
|
677 | 0 | TextEngine* pTextEngine = m_aEditWin->GetTextEngine(); |
678 | 0 | pOutDev->SetMapMode(MapMode(MapUnit::Map100thMM)); |
679 | 0 | vcl::Font aFont( m_aEditWin->GetOutWin()->GetFont() ); |
680 | 0 | Size aSize( aFont.GetFontSize() ); |
681 | 0 | aSize = m_aEditWin->GetOutWin()->PixelToLogic(aSize, MapMode(MapUnit::Map100thMM)); |
682 | 0 | aFont.SetFontSize( aSize ); |
683 | 0 | aFont.SetColor( COL_BLACK ); |
684 | 0 | pOutDev->SetFont( aFont ); |
685 | |
|
686 | 0 | OUString aTitle( GetViewFrame().GetWindow().GetText() ); |
687 | |
|
688 | 0 | const tools::Long nLineHeight = pOutDev->GetTextHeight(); // slightly more |
689 | 0 | const tools::Long nParaSpace = 10; |
690 | |
|
691 | 0 | Size aPaperSz = pOutDev->GetOutputSize(); |
692 | 0 | aPaperSz.AdjustWidth( -(LMARGPRN + RMARGPRN) ); |
693 | 0 | aPaperSz.AdjustHeight( -(TMARGPRN + BMARGPRN) ); |
694 | | |
695 | | // nLinepPage is not true, if lines have to be wrapped... |
696 | 0 | const tools::Long nLinespPage = nLineHeight ? aPaperSz.Height() / nLineHeight : 1; |
697 | 0 | const tools::Long nCharWidth = pOutDev->GetTextWidth(u"X"_ustr); |
698 | 0 | const sal_Int32 nCharspLine = nCharWidth ? static_cast<sal_Int32>(aPaperSz.Width() / nCharWidth) : 1; |
699 | 0 | const sal_uInt32 nParas = pTextEngine->GetParagraphCount(); |
700 | |
|
701 | 0 | const sal_Int32 nPages = static_cast<sal_Int32>(nParas / nLinespPage + 1 ); |
702 | 0 | sal_Int32 nCurPage = 1; |
703 | | |
704 | | // Print header... |
705 | 0 | if (!bCalcNumPagesOnly && nPage == nCurPage) |
706 | 0 | lcl_PrintHeader( *pOutDev, nPages, nCurPage, aTitle ); |
707 | 0 | const Point aStartPos( LMARGPRN, TMARGPRN ); |
708 | 0 | Point aPos( aStartPos ); |
709 | 0 | for ( sal_uInt32 nPara = 0; nPara < nParas; ++nPara ) |
710 | 0 | { |
711 | 0 | const OUString aLine( lcl_ConvertTabsToSpaces(pTextEngine->GetText( nPara )) ); |
712 | 0 | const sal_Int32 nLineLen = aLine.getLength(); |
713 | 0 | const sal_Int32 nLines = (nLineLen+nCharspLine-1) / nCharspLine; |
714 | 0 | for ( sal_Int32 nLine = 0; nLine < nLines; ++nLine ) |
715 | 0 | { |
716 | 0 | aPos.AdjustY(nLineHeight ); |
717 | 0 | if ( aPos.Y() > ( aPaperSz.Height() + TMARGPRN - nLineHeight/2 ) ) |
718 | 0 | { |
719 | 0 | ++nCurPage; |
720 | 0 | if (!bCalcNumPagesOnly && nPage == nCurPage) |
721 | 0 | lcl_PrintHeader( *pOutDev, nPages, nCurPage, aTitle ); |
722 | 0 | aPos = aStartPos; |
723 | 0 | } |
724 | 0 | if (!bCalcNumPagesOnly && nPage == nCurPage) |
725 | 0 | { |
726 | 0 | const sal_Int32 nStart = nLine * nCharspLine; |
727 | 0 | const sal_Int32 nLen = std::min(nLineLen-nStart, nCharspLine); |
728 | 0 | pOutDev->DrawText( aPos, aLine.copy(nStart, nLen) ); |
729 | 0 | } |
730 | 0 | } |
731 | 0 | aPos.AdjustY(nParaSpace ); |
732 | 0 | } |
733 | |
|
734 | 0 | OSL_ENSURE( bCalcNumPagesOnly || nPage <= nCurPage, "page number out of range" ); |
735 | 0 | return nCurPage; |
736 | 0 | } |
737 | | |
738 | | void SwSrcView::Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) |
739 | 0 | { |
740 | 0 | if (rHint.GetId() == SfxHintId::ModeChanged || rHint.GetId() == SfxHintId::TitleChanged) |
741 | 0 | { |
742 | 0 | const SwDocShell* pDocSh = GetDocShell(); |
743 | 0 | assert(pDocSh); |
744 | 0 | if (!(rHint.GetId() == SfxHintId::TitleChanged |
745 | 0 | && (pDocSh->IsReadOnly() || !m_aEditWin->IsReadonly()))) |
746 | 0 | { |
747 | | // Broadcast only comes once! |
748 | 0 | const bool bReadonly = pDocSh->IsReadOnly(); |
749 | 0 | m_aEditWin->SetReadonly(bReadonly); |
750 | 0 | } |
751 | 0 | } |
752 | 0 | SfxViewShell::Notify(rBC, rHint); |
753 | 0 | } |
754 | | |
755 | | void SwSrcView::Load(SwDocShell* pDocShell) |
756 | 0 | { |
757 | 0 | rtl_TextEncoding eDestEnc = RTL_TEXTENCODING_UTF8; |
758 | |
|
759 | 0 | m_aEditWin->SetReadonly(pDocShell->IsReadOnly()); |
760 | 0 | m_aEditWin->SetTextEncoding(eDestEnc); |
761 | 0 | SfxMedium* pMedium = pDocShell->GetMedium(); |
762 | |
|
763 | 0 | std::shared_ptr<const SfxFilter> pFilter = pMedium->GetFilter(); |
764 | 0 | bool bHtml = pFilter && pFilter->GetUserData() == "HTML"; |
765 | 0 | bool bDocModified = pDocShell->IsModified(); |
766 | 0 | if(bHtml && !bDocModified && pDocShell->HasName()) |
767 | 0 | { |
768 | 0 | SvStream* pStream = pMedium->GetInStream(); |
769 | 0 | if(pStream && ERRCODE_NONE == pStream->GetError() ) |
770 | 0 | { |
771 | 0 | rtl_TextEncoding eHeaderEnc = |
772 | 0 | SfxHTMLParser::GetEncodingByHttpHeader( |
773 | 0 | pDocShell->GetHeaderAttributes() ); |
774 | 0 | if( RTL_TEXTENCODING_DONTKNOW == eHeaderEnc ) |
775 | 0 | { |
776 | 0 | const char *pTmpCharSet = |
777 | 0 | rtl_getBestMimeCharsetFromTextEncoding( RTL_TEXTENCODING_ISO_8859_1 ); |
778 | 0 | eHeaderEnc = rtl_getTextEncodingFromMimeCharset( pTmpCharSet ); |
779 | 0 | } |
780 | 0 | if( RTL_TEXTENCODING_DONTKNOW != eHeaderEnc && |
781 | 0 | eDestEnc != eHeaderEnc ) |
782 | 0 | { |
783 | 0 | eDestEnc = eHeaderEnc; |
784 | 0 | m_aEditWin->SetTextEncoding(eDestEnc); |
785 | 0 | } |
786 | 0 | pStream->SetStreamEncoding( eDestEnc ); |
787 | 0 | pStream->Seek(0); |
788 | 0 | TextEngine* pTextEngine = m_aEditWin->GetTextEngine(); |
789 | 0 | pTextEngine->EnableUndo(false); |
790 | 0 | m_aEditWin->Read(*pStream); |
791 | 0 | pTextEngine->EnableUndo(true); |
792 | 0 | } |
793 | 0 | else |
794 | 0 | { |
795 | 0 | std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(GetViewFrame().GetFrameWeld(), |
796 | 0 | VclMessageType::Info, VclButtonsType::Ok, |
797 | 0 | SwResId(STR_ERR_SRCSTREAM))); |
798 | 0 | xBox->run(); |
799 | 0 | } |
800 | 0 | } |
801 | 0 | else |
802 | 0 | { |
803 | 0 | utl::TempFileNamed aTempFile; |
804 | 0 | aTempFile.EnableKillingFile(); |
805 | 0 | const OUString sFileURL( aTempFile.GetURL() ); |
806 | |
|
807 | 0 | { |
808 | 0 | SfxMedium aMedium( sFileURL,StreamMode::READWRITE ); |
809 | 0 | SwWriter aWriter( aMedium, *pDocShell->GetDoc() ); |
810 | 0 | WriterRef xWriter; |
811 | 0 | ::GetHTMLWriter(std::u16string_view(), aMedium.GetBaseURL( true ), xWriter); |
812 | 0 | const OUString sWriteName = pDocShell->HasName() |
813 | 0 | ? pMedium->GetName() |
814 | 0 | : sFileURL; |
815 | 0 | ErrCodeMsg nRes = aWriter.Write(xWriter, &sWriteName); |
816 | 0 | if(nRes) |
817 | 0 | { |
818 | 0 | ErrorHandler::HandleError(nRes); |
819 | 0 | m_aEditWin->SetReadonly(true); |
820 | 0 | } |
821 | 0 | aMedium.Commit(); |
822 | 0 | SvStream* pInStream = aMedium.GetInStream(); |
823 | 0 | pInStream->Seek(0); |
824 | 0 | pInStream->SetStreamEncoding( eDestEnc ); |
825 | |
|
826 | 0 | m_aEditWin->Read(*pInStream); |
827 | 0 | } |
828 | 0 | } |
829 | 0 | m_aEditWin->ClearModifyFlag(); |
830 | |
|
831 | 0 | m_eLoadEncoding = eDestEnc; |
832 | |
|
833 | 0 | if(bDocModified) |
834 | 0 | pDocShell->SetModified();// The flag will be reset in between times. |
835 | | // Disable AutoLoad |
836 | 0 | pDocShell->SetAutoLoad(INetURLObject(), 0, false); |
837 | | assert(dynamic_cast<SwWebDocShell*>( pDocShell) && "Why no WebDocShell?" ); |
838 | 0 | sal_uInt16 nLine = static_cast<SwWebDocShell*>(pDocShell)->GetSourcePara(); |
839 | 0 | m_aEditWin->SetStartLine(nLine); |
840 | 0 | m_aEditWin->GetTextEngine()->ResetUndo(); |
841 | 0 | m_aEditWin->GetOutWin()->GrabFocus(); |
842 | 0 | } |
843 | | |
844 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |