• Welcome to PlanetSquires Forums.
 

WinFBE on GitHub (November 12, 2016)

Started by Paul Squires, November 12, 2016, 04:00:41 PM

Previous topic - Next topic

Paul Squires

Ok.... I can reproduce the GPF with the Project Options OK button.
Paul Squires
PlanetSquires Software
WinFBE Editor and Visual Designer

José Roca

> I did make changes to the {CURDRIVE} replacement macro code that I use to substitute the drive letter for settings like the compiler, etc. Is your compiler setup on the same drive as your project, or different drive?

In the same drive.

Paul Squires

Looks like a GPF during config save during the call to ProcessToCurdrive(). I switched to your newest version of CWSTR and it could be that the passing of the fixed length WSTRING to the function designed now to accept CWSTR is failing. I need to test more to find the exact GPF location but that is my initial findings and it does appear that it is the ProcessToCurdrive where the GPF is happening.
Paul Squires
PlanetSquires Software
WinFBE Editor and Visual Designer

Paul Squires

I have stripped out code and created a test file to try to isolate the error:


#Define UNICODE
#Define _WIN32_WINNT &h0602 

#Include Once "windows.bi"
#Include Once "Afx\AfxStr.inc"
#Include Once "Afx\AfxCtl.inc"

Type clsConfig
   Private:
      _ConfigFilename As String
     
   Public:
      FBWINCompiler32      As WString * MAX_PATH = ""
      FBWINCompiler64      As WString * MAX_PATH = ""
      CompilerSwitches     As WString * MAX_PATH = ""
      CompilerHelpfile     As WString * MAX_PATH = ""
      Win32APIHelpfile     As WString * MAX_PATH = ""
End Type


Type clsApp
   Private:
   Public:
      ProjectFilename      As CWSTR     
End Type


'  Global classes
Dim Shared gApp As clsApp
Dim Shared gConfig As clsConfig


' ========================================================================================
' Process prefix {CURDRIVE} and convert to current drive letter.
' ========================================================================================
Function ProcessToCurdrive( ByRef wzFilename As CWSTR ) As CWSTR
   ' For each folder location determine if it resides on the same drive as
   ' the project file. If it does then substitute the replaceable parameter
   ' {CURDRIVE} for the drive letter. This allows you to easily run the editor
   ' on different media (eg. thumb drive) that may be assigned a different
   ' drive letter.
   dim zText as CWSTR
   if AfxFileExists(gApp.ProjectFilename) Then
      zText = gApp.ProjectFilename
   else
      zText = exepath
   end if     
   Dim wzCurDrive As CWSTR = LCase(Left(**zText, 3))  ' eg. D:\

   If LCase(Left(**wzFilename, 3)) = wzCurDrive Then
      wzFilename = "{CURDRIVE}" & Mid(**wzFilename, 2)
   End If

   Return wzFilename
End Function


''  START TEST CODE
gApp.ProjectFilename = "X:\FB\Projects\test.wfbe"
gConfig.FBWINCompiler32 = "X:\FB\FreeBASIC-1.05.0-win32\fbc.exe"


gConfig.FBWINCompiler32 = ProcessToCurdrive(gConfig.FBWINCompiler32)

print gConfig.FBWINCompiler32
sleep


Paul Squires
PlanetSquires Software
WinFBE Editor and Visual Designer

Paul Squires

