Repository URL to install this package:
|
Version:
3.2.0 ▾
|
{
This file is part of the Free Pascal packages library.
Copyright (c) 2013 by Yury Sidorov, member of the
Free Pascal development team
This unit is used to get format settings of the current
Mac OS UI locale. Works on Mac OS X 10.3 or later.
Function CFStringToStr() has been taken from CarbonProc LCL unit.
See the file COPYING.FPC, included in this distribution,
for details about the copyright.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
**********************************************************************}
unit iosxlocale;
{$mode objfpc}{$H+}
interface
uses
SysUtils, MacOSAll;
procedure GetMacFormatSettings(var ASettings: TFormatSettings);
implementation
{------------------------------------------------------------------------------
Name: CFStringToStr
Params: AString - Core Foundation string ref
Encoding - Result data encoding format
Returns: UTF-8 string
Converts Core Foundation string to string
------------------------------------------------------------------------------}
function CFStringToStr(AString: CFStringRef): UTF8String;
var
Str: Pointer;
StrSize: CFIndex;
StrRange: CFRange;
begin
if AString=nil then
begin
Result:='';
Exit;
end;
// Try the quick way first
Str:=CFStringGetCStringPtr(AString, kCFStringEncodingUTF8);
if Str<>nil then
Result:=PChar(Str)
else
begin
// if that doesn't work this will
StrRange.location:=0;
StrRange.length:=CFStringGetLength(AString);
CFStringGetBytes(AString, StrRange, kCFStringEncodingUTF8,
Ord('?'), False, nil, 0, StrSize{%H-});
SetLength(Result, StrSize);
if StrSize>0 then
CFStringGetBytes(AString, StrRange, kCFStringEncodingUTF8,
Ord('?'), False, @Result[1], StrSize, StrSize);
end;
end;
function StrOfChar(c: AnsiChar; Count: integer): utf8string;
begin
SetLength(Result, Count);
FillChar(PAnsiChar(Result)^, Count, c);
end;
function ConvertFormatStr(const fmt: utf8string): utf8string;
var
cnt: integer;
c, q: AnsiChar;
p: PAnsiChar;
s: utf8string;
begin
Result:='';
q:=#0;
cnt:=1;
p:=PAnsiChar(fmt);
while p^<>#0 do
begin
s:='';
c:=p^;
if c in ['''', '"'] then
begin
if q=#0 then
q:=c
else
if c=q then
begin
q:=#0;
cnt:=1;
end;
s:=c;
end
else if q <> #0 then
s:=c
else
begin
if (p+1)^=c then
Inc(cnt)
else
begin
case c of
'y', 'Y':
begin
c:='y';
if cnt > 2 then
cnt:=4
else
cnt:=2;
end;
'M', 'L':
begin
c:='m';
if cnt > 4 then
cnt:=3;
end;
'd':
if cnt > 2 then
cnt:=2;
'E', 'e', 'c':
begin
c:='d';
if (cnt < 3) or (cnt > 4) then
cnt:=3;
end;
'a':
begin
cnt:=0;
s:='ampm';
end;
'h', 'H', 'k', 'K':
begin
c:='h';
if cnt > 2 then
cnt:=2;
end;
'm':
begin
c:='n';
if cnt>2 then
cnt:=2;
end;
's':
if cnt>2 then
cnt:=2;
'S':
begin
c:='z';
cnt:=1;
end;
'G','u','Q','q','w','W','D','F','g','A','z','Z','v':
cnt:=0;
end;
if cnt>0 then
s:=StrOfChar(c, cnt);
cnt:=1;
end;
end;
Inc(p);
if s<>'' then
Result:=Result+s;
end;
end;
procedure GetMacFormatSettings(var ASettings: TFormatSettings);
var
loc: CFLocaleRef;
function _GetFormat(dateStyle: CFDateFormatterStyle; timeStyle: CFDateFormatterStyle; const DefFormat: utf8string): utf8string;
var
fmt: CFDateFormatterRef;
begin
Result:='';
fmt:=CFDateFormatterCreate(nil, loc, dateStyle, timeStyle);
if fmt <> nil then
begin
Result:=ConvertFormatStr(CFStringToStr(CFDateFormatterGetFormat(fmt)));
CFRelease(fmt);
end;
if Result = '' then
Result:=DefFormat;
end;
function _DateToStr(fmt: CFDateFormatterRef; const AFormat: utf8string; AYear: integer; AMonth, ADay, AHour: byte;
const ADefault: utf8string): utf8string;
var
cs: CFStringRef;
gd: CFGregorianDate;
at: CFAbsoluteTime;
tz: CFTimeZoneRef;
begin
cs:=CFStringCreateWithCString(nil, Pointer(PAnsiChar(AFormat)), kCFStringEncodingUTF8);
CFDateFormatterSetFormat(fmt, cs);
CFRelease(cs);
FillChar(gd, SIzeOf(gd), 0);
gd.year:=AYear;
gd.month:=AMonth;
gd.day:=ADay;
gd.hour:=AHour;
tz:=CFTimeZoneCopyDefault;
at:=CFGregorianDateGetAbsoluteTime(gd, tz);
CFRelease(tz);
cs:=CFDateFormatterCreateStringWithAbsoluteTime(nil, fmt, at);
Result:=CFStringToStr(cs);
CFRelease(cs);
if Result = '' then
Result:=ADefault;
end;
function _GetSeparator(dateStyle: CFDateFormatterStyle; timeStyle: CFDateFormatterStyle; DefSep: char): char;
var
fmt: CFDateFormatterRef;
s: utf8string;
p: PAnsiChar;
begin
Result:=DefSep;
fmt:=CFDateFormatterCreate(nil, loc, dateStyle, timeStyle);
if fmt <> nil then
begin
s:=_DateToStr(fmt, CFStringToStr(CFDateFormatterGetFormat(fmt)), 2000, 1, 1, 0, DefSep);
s:=Trim(s);
p:=PAnsiChar(s);
while p^<>#0 do
if (p^>' ') and (p^<'A') and not (p^ in ['0'..'9']) then
begin
Result:=p^;
break;
end
else
Inc(p);
CFRelease(fmt);
end;
end;
var
s: utf8string;
fmt: CFDateFormatterRef;
i: integer;
begin
with ASettings do
begin
loc:=CFLocaleCopyCurrent;
if loc=nil then
exit;
s:=CFStringToStr(CFLocaleGetValue(loc, kCFLocaleDecimalSeparator));
if Length(s)=1 then
DecimalSeparator:=s[1];
s:=CFStringToStr(CFLocaleGetValue(loc, kCFLocaleGroupingSeparator));
if Length(s)=1 then
ThousandSeparator:=s[1]
else
ThousandSeparator:=' '; // Unicode char has been returned. Probably it is a whitespace
CurrencyString:=CFStringToStr(CFLocaleGetValue(loc, kCFLocaleCurrencySymbol));
DateSeparator:=_GetSeparator(kCFDateFormatterShortStyle, kCFDateFormatterNoStyle, DateSeparator);
TimeSeparator:=_GetSeparator(kCFDateFormatterNoStyle, kCFDateFormatterShortStyle, TimeSeparator);
LongDateFormat:=_GetFormat(kCFDateFormatterLongStyle, kCFDateFormatterNoStyle, LongDateFormat);
ShortDateFormat:=_GetFormat(kCFDateFormatterShortStyle, kCFDateFormatterNoStyle, ShortDateFormat);
LongTimeFormat:=_GetFormat(kCFDateFormatterNoStyle, kCFDateFormatterLongStyle, LongTimeFormat);
ShortTimeFormat:=_GetFormat(kCFDateFormatterNoStyle, kCFDateFormatterShortStyle, ShortTimeFormat);
fmt:=CFDateFormatterCreate(nil, loc, kCFDateFormatterNoStyle, kCFDateFormatterNoStyle);
if fmt<>nil then
begin
for i:=1 to 12 do
begin
LongMonthNames[i]:=_DateToStr(fmt, 'LLLL', 2006, i, 1, 0, LongMonthNames[i]);
ShortMonthNames[i]:=_DateToStr(fmt, 'LLL', 2006, i, 1, 0, ShortMonthNames[i]);
end;
for i:=1 to 7 do
begin
LongDayNames[i]:=_DateToStr(fmt, 'cccc', 2006, 1, i, 0, LongDayNames[i]);
ShortDayNames[i]:=_DateToStr(fmt, 'ccc', 2006, 1, i, 0, ShortDayNames[i]);
end;
TimeAMString:=_DateToStr(fmt, 'a', 2006, 1, 1, 1, TimeAMString);
TimePMString:=_DateToStr(fmt, 'a', 2006, 1, 1, 13, TimePMString);
CFRelease(fmt);
end;
CFRelease(loc);
end;
end;
initialization
GetMacFormatSettings(DefaultFormatSettings);
end.