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