Date: 02-16-2022
Return to Index
created by gbSnippets
'Most programmers have come to expect an editor to provide capabilities
'like Intellisense, as Microsoft calls it. In Scintilla terminology
'the features that Intellisense offers are:
'1. AutoCompletion lists when a member of a keyword group is being
' typed, giving the user a selectable list of group members
'2. Call Tips to list the arguments of functions, with highlighting
' of which argument is currently being typed
'Primary Code:
'This displays a completion list.
txtOptions = "if ifone iffive iffour ifthree iftwo" + Chr$(0)
SendMessage hSci, %SCI_AutoCShow, 2, StrPTR(txtOptions)
'To cancel any displayed autopletion list, use this:
SendMessage hSci, %SCI_AutoCCancel, 0, 0
'Compilable Example: (Jose Includes)
#Compiler PBWin 9, PBWin 10
#Compile EXE
#Dim All
%Unicode=1
#Debug Error On 'catch array/pointer errors - OFF in production
#Debug Display On 'display untrapped errors - OFF in production
#Include "Win32API.inc"
#Include "scintilla_gb.inc"
%ID_Sci = 1000
Global hDlg, hSci, hLib As DWord
Global txtOptions As String
Global ListSeparator As Long
'Intellisense globals
Global Ref_MemTerm1() As String, Ref_MemMember1() As String
Global Ref_MemTerm2() As String, Ref_MemMember2() As String
Global Ref_Term1() As String, Ref_Desc1() As String, Ref_Syntax1() As String
Global Ref_Term2() As String, Ref_Desc2() As String, Ref_Syntax2() As String
Global Ref_Term3() As String, Ref_Desc3() As String, Ref_Syntax3() As String
Function PBMain() As Long
hLib = LoadLibrary("SCILEXER.DLL")
Dialog New Pixels, 0, "Scintilla Example",300,300,300,150, %WS_OverlappedWindow To hDlg
Control Add "Scintilla", hDlg, %ID_Sci, "", 10,10,180,130, %WS_Child Or %WS_Visible
Control Handle hDlg, %ID_Sci To hSci 'get handle to Scintilla window
Dialog Show Modal hDlg Call DlgProc
End Function
CallBack Function DlgProc() As Long
Local CharAtLeft As String
Local iPos as Long
Local pNSC As SCNotification Ptr ' // Scintilla notification messages
Select Case CB.Msg
Case %WM_InitDialog
InitializeScintilla
InitializeIntellisense
PostMessage hSci, %SCI_SetSel, 0,0 'unselect initially
Case %WM_NOTIFY
Select Case CB.NmID
Case %ID_Sci
pNSC = CB.lParam
CharAtLeft = Chr$(@pNSC.ch)
iPos = SendMessage( hSci, %SCI_GetCurrentPos, 0, 0) 'get current position
Select Case @pNSC.hdr.Code
Case %SCN_CHARADDED
If Instr("(. ", CharAtLeft) Then
Intellisense(iPos, CharAtLeft)
Else
Dialog Set Text hDlg, Str$(iPos) + " " + CharAtLeft
End If
Case %SCN_AutoCSelection
'if want to override selection, do something here
End Select
End Select
Case %WM_Size
Control Set Size hDlg, %ID_Sci, Lo(Word, CB.lParam)-20, Hi(Word, CB.lParam)-20
Case %WM_Destroy
If hLib Then FreeLibrary hLib 'free the Scintilla library
End Select
End Function
Sub InitializeScintilla
Local txt As String
txt = "If x = 2 Then" + $CrLf + " 'do nothing" + $Crlf
txt = txt + "Else" + $crlf + " x = 0" + $crlf + "End If" + Chr$(0)
SendMessage hSci, %SCI_SetText, 0, StrPTR(txt)
SendMessage hSci, %SCI_SetMarginWidthN, 0, 20
SendMessage hSci, %SCI_GoToPos, 2, 0 'no selection (set anchor=curpos=iPos)
Control Set Focus hDlg, %ID_Sci
End Sub
Sub InitializeIntellisense
Dim Ref_Term1(0), Ref_Desc1(0), Ref_Syntax1(0)
Dim Ref_Term2(0), Ref_Desc2(0), Ref_Syntax2(0)
Dim Ref_Term3(0), Ref_Desc3(0), Ref_Syntax3(0)
Dim Ref_MemTerm1(0), Ref_MemMember1(0)
Dim Ref_MemTerm2(0), Ref_MemMember2(0)
LoadRef "word1_short.txt", Ref_Term1(), Ref_Syntax1()
LoadRef "word2_short.txt", Ref_Term2(), Ref_Syntax2()
LoadRef "word3_short.txt", Ref_Term3(), Ref_Syntax3()
LoadRef "members1.txt", Ref_memTerm1(), Ref_memMember1()
LoadRef "members2.txt", Ref_memTerm2(), Ref_memMember2()
ListSeparator = Asc(".") 'not use space because PowerBASIC uses 3-word keyword groups
SendMessage hSci, %SCI_AutoCSetSeparator, ListSeparator, 0 'set separator
End Sub
Sub LoadRef (sFile$, ArrayTerm() As String, ArraySyntax() As String)
'load any of the 5 reference files - all use the same content format sWord:::::sSyntax
Local temp$, i As Long
Open sFile$ For Binary as #1 : Get$ #1, Lof(1), temp$ : Close
temp$ = RTrim$(temp$,$crlf)
ReDim ArrayTerm(ParseCount(temp$,$crlf)-1) As String, ArraySyntax(UBound(ArrayTerm)) As String
Parse temp$,ArrayTerm(),$crlf
For i = 0 to UBound(ArrayTerm)
ArraySyntax(i) = Parse$(ArrayTerm(i),":::::", 2)
ArrayTerm(i) = Parse$(ArrayTerm(i),":::::", 1)
Next i
End Sub
Function WordsToLeft(WA As String, WB As String, WC As String, iPos As Long) As Long
Local iCount, iLine, iStart As Long, LeftText As String, TR as Sci_TextRange
'get LeftText
iLine = SendMessage( hSci, %SCI_LineFromPosition, iPos, 0) 'line that contains iPos
iStart = SendMessage( hSci, %SCI_PositionFromLine, iLine, 0) 'position of 1st char in line
TR.chrg.cpmin = iStart 'first character to get
TR.chrg.cpmax = iPos-1 'last character to get
LeftText = String$(iPos-iStart, " ") + $Nul
TR.lpstrText = StrPTR(LeftText)
SendMessage hSci, %SCI_GetTextRange, 0, VarPTR(TR) 'get range of text
LeftText = Trim$(TR.@lpstrText)
LeftText = Retain$(LeftText, Any Chr$(65 To 90, 97 To 122, 48 To 57, $Spc, "$%?!")) 'remove all but word characters
'get right-most 3 words of text
iCount = ParseCount(LeftText, " ")
WC = Parse$(LeftText," ",iCount)
WB = Parse$(LeftText," ",iCount-1)
WA = Parse$(LeftText," ",iCount-2)
End Function
Function BSearch(ByVal sWord As String, iArrayPos&, ArrayTerm() As String, ArraySyntax() As String) As Long
Local Upper As Long, Lower As Long
Lower = LBound(ArrayTerm) : Upper = UBound(ArrayTerm) : sWord = LCase$(sWord)
'test boundary values
If sWord = ArrayTerm(Lower) Then iArrayPos& = Lower : Function = 1 : Exit Function
If sWord = ArrayTerm(Upper) Then iArrayPos& = Upper : Function = 1 : Exit Function
If sWord < ArrayTerm(Lower) Then iArrayPos& = Lower - 1 : Function = 0 : Exit Function
If sWord > ArrayTerm(Upper) Then iArrayPos& = Upper + 1 : Function = 0 : Exit Function
'loop through remaining entries until searchterm found, or it's determined that term is not in the array
Do Until (Upper <= (Lower+1))
iArrayPos& = (Lower + Upper) / 2
If sWord > ArrayTerm(iArrayPos&) Then
Lower = iArrayPos&
ElseIf sWord < ArrayTerm(iArrayPos&) Then
Upper = iArrayPos&
Else
Function = 1 : Exit Function
End If
Loop
End Function
Sub Intellisense(iPos As Long, CharAtLeft As String)
Local WA, WB, WC, sWord, sSyntax As String
Local LeftPos, iReturn As Long
'get prior 3 words
WordsToLeft(WA,WB,WC,iPos)
Dialog Set Text hDlg, "Pos: " + Str$(iPos) + " Char: " + CharAtLeft + " " _
+ " Words: " + "___" + WA + " " + WB + " " + WC + "___"
' If SearchWordABC(WordA,WordB,WordC,WordList,LeftPos) Then
If Len(WA) AND BSearch(Build$(WA,$spc,WB,$spc,WC), iReturn, Ref_Term3(), Ref_Syntax3()) Then
'3 word sequence was found - display arguments
sWord$ = Build$(WA,$spc,WB,$spc,WC)
sSyntax = Ref_Syntax3(iReturn)
SendMessage hSci, %SCI_CallTipShow, iPos, StrPTR(sSyntax)
' DisplaySyntaxLabel (sSyntax)
ElseIf Len(WB) AND BSearch(Build$(WB,$spc,WC), iReturn, Ref_memTerm2(), Ref_memMember2()) Then
'2 word sequence was found - display 3rd members
sWord$ = Build$(WB,$spc,WC)
sSyntax = Ref_memMember2(iReturn)
SendMessage hSci, %SCI_AutoCShow, LeftPos, StrPTR(sSyntax)
' DisplaySyntaxListbox (sSyntax)
ElseIf Len(WB) AND BSearch(Build$(WB,$spc,WC), iReturn, Ref_Term2(), Ref_Syntax2()) Then
'2 word sequence was found with syntax - display arguments
sWord$ = Build$(WB,$spc,WC)
sSyntax = Ref_Syntax2(iReturn)
SendMessage hSci, %SCI_CallTipShow, iPos, StrPTR(sSyntax)
' DisplaySyntaxLabel (sSyntax)
ElseIf Len(WC) AND BSearch(WC, iReturn, Ref_memTerm1(), Ref_memMember1()) Then
'1 word sequence was found - display 2nd member
sWord$ = WC
sSyntax = Ref_memMember1(iReturn)
SendMessage hSci, %SCI_AutoCShow, LeftPos, StrPTR(sSyntax)
' DisplaySyntaxListBox (sSyntax)
ElseIf Len(WC) AND BSearch(WC, iReturn, Ref_Term1(), Ref_Syntax1()) Then
'1 word sequence was found - display arguments
sWord$ = WC
sSyntax = ModifySyntax(CharAtLeft, Ref_Syntax1(iReturn))
SendMessage hSci, %SCI_CallTipShow, iPos, StrPTR(sSyntax)
' DisplaySyntaxLabel (sSyntax)
Else
'no matches were found close call tips and autocomplete
SendMessage hSci, %SCI_CallTipCancel, 0, 0
SendMessage hSci, %SCI_AutoCCancel, 0, 0
End If
End Sub
Function ModifySyntax (sChar$, ByVal sSyntax$) As String
' If sChar$ = " " AND Left$(sSyntax$,1) = "(" Then 'optional way to skip leading (
' sSyntax$ = Mid$(sSyntax$, 2, Len(sSyntax$)-2)
If sChar$ = "(" AND Left$(sSyntax$,1) = "(" Then
sSyntax$ = Mid$(sSyntax$, 2) 'do not allow ((
ElseIf sChar$ = "(" AND Left$(sSyntax$,1) <> "(" Then
sSyntax$ = "" 'if sChar is (, then sSyntax must also start with (, otherwise, don't show sSyntax
End If
Function = sSyntax$
End Function
'gbs_00660
'Date: 03-10-2012
http://www.garybeene.com/sw/gbsnippets.htm