sysucode.inc 49 KB

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