Recent

Author Topic: [SOLVED] Are there units that give access to setlocale and the LC_* constants?  (Read 785 times)

Gustavo 'Gus' Carreno

  • Hero Member
  • *****
  • Posts: 1248
  • Professional amateur ;-P
Hey Y'All,

While doing my fp-ncurses-tui I need to use setlocale with the LC_* constants.

In a piece of code that I had laying around from previous ncurses experimentation, I used the initc unit, for some reason I can't quite remember now, but I still needed to add this to my code, in order to use setlocale:
Code: Pascal  [Select][+][-]
  1. function setlocale(cat : integer; p : pchar):pchar; cdecl; external clib;
  2.  
  3. const
  4.   LC_ALL = 6;

I've also been suggested to use the clocale unit to mitigate this issue, but it didn't work. Granted, I did not have a look at what that unit contains and I may be barking up the wrong tree here.

So, my question is: What do I need to include in my uses section so I can manage the locale without having to declare my own stuff. Cuz, if my code gets stale, and it will, I would rather prefer to rely on code from the core team, than from hacks of my own!!

Cheers,
Gus
« Last Edit: June 23, 2025, 11:16:58 am by Gustavo 'Gus' Carreno »
Lazarus 3.99(main) FPC 3.3.1(main) Ubuntu 23.10 64b Dark Theme
Lazarus 3.0.0(stable) FPC 3.2.2(stable) Ubuntu 23.10 64b Dark Theme
http://github.com/gcarreno

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 12311
  • FPC developer.
Afaik there is no general unix locale interface that abstracts setlocale for user usage.   Clocale is only meant to initialize the FPC rtl with locale dependent defaults on *nix, not as a way to manipulate locale itself.

Afaik there are also slight differences between various OSes implementations of locale.  Studying clocale can help you avoid certain pittfalls.


Gustavo 'Gus' Carreno

  • Hero Member
  • *****
  • Posts: 1248
  • Professional amateur ;-P
Hey MarcoV,

Afaik there is no general unix locale interface that abstracts setlocale for user usage.   Clocale is only meant to initialize the FPC rtl with locale dependent defaults on *nix, not as a way to manipulate locale itself.

Afaik there are also slight differences between various OSes implementations of locale.  Studying clocale can help you avoid certain pittfalls.

Thanks !! That helps me get situated.

I'll have to do a deep dive into the clocale unit in order to understand more stuff related to this.

And, yes, various OSs do have different values for the LC_*. I was able to confirm that when I had a look at my local version of locale.h and saw that the numbers are actually macros.
This pretty much means that I would need to find said macros and grok the magic they are performing. Not keen on that :D

In any case, many thanks for pointing this out. I'll have a good look at clocale to get my head straight!

Cheers,
Gus
Lazarus 3.99(main) FPC 3.3.1(main) Ubuntu 23.10 64b Dark Theme
Lazarus 3.0.0(stable) FPC 3.2.2(stable) Ubuntu 23.10 64b Dark Theme
http://github.com/gcarreno

Gustavo 'Gus' Carreno

  • Hero Member
  • *****
  • Posts: 1248
  • Professional amateur ;-P
Hey MarcoV,


So, like you suggested, I went to have a look at clocale.pp and I found this:
Code: Pascal  [Select][+][-]
  1. Const
  2. {...}
  3. // checked for Linux only, but might be general glibc.
  4.   __LC_CTYPE    = 0;
  5.   __LC_NUMERIC  = 1;
  6.   __LC_TIME     = 2;
  7.   __LC_COLLATE  = 3;
  8.   __LC_MONETARY = 4;
  9.   __LC_MESSAGES = 5;
  10.   __LC_ALL      = 6;
  11.  
  12. {...}
  13.  
  14. {$ifdef netbsd}
  15.   { NetBSD has a new setlocale function defined in /usr/include/locale.h
  16.     that should be used }
  17. function setlocale(category: cint; locale: PAnsiChar): PAnsiChar; cdecl; external clib name '__setlocale_mb_len_max_32';
  18. {$else}
  19. function setlocale(category: cint; locale: PAnsiChar): PAnsiChar; cdecl; external clib name 'setlocale';
  20. {$endif}

