xref: /trunk/main/starmath/source/edit.cxx (revision d107581f)
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 
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 
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 
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 
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 
166 SmViewShell * SmEditWindow::GetView()
167 {
168     return rCmdBox.GetView();
169 }
170 
171 
172 SmDocShell * SmEditWindow::GetDoc()
173 {
174     SmViewShell *pView = rCmdBox.GetView();
175     return pView ? pView->GetDoc() : 0;
176 }
177 
178 
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 
194 SfxItemPool * SmEditWindow::GetEditEngineItemPool()
195 {
196     SmDocShell *pDoc = GetDoc();
197     return pDoc ? &pDoc->GetEditEngineItemPool() : 0;
198 }
199 
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 
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 
246 IMPL_LINK( SmEditWindow, ModifyTimerHdl, Timer *, EMPTYARG /*pTimer*/ )
247 {
248     SmModule *pp = SM_MOD();
249 	if (pp->GetConfig()->IsAutoRedraw())
250 		Flush();
251     aModifyTimer.Stop();
252 	return 0;
253 }
254 
255 
256 IMPL_LINK(SmEditWindow, CursorMoveTimerHdl, Timer *, EMPTYARG /*pTimer*/)
257 	// every once in a while check cursor position (selection) of edit
258 	// window and if it has changed (try to) set the formula-cursor
259 	// according to that.
260 {
261 	ESelection	aNewSelection   (GetSelection());
262 
263 	if (!aNewSelection.IsEqual(aOldSelection))
264     {   SmViewShell *pView = rCmdBox.GetView();
265 
266 		if (pView)
267 		{
268 			// get row and column to look for
269 			sal_uInt16	nRow, nCol;
270 			SmGetLeftSelectionPart(aNewSelection, nRow, nCol);
271 			nRow++;
272 			nCol++;
273 
274 			pView->GetGraphicWindow().SetCursorPos(nRow, nCol);
275 
276 			aOldSelection = aNewSelection;
277 		}
278 	}
279     aCursorMoveTimer.Stop();
280 
281 	return 0;
282 }
283 
284 
285 void SmEditWindow::Resize()
286 {
287 	if (!pEditView)
288 		CreateEditView();
289 
290 	if (pEditView)
291 	{
292 		pEditView->SetOutputArea(AdjustScrollBars());
293 		pEditView->ShowCursor();
294 
295         DBG_ASSERT( pEditView->GetEditEngine(), "EditEngine missing" );
296 		const long nMaxVisAreaStart = pEditView->GetEditEngine()->GetTextHeight() -
297 									  pEditView->GetOutputArea().GetHeight();
298 		if (pEditView->GetVisArea().Top() > nMaxVisAreaStart)
299 		{
300 			Rectangle aVisArea(pEditView->GetVisArea() );
301 			aVisArea.Top() = (nMaxVisAreaStart > 0 ) ? nMaxVisAreaStart : 0;
302 			aVisArea.SetSize(pEditView->GetOutputArea().GetSize());
303 			pEditView->SetVisArea(aVisArea);
304 			pEditView->ShowCursor();
305 		}
306 		InitScrollBars();
307 	}
308 	Invalidate();
309 }
310 
311 void SmEditWindow::MouseButtonUp(const MouseEvent &rEvt)
312 {
313 	if (pEditView)
314 		pEditView->MouseButtonUp(rEvt);
315 	else
316 		Window::MouseButtonUp (rEvt);
317 
318 	// ggf FormulaCursor neu positionieren
319 	CursorMoveTimerHdl(&aCursorMoveTimer);
320 	InvalidateSlots();
321 }
322 
323 void SmEditWindow::MouseButtonDown(const MouseEvent &rEvt)
324 {
325 	if (pEditView)
326 		pEditView->MouseButtonDown(rEvt);
327 	else
328 		Window::MouseButtonDown (rEvt);
329 
330 	GrabFocus();
331 }
332 
333 void SmEditWindow::Command(const CommandEvent& rCEvt)
334 {
335     sal_Bool bForwardEvt = sal_True;
336 	if (rCEvt.GetCommand() == COMMAND_CONTEXTMENU)
337 	{
338 		GetParent()->ToTop();
339 
340         Point aPoint = rCEvt.GetMousePosPixel();
341 		PopupMenu* pPopupMenu = new PopupMenu(SmResId(RID_COMMANDMENU));
342 
343         // added for replaceability of context menus #96085, #93782
344         Menu* pMenu = NULL;
345         ::com::sun::star::ui::ContextMenuExecuteEvent aEvent;
346         aEvent.SourceWindow = VCLUnoHelper::GetInterface( this );
347         aEvent.ExecutePosition.X = aPoint.X();
348         aEvent.ExecutePosition.Y = aPoint.Y();
349         ::rtl::OUString sDummy;
350         if ( GetView()->TryContextMenuInterception( *pPopupMenu, sDummy, pMenu, aEvent ) )
351         {
352             if ( pMenu )
353             {
354                 delete pPopupMenu;
355                 pPopupMenu = (PopupMenu*) pMenu;
356             }
357         }
358 
359         pPopupMenu->SetSelectHdl(LINK(this, SmEditWindow, MenuSelectHdl));
360 
361         pPopupMenu->Execute( this, aPoint );
362 		delete pPopupMenu;
363         bForwardEvt = sal_False;
364 	}
365     else if (rCEvt.GetCommand() == COMMAND_WHEEL)
366         bForwardEvt = !HandleWheelCommands( rCEvt );
367 
368     if (bForwardEvt)
369     {
370         if (pEditView)
371             pEditView->Command( rCEvt );
372         else
373             Window::Command (rCEvt);
374     }
375 }
376 
377 
378 sal_Bool SmEditWindow::HandleWheelCommands( const CommandEvent &rCEvt )
379 {
380     sal_Bool bCommandHandled = sal_False;    // true if the CommandEvent needs not
381                                     // to be passed on (because it has fully
382                                     // been taken care of).
383 
384     const CommandWheelData* pWData = rCEvt.GetWheelData();
385     if (pWData)
386     {
387         if (COMMAND_WHEEL_ZOOM == pWData->GetMode())
388             bCommandHandled = sal_True;     // no zooming in Command window
389         else
390             bCommandHandled = HandleScrollCommand( rCEvt, pHScrollBar, pVScrollBar);
391     }
392 
393     return bCommandHandled;
394 }
395 
396 
397 IMPL_LINK_INLINE_START( SmEditWindow, MenuSelectHdl, Menu *, pMenu )
398 {
399     SmViewShell *pViewSh = rCmdBox.GetView();
400 	if (pViewSh)
401 		pViewSh->GetViewFrame()->GetDispatcher()->Execute(
402 				SID_INSERTCOMMAND, SFX_CALLMODE_STANDARD,
403 				new SfxInt16Item(SID_INSERTCOMMAND, pMenu->GetCurItemId()), 0L);
404 	return 0;
405 }
406 IMPL_LINK_INLINE_END( SmEditWindow, MenuSelectHdl, Menu *, pMenu )
407 
408 void SmEditWindow::KeyInput(const KeyEvent& rKEvt)
409 {
410 	if (rKEvt.GetKeyCode().GetCode() == KEY_ESCAPE)
411 	{
412 		sal_Bool bCallBase = sal_True;
413 		SfxViewShell* pViewShell = GetView();
414 		if ( pViewShell && pViewShell->ISA(SmViewShell) )
415 		{
416             // Terminate possible InPlace mode
417             bCallBase = !pViewShell->Escape();
418 		}
419 		if ( bCallBase )
420 			Window::KeyInput( rKEvt );
421 	}
422 	else
423 	{
424         // Timer neu starten, um den Handler (auch bei laengeren Eingaben)
425         // moeglichst nur einmal am Ende aufzurufen.
426 		aCursorMoveTimer.Start();
427 
428         DBG_ASSERT( pEditView, "EditView missing (NULL pointer)" );
429         if (!pEditView)
430             CreateEditView();
431 		if ( !pEditView->PostKeyEvent(rKEvt) )
432 		{
433             SmViewShell *pView = GetView();
434             if ( pView && !pView->KeyInput(rKEvt) )
435 			{
436 				/* fuert bei F1 (Hilfe) zum Zerstoeren von this! */
437 				Flush();
438 				if ( aModifyTimer.IsActive() )
439 					aModifyTimer.Stop();
440 				Window::KeyInput(rKEvt);
441 			}
442 			else
443 			{
444 				//SFX hat evtl. Slot an der View gecallt und dabei (wg. Hack
445 				//im SFX) den Focus auf die View gesetzt
446 				SfxViewShell* pVShell = GetView();
447 				if ( pVShell && pVShell->ISA(SmViewShell) &&
448 					 ((SmViewShell*)pVShell)->GetGraphicWindow().HasFocus() )
449 				{
450 					GrabFocus();
451 				}
452 			}
453 		}
454 		else
455         {
456             // have doc-shell modified only for formula input/change and not
457             // cursor travelling and such things...
458             SmDocShell *pDocShell = GetDoc();
459             if (pDocShell)
460                 pDocShell->SetModified( GetEditEngine()->IsModified() );
461 
462             aModifyTimer.Start();
463         }
464 
465 		InvalidateSlots();
466 	}
467 }
468 
469 void SmEditWindow::Paint(const Rectangle& rRect)
470 {
471 	if (!pEditView)
472 		CreateEditView();
473 	pEditView->Paint(rRect);
474 }
475 
476 void SmEditWindow::CreateEditView()
477 {
478     EditEngine *pEditEngine = GetEditEngine();
479 
480     //! pEditEngine and pEditView may be 0.
481     //! For example when the program is used by the document-converter
482 	if (!pEditView && pEditEngine)
483 	{
484 		pEditView = new EditView( pEditEngine, this );
485 		pEditEngine->InsertView( pEditView );
486 
487         if (!pVScrollBar)
488             pVScrollBar = new ScrollBar(this, WinBits(WB_VSCROLL));
489         if (!pHScrollBar)
490             pHScrollBar = new ScrollBar(this, WinBits(WB_HSCROLL));
491         if (!pScrollBox)
492             pScrollBox  = new ScrollBarBox(this);
493 		pVScrollBar->SetScrollHdl(LINK(this, SmEditWindow, ScrollHdl));
494 		pHScrollBar->SetScrollHdl(LINK(this, SmEditWindow, ScrollHdl));
495         pVScrollBar->EnableDrag( sal_True );
496         pHScrollBar->EnableDrag( sal_True );
497 
498 		pEditView->SetOutputArea(AdjustScrollBars());
499 
500 		ESelection eSelection;
501 
502 		pEditView->SetSelection(eSelection);
503 		Update();
504 		pEditView->ShowCursor(sal_True, sal_True);
505 
506 		pEditEngine->SetStatusEventHdl( LINK(this, SmEditWindow, EditStatusHdl) );
507 		SetPointer(pEditView->GetPointer());
508 
509 		SetScrollBarRanges();
510 	}
511 }
512 
513 
514 IMPL_LINK( SmEditWindow, EditStatusHdl, EditStatus *, EMPTYARG /*pStat*/ )
515 {
516     if (!pEditView)
517 		return 1;
518 	else
519 	{
520 		Resize();
521 		return 0;
522 	}
523 }
524 
525 IMPL_LINK_INLINE_START( SmEditWindow, ScrollHdl, ScrollBar *, EMPTYARG /*pScrollBar*/ )
526 {
527     DBG_ASSERT(pEditView, "EditView missing");
528     if (pEditView)
529     {
530         pEditView->SetVisArea(Rectangle(Point(pHScrollBar->GetThumbPos(),
531                                             pVScrollBar->GetThumbPos()),
532                                         pEditView->GetVisArea().GetSize()));
533         pEditView->Invalidate();
534     }
535 	return 0;
536 }
537 IMPL_LINK_INLINE_END( SmEditWindow, ScrollHdl, ScrollBar *, pScrollBar )
538 
539 Rectangle SmEditWindow::AdjustScrollBars()
540 {
541 	const Size aOut( GetOutputSizePixel() );
542 	Point aPoint;
543 	Rectangle aRect( aPoint, aOut );
544 
545 	if (pVScrollBar && pHScrollBar && pScrollBox)
546 	{
547 		const long nTmp = GetSettings().GetStyleSettings().GetScrollBarSize();
548 		Point aPt( aRect.TopRight() ); aPt.X() -= nTmp -1L;
549 		pVScrollBar->SetPosSizePixel( aPt, Size(nTmp, aOut.Height() - nTmp));
550 
551 		aPt = aRect.BottomLeft(); aPt.Y() -= nTmp - 1L;
552 		pHScrollBar->SetPosSizePixel( aPt, Size(aOut.Width() - nTmp, nTmp));
553 
554 		aPt.X() = pHScrollBar->GetSizePixel().Width();
555 		aPt.Y() = pVScrollBar->GetSizePixel().Height();
556 		pScrollBox->SetPosSizePixel(aPt, Size(nTmp, nTmp ));
557 
558 		aRect.Right()  = aPt.X() - 2;
559 		aRect.Bottom() = aPt.Y() - 2;
560 	}
561 	return aRect;
562 }
563 
564 void SmEditWindow::SetScrollBarRanges()
565 {
566 	// Extra-Methode, nicht InitScrollBars, da auch fuer EditEngine-Events.
567     EditEngine *pEditEngine = GetEditEngine();
568 	if (pVScrollBar && pHScrollBar && pEditEngine && pEditView)
569 	{
570 		long nTmp = pEditEngine->GetTextHeight();
571 		pVScrollBar->SetRange(Range(0, nTmp));
572 		pVScrollBar->SetThumbPos(pEditView->GetVisArea().Top());
573 
574 		nTmp = pEditEngine->GetPaperSize().Width();
575 		pHScrollBar->SetRange(Range(0,nTmp));
576 		pHScrollBar->SetThumbPos(pEditView->GetVisArea().Left());
577 	}
578 }
579 
580 void SmEditWindow::InitScrollBars()
581 {
582     if (pVScrollBar && pHScrollBar && pScrollBox && pEditView)
583 	{
584 		const Size aOut( pEditView->GetOutputArea().GetSize() );
585 		pVScrollBar->SetVisibleSize(aOut.Height());
586 		pVScrollBar->SetPageSize(aOut.Height() * 8 / 10);
587 		pVScrollBar->SetLineSize(aOut.Height() * 2 / 10);
588 
589 		pHScrollBar->SetVisibleSize(aOut.Width());
590 		pHScrollBar->SetPageSize(aOut.Width() * 8 / 10);
591 		pHScrollBar->SetLineSize(SCROLL_LINE );
592 
593 		SetScrollBarRanges();
594 
595 		pVScrollBar->Show();
596 		pHScrollBar->Show();
597 		pScrollBox->Show();
598 	}
599 }
600 
601 
602 String SmEditWindow::GetText() const
603 {
604 	String aText;
605     EditEngine *pEditEngine = const_cast< SmEditWindow* >(this)->GetEditEngine();
606 	DBG_ASSERT( pEditEngine, "EditEngine missing" );
607 	if (pEditEngine)
608 		aText = pEditEngine->GetText( LINEEND_LF );
609 	return aText;
610 }
611 
612 
613 void SmEditWindow::SetText(const XubString& rText)
614 {
615     EditEngine *pEditEngine = GetEditEngine();
616 	DBG_ASSERT( pEditEngine, "EditEngine missing" );
617 	if (pEditEngine  &&  !pEditEngine->IsModified())
618 	{
619 		if (!pEditView)
620 			CreateEditView();
621 
622 		ESelection eSelection = pEditView->GetSelection();
623 
624 		pEditEngine->SetText(rText);
625 		pEditEngine->ClearModifyFlag();
626 
627         //! Hier die Timer neu zu starten verhindert, dass die Handler fuer andere
628 		//! (im Augenblick nicht mehr aktive) Math Tasks aufgerufen werden.
629 		aModifyTimer.Start();
630 		aCursorMoveTimer.Start();
631 
632 		pEditView->SetSelection(eSelection);
633 	}
634 }
635 
636 
637 void SmEditWindow::GetFocus()
638 {
639 	Window::GetFocus();
640 
641     if (xAccessible.is())
642     {
643         // Note: will implicitly send the AccessibleStateType::FOCUSED event
644         ::accessibility::AccessibleTextHelper *pHelper = pAccessible->GetTextHelper();
645         if (pHelper)
646             pHelper->SetFocus( sal_True );
647     }
648 
649     if (!pEditView)
650          CreateEditView();
651     EditEngine *pEditEngine = GetEditEngine();
652 	if (pEditEngine)
653 		pEditEngine->SetStatusEventHdl( LINK(this, SmEditWindow, EditStatusHdl) );
654 }
655 
656 
657 void SmEditWindow::LoseFocus()
658 {
659     EditEngine *pEditEngine = GetEditEngine();
660 	if (pEditEngine)
661 		pEditEngine->SetStatusEventHdl( Link() );
662 
663 	Window::LoseFocus();
664 
665     if (xAccessible.is())
666     {
667         // Note: will implicitly send the AccessibleStateType::FOCUSED event
668         ::accessibility::AccessibleTextHelper *pHelper = pAccessible->GetTextHelper();
669         if (pHelper)
670             pHelper->SetFocus( sal_False );
671     }
672 }
673 
674 
675 sal_Bool SmEditWindow::IsAllSelected() const
676 {
677     sal_Bool bRes = sal_False;
678     EditEngine *pEditEngine = ((SmEditWindow *) this)->GetEditEngine();
679 	DBG_ASSERT( pEditView, "NULL pointer" );
680     DBG_ASSERT( pEditEngine, "NULL pointer" );
681     if (pEditEngine  &&  pEditView)
682     {
683         ESelection eSelection( pEditView->GetSelection() );
684         sal_Int32 nParaCnt = pEditEngine->GetParagraphCount();
685         if (!(nParaCnt - 1))
686         {
687             String Text( pEditEngine->GetText( LINEEND_LF ) );
688             bRes = !eSelection.nStartPos && (eSelection.nEndPos == Text.Len () - 1);
689         }
690         else
691         {
692             bRes = !eSelection.nStartPara && (eSelection.nEndPara == nParaCnt - 1);
693         }
694     }
695     return bRes;
696 }
697 
698 void SmEditWindow::SelectAll()
699 {
700 	DBG_ASSERT( pEditView, "NULL pointer" );
701 	if (pEditView)
702 	{
703 		// 0xFFFF as last two parameters refers to the end of the text
704 		pEditView->SetSelection( ESelection( 0, 0, 0xFFFF, 0xFFFF ) );
705 	}
706 }
707 
708 void SmEditWindow::InsertCommand(sal_uInt16 nCommand)
709 {
710     DBG_ASSERT( pEditView, "EditView missing" );
711     if (pEditView)
712     {
713         //Anfang der Selektion merken und hinterher den Cursor daraufsetzen. Nur so
714         //macht das SelNextMark() Sinn.
715         ESelection aSelection = pEditView->GetSelection();
716         aSelection.nEndPos  = aSelection.nStartPos;
717         aSelection.nEndPara = aSelection.nStartPara;
718 
719         DBG_ASSERT( pEditView, "NULL pointer" );
720         String  aText = String(SmResId(nCommand));
721         pEditView->InsertText(aText);
722 
723         if (HasMark(aText))
724         {   // set selection to next mark
725             pEditView->SetSelection(aSelection);
726             SelNextMark();
727         }
728         else
729         {   // set selection after inserted text
730             aSelection.nEndPos    = aSelection.nEndPos + sal::static_int_cast< xub_StrLen >(aText.Len());
731             aSelection.nStartPos  = aSelection.nEndPos;
732             pEditView->SetSelection(aSelection);
733         }
734 
735         aModifyTimer.Start();
736 		aCursorMoveTimer.Start();
737 
738         GrabFocus();
739     }
740 }
741 
742 void SmEditWindow::MarkError(const Point &rPos)
743 {
744     DBG_ASSERT( pEditView, "EditView missing" );
745     if (pEditView)
746     {
747         const xub_StrLen    nCol = sal::static_int_cast< xub_StrLen >(rPos.X());
748         const sal_uInt16        nRow = sal::static_int_cast< sal_uInt16 >(rPos.Y() - 1);
749 
750         pEditView->SetSelection(ESelection(nRow, nCol - 1, nRow, nCol));
751         GrabFocus();
752     }
753 }
754 
755 void SmEditWindow::SelNextMark()
756 {
757     EditEngine *pEditEngine = GetEditEngine();
758 	DBG_ASSERT( pEditView, "NULL pointer" );
759 	DBG_ASSERT( pEditEngine, "NULL pointer" );
760     if (pEditEngine  &&  pEditView)
761     {
762         ESelection eSelection = pEditView->GetSelection();
763         sal_uInt16     Pos        = eSelection.nEndPos;
764         String     aMark (C2S("<?>"));
765         String     aText;
766         sal_uInt16     nCounts    = pEditEngine->GetParagraphCount();
767 
768         while (eSelection.nEndPara < nCounts)
769         {
770             aText = pEditEngine->GetText( eSelection.nEndPara );
771             Pos   = aText.Search(aMark, Pos);
772 
773             if (Pos != STRING_NOTFOUND)
774             {
775                 pEditView->SetSelection(ESelection (eSelection.nEndPara, Pos, eSelection.nEndPara, Pos + 3));
776                 break;
777             }
778 
779             Pos = 0;
780             eSelection.nEndPara++;
781         }
782     }
783 }
784 
785 void SmEditWindow::SelPrevMark()
786 {
787     EditEngine *pEditEngine = GetEditEngine();
788 	DBG_ASSERT( pEditEngine, "NULL pointer" );
789 	DBG_ASSERT( pEditView, "NULL pointer" );
790     if (pEditEngine  &&  pEditView)
791     {
792         ESelection eSelection = pEditView->GetSelection();
793         sal_uInt16     Pos        = STRING_NOTFOUND;
794         xub_StrLen Max        = eSelection.nStartPos;
795         String     Text( pEditEngine->GetText( eSelection.nStartPara ) );
796         String     aMark (C2S("<?>"));
797         sal_uInt16     nCounts    = pEditEngine->GetParagraphCount();
798 
799         do
800         {
801             sal_uInt16 Fnd = Text.Search(aMark, 0);
802 
803             while ((Fnd < Max) && (Fnd != STRING_NOTFOUND))
804             {
805                 Pos = Fnd;
806                 Fnd = Text.Search(aMark, Fnd + 1);
807             }
808 
809             if (Pos == STRING_NOTFOUND)
810             {
811                 eSelection.nStartPara--;
812                 Text = pEditEngine->GetText( eSelection.nStartPara );
813                 Max = Text.Len();
814             }
815         }
816         while ((eSelection.nStartPara < nCounts) &&
817             (Pos == STRING_NOTFOUND));
818 
819         if (Pos != STRING_NOTFOUND)
820         {
821             pEditView->SetSelection(ESelection (eSelection.nStartPara, Pos, eSelection.nStartPara, Pos + 3));
822         }
823     }
824 }
825 
826 sal_Bool SmEditWindow::HasMark(const String& rText) const
827 	// returns true iff 'rText' contains a mark
828 {
829 	return rText.SearchAscii("<?>", 0) != STRING_NOTFOUND;
830 }
831 
832 void SmEditWindow::MouseMove(const MouseEvent &rEvt)
833 {
834 	if (pEditView)
835 		pEditView->MouseMove(rEvt);
836 }
837 
838 sal_Int8 SmEditWindow::AcceptDrop( const AcceptDropEvent& /*rEvt*/ )
839 {
840 	return pEditView ? /*pEditView->QueryDrop( rEvt )*/DND_ACTION_NONE: DND_ACTION_NONE;
841 }
842 
843 sal_Int8 SmEditWindow::ExecuteDrop( const ExecuteDropEvent& /*rEvt*/ )
844 {
845 	return pEditView ? /*pEditView->Drop( rEvt )*/DND_ACTION_NONE : DND_ACTION_NONE;
846 }
847 
848 ESelection SmEditWindow::GetSelection() const
849 {
850     // pointer may be 0 when reloading a document and the old view
851     // was already destroyed
852     //(DBG_ASSERT( pEditView, "NULL pointer" );
853 	ESelection eSel;
854 	if (pEditView)
855 		eSel = pEditView->GetSelection();
856 	return eSel;
857 }
858 
859 void SmEditWindow::SetSelection(const ESelection &rSel)
860 {
861 	DBG_ASSERT( pEditView, "NULL pointer" );
862     if (pEditView)
863         pEditView->SetSelection(rSel);
864 	InvalidateSlots();
865 }
866 
867 sal_Bool SmEditWindow::IsEmpty() const
868 {
869     EditEngine *pEditEngine = ((SmEditWindow *) this)->GetEditEngine();
870     sal_Bool bEmpty = sal::static_int_cast< sal_Bool >(
871                     pEditEngine ? pEditEngine->GetTextLen() == 0 : sal_False);
872     return bEmpty;
873 }
874 
875 sal_Bool SmEditWindow::IsSelected() const
876 {
877     return pEditView ? pEditView->HasSelection() : sal_False;
878 }
879 
880 void SmEditWindow::Cut()
881 {
882     DBG_ASSERT( pEditView, "EditView missing" );
883     if (pEditView)
884     {
885         pEditView->Cut();
886         GetDoc()->SetModified( sal_True );
887     }
888 }
889 
890 void SmEditWindow::Copy()
891 {
892     DBG_ASSERT( pEditView, "EditView missing" );
893     if (pEditView)
894         pEditView->Copy();
895 }
896 
897 void SmEditWindow::Paste()
898 {
899     DBG_ASSERT( pEditView, "EditView missing" );
900     if (pEditView)
901     {
902         pEditView->Paste();
903         GetDoc()->SetModified( sal_True );
904     }
905 }
906 
907 void SmEditWindow::Delete()
908 {
909     DBG_ASSERT( pEditView, "EditView missing" );
910     if (pEditView)
911     {
912         pEditView->DeleteSelected();
913         GetDoc()->SetModified( sal_True );
914     }
915 }
916 
917 void SmEditWindow::InsertText(const String& Text)
918 {
919     DBG_ASSERT( pEditView, "EditView missing" );
920     if (pEditView)
921     {
922         pEditView->InsertText(Text);
923         aModifyTimer.Start();
924 		aCursorMoveTimer.Start();
925     }
926 }
927 
928 void SmEditWindow::Flush()
929 {
930     EditEngine *pEditEngine = GetEditEngine();
931 	if (pEditEngine  &&  pEditEngine->IsModified())
932 	{
933 		pEditEngine->ClearModifyFlag();
934         SmViewShell *pViewSh = rCmdBox.GetView();
935 		if (pViewSh)
936         {
937 			pViewSh->GetViewFrame()->GetDispatcher()->Execute(
938 					SID_TEXT, SFX_CALLMODE_STANDARD,
939 					new SfxStringItem(SID_TEXT, GetText()), 0L);
940         }
941 	}
942 
943 	if (aCursorMoveTimer.IsActive())
944 	{
945 		aCursorMoveTimer.Stop();
946 		// ggf noch die (neue) FormulaCursor Position setzen
947 		CursorMoveTimerHdl(&aCursorMoveTimer);
948 	}
949 }
950 
951 
952 void SmEditWindow::DeleteEditView( SmViewShell & /*rView*/ )
953 {
954     if (pEditView)
955     {
956         EditEngine *pEditEngine = pEditView->GetEditEngine();
957         if (pEditEngine)
958         {
959             pEditEngine->SetStatusEventHdl( Link() );
960             pEditEngine->RemoveView( pEditView );
961         }
962         delete pEditView;
963         pEditView = 0;
964     }
965 }
966 
967 
968 uno::Reference< XAccessible > SmEditWindow::CreateAccessible()
969 {
970     if (!pAccessible)
971     {
972         pAccessible = new SmEditAccessible( this );
973         xAccessible = pAccessible;
974         pAccessible->Init();
975     }
976     return xAccessible;
977 }
978 
979