Latest source and binaries attached.
Biggest change is the inclusion of Jose's source code template system.
We need to unscale the passed coordinates. Also some adjustments because of the change of window style. Looks fine at 192 DPI; check it in your system.
Function frmTemplates_Show (ByVal hParent As HWnd, ByVal x As Long, ByVal y As Long) As Long
Dim pWindow As CWindow Ptr = New CWindow
pWindow->DPI = AfxCWindowPtr(hParent)->DPI
pWindow->Create(hParent, "Templates", @frmTemplates_WndProc, pWindow->UnScaleX(x) + 5, pWindow->UnscaleY(y) + 5, 420, 405, _
WS_VISIBLE Or WS_CAPTION Or WS_POPUPWINDOW, WS_EX_WINDOWEDGE)
pWindow->SetClientSize(415, 380)
' Set the small and large icon for the main window (must be set after main window is created)
pWindow->BigIcon = LoadImage( pWindow->InstanceHandle, "IMAGE_MAINICON", IMAGE_ICON, 32, 32, LR_SHARED)
pWindow->SmallIcon = LoadImage( pWindow->InstanceHandle, "IMAGE_MAINICON", IMAGE_ICON, 16, 16, LR_SHARED)
' Add a listbox
Dim hListBox As HWnd = pWindow->AddControl("ListBox", , IDC_FRMTEMPLATES_LISTBOX, "", _
WS_CHILD Or WS_VISIBLE Or WS_HSCROLL Or WS_VSCROLL Or WS_BORDER Or WS_TABSTOP Or _
LBS_STANDARD Or LBS_HASSTRINGS Or LBS_SORT Or LBS_NOTIFY Or LBS_NOINTEGRALHEIGHT, WS_EX_CLIENTEDGE)
pWindow->SetWindowPos hListBox, Null, 8, 8, 399, 335, SWP_NOZORDER
SendMessageW hListBox, LB_SETHORIZONTALEXTENT, Cast(WPARAM, 600 * pWindow->rxRatio), 0
' Add the buttons
pWindow->AddControl("Button", , IDOK, "&OK", 245, 343, 74, 28, _
WS_CHILD Or WS_VISIBLE Or WS_TABSTOP Or BS_FLAT Or BS_DEFPUSHBUTTON, WS_EX_NOPARENTNOTIFY)
pWindow->AddControl("Button", , IDCANCEL, "&Cancel", 333, 343, 74, 28, _
WS_CHILD Or WS_VISIBLE Or WS_TABSTOP Or BS_FLAT, WS_EX_NOPARENTNOTIFY)
this.FindReplace( "|", "" ) fails because FB strings are asciiz strings and it passes a null pointer instead of a pointer to an empty string. We could ulse a BSTR, but as your workaround works, it isn't needed.
What I can't find is why the view is not scrolled to the position of the caret. We are using SciMsg( m_pSci, SCI_GOTOPOS, newPos, 0) and SCI_GOTOPOS sets the caret at pos and scrolls the view to make the caret visible, if necessary. The purpose of "|" is to set a position where the view will be scrolled; otherwise, does not make sense.
I believe the view is not scrolled into view because at the time that this.FindReplace is called, the Scintilla window is not display and the height and width of the Scintilla has not been set. So, I expect that Scintilla can't scroll because it has no window height to calculate whether to scroll or not. If you add the following at the end of clsDocument.DisplayStats then the window will scroll into view. That's because the window is sized and visible at that time.
curPos = SciMsg( m_pSci, SCI_GETCURRENTPOS, 0, 0)
SciMsg( m_pSci, SCI_GOTOPOS, curPos, 0)
I have attached a screenshot to show what the Templates window looks like on my screen with your measurement changes.
Looks fine.
There is still an small DPI problem:
In ApplyProperties, you have some fixed values, e.g.
SciMsg( m_pSci, SCI_SETMARGINWIDTHN, 2, Iif(gConfig.FoldMargin, 16, 0) )
when it should be
SciMsg( m_pSci, SCI_SETMARGINWIDTHN, 2, Iif(gConfig.FoldMargin, 16 * pWindow.rxRatio, 0) )
because of this, the folding symbols appear too small in my system (see capture).
We can't use fixed pixel values.
You need also to change
'' INDENTATION GUIDES
If gConfig.IndentGuides Then
SciMsg( m_pSci, SCI_SETINDENTATIONGUIDES, CTrue, 0)
Else
SciMsg( m_pSci, SCI_SETINDENTATIONGUIDES, False, 0)
End If
You're using True and the indentation guides aren't displayed.
You have to use CTrue.
Be careful with the boolean True because some third party controls such Scintilla, written in C, don't like -1 instead of 1.
We were getting the rect of the toolbar, when we should ask for the rect of the rebar.
' SendMessageW(ptbn->hdr.hwndFrom, TB_GETRECT, ptbn->iItem, Cast(LPARAM, @rc))
SendMessageW(GetDlgItem(HWnd, IDC_FRMMAIN_REBAR), RB_GETRECT, 0, cast(LPARAM, @rc))
and
Function frmTemplates_Show (ByVal hParent As HWnd, ByVal x As Long, ByVal y As Long) As Long
Dim pWindow As CWindow Ptr = New CWindow
pWindow->DPI = AfxCWindowPtr(hParent)->DPI
pWindow->Create(hParent, "Templates", @frmTemplates_WndProc, pWindow->UnScaleX(x), pWindow->UnscaleY(y), 420, 405, _
WS_VISIBLE Or WS_CAPTION Or WS_POPUPWINDOW, WS_EX_WINDOWEDGE)
pWindow->SetClientSize(415, 380)
Thanks! I have all of these changes made now. I am working on the compile process and resulting display of warnings and errors. Hope to have that finished tonight and be able to post the source and binaries before I go to bed.
Here is some code that I use in my PB editor to check if the the program that we are going to compile is already running.
' ========================================================================================
' // Get the full process image name
' ========================================================================================
FUNCTION FBSED_GetFullProcessImageName (BYREF pe32w AS PROCESSENTRY32W) AS WSTRING
LOCAL hProcess AS DWORD
LOCAL wszExeName AS WSTRINGZ * %MAX_PATH
LOCAL dwSize AS DWORD
hProcess = OpenProcess(%PROCESS_QUERY_INFORMATION OR %PROCESS_VM_READ, 1, pe32w.th32ProcessID)
IF hProcess THEN
dwSize = %MAX_PATH
IF ISTRUE QueryFullProcessImageNameW(hProcess, 0, wszExeName, dwSize) THEN
FUNCTION = wszExeName
END IF
CloseHandle hProcess
END IF
END FUNCTION
' ========================================================================================
' ========================================================================================
' // Checks if the program that we are going to compile is already running
' ========================================================================================
FUNCTION FBSED_IsProcessRunning(BYVAL bstrExeFileName AS WSTRING) AS LONG
LOCAL hSnapShot AS DWORD
LOCAL pe32w AS PROCESSENTRY32W
pe32w.dwSize = SIZEOF(pe32w)
bstrExeFileName = UCASE$(bstrExeFileName)
hSnapShot = CreateToolhelp32Snapshot(%TH32CS_SNAPPROCESS, 0)
IF hSnapShot <> %INVALID_HANDLE_VALUE THEN
IF ISTRUE Process32First(hSnapShot, pe32w) THEN
IF UCASE$(FBSED_GetFullProcessImageName(pe32w)) = bstrExeFileName THEN
FUNCTION = %TRUE
ELSE
WHILE Process32Next(hSnapShot, pe32w) > 0
IF UCASE$(FBSED_GetFullProcessImageName(pe32w)) = bstrExeFileName THEN
FUNCTION = %TRUE
EXIT DO
END IF
WEND
END IF
END IF
END IF
CloseHandle hSnapShot
END FUNCTION
' ========================================================================================
Quote from: Jose Roca on June 21, 2016, 06:18:35 PM
Here is some code that I use in my PB editor to check if the the program that we are going to compile is already running.
' ========================================================================================
' // Get the full process image name
' ========================================================================================
FUNCTION FBSED_GetFullProcessImageName (BYREF pe32w AS PROCESSENTRY32W) AS WSTRING
LOCAL hProcess AS DWORD
LOCAL wszExeName AS WSTRINGZ * %MAX_PATH
LOCAL dwSize AS DWORD
hProcess = OpenProcess(%PROCESS_QUERY_INFORMATION OR %PROCESS_VM_READ, 1, pe32w.th32ProcessID)
IF hProcess THEN
dwSize = %MAX_PATH
IF ISTRUE QueryFullProcessImageNameW(hProcess, 0, wszExeName, dwSize) THEN
FUNCTION = wszExeName
END IF
CloseHandle hProcess
END IF
END FUNCTION
' ========================================================================================
' ========================================================================================
' // Checks if the program that we are going to compile is already running
' ========================================================================================
FUNCTION FBSED_IsProcessRunning(BYVAL bstrExeFileName AS WSTRING) AS LONG
LOCAL hSnapShot AS DWORD
LOCAL pe32w AS PROCESSENTRY32W
pe32w.dwSize = SIZEOF(pe32w)
bstrExeFileName = UCASE$(bstrExeFileName)
hSnapShot = CreateToolhelp32Snapshot(%TH32CS_SNAPPROCESS, 0)
IF hSnapShot <> %INVALID_HANDLE_VALUE THEN
IF ISTRUE Process32First(hSnapShot, pe32w) THEN
IF UCASE$(FBSED_GetFullProcessImageName(pe32w)) = bstrExeFileName THEN
FUNCTION = %TRUE
ELSE
WHILE Process32Next(hSnapShot, pe32w) > 0
IF UCASE$(FBSED_GetFullProcessImageName(pe32w)) = bstrExeFileName THEN
FUNCTION = %TRUE
EXIT DO
END IF
WEND
END IF
END IF
END IF
CloseHandle hSnapShot
END FUNCTION
' ========================================================================================
Thanks Jose, I believe that you sent this to me a few months ago. I never ended up using it because I believe that it required Vista or higher and I still had a large number of FireFly customers using WinXP. I will add this code to WinFBE tomorrow.
I think that XP is too outdated to continue supporting it. Many things in the CWindow framework, beginning with High DPI, aren't supported by this OS (it supports large fonts, that isn't quite the same).
You're already using code that requires Vista or superior, like the IFileDialog interface.
People isn't going to use 96 DPI forever, and when they will have to use a higher DPI they will realize how awful their applications look and behave. We must no longer think in terms of pixels, but of DIPs (device independent units).
I agree 100%. I have no desire to support WinXP whatsoever especially for all my new projects and this WinFBE editor.
However, with Firefly I had many customers who continued to use WinXP and I didn't want to break the program for them.
Here is the FB translation of your IsProcessRunning code. Seems to work perfectly.
#Include Once "win\TlHelp32.bi"
' ========================================================================================
' Get the full process image name
' ========================================================================================
Function GetProcessImageName( ByVal pe32w As PROCESSENTRY32W Ptr ) As WString Ptr
Dim dwSize As Long
Dim hProcess As HANDLE
Dim wszExeName As WString * MAX_PATH
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION Or PROCESS_VM_READ, 1, pe32w->th32ProcessID)
If hProcess Then
dwSize = MAX_PATH
If QueryFullProcessImageNameW( hProcess, 0, @wszExeName, @dwSize ) Then
Function = @wszExeName
End If
CloseHandle hProcess
End If
End Function
' ========================================================================================
' Checks if the program that we are going to compile is already running
' ========================================================================================
Function IsProcessRunning( ByVal pwszExeFileName As WString Ptr ) As BOOLEAN
Dim hSnapShot As HANDLE
Dim pe32w As PROCESSENTRY32W
Dim wszExeFileName As WString * MAX_PATH = Ucase(*pwszExeFileName)
pe32w.dwSize = Sizeof(pe32w)
hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
If hSnapShot <> INVALID_HANDLE_VALUE Then
If Process32First(hSnapShot, @pe32w) Then
If Ucase(*GetProcessImageName(@pe32w)) = wszExeFileName Then
Function = True
Else
Do While Process32Next(hSnapShot, @pe32w) > 0
If Ucase(*GetProcessImageName(@pe32w)) = wszExeFileName Then
Function = True
Exit Do
End If
Loop
End If
End If
End If
CloseHandle hSnapShot
End Function
This part must be changed because it is returning a pointer to a local variable. We have to pass wszExeName as a byref parameter that will receive the path. In the PB version, I'm returning a BSTR because the PB compiler has support for them an will return a copy.
' ========================================================================================
' Get the full process image name
' ========================================================================================
Function GetProcessImageName( ByVal pe32w As PROCESSENTRY32W Ptr ) As WString Ptr
Dim dwSize As Long
Dim hProcess As HANDLE
Dim wszExeName As WString * MAX_PATH
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION Or PROCESS_VM_READ, 1, pe32w->th32ProcessID)
If hProcess Then
dwSize = MAX_PATH
If QueryFullProcessImageNameW( hProcess, 0, @wszExeName, @dwSize ) Then
Function = @wszExeName
End If
CloseHandle hProcess
End If
End Function
hmmmm.... yes, that sounds right. I wonder why it was working for me. The allocated memory for that local variable must still have been valid after the return from the function. Just lucky I guess. I will change the code to pass it by reference. I guess dim'ing wszExeName as static probably would work also.
Here is the corrected version:
#Include Once "win\TlHelp32.bi"
' ========================================================================================
' Get the full process image name
' ========================================================================================
Function GetProcessImageName( ByVal pe32w As PROCESSENTRY32W Ptr, _
ByVal pwszExeName As WString Ptr _
) As Long
Dim dwSize As Long
Dim hProcess As HANDLE
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION Or PROCESS_VM_READ, 1, pe32w->th32ProcessID)
If hProcess Then
dwSize = MAX_PATH
QueryFullProcessImageNameW( hProcess, 0, pwszExeName, @dwSize )
CloseHandle hProcess
End If
End Function
' ========================================================================================
' Checks if the program that we are going to compile is already running
' ========================================================================================
Function IsProcessRunning( ByVal pwszExeFileName As WString Ptr ) As BOOLEAN
Dim hSnapShot As HANDLE
Dim pe32w As PROCESSENTRY32W
Dim wszExeFileName As WString * MAX_PATH = Ucase(*pwszExeFileName)
Dim wszExeProcessName As WString * MAX_PATH
pe32w.dwSize = Sizeof(pe32w)
hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
If hSnapShot <> INVALID_HANDLE_VALUE Then
If Process32First(hSnapShot, @pe32w) Then
GetProcessImageName( @pe32w, @wszExeProcessName )
If Ucase(wszExeProcessName) = wszExeFileName Then
Function = True
Else
Do While Process32Next(hSnapShot, @pe32w) > 0
GetProcessImageName( @pe32w, @wszExeProcessName )
If Ucase(wszExeProcessName) = wszExeFileName Then
Function = True
Exit Do
End If
Loop
End If
End If
End If
CloseHandle hSnapShot
End Function
This sounds like a candidate for a static array of temps.
With BCX;bc9 many library routines return a bcx string -> a c char array.
This is how it is done. Shown is the mid$ function.
You could use a CBstr class or just a bstr??
James
char *mid (const char *S, int start, int length)
{
char *strtmp;
register int tmplen = strlen(S);
if(start > tmplen || start < 1) return BCX_TmpStr(1, 1, 1);
if (length < 0 || length > (tmplen - start) + 1)
length = (tmplen - start) + 1;
strtmp = BCX_TmpStr(length, 1, 1);
return (char*)memcpy(strtmp, &S[start - 1], length);
}
#ifndef BCXTmpStrSize
#define BCXTmpStrSize 2048
#endif
char *BCX_TmpStr (size_t Bites, size_t iPad, int iAlloc)
{
static int StrCnt;
static char *StrFunc[BCXTmpStrSize];
StrCnt = (StrCnt + 1) & (BCXTmpStrSize - 1);
if(StrFunc[StrCnt]) {
free (StrFunc[StrCnt]);
StrFunc[StrCnt] = NULL;
}
#if defined BCX_MAX_VAR_SIZE
if(Bites * sizeof(char) > BCX_MAX_VAR_SIZE)
{
printf("Buffer Overflow caught in BCX_TmpStr - requested space of %d EXCEEDS %d\n", (int)(Bites * sizeof(char)), BCX_MAX_VAR_SIZE);
abort();
}
#endif
if(iAlloc) StrFunc[StrCnt] = (char*)calloc(Bites + iPad + 1, sizeof(char));
return StrFunc[StrCnt];
}
On further investigation I see the variable in question was a WSTRING.
WSTRING is a native data type and I assumed the compiler was smart enough to do the copy.
Now with BSTR or CBStr that would be a different story.
James
The editor always displays the compiler results, which can be annoying.
In CSED I have the following options (checkboxes):
Compiler results:
- Display results
- Delete log file
- Beep on completion
- Display warnings
Errors are always displayed, of course.
Good idea. In the FireFly program I have the following option which I will also build into this editor:
[ ] Suppress results if no errors occur during the compile.
Some code to add autoindentation:
In Scintilla_OnNotify add
CASE SCN_CHARADDED
IF pNSC->ch = 13 THEN
IF gConfig.AutoIndentation THEN
DIM pDoc AS clsDocument PTR = gTTabCtl.GetActiveDocumentPtr()
IF pDoc THEN
hEdit = pDoc->hWindow
' // Current position
DIM curPos AS LONG = SendMessage(hEdit, SCI_GETCURRENTPOS, 0, 0)
' // Current line
nLine = SendMessage(hEdit, SCI_LINEFROMPOSITION, curPos, 0)
' // Line length of the previous line
DIM LineLen AS LONG = SendMessage(hEdit, SCI_LINELENGTH, nLine - 1, 0)
IF LineLen < 1 THEN EXIT FUNCTION
' // Get the text of the previous line
DIM buffer AS STRING = SPACE(LineLen)
SendMessage(hEdit, SCI_GETLINE, nLine - 1, cast(LPARAM, STRPTR(buffer)))
' // Get the tab width
DIM TabSize AS LONG = SendMessage(hEdit, SCI_GETTABWIDTH, 0, 0)
' // Calculate the number of spaces to fill on the left
DIM nSpaces AS LONG, i AS LONG
FOR i = 1 TO LEN(buffer)
IF MID(buffer, i, 1) <> " " THEN
IF MID(buffer, i, 1) = CHR(9) THEN
nSpaces = nSpaces + TabSize
ELSE
EXIT FOR
END IF
ELSE
nSpaces = nSpaces + 1
END IF
NEXT
DIM strFill AS STRING = ""
' // Remove $CRLF
buffer = FF_Remove(buffer, CHR(13))
buffer = FF_Remove(buffer, CHR(10))
' // Remove spaces and tabs and convert to uppercase
buffer = TRIM(UCASE(buffer), ANY CHR(32, 9))
IF (LEFT$(buffer, 3) = "IF " AND RIGHT$(buffer, 5) = " THEN") OR _
LEFT$(buffer, 4) = "ELSE" OR _
LEFT$(buffer, 7) = "SELECT " OR _
LEFT$(buffer, 5) = "CASE " OR _
LEFT$(buffer, 4) = "FOR " OR _
LEFT$(buffer, 3) = "DO " OR _
buffer = "DO" OR _
LEFT$(buffer, 6) = "WHILE " OR _
buffer = "WHILE" THEN
' // Indentation size
DIM IndentSize AS LONG = SendMessage(hEdit, SCI_GETINDENT, 0, 0)
' // Add spaces to indent the line
strFill = SPACE(nSpaces + IndentSize)
ELSE
' Add the same spaces on the left that the line above
strFill = SPACE(nSpaces)
END IF
' *** TODO: If using tabs, replace spaces with tabs
' // Indents the line
SendMessage(hEdit, SCI_ADDTEXT, LEN(strFill), cast(LPARAM, STRPTR(strFill)))
END IF
END IF
END IF
Some PB code to replace spaces with tabs:
' ========================================================================================
' Replaces spaces with tabs
' Based on code originally written by Steve Miltiadous
' ========================================================================================
FUNCTION SCIP_SpacesToTabs (BYVAL pSci AS DWORD, BYVAL strIn AS STRING) AS STRING
LOCAL i AS LONG ' // Loop counter
LOCAL TabSize AS LONG ' // Size of the tab
LOCAL strSpc AS STRING ' // Spaces
LOCAL strTab AS STRING ' // Tabs
LOCAL strOut AS STRING ' // Output string
IF ISNULL(strIn) THEN EXIT FUNCTION
' // Retrieve the tab size
TabSize = SCIP_GetTabWidth(pSci)
IF TabSize < 1 THEN
FUNCTION = strIn
EXIT FUNCTION
END IF
' // Calculate the number of spaces and tabs needed
FOR i = 1 TO LEN(strIn)
IF INSTR(MID$(strIn, i, 1), CHR$(32)) THEN
strSpc += MID$(strIn, i, 1)
ELSEIF INSTR(MID$(strIn, i, 1), CHR$(9) ) THEN
strTab += MID$(strIn, i, 1)
ELSE
EXIT FOR
END IF
NEXT
' // Replace spaces with tabs
IF LEN(strSpc) >= TabSize THEN
REPLACE SPACE$(TabSize) WITH $TAB IN strSpc
strOut = strTab & strSpc & MID$(strIn, i)
ELSE
strOut = strIn
END IF
' // Return the resulting string
FUNCTION = strOut
END FUNCTION
' ========================================================================================
If the user selects the Russian charset, he can use the following code to set the text in Russian:
' // Adds a button
DIM cb AS CBSTR = AfxUcode("&Отмена", 1251)
DIM hButton AS HWND = pWindow.AddControl("Button", , IDCANCEL, cb, 350, 250, 75, 23)
Same for the other charsets supported by Scintilla.
We have to use AfxUcode("&Отмена", 1251) because although we are seeing "&Отмена" in the editor, in reality it is an ansi string, "&ÎòìåÃà ".
If we declare the parameter as BYREF WSTRING, instead of BYVAL WSTRING PTR, we can pass the CBSTR variable directly, without having to deference it with *.
So if the parameter is BYREF WSTRING, we can pass cb, else *cb.
This can be used for functions in which we want to return an string. We will return a BSTR that will be assigned to a CBSTR. What we should not do is to pass the returned string directly to a function because it won't be freed.
It's not perfect, but that is what we have. Only the compiler can ascertain if a string is temporary and free it.
If WSTR had a an optional codepage parameter, we coud use:
DIM hButton AS HWND = pWindow.AddControl("Button", , IDCANCEL, WSTR("&Отмена", 1251), 350, 250, 75, 23)
We must request to the developers of the compiler to modify WSTR to allow this optional codepage parameter.
Or better yet, to request the addition to the language of UCODE and ACODE, with support for the optional CodePage parameter. The big advantage of implementing it in the language is that the compiler will take care of freeing the temporary WSTRINGs.
Quote from: Jose Roca on July 01, 2016, 01:20:10 AM
Some code to add autoindentation:
In Scintilla_OnNotify add
CASE SCN_CHARADDED
IF pNSC->ch = 13 THEN
IF gConfig.AutoIndentation THEN
DIM pDoc AS clsDocument PTR = gTTabCtl.GetActiveDocumentPtr()
IF pDoc THEN
hEdit = pDoc->hWindow
' // Current position
DIM curPos AS LONG = SendMessage(hEdit, SCI_GETCURRENTPOS, 0, 0)
' // Current line
nLine = SendMessage(hEdit, SCI_LINEFROMPOSITION, curPos, 0)
' // Line length of the previous line
DIM LineLen AS LONG = SendMessage(hEdit, SCI_LINELENGTH, nLine - 1, 0)
IF LineLen < 1 THEN EXIT FUNCTION
' // Get the text of the previous line
DIM buffer AS STRING = SPACE(LineLen)
SendMessage(hEdit, SCI_GETLINE, nLine - 1, cast(LPARAM, STRPTR(buffer)))
' // Get the tab width
DIM TabSize AS LONG = SendMessage(hEdit, SCI_GETTABWIDTH, 0, 0)
' // Calculate the number of spaces to fill on the left
DIM nSpaces AS LONG, i AS LONG
FOR i = 1 TO LEN(buffer)
IF MID(buffer, i, 1) <> " " THEN
IF MID(buffer, i, 1) = CHR(9) THEN
nSpaces = nSpaces + TabSize
ELSE
EXIT FOR
END IF
ELSE
nSpaces = nSpaces + 1
END IF
NEXT
DIM strFill AS STRING = ""
' // Remove $CRLF
buffer = FF_Remove(buffer, CHR(13))
buffer = FF_Remove(buffer, CHR(10))
' // Remove spaces and tabs and convert to uppercase
buffer = TRIM(UCASE(buffer), ANY CHR(32, 9))
IF (LEFT$(buffer, 3) = "IF " AND RIGHT$(buffer, 5) = " THEN") OR _
LEFT$(buffer, 4) = "ELSE" OR _
LEFT$(buffer, 7) = "SELECT " OR _
LEFT$(buffer, 5) = "CASE " OR _
LEFT$(buffer, 4) = "FOR " OR _
LEFT$(buffer, 3) = "DO " OR _
buffer = "DO" OR _
LEFT$(buffer, 6) = "WHILE " OR _
buffer = "WHILE" THEN
' // Indentation size
DIM IndentSize AS LONG = SendMessage(hEdit, SCI_GETINDENT, 0, 0)
' // Add spaces to indent the line
strFill = SPACE(nSpaces + IndentSize)
ELSE
' Add the same spaces on the left that the line above
strFill = SPACE(nSpaces)
END IF
' *** TODO: If using tabs, replace spaces with tabs
' // Indents the line
SendMessage(hEdit, SCI_ADDTEXT, LEN(strFill), cast(LPARAM, STRPTR(strFill)))
END IF
END IF
END IF
Thanks Jose! and you already converted it to FB, awesome! I have just implemented this into the editor. It makes code editing so much better.
I will upload new code later tonight. Just finishing some code in the project management sections.
That code has let me to know that something was wrong with the 64-bit DLL, because it does work if compiled with 32-bit but not with 64-bit. As the 64-bit DLL that I found is for a .NET project, maybe they have changed the way notifications work.
I have been able to get the notifications to work on 64 bit. I modified your Scintilla include file as follows:
Type Sci_NotifyHeader Field = 4
' /* Compatible with Windows NMHDR.
' // code should be DWORD, but it is defined as LONG in PBWin 9 built-in NMHDR structure.
' * hwndFrom is really an environment specific window handle or pointer
' * but most clients of Scintilla.h do not have this type visible. */
' hwndFrom As uLong ' void *hwndFrom
' idfrom As uLong ' uptr_t idFrom
' code As Long ' unsigned int code
hwndFrom as HWND
idFrom As UINT_PTR
code As UINT
End Type
Type SCNotification Field = 4
hdr As Sci_NotifyHeader
position As Integer
ch As Integer
modifiers As Integer
modificationType As Integer
lpText As ZString Ptr
length As Integer
linesAdded As Integer
message As uInteger ' must be DWORD, not LONG
wParam As uInteger
lParam As Integer
nLine As Integer
foldLevelNow As Integer
foldLevelPrev As Integer
margin As Integer
listType As Integer
x As Integer
y As Integer
token As Integer
annotationLinesAdded As Integer
updated As Integer
End Type
I expect that the other TYPE's may also need to be updated to change Long and ULong to the compiler dependent Integer and UInteger.