iosxwstr.pp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 2015 by Jonas Maebe,
  4. member of the Free Pascal development team.
  5. CoreFoundation-based wide string support
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. {$mode objfpc}
  13. {$implicitexceptions off}
  14. unit iosxwstr;
  15. interface
  16. {$linkframework CoreFoundation}
  17. procedure SetCFWidestringManager;
  18. implementation
  19. uses
  20. unixcp,
  21. { for access to libiconv-based routines }
  22. cwstring,
  23. MacTypes,
  24. CFBase,CFString,CFStringEncodingExt,CFLocale;
  25. procedure fpc_rangeerror; [external name 'FPC_RANGEERROR'];
  26. var
  27. CWStringWideStringManager: TUnicodeStringManager;
  28. procedure InitThread;
  29. begin
  30. { we don't need anything special, but since we may use cwstring itself,
  31. call through to it }
  32. CWStringWideStringManager.ThreadInitProc;
  33. end;
  34. procedure FiniThread;
  35. begin
  36. { we don't need anything special, but since we may use cwstring itself,
  37. call through to it }
  38. CWStringWideStringManager.ThreadFiniProc;
  39. end;
  40. function get_cfencoding_for_cp(cp: TSystemCodePage): CFStringEncoding;
  41. var
  42. defscp: TSystemCodePage;
  43. begin
  44. { translate placeholder code pages }
  45. if (cp=CP_ACP) or
  46. (cp=CP_OEMCP) then
  47. cp:=DefaultSystemCodePage;
  48. result:=CFStringConvertWindowsCodepageToEncoding(cp);
  49. end;
  50. procedure GetAnsiDataFromCFString(str: CFstringRef; cfcp: CFStringEncoding; estimated_length: SizeInt; var dest: RawByteString);
  51. var
  52. range: CFRange;
  53. encodedlen,convertedchars: CFIndex;
  54. strlen: SizeInt;
  55. begin
  56. { first rough estimate for the length }
  57. setlength(dest,estimated_length);
  58. { try to convert }
  59. range.location:=0;
  60. strlen:=CFStringGetLength(str);
  61. range.length:=strlen;
  62. convertedchars:=CFStringGetBytes(str,range,cfcp,ByteParameter('?'),false,UInt8Ptr(dest),estimated_length,encodedlen);
  63. { failed -> bail out }
  64. if convertedchars<0 then
  65. begin
  66. CFRelease(str);
  67. runerror(231);
  68. end
  69. { if partially succesful, recreate with the required len }
  70. else if convertedchars<strlen then
  71. begin
  72. setlength(dest,encodedlen);
  73. { try again }
  74. convertedchars:=CFStringGetBytes(str,range,cfcp,ByteParameter('?'),false,UInt8Ptr(dest),encodedlen,encodedlen);
  75. { failed again ? }
  76. if convertedchars<>strlen then
  77. begin
  78. CFRelease(str);
  79. runerror(231);
  80. end;
  81. end;
  82. { truncate }
  83. setlength(dest,encodedlen);
  84. end;
  85. function CFStringCreateFromAnsiData(data: pchar; len: SizeInt; cp: TSystemCodePage): CFStringRef;
  86. var
  87. strlen,encodedlen: CFIndex;
  88. range: CFRange;
  89. cfcp: CFStringEncoding;
  90. begin
  91. result:=nil;
  92. { get source cf codepage }
  93. cfcp:=get_cfencoding_for_cp(cp);
  94. { unsupported encoding -> try libiconv instead }
  95. if cfcp=kCFStringEncodingInvalidId then
  96. exit;
  97. { make a cfstring from the original data }
  98. result:=CFStringCreateWithBytesNoCopy(nil,UnivPtr(data),len,cfcp,false,kCFAllocatorNull);
  99. end;
  100. function CFStringCreateFromAnsiDataOptionallyViaUnicodeString(data: pchar; len: SizeInt; cp: TSystemCodePage; out wtemp: UnicodeString): CFStringRef;
  101. begin
  102. result:=CFStringCreateFromAnsiData(data,len,cp);
  103. { failed -> translate via libiconv and then create using the unicodestring
  104. characters; since we use the no-copy constructor for performance
  105. reasons, the unicodestring has to survive this routine }
  106. if not assigned(result) then
  107. begin
  108. CWStringWideStringManager.Ansi2UnicodeMoveProc(data,cp,wtemp,len);
  109. result:=CFStringCreateWithCharactersNoCopy(nil,UniCharPtr(wtemp),len,kCFAllocatorNull);
  110. end;
  111. end;
  112. function CFStringCreateFromWideData(data: pwidechar; len: SizeInt): CFStringRef; inline;
  113. begin
  114. { make a cfstring from the utf-16 data }
  115. result:=CFStringCreateWithCharactersNoCopy(nil,UniCharPtr(data),len,kCFAllocatorNull);
  116. end;
  117. function CFStringCreateFromWideDataOptionallyViaUUTF8String(data: pwidechar; len: SizeInt; out temp: RawByteString): CFStringRef;
  118. begin
  119. result:=CFStringCreateFromWideData(data,len);
  120. { failed -> translate to UTF-8 via libiconv to filter out any
  121. potentially invalid characters and then create using the unicodestring
  122. characters; since we use the no-copy constructor for performance
  123. reasons, the unicodestring has to survive this routine }
  124. if not assigned(result) then
  125. begin
  126. CWStringWideStringManager.Unicode2AnsiMoveProc(data,temp,CP_UTF8,len);
  127. result:=CFStringCreateWithBytesNoCopy(nil,UnivPtr(temp),length(temp),kCFStringEncodingUTF8,false,kCFAllocatorNull);
  128. if not assigned(result) then
  129. runerror(231)
  130. end;
  131. end;
  132. procedure Wide2AnsiMove(source:pwidechar; var dest:RawByteString; cp:TSystemCodePage; len:SizeInt);
  133. var
  134. str: CFStringRef;
  135. strlen,estimatedlen: CFIndex;
  136. cfcp: CFStringEncoding;
  137. begin
  138. str:=nil;
  139. { get target cf codepage }
  140. cfcp:=get_cfencoding_for_cp(cp);
  141. { unsupported encoding -> default move }
  142. if cfcp<>kCFStringEncodingInvalidId then
  143. { make a cfstring from the utf-16 data }
  144. str:=CFStringCreateFromWideData(source,len);
  145. { You cannot create a CFString for a sequence that contains an error :/
  146. We want to replace the error positions with '?' -> fall back to libiconv
  147. }
  148. if not assigned(str) then
  149. begin
  150. CWStringWideStringManager.Unicode2AnsiMoveProc(source,dest,cp,len);
  151. exit;
  152. end;
  153. GetAnsiDataFromCFString(str,cfcp,len*3,dest);
  154. { set code page }
  155. SetCodePage(dest,cp,false);
  156. { release cfstring }
  157. CFRelease(str);
  158. end;
  159. procedure Ansi2WideMove(source:pchar; cp:TSystemCodePage; var dest:widestring; len:SizeInt);
  160. var
  161. str: CFStringRef;
  162. strlen,encodedlen: CFIndex;
  163. range: CFRange;
  164. cfcp: CFStringEncoding;
  165. begin
  166. str:=CFStringCreateFromAnsiData(source,len,cp);
  167. { You cannot create a CFString for a sequence that contains an error :/
  168. We want to replace the error positions with '?' -> fall back to libiconv
  169. }
  170. if not assigned(str) then
  171. begin
  172. CWStringWideStringManager.Ansi2UnicodeMoveProc(source,cp,dest,len);
  173. exit;
  174. end;
  175. { convert }
  176. range.location:=0;
  177. strlen:=CFStringGetLength(str);
  178. range.length:=strlen;
  179. setlength(dest,strlen);
  180. CFStringGetCharacters(str,range,UniCharPtr(dest));
  181. { release cfstring }
  182. CFRelease(str);
  183. end;
  184. function LowerWideString(const s : WideString) : WideString;
  185. var
  186. str: CFStringRef;
  187. mstr: CFMutableStringRef;
  188. range: CFRange;
  189. encodedlen: CFIndex;
  190. locale: CFLocaleRef;
  191. temp: RawByteString;
  192. begin
  193. { empty string -> exit }
  194. if s='' then
  195. begin
  196. result:='';
  197. exit;
  198. end;
  199. { create cfstring from the string data }
  200. str:=CFStringCreateFromWideDataOptionallyViaUUTF8String(pwidechar(s),length(s),temp);
  201. { convert to mutable cfstring }
  202. mstr:=CFStringCreateMutableCopy(nil,0,str);
  203. { lowercase }
  204. locale:=CFLocaleCopyCurrent;
  205. CFStringLowercase(mstr,locale);
  206. CFRelease(locale);
  207. { extract the data again }
  208. range.location:=0;
  209. range.length:=CFStringGetLength(CFStringRef(mstr));
  210. setlength(result,range.length);
  211. CFStringGetCharacters(mstr,range,UniCharPtr(result));
  212. CFRelease(mstr);
  213. CFRelease(str);
  214. end;
  215. function UpperWideString(const s : WideString) : WideString;
  216. var
  217. str: CFStringRef;
  218. mstr: CFMutableStringRef;
  219. range: CFRange;
  220. encodedlen: CFIndex;
  221. locale: CFLocaleRef;
  222. temp: RawByteString;
  223. begin
  224. { empty string -> exit }
  225. if s='' then
  226. begin
  227. result:='';
  228. exit;
  229. end;
  230. { create cfstring from the string data }
  231. str:=CFStringCreateFromWideDataOptionallyViaUUTF8String(pwidechar(s),length(s),temp);
  232. { convert to mutable cfstring }
  233. mstr:=CFStringCreateMutableCopy(nil,0,str);
  234. { lowercase }
  235. locale:=CFLocaleCopyCurrent;
  236. CFStringUppercase(mstr,locale);
  237. CFRelease(locale);
  238. { extract the data again }
  239. range.location:=0;
  240. range.length:=CFStringGetLength(CFStringRef(mstr));
  241. setlength(result,range.length);
  242. CFStringGetCharacters(mstr,range,UniCharPtr(result));
  243. CFRelease(mstr);
  244. CFRelease(str);
  245. end;
  246. function UpperLowerAnsiString(const s: AnsiString; upper: boolean): AnsiString;
  247. var
  248. str: CFStringRef;
  249. mstr: CFMutableStringRef;
  250. cfcp: CFStringEncoding;
  251. locale: CFLocaleRef;
  252. wtemp: UnicodeString;
  253. range: CFRange;
  254. begin
  255. if s='' then
  256. begin
  257. result:='';
  258. exit
  259. end;
  260. str:=CFStringCreateFromAnsiDataOptionallyViaUnicodeString(pchar(s),length(s),StringCodePage(s),wtemp);
  261. { unsupported encoding for either CF or iconv -> return original string }
  262. if not assigned(str) then
  263. begin
  264. result:=s;
  265. exit;
  266. end;
  267. { convert to mutable cfstring }
  268. mstr:=CFStringCreateMutableCopy(nil,0,str);
  269. CFRelease(str);
  270. { upper/lowercase }
  271. locale:=CFLocaleCopyCurrent;
  272. if upper then
  273. CFStringUppercase(mstr,locale)
  274. else
  275. CFStringLowercase(mstr,locale);
  276. CFRelease(locale);
  277. { convert back to ansistring }
  278. cfcp:=get_cfencoding_for_cp(StringCodePage(s));
  279. if cfcp<>kCFStringEncodingInvalidId then
  280. begin
  281. GetAnsiDataFromCFString(CFStringRef(mstr),cfcp,length(s),RawByteString(result));
  282. SetCodePage(RawByteString(result),StringCodePage(s),false);
  283. end
  284. else
  285. begin
  286. { unsupported encoding -> use libiconv instead via UTF-16
  287. intermediate }
  288. range.location:=0;
  289. range.length:=CFStringGetLength(mstr);
  290. SetLength(wtemp,range.length);
  291. CFStringGetCharacters(mstr,range,UniCharPtr(wtemp));
  292. CWStringWideStringManager.Wide2AnsiMoveProc(pwidechar(wtemp),RawByteString(result),StringCodePage(s),range.length);
  293. end;
  294. CFRelease(mstr);
  295. end;
  296. function LowerAnsiString(const s: AnsiString): AnsiString;
  297. begin
  298. result:=UpperLowerAnsiString(s,false);
  299. end;
  300. function UpperAnsiString(const s: AnsiString): AnsiString;
  301. begin
  302. result:=UpperLowerAnsiString(s,true);
  303. end;
  304. function CompareCFStrings(const s1, s2: CFStringRef; case_insensitive: boolean): longint;
  305. var
  306. flags: CFStringCompareFlags;
  307. begin
  308. flags:=0;
  309. if case_insensitive then
  310. flags:=flags or kCFCompareCaseInsensitive;
  311. result:=CFStringCompare(s1,s2,flags)
  312. end;
  313. function CompareWideString(const s1, s2 : WideString) : PtrInt;
  314. var
  315. cfstr1, cfstr2: CFStringRef;
  316. temp1, temp2: RawByteString;
  317. begin
  318. cfstr1:=CFStringCreateFromWideDataOptionallyViaUUTF8String(pwidechar(s1),length(s1),temp1);
  319. cfstr2:=CFStringCreateFromWideDataOptionallyViaUUTF8String(pwidechar(s2),length(s2),temp2);
  320. result:=CompareCFStrings(cfstr1,cfstr2,false);
  321. CFRelease(cfstr1);
  322. CFRelease(cfstr2);
  323. end;
  324. function CompareTextWideString(const s1, s2 : WideString): PtrInt;
  325. var
  326. cfstr1, cfstr2: CFStringRef;
  327. temp1, temp2: RawByteString;
  328. begin
  329. cfstr1:=CFStringCreateFromWideDataOptionallyViaUUTF8String(pwidechar(s1),length(s1),temp1);
  330. cfstr2:=CFStringCreateFromWideDataOptionallyViaUUTF8String(pwidechar(s2),length(s2),temp2);
  331. result:=CompareCFStrings(cfstr1,cfstr2,true);
  332. CFRelease(cfstr1);
  333. CFRelease(cfstr2);
  334. end;
  335. function InternalCodePointLength(const Str: PChar; cfcp: CFStringEncoding; maxlookahead: ptrint): PtrInt;
  336. var
  337. cfstr: CFStringRef;
  338. begin
  339. result:=0;
  340. { try creating a string with the first 1, 2, ... bytes until we find a
  341. valid one }
  342. while (str[result]<>#0) and
  343. (result<maxlookahead) do
  344. begin
  345. inc(result);
  346. cfstr:=CFStringCreateWithBytesNoCopy(nil,UnivPtr(Str),result,cfcp,false,kCFAllocatorNull);
  347. if assigned(cfstr) then
  348. begin
  349. CFRelease(cfstr);
  350. exit;
  351. end;
  352. end;
  353. result:=-1;
  354. end;
  355. function CharLengthPChar(const Str: PChar): PtrInt;
  356. var
  357. cfstr: CFStringRef;
  358. cfcp: CFStringEncoding;
  359. s: PChar;
  360. tmplen: PtrInt;
  361. begin
  362. result:=0;
  363. if str[0]=#0 then
  364. exit;
  365. cfcp:=get_cfencoding_for_cp(DefaultSystemCodePage);
  366. if cfcp=kCFStringEncodingInvalidId then
  367. begin
  368. { or -1? }
  369. result:=strlen(Str);
  370. exit
  371. end;
  372. s:=str;
  373. repeat
  374. tmplen:=InternalCodePointLength(s,cfcp,8);
  375. { invalid -> skip }
  376. if tmplen=-1 then
  377. tmplen:=1;
  378. inc(s,tmplen);
  379. inc(result);
  380. until s[0]=#0;
  381. end;
  382. function CodePointLength(const Str: PChar; maxlookahead: ptrint): PtrInt;
  383. var
  384. cfstr: CFStringRef;
  385. cfcp: CFStringEncoding;
  386. begin
  387. result:=0;
  388. if str[0]=#0 then
  389. exit;
  390. cfcp:=get_cfencoding_for_cp(DefaultSystemCodePage);
  391. if cfcp=kCFStringEncodingInvalidId then
  392. begin
  393. { if we would return -1, then the caller would keep trying with
  394. longer and longer sequences, but that wouldn't change anything }
  395. result:=1;
  396. exit
  397. end;
  398. result:=InternalCodePointLength(str,cfcp,maxlookahead);
  399. end;
  400. function CompareStrAnsiString(const s1, s2: ansistring): PtrInt;
  401. var
  402. cfstr1, cfstr2: CFStringRef;
  403. wtemp1, wtemp2: UnicodeString;
  404. begin
  405. cfstr1:=CFStringCreateFromAnsiDataOptionallyViaUnicodeString(pchar(s1),length(s1),StringCodePage(s1),wtemp1);
  406. cfstr2:=CFStringCreateFromAnsiDataOptionallyViaUnicodeString(pchar(s2),length(s2),StringCodePage(s2),wtemp2);
  407. result:=CompareCFStrings(cfstr1,cfstr2,false);
  408. CFRelease(cfstr1);
  409. CFRelease(cfstr2);
  410. end;
  411. function StrCompAnsi(s1,s2 : PChar): PtrInt;
  412. var
  413. cfstr1, cfstr2: CFStringRef;
  414. wtemp1, wtemp2: UnicodeString;
  415. begin
  416. cfstr1:=CFStringCreateFromAnsiDataOptionallyViaUnicodeString(s1,strlen(s1),DefaultSystemCodePage,wtemp1);
  417. cfstr2:=CFStringCreateFromAnsiDataOptionallyViaUnicodeString(s2,strlen(s2),DefaultSystemCodePage,wtemp2);
  418. result:=CompareCFStrings(cfstr1,cfstr2,false);
  419. CFRelease(cfstr1);
  420. CFRelease(cfstr2);
  421. end;
  422. function AnsiCompareText(const S1, S2: ansistring): PtrInt;
  423. var
  424. cfstr1, cfstr2: CFStringRef;
  425. wtemp1, wtemp2: UnicodeString;
  426. begin
  427. cfstr1:=CFStringCreateFromAnsiDataOptionallyViaUnicodeString(pchar(s1),length(s1),DefaultSystemCodePage,wtemp1);
  428. cfstr2:=CFStringCreateFromAnsiDataOptionallyViaUnicodeString(pchar(s2),length(s2),DefaultSystemCodePage,wtemp2);
  429. result:=CompareCFStrings(cfstr1,cfstr2,true);
  430. CFRelease(cfstr1);
  431. CFRelease(cfstr2);
  432. end;
  433. function AnsiStrIComp(S1, S2: PChar): PtrInt;
  434. var
  435. cfstr1, cfstr2: CFStringRef;
  436. wtemp1, wtemp2: UnicodeString;
  437. begin
  438. cfstr1:=CFStringCreateFromAnsiDataOptionallyViaUnicodeString(s1,strlen(s1),DefaultSystemCodePage,wtemp1);
  439. cfstr2:=CFStringCreateFromAnsiDataOptionallyViaUnicodeString(s2,strlen(s2),DefaultSystemCodePage,wtemp2);
  440. result:=CompareCFStrings(cfstr1,cfstr2,true);
  441. CFRelease(cfstr1);
  442. CFRelease(cfstr2);
  443. end;
  444. function AnsiStrLComp(S1, S2: PChar; MaxLen: PtrUInt): PtrInt;
  445. var
  446. cfstr1, cfstr2: CFStringRef;
  447. wtemp1, wtemp2: UnicodeString;
  448. begin
  449. cfstr1:=CFStringCreateFromAnsiDataOptionallyViaUnicodeString(s1,MaxLen,StringCodePage(s1),wtemp1);
  450. cfstr2:=CFStringCreateFromAnsiDataOptionallyViaUnicodeString(s2,MaxLen,StringCodePage(s2),wtemp2);
  451. result:=CompareCFStrings(cfstr1,cfstr2,false);
  452. CFRelease(cfstr1);
  453. CFRelease(cfstr2);
  454. end;
  455. function AnsiStrLIComp(S1, S2: PChar; MaxLen: PtrUInt): PtrInt;
  456. var
  457. cfstr1, cfstr2: CFStringRef;
  458. wtemp1, wtemp2: UnicodeString;
  459. begin
  460. cfstr1:=CFStringCreateFromAnsiDataOptionallyViaUnicodeString(s1,MaxLen,StringCodePage(s1),wtemp1);
  461. cfstr2:=CFStringCreateFromAnsiDataOptionallyViaUnicodeString(s2,MaxLen,StringCodePage(s2),wtemp2);
  462. result:=CompareCFStrings(cfstr1,cfstr2,true);
  463. CFRelease(cfstr1);
  464. CFRelease(cfstr2);
  465. end;
  466. procedure ansi2pchar(const s: ansistring; const orgp: pchar; out p: pchar);
  467. var
  468. newlen: sizeint;
  469. begin
  470. newlen:=length(s);
  471. if newlen>strlen(orgp) then
  472. fpc_rangeerror;
  473. p:=orgp;
  474. if (newlen>0) then
  475. move(s[1],p[0],newlen);
  476. p[newlen]:=#0;
  477. end;
  478. function AnsiStrLower(Str: PChar): PChar;
  479. var
  480. temp: ansistring;
  481. begin
  482. temp:=loweransistring(str);
  483. ansi2pchar(temp,str,result);
  484. end;
  485. function AnsiStrUpper(Str: PChar): PChar;
  486. var
  487. temp: ansistring;
  488. begin
  489. temp:=upperansistring(str);
  490. ansi2pchar(temp,str,result);
  491. end;
  492. function GetStandardCodePage(const stdcp: TStandardCodePageEnum): TSystemCodePage;
  493. var
  494. langinfo: pchar;
  495. begin
  496. { don't use CFStringGetSystemEncoding, that one returns MacRoman on e.g.
  497. an English system, which is definitely not what we want. Since there are
  498. no "ansi" interfaces on OS X and all APIs support all characters, always
  499. use UTF-8. Additionally,  Darwin always uses UTF-8 for file system
  500. operations }
  501. result:=CP_UTF8;
  502. end;
  503. procedure SetStdIOCodePage(var T: Text); inline;
  504. begin
  505. case TextRec(T).Mode of
  506. fmInput:TextRec(T).CodePage:=GetStandardCodePage(scpConsoleInput);
  507. fmOutput:TextRec(T).CodePage:=GetStandardCodePage(scpConsoleOutput);
  508. end;
  509. end;
  510. procedure SetStdIOCodePages; inline;
  511. begin
  512. SetStdIOCodePage(Input);
  513. SetStdIOCodePage(Output);
  514. SetStdIOCodePage(ErrOutput);
  515. SetStdIOCodePage(StdOut);
  516. SetStdIOCodePage(StdErr);
  517. end;
  518. procedure SetCFWideStringManager;
  519. var
  520. CFWideStringManager : TUnicodeStringManager;
  521. begin
  522. GetUnicodeStringManager(CWStringWideStringManager);
  523. CFWideStringManager:=CWStringWideStringManager;
  524. with CFWideStringManager do
  525. begin
  526. Wide2AnsiMoveProc:=@Wide2AnsiMove;
  527. Ansi2WideMoveProc:=@Ansi2WideMove;
  528. UpperWideStringProc:=@UpperWideString;
  529. LowerWideStringProc:=@LowerWideString;
  530. CompareWideStringProc:=@CompareWideString;
  531. CompareTextWideStringProc:=@CompareTextWideString;
  532. CharLengthPCharProc:=@CharLengthPChar;
  533. CodePointLengthProc:=@CodePointLength;
  534. UpperAnsiStringProc:=@UpperAnsiString;
  535. LowerAnsiStringProc:=@LowerAnsiString;
  536. CompareStrAnsiStringProc:=@CompareStrAnsiString;
  537. CompareTextAnsiStringProc:=@AnsiCompareText;
  538. StrCompAnsiStringProc:=@StrCompAnsi;
  539. StrICompAnsiStringProc:=@AnsiStrIComp;
  540. StrLCompAnsiStringProc:=@AnsiStrLComp;
  541. StrLICompAnsiStringProc:=@AnsiStrLIComp;
  542. StrLowerAnsiStringProc:=@AnsiStrLower;
  543. StrUpperAnsiStringProc:=@AnsiStrUpper;
  544. ThreadInitProc:=@InitThread;
  545. ThreadFiniProc:=@FiniThread;
  546. { Unicode }
  547. Unicode2AnsiMoveProc:=@Wide2AnsiMove;
  548. Ansi2UnicodeMoveProc:=@Ansi2WideMove;
  549. UpperUnicodeStringProc:=@UpperWideString;
  550. LowerUnicodeStringProc:=@LowerWideString;
  551. CompareUnicodeStringProc:=@CompareWideString;
  552. CompareTextUnicodeStringProc:=@CompareTextWideString;
  553. { CodePage }
  554. GetStandardCodePageProc:=@GetStandardCodePage;
  555. end;
  556. SetUnicodeStringManager(CFWideStringManager);
  557. end;
  558. initialization
  559. SetCFWideStringManager;
  560. { set the DefaultSystemCodePage }
  561. DefaultSystemCodePage:=GetStandardCodePage(scpAnsi);
  562. DefaultFileSystemCodePage:=GetStandardCodePage(scpFileSystemSingleByte);
  563. DefaultRTLFileSystemCodePage:=DefaultFileSystemCodePage;
  564. SetStdIOCodePages;
  565. { don't call init, we don't need to do anything and the cwstring routine we
  566. call through has already been called from the init code of cwstring itself
  567. InitThread;
  568. }
  569. finalization
  570. { don't call for the same reason as not calling FiniThread
  571. FiniThread;
  572. }
  573. { restore previous widestring manager so that subsequent calls
  574. into the widestring manager won't trigger the finalized functionality }
  575. SetWideStringManager(CWStringWideStringManager);
  576. end.