.....hmmmm  Maybe the code above is not the point of failure after all because the test code seems to be working okay (at least in the few tests of the code I have run so far).  :(
Paul Squires
PlanetSquires Software
WinFBE Editor and Visual Designer

Paul Squires

Changing the internal code to use CWSTR instead of mixing WSTRING with CWSTR seems to have fixed the problem. Nevertheless, I will continue to change all code within WinFBE to use WSTR when at all possible. I will post an update to GitHub later tonight that should resolve this GPF issue.
Paul Squires
PlanetSquires Software
WinFBE Editor and Visual Designer

José Roca

#36
I also use WSTRING whenever possible, not because I have noticed any problem with CWSTR, but because it has less overhead. I mainly use CWSTR to return the result of a function or when I need a dynamic unicode variable. But the paths losing the drive letter, seems another kind of problem. Besides, I also had GPFs before you used the latest version of CWSTR, and the constructors haven't changed. The main change has been the removal of the @ operator and the addition of the wstr, vptr, sptr and utf8 methods/properties.


Paul Squires

Thanks Jose, no doubt that the CWSTR class was not the problem. That class works very well. I have made many code changes and my initial few tests have not resulted in GPF. I have uploaded the new code and exe's to GitGub. Please give it a quick try to see if it works okay for you. I plan to spend tomorrow working with the editor to specifically try to break it and find problems.
Paul Squires
PlanetSquires Software
WinFBE Editor and Visual Designer

José Roca

Not GPFs for now. Will do more tests.

It would be nice if you save the width of the explorer window if resized with the splitter. Now it starts always at the same width.

Marc Pons

Hi Paul

Still not able to test your new editor (xp only)

But, looked at your code, and here some minor remarks ' ========================================================================================
' Process prefix {CURDRIVE} and convert to current drive letter.
' ========================================================================================
Function ProcessToCurdrive( ByRef wzFilename As CWSTR ) As CWSTR
   ' For each folder location determine if it resides on the same drive as
   ' the project file. If it does then substitute the replaceable parameter
   ' {CURDRIVE} for the drive letter. This allows you to easily run the editor
   ' on different media (eg. thumb drive) that may be assigned a different
   ' drive letter.
   dim zText as CWSTR
   if AfxFileExists(gApp.ProjectFilename) Then
      zText = gApp.ProjectFilename
   else
      zText = exepath
   end if
   Dim wzCurDrive As CWSTR = LCase(Left(**zText, 3))  ' eg. D:\

   If LCase(Left(**wzFilename, 3)) = **wzCurDrive Then        ' better compare homogeneous types , here wstrings
      wzFilename = wstr("{CURDRIVE}") & Mid(**wzFilename, 2)  ' 2 wstrings, not an obligation but faster
   End If

   Return wzFilename
End Function


' ========================================================================================
' Process current drive to prefix {CURDRIVE}
' ========================================================================================
Function ProcessFromCurdrive( ByRef wzFilename As CWSTR ) As CWSTR
   ' For each folder location determine if it resides on the same drive as
   ' the project file. If it does then substitute the replaceable parameter
   ' {CURDRIVE} for the drive letter. This allows you to easily run the editor
   ' on different media (eg. thumb drive) that may be assigned a different
   ' drive letter.
   dim zText as CWSTR
   if AfxFileExists(gApp.ProjectFilename) Then
      zText = gApp.ProjectFilename
   else
      zText = exepath
   end if
   If Ucase(Left(**wzFilename, 10)) = wstr("{CURDRIVE}") Then    ' better compare homogeneous types , here wstrings
      wzFilename = Left(**zText, 1) & Mid(**wzFilename, 11) ' better dereferencing with mid
   End If

   Return wzFilename
End Function



Paul Squires

Thanks Jose and Marc, I appreciate both suggestions and I will implement them both for the next update.
:)
Paul Squires
PlanetSquires Software
WinFBE Editor and Visual Designer

Paul Squires

Jose, I don't remember seeing such a function in your Afx functions so maybe you can consider adding this one. It is obviously based heavily off of your AfxGetWindowText routine.


' ========================================================================================
' Return CWSTR text for item in ComboBox
' ========================================================================================
Private Function AfxGetComboBoxText( ByVal hWndControl As HWnd, ByVal nIndex As Long ) As CWSTR
   DIM nLen AS LONG = SendMessageW(hWndControl, CB_GETLBTEXTLEN, nIndex, 0)
   DIM wszText AS CWSTR = SPACE(nLen + 1)
   SendMessageW(hWndControl, CB_GETLBTEXT, nIndex, cast(LPARAM, *wszText))
   RETURN wszText
End Function           

Paul Squires
PlanetSquires Software
WinFBE Editor and Visual Designer

Marc Pons

#42
Paul,

As Jose said:
QuoteI also use WSTRING whenever possible, not because I have noticed any problem with CWSTR, but because it has less overhead.

