[ooo-build-commit] .: 6 commits - patches/dev300
Cédric Bosdonnat
cbosdo at kemper.freedesktop.org
Wed Sep 22 12:41:47 PDT 2010
patches/dev300/apply | 8
patches/dev300/maths_baseline_fix.diff | 835 +++
patches/dev300/online_gallery.diff | 2307 +++++++++
patches/dev300/sc-single-right.diff | 603 ++
patches/dev300/sd_effects_styles.diff | 3821 +++++++++++++++
patches/dev300/symbols-20-august.diff | 238
patches/dev300/vEdit-13-August.diff | 7896 +++++++++++++++++++++++++++++++++
7 files changed, 15707 insertions(+), 1 deletion(-)
New commits:
commit b0bb9d72d1756b5fde48abba5dee4cc5b95cf277
Author: Cédric Bosdonnat <cedricbosdo at openoffice.org>
Date: Wed Sep 22 21:40:51 2010 +0200
Added the GSoc student's patches to their section
diff --git a/patches/dev300/apply b/patches/dev300/apply
index e253e41..73e91ce 100644
--- a/patches/dev300/apply
+++ b/patches/dev300/apply
@@ -2954,9 +2954,15 @@ oox-pptx-import-fix-groups-2.diff, n#619678, rodo
# soffice process doesn't block ( under linux ) connect
# to raised office instance instead ( should work for windows too )
smoketest-officeconnection-fix.diff
-[ GSoC2010 ]
+[ GSoC2010 ]
# Patches from GSoC 2010 students.
+maths_baseline_fix.diff, i#972, spiso
+online_gallery.diff, tijana
+sc-single-right.diff, td123
+sd_effects_styles.diff, pixie
+symbols-20-august.diff, i#11167, jopsen
+vEdit-13-August.diff, jopsen
[ OOXML ]
oox-pptx-import-fix-placeholder-text-style.diff, n#592906, n#479834, rodo
commit ccc534c27bc51526a291e21797ac337a7a695346
Author: Thomas Dziedzic <tdziedz2 at illinois.edu>
Date: Wed Sep 22 21:40:32 2010 +0200
Pushed Thomas' patch AS IS
diff --git a/patches/dev300/sc-single-right.diff b/patches/dev300/sc-single-right.diff
new file mode 100644
index 0000000..51f54e4
--- /dev/null
+++ b/patches/dev300/sc-single-right.diff
@@ -0,0 +1,603 @@
+--- sc/source/ui/view/gridwin.cxx.orig2 2010-08-10 11:27:53.922000033 -0500
++++ sc/source/ui/view/gridwin.cxx 2010-08-15 22:09:59.868000093 -0500
+@@ -123,6 +123,8 @@
+ #include "cellsh.hxx"
+ #include "overlayobject.hxx"
+
++#include "popmenu.hxx"
++
+ #include "drawview.hxx"
+ #include <svx/sdrpagewindow.hxx>
+ #include <svx/sdr/overlay/overlaymanager.hxx>
+@@ -449,7 +451,8 @@
+ nPaintCount( 0 ),
+ bNeedsRepaint( FALSE ),
+ bAutoMarkVisible( FALSE ),
+- bListValButton( FALSE )
++ bListValButton( FALSE ),
++ bMoveSingle( false )
+ {
+ switch(eWhich)
+ {
+@@ -1512,6 +1515,29 @@
+
+ aCurMousePos = rMEvt.GetPosPixel();
+
++ std::vector<Rectangle> aPixelRects;
++ GetSelectionRects( aPixelRects );
++
++ // is there a better way to test if the selected rectangle is only 1 cell
++ BOOL test;
++ std::vector<Rectangle>::iterator it = aPixelRects.begin();
++ if( aPixelRects.size() )
++ test = it->Top() == it->Bottom() && it->Left() == it->Right();
++
++ ScRange aRange;
++ ScMarkType eMarkType = pViewData->GetSimpleArea( aRange );
++
++ if( bMoveSingle && /*rMEvt.IsLeft() &&*/ ( ( eMarkType != SC_MARK_MULTI && test ) || !pViewData->GetMarkData().IsMarked() ) )
++ {
++ //bMoveSingle = false;
++
++ SCCOL nCol = pViewData->GetCurX();
++ SCROW nRow = pViewData->GetCurY();
++ SCTAB nTab = pViewData->GetTabNo();
++
++ pViewData->GetView()->MarkCursor( nCol, nRow, nTab );
++ }
++
+ // Filter-Popup beendet sich mit eigenem Mausklick, nicht erst beim Klick
+ // in das GridWindow, darum ist die folgende Abfrage nicht mehr noetig:
+ #if 0
+@@ -1783,7 +1809,7 @@
+ // Gridwin - SelectionEngine
+ //
+
+- if ( rMEvt.IsLeft() )
++ if ( rMEvt.IsLeft() || ( rMEvt.IsRight() && bMoveSingle ) )
+ {
+ ScViewSelectionEngine* pSelEng = pViewData->GetView()->GetSelEngine();
+ pSelEng->SetWindow(this);
+@@ -2257,6 +2283,8 @@
+
+ void __EXPORT ScGridWindow::MouseMove( const MouseEvent& rMEvt )
+ {
++ bMoveSingle = false;
++
+ aCurMousePos = rMEvt.GetPosPixel();
+
+ if ( rMEvt.IsLeaveWindow() && pNoteMarker && !pNoteMarker->IsByKeyboard() )
+@@ -2446,14 +2474,48 @@
+ {
+ BOOL bAlt = rMEvt.IsMod2();
+
++ //ScMarkData& rMark = pViewData->GetMarkData();
++ //EditView* pEditView = pViewData->GetEditView( eWhich );
++ //Cursor* pCur = pEditView->GetCursor();
++ //SCTAB nTab = pViewData->GetTabNo();
++ SCCOL nX = pViewData->GetCurX();
++ SCROW nY = pViewData->GetCurY();
++ Point aScrPos = pViewData->GetScrPos( nX, nY, eWhich, TRUE );
++
++ long nSizeXPix;
++ long nSizeYPix;
++
++ // get dimensions of cursor
++ pViewData->GetMergeSizePixel( nX, nY, nSizeXPix, nSizeYPix );
++
++
++ BOOL bLeft = ((aCurMousePos.X() >= aScrPos.X() && aCurMousePos.X() <= aScrPos.X() + 1) && aCurMousePos.Y() >= aScrPos.Y() && aCurMousePos.Y() <= aScrPos.Y() + nSizeYPix );
++ BOOL bTop = ((aCurMousePos.Y() >= aScrPos.Y() && aCurMousePos.Y() <= aScrPos.Y() + 1) && aCurMousePos.X() >= aScrPos.X() && aCurMousePos.X() <= aScrPos.X() + nSizeXPix );
++ // bottom and right borders actually count as the next cells that's why we do == instead of by range
++ // need to fix checking if click is on border but changes to a different cell or is this desireable?
++ BOOL bBottom = ((aCurMousePos.Y() == aScrPos.Y() + nSizeYPix - 1) &&
++ aCurMousePos.X() >= aScrPos.X() && aCurMousePos.X() <= aScrPos.X() + nSizeXPix );
++ BOOL bRight = ((aCurMousePos.X() == aScrPos.X() + nSizeXPix - 1) &&
++ aCurMousePos.Y() >= aScrPos.Y() && aCurMousePos.Y() <= aScrPos.Y() + nSizeYPix );
++ //BOOL bBottom = ((aCurMousePos.Y() >= aScrPos.Y() + nSizeYPix - 1 && aCurMousePos.Y() <= aScrPos.Y() + nSizeYPix + 1) &&
++ // aCurMousePos.X() >= aScrPos.X() && aCurMousePos.X() <= aScrPos.X() + nSizeXPix );
++ //BOOL bRight = ((aCurMousePos.X() >= aScrPos.X() + nSizeXPix - 1 && aCurMousePos.X() <= aScrPos.X() + nSizeXPix + 1) &&
++ // aCurMousePos.Y() >= aScrPos.Y() && aCurMousePos.Y() <= aScrPos.Y() + nSizeYPix );
++
+ if (bEditMode) // Edit-Mode muss zuerst kommen!
+ SetPointer( Pointer( POINTER_ARROW ) );
+- else if ( !bAlt && !nButtonDown &&
+- GetEditUrl(rMEvt.GetPosPixel()) )
++ else if ( !bAlt && !nButtonDown && GetEditUrl(rMEvt.GetPosPixel()) )
+ SetPointer( Pointer( POINTER_REFHAND ) );
++ else if ( ( bLeft || bTop || bBottom || bRight ) )
++ {
++ SetPointer( Pointer( POINTER_MOVE ) );
++ bMoveSingle = TRUE;
++ return;
++ }
+ else if ( DrawMouseMove(rMEvt) ) // setzt Pointer um
+ return;
+ }
++
+ }
+
+ if ( pViewData->GetView()->GetSelEngine()->SelMouseMove( rMEvt ) )
+@@ -2765,6 +2827,12 @@
+
+ if ( nCmd == COMMAND_CONTEXTMENU && !SC_MOD()->GetIsWaterCan() )
+ {
++ // don't display context menu when we are over the cursor border, to implement right click dragging
++ if (bMoveSingle)
++ {
++ return;
++ }
++
+ if (pViewData->IsAnyFillMode())
+ {
+ pViewData->GetView()->StopRefMode();
+@@ -3832,11 +3900,11 @@
+ const ScDragData& rData = pScMod->GetDragData();
+
+ return DropTransferObj( rData.pCellTransfer, nDragStartX, nDragStartY,
+- PixelToLogic(rEvt.maPosPixel), rEvt.mnAction );
++ PixelToLogic(rEvt.maPosPixel), rEvt.maPosPixel, rEvt.mnAction );
+ }
+
+ sal_Int8 ScGridWindow::DropTransferObj( ScTransferObj* pTransObj, SCCOL nDestPosX, SCROW nDestPosY,
+- const Point& rLogicPos, sal_Int8 nDndAction )
++ const Point& rLogicPos, const Point& rMousePos, sal_Int8 nDndAction )
+ {
+ if ( !pTransObj )
+ return 0;
+@@ -3859,6 +3927,8 @@
+ bIsMove = ( nDndAction & DND_ACTION_MOVE && !bIsNavi );
+ }
+
++ bool bIsRight = ( nDndAction == DND_ACTION_RIGHT && !bIsNavi );
++
+ BOOL bIsLink = ( nDndAction == DND_ACTION_LINK );
+
+ ScRange aSource = pTransObj->GetRange();
+@@ -3949,6 +4019,7 @@
+ {
+ // call with bApi = TRUE to avoid error messages in drop handler
+ bDone = pDocSh->GetDocFunc().InsertCells( aDest, NULL, meDragInsertMode, TRUE /*bRecord*/, TRUE /*bApi*/, TRUE /*bPartOfPaste*/ );
++
+ if ( bDone )
+ {
+ if ( nThisTab == nSourceTab )
+@@ -3976,6 +4047,195 @@
+ // call with bApi = TRUE to avoid error messages in drop handler
+ bDone = pView->LinkBlock( aSource, aDest.aStart, TRUE /*bApi*/ );
+ }
++ else if ( bIsRight )
++ {
++ ScPopupMenu maPopup(ScResId( RID_POPUP_RIGHTDRAGDROP ));
++
++ // GetMousePosPixel() returns the position from the start of the drag.. need to fix this, workaround segfaults :S
++ //EditView* pEditView = pViewData->GetEditView( eWhich );
++ //Cursor* pCur = pEditView->GetCursor();
++ sal_uInt16 nItemId = maPopup.Execute( this, rMousePos);//Point(nDestPosX * pCur->GetWidth(), nDestPosY * pCur->GetHeight() )); //GetMousePosPixel()); //Point(nDestPosX, nDestPosY));
++
++ //maPopup.Execute(pViewData->GetView()->GetWindowByPos( eWhich ), Point(0,0));/*rLogicPos);*/
++
++ // follow excel's format for now
++ switch ( nItemId )
++ {
++ case RID_RIGHTDRAGDROP_MOVE:
++ // Move Here
++ bIsMove = TRUE;
++ bDone = pView->MoveBlockTo( aSource, aDest.aStart, bIsMove, TRUE /*bRecord*/, TRUE /*bPaint*/, TRUE /*bApi*/ );
++ break;
++
++ case RID_RIGHTDRAGDROP_COPY:
++ // Copy Here
++ bIsMove = FALSE;
++ bDone = pView->MoveBlockTo( aSource, aDest.aStart, bIsMove, TRUE /*bRecord*/, TRUE /*bPaint*/, TRUE /*bApi*/ );
++ break;
++
++ case RID_RIGHTDRAGDROP_COPYVALUES:
++ // Copy Here as Values Only
++ break;
++
++ case RID_RIGHTDRAGDROP_COPYFORMATS:
++ // Copy Here as Formats Only
++ break;
++
++ case RID_RIGHTDRAGDROP_LINK:
++ // Link Here
++ bIsLink = TRUE;
++ bDone = pView->LinkBlock( aSource, aDest.aStart, TRUE /*bApi*/ );
++ break;
++
++ case RID_RIGHTDRAGDROP_HYPERLINK:
++ // Create Hyperlink Here
++ break;
++
++ case RID_RIGHTDRAGDROP_SHIFTDOWNC:
++ // Shift Down and Copy
++ meDragInsertMode = INS_CELLSDOWN;
++ aUndo = ScGlobal::GetRscString( bIsMove ? STR_UNDO_MOVE : STR_UNDO_COPY );
++ pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo );
++
++ bDone = TRUE;
++ bIsMove = FALSE;
++ if ( meDragInsertMode != INS_NONE )
++ {
++ // call with bApi = TRUE to avoid error messages in drop handler
++ bDone = pDocSh->GetDocFunc().InsertCells( aDest, NULL, meDragInsertMode, TRUE /*bRecord*/, TRUE /*bApi*/, TRUE /*bPartOfPaste*/ );
++ if ( bDone )
++ {
++ if ( nThisTab == nSourceTab )
++ {
++ if ( meDragInsertMode == INS_CELLSDOWN &&
++ nDestPosX == aSource.aStart.Col() && nDestPosY < aSource.aStart.Row() )
++ {
++ bDone = aSource.Move( 0, nSizeY, 0, pSourceDoc );
++ }
++ else if ( meDragInsertMode == INS_CELLSRIGHT &&
++ nDestPosY == aSource.aStart.Row() && nDestPosX < aSource.aStart.Col() )
++ {
++ bDone = aSource.Move( nSizeX, 0, 0, pSourceDoc );
++ }
++ }
++ pDocSh->UpdateOle( pViewData );
++ pView->CellContentChanged();
++ }
++ }
++ bDone = pView->MoveBlockTo( aSource, aDest.aStart, bIsMove, TRUE /*bRecord*/, TRUE /*bPaint*/, TRUE /*bApi*/ );
++ break;
++
++ case RID_RIGHTDRAGDROP_SHIFTRIGHTC:
++ // Shift Right and Copy
++ meDragInsertMode = INS_CELLSRIGHT;
++ aUndo = ScGlobal::GetRscString( bIsMove ? STR_UNDO_MOVE : STR_UNDO_COPY );
++ pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo );
++
++ bDone = TRUE;
++ bIsMove = FALSE;
++ if ( meDragInsertMode != INS_NONE )
++ {
++ // call with bApi = TRUE to avoid error messages in drop handler
++ bDone = pDocSh->GetDocFunc().InsertCells( aDest, NULL, meDragInsertMode, TRUE /*bRecord*/, TRUE /*bApi*/, TRUE /*bPartOfPaste*/ );
++ if ( bDone )
++ {
++ if ( nThisTab == nSourceTab )
++ {
++ if ( meDragInsertMode == INS_CELLSDOWN &&
++ nDestPosX == aSource.aStart.Col() && nDestPosY < aSource.aStart.Row() )
++ {
++ bDone = aSource.Move( 0, nSizeY, 0, pSourceDoc );
++ }
++ else if ( meDragInsertMode == INS_CELLSRIGHT &&
++ nDestPosY == aSource.aStart.Row() && nDestPosX < aSource.aStart.Col() )
++ {
++ bDone = aSource.Move( nSizeX, 0, 0, pSourceDoc );
++ }
++ }
++ pDocSh->UpdateOle( pViewData );
++ pView->CellContentChanged();
++ }
++ }
++ bDone = pView->MoveBlockTo( aSource, aDest.aStart, bIsMove, TRUE /*bRecord*/, TRUE /*bPaint*/, TRUE /*bApi*/ );
++ break;
++
++ case RID_RIGHTDRAGDROP_SHIFTDOWNM:
++ // Shift Down and Move
++ meDragInsertMode = INS_CELLSDOWN;
++ aUndo = ScGlobal::GetRscString( bIsMove ? STR_UNDO_MOVE : STR_UNDO_COPY );
++ pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo );
++
++ bDone = TRUE;
++ bIsMove = TRUE;
++ if ( meDragInsertMode != INS_NONE )
++ {
++ // call with bApi = TRUE to avoid error messages in drop handler
++ bDone = pDocSh->GetDocFunc().InsertCells( aDest, NULL, meDragInsertMode, TRUE /*bRecord*/, TRUE /*bApi*/, TRUE /*bPartOfPaste*/ );
++ if ( bDone )
++ {
++ if ( nThisTab == nSourceTab )
++ {
++ if ( meDragInsertMode == INS_CELLSDOWN &&
++ nDestPosX == aSource.aStart.Col() && nDestPosY < aSource.aStart.Row() )
++ {
++ bDone = aSource.Move( 0, nSizeY, 0, pSourceDoc );
++ }
++ else if ( meDragInsertMode == INS_CELLSRIGHT &&
++ nDestPosY == aSource.aStart.Row() && nDestPosX < aSource.aStart.Col() )
++ {
++ bDone = aSource.Move( nSizeX, 0, 0, pSourceDoc );
++ }
++ }
++ pDocSh->UpdateOle( pViewData );
++ pView->CellContentChanged();
++ }
++ }
++ bDone = pView->MoveBlockTo( aSource, aDest.aStart, bIsMove, TRUE /*bRecord*/, TRUE /*bPaint*/, TRUE /*bApi*/ );
++ break;
++
++ case RID_RIGHTDRAGDROP_SHIFTRIGHTM:
++ // Shift Right and Move
++ meDragInsertMode = INS_CELLSRIGHT;
++ aUndo = ScGlobal::GetRscString( bIsMove ? STR_UNDO_MOVE : STR_UNDO_COPY );
++ pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo );
++
++ bDone = TRUE;
++ bIsMove = TRUE;
++ if ( meDragInsertMode != INS_NONE )
++ {
++ // call with bApi = TRUE to avoid error messages in drop handler
++ bDone = pDocSh->GetDocFunc().InsertCells( aDest, NULL, meDragInsertMode, TRUE /*bRecord*/, TRUE /*bApi*/, TRUE /*bPartOfPaste*/ );
++ if ( bDone )
++ {
++ if ( nThisTab == nSourceTab )
++ {
++ if ( meDragInsertMode == INS_CELLSDOWN &&
++ nDestPosX == aSource.aStart.Col() && nDestPosY < aSource.aStart.Row() )
++ {
++ bDone = aSource.Move( 0, nSizeY, 0, pSourceDoc );
++ }
++ else if ( meDragInsertMode == INS_CELLSRIGHT &&
++ nDestPosY == aSource.aStart.Row() && nDestPosX < aSource.aStart.Col() )
++ {
++ bDone = aSource.Move( nSizeX, 0, 0, pSourceDoc );
++ }
++ }
++ pDocSh->UpdateOle( pViewData );
++ pView->CellContentChanged();
++ }
++ }
++ bDone = pView->MoveBlockTo( aSource, aDest.aStart, bIsMove, TRUE /*bRecord*/, TRUE /*bPaint*/, TRUE /*bApi*/ );
++ break;
++
++ case 0:
++ // nothing selected
++ case RID_RIGHTDRAGDROP_CANCEL:
++ // Cancel
++ default:
++ // Need to return DND_ACTION_NONE to prevent moving the shaded area if nothing is to be done.
++ return DND_ACTION_NONE;
++ }
++ }
+ else
+ {
+ // call with bApi = TRUE to avoid error messages in drop handler
+@@ -4317,7 +4577,7 @@
+ {
+ // keep a reference to the data in case the selection is changed during paste
+ uno::Reference<datatransfer::XTransferable> xRef( pCellTransfer );
+- DropTransferObj( pCellTransfer, nPosX, nPosY, aLogicPos, DND_ACTION_COPY );
++ DropTransferObj( pCellTransfer, nPosX, nPosY, aLogicPos, rPosPixel, DND_ACTION_COPY );
+ }
+ else
+ {
+--- sc/source/ui/inc/gridwin.hxx.orig2 2010-08-16 21:54:09.998000096 -0500
++++ sc/source/ui/inc/gridwin.hxx 2010-08-16 21:54:18.584000098 -0500
+@@ -116,6 +116,8 @@
+
+ ::boost::shared_ptr<Rectangle> mpAutoFillRect;
+
++ bool bMoveSingle;
++
+ /**
+ * Stores current visible column and row ranges, used to avoid expensive
+ * operations on objects that are outside visible area.
+--- sc/inc/sc.hrc.orig2 2010-08-14 09:16:59.107000093 -0500
++++ sc/inc/sc.hrc 2010-08-14 09:31:40.135000093 -0500
+@@ -1643,6 +1643,21 @@
+
+ #define SC_DIALOGS_END (SC_DIALOGS_START + 155)
+
++// Popup for right dragging.
++#define RID_POPUP_RIGHTDRAGDROP (SC_DIALOGS_START + 156)
++#define RID_RIGHTDRAGDROP_MOVE (SC_DIALOGS_START + 157)
++#define RID_RIGHTDRAGDROP_COPY (SC_DIALOGS_START + 158)
++#define RID_RIGHTDRAGDROP_COPYVALUES (SC_DIALOGS_START + 159)
++#define RID_RIGHTDRAGDROP_COPYFORMATS (SC_DIALOGS_START + 160)
++#define RID_RIGHTDRAGDROP_LINK (SC_DIALOGS_START + 161)
++#define RID_RIGHTDRAGDROP_HYPERLINK (SC_DIALOGS_START + 162)
++#define RID_RIGHTDRAGDROP_SHIFTDOWNC (SC_DIALOGS_START + 163)
++#define RID_RIGHTDRAGDROP_SHIFTRIGHTC (SC_DIALOGS_START + 164)
++#define RID_RIGHTDRAGDROP_SHIFTDOWNM (SC_DIALOGS_START + 165)
++#define RID_RIGHTDRAGDROP_SHIFTRIGHTM (SC_DIALOGS_START + 166)
++#define RID_RIGHTDRAGDROP_CANCEL (SC_DIALOGS_START + 167)
++
++
+ #ifndef STD_MASKCOLOR
+ #define STD_MASKCOLOR Color { Red = 0xFF00; Green = 0x0000; Blue = 0xFF00; }
+ #endif
+--- sc/source/ui/navipi/navipi.src.orig2 2010-08-14 09:36:21.672000092 -0500
++++ sc/source/ui/navipi/navipi.src 2010-08-15 17:25:02.982000089 -0500
+@@ -370,45 +370,70 @@
+ };
+ };
+ };
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
++Menu RID_POPUP_RIGHTDRAGDROP
++{
++ ItemList =
++ {
++ MenuItem
++ {
++ Identifier = RID_RIGHTDRAGDROP_MOVE ;
++ Text [ en-US ] = "Move Here" ;
++ };
++ MenuItem
++ {
++ Identifier = RID_RIGHTDRAGDROP_COPY ;
++ Text [ en-US ] = "Copy Here" ;
++ };
++ //MenuItem
++ //{
++ // Identifier = RID_RIGHTDRAGDROP_COPYVALUES ;
++ // Text [ en-US ] = "Copy Here as Values Only" ;
++ //};
++ //MenuItem
++ //{
++ // Identifier = RID_RIGHTDRAGDROP_COPYFORMATS ;
++ // Text [ en-US ] = "Copy Here as Formats Only" ;
++ //};
++ MenuItem
++ {
++ Identifier = RID_RIGHTDRAGDROP_LINK ;
++ Text [ en-US ] = "Link Here" ;
++ };
++ //MenuItem
++ //{
++ // Identifier = RID_RIGHTDRAGDROP_HYPERLINK ;
++ // Text [ en-US ] = "Create Hyperlink Here" ;
++ //};
++ //////////////////////////////////////////////////
++ MenuItem { Separator = TRUE ; };
++ //////////////////////////////////////////////////
++ MenuItem
++ {
++ Identifier = RID_RIGHTDRAGDROP_SHIFTDOWNC ;
++ Text [ en-US ] = "Shift Down and Copy" ;
++ };
++ MenuItem
++ {
++ Identifier = RID_RIGHTDRAGDROP_SHIFTRIGHTC ;
++ Text [ en-US ] = "Shift Right and Copy" ;
++ };
++ MenuItem
++ {
++ Identifier = RID_RIGHTDRAGDROP_SHIFTDOWNM ;
++ Text [ en-US ] = "Shift Down and Move" ;
++ };
++ MenuItem
++ {
++ Identifier = RID_RIGHTDRAGDROP_SHIFTRIGHTM ;
++ Text [ en-US ] = "Shift Right and Move" ;
++ };
++ //////////////////////////////////////////////////
++ MenuItem { Separator = TRUE ; };
++ //////////////////////////////////////////////////
++ MenuItem
++ {
++ Identifier = RID_RIGHTDRAGDROP_CANCEL ;
++ Text [ en-US ] = "Cancel" ;
++ };
++ };
++};
+--- vcl/source/window/seleng.cxx.orig2 2010-08-10 11:35:56.392000035 -0500
++++ vcl/source/window/seleng.cxx 2010-08-14 08:20:22.702000092 -0500
+@@ -202,7 +202,7 @@
+ BOOL SelectionEngine::SelMouseButtonDown( const MouseEvent& rMEvt )
+ {
+ nFlags &= (~SELENG_CMDEVT);
+- if ( !pFunctionSet || !pWin || rMEvt.GetClicks() > 1 || rMEvt.IsRight() )
++ if ( !pFunctionSet || !pWin || rMEvt.GetClicks() > 1)
+ return FALSE;
+
+ USHORT nModifier = rMEvt.GetModifier() | nLockedMods;
+--- vcl/source/window/winproc.cxx.orig2 2010-08-12 20:54:52.205000092 -0500
++++ vcl/source/window/winproc.cxx 2010-08-13 23:26:41.251000089 -0500
+@@ -546,8 +546,8 @@
+ // den Status der Maustasten, damit man mit Mod1 z.B. sofort
+ // in den Kopiermodus gehen kann.
+ const MouseSettings& rMSettings = pMouseDownWin->GetSettings().GetMouseSettings();
+- if ( (nCode & (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE)) ==
+- (rMSettings.GetStartDragCode() & (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE)) )
++ if ( ( (nCode & (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE)) ==
++ (rMSettings.GetStartDragCode() & (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE)) ) || ( nCode & MOUSE_RIGHT ) )
+ {
+ if ( !pMouseDownWin->ImplGetFrameData()->mbStartDragCalled )
+ {
+@@ -697,8 +697,8 @@
+ pChild->ImplGetFrameData()->mnFirstMouseX = nMouseX;
+ pChild->ImplGetFrameData()->mnFirstMouseY = nMouseY;
+ pChild->ImplGetFrameData()->mnFirstMouseCode = nCode;
+- pChild->ImplGetFrameData()->mbStartDragCalled = !((nCode & (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE)) ==
+- (rMSettings.GetStartDragCode() & (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE)));
++ pChild->ImplGetFrameData()->mbStartDragCalled = !( ((nCode & (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE)) ==
++ (rMSettings.GetStartDragCode() & (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE))) || ( nCode & MOUSE_RIGHT ) );
+ }
+ pChild->ImplGetFrameData()->mnMouseDownTime = nMsgTime;
+ }
+--- vcl/unx/source/dtrans/X11_selection.cxx.orig2 2010-08-13 21:04:01.229000093 -0500
++++ vcl/unx/source/dtrans/X11_selection.cxx 2010-08-14 08:22:34.206000092 -0500
+@@ -2763,9 +2763,10 @@
+ sendDropPosition( true, rMessage.xkey.time );
+ }
+ }
+- else if(
++ else if((
+ ( rMessage.type == ButtonPress || rMessage.type == ButtonRelease ) &&
+- rMessage.xbutton.button == m_nDragButton )
++ rMessage.xbutton.button == m_nDragButton ) ||
++ ( rMessage.xbutton.button == Button3 ) )
+ {
+ bool bCancel = true;
+ if( m_aDropWindow != None )
+@@ -2783,7 +2784,7 @@
+ dtde.Context = new DropTargetDropContext( m_aCurrentDropWindow, m_nDropTimestamp, *this );
+ dtde.LocationX = x;
+ dtde.LocationY = y;
+- dtde.DropAction = m_nUserDragAction;
++ dtde.DropAction = ( rMessage.xbutton.button == Button3 ) ? DNDConstants::ACTION_RIGHT : m_nUserDragAction;
+ dtde.SourceActions = m_nSourceActions;
+ dtde.Transferable = m_xDragSourceTransferable;
+ m_bDropSent = true;
+--- svtools/inc/svtools/transfer.hxx.orig2 2010-08-14 00:03:15.653000092 -0500
++++ svtools/inc/svtools/transfer.hxx 2010-08-14 01:10:08.078000092 -0500
+@@ -73,6 +73,7 @@
+ #define DND_ACTION_MOVE ::com::sun::star::datatransfer::dnd::DNDConstants::ACTION_MOVE
+ #define DND_ACTION_COPYMOVE ::com::sun::star::datatransfer::dnd::DNDConstants::ACTION_COPY_OR_MOVE
+ #define DND_ACTION_LINK ::com::sun::star::datatransfer::dnd::DNDConstants::ACTION_LINK
++#define DND_ACTION_RIGHT ::com::sun::star::datatransfer::dnd::DNDConstants::ACTION_RIGHT
+
+ #define DND_POINTER_NONE 0
+ #define DND_IMAGE_NONE 0
+--- offapi/com/sun/star/datatransfer/dnd/DNDConstants.idl.orig2 2010-08-14 01:09:16.240000096 -0500
++++ offapi/com/sun/star/datatransfer/dnd/DNDConstants.idl 2010-08-14 01:09:23.002000093 -0500
+@@ -76,6 +76,12 @@
+ const byte ACTION_REFERENCE = 0x04;
+
+ //=============================================================================
++ /** Action for right click dragging.
++ */
++
++ const byte ACTION_RIGHT = 0x08;
++
++ //=============================================================================
+ /** Action default.
+ */
+
commit d6b73c9d63b02142b9d48d9fed1573912ee3705e
Author: Jonas Jensen <jopsen at gmail.com>
Date: Wed Sep 22 21:39:23 2010 +0200
Pushed Jonas' patches AS IS
diff --git a/patches/dev300/symbols-20-august.diff b/patches/dev300/symbols-20-august.diff
new file mode 100644
index 0000000..6d91994
--- /dev/null
+++ b/patches/dev300/symbols-20-august.diff
@@ -0,0 +1,238 @@
+diff --git extras/source/truetype/symbol/OpenSymbol.sfd extras/source/truetype/symbol/OpenSymbol.sfd
+index e04c03f..d6ecc95 100644
+--- extras/source/truetype/symbol/OpenSymbol.sfd
++++ extras/source/truetype/symbol/OpenSymbol.sfd
+@@ -13,13 +13,14 @@ Descent: 410
+ LayerCount: 2
+ Layer: 0 1 "Back" 1
+ Layer: 1 1 "Fore" 0
++NeedsXUIDChange: 1
+ XUID: [1021 161 2043615882 15846768]
+ FSType: 8
+ OS2Version: 0
+ OS2_WeightWidthSlopeOnly: 0
+ OS2_UseTypoMetrics: 1
+ CreationTime: 1144938807
+-ModificationTime: 1238168413
++ModificationTime: 1281980608
+ PfmFamily: 81
+ TTFWeight: 400
+ TTFWidth: 5
+@@ -591,8 +592,8 @@ NameList: Adobe Glyph List
+ DisplaySize: -24
+ AntiAlias: 1
+ FitToEm: 1
+-WinInfo: 0 45 18
+-BeginChars: 65539 912
++WinInfo: 135 45 18
++BeginChars: 65539 914
+
+ StartChar: .notdef
+ Encoding: 65536 -1 0
+@@ -100162,5 +100163,88 @@ SplineSet
+ EndSplineSet
+ Validated: 1
+ EndChar
++
++StartChar: uni27FC
++Encoding: 10236 10236 912
++Width: 2048
++VWidth: 0
++Flags: W
++LayerCount: 2
++Fore
++SplineSet
++120.605 893.365 m 0,0,1
++ 130.745 894.649 130.745 894.649 139.122 886.971 c 128,-1,2
++ 147.499 879.293 147.499 879.293 147.099 869.08 c 2,3,-1
++ 147.099 657.135 l 1,4,-1
++ 1753.62 657.135 l 1,5,6
++ 1721.36 678.613 1721.36 678.613 1692.21 706.222 c 128,-1,7
++ 1663.06 733.83 1663.06 733.83 1644.5 757.892 c 128,-1,8
++ 1625.94 781.953 1625.94 781.953 1611.99 802.947 c 128,-1,9
++ 1598.04 823.94 1598.04 823.94 1591.94 836.207 c 2,10,-1
++ 1585.83 848.475 l 1,11,12
++ 1580.32 857.07 1580.32 857.07 1583.64 867.92 c 128,-1,13
++ 1586.96 878.77 1586.96 878.77 1596.33 882.81 c 128,-1,14
++ 1605.71 886.85 1605.71 886.85 1615.88 881.814 c 128,-1,15
++ 1626.05 876.778 1626.05 876.778 1628.51 866.872 c 1,16,17
++ 1631.31 860.546 1631.31 860.546 1636.84 849.729 c 128,-1,18
++ 1642.37 838.911 1642.37 838.911 1662.49 809.124 c 128,-1,19
++ 1682.61 779.338 1682.61 779.338 1706.09 753.681 c 128,-1,20
++ 1729.56 728.024 1729.56 728.024 1768.64 699.899 c 128,-1,21
++ 1807.71 671.774 1807.71 671.774 1850.76 656.4 c 1,22,23
++ 1865.45 654.098 1865.45 654.098 1865.48 633.585 c 0,24,25
++ 1865.49 624.275 1865.49 624.275 1861.81 618.755 c 128,-1,26
++ 1858.13 613.236 1858.13 613.236 1854.45 612.371 c 2,27,-1
++ 1850.76 611.507 l 1,28,29
++ 1807.71 596.133 1807.71 596.133 1768.99 568.798 c 128,-1,30
++ 1730.26 541.464 1730.26 541.464 1705.74 513.434 c 128,-1,31
++ 1681.21 485.405 1681.21 485.405 1662.84 459.572 c 128,-1,32
++ 1644.47 433.739 1644.47 433.739 1636.49 417.386 c 2,33,-1
++ 1628.51 401.033 l 1,34,35
++ 1626.05 391.127 1626.05 391.127 1615.88 386.09 c 128,-1,36
++ 1605.71 381.053 1605.71 381.053 1596.33 385.093 c 128,-1,37
++ 1586.96 389.134 1586.96 389.134 1583.64 399.985 c 128,-1,38
++ 1580.32 410.837 1580.32 410.837 1585.83 419.432 c 0,39,40
++ 1587.95 424.066 1587.95 424.066 1592.14 432.201 c 128,-1,41
++ 1596.33 440.337 1596.33 440.337 1611.48 464.117 c 128,-1,42
++ 1626.63 487.897 1626.63 487.897 1644.23 510.113 c 128,-1,43
++ 1661.82 532.328 1661.82 532.328 1690.99 560.441 c 128,-1,44
++ 1720.15 588.555 1720.15 588.555 1752.15 610.037 c 1,45,-1
++ 147.099 610.037 l 1,46,-1
++ 147.099 398.091 l 2,47,48
++ 147.231 388.76 147.231 388.76 140.056 381.483 c 128,-1,49
++ 132.882 374.206 132.882 374.206 123.55 374.206 c 128,-1,50
++ 114.217 374.206 114.217 374.206 107.042 381.483 c 128,-1,51
++ 99.8674 388.76 99.8674 388.76 100 398.091 c 2,52,-1
++ 100 629.171 l 2,53,54
++ 99.1577 633.586 99.1577 633.586 100 638.002 c 2,55,-1
++ 100 869.082 l 2,56,57
++ 99.6602 877.819 99.6602 877.819 105.795 885.049 c 128,-1,58
++ 111.93 892.279 111.93 892.279 120.605 893.365 c 0,0,1
++EndSplineSet
++EndChar
++
++StartChar: uni2312
++Encoding: 8978 8978 913
++Width: 760
++VWidth: 0
++Flags: W
++LayerCount: 2
++Fore
++SplineSet
++30.002 1123.25 m 1,0,1
++ 30.002 1218.06 30.002 1218.06 76.9414 1298.72 c 128,-1,2
++ 123.88 1379.38 123.88 1379.38 204.536 1426.31 c 128,-1,3
++ 285.192 1473.25 285.192 1473.25 380.001 1473.25 c 128,-1,4
++ 474.809 1473.25 474.809 1473.25 555.465 1426.31 c 128,-1,5
++ 636.121 1379.38 636.121 1379.38 683.061 1298.72 c 128,-1,6
++ 730 1218.06 730 1218.06 730 1123.25 c 1,7,-1
++ 643.486 1123.25 l 1,8,9
++ 643.486 1232.78 643.486 1232.78 566.506 1309.76 c 128,-1,10
++ 489.525 1386.74 489.525 1386.74 380.001 1386.74 c 128,-1,11
++ 270.477 1386.74 270.477 1386.74 193.496 1309.76 c 128,-1,12
++ 116.515 1232.78 116.515 1232.78 116.515 1123.25 c 1,13,-1
++ 30.002 1123.25 l 1,0,1
++EndSplineSet
++EndChar
+ EndChars
+ EndSplineFont
+diff --git extras/source/truetype/symbol/opens___.ttf extras/source/truetype/symbol/opens___.ttf
+index b4f169f..b7fb394 100644
+Binary files extras/source/truetype/symbol/opens___.ttf and extras/source/truetype/symbol/opens___.ttf differ
+diff --git officecfg/registry/data/org/openoffice/Office/Math.xcu officecfg/registry/data/org/openoffice/Office/Math.xcu
+index cf11e57..b185902 100644
+--- officecfg/registry/data/org/openoffice/Office/Math.xcu
++++ officecfg/registry/data/org/openoffice/Office/Math.xcu
+@@ -994,5 +994,19 @@
+ <value>Id1</value>
+ </prop>
+ </node>
++ <node oor:name="mapsto" oor:op="replace">
++ <prop oor:name="Char">
++ <value>10236</value>
++ </prop>
++ <prop oor:name="Set">
++ <value>Special</value>
++ </prop>
++ <prop oor:name="Predefined">
++ <value>true</value>
++ </prop>
++ <prop oor:name="FontFormatId">
++ <value>Id1</value>
++ </prop>
++ </node>
+ </node>
+ </oor:component-data>
+diff --git starmath/inc/parse.hxx starmath/inc/parse.hxx
+index 0211d97..b462abb 100644
+--- starmath/inc/parse.hxx
++++ starmath/inc/parse.hxx
+@@ -106,7 +106,7 @@ enum SmTokenType
+ TLEFTARROW, TRIGHTARROW, TUPARROW, TDOWNARROW, TDIVIDES,
+ TNDIBVIDES, TSETN, TSETZ, TSETQ, TSETR,
+ TSETC, TWIDEVEC, TWIDETILDE, TWIDEHAT, TWIDESLASH,
+- TWIDEBACKSLASH, TLDBRACKET, TRDBRACKET,
++ TWIDEBACKSLASH, TLDBRACKET, TRDBRACKET, TBOW,
+ TUNKNOWN, TDEBUG
+ };
+
+diff --git starmath/inc/types.hxx starmath/inc/types.hxx
+index b8cb4d0..4596877 100644
+--- starmath/inc/types.hxx
++++ starmath/inc/types.hxx
+@@ -165,6 +165,7 @@ enum MathSymbol
+ MS_FORALL = (sal_Unicode) 0x2200,
+
+ MS_HAT = (sal_Unicode) 0xE091,
++ MS_BOW = (sal_Unicode) 0x2312,
+ MS_CHECK = (sal_Unicode) 0xE092,
+ MS_BREVE = (sal_Unicode) 0xE093,
+ MS_ACUTE = (sal_Unicode) 0xE094,
+diff --git starmath/source/parse.cxx starmath/source/parse.cxx
+index aab3502..3fc2912 100644
+--- starmath/source/parse.cxx
++++ starmath/source/parse.cxx
+@@ -202,7 +202,7 @@ static const SmTokenTableEntry aTokenTable[] =
+ { "infinity" , TINFINITY, MS_INFINITY, TGSTANDALONE, 5},
+ { "infty" , TINFINITY, MS_INFINITY, TGSTANDALONE, 5},
+ { "int", TINT, MS_INT, TGOPER, 5},
+- { "intersection", TINTERSECT, MS_INTERSECT, TGPRODUCT, 0},
++ { "intersection", TINTERSECT, MS_INTERSECT, TGPRODUCT | TGOPER, 0},
+ { "ital", TITALIC, '\0', TGFONTATTR, 5},
+ { "italic", TITALIC, '\0', TGFONTATTR, 5},
+ { "lambdabar" , TLAMBDABAR, MS_LAMBDABAR, TGSTANDALONE, 5},
+@@ -312,13 +312,14 @@ static const SmTokenTableEntry aTokenTable[] =
+ { "transr", TTRANSR, MS_TRANSR, TGRELATION, 0},
+ { "underbrace", TUNDERBRACE, MS_UNDERBRACE, TGPRODUCT, 5},
+ { "underline", TUNDERLINE, '\0', TGATTRIBUT, 5},
+- { "union", TUNION, MS_UNION, TGSUM, 0},
++ { "union", TUNION, MS_UNION, TGSUM | TGOPER, 0},
+ { "uoper", TUOPER, '\0', TGUNOPER, 5},
+ { "uparrow" , TUPARROW, MS_UPARROW, TGSTANDALONE, 5},
+ { "vec", TVEC, MS_VEC, TGATTRIBUT, 5},
+ { "white", TWHITE, '\0', TGCOLOR, 0},
+ { "widebslash", TWIDEBACKSLASH, MS_BACKSLASH, TGPRODUCT, 0 },
+ { "widehat", TWIDEHAT, MS_HAT, TGATTRIBUT, 5},
++ { "bow", TBOW, MS_BOW, TGATTRIBUT, 5},
+ { "widetilde", TWIDETILDE, MS_TILDE, TGATTRIBUT, 5},
+ { "wideslash", TWIDESLASH, MS_SLASH, TGPRODUCT, 0 },
+ { "widevec", TWIDEVEC, MS_VEC, TGATTRIBUT, 5},
+@@ -1624,6 +1625,8 @@ void SmParser::Oper()
+
+ switch (eType)
+ {
++ case TINTERSECT:
++ case TUNION :
+ case TSUM :
+ case TPROD :
+ case TCOPROD :
+@@ -1781,6 +1784,7 @@ void SmParser::Attribut()
+
+ case TWIDEVEC :
+ case TWIDEHAT :
++ case TBOW :
+ case TWIDETILDE :
+ pAttr = new SmMathSymbolNode(CurToken);
+ eScaleMode = SCALE_WIDTH;
+diff --git starmath/source/symbol.src starmath/source/symbol.src
+index c4cab66..ed0fb9b 100644
+--- starmath/source/symbol.src
++++ starmath/source/symbol.src
+@@ -268,6 +268,7 @@ Resource RID_LOCALIZED_NAMES
+ < "perthousand" ; > ;
+ < "and" ; > ;
+ < "or" ; > ;
++ < "mapsto" ; > ;
+ };
+ };
+ StringArray RID_UI_SYMBOL_NAMES
+@@ -340,6 +341,7 @@ Resource RID_LOCALIZED_NAMES
+ < "perthousand" ; > ;
+ < "and" ; > ;
+ < "or" ; > ;
++ < "mapsto" ; > ;
+ };
+ };
+ };
diff --git a/patches/dev300/vEdit-13-August.diff b/patches/dev300/vEdit-13-August.diff
new file mode 100644
index 0000000..117a757
--- /dev/null
+++ b/patches/dev300/vEdit-13-August.diff
@@ -0,0 +1,7896 @@
+diff --git starmath/inc/caret.hxx starmath/inc/caret.hxx
+new file mode 100644
+index 0000000..b1ff954
+--- /dev/null
++++ starmath/inc/caret.hxx
+@@ -0,0 +1,445 @@
++#ifndef CARET_H
++#define CARET_H
++
++#include "node.hxx"
++
++/** Representation of caret position with an equantion */
++struct SmCaretPos{
++ SmCaretPos(SmNode* selectedNode = NULL, int iIndex = 0) {
++ pSelectedNode = selectedNode;
++ Index = iIndex;
++ }
++ /** Selected node */
++ SmNode* pSelectedNode;
++ /** Index within the selected node
++ *
++ * 0: Position infront of a node
++ * 1: Position after a node or after first char in SmTextNode
++ * n: Position after n char in SmTextNode
++ *
++ * Notice how there's special cases for SmTextNode.
++ */
++ //TODO: Special cases for SmBlankNode is needed
++ //TODO: Consider forgetting about the todo above... As it's really unpleasent.
++ int Index;
++ /** True, if this is a valid caret position */
++ bool IsValid() { return pSelectedNode != NULL; }
++ bool operator!=(SmCaretPos pos) const {
++ return pos.pSelectedNode != pSelectedNode || Index != pos.Index;
++ }
++ bool operator==(SmCaretPos pos) const {
++ return pos.pSelectedNode == pSelectedNode && Index == pos.Index;
++ }
++ /** Get the caret position after pNode, regardless of pNode
++ *
++ * Gets the caret position following pNode, this is SmCaretPos(pNode, 1).
++ * Unless pNode is an instance of SmTextNode, then the index is the text length.
++ */
++ static SmCaretPos GetPosAfter(SmNode* pNode) {
++ if(pNode && pNode->GetType() == NTEXT)
++ return SmCaretPos(pNode, ((SmTextNode*)pNode)->GetText().Len());
++ return SmCaretPos(pNode, 1);
++ }
++};
++
++/** A line that represents a caret */
++class SmCaretLine{
++public:
++ SmCaretLine(long left = 0, long top = 0, long height = 0) {
++ _top = top;
++ _left = left;
++ _height = height;
++ }
++ long GetTop() const {return _top;}
++ long GetLeft() const {return _left;}
++ long GetHeight() const {return _height;}
++ long SquaredDistanceX(SmCaretLine line) const{
++ return (GetLeft() - line.GetLeft()) * (GetLeft() - line.GetLeft());
++ }
++ long SquaredDistanceX(Point pos) const{
++ return (GetLeft() - pos.X()) * (GetLeft() - pos.X());
++ }
++ long SquaredDistanceY(SmCaretLine line) const{
++ long d = GetTop() - line.GetTop();
++ if(d < 0)
++ d = (d * -1) - GetHeight();
++ else
++ d = d - line.GetHeight();
++ if(d < 0)
++ return 0;
++ return d * d;
++ }
++ long SquaredDistanceY(Point pos) const{
++ long d = GetTop() - pos.Y();
++ if(d < 0)
++ d = (d * -1) - GetHeight();
++ if(d < 0)
++ return 0;
++ return d * d;
++ }
++private:
++ long _top;
++ long _left;
++ long _height;
++};
++
++/////////////////////////////// SmCaretPosGraph////////////////////////////////
++
++/** An entry in SmCaretPosGraph */
++struct SmCaretPosGraphEntry{
++ SmCaretPosGraphEntry(SmCaretPos pos = SmCaretPos(),
++ SmCaretPosGraphEntry* left = NULL,
++ SmCaretPosGraphEntry* right = NULL){
++ CaretPos = pos;
++ Left = left;
++ Right = right;
++ }
++ /** Caret position */
++ SmCaretPos CaretPos;
++ /** Entry to the left visually */
++ SmCaretPosGraphEntry* Left;
++ /** Entry to the right visually */
++ SmCaretPosGraphEntry* Right;
++ void SetRight(SmCaretPosGraphEntry* right){
++ Right = right;
++ }
++ void SetLeft(SmCaretPosGraphEntry* left){
++ Left = left;
++ }
++};
++
++/** Define SmCaretPosGraph to be less than one page 4096 */
++#define SmCaretPosGraphSize 255
++
++class SmCaretPosGraph;
++
++/** Iterator for SmCaretPosGraph */
++class SmCaretPosGraphIterator{
++public:
++ SmCaretPosGraphIterator(SmCaretPosGraph* graph){
++ pGraph = graph;
++ nOffset = 0;
++ pEntry = NULL;
++ }
++ /** Get the next entry, NULL if none */
++ SmCaretPosGraphEntry* Next();
++ /** Get the current entry, NULL if none */
++ SmCaretPosGraphEntry* Current(){
++ return pEntry;
++ }
++ /** Get the current entry, NULL if none */
++ SmCaretPosGraphEntry* operator->(){
++ return pEntry;
++ }
++private:
++ /** Next entry to return */
++ int nOffset;
++ /** Current graph */
++ SmCaretPosGraph* pGraph;
++ /** Current entry */
++ SmCaretPosGraphEntry* pEntry;
++};
++
++
++/** A graph over all caret positions
++ * @remarks Graphs can only grow, entries cannot be removed!
++ */
++class SmCaretPosGraph{
++public:
++ SmCaretPosGraph(){
++ pNext = NULL;
++ nOffset = 0;
++ }
++ ~SmCaretPosGraph();
++ SmCaretPosGraphEntry* Add(SmCaretPosGraphEntry entry);
++ SmCaretPosGraphEntry* Add(SmCaretPos pos,
++ SmCaretPosGraphEntry* left = NULL,
++ SmCaretPosGraphEntry* right = NULL){
++ j_assert(pos.Index >= 0, "Index shouldn't be -1!");
++ return Add(SmCaretPosGraphEntry(pos, left, right));
++ }
++ /** Get an iterator for this graph */
++ SmCaretPosGraphIterator GetIterator(){
++ return SmCaretPosGraphIterator(this);
++ }
++ friend class SmCaretPosGraphIterator;
++private:
++ /** Next graph, to be used when this graph is full */
++ SmCaretPosGraph* pNext;
++ /** Next free entry in graph */
++ int nOffset;
++ /** Entries in this graph segment */
++ SmCaretPosGraphEntry Graph[SmCaretPosGraphSize];
++};
++
++/** \page visual_formula_editing Visual Formula Editing
++ * A visual formula editor allows users to easily edit formulas without having to learn and
++ * use complicated commands. A visual formula editor is a WYSIWYG editor. For OpenOffice Math
++ * this essentially means that you can click on the formula image, to get a caret, which you
++ * can move with arrow keys, and use to modify the formula by entering text, clicking buttons
++ * or using shortcuts.
++ *
++ * \subsection formula_trees Formula Trees
++ * A formula in OpenOffice Math is a tree of nodes, take for instance the formula
++ * "A + {B cdot C} over D", it looks like this
++ * \f$ \mbox{A} + \frac{\mbox{B} \cdot \mbox{C}}{\mbox{D}} \f$. The tree for this formula
++ * looks like this:
++ *
++ * \dot
++ * digraph {
++ * labelloc = "t";
++ * label= "Equation: \"A + {B cdot C} over D\"";
++ * size = "9,9";
++ * n0 [label="SmTableNode (1)"];
++ * n0 -> n1 [label="0"];
++ * n1 [label="SmLineNode (2)"];
++ * n1 -> n2 [label="0"];
++ * n2 [label="SmExpressionNode (3)"];
++ * n2 -> n3 [label="0"];
++ * n3 [label="SmBinHorNode (4)"];
++ * n3 -> n4 [label="0"];
++ * n4 [label="SmTextNode: A (5)"];
++ * n3 -> n5 [label="1"];
++ * n5 [label="SmMathSymbolNode: î (6)"];
++ * n3 -> n6 [label="2"];
++ * n6 [label="SmBinVerNode (7)"];
++ * n6 -> n7 [label="0"];
++ * n7 [label="SmExpressionNode (8)"];
++ * n7 -> n8 [label="0"];
++ * n8 [label="SmBinHorNode (9)"];
++ * n8 -> n9 [label="0"];
++ * n9 [label="SmTextNode: B (10)"];
++ * n8 -> n10 [label="1"];
++ * n10 [label="SmMathSymbolNode: â
(11)"];
++ * n8 -> n11 [label="2"];
++ * n11 [label="SmTextNode: C (12)"];
++ * n6 -> n12 [label="1"];
++ * n12 [label="SmRectangleNode (13)"];
++ * n6 -> n13 [label="2"];
++ * n13 [label="SmTextNode: D (14)"];
++ * }
++ * \enddot
++ *
++ * The vertices are nodes, their label says what kind of node and the number in parentheses is
++ * the identifier of the node (In practices a pointer is used instead of the id). The direction
++ * of the edges tells which node is parent and which is child. The label of the edges are the
++ * child node index number, given to SmNode::GetSubNode() of the parent to get the child node.
++ *
++ *
++ * \subsection visual_lines Visual Lines
++ *
++ * Inorder to do caret movement in visual lines, we need a definition of caret position and
++ * visual line. In a tree such as the above there are three visual lines. There's the outer most
++ * line, with entries such as
++ * \f$\mbox{A}\f$, \f$ + \f$ and \f$ \frac{\mbox{B} \cdot \mbox{C}}{\mbox{D}} \f$. Then there's
++ * the numerator line of the fraction it has entries \f$ \mbox{B} \f$, \f$ \cdot \f$ and \f$ \mbox{C} \f$.
++ * And last by not least there's the denominator line of the fraction it's only entry is \f$ \mbox{D} \f$.
++ *
++ * For visual editing it should be possible to place a caret on both sides of any line entry,
++ * consider a line entry a character or construction that in a line is treated as a character.
++ * Imagine the caret is placed to the right of the plus sign (id: 6), now if user presses
++ * backspace this should delete the plus sign (id: 6), and if the user presses delete this
++ * should delete the entire fraction (id: 7). This is because the caret is in the outer most
++ * line where the fraction is considered a line entry.
++ *
++ * However, inorder to prevent users from accidentally deleting large subtrees, just because
++ * they logically placed there caret a in the wrong line, require that complex constructions
++ * such as a fraction is selected before it is deleted. Thus in this case it wouldn't be
++ * deleted, but only selected and then deleted if the user hit delete again. Anyway, this is
++ * slightly off topic for now.
++ *
++ * Important about visual lines is that they don't always have an SmExpressionNode as root
++ * and the entries in a visual line is all the nodes of a subtree ordered left to right that
++ * isn't either an SmExpressionNode, SmBinHorNode or SmUnHorNode.
++ *
++ *
++ * \subsection caret_positions Caret Positions
++ *
++ * A caret position in OpenOffice Math is representated by an instance of SmCaretPos.
++ * That is a caret position is a node and an index related to this node. For most nodes the
++ * index 0, means caret is infront of this node, the index 1 means caret is after this node.
++ * For SmTextNode the index is the caret position after the specified number of characters,
++ * imagine an SmTextNode with the number 1337. The index 3 in such SmTextNode would mean a
++ * caret placed right before 7, e.g. "133|7".
++ *
++ * For SmExpressionNode, SmBinHorNode and SmUnHorNode the only legal index is 0, which means
++ * infront of the node. Actually the index 0 may only because for the first caret position
++ * in a visual line. From the example above, consider the following subtree that constitutes
++ * a visual line:
++ *
++ * \dot
++ * digraph {
++ * labelloc = "t";
++ * label= "Subtree that constitutes a visual line";
++ * size = "7,5";
++ * n7 [label="SmExpressionNode (8)"];
++ * n7 -> n8 [label="0"];
++ * n8 [label="SmBinHorNode (9)"];
++ * n8 -> n9 [label="0"];
++ * n9 [label="SmTextNode: B (10)"];
++ * n8 -> n10 [label="1"];
++ * n10 [label="SmMathSymbolNode: â
(11)"];
++ * n8 -> n11 [label="2"];
++ * n11 [label="SmTextNode: C (12)"];
++ * }
++ * \enddot
++ * Here the caret positions are:
++ *
++ * <TABLE>
++ * <TR><TD><B>Caret position:</B></TD><TD><B>Example:</B></TD>
++ * </TR><TR>
++ * <TD>{id: 8, index: 0}</TD>
++ * <TD>\f$ \mid \mbox{C} \cdot \mbox{C} \f$</TD>
++ * </TR><TR>
++ * <TD>{id: 10, index: 1}</TD>
++ * <TD>\f$ \mbox{C} \mid \cdot \mbox{C} \f$</TD>
++ * </TR><TR>
++ * <TD>{id: 11, index: 1}</TD>
++ * <TD>\f$ \mbox{C} \cdot \mid \mbox{C} \f$</TD>
++ * </TR><TR>
++ * <TD>{id: 12, index: 1}</TD>
++ * <TD>\f$ \mbox{C} \cdot \mbox{C} \mid \f$</TD>
++ * </TR><TR>
++ * </TABLE>
++ *
++ * Where \f$ \mid \f$ is used to denote caret position.
++ *
++ * With these exceptions included in the definition the id and index: {id: 11, index: 0} does
++ * \b not constitute a caret position in the given context. Note the method
++ * SmCaretPos::IsValid() does not check if this invariant holds true, but code in SmCaret,
++ * SmSetSelectionVisitor and other places depends on this invariant to hold.
++ *
++ *
++ * \subsection caret_movement Caret Movement
++ *
++ * As the placement of caret positions depends very much on the context within which a node
++ * appears it is not trivial to find all caret positions and determine which follows which.
++ * In OpenOffice Math this is done by the SmCaretPosGraphBuildingVisitor. This visitor builds
++ * graph (an instnce of SmCaretPosGraph) over the caret positions. For details on how this
++ * graph is build, and how new methods should be implemented see SmCaretPosGraphBuildingVisitor.
++ *
++ * The result of the SmCaretPosGraphBuildingVisitor is a graph over the caret positions in a
++ * formula, representated by an instance of SmCaretPosGraph. Each entry (instances of SmCaretPosGraphEntry)
++ * has a pointer to the entry to the left and right of itself. This way we can easily find
++ * the caret position to a right or left of a given caret position. Note each caret position
++ * only appears once in this graph.
++ *
++ * When searching for a caret position after a left click on the formula this map is also used.
++ * We simply iterate over all entries, uses the SmCaretPos2LineVisitor to find a line for each
++ * caret position. Then the distance from the click to the line is computed and we choose the
++ * caret position closest to the click.
++ *
++ * For up and down movement, we also iterator over all caret positions and use SmCaretPos2LineVisitor
++ * to find a line for each caret position. Then we compute the distance from the current
++ * caret position to every other caret position and chooses the one closest that is either
++ * above or below the current caret position, depending on wether we're doing up or down movement.
++ *
++ * This result of this approach to caret movement is that we have logically predictable
++ * movement for left and right, whilst leftclick, up and down movement depends on the sizes
++ * and placement of all node and may be less logically predictable. This solution also means
++ * that we only have one complex visitor generating the graph, imagine the nightmare if we
++ * had a visitor for movement in each direction.
++ *
++ * Making up and down movement independent of node sizes and placement wouldn't necessarily
++ * be a good thing either. Consider the formula \f$ \frac{1+2+3+4+5}{6} \f$, if the caret is
++ * placed as displayed here: \f$ \frac{1+2+3+4+5}{6 \mid} \f$, up movement should move to right
++ * after "3": \f$ \frac{1+2+3|+4+5}{6} \f$. However, such a move depends on the sizes and placement
++ * of all nodes in the fraction.
++ *
++ *
++ * \subsubsection caretpos_graph_example Example of Caret Position Graph
++ *
++ * If we consider the formula
++ * \f$ \mbox{A} + \frac{\mbox{B} \cdot \mbox{C}}{\mbox{D}} \f$ from \ref formula_trees.
++ * It has the following caret positions:
++ *
++ * <TABLE>
++ * <TR>
++ * <TD><B>Caret position:</B></TD>
++ * <TD><B>Example:</B></TD>
++ * </TR><TR>
++ * <TD>{id: 3, index: 0}</TD>
++ * <TD>\f$ \mid\mbox{A} + \frac{\mbox{B} \cdot \mbox{C}}{\mbox{D}} \f$</TD>
++ * </TR><TR>
++ * <TD>{id: 5, index: 1}</TD>
++ * <TD>\f$ \mbox{A}\mid + \frac{\mbox{B} \cdot \mbox{C}}{\mbox{D}} \f$</TD>
++ * </TR><TR>
++ * <TD>{id: 6, index: 1}</TD>
++ * <TD>\f$ \mbox{A} + \mid \frac{\mbox{B} \cdot \mbox{C}}{\mbox{D}} \f$</TD>
++ * </TR><TR>
++ * <TD>{id: 8, index: 0}</TD>
++ * <TD>\f$ \mbox{A} + \frac{ \mid \mbox{B} \cdot \mbox{C}}{\mbox{D}} \f$</TD>
++ * </TR><TR>
++ * <TD>{id: 10, index: 1}</TD>
++ * <TD>\f$ \mbox{A} + \frac{\mbox{B} \mid \cdot \mbox{C}}{\mbox{D}} \f$</TD>
++ * </TR><TR>
++ * <TD>{id: 11, index: 1}</TD>
++ * <TD>\f$ \mbox{A} + \frac{\mbox{B} \cdot \mid \mbox{C}}{\mbox{D}} \f$</TD>
++ * </TR><TR>
++ * <TD>{id: 12, index: 1}</TD>
++ * <TD>\f$ \mbox{A} + \frac{\mbox{B} \cdot \mbox{C} \mid}{\mbox{D}} \f$</TD>
++ * </TR><TR>
++ * <TD>{id: 14, index: 0}</TD>
++ * <TD>\f$ \mbox{A} + \frac{\mbox{B} \cdot \mbox{C}}{\mid \mbox{D}} \f$</TD>
++ * </TR><TR>
++ * <TD>{id: 14, index: 1}</TD>
++ * <TD>\f$ \mbox{A} + \frac{\mbox{B} \cdot \mbox{C}}{\mbox{D} \mid} \f$</TD>
++ * </TR><TR>
++ * <TD>{id: 7, index: 1}</TD>
++ * <TD>\f$ \mbox{A} + \frac{\mbox{B} \cdot \mbox{C}}{\mbox{D}} \mid \f$</TD>
++ * </TR>
++ * </TABLE>
++ *
++ * Below is a directed graph over the caret postions and how you can move between them.
++ * \dot
++ * digraph {
++ * labelloc = "t";
++ * label= "Caret Position Graph";
++ * size = "4,6";
++ * p0 [label = "{id: 3, index: 0}"];
++ * p0 -> p1 [fontsize = 10.0, label = "right"];
++ * p1 [label = "{id: 5, index: 1}"];
++ * p1 -> p0 [fontsize = 10.0, label = "left"];
++ * p1 -> p2 [fontsize = 10.0, label = "right"];
++ * p2 [label = "{id: 6, index: 1}"];
++ * p2 -> p1 [fontsize = 10.0, label = "left"];
++ * p2 -> p3 [fontsize = 10.0, label = "right"];
++ * p3 [label = "{id: 8, index: 0}"];
++ * p3 -> p2 [fontsize = 10.0, label = "left"];
++ * p3 -> p4 [fontsize = 10.0, label = "right"];
++ * p4 [label = "{id: 10, index: 1}"];
++ * p4 -> p3 [fontsize = 10.0, label = "left"];
++ * p4 -> p5 [fontsize = 10.0, label = "right"];
++ * p5 [label = "{id: 11, index: 1}"];
++ * p5 -> p4 [fontsize = 10.0, label = "left"];
++ * p5 -> p6 [fontsize = 10.0, label = "right"];
++ * p6 [label = "{id: 12, index: 1}"];
++ * p6 -> p5 [fontsize = 10.0, label = "left"];
++ * p6 -> p9 [fontsize = 10.0, label = "right"];
++ * p7 [label = "{id: 14, index: 0}"];
++ * p7 -> p2 [fontsize = 10.0, label = "left"];
++ * p7 -> p8 [fontsize = 10.0, label = "right"];
++ * p8 [label = "{id: 14, index: 1}"];
++ * p8 -> p7 [fontsize = 10.0, label = "left"];
++ * p8 -> p9 [fontsize = 10.0, label = "right"];
++ * p9 [label = "{id: 7, index: 1}"];
++ * p9 -> p6 [fontsize = 10.0, label = "left"];
++ * }
++ * \enddot
++ */
++
++/* TODO: Write documentation about the following keywords:
++ *
++ * Visual Selections:
++ * - Show images
++ * - Talk about how the visitor does this
++ *
++ * Modifying a Visual Line:
++ * - Find top most non-compo of the line (e.g. The subtree that constitutes a line)
++ * - Make the line into a list
++ * - Edit the list, add/remove/modify nodes
++ * - Parse the list back into a subtree
++ * - Insert the new subtree where the old was taken
++ */
++
++#endif /* CARET_H */
+diff --git starmath/inc/cursor.hxx starmath/inc/cursor.hxx
+new file mode 100644
+index 0000000..ff865a8
+--- /dev/null
++++ starmath/inc/cursor.hxx
+@@ -0,0 +1,404 @@
++#ifndef SMCURSOR_H
++#define SMCURSOR_H
++
++#include "node.hxx"
++#include "caret.hxx"
++
++/** Factor to multiple the squared horizontical distance with
++ * Used for Up and Down movement.
++ */
++#define HORIZONTICAL_DISTANCE_FACTOR 10
++
++/** Enum of direction for movement */
++enum SmMovementDirection{
++ MoveUp,
++ MoveDown,
++ MoveLeft,
++ MoveRight
++};
++
++/** Enum of elements that can inserted into a formula */
++enum SmFormulaElement{
++ BlankElement,
++ FactorialElement,
++ PlusElement,
++ MinusElement,
++ CDotElement,
++ EqualElement,
++ LessThanElement,
++ GreaterThanElement
++};
++
++/** Bracket types that can be inserted */
++enum SmBracketType {
++ /** None brackets, left command "none" */
++ NoneBrackets,
++ /** Round brackets, left command "(" */
++ RoundBrackets,
++ /**Square brackets, left command "[" */
++ SquareBrackets,
++ /** Double square brackets, left command "ldbracket" */
++ DoubleSquareBrackets,
++ /** Line brackets, left command "lline" */
++ LineBrackets,
++ /** Double line brackets, left command "ldline" */
++ DoubleLineBrackets,
++ /** Curly brackets, left command "lbrace" */
++ CurlyBrackets,
++ /** Angle brackets, left command "langle" */
++ AngleBrackets,
++ /** Ceiling brackets, left command "lceil" */
++ CeilBrackets,
++ /** Floor brackets, left command "lfloor" */
++ FloorBrackets
++};
++
++/** A list of nodes */
++typedef std::list<SmNode*> SmNodeList;
++
++class SmDocShell;
++
++/** Formula cursor
++ *
++ * This class is used to represent a cursor in a formula, which can be used to manipulate
++ * an formula programmatically.
++ * @remarks This class is a very intimite friend of SmDocShell.
++ */
++class SmCursor{
++public:
++ SmCursor(SmNode* tree, SmDocShell* pShell){
++ //Initialize members
++ pTree = tree;
++ anchor = NULL;
++ position = NULL;
++ pGraph = NULL;
++ pDocShell = pShell;
++ pClipboard = NULL;
++ nEditSections = 0;
++ //Build graph
++ BuildGraph();
++ }
++
++ ~SmCursor(){
++ SetClipboard();
++ if(pGraph)
++ delete pGraph;
++ pGraph = NULL;
++ }
++
++ /** Gets the anchor */
++ SmCaretPos GetAnchor(){ return anchor->CaretPos; }
++
++ /** Get position */
++ SmCaretPos GetPosition() { return position->CaretPos; }
++
++ /** True, if the cursor has a selection */
++ bool HasSelection() { return anchor != position; }
++
++ /** Move the position of this cursor */
++ void Move(OutputDevice* pDev, SmMovementDirection direction, bool bMoveAnchor = true);
++
++ /** Move to the caret position closet to a given point */
++ void MoveTo(OutputDevice* pDev, Point pos, bool bMoveAnchor = true);
++
++ /** Delete the current selection or do nothing */
++ void Delete();
++
++ /** Insert text at the current position */
++ void InsertText(XubString aString);
++
++ /** Insert an element into the formula */
++ void InsertElement(SmFormulaElement element);
++
++ /** Insert a command specified in commands.src*/
++ void InsertCommand(USHORT nCommand);
++
++ /** Insert command text translated into line entries at position
++ *
++ * Note: This method uses the parser to translate a command text into a
++ * tree, then it copies line entries from this tree into the current tree.
++ * Will not work for commands such as newline or ##, if position is in a matrix.
++ * This will work for stuff like "A intersection B". But stuff spaning multiple lines
++ * or dependent on the context which position is placed in will not work!
++ */
++ void InsertCommandText(String aCommandText);
++
++ /** Insert a special node created from aString
++ *
++ * Used for handling insert request from the "catalog" dialog.
++ * The provided string should be formatet as the desired command: %phi
++ * Note: this method ONLY supports commands defined in Math.xcu
++ *
++ * For more complex expressions use InsertCommandText, this method doesn't
++ * use SmParser, this means that it's faster, but not as strong.
++ */
++ void InsertSpecial(XubString aString);
++
++ /** Create sub-/super script
++ *
++ * If there's a selection, it will be move into the appropriate sub-/super scription
++ * of the node infront of it. If there's no node infront of position (or the selection),
++ * a sub-/super scription of a new SmPlaceNode will be made.
++ *
++ * If there's is an existing subscription of the node, the caret will be moved into it,
++ * and any selection will replace it.
++ */
++ void InsertSubSup(SmSubSup eSubSup);
++
++ /** Create a limit on an SmOperNode
++ *
++ * This this method only work if the caret is inside an SmOperNode, or to the right of one.
++ * Notice also that this method ignores any selection made.
++ *
++ * @param bMoveCaret If true that caret will be moved into the limit.
++ *
++ * @returns True, if the caret was in a context where this operation was possible.
++ */
++ BOOL InsertLimit(SmSubSup eSubSup, BOOL bMoveCaret = TRUE);
++
++ /** Insert a new row or newline
++ *
++ * Inserts a new row if position is in an matrix or stack command.
++ * Otherwise a newline is inserted if we're in a toplevel line.
++ *
++ * @returns True, if a new row/line could be inserted.
++ *
++ * @remarks If the caret is placed in a subline of a command that doesn't support
++ * this operator the method returns FALSE, and doesn't do anything.
++ */
++ BOOL InsertRow();
++
++ /** Insert a fraction, use selection as numerator */
++ void InsertFraction();
++
++ /** Create brackets around current selection, or new SmPlaceNode */
++ void InsertBrackets(SmBracketType eBracketType);
++
++ /** Copy the current selection */
++ void Copy();
++ /** Cut the current selection */
++ void Cut(){
++ Copy();
++ Delete();
++ }
++ /** Paste the clipboard */
++ void Paste();
++
++ /** Returns true if more than one node is selected
++ *
++ * This method is used for implementing backspace and delete.
++ * If one of these causes a complex selection, e.g. a node with
++ * subnodes or similar, this should not be deleted imidiately.
++ */
++ bool HasComplexSelection();
++
++ /** Finds the topmost node in a visual line
++ *
++ * If MoveUpIfSelected is true, this will move up to the parent line
++ * if the parent of the current line is selected.
++ */
++ static SmNode* FindTopMostNodeInLine(SmNode* pSNode, bool MoveUpIfSelected = false);
++
++ /** Draw the caret */
++ void Draw(OutputDevice& pDev, Point Offset);
++
++private:
++ friend class SmDocShell;
++
++ SmCaretPosGraphEntry *anchor,
++ *position;
++ /** Formula tree */
++ SmNode* pTree;
++ /** Owner of the formula tree */
++ SmDocShell* pDocShell;
++ /** Graph over caret position in the current tree */
++ SmCaretPosGraph* pGraph;
++ /** Clipboard holder */
++ SmNodeList* pClipboard;
++
++ /** Returns a node that is selected, if any could be found */
++ SmNode* FindSelectedNode(SmNode* pNode);
++
++ /** Is this one of the nodes used to compose a line
++ *
++ * These are SmExpression, SmBinHorNode, SmUnHorNode etc.
++ */
++ static bool IsLineCompositionNode(SmNode* pNode);
++
++ /** Count number of selected nodes, excluding line composition nodes
++ *
++ * Note this function doesn't count line composition nodes and it
++ * does count all subnodes as well as the owner nodes.
++ *
++ * Used by SmCursor::HasComplexSelection()
++ */
++ int CountSelectedNodes(SmNode* pNode);
++
++ /** Convert a visual line to a list
++ *
++ * Note this method will delete all the nodes that will no longer be needed.
++ * that includes pLine!
++ * This method also deletes SmErrorNode's as they're just meta info in the line.
++ */
++ static SmNodeList* LineToList(SmStructureNode* pLine, SmNodeList* pList = new SmNodeList());
++
++ /** Clone a visual line to a list
++ *
++ * Doesn't clone SmErrorNode's these are ignored, as they are context dependent metadata.
++ */
++ static SmNodeList* CloneLineToList(SmStructureNode* pLine,
++ bool bOnlyIfSelected = false,
++ SmNodeList* pList = new SmNodeList());
++
++ /** Build pGraph over caret positions */
++ void BuildGraph();
++
++ /** Insert new nodes in the tree after position */
++ void InsertNodes(SmNodeList* pNewNodes);
++
++ /** tries to set position to a specific SmCaretPos
++ *
++ * @returns false on failure to find the position in pGraph.
++ */
++ bool SetCaretPosition(SmCaretPos pos, bool moveAnchor = false);
++
++ /** Set selected on nodes of the tree */
++ void AnnotateSelection();
++
++ /** Set the clipboard, and release current clipboard
++ *
++ * Call this method with NULL to reset the clipboard
++ * @remarks: This method takes ownership of pList.
++ */
++ void SetClipboard(SmNodeList* pList = NULL);
++
++ /** Clone list of nodes (creates a deep clone) */
++ static SmNodeList* CloneList(SmNodeList* pList);
++
++ /** Find an iterator pointing to the node in pLineList following aCaretPos
++ *
++ * If aCaretPos::pSelectedNode cannot be found it is assumed that it's infront of pLineList,
++ * thus not an element in pLineList. In this case this method returns an iterator to the
++ * first element in pLineList.
++ *
++ * If the current position is inside an SmTextNode, this node will be split in two, for this
++ * reason you should beaware that iterators to elements in pLineList may be invalidated, and
++ * that you should call PatchLineList() with this iterator if no action is taken.
++ */
++ static SmNodeList::iterator FindPositionInLineList(SmNodeList* pLineList, SmCaretPos aCaretPos);
++
++ /** Patch a line list after modification, merge SmTextNode, remove SmPlaceNode etc.
++ *
++ * @param pLineList The line list to patch
++ * @param aIter Iterator pointing to the element that needs to be patched with it's previous.
++ *
++ * When the list is patched text nodes before and after aIter will be merged.
++ * If there's an, in the context, inappropriate SmPlaceNode before or after aIter it will also be
++ * removed.
++ *
++ * @returns A caret position equivalent to one selecting the node before aIter, the method returns
++ * an invalid SmCaretPos to indicate placement infront of the line.
++ */
++ static SmCaretPos PatchLineList(SmNodeList* pLineList, SmNodeList::iterator aIter);
++
++ /** Take selected nodes from a list
++ *
++ * Puts the selected nodes into pSelectedNodes, or if pSelectedNodes is NULL deletes
++ * the selected nodes.
++ * Note: If there's a selection inside an SmTextNode this node will be split, and it
++ * will not be merged when the selection have been taken. Use PatchLineList on the
++ * iterator returns to fix this.
++ *
++ * @returns An iterator pointing to the element following the selection taken.
++ */
++ static SmNodeList::iterator TakeSelectedNodesFromList(SmNodeList *pLineList,
++ SmNodeList *pSelectedNodes = NULL);
++
++ /** Create an instance of SmMathSymbolNode usable for brackets */
++ static SmNode *CreateBracket(SmBracketType eBracketType, BOOL bIsLeft);
++
++ /** The number of times BeginEdit have been called
++ * Used to allow nesting of BeginEdit() and EndEdit() sections
++ */
++ int nEditSections;
++ /** Holds data for BeginEdit() and EndEdit() */
++ BOOL bIsEnabledSetModifiedSmDocShell;
++ /** Begin section where the tree will be modified */
++ void BeginEdit();
++ /** End section where the tree will be modified */
++ void EndEdit();
++ /** Request the formula is repainted */
++ void RequestRepaint();
++};
++
++/** Minimalistic recursive decent SmNodeList parser
++ *
++ * This parser is used to take a list of nodes that constitues a line
++ * and parse them to a tree of SmBinHorNode, SmUnHorNode and SmExpression.
++ *
++ * Please note, this will not handle all kinds of nodes, only nodes that
++ * constitues and entry in a line.
++ *
++ * Below is an EBNF representation of the grammar used for this parser:
++ * \code
++ * Expression -> Relation*
++ * Relation -> Sum [(=|<|>|...) Sum]*
++ * Sum -> Product [(+|-) Product]*
++ * Product -> Factor [(*|/) Factor]*
++ * Factor -> [+|-|-+|...]* Factor | Postfix
++ * Postfix -> node [!]*
++ * \endcode
++ */
++class SmNodeListParser{
++public:
++ /** Create an instance of SmNodeListParser */
++ SmNodeListParser(){
++ pList = NULL;
++ }
++ /** Parse a list of nodes to an expression
++ *
++ * If bDeleteErrorNodes is true, old error nodes will be deleted.
++ */
++ SmNode* Parse(SmNodeList* list, bool bDeleteErrorNodes = true);
++ /** True, if the token is an operator */
++ static BOOL IsOperator(const SmToken &token);
++ /** True, if the token is a relation operator */
++ static BOOL IsRelationOperator(const SmToken &token);
++ /** True, if the token is a sum operator */
++ static BOOL IsSumOperator(const SmToken &token);
++ /** True, if the token is a product operator */
++ static BOOL IsProductOperator(const SmToken &token);
++ /** True, if the token is a unary operator */
++ static BOOL IsUnaryOperator(const SmToken &token);
++ /** True, if the token is a postfix operator */
++ static BOOL IsPostfixOperator(const SmToken &token);
++private:
++ SmNodeList* pList;
++ /** Get the current terminal */
++ SmNode* Terminal(){
++ if(pList->size() > 0)
++ return pList->front();
++ return NULL;
++ }
++ /** Move to next terminal */
++ SmNode* Next(){
++ pList->pop_front();
++ return Terminal();
++ }
++ /** Take the current terminal */
++ SmNode* Take(){
++ SmNode* pRetVal = Terminal();
++ Next();
++ return pRetVal;
++ }
++ SmNode* Expression();
++ SmNode* Relation();
++ SmNode* Sum();
++ SmNode* Product();
++ SmNode* Factor();
++ SmNode* Postfix();
++ SmNode* Error();
++};
++
++
++#endif /* SMCURSOR_H */
+diff --git starmath/inc/document.hxx starmath/inc/document.hxx
+index 364eff2..1e7cd62 100644
+--- starmath/inc/document.hxx
++++ starmath/inc/document.hxx
+@@ -47,6 +47,7 @@ class SmNode;
+ class SfxMenuBarManager;
+ class SfxPrinter;
+ class Printer;
++class SmCursor;
+
+ #define HINT_DATACHANGED 1004
+
+@@ -105,6 +106,7 @@ class SmDocShell : public SfxObjectShell, public SfxListener
+ {
+ friend class SmPrinterAccess;
+ friend class SmModel;
++ friend class SmCursor;
+
+ String aText;
+ SmFormat aFormat;
+@@ -122,6 +124,7 @@ class SmDocShell : public SfxObjectShell, public SfxListener
+ nBottomBorder;
+ USHORT nModifyCount;
+ BOOL bIsFormulaArranged;
++ SmCursor *pCursor;
+
+
+
+@@ -157,10 +160,15 @@ class SmDocShell : public SfxObjectShell, public SfxListener
+ OutputDevice* GetRefDev();
+
+ BOOL IsFormulaArranged() const { return bIsFormulaArranged; }
+- void SetFormulaArranged(BOOL bVal) { bIsFormulaArranged = bVal; }
++ void SetFormulaArranged(BOOL bVal) { bIsFormulaArranged = bVal; }
+
+ virtual BOOL ConvertFrom(SfxMedium &rMedium);
+
++ /** Called whenever the formula is changed
++ * Deletes the current cursor
++ */
++ void InvalidateCursor();
++
+ public:
+ TYPEINFO();
+ SFX_DECL_INTERFACE(SFX_INTERFACE_SMA_START+1)
+@@ -204,7 +212,7 @@ public:
+ EditEngine & GetEditEngine();
+ SfxItemPool & GetEditEngineItemPool();
+
+- void Draw(OutputDevice &rDev, Point &rPosition);
++ void DrawFormula(OutputDevice &rDev, Point &rPosition, BOOL bDrawSelection = FALSE);
+ Size GetSize();
+
+ void Repaint();
+@@ -218,6 +226,15 @@ public:
+
+ virtual void SetVisArea (const Rectangle & rVisArea);
+ virtual void SetModified(BOOL bModified);
++
++ /** Get a cursor for modifying this document
++ * @remarks Don't store this reference, a new cursor may be made...
++ */
++ SmCursor& GetCursor();
++ /** True, if cursor have previously been requested and thus
++ * has some sort of position.
++ */
++ BOOL HasCursor() { return pCursor != NULL; }
+ };
+
+
+diff --git starmath/inc/edit.hxx starmath/inc/edit.hxx
+index 595564f..56bafab 100644
+--- starmath/inc/edit.hxx
++++ starmath/inc/edit.hxx
+@@ -68,15 +68,13 @@ class SmEditWindow : public Window, public DropTargetHelper
+ ScrollBar *pHScrollBar,
+ *pVScrollBar;
+ ScrollBarBox *pScrollBox;
+- Timer aModifyTimer,
+- aCursorMoveTimer;
++ Timer aModifyTimer;
+ ESelection aOldSelection;
+
+ virtual void KeyInput(const KeyEvent& rKEvt);
+ virtual void Command(const CommandEvent& rCEvt);
+ DECL_LINK(MenuSelectHdl, Menu *);
+ DECL_LINK(ModifyTimerHdl, Timer *);
+- DECL_LINK(CursorMoveTimerHdl, Timer *);
+
+ virtual void DataChanged( const DataChangedEvent& );
+ virtual void Resize();
+diff --git starmath/inc/node.hxx starmath/inc/node.hxx
+index dabb503..7a19b6a 100644
+--- starmath/inc/node.hxx
++++ starmath/inc/node.hxx
+@@ -31,6 +31,24 @@
+
+
+ #include <vector>
++#include <fstream>
++#include <iostream>
++#include <stdio.h>
++
++//My special assert macro
++//TODO: replace this with DBG_ASSERT when this patch moves to production, can be done using search/replace
++#define j_assert(cond, msg) do{ \
++ if(!(cond)) \
++ { \
++ std::cerr<<"Failed assertion: "<<msg<<", at line "; \
++ char* f = (char*)__FILE__; \
++ f += strlen(f); \
++ do f--; while(*f != '/'); \
++ do f--; while(*f != '/'); \
++ do f--; while(*f != '/'); \
++ fprintf(stderr, "%d in %s\n", __LINE__, f + 1); \
++ } \
++ } while(false)
+
+ #include "parse.hxx"
+ #include "types.hxx"
+@@ -41,6 +59,7 @@
+ #define ATTR_BOLD 0x0001
+ #define ATTR_ITALIC 0x0002
+
++
+ #define FNTSIZ_ABSOLUT 1
+ #define FNTSIZ_PLUS 2
+ #define FNTSIZ_MINUS 3
+@@ -59,6 +78,7 @@
+
+ extern SmFormat *pActiveFormat;
+
++class SmVisitor;
+ class SmDocShell;
+ class SmNode;
+ class SmStructureNode;
+@@ -97,6 +117,8 @@ class SmNode : public SmRect
+ nAttributes;
+ BOOL bIsPhantom,
+ bIsDebug;
++
++ BOOL bIsSelected;
+ protected:
+ SmNode(SmNodeType eNodeType, const SmToken &rNodeToken);
+
+@@ -160,7 +182,6 @@ public:
+ #ifdef SM_RECT_DEBUG
+ using SmRect::Draw;
+ #endif
+- virtual void Draw(OutputDevice &rDev, const Point &rPosition) const;
+
+ virtual void GetAccessibleText( String &rText ) const;
+ sal_Int32 GetAccessibleIndex() const { return nAccIndex; }
+@@ -180,12 +201,126 @@ public:
+
+ const SmNode * FindTokenAt(USHORT nRow, USHORT nCol) const;
+ const SmNode * FindRectClosestTo(const Point &rPoint) const;
+-};
++
++ /** Accept a visitor
++ * Calls the method for this class on the visitor
++ */
++ virtual void Accept(SmVisitor* pVisitor);
++
++ /** True if this node is selected */
++ BOOL IsSelected() const {return bIsSelected;}
++ void SetSelected(BOOL Selected = true) {bIsSelected = Selected;}
++
++ /** The tree as dot graph for graphviz, usable for debugging
++ * Convert the output to a image using $ dot graph.gv -Tpng > graph.png
++ */
++ inline void DumpAsDot(std::ostream &out, String* label = NULL) const{
++ int id = 0;
++ DumpAsDot(out, label, -1, id, -1);
++ }
+
++ /** Get the parent node of this node */
++ SmStructureNode* GetParent(){ return aParentNode; }
++ /** Set the parent node */
++ void SetParent(SmStructureNode* parent){
++ aParentNode = parent;
++ }
++
++ /** Get the index of a child node
++ *
++ * Returns -1, if pSubNode isn't a subnode of this.
++ */
++ int IndexOfSubNode(SmNode* pSubNode){
++ USHORT nSize = GetNumSubNodes();
++ for(USHORT i = 0; i < nSize; i++)
++ if(pSubNode == GetSubNode(i))
++ return i;
++ return -1;
++ }
++ /** Set the token for this node */
++ void SetToken(SmToken& token){
++ aNodeToken = token;
++ }
++protected:
++ /** Sets parent on children of this node */
++ void ClaimPaternity(){
++ SmNode* pNode;
++ USHORT nSize = GetNumSubNodes();
++ for (USHORT i = 0; i < nSize; i++)
++ if (NULL != (pNode = GetSubNode(i)))
++ pNode->SetParent((SmStructureNode*)this); //Cast is valid if we have children
++ }
++private:
++ SmStructureNode* aParentNode;
++ void DumpAsDot(std::ostream &out, String* label, int number, int& id, int parent) const;
++};
+
+ ////////////////////////////////////////////////////////////////////////////////
+
++/** A simple auxiliary iterator class for SmNode
++ *
++ * Example of iteration over children of pMyNode:
++ * \code
++ * //Node to iterate over:
++ * SmNode* pMyNode = 0;// A pointer from somewhere
++ * //The iterator:
++ * SmNodeIterator it(pMyNode);
++ * //The iteration:
++ * while(it.Next()) {
++ * it->SetSelected(true);
++ * }
++ * \endcode
++ */
++class SmNodeIterator{
++public:
++ SmNodeIterator(SmNode* node, bool bReverse = false){
++ pNode = node;
++ nSize = pNode->GetNumSubNodes();
++ nIndex = 0;
++ pChildNode = NULL;
++ bIsReverse = bReverse;
++ }
++ /** Get the subnode or NULL if none */
++ SmNode* Next(){
++ while(!bIsReverse && nIndex < nSize){
++ if(NULL != (pChildNode = pNode->GetSubNode(nIndex++)))
++ return pChildNode;
++ }
++ while(bIsReverse && nSize > 0){
++ if(NULL != (pChildNode = pNode->GetSubNode((nSize--)-1)))
++ return pChildNode;
++ }
++ pChildNode = NULL;
++ return NULL;
++ }
++ /** Get the current child node, NULL if none */
++ SmNode* Current(){
++ return pChildNode;
++ }
++ /** Get the current child node, NULL if none */
++ SmNode* operator->(){
++ return pChildNode;
++ }
++private:
++ /** Current child */
++ SmNode* pChildNode;
++ /** Node whos children we're iterating over */
++ SmNode* pNode;
++ /** Size of the node */
++ USHORT nSize;
++ /** Current index in the node */
++ USHORT nIndex;
++ /** Move reverse */
++ bool bIsReverse;
++};
++
++////////////////////////////////////////////////////////////////////////////////
+
++/** Abstract baseclass for all composite node
++ *
++ * Subclasses of this class can have subnodes. Nodes that doesn't derivate from
++ * this class does not have subnodes.
++ */
+ class SmStructureNode : public SmNode
+ {
+ SmNodeArray aSubNodes;
+@@ -212,12 +347,29 @@ public:
+ virtual SmStructureNode & operator = ( const SmStructureNode &rNode );
+
+ virtual void GetAccessibleText( String &rText ) const;
++
++ void SetSubNode(USHORT nIndex, SmNode* pNode){
++ int size = aSubNodes.size();
++ if(size <= nIndex){
++ //Resize subnodes array
++ aSubNodes.resize(nIndex + 1);
++ //Set new slots to NULL
++ for(int i = size; i < nIndex+1; i++)
++ aSubNodes[i] = NULL;
++ }
++ aSubNodes[nIndex] = pNode;
++ ClaimPaternity();
++ }
+ };
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+
+-
++/** Abstract base class for all visible node
++ *
++ * Nodes that doesn't derivate from this class doesn't draw anything, but their
++ * children.
++ */
+ class SmVisibleNode : public SmNode
+ {
+ protected:
+@@ -252,7 +404,10 @@ public:
+
+ ////////////////////////////////////////////////////////////////////////////////
+
+-
++/** Draws a rectangle
++ *
++ * Used for drawing the line in the OVER and OVERSTRIKE commands.
++ */
+ class SmRectangleNode : public SmGraphicNode
+ {
+ Size aToSize;
+@@ -270,15 +425,19 @@ public:
+ #ifdef SM_RECT_DEBUG
+ using SmRect::Draw;
+ #endif
+- virtual void Draw(OutputDevice &rDev, const Point &rPosition) const;
++
+
+ void CreateTextFromNode(String &rText);
++ void Accept(SmVisitor* pVisitor);
+ };
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+
+-
++/** Polygon line node
++ *
++ * Used to draw the slash of the WIDESLASH command by SmBinDiagonalNode.
++ */
+ class SmPolyLineNode : public SmGraphicNode
+ {
+ Polygon aPoly;
+@@ -289,6 +448,8 @@ public:
+ SmPolyLineNode(const SmToken &rNodeToken);
+
+ long GetWidth() const { return nWidth; }
++ Size GetToSize() const { return aToSize; }
++ Polygon &GetPolygon() { return aPoly; }
+
+ virtual void AdaptToX(const OutputDevice &rDev, ULONG nWidth);
+ virtual void AdaptToY(const OutputDevice &rDev, ULONG nHeight);
+@@ -298,17 +459,29 @@ public:
+ #ifdef SM_RECT_DEBUG
+ using SmRect::Draw;
+ #endif
+- virtual void Draw(OutputDevice &rDev, const Point &rPosition) const;
++
++ void Accept(SmVisitor* pVisitor);
+ };
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+
+-
++/** Text node
++ *
++ * @remarks This class also serves as baseclass for all nodes that contains text.
++ */
+ class SmTextNode : public SmVisibleNode
+ {
+ XubString aText;
+ USHORT nFontDesc;
++ /** Index within text where the selection starts
++ * @remarks Only valid if SmNode::IsSelected() is true
++ */
++ xub_StrLen nSelectionStart;
++ /** Index within text where the selection ends
++ * @remarks Only valid if SmNode::IsSelected() is true
++ */
++ xub_StrLen nSelectionEnd;
+
+ protected:
+ SmTextNode(SmNodeType eNodeType, const SmToken &rNodeToken, USHORT nFontDescP)
+@@ -328,6 +501,25 @@ public:
+ USHORT GetFontDesc() const { return nFontDesc; }
+ void SetText(const XubString &rText) { aText = rText; }
+ const XubString & GetText() const { return aText; }
++ /** Change the text of this node, including the underlying token */
++ void ChangeText(const XubString &rText) {
++ aText = rText;
++ SmToken token = GetToken();
++ token.aText = rText;
++ SetToken(token);
++ }
++ /** Index within GetText() where the selection starts
++ * @remarks Only valid of SmNode::IsSelected() is true
++ */
++ xub_StrLen GetSelectionStart() const {return nSelectionStart;}
++ /** Index within GetText() where the selection end
++ * @remarks Only valid of SmNode::IsSelected() is true
++ */
++ xub_StrLen GetSelectionEnd() const {return nSelectionEnd;}
++ /** Set the index within GetText() where the selection starts */
++ void SetSelectionStart(xub_StrLen index) {nSelectionStart = index;}
++ /** Set the index within GetText() where the selection end */
++ void SetSelectionEnd(xub_StrLen index) {nSelectionEnd = index;}
+
+ virtual void Prepare(const SmFormat &rFormat, const SmDocShell &rDocShell);
+ virtual void Arrange(const OutputDevice &rDev, const SmFormat &rFormat);
+@@ -336,15 +528,22 @@ public:
+ #ifdef SM_RECT_DEBUG
+ using SmRect::Draw;
+ #endif
+- virtual void Draw(OutputDevice &rDev, const Point &rPosition) const;
++
+
+ virtual void GetAccessibleText( String &rText ) const;
++ void Accept(SmVisitor* pVisitor);
+ };
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+
+-
++/** Special node for user defined characters
++ *
++ * Node used for pre- and user-defined characters from:
++ * officecfg/registry/data/org/openoffice/Office/Math.xcu
++ *
++ * This is just single characters, I think.
++ */
+ class SmSpecialNode : public SmTextNode
+ {
+ protected:
+@@ -363,13 +562,22 @@ public:
+ #ifdef SM_RECT_DEBUG
+ using SmRect::Draw;
+ #endif
+- virtual void Draw(OutputDevice &rDev, const Point &rPosition) const;
++
++ void Accept(SmVisitor* pVisitor);
+ };
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+
+-
++/** Glyph node for custom operators
++ *
++ * This node is used with commands: oper, uoper and boper.
++ * E.g. in "A boper op B", "op" will be an instance of SmGlyphSpecialNode.
++ * "boper" simply inteprets "op", the following token, as an binary operator.
++ * The command "uoper" interprets the following token as unary operator.
++ * For these commands an instance of SmGlyphSpecialNode is used for the
++ * operator token, following the command.
++ */
+ class SmGlyphSpecialNode : public SmSpecialNode
+ {
+ public:
+@@ -378,12 +586,16 @@ public:
+ {}
+
+ virtual void Arrange(const OutputDevice &rDev, const SmFormat &rFormat);
++ void Accept(SmVisitor* pVisitor);
+ };
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+
+-
++/** Math symbol node
++ *
++ * Use for math symbols such as plus, minus and integrale in the INT command.
++ */
+ class SmMathSymbolNode : public SmSpecialNode
+ {
+ protected:
+@@ -404,12 +616,18 @@ public:
+ virtual void Prepare(const SmFormat &rFormat, const SmDocShell &rDocShell);
+ virtual void Arrange(const OutputDevice &rDev, const SmFormat &rFormat);
+ void CreateTextFromNode(String &rText);
++ void Accept(SmVisitor* pVisitor);
+ };
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+
+-
++/** Root symbol node
++ *
++ * Root symbol node used by SmRootNode to create the root symbol, infront of
++ * the line with the line above. I don't think this node should be used for
++ * anything else.
++ */
+ class SmRootSymbolNode : public SmMathSymbolNode
+ {
+ ULONG nBodyWidth; // width of body (argument) of root sign
+@@ -419,19 +637,26 @@ public:
+ : SmMathSymbolNode(NROOTSYMBOL, rNodeToken)
+ {}
+
++ ULONG GetBodyWidth() const {return nBodyWidth;};
+ virtual void AdaptToX(const OutputDevice &rDev, ULONG nWidth);
+ virtual void AdaptToY(const OutputDevice &rDev, ULONG nHeight);
+
+ #ifdef SM_RECT_DEBUG
+ using SmRect::Draw;
+ #endif
+- virtual void Draw(OutputDevice &rDev, const Point &rPosition) const;
++
++ void Accept(SmVisitor* pVisitor);
+ };
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+
+-
++/** Place node
++ *
++ * Used to create the <?> command, that denotes place where something can be
++ * written.
++ * It is drawn as a square with a shadow.
++ */
+ class SmPlaceNode : public SmMathSymbolNode
+ {
+ public:
+@@ -439,15 +664,21 @@ public:
+ : SmMathSymbolNode(NPLACE, rNodeToken)
+ {
+ }
++ SmPlaceNode() : SmMathSymbolNode(NPLACE, SmToken(TPLACE, MS_PLACE, "<?>")) {};
+
+ virtual void Prepare(const SmFormat &rFormat, const SmDocShell &rDocShell);
+ virtual void Arrange(const OutputDevice &rDev, const SmFormat &rFormat);
++ void Accept(SmVisitor* pVisitor);
+ };
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+
+-
++/** Error node, for parsing errors
++ *
++ * This node is used for parsing errors and draws an questionmark turned upside
++ * down (inverted question mark).
++ */
+ class SmErrorNode : public SmMathSymbolNode
+ {
+ public:
+@@ -459,12 +690,19 @@ public:
+
+ virtual void Prepare(const SmFormat &rFormat, const SmDocShell &rDocShell);
+ virtual void Arrange(const OutputDevice &rDev, const SmFormat &rFormat);
++ void Accept(SmVisitor* pVisitor);
+ };
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+
+-
++/** Table node
++ *
++ * This is the root node for the formula tree. This node is also used for the
++ * STACK and BINOM commands. When used for root node, its
++ * children are instances of SmLineNode, and in some obscure cases the a child
++ * can be an instance of SmExpressionNode, mainly when errors occur.
++ */
+ class SmTableNode : public SmStructureNode
+ {
+ public:
+@@ -476,12 +714,17 @@ public:
+ virtual SmNode * GetLeftMost();
+
+ virtual void Arrange(const OutputDevice &rDev, const SmFormat &rFormat);
++ void Accept(SmVisitor* pVisitor);
+ };
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+
+-
++/** A line
++ *
++ * Used as child of SmTableNode when the SmTableNode is the root node of the
++ * formula tree.
++ */
+ class SmLineNode : public SmStructureNode
+ {
+ protected:
+@@ -496,12 +739,18 @@ public:
+
+ virtual void Prepare(const SmFormat &rFormat, const SmDocShell &rDocShell);
+ virtual void Arrange(const OutputDevice &rDev, const SmFormat &rFormat);
++ void Accept(SmVisitor* pVisitor);
+ };
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+
+-
++/** Expression node
++ *
++ * Used whenever you have an expression such as "A OVER {B + C}", here there is
++ * an expression node that allows "B + C" to be the denominator of the
++ * SmBinVerNode, that the OVER command creates.
++ */
+ class SmExpressionNode : public SmLineNode
+ {
+ public:
+@@ -511,12 +760,16 @@ public:
+
+ virtual void Arrange(const OutputDevice &rDev, const SmFormat &rFormat);
+ void CreateTextFromNode(String &rText);
++ void Accept(SmVisitor* pVisitor);
+ };
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+
+-
++/** Unary horizontical node
++ *
++ * The same as SmBinHorNode except this is for unary operators.
++ */
+ class SmUnHorNode : public SmStructureNode
+ {
+ public:
+@@ -527,12 +780,23 @@ public:
+ }
+
+ virtual void Arrange(const OutputDevice &rDev, const SmFormat &rFormat);
++ void Accept(SmVisitor* pVisitor);
+ };
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+
+-
++/** Root node
++ *
++ * Used for create square roots and other roots, example:
++ * \f$ \sqrt[\mbox{[Argument]}]{\mbox{[Body]}} \f$.
++ *
++ * Children:<BR>
++ * 0: Argument (optional)<BR>
++ * 1: Symbol (instance of SmRootSymbolNode)<BR>
++ * 2: Body<BR>
++ * Where argument is optinal and may be NULL.
++ */
+ class SmRootNode : public SmStructureNode
+ {
+ protected:
+@@ -549,12 +813,23 @@ public:
+
+ virtual void Arrange(const OutputDevice &rDev, const SmFormat &rFormat);
+ void CreateTextFromNode(String &rText);
++ void Accept(SmVisitor* pVisitor);
+ };
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+
+-
++/** Binary horizontial node
++ *
++ * This node is used for binary operators. In a formula such as "A + B".
++ *
++ * Children:<BR>
++ * 0: Left operand<BR>
++ * 1: Binary operator<BR>
++ * 2: Right operand<BR>
++ *
++ * None of the children may be NULL.
++ */
+ class SmBinHorNode : public SmStructureNode
+ {
+ public:
+@@ -565,12 +840,24 @@ public:
+ }
+
+ virtual void Arrange(const OutputDevice &rDev, const SmFormat &rFormat);
++ void Accept(SmVisitor* pVisitor);
+ };
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+
+-
++/** Binary horizontical node
++ *
++ * This node is used for creating the OVER command, consider the formula:
++ * "numerator OVER denominator", which looks like
++ * \f$ \frac{\mbox{numerator}}{\mbox{denominator}} \f$
++ *
++ * Children:<BR>
++ * 0: Numerator<BR>
++ * 1: Line (instance of SmRectangleNode)<BR>
++ * 2: Denominator<BR>
++ * None of the children may be NULL.
++ */
+ class SmBinVerNode : public SmStructureNode
+ {
+ public:
+@@ -585,12 +872,22 @@ public:
+
+ virtual void Arrange(const OutputDevice &rDev, const SmFormat &rFormat);
+ void CreateTextFromNode(String &rText);
++ void Accept(SmVisitor* pVisitor);
+ };
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+
+-
++/** Binary diagonal node
++ *
++ * Used for implementing the WIDESLASH command, example: "A WIDESLASH B".
++ *
++ * Children:<BR>
++ * 0: Left operand<BR>
++ * 1: right operand<BR>
++ * 2: Line (instance of SmPolyLineNode).<BR>
++ * None of the children may be NULL.
++ */
+ class SmBinDiagonalNode : public SmStructureNode
+ {
+ BOOL bAscending;
+@@ -605,35 +902,53 @@ public:
+ void SetAscending(BOOL bVal) { bAscending = bVal; }
+
+ virtual void Arrange(const OutputDevice &rDev, const SmFormat &rFormat);
++ void Accept(SmVisitor* pVisitor);
+ };
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+
+
+-// enums used to index sub-/supscripts in the 'aSubNodes' array
+-// in 'SmSubSupNode'
+-// See graphic for positions at char:
+-//
+-// CSUP
+-//
+-// LSUP H H RSUP
+-// H H
+-// HHHH
+-// H H
+-// LSUB H H RSUB
+-//
+-// CSUB
+-//
++/** Enum used to index sub-/supscripts in the 'aSubNodes' array
++ * in 'SmSubSupNode'
++ *
++ * See graphic for positions at char:
++ *
++ * \code
++ * CSUP
++ *
++ * LSUP H H RSUP
++ * H H
++ * HHHH
++ * H H
++ * LSUB H H RSUB
++ *
++ * CSUB
++ * \endcode
++ */
+ enum SmSubSup
+ { CSUB, CSUP, RSUB, RSUP, LSUB, LSUP
+ };
+
+-// numbers of entries in the above enum (that is: the number of possible
+-// sub-/supscripts)
++/** numbers of entries in the above enum (that is: the number of possible
++ * sub-/supscripts)
++ */
+ #define SUBSUP_NUM_ENTRIES 6
+
+-
++/** Super- and subscript node
++ *
++ * Used for creating super- and subscripts for commands such as:
++ * "^", "_", "lsup", "lsub", "csup" and "csub".
++ * Example: "A^2" which looks like: \f$ A^2 \f$
++ *
++ * This node is also used for creating limits on SmOperNode, when
++ * "FROM" and "TO" commands are used with "INT", "SUM" or similar.
++ *
++ * Children of this node can be enumerated using the SmSubSup enum.
++ * Please note that children may be NULL, except for the body.
++ * It is recommended that you access children using GetBody() and
++ * GetSubSup().
++ */
+ class SmSubSupNode : public SmStructureNode
+ {
+ BOOL bUseLimits;
+@@ -646,7 +961,9 @@ public:
+ bUseLimits = FALSE;
+ }
+
++ /** Get body (Not NULL) */
+ SmNode * GetBody() { return GetSubNode(0); }
++ /** Get body (Not NULL) */
+ const SmNode * GetBody() const
+ {
+ return ((SmSubSupNode *) this)->GetBody();
+@@ -655,17 +972,39 @@ public:
+ void SetUseLimits(BOOL bVal) { bUseLimits = bVal; }
+ BOOL IsUseLimits() const { return bUseLimits; };
+
++ /** Get super- or subscript
++ * @remarks this method may return NULL.
++ */
+ SmNode * GetSubSup(SmSubSup eSubSup) { return GetSubNode( sal::static_int_cast< USHORT >(1 + eSubSup) ); };
+
++ /** Set the body */
++ void SetBody(SmNode* pBody) { SetSubNode(0, pBody); }
++ void SetSubSup(SmSubSup eSubSup, SmNode* pScript) { SetSubNode( 1 + eSubSup, pScript); }
++
+ virtual void Arrange(const OutputDevice &rDev, const SmFormat &rFormat);
+ void CreateTextFromNode(String &rText);
++ void Accept(SmVisitor* pVisitor);
+
+ };
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+
+-
++/** Node for brace construction
++ *
++ * Used for "lbrace [body] rbrace" and similar constructions.
++ * Should look like \f$ \{\mbox{[body]}\} \f$
++ *
++ * Children:<BR>
++ * 0: Opening brace<BR>
++ * 1: Body (usually SmBracebodyNode)<BR>
++ * 2: Closing brace<BR>
++ * None of the children can be NULL.
++ *
++ * Note that child 1 (Body) is usually SmBracebodyNode, I don't know if it can
++ * be an SmExpressionNode, haven't seen the case. But didn't quite read parser.cxx
++ * enought to exclude this possibility.
++ */
+ class SmBraceNode : public SmStructureNode
+ {
+ public:
+@@ -677,12 +1016,21 @@ public:
+
+ virtual void Arrange(const OutputDevice &rDev, const SmFormat &rFormat);
+ void CreateTextFromNode(String &rText);
++ void Accept(SmVisitor* pVisitor);
+ };
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+
+-
++/** Body of an SmBraceNode
++ *
++ * This usually only has one child an SmExpressionNode, however, it can also
++ * have other children.
++ * Consider the formula "lbrace [body1] mline [body2] rbrace", looks like:
++ * \f$ \{\mbox{[body1] | [body2]}\} \f$.
++ * In this case SmBracebodyNode will have three children, "[body1]", "|" and
++ * [body2].
++ */
+ class SmBracebodyNode : public SmStructureNode
+ {
+ long nBodyHeight;
+@@ -692,6 +1040,7 @@ public:
+
+ virtual void Arrange(const OutputDevice &rDev, const SmFormat &rFormat);
... etc. - the rest is truncated
More information about the ooo-build-commit
mailing list