Jump to content


  • Content Count

  • Joined

  • Last visited

Everything posted by MarkShark

  1. The situation: I'm trying to emulate a combobox using a buttoned edit control and another parented control as the "box". This works fairly well, but I want to handle the standard Windows combobox hotkeys for toggling the box visibility which are F4 (easy) and Alt-Up/Alt-Down (much less easy as it turns out since I almost always use the up down arrows on the numberpad.) The problem: Using Alt-Up and Alt-Down from the numberpad (as opposed to the up/down dedicated keys) generates alt code characters. This happens even if the numlock is off (I was surprised by this.) The only solution I've found: I'm just filtering out the possible alt-code characters in OnKeyPress. This isn't ideal as if you hold down Alt and just hit up or down like crazy you can generate a large number of different characters, and I'd like to filter them all or come up with a much better way than an overly large case statement. Any thoughts or ideas?
  2. MarkShark

    Bug: Lock Controls is not restored at IDE start!

    As a possibly related note. I've created a bug report Lock Controls not visible initially regarding that menu item having some issues when placed on an IDE toolbar. I always do this when I customize the IDE after install. It's a very useful feature.
  3. Hi all! Is there a library routine or api function that will compare two utf8 strings or buffers without converting them to UTF16? I'm looking for something analogous to AnsiCompareStr. Thanks! -Mark
  4. MarkShark

    TScrollBar PageSize & Max

    I did a lot of trial and error while working on the scrollbars for SynEdit and setting min to 1 seemed necessary. The code I ended up with is in SynEditScrollBars. The official documentation did seem a bit off in some cases. -Mark
  5. MarkShark

    Bug in TButton with Multi-Line Caption?

    Is this with Delphi 12 - Athens? Could it be related to this issue mentioned on Stack Overflow? To test if that's the issue just try changing #13#10 to + #13 + #10 to see if it makes a difference. Stack Overflow: Issue related to character literals: https://stackoverflow.com/a/78186835/113128
  6. I currently have a background worker that I use to serialize a queue of workitems. The code to create the worker is: FWorker := Parallel.BackgroundWorker .NumTasks(1) .Execute(HandleWorkItem); In this case the HandleWorkItem method is just a dummy method as I actually pass in the workitem code when I schedule the workitem. E.g.: FWorker.Schedule( FWorker.CreateWorkItem(TOmniValue.FromRecord(MyWorkItemDataRec)), FWorker.Config.OnExecute( procedure(const workItem: IOmniWorkItem) var TaskResult: TTaskResult; begin // Do a bunch of work here in a background thread // Now set the Result TOmniValue from a record. workItem.Result := TOmniValue.FromRecord(TaskResult); end) .OnRequestDone(DoneMethod) ); end; This works extremely well, but I'd like to notify the calling thread of the progress. I thought maybe that IOmniWorkItemConfig would have an OnMessage(eventHandler: TOmniTaskMessageEvent) that I could set during the Schedule call (much like OnRequestDone) but I haven't figured out how to do that. Any help or suggestions appreciated.
  7. MarkShark

    Notification message from an OmniWorkItem

    Just wanted to mention that I realize I can add a notification handler to the entire FWorker with: FWorker := Parallel.BackgroundWorker .NumTasks(1) .TaskConfig(Parallel.TaskConfig.OnMessage(HandleTaskNotification)) .Execute(HandleQueryWorkItem); But I'm wondering if I can do a WorkItem specific handler with the Schedule() call.
  8. MarkShark

    How to create new FireDac components

    Blast from the past! I worked at the Lab of Computer Science at Mass General Hospital right out of College (a great place with wonderful people.) I worked on Mumps for a few years back then. The database for Mumps/M is a hieratical database and it's not easy to do a direct translation to a relational database (based on knowledge from 30 years ago so it might be completely out of date! lol) In any case, I might look at Zeoslib instead of Firedac since it's open source and might be easier to create a new driver with. Sorry to not be more helpful!
  9. As of Delphi 11.2 they fixed the wholeword option handing (https://quality.embarcadero.com/browse/RSP-20731) however they changed the way that SelStart works when searching backwards (its' now -1 based instead of zero based..) To fix it to match the earlier behavior you have to do something like: if soDown in StringOptions then Result := SearchBuf(Buf, BufLen, SelStart, SelLength, SearchString, StringOptions) else Result := SearchBuf(Buf, BufLen, SelStart - 1, SelLength, SearchString, StringOptions); Basically, when searching backwards a SelStart of zero means to start the search at char position 1. Maybe there's some reason to make it work that way, but it's a change from earlier versions where searching forwards and backwards used the easier to understand base of zero as the start of the search. I haven't created a bug report for this as I had some problems with attempting to do it recently. Also is there a way to do an ifdef specific to 11.2?
  10. Issue #78 and my pull request to start to fix it is #79. I have it fixed and tested, just needed that last bit of info about the 11.2 problem. Works great in my testing so far.
  11. Thanks! Is using Searchbuf (unfortunately with the $if to fix this issue) ok to use as a solution to the SynEdit search engine issue I've been working on? Otherwise, we'd need a reverse version of the current "Next" function which looks like it might be a Boyer-Moore implementation?
  12. I was writing a simple record helper for TBytes and realized that some of my routines call SetLength. I'm wondering if this is a problem since the array could/will be reallocated in memory. Simple example: TTestBytesHelper = record helper for TBytes private function GetLength: Integer; inline; public function ReadFromStream(AStream: TStream; ACount: Integer): Integer; property Length: Integer read GetLength; end; { TTestBytesHelper } function TTestBytesHelper.GetLength: Integer; begin Result := System.Length(Self); end; function TTestBytesHelper.ReadFromStream(AStream: TStream; ACount: Integer): Integer; begin // Wondering about this SetLength call! System.SetLength(Self, ACount); Result := AStream.Read(Self, ACount); end; In my testing the ReadFromStream function does seem to work fine. I'm just wondering if calling SetLength on Self while in a record helper is ok to do. Thanks for any insight!
  13. MarkShark

    Project Magician blues

    I use Project Magician, but I don't use custom manifests, so this may or may not be helpful! In the help file it mentions that the child configurations cleaning setting "Application Settings" affects Icons, Manifest File, Output Settings and Appearance, and so that setting is probably what's clearing the child settings in this case. You can clear that setting to see if it helps. What I'd love is for Uwe to open source the tool, but it's definitely been useful to me "as is". I use addition custom .optset files to set version info and such but doing so is undocumented at best.
  14. MarkShark

    SynEdit - Get current SQL command block

    Hey @aehimself SynEdit does have the SQLHighlighter which can give you some context information about the SQL, but it doesn't really have a full SQL script processor. Have you looked at the one in ZeosLib? I don't use it for my stuff as I had written one for Oracle's scripting language way back and then adopted it for the other databases with my newer products. Note that you will have to use some sort of statement terminator (which can be as simple as a semicolon or it can be super complex with Oracle's SQLPlus syntax or less complex with a standard "set terminator" type statement.) My tools are Golden (for Oracle) and GoldSqall (for Oracle, PostgresSQL, Firebird, MySQL, etc) and they all have to do exactly what you're doing. -Mark Ford Benthic Software
  15. MarkShark

    XML viewer component

    SynEdit (https://github.com/TurboPack/SynEdit) can handle huge files and has an XML highlighter (Note: I haven't used that highlighter myself.)
  16. MarkShark

    SynEdit with memory leak?

    My testing with MaxUndo = 1 (to most closely match a TMemo) doesn't show any leaks. I've also tested the other scenarios with no leak issues that I could detect. It's very true that the default settings can chew through a lot of memory for the undo stuff, so in the case of a log like this you must limit or manage the undo. On a related note: Am I correct that LockUndo/UnlockUndo must always be followed by a ClearUndo in order to keep everything in sync? I wasn't' sure if that happened automatically or perhaps is just not an issue. -Mark @pyscripter I'm very impressed by how few issues there have been for such a major rewrite! Well done!
  17. MarkShark


    I've used: SVGIconImageList also: Image32 Good stuff!
  18. MarkShark

    SynEdit preferred version?

    Hey all. I use SynEdit in a few projects and I was wondering if anyone has insight on which of the various version is the preferred one to use. I'm on 10.4 and don't need backwards compatibility btw. The one that is on "GetIt" appears to be an older version (1.5.) The one listed as SynEdit2 on github by pyscripter appears to be active, includes some nice changes (ole drag and drop for example) lots of fixes and cleanup (some related to removing support for older Delphi versions.) The one listed as SynEdit/SynEdit on github which seems to be more actively developed then the other two. I've worked with the second two and, as always, it seems when working with third party components I have to make a few changes to the source (adding some missing properties, fixing the extra space on word wrap lines (thanks to a stack overflow answer) and a few other minor issues) which have to be merged into each new update, so picking the "correct" one will obviously help. On a side note I have a feeling that the correct answer might be that there is no correct answer... Just looking for any feedback or thoughts. And this post wouldn't be complete without thanking and acknowledging all the great work people have done on these projects! -Mark
  19. This is going to sound like a homework assignment, but it's actually needed for some ZeosLib code to handle PostgreSQL client library digital array format. The array information is the following: NDims: The number of dimensions: Example: 3 DimArray: An array of dimension sizes. Example [1,2,2] ItemsArray: An array of data items (say Integer.) Example: [1,2,3,4] I'm trying to figure out an algorithm to turn the information above into a string that has a format like: {{{1,2},{3,4}}}. I've got it working for 1 and 2 dimensions, but it seems like I'm brute forcing it when it seems like a more clever approach should be possible. Any tips, hints, or psuedo-code (or actual code!) appreciated!
  20. @PeterBelow Thank you for that! It works perfectly.
  21. A good way to test or discover this kind of bug is to use FastMM's allocate TopDown feature.
  22. MarkShark

    SynEdit just got a major uplift

    It sounds like it's a component streaming property error. Make sure to open each form that has a SynEdit on it in the Delphi IDE and then save the form. That should fix any of those types of errors. Another thought is to make sure you have the latest version and to build and install the packages.
  23. Hi all! I often find myself needing to look up a string token in a dictionary. Usually, the token is part of a larger string being parsed. Currently I take a copy of that portion of the string using SetString or Copy and use that new string for the lookup. The code looks something like this: // Not shown: parse some source string and get a pointer to the first char of the token and the length of said token // Now get a copy of that token so we can look it up in the dictionary SetString(TempToken, FTokenStart, FTokenLength); if not FTokenDictionary.TryGetValue(TempToken, Result) then Result := UnknownToken; I'm wondering if there's any way to avoid the SetString part of this. Thanks for any ideas!
  24. I realized in my benchmarking above that I was comparing a case insensitive dictionary to a case sensitive one. After correcting that the performance improvement for using this technique is 30%, which is still significant, but not what I reported above for sure lol. I do notice something odd. I'm loading about 300 SQL keywords (select, from, etc.) into a dictionary<string, integer> and if I check FKeywords.Collisions I'm getting a result of 90. Looking at the code for TDictionary it looks like they take the results of the hash and convert it a positive integer for the array of buckets (I hope that's the correct terminology.) I *think* that's where the collisions come in. It looks like Spring4d doesn't have the collisions property, so I haven't been able to do a sanity check against it.
  25. @Stefan Glienke Thank you! My code is very close to yours, which is a nice validation for me lol. I also put the "stored" string in the record (@Frost I also tested keeping them in a separate list to remove the record being managed, but it didn't seem to make any difference when I benchmarked it.) I would be using Spring4D for this in my own code, however it may end up in SynEdit's highlighters and so I'm trying to keep dependencies down and to leverage the rtl as much as possible.