Jump to content

dummzeuch

Members
  • Content Count

    3069
  • Joined

  • Last visited

  • Days Won

    112

Posts posted by dummzeuch


  1. 22 minutes ago, bravesofts said:

    Thanks, that worked correctly!

    However, I'm still not knowing the native way to distinguish between true menu bar items (top-level items in the TMainMenu) and internal submenu items !

    You apparently missed my answer:

    1 hour ago, dummzeuch said:

    TMenuItem has got a Parent property of type TMenuItem. I haven't checked but I would assume that it is NIL for main menu items.

     

    Edit: I was wrong. See online help here:

     

    https://docwiki.embarcadero.com/Libraries/en/Vcl.Menus.TMenuItem.Parent

     

    It's identical to the MainMenu's Items property. But that's just as good for detecting main menu items.

     


  2. You must set the height of the memo with alBottom. Everything else will adjust automatically (unless the splitter  acts up then it will be moved above the memo with alClient 😞 in that case you can hopefully set the splitter's top position to move it back between the memos where it belongs).

    • Like 2

  3. On 9/20/2024 at 11:10 AM, havrlisan said:

    I'll also mention GExperts throughout this post, as it includes some useful features that can speed up using the tools listed below.

    In addition to allowing to change keyboard shortcuts, GExperts has the Uses Clause Manager which on the Identifier tab offers similar functionality as the Delphi Uses Helper. The UI is very different though, but it also finds partial matches (but not typos).

    • Like 1
    • Thanks 1

  4. As @DelphiUdIT already said: The first thing you need is a compiler that creates binaries for Linux. And Delphi Professional - regardless which version - doesn't include that. According to Embarcadero's overview, you need at least the Enterprise SKU.

     

    On top of that, you might need GUI libraries, this is where FMXLinux comes into play. Of course the question is, whether you actually need a GUI. What kind of applications do you plan to develop?

    • Thanks 1

  5. Just to make one thing clear: GExperts does not support the 64 bit version of the IDE and the installer does not add it to that IDE.

     

    The error you get regarding the UsesClauseManager may well be caused by a problem of the IDE itself before that.

     

    I don't use the C++ personality of Rad Studio (I usually only install the Delphi personality), so I can't really say anything about the cause. And since nobody else working on GExperts (there currently is 3 of us off and on) uses C++, there is little chance of fixing any problems with it. Unless of course somebody else steps forward now.


  6. I am using GExperts with Delphi (RAD Studio) 12.3 and it works just fine. But admittedly I am using a DLL compiled from the current sources.

     

    What do you mean by "the IDE fails to start"? Is there any error message?


  7. On 4/11/2025 at 10:23 AM, dummzeuch said:

    Knowing my luck, it might be yet another effect of using two screens in a peculiar setup that's apparently unique on planet earth.

    It apparently is: It does not happen on my laptop with a single HD screen. Nor on my desktop when I turn off the 4K monitor or alternatively the HD monitor. And after starting Delphi once with only the HD monitor connected, it no longer happens with both monitors.

     

    Sounds like an easily reproducible problem, doesn't it?

    • Haha 2

  8. You probably copied source code that only contained line feeds (#10) or only carriage return (#13) rather than the Windows (DOS) convention with carriage return followed by line feed (#13#10).

    Notepad cannot handle this, other editors (e.g. Notepad++) can. The latter can also convert between the different styles too.

    The IDE in the latest versions can automatically correct that for you, if this option is enabled.


  9. 23 minutes ago, Uwe Raabe said:

    It doesn't happen here and at least I cannot remember having this seen anytime.

     

    As usual: Can you reproduce with a vanilla IDE installation?

    I am sure it has been like this from the first Delphi 12 installation which of course was "vanilla" back then. But since I just realized it might be a bug I have not yet tried to reproduce it.

     

    Knowing my luck, it might be yet another effect of using two screens in a peculiar setup that's apparently unique on planet earth.


  10. IDE toolbars get scrambled over time

     

    The toolbars of the IDE lose icons when starting, exiting and restarting the IDE multiple times (see screenshot). This bug had already been reported in the old quality portal for Delphi 11 and 12. It’s still there in Delphi 12.1. Resetting the toolbars to their default using the View → Toolbars → Customize dialog, helps for a while before the same happens again.

     

    https://embt.atlassian.net/servicedesk/customer/portal/1/RSS-515

     

    It seems to have been fixed in Delphi 12.3, at last I have not seen this problem after I updated my installations.

    Maybe it has been fixed? The bug report is still open though, so maybe that was a side effect of some other change?


  11. I just realized that this might be a bug: All my IDE windows look like this. The close button is not displayed, but it is there and works.

    Is that just another oddity of my particular installation(s) or does this happen everywhere?

    image.png.bab6d4d11c605782cf0b36fc2374a20f.png

     

    When the window is drawn I can for a short time see that there is actually a red button with a diagonal cross in it, like it should be, but it is overwritten with just the blue title bar. This is also the case for the main IDE window itself. Docked windows do have the close button, but as soon as I undock them it disappears too. It comes back when I dock them.


  12. Here you go:

    type
      TOnSshExecDataRecieve = procedure(const AData: TBytes; ADataLen: Int64) of object;
    
    // ...
    
      { Execute commands on the host and get Output/Errorcode back }
      ISshExec = interface
        ['{CA97A730-667A-4800-AF5D-77D5A4DDB192}']
        procedure SetBufferSize(Size: Int64);
        procedure Cancel;
        // ---- change 
        procedure SetOnStdErrReceive(ACallback: TOnSshExecDataRecieve);
        procedure SetOnStdOutReceive(ACallback: TOnSshExecDataRecieve);
        // ---- endchange 
        procedure Exec(const Command: string; var Output, ErrOutput: string; var ExitCode: Integer);
        property BufferSize: Int64 write SetBufferSize;
      end;
    
    // ...
    
    type
      TSshExec = class(TInterfacedObject, ISshExec)
      private
        FSession : ISshSession;
        FBufferSize: Int64;
        FCancelled: Boolean;
        // ---- change 
        FOnStdErrReceive: TOnSshExecDataRecieve;
        FOnStdOutReceive: TOnSshExecDataRecieve;
        procedure doOnStdErrReceive(const AData: TBytes; ADataLen: Int64);
        procedure doOnStdOutReceive(const AData: TBytes; ADataLen: Int64);
        // ---- end change 
        procedure SetBufferSize(Size: Int64);
        procedure Cancel;
        procedure Exec(const Command: string; var Output, ErrOutput: string; var ExitCode: Integer);
        // ---- change 
        procedure SetOnStdErrReceive(ACallback: TOnSshExecDataRecieve);
        procedure SetOnStdOutReceive(ACallback: TOnSshExecDataRecieve);
        // ---- end change 
      public
        constructor Create(Session: ISshSession);
      end;
    
    // ...
    
    // ---- change 
    procedure TSshExec.doOnStdErrReceive(const AData: TBytes; ADataLen: Int64);
    begin
      if Assigned(FOnStdErrReceive) then
        FOnStdErrReceive(AData, ADataLen);
    end;
    
    procedure TSshExec.doOnStdOutReceive(const AData: TBytes; ADataLen: Int64);
    begin
      if Assigned(FOnStdOutReceive) then
        FOnStdOutReceive(AData, ADataLen);
    end;
    // ---- end change 
    
    procedure TSshExec.Exec(const Command: string; var Output, ErrOutput: string;
      var ExitCode: Integer);
    var
      Channel: PLIBSSH2_CHANNEL;
      M: TMarshaller;
      ReadBuffer, OutBuffer, ErrBuffer: TBytes;
      StdStream, ErrStream: TBytesStream;
      TimeVal: TTimeVal;
      ReadFds: TFdSet;
      BytesRead: ssize_t;
      ReturnCode: integer;
      OldBlocking: Boolean;
    begin
      if FSession.SessionState <>  session_Authorized then
        raise ESshError.CreateRes(@Err_SessionAuth);
    
      FCancelled := False;
      Channel := libssh2_channel_open_session(FSession.Addr);
      if Channel = nil then
        CheckLibSsh2Result(libssh2_session_last_errno(FSession.Addr), FSession,
         'libssh2_channel_open_session');
    
      TimeVal.tv_sec := 1;  // check for cancel every one second
      TimeVal.tv_usec := 0;
    
      StdStream := TBytesStream.Create(OutBuffer);
      ErrStream := TBytesStream.Create(ErrBuffer);
      SetLength(ReadBuffer, FBufferSize);
      OldBlocking := FSession.Blocking;
      FSession.Blocking := False;
      try
        Repeat
          ReturnCode := libssh2_channel_exec(Channel,
            M.AsAnsi(Command, FSession.CodePage).ToPointer);
          CheckLibSsh2Result(ReturnCode, FSession, 'libssh2_channel_exec');
        Until ReturnCode <> LIBSSH2_ERROR_EAGAIN;
    
        // Stop waiting if cancelled of Channel is sent EOF
        while not FCancelled do
        begin
          // Wait until there is something to read on the Channel
          Repeat
            FD_ZERO(ReadFds);
            _FD_SET(FSession.Socket, ReadFds);
            ReturnCode := select(0, @ReadFds, nil, nil, @TimeVal);
            if ReturnCode < 0 then CheckSocketResult(WSAGetLastError, 'select');
            if libssh2_channel_eof(Channel) = 1 then Break;
          Until (ReturnCode > 0) or FCancelled;
    
          try
            // Standard output
            BytesRead :=  libssh2_channel_read(Channel, PAnsiChar(ReadBuffer),
              FBufferSize);
            CheckLibSsh2Result(BytesRead, FSession, 'libssh2_channel_read_ex');
            // ---- change 
            if BytesRead > 0 then begin
              StdStream.WriteBuffer(ReadBuffer, BytesRead);
              DoOnStdOutReceive(ReadBuffer, BytesRead);
            end;
            // ---- end change 
    
            // Error output
            BytesRead :=  libssh2_channel_read_stderr(Channel,
              PAnsiChar(ReadBuffer), FBufferSize);
            CheckLibSsh2Result(BytesRead, FSession, 'libssh2_channel_read_ex');
            // ---- change 
            if BytesRead > 0 then begin
              ErrStream.WriteBuffer(ReadBuffer, BytesRead);
              DoOnStdErrReceive(ReadBuffer, BytesRead);
            end;
            // ---- end change 
          except
            on E: Exception do
              begin
                OutputDebugString(PChar(E.Message));
                Break;
              end;
          end;
    
          // BytesRead will be either > 0 or LIBSSH2_ERROR_EAGAIN until
          // the command is processed
          if BytesRead = 0 then Break;
        end;
    
        Output := AnsiToUnicode(PAnsiChar(StdStream.Memory),
            StdStream.Size, FSession.CodePage);
        ErrOutput := AnsiToUnicode(PAnsiChar(ErrStream.Memory),
            ErrStream.Size, FSession.CodePage);
    
        // libssh2_channel_close sends SSH_MSG_CLOSE to the host
        libssh2_channel_close(Channel);
        if FCancelled then
          ExitCode := 130 // ^C on Linux
        else
          Exitcode := libssh2_channel_get_exit_status(Channel);
      finally
        StdStream.Free;
        ErrStream.Free;
        libssh2_channel_free(Channel);
        FSession.Blocking := OldBlocking;
      end;
    end;
    
    // ---- change 
    procedure TSshExec.SetOnStdErrReceive(ACallback: TOnSshExecDataRecieve);
    begin
      FOnStdErrReceive := ACallback
    end;
    
    procedure TSshExec.SetOnStdOutReceive(ACallback: TOnSshExecDataRecieve);
    begin
      FOnStdOutReceive := ACallback;
    end;
    // ---- end change 

    This passes the raw bytes received to the callback. Maybe it is possible to convert them to a string first? Or maybe call every time a line feed is received? Also, maybe the callbacks are enough so collecting the whole output is no longer necessary.

    I'll see how far I get with this.

    • Like 1

  13. My problem is not that the main thread is blocked by the call but that I get the output of the command only after it has finished (which can take 30 minutes). During that time the output is received and stored in a memory stream to be converted to a string. Access to this partial output not available.

    I know that I could adapt the source code to change that behavior. But I was asking whether I may just be missing something (maybe a different interface?) in the library that already exists.

     

    @pyscripter Yes, I am (now) using the latest sources. No I haven't updated the binaries, but the problem is in the Delphi code.

    (Just in case you missed my edits in the original question: The timeout no longer occurs.)


  14. I am using ISshExec.Exec from @pyscripter's ssh-pascal library for running a command that calculates checksums on all files in a directory tree. Since this is potentially a large tree and some of the files are huge, this takes quite a while.

    Unfortunately Exec is synchronously waiting for the output of the command which creates two issues:

     

    1. My program has to wait for the command to finish before it can get any output.
    2. For the huge files calculating the checksum takes longer than the standard timeout which raises an exception in the Exec method (actually in ReadStringFromChannel) and stops reading (the command continues running though)

     

    Is there any existing way to get the output asynchronously?

     

    EDIT: I just found that my ssh-pascal library was outdated, in particular the reading code has changed significantly. Maybe my second point has become moot. I'll check.

    EDIT2: No, the timeout still occurs.

    EDIT3: Hm, now I can't reproduce the timeout. Maybe I didn't rebuild the executable correctly before trying, so it was still using the old code.


  15. 2 hours ago, Joseph MItzen said:

    When 100% of Delphi developers were Windows users who just wanted a button they could push to cross-compile their code to Linux, they gave us a new framework and attempted to get the IDE itself to run on Linux. Linux desktop was barely even a thing then.

    I for one loved Kylix, I even bought it twice - once through my employer (I partly owned the company at the time) and another one for personal use. That was a brief period when I hoped that Linux would actually take off on the desktop. Unfortunately, that never happened. Even now, with the end of support for Windows 10 looming and millions of perfectly usable computers in danger of being turned into electronic waste, Linux on the desktop is not gaining any visible market share.

    • Sad 1

  16. 10 hours ago, Brandon Staggs said:

    On the flip side, however, since ARM-based Windows machines run x64 apps just fine, there is no real pressure on Embarcadero to rush offering a compiler. 

    Anybody remember OS/2? They had great support for running DOS and Windows 16 bit programs. So nobody bothered to write any native OS/2 programs. Guess what happened when Windows went 32 bits? (OK, that was not the only reason for OS/2's demise, but a big part of it.)

    • Like 2

  17. 17 hours ago, PeterPanettone said:

    By the way, where does the money from the license fees of millions of Delphi users go?

    As always: Into the pockets of the parent company Idera. It's called a "Gewinnabführungsvertrag" in Germany.

     

    On the other hand how do you know that there are millions of Delphi users? And more importantly: Do you know that they have paid for a license recently? Maybe 99% of these supposed millions are still using Delphi 5 or 7?

    • Like 2

  18. Hm, on the Delphi history page it says:

    "Highest Position (since 2001): #6 in Oct 2001"

     

    But in the chart the maximum seems to be August 2004 with 5.87%:

     

    image.thumb.png.e2509abdf875cac5ce6e7d010251f3f2.png

     

    OK, one is the rank (#6 at 2.77%) the other is the percentage (5.87%), but it still seems odd.

×