xref: /trunk/main/starmath/source/edit.cxx (revision 7a9d3b93)
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 		pEditView->SetSelection( ESelection( 0, 0, EE_PARA_MAX, EE_INDEX_MAX ) );
702 	}
703 }
704 
InsertCommand(sal_uInt16 nCommand)705 void SmEditWindow::InsertCommand(sal_uInt16 nCommand)
706 {
707     DBG_ASSERT( pEditView, "EditView missing" );
708     if (pEditView)
709     {
710         //Anfang der Selektion merken und hinterher den Cursor daraufsetzen. Nur so
711         //macht das SelNextMark() Sinn.
712         ESelection aSelection = pEditView->GetSelection();
713         aSelection.nEndPos  = aSelection.nStartPos;
714         aSelection.nEndPara = aSelection.nStartPara;
715 
716         DBG_ASSERT( pEditView, "NULL pointer" );
717         String  aText = String(SmResId(nCommand));
718         pEditView->InsertText(aText);
719 
720         if (HasMark(aText))
721         {   // set selection to next mark
722             pEditView->SetSelection(aSelection);
723             SelNextMark();
724         }
725         else
726         {   // set selection after inserted text
727             aSelection.nEndPos    = aSelection.nEndPos + sal::static_int_cast< xub_StrLen >(aText.Len());
728             aSelection.nStartPos  = aSelection.nEndPos;
729             pEditView->SetSelection(aSelection);
730         }
731 
732         aModifyTimer.Start();
733 		aCursorMoveTimer.Start();
734 
735         GrabFocus();
736     }
737 }
738 
MarkError(const Point & rPos)739 void SmEditWindow::MarkError(const Point &rPos)
740 {
741     DBG_ASSERT( pEditView, "EditView missing" );
742     if (pEditView)
743     {
744         const xub_StrLen    nCol = sal::static_int_cast< xub_StrLen >(rPos.X());
745         const sal_uInt16        nRow = sal::static_int_cast< sal_uInt16 >(rPos.Y() - 1);
746 
747         pEditView->SetSelection(ESelection(nRow, nCol - 1, nRow, nCol));
748         GrabFocus();
749     }
750 }
751 
SelNextMark()752 void SmEditWindow::SelNextMark()
753 {
754     EditEngine *pEditEngine = GetEditEngine();
755 	DBG_ASSERT( pEditView, "NULL pointer" );
756 	DBG_ASSERT( pEditEngine, "NULL pointer" );
757     if (pEditEngine  &&  pEditView)
758     {
759         ESelection eSelection = pEditView->GetSelection();
760         sal_uInt16     Pos        = eSelection.nEndPos;
761         String     aMark (C2S("<?>"));
762         String     aText;
763         sal_uInt32     nCounts    = pEditEngine->GetParagraphCount();
764 
765         while (eSelection.nEndPara < nCounts)
766         {
767             aText = pEditEngine->GetText( eSelection.nEndPara );
768             Pos   = aText.Search(aMark, Pos);
769 
770             if (Pos != STRING_NOTFOUND)
771             {
772                 pEditView->SetSelection(ESelection (eSelection.nEndPara, Pos, eSelection.nEndPara, Pos + 3));
773                 break;
774             }
775 
776             Pos = 0;
777             eSelection.nEndPara++;
778         }
779     }
780 }
781 
SelPrevMark()782 void SmEditWindow::SelPrevMark()
783 {
784     EditEngine *pEditEngine = GetEditEngine();
785 	DBG_ASSERT( pEditEngine, "NULL pointer" );
786 	DBG_ASSERT( pEditView, "NULL pointer" );
787     if (pEditEngine  &&  pEditView)
788     {
789         ESelection eSelection = pEditView->GetSelection();
790         sal_uInt16     Pos        = STRING_NOTFOUND;
791         xub_StrLen Max        = eSelection.nStartPos;
792         String     Text( pEditEngine->GetText( eSelection.nStartPara ) );
793         String     aMark (C2S("<?>"));
794         sal_uInt16     nCounts    = pEditEngine->GetParagraphCount();
795 
796         do
797         {
798             sal_uInt16 Fnd = Text.Search(aMark, 0);
799 
800             while ((Fnd < Max) && (Fnd != STRING_NOTFOUND))
801             {
802                 Pos = Fnd;
803                 Fnd = Text.Search(aMark, Fnd + 1);
804             }
805 
806             if (Pos == STRING_NOTFOUND)
807             {
808                 eSelection.nStartPara--;
809                 Text = pEditEngine->GetText( eSelection.nStartPara );
810                 Max = Text.Len();
811             }
812         }
813         while ((eSelection.nStartPara < nCounts) &&
814             (Pos == STRING_NOTFOUND));
815 
816         if (Pos != STRING_NOTFOUND)
817         {
818             pEditView->SetSelection(ESelection (eSelection.nStartPara, Pos, eSelection.nStartPara, Pos + 3));
819         }
820     }
821 }
822 
HasMark(const String & rText) const823 sal_Bool SmEditWindow::HasMark(const String& rText) const
824 	// returns true iff 'rText' contains a mark
825 {
826 	return rText.SearchAscii("<?>", 0) != STRING_NOTFOUND;
827 }
828 
MouseMove(const MouseEvent & rEvt)829 void SmEditWindow::MouseMove(const MouseEvent &rEvt)
830 {
831 	if (pEditView)
832 		pEditView->MouseMove(rEvt);
833 }
834 
AcceptDrop(const AcceptDropEvent &)835 sal_Int8 SmEditWindow::AcceptDrop( const AcceptDropEvent& /*rEvt*/ )
836 {
837 	return pEditView ? /*pEditView->QueryDrop( rEvt )*/DND_ACTION_NONE: DND_ACTION_NONE;
838 }
839 
ExecuteDrop(const ExecuteDropEvent &)840 sal_Int8 SmEditWindow::ExecuteDrop( const ExecuteDropEvent& /*rEvt*/ )
841 {
842 	return pEditView ? /*pEditView->Drop( rEvt )*/DND_ACTION_NONE : DND_ACTION_NONE;
843 }
844 
GetSelection() const845 ESelection SmEditWindow::GetSelection() const
846 {
847     // pointer may be 0 when reloading a document and the old view
848     // was already destroyed
849     //(DBG_ASSERT( pEditView, "NULL pointer" );
850 	ESelection eSel;
851 	if (pEditView)
852 		eSel = pEditView->GetSelection();
853 	return eSel;
854 }
855 
SetSelection(const ESelection & rSel)856 void SmEditWindow::SetSelection(const ESelection &rSel)
857 {
858 	DBG_ASSERT( pEditView, "NULL pointer" );
859     if (pEditView)
860         pEditView->SetSelection(rSel);
861 	InvalidateSlots();
862 }
863 
IsEmpty() const864 sal_Bool SmEditWindow::IsEmpty() const
865 {
866     EditEngine *pEditEngine = ((SmEditWindow *) this)->GetEditEngine();
867     sal_Bool bEmpty = sal::static_int_cast< sal_Bool >(
868                     pEditEngine ? pEditEngine->GetTextLen() == 0 : sal_False);
869     return bEmpty;
870 }
871 
IsSelected() const872 sal_Bool SmEditWindow::IsSelected() const
873 {
874     return pEditView ? pEditView->HasSelection() : sal_False;
875 }
876 
877 
UpdateStatus(bool bSetDocModified)878 void SmEditWindow::UpdateStatus( bool bSetDocModified )
879 {
880     SmModule *pMod = SM_MOD();
881     if (pMod && pMod->GetConfig()->IsAutoRedraw())
882         Flush();
883     if ( bSetDocModified )
884         GetDoc()->SetModified( sal_True );
885 }
886 
Cut()887 void SmEditWindow::Cut()
888 {
889     DBG_ASSERT( pEditView, "EditView missing" );
890     if (pEditView)
891     {
892         pEditView->Cut();
893         UpdateStatus( sal_True );
894     }
895 }
896 
Copy()897 void SmEditWindow::Copy()
898 {
899     DBG_ASSERT( pEditView, "EditView missing" );
900     if (pEditView)
901         pEditView->Copy();
902 }
903 
Paste()904 void SmEditWindow::Paste()
905 {
906     DBG_ASSERT( pEditView, "EditView missing" );
907     if (pEditView)
908     {
909         pEditView->Paste();
910         UpdateStatus( sal_True );
911     }
912 }
913 
Delete()914 void SmEditWindow::Delete()
915 {
916     DBG_ASSERT( pEditView, "EditView missing" );
917     if (pEditView)
918     {
919         pEditView->DeleteSelected();
920         UpdateStatus( sal_True );
921     }
922 }
923 
InsertText(const String & Text)924 void SmEditWindow::InsertText(const String& Text)
925 {
926     DBG_ASSERT( pEditView, "EditView missing" );
927     if (pEditView)
928     {
929         pEditView->InsertText(Text);
930         aModifyTimer.Start();
931 		aCursorMoveTimer.Start();
932     }
933 }
934 
Flush()935 void SmEditWindow::Flush()
936 {
937     EditEngine *pEditEngine = GetEditEngine();
938 	if (pEditEngine  &&  pEditEngine->IsModified())
939 	{
940 		pEditEngine->ClearModifyFlag();
941         SmViewShell *pViewSh = rCmdBox.GetView();
942 		if (pViewSh)
943         {
944 			pViewSh->GetViewFrame()->GetDispatcher()->Execute(
945 					SID_TEXT, SFX_CALLMODE_STANDARD,
946 					new SfxStringItem(SID_TEXT, GetText()), 0L);
947         }
948 	}
949 
950 	if (aCursorMoveTimer.IsActive())
951 	{
952 		aCursorMoveTimer.Stop();
953 		// ggf noch die (neue) FormulaCursor Position setzen
954 		CursorMoveTimerHdl(&aCursorMoveTimer);
955 	}
956 }
957 
958 
DeleteEditView(SmViewShell &)959 void SmEditWindow::DeleteEditView( SmViewShell & /*rView*/ )
960 {
961     if (pEditView)
962     {
963         EditEngine *pEditEngine = pEditView->GetEditEngine();
964         if (pEditEngine)
965         {
966             pEditEngine->SetStatusEventHdl( Link() );
967             pEditEngine->RemoveView( pEditView );
968         }
969         delete pEditView;
970         pEditView = 0;
971     }
972 }
973 
974 
CreateAccessible()975 uno::Reference< XAccessible > SmEditWindow::CreateAccessible()
976 {
977     if (!pAccessible)
978     {
979         pAccessible = new SmEditAccessible( this );
980         xAccessible = pAccessible;
981         pAccessible->Init();
982     }
983     return xAccessible;
984 }
985 
986