The start was taken from here
Download (AutoComplete.pb + keyword.txt + Snippet\For.pb)
Tried to use FindData.pbi, but in this case it is required to enter case-sensitive letters.
Code: Select all
EnableExplicit
InitScintilla()
Define hdr$, hdrLen
;- Global
Global *buffer
Global autocompTypeChar = ':'
Global typ$ = Chr(autocompTypeChar)
Global autocompSeparatorChar = #LF
Global sep$ = Chr(autocompSeparatorChar)
Global *autocompAutoCanceledByCharacters = UTF8(";,' .")
; Global *autocompAutoSelectedByCharacters = UTF8("|({")
Global autocompList.s = sep$ + "For" + typ$ + 0 + sep$ + ;type=0 (just for test)
"If" + typ$ + 1 + sep$ + ;type=1 (just for test)
"Next" + sep$ +
"Str" + sep$ +
"Ter" + #DQUOTE$ + sep$ +
"Web" + sep$
Global *autocompList
Global Format, length, bytes
CompilerIf #PB_Compiler_Debugger
Global SnippetPath$ = #PB_Compiler_FilePath + "Snippet\"
Global KeywordPath$ = #PB_Compiler_FilePath + "keyword.txt"
CompilerElse
Global SnippetPath$ = GetPathPart(ProgramFilename()) + "Snippet\"
Global KeywordPath$ = GetPathPart(ProgramFilename()) + "keyword.txt"
CompilerEndIf
Debug SnippetPath$
Debug KeywordPath$
#File = 0
If ReadFile(#File, KeywordPath$, #PB_UTF8)
; Format = ReadStringFormat(#File)
; If Format = #PB_UTF8
length = Lof(#File)
If length
*autocompList = AllocateMemory(length)
If *autocompList
bytes = ReadData(#File, *autocompList, length)
autocompList = PeekS(*autocompList, -1, #PB_UTF8)
; *autocompList = @autocompList
; FreeMemory(*autocompList)
EndIf
Else
*autocompList = UTF8(autocompList)
EndIf
; EndIf
CloseFile(#File)
Else
*autocompList = UTF8(autocompList)
EndIf
Procedure.s GetTextFile(Path$)
Protected Result$, *mem
#File = 0
If ReadFile(#File, Path$, #PB_UTF8)
; Format = ReadStringFormat(#File)
; If Format = #PB_UTF8
length = Lof(#File)
If length
*mem = AllocateMemory(length)
If *mem
bytes = ReadData(#File, *mem, length)
Result$ = PeekS(*mem, bytes, #PB_UTF8)
FreeMemory(*mem)
EndIf
EndIf
; EndIf
CloseFile(#File)
Else
Result$ = GetFilePart(Path$, #PB_FileSystem_NoExtension)
EndIf
ProcedureReturn Result$
EndProcedure
ProcedureDLL AutoCompletionScintillaCB(Gadget, *scinotify.SCNotification)
Protected Pos, WordStart, autocompSearchLength, *pos, PosFind, PosFind2, *DestinationMemoryID, tmp$;, range.TextRange
Protected tmp, word$, length
With *scinotify
If \nmhdr\code = #SCN_CHARADDED
Select \ch
Case 'a' To 'z', 'A' To 'Z';, '0' To '9'
Pos = ScintillaSendMessage(0, #SCI_GETCURRENTPOS) ; возвращает текущую позицию.
WordStart = ScintillaSendMessage(0, #SCI_WORDSTARTPOSITION, Pos, 1) ; сообщения возвращают начало слова
autocompSearchLength = Pos - WordStart
*pos = ScintillaSendMessage(0, #SCI_GETCHARACTERPOINTER) ; прямой доступ
word$ = PeekS(*pos + WordStart, autocompSearchLength, #PB_UTF8) ; #PB_ByteLength
word$ = sep$ + word$
PosFind = FindString(autocompList, word$, 1, #PB_String_NoCase)
If PosFind
Repeat
tmp = PosFind2
PosFind2 =FindString(autocompList, word$, PosFind2 + 1, #PB_String_NoCase)
Until PosFind2 = 0
If tmp
PosFind2 = FindString(autocompList, sep$, tmp + 1)
If PosFind2
; Debug word$
; Debug Str(PosFind) + " " + Str(PosFind2) + " " + Str(PosFind2 - PosFind)
; если позиции не изменяются надо не перерисовывать список
*DestinationMemoryID = AllocateMemory(PosFind2 - PosFind - 1)
CopyMemory(*autocompList + PosFind, *DestinationMemoryID , PosFind2 - PosFind - 1)
ScintillaSendMessage(0, #SCI_AUTOCSHOW, autocompSearchLength, *DestinationMemoryID)
FreeMemory(*DestinationMemoryID)
EndIf
EndIf
; Else
; ScintillaSendMessage(0, #SCI_AUTOCCANCEL)
EndIf
EndSelect
; EndIf
ElseIf \nmhdr\code = #SCN_AUTOCSELECTION ; удалите сообщение если нужно вставить ключевое слово без фрагмента
ScintillaSendMessage(0, #SCI_AUTOCCANCEL) ; омена вставки
; Debug PeekS(\text, -1, #PB_UTF8)
tmp$ = PeekS(\text, -1, #PB_UTF8)
tmp = Len(tmp$)
tmp$ = GetTextFile(SnippetPath$ + tmp$ + ".pb")
length = Len(tmp$)
*DestinationMemoryID = UTF8(tmp$)
Pos = ScintillaSendMessage(0, #SCI_GETCURRENTPOS) ; возвращает текущую позицию.
WordStart = ScintillaSendMessage(0, #SCI_WORDSTARTPOSITION, Pos, 1) ; сообщения возвращают начало слова
ScintillaSendMessage(0, #SCI_DELETERANGE, WordStart, Pos - WordStart) ; удалить введённое слово
; вставка фрагментов из одноимённого файла. Вместо вставки слова прочитать одноимённый файл и вставить его содержимое.
ScintillaSendMessage(0, #SCI_INSERTTEXT, -1, *DestinationMemoryID)
FreeMemory(*DestinationMemoryID)
If length = tmp
Pos + length - 1
Else
Pos + length
EndIf
ScintillaSendMessage(0, #SCI_GOTOPOS, Pos)
; ElseIf \nmhdr\code = #SCN_MODIFIED And \modificationType & #SC_MOD_DELETETEXT
ElseIf \nmhdr\code = #SCN_AUTOCCHARDELETED ; если удалить символ, то обновить список
Pos = ScintillaSendMessage(0, #SCI_GETCURRENTPOS) ; возвращает текущую позицию.
WordStart = ScintillaSendMessage(0, #SCI_WORDSTARTPOSITION, Pos, 1) ; сообщения возвращают начало слова
autocompSearchLength = Pos - WordStart
*pos = ScintillaSendMessage(0, #SCI_GETCHARACTERPOINTER) ; прямой доступ
word$ = PeekS(*pos + WordStart, autocompSearchLength, #PB_UTF8) ; #PB_ByteLength
word$ = sep$ + word$
PosFind = FindString(autocompList, word$, 1, #PB_String_NoCase)
If PosFind
Repeat
tmp = PosFind2
PosFind2 =FindString(autocompList, word$, PosFind2 + 1, #PB_String_NoCase)
Until PosFind2 = 0
If tmp
PosFind2 = FindString(autocompList, sep$, tmp + 1)
If PosFind2
; Debug word$
; Debug Str(PosFind) + " " + Str(PosFind2) + " " + Str(PosFind2 - PosFind)
; если позиции не изменяются надо не перерисовывать список
*DestinationMemoryID = AllocateMemory(PosFind2 - PosFind - 1)
CopyMemory(*autocompList + PosFind, *DestinationMemoryID , PosFind2 - PosFind - 1)
ScintillaSendMessage(0, #SCI_AUTOCSHOW, autocompSearchLength, *DestinationMemoryID)
FreeMemory(*DestinationMemoryID)
EndIf
EndIf
; Else
; ScintillaSendMessage(0, #SCI_AUTOCCANCEL)
EndIf
EndIf
EndWith
EndProcedure
; hdr$ = ""
; hdr$ + "----------------------------------------" + #CR$
; hdr$ + "Тестируйте автозавершение" + #CR$
; hdr$ + "----------------------------------------" + #CR$
; hdrLen = StringByteLength(hdr$, #PB_UTF8)
;- GUI
OpenWindow(0, 0, 0, 600, 700, "Тест автозавершение", #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_MinimizeGadget)
ScintillaGadget(0, 0, 0, WindowWidth(0), WindowHeight(0), @AutoCompletionScintillaCB())
*buffer=UTF8("Consolas")
ScintillaSendMessage(0, #SCI_STYLESETFONT, #STYLE_DEFAULT, *buffer)
FreeMemory(*buffer)
ScintillaSendMessage(0, #SCI_STYLESETSIZE, #STYLE_DEFAULT, 12) ; размер шрифта
ScintillaSendMessage(0, #SCI_SETWRAPMODE, #SC_WRAP_WHITESPACE)
ScintillaSendMessage(0, #SCI_SETCODEPAGE, #SC_CP_UTF8)
ScintillaSendMessage(0, #SCI_SETMARGINWIDTHN, 1, 0) ; Устанавливает ширину 0, поля 1 (номеров строк)
; установить настройки CHARACTER (автодополнение, выбор и другие функции используют эти настройки)
; Задать набор символов, которые являются элементами слов
*buffer=UTF8("abcdefghijklmnopqrstuvwxyz_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
ScintillaSendMessage(0, #SCI_SETWORDCHARS, 0, *buffer)
FreeMemory(*buffer)
;ScintillaSendMessage(0, #SCI_SETWHITESPACECHARS, 0, MakeUTF8Text(" " + #TAB$ + #CR$ + #LF$)) ;<= Uncomment this line if you want change default values
;ScintillaSendMessage(0, #SCI_SETPUNCTUATIONCHARS, 0, MakeUTF8Text("(){}[];:,'"+#DQUOTE$)) ;<= Uncomment this line if you want change default values
; *buffer=UTF8(hdr$)
; ScintillaSendMessage(0, #SCI_SETTEXT, 0, *buffer)
; FreeMemory(*buffer)
; ScintillaSendMessage(0, #SCI_GOTOPOS, hdrLen)
SetActiveGadget(0)
ScintillaSendMessage(0, #SCI_AUTOCSETMAXHEIGHT, 15) ; в символах
ScintillaSendMessage(0, #SCI_AUTOCSETMAXWIDTH, 50) ; в символах
ScintillaSendMessage(0, #SCI_AUTOCSETAUTOHIDE, #True) ;True => автоматически скрыть, если нет совпадения
ScintillaSendMessage(0, #SCI_AUTOCSETCHOOSESINGLE, #False) ;True => автоматический выбор, если только одно совпадение
ScintillaSendMessage(0, #SCI_AUTOCSETIGNORECASE, #True) ;True => выполнить безрегистровый поиск ('a' = 'A')
ScintillaSendMessage(0, #SCI_AUTOCSTOPS, 0, *autocompAutoCanceledByCharacters)
; ScintillaSendMessage(0, #SCI_AUTOCSETFILLUPS, 0, *autocompAutoSelectedByCharacters)
ScintillaSendMessage(0, #SCI_AUTOCSETSEPARATOR, autocompSeparatorChar)
ScintillaSendMessage(0, #SCI_AUTOCSETTYPESEPARATOR, autocompTypeChar)
; ScintillaSendMessage(0, #SCI_AUTOCSETORDER, #SC_ORDER_PERFORMSORT) ;<= потому что мой список автодополнения неупорядочен
ScintillaSendMessage(0, #SCI_AUTOCSETORDER, #SC_ORDER_PRESORTED) ;<= список отсортирован
; ScintillaSendMessage(0, #SCI_SETMODEVENTMASK, #SC_MOD_DELETETEXT) ; модификация реагирует только на удаление текста
Repeat:Until WaitWindowEvent() = #PB_Event_CloseWindow
FreeMemory(*autocompAutoCanceledByCharacters)
; FreeMemory(*autocompAutoSelectedByCharacters)
FreeMemory(*autocompList)