xref: /aoo4110/main/starmath/source/edit.cxx (revision b1cdbd2c)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_starmath.hxx"
26 
27 
28 #include <com/sun/star/accessibility/XAccessible.hpp>
29 #include <com/sun/star/accessibility/AccessibleEventObject.hpp>
30 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
31 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
32 #include <toolkit/helper/vclunohelper.hxx>
33 
34 
35 #include "starmath.hrc"
36 #define ITEMID_FONT 		1
37 #define ITEMID_FONTHEIGHT	2
38 #define ITEMID_LRSPACE		3
39 #define ITEMID_WEIGHT		4
40 
41 
42 #include <vcl/menu.hxx>
43 #include <editeng/editview.hxx>
44 #include <editeng/editeng.hxx>
45 #include <editeng/editstat.hxx>
46 #include <editeng/eeitem.hxx>
47 #include <sfx2/dispatch.hxx>
48 #include <svl/intitem.hxx>
49 #include <svl/itempool.hxx>
50 #include <svl/stritem.hxx>
51 #include <editeng/fhgtitem.hxx>
52 #include <editeng/wghtitem.hxx>
53 #include <editeng/lrspitem.hxx>
54 #include <svl/itemset.hxx>
55 #include <editeng/fontitem.hxx>
56 #include <sfx2/viewfrm.hxx>
57 
58 #include "edit.hxx"
59 #include "view.hxx"
60 #include "document.hxx"
61 #include "config.hxx"
62 
63 #define SCROLL_LINE 		24
64 
65 #define MINWIDTH		200
66 #define MINHEIGHT		200
67 #define MINSPLIT		40
68 #define SPLITTERWIDTH	2
69 
70 
71 using namespace com::sun::star::accessibility;
72 using namespace com::sun::star;
73 using namespace com::sun::star::uno;
74 
75 ////////////////////////////////////////
76 
77 
SmGetLeftSelectionPart(const ESelection aSel,sal_uInt16 & nPara,sal_uInt16 & nPos)78 void SmGetLeftSelectionPart(const ESelection aSel,
79 							sal_uInt16 &nPara, sal_uInt16 &nPos)
80 	// returns paragraph number and position of the selections left part
81 {
82 	// compare start and end of selection and use the one that comes first
83 	if (	aSel.nStartPara <  aSel.nEndPara
84 		||	(aSel.nStartPara == aSel.nEndPara  &&  aSel.nStartPos < aSel.nEndPos) )
85 	{	nPara = aSel.nStartPara;
86 		nPos  = aSel.nStartPos;
87 	}
88 	else
89 	{	nPara = aSel.nEndPara;
90 		nPos  = aSel.nEndPos;
91 	}
92 }
93 
94 ////////////////////////////////////////
95 
SmEditWindow(SmCmdBoxWindow & rMyCmdBoxWin)96 SmEditWindow::SmEditWindow( SmCmdBoxWindow &rMyCmdBoxWin ) :
97     Window              (&rMyCmdBoxWin),
98     DropTargetHelper    ( this ),
99     pAccessible         (0),
100     rCmdBox             (rMyCmdBoxWin),
101     pEditView           (0),
102     pHScrollBar         (0),
103     pVScrollBar         (0),
104     pScrollBox          (0)
105 {
106 	SetHelpId(HID_SMA_COMMAND_WIN_EDIT);
107 	SetMapMode(MAP_PIXEL);
108 
109     // Even RTL languages don't use RTL for math
110     rCmdBox.GetEditWindow()->EnableRTL( sal_False );
111 
112     ApplyColorConfigValues( SM_MOD()->GetColorConfig() );
113 
114     // compare DataChanged
115 	SetBackground( GetSettings().GetStyleSettings().GetWindowColor() );
116 
117 	aModifyTimer.SetTimeoutHdl(LINK(this, SmEditWindow, ModifyTimerHdl));
118 	aModifyTimer.SetTimeout(500);
119 
120 	aCursorMoveTimer.SetTimeoutHdl(LINK(this, SmEditWindow, CursorMoveTimerHdl));
121 	aCursorMoveTimer.SetTimeout(500);
122 
123 	// if not called explicitly the this edit window within the
124 	// command window will just show an empty gray panel.
125     Show();
126 }
127 
128 
~SmEditWindow()129 SmEditWindow::~SmEditWindow()
130 {
131 	aCursorMoveTimer.Stop();
132 	aModifyTimer.Stop();
133 
134 
135     // #112565# clean up of classes used for accessibility
136     // must be done before EditView (and thus EditEngine) is no longer
137     // available for those classes.
138     if (pAccessible)
139         pAccessible->ClearWin();    // make Accessible defunctional
140     // Note: memory for pAccessible will be freed when the reference
141     // xAccessible is released.
142 
143     if (pEditView)
144     {
145         EditEngine *pEditEngine = pEditView->GetEditEngine();
146         if (pEditEngine)
147         {
148             pEditEngine->SetStatusEventHdl( Link() );
149             pEditEngine->RemoveView( pEditView );
150         }
151     }
152 	delete pEditView;
153 	delete pHScrollBar;
154 	delete pVScrollBar;
155 	delete pScrollBox;
156 }
157 
InvalidateSlots()158 void SmEditWindow::InvalidateSlots()
159 {
160 	SfxBindings& rBind = GetView()->GetViewFrame()->GetBindings();
161 	rBind.Invalidate(SID_COPY);
162 	rBind.Invalidate(SID_CUT);
163 	rBind.Invalidate(SID_DELETE);
164 }
165 
GetView()166 SmViewShell * SmEditWindow::GetView()
167 {
168     return rCmdBox.GetView();
169 }
170 
171 
GetDoc()172 SmDocShell * SmEditWindow::GetDoc()
173 {
174     SmViewShell *pView = rCmdBox.GetView();
175     return pView ? pView->GetDoc() : 0;
176 }
177 
178 
GetEditEngine()179 EditEngine * SmEditWindow::GetEditEngine()
180 {
181     EditEngine *pEditEng = 0;
182     if (pEditView)
183         pEditEng = pEditView->GetEditEngine();
184     else
185     {
186         SmDocShell *pDoc = GetDoc();
187         if (pDoc)
188             pEditEng = &pDoc->GetEditEngine();
189     }
190     return pEditEng;
191 }
192 
193 
GetEditEngineItemPool()194 SfxItemPool * SmEditWindow::GetEditEngineItemPool()
195 {
196     SmDocShell *pDoc = GetDoc();
197     return pDoc ? &pDoc->GetEditEngineItemPool() : 0;
198 }
199 
ApplyColorConfigValues(const svtools::ColorConfig & rColorCfg)200 void SmEditWindow::ApplyColorConfigValues( const svtools::ColorConfig &rColorCfg )
201 {
202     // Note: SetBackground still done in SmEditWindow::DataChanged
203 #if OSL_DEBUG_LEVEL > 1
204 //   ColorData nVal = rColorCfg.GetColorValue(svtools::FONTCOLOR).nColor;
205 #endif
206     SetTextColor( rColorCfg.GetColorValue(svtools::FONTCOLOR).nColor );
207     Invalidate();
208 }
209 
DataChanged(const DataChangedEvent &)210 void SmEditWindow::DataChanged( const DataChangedEvent& )
211 {
212     const StyleSettings aSettings( GetSettings().GetStyleSettings() );
213 
214     ApplyColorConfigValues( SM_MOD()->GetColorConfig() );
215     SetBackground( aSettings.GetWindowColor() );
216 
217     // edit fields in other Applications use this font instead of
218     // the application font thus we use this one too
219     SetPointFont( aSettings.GetFieldFont() /*aSettings.GetAppFont()*/ );
220 
221     EditEngine  *pEditEngine = GetEditEngine();
222     SfxItemPool *pEditEngineItemPool = GetEditEngineItemPool();
223 
224 	if (pEditEngine && pEditEngineItemPool)
225 	{
226         //!
227         //! see also SmDocShell::GetEditEngine() !
228         //!
229 
230 		pEditEngine->SetDefTab( sal_uInt16( GetTextWidth( C2S("XXXX") ) ) );
231 
232         SetEditEngineDefaultFonts( *pEditEngine, *pEditEngineItemPool );
233 
234 		// forces new settings to be used
235         // unfortunately this resets the whole edit engine
236         // thus we need to save at least the text
237         String aTxt( pEditEngine->GetText( LINEEND_LF ) );
238 		pEditEngine->Clear();	//#77957 incorrect font size
239         pEditEngine->SetText( aTxt );
240 	}
241 
242 	AdjustScrollBars();
243 	Resize();
244 }
245 
IMPL_LINK(SmEditWindow,ModifyTimerHdl,Timer *,EMPTYARG)246 IMPL_LINK( SmEditWindow, ModifyTimerHdl, Timer *, EMPTYARG /*pTimer*/ )
247 {
248     UpdateStatus();
249     aModifyTimer.Stop();
250 	return 0;
251 }
252 
253 
IMPL_LINK(SmEditWindow,CursorMoveTimerHdl,Timer *,EMPTYARG)254 IMPL_LINK(SmEditWindow, CursorMoveTimerHdl, Timer *, EMPTYARG /*pTimer*/)
255 	// every once in a while check cursor position (selection) of edit
256 	// window and if it has changed (try to) set the formula-cursor
257 	// according to that.
258 {
259 	ESelection	aNewSelection   (GetSelection());
260 
261 	if (!aNewSelection.IsEqual(aOldSelection))
262     {   SmViewShell *pView = rCmdBox.GetView();
263 
264 		if (pView)
265 		{
266 			// get row and column to look for
267 			sal_uInt16	nRow, nCol;
268 			SmGetLeftSelectionPart(aNewSelection, nRow, nCol);
269 			nRow++;
270 			nCol++;
271 
272 			pView->GetGraphicWindow().SetCursorPos(nRow, nCol);
273 
274 			aOldSelection = aNewSelection;
275 		}
276 	}
277     aCursorMoveTimer.Stop();
278 
279 	return 0;
280 }
281 
282 
Resize()283 void SmEditWindow::Resize()
284 {
285 	if (!pEditView)
286 		CreateEditView();
287 
288 	if (pEditView)
289 	{
290 		pEditView->SetOutputArea(AdjustScrollBars());
291 		pEditView->ShowCursor();
292 
293         DBG_ASSERT( pEditView->GetEditEngine(), "EditEngine missing" );
294 		const long nMaxVisAreaStart = pEditView->GetEditEngine()->GetTextHeight() -
295 									  pEditView->GetOutputArea().GetHeight();
296 		if (pEditView->GetVisArea().Top() > nMaxVisAreaStart)
297 		{
298 			Rectangle aVisArea(pEditView->GetVisArea() );
299 			aVisArea.Top() = (nMaxVisAreaStart > 0 ) ? nMaxVisAreaStart : 0;
300 			aVisArea.SetSize(pEditView->GetOutputArea().GetSize());
301 			pEditView->SetVisArea(aVisArea);
302 			pEditView->ShowCursor();
303 		}
304 		InitScrollBars();
305 	}
306 	Invalidate();
307 }
308 
MouseButtonUp(const MouseEvent & rEvt)309 void SmEditWindow::MouseButtonUp(const MouseEvent &rEvt)
310 {
311 	if (pEditView)
312 		pEditView->MouseButtonUp(rEvt);
313 	else
314 		Window::MouseButtonUp (rEvt);
315 
316 	// ggf FormulaCursor neu positionieren
317 	CursorMoveTimerHdl(&aCursorMoveTimer);
318 	InvalidateSlots();
319 }
320 
MouseButtonDown(const MouseEvent & rEvt)321 void SmEditWindow::MouseButtonDown(const MouseEvent &rEvt)
322 {
323 	if (pEditView)
324 		pEditView->MouseButtonDown(rEvt);
325 	else
326 		Window::MouseButtonDown (rEvt);
327 
328 	GrabFocus();
329 }
330 
Command(const CommandEvent & rCEvt)331 void SmEditWindow::Command(const CommandEvent& rCEvt)
332 {
333     sal_Bool bForwardEvt = sal_True;
334 	if (rCEvt.GetCommand() == COMMAND_CONTEXTMENU)
335 	{
336 		GetParent()->ToTop();
337 
338         Point aPoint = rCEvt.GetMousePosPixel();
339 		PopupMenu* pPopupMenu = new PopupMenu(SmResId(RID_COMMANDMENU));
340 
341         // added for replaceability of context menus #96085, #93782
342         Menu* pMenu = NULL;
343         ::com::sun::star::ui::ContextMenuExecuteEvent aEvent;
344         aEvent.SourceWindow = VCLUnoHelper::GetInterface( this );
345         aEvent.ExecutePosition.X = aPoint.X();
346         aEvent.ExecutePosition.Y = aPoint.Y();
347         ::rtl::OUString sDummy;
348         if ( GetView()->TryContextMenuInterception( *pPopupMenu, sDummy, pMenu, aEvent ) )
349         {
350             if ( pMenu )
351             {
352                 delete pPopupMenu;
353                 pPopupMenu = (PopupMenu*) pMenu;
354             }
355         }
356 
357         pPopupMenu->SetSelectHdl(LINK(this, SmEditWindow, MenuSelectHdl));
358 
359         pPopupMenu->Execute( this, aPoint );
360 		delete pPopupMenu;
361         bForwardEvt = sal_False;
362 	}
363     else if (rCEvt.GetCommand() == COMMAND_WHEEL)
364         bForwardEvt = !HandleWheelCommands( rCEvt );
365 
366     if (bForwardEvt)
367     {
368         if (pEditView)
369             pEditView->Command( rCEvt );
370         else
371             Window::Command (rCEvt);
372     }
373 }
374 
375 
HandleWheelCommands(const CommandEvent & rCEvt)376 sal_Bool SmEditWindow::HandleWheelCommands( const CommandEvent &rCEvt )
377 {
378     sal_Bool bCommandHandled = sal_False;    // true if the CommandEvent needs not
379                                     // to be passed on (because it has fully
380                                     // been taken care of).
381 
382     const CommandWheelData* pWData = rCEvt.GetWheelData();
383     if (pWData)
384     {
385         if (COMMAND_WHEEL_ZOOM == pWData->GetMode())
386             bCommandHandled = sal_True;     // no zooming in Command window
387         else
388             bCommandHandled = HandleScrollCommand( rCEvt, pHScrollBar, pVScrollBar);
389     }
390 
391     return bCommandHandled;
392 }
393 
394 
IMPL_LINK_INLINE_START(SmEditWindow,MenuSelectHdl,Menu *,pMenu)395 IMPL_LINK_INLINE_START( SmEditWindow, MenuSelectHdl, Menu *, pMenu )
396 {
397     SmViewShell *pViewSh = rCmdBox.GetView();
398 	if (pViewSh)
399 		pViewSh->GetViewFrame()->GetDispatcher()->Execute(
400 				SID_INSERTCOMMAND, SFX_CALLMODE_STANDARD,
401 				new SfxInt16Item(SID_INSERTCOMMAND, pMenu->GetCurItemId()), 0L);
402 	return 0;
403 }
IMPL_LINK_INLINE_END(SmEditWindow,MenuSelectHdl,Menu *,pMenu)404 IMPL_LINK_INLINE_END( SmEditWindow, MenuSelectHdl, Menu *, pMenu )
405 
406 void SmEditWindow::KeyInput(const KeyEvent& rKEvt)
407 {
408 	if (rKEvt.GetKeyCode().GetCode() == KEY_ESCAPE)
409 	{
410 		sal_Bool bCallBase = sal_True;
411 		SfxViewShell* pViewShell = GetView();
412 		if ( pViewShell && pViewShell->ISA(SmViewShell) )
413 		{
414             // Terminate possible InPlace mode
415             bCallBase = !pViewShell->Escape();
416 		}
417 		if ( bCallBase )
418 			Window::KeyInput( rKEvt );
419 	}
420 	else
421 	{
422         // Timer neu starten, um den Handler (auch bei laengeren Eingaben)
423         // moeglichst nur einmal am Ende aufzurufen.
424 		aCursorMoveTimer.Start();
425 
426         DBG_ASSERT( pEditView, "EditView missing (NULL pointer)" );
427         if (!pEditView)
428             CreateEditView();
429 		if ( !pEditView->PostKeyEvent(rKEvt) )
430 		{
431             SmViewShell *pView = GetView();
432             if ( pView && !pView->KeyInput(rKEvt) )
433 			{
434 				/* fuert bei F1 (Hilfe) zum Zerstoeren von this! */
435 				Flush();
436 				if ( aModifyTimer.IsActive() )
437 					aModifyTimer.Stop();
438 				Window::KeyInput(rKEvt);
439 			}
440 			else
441 			{
442 				//SFX hat evtl. Slot an der View gecallt und dabei (wg. Hack
443 				//im SFX) den Focus auf die View gesetzt
444 				SfxViewShell* pVShell = GetView();
445 				if ( pVShell && pVShell->ISA(SmViewShell) &&
446 					 ((SmViewShell*)pVShell)->GetGraphicWindow().HasFocus() )
447 				{
448 					GrabFocus();
449 				}
450 			}
451 		}
452 		else
453         {
454             // have doc-shell modified only for formula input/change and not
455             // cursor travelling and such things...
456             SmDocShell *pDocShell = GetDoc();
457             if (pDocShell)
458                 pDocShell->SetModified( GetEditEngine()->IsModified() );
459 
460             aModifyTimer.Start();
461         }
462 
463 		InvalidateSlots();
464 	}
465 }
466 
Paint(const Rectangle & rRect)467 void SmEditWindow::Paint(const Rectangle& rRect)
468 {
469 	if (!pEditView)
470 		CreateEditView();
471 	pEditView->Paint(rRect);
472 }
473 
CreateEditView()474 void SmEditWindow::CreateEditView()
475 {
476     EditEngine *pEditEngine = GetEditEngine();
477 
478     //! pEditEngine and pEditView may be 0.
479     //! For example when the program is used by the document-converter
480 	if (!pEditView && pEditEngine)
481 	{
482 		pEditView = new EditView( pEditEngine, this );
483 		pEditEngine->InsertView( pEditView );
484 
485         if (!pVScrollBar)
486             pVScrollBar = new ScrollBar(this, WinBits(WB_VSCROLL));
487         if (!pHScrollBar)
488             pHScrollBar = new ScrollBar(this, WinBits(WB_HSCROLL));
489         if (!pScrollBox)
490             pScrollBox  = new ScrollBarBox(this);
491 		pVScrollBar->SetScrollHdl(LINK(this, SmEditWindow, ScrollHdl));
492 		pHScrollBar->SetScrollHdl(LINK(this, SmEditWindow, ScrollHdl));
493         pVScrollBar->EnableDrag( sal_True );
494         pHScrollBar->EnableDrag( sal_True );
495 
496 		pEditView->SetOutputArea(AdjustScrollBars());
497 
498 		ESelection eSelection;
499 
500 		pEditView->SetSelection(eSelection);
501 		Update();
502 		pEditView->ShowCursor(sal_True, sal_True);
503 
504 		pEditEngine->SetStatusEventHdl( LINK(this, SmEditWindow, EditStatusHdl) );
505 		SetPointer(pEditView->GetPointer());
506 
507 		SetScrollBarRanges();
508 	}
509 }
510 
511 
IMPL_LINK(SmEditWindow,EditStatusHdl,EditStatus *,EMPTYARG)512 IMPL_LINK( SmEditWindow, EditStatusHdl, EditStatus *, EMPTYARG /*pStat*/ )
513 {
514     if (!pEditView)
515 		return 1;
516 	else
517 	{
518 		Resize();
519 		return 0;
520 	}
521 }
522 
IMPL_LINK_INLINE_START(SmEditWindow,ScrollHdl,ScrollBar *,EMPTYARG)523 IMPL_LINK_INLINE_START( SmEditWindow, ScrollHdl, ScrollBar *, EMPTYARG /*pScrollBar*/ )
524 {
525     DBG_ASSERT(pEditView, "EditView missing");
526     if (pEditView)
527     {
528         pEditView->SetVisArea(Rectangle(Point(pHScrollBar->GetThumbPos(),
529                                             pVScrollBar->GetThumbPos()),
530                                         pEditView->GetVisArea().GetSize()));
531         pEditView->Invalidate();
532     }
533 	return 0;
534 }
IMPL_LINK_INLINE_END(SmEditWindow,ScrollHdl,ScrollBar *,pScrollBar)535 IMPL_LINK_INLINE_END( SmEditWindow, ScrollHdl, ScrollBar *, pScrollBar )
536 
537 Rectangle SmEditWindow::AdjustScrollBars()
538 {
539 	const Size aOut( GetOutputSizePixel() );
540 	Point aPoint;
541 	Rectangle aRect( aPoint, aOut );
542 
543 	if (pVScrollBar && pHScrollBar && pScrollBox)
544 	{
545 		const long nTmp = GetSettings().GetStyleSettings().GetScrollBarSize();
546 		Point aPt( aRect.TopRight() ); aPt.X() -= nTmp -1L;
547 		pVScrollBar->SetPosSizePixel( aPt, Size(nTmp, aOut.Height() - nTmp));
548 
549 		aPt = aRect.BottomLeft(); aPt.Y() -= nTmp - 1L;
550 		pHScrollBar->SetPosSizePixel( aPt, Size(aOut.Width() - nTmp, nTmp));
551 
552 		aPt.X() = pHScrollBar->GetSizePixel().Width();
553 		aPt.Y() = pVScrollBar->GetSizePixel().Height();
554 		pScrollBox->SetPosSizePixel(aPt, Size(nTmp, nTmp ));
555 
556 		aRect.Right()  = aPt.X() - 2;
557 		aRect.Bottom() = aPt.Y() - 2;
558 	}
559 	return aRect;
560 }
561 
SetScrollBarRanges()562 void SmEditWindow::SetScrollBarRanges()
563 {
564 	// Extra-Methode, nicht InitScrollBars, da auch fuer EditEngine-Events.
565     EditEngine *pEditEngine = GetEditEngine();
566 	if (pVScrollBar && pHScrollBar && pEditEngine && pEditView)
567 	{
568 		long nTmp = pEditEngine->GetTextHeight();
569 		pVScrollBar->SetRange(Range(0, nTmp));
570 		pVScrollBar->SetThumbPos(pEditView->GetVisArea().Top());
571 
572 		nTmp = pEditEngine->GetPaperSize().Width();
573 		pHScrollBar->SetRange(Range(0,nTmp));
574 		pHScrollBar->SetThumbPos(pEditView->GetVisArea().Left());
575 	}
576 }
577 
InitScrollBars()578 void SmEditWindow::InitScrollBars()
579 {
580     if (pVScrollBar && pHScrollBar && pScrollBox && pEditView)
581 	{
582 		const Size aOut( pEditView->GetOutputArea().GetSize() );
583 		pVScrollBar->SetVisibleSize(aOut.Height());
584 		pVScrollBar->SetPageSize(aOut.Height() * 8 / 10);
585 		pVScrollBar->SetLineSize(aOut.Height() * 2 / 10);
586 
587 		pHScrollBar->SetVisibleSize(aOut.Width());
588 		pHScrollBar->SetPageSize(aOut.Width() * 8 / 10);
589 		pHScrollBar->SetLineSize(SCROLL_LINE );
590 
591 		SetScrollBarRanges();
592 
593 		pVScrollBar->Show();
594 		pHScrollBar->Show();
595 		pScrollBox->Show();
596 	}
597 }
598 
599 
GetText() const600 String SmEditWindow::GetText() const
601 {
602 	String aText;
603     EditEngine *pEditEngine = const_cast< SmEditWindow* >(this)->GetEditEngine();
604 	DBG_ASSERT( pEditEngine, "EditEngine missing" );
605 	if (pEditEngine)
606 		aText = pEditEngine->GetText( LINEEND_LF );
607 	return aText;
608 }
609 
610 
SetText(const XubString & rText)611 void SmEditWindow::SetText(const XubString& rText)
612 {
613     EditEngine *pEditEngine = GetEditEngine();
614 	DBG_ASSERT( pEditEngine, "EditEngine missing" );
615 	if (pEditEngine  &&  !pEditEngine->IsModified())
616 	{
617 		if (!pEditView)
618 			CreateEditView();
619 
620 		ESelection eSelection = pEditView->GetSelection();
621 
622 		pEditEngine->SetText(rText);
623 		pEditEngine->ClearModifyFlag();
624 
625         //! Hier die Timer neu zu starten verhindert, dass die Handler fuer andere
626 		//! (im Augenblick nicht mehr aktive) Math Tasks aufgerufen werden.
627 		aModifyTimer.Start();
628 		aCursorMoveTimer.Start();
629 
630 		pEditView->SetSelection(eSelection);
631 	}
632 }
633 
634 
GetFocus()635 void SmEditWindow::GetFocus()
636 {
637 	Window::GetFocus();
638 
639     if (xAccessible.is())
640     {
641         // Note: will implicitly send the AccessibleStateType::FOCUSED event
642         ::accessibility::AccessibleTextHelper *pHelper = pAccessible->GetTextHelper();
643         if (pHelper)
644             pHelper->SetFocus( sal_True );
645     }
646 
647     if (!pEditView)
648          CreateEditView();
649     EditEngine *pEditEngine = GetEditEngine();
650 	if (pEditEngine)
651 		pEditEngine->SetStatusEventHdl( LINK(this, SmEditWindow, EditStatusHdl) );
652 }
653 
654 
LoseFocus()655 void SmEditWindow::LoseFocus()
656 {
657     EditEngine *pEditEngine = GetEditEngine();
658 	if (pEditEngine)
659 		pEditEngine->SetStatusEventHdl( Link() );
660 
661 	Window::LoseFocus();
662 
663     if (xAccessible.is())
664     {
665         // Note: will implicitly send the AccessibleStateType::FOCUSED event
666         ::accessibility::AccessibleTextHelper *pHelper = pAccessible->GetTextHelper();
667         if (pHelper)
668             pHelper->SetFocus( sal_False );
669     }
670 }
671 
672 
IsAllSelected() const673 sal_Bool SmEditWindow::IsAllSelected() const
674 {
675     sal_Bool bRes = sal_False;
676     EditEngine *pEditEngine = ((SmEditWindow *) this)->GetEditEngine();
677 	DBG_ASSERT( pEditView, "NULL pointer" );
678     DBG_ASSERT( pEditEngine, "NULL pointer" );
679     if (pEditEngine  &&  pEditView)
680     {
681         ESelection eSelection( pEditView->GetSelection() );
682         sal_Int32 nParaCnt = pEditEngine->GetParagraphCount();
683         if (!(nParaCnt - 1))
684         {
685             String Text( pEditEngine->GetText( LINEEND_LF ) );
686             bRes = !eSelection.nStartPos && (eSelection.nEndPos == Text.Len () - 1);
687         }
688         else
689         {
690             bRes = !eSelection.nStartPara && (eSelection.nEndPara == nParaCnt - 1);
691         }
692     }
693     return bRes;
694 }
695 
SelectAll()696 void SmEditWindow::SelectAll()
697 {
698 	DBG_ASSERT( pEditView, "NULL pointer" );
699 	if (pEditView)
700 	{
701 		// 0xFFFF as last two parameters refers to the end of the text
702 		pEditView->SetSelection( ESelection( 0, 0, 0xFFFF, 0xFFFF ) );
703 	}
704 }
705 
InsertCommand(sal_uInt16 nCommand)706 void SmEditWindow::InsertCommand(sal_uInt16 nCommand)
707 {
708     DBG_ASSERT( pEditView, "EditView missing" );
709     if (pEditView)
710     {
711         //Anfang der Selektion merken und hinterher den Cursor daraufsetzen. Nur so
712         //macht das SelNextMark() Sinn.
713         ESelection aSelection = pEditView->GetSelection();
714         aSelection.nEndPos  = aSelection.nStartPos;
715         aSelection.nEndPara = aSelection.nStartPara;
716 
717         DBG_ASSERT( pEditView, "NULL pointer" );
718         String  aText = String(SmResId(nCommand));
719         pEditView->InsertText(aText);
720 
721         if (HasMark(aText))
722         {   // set selection to next mark
723             pEditView->SetSelection(aSelection);
724             SelNextMark();
725         }
726         else
727         {   // set selection after inserted text
728             aSelection.nEndPos    = aSelection.nEndPos + sal::static_int_cast< xub_StrLen >(aText.Len());
729             aSelection.nStartPos  = aSelection.nEndPos;
730             pEditView->SetSelection(aSelection);
731         }
732 
733         aModifyTimer.Start();
734 		aCursorMoveTimer.Start();
735 
736         GrabFocus();
737     }
738 }
739 
MarkError(const Point & rPos)740 void SmEditWindow::MarkError(const Point &rPos)
741 {
742     DBG_ASSERT( pEditView, "EditView missing" );
743     if (pEditView)
744     {
745         const xub_StrLen    nCol = sal::static_int_cast< xub_StrLen >(rPos.X());
746         const sal_uInt16        nRow = sal::static_int_cast< sal_uInt16 >(rPos.Y() - 1);
747 
748         pEditView->SetSelection(ESelection(nRow, nCol - 1, nRow, nCol));
749         GrabFocus();
750     }
751 }
752 
SelNextMark()753 void SmEditWindow::SelNextMark()
754 {
755     EditEngine *pEditEngine = GetEditEngine();
756 	DBG_ASSERT( pEditView, "NULL pointer" );
757 	DBG_ASSERT( pEditEngine, "NULL pointer" );
758     if (pEditEngine  &&  pEditView)
759     {
760         ESelection eSelection = pEditView->GetSelection();
761         sal_uInt16     Pos        = eSelection.nEndPos;
762         String     aMark (C2S("<?>"));
763         String     aText;
764         sal_uInt16     nCounts    = pEditEngine->GetParagraphCount();
765 
766         while (eSelection.nEndPara < nCounts)
767         {
768             aText = pEditEngine->GetText( eSelection.nEndPara );
769             Pos   = aText.Search(aMark, Pos);
770 
771             if (Pos != STRING_NOTFOUND)
772             {
773                 pEditView->SetSelection(ESelection (eSelection.nEndPara, Pos, eSelection.nEndPara, Pos + 3));
774                 break;
775             }
776 
777             Pos = 0;
778             eSelection.nEndPara++;
779         }
780     }
781 }
782 
SelPrevMark()783 void SmEditWindow::SelPrevMark()
784 {
785     EditEngine *pEditEngine = GetEditEngine();
786 	DBG_ASSERT( pEditEngine, "NULL pointer" );
787 	DBG_ASSERT( pEditView, "NULL pointer" );
788     if (pEditEngine  &&  pEditView)
789     {
790         ESelection eSelection = pEditView->GetSelection();
791         sal_uInt16     Pos        = STRING_NOTFOUND;
792         xub_StrLen Max        = eSelection.nStartPos;
793         String     Text( pEditEngine->GetText( eSelection.nStartPara ) );
794         String     aMark (C2S("<?>"));
795         sal_uInt16     nCounts    = pEditEngine->GetParagraphCount();
796 
797         do
798         {
799             sal_uInt16 Fnd = Text.Search(aMark, 0);
800 
801             while ((Fnd < Max) && (Fnd != STRING_NOTFOUND))
802             {
803                 Pos = Fnd;
804                 Fnd = Text.Search(aMark, Fnd + 1);
805             }
806 
807             if (Pos == STRING_NOTFOUND)
808             {
809                 eSelection.nStartPara--;
810                 Text = pEditEngine->GetText( eSelection.nStartPara );
811                 Max = Text.Len();
812             }
813         }
814         while ((eSelection.nStartPara < nCounts) &&
815             (Pos == STRING_NOTFOUND));
816 
817         if (Pos != STRING_NOTFOUND)
818         {
819             pEditView->SetSelection(ESelection (eSelection.nStartPara, Pos, eSelection.nStartPara, Pos + 3));
820         }
821     }
822 }
823 
HasMark(const String & rText) const824 sal_Bool SmEditWindow::HasMark(const String& rText) const
825 	// returns true iff 'rText' contains a mark
826 {
827 	return rText.SearchAscii("<?>", 0) != STRING_NOTFOUND;
828 }
829 
MouseMove(const MouseEvent & rEvt)830 void SmEditWindow::MouseMove(const MouseEvent &rEvt)
831 {
832 	if (pEditView)
833 		pEditView->MouseMove(rEvt);
834 }
835 
AcceptDrop(const AcceptDropEvent &)836 sal_Int8 SmEditWindow::AcceptDrop( const AcceptDropEvent& /*rEvt*/ )
837 {
838 	return pEditView ? /*pEditView->QueryDrop( rEvt )*/DND_ACTION_NONE: DND_ACTION_NONE;
839 }
840 
ExecuteDrop(const ExecuteDropEvent &)841 sal_Int8 SmEditWindow::ExecuteDrop( const ExecuteDropEvent& /*rEvt*/ )
842 {
843 	return pEditView ? /*pEditView->Drop( rEvt )*/DND_ACTION_NONE : DND_ACTION_NONE;
844 }
845 
GetSelection() const846 ESelection SmEditWindow::GetSelection() const
847 {
848     // pointer may be 0 when reloading a document and the old view
849     // was already destroyed
850     //(DBG_ASSERT( pEditView, "NULL pointer" );
851 	ESelection eSel;
852 	if (pEditView)
853 		eSel = pEditView->GetSelection();
854 	return eSel;
855 }
856 
SetSelection(const ESelection & rSel)857 void SmEditWindow::SetSelection(const ESelection &rSel)
858 {
859 	DBG_ASSERT( pEditView, "NULL pointer" );
860     if (pEditView)
861         pEditView->SetSelection(rSel);
862 	InvalidateSlots();
863 }
864 
IsEmpty() const865 sal_Bool SmEditWindow::IsEmpty() const
866 {
867     EditEngine *pEditEngine = ((SmEditWindow *) this)->GetEditEngine();
868     sal_Bool bEmpty = sal::static_int_cast< sal_Bool >(
869                     pEditEngine ? pEditEngine->GetTextLen() == 0 : sal_False);
870     return bEmpty;
871 }
872 
IsSelected() const873 sal_Bool SmEditWindow::IsSelected() const
874 {
875     return pEditView ? pEditView->HasSelection() : sal_False;
876 }
877 
878 
UpdateStatus(bool bSetDocModified)879 void SmEditWindow::UpdateStatus( bool bSetDocModified )
880 {
881     SmModule *pMod = SM_MOD();
882     if (pMod && pMod->GetConfig()->IsAutoRedraw())
883         Flush();
884     if ( bSetDocModified )
885         GetDoc()->SetModified( sal_True );
886 }
887 
Cut()888 void SmEditWindow::Cut()
889 {
890     DBG_ASSERT( pEditView, "EditView missing" );
891     if (pEditView)
892     {
893         pEditView->Cut();
894         UpdateStatus( sal_True );
895     }
896 }
897 
Copy()898 void SmEditWindow::Copy()
899 {
900     DBG_ASSERT( pEditView, "EditView missing" );
901     if (pEditView)
902         pEditView->Copy();
903 }
904 
Paste()905 void SmEditWindow::Paste()
906 {
907     DBG_ASSERT( pEditView, "EditView missing" );
908     if (pEditView)
909     {
910         pEditView->Paste();
911         UpdateStatus( sal_True );
912     }
913 }
914 
Delete()915 void SmEditWindow::Delete()
916 {
917     DBG_ASSERT( pEditView, "EditView missing" );
918     if (pEditView)
919     {
920         pEditView->DeleteSelected();
921         UpdateStatus( sal_True );
922     }
923 }
924 
InsertText(const String & Text)925 void SmEditWindow::InsertText(const String& Text)
926 {
927     DBG_ASSERT( pEditView, "EditView missing" );
928     if (pEditView)
929     {
930         pEditView->InsertText(Text);
931         aModifyTimer.Start();
932 		aCursorMoveTimer.Start();
933     }
934 }
935 
Flush()936 void SmEditWindow::Flush()
937 {
938     EditEngine *pEditEngine = GetEditEngine();
939 	if (pEditEngine  &&  pEditEngine->IsModified())
940 	{
941 		pEditEngine->ClearModifyFlag();
942         SmViewShell *pViewSh = rCmdBox.GetView();
943 		if (pViewSh)
944         {
945 			pViewSh->GetViewFrame()->GetDispatcher()->Execute(
946 					SID_TEXT, SFX_CALLMODE_STANDARD,
947 					new SfxStringItem(SID_TEXT, GetText()), 0L);
948         }
949 	}
950 
951 	if (aCursorMoveTimer.IsActive())
952 	{
953 		aCursorMoveTimer.Stop();
954 		// ggf noch die (neue) FormulaCursor Position setzen
955 		CursorMoveTimerHdl(&aCursorMoveTimer);
956 	}
957 }
958 
959 
DeleteEditView(SmViewShell &)960 void SmEditWindow::DeleteEditView( SmViewShell & /*rView*/ )
961 {
962     if (pEditView)
963     {
964         EditEngine *pEditEngine = pEditView->GetEditEngine();
965         if (pEditEngine)
966         {
967             pEditEngine->SetStatusEventHdl( Link() );
968             pEditEngine->RemoveView( pEditView );
969         }
970         delete pEditView;
971         pEditView = 0;
972     }
973 }
974 
975 
CreateAccessible()976 uno::Reference< XAccessible > SmEditWindow::CreateAccessible()
977 {
978     if (!pAccessible)
979     {
980         pAccessible = new SmEditAccessible( this );
981         xAccessible = pAccessible;
982         pAccessible->Init();
983     }
984     return xAccessible;
985 }
986 
987