sysucode.inc 49 KB

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