xref: /core/sd/source/ui/func/futext.cxx (revision 9090dc1f)
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 <futext.hxx>
21 #include <editeng/eeitem.hxx>
22 #include <svx/sdrpagewindow.hxx>
23 #include <svx/sdrpaintwindow.hxx>
24 #include <tools/urlobj.hxx>
25 #include <vcl/help.hxx>
26 #include <editeng/fhgtitem.hxx>
27 #include <svl/intitem.hxx>
28 #include <svl/stritem.hxx>
29 #include <svx/svdotext.hxx>
30 #include <editeng/flditem.hxx>
31 #include <svl/style.hxx>
32 #include <svx/svdpagv.hxx>
33 #include <svx/sdtmfitm.hxx>
34 #include <svx/sdtagitm.hxx>
35 #include <svx/sdtfsitm.hxx>
36 #include <sfx2/viewfrm.hxx>
37 #include <sfx2/dispatch.hxx>
38 #include <sfx2/bindings.hxx>
39 #include <sfx2/request.hxx>
40 #include <editeng/editeng.hxx>
41 #include <svx/svdoutl.hxx>
42 #include <svx/svxids.hrc>
43 #include <svx/sdr/overlay/overlaymanager.hxx>
44 #include <sfx2/docfile.hxx>
45 #include <editeng/outlobj.hxx>
46 #include <osl/diagnose.h>
47 
48 #include <editeng/frmdiritem.hxx>
49 
50 #include <svx/svdetc.hxx>
51 #include <editeng/editview.hxx>
52 
53 #include <sdresid.hxx>
54 #include <app.hrc>
55 
56 #include <ViewShell.hxx>
57 #include <ViewShellBase.hxx>
58 #include <View.hxx>
59 #include <Window.hxx>
60 #include <drawdoc.hxx>
61 #include <sdpage.hxx>
62 #include <FrameView.hxx>
63 #include <ToolBarManager.hxx>
64 #include <DrawDocShell.hxx>
65 #include <strings.hrc>
66 #include <pres.hxx>
67 
68 using namespace ::com::sun::star;
69 using namespace ::com::sun::star::uno;
70 using namespace ::com::sun::star::lang;
71 using namespace ::com::sun::star::linguistic2;
72 
73 namespace sd {
74 
75 const sal_uInt16 SidArray[] = {
76     SID_STYLE_FAMILY2,                //    5542
77     SID_STYLE_FAMILY5,                //    5545
78     SID_REDO,                         //    5700
79     SID_UNDO,                         //    5701
80     SID_CUT,                          //    5710
81     SID_COPY,                         //    5711
82     SID_ATTR_TABSTOP,                 //   10002
83     SID_ATTR_CHAR_FONT,               //   10007
84     SID_ATTR_CHAR_POSTURE,            //   10008
85     SID_ATTR_CHAR_WEIGHT,             //   10009
86     SID_ATTR_CHAR_SHADOWED,           //   10010
87     SID_ATTR_CHAR_STRIKEOUT,          //   10013
88     SID_ATTR_CHAR_UNDERLINE,          //   10014
89     SID_ATTR_CHAR_FONTHEIGHT,         //   10015
90     SID_ATTR_CHAR_COLOR,              //   10017
91     SID_ATTR_CHAR_KERNING,            //   10018
92     SID_ATTR_CHAR_CASEMAP,            //   10019
93     SID_ATTR_PARA_ADJUST_LEFT,        //   10028
94     SID_ATTR_PARA_ADJUST_RIGHT,       //   10029
95     SID_ATTR_PARA_ADJUST_CENTER,      //   10030
96     SID_ATTR_PARA_ADJUST_BLOCK,       //   10031
97     SID_ATTR_PARA_LINESPACE_10,       //   10034
98     SID_ATTR_PARA_LINESPACE_15,       //   10035
99     SID_ATTR_PARA_LINESPACE_20,       //   10036
100     SID_ATTR_PARA_ULSPACE,            //   10042
101     SID_ATTR_PARA_LRSPACE,            //   10043
102     SID_ATTR_TRANSFORM_POS_X,         //   10088
103     SID_ATTR_TRANSFORM_POS_Y,         //   10089
104     SID_ATTR_TRANSFORM_WIDTH,         //   10090
105     SID_ATTR_TRANSFORM_HEIGHT,        //   10091
106     SID_ATTR_TRANSFORM_ROT_X,         //   10093
107     SID_ATTR_TRANSFORM_ROT_Y,         //   10094
108     SID_ATTR_TRANSFORM_ANGLE,         //   10095 //Added
109     SID_OUTLINE_UP,                   //   10150
110     SID_OUTLINE_DOWN,                 //   10151
111     SID_OUTLINE_LEFT,                 //   10152
112     SID_OUTLINE_RIGHT,                //   10153
113     SID_ATTR_TRANSFORM_PROTECT_POS,   //   10236
114     SID_ATTR_TRANSFORM_PROTECT_SIZE,  //   10237 //Added
115     SID_FORMTEXT_STYLE,               //   10257
116     SID_SET_SUPER_SCRIPT,             //   10294
117     SID_SET_SUB_SCRIPT,               //   10295
118     SID_ATTR_TRANSFORM_AUTOWIDTH,     //   10310
119     SID_ATTR_TRANSFORM_AUTOHEIGHT,    //   10311 //Added
120     SID_HYPERLINK_GETLINK,            //   10361
121     SID_DEC_INDENT,                   //   10461
122     SID_INC_INDENT,                   //   10462
123     SID_CHARMAP,                      //   10503
124     SID_TEXTDIRECTION_LEFT_TO_RIGHT,  //   10907
125     SID_TEXTDIRECTION_TOP_TO_BOTTOM,  //   10908
126     SID_ATTR_PARA_LEFT_TO_RIGHT,      //   10950
127     SID_ATTR_PARA_RIGHT_TO_LEFT,      //   10951
128     SID_PARASPACE_INCREASE,           //   11145
129     SID_PARASPACE_DECREASE,           //   11146
130     FN_NUM_BULLET_ON,                 //   20138
131                             0 };
132 
133 
134 /**
135  * base class for text functions
136  */
137 FuText::FuText( ViewShell* pViewSh, ::sd::Window* pWin, ::sd::View* pView, SdDrawDocument* pDoc, SfxRequest& rReq )
138 : FuConstruct(pViewSh, pWin, pView, pDoc, rReq)
139 , bFirstObjCreated(false)
140 , bJustEndedEdit(false)
141 , rRequest (rReq)
142 {
143 }
144 
145 rtl::Reference<FuPoor> FuText::Create( ViewShell* pViewSh, ::sd::Window* pWin, ::sd::View* pView, SdDrawDocument* pDoc, SfxRequest& rReq )
146 {
147     rtl::Reference<FuPoor> xFunc( new FuText( pViewSh, pWin, pView, pDoc, rReq ) );
148     return xFunc;
149 }
150 
151 void FuText::disposing()
152 {
153     if(mpView)
154     {
155         if(mpView->SdrEndTextEdit() == SdrEndTextEditKind::Deleted)
156             mxTextObj.reset(nullptr);
157 
158         // reset the RequestHandler of the used Outliner to the handler of the document
159         ::Outliner* pOutliner = mpView->GetTextEditOutliner();
160 
161         if (pOutliner)
162             pOutliner->SetStyleSheetPool(static_cast<SfxStyleSheetPool*>(mpDoc->GetStyleSheetPool()));
163     }
164 }
165 
166 /*************************************************************************
167 |*
168 |* Execute functionality of this class:
169 |*
170 |* #71422: Start the functionality of this class in this method
171 |* and not in the ctor.
172 |* If you construct an object of this class and you put the
173 |* address of this object to pFuActual you've got a problem,
174 |* because some methods inside DoExecute use the pFuActual-Pointer.
175 |* If the code inside DoExecute is executed inside the ctor,
176 |* the value of pFuActual is not right. And the value will not
177 |* be right until the ctor finished !!!
178 |*
179 \************************************************************************/
180 void FuText::DoExecute( SfxRequest& )
181 {
182     mpViewShell->GetViewShellBase().GetToolBarManager()->SetToolBarShell(
183         ToolBarManager::ToolBarGroup::Function,
184         ToolbarId::Draw_Text_Toolbox_Sd);
185 
186     mpView->SetCurrentObj(OBJ_TEXT);
187     mpView->SetEditMode(SdrViewEditMode::Edit);
188 
189     MouseEvent aMEvt(mpWindow->GetPointerPosPixel());
190 
191     if (nSlotId == SID_TEXTEDIT)
192     {
193         // Try to select an object
194         SdrPageView* pPV = mpView->GetSdrPageView();
195         SdrViewEvent aVEvt;
196         mpView->PickAnything(aMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt);
197         mpView->MarkObj(aVEvt.pRootObj, pPV);
198 
199         mxTextObj.reset( dynamic_cast< SdrTextObj* >( aVEvt.pObj ) );
200     }
201     else if (mpView->AreObjectsMarked())
202     {
203         const SdrMarkList& rMarkList = mpView->GetMarkedObjectList();
204 
205         if (rMarkList.GetMarkCount() == 1)
206         {
207             SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
208             mxTextObj.reset( dynamic_cast< SdrTextObj* >( pObj ) );
209         }
210     }
211 
212     // check for table
213     if (mpView->AreObjectsMarked())
214     {
215         const SdrMarkList& rMarkList = mpView->GetMarkedObjectList();
216 
217         if (rMarkList.GetMarkCount() == 1)
218         {
219             SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
220             if( pObj && (pObj->GetObjInventor() == SdrInventor::Default ) && (pObj->GetObjIdentifier() == OBJ_TABLE) )
221             {
222                 mpViewShell->GetViewShellBase().GetToolBarManager()->AddToolBarShell(ToolBarManager::ToolBarGroup::Function, ToolbarId::Draw_Table_Toolbox);
223             }
224         }
225     }
226 
227     bool bQuickDrag = true;
228 
229     const SfxItemSet* pArgs = rRequest.GetArgs();
230 
231     if (pArgs
232 
233         // test for type before using
234         && SID_TEXTEDIT == nSlotId
235         && SfxItemState::SET == pArgs->GetItemState(SID_TEXTEDIT)
236 
237         && static_cast<const SfxUInt16Item&>(pArgs->Get(SID_TEXTEDIT)).GetValue() == 2)
238     {
239         // Selection by doubleclick -> don't allow QuickDrag
240         bQuickDrag = false;
241     }
242 
243     SetInEditMode(aMEvt, bQuickDrag);
244 }
245 
246 bool FuText::MouseButtonDown(const MouseEvent& rMEvt)
247 {
248     bMBDown = true;
249     bJustEndedEdit = false;
250 
251     bool bReturn = FuDraw::MouseButtonDown(rMEvt);
252 
253     SdrViewEvent aVEvt;
254     SdrHitKind eHit = mpView->PickAnything(rMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt);
255 
256     // handle URL also during the text editing
257     if (rMEvt.GetClicks() == 1 && rMEvt.IsLeft() && rMEvt.IsMod1())
258     {
259         OutlinerView* pOLV = mpView->GetTextEditOutlinerView();
260 
261         if (mxTextObj.is() && pOLV && pOLV->GetFieldUnderMousePointer())
262         {
263             const SvxFieldItem* pFieldItem = pOLV->GetFieldUnderMousePointer();
264             if (pFieldItem)
265             {
266                 const SvxFieldData* pField = pFieldItem->GetField();
267 
268                 if (auto pURLField = dynamic_cast< const SvxURLField *>( pField ))
269                 {
270                     eHit = SdrHitKind::MarkedObject;
271                     aVEvt.eEvent = SdrEventKind::ExecuteUrl;
272                     aVEvt.pURLField = pURLField;
273                 }
274             }
275         }
276     }
277 
278     if (eHit == SdrHitKind::TextEdit)
279     {
280         // hit text -> SdrView handles event
281         if (mpView->MouseButtonDown(rMEvt, mpWindow->GetOutDev()))
282             return true;
283     }
284 
285     if (rMEvt.GetClicks() == 1)
286     {
287         if (mpView->IsTextEdit() && eHit != SdrHitKind::MarkedObject && eHit != SdrHitKind::Handle)
288         {
289             // finish text input
290             if(mpView->SdrEndTextEdit() == SdrEndTextEditKind::Deleted)
291             {
292                 /* Bugfix from MBA: during a double click onto the unused? area
293                    in text mode, we get with the second click eHit =
294                    SdrHitKind::TextEditObj since it goes to the TextObject which was
295                    created with the first click. But this is removed by
296                    SdrEndTextEdit since it is empty. But it is still in the mark
297                    list. The call MarkObj further below accesses then the dead
298                    object. As a simple fix, we determine eHit after
299                    SdrEndTextEdit again, this returns then SdrHitKind::NONE. */
300                 mxTextObj.reset(nullptr);
301                 eHit = mpView->PickAnything(rMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt);
302             }
303 
304             mpView->SetCurrentObj(OBJ_TEXT);
305             mpView->SetEditMode(SdrViewEditMode::Edit);
306         }
307 
308         if (rMEvt.IsLeft() || rMEvt.IsRight())
309         {
310             mpWindow->CaptureMouse();
311             SdrPageView* pPV = mpView->GetSdrPageView();
312 
313             if (eHit == SdrHitKind::TextEdit)
314             {
315                 SetInEditMode(rMEvt, false);
316             }
317             else
318             {
319                 // Don't remark table when clicking in it, mark change triggers a lot of updating
320                 bool bMarkChanges = true;
321                 rtl::Reference< sdr::SelectionController > xSelectionController(mpView->getSelectionController());
322                 if (eHit == SdrHitKind::TextEditObj && xSelectionController.is())
323                 {
324                     const SdrMarkList& rMarkList = mpView->GetMarkedObjectList();
325                     if (rMarkList.GetMarkCount() == 1 && rMarkList.GetMark(0)->GetMarkedSdrObj() == aVEvt.pRootObj)
326                         bMarkChanges = false;
327                 }
328 
329                 if (eHit != SdrHitKind::Handle)
330                 {
331                     // deselect selection
332                     if (!rMEvt.IsShift() && eHit == SdrHitKind::TextEditObj)
333                     {
334                         if(bMarkChanges)
335                         {
336                             mpView->UnmarkAll();
337                             mpView->SetDragMode(SdrDragMode::Move);
338                         }
339                     }
340                 }
341 
342                 if ( aVEvt.eEvent == SdrEventKind::ExecuteUrl                   ||
343                      eHit == SdrHitKind::Handle                                 ||
344                      eHit == SdrHitKind::MarkedObject                           ||
345                      eHit == SdrHitKind::TextEditObj                            ||
346                      ( eHit == SdrHitKind::UnmarkedObject && bFirstObjCreated &&
347                        !bPermanent ) )
348                 {
349                     // Handle, hit marked or unmarked object
350                     if (eHit == SdrHitKind::TextEditObj)
351                     {
352                         /* hit text of unmarked object:
353                            select object and set to EditMode */
354                         if (bMarkChanges)
355                             mpView->MarkObj(aVEvt.pRootObj, pPV);
356 
357                         if (auto pSdrTextObj = dynamic_cast<SdrTextObj *>( aVEvt.pObj ))
358                         {
359                             mxTextObj.reset( pSdrTextObj );
360                         }
361 
362                         SetInEditMode(rMEvt, true);
363                     }
364                     else if (aVEvt.eEvent == SdrEventKind::ExecuteUrl && !rMEvt.IsMod2())
365                     {
366                         // execute URL
367                         mpWindow->ReleaseMouse();
368                         SfxStringItem aStrItem(SID_FILE_NAME, aVEvt.pURLField->GetURL());
369                         SfxStringItem aReferer(SID_REFERER, mpDocSh->GetMedium()->GetName());
370                         SfxBoolItem aBrowseItem( SID_BROWSE, true );
371                         SfxViewFrame* pFrame = mpViewShell->GetViewFrame();
372                         mpWindow->ReleaseMouse();
373 
374                         if (rMEvt.IsMod1())
375                         {
376                             // open in new frame
377                             pFrame->GetDispatcher()->ExecuteList(SID_OPENDOC,
378                                 SfxCallMode::ASYNCHRON | SfxCallMode::RECORD,
379                                 { &aStrItem, &aBrowseItem, &aReferer });
380                         }
381                         else
382                         {
383                             // open in current frame
384                             SfxFrameItem aFrameItem(SID_DOCFRAME, pFrame);
385                             pFrame->GetDispatcher()->ExecuteList(SID_OPENDOC,
386                                 SfxCallMode::ASYNCHRON | SfxCallMode::RECORD,
387                                 { &aStrItem, &aFrameItem, &aBrowseItem, &aReferer });
388                         }
389                     }
390                     else
391                     {
392                         // drag object or handle
393 
394                         // #i78748#
395                         // do the EndTextEdit first, it will delete the handles and force a
396                         // recreation. This will make aVEvt.pHdl to point to a deleted handle,
397                         // thus it is necessary to reset it and to get it again.
398 
399                         // #i112855#
400                         // cl: I'm not sure why we checked here also for mxTextObj->GetOutlinerParaObject
401                         // this caused SdrEndTextEdit() to be called also when not in text editing and
402                         // this does not make sense and caused troubles. (see issue 112855)
403 
404                         if( mpView->IsTextEdit() )
405                         {
406                             mpView->SdrEndTextEdit();
407                             bJustEndedEdit = true;
408 
409                             if(aVEvt.pHdl)
410                             {
411                                 // force new handle identification, the pointer will be dead here
412                                 // since SdrEndTextEdit has reset (deleted) the handles.
413                                 aVEvt.pHdl = nullptr;
414                                 mpView->PickAnything(rMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt);
415                             }
416                         }
417 
418                         if (!aVEvt.pHdl)
419                         {
420                             if( eHit == SdrHitKind::UnmarkedObject )
421                             {
422                                 if ( !rMEvt.IsShift() )
423                                     mpView->UnmarkAll();
424 
425                                 mpView->MarkObj(aVEvt.pRootObj, pPV);
426                             }
427 
428                             // Drag object
429                             bFirstMouseMove = true;
430                             aDragTimer.Start();
431                         }
432 
433                         if ( ! rMEvt.IsRight())
434                         {
435                             // we need to pick again since SdrEndTextEdit can rebuild the handles list
436                             eHit = mpView->PickAnything(rMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt);
437                             if( (eHit == SdrHitKind::Handle) || (eHit == SdrHitKind::MarkedObject) )
438                             {
439                                 sal_uInt16 nDrgLog = sal_uInt16 ( mpWindow->PixelToLogic(Size(DRGPIX,0)).Width() );
440                                 mpView->BegDragObj(aMDPos, nullptr, aVEvt.pHdl, nDrgLog);
441                             }
442                         }
443                         bReturn = true;
444                     }
445                 }
446                 else if ( nSlotId != SID_TEXTEDIT &&
447                           (bPermanent || !bFirstObjCreated) )
448                 {
449                     // create object
450                     mpView->SetCurrentObj(OBJ_TEXT);
451                     mpView->SetEditMode(SdrViewEditMode::Create);
452                     sal_uInt16 nDrgLog = sal_uInt16 ( mpWindow->PixelToLogic(Size(DRGPIX,0)).Width() );
453                     mpView->BegCreateObj(aMDPos, nullptr, nDrgLog);
454                 }
455                 else
456                 {
457                     // select
458                     if( !rMEvt.IsShift() )
459                         mpView->UnmarkAll();
460 
461                     mpView->BegMarkObj( aMDPos );
462                 }
463             }
464         }
465     }
466     else if ( rMEvt.GetClicks() == 2 && !mpView->IsTextEdit() )
467     {
468         MouseEvent aMEvt( mpWindow->GetPointerPosPixel() );
469         SetInEditMode( aMEvt, false );
470     }
471 
472     if (!bIsInDragMode)
473     {
474         ForcePointer(&rMEvt);
475         mpViewShell->GetViewFrame()->GetBindings().Invalidate(SidArray);
476     }
477 
478     return bReturn;
479 }
480 
481 bool FuText::MouseMove(const MouseEvent& rMEvt)
482 {
483     bool bReturn = FuDraw::MouseMove(rMEvt);
484 
485     if (aDragTimer.IsActive() )
486     {
487         if( bFirstMouseMove )
488             bFirstMouseMove = false;
489         else
490             aDragTimer.Stop();
491     }
492 
493     if (!bReturn && mpView->IsAction() && !mpDocSh->IsReadOnly())
494     {
495         Point aPix(rMEvt.GetPosPixel());
496         Point aPnt(mpWindow->PixelToLogic(aPix));
497 
498         ForceScroll(aPix);
499         mpView->MovAction(aPnt);
500     }
501 
502     ForcePointer(&rMEvt);
503 
504     return bReturn;
505 }
506 
507 void FuText::ImpSetAttributesForNewTextObject(SdrTextObj* pTxtObj)
508 {
509     if(mpDoc->GetDocumentType() == DocumentType::Impress)
510     {
511         if( nSlotId == SID_ATTR_CHAR )
512         {
513             /* Create Impress text object (rescales to line height)
514                We get the correct height during the subsequent creation of the
515                object, otherwise we draw too much */
516             SfxItemSet aSet(mpViewShell->GetPool());
517             aSet.Put(makeSdrTextMinFrameHeightItem(0));
518             aSet.Put(makeSdrTextAutoGrowWidthItem(false));
519             aSet.Put(makeSdrTextAutoGrowHeightItem(true));
520             pTxtObj->SetMergedItemSet(aSet);
521             pTxtObj->AdjustTextFrameWidthAndHeight();
522             aSet.Put(makeSdrTextMaxFrameHeightItem(pTxtObj->GetLogicRect().GetSize().Height()));
523             pTxtObj->SetMergedItemSet(aSet);
524             const SfxViewShell* pCurrentViewShell = SfxViewShell::Current();
525             if (pCurrentViewShell && (pCurrentViewShell->isLOKMobilePhone() || pCurrentViewShell->isLOKTablet()))
526                 pTxtObj->SetText(SdResId(STR_PRESOBJ_TEXT_EDIT_MOBILE));
527         }
528         else if( nSlotId == SID_ATTR_CHAR_VERTICAL )
529         {
530             SfxItemSet aSet(mpViewShell->GetPool());
531             aSet.Put(makeSdrTextMinFrameWidthItem(0));
532             aSet.Put(makeSdrTextAutoGrowWidthItem(true));
533             aSet.Put(makeSdrTextAutoGrowHeightItem(false));
534 
535             // Needs to be set since default is SDRTEXTHORZADJUST_BLOCK
536             aSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_RIGHT));
537             pTxtObj->SetMergedItemSet(aSet);
538             pTxtObj->AdjustTextFrameWidthAndHeight();
539             aSet.Put(makeSdrTextMaxFrameWidthItem(pTxtObj->GetLogicRect().GetSize().Width()));
540             pTxtObj->SetMergedItemSet(aSet);
541         }
542     }
543     else
544     {
545         if( nSlotId == SID_ATTR_CHAR_VERTICAL )
546         {
547             // draw text object, needs to be initialized when vertical text is used
548             SfxItemSet aSet(mpViewShell->GetPool());
549 
550             aSet.Put(makeSdrTextAutoGrowWidthItem(true));
551             aSet.Put(makeSdrTextAutoGrowHeightItem(false));
552 
553             // Set defaults for vertical click-n'drag text object, pool defaults are:
554             // SdrTextVertAdjustItem: SDRTEXTVERTADJUST_TOP
555             // SdrTextHorzAdjustItem: SDRTEXTHORZADJUST_BLOCK
556             // Analog to that:
557             aSet.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_BLOCK));
558             aSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_RIGHT));
559 
560             pTxtObj->SetMergedItemSet(aSet);
561         }
562     }
563 }
564 
565 void FuText::ImpSetAttributesFitToSize(SdrTextObj* pTxtObj)
566 {
567     // FitToSize (fit to frame)
568     SfxItemSet aSet(mpViewShell->GetPool(), svl::Items<SDRATTR_TEXT_AUTOGROWHEIGHT, SDRATTR_TEXT_AUTOGROWWIDTH>{});
569     aSet.Put(SdrTextFitToSizeTypeItem(drawing::TextFitToSizeType_PROPORTIONAL));
570     aSet.Put(makeSdrTextAutoGrowHeightItem(false));
571     aSet.Put(makeSdrTextAutoGrowWidthItem(false));
572     pTxtObj->SetMergedItemSet(aSet);
573     pTxtObj->AdjustTextFrameWidthAndHeight();
574 }
575 
576 void FuText::ImpSetAttributesFitToSizeVertical(SdrTextObj* pTxtObj)
577 {
578     SfxItemSet aSet(mpViewShell->GetPool(),
579         svl::Items<SDRATTR_TEXT_AUTOGROWHEIGHT, SDRATTR_TEXT_AUTOGROWWIDTH>{});
580     aSet.Put(SdrTextFitToSizeTypeItem(drawing::TextFitToSizeType_PROPORTIONAL));
581     aSet.Put(makeSdrTextAutoGrowHeightItem(false));
582     aSet.Put(makeSdrTextAutoGrowWidthItem(false));
583     pTxtObj->SetMergedItemSet(aSet);
584     pTxtObj->AdjustTextFrameWidthAndHeight();
585 }
586 
587 void FuText::ImpSetAttributesFitCommon(SdrTextObj* pTxtObj)
588 {
589     // Normal Textobject
590     if (mpDoc->GetDocumentType() != DocumentType::Impress)
591         return;
592 
593     if( nSlotId == SID_ATTR_CHAR )
594     {
595         // Impress text object (rescales to line height)
596         SfxItemSet aSet(mpViewShell->GetPool());
597         aSet.Put(makeSdrTextMinFrameHeightItem(0));
598         aSet.Put(makeSdrTextMaxFrameHeightItem(0));
599         aSet.Put(makeSdrTextAutoGrowHeightItem(true));
600         aSet.Put(makeSdrTextAutoGrowWidthItem(false));
601         pTxtObj->SetMergedItemSet(aSet);
602     }
603     else if( nSlotId == SID_ATTR_CHAR_VERTICAL )
604     {
605         SfxItemSet aSet(mpViewShell->GetPool());
606         aSet.Put(makeSdrTextMinFrameWidthItem(0));
607         aSet.Put(makeSdrTextMaxFrameWidthItem(0));
608         aSet.Put(makeSdrTextAutoGrowWidthItem(true));
609         aSet.Put(makeSdrTextAutoGrowHeightItem(false));
610         pTxtObj->SetMergedItemSet(aSet);
611     }
612 
613     pTxtObj->AdjustTextFrameWidthAndHeight();
614 }
615 
616 bool FuText::MouseButtonUp(const MouseEvent& rMEvt)
617 {
618     bool bReturn = false;
619     if (aDragTimer.IsActive())
620     {
621         aDragTimer.Stop();
622         bIsInDragMode = false;
623     }
624 
625     mpViewShell->GetViewFrame()->GetBindings().Invalidate( SidArray );
626 
627     Point aPnt( mpWindow->PixelToLogic( rMEvt.GetPosPixel() ) );
628 
629     if( (mpView && mpView->MouseButtonUp(rMEvt, mpWindow->GetOutDev())) || rMEvt.GetClicks() == 2 )
630         return true; // handle event from SdrView
631 
632     bool bEmptyTextObj = false;
633 
634     if (mxTextObj.is())
635     {
636         bool bReset = true;
637 
638         if (mpView)
639         {
640             const SdrMarkList& rMarkList = mpView->GetMarkedObjectList();
641 
642             if (rMarkList.GetMarkCount() == 1
643                 && ( rMarkList.GetMark(0)->GetMarkedSdrObj() == mxTextObj.get()) )
644             {
645                 if( mxTextObj.is() && !GetTextObj()->GetOutlinerParaObject() )
646                     bEmptyTextObj = true;
647                 else
648                     bFirstObjCreated = true;
649                 bReset = false;
650             }
651         }
652 
653         if (bReset)
654         {
655             mxTextObj.reset(nullptr);
656         }
657     }
658 
659     if( mpView && mpView->IsDragObj())
660     {
661         // object was moved
662         FrameView* pFrameView = mpViewShell->GetFrameView();
663         bool bDragWithCopy = (rMEvt.IsMod1() && pFrameView->IsDragWithCopy());
664 
665         if (bDragWithCopy)
666         {
667             bDragWithCopy = !mpView->IsPresObjSelected(false);
668         }
669 
670         mpView->SetDragWithCopy(bDragWithCopy);
671         mpView->EndDragObj( mpView->IsDragWithCopy() );
672         mpView->ForceMarkedToAnotherPage();
673         mpView->SetCurrentObj(OBJ_TEXT);
674 
675         sal_uInt16 nDrgLog = sal_uInt16 ( mpWindow->PixelToLogic(Size(DRGPIX,0)).Width() );
676 
677         if (bJustEndedEdit)
678         {
679             bJustEndedEdit = false;
680             FuPoor::cancel();
681         }
682         if ((rMEvt.GetClicks() != 2) &&
683             !rMEvt.IsShift() && !rMEvt.IsMod1() && !rMEvt.IsMod2() && !rMEvt.IsRight() &&
684             std::abs(aPnt.X() - aMDPos.X()) < nDrgLog &&
685             std::abs(aPnt.Y() - aMDPos.Y()) < nDrgLog)
686         {
687             /*************************************************************
688             * From text mode, you don't want to rotate immediately.
689             **************************************************************/
690             SdrPageView* pPV;
691             SdrObject* pObj = mpView->PickObj(aMDPos, mpView->getHitTolLog(), pPV, SdrSearchOptions::ALSOONMASTER | SdrSearchOptions::BEFOREMARK);
692             if (pObj && pPV->IsObjMarkable(pObj))
693             {
694                 mpView->UnmarkAllObj();
695                 mpView->MarkObj(pObj,pPV);
696                 return bReturn;
697             }
698         }
699     }
700     else if( mpView && mpView->IsCreateObj() && rMEvt.IsLeft())
701     {
702         // object was created
703         mxTextObj.reset( dynamic_cast< SdrTextObj* >( mpView->GetCreateObj() ) );
704 
705         if( mxTextObj.is() )
706         {
707             //AW outliner needs to be set to vertical when there is no
708             // outliner object up to now; also it needs to be set back to not
709             // vertical when there was a vertical one used last time.
710             OutlinerParaObject* pOPO = GetTextObj()->GetOutlinerParaObject();
711             SdrOutliner& rOutl(mxTextObj->getSdrModelFromSdrObject().GetDrawOutliner(GetTextObj()));
712             bool bVertical((pOPO && pOPO->IsVertical())
713                 || nSlotId == SID_ATTR_CHAR_VERTICAL
714                 || nSlotId == SID_TEXT_FITTOSIZE_VERTICAL);
715             rOutl.SetVertical(bVertical);
716 
717             // Before ImpSetAttributesForNewTextObject the vertical writing mode
718             // needs to be set at the object. This is done here at the OutlinerParaObject
719             // directly to not mirror the layout text items involved. These items will be set
720             // from ImpSetAttributesForNewTextObject and below.
721             OutlinerParaObject* pPara = GetTextObj()->GetOutlinerParaObject();
722 
723             if(!pPara)
724             {
725                 GetTextObj()->ForceOutlinerParaObject();
726                 pPara = GetTextObj()->GetOutlinerParaObject();
727             }
728 
729             if(pPara && bVertical != pPara->IsVertical())
730             {
731                 // set ParaObject orientation accordingly
732                 pPara->SetVertical(bVertical);
733             }
734 
735             ImpSetAttributesForNewTextObject(GetTextObj());
736         }
737 
738         if (!mpView->EndCreateObj(SdrCreateCmd::ForceEnd))
739         {
740             // it was not possible to create text object
741             mxTextObj.reset(nullptr);
742         }
743         else if (nSlotId == SID_TEXT_FITTOSIZE)
744         {
745             ImpSetAttributesFitToSize(GetTextObj());
746 
747             SetInEditMode(rMEvt, false);
748         }
749         else if ( nSlotId == SID_TEXT_FITTOSIZE_VERTICAL )
750         {
751             ImpSetAttributesFitToSizeVertical(GetTextObj());
752 
753             SetInEditMode(rMEvt, false);
754         }
755         else
756         {
757             ImpSetAttributesFitCommon(GetTextObj());
758 
759             // thereby the handles and the gray frame are correct
760             mpView->AdjustMarkHdl();
761             mpView->PickHandle(aPnt);
762             SetInEditMode(rMEvt, false);
763         }
764     }
765     else if ( mpView && mpView->IsAction())
766     {
767         mpView->EndAction();
768     }
769 
770     ForcePointer(&rMEvt);
771     mpWindow->ReleaseMouse();
772     sal_uInt16 nDrgLog1 = sal_uInt16 ( mpWindow->PixelToLogic(Size(DRGPIX,0)).Width() );
773 
774     if ( mpView && !mpView->AreObjectsMarked() &&
775          std::abs(aMDPos.X() - aPnt.X()) < nDrgLog1 &&
776          std::abs(aMDPos.Y() - aPnt.Y()) < nDrgLog1 &&
777          !rMEvt.IsShift() && !rMEvt.IsMod2() )
778     {
779         SdrPageView* pPV2 = mpView->GetSdrPageView();
780         SdrViewEvent aVEvt;
781         mpView->PickAnything(rMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt);
782         mpView->MarkObj(aVEvt.pRootObj, pPV2);
783     }
784 
785     if ( !mxTextObj.is() && mpView )
786     {
787         if ( ( (!bEmptyTextObj   &&  bPermanent) ||
788              (!bFirstObjCreated && !bPermanent) ) &&
789               !mpDocSh->IsReadOnly()               &&
790               nSlotId != SID_TEXTEDIT )
791         {
792             // text body (left-justified AutoGrow)
793             mpView->SetCurrentObj(OBJ_TEXT);
794             mpView->SetEditMode(SdrViewEditMode::Create);
795             sal_uInt16 nDrgLog = sal_uInt16 ( mpWindow->PixelToLogic(Size(DRGPIX,0)).Width() );
796             mpView->BegCreateObj(aMDPos, nullptr, nDrgLog);
797 
798             bool bSnapEnabled = mpView->IsSnapEnabled();
799 
800             if (bSnapEnabled)
801                 mpView->SetSnapEnabled(false);
802 
803             aPnt.AdjustX(nDrgLog + nDrgLog );
804             aPnt.AdjustY(nDrgLog + nDrgLog );
805             mpView->MovAction(aPnt);
806 
807             mxTextObj.reset( dynamic_cast< SdrTextObj* >( mpView->GetCreateObj() ) );
808 
809             if(mxTextObj.is())
810             {
811                 GetTextObj()->SetDisableAutoWidthOnDragging(true);
812             }
813 
814             if(!mpView->EndCreateObj(SdrCreateCmd::ForceEnd))
815             {
816                 mxTextObj.reset(nullptr);
817             }
818 
819             if(bSnapEnabled)
820                 mpView->SetSnapEnabled(bSnapEnabled);
821 
822             if(mxTextObj.is())
823             {
824                 SfxItemSet aSet(mpViewShell->GetPool());
825                 aSet.Put(makeSdrTextMinFrameHeightItem(0));
826                 aSet.Put(makeSdrTextMinFrameWidthItem(0));
827                 aSet.Put(makeSdrTextAutoGrowHeightItem(true));
828                 aSet.Put(makeSdrTextAutoGrowWidthItem(true));
829 
830                 if(nSlotId == SID_ATTR_CHAR_VERTICAL)
831                 {
832                     // Here, all items which need to be different from pool default need to be set
833                     // again on the newly created text object.
834                     // Since this is a simple click text object, it is first created, then SetVertical()
835                     // is used, then ImpSetAttributesForNewTextObject is called and then the object is
836                     // deleted again since not the minimum drag distance was travelled. Then, a new
837                     // click text object is created and thus all that stuff needs to be set again here.
838 
839                     // Before using the new object the vertical writing mode
840                     // needs to be set. This is done here at the OutlinerParaObject
841                     // directly to not mirror the layout text items involved. These items will be set
842                     // below.
843                     OutlinerParaObject* pPara = GetTextObj()->GetOutlinerParaObject();
844 
845                     if(!pPara)
846                     {
847                         GetTextObj()->ForceOutlinerParaObject();
848                         pPara = GetTextObj()->GetOutlinerParaObject();
849                     }
850 
851                     if(pPara && !pPara->IsVertical())
852                     {
853                         // set ParaObject orientation accordingly
854                         pPara->SetVertical(true);
855                     }
856 
857                     aSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_RIGHT));
858 
859                     // Analog to the else case below, for vertical simple click texts
860                     // one of the default set items from ImpSetAttributesForNewTextObject
861                     // needs to be adapted to non-block mode.
862                     const SfxItemSet& rSet = mpView->GetDefaultAttr();
863                     SvxFrameDirection eDirection = rSet.Get(EE_PARA_WRITINGDIR).GetValue();
864 
865                     if(SvxFrameDirection::Horizontal_RL_TB == eDirection || SvxFrameDirection::Vertical_RL_TB == eDirection)
866                     {
867                         aSet.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_BOTTOM));
868                     }
869                     else
870                     {
871                         aSet.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_TOP));
872                     }
873                 }
874                 else
875                 {
876                     // This is for Format/Page settings. Since this also leads
877                     // to the object defaults to be changed, i think this code can be
878                     // removed. CL. wanted to take a look before adding this.
879 
880                     // Look in the object defaults if left-to-right is wanted. If
881                     // yes, set text anchoring to right to let the box grow to left.
882                     const SfxItemSet& rSet = mpView->GetDefaultAttr();
883                     SvxFrameDirection eDirection = rSet.Get(EE_PARA_WRITINGDIR).GetValue();
884 
885                     if(SvxFrameDirection::Horizontal_RL_TB == eDirection)
886                     {
887                         aSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_RIGHT));
888                     }
889                     else
890                     {
891                         aSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_LEFT));
892                     }
893                 }
894 
895                 GetTextObj()->SetMergedItemSet(aSet);
896                 GetTextObj()->SetDisableAutoWidthOnDragging(true);
897                 SetInEditMode(rMEvt, false);
898             }
899 
900             bFirstObjCreated = true;
901         }
902         else
903         {
904             // switch to selection
905             if (mpView->SdrEndTextEdit() == SdrEndTextEditKind::Deleted)
906             {
907                 mxTextObj.reset(nullptr);
908             }
909 
910             mpViewShell->GetViewFrame()->GetDispatcher()->Execute( SID_OBJECT_SELECT,
911                                       SfxCallMode::ASYNCHRON | SfxCallMode::RECORD );
912         }
913     }
914     if (bJustEndedEdit)
915     {
916         bJustEndedEdit = false;
917         FuPoor::cancel();
918     }
919     bMBDown = false;
920     FuConstruct::MouseButtonUp(rMEvt);
921     return bReturn;
922 }
923 
924 /**
925  * handle keyboard events
926  * @returns sal_True if the event was handled, sal_False otherwise
927  */
928 bool FuText::KeyInput(const KeyEvent& rKEvt)
929 {
930     bool bReturn = false;
931 
932     vcl::KeyCode nCode = rKEvt.GetKeyCode();
933     bool bShift = nCode.IsShift();
934 
935     if(mxTextObj.is())
936     {
937         // maybe object is deleted, test if it's equal to the selected object
938         const SdrMarkList& rMarkList = mpView->GetMarkedObjectList();
939         SdrObject* pSelectedObj = nullptr;
940 
941         if(1 == rMarkList.GetMarkCount())
942         {
943             SdrMark* pMark = rMarkList.GetMark(0);
944             pSelectedObj = pMark->GetMarkedSdrObj();
945         }
946 
947         if(mxTextObj.get() != pSelectedObj)
948         {
949             mxTextObj.reset(nullptr);
950         }
951     }
952 
953     if ( mxTextObj.is() && mxTextObj->GetObjInventor() == SdrInventor::Default && mxTextObj->GetObjIdentifier() == OBJ_TITLETEXT && rKEvt.GetKeyCode().GetCode() == KEY_RETURN )
954     {
955         // title text object: always soft breaks
956         bShift = true;
957     }
958 
959     sal_uInt16 nKey = nCode.GetCode();
960     vcl::KeyCode aKeyCode (nKey, bShift, nCode.IsMod1(), nCode.IsMod2(), nCode.IsMod3() );
961     KeyEvent aKEvt(rKEvt.GetCharCode(), aKeyCode);
962 
963     bool bOK = true;
964 
965     if (mpDocSh->IsReadOnly())
966     {
967         bOK = !EditEngine::DoesKeyChangeText(aKEvt);
968     }
969     if( aKeyCode.GetCode() == KEY_PAGEUP || aKeyCode.GetCode() == KEY_PAGEDOWN )
970     {
971         bOK = false;   // default handling in base class
972     }
973 
974     if (bOK && mpView->KeyInput(aKEvt, mpWindow) )
975     {
976         bReturn = true;
977 
978         mpViewShell->GetViewFrame()->GetBindings().Invalidate( SidArray );
979 
980     }
981     else if (aKeyCode == KEY_ESCAPE)
982     {
983         bReturn = cancel();
984     }
985 
986     if( bPermanent )
987     {
988         mpView->SetCurrentObj(OBJ_TEXT);
989         mpView->SetEditMode(SdrViewEditMode::Create);
990     }
991 
992     if (!bReturn)
993     {
994         bReturn = FuDraw::KeyInput(aKEvt);
995     }
996 
997     return bReturn;
998 }
999 
1000 void FuText::Activate()
1001 {
1002     mpView->SetQuickTextEditMode(mpViewShell->GetFrameView()->IsQuickEdit());
1003 
1004     // #i89661# it's no longer necessary to make it so big here, it's fine tuned
1005     // for text objects in SdrMarkView::CheckSingleSdrObjectHit
1006     mpView->SetHitTolerancePixel( 2 * HITPIX );
1007 
1008     OutlinerView* pOLV = mpView->GetTextEditOutlinerView();
1009 
1010     if (pOLV)
1011         pOLV->ShowCursor(/*bGotoCursor=*/true, /*bActivate=*/true);
1012 
1013     FuConstruct::Activate();
1014 
1015     if( pOLV )
1016         mpView->SetEditMode(SdrViewEditMode::Edit);
1017 }
1018 
1019 void FuText::Deactivate()
1020 {
1021     OutlinerView* pOLV = mpView->GetTextEditOutlinerView();
1022 
1023     if (pOLV)
1024         pOLV->HideCursor(/*bDeactivate=*/true);
1025 
1026     mpView->SetHitTolerancePixel( HITPIX );
1027 
1028     FuConstruct::Deactivate();
1029 }
1030 
1031 /**
1032  * Sets the object into the edit mode.
1033  */
1034 void FuText::SetInEditMode(const MouseEvent& rMEvt, bool bQuickDrag)
1035 {
1036     SdrPageView* pPV = mpView->GetSdrPageView();
1037     if( mxTextObj.is() && (mxTextObj->getSdrPageFromSdrObject() == pPV->GetPage()) )
1038     {
1039         mpView->SetCurrentObj(OBJ_TEXT);
1040 
1041         if( bPermanent )
1042             mpView->SetEditMode(SdrViewEditMode::Create);
1043         else
1044             mpView->SetEditMode(SdrViewEditMode::Edit);
1045 
1046         bool bEmptyOutliner = false;
1047 
1048         if (!GetTextObj()->GetOutlinerParaObject() && mpView->GetTextEditOutliner())
1049         {
1050             ::Outliner* pOutl = mpView->GetTextEditOutliner();
1051             sal_Int32 nParagraphCnt = pOutl->GetParagraphCount();
1052             Paragraph* p1stPara = pOutl->GetParagraph( 0 );
1053 
1054             if (nParagraphCnt==1 && p1stPara)
1055             {
1056                 // with only one paragraph
1057                 if (pOutl->GetText(p1stPara).isEmpty())
1058                 {
1059                     bEmptyOutliner = true;
1060                 }
1061             }
1062         }
1063 
1064         if (GetTextObj() != mpView->GetTextEditObject() || bEmptyOutliner)
1065         {
1066             SdrInventor nInv = mxTextObj->GetObjInventor();
1067             sal_uInt16  nSdrObjKind = mxTextObj->GetObjIdentifier();
1068 
1069             if (nInv == SdrInventor::Default && GetTextObj()->HasTextEdit() &&
1070                 (nSdrObjKind == OBJ_TEXT ||
1071                  nSdrObjKind == OBJ_TITLETEXT ||
1072                  nSdrObjKind == OBJ_OUTLINETEXT || !mxTextObj->IsEmptyPresObj() ) )
1073             {
1074                 // create new outliner (owned by SdrObjEditView)
1075                 std::unique_ptr<SdrOutliner> pOutl = SdrMakeOutliner(OutlinerMode::OutlineObject, *mpDoc);
1076 
1077                 if (bEmptyOutliner)
1078                     mpView->SdrEndTextEdit(true);
1079 
1080                 SdrTextObj* pTextObj = GetTextObj();
1081                 if( pTextObj )
1082                 {
1083                     OutlinerParaObject* pOPO = pTextObj->GetOutlinerParaObject();
1084                     if( pOPO && pOPO->IsVertical() )
1085                     {
1086                         pOutl->SetVertical(pOPO->GetDirectVertical());
1087                         pOutl->SetRotation(pOPO->GetRotation());
1088                     }
1089                     else if (nSlotId == SID_ATTR_CHAR_VERTICAL || nSlotId == SID_TEXT_FITTOSIZE_VERTICAL)
1090                         pOutl->SetVertical( true );
1091 
1092                     if( pTextObj->getTextCount() > 1 )
1093                     {
1094                         Point aPix(rMEvt.GetPosPixel());
1095                         Point aPnt(mpWindow->PixelToLogic(aPix));
1096                         pTextObj->setActiveText( pTextObj->CheckTextHit(aPnt ) );
1097                     }
1098 
1099                     if (mpView->SdrBeginTextEdit(pTextObj, pPV, mpWindow, true, pOutl.release()) && mxTextObj->GetObjInventor() == SdrInventor::Default)
1100                     {
1101                         //tdf#102293 flush overlay before going on to pass clicks down to
1102                         //the outline view which will want to paint selections
1103                         for (sal_uInt32 b = 0; b < pPV->PageWindowCount(); ++b)
1104                         {
1105                             const SdrPageWindow& rPageWindow = *pPV->GetPageWindow(b);
1106                             if (!rPageWindow.GetPaintWindow().OutputToWindow())
1107                                 continue;
1108                             const rtl::Reference< sdr::overlay::OverlayManager >& xManager = rPageWindow.GetOverlayManager();
1109                             if (!xManager.is())
1110                                 continue;
1111                             xManager->flush();
1112                         }
1113 
1114                         bFirstObjCreated = true;
1115                         DeleteDefaultText();
1116 
1117                         OutlinerView* pOLV = mpView->GetTextEditOutlinerView();
1118 
1119                         nSdrObjKind = mxTextObj->GetObjIdentifier();
1120 
1121                         SdrViewEvent aVEvt;
1122                         SdrHitKind eHit = mpView->PickAnything(rMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt);
1123 
1124                         if (eHit == SdrHitKind::TextEdit)
1125                         {
1126                             // hit text
1127                             if (nSdrObjKind == OBJ_TEXT ||
1128                                 nSdrObjKind == OBJ_TITLETEXT ||
1129                                 nSdrObjKind == OBJ_OUTLINETEXT ||
1130                                 nSdrObjKind == OBJ_TABLE ||
1131                                 nSlotId == SID_TEXTEDIT ||
1132                                 !bQuickDrag)
1133                             {
1134                                 pOLV->MouseButtonDown(rMEvt);
1135                                 pOLV->MouseMove(rMEvt);
1136                                 pOLV->MouseButtonUp(rMEvt);
1137                             }
1138 
1139                             if (mpViewShell->GetFrameView()->IsQuickEdit() && bQuickDrag && GetTextObj()->GetOutlinerParaObject())
1140                             {
1141                                 pOLV->MouseButtonDown(rMEvt);
1142                             }
1143                         }
1144                         else
1145                         {
1146                             // Move cursor to end of text
1147                             ESelection aNewSelection(EE_PARA_NOT_FOUND, EE_INDEX_NOT_FOUND, EE_PARA_NOT_FOUND, EE_INDEX_NOT_FOUND);
1148                             if (pOLV != nullptr)
1149                                 pOLV->SetSelection(aNewSelection);
1150                         }
1151                     }
1152                     else
1153                     {
1154                         mpView->RestoreDefaultText( mxTextObj.get() );
1155                     }
1156                 }
1157             }
1158         }
1159     }
1160     else
1161     {
1162         mxTextObj.reset(nullptr);
1163     }
1164 }
1165 
1166 /**
1167  * Text entry is started, if necessary delete the default text.
1168  */
1169 void FuText::DeleteDefaultText()
1170 {
1171     if ( !(mxTextObj.is() && mxTextObj->IsEmptyPresObj()) )
1172         return;
1173 
1174     SdPage* pPage = static_cast<SdPage*>( mxTextObj->getSdrPageFromSdrObject() );
1175 
1176     if (!pPage)
1177         return;
1178 
1179     PresObjKind ePresObjKind = pPage->GetPresObjKind(mxTextObj.get());
1180 
1181     if ( !(ePresObjKind == PresObjKind::Title   ||
1182            ePresObjKind == PresObjKind::Outline ||
1183            ePresObjKind == PresObjKind::Notes   ||
1184            ePresObjKind == PresObjKind::Text      ) ||
1185           pPage->IsMasterPage() )
1186         return;
1187 
1188     ::Outliner* pOutliner = mpView->GetTextEditOutliner();
1189     SfxStyleSheet* pSheet = pOutliner->GetStyleSheet( 0 );
1190     bool bIsUndoEnabled = pOutliner->IsUndoEnabled();
1191     if( bIsUndoEnabled )
1192         pOutliner->EnableUndo(false);
1193 
1194     pOutliner->SetText( OUString(), pOutliner->GetParagraph( 0 ) );
1195 
1196     if( bIsUndoEnabled )
1197         pOutliner->EnableUndo(true);
1198 
1199     if (pSheet &&
1200         (ePresObjKind == PresObjKind::Notes || ePresObjKind == PresObjKind::Text))
1201         pOutliner->SetStyleSheet(0, pSheet);
1202 
1203     mxTextObj->SetEmptyPresObj(true);
1204 }
1205 
1206 bool FuText::RequestHelp(const HelpEvent& rHEvt)
1207 {
1208     bool bReturn = false;
1209 
1210     OutlinerView* pOLV = mpView->GetTextEditOutlinerView();
1211 
1212     if ((Help::IsBalloonHelpEnabled() || Help::IsQuickHelpEnabled()) &&
1213         mxTextObj.is() && pOLV && pOLV->GetFieldUnderMousePointer())
1214     {
1215         OUString aHelpText;
1216         const SvxFieldItem* pFieldItem = pOLV->GetFieldUnderMousePointer();
1217         const SvxFieldData* pField = pFieldItem->GetField();
1218 
1219         if (auto pURLField = dynamic_cast< const SvxURLField *>( pField ))
1220         {
1221             // URL-Field
1222             aHelpText = INetURLObject::decode( pURLField->GetURL(), INetURLObject::DecodeMechanism::WithCharset );
1223         }
1224         if (!aHelpText.isEmpty())
1225         {
1226             ::tools::Rectangle aLogicPix = mpWindow->LogicToPixel(mxTextObj->GetLogicRect());
1227             ::tools::Rectangle aScreenRect(mpWindow->OutputToScreenPixel(aLogicPix.TopLeft()),
1228                                   mpWindow->OutputToScreenPixel(aLogicPix.BottomRight()));
1229 
1230             if (Help::IsBalloonHelpEnabled())
1231             {
1232                 Help::ShowBalloon( static_cast<vcl::Window*>(mpWindow), rHEvt.GetMousePosPixel(), aScreenRect, aHelpText);
1233                 bReturn = true;
1234             }
1235             else if (Help::IsQuickHelpEnabled())
1236             {
1237                 Help::ShowQuickHelp( static_cast<vcl::Window*>(mpWindow), aScreenRect, aHelpText);
1238                 bReturn = true;
1239             }
1240         }
1241     }
1242 
1243     if (!bReturn)
1244     {
1245         bReturn = FuConstruct::RequestHelp(rHEvt);
1246     }
1247 
1248     return bReturn;
1249 }
1250 
1251 void FuText::ReceiveRequest(SfxRequest& rReq)
1252 {
1253     nSlotId = rReq.GetSlot();
1254 
1255     // then we call the base class (besides others, nSlotId is NOT set there)
1256     FuPoor::ReceiveRequest(rReq);
1257 
1258     if (!(nSlotId == SID_TEXTEDIT || mpViewShell->GetFrameView()->IsQuickEdit() || SID_ATTR_CHAR == nSlotId))
1259         return;
1260 
1261     MouseEvent aMEvt(mpWindow->GetPointerPosPixel());
1262 
1263     mxTextObj.reset(nullptr);
1264 
1265     if (nSlotId == SID_TEXTEDIT)
1266     {
1267         // are we currently editing?
1268         mxTextObj.reset( mpView->GetTextEditObject() );
1269 
1270         if (!mxTextObj.is())
1271         {
1272             // Try to select an object
1273             SdrPageView* pPV = mpView->GetSdrPageView();
1274             SdrViewEvent aVEvt;
1275             mpView->PickAnything(aMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt);
1276             mpView->MarkObj(aVEvt.pRootObj, pPV);
1277 
1278             if (auto pSdrTextObj = dynamic_cast< SdrTextObj *>( aVEvt.pObj ))
1279             {
1280                 mxTextObj.reset( pSdrTextObj );
1281             }
1282         }
1283     }
1284     else if (mpView->AreObjectsMarked())
1285     {
1286         const SdrMarkList& rMarkList = mpView->GetMarkedObjectList();
1287 
1288         if (rMarkList.GetMarkCount() == 1)
1289         {
1290             SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
1291 
1292             if( auto pTextObj = dynamic_cast<SdrTextObj *>( pObj ))
1293             {
1294                 mxTextObj.reset( pTextObj );
1295             }
1296         }
1297     }
1298 
1299     bool bQuickDrag = true;
1300 
1301     const SfxItemSet* pArgs = rReq.GetArgs();
1302 
1303     if (pArgs
1304 
1305         // test for type before using
1306         && SID_TEXTEDIT == nSlotId
1307         && SfxItemState::SET == pArgs->GetItemState(SID_TEXTEDIT)
1308 
1309         && static_cast<const SfxUInt16Item&>( pArgs->Get(SID_TEXTEDIT)).GetValue() == 2)
1310     {
1311         // selection with double click -> do not allow QuickDrag
1312         bQuickDrag = false;
1313     }
1314 
1315     SetInEditMode(aMEvt, bQuickDrag);
1316 }
1317 
1318 void FuText::DoubleClick(const MouseEvent& )
1319 {
1320     // Nothing to do
1321 }
1322 
1323 /** Removed the insertion of default text and putting a new text
1324     object directly into edit mode.
1325 */
1326 SdrObjectUniquePtr FuText::CreateDefaultObject(const sal_uInt16 nID, const ::tools::Rectangle& rRectangle)
1327 {
1328     SdrObjectUniquePtr pObj( SdrObjFactory::MakeNewObject(
1329         mpView->getSdrModelFromSdrView(),
1330         mpView->GetCurrentObjInventor(),
1331         mpView->GetCurrentObjIdentifier(),
1332         nullptr) );
1333 
1334     if(pObj)
1335     {
1336         if( auto pText = dynamic_cast< SdrTextObj *>( pObj.get() ) )
1337         {
1338             pText->SetLogicRect(rRectangle);
1339 
1340             bool bVertical = (SID_ATTR_CHAR_VERTICAL == nID || SID_TEXT_FITTOSIZE_VERTICAL == nID);
1341             pText->SetVerticalWriting(bVertical);
1342 
1343             ImpSetAttributesForNewTextObject(pText);
1344 
1345             if (nSlotId == SID_TEXT_FITTOSIZE)
1346             {
1347                 ImpSetAttributesFitToSize(pText);
1348             }
1349             else if ( nSlotId == SID_TEXT_FITTOSIZE_VERTICAL )
1350             {
1351                 ImpSetAttributesFitToSizeVertical(pText);
1352             }
1353             else
1354             {
1355                 ImpSetAttributesFitCommon(pText);
1356             }
1357 
1358             // Put text object into edit mode.
1359             SdrPageView* pPV = mpView->GetSdrPageView();
1360             mpView->SdrBeginTextEdit(pText, pPV);
1361         }
1362         else
1363         {
1364             OSL_FAIL("Object is NO text object");
1365         }
1366     }
1367 
1368     return pObj;
1369 }
1370 
1371 /** is called when the current function should be aborted. <p>
1372     This is used when a function gets a KEY_ESCAPE but can also
1373     be called directly.
1374 
1375     @returns true if an active function was aborted
1376 */
1377 bool FuText::cancel()
1378 {
1379     if ( mpView->IsTextEdit() )
1380     {
1381         if(mpView->SdrEndTextEdit() == SdrEndTextEditKind::Deleted)
1382             mxTextObj.reset(nullptr);
1383 
1384         mpView->SetCurrentObj(OBJ_TEXT);
1385         mpView->SetEditMode(SdrViewEditMode::Edit);
1386         return true;
1387     }
1388     else
1389     {
1390         return false;
1391     }
1392 }
1393 
1394 void FuText::ChangeFontSize( bool bGrow, OutlinerView* pOLV, const FontList* pFontList, ::sd::View* pView )
1395 {
1396     if( !pFontList || !pView )
1397         return;
1398 
1399     if( pOLV )
1400     {
1401         pOLV->GetEditView().ChangeFontSize( bGrow, pFontList );
1402     }
1403     else
1404     {
1405 
1406         pView->BegUndo(SdResId(bGrow ? STR_GROW_FONT_SIZE : STR_SHRINK_FONT_SIZE));
1407         const SdrMarkList& rMarkList = pView->GetMarkedObjectList();
1408         for( size_t nMark = 0; nMark < rMarkList.GetMarkCount(); ++nMark )
1409         {
1410             SdrTextObj* pTextObj = dynamic_cast< SdrTextObj* >( rMarkList.GetMark(nMark)->GetMarkedSdrObj() );
1411             if( pTextObj )
1412             {
1413                 rtl::Reference<sdr::SelectionController> xSelectionController(pView->getSelectionController());
1414                 if (xSelectionController.is() && xSelectionController->ChangeFontSize(bGrow, pFontList))
1415                 {
1416                     continue;
1417                 }
1418                 for( sal_Int32 nText = 0; nText < pTextObj->getTextCount(); nText++ )
1419                 {
1420                     pTextObj->setActiveText( nText );
1421 
1422                     // Put text object into edit mode.
1423                     SdrPageView* pPV = pView->GetSdrPageView();
1424                     pView->SdrBeginTextEdit(pTextObj, pPV);
1425 
1426                     pOLV = pView->GetTextEditOutlinerView();
1427                     if( pOLV )
1428                     {
1429                         EditEngine* pEditEngine = pOLV->GetEditView().GetEditEngine();
1430                         if( pEditEngine )
1431                         {
1432                             ESelection aSel;
1433                             aSel.nEndPara = pEditEngine->GetParagraphCount()-1;
1434                             aSel.nEndPos = pEditEngine->GetTextLen(aSel.nEndPara);
1435                             pOLV->SetSelection(aSel);
1436                         }
1437 
1438                         ChangeFontSize( bGrow, pOLV, pFontList, pView );
1439                     }
1440 
1441                     pView->SdrEndTextEdit();
1442                 }
1443 
1444                 SfxItemSet aShapeSet( pTextObj->GetMergedItemSet() );
1445                 if( EditView::ChangeFontSize( bGrow, aShapeSet, pFontList ) )
1446                 {
1447                     pTextObj->SetObjectItemNoBroadcast( aShapeSet.Get( EE_CHAR_FONTHEIGHT ) );
1448                     pTextObj->SetObjectItemNoBroadcast( aShapeSet.Get( EE_CHAR_FONTHEIGHT_CJK ) );
1449                     pTextObj->SetObjectItemNoBroadcast( aShapeSet.Get( EE_CHAR_FONTHEIGHT_CTL ) );
1450                 }
1451             }
1452         }
1453         pView->EndUndo();
1454     }
1455 }
1456 
1457 void FuText::InvalidateBindings()
1458 {
1459     mpViewShell->GetViewFrame()->GetBindings().Invalidate(SidArray);
1460 }
1461 
1462 
1463 } // end of namespace sd
1464 
1465 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1466