From f722542ceea557e906699c60b10b3ace1f41c238 Mon Sep 17 00:00:00 2001 From: D G Turner Date: Sat, 10 Dec 2011 20:12:35 +0000 Subject: AGI: Replace usage of 'goto'. --- engines/agi/predictive.cpp | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) (limited to 'engines/agi/predictive.cpp') diff --git a/engines/agi/predictive.cpp b/engines/agi/predictive.cpp index edfe83b1cb..3290068d5a 100644 --- a/engines/agi/predictive.cpp +++ b/engines/agi/predictive.cpp @@ -96,8 +96,6 @@ void bringWordtoTop(char *str, int wordnum) { } bool AgiEngine::predictiveDialog() { - int key = 0, active = -1, lastactive = 0; - bool rc = false; uint8 x; int y; int bx[17], by[17]; @@ -105,7 +103,6 @@ bool AgiEngine::predictiveDialog() { char temp[MAXWORDLEN + 1], repeatcount[MAXWORDLEN]; AgiBlock tmpwindow; bool navigationwithkeys = false; - bool processkey; const char *buttonStr[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9", "0" }; const char *buttons[] = { @@ -189,8 +186,11 @@ bool AgiEngine::predictiveDialog() { int mode = kModePre; bool needRefresh = true; - - while (!shouldQuit()) { + int active = -1, lastactive = 0; + bool rc = false; + bool closeDialog = false; + bool enterPredictiveResult = false; + while (!closeDialog && !shouldQuit()) { if (needRefresh) { for (int i = 0; buttons[i]; i++) { int color1 = colors[i * 2]; @@ -234,9 +234,10 @@ bool AgiEngine::predictiveDialog() { _gfx->doUpdate(); } + bool processkey = false; + pollTimer(); - key = doPollKeyboard(); - processkey = false; + int key = doPollKeyboard(); switch (key) { case KEY_ENTER: if (navigationwithkeys) { @@ -251,7 +252,8 @@ bool AgiEngine::predictiveDialog() { break; case KEY_ESCAPE: rc = false; - goto getout; + closeDialog = true; + break; case BUTTON_LEFT: navigationwithkeys = false; for (int i = 0; buttons[i]; i++) { @@ -361,7 +363,7 @@ bool AgiEngine::predictiveDialog() { break; } - if (processkey) { + if (processkey && !closeDialog) { if (active >= 0) { needRefresh = true; lastactive = active; @@ -442,7 +444,8 @@ bool AgiEngine::predictiveDialog() { if (mode == kModePre && _predictiveDictActLine && numMatchingWords > 1 && _wordNumber != 0) bringWordtoTop(_predictiveDictActLine, _wordNumber); rc = true; - goto press; + enterPredictiveResult = true; + closeDialog = true; } else if (active == 14) { // Mode mode++; if (mode > kModeAbc) @@ -456,17 +459,18 @@ bool AgiEngine::predictiveDialog() { _currentWord.clear(); memset(repeatcount, 0, sizeof(repeatcount)); } else { - goto press; + enterPredictiveResult = true; + closeDialog = true; } } } } - press: - Common::strlcpy(_predictiveResult, prefix.c_str(), sizeof(_predictiveResult)); - Common::strlcat(_predictiveResult, _currentWord.c_str(), sizeof(_predictiveResult)); + if (enterPredictiveResult) { + Common::strlcpy(_predictiveResult, prefix.c_str(), sizeof(_predictiveResult)); + Common::strlcat(_predictiveResult, _currentWord.c_str(), sizeof(_predictiveResult)); + } - getout: // if another window was shown, bring it up again if (!tmpwindow.active) closeWindow(); -- cgit v1.2.3 From 41ba2433f57f064f3119b5b5c1247eadb32d5977 Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Fri, 6 Jan 2012 09:38:41 +0100 Subject: AGI: Fix predictive input binary search Note that there are still issues with this input mode. If the binary search hits a prefix match before finding the full match, it won't recognize the full match. (Example: typing "buy" will show "buz" because it's aiming for "buzzard" without realizing "buy" exists.) --- engines/agi/predictive.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines/agi/predictive.cpp') diff --git a/engines/agi/predictive.cpp b/engines/agi/predictive.cpp index 3290068d5a..56d9190e7f 100644 --- a/engines/agi/predictive.cpp +++ b/engines/agi/predictive.cpp @@ -570,7 +570,7 @@ bool AgiEngine::matchWord() { int hi = _predictiveDictLineCount - 1; int lo = 0; int line = 0; - while (lo < hi) { + while (lo <= hi) { line = (lo + hi) / 2; int cmpVal = strncmp(_predictiveDictLine[line], _currentCode.c_str(), _currentCode.size()); if (cmpVal > 0) -- cgit v1.2.3 From 43e2fde7a951d362ab06f20bc043698f0e1e47c3 Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Fri, 6 Jan 2012 11:20:46 +0100 Subject: AGI: Fix ignoring some exact matches in predictive input The matcher now always tries an exact match before trying an inexact one. Together with 41ba2433f, this fixes bug #3470080. --- engines/agi/predictive.cpp | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) (limited to 'engines/agi/predictive.cpp') diff --git a/engines/agi/predictive.cpp b/engines/agi/predictive.cpp index 56d9190e7f..585a633bb0 100644 --- a/engines/agi/predictive.cpp +++ b/engines/agi/predictive.cpp @@ -556,7 +556,7 @@ void AgiEngine::loadDict() { debug("Time to parse pred.dic: %d, total: %d", time3-time2, time3-time1); } -bool AgiEngine::matchWord() { +bool AgiEngine::matchWord(bool onlyExact) { // If no text has been entered, then there is no match. if (_currentCode.empty()) return false; @@ -565,14 +565,29 @@ bool AgiEngine::matchWord() { if (_currentCode.size() > MAXWORDLEN) return false; - // Perform a binary search on the dictionary to find the first - // entry that has _currentCode as a prefix. + if (!onlyExact) { + // First always try an exact match. + bool ret = matchWord(true); + if (ret) + return true; + } + + // The entries in the dictionary consist of a code, a space, and then + // a space-separated list of words matching this code. + // To exactly match a code, we therefore match the code plus the trailing + // space in the dictionary. + Common::String code = _currentCode; + if (onlyExact) + code += " "; + + // Perform a binary search on the dictionary to find an entry that has + // _currentCode as a prefix. int hi = _predictiveDictLineCount - 1; int lo = 0; int line = 0; while (lo <= hi) { line = (lo + hi) / 2; - int cmpVal = strncmp(_predictiveDictLine[line], _currentCode.c_str(), _currentCode.size()); + int cmpVal = strncmp(_predictiveDictLine[line], code.c_str(), code.size()); if (cmpVal > 0) hi = line - 1; else if (cmpVal < 0) @@ -585,7 +600,7 @@ bool AgiEngine::matchWord() { _currentWord.clear(); _wordNumber = 0; - if (0 == strncmp(_predictiveDictLine[line], _currentCode.c_str(), _currentCode.size())) { + if (0 == strncmp(_predictiveDictLine[line], code.c_str(), code.size())) { _predictiveDictActLine = _predictiveDictLine[line]; char tmp[MAXLINELEN]; strncpy(tmp, _predictiveDictActLine, MAXLINELEN); -- cgit v1.2.3 From 8c7cd344c7560e655c0cee3136905f64a0e9ac47 Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Fri, 6 Jan 2012 23:26:08 +0100 Subject: AGI: Clean up predictive matching Specifically: * Don't enable the 'next' button in predictive mode when we don't have a full match. Doing this didn't make sense since you'd iterate over a seemingly arbitrary set of completions instead of all possible ones. * Do only a single binary search. * Fix the width of the mode button for mouse press detections. --- engines/agi/predictive.cpp | 36 +++++++++++++++++------------------- 1 file changed, 17 insertions(+), 19 deletions(-) (limited to 'engines/agi/predictive.cpp') diff --git a/engines/agi/predictive.cpp b/engines/agi/predictive.cpp index 585a633bb0..e27a2e81f8 100644 --- a/engines/agi/predictive.cpp +++ b/engines/agi/predictive.cpp @@ -112,7 +112,7 @@ bool AgiEngine::predictiveDialog() { "(#)next", "add", "<", "Cancel", "OK", - "Pre", "(0) ", NULL + "(*)Pre", "(0) ", NULL }; const int colors[] = { 15, 0, 15, 0, 15, 0, @@ -556,7 +556,7 @@ void AgiEngine::loadDict() { debug("Time to parse pred.dic: %d, total: %d", time3-time2, time3-time1); } -bool AgiEngine::matchWord(bool onlyExact) { +bool AgiEngine::matchWord() { // If no text has been entered, then there is no match. if (_currentCode.empty()) return false; @@ -565,23 +565,13 @@ bool AgiEngine::matchWord(bool onlyExact) { if (_currentCode.size() > MAXWORDLEN) return false; - if (!onlyExact) { - // First always try an exact match. - bool ret = matchWord(true); - if (ret) - return true; - } - // The entries in the dictionary consist of a code, a space, and then // a space-separated list of words matching this code. // To exactly match a code, we therefore match the code plus the trailing // space in the dictionary. - Common::String code = _currentCode; - if (onlyExact) - code += " "; + Common::String code = _currentCode + " "; - // Perform a binary search on the dictionary to find an entry that has - // _currentCode as a prefix. + // Perform a binary search on the dictionary. int hi = _predictiveDictLineCount - 1; int lo = 0; int line = 0; @@ -593,24 +583,32 @@ bool AgiEngine::matchWord(bool onlyExact) { else if (cmpVal < 0) lo = line + 1; else { - hi = line; break; } } + bool partial = hi < lo; + if (partial) { + // Didn't find an exact match, but 'lo' now points to the first entry + // lexicographically greater than the current code, so that will + // be the first entry with the current code as a prefix, if it exists. + line = lo; + _predictiveDictActLine = NULL; + } else { + _predictiveDictActLine = _predictiveDictLine[line]; + } + _currentWord.clear(); _wordNumber = 0; - if (0 == strncmp(_predictiveDictLine[line], code.c_str(), code.size())) { - _predictiveDictActLine = _predictiveDictLine[line]; + if (0 == strncmp(_predictiveDictLine[line], _currentCode.c_str(), _currentCode.size())) { char tmp[MAXLINELEN]; - strncpy(tmp, _predictiveDictActLine, MAXLINELEN); + strncpy(tmp, _predictiveDictLine[line], MAXLINELEN); tmp[MAXLINELEN - 1] = 0; char *tok = strtok(tmp, " "); tok = strtok(NULL, " "); _currentWord = Common::String(tok, _currentCode.size()); return true; } else { - _predictiveDictActLine = NULL; return false; } } -- cgit v1.2.3 From d4a81009e499c65da299262049acbaeeae313679 Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Fri, 6 Jan 2012 23:38:41 +0100 Subject: AGI: Fix stuck next button when switching back to predictive mode --- engines/agi/predictive.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'engines/agi/predictive.cpp') diff --git a/engines/agi/predictive.cpp b/engines/agi/predictive.cpp index e27a2e81f8..4bb378934d 100644 --- a/engines/agi/predictive.cpp +++ b/engines/agi/predictive.cpp @@ -458,6 +458,7 @@ bool AgiEngine::predictiveDialog() { _currentCode.clear(); _currentWord.clear(); memset(repeatcount, 0, sizeof(repeatcount)); + _predictiveDictActLine = NULL; } else { enterPredictiveResult = true; closeDialog = true; -- cgit v1.2.3