The Wiert Corner – irregular stream of stuff

Jeroen W. Pluimers on .NET, C#, Delphi, databases, and personal interests

  • My badges

  • Twitter Updates

  • My Flickr Stream

  • Pages

  • All categories

  • Enter your email address to subscribe to this blog and receive notifications of new posts by email.

    Join 1,380 other followers

Archive for the ‘Delphi XE3’ Category

Delphi, IBX and the Turkish I problem

Posted by jpluimers on 2018/06/13

Last year, it took a while to reproduce and it is likely not fixed anytime soon: if you use Delphi and IBX (InterBase Express) to connect to either InterBase or FireBird database, then in the Turkish locale do not use lowercase SQL in your Delphi code as it will break on the

I’ve decided to put this in a separate post than the one I discovered the issue in as that one focused on the Unicode and language background of the various i/I/ characters and this post on the Delphi part.

So for the non-Delphi part, read Source: Field “id” not found and the The Turkish-İ/I/i/ı and case conversion – Update on the dasBlog Turkish-I bug and a reminder to me on Globalization – Scott Hanselman.

In general, this problem is called [WayBack] Case Folding and many environments do not have good and ready to use solutions for this.

Basically when working with case-insensitive language identifiers, you should always use culture invariant text comparison operations. In most languages, people use either lowercase or uppercase converted operations which for Delphi >= come down to using :

