iosxlocale.pp 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. {
  2. This file is part of the Free Pascal packages library.
  3. Copyright (c) 2013 by Yury Sidorov, member of the
  4. Free Pascal development team
  5. This unit is used to get format settings of the current
  6. Mac OS UI locale. Works on Mac OS X 10.3 or later.
  7. Function CFStringToStr() has been taken from CarbonProc LCL unit.
  8. See the file COPYING.FPC, included in this distribution,
  9. for details about the copyright.
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  13. **********************************************************************}
  14. {$IFNDEF FPC_DOTTEDUNITS}
  15. unit iosxlocale;
  16. {$ENDIF FPC_DOTTEDUNITS}
  17. {$mode objfpc}{$H+}
  18. interface
  19. {$IFDEF FPC_DOTTEDUNITS}
  20. uses
  21. System.SysUtils, MacOsApi.MacOSAll;
  22. {$ELSE FPC_DOTTEDUNITS}
  23. uses
  24. SysUtils, MacOSAll;
  25. {$ENDIF FPC_DOTTEDUNITS}
  26. procedure GetMacFormatSettings(var ASettings: TFormatSettings);
  27. implementation
  28. {------------------------------------------------------------------------------
  29. Name: CFStringToStr
  30. Params: AString - Core Foundation string ref
  31. Encoding - Result data encoding format
  32. Returns: UTF-8 string
  33. Converts Core Foundation string to string
  34. ------------------------------------------------------------------------------}
  35. function CFStringToStr(AString: CFStringRef): UTF8String;
  36. var
  37. Str: Pointer;
  38. StrSize: CFIndex;
  39. StrRange: CFRange;
  40. begin
  41. if AString=nil then
  42. begin
  43. Result:='';
  44. Exit;
  45. end;
  46. // Try the quick way first
  47. Str:=CFStringGetCStringPtr(AString, kCFStringEncodingUTF8);
  48. if Str<>nil then
  49. Result:=PAnsiChar(Str)
  50. else
  51. begin
  52. // if that doesn't work this will
  53. StrRange.location:=0;
  54. StrRange.length:=CFStringGetLength(AString);
  55. CFStringGetBytes(AString, StrRange, kCFStringEncodingUTF8,
  56. Ord('?'), False, nil, 0, StrSize{%H-});
  57. SetLength(Result, StrSize);
  58. if StrSize>0 then
  59. CFStringGetBytes(AString, StrRange, kCFStringEncodingUTF8,
  60. Ord('?'), False, @Result[1], StrSize, StrSize);
  61. end;
  62. end;
  63. function StrOfChar(c: AnsiChar; Count: integer): utf8string;
  64. begin
  65. SetLength(Result, Count);
  66. FillChar(PAnsiChar(Result)^, Count, c);
  67. end;
  68. function ConvertFormatStr(const fmt: utf8string): utf8string;
  69. var
  70. cnt: integer;
  71. c, q: AnsiChar;
  72. p: PAnsiChar;
  73. s: utf8string;
  74. begin
  75. Result:='';
  76. q:=#0;
  77. cnt:=1;
  78. p:=PAnsiChar(fmt);
  79. while p^<>#0 do
  80. begin
  81. s:='';
  82. c:=p^;
  83. if c in ['''', '"'] then
  84. begin
  85. if q=#0 then
  86. q:=c
  87. else
  88. if c=q then
  89. begin
  90. q:=#0;
  91. cnt:=1;
  92. end;
  93. s:=c;
  94. end
  95. else if q <> #0 then
  96. s:=c
  97. else
  98. begin
  99. if (p+1)^=c then
  100. Inc(cnt)
  101. else
  102. begin
  103. case c of
  104. 'y', 'Y':
  105. begin
  106. c:='y';
  107. if cnt > 2 then
  108. cnt:=4
  109. else
  110. cnt:=2;
  111. end;
  112. 'M', 'L':
  113. begin
  114. c:='m';
  115. if cnt > 4 then
  116. cnt:=3;
  117. end;
  118. 'd':
  119. if cnt > 2 then
  120. cnt:=2;
  121. 'E', 'e', 'c':
  122. begin
  123. c:='d';
  124. if (cnt < 3) or (cnt > 4) then
  125. cnt:=3;
  126. end;
  127. 'a':
  128. begin
  129. cnt:=0;
  130. s:='ampm';
  131. end;
  132. 'h', 'H', 'k', 'K':
  133. begin
  134. c:='h';
  135. if cnt > 2 then
  136. cnt:=2;
  137. end;
  138. 'm':
  139. begin
  140. c:='n';
  141. if cnt>2 then
  142. cnt:=2;
  143. end;
  144. 's':
  145. if cnt>2 then
  146. cnt:=2;
  147. 'S':
  148. begin
  149. c:='z';
  150. cnt:=1;
  151. end;
  152. 'G','u','Q','q','w','W','D','F','g','A','z','Z','v':
  153. cnt:=0;
  154. end;
  155. if cnt>0 then
  156. s:=StrOfChar(c, cnt);
  157. cnt:=1;
  158. end;
  159. end;
  160. Inc(p);
  161. if s<>'' then
  162. Result:=Result+s;
  163. end;
  164. end;
  165. procedure GetMacFormatSettings(var ASettings: TFormatSettings);
  166. var
  167. loc: CFLocaleRef;
  168. function _GetFormat(dateStyle: CFDateFormatterStyle; timeStyle: CFDateFormatterStyle; const DefFormat: utf8string): utf8string;
  169. var
  170. fmt: CFDateFormatterRef;
  171. begin
  172. Result:='';
  173. fmt:=CFDateFormatterCreate(nil, loc, dateStyle, timeStyle);
  174. if fmt <> nil then
  175. begin
  176. Result:=ConvertFormatStr(CFStringToStr(CFDateFormatterGetFormat(fmt)));
  177. CFRelease(fmt);
  178. end;
  179. if Result = '' then
  180. Result:=DefFormat;
  181. end;
  182. function _DateToStr(fmt: CFDateFormatterRef; const AFormat: utf8string; AYear: integer; AMonth, ADay, AHour: byte;
  183. const ADefault: utf8string): utf8string;
  184. var
  185. cs: CFStringRef;
  186. gd: CFGregorianDate;
  187. at: CFAbsoluteTime;
  188. tz: CFTimeZoneRef;
  189. begin
  190. cs:=CFStringCreateWithCString(nil, Pointer(PAnsiChar(AFormat)), kCFStringEncodingUTF8);
  191. CFDateFormatterSetFormat(fmt, cs);
  192. CFRelease(cs);
  193. FillChar(gd, SIzeOf(gd), 0);
  194. gd.year:=AYear;
  195. gd.month:=AMonth;
  196. gd.day:=ADay;
  197. gd.hour:=AHour;
  198. tz:=CFTimeZoneCopyDefault;
  199. at:=CFGregorianDateGetAbsoluteTime(gd, tz);
  200. CFRelease(tz);
  201. cs:=CFDateFormatterCreateStringWithAbsoluteTime(nil, fmt, at);
  202. Result:=CFStringToStr(cs);
  203. CFRelease(cs);
  204. if Result = '' then
  205. Result:=ADefault;
  206. end;
  207. function _GetSeparator(dateStyle: CFDateFormatterStyle; timeStyle: CFDateFormatterStyle; DefSep: AnsiChar): AnsiChar;
  208. var
  209. fmt: CFDateFormatterRef;
  210. s: utf8string;
  211. p: PAnsiChar;
  212. begin
  213. Result:=DefSep;
  214. fmt:=CFDateFormatterCreate(nil, loc, dateStyle, timeStyle);
  215. if fmt <> nil then
  216. begin
  217. s:=_DateToStr(fmt, CFStringToStr(CFDateFormatterGetFormat(fmt)), 2000, 1, 1, 0, DefSep);
  218. s:=Trim(s);
  219. p:=PAnsiChar(s);
  220. while p^<>#0 do
  221. if (p^>' ') and (p^<'A') and not (p^ in ['0'..'9']) then
  222. begin
  223. Result:=p^;
  224. break;
  225. end
  226. else
  227. Inc(p);
  228. CFRelease(fmt);
  229. end;
  230. end;
  231. var
  232. s: utf8string;
  233. fmt: CFDateFormatterRef;
  234. i: integer;
  235. begin
  236. with ASettings do
  237. begin
  238. loc:=CFLocaleCopyCurrent;
  239. if loc=nil then
  240. exit;
  241. s:=CFStringToStr(CFLocaleGetValue(loc, kCFLocaleDecimalSeparator));
  242. if Length(s)=1 then
  243. DecimalSeparator:=s[1];
  244. s:=CFStringToStr(CFLocaleGetValue(loc, kCFLocaleGroupingSeparator));
  245. if Length(s)=1 then
  246. ThousandSeparator:=s[1]
  247. else
  248. ThousandSeparator:=' '; // Unicode AnsiChar has been returned. Probably it is a whitespace
  249. CurrencyString:=CFStringToStr(CFLocaleGetValue(loc, kCFLocaleCurrencySymbol));
  250. DateSeparator:=_GetSeparator(kCFDateFormatterShortStyle, kCFDateFormatterNoStyle, DateSeparator);
  251. TimeSeparator:=_GetSeparator(kCFDateFormatterNoStyle, kCFDateFormatterShortStyle, TimeSeparator);
  252. LongDateFormat:=_GetFormat(kCFDateFormatterLongStyle, kCFDateFormatterNoStyle, LongDateFormat);
  253. ShortDateFormat:=_GetFormat(kCFDateFormatterShortStyle, kCFDateFormatterNoStyle, ShortDateFormat);
  254. LongTimeFormat:=_GetFormat(kCFDateFormatterNoStyle, kCFDateFormatterLongStyle, LongTimeFormat);
  255. ShortTimeFormat:=_GetFormat(kCFDateFormatterNoStyle, kCFDateFormatterShortStyle, ShortTimeFormat);
  256. fmt:=CFDateFormatterCreate(nil, loc, kCFDateFormatterNoStyle, kCFDateFormatterNoStyle);
  257. if fmt<>nil then
  258. begin
  259. for i:=1 to 12 do
  260. begin
  261. LongMonthNames[i]:=_DateToStr(fmt, 'LLLL', 2006, i, 1, 0, LongMonthNames[i]);
  262. ShortMonthNames[i]:=_DateToStr(fmt, 'LLL', 2006, i, 1, 0, ShortMonthNames[i]);
  263. end;
  264. for i:=1 to 7 do
  265. begin
  266. LongDayNames[i]:=_DateToStr(fmt, 'cccc', 2006, 1, i, 0, LongDayNames[i]);
  267. ShortDayNames[i]:=_DateToStr(fmt, 'ccc', 2006, 1, i, 0, ShortDayNames[i]);
  268. end;
  269. TimeAMString:=_DateToStr(fmt, 'a', 2006, 1, 1, 1, TimeAMString);
  270. TimePMString:=_DateToStr(fmt, 'a', 2006, 1, 1, 13, TimePMString);
  271. CFRelease(fmt);
  272. end;
  273. CFRelease(loc);
  274. end;
  275. end;
  276. initialization
  277. GetMacFormatSettings(DefaultFormatSettings);
  278. end.