So, I was super glad that this means I only need to include clocale (since it already uses initc ) and I have access to setlocale and the __LC_* constants!!!

But, and color me utterly confused, when I do the changes on the lazncurses project and I get this:
Code: Text  [Select][+][-]
  1. laz_nCurses.pas(25,3) Error: Identifier not found "setlocale"
  2. laz_nCurses.pas(25,13) Error: Identifier not found "__LC_ALL"

What the heck is going wrong??? Especially because when I load clocale.pp in Lazarus, the code I need is not grayd out.
The compiler should be able to find that, right?

What am I missing here?!?!?

Cheers,
Gus
Lazarus 3.99(main) FPC 3.3.1(main) Ubuntu 23.10 64b Dark Theme
Lazarus 3.0.0(stable) FPC 3.2.2(stable) Ubuntu 23.10 64b Dark Theme
http://github.com/gcarreno

Gustavo 'Gus' Carreno

  • Hero Member
  • *****
  • Posts: 1248
  • Professional amateur ;-P
Hey MarcoV,

Just to be thorough, this works:
Code: Pascal  [Select][+][-]
  1. program laz_nCurses;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. uses
  6.   SysUtils, initc, ctypes, clocale, ncurses;
  7.  
  8. function setlocale(category: cint; locale: PAnsiChar): PAnsiChar; cdecl; external clib name 'setlocale';
  9.  
  10. const
  11.   // checked for Linux only, but might be general glibc.
  12.     __LC_CTYPE    = 0;
  13.     __LC_NUMERIC  = 1;
  14.     __LC_TIME     = 2;
  15.     __LC_COLLATE  = 3;
  16.     __LC_MONETARY = 4;
  17.     __LC_MESSAGES = 5;
  18.     __LC_ALL      = 6;

But that's a major DUH :D

And I don't even get an error telling me that there's a double declaration!!!

And this doesn't:
Code: Pascal  [Select][+][-]
  1. program laz_nCurses;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. uses
  6.   SysUtils, initc, ctypes, clocale, ncurses;
  7.  
  8. //function setlocale(category: cint; locale: PAnsiChar): PAnsiChar; cdecl; external clib name 'setlocale';
  9.  
  10. //const
  11. //  // checked for Linux only, but might be general glibc.
  12. //    __LC_CTYPE    = 0;
  13. //    __LC_NUMERIC  = 1;
  14. //    __LC_TIME     = 2;
  15. //    __LC_COLLATE  = 3;
  16. //    __LC_MONETARY = 4;
  17. //    __LC_MESSAGES = 5;
  18. //    __LC_ALL      = 6;

As you can see, it makes no sense, at least superficially, as to why I don't get those declarations when I include all the necessary units!!

Cheers,
Gus
Lazarus 3.99(main) FPC 3.3.1(main) Ubuntu 23.10 64b Dark Theme
Lazarus 3.0.0(stable) FPC 3.2.2(stable) Ubuntu 23.10 64b Dark Theme
http://github.com/gcarreno

jamie

  • Hero Member
  • *****
  • Posts: 6989
FormatSettings Record does not help?

The only true wisdom is knowing you know nothing

Gustavo 'Gus' Carreno

  • Hero Member
  • *****
  • Posts: 1248
  • Professional amateur ;-P
Hey Jamie,

FormatSettings Record does not help?

Not really since that's Lazarus centric and my initial issue was with ncurses.
I'm now under the impression that the issues that I'm having with ncurses have nothing to do with the terminal's locale, but have all the hints that it's something related to fpc switches!!

