sysucode.inc 51 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718
  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. for I := 0 to Pred (Length (S)) do
  1143. PWideChar (Result) [I] := Sys_UniToUpper (S [Succ (I)]);
  1144. end;
  1145. function OS2LowerUnicodeString (const S: UnicodeString): UnicodeString;
  1146. var
  1147. I: cardinal;
  1148. begin
  1149. SetLength (Result, Length (S));
  1150. for I := 0 to Pred (Length (S)) do
  1151. PWideChar (Result) [I] := Sys_UniToLower (S [Succ (I)]);
  1152. end;
  1153. function NoNullsUnicodeString (const S: UnicodeString): UnicodeString;
  1154. var
  1155. I: cardinal;
  1156. begin
  1157. Result := S;
  1158. UniqueString (Result);
  1159. for I := 1 to Length (S) do
  1160. if Result [I] = WNull then
  1161. Result [I] := ' ';
  1162. end;
  1163. function OS2CompareUnicodeString (const S1, S2: UnicodeString): PtrInt;
  1164. var
  1165. HS1, HS2: UnicodeString;
  1166. begin
  1167. { UniStrColl interprets null chars as end-of-string -> filter out }
  1168. HS1 := NoNullsUnicodeString (S1);
  1169. HS2 := NoNullsUnicodeString (S2);
  1170. Result := Sys_UniStrColl (DefLocObj, PWideChar (HS1), PWideChar (HS2));
  1171. if Result < -1 then
  1172. Result := -1
  1173. else if Result > 1 then
  1174. Result := 1;
  1175. end;
  1176. function OS2CompareTextUnicodeString (const S1, S2: UnicodeString): PtrInt;
  1177. begin
  1178. Result := OS2CompareUnicodeString (OS2UpperUnicodeString (S1),
  1179. OS2UpperUnicodeString (S2));
  1180. {$WARNING Language independent uppercase routine may not be appropriate for language dependent case insensitive comparison!}
  1181. end;
  1182. function OS2UpperAnsiString (const S: AnsiString): AnsiString;
  1183. var
  1184. RC: cardinal;
  1185. begin
  1186. Result := S;
  1187. UniqueString (Result);
  1188. FillChar (EmptyCC, SizeOf (EmptyCC), 0);
  1189. RC := DosMapCase (Length (Result), EmptyCC, PChar (Result));
  1190. { What to do in case of a failure??? }
  1191. if RC <> 0 then
  1192. Result := UpCase (S); { Use a fallback? }
  1193. end;
  1194. function OS2LowerAnsiString (const S: AnsiString): AnsiString;
  1195. var
  1196. I: PtrUInt;
  1197. function IsDBCSLeadChar (C: char): boolean;
  1198. var
  1199. D: byte;
  1200. begin
  1201. IsDBCSLeadChar := false;
  1202. D := 0;
  1203. while D < DBCSLeadRangesEnd do
  1204. begin
  1205. if (C >= DBCSLeadRanges [D]) and (C <= DBCSLeadRanges [Succ (D)]) then
  1206. begin
  1207. IsDBCSLeadChar := true;
  1208. Exit;
  1209. end;
  1210. Inc (D, 2);
  1211. end;
  1212. end;
  1213. begin
  1214. (*
  1215. OS/2 provides no direct solution for lowercase conversion of MBCS strings.
  1216. If Unicode support is available, using Unicode routines is the best solution.
  1217. If not, we use a translation table built at startup by translating the full
  1218. character set to uppercase and using that for creation of a lookup table
  1219. (as already done in sysutils). However, we need to check for DBCS (MBCS)
  1220. codepages and avoid translating the DBCS lead bytes and the following
  1221. character.
  1222. *)
  1223. if UniAPI then
  1224. Result := OS2LowerUnicodeString (S)
  1225. { Two implicit conversions... ;-) }
  1226. else
  1227. begin
  1228. Result := S;
  1229. if Length (Result) > 0 then
  1230. begin
  1231. UniqueString (Result);
  1232. if DBCSLeadRangesEnd > 0 then
  1233. begin
  1234. I := 1;
  1235. while I <= Length (Result) do
  1236. begin
  1237. if IsDBCSLeadChar (Result [I]) then
  1238. Inc (I, 2)
  1239. else
  1240. begin
  1241. Result [I] := LowerChars [Result [I]];
  1242. Inc (I);
  1243. end;
  1244. end;
  1245. end
  1246. else
  1247. for I := 1 to Length (Result) do
  1248. Result [I] := LowerChars [Result [I]];
  1249. end;
  1250. end;
  1251. end;
  1252. function OS2CompareStrAnsiString (const S1, S2: AnsiString): PtrInt;
  1253. var
  1254. I, MaxLen: PtrUInt;
  1255. begin
  1256. if UniAPI then
  1257. Result := OS2CompareUnicodeString (S1, S2) (* implicit conversions *)
  1258. else
  1259. (* Older OS/2 versions without Unicode support do not provide direct means *)
  1260. (* for case sensitive and codepage and language-aware string comparison. *)
  1261. (* We have to resort to manual comparison of the original strings together *)
  1262. (* with strings translated using the case insensitive collation sequence. *)
  1263. begin
  1264. if Length (S1) = 0 then
  1265. begin
  1266. if Length (S2) = 0 then
  1267. Result := 0
  1268. else
  1269. Result := -1;
  1270. Exit;
  1271. end
  1272. else
  1273. if Length (S2) = 0 then
  1274. begin
  1275. Result := 1;
  1276. Exit;
  1277. end;
  1278. I := 1;
  1279. MaxLen := Length (S1);
  1280. if Length (S2) < MaxLen then
  1281. MaxLen := Length (S2);
  1282. repeat
  1283. if CollationSequence [S1 [I]] = CollationSequence [S2 [I]] then
  1284. begin
  1285. if S1 [I] < S2 [I] then
  1286. begin
  1287. Result := -1;
  1288. Exit;
  1289. end
  1290. else if S1 [I] > S2 [I] then
  1291. begin
  1292. Result := 1;
  1293. Exit;
  1294. end;
  1295. end
  1296. else
  1297. begin
  1298. if CollationSequence [S1 [I]] < CollationSequence [S2 [I]] then
  1299. Result := -1
  1300. else
  1301. Result := 1;
  1302. Exit;
  1303. end;
  1304. Inc (I);
  1305. until (I > MaxLen);
  1306. if Length (S2) > MaxLen then
  1307. Result := -1
  1308. else if Length (S1) > MaxLen then
  1309. Result := 1
  1310. else
  1311. Result := 0;
  1312. end;
  1313. end;
  1314. function OS2StrCompAnsiString (S1, S2: PChar): PtrInt;
  1315. var
  1316. HSA1, HSA2: AnsiString;
  1317. HSU1, HSU2: UnicodeString;
  1318. begin
  1319. (* Do not call OS2CompareUnicodeString to skip scanning for #0. *)
  1320. HSA1 := AnsiString (S1);
  1321. HSA2 := AnsiString (S2);
  1322. if UniApi then
  1323. begin
  1324. HSU1 := HSA1; (* implicit conversion *)
  1325. HSU2 := HSA2; (* implicit conversion *)
  1326. Result := Sys_UniStrColl (DefLocObj, PWideChar (HSU1), PWideChar (HSU2));
  1327. if Result < -1 then
  1328. Result := -1
  1329. else if Result > 1 then
  1330. Result := 1;
  1331. end
  1332. else
  1333. Result := OS2CompareStrAnsiString (HSA1, HSA2);
  1334. end;
  1335. function OS2CompareTextAnsiString (const S1, S2: AnsiString): PtrInt;
  1336. var
  1337. HSA1, HSA2: AnsiString;
  1338. I: PtrUInt;
  1339. begin
  1340. if UniAPI then
  1341. Result := OS2CompareTextUnicodeString (S1, S2) (* implicit conversions *)
  1342. else
  1343. begin
  1344. (* Let's use collation strings here as a fallback *)
  1345. SetLength (HSA1, Length (S1));
  1346. if Length (HSA1) > 0 then
  1347. (* Using assembler would be much faster, but never mind... *)
  1348. for I := 1 to Length (HSA1) do
  1349. HSA1 [I] := CollationSequence [S1 [I]];
  1350. {$WARNING Results of using collation sequence with DBCS not known/tested!}
  1351. SetLength (HSA2, Length (S2));
  1352. if Length (HSA2) > 0 then
  1353. for I := 1 to Length (HSA2) do
  1354. HSA2 [I] := CollationSequence [S2 [I]];
  1355. if HSA1 = HSA2 then
  1356. Result := 0
  1357. else if HSA1 < HSA2 then
  1358. Result := -1
  1359. else
  1360. Result := 1;
  1361. end;
  1362. end;
  1363. function OS2StrICompAnsiString (S1, S2: PChar): PtrInt;
  1364. begin
  1365. Result := OS2CompareTextAnsiString (AnsiString (S1), AnsiString (S2));
  1366. end;
  1367. function OS2StrLCompAnsiString (S1, S2: PChar; MaxLen: PtrUInt): PtrInt;
  1368. var
  1369. A, B: AnsiString;
  1370. begin
  1371. if (MaxLen = 0) then
  1372. Exit (0);
  1373. SetLength (A, MaxLen);
  1374. Move (S1^, A [1], MaxLen);
  1375. SetLength (B, MaxLen);
  1376. Move (S2^, B [1], MaxLen);
  1377. Result := OS2CompareStrAnsiString (A, B);
  1378. end;
  1379. function OS2StrLICompAnsiString (S1, S2: PChar; MaxLen: PtrUInt): PtrInt;
  1380. var
  1381. A, B: AnsiString;
  1382. begin
  1383. if (MaxLen = 0) then
  1384. Exit (0);
  1385. SetLength (A, MaxLen);
  1386. Move (S1^, A [1], MaxLen);
  1387. SetLength (B, MaxLen);
  1388. Move (S2^, B [1], MaxLen);
  1389. Result := OS2CompareTextAnsiString (A, B);
  1390. end;
  1391. procedure FPC_RangeError; [external name 'FPC_RANGEERROR'];
  1392. procedure Ansi2PChar (const S: AnsiString; const OrgP: PChar; out P: Pchar);
  1393. var
  1394. NewLen: SizeUInt;
  1395. begin
  1396. NewLen := Length (S);
  1397. if NewLen > StrLen (OrgP) then
  1398. FPC_RangeError;
  1399. P := OrgP;
  1400. if (NewLen > 0) then
  1401. Move (S [1], P [0], NewLen);
  1402. P [NewLen] := #0;
  1403. end;
  1404. function OS2StrUpperAnsiString (Str: PChar): PChar;
  1405. var
  1406. Temp: AnsiString;
  1407. begin
  1408. Temp := OS2UpperAnsiString (Str);
  1409. Ansi2PChar (Temp, Str, Result);
  1410. end;
  1411. function OS2StrLowerAnsiString (Str: PChar): PChar;
  1412. var
  1413. Temp: AnsiString;
  1414. begin
  1415. Temp := OS2LowerAnsiString (Str);
  1416. Ansi2PChar (Temp, Str, Result);
  1417. end;
  1418. (*
  1419. CWSTRING:
  1420. { return value: number of code points in the string. Whenever an invalid
  1421. code point is encountered, all characters part of this invalid code point
  1422. are considered to form one "character" and the next character is
  1423. considered to be the start of a new (possibly also invalid) code point }
  1424. function CharLengthPChar(const Str: PChar): PtrInt;
  1425. var
  1426. nextlen: ptrint;
  1427. s: pchar;
  1428. {$ifndef beos}
  1429. mbstate: mbstate_t;
  1430. {$endif not beos}
  1431. begin
  1432. result:=0;
  1433. s:=str;
  1434. {$ifndef beos}
  1435. fillchar(mbstate,sizeof(mbstate),0);
  1436. {$endif not beos}
  1437. repeat
  1438. {$ifdef beos}
  1439. nextlen:=ptrint(mblen(s,MB_CUR_MAX));
  1440. {$else beos}
  1441. nextlen:=ptrint(mbrlen(s,MB_CUR_MAX,@mbstate));
  1442. {$endif beos}
  1443. { skip invalid/incomplete sequences }
  1444. if (nextlen<0) then
  1445. nextlen:=1;
  1446. inc(result,1);
  1447. inc(s,nextlen);
  1448. until (nextlen=0);
  1449. end;
  1450. function CodePointLength(const Str: PChar; maxlookahead: ptrint): PtrInt;
  1451. var
  1452. nextlen: ptrint;
  1453. {$ifndef beos}
  1454. mbstate: mbstate_t;
  1455. {$endif not beos}
  1456. begin
  1457. {$ifdef beos}
  1458. result:=ptrint(mblen(str,maxlookahead));
  1459. {$else beos}
  1460. fillchar(mbstate,sizeof(mbstate),0);
  1461. result:=ptrint(mbrlen(str,maxlookahead,@mbstate));
  1462. { mbrlen can also return -2 for "incomplete but potially valid character
  1463. and data has been processed" }
  1464. if result<0 then
  1465. result:=-1;
  1466. {$endif beos}
  1467. end;
  1468. *)
  1469. procedure InitOS2WideStringManager; inline;
  1470. var
  1471. RC: cardinal;
  1472. ErrName: array [0..MaxPathLen] of char;
  1473. P: pointer;
  1474. begin
  1475. RC := DosLoadModule (@ErrName [0], SizeOf (ErrName), @UConvName [0],
  1476. UConvHandle);
  1477. if RC = 0 then
  1478. begin
  1479. RC := DosQueryProcAddr (UConvHandle, OrdUniCreateUConvObject, nil, P);
  1480. if RC = 0 then
  1481. begin
  1482. Sys_UniCreateUConvObject := TUniCreateUConvObject (P);
  1483. RC := DosQueryProcAddr (UConvHandle, OrdUniMapCpToUcsCp, nil, P);
  1484. if RC = 0 then
  1485. begin
  1486. Sys_UniMapCpToUcsCp := TUniMapCpToUcsCp (P);
  1487. RC := DosQueryProcAddr (UConvHandle, OrdUniFreeUConvObject, nil, P);
  1488. if RC = 0 then
  1489. begin
  1490. Sys_UniFreeUConvObject := TUniFreeUConvObject (P);
  1491. RC := DosQueryProcAddr (UConvHandle, OrdUniUConvFromUcs, nil, P);
  1492. if RC = 0 then
  1493. begin
  1494. Sys_UniUConvFromUcs := TUniUConvFromUcs (P);
  1495. RC := DosQueryProcAddr (UConvHandle, OrdUniUConvToUcs, nil, P);
  1496. if RC = 0 then
  1497. begin
  1498. Sys_UniUConvToUcs := TUniUConvToUcs (P);
  1499. RC := DosLoadModule (@ErrName [0], SizeOf (ErrName),
  1500. @LibUniName [0], LibUniHandle);
  1501. if RC = 0 then
  1502. begin
  1503. RC := DosQueryProcAddr (LibUniHandle, OrdUniToLower, nil, P);
  1504. if RC = 0 then
  1505. begin
  1506. Sys_UniToLower := TUniToLower (P);
  1507. RC := DosQueryProcAddr (LibUniHandle, OrdUniToUpper, nil, P);
  1508. if RC = 0 then
  1509. begin
  1510. Sys_UniToUpper := TUniToUpper (P);
  1511. RC := DosQueryProcAddr (LibUniHandle, OrdUniStrColl, nil,
  1512. P);
  1513. if RC = 0 then
  1514. begin
  1515. Sys_UniStrColl := TUniStrColl (P);
  1516. RC := DosQueryProcAddr (LibUniHandle,
  1517. OrdUniCreateLocaleObject, nil, P);
  1518. if RC = 0 then
  1519. begin
  1520. Sys_UniCreateLocaleObject := TUniCreateLocaleObject
  1521. (P);
  1522. RC := DosQueryProcAddr (LibUniHandle,
  1523. OrdUniFreeLocaleObject, nil, P);
  1524. if RC = 0 then
  1525. begin
  1526. Sys_UniFreeLocaleObject := TUniFreeLocaleObject (P);
  1527. RC := DosQueryProcAddr (LibUniHandle,
  1528. OrdUniMapCtryToLocale, nil, P);
  1529. if RC = 0 then
  1530. begin
  1531. Sys_UniMapCtryToLocale := TUniMapCtryToLocale (P);
  1532. UniAPI := true;
  1533. end;
  1534. end;
  1535. end;
  1536. end;
  1537. end;
  1538. end;
  1539. end;
  1540. end;
  1541. end;
  1542. end;
  1543. end;
  1544. end;
  1545. end;
  1546. if RC <> 0 then
  1547. OSErrorWatch (RC);
  1548. if not (UniAPI) then
  1549. begin
  1550. Sys_UniCreateUConvObject := @DummyUniCreateUConvObject;
  1551. Sys_UniMapCpToUcsCp := @DummyUniMapCpToUcsCp;
  1552. Sys_UniFreeUConvObject := @DummyUniFreeUConvObject;
  1553. Sys_UniUConvFromUcs := @DummyUniUConvFromUcs;
  1554. Sys_UniUConvToUcs := @DummyUniUConvToUcs;
  1555. Sys_UniToLower := @DummyUniToLower;
  1556. Sys_UniToUpper := @DummyUniToUpper;
  1557. Sys_UniStrColl := @DummyUniStrColl;
  1558. Sys_UniCreateLocaleObject := @DummyUniCreateLocaleObject;
  1559. Sys_UniFreeLocaleObject := @DummyUniFreeLocaleObject;
  1560. Sys_UniMapCtryToLocale := @DummyUniMapCtryToLocale;
  1561. InitDummyAnsiSupport;
  1562. end;
  1563. { Widestring }
  1564. WideStringManager.Wide2AnsiMoveProc := @OS2Unicode2AnsiMove;
  1565. WideStringManager.Ansi2WideMoveProc := @OS2Ansi2UnicodeMove;
  1566. WideStringManager.UpperWideStringProc := @OS2UpperUnicodeString;
  1567. WideStringManager.LowerWideStringProc := @OS2LowerUnicodeString;
  1568. WideStringManager.CompareWideStringProc := @OS2CompareUnicodeString;
  1569. WideStringManager.CompareTextWideStringProc := @OS2CompareTextUnicodeString;
  1570. { Unicode }
  1571. WideStringManager.Unicode2AnsiMoveProc := @OS2Unicode2AnsiMove;
  1572. WideStringManager.Ansi2UnicodeMoveProc := @OS2Ansi2UnicodeMove;
  1573. WideStringManager.UpperUnicodeStringProc := @OS2UpperUnicodeString;
  1574. WideStringManager.LowerUnicodeStringProc := @OS2LowerUnicodeString;
  1575. WideStringManager.CompareUnicodeStringProc := @OS2CompareUnicodeString;
  1576. WideStringManager.CompareTextUnicodeStringProc :=
  1577. @OS2CompareTextUnicodeString;
  1578. { Codepage }
  1579. WideStringManager.GetStandardCodePageProc := @OS2GetStandardCodePage;
  1580. (*
  1581. CharLengthPCharProc:=@CharLengthPChar;
  1582. CodePointLengthProc:=@CodePointLength;
  1583. *)
  1584. WideStringManager.UpperAnsiStringProc := @OS2UpperAnsiString;
  1585. WideStringManager.LowerAnsiStringProc := @OS2LowerAnsiString;
  1586. WideStringManager.CompareStrAnsiStringProc := @OS2CompareStrAnsiString;
  1587. WideStringManager.CompareTextAnsiStringProc := @OS2CompareTextAnsiString;
  1588. WideStringManager.StrCompAnsiStringProc := @OS2StrCompAnsiString;
  1589. WideStringManager.StrICompAnsiStringProc := @OS2StrICompAnsiString;
  1590. WideStringManager.StrLCompAnsiStringProc := @OS2StrLCompAnsiString;
  1591. WideStringManager.StrLICompAnsiStringProc := @OS2StrLICompAnsiString;
  1592. WideStringManager.StrLowerAnsiStringProc := @OS2StrLowerAnsiString;
  1593. WideStringManager.StrUpperAnsiStringProc := @OS2StrUpperAnsiString;
  1594. end;