sysucode.inc 52 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723
  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); (* US with ISO 8859-1 *)
  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 is 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. function DummyUniMapCtryToLocale (CountryCode: cardinal; LocaleName: PWideChar;
  437. BufSize: longint): longint; cdecl;
  438. begin
  439. if BufSize = 0 then
  440. DummyUniMapCtryToLocale := Uls_Invalid
  441. else
  442. begin
  443. LocaleName^ := #0;
  444. DummyUniMapCtryToLocale := Uls_Unsupported;
  445. end;
  446. end;
  447. procedure InitDBCSLeadRanges;
  448. var
  449. RC: cardinal;
  450. begin
  451. RC := DosQueryDBCSEnv (SizeOf (DBCSLeadRanges), EmptyCC,
  452. @DBCSLeadRanges [0]);
  453. DBCSLeadRangesEnd := 0;
  454. if RC <> 0 then
  455. while (DBCSLeadRangesEnd < SizeOf (DBCSLeadRanges)) and
  456. ((DBCSLeadRanges [DBCSLeadRangesEnd] <> #0) or
  457. (DBCSLeadRanges [Succ (DBCSLeadRangesEnd)] <> #0)) do
  458. Inc (DBCSLeadRangesEnd, 2);
  459. end;
  460. procedure InitDummyAnsiSupport;
  461. var
  462. C: char;
  463. AllChars: array [char] of char;
  464. RetSize: cardinal;
  465. begin
  466. if DosQueryCollate (SizeOf (CollationSequence), EmptyCC, @CollationSequence,
  467. RetSize) <> 0 then
  468. Move (LowerChars, CollationSequence, SizeOf (CollationSequence));
  469. Move (LowerChars, AllChars, SizeOf (AllChars));
  470. if DosMapCase (SizeOf (AllChars), IsoCC, @AllChars [#0]) <> 0 then
  471. (* Codepage 819 may not be supported in all old OS/2 versions. *)
  472. begin
  473. Move (LowerCharsIso88591, AllChars, SizeOf (AllChars));
  474. DosMapCase (SizeOf (AllChars), EmptyCC, @AllChars [#0]);
  475. NoIso88591Support := true;
  476. end;
  477. for C := Low (char) to High (char) do
  478. if AllChars [C] <> C then
  479. LowerCharsIso88591 [AllChars [C]] := C;
  480. if NoIso88591Support then
  481. Move (LowerCharsIso88591, LowerChars, SizeOf (LowerChars))
  482. else
  483. begin
  484. Move (LowerChars, AllChars, SizeOf (AllChars));
  485. DosMapCase (SizeOf (AllChars), EmptyCC, @AllChars [#0]);
  486. for C := Low (char) to High (char) do
  487. if AllChars [C] <> C then
  488. LowerChars [AllChars [C]] := C;
  489. end;
  490. InitDBCSLeadRanges;
  491. end;
  492. procedure ReInitDummyAnsiSupport;
  493. var
  494. C: char;
  495. AllChars: array [char] of char;
  496. RetSize: cardinal;
  497. begin
  498. for C := Low (char) to High (char) do
  499. AllChars [C] := C;
  500. if DosQueryCollate (SizeOf (CollationSequence), EmptyCC, @CollationSequence,
  501. RetSize) <> 0 then
  502. Move (AllChars, CollationSequence, SizeOf (CollationSequence));
  503. DosMapCase (SizeOf (AllChars), EmptyCC, @AllChars [#0]);
  504. for C := Low (char) to High (char) do
  505. if AllChars [C] <> C then
  506. LowerChars [AllChars [C]] := C;
  507. InitDBCSLeadRanges;
  508. end;
  509. function DummyUniToLower (UniCharIn: WideChar): WideChar; cdecl;
  510. var
  511. C: char;
  512. begin
  513. C := UniCharIn;
  514. DummyUniToLower := LowerCharsIso88591 [C];
  515. end;
  516. function DummyUniToUpper (UniCharIn: WideChar): WideChar; cdecl;
  517. var
  518. C: char;
  519. begin
  520. DummyUniToUpper := UniCharIn;
  521. C := UniCharIn;
  522. if NoIso88591Support then
  523. begin
  524. if DosMapCase (1, EmptyCC, @C) = 0 then
  525. DummyUniToUpper := C;
  526. end
  527. else
  528. if DosMapCase (1, IsoCC, @C) = 0 then
  529. DummyUniToUpper := C
  530. end;
  531. function DummyUniStrColl (Locale_Object: TLocaleObject;
  532. const UCS1, UCS2: PWideChar): longint; cdecl;
  533. var
  534. S1, S2: ansistring;
  535. begin
  536. S1 := UCS1;
  537. S2 := UCS2;
  538. if S1 = S2 then
  539. DummyUniStrColl := 0
  540. else if S1 < S2 then
  541. DummyUniStrColl := -1
  542. else
  543. DummyUniStrColl := 1;
  544. end;
  545. function DummyUniCreateLocaleObject (LocaleSpecType: longint;
  546. const LocaleSpec: pointer; var Locale_Object: TLocaleObject): longint; cdecl;
  547. begin
  548. DummyUniCreateLocaleObject := ULS_Unsupported;
  549. end;
  550. function DummyUniFreeLocaleObject (Locale_Object: TLocaleObject): longint;
  551. cdecl;
  552. begin
  553. DummyUniFreeLocaleObject := ULS_BadObject;
  554. end;
  555. const
  556. CpXList: TCpXList = (
  557. (WinCP: CP_UTF8; OS2CP: 1208; UConvObj: nil),
  558. (WinCP: CP_ASCII; OS2CP: 367; UConvObj: nil),
  559. (WinCP: 28597; OS2CP: 813; UConvObj: nil),
  560. (WinCP: 28591; OS2CP: 819; UConvObj: nil),
  561. (WinCP: 28592; OS2CP: 912; UConvObj: nil),
  562. (WinCP: 28593; OS2CP: 913; UConvObj: nil),
  563. (WinCP: 28594; OS2CP: 914; UConvObj: nil),
  564. (WinCP: 28595; OS2CP: 915; UConvObj: nil),
  565. (WinCP: 28598; OS2CP: 916; UConvObj: nil),
  566. (WinCP: 28599; OS2CP: 920; UConvObj: nil),
  567. (WinCP: 28603; OS2CP: 921; UConvObj: nil),
  568. (WinCP: 28605; OS2CP: 923; UConvObj: nil),
  569. (WinCP: 10000; OS2CP: 1275; UConvObj: nil),
  570. (WinCP: 10006; OS2CP: 1280; UConvObj: nil),
  571. (WinCP: 10081; OS2CP: 1281; UConvObj: nil),
  572. (WinCP: 10029; OS2CP: 1282; UConvObj: nil),
  573. (WinCP: 10007; OS2CP: 1283; UConvObj: nil),
  574. (WinCP: 20273; OS2CP: 273; UConvObj: nil),
  575. (WinCP: 20277; OS2CP: 277; UConvObj: nil),
  576. (WinCP: 20278; OS2CP: 278; UConvObj: nil),
  577. (WinCP: 20280; OS2CP: 280; UConvObj: nil),
  578. (WinCP: 20284; OS2CP: 284; UConvObj: nil),
  579. (WinCP: 20285; OS2CP: 285; UConvObj: nil),
  580. (WinCP: 20290; OS2CP: 290; UConvObj: nil),
  581. (WinCP: 20297; OS2CP: 297; UConvObj: nil),
  582. (WinCP: 20420; OS2CP: 420; UConvObj: nil),
  583. (WinCP: 20424; OS2CP: 424; UConvObj: nil),
  584. (WinCP: 20833; OS2CP: 833; UConvObj: nil),
  585. (WinCP: 20838; OS2CP: 838; UConvObj: nil),
  586. (WinCP: 20866; OS2CP: 878; UConvObj: nil),
  587. (WinCP: 737; OS2CP: 851; UConvObj: nil),
  588. (WinCP: 20924; OS2CP: 924; UConvObj: nil),
  589. (WinCP: 20932; OS2CP: 932; UConvObj: nil),
  590. (WinCP: 20936; OS2CP: 936; UConvObj: nil),
  591. (WinCP: 21025; OS2CP: 1025; UConvObj: nil),
  592. (WinCP: CP_UTF16; OS2CP: CP_UTF16; UConvObj: nil),
  593. (WinCP: 37; OS2CP: 37; UConvObj: nil),
  594. (WinCP: 437; OS2CP: 437; UConvObj: nil),
  595. (WinCP: 500; OS2CP: 500; UConvObj: nil),
  596. (WinCP: 850; OS2CP: 850; UConvObj: nil),
  597. (WinCP: 852; OS2CP: 852; UConvObj: nil),
  598. (WinCP: 855; OS2CP: 855; UConvObj: nil),
  599. (WinCP: 857; OS2CP: 857; UConvObj: nil),
  600. (WinCP: 860; OS2CP: 860; UConvObj: nil),
  601. (WinCP: 861; OS2CP: 861; UConvObj: nil),
  602. (WinCP: 862; OS2CP: 862; UConvObj: nil),
  603. (WinCP: 863; OS2CP: 863; UConvObj: nil),
  604. (WinCP: 864; OS2CP: 864; UConvObj: nil),
  605. (WinCP: 865; OS2CP: 865; UConvObj: nil),
  606. (WinCP: 866; OS2CP: 866; UConvObj: nil),
  607. (WinCP: 869; OS2CP: 869; UConvObj: nil),
  608. (WinCP: 870; OS2CP: 870; UConvObj: nil),
  609. (WinCP: 874; OS2CP: 874; UConvObj: nil),
  610. (WinCP: 875; OS2CP: 875; UConvObj: nil),
  611. (WinCP: 949; OS2CP: 949; UConvObj: nil),
  612. (WinCP: 950; OS2CP: 950; UConvObj: nil),
  613. (WinCP: 1026; OS2CP: 1026; UConvObj: nil),
  614. (WinCP: 1047; OS2CP: 1047; UConvObj: nil),
  615. (WinCP: 1140; OS2CP: 1140; UConvObj: nil),
  616. (WinCP: 1141; OS2CP: 1141; UConvObj: nil),
  617. (WinCP: 1142; OS2CP: 1142; UConvObj: nil),
  618. (WinCP: 1143; OS2CP: 1143; UConvObj: nil),
  619. (WinCP: 1144; OS2CP: 1144; UConvObj: nil),
  620. (WinCP: 1145; OS2CP: 1145; UConvObj: nil),
  621. (WinCP: 1146; OS2CP: 1146; UConvObj: nil),
  622. (WinCP: 1147; OS2CP: 1147; UConvObj: nil),
  623. (WinCP: 1148; OS2CP: 1148; UConvObj: nil),
  624. (WinCP: 1149; OS2CP: 1149; UConvObj: nil),
  625. (WinCP: 1250; OS2CP: 1250; UConvObj: nil),
  626. (WinCP: 1251; OS2CP: 1251; UConvObj: nil),
  627. (WinCP: 1252; OS2CP: 1252; UConvObj: nil),
  628. (WinCP: 1253; OS2CP: 1253; UConvObj: nil),
  629. (WinCP: 1254; OS2CP: 1254; UConvObj: nil),
  630. (WinCP: 1255; OS2CP: 1255; UConvObj: nil),
  631. (WinCP: 1256; OS2CP: 1256; UConvObj: nil),
  632. (WinCP: 1257; OS2CP: 1257; UConvObj: nil)
  633. );
  634. (* Possibly add index tables for both directions and binary search??? *)
  635. {
  636. function GetRtlCpFromCpRec (const CpRec: TCpRec): TSystemCodepage; inline;
  637. begin
  638. if RtlUsesWinCp then
  639. GetRtlCp := CpRec.WinCP
  640. else
  641. GetRtlCp := TSystemCodepage (CpRec.Os2Cp);
  642. end;
  643. }
  644. function UConvObjectForCP (CP: cardinal; var UConvObj: TUConvObject): longint;
  645. var
  646. RC: longint;
  647. A: array [0..12] of WideChar;
  648. begin
  649. UConvObj := nil;
  650. RC := Sys_UniMapCpToUcsCp (CP, @A, 12);
  651. if RC = 0 then
  652. RC := Sys_UniCreateUconvObject (@A, UConvObj);
  653. {$WARNING: TODO: Deallocate some previously allocated UConvObj and try again if failed}
  654. UConvObjectForCP := RC;
  655. if RC <> 0 then
  656. OSErrorWatch (RC);
  657. end;
  658. procedure InitDefaultCP;
  659. var
  660. OS2CP, I: cardinal;
  661. NoUConvObj: TUConvObject;
  662. RCI: longint;
  663. RC: cardinal;
  664. CPArr: TCPArray;
  665. ReturnedSize: cardinal;
  666. WA: array [0..9] of WideChar; (* Even just 6 WideChars should be enough *)
  667. CI: TCountryInfo;
  668. begin
  669. if InInitDefaultCP <> -1 then
  670. begin
  671. repeat
  672. DosSleep (5);
  673. until InInitDefaultCP <> -1;
  674. Exit;
  675. end;
  676. InInitDefaultCP := ThreadID;
  677. if DefCpRec.UConvObj <> nil then
  678. begin
  679. (* Do not free the UConv object from DefCpRec, because it is also stored in
  680. the respective CPXList record! *)
  681. {
  682. RCI := Sys_UniFreeUConvObject (DefCpRec.UConvObj);
  683. if RCI <> 0 then
  684. OSErrorWatch (cardinal (RCI));
  685. }
  686. DefCpRec.UConvObj := nil;
  687. end;
  688. RC := DosQueryCP (SizeOf (CPArr), @CPArr, ReturnedSize);
  689. if (RC <> 0) and (RC <> 473) then
  690. begin
  691. OSErrorWatch (RC);
  692. CPArr [0] := 850;
  693. end
  694. else if (ReturnedSize < 4) then
  695. CPArr [0] := 850;
  696. DefaultFileSystemCodePage := OS2CPtoRtlCP (CPArr [0], cpxAll,
  697. DefCpRec.UConvObj);
  698. CachedDefFSCodepage := DefaultFileSystemCodePage;
  699. DefCpRec.OS2CP := CPArr [0];
  700. (* Find out WinCP _without_ considering RtlUsesWinCP *)
  701. I := 1;
  702. while (I <= MaxNonEqualCPMapping) and (CpXList [I].OS2CP <> DefCpRec.OS2CP)
  703. do
  704. Inc (I);
  705. if CpXList [I].OS2CP = CPArr [0] then
  706. DefCpRec.WinCP := CpXList [I].WinCP
  707. else
  708. DefCpRec.WinCP := CPArr [0];
  709. if DefLocObj <> nil then
  710. begin
  711. RCI := Sys_UniFreeLocaleObject (DefLocObj);
  712. if RCI <> 0 then
  713. OSErrorWatch (cardinal (RCI));
  714. DefLocObj := nil;
  715. end;
  716. if UniAPI then (* Do not bother with the locale object otherwise *)
  717. begin
  718. RCI := Sys_UniCreateLocaleObject (Uni_UCS_String_Pointer, @WNull, DefLocObj);
  719. if RCI <> 0 then
  720. begin
  721. OSErrorWatch (cardinal (RCI));
  722. DefLocObj := nil;
  723. (* The locale dependent routines like comparison require a valid locale *)
  724. (* setting, but the locale set using environment variable LANG is not *)
  725. (* recognized by OS/2 -> let's try to derive the locale from country *)
  726. RC := DosQueryCtryInfo (SizeOf (CI), EmptyCC, CI, ReturnedSize);
  727. if RC = 0 then
  728. begin
  729. RCI := Sys_UniMapCtryToLocale (CI.Country, @WA [0],
  730. SizeOf (WA) div SizeOf (WideChar));
  731. if RCI = 0 then
  732. begin
  733. RCI := Sys_UniCreateLocaleObject (Uni_UCS_String_Pointer, @WA [0],
  734. DefLocObj);
  735. if RCI <> 0 then
  736. begin
  737. OSErrorWatch (cardinal (RCI));
  738. DefLocObj := nil;
  739. end;
  740. end
  741. else
  742. OSErrorWatch (cardinal (RCI));
  743. end
  744. else
  745. OSErrorWatch (RC);
  746. if DefLocObj = nil then
  747. (* Still no success -> let's use the "Universal" locale as a fallback. *)
  748. begin
  749. RCI := Sys_UniCreateLocaleObject (Uni_UCS_String_Pointer, @WUniv [0],
  750. DefLocObj);
  751. if RCI <> 0 then
  752. begin
  753. OSErrorWatch (cardinal (RCI));
  754. DefLocObj := nil;
  755. end;
  756. end;
  757. end;
  758. end
  759. else (* not UniAPI *)
  760. ReInitDummyAnsiSupport;
  761. InInitDefaultCP := -1;
  762. end;
  763. function OS2CPtoRtlCP (CP: cardinal; ReqFlags: byte;
  764. var UConvObj: TUConvObject): TSystemCodepage;
  765. var
  766. I, I2: cardinal;
  767. RCI: longint;
  768. function CheckDefaultOS2CP: boolean;
  769. begin
  770. if CP = DefCpRec.OS2CP then
  771. begin
  772. CheckDefaultOS2CP := true;
  773. if RTLUsesWinCP then
  774. OS2CPtoRtlCP := DefCpRec.WinCP;
  775. if ReqFlags and CpxMappingOnly = 0 then
  776. UConvObj := DefCpRec.UConvObj;
  777. end
  778. else
  779. CheckDefaultOS2CP := false;
  780. end;
  781. begin
  782. OS2CPtoRtlCP := TSystemCodePage (CP);
  783. UConvObj := nil;
  784. if not UniAPI then (* No UniAPI => no need for UConvObj *)
  785. ReqFlags := ReqFlags or CpxMappingOnly;
  786. if CheckDefaultOS2CP then
  787. Exit;
  788. if (CachedDefFSCodepage <> DefaultFileSystemCodePage) and
  789. (InInitDefaultCP <> ThreadID) then
  790. (* InInitDefaultCP = ThreadID -> this thread is already re-initializing the cached information *)
  791. begin
  792. if InInitDefaultCP <> -1 then
  793. repeat
  794. DosSleep (5) (* Let's wait until the other thread finishes re-initialization of the cache *)
  795. until InInitDefaultCP = -1
  796. else
  797. InitDefaultCP;
  798. if CheckDefaultOS2CP then
  799. Exit;
  800. end;
  801. I := 1;
  802. if ReqFlags and CpxSpecial = CpxSpecial then
  803. I2 := 2
  804. else
  805. if ReqFlags and CpxMappingOnly = CpxMappingOnly then
  806. I2 := MaxNonEqualCPMapping
  807. else
  808. I2 := MaxCPMapping;
  809. while I <= I2 do
  810. begin
  811. if CP = CpXList [I].OS2CP then
  812. begin
  813. if RTLUsesWinCP then
  814. OS2CPtoRtlCP := CpXList [I].WinCP;
  815. if ReqFlags and CpxMappingOnly = 0 then
  816. begin
  817. if CpXList [I].UConvObj = nil then
  818. begin
  819. if UConvObjectForCP (CpXList [I].OS2CP, UConvObj) = Uls_Success then
  820. CpXList [I].UConvObj := UConvObj
  821. else
  822. UConvObj := nil;
  823. end
  824. else
  825. UConvObj := CpXList [I].UConvObj;
  826. end;
  827. Exit;
  828. end;
  829. Inc (I);
  830. end;
  831. (* If codepage was not found in the translation table and UConvObj is
  832. requested, allocate one in the temporary record. *)
  833. if ReqFlags and CpxMappingOnly = 0 then
  834. begin
  835. if TempCpRec.OS2CP = CP then
  836. UConvObj := TempCpRec.UConvObj
  837. else
  838. begin
  839. if TempCpRec.UConvObj <> nil then
  840. begin
  841. RCI := Sys_UniFreeUConvObject (TempCpRec.UConvObj);
  842. if RCI <> 0 then
  843. OSErrorWatch (cardinal (RCI));
  844. TempCpRec.UConvObj := nil;
  845. end;
  846. if UConvObjectForCP (CP, UConvObj) = Uls_Success then
  847. begin
  848. TempCpRec.UConvObj := UConvObj;
  849. TempCpRec.OS2CP := CP;
  850. end
  851. else
  852. UConvObj := nil;
  853. end;
  854. end;
  855. end;
  856. function RtlCPtoOS2CP (RtlCP: TSystemCodepage; ReqFlags: byte;
  857. var UConvObj: TUConvObject): cardinal;
  858. var
  859. I, I2: cardinal;
  860. function CheckDefaultWinCP: boolean;
  861. begin
  862. if RtlCP = DefCpRec.WinCP then
  863. begin
  864. CheckDefaultWinCP := true;
  865. RtlCPtoOS2CP := DefCpRec.WinCP;
  866. if ReqFlags and CpxMappingOnly = 0 then
  867. UConvObj := DefCpRec.UConvObj;
  868. end
  869. else
  870. CheckDefaultWinCP := false;
  871. end;
  872. begin
  873. RtlCPtoOS2CP := RtlCP;
  874. UConvObj := nil;
  875. if not UniAPI then (* No UniAPI => no need for UConvObj *)
  876. ReqFlags := ReqFlags or CpxMappingOnly;
  877. if not (RTLUsesWinCP) then
  878. begin
  879. if ReqFlags and CpxMappingOnly = 0 then
  880. OS2CPtoRtlCP (cardinal (RtlCp), ReqFlags, UConvObj);
  881. end
  882. else if CheckDefaultWinCp then
  883. Exit
  884. else
  885. begin
  886. if (CachedDefFSCodepage <> DefaultFileSystemCodePage) and
  887. (InInitDefaultCP <> ThreadID) then
  888. (* InInitDefaultCP = ThreadID -> this thread is already re-initializing the cached information *)
  889. begin
  890. if InInitDefaultCP <> -1 then
  891. repeat
  892. (* Let's wait until the other thread finishes re-initialization of the cache *)
  893. DosSleep (5)
  894. until InInitDefaultCP = -1
  895. else
  896. InitDefaultCP;
  897. if CheckDefaultWinCP then
  898. Exit;
  899. end;
  900. I := 1;
  901. if ReqFlags and CpxSpecial = CpxSpecial then
  902. I2 := 2
  903. else
  904. if ReqFlags and CpxMappingOnly = CpxMappingOnly then
  905. I2 := MaxNonEqualCPMapping
  906. else
  907. I2 := MaxCPMapping;
  908. while I <= I2 do
  909. begin
  910. if RtlCP = CpXList [I].WinCP then
  911. begin
  912. RtlCPtoOS2CP := CpXList [I].OS2CP;
  913. if ReqFlags and CpxMappingOnly = 0 then
  914. begin
  915. begin
  916. if UConvObjectForCP (CpXList [I].OS2CP, UConvObj) = Uls_Success then
  917. CpXList [I].UConvObj := UConvObj
  918. else
  919. UConvObj := nil;
  920. end
  921. end;
  922. Exit;
  923. end;
  924. Inc (I);
  925. end;
  926. (*
  927. Special processing for
  928. ExceptionWinCodepages = (CP_UTF16BE, CP_UTF7, 12000 {UTF32}, 12001 {UTF32BE})
  929. might be added here...or not ;-)
  930. if (TempCpRec.OS2CP <> High (TempCpRec.OS2CP)) or
  931. (TempCpRec.WinCP <> RtlCp) then
  932. begin
  933. if TempCpRec.UConvObj <> nil then
  934. begin
  935. RCI := Sys_UniFreeUConvObject (TempCpRec.UConvObj);
  936. if RCI <> 0 then
  937. OSErrorWatch (cardinal (RCI));
  938. end;
  939. TempCpRec.OS2CP := High (TempCpRec.OS2CP);
  940. TempCpRec.WinCP := RtlCp;
  941. end;
  942. Map to CP_ASCII aka OS2CP=367 if RtlCP not recognized and UConvObject
  943. is requested???
  944. *)
  945. (* Signalize unrecognized (untranslatable) MS Windows codepage *)
  946. OSErrorWatch (Uls_Invalid);
  947. end;
  948. end;
  949. function OS2CPtoRtlCP (CP: cardinal; ReqFlags: byte): TSystemCodepage;
  950. var
  951. NoUConvObj: TUConvObject;
  952. begin
  953. if RtlUsesWinCP then
  954. OS2CPtoRtlCP := OS2CPtoRtlCP (CP, ReqFlags or CpxMappingOnly, NoUConvObj)
  955. else
  956. OS2CPtoRtlCP := TSystemCodepage (CP);
  957. end;
  958. function RtlCPtoOS2CP (RtlCP: TSystemCodepage; ReqFlags: byte): cardinal;
  959. var
  960. NoUConvObj: TUConvObject;
  961. begin
  962. if RtlUsesWinCP then
  963. RtlCPtoOS2CP := RtlCPtoOS2CP (RtlCP, ReqFlags or CpxMappingOnly, NoUConvObj)
  964. else
  965. RtlCPtoOS2CP := RtlCP;
  966. end;
  967. procedure OS2Unicode2AnsiMove (Source: PUnicodeChar; var Dest: RawByteString;
  968. CP: TSystemCodePage; Len: SizeInt);
  969. var
  970. RCI: longint;
  971. UConvObj: TUConvObject;
  972. OS2CP: cardinal;
  973. Src2: PUnicodeChar;
  974. Len2, LenOut, OutOffset, NonIdentical: longint;
  975. Dest2: PChar;
  976. begin
  977. OS2CP := RtlCpToOS2CP (CP, CpxAll, UConvObj);
  978. { if UniAPI and (UConvObj = nil) then - OS2Unicode2AnsiMove should be never called if not UniAPI }
  979. if UConvObj = nil then
  980. begin
  981. {$WARNING Special cases like UTF-7 should be handled here, otherwise signalize error - how???}
  982. DefaultUnicode2AnsiMove (Source, Dest, CP, Len);
  983. Exit;
  984. end;
  985. LenOut := Succ (Len); (* Standard OS/2 CP is a SBCS *)
  986. SetLength (Dest, LenOut);
  987. SetCodePage (Dest, CP, false);
  988. Src2 := Source;
  989. Len2 := Len;
  990. Dest2 := PChar (Dest);
  991. RCI := Sys_UniUConvFromUcs (UConvObj, Src2, Len2, Dest2, LenOut,
  992. NonIdentical);
  993. repeat
  994. case RCI of
  995. Uls_Success:
  996. begin
  997. if LenOut > 0 then
  998. SetLength (Dest, Length (Dest) - LenOut);
  999. Break;
  1000. end;
  1001. Uls_IllegalSequence:
  1002. begin
  1003. OSErrorWatch (Uls_IllegalSequence);
  1004. { skip and set to '?' }
  1005. Inc (Src2);
  1006. Dec (Len2);
  1007. Dest2^ := '?';
  1008. Inc (Dest2);
  1009. Dec (LenOut);
  1010. end;
  1011. Uls_BufferFull:
  1012. begin
  1013. OutOffset := Dest2 - PChar (Dest);
  1014. (* Use Len2 or Len decreased by difference between Source and Src2? *)
  1015. (* Extend more this time - target is probably a DBCS or UTF-8 *)
  1016. SetLength (Dest, Length (Dest) + Succ (Len2 * 2));
  1017. { string could have been moved }
  1018. Dest2 := PChar (Dest) + OutOffset;
  1019. Inc (LenOut, Succ (Len2 * 2));
  1020. end
  1021. else
  1022. begin
  1023. SetLength (Dest, 0);
  1024. OSErrorWatch (cardinal (RCI));
  1025. { Break }
  1026. RunError (231);
  1027. end;
  1028. end;
  1029. RCI := Sys_UniUConvFromUcs (UConvObj, Src2, Len2, Dest2, LenOut,
  1030. NonIdentical);
  1031. until false;
  1032. end;
  1033. procedure OS2Ansi2UnicodeMove (Source: PChar; CP: TSystemCodePage;
  1034. var Dest: UnicodeString; Len: SizeInt);
  1035. var
  1036. RCI: longint;
  1037. UConvObj: TUConvObject;
  1038. OS2CP: cardinal;
  1039. Src2: PChar;
  1040. Len2, LenOut, OutOffset, NonIdentical: longint;
  1041. Dest2: PWideChar;
  1042. begin
  1043. OS2CP := RtlCpToOS2CP (CP, CpxAll, UConvObj);
  1044. { if UniAPI and (UConvObj = nil) then - OS2Unicode2AnsiMove should be never called if not UniAPI }
  1045. if UConvObj = nil then
  1046. begin
  1047. {$WARNING Special cases like UTF-7 should be handled here, otherwise signalize error - how???}
  1048. DefaultAnsi2UnicodeMove (Source, CP, Dest, Len);
  1049. Exit;
  1050. end;
  1051. LenOut := Succ (Len); (* Standard OS/2 CP is a SBCS *)
  1052. SetLength (Dest, LenOut);
  1053. Src2 := Source;
  1054. Len2 := Len;
  1055. Dest2 := PWideChar (Dest);
  1056. RCI := Sys_UniUConvToUcs (UConvObj, Src2, Len2, Dest2, LenOut, NonIdentical);
  1057. repeat
  1058. case RCI of
  1059. Uls_Success:
  1060. begin
  1061. if LenOut > 0 then
  1062. SetLength (Dest, Length (Dest) - LenOut);
  1063. Break;
  1064. end;
  1065. Uls_IllegalSequence:
  1066. begin
  1067. OSErrorWatch (Uls_IllegalSequence);
  1068. { skip and set to '?' }
  1069. Inc (Src2);
  1070. Dec (Len2);
  1071. Dest2^ := '?';
  1072. Inc (Dest2);
  1073. Dec (LenOut);
  1074. end;
  1075. Uls_BufferFull:
  1076. begin
  1077. OutOffset := Dest2 - PWideChar (Dest);
  1078. (* Use Len2 or Len decreased by difference between Source and Src2? *)
  1079. SetLength (Dest, Length (Dest) + Succ (Len2));
  1080. { string could have been moved }
  1081. Dest2 := PWideChar (Dest) + OutOffset;
  1082. Inc (LenOut, Succ (Len2));
  1083. end
  1084. else
  1085. begin
  1086. SetLength (Dest, 0);
  1087. OSErrorWatch (cardinal (RCI));
  1088. { Break }
  1089. RunError (231);
  1090. end;
  1091. end;
  1092. RCI := Sys_UniUConvToUcs (UConvObj, Src2, Len2, Dest2, LenOut,
  1093. NonIdentical);
  1094. until false;
  1095. end;
  1096. function RtlChangeCP (CP: TSystemCodePage): longint;
  1097. var
  1098. OS2CP, I: cardinal;
  1099. NoUConvObj: TUConvObject;
  1100. RCI: longint;
  1101. begin
  1102. OS2CP := RtlCpToOS2Cp (CP, cpxMappingOnly, NoUConvObj);
  1103. RtlChangeCP := longint (DosSetProcessCP (OS2CP));
  1104. if RtlChangeCP <> 0 then
  1105. OSErrorWatch (RtlChangeCP)
  1106. else
  1107. begin
  1108. DefaultSystemCodePage := CP;
  1109. DefaultRTLFileSystemCodePage := DefaultSystemCodePage;
  1110. DefaultFileSystemCodePage := DefaultSystemCodePage;
  1111. if OS2CP <> DefCpRec.OS2CP then
  1112. begin
  1113. if DefCpRec.UConvObj <> nil then
  1114. begin
  1115. (* Do not free the UConv object from DefCpRec, because it is also stored in
  1116. the respective CpXList record! *)
  1117. {
  1118. RCI := Sys_UniFreeUConvObject (DefCpRec.UConvObj);
  1119. if RCI <> 0 then
  1120. OSErrorWatch (cardinal (RCI));
  1121. }
  1122. DefCpRec.UConvObj := nil;
  1123. end;
  1124. DefCPRec.OS2CP := OS2CP;
  1125. RCI := Sys_UniCreateUConvObject (@WNull, DefCpRec.UConvObj);
  1126. if RCI <> 0 then
  1127. OSErrorWatch (cardinal (RCI));
  1128. (* Find out WinCP _without_ considering RtlUsesWinCP *)
  1129. I := 1;
  1130. while (I <= MaxNonEqualCPMapping) and (CpXList [I].OS2CP <> OS2CP) do
  1131. Inc (I);
  1132. if CpXList [I].OS2CP = OS2CP then
  1133. DefCpRec.WinCP := CpXList [I].WinCP
  1134. else
  1135. DefCpRec.WinCP := OS2CP;
  1136. end;
  1137. end;
  1138. end;
  1139. function OS2UpperUnicodeString (const S: UnicodeString): UnicodeString;
  1140. var
  1141. I: cardinal;
  1142. begin
  1143. SetLength (Result, Length (S));
  1144. if Length (S) > 0 then
  1145. for I := 0 to Pred (Length (S)) do
  1146. PWideChar (Result) [I] := Sys_UniToUpper (S [Succ (I)]);
  1147. end;
  1148. function OS2LowerUnicodeString (const S: UnicodeString): UnicodeString;
  1149. var
  1150. I: cardinal;
  1151. begin
  1152. SetLength (Result, Length (S));
  1153. if Length (S) > 0 then
  1154. for I := 0 to Pred (Length (S)) do
  1155. PWideChar (Result) [I] := Sys_UniToLower (S [Succ (I)]);
  1156. end;
  1157. function NoNullsUnicodeString (const S: UnicodeString): UnicodeString;
  1158. var
  1159. I: cardinal;
  1160. begin
  1161. Result := S;
  1162. UniqueString (Result);
  1163. if Length (S) > 0 then
  1164. for I := 1 to Length (S) do
  1165. if Result [I] = WNull then
  1166. Result [I] := ' ';
  1167. end;
  1168. function OS2CompareUnicodeString (const S1, S2: UnicodeString): PtrInt;
  1169. var
  1170. HS1, HS2: UnicodeString;
  1171. begin
  1172. { UniStrColl interprets null chars as end-of-string -> filter out }
  1173. HS1 := NoNullsUnicodeString (S1);
  1174. HS2 := NoNullsUnicodeString (S2);
  1175. Result := Sys_UniStrColl (DefLocObj, PWideChar (HS1), PWideChar (HS2));
  1176. if Result < -1 then
  1177. Result := -1
  1178. else if Result > 1 then
  1179. Result := 1;
  1180. end;
  1181. function OS2CompareTextUnicodeString (const S1, S2: UnicodeString): PtrInt;
  1182. begin
  1183. Result := OS2CompareUnicodeString (OS2UpperUnicodeString (S1),
  1184. OS2UpperUnicodeString (S2));
  1185. {$WARNING Language independent uppercase routine may not be appropriate for language dependent case insensitive comparison!}
  1186. end;
  1187. function OS2UpperAnsiString (const S: AnsiString): AnsiString;
  1188. var
  1189. RC: cardinal;
  1190. begin
  1191. Result := S;
  1192. UniqueString (Result);
  1193. FillChar (EmptyCC, SizeOf (EmptyCC), 0);
  1194. RC := DosMapCase (Length (Result), EmptyCC, PChar (Result));
  1195. { What to do in case of a failure??? }
  1196. if RC <> 0 then
  1197. Result := UpCase (S); { Use a fallback? }
  1198. end;
  1199. function OS2LowerAnsiString (const S: AnsiString): AnsiString;
  1200. var
  1201. I: PtrUInt;
  1202. function IsDBCSLeadChar (C: char): boolean;
  1203. var
  1204. D: byte;
  1205. begin
  1206. IsDBCSLeadChar := false;
  1207. D := 0;
  1208. while D < DBCSLeadRangesEnd do
  1209. begin
  1210. if (C >= DBCSLeadRanges [D]) and (C <= DBCSLeadRanges [Succ (D)]) then
  1211. begin
  1212. IsDBCSLeadChar := true;
  1213. Exit;
  1214. end;
  1215. Inc (D, 2);
  1216. end;
  1217. end;
  1218. begin
  1219. (*
  1220. OS/2 provides no direct solution for lowercase conversion of MBCS strings.
  1221. If Unicode support is available, using Unicode routines is the best solution.
  1222. If not, we use a translation table built at startup by translating the full
  1223. character set to uppercase and using that for creation of a lookup table
  1224. (as already done in sysutils). However, we need to check for DBCS (MBCS)
  1225. codepages and avoid translating the DBCS lead bytes and the following
  1226. character.
  1227. *)
  1228. if UniAPI then
  1229. Result := AnsiString (OS2LowerUnicodeString (UnicodeString (S)))
  1230. else
  1231. begin
  1232. Result := S;
  1233. if Length (Result) > 0 then
  1234. begin
  1235. UniqueString (Result);
  1236. if DBCSLeadRangesEnd > 0 then
  1237. begin
  1238. I := 1;
  1239. while I <= Length (Result) do
  1240. begin
  1241. if IsDBCSLeadChar (Result [I]) then
  1242. Inc (I, 2)
  1243. else
  1244. begin
  1245. Result [I] := LowerChars [Result [I]];
  1246. Inc (I);
  1247. end;
  1248. end;
  1249. end
  1250. else
  1251. for I := 1 to Length (Result) do
  1252. Result [I] := LowerChars [Result [I]];
  1253. end;
  1254. end;
  1255. end;
  1256. function OS2CompareStrAnsiString (const S1, S2: AnsiString): PtrInt;
  1257. var
  1258. I, MaxLen: PtrUInt;
  1259. begin
  1260. if UniAPI then
  1261. Result := OS2CompareUnicodeString (UnicodeString (S1), UnicodeString (S2))
  1262. else
  1263. (* Older OS/2 versions without Unicode support do not provide direct means *)
  1264. (* for case sensitive and codepage and language-aware string comparison. *)
  1265. (* We have to resort to manual comparison of the original strings together *)
  1266. (* with strings translated using the case insensitive collation sequence. *)
  1267. begin
  1268. if Length (S1) = 0 then
  1269. begin
  1270. if Length (S2) = 0 then
  1271. Result := 0
  1272. else
  1273. Result := -1;
  1274. Exit;
  1275. end
  1276. else
  1277. if Length (S2) = 0 then
  1278. begin
  1279. Result := 1;
  1280. Exit;
  1281. end;
  1282. I := 1;
  1283. MaxLen := Length (S1);
  1284. if Length (S2) < MaxLen then
  1285. MaxLen := Length (S2);
  1286. repeat
  1287. if CollationSequence [S1 [I]] = CollationSequence [S2 [I]] then
  1288. begin
  1289. if S1 [I] < S2 [I] then
  1290. begin
  1291. Result := -1;
  1292. Exit;
  1293. end
  1294. else if S1 [I] > S2 [I] then
  1295. begin
  1296. Result := 1;
  1297. Exit;
  1298. end;
  1299. end
  1300. else
  1301. begin
  1302. if CollationSequence [S1 [I]] < CollationSequence [S2 [I]] then
  1303. Result := -1
  1304. else
  1305. Result := 1;
  1306. Exit;
  1307. end;
  1308. Inc (I);
  1309. until (I > MaxLen);
  1310. if Length (S2) > MaxLen then
  1311. Result := -1
  1312. else if Length (S1) > MaxLen then
  1313. Result := 1
  1314. else
  1315. Result := 0;
  1316. end;
  1317. end;
  1318. function OS2StrCompAnsiString (S1, S2: PChar): PtrInt;
  1319. var
  1320. HSA1, HSA2: AnsiString;
  1321. HSU1, HSU2: UnicodeString;
  1322. begin
  1323. (* Do not call OS2CompareUnicodeString to skip scanning for #0. *)
  1324. HSA1 := AnsiString (S1);
  1325. HSA2 := AnsiString (S2);
  1326. if UniApi then
  1327. begin
  1328. HSU1 := UnicodeString (HSA1);
  1329. HSU2 := UnicodeString (HSA2);
  1330. Result := Sys_UniStrColl (DefLocObj, PWideChar (HSU1), PWideChar (HSU2));
  1331. if Result < -1 then
  1332. Result := -1
  1333. else if Result > 1 then
  1334. Result := 1;
  1335. end
  1336. else
  1337. Result := OS2CompareStrAnsiString (HSA1, HSA2);
  1338. end;
  1339. function OS2CompareTextAnsiString (const S1, S2: AnsiString): PtrInt;
  1340. var
  1341. HSA1, HSA2: AnsiString;
  1342. I: PtrUInt;
  1343. begin
  1344. if UniAPI then
  1345. Result := OS2CompareTextUnicodeString (UnicodeString (S1),
  1346. UnicodeString (S2))
  1347. else
  1348. begin
  1349. (* Let's use collation strings here as a fallback *)
  1350. SetLength (HSA1, Length (S1));
  1351. if Length (HSA1) > 0 then
  1352. (* Using assembler would be much faster, but never mind... *)
  1353. for I := 1 to Length (HSA1) do
  1354. HSA1 [I] := CollationSequence [S1 [I]];
  1355. {$WARNING Results of using collation sequence with DBCS not known/tested!}
  1356. SetLength (HSA2, Length (S2));
  1357. if Length (HSA2) > 0 then
  1358. for I := 1 to Length (HSA2) do
  1359. HSA2 [I] := CollationSequence [S2 [I]];
  1360. if HSA1 = HSA2 then
  1361. Result := 0
  1362. else if HSA1 < HSA2 then
  1363. Result := -1
  1364. else
  1365. Result := 1;
  1366. end;
  1367. end;
  1368. function OS2StrICompAnsiString (S1, S2: PChar): PtrInt;
  1369. begin
  1370. Result := OS2CompareTextAnsiString (AnsiString (S1), AnsiString (S2));
  1371. end;
  1372. function OS2StrLCompAnsiString (S1, S2: PChar; MaxLen: PtrUInt): PtrInt;
  1373. var
  1374. A, B: AnsiString;
  1375. begin
  1376. if (MaxLen = 0) then
  1377. Exit (0);
  1378. SetLength (A, MaxLen);
  1379. Move (S1^, A [1], MaxLen);
  1380. SetLength (B, MaxLen);
  1381. Move (S2^, B [1], MaxLen);
  1382. Result := OS2CompareStrAnsiString (A, B);
  1383. end;
  1384. function OS2StrLICompAnsiString (S1, S2: PChar; MaxLen: PtrUInt): PtrInt;
  1385. var
  1386. A, B: AnsiString;
  1387. begin
  1388. if (MaxLen = 0) then
  1389. Exit (0);
  1390. SetLength (A, MaxLen);
  1391. Move (S1^, A [1], MaxLen);
  1392. SetLength (B, MaxLen);
  1393. Move (S2^, B [1], MaxLen);
  1394. Result := OS2CompareTextAnsiString (A, B);
  1395. end;
  1396. procedure FPC_RangeError; [external name 'FPC_RANGEERROR'];
  1397. procedure Ansi2PChar (const S: AnsiString; const OrgP: PChar; out P: Pchar);
  1398. var
  1399. NewLen: SizeUInt;
  1400. begin
  1401. NewLen := Length (S);
  1402. if NewLen > StrLen (OrgP) then
  1403. FPC_RangeError;
  1404. P := OrgP;
  1405. if (NewLen > 0) then
  1406. Move (S [1], P [0], NewLen);
  1407. P [NewLen] := #0;
  1408. end;
  1409. function OS2StrUpperAnsiString (Str: PChar): PChar;
  1410. var
  1411. Temp: AnsiString;
  1412. begin
  1413. Temp := OS2UpperAnsiString (Str);
  1414. Ansi2PChar (Temp, Str, Result);
  1415. end;
  1416. function OS2StrLowerAnsiString (Str: PChar): PChar;
  1417. var
  1418. Temp: AnsiString;
  1419. begin
  1420. Temp := OS2LowerAnsiString (Str);
  1421. Ansi2PChar (Temp, Str, Result);
  1422. end;
  1423. (*
  1424. CWSTRING:
  1425. { return value: number of code points in the string. Whenever an invalid
  1426. code point is encountered, all characters part of this invalid code point
  1427. are considered to form one "character" and the next character is
  1428. considered to be the start of a new (possibly also invalid) code point }
  1429. function CharLengthPChar(const Str: PChar): PtrInt;
  1430. var
  1431. nextlen: ptrint;
  1432. s: pchar;
  1433. {$ifndef beos}
  1434. mbstate: mbstate_t;
  1435. {$endif not beos}
  1436. begin
  1437. result:=0;
  1438. s:=str;
  1439. {$ifndef beos}
  1440. fillchar(mbstate,sizeof(mbstate),0);
  1441. {$endif not beos}
  1442. repeat
  1443. {$ifdef beos}
  1444. nextlen:=ptrint(mblen(s,MB_CUR_MAX));
  1445. {$else beos}
  1446. nextlen:=ptrint(mbrlen(s,MB_CUR_MAX,@mbstate));
  1447. {$endif beos}
  1448. { skip invalid/incomplete sequences }
  1449. if (nextlen<0) then
  1450. nextlen:=1;
  1451. inc(result,1);
  1452. inc(s,nextlen);
  1453. until (nextlen=0);
  1454. end;
  1455. function CodePointLength(const Str: PChar; maxlookahead: ptrint): PtrInt;
  1456. var
  1457. nextlen: ptrint;
  1458. {$ifndef beos}
  1459. mbstate: mbstate_t;
  1460. {$endif not beos}
  1461. begin
  1462. {$ifdef beos}
  1463. result:=ptrint(mblen(str,maxlookahead));
  1464. {$else beos}
  1465. fillchar(mbstate,sizeof(mbstate),0);
  1466. result:=ptrint(mbrlen(str,maxlookahead,@mbstate));
  1467. { mbrlen can also return -2 for "incomplete but potially valid character
  1468. and data has been processed" }
  1469. if result<0 then
  1470. result:=-1;
  1471. {$endif beos}
  1472. end;
  1473. *)
  1474. procedure InitOS2WideStringManager; inline;
  1475. var
  1476. RC: cardinal;
  1477. ErrName: array [0..MaxPathLen] of char;
  1478. P: pointer;
  1479. begin
  1480. RC := DosLoadModule (@ErrName [0], SizeOf (ErrName), @UConvName [0],
  1481. UConvHandle);
  1482. if RC = 0 then
  1483. begin
  1484. RC := DosQueryProcAddr (UConvHandle, OrdUniCreateUConvObject, nil, P);
  1485. if RC = 0 then
  1486. begin
  1487. Sys_UniCreateUConvObject := TUniCreateUConvObject (P);
  1488. RC := DosQueryProcAddr (UConvHandle, OrdUniMapCpToUcsCp, nil, P);
  1489. if RC = 0 then
  1490. begin
  1491. Sys_UniMapCpToUcsCp := TUniMapCpToUcsCp (P);
  1492. RC := DosQueryProcAddr (UConvHandle, OrdUniFreeUConvObject, nil, P);
  1493. if RC = 0 then
  1494. begin
  1495. Sys_UniFreeUConvObject := TUniFreeUConvObject (P);
  1496. RC := DosQueryProcAddr (UConvHandle, OrdUniUConvFromUcs, nil, P);
  1497. if RC = 0 then
  1498. begin
  1499. Sys_UniUConvFromUcs := TUniUConvFromUcs (P);
  1500. RC := DosQueryProcAddr (UConvHandle, OrdUniUConvToUcs, nil, P);
  1501. if RC = 0 then
  1502. begin
  1503. Sys_UniUConvToUcs := TUniUConvToUcs (P);
  1504. RC := DosLoadModule (@ErrName [0], SizeOf (ErrName),
  1505. @LibUniName [0], LibUniHandle);
  1506. if RC = 0 then
  1507. begin
  1508. RC := DosQueryProcAddr (LibUniHandle, OrdUniToLower, nil, P);
  1509. if RC = 0 then
  1510. begin
  1511. Sys_UniToLower := TUniToLower (P);
  1512. RC := DosQueryProcAddr (LibUniHandle, OrdUniToUpper, nil, P);
  1513. if RC = 0 then
  1514. begin
  1515. Sys_UniToUpper := TUniToUpper (P);
  1516. RC := DosQueryProcAddr (LibUniHandle, OrdUniStrColl, nil,
  1517. P);
  1518. if RC = 0 then
  1519. begin
  1520. Sys_UniStrColl := TUniStrColl (P);
  1521. RC := DosQueryProcAddr (LibUniHandle,
  1522. OrdUniCreateLocaleObject, nil, P);
  1523. if RC = 0 then
  1524. begin
  1525. Sys_UniCreateLocaleObject := TUniCreateLocaleObject
  1526. (P);
  1527. RC := DosQueryProcAddr (LibUniHandle,
  1528. OrdUniFreeLocaleObject, nil, P);
  1529. if RC = 0 then
  1530. begin
  1531. Sys_UniFreeLocaleObject := TUniFreeLocaleObject (P);
  1532. RC := DosQueryProcAddr (LibUniHandle,
  1533. OrdUniMapCtryToLocale, nil, P);
  1534. if RC = 0 then
  1535. begin
  1536. Sys_UniMapCtryToLocale := TUniMapCtryToLocale (P);
  1537. UniAPI := true;
  1538. end;
  1539. end;
  1540. end;
  1541. end;
  1542. end;
  1543. end;
  1544. end;
  1545. end;
  1546. end;
  1547. end;
  1548. end;
  1549. end;
  1550. end;
  1551. if RC <> 0 then
  1552. OSErrorWatch (RC);
  1553. if not (UniAPI) then
  1554. begin
  1555. Sys_UniCreateUConvObject := @DummyUniCreateUConvObject;
  1556. Sys_UniMapCpToUcsCp := @DummyUniMapCpToUcsCp;
  1557. Sys_UniFreeUConvObject := @DummyUniFreeUConvObject;
  1558. Sys_UniUConvFromUcs := @DummyUniUConvFromUcs;
  1559. Sys_UniUConvToUcs := @DummyUniUConvToUcs;
  1560. Sys_UniToLower := @DummyUniToLower;
  1561. Sys_UniToUpper := @DummyUniToUpper;
  1562. Sys_UniStrColl := @DummyUniStrColl;
  1563. Sys_UniCreateLocaleObject := @DummyUniCreateLocaleObject;
  1564. Sys_UniFreeLocaleObject := @DummyUniFreeLocaleObject;
  1565. Sys_UniMapCtryToLocale := @DummyUniMapCtryToLocale;
  1566. InitDummyAnsiSupport;
  1567. end;
  1568. { Widestring }
  1569. WideStringManager.Wide2AnsiMoveProc := @OS2Unicode2AnsiMove;
  1570. WideStringManager.Ansi2WideMoveProc := @OS2Ansi2UnicodeMove;
  1571. WideStringManager.UpperWideStringProc := @OS2UpperUnicodeString;
  1572. WideStringManager.LowerWideStringProc := @OS2LowerUnicodeString;
  1573. WideStringManager.CompareWideStringProc := @OS2CompareUnicodeString;
  1574. WideStringManager.CompareTextWideStringProc := @OS2CompareTextUnicodeString;
  1575. { Unicode }
  1576. WideStringManager.Unicode2AnsiMoveProc := @OS2Unicode2AnsiMove;
  1577. WideStringManager.Ansi2UnicodeMoveProc := @OS2Ansi2UnicodeMove;
  1578. WideStringManager.UpperUnicodeStringProc := @OS2UpperUnicodeString;
  1579. WideStringManager.LowerUnicodeStringProc := @OS2LowerUnicodeString;
  1580. WideStringManager.CompareUnicodeStringProc := @OS2CompareUnicodeString;
  1581. WideStringManager.CompareTextUnicodeStringProc :=
  1582. @OS2CompareTextUnicodeString;
  1583. { Codepage }
  1584. WideStringManager.GetStandardCodePageProc := @OS2GetStandardCodePage;
  1585. (*
  1586. CharLengthPCharProc:=@CharLengthPChar;
  1587. CodePointLengthProc:=@CodePointLength;
  1588. *)
  1589. WideStringManager.UpperAnsiStringProc := @OS2UpperAnsiString;
  1590. WideStringManager.LowerAnsiStringProc := @OS2LowerAnsiString;
  1591. WideStringManager.CompareStrAnsiStringProc := @OS2CompareStrAnsiString;
  1592. WideStringManager.CompareTextAnsiStringProc := @OS2CompareTextAnsiString;
  1593. WideStringManager.StrCompAnsiStringProc := @OS2StrCompAnsiString;
  1594. WideStringManager.StrICompAnsiStringProc := @OS2StrICompAnsiString;
  1595. WideStringManager.StrLCompAnsiStringProc := @OS2StrLCompAnsiString;
  1596. WideStringManager.StrLICompAnsiStringProc := @OS2StrLICompAnsiString;
  1597. WideStringManager.StrLowerAnsiStringProc := @OS2StrLowerAnsiString;
  1598. WideStringManager.StrUpperAnsiStringProc := @OS2StrUpperAnsiString;
  1599. end;