sysucode.inc 50 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 2014-2015 by Tomas Hajny and other members
  4. of the Free Pascal development team.
  5. OS/2 UnicodeStrings 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. (* The implementation is based on native Unicode support available under
  13. OS/2 Warp 4 and above; if running under OS/2 Warp 3 and UCONV.DLL
  14. library is not available, this implementation will resort to dummy
  15. routines. This still allows providing 3rd party implementation based
  16. e.g. on the ICONV library as an external unit.
  17. *)
  18. const
  19. MaxSpecialCPTranslation = 2;
  20. MaxNonEqualCPMapping = 35;
  21. MaxCPMapping = 76;
  22. CpxAll = 0;
  23. CpxSpecial = 1;
  24. CpxMappingOnly = 2;
  25. Uls_Success = 0;
  26. Uls_API_Error_Base = $20400;
  27. Uls_Other = $20401;
  28. Uls_IllegalSequence = $20402;
  29. Uls_MaxFilesPerProc = $20403;
  30. Uls_MaxFiles = $20404;
  31. Uls_NoOp = $20405;
  32. Uls_TooManyKbd = $20406;
  33. Uls_KbdNotFound = $20407;
  34. Uls_BadHandle = $204008;
  35. Uls_NoDead = $20409;
  36. Uls_NoScan = $2040A;
  37. Uls_InvalidScan = $2040B;
  38. Uls_NotImplemented = $2040C;
  39. Uls_NoMemory = $2040D;
  40. Uls_Invalid = $2040E;
  41. Uls_BadObject = $2040F;
  42. Uls_NoToken = $20410;
  43. Uls_NoMatch = $20411;
  44. Uls_BufferFull = $20412;
  45. Uls_Range = $20413;
  46. Uls_Unsupported = $20414;
  47. Uls_BadAttr = $20415;
  48. Uls_Version = $20416;
  49. UConvName: array [0..5] of char = 'UCONV'#0;
  50. OrdUniCreateUconvObject = 1;
  51. OrdUniUconvToUcs = 2;
  52. OrdUniUconvFromUcs = 3;
  53. OrdUniFreeUconvObject = 4;
  54. OrdUniQueryUconvObject = 7;
  55. OrdUniSetUconvObject = 8;
  56. OrdUniQueryUconvCp = 9;
  57. OrdUniMapCpToUcsCp = 10;
  58. OrdUniStrFromUcs = 11;
  59. OrdUniStrToUcs = 12;
  60. Ord_UniMalloc = 13;
  61. Ord_UniFree = 14;
  62. LibUniName: array [0..6] of char = 'LIBUNI'#0;
  63. OrdUniQueryXdigit = 1;
  64. OrdUniQuerySpace = 2;
  65. OrdUniQueryPrint = 3;
  66. OrdUniQueryGraph = 4;
  67. OrdUniQueryCntrl = 5;
  68. OrdUniQueryAlpha = 6;
  69. OrdUniFreeAttrObject = 7;
  70. OrdUniQueryCharAttr = 8;
  71. OrdUniQueryUpper = 9;
  72. OrdUniQueryPunct = 10;
  73. OrdUniQueryLower = 11;
  74. OrdUniQueryDigit = 12;
  75. OrdUniQueryBlank = 13;
  76. OrdUniQueryAlnum = 14;
  77. OrdUniScanForAttr = 15;
  78. OrdUniCreateAttrObject = 16;
  79. OrdUniCreateTransformObject = 17;
  80. OrdUniFreeTransformObject = 18;
  81. OrdUniQueryLocaleObject = 19;
  82. OrdUniCreateLocaleObject = 20;
  83. OrdUniFreeLocaleObject = 21;
  84. OrdUniFreeMem = 22;
  85. OrdUniFreeLocaleInfo = 28;
  86. OrdUniQueryLocaleInfo = 29;
  87. OrdUniQueryLocaleItem = 30;
  88. OrdUniStrcat = 31;
  89. OrdUniStrchr = 32;
  90. OrdUniStrcmp = 33;
  91. OrdUniStrcmpi = 34;
  92. OrdUniStrColl = 35;
  93. OrdUniStrcpy = 36;
  94. OrdUniStrcspn = 37;
  95. OrdUniStrfmon = 38;
  96. OrdUniStrftime = 39;
  97. OrdUniStrlen = 40;
  98. OrdUniStrncat = 41;
  99. OrdUniStrncmp = 42;
  100. OrdUniStrncmpi = 43;
  101. OrdUniStrncpy = 44;
  102. OrdUniStrpbrk = 45;
  103. OrdUniStrptime = 46;
  104. OrdUniStrrchr = 47;
  105. OrdUniStrspn = 48;
  106. OrdUniStrstr = 49;
  107. OrdUniStrtod = 50;
  108. OrdUniStrtol = 51;
  109. OrdUniStrtoul = 52;
  110. OrdUniStrxfrm = 53;
  111. OrdUniLocaleStrToToken = 54;
  112. OrdUniLocaleTokenToStr = 55;
  113. OrdUniTransformStr = 56;
  114. OrdUniTransLower = 57;
  115. OrdUniTransUpper = 58;
  116. OrdUniTolower = 59;
  117. OrdUniToupper = 60;
  118. OrdUniStrupr = 61;
  119. OrdUniStrlwr = 62;
  120. OrdUniStrtok = 63;
  121. OrdUniMapCtryToLocale = 67;
  122. OrdUniMakeKey = 70;
  123. OrdUniQueryChar = 71;
  124. OrdUniGetOverride = 72;
  125. OrdUniGetColval = 73;
  126. OrdUniQueryAttr = 74;
  127. OrdUniQueryStringType = 75;
  128. OrdUniQueryCharType = 76;
  129. OrdUniQueryNumericValue = 77;
  130. OrdUniQueryCharTypeTable = 78;
  131. OrdUniProcessUconv = 80;
  132. OrdLocale = 151;
  133. OrdUniMakeUserLocale = 152;
  134. OrdUniSetUserLocaleItem = 153;
  135. OrdUniDeleteUserLocale = 154;
  136. OrdUniCompleteUserLocale = 155;
  137. OrdUniQueryLocaleValue = 156;
  138. OrdUniQueryLocaleList = 157;
  139. OrdUniQueryLanguageName = 158;
  140. OrdUniQueryCountryName = 159;
  141. Uni_Token_Pointer = 1;
  142. Uni_MBS_String_Pointer = 2;
  143. Uni_UCS_String_Pointer = 3;
  144. Uni_System_Locales = 1;
  145. Uni_User_Locales = 2;
  146. WNull: WideChar = #0;
  147. WUniv: array [0..4] of WideChar = 'UNIV'#0;
  148. type
  149. (* CP_UTF16 should be in exceptions too, because OS/2 supports only UCS2 *)
  150. (* rather than UTF-16 - ignored at least for now. *)
  151. (* ExceptionWinCodepages = (CP_UTF16BE, CP_UTF7, 12000 {UTF32}, 12001 {UTF32BE});
  152. SpecialWinCodepages = (CP_UTF8, CP_ASCII);*)
  153. TCpRec = record
  154. WinCP: TSystemCodepage;
  155. OS2CP: word;
  156. UConvObj: TUConvObject;
  157. end;
  158. TCpXList = array [1..MaxCPMapping] of TCpRec;
  159. TDummyUConvObject = record
  160. CP: cardinal;
  161. CPNameLen: byte;
  162. CPName: record end;
  163. end;
  164. PDummyUConvObject = ^TDummyUConvObject;
  165. var
  166. DBCSLeadRanges: array [0..11] of char;
  167. CollationSequence: array [char] of char;
  168. const
  169. DefCpRec: TCpRec = (WinCP: 0; OS2CP: 0; UConvObj: nil);
  170. InInitDefaultCP: int64 = -1; (* Range is bigger than TThreadID to avoid conflict *)
  171. DefLocObj: TLocaleObject = nil;
  172. IBMPrefix: packed array [1..4] of WideChar = 'IBM-';
  173. CachedDefFSCodepage: TSystemCodepage = 0;
  174. EmptyCC: TCountryCode = (Country: 0; Codepage: 0); (* Empty = current *)
  175. (* 819 = IBM codepage number for ISO 8859-1 used in FPC default *)
  176. (* dummy translation between UnicodeString and AnsiString. *)
  177. IsoCC: TCountryCode = (Country: 1; Codepage: 819); (* Empty = current *)
  178. (* The following two arrays are initialized on startup in case that *)
  179. (* Dummy* routines must be used. First for current codepage... *)
  180. DBCSLeadRangesEnd: byte = 0;
  181. LowerChars: array [char] of char =
  182. (#0, #1, #2, #3, #4, #5, #6, #7, #8, #9, #10, #11, #12, #13, #14, #15, #16,
  183. #17, #18, #19, #20, #21, #22, #23, #24, #25, #26, #27, #28, #29, #30, #31,
  184. #32, #33, #34, #35, #36, #37, #38, #39, #40, #41, #42, #43, #44, #45, #46,
  185. #47, #48, #49, #50, #51, #52, #53, #54, #55, #56, #57, #58, #59, #60, #61,
  186. #62, #63, #64, #65, #66, #67, #68, #69, #70, #71, #72, #73, #74, #75, #76,
  187. #77, #78, #79, #80, #81, #82, #83, #84, #85, #86, #87, #88, #89, #90, #91,
  188. #92, #93, #94, #95, #96, #97, #98, #99, #100, #101, #102, #103, #104, #105,
  189. #106, #107, #108, #109, #110, #111, #112, #113, #114, #115, #116, #117,
  190. #118, #119, #120, #121, #122, #123, #124, #125, #126, #127, #128, #129,
  191. #130, #131, #132, #133, #134, #135, #136, #137, #138, #139, #140, #141,
  192. #142, #143, #144, #145, #146, #147, #148, #149, #150, #151, #152, #153,
  193. #154, #155, #156, #157, #158, #159, #160, #161, #162, #163, #164, #165,
  194. #166, #167, #168, #169, #170, #171, #172, #173, #174, #175, #176, #177,
  195. #178, #179, #180, #181, #182, #183, #184, #185, #186, #187, #188, #189,
  196. #190, #191, #192, #193, #194, #195, #196, #197, #198, #199, #200, #201,
  197. #202, #203, #204, #205, #206, #207, #208, #209, #210, #211, #212, #213,
  198. #214, #215, #216, #217, #218, #219, #220, #221, #222, #223, #224, #225,
  199. #226, #227, #228, #229, #230, #231, #232, #233, #234, #235, #236, #237,
  200. #238, #239, #240, #241, #242, #243, #244, #245, #246, #247, #248, #249,
  201. #250, #251, #252, #253, #254, #255);
  202. (* ...and now for ISO 8859-1 aka IBM codepage 819 *)
  203. LowerCharsISO88591: array [char] of char =
  204. (#0, #1, #2, #3, #4, #5, #6, #7, #8, #9, #10, #11, #12, #13, #14, #15, #16,
  205. #17, #18, #19, #20, #21, #22, #23, #24, #25, #26, #27, #28, #29, #30, #31,
  206. #32, #33, #34, #35, #36, #37, #38, #39, #40, #41, #42, #43, #44, #45, #46,
  207. #47, #48, #49, #50, #51, #52, #53, #54, #55, #56, #57, #58, #59, #60, #61,
  208. #62, #63, #64, #65, #66, #67, #68, #69, #70, #71, #72, #73, #74, #75, #76,
  209. #77, #78, #79, #80, #81, #82, #83, #84, #85, #86, #87, #88, #89, #90, #91,
  210. #92, #93, #94, #95, #96, #97, #98, #99, #100, #101, #102, #103, #104, #105,
  211. #106, #107, #108, #109, #110, #111, #112, #113, #114, #115, #116, #117,
  212. #118, #119, #120, #121, #122, #123, #124, #125, #126, #127, #128, #129,
  213. #130, #131, #132, #133, #134, #135, #136, #137, #138, #139, #140, #141,
  214. #142, #143, #144, #145, #146, #147, #148, #149, #150, #151, #152, #153,
  215. #154, #155, #156, #157, #158, #159, #160, #161, #162, #163, #164, #165,
  216. #166, #167, #168, #169, #170, #171, #172, #173, #174, #175, #176, #177,
  217. #178, #179, #180, #181, #182, #183, #184, #185, #186, #187, #188, #189,
  218. #190, #191, #192, #193, #194, #195, #196, #197, #198, #199, #200, #201,
  219. #202, #203, #204, #205, #206, #207, #208, #209, #210, #211, #212, #213,
  220. #214, #215, #216, #217, #218, #219, #220, #221, #222, #223, #224, #225,
  221. #226, #227, #228, #229, #230, #231, #232, #233, #234, #235, #236, #237,
  222. #238, #239, #240, #241, #242, #243, #244, #245, #246, #247, #248, #249,
  223. #250, #251, #252, #253, #254, #255);
  224. NoIso88591Support: boolean = false;
  225. threadvar
  226. (* Temporary allocations may be performed in parallel in different threads *)
  227. TempCpRec: TCpRec;
  228. function OS2GetStandardCodePage (const stdcp: TStandardCodePageEnum): TSystemCodePage;
  229. var
  230. RC, C, RetSize: cardinal;
  231. NoUConvObject: TUConvObject;
  232. begin
  233. RC := DosQueryCP (SizeOf (C), @C, RetSize);
  234. if (RC <> 0) and (RC <> 473) then
  235. begin
  236. OSErrorWatch (RC);
  237. C := 850;
  238. end
  239. else
  240. if RetSize < SizeOf (C) then
  241. C := 850;
  242. OS2GetStandardCodePage := OS2CpToRtlCp (C, cpxMappingOnly, NoUConvObject);
  243. end;
  244. function DummyUniCreateUConvObject (const CpName: PWideChar;
  245. var UConv_Object: TUConvObject): longint; cdecl;
  246. var
  247. P: pointer;
  248. PW, PCPN: PWideChar;
  249. S: string [20];
  250. C: cardinal;
  251. L: PtrInt;
  252. I: longint;
  253. A: array [0..7] of char;
  254. CPN2: UnicodeString;
  255. RC, RetSize: cardinal;
  256. begin
  257. UConv_Object := nil;
  258. if (CpName = nil) or (CpName^ = #0) then
  259. begin
  260. RC := DosQueryCP (SizeOf (C), @C, RetSize);
  261. if (RC <> 0) and (RC <> 473) then
  262. begin
  263. C := 850;
  264. OSErrorWatch (RC);
  265. end;
  266. Str (C, CPN2); (* Str should hopefully not use this function recurrently *)
  267. L := Length (CPN2);
  268. Insert (IBMPrefix, CPN2, 1);
  269. PCPN := @CPN2 [1];
  270. end
  271. else
  272. begin
  273. PCPN := CpName;
  274. for I := 0 to 7 do
  275. if I mod 2 = 0 then
  276. A [I] := UpCase (PChar (@PCPN [0]) [I])
  277. else
  278. A [I] := PChar (@PCPN [0]) [I];
  279. if PQWord (@A)^ <> PQWord (@IBMPrefix)^ then
  280. begin
  281. DummyUniCreateUConvObject := Uls_Invalid;
  282. Exit;
  283. end;
  284. L := 0;
  285. PW := PCPN + 4;
  286. while ((PW + L)^ <> #0) and (L <= SizeOf (S)) do
  287. begin
  288. S [Succ (L)] := char (Ord ((PW + L)^));
  289. Inc (L);
  290. end;
  291. if L > SizeOf (S) then
  292. begin
  293. DummyUniCreateUConvObject := Uls_Other;
  294. Exit;
  295. end;
  296. SetLength (S, L);
  297. Val (S, C, I);
  298. if I <> 0 then
  299. begin
  300. DummyUniCreateUConvObject := Uls_Invalid;
  301. Exit;
  302. end;
  303. end;
  304. Inc (L);
  305. GetMem (P, SizeOf (TDummyUConvObject) + (L + 4) * 2);
  306. if P = nil then
  307. DummyUniCreateUConvObject := Uls_NoMemory
  308. else
  309. begin
  310. DummyUniCreateUConvObject := Uls_Success;
  311. PDummyUConvObject (P)^.CP := C;
  312. PDummyUConvObject (P)^.CpNameLen := Pred (L) + 4;
  313. Move (PCPN [0], PDummyUConvObject (P)^.CpName, (L + 4) * 2);
  314. UConv_Object := TUConvObject (P);
  315. end;
  316. end;
  317. function DummyUniFreeUConvObject (UConv_Object: TUConvObject): longint; cdecl;
  318. begin
  319. if UConv_Object <> nil then
  320. FreeMem (UConv_Object, SizeOf (TDummyUConvObject) +
  321. Succ (PDummyUConvObject (UConv_Object)^.CpNameLen) * 2);
  322. DummyUniFreeUConvObject := Uls_Success;
  323. end;
  324. function DummyUniMapCpToUcsCp (const Codepage: cardinal;
  325. CodepageName: PWideChar; const N: cardinal): longint; cdecl;
  326. var
  327. S: UnicodeString;
  328. RC, CP, RetSize: cardinal;
  329. begin
  330. if Codepage = 0 then
  331. begin
  332. RC := DosQueryCP (SizeOf (CP), @CP, RetSize);
  333. if (RC <> 0) and (RC <> 473) then
  334. begin
  335. CP := 850;
  336. OSErrorWatch (RC);
  337. end;
  338. Str (CP, S);
  339. end
  340. else
  341. Str (Codepage, S);
  342. if (N <= Length (S) + 4) or (CodepageName = nil) then
  343. DummyUniMapCptoUcsCp := Uls_Invalid
  344. else
  345. begin
  346. Move (IBMPrefix, CodepageName^, SizeOf (IBMPrefix));
  347. Move (S [1], CodepageName [4], Length (S) * SizeOf (WideChar));
  348. CodepageName [Length (S) + 4] := #0;
  349. DummyUniMapCpToUcsCp := Uls_Success;
  350. end;
  351. end;
  352. function DummyUniUConvFromUcs (UConv_Object: TUConvObject;
  353. var UcsBuf: PWideChar; var UniCharsLeft: longint; var OutBuf: PChar;
  354. var OutBytesLeft: longint; var NonIdentical: longint): longint; cdecl;
  355. var
  356. Dest, Dest2: RawByteString;
  357. NoUConvObj: TUConvObject;
  358. RtlCp: TSystemCodepage;
  359. UcsLen: PtrInt;
  360. begin
  361. if UConv_Object = nil then
  362. RtlCp := OS2GetStandardCodePage (scpAnsi)
  363. else
  364. RtlCp := OS2CpToRtlCp (PDummyUConvObject (UConv_Object)^.CP, cpxMappingOnly,
  365. NoUConvObj);
  366. DefaultUnicode2AnsiMove (UcsBuf, Dest, RtlCp, UniCharsLeft);
  367. NonIdentical := 1; { Assume at least one substitution with dummy implementation }
  368. if Length (Dest) > OutBytesLeft then
  369. begin
  370. UcsLen := 1;
  371. repeat
  372. DefaultUnicode2AnsiMove (UcsBuf, Dest2, RtlCp, UcsLen);
  373. if Length (Dest2) <= OutBytesLeft then
  374. begin
  375. Dest := Dest2;
  376. end;
  377. Inc (UcsLen);
  378. until Length (Dest2) > OutBytesLeft;
  379. Dec (UcsLen);
  380. Inc (UcsBuf, UcsLen);
  381. Dec (UniCharsLeft, UcsLen);
  382. DummyUniUConvFromUcs := Uls_BufferFull;
  383. end
  384. else
  385. begin
  386. Inc (UcsBuf, UniCharsLeft);
  387. UniCharsLeft := 0;
  388. DummyUniUConvFromUcs := Uls_Success;
  389. end;
  390. Move (Dest [1], OutBuf^, Length (Dest));
  391. Inc (OutBuf, Length (Dest));
  392. Dec (OutBytesLeft, Length (Dest));
  393. end;
  394. function DummyUniUConvToUcs (UConv_Object: TUConvObject; var InBuf: PChar;
  395. var InBytesLeft: longint; var UcsBuf: PWideChar; var UniCharsLeft: longint;
  396. var NonIdentical: longint): longint; cdecl;
  397. var
  398. Dest, Dest2: UnicodeString;
  399. NoUConvObj: TUConvObject;
  400. RtlCp: TSystemCodepage;
  401. SrcLen: PtrInt;
  402. begin
  403. if UConv_Object = nil then
  404. RtlCp := OS2GetStandardCodePage (scpAnsi)
  405. else
  406. RtlCp := OS2CpToRtlCp (PDummyUConvObject (UConv_Object)^.CP, cpxMappingOnly,
  407. NoUConvObj);
  408. DefaultAnsi2UnicodeMove (InBuf, RtlCp, Dest, InBytesLeft);
  409. NonIdentical := 0; { Assume no need for substitutions in this direction }
  410. if Length (Dest) > UniCharsLeft then
  411. begin
  412. SrcLen := 1;
  413. repeat
  414. DefaultAnsi2UnicodeMove (InBuf, RtlCp, Dest2, SrcLen);
  415. if Length (Dest2) <= UniCharsLeft then
  416. begin
  417. Dest := Dest2;
  418. end;
  419. Inc (SrcLen);
  420. until Length (Dest2) > UniCharsLeft;
  421. Dec (SrcLen);
  422. Inc (InBuf, SrcLen);
  423. Dec (InBytesLeft, SrcLen);
  424. DummyUniUConvToUcs := Uls_BufferFull; { According to IBM documentation Uls_Invalid and not Uls_BufferFull as returned by UniUConvFromUcs?! }
  425. end
  426. else
  427. begin
  428. Inc (InBuf, InBytesLeft); { Shall it be increased in case of success too??? }
  429. InBytesLeft := 0;
  430. DummyUniUConvToUcs := Uls_Success;
  431. end;
  432. Move (Dest [1], UcsBuf^, Length (Dest) * 2);
  433. Inc (UcsBuf, Length (Dest)); { Shall it be increased in case of success too??? }
  434. Dec (UniCharsLeft, Length (Dest));
  435. end;
  436. procedure InitDBCSLeadRanges;
  437. var
  438. RC: cardinal;
  439. begin
  440. RC := DosQueryDBCSEnv (SizeOf (DBCSLeadRanges), EmptyCC,
  441. @DBCSLeadRanges [0]);
  442. DBCSLeadRangesEnd := 0;
  443. if RC <> 0 then
  444. while (DBCSLeadRangesEnd < SizeOf (DBCSLeadRanges)) and
  445. ((DBCSLeadRanges [DBCSLeadRangesEnd] <> #0) or
  446. (DBCSLeadRanges [Succ (DBCSLeadRangesEnd)] <> #0)) do
  447. Inc (DBCSLeadRangesEnd, 2);
  448. end;
  449. procedure InitDummyAnsiSupport;
  450. var
  451. C: char;
  452. AllChars: array [char] of char;
  453. RetSize: cardinal;
  454. begin
  455. if DosQueryCollate (SizeOf (CollationSequence), EmptyCC, @CollationSequence,
  456. RetSize) <> 0 then
  457. Move (LowerChars, CollationSequence, SizeOf (CollationSequence));
  458. Move (LowerChars, AllChars, SizeOf (AllChars));
  459. if DosMapCase (SizeOf (AllChars), IsoCC, @AllChars [#0]) <> 0 then
  460. (* Codepage 819 may not be supported in all old OS/2 versions. *)
  461. begin
  462. Move (LowerCharsIso88591, AllChars, SizeOf (AllChars));
  463. DosMapCase (SizeOf (AllChars), EmptyCC, @AllChars [#0]);
  464. NoIso88591Support := true;
  465. end;
  466. for C := Low (char) to High (char) do
  467. if AllChars [C] <> C then
  468. LowerCharsIso88591 [AllChars [C]] := C;
  469. if NoIso88591Support then
  470. Move (LowerCharsIso88591, LowerChars, SizeOf (LowerChars))
  471. else
  472. begin
  473. Move (LowerChars, AllChars, SizeOf (AllChars));
  474. DosMapCase (SizeOf (AllChars), EmptyCC, @AllChars [#0]);
  475. for C := Low (char) to High (char) do
  476. if AllChars [C] <> C then
  477. LowerChars [AllChars [C]] := C;
  478. end;
  479. InitDBCSLeadRanges;
  480. end;
  481. procedure ReInitDummyAnsiSupport;
  482. var
  483. C: char;
  484. AllChars: array [char] of char;
  485. RetSize: cardinal;
  486. begin
  487. for C := Low (char) to High (char) do
  488. AllChars [C] := C;
  489. if DosQueryCollate (SizeOf (CollationSequence), EmptyCC, @CollationSequence,
  490. RetSize) <> 0 then
  491. Move (AllChars, CollationSequence, SizeOf (CollationSequence));
  492. DosMapCase (SizeOf (AllChars), EmptyCC, @AllChars [#0]);
  493. for C := Low (char) to High (char) do
  494. if AllChars [C] <> C then
  495. LowerChars [AllChars [C]] := C;
  496. InitDBCSLeadRanges;
  497. end;
  498. function DummyUniToLower (UniCharIn: WideChar): WideChar; cdecl;
  499. var
  500. C: char;
  501. begin
  502. C := UniCharIn;
  503. DummyUniToLower := LowerCharsIso88591 [C];
  504. end;
  505. function DummyUniToUpper (UniCharIn: WideChar): WideChar; cdecl;
  506. var
  507. C: char;
  508. begin
  509. DummyUniToUpper := UniCharIn;
  510. C := UniCharIn;
  511. if NoIso88591Support then
  512. begin
  513. if DosMapCase (1, EmptyCC, @C) = 0 then
  514. DummyUniToUpper := C;
  515. end
  516. else
  517. if DosMapCase (1, IsoCC, @C) = 0 then
  518. DummyUniToUpper := C
  519. end;
  520. function DummyUniStrColl (Locale_Object: TLocaleObject;
  521. const UCS1, UCS2: PWideChar): longint; cdecl;
  522. var
  523. S1, S2: ansistring;
  524. begin
  525. S1 := UCS1;
  526. S2 := UCS2;
  527. if S1 = S2 then
  528. DummyUniStrColl := 0
  529. else if S1 < S2 then
  530. DummyUniStrColl := -1
  531. else
  532. DummyUniStrColl := 1;
  533. end;
  534. function DummyUniCreateLocaleObject (LocaleSpecType: longint;
  535. const LocaleSpec: pointer; var Locale_Object: TLocaleObject): longint; cdecl;
  536. begin
  537. DummyUniCreateLocaleObject := ULS_Unsupported;
  538. end;
  539. function DummyUniFreeLocaleObject (Locale_Object: TLocaleObject): longint;
  540. cdecl;
  541. begin
  542. DummyUniFreeLocaleObject := ULS_BadObject;
  543. end;
  544. const
  545. CpXList: TCpXList = (
  546. (WinCP: CP_UTF8; OS2CP: 1208; UConvObj: nil),
  547. (WinCP: CP_ASCII; OS2CP: 367; UConvObj: nil),
  548. (WinCP: 28597; OS2CP: 813; UConvObj: nil),
  549. (WinCP: 28591; OS2CP: 819; UConvObj: nil),
  550. (WinCP: 28592; OS2CP: 912; UConvObj: nil),
  551. (WinCP: 28593; OS2CP: 913; UConvObj: nil),
  552. (WinCP: 28594; OS2CP: 914; UConvObj: nil),
  553. (WinCP: 28595; OS2CP: 915; UConvObj: nil),
  554. (WinCP: 28598; OS2CP: 916; UConvObj: nil),
  555. (WinCP: 28599; OS2CP: 920; UConvObj: nil),
  556. (WinCP: 28603; OS2CP: 921; UConvObj: nil),
  557. (WinCP: 28605; OS2CP: 923; UConvObj: nil),
  558. (WinCP: 10000; OS2CP: 1275; UConvObj: nil),
  559. (WinCP: 10006; OS2CP: 1280; UConvObj: nil),
  560. (WinCP: 10081; OS2CP: 1281; UConvObj: nil),
  561. (WinCP: 10029; OS2CP: 1282; UConvObj: nil),
  562. (WinCP: 10007; OS2CP: 1283; UConvObj: nil),
  563. (WinCP: 20273; OS2CP: 273; UConvObj: nil),
  564. (WinCP: 20277; OS2CP: 277; UConvObj: nil),
  565. (WinCP: 20278; OS2CP: 278; UConvObj: nil),
  566. (WinCP: 20280; OS2CP: 280; UConvObj: nil),
  567. (WinCP: 20284; OS2CP: 284; UConvObj: nil),
  568. (WinCP: 20285; OS2CP: 285; UConvObj: nil),
  569. (WinCP: 20290; OS2CP: 290; UConvObj: nil),
  570. (WinCP: 20297; OS2CP: 297; UConvObj: nil),
  571. (WinCP: 20420; OS2CP: 420; UConvObj: nil),
  572. (WinCP: 20424; OS2CP: 424; UConvObj: nil),
  573. (WinCP: 20833; OS2CP: 833; UConvObj: nil),
  574. (WinCP: 20838; OS2CP: 838; UConvObj: nil),
  575. (WinCP: 20866; OS2CP: 878; UConvObj: nil),
  576. (WinCP: 737; OS2CP: 851; UConvObj: nil),
  577. (WinCP: 20924; OS2CP: 924; UConvObj: nil),
  578. (WinCP: 20932; OS2CP: 932; UConvObj: nil),
  579. (WinCP: 20936; OS2CP: 936; UConvObj: nil),
  580. (WinCP: 21025; OS2CP: 1025; UConvObj: nil),
  581. (WinCP: CP_UTF16; OS2CP: CP_UTF16; UConvObj: nil),
  582. (WinCP: 37; OS2CP: 37; UConvObj: nil),
  583. (WinCP: 437; OS2CP: 437; UConvObj: nil),
  584. (WinCP: 500; OS2CP: 500; UConvObj: nil),
  585. (WinCP: 850; OS2CP: 850; UConvObj: nil),
  586. (WinCP: 852; OS2CP: 852; UConvObj: nil),
  587. (WinCP: 855; OS2CP: 855; UConvObj: nil),
  588. (WinCP: 857; OS2CP: 857; UConvObj: nil),
  589. (WinCP: 860; OS2CP: 860; UConvObj: nil),
  590. (WinCP: 861; OS2CP: 861; UConvObj: nil),
  591. (WinCP: 862; OS2CP: 862; UConvObj: nil),
  592. (WinCP: 863; OS2CP: 863; UConvObj: nil),
  593. (WinCP: 864; OS2CP: 864; UConvObj: nil),
  594. (WinCP: 865; OS2CP: 865; UConvObj: nil),
  595. (WinCP: 866; OS2CP: 866; UConvObj: nil),
  596. (WinCP: 869; OS2CP: 869; UConvObj: nil),
  597. (WinCP: 870; OS2CP: 870; UConvObj: nil),
  598. (WinCP: 874; OS2CP: 874; UConvObj: nil),
  599. (WinCP: 875; OS2CP: 875; UConvObj: nil),
  600. (WinCP: 949; OS2CP: 949; UConvObj: nil),
  601. (WinCP: 950; OS2CP: 950; UConvObj: nil),
  602. (WinCP: 1026; OS2CP: 1026; UConvObj: nil),
  603. (WinCP: 1047; OS2CP: 1047; UConvObj: nil),
  604. (WinCP: 1140; OS2CP: 1140; UConvObj: nil),
  605. (WinCP: 1141; OS2CP: 1141; UConvObj: nil),
  606. (WinCP: 1142; OS2CP: 1142; UConvObj: nil),
  607. (WinCP: 1143; OS2CP: 1143; UConvObj: nil),
  608. (WinCP: 1144; OS2CP: 1144; UConvObj: nil),
  609. (WinCP: 1145; OS2CP: 1145; UConvObj: nil),
  610. (WinCP: 1146; OS2CP: 1146; UConvObj: nil),
  611. (WinCP: 1147; OS2CP: 1147; UConvObj: nil),
  612. (WinCP: 1148; OS2CP: 1148; UConvObj: nil),
  613. (WinCP: 1149; OS2CP: 1149; UConvObj: nil),
  614. (WinCP: 1250; OS2CP: 1250; UConvObj: nil),
  615. (WinCP: 1251; OS2CP: 1251; UConvObj: nil),
  616. (WinCP: 1252; OS2CP: 1252; UConvObj: nil),
  617. (WinCP: 1253; OS2CP: 1253; UConvObj: nil),
  618. (WinCP: 1254; OS2CP: 1254; UConvObj: nil),
  619. (WinCP: 1255; OS2CP: 1255; UConvObj: nil),
  620. (WinCP: 1256; OS2CP: 1256; UConvObj: nil),
  621. (WinCP: 1257; OS2CP: 1257; UConvObj: nil)
  622. );
  623. (* Possibly add index tables for both directions and binary search??? *)
  624. {
  625. function GetRtlCpFromCpRec (const CpRec: TCpRec): TSystemCodepage; inline;
  626. begin
  627. if RtlUsesWinCp then
  628. GetRtlCp := CpRec.WinCP
  629. else
  630. GetRtlCp := TSystemCodepage (CpRec.Os2Cp);
  631. end;
  632. }
  633. function UConvObjectForCP (CP: cardinal; var UConvObj: TUConvObject): longint;
  634. var
  635. RC: longint;
  636. A: array [0..12] of WideChar;
  637. begin
  638. UConvObj := nil;
  639. RC := Sys_UniMapCpToUcsCp (CP, @A, 12);
  640. if RC = 0 then
  641. RC := Sys_UniCreateUconvObject (@A, UConvObj);
  642. {$WARNING: TODO: Deallocate some previously allocated UConvObj and try again if failed}
  643. UConvObjectForCP := RC;
  644. if RC <> 0 then
  645. OSErrorWatch (RC);
  646. end;
  647. procedure InitDefaultCP;
  648. var
  649. OS2CP, I: cardinal;
  650. NoUConvObj: TUConvObject;
  651. RCI: longint;
  652. RC: cardinal;
  653. CPArr: TCPArray;
  654. ReturnedSize: cardinal;
  655. begin
  656. if InInitDefaultCP <> -1 then
  657. begin
  658. repeat
  659. DosSleep (5);
  660. until InInitDefaultCP <> -1;
  661. Exit;
  662. end;
  663. InInitDefaultCP := ThreadID;
  664. if DefCpRec.UConvObj <> nil then
  665. begin
  666. (* Do not free the UConv object from DefCpRec, because it is also stored in
  667. the respective CPXList record! *)
  668. {
  669. RCI := Sys_UniFreeUConvObject (DefCpRec.UConvObj);
  670. if RCI <> 0 then
  671. OSErrorWatch (cardinal (RCI));
  672. }
  673. DefCpRec.UConvObj := nil;
  674. end;
  675. RC := DosQueryCP (SizeOf (CPArr), @CPArr, ReturnedSize);
  676. if (RC <> 0) and (RC <> 473) then
  677. begin
  678. OSErrorWatch (RC);
  679. CPArr [0] := 850;
  680. end
  681. else if (ReturnedSize < 4) then
  682. CPArr [0] := 850;
  683. DefaultFileSystemCodePage := OS2CPtoRtlCP (CPArr [0], cpxAll,
  684. DefCpRec.UConvObj);
  685. CachedDefFSCodepage := DefaultFileSystemCodePage;
  686. DefCpRec.OS2CP := CPArr [0];
  687. (* Find out WinCP _without_ considering RtlUsesWinCP *)
  688. I := 1;
  689. while (I <= MaxNonEqualCPMapping) and (CpXList [I].OS2CP <> OS2CP) do
  690. Inc (I);
  691. if CpXList [I].OS2CP = CPArr [0] then
  692. DefCpRec.WinCP := CpXList [I].WinCP
  693. else
  694. DefCpRec.WinCP := CPArr [0];
  695. if DefLocObj <> nil then
  696. begin
  697. RCI := Sys_UniFreeLocaleObject (DefLocObj);
  698. if RCI <> 0 then
  699. OSErrorWatch (cardinal (RCI));
  700. DefLocObj := nil;
  701. end;
  702. RCI := Sys_UniCreateLocaleObject (Uni_UCS_String_Pointer, @WNull, DefLocObj);
  703. if RCI <> 0 then
  704. begin
  705. OSErrorWatch (cardinal (RCI));
  706. (* The locale dependent routines like comparison require a valid locale *)
  707. (* setting, but the locale set using environment variable LANG is not *)
  708. (* recognized by OS/2 -> we try the "Universal" locale as a fallback. *)
  709. RCI := Sys_UniCreateLocaleObject (Uni_UCS_String_Pointer, @WUniv [0],
  710. DefLocObj);
  711. if RCI <> 0 then
  712. begin
  713. OSErrorWatch (cardinal (RCI));
  714. DefLocObj := nil;
  715. end;
  716. end;
  717. if not (UniAPI) then
  718. ReInitDummyAnsiSupport;
  719. InInitDefaultCP := -1;
  720. end;
  721. function OS2CPtoRtlCP (CP: cardinal; ReqFlags: byte;
  722. var UConvObj: TUConvObject): TSystemCodepage;
  723. var
  724. I, I2: cardinal;
  725. RCI: longint;
  726. function CheckDefaultOS2CP: boolean;
  727. begin
  728. if CP = DefCpRec.OS2CP then
  729. begin
  730. CheckDefaultOS2CP := true;
  731. if RTLUsesWinCP then
  732. OS2CPtoRtlCP := DefCpRec.WinCP;
  733. if ReqFlags and CpxMappingOnly = 0 then
  734. UConvObj := DefCpRec.UConvObj;
  735. end
  736. else
  737. CheckDefaultOS2CP := false;
  738. end;
  739. begin
  740. OS2CPtoRtlCP := TSystemCodePage (CP);
  741. UConvObj := nil;
  742. if not UniAPI then (* No UniAPI => no need for UConvObj *)
  743. ReqFlags := ReqFlags or CpxMappingOnly;
  744. if CheckDefaultOS2CP then
  745. Exit;
  746. if (CachedDefFSCodepage <> DefaultFileSystemCodePage) and
  747. (InInitDefaultCP <> ThreadID) then
  748. (* InInitDefaultCP = ThreadID -> this thread is already re-initializing the cached information *)
  749. begin
  750. if InInitDefaultCP <> -1 then
  751. repeat
  752. DosSleep (5) (* Let's wait until the other thread finishes re-initialization of the cache *)
  753. until InInitDefaultCP = -1
  754. else
  755. InitDefaultCP;
  756. if CheckDefaultOS2CP then
  757. Exit;
  758. end;
  759. I := 1;
  760. if ReqFlags and CpxSpecial = CpxSpecial then
  761. I2 := 2
  762. else
  763. if ReqFlags and CpxMappingOnly = CpxMappingOnly then
  764. I2 := MaxNonEqualCPMapping
  765. else
  766. I2 := MaxCPMapping;
  767. while I <= I2 do
  768. begin
  769. if CP = CpXList [I].OS2CP then
  770. begin
  771. if RTLUsesWinCP then
  772. OS2CPtoRtlCP := CpXList [I].WinCP;
  773. if ReqFlags and CpxMappingOnly = 0 then
  774. begin
  775. if CpXList [I].UConvObj = nil then
  776. begin
  777. if UConvObjectForCP (CpXList [I].OS2CP, UConvObj) = Uls_Success then
  778. CpXList [I].UConvObj := UConvObj
  779. else
  780. UConvObj := nil;
  781. end
  782. else
  783. UConvObj := CpXList [I].UConvObj;
  784. end;
  785. Exit;
  786. end;
  787. Inc (I);
  788. end;
  789. (* If codepage was not found in the translation table and UConvObj is
  790. requested, allocate one in the temporary record. *)
  791. if ReqFlags and CpxMappingOnly = 0 then
  792. begin
  793. if TempCpRec.OS2CP = CP then
  794. UConvObj := TempCpRec.UConvObj
  795. else
  796. begin
  797. if TempCpRec.UConvObj <> nil then
  798. begin
  799. RCI := Sys_UniFreeUConvObject (TempCpRec.UConvObj);
  800. if RCI <> 0 then
  801. OSErrorWatch (cardinal (RCI));
  802. end;
  803. if UConvObjectForCP (CP, UConvObj) = Uls_Success then
  804. begin
  805. TempCpRec.UConvObj := UConvObj;
  806. TempCpRec.OS2CP := CP;
  807. end
  808. else
  809. UConvObj := nil;
  810. end;
  811. end;
  812. end;
  813. function RtlCPtoOS2CP (RtlCP: TSystemCodepage; ReqFlags: byte;
  814. var UConvObj: TUConvObject): cardinal;
  815. var
  816. I, I2: cardinal;
  817. function CheckDefaultWinCP: boolean;
  818. begin
  819. if RtlCP = DefCpRec.WinCP then
  820. begin
  821. CheckDefaultWinCP := true;
  822. RtlCPtoOS2CP := DefCpRec.WinCP;
  823. if ReqFlags and CpxMappingOnly = 0 then
  824. UConvObj := DefCpRec.UConvObj;
  825. end
  826. else
  827. CheckDefaultWinCP := false;
  828. end;
  829. begin
  830. RtlCPtoOS2CP := RtlCP;
  831. UConvObj := nil;
  832. if not UniAPI then (* No UniAPI => no need for UConvObj *)
  833. ReqFlags := ReqFlags or CpxMappingOnly;
  834. if not (RTLUsesWinCP) then
  835. begin
  836. if ReqFlags and CpxMappingOnly = 0 then
  837. OS2CPtoRtlCP (cardinal (RtlCp), ReqFlags, UConvObj);
  838. end
  839. else if CheckDefaultWinCp then
  840. Exit
  841. else
  842. begin
  843. if (CachedDefFSCodepage <> DefaultFileSystemCodePage) and
  844. (InInitDefaultCP <> ThreadID) then
  845. (* InInitDefaultCP = ThreadID -> this thread is already re-initializing the cached information *)
  846. begin
  847. if InInitDefaultCP <> -1 then
  848. repeat
  849. (* Let's wait until the other thread finishes re-initialization of the cache *)
  850. DosSleep (5)
  851. until InInitDefaultCP = -1
  852. else
  853. InitDefaultCP;
  854. if CheckDefaultWinCP then
  855. Exit;
  856. end;
  857. I := 1;
  858. if ReqFlags and CpxSpecial = CpxSpecial then
  859. I2 := 2
  860. else
  861. if ReqFlags and CpxMappingOnly = CpxMappingOnly then
  862. I2 := MaxNonEqualCPMapping
  863. else
  864. I2 := MaxCPMapping;
  865. while I <= I2 do
  866. begin
  867. if RtlCP = CpXList [I].WinCP then
  868. begin
  869. RtlCPtoOS2CP := CpXList [I].OS2CP;
  870. if ReqFlags and CpxMappingOnly = 0 then
  871. begin
  872. begin
  873. if UConvObjectForCP (CpXList [I].OS2CP, UConvObj) = Uls_Success then
  874. CpXList [I].UConvObj := UConvObj
  875. else
  876. UConvObj := nil;
  877. end
  878. end;
  879. Exit;
  880. end;
  881. Inc (I);
  882. end;
  883. (*
  884. Special processing for
  885. ExceptionWinCodepages = (CP_UTF16BE, CP_UTF7, 12000 {UTF32}, 12001 {UTF32BE})
  886. might be added here...or not ;-)
  887. if (TempCpRec.OS2CP <> High (TempCpRec.OS2CP)) or
  888. (TempCpRec.WinCP <> RtlCp) then
  889. begin
  890. if TempCpRec.UConvObj <> nil then
  891. begin
  892. RCI := Sys_UniFreeUConvObject (TempCpRec.UConvObj);
  893. if RCI <> 0 then
  894. OSErrorWatch (cardinal (RCI));
  895. end;
  896. TempCpRec.OS2CP := High (TempCpRec.OS2CP);
  897. TempCpRec.WinCP := RtlCp;
  898. end;
  899. Map to CP_ASCII aka OS2CP=367 if RtlCP not recognized and UConvObject
  900. is requested???
  901. *)
  902. (* Signalize unrecognized (untranslatable) MS Windows codepage *)
  903. OSErrorWatch (Uls_Invalid);
  904. end;
  905. end;
  906. function OS2CPtoRtlCP (CP: cardinal; ReqFlags: byte): TSystemCodepage;
  907. var
  908. NoUConvObj: TUConvObject;
  909. begin
  910. if RtlUsesWinCP then
  911. OS2CPtoRtlCP := OS2CPtoRtlCP (CP, ReqFlags or CpxMappingOnly, NoUConvObj)
  912. else
  913. OS2CPtoRtlCP := TSystemCodepage (CP);
  914. end;
  915. function RtlCPtoOS2CP (RtlCP: TSystemCodepage; ReqFlags: byte): cardinal;
  916. var
  917. NoUConvObj: TUConvObject;
  918. begin
  919. if RtlUsesWinCP then
  920. RtlCPtoOS2CP := RtlCPtoOS2CP (RtlCP, ReqFlags or CpxMappingOnly, NoUConvObj)
  921. else
  922. RtlCPtoOS2CP := RtlCP;
  923. end;
  924. procedure OS2Unicode2AnsiMove (Source: PUnicodeChar; var Dest: RawByteString;
  925. CP: TSystemCodePage; Len: SizeInt);
  926. var
  927. RCI: longint;
  928. UConvObj: TUConvObject;
  929. OS2CP: cardinal;
  930. Src2: PUnicodeChar;
  931. Len2, LenOut, OutOffset, NonIdentical: longint;
  932. Dest2: PChar;
  933. begin
  934. OS2CP := RtlCpToOS2CP (CP, CpxAll, UConvObj);
  935. { if UniAPI and (UConvObj = nil) then - OS2Unicode2AnsiMove should be never called if not UniAPI }
  936. if UConvObj = nil then
  937. begin
  938. {$WARNING Special cases like UTF-7 should be handled here, otherwise signalize error - how???}
  939. DefaultUnicode2AnsiMove (Source, Dest, CP, Len);
  940. Exit;
  941. end;
  942. LenOut := Succ (Len); (* Standard OS/2 CP is a SBCS *)
  943. SetLength (Dest, LenOut);
  944. SetCodePage (Dest, CP, false);
  945. Src2 := Source;
  946. Len2 := Len;
  947. Dest2 := PChar (Dest);
  948. RCI := Sys_UniUConvFromUcs (UConvObj, Src2, Len2, Dest2, LenOut,
  949. NonIdentical);
  950. repeat
  951. case RCI of
  952. Uls_Success:
  953. begin
  954. if LenOut > 0 then
  955. SetLength (Dest, Length (Dest) - LenOut);
  956. Break;
  957. end;
  958. Uls_IllegalSequence:
  959. begin
  960. OSErrorWatch (Uls_IllegalSequence);
  961. { skip and set to '?' }
  962. Inc (Src2);
  963. Dec (Len2);
  964. Dest2^ := '?';
  965. Inc (Dest2);
  966. Dec (LenOut);
  967. end;
  968. Uls_BufferFull:
  969. begin
  970. OutOffset := Dest2 - PChar (Dest);
  971. (* Use Len2 or Len decreased by difference between Source and Src2? *)
  972. (* Extend more this time - target is probably a DBCS or UTF-8 *)
  973. SetLength (Dest, Length (Dest) + Succ (Len2 * 2));
  974. { string could have been moved }
  975. Dest2 := PChar (Dest) + OutOffset;
  976. Inc (LenOut, Succ (Len2 * 2));
  977. end
  978. else
  979. begin
  980. SetLength (Dest, 0);
  981. OSErrorWatch (cardinal (RCI));
  982. { Break }
  983. RunError (231);
  984. end;
  985. end;
  986. RCI := Sys_UniUConvFromUcs (UConvObj, Src2, Len2, Dest2, LenOut,
  987. NonIdentical);
  988. until false;
  989. end;
  990. procedure OS2Ansi2UnicodeMove (Source: PChar; CP: TSystemCodePage;
  991. var Dest: UnicodeString; Len: SizeInt);
  992. var
  993. RCI: longint;
  994. UConvObj: TUConvObject;
  995. OS2CP: cardinal;
  996. Src2: PChar;
  997. Len2, LenOut, OutOffset, NonIdentical: longint;
  998. Dest2: PWideChar;
  999. begin
  1000. OS2CP := RtlCpToOS2CP (CP, CpxAll, UConvObj);
  1001. { if UniAPI and (UConvObj = nil) then - OS2Unicode2AnsiMove should be never called if not UniAPI }
  1002. if UConvObj = nil then
  1003. begin
  1004. {$WARNING Special cases like UTF-7 should be handled here, otherwise signalize error - how???}
  1005. DefaultAnsi2UnicodeMove (Source, CP, Dest, Len);
  1006. Exit;
  1007. end;
  1008. LenOut := Succ (Len); (* Standard OS/2 CP is a SBCS *)
  1009. SetLength (Dest, LenOut);
  1010. Src2 := Source;
  1011. Len2 := Len;
  1012. Dest2 := PWideChar (Dest);
  1013. RCI := Sys_UniUConvToUcs (UConvObj, Src2, Len2, Dest2, LenOut, NonIdentical);
  1014. repeat
  1015. case RCI of
  1016. Uls_Success:
  1017. begin
  1018. if LenOut > 0 then
  1019. SetLength (Dest, Length (Dest) - LenOut);
  1020. Break;
  1021. end;
  1022. Uls_IllegalSequence:
  1023. begin
  1024. OSErrorWatch (Uls_IllegalSequence);
  1025. { skip and set to '?' }
  1026. Inc (Src2);
  1027. Dec (Len2);
  1028. Dest2^ := '?';
  1029. Inc (Dest2);
  1030. Dec (LenOut);
  1031. end;
  1032. Uls_BufferFull:
  1033. begin
  1034. OutOffset := Dest2 - PWideChar (Dest);
  1035. (* Use Len2 or Len decreased by difference between Source and Src2? *)
  1036. SetLength (Dest, Length (Dest) + Succ (Len2));
  1037. { string could have been moved }
  1038. Dest2 := PWideChar (Dest) + OutOffset;
  1039. Inc (LenOut, Succ (Len2));
  1040. end
  1041. else
  1042. begin
  1043. SetLength (Dest, 0);
  1044. OSErrorWatch (cardinal (RCI));
  1045. { Break }
  1046. RunError (231);
  1047. end;
  1048. end;
  1049. RCI := Sys_UniUConvToUcs (UConvObj, Src2, Len2, Dest2, LenOut,
  1050. NonIdentical);
  1051. until false;
  1052. end;
  1053. function RtlChangeCP (CP: TSystemCodePage): longint;
  1054. var
  1055. OS2CP, I: cardinal;
  1056. NoUConvObj: TUConvObject;
  1057. RCI: longint;
  1058. begin
  1059. OS2CP := RtlCpToOS2Cp (CP, cpxMappingOnly, NoUConvObj);
  1060. RtlChangeCP := longint (DosSetProcessCP (OS2CP));
  1061. if RtlChangeCP <> 0 then
  1062. OSErrorWatch (RtlChangeCP)
  1063. else
  1064. begin
  1065. DefaultSystemCodePage := CP;
  1066. DefaultRTLFileSystemCodePage := DefaultSystemCodePage;
  1067. DefaultFileSystemCodePage := DefaultSystemCodePage;
  1068. if OS2CP <> DefCpRec.OS2CP then
  1069. begin
  1070. if DefCpRec.UConvObj <> nil then
  1071. begin
  1072. (* Do not free the UConv object from DefCpRec, because it is also stored in
  1073. the respective CpXList record! *)
  1074. {
  1075. RCI := Sys_UniFreeUConvObject (DefCpRec.UConvObj);
  1076. if RCI <> 0 then
  1077. OSErrorWatch (cardinal (RCI));
  1078. }
  1079. DefCpRec.UConvObj := nil;
  1080. end;
  1081. DefCPRec.OS2CP := OS2CP;
  1082. RCI := Sys_UniCreateUConvObject (@WNull, DefCpRec.UConvObj);
  1083. if RCI <> 0 then
  1084. OSErrorWatch (cardinal (RCI));
  1085. (* Find out WinCP _without_ considering RtlUsesWinCP *)
  1086. I := 1;
  1087. while (I <= MaxNonEqualCPMapping) and (CpXList [I].OS2CP <> OS2CP) do
  1088. Inc (I);
  1089. if CpXList [I].OS2CP = OS2CP then
  1090. DefCpRec.WinCP := CpXList [I].WinCP
  1091. else
  1092. DefCpRec.WinCP := OS2CP;
  1093. end;
  1094. end;
  1095. end;
  1096. function OS2UpperUnicodeString (const S: UnicodeString): UnicodeString;
  1097. var
  1098. I: cardinal;
  1099. begin
  1100. SetLength (Result, Length (S));
  1101. for I := 0 to Pred (Length (S)) do
  1102. PWideChar (Result) [I] := Sys_UniToUpper (S [Succ (I)]);
  1103. end;
  1104. function OS2LowerUnicodeString (const S: UnicodeString): UnicodeString;
  1105. var
  1106. I: cardinal;
  1107. begin
  1108. SetLength (Result, Length (S));
  1109. for I := 0 to Pred (Length (S)) do
  1110. PWideChar (Result) [I] := Sys_UniToLower (S [Succ (I)]);
  1111. end;
  1112. function NoNullsUnicodeString (const S: UnicodeString): UnicodeString;
  1113. var
  1114. I: cardinal;
  1115. begin
  1116. Result := S;
  1117. UniqueString (Result);
  1118. for I := 1 to Length (S) do
  1119. if Result [I] = WNull then
  1120. Result [I] := ' ';
  1121. end;
  1122. function OS2CompareUnicodeString (const S1, S2: UnicodeString): PtrInt;
  1123. var
  1124. HS1, HS2: UnicodeString;
  1125. begin
  1126. { UniStrColl interprets null chars as end-of-string -> filter out }
  1127. HS1 := NoNullsUnicodeString (S1);
  1128. HS2 := NoNullsUnicodeString (S2);
  1129. Result := Sys_UniStrColl (DefLocObj, PWideChar (HS1), PWideChar (HS2));
  1130. if Result < -1 then
  1131. Result := -1
  1132. else if Result > 1 then
  1133. Result := 1;
  1134. end;
  1135. function OS2CompareTextUnicodeString (const S1, S2: UnicodeString): PtrInt;
  1136. begin
  1137. Result := OS2CompareUnicodeString (OS2UpperUnicodeString (S1),
  1138. OS2UpperUnicodeString (S2));
  1139. {$WARNING Language independent uppercase routine may not be appropriate for language dependent case insensitive comparison!}
  1140. end;
  1141. function OS2UpperAnsiString (const S: AnsiString): AnsiString;
  1142. var
  1143. RC: cardinal;
  1144. begin
  1145. Result := S;
  1146. UniqueString (Result);
  1147. FillChar (EmptyCC, SizeOf (EmptyCC), 0);
  1148. RC := DosMapCase (Length (Result), EmptyCC, PChar (Result));
  1149. { What to do in case of a failure??? }
  1150. if RC <> 0 then
  1151. Result := UpCase (S); { Use a fallback? }
  1152. end;
  1153. function OS2LowerAnsiString (const S: AnsiString): AnsiString;
  1154. var
  1155. I: PtrUInt;
  1156. function IsDBCSLeadChar (C: char): boolean;
  1157. var
  1158. D: byte;
  1159. begin
  1160. IsDBCSLeadChar := false;
  1161. D := 0;
  1162. while D < DBCSLeadRangesEnd do
  1163. begin
  1164. if (C >= DBCSLeadRanges [D]) and (C <= DBCSLeadRanges [Succ (D)]) then
  1165. begin
  1166. IsDBCSLeadChar := true;
  1167. Exit;
  1168. end;
  1169. Inc (D, 2);
  1170. end;
  1171. end;
  1172. begin
  1173. (*
  1174. OS/2 provides no direct solution for lowercase conversion of MBCS strings.
  1175. If Unicode support is available, using Unicode routines is the best solution.
  1176. If not, we use a translation table built at startup by translating the full
  1177. character set to uppercase and using that for creation of a lookup table
  1178. (as already done in sysutils). However, we need to check for DBCS (MBCS)
  1179. codepages and avoid translating the DBCS lead bytes and the following
  1180. character.
  1181. *)
  1182. if UniAPI then
  1183. Result := OS2LowerUnicodeString (S)
  1184. { Two implicit conversions... ;-) }
  1185. else
  1186. begin
  1187. Result := S;
  1188. if Length (Result) > 0 then
  1189. begin
  1190. UniqueString (Result);
  1191. if DBCSLeadRangesEnd > 0 then
  1192. begin
  1193. I := 1;
  1194. while I <= Length (Result) do
  1195. begin
  1196. if IsDBCSLeadChar (Result [I]) then
  1197. Inc (I, 2)
  1198. else
  1199. begin
  1200. Result [I] := LowerChars [Result [I]];
  1201. Inc (I);
  1202. end;
  1203. end;
  1204. end
  1205. else
  1206. for I := 1 to Length (Result) do
  1207. Result [I] := LowerChars [Result [I]];
  1208. end;
  1209. end;
  1210. end;
  1211. function OS2CompareStrAnsiString (const S1, S2: AnsiString): PtrInt;
  1212. var
  1213. I, MaxLen: PtrUInt;
  1214. begin
  1215. if UniAPI then
  1216. Result := OS2CompareUnicodeString (S1, S2) (* implicit conversions *)
  1217. else
  1218. (* Older OS/2 versions without Unicode support do not provide direct means *)
  1219. (* for case sensitive and codepage and language-aware string comparison. *)
  1220. (* We have to resort to manual comparison of the original strings together *)
  1221. (* with strings translated using the case insensitive collation sequence. *)
  1222. begin
  1223. if Length (S1) = 0 then
  1224. begin
  1225. if Length (S2) = 0 then
  1226. Result := 0
  1227. else
  1228. Result := -1;
  1229. Exit;
  1230. end
  1231. else
  1232. if Length (S2) = 0 then
  1233. begin
  1234. Result := 1;
  1235. Exit;
  1236. end;
  1237. I := 1;
  1238. MaxLen := Length (S1);
  1239. if Length (S2) < MaxLen then
  1240. MaxLen := Length (S2);
  1241. repeat
  1242. if CollationSequence [S1 [I]] = CollationSequence [S2 [I]] then
  1243. begin
  1244. if S1 [I] < S2 [I] then
  1245. begin
  1246. Result := -1;
  1247. Exit;
  1248. end
  1249. else if S1 [I] > S2 [I] then
  1250. begin
  1251. Result := 1;
  1252. Exit;
  1253. end;
  1254. end
  1255. else
  1256. begin
  1257. if CollationSequence [S1 [I]] < CollationSequence [S2 [I]] then
  1258. Result := -1
  1259. else
  1260. Result := 1;
  1261. Exit;
  1262. end;
  1263. Inc (I);
  1264. until (I > MaxLen);
  1265. if Length (S2) > MaxLen then
  1266. Result := -1
  1267. else if Length (S1) > MaxLen then
  1268. Result := 1
  1269. else
  1270. Result := 0;
  1271. end;
  1272. end;
  1273. function OS2StrCompAnsiString (S1, S2: PChar): PtrInt;
  1274. var
  1275. HSA1, HSA2: AnsiString;
  1276. HSU1, HSU2: UnicodeString;
  1277. begin
  1278. (* Do not call OS2CompareUnicodeString to skip scanning for #0. *)
  1279. HSA1 := AnsiString (S1);
  1280. HSA2 := AnsiString (S2);
  1281. if UniApi then
  1282. begin
  1283. HSU1 := HSA1; (* implicit conversion *)
  1284. HSU2 := HSA2; (* implicit conversion *)
  1285. Result := Sys_UniStrColl (DefLocObj, PWideChar (HSU1), PWideChar (HSU2));
  1286. if Result < -1 then
  1287. Result := -1
  1288. else if Result > 1 then
  1289. Result := 1;
  1290. end
  1291. else
  1292. Result := OS2CompareStrAnsiString (HSA1, HSA2);
  1293. end;
  1294. function OS2CompareTextAnsiString (const S1, S2: AnsiString): PtrInt;
  1295. var
  1296. HSA1, HSA2: AnsiString;
  1297. I: PtrUInt;
  1298. begin
  1299. if UniAPI then
  1300. Result := OS2CompareTextUnicodeString (S1, S2) (* implicit conversions *)
  1301. else
  1302. begin
  1303. (* Let's use collation strings here as a fallback *)
  1304. SetLength (HSA1, Length (S1));
  1305. if Length (HSA1) > 0 then
  1306. (* Using assembler would be much faster, but never mind... *)
  1307. for I := 1 to Length (HSA1) do
  1308. HSA1 [I] := CollationSequence [S1 [I]];
  1309. {$WARNING Results of using collation sequence with DBCS not known/tested!}
  1310. SetLength (HSA2, Length (S2));
  1311. if Length (HSA2) > 0 then
  1312. for I := 1 to Length (HSA2) do
  1313. HSA2 [I] := CollationSequence [S2 [I]];
  1314. if HSA1 = HSA2 then
  1315. Result := 0
  1316. else if HSA1 < HSA2 then
  1317. Result := -1
  1318. else
  1319. Result := 1;
  1320. end;
  1321. end;
  1322. function OS2StrICompAnsiString (S1, S2: PChar): PtrInt;
  1323. begin
  1324. Result := OS2CompareTextAnsiString (AnsiString (S1), AnsiString (S2));
  1325. end;
  1326. function OS2StrLCompAnsiString (S1, S2: PChar; MaxLen: PtrUInt): PtrInt;
  1327. var
  1328. A, B: AnsiString;
  1329. begin
  1330. if (MaxLen = 0) then
  1331. Exit (0);
  1332. SetLength (A, MaxLen);
  1333. Move (S1^, A [1], MaxLen);
  1334. SetLength (B, MaxLen);
  1335. Move (S2^, B [1], MaxLen);
  1336. Result := OS2CompareStrAnsiString (A, B);
  1337. end;
  1338. function OS2StrLICompAnsiString (S1, S2: PChar; MaxLen: PtrUInt): PtrInt;
  1339. var
  1340. A, B: AnsiString;
  1341. begin
  1342. if (MaxLen = 0) then
  1343. Exit (0);
  1344. SetLength (A, MaxLen);
  1345. Move (S1^, A [1], MaxLen);
  1346. SetLength (B, MaxLen);
  1347. Move (S2^, B [1], MaxLen);
  1348. Result := OS2CompareTextAnsiString (A, B);
  1349. end;
  1350. procedure FPC_RangeError; [external name 'FPC_RANGEERROR'];
  1351. procedure Ansi2PChar (const S: AnsiString; const OrgP: PChar; out P: Pchar);
  1352. var
  1353. NewLen: SizeUInt;
  1354. begin
  1355. NewLen := Length (S);
  1356. if NewLen > StrLen (OrgP) then
  1357. FPC_RangeError;
  1358. P := OrgP;
  1359. if (NewLen > 0) then
  1360. Move (S [1], P [0], NewLen);
  1361. P [NewLen] := #0;
  1362. end;
  1363. function OS2StrUpperAnsiString (Str: PChar): PChar;
  1364. var
  1365. Temp: AnsiString;
  1366. begin
  1367. Temp := OS2UpperAnsiString (Str);
  1368. Ansi2PChar (Temp, Str, Result);
  1369. end;
  1370. function OS2StrLowerAnsiString (Str: PChar): PChar;
  1371. var
  1372. Temp: AnsiString;
  1373. begin
  1374. Temp := OS2LowerAnsiString (Str);
  1375. Ansi2PChar (Temp, Str, Result);
  1376. end;
  1377. (*
  1378. CWSTRING:
  1379. { return value: number of code points in the string. Whenever an invalid
  1380. code point is encountered, all characters part of this invalid code point
  1381. are considered to form one "character" and the next character is
  1382. considered to be the start of a new (possibly also invalid) code point }
  1383. function CharLengthPChar(const Str: PChar): PtrInt;
  1384. var
  1385. nextlen: ptrint;
  1386. s: pchar;
  1387. {$ifndef beos}
  1388. mbstate: mbstate_t;
  1389. {$endif not beos}
  1390. begin
  1391. result:=0;
  1392. s:=str;
  1393. {$ifndef beos}
  1394. fillchar(mbstate,sizeof(mbstate),0);
  1395. {$endif not beos}
  1396. repeat
  1397. {$ifdef beos}
  1398. nextlen:=ptrint(mblen(s,MB_CUR_MAX));
  1399. {$else beos}
  1400. nextlen:=ptrint(mbrlen(s,MB_CUR_MAX,@mbstate));
  1401. {$endif beos}
  1402. { skip invalid/incomplete sequences }
  1403. if (nextlen<0) then
  1404. nextlen:=1;
  1405. inc(result,1);
  1406. inc(s,nextlen);
  1407. until (nextlen=0);
  1408. end;
  1409. function CodePointLength(const Str: PChar; maxlookahead: ptrint): PtrInt;
  1410. var
  1411. nextlen: ptrint;
  1412. {$ifndef beos}
  1413. mbstate: mbstate_t;
  1414. {$endif not beos}
  1415. begin
  1416. {$ifdef beos}
  1417. result:=ptrint(mblen(str,maxlookahead));
  1418. {$else beos}
  1419. fillchar(mbstate,sizeof(mbstate),0);
  1420. result:=ptrint(mbrlen(str,maxlookahead,@mbstate));
  1421. { mbrlen can also return -2 for "incomplete but potially valid character
  1422. and data has been processed" }
  1423. if result<0 then
  1424. result:=-1;
  1425. {$endif beos}
  1426. end;
  1427. *)
  1428. procedure InitOS2WideStringManager; inline;
  1429. var
  1430. RC: cardinal;
  1431. ErrName: array [0..MaxPathLen] of char;
  1432. P: pointer;
  1433. begin
  1434. RC := DosLoadModule (@ErrName [0], SizeOf (ErrName), @UConvName [0],
  1435. UConvHandle);
  1436. if RC = 0 then
  1437. begin
  1438. RC := DosQueryProcAddr (UConvHandle, OrdUniCreateUConvObject, nil, P);
  1439. if RC = 0 then
  1440. begin
  1441. Sys_UniCreateUConvObject := TUniCreateUConvObject (P);
  1442. RC := DosQueryProcAddr (UConvHandle, OrdUniMapCpToUcsCp, nil, P);
  1443. if RC = 0 then
  1444. begin
  1445. Sys_UniMapCpToUcsCp := TUniMapCpToUcsCp (P);
  1446. RC := DosQueryProcAddr (UConvHandle, OrdUniFreeUConvObject, nil, P);
  1447. if RC = 0 then
  1448. begin
  1449. Sys_UniFreeUConvObject := TUniFreeUConvObject (P);
  1450. RC := DosQueryProcAddr (UConvHandle, OrdUniUConvFromUcs, nil, P);
  1451. if RC = 0 then
  1452. begin
  1453. Sys_UniUConvFromUcs := TUniUConvFromUcs (P);
  1454. RC := DosQueryProcAddr (UConvHandle, OrdUniUConvToUcs, nil, P);
  1455. if RC = 0 then
  1456. begin
  1457. Sys_UniUConvToUcs := TUniUConvToUcs (P);
  1458. RC := DosLoadModule (@ErrName [0], SizeOf (ErrName),
  1459. @LibUniName [0], LibUniHandle);
  1460. if RC = 0 then
  1461. begin
  1462. RC := DosQueryProcAddr (LibUniHandle, OrdUniToLower, nil, P);
  1463. if RC = 0 then
  1464. begin
  1465. Sys_UniToLower := TUniToLower (P);
  1466. RC := DosQueryProcAddr (LibUniHandle, OrdUniToUpper, nil, P);
  1467. if RC = 0 then
  1468. begin
  1469. Sys_UniToUpper := TUniToUpper (P);
  1470. RC := DosQueryProcAddr (LibUniHandle, OrdUniStrColl, nil,
  1471. P);
  1472. if RC = 0 then
  1473. begin
  1474. Sys_UniStrColl := TUniStrColl (P);
  1475. RC := DosQueryProcAddr (LibUniHandle,
  1476. OrdUniCreateLocaleObject, nil, P);
  1477. if RC = 0 then
  1478. begin
  1479. Sys_UniCreateLocaleObject := TUniCreateLocaleObject
  1480. (P);
  1481. RC := DosQueryProcAddr (LibUniHandle,
  1482. OrdUniFreeLocaleObject, nil, P);
  1483. if RC = 0 then
  1484. begin
  1485. Sys_UniFreeLocaleObject := TUniFreeLocaleObject (P);
  1486. UniAPI := true;
  1487. end;
  1488. end;
  1489. end;
  1490. end;
  1491. end;
  1492. end;
  1493. end;
  1494. end;
  1495. end;
  1496. end;
  1497. end;
  1498. end;
  1499. if RC <> 0 then
  1500. OSErrorWatch (RC);
  1501. if not (UniAPI) then
  1502. begin
  1503. Sys_UniCreateUConvObject := @DummyUniCreateUConvObject;
  1504. Sys_UniMapCpToUcsCp := @DummyUniMapCpToUcsCp;
  1505. Sys_UniFreeUConvObject := @DummyUniFreeUConvObject;
  1506. Sys_UniUConvFromUcs := @DummyUniUConvFromUcs;
  1507. Sys_UniUConvToUcs := @DummyUniUConvToUcs;
  1508. Sys_UniToLower := @DummyUniToLower;
  1509. Sys_UniToUpper := @DummyUniToUpper;
  1510. Sys_UniStrColl := @DummyUniStrColl;
  1511. Sys_UniCreateLocaleObject := @DummyUniCreateLocaleObject;
  1512. Sys_UniFreeLocaleObject := @DummyUniFreeLocaleObject;
  1513. InitDummyAnsiSupport;
  1514. end;
  1515. { Widestring }
  1516. WideStringManager.Wide2AnsiMoveProc := @OS2Unicode2AnsiMove;
  1517. WideStringManager.Ansi2WideMoveProc := @OS2Ansi2UnicodeMove;
  1518. WideStringManager.UpperWideStringProc := @OS2UpperUnicodeString;
  1519. WideStringManager.LowerWideStringProc := @OS2LowerUnicodeString;
  1520. WideStringManager.CompareWideStringProc := @OS2CompareUnicodeString;
  1521. WideStringManager.CompareTextWideStringProc := @OS2CompareTextUnicodeString;
  1522. { Unicode }
  1523. WideStringManager.Unicode2AnsiMoveProc := @OS2Unicode2AnsiMove;
  1524. WideStringManager.Ansi2UnicodeMoveProc := @OS2Ansi2UnicodeMove;
  1525. WideStringManager.UpperUnicodeStringProc := @OS2UpperUnicodeString;
  1526. WideStringManager.LowerUnicodeStringProc := @OS2LowerUnicodeString;
  1527. WideStringManager.CompareUnicodeStringProc := @OS2CompareUnicodeString;
  1528. WideStringManager.CompareTextUnicodeStringProc :=
  1529. @OS2CompareTextUnicodeString;
  1530. { Codepage }
  1531. WideStringManager.GetStandardCodePageProc := @OS2GetStandardCodePage;
  1532. (*
  1533. CharLengthPCharProc:=@CharLengthPChar;
  1534. CodePointLengthProc:=@CodePointLength;
  1535. *)
  1536. WideStringManager.UpperAnsiStringProc := @OS2UpperAnsiString;
  1537. WideStringManager.LowerAnsiStringProc := @OS2LowerAnsiString;
  1538. WideStringManager.CompareStrAnsiStringProc := @OS2CompareStrAnsiString;
  1539. WideStringManager.CompareTextAnsiStringProc := @OS2CompareTextAnsiString;
  1540. WideStringManager.StrCompAnsiStringProc := @OS2StrCompAnsiString;
  1541. WideStringManager.StrICompAnsiStringProc := @OS2StrICompAnsiString;
  1542. WideStringManager.StrLCompAnsiStringProc := @OS2StrLCompAnsiString;
  1543. WideStringManager.StrLICompAnsiStringProc := @OS2StrLICompAnsiString;
  1544. WideStringManager.StrLowerAnsiStringProc := @OS2StrLowerAnsiString;
  1545. WideStringManager.StrUpperAnsiStringProc := @OS2StrUpperAnsiString;
  1546. end;