11#include <document.hxx>
15#include <editeng/editeng.hxx>
16#include <LibreOfficeKit/LibreOfficeKitEnums.h>
17#include <osl/diagnose.h>
27 OSL_ENSURE(NewPos,
"NewPos shouldn't be NULL here!");
32 OSL_ENSURE(NewPos,
"NewPos shouldn't be NULL here!");
44 for(
const auto &pEntry : *
mpGraph)
51 if(curr_line.GetTop() <= from_line.
GetTop() && direction ==
MoveDown)
continue;
53 if(curr_line.GetTop() + curr_line.GetHeight() >= from_line.
GetTop() + from_line.
GetHeight()
54 && direction ==
MoveUp)
continue;
59 curr_line.SquaredDistanceY(from_line);
61 if(dbp_sq <= dp_sq)
continue;
64 best_line = curr_line;
65 NewPos = pEntry.get();
68 best_line.SquaredDistanceY(from_line);
88 for(
const auto &pEntry : *
mpGraph)
90 OSL_ENSURE(pEntry->CaretPos.IsValid(),
"The caret position graph may not have invalid positions!");
98 if(dbp_sq <= dp_sq)
continue;
101 NewPos = pEntry.get();
133 for(
const auto &pEntry : *
mpGraph)
135 if(_anchor == pEntry->CaretPos)
137 if(_position == pEntry->CaretPos)
156 for(
const auto &pEntry : *
mpGraph)
158 if(pEntry->CaretPos ==
pos)
198 assert(nLineOffsetIdx >= 0);
203 size_t nLineOffset = nLineOffsetIdx;
208 OSL_ENSURE(pMergeLine,
"pMergeLine cannot be NULL!");
211 std::unique_ptr<SmNodeList> pLineList(
new SmNodeList);
213 if(!pLineList->empty()){
215 SmNodeList::iterator patchPoint = pLineList->end();
226 pLineParent->
SetSubNode(nLineOffset-1, pLine);
233 else if(
i > nLineOffset)
283 OSL_ENSURE(pLine !=
mpTree,
"Shouldn't be able to select the entire tree");
289 assert(nLineOffset >= 0);
294 std::unique_ptr<SmNodeList> pLineList(
new SmNodeList);
304 FinishEdit(std::move(pLineList), pLineParent, nLineOffset, PosAfterDelete);
308 if(pNewNodes->empty()){
320 const bool bSelectedIsTopMost = pLine ==
pos.pSelectedNode;
325 assert(nParentIndex >= 0);
328 std::unique_ptr<SmNodeList> pLineList(
new SmNodeList);
332 SmNodeList::iterator it = bSelectedIsTopMost ? pLineList->begin()
336 SmNodeList::iterator newIt,
339 for(newIt = pNewNodes->begin(); newIt != pNewNodes->end(); ++newIt){
340 insIt = pLineList->insert(it, *newIt);
341 if(newIt == pNewNodes->begin())
351 FinishEdit(std::move(pLineList), pLineParent, nParentIndex, PosAfterInsert);
358 SmNodeList::iterator it = std::find(pLineList->begin(), pLineList->end(), rCaretPos.
pSelectedNode);
359 if (it != pLineList->end())
374 assert(!str2.isEmpty());
377 it = pLineList->insert(it, pNewText);
385 return pLineList->begin();
392 if(aIter != pLineList->end())
394 if(aIter != pLineList->begin()) {
406 next->GetToken().eType ==
TNUMBER) ){
410 OUString newText = pText->
GetText() + pOldN->GetText();
413 pLineList->erase(aIter);
420 aIter = pLineList->erase(aIter);
423 if(aIter != pLineList->begin())
425 if(aIter == pLineList->begin())
430 aIter = pLineList->erase(aIter);
443 SmNodeList::iterator retval;
444 SmNodeList::iterator it = pLineList->begin();
445 while(it != pLineList->end()){
446 if((*it)->IsSelected()){
450 OUString aText = pText->
GetText();
455 len2 = start3 - start2,
456 len3 = aText.getLength() - start3;
461 OUString str = aText.copy(0, len1);
465 it = pLineList->erase(it);
472 OUString str = aText.copy(start3, len3);
475 retval = pLineList->insert(it, pSeg3);
478 if(pSelectedNodes && len2 > 0) {
479 OUString str = aText.copy(start2, len2);
482 pSelectedNodes->push_back(pSeg2);
486 retval = it = pLineList->erase(it);
488 pSelectedNodes->push_back(pNode);
513 assert(nParentIndex >= 0);
522 std::unique_ptr<SmNodeList> pLineList(
new SmNodeList);
526 std::unique_ptr<SmNodeList> pSelectedNodesList(
new SmNodeList);
527 SmNodeList::iterator it;
535 bool bPatchLine = !pSelectedNodesList->empty();
536 if(it != pLineList->begin()) {
544 it = pLineList->insert(it, pSubject);
570 std::unique_ptr<SmNodeList> pScriptLineList(
new SmNodeList);
574 unsigned int nOldSize = pScriptLineList->size();
575 pScriptLineList->insert(pScriptLineList->end(), pSelectedNodesList->begin(), pSelectedNodesList->end());
576 pSelectedNodesList.reset();
579 if(0 < nOldSize && nOldSize < pScriptLineList->
size()) {
580 SmNodeList::iterator iPatchPoint = pScriptLineList->begin();
581 std::advance(iPatchPoint, nOldSize);
587 if (!pScriptLineList->empty())
592 pScriptLineList.reset();
595 pSubSup->
SetSubSup(eSubSup, pScriptLine);
598 FinishEdit(std::move(pLineList), pLineParent, nParentIndex, PosAfterScript, pScriptLine);
618 assert(nParentIndex >= 0);
621 std::unique_ptr<SmNodeList> pLineList(
new SmNodeList);
625 std::unique_ptr<SmNodeList> pSelectedNodesList(
new SmNodeList);
626 SmNodeList::iterator it;
633 std::unique_ptr<SmNode> pBodyNode;
635 if(pSelectedNodesList->empty()) {
637 PosAfterInsert =
SmCaretPos(pBodyNode.get(), 1);
641 pSelectedNodesList.reset();
647 std::unique_ptr<SmNode> pLeft(
CreateBracket(eBracketType,
true) ),
650 pBody->SetSubNodes(std::move(pBodyNode),
nullptr);
651 pBrace->
SetSubNodes(std::move(pLeft), std::move(pBody), std::move(pRight));
655 pLineList->insert(it, pBrace);
658 if( !PosAfterInsert.
IsValid() )
659 PosAfterInsert = aAfter;
662 FinishEdit(std::move(pLineList), pLineParent, nParentIndex, PosAfterInsert);
668 switch(eBracketType){
680 switch(eBracketType) {
712 assert(nParentIndex >= 0);
717 int nTableIndex = nParentIndex;
727 assert(nTableIndex >= 0);
733 if(!pTable && !pMatrix)
740 std::unique_ptr<SmNodeList> pLineList(
new SmNodeList);
744 SmNodeList::iterator it;
756 std::unique_ptr<SmNodeList> pNewLineList(
new SmNodeList);
759 pNewLineList->splice(pNewLineList->begin(), rLineList, it, rLineList.end());
761 it = pLineList->end();
762 if(it != pLineList->begin())
764 if(pNewLineList->empty())
767 std::unique_ptr<SmNode> pNewLine(
SmNodeListParser().Parse(pNewLineList.get()));
768 pNewLineList.reset();
772 pNewLineNode->SetSubNodes(std::move(pNewLine),
nullptr);
773 pNewLine = std::move(pNewLineNode);
776 PosAfterInsert =
SmCaretPos(pNewLine.get(), 0);
782 pTable->
SetSubNode(nTableIndex + 1, pNewLine.release());
798 int nRowStart = (nParentIndex - nParentIndex % cols) + cols;
801 for(
int i = nRowStart;
i < nRowStart + cols;
i++) {
803 if(
i == nParentIndex + cols)
811 FinishEdit(std::move(pLineList), pLineParent, nParentIndex, PosAfterInsert);
833 assert(nParentIndex >= 0);
839 std::unique_ptr<SmNodeList> pLineList(
new SmNodeList);
843 std::unique_ptr<SmNodeList> pSelectedNodesList(
new SmNodeList);
844 SmNodeList::iterator it;
851 bool bEmptyFraction = pSelectedNodesList->empty();
852 std::unique_ptr<SmNode> pNum( bEmptyFraction
856 pSelectedNodesList.reset();
861 pFrac->
SetSubNodes(std::move(pNum), std::move(pRect), std::move(pDenom));
864 SmNodeList::iterator patchIt = pLineList->insert(it, pFrac);
884 token.
aText = aString;
891 std::unique_ptr<SmNodeList> pList(
new SmNodeList);
892 pList->push_front(pText);
904 SmNode* pNewNode =
nullptr;
914 pNewNode = pBlankNode;
947 token.
aText =
"cdot";
983 token.
aText =
"\"%\"";
993 std::unique_ptr<SmNodeList> pList(
new SmNodeList);
994 pList->push_front(pNewNode);
1013 token.
aText = aString;
1020 std::unique_ptr<SmNodeList> pList(
new SmNodeList);
1021 pList->push_front(pSpecial);
1035 SmNode* pSubExpr = xSubExpr.release();
1036 std::unique_ptr<SmNodeList> pLineList(
new SmNodeList);
1075 aClipboard.push_front(std::move(pClone));
1078 aClipboard.push_front(std::unique_ptr<SmNode>(aCloneFactory.
Clone(pLine)));
1083 if (!aClipboard.empty())
1099 std::unique_ptr<SmNodeList> pClones(
new SmNodeList);
1101 for(
auto &xNode : rClipboard){
1102 SmNode *pClone = aCloneFactory.
Clone(xNode.get());
1103 pClones->push_back(pClone);
1120 ((MoveUpIfSelected &&
1135 if(pChild->IsSelected())
1145 for(
auto pChild : *pLine)
1149 switch(pChild->GetType()){
1162 list.push_back(pChild);
1171 for(
auto pChild : *pLine)
1186 pClipboard->push_back(std::move(pClone));
1188 pClipboard->push_back(std::unique_ptr<SmNode>(aCloneFactory.
Clone(pChild)));
1236 int entries = pLineList->size();
1240 std::unique_ptr<SmNode> pLine(
parser.Parse(pLineList.get()));
1245 nParentIndex == 0 &&
1249 std::unique_ptr<SmBraceNode> pBrace(
new SmBraceNode(aTok));
1254 pBody->SetSubNodes(std::move(pLine),
nullptr);
1255 pBrace->SetSubNodes(std::move(pLeft), std::move(pBody), std::move(pRight));
1257 pLine = std::move(pBrace);
1274 pStartLine = pLine.get();
1277 pParent->
SetSubNode(nParentIndex, pLine.release());
1339 pViewSh->SendCaretToLOK();
1344 pViewSh->GetGraphicWidget().Invalidate();
1351 if (!
pos.IsValid()) {
1359 if (
pos.nIndex < pTextNode->
GetText().getLength()) {
1364 if (
pos.nIndex < 1) {
1383 pNode = pParentNode;
1398 if (!pClosingNode) {
1405 switch (eBracketType) {
1421 SmNodeList::iterator it =
pList->begin();
1422 while(it !=
pList->end()) {
1426 it =
pList->erase(it);
1449 std::unique_ptr<SmNode> pLeft(
Sum());
1453 std::unique_ptr<SmNode> pOper(
Take());
1455 std::unique_ptr<SmNode> pRight(
Sum());
1458 pNewNode->SetSubNodes(std::move(pLeft), std::move(pOper), std::move(pRight));
1459 pLeft = std::move(pNewNode);
1461 return pLeft.release();
1466 std::unique_ptr<SmNode> pLeft(
Product());
1470 std::unique_ptr<SmNode> pOper(
Take());
1472 std::unique_ptr<SmNode> pRight(
Product());
1475 pNewNode->SetSubNodes(std::move(pLeft), std::move(pOper), std::move(pRight));
1476 pLeft = std::move(pNewNode);
1478 return pLeft.release();
1483 std::unique_ptr<SmNode> pLeft(
Factor());
1487 std::unique_ptr<SmNode> pOper(
Take());
1489 std::unique_ptr<SmNode> pRight(
Factor());
1492 pNewNode->SetSubNodes(std::move(pLeft), std::move(pOper), std::move(pRight));
1493 pLeft = std::move(pNewNode);
1495 return pLeft.release();
1506 std::unique_ptr<SmNode> pOper(
Terminal()),
1512 pArg.reset(
Error());
1514 pUnary->
SetSubNodes(std::move(pOper), std::move(pArg));
1523 std::unique_ptr<SmNode> pArg;
1525 pArg.reset(
Error());
1532 std::unique_ptr<SmNode> pOper(
Take());
1533 pUnary->SetSubNodes(std::move(pArg), std::move(pOper));
1534 pArg = std::move(pUnary);
1536 return pArg.release();
virtual std::unique_ptr< SmNode > ParseExpression(const OUString &rBuffer)=0
Parse rBuffer to formula subtree that constitutes an expression.
void QuickFormatDoc(bool bFull=false)
void QuickInsertText(const OUString &rText, const ESelection &rSel)
bool IsEnableSetModified() const
void EnableSetModified(bool bEnable=true)
SfxObjectCreateMode GetCreateMode() const
void IncreaseBy(const SmToken &rToken, sal_uInt32 nMultiplyBy=1)
Node for brace construction.
const SmMathSymbolNode * ClosingBrace() const
Returns the node containing the data of the closing brace.
Visitor for drawing a caret position.
A line that represents a caret.
tools::Long SquaredDistanceY(const SmCaretLine &line) const
tools::Long GetHeight() const
tools::Long SquaredDistanceX(const SmCaretLine &line) const
tools::Long GetTop() const
Visitor getting a line from a caret position.
const SmCaretLine & GetResult() const
A visitor for building a SmCaretPosGraph.
const tools::Rectangle & getCaret() const
Visitor for cloning a pNode.
SmNode * Clone(SmNode *pNode)
Clone a pNode.
void Delete()
Delete the current selection or do nothing.
void InsertElement(SmFormulaElement element)
Insert an element into the formula.
static SmNodeList::iterator TakeSelectedNodesFromList(SmNodeList *pLineList, SmNodeList *pSelectedNodes=nullptr)
Take selected nodes from a list.
void InsertFraction()
Insert a fraction, use selection as numerator.
SmCaretPosGraphEntry * mpPosition
const SmCaretPos & GetPosition() const
Get position.
void InsertBrackets(SmBracketType eBracketType)
Create brackets around current selection, or new SmPlaceNode.
void Copy()
Copy the current selection.
static SmNode * CreateBracket(SmBracketType eBracketType, bool bIsLeft)
Create an instance of SmMathSymbolNode usable for brackets.
void DeletePrev(OutputDevice *pDev)
Delete selection, previous element or merge lines.
void Draw(OutputDevice &pDev, Point Offset, bool isCaretVisible)
Draw the caret.
SmNode * mpTree
Formula tree.
static SmNode * FindTopMostNodeInLine(SmNode *pSNode, bool MoveUpIfSelected=false)
Finds the topmost node in a visual line.
SmCaretPosGraphEntry * mpAnchor
bool HasSelection() const
True, if the cursor has a selection.
bool IsAtTailOfBracket(SmBracketType eBracketType) const
static std::unique_ptr< SmNodeList > CloneList(SmClipboard &rClipboard)
Clone list of nodes in a clipboard (creates a deep clone)
void InsertNodes(std::unique_ptr< SmNodeList > pNewNodes)
Insert new nodes in the tree after position.
int CountSelectedNodes(SmNode *pNode)
Count number of selected nodes, excluding line composition nodes.
void FinishEdit(std::unique_ptr< SmNodeList > pLineList, SmStructureNode *pParent, int nParentIndex, SmCaretPos PosAfterEdit, SmNode *pStartLine=nullptr)
Finish editing.
void EndEdit()
End edit section where the tree will be modified.
void MoveTo(OutputDevice *pDev, const Point &pos, bool bMoveAnchor)
Move to the caret position closest to a given point.
static void NodeToList(SmNode *&rpNode, SmNodeList &rList)
Auxiliary function for calling LineToList on a node.
SmClipboard maClipboard
Clipboard holder.
void Paste()
Paste the clipboard.
SmNode * FindSelectedNode(SmNode *pNode)
Returns a node that is selected, if any could be found.
static void CloneLineToClipboard(SmStructureNode *pLine, SmClipboard *pClipboard)
Clone a visual line to a clipboard.
void BuildGraph()
Build pGraph over caret positions.
SmDocShell * mpDocShell
Owner of the formula tree.
void RequestRepaint()
Request the formula is repainted.
bool SetCaretPosition(SmCaretPos pos)
tries to set position to a specific SmCaretPos
int mnEditSections
The number of times BeginEdit have been called Used to allow nesting of BeginEdit() and EndEdit() sec...
bool HasComplexSelection()
Returns true if more than one node is selected.
static bool IsLineCompositionNode(SmNode const *pNode)
Is this one of the nodes used to compose a line.
std::unique_ptr< SmCaretPosGraph > mpGraph
Graph over caret position in the current tree.
tools::Rectangle GetCaretRectangle(OutputDevice &rOutDev) const
void InsertSubSup(SmSubSup eSubSup)
Create sub-/super script.
void InsertCommandText(const OUString &aCommandText)
Insert command text translated into line entries at position.
static SmNodeList::iterator FindPositionInLineList(SmNodeList *pLineList, const SmCaretPos &rCaretPos)
Find an iterator pointing to the node in pLineList following rCaretPos.
bool InsertRow()
Insert a new row or newline.
void BeginEdit()
Begin edit section where the tree will be modified.
bool mbIsEnabledSetModifiedSmDocShell
Holds data for BeginEdit() and EndEdit()
static void LineToList(SmStructureNode *pLine, SmNodeList &rList)
Convert a visual line to a list.
static SmCaretPos PatchLineList(SmNodeList *pLineList, SmNodeList::iterator aIter)
Patch a line list after modification, merge SmTextNode, remove SmPlaceNode etc.
void AnnotateSelection() const
Set selected on nodes of the tree.
void InsertText(const OUString &aString)
Insert text at the current position.
void Move(OutputDevice *pDev, SmMovementDirection direction, bool bMoveAnchor=true)
Move the position of this cursor.
tools::Rectangle GetSelectionRectangle(OutputDevice &rOutDev) const
void InsertSpecial(std::u16string_view aString)
Insert a special node created from aString.
virtual void OnDocumentPrinterChanged(Printer *) override
EditEngine & GetEditEngine()
void SetFormulaArranged(bool bVal)
virtual void SetModified(bool bModified=true) override
const SmFormat & GetFormat() const
AbstractSmParser * GetParser()
Error node, for parsing errors.
void SetRowCol(sal_uInt16 nMatrixRows, sal_uInt16 nMatrixCols)
Sets the dimensions of the matrix.
sal_uInt16 GetNumRows() const
Gets the number of rows of the matrix.
sal_uInt16 GetNumCols() const
Gets the number of columns of the matrix.
Minimalistic recursive decent SmNodeList parser.
SmNode * Parse(SmNodeList *list)
Parse a list of nodes to an expression.
static bool IsOperator(const SmToken &token)
True, if the token is an operator.
static bool IsRelationOperator(const SmToken &token)
True, if the token is a relation operator.
SmNode * Next()
Move to next terminal.
SmNode * Take()
Take the current terminal.
static bool IsProductOperator(const SmToken &token)
True, if the token is a product operator.
static bool IsUnaryOperator(const SmToken &token)
True, if the token is a unary operator.
static bool IsSumOperator(const SmToken &token)
True, if the token is a sum operator.
static bool IsPostfixOperator(const SmToken &token)
True, if the token is a postfix operator.
SmNode * Terminal()
Get the current terminal.
Extract command text from pNodes.
SmScaleMode GetScaleMode() const
Gets the scale mode.
virtual size_t GetNumSubNodes() const =0
Gets the number of subnodes.
virtual void Prepare(const SmFormat &rFormat, const SmDocShell &rDocShell, int nDepth)
Prepare preliminary settings about font and text (e.g.
const SmToken & GetToken() const
Gets the token.
bool IsSelected() const
Checks if the node is selected.
void SetScaleMode(SmScaleMode eMode)
Sets the scale mode to eMode.
const SmStructureNode * GetParent() const
Gets the parent node of this node.
SmNodeType GetType() const
Gets the node type.
void SetToken(SmToken const &token)
Sets the token for this node.
const tools::Rectangle & GetSelection()
Set Selection Visitor Sets the IsSelected( ) property on all SmNodes of the tree.
Special node for user defined characters.
virtual void Prepare(const SmFormat &rFormat, const SmDocShell &rDocShell, int nDepth) override
Prepare preliminary settings about font and text (e.g.
Abstract baseclass for all composite node.
int IndexOfSubNode(SmNode const *pSubNode)
Get the index of the child node pSubNode.
virtual size_t GetNumSubNodes() const override
Gets the number of subnodes.
void SetSubNodes(std::unique_ptr< SmNode > pFirst, std::unique_ptr< SmNode > pSecond, std::unique_ptr< SmNode > pThird=nullptr)
Sets subnodes, used for operators.
virtual SmNode * GetSubNode(size_t nIndex) override
Gets the subnode of index nIndex.
void SetSubNode(size_t nIndex, SmNode *pNode)
Sets the subnode pNode at nIndex.
void ClearSubNodes()
Does the cleaning of the subnodes.
Super- and subscript node.
void SetSubSup(SmSubSup eSubSup, SmNode *pScript)
Sets the node with the data of what has to be superindex or subindex.
const SmNode * GetSubSup(SmSubSup eSubSup) const
Gets the node with the data of what has to be superindex or subindex.
void SetBody(SmNode *pBody)
Sets the node with the data of what has to be superindex or subindex.
void ChangeText(const OUString &rText)
Change the text of this node, including the underlying token to rText.
void AdjustFontDesc()
Try to guess the correct FontDesc, used during visual editing.
void SetText(const OUString &rText)
Sets the node text to rText.
const OUString & GetText() const
Gets the node text.
sal_Int32 GetSelectionStart() const
Index within GetText() where the selection starts.
sal_uInt16 GetFontDesc() const
Returns the font type being used (text, variable, symbol, ...).
sal_Int32 GetSelectionEnd() const
Index within GetText() where the selection ends.
virtual void Prepare(const SmFormat &rFormat, const SmDocShell &rDocShell, int nDepth) override
Prepare preliminary settings about font and text (e.g.
SmFormulaElement
Enum of elements that can inserted into a formula.
std::list< SmNode * > SmNodeList
A list of nodes.
#define HORIZONTICAL_DISTANCE_FACTOR
Factor to multiple the squared horizontal distance with Used for Up and Down movement.
std::list< std::unique_ptr< SmNode > > SmClipboard
SmBracketType
Bracket types that can be inserted.
@ Round
Round brackets, left command "(".
@ Square
Square brackets, left command "[".
@ Curly
Curly brackets, left command "lbrace".
SmMovementDirection
Enum of direction for movement.
OString strip(const OString &rIn, char c)
std::vector< SmNode * > SmNodeArray
SmSubSup
Enum used to index sub-/supscripts in the 'maSubNodes' array in 'SmSubSupNode'.
An entry in SmCaretPosGraph.
SmCaretPosGraphEntry * Left
Entry to the left visually.
SmCaretPosGraphEntry * Right
Entry to the right visually.
const SmCaretPos CaretPos
Caret position.
Representation of caret position with an equation.
bool IsValid() const
True, if this is a valid caret position.
int nIndex
Index (invariant: non-negative) within the selected node.
SmNode * pSelectedNode
Selected node.
static SmCaretPos GetPosAfter(SmNode *pNode)
Get the caret position after pNode, regardless of pNode.
void setChar(sal_Unicode cChar)
sal_Unicode const MS_FACT
sal_Unicode const MS_LBRACKET
sal_Unicode const MS_PLUS
sal_Unicode const MS_MINUS
sal_Unicode const MS_RBRACKET
sal_Unicode const MS_CDOT
sal_Unicode const MS_ASSIGN
sal_Unicode const MS_RPARENT
sal_Unicode const MS_PERCENT
sal_Unicode const MS_RBRACE
sal_Unicode const MS_LBRACE
sal_Unicode const MS_LPARENT
SmViewShell * SmGetActiveView()
! Since this method is based on the current focus it is somewhat ! unreliable and may return unexpect...