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