// Scintilla source code edit control /** @file AutoComplete.cxx ** Defines the auto completion list box. **/ // Copyright 1998-2003 by Neil Hodgson // The License.txt file describes the conditions under which this software may be distributed. #include #include #include #include "Platform.h" #include "PropSet.h" #include "AutoComplete.h" AutoComplete::AutoComplete() : active(false), separator(' '), typesep('?'), ignoreCase(false), chooseSingle(false), lb(0), posStart(0), startLen(0), cancelAtStartPos(true), autoHide(true), dropRestOfWord(false) { lb = ListBox::Allocate(); stopChars[0] = '\0'; fillUpChars[0] = '\0'; } AutoComplete::~AutoComplete() { if (lb) { lb->Destroy(); delete lb; lb = 0; } } bool AutoComplete::Active() { return active; } void AutoComplete::Start(Window &parent, int ctrlID, int position, int startLen_, int lineHeight, bool unicodeMode) { if (active) { Cancel(); } lb->Create(parent, ctrlID, lineHeight, unicodeMode); lb->Clear(); active = true; startLen = startLen_; posStart = position; } void AutoComplete::SetStopChars(const char *stopChars_) { strncpy(stopChars, stopChars_, sizeof(stopChars)); stopChars[sizeof(stopChars) - 1] = '\0'; } bool AutoComplete::IsStopChar(char ch) { return ch && strchr(stopChars, ch); } void AutoComplete::SetFillUpChars(const char *fillUpChars_) { strncpy(fillUpChars, fillUpChars_, sizeof(fillUpChars)); fillUpChars[sizeof(fillUpChars) - 1] = '\0'; } bool AutoComplete::IsFillUpChar(char ch) { return ch && strchr(fillUpChars, ch); } void AutoComplete::SetSeparator(char separator_) { separator = separator_; } char AutoComplete::GetSeparator() { return separator; } void AutoComplete::SetTypesep(char separator_) { typesep = separator_; } char AutoComplete::GetTypesep() { return typesep; } void AutoComplete::SetList(const char *list) { lb->Clear(); char *words = new char[strlen(list) + 1]; if (words) { strcpy(words, list); char *startword = words; char *numword = NULL; int i = 0; for (; words && words[i]; i++) { if (words[i] == separator) { words[i] = '\0'; if (numword) *numword = '\0'; lb->Append(startword, numword?atoi(numword + 1):-1); startword = words + i + 1; numword = NULL; } else if (words[i] == typesep) { numword = words + i; } } if (startword) { if (numword) *numword = '\0'; lb->Append(startword, numword?atoi(numword + 1):-1); } delete []words; } } void AutoComplete::Show() { lb->Show(); lb->Select(0); } void AutoComplete::Cancel() { if (lb->Created()) { lb->Destroy(); active = false; } } void AutoComplete::Move(int delta) { int count = lb->Length(); int current = lb->GetSelection(); current += delta; if (current >= count) current = count - 1; if (current < 0) current = 0; lb->Select(current); } void AutoComplete::Select(const char *word) { size_t lenWord = strlen(word); int location = -1; const int maxItemLen=1000; char item[maxItemLen]; int start = 0; // lower bound of the api array block to search int end = lb->Length() - 1; // upper bound of the api array block to search while ((start <= end) && (location == -1)) { // Binary searching loop int pivot = (start + end) / 2; lb->GetValue(pivot, item, maxItemLen); int cond; if (ignoreCase) cond = CompareNCaseInsensitive(word, item, lenWord); else cond = strncmp(word, item, lenWord); if (!cond) { // Find first match while (pivot > start) { lb->GetValue(pivot-1, item, maxItemLen); if (ignoreCase) cond = CompareNCaseInsensitive(word, item, lenWord); else cond = strncmp(word, item, lenWord); if (0 != cond) break; --pivot; } location = pivot; } else if (cond < 0) { end = pivot - 1; } else if (cond > 0) { start = pivot + 1; } } if (location == -1 && autoHide) Cancel(); else lb->Select(location); }