if you use in a function intended to be generic, the CWSTR like that to create a buffer:
DIM wszText AS CWSTR = SPACE(nLen + 1)
you have to know , if you use that kind of function heavily on your code , you are drasticly slowing down the process

here different alternatives to create wstring buffer tested for speed

#include once "afx/cwstr.inc"
#Include Once "crt/time.bi"   

using afx

dim as long x
dim as string s1
dim as wstring ptr pw1

dim cw1 as cwstr
dim as double z1, z2


'if you need at least a wstring len of 65  ( so 66 wchar with the null ) = 132 bytes

z1 = clock()
dim as wstring ptr pw2 = allocate(2)  'to initialize with minimum
   for x = 1 to 100000
pw2 = reallocate(pw2,(65 + 1) * 2)  ' 132bytes
   NEXT
deallocate pw2   'no leak
z2 = clock()
pw2= NULL
   print : print "reallocate  time = " + str(z2 - z1) + " ms" : print


z1 = clock()
   for x = 1 to 1000000
      s1 = SPACE(66 * 2)     ' 133 bytes with the null
pw1 = cptr(wstring ptr,strptr(s1))
   NEXT
   z2 = clock()
   print : print "s1 space(cptr)  time = " + str(z2 - z1) + " ms" : print

z1 = clock()
   for x = 1 to 1000000
      s1 = SPACE(66 * 2) ' 133 bytes with the null
pw1 = cast(wstring ptr,strptr(s1))
   NEXT
   z2 = clock()
   print : print "s1 space(cptr)  time = " + str(z2 - z1) + " ms" : print

z1 = clock()
   for x = 1 to 1000000
      s1 = string(66 * 2, 32) ' 133 bytes with the null
pw1 = cptr(wstring ptr,strptr(s1))
   NEXT
   z2 = clock()
   print : print "s1 string(cptr) time = " + str(z2 - z1) + " ms" : print

z1 = clock()
   for x = 1 to 1000000
      s1 = string(66 * 2, 32) ' 133 bytes with the null
pw1 = cast(wstring ptr,strptr(s1))
   NEXT
   z2 = clock()
   print : print "s1 string(cast) time = " + str(z2 - z1) + " ms" : print

z1 = clock()
   for x = 1 to 1000000
      cw1 = SPACE(65) ' space gives you 66 bytes , converted to cwstr gives you 132 bytes, but with minimal buffer size gives you (260+1)* 2
pw1 = *cw1
   NEXT
   z2 = clock()
   print : print "cw1   time = " + str(z2 - z1) + " ms" : print


z1 = clock()
   for x = 1 to 1000000
      cw1.capacity = 132 ' gives you 132 bytes ,  but with minimal buffer size gives you (260 + 1)* 2
pw1 = *cw1
   NEXT
   z2 = clock()
   print : print "cw1 capacity  time = " + str(z2 - z1) + " ms" : print
sleep
print "press any key to finish"


I also like the dynamic wstring , but better not to use them just for buffer , if you don't want to play with alloc/realloc/dealloc,
capacity property is ok or string of spaces with the double of character is an acceptable alternative

José Roca

> Jose, I don't remember seeing such a function in your Afx functions so maybe you can consider adding this one. It is obviously based heavily off of your AfxGetWindowText routine.

I will add it, and another for list boxes.

BTW without a wrapper is not hard to get it, since I added a constructor to allocate room in characters to CWSTR.


DIM cwsText AS CWSTR = ListBox_GetTextLen(hListBox, curSel) + 1
ListBox_GetText(hListBox, curSel, *cwsText)


Paul Squires

Updated GitHub repository:

- Added: Editor now remembers the width of the Explorer pane between sessions.
- Added: WSTR as a FreeBasic keyword.
- Added: WSTR to better dereference the "{CURDRIVE}" string literal located in modRoutines.inc source code.
- Changed: The compiler results output listview is now positioned at the first entry in the list rather than at the first "Error" that is displayed in the list. The first entry could be a Warning or an Error.
- General code cleanup and removal of unused and unreferenced code.

Paul Squires
PlanetSquires Software
WinFBE Editor and Visual Designer