PlanetSquires Forums

Support Forums => WinFBE - Code Editor and Visual Designer => Topic started by: Paul Squires on June 20, 2016, 06:52:01 PM

Title: WinFBE using CWindow #8
Post by: Paul Squires on June 20, 2016, 06:52:01 PM
Latest source and binaries attached.
Biggest change is the inclusion of Jose's source code template system.
Title: Re: WinFBE using CWindow #8
Post by: JosÚ Roca on June 20, 2016, 10:13:47 PM
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.

Code: [Select]
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.

Title: Re: WinFBE using CWindow #8
Post by: Paul Squires on June 20, 2016, 10:48:41 PM
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.
Title: Re: WinFBE using CWindow #8
Post by: JosÚ Roca on June 20, 2016, 11:17:58 PM
Looks fine.

There is still an small DPI problem:

In ApplyProperties, you have some fixed values, e.g.

Code: [Select]
SciMsg( m_pSci, SCI_SETMARGINWIDTHN, 2, Iif(gConfig.FoldMargin, 16, 0) )

when  it should be

Code: [Select]
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.
Title: Re: WinFBE using CWindow #8
Post by: JosÚ Roca on June 20, 2016, 11:25:37 PM
You need also to change

Code: [Select]
   ''  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.
Title: Re: WinFBE using CWindow #8
Post by: JosÚ Roca on June 21, 2016, 12:21:18 AM
We were getting the rect of the toolbar, when we should ask for the rect of the rebar.

Code: [Select]
'                  SendMessageW(ptbn->hdr.hwndFrom, TB_GETRECT, ptbn->iItem, Cast(LPARAM, @rc))
                  SendMessageW(GetDlgItem(HWnd, IDC_FRMMAIN_REBAR), RB_GETRECT, 0, cast(LPARAM, @rc))

and

Code: [Select]
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)
Title: Re: WinFBE using CWindow #8
Post by: Paul Squires on June 21, 2016, 05:11:47 PM
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.
Title: Re: WinFBE using CWindow #8
Post by: JosÚ Roca on June 21, 2016, 05:48: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.

Code: [Select]
' ========================================================================================
' // 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
' ========================================================================================
Title: Re: WinFBE using CWindow #8
Post by: Paul Squires on June 29, 2016, 10:51:40 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.

Code: [Select]
' ========================================================================================
' // 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.
Title: Re: WinFBE using CWindow #8
Post by: JosÚ Roca on June 29, 2016, 11:30:29 PM
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).

Title: Re: WinFBE using CWindow #8
Post by: Paul Squires on June 30, 2016, 08:01:56 AM
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.
Title: Re: WinFBE using CWindow #8
Post by: Paul Squires on June 30, 2016, 08:47:27 AM
Here is the FB translation of your IsProcessRunning code. Seems to work perfectly.

Code: [Select]
#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
Title: Re: WinFBE using CWindow #8
Post by: JosÚ Roca on June 30, 2016, 10:57:45 AM
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.

Code: [Select]
' ========================================================================================
' 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
Title: Re: WinFBE using CWindow #8
Post by: Paul Squires on June 30, 2016, 04:27:40 PM
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.
Title: Re: WinFBE using CWindow #8
Post by: Paul Squires on June 30, 2016, 06:02:19 PM
Here is the corrected version:

Code: [Select]
#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

Title: Re: WinFBE using CWindow #8
Post by: James Fuller on June 30, 2016, 08:00:22 PM
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

Code: [Select]
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];
}

Title: Re: WinFBE using CWindow #8
Post by: James Fuller on June 30, 2016, 08:50:57 PM
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

Title: Re: WinFBE using CWindow #8
Post by: JosÚ Roca on June 30, 2016, 11:09:50 PM
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.
Title: Re: WinFBE using CWindow #8
Post by: Paul Squires on June 30, 2016, 11:22:00 PM
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.
Title: Re: WinFBE using CWindow #8
Post by: JosÚ Roca on July 01, 2016, 12:50:10 AM
Some code to add autoindentation:

In Scintilla_OnNotify add

Code: [Select]
      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
Title: Re: WinFBE using CWindow #8
Post by: JosÚ Roca on July 01, 2016, 01:15:24 AM
Some PB code to replace spaces with tabs:

Code: [Select]
' ========================================================================================
' 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
' ========================================================================================
Title: Re: WinFBE using CWindow #8
Post by: JosÚ Roca on July 01, 2016, 02:27:31 AM
If the user selects the Russian charset, he can use the following code to set the text in Russian:

Code: [Select]
   ' // 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, "&╬˛ýňÝÓ".
Title: Re: WinFBE using CWindow #8
Post by: JosÚ Roca on July 01, 2016, 02:40:04 AM
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.
Title: Re: WinFBE using CWindow #8
Post by: JosÚ Roca on July 01, 2016, 02:48:31 AM
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:

Code: [Select]
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.


Title: Re: WinFBE using CWindow #8
Post by: JosÚ Roca on July 01, 2016, 01:00:17 PM
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.
Title: Re: WinFBE using CWindow #8
Post by: Paul Squires on July 02, 2016, 08:20:04 PM
Some code to add autoindentation:

In Scintilla_OnNotify add

Code: [Select]
      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.
Title: Re: WinFBE using CWindow #8
Post by: JosÚ Roca on July 02, 2016, 08:43:43 PM
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.
Title: Re: WinFBE using CWindow #8
Post by: Paul Squires on July 02, 2016, 10:08:05 PM
I have been able to get the notifications to work on 64 bit. I modified your Scintilla include file as follows:

Code: [Select]
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.