• Welcome to PlanetSquires Forums.
 

WinFBE using CWindow #8

Started by Paul Squires, June 20, 2016, 06:52:01 PM

Previous topic - Next topic

James Fuller

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];
}



James Fuller

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


José Roca

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.

Paul Squires

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.
Paul Squires
PlanetSquires Software
WinFBE Editor and Visual Designer

José Roca

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


José Roca

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
' ========================================================================================


José Roca

#21
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, "&Îòìåíà".

José Roca

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.

José Roca

#23
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.



José Roca

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.

Paul Squires

Quote from: Jose Roca on July 01, 2016, 12:50: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.
Paul Squires
PlanetSquires Software
WinFBE Editor and Visual Designer

José Roca

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.

Paul Squires

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.
Paul Squires
PlanetSquires Software
WinFBE Editor and Visual Designer