Jump to content

Jim McKeeth

Members
  • Content Count

    64
  • Joined

  • Last visited

  • Days Won

    9

Posts posted by Jim McKeeth


  1. On 5/22/2024 at 4:12 PM, Tom F said:

    I suppose it's likely I did something to cause this problem.  But, that it happened on a clean install of D12 surprised me.  It's hard to imagine how the problem came to be.

    But, I'm glad it's behind me. 🙂

    I would be concerned... This sounds like you have something else causing trouble. It could be an indication of some corruption in your installation, or some other software that is causing the trouble. 

     

    If things are working then no need to mess with it, but I would recommend using this as motivation to make sure you have a good backups of your data, so you will be ready if you need to create a fresh Windows install sometime soon.

    • Like 2

  2. It's been a long time since I've done much development with Windows services. I'm aware of the trick of creating a non-service version of the project, but sometimes that introduces subtle changes. I seem to remember a Host Application that would restart the service and then attach the debugger to the service. I know it is a little more complicated then that since you need to stop the service before compiling.

     

    I imagine it worked something like this:

    1. Run from IDE
    2. Compiles
    3. Automatically stops service
    4. Links to EXE (or maybe it deployed it....)
    5. Automatically restart service
    6. Attaches debugger
    7. Productivity

     

    image.thumb.png.3192810a9099d3c92e8a5387abbb65c6.png 

     

    Is there a tool like this already? It might have been an in-house tool, or a fever dream.... All options are equally likely. If it was the latter two then I might try building it again.

     

    Also, is there a list of macros like $(SanitizedProjectName) that are available in the IDE? I only found one mention of that one in the DocWiki, and that was only about a related bug fixes. There is the Transfer Macro list, but I believe some of those are specific to the Tool Properties, and it is still missing others like $(platform), $(target), etc. Completely unrelated, but there is a weird behavior I just noticed in the Tool Properties dialog. When you drop down the Macro's list, the edit boxes and labels all blank out. If you click the Insert button then it puts the dialog in a weird state too.

    image.thumb.png.22e1b413523dda24f449b00cff04cfbe.png 

     

    Thanks!

     

    -Jim


  3. 33 minutes ago, Remy Lebeau said:

    IDK what WriteTagString() is trying to accomplish. It is converting characters into bytes, completely ignoring the pointer that is inside the string.

     

    739930060_BadIdea.gif.3b23d5e08180c7f82c68117920830100.gif

     

    Convert the string into an array of AnsiChar, which is just an array of bytes, which is absolute to a NativeInt....

    type TBadIdea = array [0..7] of AnsiChar;

    So there is no pointer....

     

    image.png.1322a8a1c1ba60c49dbe6215856c16dc.png

     

    It is bytes all the way down....


  4. 17 hours ago, Uwe Raabe said:

    @PeterBelow It is even possible to inject new properties to the Object Inspector. In Cmon.DataSense.Design.pas I use this technique to add a DataSource and DataField property to supported controls. The additional data is stored in a special component (TDataSense) using a dictionary internally:

    This is the right answer. You can see an example of this when you put a component on a TRelativePanel. Notice how there are additional properties after Width in the Object Inspector...

     

    image.thumb.png.7b4958d0dd64bef014ca4b1f03498cea.png


  5. This might be an even worse idea.... 

    {$IFDEF Win64}
    type TBadIdea = array [0..7] of AnsiChar;
    {$ENDIF}
    {$IFDEF Win32}
    type TBadIdea = array [0..3] of AnsiChar;
    {$ENDIF}
    
    function ReadTagString(Tag: NativeInt): String;
    var 
      BadIdea: TBadIdea absolute Tag;
    begin
      Result := string(BadIdea);
    end;
    
    function WriteTagString(Tag: String): NativeInt;
    var 
      BadIdea: TBadIdea absolute Result;
    begin
      for var i := 1 to SizeOf(NativeInt) do
        if i <= Length(Tag) then
          BadIdea[i-1] := AnsiChar(Tag[i])
        else
          BadIdea[i-1] := #0;
    end;
    
    procedure TFormEvenWorse.btnSetClick(Sender: TObject);
    begin
      Tag := WriteTagString(edtValue.Text);
      edtValue.Text := '';
    end;
    
    procedure TFormEvenWorse.btnReadClick(Sender: TObject);
    begin
      edtValue.Text := string(ReadTagString(Tag));
    end;

    1540062048_Thinkiftheyshould.thumb.jpeg.9b7911d94da75798589a2633de4160d4.jpeg

     

    There should be better handling of Ansi vs Unicode strings. Technically if you are only going to store characters you could make more efficient use of the bytes. 


  6. I was talking to someone the other day about this too. I had thought about creating an IDE add-in to effectively "lock the form," where it ignores all those "accidental" changes. I think it would be really useful to also ignore things like active tab in the tab control, etc. Usually when I'm submitting changes in source control I only want to submit the minimum changes for the fix I made, but then I want to make sure that that subset works, so I have to revert unneeded changes, test that code state, and then submit it. So a filter or lock would be really helpful.

    • Like 3

  7. 9 hours ago, Tommi Prami said:

      GetIT Seems to be down... Are the GetIT based installer and ISO installer compatible with each other. At least they used not to be??

    Yes they are @Tommi Prami. I forget what version the incompatibility was fixed, but the installer still says they aren't compatible, but I've successfully switched during an update.

    • Like 1

  8. With 12.2 Patch 1 just dropping, we've all spent some time updating. I have a process for updating, but I'm always curious what everyone's process is. I'll share mine:

     

    1. Ideally I have a complete backup of my system
    2. Backup my activation/license files: "C:\ProgramData\Embarcadero" (I just zip files and folders including hidden)
      • Your activation should still work after a recovery if your computer name doesn't change
    3. Backup settings with MigrationTool  "C:\Program Files (x86)\Embarcadero\Studio\23.0\bin\migrationtool.exe"
         image.png
      • I used to always export the registry too, but haven't that in a while. Might still be useful.
      • Computer\HKEY_CURRENT_USER\Software\Embarcadero\BDS\23.0
    4. Manually backup GetIt Packages via GetItCmd (ran from the RAD Studio Command Prompt):
      getitcmd -l= -f=installed >getitpkgs.txt
    5. Uninstall all the GetIt packages (Parnassus seems to be the most likely to cause trouble, but FMXLinux has hit me too, so I just uninstall them all)
      • Get the packages names from the manual backup 
        getitcmd -u=FmxLinux-12-1.78;ParnassusCoreEditor-12-1.6.4.1;CodeSite-5.4.4;AWSSDKforDelphi-12

         

    6. Start the installation
      1. Let it automatically uninstall, keeping the settings (the default)
      2. Before it starts the install I manually delete the CatalogRepository folders
        • C:\Users\jim\Documents\Embarcadero\Studio\23.0\CatalogRepository
        • C:\Users\Public\Documents\Embarcadero\Studio\23.0\CatalogRepository
    7. Manually reinstall the GetIt packages
      getitcmd -i=FmxLinux-12-1.78;ParnassusCoreEditor-12-1.6.4.1;CodeSite-5.4.4;AWSSDKforDelphi-12

       

    8. The MigrationTool doesn't seem to like restoring to the same version it was backed up from, which is frustrating, but maybe I'm missing something. When I restore from a backup of 12.x then 12.x is missing from the dropdown list. I've never had to use it, but in theory I figure I could edit the backup file to make it work if worse comes to worse.   

     

    image.png

    • Like 5

  9. On 10/19/2024 at 3:27 AM, Rafal.B said:

    It works 👍

    It works for me too, but it isn't an official solution, so it may not work for everyone in all circumstances. Likewise, it is possible there are some incompatible use cases in 12.2. 

     

  10. I found myself down the rabbit hole of IEEE 754 standard on Floating-Point numbers (which Delphi follows), specifically the different values of NaN.... There are multiple potential internal values for NaN, all which evaluate as fsNaN. I found what I believe to be a bug, but I'm curious if anyone else has any thoughts on it. (As I was writing this up I discovered the behavior is only on Win32, so I've decided it must be a bug (RSS-1831), but sharing here anyway because I find the details interesting.)

     

    In short: IEEE 754 distinguishes between Signaling NaN and Quiet NaN. Delphi defaults to Quiet NaN, but you can make it signaling manually. Unfortunately, when a float is returned from a function in the Win32 compiler, the quiet flag is set. I was testing to see if Delphi converted it into an exception, which would be understandable, but instead it just silently sets the quiet flag, suppressing the signaling state.

     

    Testing in FPC, Delphi Win64, or Delphi Linux64, and the flag value doesn't change, which is what I would expect.

     

    Detailed explanation and background

     

    IEEE 754 divides a float into 3 parts

     

    1. Sign
    2. Exponent
    3. Fraction

     

    For a NaN the Exponent bits are all set ($FF in Single), any value for sign (Delphi's default NaN has it set, making it a negative NaN, which doesn't carry any specific significance), and the Fraction is anything but all 0. This allows for quiet a few different values that all are treated as NaN. What may distinguish the different values of NaN is signaling vs. quiet NaN. The Quiet flag is usually the first bit of the fraction. When the quiet flag isn't set, then it is considered a signaling NaN.

     

    The internal the internal representation of a NaN is typically displayed as follows (notice this is reversed from how Delphi stores the value in memory to put the most significant bit first.)

    S   Exponent   Fraction
    1 | 11111111 | 10000000000000000000000
                   ^ The quiet flag  

    So a signaling NaN is has an value for Faction without that first bit set.

     

     

    What I found in Delphi Win32 is it handles all these values correctly, except that if the quiet flag is missing (making it a signaling NaN), then when the value is returned from a function the quiet flag is set.

     

    Before returning from function: (Notice that the debugger recognizes it as negative NaN. Very nice!)

    before function return 

    This is 1 | 11111111 | 00000000000000000000001 in binary, which doesn't have the Quiet flag set

     

    image.thumb.png.4f223e0737eb6cb45188a2a084daa623.png

    1 | 11111111 | 10000000000000000000001
    After return it isn't the Default NaN, but it is the previous value with the Quiet flag set.

     

    Here is some sample code that demonstrates the behavior

    // The Delphi Win32 (tested in Delphi 12.1 and 12.2) sets NaN's quiet flag when are returning from a function
    // More information on IEEE 754 NaN https://en.wikipedia.org/wiki/NaN#Quiet_NaN
    // More information on this code: https://gist.github.com/jimmckeeth/2b4f017917afbae88ee7a3deb75b4ef7
    program NaNSignalBug;
    
    {$APPTYPE CONSOLE}
    
    uses
      System.SysUtils;//, SingleUtils in 'SingleUtils.pas';
    
    function is_Signaling(const NaN: Single): Boolean;
    begin
      Result := NaN.IsNan and (NaN.Frac and $400000 = 0);
    end;
    
    function NaNDetails(const Value: Single): string;
    begin
      if value.IsNan then
      begin
        if is_Signaling(value) then
          Result := 'NaN is Signaling'
        else
          Result := 'NaN is Quiet';
      end else
        Result := 'Not a NaN';
    end;
    
    procedure MakeSignaling(var NaN: Single);
    begin
      NaN.Exp := 255;
      NaN.Frac := NaN.Frac and not (1 shl 22);
      Assert(is_Signaling(NaN));
      Writeln('Manipulated: ',NaNDetails(NaN),#9, '// Line 33');
    end;
    
    // When a NaN is returned from a function the Signal bit is set
    function SignalingNaN: Single;
    begin
      Result := Single.NaN;
      Result.Frac := 1;
      MakeSignaling(Result);
      Assert(is_Signaling(Result));
      Writeln(#9,'SignalingNaN Returning',#9'// Line 43');
    end;
    
    function NestedNaN: Single;
    begin
      var NaN : Single := SignalingNaN;
      // The quiet bit was set
      Writeln('Returned:    ',NaNDetails(NaN),#9, '// Line 50');
      // without returning it from a function it works fine
      MakeSignaling(NaN);
      Writeln('Manipulated: ',NaNDetails(NaN),#9, '// Line 53');
      Assert(is_Signaling(NaN));
      Writeln(#9,'NestedNaN Returning ',#9,'// Line 55');
      Exit(NaN);
    end;
    
    
    begin
      try
        Writeln(TOSVersion.ToString);
        Writeln('Used: ',SizeOf(NativeInt)*8,'-bit compiler');
        var NaN : Single := NestedNaN;
        // The quiet bit was set
        Writeln('Returned:    ', NaNDetails(NaN),#9,'// Line 66');
        //Assert(is_Signaling(NaN)); // Fails on Win32
        // without returning it from a function it works fine
        MakeSignaling(NaN);
        Writeln('Manipulated: ', NaNDetails(NaN),#9,'// Line 70');
        Assert(is_Signaling(NaN));
      except
        on E: Exception do
          Writeln(E.ClassName, ': ', E.Message);
      end;
      readln;
    end.

    and here is the output

    Windows 11 (Version 23H2, OS Build 22631.4169, 64-bit Edition)
    Used: 32-bit compiler
    Manipulated: NaN is Signaling   // Line 33
            SignalingNaN Returning  // Line 43
    Returned:    NaN is Quiet       // Line 50
    Manipulated: NaN is Signaling   // Line 33
    Manipulated: NaN is Signaling   // Line 53
            NestedNaN Returning     // Line 55
    Returned:    NaN is Quiet       // Line 66
    Manipulated: NaN is Signaling   // Line 33
    Manipulated: NaN is Signaling   // Line 70

    and a more detailed look at the NaN values

    Default NaN
    Value of :                     Nan
    Special  : fsNaN
    Sign     : TRUE
    Exponent : 255
    Fraction : 4194304
    Size     : 4
    InvertHex: $FFC00000
    1 | 11111111 | 10000000000000000000000
    -----------------
    
    Singnaling NaN
    Value of :                     Nan
    Special  : fsNaN
    Sign     : TRUE
    Exponent : 255
    Fraction : 1
    Size     : 4
    InvertHex: $FF800001
    1 | 11111111 | 00000000000000000000001
    -----------------
    
    Returned from Function
    Value of :                     Nan
    Special  : fsNaN
    Sign     : TRUE
    Exponent : 255
    Fraction : 4194305
    Size     : 4
    InvertHex: $FFC00001
    1 | 11111111 | 10000000000000000000001

    @David Heffernan it was suggested I tag you on this...

    NaNSignalBug.dpr

    • Like 2

  11.  

    On 7/1/2024 at 11:00 AM, Rollo62 said:

    In case of someone is overwhelmed from reality, you could consider to introduce several "dummy-mode levels",

    I made the different color system boxes collapsible. When I add more I'll default to collapsing the less common ones, and make it based on preference. 

     

    On 7/1/2024 at 11:00 AM, Rollo62 said:

    Color theory is a science on its own.

    Yes it is. I'm working on named colors and more palette options now.

    • Like 2
×