Jump to content

Joseph MItzen

Members
  • Content Count

    270
  • Joined

  • Last visited

  • Days Won

    7

Posts posted by Joseph MItzen


  1. Why does this seem to just be a Delphi thing, insisting we still use 32bit even though it's been about 19 years since the first 64bit x86 chip was announced? Why is embracing modernity a bad idea to you? You can't buy 32bit CPUs anymore, 32bit OSes are disappearing - even with Linux, etc. Just recompile your code and move on I say.


  2. Delphi has always been inexplicably poor for calling external command line programs; FreePascal is actually much better at it (as is most everything else).

     

    This is the standard code every Delphi user seems to use to do what you want (because only @Remy Lebeau and @David Heffernan understand it):

     

    https://stackoverflow.com/questions/9119999/getting-output-from-a-shell-dos-app-into-a-delphi-app

     

     

     

    • Haha 1

  3. Wow, 3.31.1 was released in January of 2020. There's no reason that the SQLite version shouldn't be replaced with the current one for each Delphi update. It's not like the IDE is a single file where static linking might make sense either.

     

    The good news is that if I'm reading this correctly if you change your TFDPhysSQLiteDriverLink.EngineLinkage property you can use dynamic linking and then use a more recent SQLite DLL....

     

    https://docwiki.embarcadero.com/RADStudio/Sydney/en/Connect_to_SQLite_database_(FireDAC)

     

    Lots of awesome changes since 3.31.1, such as DROP COLUMN, RIGHT and FULL JOIN, UPSERT, a STRICT option that finally makes static typing an option, the JSON support is now built in, etc. SQLite now has a lot of features missing from Interbase. 🙂


  4. On 5/13/2022 at 10:47 AM, Darian Miller said:

    Now includes Delphi / RAD Studio options.

    This isn't the first time it included Delphi. After a lot of pressure one year they opened a lot of questions up with write-in options and in spite of a promotional campaign from Marco, David I., etc., Delphi only scored 0.78% so it was omitted from future surveys. The most frustrating thing is that they've decided the simplest way to anonymize the raw survey data they distribute is to omit any write-in answers. 😞 That made it impossible for me to do data analysis regarding Delphi from that point forward. Being a formal choice again will be great because I know myself and a few others in the community loved to slice and dice the Delphi data.

    • Like 1

  5. On 4/8/2022 at 3:56 AM, Fr0sT.Brutal said:

    only in the form "(import some-library-that-will-do-all-the-work).run()"

    You left out a step... now if Embarcadero has its way it's going to be... run Delphi to call Python to call some library that will do all the work! Ironically by the way  this Delphi program CoCa is simply a GUI that builds a command line to use to call a C++ program, Argyll, that indeed does all the work. 

     

    1276464099_DelphiPythonScreenshot_20220415_023742.thumb.png.696beda48af0cc8394b165811a320efa.png2122126657_DelphiPythonScreenshot_20220415_023804.thumb.png.250cca6a3fba77c265ee7fbc57aeea71.png


  6. On 4/9/2022 at 3:56 AM, Vincent Gsell said:

    Very sorry for the delphi world, but as I see it, if "multilingual" stuff and "UI" stuff is not important for you, yes, it can be rewrite in python :)))) 

    The Qt Company produces their own LGPL bindings for the Qt cross-platform GUI framework. Python also has bindings for the other major open source cross-platform frameworks, Gtk and WxWidgets, as well as bindings to native Windows and Coco libraries. Notable open source programs that use Python and Qt are the ebook management program Calibre, the Dropbox client, the OpenShot video editor, the Orange data mining suite, the Puddletag audio metadata editor, the QGIS Geographical Information System, the TortoiseHg front-end for the distributed version control system Mercurial, and the IDEs ERIC and Spyder. Have you looked at the pictures of this program? It's not much beyond some drop-downs and toggle buttons. 

     

    Python has a multilingual internationalization services module in its standard library. Oh, and unlike VCL and FireMonkey, Qt supports right to left languages. 😜

     

     


  7. On 4/8/2022 at 4:18 AM, Sherlock said:

    You forgot the "...which in turn import a ton of more libraries all of which may or may not contain some serious security issues" part 😉

     

    Yes, better to use Delphi, where you can be sure it contains serious security issues! :classic_biggrin: I don't think we're in a position to snipe... what follows is a portion of the log Core Security Technologies kept of their attempt to report the VCL Buffer Overflow vulnerability to Embarcadero. You might want to have some tissues handy....

     

    Report Timeline

    • 2014-05-29: Core Security Technologies attempts to contact Embarcadero.
    • 2014-06-03: Core Security Technologies asks for a reply.
    • 2014-06-09: Core Security Technologies attempts to contact vendor again.
    • 2014-06-12: Core Security Technologies contacts the US-CERT for assistance in order to coordinate the "coordinated disclosure" of the advisory.
    • 2014-06-16: US-CERT answers assigning the following tracking code to the report: VU#646748.
    • 2014-06-30: First release date missed.
    • 2014-07-10: US-CERT informs that they were able to contact the vendor and that a public bug tracking link was published by Embarcadero.
    • 2014-07-10: Core Security Technologies contacts the US-CERT asking for vendor's contact information and informs them that the Embarcadero's bug tracking entry forces us to publish the advisory because the vulnerability details are now public.
    • 2014-07-28: Core Security Technologies receives a reply from Embarcadero stating they expect to have a tentative date for a fix the week of July 28,2014.
    • 2014-07-29: Core Security Technologies replies to Embarcadero that considering there is a public bug tracking report link, we would like to publish the advisory as soon as possible in order to help to protect the users.
    • 2014-08-04: Embarcadero informs Core Security Technologies that they have a fix ready which is currently under internal review. They hope to give Core Security Technologies an expected release date by the end of the week.
    • 2014-08-08: Expected release date (or reply) not received from Embarcadero, Core Security Technologies writes again asking for an update.
    • 2014-08-11: Core Security Technologies notices the status of the public bug tracking report was changed to "fixed". Core Security Technologies emails the Embarcadero asking for clarification about the new status. Two questions are submitted to the Embarcadero (1) Core Security Technologies asks Embarcadero to confirm whether the new status means the fix was made public and (2) in case the fix is still not public, Core Security Technologies requests the tentative release date.
    • 2014-08-11: Embarcadero informs Core Security Technologies that they are testing the fix internally and that they are planning to release it publicly on August 15, 2014.
    • 2014-08-11: Core Security Technologies requests Embarcadero link to the fix so it can be include in the coordinated advisory report.
    • 2014-08-11: Embarcadero replies to Core Security Technologies stating that the link will be delivered August 15, 2014.
    • 2014-08-12: Core Security Technologies requests the estimated time when the fix will be public on August 15, 2014.
    • 2014-08-12: Embarcadero replies that they estimate the fix will be released on August 15, 2014, at 3 p.m. PDT.
    • 2014-08-14: Core Security Technologies requests Embarcadero to postpone the fix release day to August 18, 2014 in order to give users time to patch their software and avoid giving a two-day head start to potential malicious parties. Core Security Technologies informs Embarcadero that it will release the advisory on August 19, 2014 if they accept the postponement. Additionally, Core Security Technologies offers help in contacting third parties affected by this vulnerability.
    • 2014-08-14: Embarcadero agrees with suggested release approach and will postpone the publishing of the fix until August 18, 2014 at 10 a.m. PDT. They also state they are internally discussing how they will notify their customers.
    • 2014-08-15: Core Security Technologies requests Embarcadero deliver the support article and fix so it can be verified.
    • 2014-08-15: Embarcadero sends Core Security Technologies a copy of the support article.
    • 2014-08-15: Upon review of the proposed fix, Core Security Technologies informs Embarcadero that the fix seems incorrect.
    • 2014-08-15: Embarcadero indicates they will investigate based on that assessment of the fix, and says they will need to delay the publishing of the fix until the issue is resolved.
    • 2014-08-15: Embarcadero confirms a problem with the proposed fix was included in the support article and indicates they have a fixed the problem. Embarcadero requests confirmation from Core Security Technologies regarding the new article that includes the updated fix.
    • 2014-08-18: Embarcadero informs Core Security Technologies of updated content in the article, and proposes publishing the same day.
    • 2014-08-18: Core Security Technologies didn't reply due to a national holiday affecting their Buenos Aires offices, but Embarcadero publishes the fix and an accompanying support article.
    • 2014-08-19: Core Security Technologies requests the fix from Embarcadero to update the advisory and verify it.
    • 2014-08-19: Embarcadero replies sending Core Security Technologies a link to the fix. Due to the fact that the fix was released on August 18, 2014 Core Security Technologies schedules the advisory publication for August 20, 2014, leaving the fix analysis task for post-advisory release.
    • 2014-08-20: Advisory CORE-2014-0004 published.
    • Haha 1

  8. On 4/8/2022 at 4:46 AM, Vincent Gsell said:

    - Python is a language that mainly calls libraries, written in languages like c, c++, pascal (or any other archetypal language) 

    Python is a language that has over 360K open source libraries available in its package manager, hence there is very little need to reinvent the wheel, and the Python Package Index has over 360K wheels. Most of those 360K libraries are written in python. JP Morgan revealed they had 35 million lines of Python code when discussing porting Python 2 code to Python 3, and Dropbox has stated in interviews that it has 4 million lines of Python code. Python isn't merely a wrapper for C++. Because it can be the ultimate glue language (wrappers exist for most languages) doesn't remotely mean that's all it's good for.  For instance,  Python powers some of the most trafficked sites on the Internet as well, including Reddit, Instagram and Pinterest. 

    On 4/8/2022 at 4:46 AM, Vincent Gsell said:

    Python therefore allows easy access to an underlying complexity. *But*, this complexity is hidden in libraries. No magic.


    This is simply incorrect. The language has many features that reduce the need for code (not the least of which is dynamic typing). Python guru Raymond Hettinger has said that any step that can be expressed in a single English sentence should be able to be written in a single line of Python code. I've personally ported many older Delphi programs to Python. Admittedly Delphi has added many nice things to require less code (such as type inference) since those programs were written. But using Delphi 5 to 7-era codebases as a metric, I found that the Python savings grew larger as the Delphi code size increased. The largest program I converted had the biggest line count ratio difference, with the Python program being 1/6 the number of lines of the original Delphi program. 

     

    Python offers list comprehensions, a real set type (not a boolean array pretending to be a set), decorators, context managers, bigints, arbitrary precision, fractions, complex numbers, dictionary literals, default dicts, multiple inheritance, named tuples, iteration everywhere, array slicing, yield, generator expressions, a new high-powered case/switch statement dubbed 'structured pattern matching' that's one part case statement one part regex, async, a very smart string that automatically stores text as anything from UTF-8 to UTF-32 internally as needed, argument packing/unpacking, f-strings, a datetime that's both timezone and daylight savings time aware, keyword arguments, assignment expressions, try-else-finally :-), ... the list goes on and on. No magic? The only magic it doesn't have is Penn and Teller.

    On 4/8/2022 at 4:46 AM, Vincent Gsell said:

    So, in your case, rewriting in python what your program does is total nonsense : It would it be 1000 times slower, it wouldn't be necessarily simpler, and it would be as verbose as it is now. And many times more weak, technically/support speaking.

    If the benchmark question I posted here a few weeks ago is any indication, it could end up being 5X faster. :classic_biggrin: It would definitely be simpler and far less verbose, especially since this is older code. And not "weak" because it would be utilizing modern, well-supported open source libraries for everything but the application-specific functionality (which should be put in its own library so others can use it in the future!).

     

    These were the top ten most downloaded Python modules in the last day:

    1    boto3    9,519,635
    2    requests    7,999,561
    3    urllib3    7,918,776
    4    setuptools    7,705,713
    5    botocore    7,584,452
    6    idna    6,303,478
    7    s3transfer    6,256,215
    8    typing-extensions    5,983,085
    9    six    5,880,653
    10    certifi    5,595,107
    11    python-dateutil    5,563,439
    12    pyyaml    5,482,592
    13    charset-normalizer    5,112,908
    14    click    4,330,631
    15    awscli    4,317,207
    16    wheel    4,218,955
    17    numpy    4,078,225
    18    pyparsing    4,078,047
    19    packaging    4,043,536
    20    cryptography    3,917,836

     

    In the last day, the least-downloaded package on that list was downloaded about 8X more than the number of Delphi users on Earth. If Linus' Law, "Given enough eyeballs, all bugs are shallow" holds, that's a lot of eyeballs. (In the last month, the #1 package on that list was downloaded 253 million times!!!). With that level of usage, and the fact that the source is open, this greatly diminishes the odds of encountering a "corner case" bug in a popular package, or of bugs going unfixed for years as in certain, um, other libraries. I don't see how this type of usage and visibility would render things less, as opposed to more, secure. 

     

    I'm not going to weigh all the pros and cons of porting code, especially without examining the code first, but you neglect to mention that porting to Python will open up a much larger pool of potential contributors than sticking with Delphi, which for a potential open source project would be a major factor. Python is also popular among digital studios (Disney was a major sponsor of one of the PyCon events for this reason), the open source 3D modeling software Blender and the open source image editing program GIMP both offer support for plugins written in Python, openCV maintains its own Python wrapper, and the Python package Pillow is very popular for scripted/automated image manipulation. There are also plenty of articles like the below (as well as podcast episodes with similar topics) floating around:

     

    https://blog.matthewgove.com/2021/02/06/photographers-heres-how-to-boost-your-income-with-python-automation/

     

    Heck, they're even offering the same idea to KIDS today....

     

    https://kidscodecs.com/python-photo-editing-pilow/

     

     

    In short, you're likely to find more serious photographers have already been exposed to Python than to Delphi. Many also use Macs, which means that the old Delphi program would need to be ported anyway to FireMonkey if it wanted to reach that sizable base of users (Python, of course, supports all major and minor operating systems). 

     

    Finally, open source enthusiasts are unlikely to warm to the idea of needing to use a proprietary language, IDE and framework to contribute to the project. Even taking into account the monetarily free version, they're unlikely to treasure needing to give personal info to Embarcadero, the stream of emails (and sometimes phone calls!), etc. And needing to develop on Windows? That might be the final straw. The 2021 Stack Overflow Survey shows that 45.33% of developers do their work in Windows, with 25.32% in Linux, 25.19% in OS X, 3.29% in Windows Subsystem for Linux, and 0.18% in BSD. You shrink the potential contributor pool by more than half by limiting developers to Windows. I have no numbers for this, but my instinct suggests the biggest enthusiasts for open source contribution are probably disproportionately found in that 25.32% who are using Linux as well.

     

    There are a lot of factors to consider, but with all due respect I hardly consider the option to port the project to Python "nonsense". 

     

    Attached to the bottom are two images; one is from an article on a programming competition website discussing whether Python should be an allowable language and the second is from an old Paypal Engineers' blog entry called "10 Myths Of Enterprise Python" comparing their ASF XML Serialization library written in C++ to the version they rewrote with Python (1580 lines vs. 130!).

     

     

    python_c++_1229911_10151848862276101_2040990685_n.jpg

    cpp_py_medium.png


  9. On 3/31/2022 at 4:26 PM, Joe Sansalone said:

    Hi,

     

    In terms of performance:

    Has anyone tested Interbase with encryption (at rest and in motion) vs no encryption?

     

    Even rough comparisons would be useful.

    Just looking for any data describing relative performance.

     

    Thanks,

    Joe

     

    While I don't have numbers for you, I do have this perspective - Interbase's encryption is effectively useless. People have occasionally proposed the same feature for PostgreSQL, and every time there's both little interest and sound arguments about why it's useless.

     

    If you want to protect your data if someone walks off with a server hard drive, you have OS-level or hardware level full-disk encryption available. Embarcadero would argue that this doesn't protect anyone from snooping while the system is running, since the encryption in this case is transparent to the running OS. That's true, but Interbase's solution won't help you here either. Here's why:

     

    On a typical server, the database is given its own user account and is the only application running as this user. All the files are set to belong to the database only. This makes sense as nothing else should be touching the raw database files. So in this case there would be a user "interbase" that owns all of Interbase's files and the Interbase executable is the only application that should be able to touch the raw database files. All well and good. Data is encrypted within the Interbase database to protect it from someone who manages to gain access to the raw database files anyway. But here you're not helped. The encryption key is stored on the server. The "interbase" user owns the key file. If anyone has gained sufficient access rights to read the raw database file, they also have the right to read the key file, since it's going to have the same access privileges. Now if you have the raw database file and the encryption key you can decrypt the encrypted data and the Interbase encryption was useless in protecting your data.

     

    Some would argue it's better to do encryption on the client end and store the encrypted data in the database. Now if someone gains access to the server and the database file they still need to also gain access to the client to get the encryption key. This is more secure, but if encryption happens on the client end the database can't read the unencrypted data and hence indexes won't work on those columns.

     

    So IMHO neither of these solutions accomplish much and in most instances aren't worth the hassle.


  10. On 3/15/2022 at 6:54 AM, Anders Melander said:

    The problem I'm talking about is the production of the sessions. I mean how difficult is it to ensure that sessions doesn't run over time, that the sound works and there 's capacity to handle everyone signed up. And when things go wrong we don't need to hear every random thought that goes through the moderators head, spoken out loud as he fumbles with trying to resolve the issues.

    That happens during the convention too? Dang. I signed up for one of their "TCoffee and Code" sessions a while back with the topic of "Real-Time Financial Software Development with Delphi". I'd been talking to someone about possibly working with them on some financial software to test some investing ideas they had and I was curious what the state of financial libraries for Delphi was. I wasn't aware of any, so I thought this would be interesting.

     

    I set aside my lunch time to watch. Jim McKeith had decided to try hosting the webinar via YouTube and it was not going well. Jim struggled to get everyone's audio working. I suggested the next event be moved to OnlyFans, but he and the guests decided against that idea. :classic_biggrin: What followed was half an hour of the attendees offering advice to Jim to try to fix the problems. If you've ever wanted to see Jim McKeith's head shrink and fly around your screen (and who hasn't?) feel free to click here. The next half hour saw the guest tell war stories about what it was like trying to create financial software in the 1980s. Now I enjoy 80's tech nostalgia as much as anyone, but this wasn't exactly what I'd expected to get out of this webinar. About 1 hour 10 minutes in my lunch time was past done and I had to log out, never actually learning anything about financial software development with Delphi, real-time or not (guest was still talking about Turbo Pascal). The final cut of the video on YouTube shows the talk ran just shy of two and a half hours! (Coffee must have gotten cold). Sadly I never made the time to watch the remaining hour and a half to see if it got better. And now I'm hearing that even CodeRage or DelphiCon or whatever it is nowadays has the same kind of issues, even after staging it all these years. Shame.

    • Like 4

  11. 13 hours ago, dummzeuch said:

    Have you tried integer instead of Int64? Or are we talking the 64 bit compiler?

     

    (1 billion is < 2^31 of I'm not totally mistaken.)

    The sum of the values is 233,333,334,166,666,668 which would overflow a 32bit Integer. I tried changing the loop counter to Integer, but that didn't produce any change in the time.


  12. About a month ago I was doing some benchmarks of FreePascal under Linux and got an unexpected result. Thanks to some help here I was able to get Delphi Community Edition installed yesterday and found the same anomaly with Delphi targeting Windows. I was wondering if I'm missing something in the below benchmark or something has changed with the new compiler and there's something I'm doing I'm not aware of that significantly impacts performance.

     

    The benchmark consists of summing the total of all the numbers between 1 and 1 billion which are evenly divisible by 3 or 5 and printing the total. It seems to me that it's a short, simple and straightforward test that should have one simple, obvious way to implement it in Pascal:

    program numtest8;
    
    Var total, num : Int64;
    begin
      total := 0;
      for num := 1 to 1000000000 Do
          if (num mod 3 = 0) or (num mod 5 = 0) Then
                total := total + num;
    WriteLn(total);
    
    end.

    Compiled with maximum performance under FreePascal (I tried other O settings; they didn't make any difference) these are the results I get on a Ryzen 2700 8 core CPU with stock cooler, best of 3:

     

    64bit, Linux: 11.36 seconds, 99% CPU

    64bit, Windows 11 VM, 11.43 seconds (PowerShell doesn't report CPU usage with the timing information)

     

    This is the figure for Delphi:

     

    64bit, Windows 11 VM: 11.38 seconds

     

    Those figures seem rather consistent across two compilers, two operating systems, a VM and bare metal, so nothing weird. But here's the weird part (cue spooky music):

     

    I was also performing the benchmark across other languages, single core vs. parallel, etc. One language tested was Python. I was able to create a single-threaded Python version that beat a multicore version, but that's a weird result for another forum. It's this that has me stumped. What follows is a test with PyPy, a JIT-enabled version of the Python runtime. Here's the source code:

     

    total = 0
    
    for x in range(1, 1_000_000_001):
        if x % 3 == 0 or x % 5 == 0:
            total = total + x
            
    print(total)        

    Note: if I were performing the benchmark this way in regular Python, it'd still be running; loops kill Python performance. The best way of writing this code in regular Python gives a result of 1 minute, 15 seconds (!!!). But PyPy was much better... too much better:

     

    PyPy3.9 v7.3.8, 64bit, Linux: 3.34 seconds, 99% CPU

    PyPy3.9 V7.3.8 64bit, Windows VM: 3.41 seconds

     

    PyPy performed over 3X faster than Delphi / FreePascal, and that's including the time it takes to compile on the fly! The CPU data from the Linux run proves what I already knew about PyPy, that it doesn't do any automatic parallelization that might explain this result. Is there some fancy new CPU instruction it could be using that the Pascal compilers aren't? I seem to recall that at least the Delphi 32bit compiler didn't perform bit-shifting to do division; could that still be the case and the divisions are killing the performance?

     

    I decided to test another JIT option for Python, Numba. Numba is intended to JIT mathematical operations only. It's not a Python runtime, but a regular library that takes Python functions and compiles them. It also has a cache function and a pre-compile option. I was lazy and since I didn't know how the pre-compile function worked I just used the cache option and ran it once to cache the compiled function then performed benchmarks. The code:

     

    from numba import jit
    
    
    @jit(nopython=True, cache=True, fastmath=True)
    def test():
        total = 0
        for num in range(1, 1_000_000_001):
            if num % 3 == 0 or num % 5 == 0:
                total = total + num
        return total
    
    answer = test()
    print(answer)

    Python3.10.2 + Numba, 64bit, Linux: 2.07 seconds, 158% CPU

    Python3.10.2 + Numba, 64bit, Windows VM: 2.49 seconds

     

    I can't really explain the 158% CPU figure, as I know that numba can do some parallelization but a debug run suggested it couldn't find anything to parallelize. Regardless, it knocked almost a second off the PyPy time, probably due to caching the compiled function.

     

    I could tell Numba to explicitly parallelize:

    from numba import jit, prange
    
    
    @jit(nopython=True, cache=True, parallel=True, fastmath=True)
    def test():
        total = 0
        for num in prange(1, 1_000_000_001):
            if num % 3 == 0 or num % 5 == 0:
                total = total + num
        return total
    
    answer = test()
    print(answer)

    And now we get:

    Python3.10.2 + Numba, 64bit, Linux: 0.84 seconds, 743% CPU

    Python3.10.2 + Numba, 64bit, Windows VM:  1.20 seconds

     

    Clearly here the CPU results under Linux are consistent with an 8-core CPU.

     

    So the mystery is: With a statically typed, compiled language, we get circa 11.4 seconds across OSes and compilers. With a dynamically typed language with its own runtime VM, and one notoriously slow at that, we get 3.4 seconds at worst including JIT compile time, , 2.0 - 2.5 seconds pre-compiled with some possible automatic optimization, and 0.8 - 1.2 seconds with explicitly requesting the loop be parallelized. Those results are... unexpected. Now I honestly thought that JITted Python could match or ever-so-slightly beat FreePascal, because I've seen that happen before several years ago. But at least 3X faster to 10X faster? That was a shock.

     

    I'm half hoping someone will tell me I'm an idiot and I should never write Pascal code like that and if I just do X it'll speed up 300%. If not, my best guess after days of thought is that vague memory about bit-shifting. I remember when I read that Delphi didn't do that because Tiny C, a C compiler so tiny it fits on a 3.5" floppy disk - with operating system! - only has three optimizations, but one of them is bit-shifting. That would seem to imply it's rather useful.

     

    I'd be interested if anyone has any insight into why Delphi and FreePascal performed so poorly in this benchmark. I'd really like to rule out any mistakes on my end. If we can figure out what's killing the Delphi performance - and it's not me - these results should make for a very, very interesting QC feature request. :classic_biggrin:

     

    • Like 1

  13. 12 hours ago, Fons N said:

    Hi,

     

    I got the same problem (in the Pro version of Delphi). Mike helped me out. As I don't know how to put a link to that answer, I just made a copy of his answer. So, thank him, not me. It the answer as Lajos gave, but with pictures. I also find that easier (but that may be my age :classic_biggrin:).

     

    Fons

     

    Thank you! This worked, but I must say I'd probably have never figured it out in a million years on my own. Interface-wise, it makes no sense at all.


  14. 19 minutes ago, Anders Melander said:

    I remember that incident. Classic Nick.

    To be fair, the Nick Hodges of today isn't like that anymore. I think once he stopped posting in the old forum he became a much happier person. Even he admitted that that environment tended to bring out the worst in people. Apparently he's now the developer advocate at Rollbar, so he's no longer employed working with Delphi either. I rather like New Nick.

×