sysucode.inc 37 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 2014 by Tomas Hajny,
  4. member 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_Other = $20401;
  27. Uls_IllegalSequence = $20402;
  28. Uls_MaxFilesPerProc = $20403;
  29. Uls_MaxFiles = $20404;
  30. Uls_NoOp = $20405;
  31. Uls_TooManyKbd = $20406;
  32. Uls_KbdNotFound = $20407;
  33. Uls_BadHandle = $204008;
  34. Uls_NoDead = $20409;
  35. Uls_NoScan = $2040A;
  36. Uls_InvalidScan = $2040B;
  37. Uls_NotImplemented = $2040C;
  38. Uls_NoMemory = $2040D;
  39. Uls_Invalid = $2040E;
  40. Uls_BadObject = $2040F;
  41. Uls_NoToken = $20410;
  42. Uls_NoMatch = $20411;
  43. Uls_BufferFull = $20412;
  44. Uls_Range = $20413;
  45. Uls_Unsupported = $20414;
  46. Uls_BadAttr = $20415;
  47. Uls_Version = $20416;
  48. UConvName: array [0..5] of char = 'UCONV'#0;
  49. OrdUniCreateUconvObject = 1;
  50. OrdUniUconvToUcs = 2;
  51. OrdUniUconvFromUcs = 3;
  52. OrdUniFreeUconvObject = 4;
  53. OrdUniQueryUconvObject = 7;
  54. OrdUniSetUconvObject = 8;
  55. OrdUniQueryUconvCp = 9;
  56. OrdUniMapCpToUcsCp = 10;
  57. OrdUniStrFromUcs = 11;
  58. OrdUniStrToUcs = 12;
  59. Ord_UniMalloc = 13;
  60. Ord_UniFree = 14;
  61. LibUniName: array [0..6] of char = 'LIBUNI'#0;
  62. WNull: WideChar = #0;
  63. type
  64. (* CP_UTF16 should be in exceptions too, because OS/2 supports only UCS2 *)
  65. (* rather than UTF-16 - ignored at least for now. *)
  66. (* ExceptionWinCodepages = (CP_UTF16BE, CP_UTF7, 12000 {UTF32}, 12001 {UTF32BE});
  67. SpecialWinCodepages = (CP_UTF8, CP_ASCII);*)
  68. TCpRec = record
  69. WinCP: TSystemCodepage;
  70. OS2CP: word;
  71. UConvObj: TUConvObject;
  72. end;
  73. TCpXList = array [1..MaxCPMapping] of TCpRec;
  74. TLocaleObject = pointer;
  75. TDummyUConvObject = record
  76. CP: cardinal;
  77. CPNameLen: byte;
  78. CPName: record end;
  79. end;
  80. PDummyUConvObject = ^TDummyUConvObject;
  81. const
  82. DefCpRec: TCpRec = (WinCP: 0; OS2CP: 0; UConvObj: nil);
  83. IBMPrefix: packed array [1..4] of WideChar = 'IBM-';
  84. threadvar
  85. (* Temporary allocations may be performed in parallel in different threads *)
  86. TempCpRec: TCpRec;
  87. function OS2GetStandardCodePage (const stdcp: TStandardCodePageEnum): TSystemCodePage;
  88. var
  89. RC, C, RetSize: cardinal;
  90. NoUConvObject: TUConvObject;
  91. begin
  92. RC := DosQueryCP (SizeOf (C), @C, RetSize);
  93. if (RC <> 0) and (RC <> 473) then
  94. begin
  95. OSErrorWatch (RC);
  96. C := 850;
  97. end;
  98. OS2GetStandardCodePage := OS2CpToRtlCp (C, cpxMappingOnly, NoUConvObject);
  99. end;
  100. function DummyUniCreateUConvObject (const CpName: PWideChar;
  101. var UConv_Object: TUConvObject): longint; cdecl;
  102. var
  103. P: pointer;
  104. PW, PCPN: PWideChar;
  105. S: string [20];
  106. C: cardinal;
  107. L: PtrInt;
  108. I: longint;
  109. A: array [0..7] of char;
  110. CPN2: UnicodeString;
  111. RC, RetSize: cardinal;
  112. begin
  113. UConv_Object := nil;
  114. if (CpName = nil) or (CpName^ = #0) then
  115. begin
  116. RC := DosQueryCP (SizeOf (C), @C, RetSize);
  117. if (RC <> 0) and (RC <> 473) then
  118. begin
  119. C := 850;
  120. OSErrorWatch (RC);
  121. end;
  122. Str (C, CPN2); (* Str should hopefully not use this function recurrently *)
  123. L := Length (CPN2);
  124. Insert (IBMPrefix, CPN2, 1);
  125. PCPN := @CPN2 [1];
  126. end
  127. else
  128. begin
  129. PCPN := CpName;
  130. for I := 0 to 7 do
  131. if I mod 2 = 0 then
  132. A [I] := UpCase (PChar (@PCPN [0]) [I])
  133. else
  134. A [I] := PChar (@PCPN [0]) [I];
  135. if PQWord (@A)^ <> PQWord (@IBMPrefix)^ then
  136. begin
  137. DummyUniCreateUConvObject := Uls_Invalid;
  138. Exit;
  139. end;
  140. L := 0;
  141. PW := PCPN + 4;
  142. while ((PW + L)^ <> #0) and (L <= SizeOf (S)) do
  143. begin
  144. S [Succ (L)] := char (Ord ((PW + L)^));
  145. Inc (L);
  146. end;
  147. if L > SizeOf (S) then
  148. begin
  149. DummyUniCreateUConvObject := Uls_Other;
  150. Exit;
  151. end;
  152. SetLength (S, L);
  153. Val (S, C, I);
  154. if I <> 0 then
  155. begin
  156. DummyUniCreateUConvObject := Uls_Invalid;
  157. Exit;
  158. end;
  159. end;
  160. Inc (L);
  161. GetMem (P, SizeOf (TDummyUConvObject) + (L + 4) * 2);
  162. if P = nil then
  163. DummyUniCreateUConvObject := Uls_NoMemory
  164. else
  165. begin
  166. DummyUniCreateUConvObject := Uls_Success;
  167. PDummyUConvObject (P)^.CP := C;
  168. PDummyUConvObject (P)^.CpNameLen := Pred (L) + 4;
  169. Move (PCPN [0], PDummyUConvObject (P)^.CpName, (L + 4) * 2);
  170. UConv_Object := TUConvObject (P);
  171. end;
  172. end;
  173. function DummyUniFreeUConvObject (UConv_Object: TUConvObject): longint; cdecl;
  174. begin
  175. if UConv_Object <> nil then
  176. FreeMem (UConv_Object, SizeOf (TDummyUConvObject) +
  177. Succ (PDummyUConvObject (UConv_Object)^.CpNameLen) * 2);
  178. DummyUniFreeUConvObject := Uls_Success;
  179. end;
  180. function DummyUniMapCpToUcsCp (const Codepage: cardinal;
  181. CodepageName: PWideChar; const N: cardinal): longint; cdecl;
  182. var
  183. S: UnicodeString;
  184. RC, CP, RetSize: cardinal;
  185. begin
  186. if Codepage = 0 then
  187. begin
  188. RC := DosQueryCP (SizeOf (CP), @CP, RetSize);
  189. if (RC <> 0) and (RC <> 473) then
  190. begin
  191. CP := 850;
  192. OSErrorWatch (RC);
  193. end;
  194. Str (CP, S);
  195. end
  196. else
  197. Str (Codepage, S);
  198. if (N <= Length (S) + 4) or (CodepageName = nil) then
  199. DummyUniMapCptoUcsCp := Uls_Invalid
  200. else
  201. begin
  202. Move (IBMPrefix, CodepageName^, SizeOf (IBMPrefix));
  203. Move (S [1], CodepageName [4], Length (S) * SizeOf (WideChar));
  204. CodepageName [Length (S) + 4] := #0;
  205. DummyUniMapCpToUcsCp := Uls_Success;
  206. end;
  207. end;
  208. function DummyUniUConvFromUcs (UConv_Object: TUConvObject;
  209. var UcsBuf: PWideChar; var UniCharsLeft: longint; var OutBuf: PChar;
  210. var OutBytesLeft: longint; var NonIdentical: longint): longint; cdecl;
  211. var
  212. Dest, Dest2: RawByteString;
  213. NoUConvObj: TUConvObject;
  214. RtlCp: TSystemCodepage;
  215. UcsLen: PtrInt;
  216. begin
  217. if UConv_Object = nil then
  218. RtlCp := OS2GetStandardCodePage (scpAnsi)
  219. else
  220. RtlCp := OS2CpToRtlCp (PDummyUConvObject (UConv_Object)^.CP, cpxMappingOnly,
  221. NoUConvObj);
  222. DefaultUnicode2AnsiMove (UcsBuf, Dest, RtlCp, UniCharsLeft);
  223. NonIdentical := 1; { Assume at least one substitution with dummy implementation }
  224. if Length (Dest) > OutBytesLeft then
  225. begin
  226. UcsLen := 1;
  227. repeat
  228. DefaultUnicode2AnsiMove (UcsBuf, Dest2, RtlCp, UcsLen);
  229. if Length (Dest2) <= OutBytesLeft then
  230. begin
  231. Dest := Dest2;
  232. end;
  233. Inc (UcsLen);
  234. until Length (Dest2) > OutBytesLeft;
  235. Dec (UcsLen);
  236. Inc (UcsBuf, UcsLen);
  237. Dec (UniCharsLeft, UcsLen);
  238. DummyUniUConvFromUcs := Uls_BufferFull;
  239. end
  240. else
  241. begin
  242. Inc (UcsBuf, UniCharsLeft);
  243. UniCharsLeft := 0;
  244. DummyUniUConvFromUcs := Uls_Success;
  245. end;
  246. Move (Dest [1], OutBuf^, Length (Dest));
  247. Inc (OutBuf, Length (Dest));
  248. Dec (OutBytesLeft, Length (Dest));
  249. end;
  250. function DummyUniUConvToUcs (UConv_Object: TUConvObject; var InBuf: PChar;
  251. var InBytesLeft: longint; var UcsBuf: PWideChar; var UniCharsLeft: longint;
  252. var NonIdentical: longint): longint; cdecl;
  253. var
  254. Dest, Dest2: UnicodeString;
  255. NoUConvObj: TUConvObject;
  256. RtlCp: TSystemCodepage;
  257. SrcLen: PtrInt;
  258. begin
  259. if UConv_Object = nil then
  260. RtlCp := OS2GetStandardCodePage (scpAnsi)
  261. else
  262. RtlCp := OS2CpToRtlCp (PDummyUConvObject (UConv_Object)^.CP, cpxMappingOnly,
  263. NoUConvObj);
  264. DefaultAnsi2UnicodeMove (InBuf, RtlCp, Dest, InBytesLeft);
  265. NonIdentical := 0; { Assume no need for substitutions in this direction }
  266. if Length (Dest) > UniCharsLeft then
  267. begin
  268. SrcLen := 1;
  269. repeat
  270. DefaultAnsi2UnicodeMove (InBuf, RtlCp, Dest2, SrcLen);
  271. if Length (Dest2) <= UniCharsLeft then
  272. begin
  273. Dest := Dest2;
  274. end;
  275. Inc (SrcLen);
  276. until Length (Dest2) > UniCharsLeft;
  277. Dec (SrcLen);
  278. Inc (InBuf, SrcLen);
  279. Dec (InBytesLeft, SrcLen);
  280. DummyUniUConvToUcs := Uls_BufferFull; { According to IBM documentation Uls_Invalid and not Uls_BufferFull as returned by UniUConvFromUcs?! }
  281. end
  282. else
  283. begin
  284. Inc (InBuf, InBytesLeft); { Shall it be increased in case of success too??? }
  285. InBytesLeft := 0;
  286. DummyUniUConvToUcs := Uls_Success;
  287. end;
  288. Move (Dest [1], UcsBuf^, Length (Dest) * 2);
  289. Inc (UcsBuf, Length (Dest)); { Shall it be increased in case of success too??? }
  290. Dec (UniCharsLeft, Length (Dest));
  291. end;
  292. const
  293. CpXList: TCpXList = (
  294. (WinCP: CP_UTF8; OS2CP: 1208; UConvObj: nil),
  295. (WinCP: CP_ASCII; OS2CP: 367; UConvObj: nil),
  296. (WinCP: 28597; OS2CP: 813; UConvObj: nil),
  297. (WinCP: 28591; OS2CP: 819; UConvObj: nil),
  298. (WinCP: 28592; OS2CP: 912; UConvObj: nil),
  299. (WinCP: 28593; OS2CP: 913; UConvObj: nil),
  300. (WinCP: 28594; OS2CP: 914; UConvObj: nil),
  301. (WinCP: 28595; OS2CP: 915; UConvObj: nil),
  302. (WinCP: 28598; OS2CP: 916; UConvObj: nil),
  303. (WinCP: 28599; OS2CP: 920; UConvObj: nil),
  304. (WinCP: 28603; OS2CP: 921; UConvObj: nil),
  305. (WinCP: 28605; OS2CP: 923; UConvObj: nil),
  306. (WinCP: 10000; OS2CP: 1275; UConvObj: nil),
  307. (WinCP: 10006; OS2CP: 1280; UConvObj: nil),
  308. (WinCP: 10081; OS2CP: 1281; UConvObj: nil),
  309. (WinCP: 10029; OS2CP: 1282; UConvObj: nil),
  310. (WinCP: 10007; OS2CP: 1283; UConvObj: nil),
  311. (WinCP: 20273; OS2CP: 273; UConvObj: nil),
  312. (WinCP: 20277; OS2CP: 277; UConvObj: nil),
  313. (WinCP: 20278; OS2CP: 278; UConvObj: nil),
  314. (WinCP: 20280; OS2CP: 280; UConvObj: nil),
  315. (WinCP: 20284; OS2CP: 284; UConvObj: nil),
  316. (WinCP: 20285; OS2CP: 285; UConvObj: nil),
  317. (WinCP: 20290; OS2CP: 290; UConvObj: nil),
  318. (WinCP: 20297; OS2CP: 297; UConvObj: nil),
  319. (WinCP: 20420; OS2CP: 420; UConvObj: nil),
  320. (WinCP: 20424; OS2CP: 424; UConvObj: nil),
  321. (WinCP: 20833; OS2CP: 833; UConvObj: nil),
  322. (WinCP: 20838; OS2CP: 838; UConvObj: nil),
  323. (WinCP: 20866; OS2CP: 878; UConvObj: nil),
  324. (WinCP: 737; OS2CP: 851; UConvObj: nil),
  325. (WinCP: 20924; OS2CP: 924; UConvObj: nil),
  326. (WinCP: 20932; OS2CP: 932; UConvObj: nil),
  327. (WinCP: 20936; OS2CP: 936; UConvObj: nil),
  328. (WinCP: 21025; OS2CP: 1025; UConvObj: nil),
  329. (WinCP: CP_UTF16; OS2CP: CP_UTF16; UConvObj: nil),
  330. (WinCP: 37; OS2CP: 37; UConvObj: nil),
  331. (WinCP: 437; OS2CP: 437; UConvObj: nil),
  332. (WinCP: 500; OS2CP: 500; UConvObj: nil),
  333. (WinCP: 850; OS2CP: 850; UConvObj: nil),
  334. (WinCP: 852; OS2CP: 852; UConvObj: nil),
  335. (WinCP: 855; OS2CP: 855; UConvObj: nil),
  336. (WinCP: 857; OS2CP: 857; UConvObj: nil),
  337. (WinCP: 860; OS2CP: 860; UConvObj: nil),
  338. (WinCP: 861; OS2CP: 861; UConvObj: nil),
  339. (WinCP: 862; OS2CP: 862; UConvObj: nil),
  340. (WinCP: 863; OS2CP: 863; UConvObj: nil),
  341. (WinCP: 864; OS2CP: 864; UConvObj: nil),
  342. (WinCP: 865; OS2CP: 865; UConvObj: nil),
  343. (WinCP: 866; OS2CP: 866; UConvObj: nil),
  344. (WinCP: 869; OS2CP: 869; UConvObj: nil),
  345. (WinCP: 870; OS2CP: 870; UConvObj: nil),
  346. (WinCP: 874; OS2CP: 874; UConvObj: nil),
  347. (WinCP: 875; OS2CP: 875; UConvObj: nil),
  348. (WinCP: 949; OS2CP: 949; UConvObj: nil),
  349. (WinCP: 950; OS2CP: 950; UConvObj: nil),
  350. (WinCP: 1026; OS2CP: 1026; UConvObj: nil),
  351. (WinCP: 1047; OS2CP: 1047; UConvObj: nil),
  352. (WinCP: 1140; OS2CP: 1140; UConvObj: nil),
  353. (WinCP: 1141; OS2CP: 1141; UConvObj: nil),
  354. (WinCP: 1142; OS2CP: 1142; UConvObj: nil),
  355. (WinCP: 1143; OS2CP: 1143; UConvObj: nil),
  356. (WinCP: 1144; OS2CP: 1144; UConvObj: nil),
  357. (WinCP: 1145; OS2CP: 1145; UConvObj: nil),
  358. (WinCP: 1146; OS2CP: 1146; UConvObj: nil),
  359. (WinCP: 1147; OS2CP: 1147; UConvObj: nil),
  360. (WinCP: 1148; OS2CP: 1148; UConvObj: nil),
  361. (WinCP: 1149; OS2CP: 1149; UConvObj: nil),
  362. (WinCP: 1250; OS2CP: 1250; UConvObj: nil),
  363. (WinCP: 1251; OS2CP: 1251; UConvObj: nil),
  364. (WinCP: 1252; OS2CP: 1252; UConvObj: nil),
  365. (WinCP: 1253; OS2CP: 1253; UConvObj: nil),
  366. (WinCP: 1254; OS2CP: 1254; UConvObj: nil),
  367. (WinCP: 1255; OS2CP: 1255; UConvObj: nil),
  368. (WinCP: 1256; OS2CP: 1256; UConvObj: nil),
  369. (WinCP: 1257; OS2CP: 1257; UConvObj: nil)
  370. );
  371. (* Possibly add index tables for both directions and binary search??? *)
  372. function UConvObjectForCP (CP: cardinal; var UConvObj: TUConvObject): longint;
  373. var
  374. RC: longint;
  375. A: array [0..12] of WideChar;
  376. begin
  377. UConvObj := nil;
  378. RC := Sys_UniMapCpToUcsCp (CP, @A, 12);
  379. if RC = 0 then
  380. RC := Sys_UniCreateUconvObject (@A, UConvObj);
  381. {$WARNING: TODO: Deallocate some previously allocated UConvObj and try again if failed}
  382. UConvObjectForCP := RC;
  383. if RC <> 0 then
  384. OSErrorWatch (RC);
  385. end;
  386. function OS2CPtoRtlCP (CP: cardinal; ReqFlags: byte;
  387. var UConvObj: TUConvObject): TSystemCodepage;
  388. var
  389. I, I2: cardinal;
  390. RCI: longint;
  391. begin
  392. OS2CPtoRtlCP := TSystemCodePage (CP);
  393. UConvObj := nil;
  394. if not UniAPI then (* No UniAPI => no need for UConvObj *)
  395. ReqFlags := ReqFlags or CpxMappingOnly;
  396. if CP = DefCpRec.OS2CP then
  397. begin
  398. if RTLUsesWinCP then
  399. OS2CPtoRtlCP := DefCpRec.WinCP;
  400. if ReqFlags and CpxMappingOnly = 0 then
  401. UConvObj := DefCpRec.UConvObj;
  402. end
  403. else
  404. begin
  405. I := 1;
  406. if ReqFlags and CpxSpecial = CpxSpecial then
  407. I2 := 2
  408. else
  409. if ReqFlags and CpxMappingOnly = CpxMappingOnly then
  410. I2 := MaxNonEqualCPMapping
  411. else
  412. I2 := MaxCPMapping;
  413. while I <= I2 do
  414. begin
  415. if CP = CpXList [I].OS2CP then
  416. begin
  417. if RTLUsesWinCP then
  418. OS2CPtoRtlCP := CpXList [I].WinCP;
  419. if ReqFlags and CpxMappingOnly = 0 then
  420. begin
  421. if CpXList [I].UConvObj = nil then
  422. begin
  423. if UConvObjectForCP (CpXList [I].OS2CP, UConvObj) = Uls_Success
  424. then
  425. CpXList [I].UConvObj := UConvObj
  426. else
  427. UConvObj := nil;
  428. end
  429. else
  430. UConvObj := CpXList [I].UConvObj;
  431. end;
  432. Exit;
  433. end;
  434. Inc (I);
  435. end;
  436. (* If codepage was not found in the translation table and UConvObj is
  437. requested, allocate one in the temporary record. *)
  438. if ReqFlags and CpxMappingOnly = 0 then
  439. begin
  440. if TempCpRec.OS2CP = CP then
  441. UConvObj := TempCpRec.UConvObj
  442. else
  443. begin
  444. if TempCpRec.UConvObj <> nil then
  445. begin
  446. RCI := Sys_UniFreeUConvObject (TempCpRec.UConvObj);
  447. if RCI <> 0 then
  448. OSErrorWatch (cardinal (RCI));
  449. end;
  450. if UConvObjectForCP (CP, UConvObj) = Uls_Success then
  451. begin
  452. TempCpRec.UConvObj := UConvObj;
  453. TempCpRec.OS2CP := CP;
  454. end
  455. else
  456. UConvObj := nil;
  457. end;
  458. end;
  459. end;
  460. end;
  461. function RtlCPtoOS2CP (RtlCP: TSystemCodepage; ReqFlags: byte;
  462. var UConvObj: TUConvObject): cardinal;
  463. var
  464. I, I2: cardinal;
  465. begin
  466. RtlCPtoOS2CP := RtlCP;
  467. UConvObj := nil;
  468. if not UniAPI then (* No UniAPI => no need for UConvObj *)
  469. ReqFlags := ReqFlags or CpxMappingOnly;
  470. if not (RTLUsesWinCP) then
  471. begin
  472. if ReqFlags and CpxMappingOnly = 0 then
  473. OS2CPtoRtlCP (cardinal (RtlCp), ReqFlags, UConvObj);
  474. end
  475. else if RtlCP = DefCpRec.WinCP then
  476. begin
  477. RtlCPtoOS2CP := DefCpRec.WinCP;
  478. if ReqFlags and CpxMappingOnly = 0 then
  479. UConvObj := DefCpRec.UConvObj;
  480. end
  481. else
  482. begin
  483. I := 1;
  484. if ReqFlags and CpxSpecial = CpxSpecial then
  485. I2 := 2
  486. else
  487. if ReqFlags and CpxMappingOnly = CpxMappingOnly then
  488. I2 := MaxNonEqualCPMapping
  489. else
  490. I2 := MaxCPMapping;
  491. while I <= I2 do
  492. begin
  493. if RtlCP = CpXList [I].WinCP then
  494. begin
  495. RtlCPtoOS2CP := CpXList [I].OS2CP;
  496. if ReqFlags and CpxMappingOnly = 0 then
  497. begin
  498. begin
  499. if UConvObjectForCP (CpXList [I].OS2CP, UConvObj) = Uls_Success then
  500. CpXList [I].UConvObj := UConvObj
  501. else
  502. UConvObj := nil;
  503. end
  504. end;
  505. Exit;
  506. end;
  507. Inc (I);
  508. end;
  509. (*
  510. Special processing for
  511. ExceptionWinCodepages = (CP_UTF16BE, CP_UTF7, 12000 {UTF32}, 12001 {UTF32BE})
  512. might be added here...or not ;-)
  513. if (TempCpRec.OS2CP <> High (TempCpRec.OS2CP)) or
  514. (TempCpRec.WinCP <> RtlCp) then
  515. begin
  516. if TempCpRec.UConvObj <> nil then
  517. begin
  518. RCI := Sys_UniFreeUConvObject (TempCpRec.UConvObj);
  519. if RCI <> 0 then
  520. OSErrorWatch (cardinal (RCI));
  521. end;
  522. TempCpRec.OS2CP := High (TempCpRec.OS2CP);
  523. TempCpRec.WinCP := RtlCp;
  524. end;
  525. Map to CP_ASCII aka OS2CP=367 if RtlCP not recognized and UConvObject
  526. is requested???
  527. *)
  528. (* Signalize unrecognized (untranslatable) MS Windows codepage *)
  529. OSErrorWatch (Uls_Invalid);
  530. end;
  531. end;
  532. function OS2CPtoRtlCP (CP: cardinal; ReqFlags: byte): TSystemCodepage;
  533. var
  534. NoUConvObj: TUConvObject;
  535. begin
  536. if RtlUsesWinCP then
  537. OS2CPtoRtlCP := OS2CPtoRtlCP (CP, ReqFlags or CpxMappingOnly, NoUConvObj)
  538. else
  539. OS2CPtoRtlCP := TSystemCodepage (CP);
  540. end;
  541. function RtlCPtoOS2CP (RtlCP: TSystemCodepage; ReqFlags: byte): cardinal;
  542. var
  543. NoUConvObj: TUConvObject;
  544. begin
  545. if RtlUsesWinCP then
  546. RtlCPtoOS2CP := RtlCPtoOS2CP (RtlCP, ReqFlags or CpxMappingOnly, NoUConvObj)
  547. else
  548. RtlCPtoOS2CP := RtlCP;
  549. end;
  550. procedure OS2Unicode2AnsiMove (Source: PUnicodeChar; var Dest: RawByteString;
  551. CP: TSystemCodePage; Len: SizeInt);
  552. var
  553. RCI: longint;
  554. UConvObj: TUConvObject;
  555. OS2CP: cardinal;
  556. Src2: PUnicodeChar;
  557. Len2, LenOut, OutOffset, NonIdentical: longint;
  558. Dest2: PChar;
  559. begin
  560. OS2CP := RtlCpToOS2CP (CP, CpxAll, UConvObj);
  561. { if UniAPI and (UConvObj = nil) then - OS2Unicode2AnsiMove should be never called if not UniAPI }
  562. if UConvObj = nil then
  563. begin
  564. {$WARNING Special cases like UTF-7 should be handled here, otherwise signalize error - how???}
  565. DefaultUnicode2AnsiMove (Source, Dest, CP, Len);
  566. Exit;
  567. end;
  568. LenOut := Succ (Len); (* Standard OS/2 CP is a SBCS *)
  569. SetLength (Dest, LenOut);
  570. SetCodePage (Dest, CP, false);
  571. Src2 := Source;
  572. Len2 := Len;
  573. Dest2 := PChar (Dest);
  574. RCI := Sys_UniUConvFromUcs (UConvObj, Src2, Len2, Dest2, LenOut,
  575. NonIdentical);
  576. repeat
  577. case RCI of
  578. Uls_Success:
  579. begin
  580. if LenOut > 0 then
  581. SetLength (Dest, Length (Dest) - LenOut);
  582. Break;
  583. end;
  584. Uls_IllegalSequence:
  585. begin
  586. OSErrorWatch (Uls_IllegalSequence);
  587. { skip and set to '?' }
  588. Inc (Src2);
  589. Dec (Len2);
  590. Dest2^ := '?';
  591. Inc (Dest2);
  592. Dec (LenOut);
  593. end;
  594. Uls_BufferFull:
  595. begin
  596. OutOffset := Dest2 - PChar (Dest);
  597. (* Use Len2 or Len decreased by difference between Source and Src2? *)
  598. (* Extend more this time - target is probably a DBCS or UTF-8 *)
  599. SetLength (Dest, Length (Dest) + Succ (Len2 * 2));
  600. { string could have been moved }
  601. Dest2 := PChar (Dest) + OutOffset;
  602. Inc (LenOut, Succ (Len2 * 2));
  603. end
  604. else
  605. begin
  606. SetLength (Dest, 0);
  607. OSErrorWatch (cardinal (RCI));
  608. { Break }
  609. RunError (231);
  610. end;
  611. end;
  612. RCI := Sys_UniUConvFromUcs (UConvObj, Src2, Len2, Dest2, LenOut,
  613. NonIdentical);
  614. until false;
  615. end;
  616. procedure OS2Ansi2UnicodeMove (Source: PChar; CP: TSystemCodePage;
  617. var Dest: UnicodeString; Len: SizeInt);
  618. var
  619. RCI: longint;
  620. UConvObj: TUConvObject;
  621. OS2CP: cardinal;
  622. Src2: PChar;
  623. Len2, LenOut, OutOffset, NonIdentical: longint;
  624. Dest2: PWideChar;
  625. begin
  626. OS2CP := RtlCpToOS2CP (CP, CpxAll, UConvObj);
  627. { if UniAPI and (UConvObj = nil) then - OS2Unicode2AnsiMove should be never called if not UniAPI }
  628. if UConvObj = nil then
  629. begin
  630. {$WARNING Special cases like UTF-7 should be handled here, otherwise signalize error - how???}
  631. DefaultAnsi2UnicodeMove (Source, CP, Dest, Len);
  632. Exit;
  633. end;
  634. LenOut := Succ (Len); (* Standard OS/2 CP is a SBCS *)
  635. SetLength (Dest, LenOut);
  636. Src2 := Source;
  637. Len2 := Len;
  638. Dest2 := PWideChar (Dest);
  639. RCI := Sys_UniUConvToUcs (UConvObj, Src2, Len2, Dest2, LenOut, NonIdentical);
  640. repeat
  641. case RCI of
  642. Uls_Success:
  643. begin
  644. if LenOut > 0 then
  645. SetLength (Dest, Length (Dest) - LenOut);
  646. Break;
  647. end;
  648. Uls_IllegalSequence:
  649. begin
  650. OSErrorWatch (Uls_IllegalSequence);
  651. { skip and set to '?' }
  652. Inc (Src2);
  653. Dec (Len2);
  654. Dest2^ := '?';
  655. Inc (Dest2);
  656. Dec (LenOut);
  657. end;
  658. Uls_BufferFull:
  659. begin
  660. OutOffset := Dest2 - PWideChar (Dest);
  661. (* Use Len2 or Len decreased by difference between Source and Src2? *)
  662. SetLength (Dest, Length (Dest) + Succ (Len2));
  663. { string could have been moved }
  664. Dest2 := PWideChar (Dest) + OutOffset;
  665. Inc (LenOut, Succ (Len2));
  666. end
  667. else
  668. begin
  669. SetLength (Dest, 0);
  670. OSErrorWatch (cardinal (RCI));
  671. { Break }
  672. RunError (231);
  673. end;
  674. end;
  675. RCI := Sys_UniUConvToUcs (UConvObj, Src2, Len2, Dest2, LenOut,
  676. NonIdentical);
  677. until false;
  678. {???
  679. PUnicodeRec(pointer(dest)-UnicodeFirstOff)^.CodePage:=CP_UTF16;
  680. }
  681. end;
  682. function RtlChangeCP (CP: TSystemCodePage): longint;
  683. var
  684. OS2CP, I: cardinal;
  685. NoUConvObj: TUConvObject;
  686. RCI: longint;
  687. begin
  688. OS2CP := RtlCpToOS2Cp (CP, cpxMappingOnly, NoUConvObj);
  689. RtlChangeCP := longint (DosSetProcessCP (OS2CP));
  690. if RtlChangeCP <> 0 then
  691. OSErrorWatch (RtlChangeCP)
  692. else
  693. begin
  694. DefaultSystemCodePage := CP;
  695. DefaultRTLFileSystemCodePage := DefaultSystemCodePage;
  696. DefaultFileSystemCodePage := DefaultSystemCodePage;
  697. if OS2CP <> DefCpRec.OS2CP then
  698. begin
  699. if DefCpRec.UConvObj <> nil then
  700. begin
  701. RCI := Sys_UniFreeUConvObject (DefCpRec.UConvObj);
  702. if RCI <> 0 then
  703. OSErrorWatch (cardinal (RCI));
  704. DefCpRec.UConvObj := nil;
  705. end;
  706. DefCPRec.OS2CP := OS2CP;
  707. RCI := Sys_UniCreateUConvObject (@WNull, DefCpRec.UConvObj);
  708. if RCI <> 0 then
  709. OSErrorWatch (cardinal (RCI));
  710. (* Find out WinCP _without_ considering RtlUsesWinCP *)
  711. I := 1;
  712. while (I <= MaxNonEqualCPMapping) and (CpXList [I].OS2CP <> OS2CP) do
  713. Inc (I);
  714. if CpXList [I].OS2CP = OS2CP then
  715. DefCpRec.WinCP := CpXList [I].WinCP
  716. else
  717. DefCpRec.WinCP := OS2CP;
  718. end;
  719. end;
  720. end;
  721. {
  722. function Win32UnicodeUpper(const s : UnicodeString) : UnicodeString;
  723. begin
  724. result:=s;
  725. UniqueString(result);
  726. if length(result)>0 then
  727. CharUpperBuff(LPWSTR(result),length(result));
  728. end;
  729. function Win32UnicodeLower(const s : UnicodeString) : UnicodeString;
  730. begin
  731. result:=s;
  732. UniqueString(result);
  733. if length(result)>0 then
  734. CharLowerBuff(LPWSTR(result),length(result));
  735. end;
  736. }
  737. (*
  738. CWSTRING:
  739. function LowerWideString(const s : WideString) : WideString;
  740. var
  741. i : SizeInt;
  742. begin
  743. SetLength(result,length(s));
  744. for i:=0 to length(s)-1 do
  745. pwidechar(result)[i]:=WideChar(towlower(wint_t(s[i+1])));
  746. end;
  747. function UpperWideString(const s : WideString) : WideString;
  748. var
  749. i : SizeInt;
  750. begin
  751. SetLength(result,length(s));
  752. for i:=0 to length(s)-1 do
  753. pwidechar(result)[i]:=WideChar(towupper(wint_t(s[i+1])));
  754. end;
  755. procedure EnsureAnsiLen(var S: AnsiString; const len: SizeInt); inline;
  756. begin
  757. if (len>length(s)) then
  758. if (length(s) < 10*256) then
  759. setlength(s,length(s)+10)
  760. else
  761. setlength(s,length(s)+length(s) shr 8);
  762. end;
  763. procedure ConcatCharToAnsiStr(const c: char; var S: AnsiString; var index: SizeInt);
  764. begin
  765. EnsureAnsiLen(s,index);
  766. pchar(@s[index])^:=c;
  767. inc(index);
  768. end;
  769. { concatenates an utf-32 char to a widestring. S *must* be unique when entering. }
  770. {$ifndef beos}
  771. procedure ConcatUTF32ToAnsiStr(const nc: wint_t; var S: AnsiString; var index: SizeInt; var mbstate: mbstate_t);
  772. {$else not beos}
  773. procedure ConcatUTF32ToAnsiStr(const nc: wint_t; var S: AnsiString; var index: SizeInt);
  774. {$endif beos}
  775. var
  776. p : pchar;
  777. mblen : size_t;
  778. begin
  779. { we know that s is unique -> avoid uniquestring calls}
  780. p:=@s[index];
  781. if (nc<=127) then
  782. ConcatCharToAnsiStr(char(nc),s,index)
  783. else
  784. begin
  785. EnsureAnsiLen(s,index+MB_CUR_MAX);
  786. {$ifndef beos}
  787. mblen:=wcrtomb(p,wchar_t(nc),@mbstate);
  788. {$else not beos}
  789. mblen:=wctomb(p,wchar_t(nc));
  790. {$endif not beos}
  791. if (mblen<>size_t(-1)) then
  792. inc(index,mblen)
  793. else
  794. begin
  795. { invalid wide char }
  796. p^:='?';
  797. inc(index);
  798. end;
  799. end;
  800. end;
  801. function LowerAnsiString(const s : AnsiString) : AnsiString;
  802. var
  803. i, slen,
  804. resindex : SizeInt;
  805. mblen : size_t;
  806. {$ifndef beos}
  807. ombstate,
  808. nmbstate : mbstate_t;
  809. {$endif beos}
  810. wc : wchar_t;
  811. begin
  812. {$ifndef beos}
  813. fillchar(ombstate,sizeof(ombstate),0);
  814. fillchar(nmbstate,sizeof(nmbstate),0);
  815. {$endif beos}
  816. slen:=length(s);
  817. SetLength(result,slen+10);
  818. i:=1;
  819. resindex:=1;
  820. while (i<=slen) do
  821. begin
  822. if (s[i]<=#127) then
  823. begin
  824. wc:=wchar_t(s[i]);
  825. mblen:= 1;
  826. end
  827. else
  828. {$ifndef beos}
  829. mblen:=mbrtowc(@wc, pchar(@s[i]), slen-i+1, @ombstate);
  830. {$else not beos}
  831. mblen:=mbtowc(@wc, pchar(@s[i]), slen-i+1);
  832. {$endif not beos}
  833. case mblen of
  834. size_t(-2):
  835. begin
  836. { partial invalid character, copy literally }
  837. while (i<=slen) do
  838. begin
  839. ConcatCharToAnsiStr(s[i],result,resindex);
  840. inc(i);
  841. end;
  842. end;
  843. size_t(-1), 0:
  844. begin
  845. { invalid or null character }
  846. ConcatCharToAnsiStr(s[i],result,resindex);
  847. inc(i);
  848. end;
  849. else
  850. begin
  851. { a valid sequence }
  852. { even if mblen = 1, the lowercase version may have a }
  853. { different length }
  854. { We can't do anything special if wchar_t is 16 bit... }
  855. {$ifndef beos}
  856. ConcatUTF32ToAnsiStr(towlower(wint_t(wc)),result,resindex,nmbstate);
  857. {$else not beos}
  858. ConcatUTF32ToAnsiStr(towlower(wint_t(wc)),result,resindex);
  859. {$endif not beos}
  860. inc(i,mblen);
  861. end;
  862. end;
  863. end;
  864. SetLength(result,resindex-1);
  865. end;
  866. function UpperAnsiString(const s : AnsiString) : AnsiString;
  867. var
  868. i, slen,
  869. resindex : SizeInt;
  870. mblen : size_t;
  871. {$ifndef beos}
  872. ombstate,
  873. nmbstate : mbstate_t;
  874. {$endif beos}
  875. wc : wchar_t;
  876. begin
  877. {$ifndef beos}
  878. fillchar(ombstate,sizeof(ombstate),0);
  879. fillchar(nmbstate,sizeof(nmbstate),0);
  880. {$endif beos}
  881. slen:=length(s);
  882. SetLength(result,slen+10);
  883. i:=1;
  884. resindex:=1;
  885. while (i<=slen) do
  886. begin
  887. if (s[i]<=#127) then
  888. begin
  889. wc:=wchar_t(s[i]);
  890. mblen:= 1;
  891. end
  892. else
  893. {$ifndef beos}
  894. mblen:=mbrtowc(@wc, pchar(@s[i]), slen-i+1, @ombstate);
  895. {$else not beos}
  896. mblen:=mbtowc(@wc, pchar(@s[i]), slen-i+1);
  897. {$endif beos}
  898. case mblen of
  899. size_t(-2):
  900. begin
  901. { partial invalid character, copy literally }
  902. while (i<=slen) do
  903. begin
  904. ConcatCharToAnsiStr(s[i],result,resindex);
  905. inc(i);
  906. end;
  907. end;
  908. size_t(-1), 0:
  909. begin
  910. { invalid or null character }
  911. ConcatCharToAnsiStr(s[i],result,resindex);
  912. inc(i);
  913. end;
  914. else
  915. begin
  916. { a valid sequence }
  917. { even if mblen = 1, the uppercase version may have a }
  918. { different length }
  919. { We can't do anything special if wchar_t is 16 bit... }
  920. {$ifndef beos}
  921. ConcatUTF32ToAnsiStr(towupper(wint_t(wc)),result,resindex,nmbstate);
  922. {$else not beos}
  923. ConcatUTF32ToAnsiStr(towupper(wint_t(wc)),result,resindex);
  924. {$endif not beos}
  925. inc(i,mblen);
  926. end;
  927. end;
  928. end;
  929. SetLength(result,resindex-1);
  930. end;
  931. function utf16toutf32(const S: WideString; const index: SizeInt; out len: longint): UCS4Char; external name 'FPC_UTF16TOUTF32';
  932. function WideStringToUCS4StringNoNulls(const s : WideString) : UCS4String;
  933. var
  934. i, slen,
  935. destindex : SizeInt;
  936. len : longint;
  937. uch : UCS4Char;
  938. begin
  939. slen:=length(s);
  940. setlength(result,slen+1);
  941. i:=1;
  942. destindex:=0;
  943. while (i<=slen) do
  944. begin
  945. uch:=utf16toutf32(s,i,len);
  946. if (uch=UCS4Char(0)) then
  947. uch:=UCS4Char(32);
  948. result[destindex]:=uch;
  949. inc(destindex);
  950. inc(i,len);
  951. end;
  952. result[destindex]:=UCS4Char(0);
  953. { destindex <= slen }
  954. setlength(result,destindex+1);
  955. end;
  956. function CompareWideString(const s1, s2 : WideString) : PtrInt;
  957. var
  958. hs1,hs2 : UCS4String;
  959. begin
  960. { wcscoll interprets null chars as end-of-string -> filter out }
  961. hs1:=WideStringToUCS4StringNoNulls(s1);
  962. hs2:=WideStringToUCS4StringNoNulls(s2);
  963. result:=wcscoll(pwchar_t(hs1),pwchar_t(hs2));
  964. end;
  965. function CompareTextWideString(const s1, s2 : WideString): PtrInt;
  966. begin
  967. result:=CompareWideString(UpperWideString(s1),UpperWideString(s2));
  968. end;
  969. function CharLengthPChar(const Str: PChar): PtrInt;
  970. var
  971. nextlen: ptrint;
  972. s: pchar;
  973. {$ifndef beos}
  974. mbstate: mbstate_t;
  975. {$endif not beos}
  976. begin
  977. result:=0;
  978. s:=str;
  979. {$ifndef beos}
  980. fillchar(mbstate,sizeof(mbstate),0);
  981. {$endif not beos}
  982. repeat
  983. {$ifdef beos}
  984. nextlen:=ptrint(mblen(str,MB_CUR_MAX));
  985. {$else beos}
  986. nextlen:=ptrint(mbrlen(str,MB_CUR_MAX,@mbstate));
  987. {$endif beos}
  988. { skip invalid/incomplete sequences }
  989. if (nextlen<0) then
  990. nextlen:=1;
  991. inc(result,nextlen);
  992. inc(s,nextlen);
  993. until (nextlen=0);
  994. end;
  995. function CodePointLength(const Str: PChar; maxlookahead: ptrint): PtrInt;
  996. var
  997. nextlen: ptrint;
  998. {$ifndef beos}
  999. mbstate: mbstate_t;
  1000. {$endif not beos}
  1001. begin
  1002. {$ifdef beos}
  1003. result:=ptrint(mblen(str,maxlookahead));
  1004. {$else beos}
  1005. fillchar(mbstate,sizeof(mbstate),0);
  1006. result:=ptrint(mbrlen(str,maxlookahead,@mbstate));
  1007. { mbrlen can also return -2 for "incomplete but potially valid character
  1008. and data has been processed" }
  1009. if result<0 then
  1010. result:=-1;
  1011. {$endif beos}
  1012. end;
  1013. function StrCompAnsiIntern(s1,s2 : PChar; len1, len2: PtrInt; canmodifys1, canmodifys2: boolean): PtrInt;
  1014. var
  1015. a,b: pchar;
  1016. i: PtrInt;
  1017. begin
  1018. if not(canmodifys1) then
  1019. getmem(a,len1+1)
  1020. else
  1021. a:=s1;
  1022. for i:=0 to len1-1 do
  1023. if s1[i]<>#0 then
  1024. a[i]:=s1[i]
  1025. else
  1026. a[i]:=#32;
  1027. a[len1]:=#0;
  1028. if not(canmodifys2) then
  1029. getmem(b,len2+1)
  1030. else
  1031. b:=s2;
  1032. for i:=0 to len2-1 do
  1033. if s2[i]<>#0 then
  1034. b[i]:=s2[i]
  1035. else
  1036. b[i]:=#32;
  1037. b[len2]:=#0;
  1038. result:=strcoll(a,b);
  1039. if not(canmodifys1) then
  1040. freemem(a);
  1041. if not(canmodifys2) then
  1042. freemem(b);
  1043. end;
  1044. function CompareStrAnsiString(const s1, s2: ansistring): PtrInt;
  1045. begin
  1046. result:=StrCompAnsiIntern(pchar(s1),pchar(s2),length(s1),length(s2),false,false);
  1047. end;
  1048. function StrCompAnsi(s1,s2 : PChar): PtrInt;
  1049. begin
  1050. result:=strcoll(s1,s2);
  1051. end;
  1052. function AnsiCompareText(const S1, S2: ansistring): PtrInt;
  1053. var
  1054. a, b: AnsiString;
  1055. begin
  1056. a:=UpperAnsistring(s1);
  1057. b:=UpperAnsistring(s2);
  1058. result:=StrCompAnsiIntern(pchar(a),pchar(b),length(a),length(b),true,true);
  1059. end;
  1060. function AnsiStrIComp(S1, S2: PChar): PtrInt;
  1061. begin
  1062. result:=AnsiCompareText(ansistring(s1),ansistring(s2));
  1063. end;
  1064. function AnsiStrLComp(S1, S2: PChar; MaxLen: PtrUInt): PtrInt;
  1065. var
  1066. a, b: pchar;
  1067. begin
  1068. if (maxlen=0) then
  1069. exit(0);
  1070. if (s1[maxlen]<>#0) then
  1071. begin
  1072. getmem(a,maxlen+1);
  1073. move(s1^,a^,maxlen);
  1074. a[maxlen]:=#0;
  1075. end
  1076. else
  1077. a:=s1;
  1078. if (s2[maxlen]<>#0) then
  1079. begin
  1080. getmem(b,maxlen+1);
  1081. move(s2^,b^,maxlen);
  1082. b[maxlen]:=#0;
  1083. end
  1084. else
  1085. b:=s2;
  1086. result:=StrCompAnsiIntern(a,b,maxlen,maxlen,a<>s1,b<>s2);
  1087. if (a<>s1) then
  1088. freemem(a);
  1089. if (b<>s2) then
  1090. freemem(b);
  1091. end;
  1092. function AnsiStrLIComp(S1, S2: PChar; MaxLen: PtrUInt): PtrInt;
  1093. var
  1094. a, b: ansistring;
  1095. begin
  1096. if (maxlen=0) then
  1097. exit(0);
  1098. setlength(a,maxlen);
  1099. move(s1^,a[1],maxlen);
  1100. setlength(b,maxlen);
  1101. move(s2^,b[1],maxlen);
  1102. result:=AnsiCompareText(a,b);
  1103. end;
  1104. procedure ansi2pchar(const s: ansistring; const orgp: pchar; out p: pchar);
  1105. var
  1106. newlen: sizeint;
  1107. begin
  1108. newlen:=length(s);
  1109. if newlen>strlen(orgp) then
  1110. fpc_rangeerror;
  1111. p:=orgp;
  1112. if (newlen>0) then
  1113. move(s[1],p[0],newlen);
  1114. p[newlen]:=#0;
  1115. end;
  1116. function AnsiStrLower(Str: PChar): PChar;
  1117. var
  1118. temp: ansistring;
  1119. begin
  1120. temp:=loweransistring(str);
  1121. ansi2pchar(temp,str,result);
  1122. end;
  1123. function AnsiStrUpper(Str: PChar): PChar;
  1124. var
  1125. temp: ansistring;
  1126. begin
  1127. temp:=upperansistring(str);
  1128. ansi2pchar(temp,str,result);
  1129. end;
  1130. {$ifdef FPC_HAS_CPSTRING}
  1131. {$i textrec.inc}
  1132. procedure SetStdIOCodePage(var T: Text); inline;
  1133. begin
  1134. case TextRec(T).Mode of
  1135. fmInput:TextRec(T).CodePage:=GetStandardCodePage(scpConsoleInput);
  1136. fmOutput:TextRec(T).CodePage:=GetStandardCodePage(scpConsoleOutput);
  1137. end;
  1138. end;
  1139. procedure SetStdIOCodePages; inline;
  1140. begin
  1141. SetStdIOCodePage(Input);
  1142. SetStdIOCodePage(Output);
  1143. SetStdIOCodePage(ErrOutput);
  1144. SetStdIOCodePage(StdOut);
  1145. SetStdIOCodePage(StdErr);
  1146. end;
  1147. {$endif FPC_HAS_CPSTRING}
  1148. *)
  1149. procedure InitOS2WideStringManager; inline;
  1150. var
  1151. RC: cardinal;
  1152. ErrName: array [0..MaxPathLen] of char;
  1153. P: pointer;
  1154. begin
  1155. RC := DosLoadModule (@ErrName [0], SizeOf (ErrName), @UConvName [0],
  1156. UConvHandle);
  1157. if RC = 0 then
  1158. begin
  1159. RC := DosQueryProcAddr (UConvHandle, OrdUniCreateUConvObject, nil, P);
  1160. if RC = 0 then
  1161. begin
  1162. Sys_UniCreateUConvObject := TUniCreateUConvObject (P);
  1163. RC := DosQueryProcAddr (UConvHandle, OrdUniMapCpToUcsCp, nil, P);
  1164. if RC = 0 then
  1165. begin
  1166. Sys_UniMapCpToUcsCp := TUniMapCpToUcsCp (P);
  1167. RC := DosQueryProcAddr (UConvHandle, OrdUniFreeUConvObject, nil, P);
  1168. if RC = 0 then
  1169. begin
  1170. Sys_UniFreeUConvObject := TUniFreeUConvObject (P);
  1171. RC := DosQueryProcAddr (UConvHandle, OrdUniUConvFromUcs, nil, P);
  1172. if RC = 0 then
  1173. begin
  1174. Sys_UniUConvFromUcs := TUniUConvFromUcs (P);
  1175. RC := DosQueryProcAddr (UConvHandle, OrdUniUConvToUcs, nil, P);
  1176. if RC = 0 then
  1177. begin
  1178. Sys_UniUConvToUcs := TUniUConvToUcs (P);
  1179. UniAPI := true;
  1180. end;
  1181. end;
  1182. end;
  1183. end;
  1184. end;
  1185. end;
  1186. if RC <> 0 then
  1187. OSErrorWatch (RC);
  1188. if not (UniAPI) then
  1189. begin
  1190. Sys_UniCreateUConvObject := @DummyUniCreateUConvObject;
  1191. Sys_UniMapCpToUcsCp := @DummyUniMapCpToUcsCp;
  1192. Sys_UniFreeUConvObject := @DummyUniFreeUConvObject;
  1193. Sys_UniUConvFromUcs := @DummyUniUConvFromUcs;
  1194. Sys_UniUConvToUcs := @DummyUniUConvToUcs;
  1195. end;
  1196. { Widestring }
  1197. WideStringManager.Wide2AnsiMoveProc := @OS2Unicode2AnsiMove;
  1198. WideStringManager.Ansi2WideMoveProc := @OS2Ansi2UnicodeMove;
  1199. { WideStringManager.UpperWideStringProc := @OS2UnicodeUpper;
  1200. WideStringManager.LowerWideStringProc := @OS2UnicodeLower;}
  1201. { Unicode }
  1202. WideStringManager.Unicode2AnsiMoveProc := @OS2Unicode2AnsiMove;
  1203. WideStringManager.Ansi2UnicodeMoveProc := @OS2Ansi2UnicodeMove;
  1204. { WideStringManager.UpperUnicodeStringProc := @OS2UnicodeUpper;
  1205. WideStringManager.LowerUnicodeStringProc := @OS2UnicodeLower;}
  1206. { Codepage }
  1207. WideStringManager.GetStandardCodePageProc := @OS2GetStandardCodePage;
  1208. (*
  1209. Wide2AnsiMoveProc:=@Wide2AnsiMove;
  1210. Ansi2WideMoveProc:=@Ansi2WideMove;
  1211. UpperWideStringProc:=@UpperWideString;
  1212. LowerWideStringProc:=@LowerWideString;
  1213. CompareWideStringProc:=@CompareWideString;
  1214. CompareTextWideStringProc:=@CompareTextWideString;
  1215. CharLengthPCharProc:=@CharLengthPChar;
  1216. CodePointLengthProc:=@CodePointLength;
  1217. UpperAnsiStringProc:=@UpperAnsiString;
  1218. LowerAnsiStringProc:=@LowerAnsiString;
  1219. CompareStrAnsiStringProc:=@CompareStrAnsiString;
  1220. CompareTextAnsiStringProc:=@AnsiCompareText;
  1221. StrCompAnsiStringProc:=@StrCompAnsi;
  1222. StrICompAnsiStringProc:=@AnsiStrIComp;
  1223. StrLCompAnsiStringProc:=@AnsiStrLComp;
  1224. StrLICompAnsiStringProc:=@AnsiStrLIComp;
  1225. StrLowerAnsiStringProc:=@AnsiStrLower;
  1226. StrUpperAnsiStringProc:=@AnsiStrUpper;
  1227. ThreadInitProc:=@InitThread;
  1228. ThreadFiniProc:=@FiniThread;
  1229. { Unicode }
  1230. Unicode2AnsiMoveProc:=@Wide2AnsiMove;
  1231. Ansi2UnicodeMoveProc:=@Ansi2WideMove;
  1232. UpperUnicodeStringProc:=@UpperWideString;
  1233. LowerUnicodeStringProc:=@LowerWideString;
  1234. CompareUnicodeStringProc:=@CompareWideString;
  1235. CompareTextUnicodeStringProc:=@CompareTextWideString;
  1236. *)
  1237. end;