But now that I've realised that including clocale does not give me visibility to setlocale and the __LC_* constants, I'm now doubling down on it just to suss out why that happens!!!
From all indications, it should give me access to those things. In reality: bupkiss !! Which is rather infuriating   >:(

Oh well, maybe one of the core devs can have an inkling why this is happening !!

Cheers,
Gus
Lazarus 3.99(main) FPC 3.3.1(main) Ubuntu 23.10 64b Dark Theme
Lazarus 3.0.0(stable) FPC 3.2.2(stable) Ubuntu 23.10 64b Dark Theme
http://github.com/gcarreno

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 12311
  • FPC developer.
clocale has those definitions in the implementation, not in the interface.

Thaddy

  • Hero Member
  • *****
  • Posts: 17396
  • Ceterum censeo Trump esse delendam
And formatsettings is RTL. Not LCL.
(sysutils)
And crossplatform, so better use that.
Greatly simplifies the problem.
« Last Edit: June 23, 2025, 09:11:31 am by Thaddy »
Due to censorship, I changed this to "Nelly the Elephant". Keeps the message clear.

Gustavo 'Gus' Carreno

  • Hero Member
  • *****
  • Posts: 1248
  • Professional amateur ;-P
Hey MarcoV,

clocale has those definitions in the implementation, not in the interface.

BLOODY HELL !!! How blind am I to not even notice that  :-[

Thanks for the correction. It was right in front of me and I didn't even notice :facepalm-hard: :headbut-desk: !!!

Ok... Now that I've acknowledged my inane stupidity...

I've had a better look at the actual code in clocale, and I understand why the interface is completely empty: All the functionality is in the initialization section.

And that code is all about Format Settings!! and in that code setlocale(__LC_ALL, '') is already called!!!

Ok, time to look at the bloody Format Settings!!

Cheers,
Gus
Lazarus 3.99(main) FPC 3.3.1(main) Ubuntu 23.10 64b Dark Theme
Lazarus 3.0.0(stable) FPC 3.2.2(stable) Ubuntu 23.10 64b Dark Theme
http://github.com/gcarreno

Gustavo 'Gus' Carreno

  • Hero Member
  • *****
  • Posts: 1248
  • Professional amateur ;-P
Re: Are there units that give access to setlocale and the LC_* constants?
« Reply #10 on: June 23, 2025, 11:16:37 am »
Hey Thaddy,

And formatsettings is RTL. Not LCL.
(sysutils)
And crossplatform, so better use that.
Greatly simplifies the problem.

I can only thank you for the correction. My bad, actually. It pretty much shows my ignorance at the lower layers of Free Pascal  :-[

I've had a better look at the actual code in clocale, and I understand why the interface is completely empty: All the functionality is in the initialization section.

And that code is all about Format Settings!! and in that code setlocale(__LC_ALL, '') is already called!!!

Ok, time to look at the Format Settings!! But adding clocale to my code is actually good... If it even makes a diff in terms of the issues with the ACS_* stuff, which I'm really suspecting it doesn't.

Cheers,
Gus
Lazarus 3.99(main) FPC 3.3.1(main) Ubuntu 23.10 64b Dark Theme
Lazarus 3.0.0(stable) FPC 3.2.2(stable) Ubuntu 23.10 64b Dark Theme
http://github.com/gcarreno

Thaddy

  • Hero Member
  • *****
  • Posts: 17396
  • Ceterum censeo Trump esse delendam
Note "formatsettings" is a global variable.
Better make a copy when you want to change something in code.
Code: Pascal  [Select][+][-]
  1. {$mode objfpc}
  2. uses sysutils;
  3. var
  4.   MyFormatSettings:TFormatSettings;
  5. begin
  6.   MyFormatSettings := FormatSettings; // make a copy
  7.   // then work with MyFormatSettings and use the functions that support it like so:
  8.   MyFormatSettings.DateSeparator := '\';
  9.   writeln(DateTimeToStr(Now,MyFormatSettings));// your changes
  10.   writeln('But the OS settings are this:');
  11.   writeln(DateTimeToStr(Now,FormatSettings));  // as per OS default
  12.   readln;
  13. end.
  14.  

Have fun! it is very powerful. Especially with databases, which are more efficient in YYYYMMDD format, because that is the natural sort order for TDateTime.
« Last Edit: June 24, 2025, 11:29:23 am by Thaddy »
Due to censorship, I changed this to "Nelly the Elephant". Keeps the message clear.

 

TinyPortal © 2005-2018