Jump to content

Mahdi Safsafi

Members
  • Content Count

    383
  • Joined

  • Last visited

  • Days Won

    10

Posts posted by Mahdi Safsafi


  1. Quote

    if i type the string as example abcdefgÄ the result returned True  and i did not specfiy Ä in the regex pattern 

    You need to match EOS "$":

    if Regexs.IsMatch(astr, '^[ء-ي-A-Z-a-z-0-9 ]+$') then // match fro the begining to the end of astr 

     


  2. Quote

    Mahdi - again: calm down now. This is not the first time I have to tell you to calm down.

    And that's not your first time when you show un-professionalism behavior(remember last time) !

    Quote

    You must stop personal attacks against other members.

    I believe that I never showed disrespect for anyone here. All what I did is argumenting. So I really don't know why you think that disagree with someone is an attack !

    And telling someone that he is not a judge, I think that's not an attack ... is it ?

    Quote

    if you feel unable to have a focused discussion on a topic, just don’t do it.
    But there is a consensus that some(!) of your posts tend to be personal against other members.

    Go on all those posts, I challenge you to prove that its me who started a discussion !

    For this post, I gave an explanation to the bug, as well as an answer, I was argumenting with some people peacefully ... until some people started provocating me! 

    So please don't be driven by your subjectivity and try to view things neutrally.

    Peace.

    • Like 1

  3. Quote

    I think the point is that you are violating the API contract ... blablabla....

    Prove it ! FYI, the vcl core is calling CM_RECREATEWND directly.

    Quote

    it seems you are doing so just because you can, because you don't know better or because you are stubborn.

    You're not the judge here ! 

    Quote

    There are multiple definitions of perverse. In this case I think David meant obstinate in opposing what is right, reasonable, or accepted (from Merriam-Webster).

     

    Don't speak on his name. He is definitely able/free to explain what he means ! 

    David tell your friends there is no need to interfere ... I really started thinking you guys are making a kind of gang here. 


  4. Quote

    You said, "I'd understand if the logic was implemented in RecreateWnd but that's not the case here". You literally talk about making a choice based on the implementation details.

    Yes, I make a lot of choice based on implementation details ! don't you ? 

    Quote

    I still can't see why you are set against calling RecreateWnd.

     

    Simply you didn't convince me (it requires more than words to convince someone) !

    Quote

    That seems perverse to me. 

    Do you use "perverse" each time you disagree with someone ? 


  5. Quote

    As a broad principle, you should not be looking to work with Windows messages when consuming VCL controls.  Sometimes one is forced into it because the control provides no official mechanism.  But when we do that, it is brittle, and subject to future implementation detail changes.

    I wish if you were right ... but things are much much more complex than that. E.g : sometimes there is an official mechanism but you choose message instead because you don't want the official mechanism to perform a paint for example ... there is a lot of those examples.

    Quote

    And there it is.  There's the point where you take a dependency on on implementation details.

    I didn't take any dependency (please read my example again) !

    Quote

    RecreateWnd is useful when creating dynamic controls as you don't know when there would be the handle available.

    When you know that the handle is allocated, its just pointless to call RecreateWnd instead of CM_RECREATEWND. 

    procedure Main.StyleChanged;
    begin
    // I won't be here if handle is empty.
    // Perform(CM_RECREATEWND, ...);
    
    // VCL core is using the same Principle too ... take a look at Vcl.Forms,... (there are call to Perform(CM_RECREATEWND) instead of RecreateWnd). 
    end;

  6. 1 hour ago, David Heffernan said:

    This doesn't make sense to me. I don't see the argument for sending a private implementation specific message rather than calling the RecreateWnd method. 

    We have plenty of private implementation specific message (CM_XX) should we make XX() for each ?

    FYI, there is no concept of private/protected for messages. Messages are public !

    I'd understand if the logic was implemented in RecreateWnd but that's not the case here !


  7. 2 hours ago, Remy Lebeau said:

    Just FYI, you should call the form's RecreateWnd() method instead of issuing the CM_RECREATEWND message manually.

     

    For Main form that's not necessary. RecreateWnd is useful when creating dynamic controls as you don't know when there would be the handle available.

     

     


  8. Quote

    I am confused here. If I don't have to free TJSONValue why is there this line in the code you propose?

    Obviously its a typos (read again Remy explanation). I believe he means :

    LJSONValueObj := TJSONObject.ParseJSONValue(IdHTTP.Post(URL_LOGIN, sList));
    try
      if LJSONValueObj is TJSONObject then
      begin
        LJSONObject := TJSONObject(LJSONValueObj);
        {$IFDEF VER230}
        LJSONPair := LJSONObject.Get('token');
        if LJSONPair <> nil then
          LJSONValue := LJSONPair.JsonValue
        else
          LJSONValue := nil;
        {$ELSE}
        LJSONValue := LJSONObject.Values['token'];
        {$ENDIF}
        if LJSONValue <> nil then
          FToken := LJSONValue.Value;
      end;
    finally
      LJSONValueObj.Free;
    end;

     


  9. The problem is that TFormStyleHook uses a cached version of Icon(See TFormStyleHook .GetIconFast ). Once the StyleHook is attached to a form it makes a cached copy of its icon. However it does not update the cache when you change the icon.

     

    Quote

    Is this function disabled while custom styles is used?

    This is a bug !

    Until we have a fix, you may need to recreate the window handle in order to change the icon.

      main_form.Icon.LoadFromFile(ico_file);
      main_form.Perform(CM_RECREATEWND, 0, 0);

     


  10. I made a quick test that uses buttons with hints and empty hints ... and it worked just fine on Delphi 10.3. Perhaps the issue is on your Delphi (can you give more details about your version, are you using vcl-style ?,...).

    Quote

    What I'd like to know is - is there a quick and easy way to go through all the properties in an application and check if there is text in all the Hint property where the ShowHint is checked, or vice versa see if there is text whenever the ShowHint is not checked? Going through every form and every component would take forever...

     

    Something like this ?

    procedure CheckEmptyHint(AComponent: TComponent);
    var
      LComponent: TComponent;
      LControl: TControl;
    begin
      if (AComponent is TControl) then
      begin
        LControl := TControl(AComponent);
        if LControl.ShowHint and (LControl.Hint = EmptyStr) then
          Main.Memo1.Lines.Add(Format('%s has empty hint property.', [AComponent.Name]));
      end;
      for LComponent in AComponent do
        CheckEmptyHint(LComponent);
    end;
    // CheckEmptyHint(Application);

     

    • Like 1

  11. Quote

    Nice catch, I was comparing against the RTL code 😉 

     Seems to be even faster as the RTL #13#10 code.

    --  command line :classic_biggrin:

    Quote

    That did not work out well. I'll let the case out, less implementation detail on PChar.

    It should work after all its just a two-byte type.

     


  12. Quote

    Can you give me a test case for the incorrect handling of the trailing? This would be important to know.

    Your new version rocks ! it passed all the cases, except this:

    LineBreak = '--';
    Text      =   LineBreak;
    LIST.COUNT= EXPECT(0) GOT(1)
    Quote

     It's also faster than yours by the way, and your implementation fails on 7 test-cases of mine.

    Great job 🙂 

    Perhaps you can use xor operator to handle LinebreakLength when its in [1,2,3,4]:

     case length (linebreak) of
         1: b := (PWord(P + i)^ xor PWord(fc + i)^) = 0;
         2,3,4:...
         else for ...
    
                   

     


  13. 39 minutes ago, Stefan Glienke said:

    What you describe is exactly what traits are in Scala. Well minus the fact that traits can even declare fields but when they always implemented by objects that would work as well - hence I would not call them anything like "so and so interface" - because while they might be similar they would be a completely different beast and not to be mixed with them.

    

    I'm not aware about Scala but is this like what java does with default implementation for interface ?

    • Like 1

  14. Quote

    I would suggest try to remove one conditional jump more from your last version ... is cheaper that comparing and jumping

    @Kas Ob

    Performance is not always related to conditional jump. 

    I made a quick optimization on SetTextStr, bellow is my implementation and it uses jcc heavy but outperforms original/Attila algo.

    You can use jcc to make your own prediction (cheat and step):

    // this algo can be optimized further
    // requires length(LineBreak) > 1
    procedure TStringList2.SetTextStr(const Value: string);
    label Again;
    var
      P, PStart, PEnd: PChar;
      s: string;
      FirstLineBreakChar: Char;
      LastLineBreakChar: Char;
      LineBreakLength: integer;
      TextLength: integer;
      PMax: PChar;
      function IsBreak(PC: PChar): Boolean;
      var
        P: PChar;
      begin
        P := PChar(LineBreak);
        while (P^ <> #00) do
        begin
          if P^ <> PC^ then
            Exit(False);
          inc(P);
          inc(PC);
        end;
        Result := True;
      end;
    
    begin
      LineBreakLength := Length(LineBreak);
      if (LineBreakLength = 1) or (LineBreak = sLineBreak) then
      begin
        // this algo does not handle LineBreakLength = 1
        inherited
      end
      else
      begin
        BeginUpdate();
        try
          Clear();
          FirstLineBreakChar := LineBreak[1];
          LastLineBreakChar := LineBreak[LineBreakLength];
          TextLength := Length(Value);
          P := PChar(Value);
          PStart := P;
          PEnd := P + TextLength;
          if P^ <> #00 then
          begin
          Again:
            // skip all non important char:
            while (P^ <> FirstLineBreakChar) and (P^ <> #00) do
              inc(P);
    
            PMax := P + LineBreakLength;
            // either null or  FirstLineBreakChar.
            if (PMax < PEnd) then
            begin
              // current char = FirstLineBreakChar ... could be a line break !
    
              if (P[LineBreakLength - 1] = LastLineBreakChar) then
              begin
                // there is a hight chance that its a linebreak !
                if IsBreak(P) then
                begin
                  // this is a linebreak.
                  SetString(s, PStart, P - PStart);
                  Add(s);
                  PStart := P + LineBreakLength;
                end;
              end;
              inc(P, LineBreakLength); // eat all processed chars...
              goto Again;
            end
            else
            begin
              if (P > PStart) then
              begin
                SetString(s, PStart, P - PStart);
                Add(s);
              end
              else if (P = PStart) then
              begin
                // didn't move.
                if (PMax <> PEnd) then
                begin
                  SetString(s, PStart, PEnd - PStart);
                  Add(s);
                end;
              end;
            end;
          end;
        finally
          EndUpdate();
        end;
      end;
    end;

    @Attila Kovacs Note that the original implementation and yours do not handle correctly trailing. 


  15. @Attila Kovacs

    Quote

    I was struggling to write this down or not, poor dummzeuch's thread is hijacked as hell, but I can't stand, sorry.

    He is really a good guy ... I'd understand if he kicked us.

    Quote

    It's interesting, how tiny things can affect the speed. Originally I was starting from 320ms and it was a replacement for the RTL which was using 10's of seconds to do the same thing.

    Indeed ! 

    BTW, AChar is de-referenced twice ! try to declare a local CH that holds AChar^ "var Ch: Char := AChar^", this may improve a little bit your function.

    Quote

    But I barely think that anybody could/would get used to it to write "if then else begin <actual code> end;" just because the most likely branch would be to do nothing.

    You're right ! that's some how difficult to cover all your logic. 


  16. 9 minutes ago, Dave Novo said:

    I wanted to modify the top record of the stack, without removing the record from the stack. Seems like with the way records work (copies all the time) that may not be possible with the current TStack implementation, given the intermediate records that are along the way. With our own structures, in situations that require it, we do take the effort to ensure there are no intermediate records and we get direct access to the address of the record we want to modify. I had not considered that the result of Peek would actually be a copy of the record at the top of the stack.

    My bad, I didn't understood you correctly. 

    As I mentioned before, you can still use @stk.List[value] to get a pointer of your record without copying the data.


  17. 3 minutes ago, David Heffernan said:

    "may" is rather weak. A more detailed clarification may be useful to the asker, to make it clear that the code you offered does not prevent a copy, and in fact just adds obfuscation. 

     

    However, it's also possible that there is premature optimisation going on here. 

    He wrote "@stk.Peek" and I understood that he wanted the address of the peeked value. 

×