You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
174 lines
3.8 KiB
174 lines
3.8 KiB
// Scintilla source code edit control |
|
/** @file AutoComplete.cxx |
|
** Defines the auto completion list box. |
|
**/ |
|
// Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org> |
|
// The License.txt file describes the conditions under which this software may be distributed. |
|
|
|
#include <stdlib.h> |
|
#include <string.h> |
|
#include <stdio.h> |
|
|
|
#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, Point location, int startLen_, |
|
int lineHeight, bool unicodeMode) { |
|
if (active) { |
|
Cancel(); |
|
} |
|
lb->Create(parent, ctrlID, location, 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->SetList(list, separator, typesep); |
|
} |
|
|
|
void AutoComplete::Show(bool show) { |
|
lb->Show(show); |
|
if (show) |
|
lb->Select(0); |
|
} |
|
|
|
void AutoComplete::Cancel() { |
|
if (lb->Created()) { |
|
lb->Clear(); |
|
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; |
|
if (ignoreCase) { |
|
// Check for exact-case match |
|
for (; pivot <= end; pivot++) { |
|
lb->GetValue(pivot, item, maxItemLen); |
|
if (!strncmp(word, item, lenWord)) { |
|
location = pivot; |
|
break; |
|
} |
|
if (CompareNCaseInsensitive(word, item, lenWord)) |
|
break; |
|
} |
|
} |
|
} else if (cond < 0) { |
|
end = pivot - 1; |
|
} else if (cond > 0) { |
|
start = pivot + 1; |
|
} |
|
} |
|
if (location == -1 && autoHide) |
|
Cancel(); |
|
else |
|
lb->Select(location); |
|
} |
|
|
|
|