The reason is simple:

  • without any parameter, ToLower and ToUpper will use [Archive.isSysLocale.DefaultLCID.
  • without any parameter, LowerCase and UpperCase will implicitly behave as if called with TLocaleOptions.loInvariantLocale, but lots of people forget they do.

The functions ToLowerInvariant and  ToUpperInvariant  were added in Delphi XE3, but ToLower(LocaleID) and ToUpper(LocaleID) in Delphi XE4.

Instead of doing uppercase and lowercase comparisons you could also use the [Archive.isSystem.SysUtils.CompareText function.

IBX however uses case conversion, and by now you will probably guessed it: IBX got it all wrong. One reproduction is at https://gist.github.com/jpluimers/643b382944ff991d07ec96abbf85548c and a thread with background is at [WayBack] What’s the Delphi equivalent of doing UpperCase with an InvariantCulture in Unicode Delphi versions? (XE and up) – Jeroen Wiert Pluimers – Google+

IBX isn’t alone: just search for other uppercase issues like Turkish i to see tons of other issues.

For IBX, I did the replacements in the diff below to fix it in Delphi XE8. I only replaced where identifiers were compared, not were actual database content was compared.

Unluckily, in the past IBX sources were hosted on CodeCentral at http://cc.embarcadero.com/Author/102 but no new bundles have been released since 2012.

Of all the locations I think IBX should not have used any case conversion here:

IBX.IBDatabaseINI.pasfunction LocalServerPath(sFile: string): string

This function uses LowerCase() but I think an NTFS specific comparison should have been used, but I’ve not investigated into a solution for that yet.

–jeroen

Read the rest of this entry »

Posted in Delphi, Delphi 10 Seattle, Delphi 10.1 Berlin (BigBen), Delphi XE3, Delphi XE4, Delphi XE5, Delphi XE6, Delphi XE7, Delphi XE8, Development, Software Development | Leave a Comment »

Reminder to self: check out “Debugging helper for TDataSet” and “debugger TDataSetVisualizer” for Delphi

Posted by jpluimers on 2018/04/24

So I won’t forget to check these out:

Via  [WayBackI like programming in Delphi, but I don’t particularly like writing applications that work with database backends… – Thomas Mueller (dummzeuch) – Google+ (thanks Stefan Glienke)

Read the rest of this entry »

Posted in Delphi, Delphi 10 Seattle, Delphi 2010, Delphi XE, Delphi XE2, Delphi XE3, Delphi XE4, Delphi XE5, Delphi XE6, Delphi XE7, Delphi XE8, Development, Software Development | 1 Comment »

How to embed a superscript Registered symbol in a Rave memo buffer.

Posted by jpluimers on 2018/04/24

Thomas Pfister came with a nice solution to this question:

[WayBack] Does anyone know how to embed a superscript Registered symbol in a Rave memo buffer? – Phillip Woon – Google+

Since Google has such bad indexing of G+, here is the solution:

procedure TForm4.RvSystem1Print(Sender: TObject);
const
  SuperscriptOn = RPTFPrefix + RPTFSuperscript + RPTFOn + RPTFSuffix; // from RpDefine.pas
  SuperscriptOff = RPTFPrefix + RPTFSuperscript + RPTFOff + RPTFSuffix;
var
  MemoBuf: TMemoBuf;
begin
  MemoBuf := TMemoBuf.Create;
  try
    MemoBuf.Text := 'Test' + SuperscriptOn + '®' + SuperscriptOff + ' Test';
    MemoBuf.PrintStart := 0.5;
    MemoBuf.PrintEnd := 8.0;

    with Sender as TBaseReport do begin
      PrintMemo(MemoBuf, 1, true);
    end;
  finally
    FreeAndNil(MemoBuf);
  end;
end;

–jeroen

Source: Does anyone know how to embed a superscript Registered symbol in a Rave memo …

Posted in Delphi, Delphi 10 Seattle, Delphi 10.1 Berlin (BigBen), Delphi 2007, Delphi 2009, Delphi 2010, Delphi XE, Delphi XE2, Delphi XE3, Delphi XE4, Delphi XE5, Delphi XE6, Delphi XE7, Delphi XE8, Development, Software Development | Leave a Comment »

Tip for the doc team: make TMonitor.Enter docs more clear on non-blocking re-entry from the same thread

Posted by jpluimers on 2018/04/19

Even when the Delphi team was large, the documentation was lacking, so with the reduced Delphi team size, I don’t have high expectations of the below to get fixed.

But since much of the post Delphi 7 run-time library looks a lot like the .NET core, you can usually fallback to the Microsoft documentation.

Tip for the doc team: make http://docwiki.embarcadero.com/Libraries/en/System.TMonitor.Enter more clear. Especially that if the same thread calls TMonitor.Enter more than one time, it will allow entry without blocking as per System.Threading.Monitor.Enter Method (Object) documentation https://msdn.microsoft.com/en-us/library/de0542zz

(note that this got introduced in Delphi XE3: http://docwiki.embarcadero.com/Libraries/XE3/en/System.TMonitor.Enter)

–jeroen

via: [WayBack] Tip for the doc team: make http://docwiki.embarcadero.com/Libraries/Seattle/e…

Posted in Delphi, Delphi 10 Seattle, Delphi 10.1 Berlin (BigBen), Delphi XE3, Delphi XE4, Delphi XE5, Delphi XE6, Delphi XE7, Delphi XE8, Development, Software Development | 2 Comments »

Reminder to Self: `TProc` is incompatible with parameterless procedures on interfaces

Posted by jpluimers on 2018/04/19

I knew that methods on interfaces were not compatible with the procedure of object (like [WayBack] TProc)or function of object construct, but they are also not compatible with the reference to procedure or reference to function construct.

Via: [WayBack] I try to call an Interface method from TThread.Syncrhonize()…and Berlin don’t accept that… – Paul TOTH – Google+

If you want it fixed, vote for [RSP-13007] Interface methods are not assignable to anonymous method variable – Embarcadero Technologies (Thanks Stefan Glienke).

You can work around it with an anonymous method.

This won’t work:

program Project1;
{$APPTYPE CONSOLE}
uses
  SysUtils;
 
type
  ITest = interface
    ['{B5AD87E8-A3DF-4B83-BE14-997C2E76A06C}']
    procedure Run;
  end;
 
  TTest = class(TInterfacedObject, ITest)
    procedure Run;
  end;
 
procedure TTest.Run;
begin
  Writeln('PASS')
end;
 
var
  test: ITest; // <- change this to TTest and it compiles
  proc: TProc;
begin
  test := TTest.Create;
  proc := procedure begin test.Run; end; // <- this compiles
  proc := test.Run; // E2010 Incompatible types: 'TProc' and 'procedure, untyped pointer or untyped parameter'
  proc();
  Readln;
end.

–jeroen

 

Posted in Delphi, Delphi 10 Seattle, Delphi 10.1 Berlin (BigBen), Delphi XE, Delphi XE2, Delphi XE3, Delphi XE4, Delphi XE5, Delphi XE6, Delphi XE7, Delphi XE8, Development, Software Development | Leave a Comment »

 
%d bloggers like this: