iosxlocale.pp 9.0 KB

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