sysucode.inc 51 KB

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