summaryrefslogtreecommitdiff
path: root/starmath
diff options
context:
space:
mode:
authorDaisuke Nishino <niboshi000@gmail.com>2011-11-15 19:42:35 +0900
committerNoel Power <noel.power@novell.com>2011-11-16 14:54:21 +0000
commit20dde3737f250ab48b80a28c9c03d348e486dd8b (patch)
tree03324ac0aac8af25f8b98019d45415698c28979d /starmath
parent1b6d2c7f465cb1249e33d9e873f11756be634a3a (diff)
Move cursor to the right of brace when the closing brace is typed.
Diffstat (limited to 'starmath')
-rw-r--r--starmath/inc/caret.hxx2
-rw-r--r--starmath/inc/cursor.hxx5
-rw-r--r--starmath/inc/node.hxx7
-rw-r--r--starmath/source/cursor.cxx89
-rw-r--r--starmath/source/node.cxx15
-rw-r--r--starmath/source/view.cxx8
6 files changed, 122 insertions, 4 deletions
diff --git a/starmath/inc/caret.hxx b/starmath/inc/caret.hxx
index cec8bd722482..76e25279fb55 100644
--- a/starmath/inc/caret.hxx
+++ b/starmath/inc/caret.hxx
@@ -50,7 +50,7 @@ struct SmCaretPos{
//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 IsValid() const { return pSelectedNode != NULL; }
bool operator!=(SmCaretPos pos) const {
return pos.pSelectedNode != pSelectedNode || Index != pos.Index;
}
diff --git a/starmath/inc/cursor.hxx b/starmath/inc/cursor.hxx
index 6b6e7168a59c..dcfea886736d 100644
--- a/starmath/inc/cursor.hxx
+++ b/starmath/inc/cursor.hxx
@@ -118,7 +118,7 @@ public:
SmCaretPos GetAnchor(){ return anchor->CaretPos; }
/** Get position */
- SmCaretPos GetPosition() { return position->CaretPos; }
+ SmCaretPos GetPosition() const { return position->CaretPos; }
/** True, if the cursor has a selection */
bool HasSelection() { return anchor != position; }
@@ -236,6 +236,9 @@ public:
/** Draw the caret */
void Draw(OutputDevice& pDev, Point Offset, bool isCaretVisible);
+ bool IsAtTailOfBracket(SmBracketType eBracketType, SmBraceNode** ppBraceNode = NULL) const;
+ void MoveAfterBracket(SmBraceNode* pBraceNode, bool bMoveAnchor = true);
+
private:
friend class SmDocShell;
diff --git a/starmath/inc/node.hxx b/starmath/inc/node.hxx
index 07aca32eaa29..1ecde44b406e 100644
--- a/starmath/inc/node.hxx
+++ b/starmath/inc/node.hxx
@@ -119,13 +119,13 @@ public:
virtual SmNode * GetSubNode(sal_uInt16 nIndex);
const SmNode * GetSubNode(sal_uInt16 nIndex) const
{
- return ((SmNode *) this)->GetSubNode(nIndex);
+ return const_cast<SmNode *>(this)->GetSubNode(nIndex);
}
virtual SmNode * GetLeftMost();
const SmNode * GetLeftMost() const
{
- return ((SmNode *) this)->GetLeftMost();
+ return const_cast<SmNode *>(this)->GetLeftMost();
}
sal_uInt16 & Flags() { return nFlags; }
@@ -149,6 +149,8 @@ public:
virtual void Prepare(const SmFormat &rFormat, const SmDocShell &rDocShell);
virtual void PrepareAttributes();
+ sal_uInt16 FindIndex() const;
+
#if OSL_DEBUG_LEVEL
void ToggleDebug() const;
#endif
@@ -206,6 +208,7 @@ public:
/** Get the parent node of this node */
SmStructureNode* GetParent(){ return aParentNode; }
+ const SmStructureNode* GetParent() const { return aParentNode; }
/** Set the parent node */
void SetParent(SmStructureNode* parent){
aParentNode = parent;
diff --git a/starmath/source/cursor.cxx b/starmath/source/cursor.cxx
index 5d92d44691c3..ab4094ab03e2 100644
--- a/starmath/source/cursor.cxx
+++ b/starmath/source/cursor.cxx
@@ -1474,6 +1474,95 @@ void SmCursor::RequestRepaint(){
}
}
+bool SmCursor::IsAtTailOfBracket(SmBracketType eBracketType, SmBraceNode** ppBraceNode) const {
+ const SmCaretPos pos = GetPosition();
+ if (!pos.IsValid()) {
+ return false;
+ }
+
+ SmNode* pNode = pos.pSelectedNode;
+
+ if (pNode->GetType() == NTEXT) {
+ SmTextNode* pTextNode = static_cast<SmTextNode*>(pNode);
+ if (pos.Index < pTextNode->GetText().Len()) {
+ // The cursor is on a text node and at the middle of it.
+ return false;
+ }
+ } else {
+ if (pos.Index < 1) {
+ return false;
+ }
+ }
+
+ while (true) {
+ SmStructureNode* pParentNode = pNode->GetParent();
+ if (!pParentNode) {
+ // There's no brace body node in the ancestors.
+ return false;
+ }
+
+ sal_uInt16 index = pNode->FindIndex();
+ if (index + 1 != pParentNode->GetNumSubNodes()) {
+ // The cursor is not at the tail at one of ancestor nodes.
+ return false;
+ }
+
+ pNode = pParentNode;
+ if (pNode->GetType() == NBRACEBODY) {
+ // Found the brace body node.
+ break;
+ }
+ }
+
+ SmStructureNode* pBraceNodeTmp = pNode->GetParent();
+ if (!pBraceNodeTmp || pBraceNodeTmp->GetType() != NBRACE) {
+ // Brace node is invalid.
+ return false;
+ }
+
+ SmBraceNode* pBraceNode = static_cast<SmBraceNode*>(pBraceNodeTmp);
+ SmMathSymbolNode* pClosingNode = pBraceNode->ClosingBrace();
+ if (!pClosingNode) {
+ // Couldn't get closing symbol node.
+ return false;
+ }
+
+ // Check if the closing brace matches eBracketType.
+ SmTokenType eClosingTokenType = pClosingNode->GetToken().eType;
+ switch (eBracketType) {
+ case NoneBrackets: if (eClosingTokenType != TNONE) { return false; } break;
+ case RoundBrackets: if (eClosingTokenType != TRPARENT) { return false; } break;
+ case SquareBrackets: if (eClosingTokenType != TRBRACKET) { return false; } break;
+ case DoubleSquareBrackets: if (eClosingTokenType != TRDBRACKET) { return false; } break;
+ case LineBrackets: if (eClosingTokenType != TRLINE) { return false; } break;
+ case DoubleLineBrackets: if (eClosingTokenType != TRDLINE) { return false; } break;
+ case CurlyBrackets: if (eClosingTokenType != TRBRACE) { return false; } break;
+ case AngleBrackets: if (eClosingTokenType != TRANGLE) { return false; } break;
+ case CeilBrackets: if (eClosingTokenType != TRCEIL) { return false; } break;
+ case FloorBrackets: if (eClosingTokenType != TRFLOOR) { return false; } break;
+ default:
+ return false;
+ }
+
+ if (ppBraceNode) {
+ *ppBraceNode = static_cast<SmBraceNode*>(pBraceNode);
+ }
+
+ return true;
+}
+
+void SmCursor::MoveAfterBracket(SmBraceNode* pBraceNode, bool bMoveAnchor)
+{
+ position->CaretPos.pSelectedNode = pBraceNode;
+ position->CaretPos.Index = 1;
+ if (bMoveAnchor) {
+ anchor->CaretPos.pSelectedNode = pBraceNode;
+ anchor->CaretPos.Index = 1;
+ }
+ RequestRepaint();
+}
+
+
/////////////////////////////////////// SmNodeListParser ///////////////////////////////////////
SmNode* SmNodeListParser::Parse(SmNodeList* list, bool bDeleteErrorNodes){
diff --git a/starmath/source/node.cxx b/starmath/source/node.cxx
index 93dbedf73ea5..29ed2837980a 100644
--- a/starmath/source/node.cxx
+++ b/starmath/source/node.cxx
@@ -381,6 +381,21 @@ void SmNode::Prepare(const SmFormat &rFormat, const SmDocShell &rDocShell)
pNode->Prepare(rFormat, rDocShell);
}
+sal_uInt16 SmNode::FindIndex() const
+{
+ const SmStructureNode* pParent = GetParent();
+ if (!pParent) { return 0; }
+
+ for (sal_uInt16 i = 0; i < pParent->GetNumSubNodes(); ++i) {
+ if (pParent->GetSubNode(i) == this) {
+ return i;
+ }
+ }
+
+ DBG_ASSERT(false, "Connection between parent and child is inconsistent.");
+ return 0;
+}
+
#if OSL_DEBUG_LEVEL > 1
void SmNode::ToggleDebug() const
diff --git a/starmath/source/view.cxx b/starmath/source/view.cxx
index 0dec05a7bf38..a77a32a92e77 100644
--- a/starmath/source/view.cxx
+++ b/starmath/source/view.cxx
@@ -504,6 +504,8 @@ void SmGraphicWindow::KeyInput(const KeyEvent& rKEvt)
default:
{
sal_Unicode code = rKEvt.GetCharCode();
+ SmBraceNode* pBraceNode = NULL;
+
if(code == ' ') {
rCursor.InsertElement(BlankElement);
}else if(code == 'c' && rKEvt.GetKeyCode().IsMod1()) {
@@ -524,6 +526,12 @@ void SmGraphicWindow::KeyInput(const KeyEvent& rKEvt)
rCursor.InsertElement(FactorialElement);
}else if(code == '%') {
rCursor.InsertElement(PercentElement);
+ }else if(code == ')' && rCursor.IsAtTailOfBracket(RoundBrackets, &pBraceNode)) {
+ rCursor.MoveAfterBracket(pBraceNode);
+ }else if(code == ']' && rCursor.IsAtTailOfBracket(SquareBrackets, &pBraceNode)) {
+ rCursor.MoveAfterBracket(pBraceNode);
+ }else if(code == '}' && rCursor.IsAtTailOfBracket(CurlyBrackets, &pBraceNode)) {
+ rCursor.MoveAfterBracket(pBraceNode);
}else{
if(code != 0){
rCursor.InsertText(code);