Line data Source code
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 <comphelper/string.hxx>
21 : #include <hintids.hxx>
22 :
23 : #include <doc.hxx>
24 : #include <osl/thread.h>
25 : #include <vcl/help.hxx>
26 : #include <svl/stritem.hxx>
27 : #include <unotools/securityoptions.hxx>
28 : #include <tools/urlobj.hxx>
29 : #include <txtrfmrk.hxx>
30 : #include <fmtrfmrk.hxx>
31 : #include <editeng/flditem.hxx>
32 : #include <svl/urihelper.hxx>
33 : #include <svx/svdotext.hxx>
34 : #include <editeng/outliner.hxx>
35 : #include <svl/itemiter.hxx>
36 : #include <svx/svdview.hxx>
37 : #include <svx/svdpagv.hxx>
38 : #include <swmodule.hxx>
39 : #include <modcfg.hxx>
40 : #include <view.hxx>
41 : #include <wrtsh.hxx>
42 : #include <docsh.hxx>
43 : #include <edtwin.hxx>
44 : #include <dpage.hxx>
45 : #include <shellres.hxx>
46 : #include <docufld.hxx>
47 : #include <dbfld.hxx>
48 : #include <reffld.hxx>
49 : #include <cellatr.hxx>
50 : #include <shdwcrsr.hxx>
51 : #include <fmtcol.hxx>
52 : #include <charfmt.hxx>
53 : #include <fmtftn.hxx>
54 : #include <redline.hxx>
55 : #include <tox.hxx>
56 : #include <txttxmrk.hxx>
57 : #include <uitool.hxx>
58 : #include <viewopt.hxx>
59 : #include <docvw.hrc>
60 : #include <utlui.hrc>
61 :
62 : #include <PostItMgr.hxx>
63 : #include <fmtfld.hxx>
64 :
65 : #include <IDocumentMarkAccess.hxx>
66 : #include <ndtxt.hxx>
67 :
68 0 : static OUString lcl_GetRedlineHelp( const SwRangeRedline& rRedl, bool bBalloon )
69 : {
70 0 : sal_uInt16 nResId = 0;
71 0 : switch( rRedl.GetType() )
72 : {
73 0 : case nsRedlineType_t::REDLINE_INSERT: nResId = STR_REDLINE_INSERT; break;
74 0 : case nsRedlineType_t::REDLINE_DELETE: nResId = STR_REDLINE_DELETE; break;
75 0 : case nsRedlineType_t::REDLINE_FORMAT: nResId = STR_REDLINE_FORMAT; break;
76 0 : case nsRedlineType_t::REDLINE_TABLE: nResId = STR_REDLINE_TABLE; break;
77 0 : case nsRedlineType_t::REDLINE_FMTCOLL: nResId = STR_REDLINE_FMTCOLL; break;
78 : }
79 :
80 0 : OUStringBuffer sBuf;
81 0 : if( nResId )
82 : {
83 0 : sBuf.append(SW_RESSTR(nResId));
84 0 : sBuf.append(": ");
85 0 : sBuf.append(rRedl.GetAuthorString());
86 0 : sBuf.append(" - ");
87 0 : sBuf.append(GetAppLangDateTimeString(rRedl.GetTimeStamp()));
88 0 : if( bBalloon && !rRedl.GetComment().isEmpty() )
89 0 : sBuf.append('\n').append(rRedl.GetComment());
90 : }
91 0 : return sBuf.makeStringAndClear();
92 : }
93 :
94 0 : OUString SwEditWin::ClipLongToolTip(const OUString& rText)
95 : {
96 0 : OUString sDisplayText(rText);
97 0 : long nTextWidth = GetTextWidth(sDisplayText);
98 0 : long nMaxWidth = GetDesktopRectPixel().GetWidth() * 2 / 3;
99 0 : nMaxWidth = PixelToLogic(Size(nMaxWidth, 0)).Width();
100 0 : if (nTextWidth > nMaxWidth)
101 0 : sDisplayText = GetEllipsisString(sDisplayText, nMaxWidth, DrawTextFlags::CenterEllipsis);
102 0 : return sDisplayText;
103 : }
104 :
105 0 : void SwEditWin::RequestHelp(const HelpEvent &rEvt)
106 : {
107 0 : SwWrtShell &rSh = m_rView.GetWrtShell();
108 0 : bool bQuickBalloon = bool(rEvt.GetMode() & ( HelpEventMode::QUICK | HelpEventMode::BALLOON ));
109 0 : if(bQuickBalloon && !rSh.GetViewOptions()->IsShowContentTips())
110 0 : return;
111 0 : bool bContinue = true;
112 0 : SET_CURR_SHELL(&rSh);
113 0 : OUString sText;
114 0 : Point aPos( PixelToLogic( ScreenToOutputPixel( rEvt.GetMousePosPixel() ) ));
115 0 : bool bBalloon = bool(rEvt.GetMode() & HelpEventMode::BALLOON);
116 :
117 0 : SdrView *pSdrView = rSh.GetDrawView();
118 :
119 0 : if( bQuickBalloon )
120 : {
121 0 : if( pSdrView )
122 : {
123 0 : SdrPageView* pPV = pSdrView->GetSdrPageView();
124 0 : SwDPage* pPage = pPV ? static_cast<SwDPage*>(pPV->GetPage()) : 0;
125 0 : bContinue = pPage && pPage->RequestHelp(this, pSdrView, rEvt);
126 : }
127 : }
128 :
129 0 : if( bContinue && bQuickBalloon)
130 : {
131 0 : SwRect aFieldRect;
132 : SwContentAtPos aContentAtPos( SwContentAtPos::SW_FIELD |
133 : SwContentAtPos::SW_INETATTR |
134 : SwContentAtPos::SW_FTN |
135 : SwContentAtPos::SW_REDLINE |
136 : SwContentAtPos::SW_TOXMARK |
137 : SwContentAtPos::SW_REFMARK |
138 : SwContentAtPos::SW_SMARTTAG |
139 : #ifdef DBG_UTIL
140 : SwContentAtPos::SW_TABLEBOXVALUE |
141 : ( bBalloon ? SwContentAtPos::SW_CURR_ATTRS : 0) |
142 : #endif
143 0 : SwContentAtPos::SW_TABLEBOXFML );
144 :
145 0 : if( rSh.GetContentAtPos( aPos, aContentAtPos, false, &aFieldRect ) )
146 : {
147 0 : QuickHelpFlags nStyle = QuickHelpFlags::NONE; // style of quick help
148 0 : switch( aContentAtPos.eContentAtPos )
149 : {
150 : case SwContentAtPos::SW_TABLEBOXFML:
151 0 : sText = "= ";
152 0 : sText += static_cast<const SwTableBoxFormula*>(aContentAtPos.aFnd.pAttr)->GetFormula();
153 0 : break;
154 : #ifdef DBG_UTIL
155 : case SwContentAtPos::SW_TABLEBOXVALUE:
156 : {
157 : sText = OStringToOUString(OString::number(
158 : static_cast<const SwTableBoxValue*>(aContentAtPos.aFnd.pAttr)->GetValue()),
159 : osl_getThreadTextEncoding());
160 : }
161 : break;
162 : case SwContentAtPos::SW_CURR_ATTRS:
163 : sText = aContentAtPos.sStr;
164 : break;
165 : #endif
166 :
167 : case SwContentAtPos::SW_INETATTR:
168 : {
169 0 : sText = static_cast<const SfxStringItem*>(aContentAtPos.aFnd.pAttr)->GetValue();
170 0 : sText = URIHelper::removePassword( sText,
171 : INetURLObject::WAS_ENCODED,
172 0 : INetURLObject::DECODE_UNAMBIGUOUS);
173 : //#i63832# remove the link target type
174 0 : sal_Int32 nFound = sText.indexOf(cMarkSeparator);
175 0 : if( nFound != -1 && (++nFound) < sText.getLength() )
176 : {
177 0 : OUString sSuffix( sText.copy(nFound) );
178 0 : if( sSuffix == "table" ||
179 0 : sSuffix == "frame" ||
180 0 : sSuffix == "region" ||
181 0 : sSuffix == "outline" ||
182 0 : sSuffix == "text" ||
183 0 : sSuffix == "graphic" ||
184 0 : sSuffix == "ole" )
185 0 : sText = sText.copy( 0, nFound - 1);
186 : }
187 : // #i104300#
188 : // special handling if target is a cross-reference bookmark
189 : {
190 0 : OUString sTmpSearchStr = sText.copy( 1 );
191 : IDocumentMarkAccess* const pMarkAccess =
192 0 : rSh.getIDocumentMarkAccess();
193 : IDocumentMarkAccess::const_iterator_t ppBkmk =
194 0 : pMarkAccess->findBookmark( sTmpSearchStr );
195 0 : if ( ppBkmk != pMarkAccess->getBookmarksEnd() &&
196 0 : IDocumentMarkAccess::GetType( *(ppBkmk->get()) )
197 : == IDocumentMarkAccess::MarkType::CROSSREF_HEADING_BOOKMARK )
198 : {
199 0 : SwTextNode* pTextNode = ppBkmk->get()->GetMarkStart().nNode.GetNode().GetTextNode();
200 0 : if ( pTextNode )
201 : {
202 0 : sText = pTextNode->GetExpandText( 0, pTextNode->Len(), true, true );
203 :
204 0 : if( !sText.isEmpty() )
205 : {
206 0 : OUStringBuffer sTmp(comphelper::string::remove(sText, 0xad));
207 0 : for (sal_Int32 i = 0; i < sTmp.getLength(); ++i)
208 : {
209 0 : if (sTmp[i] < 0x20)
210 0 : sTmp[i] = 0x20;
211 0 : else if (sTmp[i] == 0x2011)
212 0 : sTmp[i] = '-';
213 : }
214 0 : sText = sTmp.makeStringAndClear();
215 : }
216 : }
217 0 : }
218 : }
219 : // #i80029#
220 0 : bool bExecHyperlinks = m_rView.GetDocShell()->IsReadOnly();
221 0 : if ( !bExecHyperlinks )
222 : {
223 0 : SvtSecurityOptions aSecOpts;
224 0 : bExecHyperlinks = !aSecOpts.IsOptionSet( SvtSecurityOptions::E_CTRLCLICK_HYPERLINK );
225 :
226 0 : sText = ": " + sText;
227 0 : if ( !bExecHyperlinks )
228 0 : sText = SwViewShell::GetShellRes()->aLinkCtrlClick + sText;
229 : else
230 0 : sText = SwViewShell::GetShellRes()->aLinkClick + sText;
231 : }
232 0 : break;
233 : }
234 : case SwContentAtPos::SW_SMARTTAG:
235 : {
236 0 : vcl::KeyCode aCode( KEY_SPACE );
237 0 : vcl::KeyCode aModifiedCode( KEY_SPACE, KEY_MOD1 );
238 0 : OUString aModStr( aModifiedCode.GetName() );
239 0 : aModStr = aModStr.replaceFirst(aCode.GetName(), OUString());
240 0 : aModStr = aModStr.replaceAll("+", OUString());
241 0 : sText = SW_RESSTR(STR_SMARTTAG_CLICK).replaceAll("%s", aModStr);
242 : }
243 0 : break;
244 :
245 : case SwContentAtPos::SW_FTN:
246 0 : if( aContentAtPos.pFndTextAttr && aContentAtPos.aFnd.pAttr )
247 : {
248 0 : const SwFormatFootnote* pFootnote = static_cast<const SwFormatFootnote*>(aContentAtPos.aFnd.pAttr);
249 0 : OUString sTmp;
250 0 : pFootnote->GetFootnoteText( sTmp );
251 0 : sText = SW_RESSTR( pFootnote->IsEndNote()
252 0 : ? STR_ENDNOTE : STR_FTNNOTE ) + sTmp;
253 0 : bBalloon = true;
254 0 : if( aContentAtPos.IsInRTLText() )
255 0 : nStyle |= QuickHelpFlags::BiDiRtl;
256 : }
257 0 : break;
258 :
259 : case SwContentAtPos::SW_REDLINE:
260 0 : sText = lcl_GetRedlineHelp(*aContentAtPos.aFnd.pRedl, bBalloon);
261 0 : break;
262 :
263 : case SwContentAtPos::SW_TOXMARK:
264 0 : sText = aContentAtPos.sStr;
265 0 : if( !sText.isEmpty() && aContentAtPos.pFndTextAttr )
266 : {
267 : const SwTOXType* pTType = aContentAtPos.pFndTextAttr->
268 0 : GetTOXMark().GetTOXType();
269 0 : if( pTType && !pTType->GetTypeName().isEmpty() )
270 : {
271 0 : sText = ": " + sText;
272 0 : sText = pTType->GetTypeName() + sText;
273 : }
274 : }
275 0 : break;
276 : case SwContentAtPos::SW_REFMARK:
277 0 : if(aContentAtPos.aFnd.pAttr)
278 : {
279 0 : sText = SW_RESSTR(STR_CONTENT_TYPE_SINGLE_REFERENCE);
280 0 : sText += ": ";
281 0 : sText += static_cast<const SwFormatRefMark*>(aContentAtPos.aFnd.pAttr)->GetRefName();
282 : }
283 0 : break;
284 :
285 : default:
286 : {
287 0 : SwModuleOptions* pModOpt = SW_MOD()->GetModuleConfig();
288 0 : if(!pModOpt->IsHideFieldTips())
289 : {
290 0 : const SwField* pField = aContentAtPos.aFnd.pField;
291 0 : switch( pField->Which() )
292 : {
293 : case RES_SETEXPFLD:
294 : case RES_TABLEFLD:
295 : case RES_GETEXPFLD:
296 : {
297 0 : sal_uInt16 nOldSubType = pField->GetSubType();
298 0 : const_cast<SwField*>(pField)->SetSubType(nsSwExtendedSubType::SUB_CMD);
299 0 : sText = pField->ExpandField(true);
300 0 : const_cast<SwField*>(pField)->SetSubType(nOldSubType);
301 : }
302 0 : break;
303 :
304 : case RES_POSTITFLD:
305 : {
306 0 : break;
307 : }
308 : case RES_INPUTFLD: // BubbleHelp, because the suggestion could be quite long
309 0 : bBalloon = true;
310 : /* no break */
311 : case RES_JUMPEDITFLD:
312 0 : sText = pField->GetPar2();
313 0 : break;
314 :
315 : case RES_DBFLD:
316 0 : sText = pField->GetFieldName();
317 0 : break;
318 :
319 : case RES_USERFLD:
320 : case RES_HIDDENTXTFLD:
321 0 : sText = pField->GetPar1();
322 0 : break;
323 :
324 : case RES_DOCSTATFLD:
325 0 : break;
326 :
327 : case RES_MACROFLD:
328 0 : sText = static_cast<const SwMacroField*>(pField)->GetMacro();
329 0 : break;
330 :
331 : case RES_GETREFFLD:
332 : {
333 : // #i85090#
334 0 : const SwGetRefField* pRefField( dynamic_cast<const SwGetRefField*>(pField) );
335 : OSL_ENSURE( pRefField,
336 : "<SwEditWin::RequestHelp(..)> - unexpected type of <pField>" );
337 0 : if ( pRefField )
338 : {
339 0 : if ( pRefField->IsRefToHeadingCrossRefBookmark() ||
340 0 : pRefField->IsRefToNumItemCrossRefBookmark() )
341 : {
342 0 : sText = pRefField->GetExpandedTextOfReferencedTextNode();
343 0 : if ( sText.getLength() > 80 )
344 : {
345 0 : sText = sText.copy(0, 80) + "...";
346 : }
347 : }
348 : else
349 : {
350 0 : sText = static_cast<const SwGetRefField*>(pField)->GetSetRefName();
351 : }
352 : }
353 : }
354 0 : break;
355 : }
356 : }
357 :
358 0 : if( sText.isEmpty() )
359 : {
360 0 : aContentAtPos.eContentAtPos = SwContentAtPos::SW_REDLINE;
361 0 : if( rSh.GetContentAtPos( aPos, aContentAtPos, false, &aFieldRect ) )
362 0 : sText = lcl_GetRedlineHelp(*aContentAtPos.aFnd.pRedl, bBalloon);
363 : }
364 : }
365 : }
366 0 : if (!sText.isEmpty())
367 : {
368 0 : if( bBalloon )
369 0 : Help::ShowBalloon( this, rEvt.GetMousePosPixel(), sText );
370 : else
371 : {
372 : // the show the help
373 0 : Rectangle aRect( aFieldRect.SVRect() );
374 0 : Point aPt( OutputToScreenPixel( LogicToPixel( aRect.TopLeft() )));
375 0 : aRect.Left() = aPt.X();
376 0 : aRect.Top() = aPt.Y();
377 0 : aPt = OutputToScreenPixel( LogicToPixel( aRect.BottomRight() ));
378 0 : aRect.Right() = aPt.X();
379 0 : aRect.Bottom() = aPt.Y();
380 0 : OUString sDisplayText(ClipLongToolTip(sText));
381 0 : Help::ShowQuickHelp(this, aRect, sDisplayText, nStyle);
382 : }
383 : }
384 :
385 0 : bContinue = false;
386 : }
387 0 : if( bContinue )
388 : {
389 0 : SwTab nTabCols = rSh.WhichMouseTabCol(aPos);
390 0 : sal_uInt16 nTabRes = 0;
391 0 : switch(nTabCols)
392 : {
393 : case SwTab::COL_HORI:
394 : case SwTab::COL_VERT:
395 0 : nTabRes = STR_TABLE_COL_ADJUST;
396 0 : break;
397 : case SwTab::ROW_HORI:
398 : case SwTab::ROW_VERT:
399 0 : nTabRes = STR_TABLE_ROW_ADJUST;
400 0 : break;
401 : // #i32329# Enhanced table selection
402 : case SwTab::SEL_HORI:
403 : case SwTab::SEL_HORI_RTL:
404 : case SwTab::SEL_VERT:
405 0 : nTabRes = STR_TABLE_SELECT_ALL;
406 0 : break;
407 : case SwTab::ROWSEL_HORI:
408 : case SwTab::ROWSEL_HORI_RTL:
409 : case SwTab::ROWSEL_VERT:
410 0 : nTabRes = STR_TABLE_SELECT_ROW;
411 0 : break;
412 : case SwTab::COLSEL_HORI:
413 : case SwTab::COLSEL_VERT:
414 0 : nTabRes = STR_TABLE_SELECT_COL;
415 0 : break;
416 0 : case SwTab::COL_NONE: break; // prevent compiler warning
417 : }
418 0 : if(nTabRes)
419 : {
420 0 : sText = SW_RESSTR(nTabRes);
421 0 : Size aTextSize( GetTextWidth(sText), GetTextHeight());
422 0 : Rectangle aRect(rEvt.GetMousePosPixel(), aTextSize);
423 0 : OUString sDisplayText(ClipLongToolTip(sText));
424 0 : Help::ShowQuickHelp(this, aRect, sDisplayText);
425 : }
426 0 : bContinue = false;
427 0 : }
428 : }
429 :
430 0 : if( bContinue )
431 0 : Window::RequestHelp( rEvt );
432 : }
433 :
434 27195 : void SwEditWin::PrePaint(vcl::RenderContext& /*rRenderContext*/)
435 : {
436 27195 : SwWrtShell* pWrtShell = GetView().GetWrtShellPtr();
437 :
438 27195 : if(pWrtShell)
439 : {
440 27195 : pWrtShell->PrePaint();
441 : }
442 27195 : }
443 :
444 6024 : void SwEditWin::Paint(vcl::RenderContext& rRenderContext, const Rectangle& rRect)
445 : {
446 6024 : SwWrtShell* pWrtShell = GetView().GetWrtShellPtr();
447 6024 : if(!pWrtShell)
448 6024 : return;
449 6024 : bool bPaintShadowCrsr = false;
450 6024 : if( m_pShadCrsr )
451 : {
452 0 : Rectangle aRect( m_pShadCrsr->GetRect());
453 : // fully resides inside?
454 0 : if( rRect.IsInside( aRect ) )
455 : // dann aufheben
456 0 : delete m_pShadCrsr, m_pShadCrsr = 0;
457 0 : else if( rRect.IsOver( aRect ))
458 : {
459 : // resides somewhat above, then everything is clipped outside
460 : // and we have to make the "inner part" at the end of the
461 : // Paint visible again. Otherwise Paint errors occur!
462 0 : bPaintShadowCrsr = true;
463 : }
464 : }
465 :
466 12048 : if ( GetView().GetVisArea().GetWidth() <= 0 ||
467 6024 : GetView().GetVisArea().GetHeight() <= 0 )
468 0 : Invalidate( rRect );
469 : else
470 6024 : pWrtShell->Paint(rRenderContext, rRect);
471 :
472 6024 : if( bPaintShadowCrsr )
473 0 : m_pShadCrsr->Paint();
474 177 : }
475 :
476 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|