summaryrefslogtreecommitdiff
path: root/sw
diff options
context:
space:
mode:
authorNico Weyand <nico.weyand@gmail.com>2012-09-02 22:09:38 +0200
committerTomaž Vajngerl <quikee@gmail.com>2012-09-02 22:09:38 +0200
commit51f9e894f46e718200a14bcd61e9e44c64bc5396 (patch)
tree2bcfe6dfb102cce9807003d8b50a8ad18261c741 /sw
parent4b161067d46ddd48b4602ccdcc4d1b2545e2ac83 (diff)
Improved usage of the auto-complete tree structure.
Auto-complete lookup structure remembers as-you-type the character position in a word. Currently the whole word was always looked up which was not necessary. This patch improves this. Change-Id: I7dced25707979377ae3f696a5987956d2308aeec
Diffstat (limited to 'sw')
-rw-r--r--sw/inc/acmplwrd.hxx16
-rw-r--r--sw/source/core/doc/acmplwrd.cxx44
-rw-r--r--sw/source/ui/docvw/edtwin.cxx126
3 files changed, 160 insertions, 26 deletions
diff --git a/sw/inc/acmplwrd.hxx b/sw/inc/acmplwrd.hxx
index 72421c384c7b..8e0dd750141a 100644
--- a/sw/inc/acmplwrd.hxx
+++ b/sw/inc/acmplwrd.hxx
@@ -79,7 +79,21 @@ public:
void CheckChangedList(const editeng::SortedAutoCompleteStrings& rNewLst);
- bool GetWordsMatching(String aMatch, std::vector<String>& aWords) const;
+ // Resets the current position within the tree to its root node.
+ void returnToRoot();
+
+ // Advances to a given node within the AutoComplete tree.
+ void gotoNode(OUString sNode);
+
+ // Advances from the current position towards the node keyed with cKey.
+ void advance(const sal_Unicode cKey);
+
+ // Goes back one char within the tree, except if the current node is already the root node.
+ void goBack();
+
+ // Returns all words matching a given prefix aMatch. If bIgnoreCurrentPos is set, the current
+ // position within the tree is ignored and replaced by aMatch.
+ bool GetWordsMatching(String aMatch, std::vector<String>& aWords, sal_Bool bIgnoreCurrentPos) const;
};
diff --git a/sw/source/core/doc/acmplwrd.cxx b/sw/source/core/doc/acmplwrd.cxx
index d569e16edc7a..65ce21aa47c3 100644
--- a/sw/source/core/doc/acmplwrd.cxx
+++ b/sw/source/core/doc/acmplwrd.cxx
@@ -355,18 +355,52 @@ void SwAutoCompleteWord::SetMinWordLen( sal_uInt16 n )
nMinWrdLen = n;
}
-bool SwAutoCompleteWord::GetWordsMatching(String aMatch, std::vector<String>& aWords) const
+// Resets the current position within the tree to its root node.
+void SwAutoCompleteWord::returnToRoot()
{
- OUString aStringRoot = OUString(aMatch);
- m_LookupTree->gotoNode( aStringRoot );
+ m_LookupTree->returnToRoot();
+}
+
+// Advances to a given node within the AutoComplete tree.
+void SwAutoCompleteWord::gotoNode(OUString sNode)
+{
+ m_LookupTree->gotoNode( sNode );
+}
+
+// Advances from the current position towards the node keyed with cKey.
+void SwAutoCompleteWord::advance(const sal_Unicode cKey)
+{
+ m_LookupTree->advance( cKey );
+}
+
+// Goes back one char within the tree, except if the current node is already the root node.
+void SwAutoCompleteWord::goBack()
+{
+ m_LookupTree->goBack();
+}
+
+// Returns all words matching a given prefix aMatch. If bIgnoreCurrentPos is set, the current
+// position within the tree is ignored and replaced by aMatch.
+bool SwAutoCompleteWord::GetWordsMatching(String aMatch, std::vector<String>& aWords, sal_Bool bIgnoreCurrentPos) const
+{
+ OUString aStringRoot = OUString( aMatch );
+
+ // The lookup tree already contains the information about the root keyword in most cases. Only if we don't trust that
+ // information (e.g. if we need some autocompletion for a place other than the main writing area), the location within
+ // the tree needs to be refreshed.
+ if (bIgnoreCurrentPos)
+ {
+ m_LookupTree->gotoNode( aStringRoot );
+ }
+
OUString aAutocompleteWord = m_LookupTree->suggestAutoCompletion();
if (aAutocompleteWord.isEmpty())
+ {
return false;
+ }
OUString aCompleteWord = aStringRoot + aAutocompleteWord;
-
aWords.push_back( String(aCompleteWord) );
-
return true;
}
diff --git a/sw/source/ui/docvw/edtwin.cxx b/sw/source/ui/docvw/edtwin.cxx
index 812d7bd8af28..1ccb7fb38c82 100644
--- a/sw/source/ui/docvw/edtwin.cxx
+++ b/sw/source/ui/docvw/edtwin.cxx
@@ -314,7 +314,9 @@ struct QuickHelpData
if( 0 == nCurArrPos-- )
nCurArrPos = (bEndLess && !m_bIsAutoText ) ? m_aHelpStrings.size()-1 : 0;
}
- void FillStrArr( SwWrtShell& rSh, const String& rWord );
+
+ // Fills internal structures with hopefully helpful information.
+ void FillStrArr( SwWrtShell& rSh, const String& rWord, sal_Bool bIgnoreCurrentPos );
void SortAndFilter();
};
@@ -1519,6 +1521,19 @@ void SwEditWin::KeyInput(const KeyEvent &rKEvt)
sal_Bool bStopKeyInputTimer = sal_True;
String sFmlEntry;
+ enum SW_AutoCompleteAction { ACA_NoOp, // No maintenance operation required for AutoComplete tree
+ ACA_ReturnToRoot, // Input of a char marking the end of a word, like '.', ' ', etc.
+ ACA_SingleCharInput,
+ ACA_SingleBackspace,
+ ACA_Refresh }; // Refresh AutoComplete information completely.
+
+ // Do refresh by default to gracefully handle all unimplemented special cases.
+ SW_AutoCompleteAction eAutoCompleteAction = ACA_Refresh;
+ // TODO: Make sure eAutoCompleteAction is set to something other than ACA_Refresh to increase performance.
+
+ // Stores input char in case ACA_SingleCharInput is used. Defaults to aCh to avoid compiler warning.
+ sal_Unicode aSingleCharInput = aCh;
+
enum SW_KeyState { KS_Start,
KS_CheckKey, KS_InsChar, KS_InsTab,
KS_NoNum, KS_NumOff, KS_NumOrNoNum, KS_NumDown, KS_NumUp,
@@ -1786,9 +1801,9 @@ KEYINPUT_CHECKTABLE_INSDEL:
case KEY_DELETE:
if ( !rSh.HasReadonlySel() )
{
- if (rSh.IsInFrontOfLabel() &&
- rSh.NumOrNoNum(sal_False))
+ if (rSh.IsInFrontOfLabel() && rSh.NumOrNoNum(sal_False))
eKeyState = KS_NumOrNoNum;
+ eAutoCompleteAction = ACA_NoOp;
}
else
{
@@ -1806,6 +1821,7 @@ KEYINPUT_CHECKTABLE_INSDEL:
bTblIsColMode = sal_True;
aKeyInputTimer.Start();
bStopKeyInputTimer = sal_False;
+ eAutoCompleteAction = ACA_NoOp;
}
break;
case KEY_INSERT | KEY_MOD2:
@@ -1817,6 +1833,7 @@ KEYINPUT_CHECKTABLE_INSDEL:
bTblIsColMode = sal_True;
aKeyInputTimer.Start();
bStopKeyInputTimer = sal_False;
+ eAutoCompleteAction = ACA_NoOp;
}
break;
@@ -1853,6 +1870,8 @@ KEYINPUT_CHECKTABLE_INSDEL:
eKeyState = KS_CheckAutoCorrect, eNextKeyState = KS_AutoFmtByInput;
else
eNextKeyState = eKeyState, eKeyState = KS_CheckAutoCorrect;
+
+ eAutoCompleteAction = ACA_ReturnToRoot;
}
break;
@@ -1885,6 +1904,11 @@ KEYINPUT_CHECKTABLE_INSDEL:
bDone = rSh.TryRemoveIndent();
}
+ if ( bOnlyBackspaceKey )
+ {
+ eAutoCompleteAction = ACA_SingleBackspace;
+ }
+
if (bDone)
eKeyState = KS_Ende;
else
@@ -2091,10 +2115,12 @@ KEYINPUT_CHECKTABLE_INSDEL:
{
eKeyState = KS_InsTab;
}
+ eAutoCompleteAction = ACA_NoOp;
}
break;
case KEY_TAB | KEY_MOD1 | KEY_SHIFT:
+ {
if( aTmpQHD.HasCntnt() && !rSh.HasSelection() &&
!rSh.HasReadonlySel() )
{
@@ -2106,7 +2132,11 @@ KEYINPUT_CHECKTABLE_INSDEL:
else if((rSh.GetSelectionType() & (nsSelectionType::SEL_DRW|nsSelectionType::SEL_DRW_FORM|
nsSelectionType::SEL_FRM|nsSelectionType::SEL_OLE|nsSelectionType::SEL_GRF)) &&
rSh.GetDrawView()->AreObjectsMarked())
+ {
eKeyState = KS_EnterDrawHandleMode;
+ }
+ eAutoCompleteAction = ACA_NoOp;
+ }
break;
case KEY_F2 :
if( !rSh.HasReadonlySel() )
@@ -2116,6 +2146,7 @@ KEYINPUT_CHECKTABLE_INSDEL:
eKeyState = KS_GoIntoFly;
else if((nSelectionType & nsSelectionType::SEL_DRW))
eKeyState = KS_GoIntoDrawing;
+ eAutoCompleteAction = ACA_NoOp;
}
break;
}
@@ -2165,6 +2196,7 @@ KEYINPUT_CHECKTABLE_INSDEL:
}
break;
}
+ eAutoCompleteAction = ACA_NoOp;
}
break;
@@ -2184,6 +2216,7 @@ KEYINPUT_CHECKTABLE_INSDEL:
FlushInBuffer();
break;
}
+ eAutoCompleteAction = ACA_NoOp;
}
break;
@@ -2194,11 +2227,14 @@ KEYINPUT_CHECKTABLE_INSDEL:
!rKeyCode.IsMod2() &&
rKeyCode.GetModifier() != (KEY_MOD1) &&
rKeyCode.GetModifier() != (KEY_MOD1|KEY_SHIFT) &&
- SW_ISPRINTABLE( aCh );
+ SW_ISPRINTABLE( aCh );
- if (bNormalChar && rSh.IsInFrontOfLabel())
+ if( bNormalChar )
{
- rSh.NumOrNoNum(sal_False);
+ eAutoCompleteAction = ACA_SingleCharInput;
+ aSingleCharInput = aCh;
+ if ( rSh.IsInFrontOfLabel() )
+ rSh.NumOrNoNum(sal_False);
}
if( aInBuffer.Len() && ( !bNormalChar || bIsDocReadOnly ))
@@ -2248,17 +2284,23 @@ KEYINPUT_CHECKTABLE_INSDEL:
}
break;
case KS_LaunchOLEObject:
+ {
rSh.LaunchOLEObj();
eKeyState = KS_Ende;
+ eAutoCompleteAction = ACA_NoOp;
+ }
break;
- case KS_GoIntoFly :
+ case KS_GoIntoFly:
+ {
rSh.UnSelectFrm();
rSh.LeaveSelFrmMode();
rView.AttrChangedNotify(&rSh);
rSh.MoveSection( fnSectionCurr, fnSectionEnd );
eKeyState = KS_Ende;
+ eAutoCompleteAction = ACA_NoOp;
+ }
break;
- case KS_GoIntoDrawing :
+ case KS_GoIntoDrawing:
{
SdrObject* pObj = rSh.GetDrawView()->GetMarkedObjectList().GetMark(0)->GetMarkedSdrObj();
if(pObj)
@@ -2268,6 +2310,7 @@ KEYINPUT_CHECKTABLE_INSDEL:
((SwDrawTextShell*)rView.GetCurShell())->Init();
}
eKeyState = KS_Ende;
+ eAutoCompleteAction = ACA_NoOp;
}
break;
case KS_EnterDrawHandleMode:
@@ -2277,6 +2320,7 @@ KEYINPUT_CHECKTABLE_INSDEL:
((SdrHdlList&)rHdlList).TravelFocusHdl(bForward);
eKeyState = KS_Ende;
+ eAutoCompleteAction = ACA_NoOp;
}
break;
case KS_InsTab:
@@ -2288,6 +2332,7 @@ KEYINPUT_CHECKTABLE_INSDEL:
break;
}
aCh = '\t';
+ eAutoCompleteAction = ACA_ReturnToRoot;
// no break!
case KS_InsChar:
if (rSh.GetChar(sal_False)==CH_TXT_ATR_FORMELEMENT)
@@ -2389,6 +2434,7 @@ KEYINPUT_CHECKTABLE_INSDEL:
rSh.AutoCorrect( *pACorr, static_cast< sal_Unicode >('\0') );
}
eKeyState = eNextKeyState;
+ eAutoCompleteAction = ACA_NoOp;
}
break;
@@ -2597,29 +2643,64 @@ KEYINPUT_CHECKTABLE_INSDEL:
bTblInsDelMode = sal_False;
}
+ bool bInsertBufferedChars = bFlushBuffer && aInBuffer.Len();
+ bool bAutoCompleteEnabled = pACfg && pACorr && ( pACfg->IsAutoTextTip() || pACorr->GetSwFlags().bAutoCompleteWords );
+ bool bGotWord = false;
+ String sPrefix;
+
// in case the buffered characters are inserted
- if( bFlushBuffer && aInBuffer.Len() )
+ if( bInsertBufferedChars )
{
// bFlushCharBuffer was not resetted here
// why not?
sal_Bool bSave = bFlushCharBuffer;
FlushInBuffer();
bFlushCharBuffer = bSave;
+ }
- // maybe show Tip-Help
- String sWord;
- if( bNormalChar && pACfg && pACorr &&
- ( pACfg->IsAutoTextTip() ||
- pACorr->GetSwFlags().bAutoCompleteWords ) &&
- rSh.GetPrevAutoCorrWord( *pACorr, sWord ) )
+ // maintain AutoComplete tree
+ if( bAutoCompleteEnabled )
+ {
+ // avoid unnecessary calls to GetPrevAutoCorrWord
+ if( (bInsertBufferedChars && bNormalChar) || eAutoCompleteAction == ACA_Refresh )
+ {
+ bGotWord = rSh.GetPrevAutoCorrWord( *pACorr, sPrefix );
+ }
+
+ SwAutoCompleteWord& rACList = rSh.GetAutoCompleteWords();
+
+ switch( eAutoCompleteAction )
{
- ShowAutoTextCorrectQuickHelp(sWord, pACfg, pACorr);
+ case ACA_NoOp:
+ // do nothing
+ break;
+
+ case ACA_ReturnToRoot:
+ rACList.returnToRoot();
+ break;
+
+ case ACA_SingleCharInput:
+ rACList.advance( aSingleCharInput );
+ break;
+
+ case ACA_SingleBackspace:
+ rACList.goBack();
+ break;
+
+ case ACA_Refresh:
+ rACList.gotoNode( sPrefix );
+ break;
}
}
+ if( bInsertBufferedChars && bNormalChar && bAutoCompleteEnabled && bGotWord )
+ {
+ ShowAutoTextCorrectQuickHelp( sPrefix, pACfg, pACorr );
+ }
+
// get the word count dialog to update itself
SwWordCountWrapper *pWrdCnt = (SwWordCountWrapper*)GetView().GetViewFrame()->GetChildWindow(SwWordCountWrapper::GetChildWindowId());
- if (pWrdCnt)
+ if( pWrdCnt )
pWrdCnt->UpdateCounts();
}
@@ -5059,10 +5140,13 @@ void SwEditWin::Command( const CommandEvent& rCEvt )
SvxAutoCorrCfg& rACfg = SvxAutoCorrCfg::Get();
SvxAutoCorrect* pACorr = rACfg.GetAutoCorrect();
if( pACorr &&
+ // If autocompletion required...
( rACfg.IsAutoTextTip() ||
pACorr->GetSwFlags().bAutoCompleteWords ) &&
+ // ... and extraction of last word from text input was successful...
rSh.GetPrevAutoCorrWord( *pACorr, sWord ) )
{
+ // ... request for auto completion help to be shown.
ShowAutoTextCorrectQuickHelp(sWord, &rACfg, pACorr, sal_True);
}
}
@@ -5584,7 +5668,7 @@ void QuickHelpData::Stop( SwWrtShell& rSh )
ClearCntnt();
}
-void QuickHelpData::FillStrArr( SwWrtShell& rSh, const String& rWord )
+void QuickHelpData::FillStrArr( SwWrtShell& rSh, const String& rWord, sal_Bool bIgnoreCurrentPos )
{
enum Capitalization { CASE_LOWER, CASE_UPPER, CASE_SENTENCE, CASE_OTHER };
@@ -5651,7 +5735,8 @@ void QuickHelpData::FillStrArr( SwWrtShell& rSh, const String& rWord )
// Add matching words from AutoCompleteWord list
const SwAutoCompleteWord& rACList = rSh.GetAutoCompleteWords();
std::vector<String> strings;
- if ( rACList.GetWordsMatching( rWord, strings ) )
+
+ if ( rACList.GetWordsMatching( rWord, strings, bIgnoreCurrentPos ) )
{
for (unsigned int i= 0; i<strings.size(); i++)
{
@@ -5728,7 +5813,8 @@ void SwEditWin::ShowAutoTextCorrectQuickHelp(
!pACorr ||
pACorr->GetSwFlags().bAutoCmpltShowAsTip;
- pQuickHlpData->FillStrArr( rSh, rWord );
+ // Get the neccessary data to show help text.
+ pQuickHlpData->FillStrArr( rSh, rWord, bFromIME );
}