sysucode.inc 51 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725
  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 <> OS2CP) do
  703. Inc (I);
  704. if CpXList [I].OS2CP = CPArr [0] then
  705. DefCpRec.WinCP := CpXList [I].WinCP
  706. else
  707. DefCpRec.WinCP := CPArr [0];
  708. if DefLocObj <> nil then
  709. begin
  710. RCI := Sys_UniFreeLocaleObject (DefLocObj);
  711. if RCI <> 0 then
  712. OSErrorWatch (cardinal (RCI));
  713. DefLocObj := nil;
  714. end;
  715. if UniAPI then (* Do not bother with the locale object otherwise *)
  716. begin
  717. RCI := Sys_UniCreateLocaleObject (Uni_UCS_String_Pointer, @WNull, DefLocObj);
  718. if RCI <> 0 then
  719. begin
  720. OSErrorWatch (cardinal (RCI));
  721. DefLocObj := nil;
  722. (* The locale dependent routines like comparison require a valid locale *)
  723. (* setting, but the locale set using environment variable LANG is not *)
  724. (* recognized by OS/2 -> let's try to derive the locale from country *)
  725. RC := DosQueryCtryInfo (SizeOf (CI), EmptyCC, CI, ReturnedSize);
  726. if RC = 0 then
  727. begin
  728. RCI := Sys_UniMapCtryToLocale (CI.Country, @WA [0],
  729. SizeOf (WA) div SizeOf (WideChar));
  730. if RCI = 0 then
  731. begin
  732. RCI := Sys_UniCreateLocaleObject (Uni_UCS_String_Pointer, @WA [0],
  733. DefLocObj);
  734. if RCI <> 0 then
  735. begin
  736. OSErrorWatch (cardinal (RCI));
  737. DefLocObj := nil;
  738. end;
  739. end
  740. else
  741. OSErrorWatch (cardinal (RCI));
  742. end
  743. else
  744. OSErrorWatch (RC);
  745. if DefLocObj = nil then
  746. (* Still no success -> let's use the "Universal" locale as a fallback. *)
  747. begin
  748. RCI := Sys_UniCreateLocaleObject (Uni_UCS_String_Pointer, @WUniv [0],
  749. DefLocObj);
  750. if RCI <> 0 then
  751. begin
  752. OSErrorWatch (cardinal (RCI));
  753. DefLocObj := nil;
  754. end;
  755. end;
  756. end;
  757. end
  758. else (* not UniAPI *)
  759. ReInitDummyAnsiSupport;
  760. InInitDefaultCP := -1;
  761. end;
  762. function OS2CPtoRtlCP (CP: cardinal; ReqFlags: byte;
  763. var UConvObj: TUConvObject): TSystemCodepage;
  764. var
  765. I, I2: cardinal;
  766. RCI: longint;
  767. function CheckDefaultOS2CP: boolean;
  768. begin
  769. if CP = DefCpRec.OS2CP then
  770. begin
  771. CheckDefaultOS2CP := true;
  772. if RTLUsesWinCP then
  773. OS2CPtoRtlCP := DefCpRec.WinCP;
  774. if ReqFlags and CpxMappingOnly = 0 then
  775. UConvObj := DefCpRec.UConvObj;
  776. end
  777. else
  778. CheckDefaultOS2CP := false;
  779. end;
  780. begin
  781. OS2CPtoRtlCP := TSystemCodePage (CP);
  782. UConvObj := nil;
  783. if not UniAPI then (* No UniAPI => no need for UConvObj *)
  784. ReqFlags := ReqFlags or CpxMappingOnly;
  785. if CheckDefaultOS2CP then
  786. Exit;
  787. if (CachedDefFSCodepage <> DefaultFileSystemCodePage) and
  788. (InInitDefaultCP <> ThreadID) then
  789. (* InInitDefaultCP = ThreadID -> this thread is already re-initializing the cached information *)
  790. begin
  791. if InInitDefaultCP <> -1 then
  792. repeat
  793. DosSleep (5) (* Let's wait until the other thread finishes re-initialization of the cache *)
  794. until InInitDefaultCP = -1
  795. else
  796. InitDefaultCP;
  797. if CheckDefaultOS2CP then
  798. Exit;
  799. end;
  800. I := 1;
  801. if ReqFlags and CpxSpecial = CpxSpecial then
  802. I2 := 2
  803. else
  804. if ReqFlags and CpxMappingOnly = CpxMappingOnly then
  805. I2 := MaxNonEqualCPMapping
  806. else
  807. I2 := MaxCPMapping;
  808. while I <= I2 do
  809. begin
  810. if CP = CpXList [I].OS2CP then
  811. begin
  812. if RTLUsesWinCP then
  813. OS2CPtoRtlCP := CpXList [I].WinCP;
  814. if ReqFlags and CpxMappingOnly = 0 then
  815. begin
  816. if CpXList [I].UConvObj = nil then
  817. begin
  818. if UConvObjectForCP (CpXList [I].OS2CP, UConvObj) = Uls_Success then
  819. CpXList [I].UConvObj := UConvObj
  820. else
  821. UConvObj := nil;
  822. end
  823. else
  824. UConvObj := CpXList [I].UConvObj;
  825. end;
  826. Exit;
  827. end;
  828. Inc (I);
  829. end;
  830. (* If codepage was not found in the translation table and UConvObj is
  831. requested, allocate one in the temporary record. *)
  832. if ReqFlags and CpxMappingOnly = 0 then
  833. begin
  834. if TempCpRec.OS2CP = CP then
  835. UConvObj := TempCpRec.UConvObj
  836. else
  837. begin
  838. if TempCpRec.UConvObj <> nil then
  839. begin
  840. RCI := Sys_UniFreeUConvObject (TempCpRec.UConvObj);
  841. if RCI <> 0 then
  842. OSErrorWatch (cardinal (RCI));
  843. TempCpRec.UConvObj := nil;
  844. end;
  845. if UConvObjectForCP (CP, UConvObj) = Uls_Success then
  846. begin
  847. TempCpRec.UConvObj := UConvObj;
  848. TempCpRec.OS2CP := CP;
  849. end
  850. else
  851. UConvObj := nil;
  852. end;
  853. end;
  854. end;
  855. function RtlCPtoOS2CP (RtlCP: TSystemCodepage; ReqFlags: byte;
  856. var UConvObj: TUConvObject): cardinal;
  857. var
  858. I, I2: cardinal;
  859. function CheckDefaultWinCP: boolean;
  860. begin
  861. if RtlCP = DefCpRec.WinCP then
  862. begin
  863. CheckDefaultWinCP := true;
  864. RtlCPtoOS2CP := DefCpRec.WinCP;
  865. if ReqFlags and CpxMappingOnly = 0 then
  866. UConvObj := DefCpRec.UConvObj;
  867. end
  868. else
  869. CheckDefaultWinCP := false;
  870. end;
  871. begin
  872. RtlCPtoOS2CP := RtlCP;
  873. UConvObj := nil;
  874. if not UniAPI then (* No UniAPI => no need for UConvObj *)
  875. ReqFlags := ReqFlags or CpxMappingOnly;
  876. if not (RTLUsesWinCP) then
  877. begin
  878. if ReqFlags and CpxMappingOnly = 0 then
  879. OS2CPtoRtlCP (cardinal (RtlCp), ReqFlags, UConvObj);
  880. end
  881. else if CheckDefaultWinCp then
  882. Exit
  883. else
  884. begin
  885. if (CachedDefFSCodepage <> DefaultFileSystemCodePage) and
  886. (InInitDefaultCP <> ThreadID) then
  887. (* InInitDefaultCP = ThreadID -> this thread is already re-initializing the cached information *)
  888. begin
  889. if InInitDefaultCP <> -1 then
  890. repeat
  891. (* Let's wait until the other thread finishes re-initialization of the cache *)
  892. DosSleep (5)
  893. until InInitDefaultCP = -1
  894. else
  895. InitDefaultCP;
  896. if CheckDefaultWinCP then
  897. Exit;
  898. end;
  899. I := 1;
  900. if ReqFlags and CpxSpecial = CpxSpecial then
  901. I2 := 2
  902. else
  903. if ReqFlags and CpxMappingOnly = CpxMappingOnly then
  904. I2 := MaxNonEqualCPMapping
  905. else
  906. I2 := MaxCPMapping;
  907. while I <= I2 do
  908. begin
  909. if RtlCP = CpXList [I].WinCP then
  910. begin
  911. RtlCPtoOS2CP := CpXList [I].OS2CP;
  912. if ReqFlags and CpxMappingOnly = 0 then
  913. begin
  914. begin
  915. if UConvObjectForCP (CpXList [I].OS2CP, UConvObj) = Uls_Success then
  916. CpXList [I].UConvObj := UConvObj
  917. else
  918. UConvObj := nil;
  919. end
  920. end;
  921. Exit;
  922. end;
  923. Inc (I);
  924. end;
  925. (*
  926. Special processing for
  927. ExceptionWinCodepages = (CP_UTF16BE, CP_UTF7, 12000 {UTF32}, 12001 {UTF32BE})
  928. might be added here...or not ;-)
  929. if (TempCpRec.OS2CP <> High (TempCpRec.OS2CP)) or
  930. (TempCpRec.WinCP <> RtlCp) then
  931. begin
  932. if TempCpRec.UConvObj <> nil then
  933. begin
  934. RCI := Sys_UniFreeUConvObject (TempCpRec.UConvObj);
  935. if RCI <> 0 then
  936. OSErrorWatch (cardinal (RCI));
  937. end;
  938. TempCpRec.OS2CP := High (TempCpRec.OS2CP);
  939. TempCpRec.WinCP := RtlCp;
  940. end;
  941. Map to CP_ASCII aka OS2CP=367 if RtlCP not recognized and UConvObject
  942. is requested???
  943. *)
  944. (* Signalize unrecognized (untranslatable) MS Windows codepage *)
  945. OSErrorWatch (Uls_Invalid);
  946. end;
  947. end;
  948. function OS2CPtoRtlCP (CP: cardinal; ReqFlags: byte): TSystemCodepage;
  949. var
  950. NoUConvObj: TUConvObject;
  951. begin
  952. if RtlUsesWinCP then
  953. OS2CPtoRtlCP := OS2CPtoRtlCP (CP, ReqFlags or CpxMappingOnly, NoUConvObj)
  954. else
  955. OS2CPtoRtlCP := TSystemCodepage (CP);
  956. end;
  957. function RtlCPtoOS2CP (RtlCP: TSystemCodepage; ReqFlags: byte): cardinal;
  958. var
  959. NoUConvObj: TUConvObject;
  960. begin
  961. if RtlUsesWinCP then
  962. RtlCPtoOS2CP := RtlCPtoOS2CP (RtlCP, ReqFlags or CpxMappingOnly, NoUConvObj)
  963. else
  964. RtlCPtoOS2CP := RtlCP;
  965. end;
  966. procedure OS2Unicode2AnsiMove (Source: PUnicodeChar; var Dest: RawByteString;
  967. CP: TSystemCodePage; Len: SizeInt);
  968. var
  969. RCI: longint;
  970. UConvObj: TUConvObject;
  971. OS2CP: cardinal;
  972. Src2: PUnicodeChar;
  973. Len2, LenOut, OutOffset, NonIdentical: longint;
  974. Dest2: PChar;
  975. begin
  976. OS2CP := RtlCpToOS2CP (CP, CpxAll, UConvObj);
  977. { if UniAPI and (UConvObj = nil) then - OS2Unicode2AnsiMove should be never called if not UniAPI }
  978. if UConvObj = nil then
  979. begin
  980. {$WARNING Special cases like UTF-7 should be handled here, otherwise signalize error - how???}
  981. DefaultUnicode2AnsiMove (Source, Dest, CP, Len);
  982. Exit;
  983. end;
  984. LenOut := Succ (Len); (* Standard OS/2 CP is a SBCS *)
  985. SetLength (Dest, LenOut);
  986. SetCodePage (Dest, CP, false);
  987. Src2 := Source;
  988. Len2 := Len;
  989. Dest2 := PChar (Dest);
  990. RCI := Sys_UniUConvFromUcs (UConvObj, Src2, Len2, Dest2, LenOut,
  991. NonIdentical);
  992. repeat
  993. case RCI of
  994. Uls_Success:
  995. begin
  996. if LenOut > 0 then
  997. SetLength (Dest, Length (Dest) - LenOut);
  998. Break;
  999. end;
  1000. Uls_IllegalSequence:
  1001. begin
  1002. OSErrorWatch (Uls_IllegalSequence);
  1003. { skip and set to '?' }
  1004. Inc (Src2);
  1005. Dec (Len2);
  1006. Dest2^ := '?';
  1007. Inc (Dest2);
  1008. Dec (LenOut);
  1009. end;
  1010. Uls_BufferFull:
  1011. begin
  1012. OutOffset := Dest2 - PChar (Dest);
  1013. (* Use Len2 or Len decreased by difference between Source and Src2? *)
  1014. (* Extend more this time - target is probably a DBCS or UTF-8 *)
  1015. SetLength (Dest, Length (Dest) + Succ (Len2 * 2));
  1016. { string could have been moved }
  1017. Dest2 := PChar (Dest) + OutOffset;
  1018. Inc (LenOut, Succ (Len2 * 2));
  1019. end
  1020. else
  1021. begin
  1022. SetLength (Dest, 0);
  1023. OSErrorWatch (cardinal (RCI));
  1024. { Break }
  1025. RunError (231);
  1026. end;
  1027. end;
  1028. RCI := Sys_UniUConvFromUcs (UConvObj, Src2, Len2, Dest2, LenOut,
  1029. NonIdentical);
  1030. until false;
  1031. end;
  1032. procedure OS2Ansi2UnicodeMove (Source: PChar; CP: TSystemCodePage;
  1033. var Dest: UnicodeString; Len: SizeInt);
  1034. var
  1035. RCI: longint;
  1036. UConvObj: TUConvObject;
  1037. OS2CP: cardinal;
  1038. Src2: PChar;
  1039. Len2, LenOut, OutOffset, NonIdentical: longint;
  1040. Dest2: PWideChar;
  1041. begin
  1042. OS2CP := RtlCpToOS2CP (CP, CpxAll, UConvObj);
  1043. { if UniAPI and (UConvObj = nil) then - OS2Unicode2AnsiMove should be never called if not UniAPI }
  1044. if UConvObj = nil then
  1045. begin
  1046. {$WARNING Special cases like UTF-7 should be handled here, otherwise signalize error - how???}
  1047. DefaultAnsi2UnicodeMove (Source, CP, Dest, Len);
  1048. Exit;
  1049. end;
  1050. LenOut := Succ (Len); (* Standard OS/2 CP is a SBCS *)
  1051. SetLength (Dest, LenOut);
  1052. Src2 := Source;
  1053. Len2 := Len;
  1054. Dest2 := PWideChar (Dest);
  1055. RCI := Sys_UniUConvToUcs (UConvObj, Src2, Len2, Dest2, LenOut, NonIdentical);
  1056. repeat
  1057. case RCI of
  1058. Uls_Success:
  1059. begin
  1060. if LenOut > 0 then
  1061. SetLength (Dest, Length (Dest) - LenOut);
  1062. Break;
  1063. end;
  1064. Uls_IllegalSequence:
  1065. begin
  1066. OSErrorWatch (Uls_IllegalSequence);
  1067. { skip and set to '?' }
  1068. Inc (Src2);
  1069. Dec (Len2);
  1070. Dest2^ := '?';
  1071. Inc (Dest2);
  1072. Dec (LenOut);
  1073. end;
  1074. Uls_BufferFull:
  1075. begin
  1076. OutOffset := Dest2 - PWideChar (Dest);
  1077. (* Use Len2 or Len decreased by difference between Source and Src2? *)
  1078. SetLength (Dest, Length (Dest) + Succ (Len2));
  1079. { string could have been moved }
  1080. Dest2 := PWideChar (Dest) + OutOffset;
  1081. Inc (LenOut, Succ (Len2));
  1082. end
  1083. else
  1084. begin
  1085. SetLength (Dest, 0);
  1086. OSErrorWatch (cardinal (RCI));
  1087. { Break }
  1088. RunError (231);
  1089. end;
  1090. end;
  1091. RCI := Sys_UniUConvToUcs (UConvObj, Src2, Len2, Dest2, LenOut,
  1092. NonIdentical);
  1093. until false;
  1094. end;
  1095. function RtlChangeCP (CP: TSystemCodePage): longint;
  1096. var
  1097. OS2CP, I: cardinal;
  1098. NoUConvObj: TUConvObject;
  1099. RCI: longint;
  1100. begin
  1101. OS2CP := RtlCpToOS2Cp (CP, cpxMappingOnly, NoUConvObj);
  1102. RtlChangeCP := longint (DosSetProcessCP (OS2CP));
  1103. if RtlChangeCP <> 0 then
  1104. OSErrorWatch (RtlChangeCP)
  1105. else
  1106. begin
  1107. DefaultSystemCodePage := CP;
  1108. DefaultRTLFileSystemCodePage := DefaultSystemCodePage;
  1109. DefaultFileSystemCodePage := DefaultSystemCodePage;
  1110. if OS2CP <> DefCpRec.OS2CP then
  1111. begin
  1112. if DefCpRec.UConvObj <> nil then
  1113. begin
  1114. (* Do not free the UConv object from DefCpRec, because it is also stored in
  1115. the respective CpXList record! *)
  1116. {
  1117. RCI := Sys_UniFreeUConvObject (DefCpRec.UConvObj);
  1118. if RCI <> 0 then
  1119. OSErrorWatch (cardinal (RCI));
  1120. }
  1121. DefCpRec.UConvObj := nil;
  1122. end;
  1123. DefCPRec.OS2CP := OS2CP;
  1124. RCI := Sys_UniCreateUConvObject (@WNull, DefCpRec.UConvObj);
  1125. if RCI <> 0 then
  1126. OSErrorWatch (cardinal (RCI));
  1127. (* Find out WinCP _without_ considering RtlUsesWinCP *)
  1128. I := 1;
  1129. while (I <= MaxNonEqualCPMapping) and (CpXList [I].OS2CP <> OS2CP) do
  1130. Inc (I);
  1131. if CpXList [I].OS2CP = OS2CP then
  1132. DefCpRec.WinCP := CpXList [I].WinCP
  1133. else
  1134. DefCpRec.WinCP := OS2CP;
  1135. end;
  1136. end;
  1137. end;
  1138. function OS2UpperUnicodeString (const S: UnicodeString): UnicodeString;
  1139. var
  1140. I: cardinal;
  1141. begin
  1142. SetLength (Result, Length (S));
  1143. if Length (S) > 0 then
  1144. for I := 0 to Pred (Length (S)) do
  1145. PWideChar (Result) [I] := Sys_UniToUpper (S [Succ (I)]);
  1146. end;
  1147. function OS2LowerUnicodeString (const S: UnicodeString): UnicodeString;
  1148. var
  1149. I: cardinal;
  1150. begin
  1151. SetLength (Result, Length (S));
  1152. if Length (S) > 0 then
  1153. for I := 0 to Pred (Length (S)) do
  1154. PWideChar (Result) [I] := Sys_UniToLower (S [Succ (I)]);
  1155. end;
  1156. function NoNullsUnicodeString (const S: UnicodeString): UnicodeString;
  1157. var
  1158. I: cardinal;
  1159. begin
  1160. Result := S;
  1161. UniqueString (Result);
  1162. if Length (S) > 0 then
  1163. for I := 1 to Length (S) do
  1164. if Result [I] = WNull then
  1165. Result [I] := ' ';
  1166. end;
  1167. function OS2CompareUnicodeString (const S1, S2: UnicodeString; Options : TCompareOptions): PtrInt;
  1168. var
  1169. HS1, HS2: UnicodeString;
  1170. begin
  1171. { UniStrColl interprets null chars as end-of-string -> filter out }
  1172. HS1 := NoNullsUnicodeString (S1);
  1173. HS2 := NoNullsUnicodeString (S2);
  1174. if coIgnoreCase in Options then
  1175. begin
  1176. HS1:=OS2UpperUnicodeString(HS1);
  1177. HS2:=OS2UpperUnicodeString(HS2);
  1178. end;
  1179. Result := Sys_UniStrColl (DefLocObj, PWideChar (HS1), PWideChar (HS2));
  1180. if Result < -1 then
  1181. Result := -1
  1182. else if Result > 1 then
  1183. Result := 1;
  1184. end;
  1185. function OS2CompareTextUnicodeString (const S1, S2: UnicodeString): PtrInt;
  1186. begin
  1187. Result := OS2CompareUnicodeString (OS2UpperUnicodeString (S1),
  1188. OS2UpperUnicodeString (S2));
  1189. {$WARNING Language independent uppercase routine may not be appropriate for language dependent case insensitive comparison!}
  1190. end;
  1191. function OS2UpperAnsiString (const S: AnsiString): AnsiString;
  1192. var
  1193. RC: cardinal;
  1194. begin
  1195. Result := S;
  1196. UniqueString (Result);
  1197. FillChar (EmptyCC, SizeOf (EmptyCC), 0);
  1198. RC := DosMapCase (Length (Result), EmptyCC, PChar (Result));
  1199. { What to do in case of a failure??? }
  1200. if RC <> 0 then
  1201. Result := UpCase (S); { Use a fallback? }
  1202. end;
  1203. function OS2LowerAnsiString (const S: AnsiString): AnsiString;
  1204. var
  1205. I: PtrUInt;
  1206. function IsDBCSLeadChar (C: char): boolean;
  1207. var
  1208. D: byte;
  1209. begin
  1210. IsDBCSLeadChar := false;
  1211. D := 0;
  1212. while D < DBCSLeadRangesEnd do
  1213. begin
  1214. if (C >= DBCSLeadRanges [D]) and (C <= DBCSLeadRanges [Succ (D)]) then
  1215. begin
  1216. IsDBCSLeadChar := true;
  1217. Exit;
  1218. end;
  1219. Inc (D, 2);
  1220. end;
  1221. end;
  1222. begin
  1223. (*
  1224. OS/2 provides no direct solution for lowercase conversion of MBCS strings.
  1225. If Unicode support is available, using Unicode routines is the best solution.
  1226. If not, we use a translation table built at startup by translating the full
  1227. character set to uppercase and using that for creation of a lookup table
  1228. (as already done in sysutils). However, we need to check for DBCS (MBCS)
  1229. codepages and avoid translating the DBCS lead bytes and the following
  1230. character.
  1231. *)
  1232. if UniAPI then
  1233. Result := OS2LowerUnicodeString (S)
  1234. { Two implicit conversions... ;-) }
  1235. else
  1236. begin
  1237. Result := S;
  1238. if Length (Result) > 0 then
  1239. begin
  1240. UniqueString (Result);
  1241. if DBCSLeadRangesEnd > 0 then
  1242. begin
  1243. I := 1;
  1244. while I <= Length (Result) do
  1245. begin
  1246. if IsDBCSLeadChar (Result [I]) then
  1247. Inc (I, 2)
  1248. else
  1249. begin
  1250. Result [I] := LowerChars [Result [I]];
  1251. Inc (I);
  1252. end;
  1253. end;
  1254. end
  1255. else
  1256. for I := 1 to Length (Result) do
  1257. Result [I] := LowerChars [Result [I]];
  1258. end;
  1259. end;
  1260. end;
  1261. function OS2CompareStrAnsiString (const S1, S2: AnsiString): PtrInt;
  1262. var
  1263. I, MaxLen: PtrUInt;
  1264. begin
  1265. if UniAPI then
  1266. Result := OS2CompareUnicodeString (S1, S2) (* implicit conversions *)
  1267. else
  1268. (* Older OS/2 versions without Unicode support do not provide direct means *)
  1269. (* for case sensitive and codepage and language-aware string comparison. *)
  1270. (* We have to resort to manual comparison of the original strings together *)
  1271. (* with strings translated using the case insensitive collation sequence. *)
  1272. begin
  1273. if Length (S1) = 0 then
  1274. begin
  1275. if Length (S2) = 0 then
  1276. Result := 0
  1277. else
  1278. Result := -1;
  1279. Exit;
  1280. end
  1281. else
  1282. if Length (S2) = 0 then
  1283. begin
  1284. Result := 1;
  1285. Exit;
  1286. end;
  1287. I := 1;
  1288. MaxLen := Length (S1);
  1289. if Length (S2) < MaxLen then
  1290. MaxLen := Length (S2);
  1291. repeat
  1292. if CollationSequence [S1 [I]] = CollationSequence [S2 [I]] then
  1293. begin
  1294. if S1 [I] < S2 [I] then
  1295. begin
  1296. Result := -1;
  1297. Exit;
  1298. end
  1299. else if S1 [I] > S2 [I] then
  1300. begin
  1301. Result := 1;
  1302. Exit;
  1303. end;
  1304. end
  1305. else
  1306. begin
  1307. if CollationSequence [S1 [I]] < CollationSequence [S2 [I]] then
  1308. Result := -1
  1309. else
  1310. Result := 1;
  1311. Exit;
  1312. end;
  1313. Inc (I);
  1314. until (I > MaxLen);
  1315. if Length (S2) > MaxLen then
  1316. Result := -1
  1317. else if Length (S1) > MaxLen then
  1318. Result := 1
  1319. else
  1320. Result := 0;
  1321. end;
  1322. end;
  1323. function OS2StrCompAnsiString (S1, S2: PChar): PtrInt;
  1324. var
  1325. HSA1, HSA2: AnsiString;
  1326. HSU1, HSU2: UnicodeString;
  1327. begin
  1328. (* Do not call OS2CompareUnicodeString to skip scanning for #0. *)
  1329. HSA1 := AnsiString (S1);
  1330. HSA2 := AnsiString (S2);
  1331. if UniApi then
  1332. begin
  1333. HSU1 := HSA1; (* implicit conversion *)
  1334. HSU2 := HSA2; (* implicit conversion *)
  1335. Result := Sys_UniStrColl (DefLocObj, PWideChar (HSU1), PWideChar (HSU2));
  1336. if Result < -1 then
  1337. Result := -1
  1338. else if Result > 1 then
  1339. Result := 1;
  1340. end
  1341. else
  1342. Result := OS2CompareStrAnsiString (HSA1, HSA2);
  1343. end;
  1344. function OS2CompareTextAnsiString (const S1, S2: AnsiString): PtrInt;
  1345. var
  1346. HSA1, HSA2: AnsiString;
  1347. I: PtrUInt;
  1348. begin
  1349. if UniAPI then
  1350. Result := OS2CompareTextUnicodeString (S1, S2) (* implicit conversions *)
  1351. else
  1352. begin
  1353. (* Let's use collation strings here as a fallback *)
  1354. SetLength (HSA1, Length (S1));
  1355. if Length (HSA1) > 0 then
  1356. (* Using assembler would be much faster, but never mind... *)
  1357. for I := 1 to Length (HSA1) do
  1358. HSA1 [I] := CollationSequence [S1 [I]];
  1359. {$WARNING Results of using collation sequence with DBCS not known/tested!}
  1360. SetLength (HSA2, Length (S2));
  1361. if Length (HSA2) > 0 then
  1362. for I := 1 to Length (HSA2) do
  1363. HSA2 [I] := CollationSequence [S2 [I]];
  1364. if HSA1 = HSA2 then
  1365. Result := 0
  1366. else if HSA1 < HSA2 then
  1367. Result := -1
  1368. else
  1369. Result := 1;
  1370. end;
  1371. end;
  1372. function OS2StrICompAnsiString (S1, S2: PChar): PtrInt;
  1373. begin
  1374. Result := OS2CompareTextAnsiString (AnsiString (S1), AnsiString (S2));
  1375. end;
  1376. function OS2StrLCompAnsiString (S1, S2: PChar; MaxLen: PtrUInt): PtrInt;
  1377. var
  1378. A, B: AnsiString;
  1379. begin
  1380. if (MaxLen = 0) then
  1381. Exit (0);
  1382. SetLength (A, MaxLen);
  1383. Move (S1^, A [1], MaxLen);
  1384. SetLength (B, MaxLen);
  1385. Move (S2^, B [1], MaxLen);
  1386. Result := OS2CompareStrAnsiString (A, B);
  1387. end;
  1388. function OS2StrLICompAnsiString (S1, S2: PChar; MaxLen: PtrUInt): PtrInt;
  1389. var
  1390. A, B: AnsiString;
  1391. begin
  1392. if (MaxLen = 0) then
  1393. Exit (0);
  1394. SetLength (A, MaxLen);
  1395. Move (S1^, A [1], MaxLen);
  1396. SetLength (B, MaxLen);
  1397. Move (S2^, B [1], MaxLen);
  1398. Result := OS2CompareTextAnsiString (A, B);
  1399. end;
  1400. procedure FPC_RangeError; [external name 'FPC_RANGEERROR'];
  1401. procedure Ansi2PChar (const S: AnsiString; const OrgP: PChar; out P: Pchar);
  1402. var
  1403. NewLen: SizeUInt;
  1404. begin
  1405. NewLen := Length (S);
  1406. if NewLen > StrLen (OrgP) then
  1407. FPC_RangeError;
  1408. P := OrgP;
  1409. if (NewLen > 0) then
  1410. Move (S [1], P [0], NewLen);
  1411. P [NewLen] := #0;
  1412. end;
  1413. function OS2StrUpperAnsiString (Str: PChar): PChar;
  1414. var
  1415. Temp: AnsiString;
  1416. begin
  1417. Temp := OS2UpperAnsiString (Str);
  1418. Ansi2PChar (Temp, Str, Result);
  1419. end;
  1420. function OS2StrLowerAnsiString (Str: PChar): PChar;
  1421. var
  1422. Temp: AnsiString;
  1423. begin
  1424. Temp := OS2LowerAnsiString (Str);
  1425. Ansi2PChar (Temp, Str, Result);
  1426. end;
  1427. (*
  1428. CWSTRING:
  1429. { return value: number of code points in the string. Whenever an invalid
  1430. code point is encountered, all characters part of this invalid code point
  1431. are considered to form one "character" and the next character is
  1432. considered to be the start of a new (possibly also invalid) code point }
  1433. function CharLengthPChar(const Str: PChar): PtrInt;
  1434. var
  1435. nextlen: ptrint;
  1436. s: pchar;
  1437. {$ifndef beos}
  1438. mbstate: mbstate_t;
  1439. {$endif not beos}
  1440. begin
  1441. result:=0;
  1442. s:=str;
  1443. {$ifndef beos}
  1444. fillchar(mbstate,sizeof(mbstate),0);
  1445. {$endif not beos}
  1446. repeat
  1447. {$ifdef beos}
  1448. nextlen:=ptrint(mblen(s,MB_CUR_MAX));
  1449. {$else beos}
  1450. nextlen:=ptrint(mbrlen(s,MB_CUR_MAX,@mbstate));
  1451. {$endif beos}
  1452. { skip invalid/incomplete sequences }
  1453. if (nextlen<0) then
  1454. nextlen:=1;
  1455. inc(result,1);
  1456. inc(s,nextlen);
  1457. until (nextlen=0);
  1458. end;
  1459. function CodePointLength(const Str: PChar; maxlookahead: ptrint): PtrInt;
  1460. var
  1461. nextlen: ptrint;
  1462. {$ifndef beos}
  1463. mbstate: mbstate_t;
  1464. {$endif not beos}
  1465. begin
  1466. {$ifdef beos}
  1467. result:=ptrint(mblen(str,maxlookahead));
  1468. {$else beos}
  1469. fillchar(mbstate,sizeof(mbstate),0);
  1470. result:=ptrint(mbrlen(str,maxlookahead,@mbstate));
  1471. { mbrlen can also return -2 for "incomplete but potially valid character
  1472. and data has been processed" }
  1473. if result<0 then
  1474. result:=-1;
  1475. {$endif beos}
  1476. end;
  1477. *)
  1478. procedure InitOS2WideStringManager; inline;
  1479. var
  1480. RC: cardinal;
  1481. ErrName: array [0..MaxPathLen] of char;
  1482. P: pointer;
  1483. begin
  1484. RC := DosLoadModule (@ErrName [0], SizeOf (ErrName), @UConvName [0],
  1485. UConvHandle);
  1486. if RC = 0 then
  1487. begin
  1488. RC := DosQueryProcAddr (UConvHandle, OrdUniCreateUConvObject, nil, P);
  1489. if RC = 0 then
  1490. begin
  1491. Sys_UniCreateUConvObject := TUniCreateUConvObject (P);
  1492. RC := DosQueryProcAddr (UConvHandle, OrdUniMapCpToUcsCp, nil, P);
  1493. if RC = 0 then
  1494. begin
  1495. Sys_UniMapCpToUcsCp := TUniMapCpToUcsCp (P);
  1496. RC := DosQueryProcAddr (UConvHandle, OrdUniFreeUConvObject, nil, P);
  1497. if RC = 0 then
  1498. begin
  1499. Sys_UniFreeUConvObject := TUniFreeUConvObject (P);
  1500. RC := DosQueryProcAddr (UConvHandle, OrdUniUConvFromUcs, nil, P);
  1501. if RC = 0 then
  1502. begin
  1503. Sys_UniUConvFromUcs := TUniUConvFromUcs (P);
  1504. RC := DosQueryProcAddr (UConvHandle, OrdUniUConvToUcs, nil, P);
  1505. if RC = 0 then
  1506. begin
  1507. Sys_UniUConvToUcs := TUniUConvToUcs (P);
  1508. RC := DosLoadModule (@ErrName [0], SizeOf (ErrName),
  1509. @LibUniName [0], LibUniHandle);
  1510. if RC = 0 then
  1511. begin
  1512. RC := DosQueryProcAddr (LibUniHandle, OrdUniToLower, nil, P);
  1513. if RC = 0 then
  1514. begin
  1515. Sys_UniToLower := TUniToLower (P);
  1516. RC := DosQueryProcAddr (LibUniHandle, OrdUniToUpper, nil, P);
  1517. if RC = 0 then
  1518. begin
  1519. Sys_UniToUpper := TUniToUpper (P);
  1520. RC := DosQueryProcAddr (LibUniHandle, OrdUniStrColl, nil,
  1521. P);
  1522. if RC = 0 then
  1523. begin
  1524. Sys_UniStrColl := TUniStrColl (P);
  1525. RC := DosQueryProcAddr (LibUniHandle,
  1526. OrdUniCreateLocaleObject, nil, P);
  1527. if RC = 0 then
  1528. begin
  1529. Sys_UniCreateLocaleObject := TUniCreateLocaleObject
  1530. (P);
  1531. RC := DosQueryProcAddr (LibUniHandle,
  1532. OrdUniFreeLocaleObject, nil, P);
  1533. if RC = 0 then
  1534. begin
  1535. Sys_UniFreeLocaleObject := TUniFreeLocaleObject (P);
  1536. RC := DosQueryProcAddr (LibUniHandle,
  1537. OrdUniMapCtryToLocale, nil, P);
  1538. if RC = 0 then
  1539. begin
  1540. Sys_UniMapCtryToLocale := TUniMapCtryToLocale (P);
  1541. UniAPI := true;
  1542. end;
  1543. end;
  1544. end;
  1545. end;
  1546. end;
  1547. end;
  1548. end;
  1549. end;
  1550. end;
  1551. end;
  1552. end;
  1553. end;
  1554. end;
  1555. if RC <> 0 then
  1556. OSErrorWatch (RC);
  1557. if not (UniAPI) then
  1558. begin
  1559. Sys_UniCreateUConvObject := @DummyUniCreateUConvObject;
  1560. Sys_UniMapCpToUcsCp := @DummyUniMapCpToUcsCp;
  1561. Sys_UniFreeUConvObject := @DummyUniFreeUConvObject;
  1562. Sys_UniUConvFromUcs := @DummyUniUConvFromUcs;
  1563. Sys_UniUConvToUcs := @DummyUniUConvToUcs;
  1564. Sys_UniToLower := @DummyUniToLower;
  1565. Sys_UniToUpper := @DummyUniToUpper;
  1566. Sys_UniStrColl := @DummyUniStrColl;
  1567. Sys_UniCreateLocaleObject := @DummyUniCreateLocaleObject;
  1568. Sys_UniFreeLocaleObject := @DummyUniFreeLocaleObject;
  1569. Sys_UniMapCtryToLocale := @DummyUniMapCtryToLocale;
  1570. InitDummyAnsiSupport;
  1571. end;
  1572. { Widestring }
  1573. WideStringManager.Wide2AnsiMoveProc := @OS2Unicode2AnsiMove;
  1574. WideStringManager.Ansi2WideMoveProc := @OS2Ansi2UnicodeMove;
  1575. WideStringManager.UpperWideStringProc := @OS2UpperUnicodeString;
  1576. WideStringManager.LowerWideStringProc := @OS2LowerUnicodeString;
  1577. WideStringManager.CompareWideStringProc := @OS2CompareUnicodeString;
  1578. { Unicode }
  1579. WideStringManager.Unicode2AnsiMoveProc := @OS2Unicode2AnsiMove;
  1580. WideStringManager.Ansi2UnicodeMoveProc := @OS2Ansi2UnicodeMove;
  1581. WideStringManager.UpperUnicodeStringProc := @OS2UpperUnicodeString;
  1582. WideStringManager.LowerUnicodeStringProc := @OS2LowerUnicodeString;
  1583. WideStringManager.CompareUnicodeStringProc := @OS2CompareUnicodeString;
  1584. { Codepage }
  1585. WideStringManager.GetStandardCodePageProc := @OS2GetStandardCodePage;
  1586. (*
  1587. CharLengthPCharProc:=@CharLengthPChar;
  1588. CodePointLengthProc:=@CodePointLength;
  1589. *)
  1590. WideStringManager.UpperAnsiStringProc := @OS2UpperAnsiString;
  1591. WideStringManager.LowerAnsiStringProc := @OS2LowerAnsiString;
  1592. WideStringManager.CompareStrAnsiStringProc := @OS2CompareStrAnsiString;
  1593. WideStringManager.CompareTextAnsiStringProc := @OS2CompareTextAnsiString;
  1594. WideStringManager.StrCompAnsiStringProc := @OS2StrCompAnsiString;
  1595. WideStringManager.StrICompAnsiStringProc := @OS2StrICompAnsiString;
  1596. WideStringManager.StrLCompAnsiStringProc := @OS2StrLCompAnsiString;
  1597. WideStringManager.StrLICompAnsiStringProc := @OS2StrLICompAnsiString;
  1598. WideStringManager.StrLowerAnsiStringProc := @OS2StrLowerAnsiString;
  1599. WideStringManager.StrUpperAnsiStringProc := @OS2StrUpperAnsiString;
  1600. end;