dbf_lang.pas 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676
  1. unit dbf_lang;
  2. {
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1999-2022 by Pascal Ganaye,Micha Nelissen and other members of the
  5. Free Pascal development team
  6. DBF multilang support
  7. See the file COPYING.FPC, included in this distribution,
  8. for details about the copyright.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  12. **********************************************************************}
  13. {$I dbf_common.inc}
  14. interface
  15. uses
  16. {$ifdef WINDOWS}
  17. Windows;
  18. {$else}
  19. {$ifdef KYLIX}
  20. Libc,
  21. {$endif}
  22. Types, dbf_wtil;
  23. {$endif}
  24. const
  25. //*************************************************************************//
  26. // DB3/DB4/FoxPro Lang ID consts, for readable code
  27. //*************************************************************************//
  28. // ...
  29. FoxLangId_ENU_437 = $01; // DOS USA
  30. FoxLangId_Intl_850 = $02; // DOS multilingual
  31. FoxLangId_Windows_1252 = $03; // Windows ANSI
  32. FoxLangId_Mac_10000 = $04; // Standard Macintosh
  33. // ...
  34. DbfLangId_DAN_865 = $08;
  35. DbfLangId_NLD_437 = $09;
  36. DbfLangId_NLD_850 = $0A;
  37. DbfLangId_FIN_437 = $0B;
  38. DbfLangId_FIN_850 = $0C; // is it used? does not exist in BDE
  39. DbfLangId_FRA_437 = $0D;
  40. DbfLangId_FRA_850 = $0E;
  41. DbfLangId_DEU_437 = $0F;
  42. DbfLangId_DEU_850 = $10;
  43. DbfLangId_ITA_437 = $11;
  44. DbfLangId_ITA_850 = $12;
  45. DbfLangId_JPN_932 = $13;
  46. DbfLangId_ESP_850 = $14;
  47. DbfLangId_SVE_437 = $15;
  48. DbfLangId_SVE_850 = $16;
  49. DbfLangId_NOR_865 = $17;
  50. DbfLangId_ESP_437 = $18;
  51. DbfLangId_ENG_437 = $19;
  52. DbfLangId_ENG_850 = $1A;
  53. DbfLangId_ENU_437 = $1B;
  54. DbfLangId_FRC_863 = $1C;
  55. DbfLangId_FRC_850 = $1D;
  56. // ...
  57. DbfLangId_CSY_852 = $1F;
  58. DbfLangId_CSY_867 = $20;
  59. // ...
  60. DbfLangId_HUN_852 = $22;
  61. DbfLangId_PLK_852 = $23;
  62. DbfLangId_PTG_860 = $24;
  63. DbfLangId_PTB_850 = $25;
  64. DbfLangId_RUS_866 = $26;
  65. // ...
  66. DbfLangId_ENU_850 = $37;
  67. // ...
  68. DbfLangId_CHS_936 = $4D;
  69. DbfLangId_KOR_949 = $4E;
  70. DbfLangId_CHT_950 = $4F;
  71. DbfLangId_THA_874 = $50;
  72. // ...
  73. DbfLangId_JPN_DIC_932 = $56;
  74. DbfLangId_Ascii_1252 = $57;
  75. DbfLangId_WEurope_1252 = $58;
  76. DbfLangId_Spanish_1252 = $59;
  77. // ...
  78. // Additional FoxPro references:
  79. // http://msdn.microsoft.com/en-us/library/8t45x02s%28v=VS.80%29.aspx
  80. // http://www.clicketyclick.dk/databases/xbase/format/dbf.html#DBF_STRUCT
  81. FoxLangId_German_437 = $5E;
  82. FoxLangId_Nordic_437 = $5F;
  83. FoxLangId_Nordic_850 = $60;
  84. FoxLangId_German_1252 = $61;
  85. FoxLangId_Nordic_1252 = $62;
  86. // ...
  87. FoxLangId_EEurope_852 = $64; // DOS
  88. FoxLangId_Russia_866 = $65; // DOS //todo: verify, MS docs say this is $66
  89. FoxLangId_Nordic_865 = $66; // DOS //todo: verify, MS docs say this is $65
  90. FoxLangId_Iceland_861 = $67; // DOS
  91. FoxLangId_Czech_895 = $68; // DOS Kamenicky
  92. // ...
  93. DbfLangId_POL_620 = $69; // DOS Polish Mazovia
  94. // ...
  95. FoxLangId_Greek_737 = $6A; // DOS (437G)
  96. FoxLangId_Turkish_857 = $6B; // DOS
  97. // ...
  98. FoxLangId_Taiwan_950 = $78; // Windows
  99. FoxLangId_Korean_949 = $79; // Windows
  100. FoxLangId_Chinese_936 = $7A; // Windows Chinese simplified
  101. FoxLangId_Japan_932 = $7B; // Windows
  102. FoxLangId_Thai_874 = $7C; // Windows
  103. FoxLangId_Hebrew_1255 = $7D; // Windows
  104. FoxLangId_Arabic_1256 = $7E; // Windows
  105. // ...
  106. DbfLangId_Hebrew = $85;
  107. DbfLangId_ELL_437 = $86; // greek, code page 737 (?)
  108. DbfLangId_SLO_852 = $87;
  109. DbfLangId_TRK_857 = $88;
  110. // ...
  111. DbfLangId_BUL_868 = $8E;
  112. // ...
  113. FoxLangId_Russia_10007 = $96; // Macintosh
  114. FoxLangId_EEurope_10029 = $97; // Macintosh
  115. FoxLangId_Greek_10006 = $98; // Macintosh
  116. // ...
  117. FoxLangId_Czech_1250 = $9B;
  118. FoxLangId_Czech_850 = $9C; // DOS
  119. // ...
  120. FoxLangId_EEurope_1250 = $C8; // Windows
  121. FoxLangId_Russia_1251 = $C9; // Windows
  122. FoxLangId_Turkish_1254 = $CA; // Windows
  123. FoxLangId_Greek_1253 = $CB; // Windows
  124. // special constants
  125. DbfLocale_NotFound = $010000;
  126. DbfLocale_Bul868 = $020000;
  127. //*************************************************************************//
  128. // DB3/DB4/FoxPro Language ID to CodePage conversion table
  129. // Visual FoxPro docs call language ID "code page mark"
  130. // or "code page identifier"
  131. //*************************************************************************//
  132. LangId_To_CodePage: array[Byte] of Word =
  133. // | 0| 1| 2| 3| 4| 5| 6| 7|
  134. // | 8| 9| A| B| C| D| E| F|
  135. // | | | | | | | | |
  136. {00} ( 0, 437, 850, 1252,10000, 0, 0, 0,
  137. {08} 865, 437, 850, 437, 850, 437, 850, 437,
  138. {10} 850, 437, 850, 932, 850, 437, 850, 865,
  139. {18} 437, 437, 850, 437, 863, 850, 0, 852,
  140. {20} 867, 0, 852, 852, 860, 850, 866, 0,
  141. {28} 0, 0, 0, 0, 0, 0, 0, 0,
  142. {30} 0, 0, 0, 0, 0, 0, 0, 850,
  143. {38} 0, 0, 0, 0, 0, 0, 0, 0,
  144. {40} 0, 0, 0, 0, 0, 0, 0, 0,
  145. {48} 0, 0, 0, 0, 0, 936, 949, 950,
  146. {50} 874, 0, 0, 0, 0, 0, 932, 1252,
  147. {58} 1252, 1252, 0, 0, 0, 0, 437, 437,
  148. {60} 850, 1252, 1252, 0, 852, 866, 865, 861,
  149. {68} 895, 620, 737, 857, 0, 0, 0, 0,
  150. {70} 0, 0, 0, 0, 0, 0, 0, 0,
  151. {78} 950, 949, 936, 932, 874, 1255, 1256, 0,
  152. {80} 0, 0, 0, 0, 0, 862, 437, 852,
  153. {88} 857, 0, 0, 0, 0, 0, 868, 0,
  154. {90} 0, 0, 0, 0, 0, 0,10007,10029,
  155. {98} 10006, 0, 0, 1250, 850, 0, 0, 0,
  156. {A0} 0, 0, 0, 0, 0, 0, 0, 0,
  157. {A8} 0, 0, 0, 0, 0, 0, 0, 0,
  158. {B0} 0, 0, 0, 0, 0, 0, 0, 0,
  159. {B8} 0, 0, 0, 0, 0, 0, 0, 0,
  160. {C0} 0, 0, 0, 0, 0, 0, 0, 0,
  161. {C8} 1250, 1251, 1254, 1253, 0, 0, 0, 0,
  162. {D0} 0, 0, 0, 0, 0, 0, 0, 0,
  163. {D8} 0, 0, 0, 0, 0, 0, 0, 0,
  164. {E0} 0, 0, 0, 0, 0, 0, 0, 0,
  165. {E8} 0, 0, 0, 0, 0, 0, 0, 0,
  166. {F0} 0, 0, 0, 0, 0, 0, 0, 0,
  167. {F8} 0, 0, 0, 0, 0, 0, 0, 0);
  168. {$ifdef FPC_VERSION}
  169. {$ifdef VER1_0}
  170. LANG_ARABIC = $01;
  171. LANG_HEBREW = $0d;
  172. LANG_THAI = $1e;
  173. SUBLANG_KOREAN = $01; { Korean (Extended Wansung) }
  174. SORT_CHINESE_PRC = $2; { PRC Chinese Stroke Count order }
  175. {$endif}
  176. {$endif}
  177. //*************************************************************************//
  178. // DB3/DB4/FoxPro Language ID to Locale convert table
  179. //*************************************************************************//
  180. // table
  181. LangId_To_Locale: array[Byte] of LCID =
  182. (
  183. DbfLocale_NotFound,
  184. {01} LANG_ENGLISH or (SUBLANG_ENGLISH_US shl 10) or (SORT_DEFAULT shl 16),
  185. LANG_ENGLISH or (SUBLANG_ENGLISH_UK shl 10) or (SORT_DEFAULT shl 16), {international ??}
  186. LANG_ENGLISH or (SUBLANG_ENGLISH_UK shl 10) or (SORT_DEFAULT shl 16), {windows ??}
  187. LANG_ENGLISH or (SUBLANG_ENGLISH_UK shl 10) or (SORT_DEFAULT shl 16), {macintosh ??}
  188. 0,0,0,
  189. {08} LANG_DANISH or (SUBLANG_DEFAULT shl 10) or (SORT_DEFAULT shl 16),
  190. LANG_DUTCH or (SUBLANG_DUTCH shl 10) or (SORT_DEFAULT shl 16),
  191. LANG_DUTCH or (SUBLANG_DUTCH shl 10) or (SORT_DEFAULT shl 16),
  192. LANG_FINNISH or (SUBLANG_DEFAULT shl 10) or (SORT_DEFAULT shl 16),
  193. LANG_FINNISH or (SUBLANG_DEFAULT shl 10) or (SORT_DEFAULT shl 16),
  194. LANG_FRENCH or (SUBLANG_FRENCH shl 10) or (SORT_DEFAULT shl 16),
  195. LANG_FRENCH or (SUBLANG_FRENCH shl 10) or (SORT_DEFAULT shl 16),
  196. LANG_GERMAN or (SUBLANG_GERMAN shl 10) or (SORT_DEFAULT shl 16),
  197. LANG_GERMAN or (SUBLANG_GERMAN shl 10) or (SORT_DEFAULT shl 16),
  198. LANG_ITALIAN or (SUBLANG_ITALIAN shl 10) or (SORT_DEFAULT shl 16),
  199. LANG_ITALIAN or (SUBLANG_ITALIAN shl 10) or (SORT_DEFAULT shl 16),
  200. LANG_JAPANESE or (SUBLANG_DEFAULT shl 10) or (SORT_DEFAULT shl 16),
  201. LANG_SPANISH or (SUBLANG_SPANISH shl 10) or (SORT_DEFAULT shl 16),
  202. LANG_SWEDISH or (SUBLANG_DEFAULT shl 10) or (SORT_DEFAULT shl 16),
  203. LANG_SWEDISH or (SUBLANG_DEFAULT shl 10) or (SORT_DEFAULT shl 16),
  204. LANG_NORWEGIAN or (SUBLANG_DEFAULT shl 10) or (SORT_DEFAULT shl 16),
  205. LANG_SPANISH or (SUBLANG_DEFAULT shl 10) or (SORT_DEFAULT shl 16),
  206. LANG_ENGLISH or (SUBLANG_ENGLISH_UK shl 10) or (SORT_DEFAULT shl 16),
  207. LANG_ENGLISH or (SUBLANG_ENGLISH_UK shl 10) or (SORT_DEFAULT shl 16),
  208. LANG_ENGLISH or (SUBLANG_ENGLISH_US shl 10) or (SORT_DEFAULT shl 16),
  209. LANG_FRENCH or (SUBLANG_FRENCH_CANADIAN shl 10) or (SORT_DEFAULT shl 16),
  210. LANG_FRENCH or (SUBLANG_FRENCH_CANADIAN shl 10) or (SORT_DEFAULT shl 16),
  211. {1E} 0,
  212. {1F} LANG_CZECH or (SUBLANG_DEFAULT shl 10) or (SORT_DEFAULT shl 16),
  213. 0 {Used to be LANG_CZECH in previous versions but DBase IV tables show no support here.},
  214. {21} 0,
  215. {22} LANG_HUNGARIAN or (SUBLANG_DEFAULT shl 10) or (SORT_DEFAULT shl 16),
  216. LANG_POLISH or (SUBLANG_DEFAULT shl 10) or (SORT_DEFAULT shl 16),
  217. LANG_PORTUGUESE or (SUBLANG_PORTUGUESE_BRAZILIAN shl 10) or (SORT_DEFAULT shl 16),
  218. LANG_PORTUGUESE or (SUBLANG_PORTUGUESE_BRAZILIAN shl 10) or (SORT_DEFAULT shl 16),
  219. LANG_RUSSIAN or (SUBLANG_DEFAULT shl 10) or (SORT_DEFAULT shl 16),
  220. {27} 0,0,0,0,0,0,0,0,0,
  221. {30} 0,0,0,0,0,0,0,
  222. {37} LANG_ENGLISH or (SUBLANG_ENGLISH_US shl 10) or (SORT_DEFAULT shl 16),
  223. {38} 0,0,0,0,0,0,0,0,
  224. {40} 0,0,0,0,0,0,0,0,0,0,0,0,0,
  225. {4D} LANG_CHINESE or (SUBLANG_CHINESE_SIMPLIFIED shl 10) or (SORT_DEFAULT shl 16),
  226. LANG_KOREAN or (SUBLANG_KOREAN shl 10) or (SORT_DEFAULT shl 16),
  227. LANG_CHINESE or (SUBLANG_CHINESE_TRADITIONAL shl 10) or (SORT_DEFAULT shl 16),
  228. LANG_THAI or (SUBLANG_DEFAULT shl 10) or (SORT_DEFAULT shl 16),
  229. {51} 0,0,0,0,0,
  230. {56} LANG_JAPANESE or (SUBLANG_DEFAULT shl 10) or (SORT_DEFAULT shl 16), // JPN: Dic932 ??
  231. {57} 0, // ANSI/ASCII binary (interpret e.g. as ISO 8859_1 depending on client}
  232. LANG_ENGLISH or (SUBLANG_ENGLISH_UK shl 10) or (SORT_DEFAULT shl 16), // Western Europe ??
  233. LANG_SPANISH or (SUBLANG_SPANISH shl 10) or (SORT_DEFAULT shl 16),
  234. {5A} 0,0,0,0,
  235. // FoxPro
  236. {5E} LANG_GERMAN or (SUBLANG_GERMAN shl 10) or (SORT_DEFAULT shl 16),
  237. LANG_NORWEGIAN or (SUBLANG_DEFAULT shl 10) or (SORT_DEFAULT shl 16),
  238. LANG_NORWEGIAN or (SUBLANG_DEFAULT shl 10) or (SORT_DEFAULT shl 16),
  239. LANG_GERMAN or (SUBLANG_DEFAULT shl 10) or (SORT_DEFAULT shl 16),
  240. LANG_NORWEGIAN or (SUBLANG_DEFAULT shl 10) or (SORT_DEFAULT shl 16),
  241. {63} 0,
  242. {64} LANG_CZECH or (SUBLANG_DEFAULT shl 10) or (SORT_DEFAULT shl 16), // Eastern Europe ??
  243. LANG_RUSSIAN or (SUBLANG_DEFAULT shl 10) or (SORT_DEFAULT shl 16),
  244. LANG_NORWEGIAN or (SUBLANG_DEFAULT shl 10) or (SORT_DEFAULT shl 16),
  245. LANG_ICELANDIC or (SUBLANG_DEFAULT shl 10) or (SORT_DEFAULT shl 16),
  246. LANG_CZECH or (SUBLANG_DEFAULT shl 10) or (SORT_DEFAULT shl 16),
  247. LANG_POLISH or (SUBLANG_DEFAULT shl 10) or (SORT_DEFAULT shl 16),
  248. LANG_GREEK or (SUBLANG_DEFAULT shl 10) or (SORT_DEFAULT shl 16),
  249. LANG_TURKISH or (SUBLANG_DEFAULT shl 10) or (SORT_DEFAULT shl 16),
  250. {6C} 0,0,0,0,
  251. {70} 0,0,0,0,0,0,0,0,
  252. {78} LANG_CHINESE or (SUBLANG_CHINESE_HONGKONG shl 10) or (SORT_DEFAULT shl 16),
  253. LANG_KOREAN or (SUBLANG_KOREAN shl 10) or (SORT_DEFAULT shl 16),
  254. LANG_CHINESE or (SUBLANG_CHINESE_SINGAPORE shl 10) or (SORT_CHINESE_PRC shl 16),
  255. LANG_JAPANESE or (SUBLANG_DEFAULT shl 10) or (SORT_DEFAULT shl 16), // JPN: Dic932 ??
  256. LANG_THAI or (SUBLANG_DEFAULT shl 10) or (SORT_DEFAULT shl 16),
  257. LANG_HEBREW or (SUBLANG_DEFAULT shl 10) or (SORT_DEFAULT shl 16),
  258. LANG_ARABIC or (SUBLANG_DEFAULT shl 10) or (SORT_DEFAULT shl 16),
  259. 0,
  260. {80} 0,0,0,0,0,
  261. // dBase
  262. {85} LANG_HEBREW or (SUBLANG_DEFAULT shl 10) or (SORT_DEFAULT shl 16),
  263. LANG_GREEK or (SUBLANG_DEFAULT shl 10) or (SORT_DEFAULT shl 16),
  264. LANG_SLOVAK or (SUBLANG_DEFAULT shl 10) or (SORT_DEFAULT shl 16),
  265. LANG_TURKISH or (SUBLANG_DEFAULT shl 10) or (SORT_DEFAULT shl 16),
  266. {89} 0,0,0,0,0,
  267. {8E} LANG_BULGARIAN or (SUBLANG_DEFAULT shl 10) or (SORT_DEFAULT shl 16),
  268. {8F} 0,0,0,0,0,0,0,
  269. {96} LANG_RUSSIAN or (SUBLANG_DEFAULT shl 10) or (SORT_DEFAULT shl 16),
  270. LANG_CZECH or (SUBLANG_DEFAULT shl 10) or (SORT_DEFAULT shl 16), // Eastern Europe ??
  271. LANG_GREEK or (SUBLANG_DEFAULT shl 10) or (SORT_DEFAULT shl 16),
  272. 0,0,
  273. // FoxPro
  274. {9B} LANG_CZECH or (SUBLANG_DEFAULT shl 10) or (SORT_DEFAULT shl 16),
  275. LANG_CZECH or (SUBLANG_DEFAULT shl 10) or (SORT_DEFAULT shl 16),
  276. {9D} 0,0,0,
  277. {A0} 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  278. {B0} 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  279. {C0} 0,0,0,0,0,0,0,0,
  280. {C8} LANG_CZECH or (SUBLANG_DEFAULT shl 10) or (SORT_DEFAULT shl 16), // Eastern Europe ??
  281. LANG_RUSSIAN or (SUBLANG_DEFAULT shl 10) or (SORT_DEFAULT shl 16),
  282. LANG_TURKISH or (SUBLANG_DEFAULT shl 10) or (SORT_DEFAULT shl 16),
  283. LANG_GREEK or (SUBLANG_DEFAULT shl 10) or (SORT_DEFAULT shl 16),
  284. {CC} 0,0,0,0,
  285. {D0} 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  286. {E0} 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  287. {F0} 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  288. );
  289. //*************************************************************************//
  290. // Visual FoxPro CodePage<>Language ID conversion table
  291. //*************************************************************************//
  292. // table: note layout is different:
  293. VFPCodePage_LangID: array[0..51] of integer =
  294. // Code page|Codepage identifier/LangID
  295. (
  296. 437,$01,// U.S. MS-DOS
  297. 620,$69,// Mazovia (Polish) MS-DOS
  298. 737,$6A,// Greek MS-DOS (437G)
  299. 850,$02,// International MS-DOS
  300. 852,$64,// Eastern European MS-DOS
  301. 857,$6B,// Turkish MS-DOS
  302. 861,$67,// Icelandic MS-DOS
  303. 865,$66,// Nordic MS-DOS //todo: verify this. not 65?
  304. 866,$64,// Russian MS-DOS //todo: verify this. not 66?
  305. 874,$7C,// Thai Windows
  306. 895,$68,// Kamenicky (Czech) MS-DOS
  307. 932,$7B,// Japanese Windows
  308. 936,$7A,// Chinese Simplified (PRC, Singapore) Windows
  309. 949,$79,// Korean Windows
  310. 950,$78,// Traditional Chinese (Hong Kong SAR, Taiwan) Windows
  311. 1250,$C8,// Eastern European Windows
  312. 1251,$C9,// Russian Windows
  313. 1252,$03,// Windows ANSI
  314. 1253,$CB,// Greek Windows
  315. 1254,$CA,// Turkish Windows
  316. 1255,$7D,// Hebrew Windows
  317. 1256,$7E,// Arabic Windows
  318. 10000,$04,// Standard Macintosh
  319. 10006,$98,// Greek Macintosh
  320. 10007,$96,// Russian Macintosh
  321. 10029,$97// Macintosh EE (=Eastern European?)
  322. );
  323. //*************************************************************************//
  324. // DB7 LangID Locale substrings
  325. //*************************************************************************//
  326. // convert table
  327. LangId_To_LocaleStr: array[Byte] of Cardinal =
  328. (
  329. DbfLocale_NotFound,
  330. {01} Ord('U') or (Ord('S') shl 8) or (Ord('0') shl 16),
  331. Ord('U') or (Ord('K') shl 8) or (Ord('0') shl 16),
  332. Ord('U') or (Ord('K') shl 8) or (Ord('0') shl 16),
  333. Ord('U') or (Ord('K') shl 8) or (Ord('0') shl 16),
  334. 0,0,0,
  335. {08} Ord('D') or (Ord('A') shl 8) or (Ord('0') shl 16),
  336. Ord('N') or (Ord('L') shl 8) or (Ord('0') shl 16),
  337. Ord('N') or (Ord('L') shl 8) or (Ord('0') shl 16),
  338. Ord('F') or (Ord('I') shl 8) or (Ord('0') shl 16),
  339. Ord('F') or (Ord('I') shl 8) or (Ord('0') shl 16),
  340. Ord('F') or (Ord('R') shl 8) or (Ord('0') shl 16),
  341. Ord('F') or (Ord('R') shl 8) or (Ord('0') shl 16),
  342. Ord('D') or (Ord('E') shl 8) or (Ord('0') shl 16),
  343. Ord('D') or (Ord('E') shl 8) or (Ord('0') shl 16),
  344. Ord('I') or (Ord('T') shl 8) or (Ord('0') shl 16),
  345. Ord('I') or (Ord('T') shl 8) or (Ord('1') shl 16),
  346. Ord('J') or (Ord('P') shl 8) or (Ord('0') shl 16),
  347. Ord('E') or (Ord('S') shl 8) or (Ord('0') shl 16),
  348. Ord('S') or (Ord('V') shl 8) or (Ord('0') shl 16),
  349. Ord('S') or (Ord('V') shl 8) or (Ord('1') shl 16),
  350. Ord('N') or (Ord('O') shl 8) or (Ord('0') shl 16),
  351. Ord('E') or (Ord('S') shl 8) or (Ord('1') shl 16),
  352. Ord('U') or (Ord('K') shl 8) or (Ord('0') shl 16),
  353. Ord('U') or (Ord('K') shl 8) or (Ord('0') shl 16),
  354. Ord('U') or (Ord('S') shl 8) or (Ord('0') shl 16),
  355. Ord('C') or (Ord('F') shl 8) or (Ord('1') shl 16),
  356. Ord('C') or (Ord('F') shl 8) or (Ord('1') shl 16),
  357. {1E} 0,
  358. {1F} Ord('C') or (Ord('Z') shl 8) or (Ord('0') shl 16),
  359. Ord('C') or (Ord('Z') shl 8) or (Ord('0') shl 16),
  360. {21} 0,
  361. {22} Ord('H') or (Ord('D') shl 8) or (Ord('C') shl 16),
  362. Ord('P') or (Ord('O') shl 8) or (Ord('0') shl 16),
  363. Ord('P') or (Ord('T') shl 8) or (Ord('0') shl 16),
  364. Ord('P') or (Ord('T') shl 8) or (Ord('0') shl 16),
  365. Ord('R') or (Ord('U') shl 8) or (Ord('0') shl 16),
  366. {27} 0,0,0,0,0,0,0,0,0,
  367. {30} 0,0,0,0,0,0,0,
  368. {37} Ord('U') or (Ord('S') shl 8) or (Ord('0') shl 16),
  369. {38} 0,0,0,0,0,0,0,0,
  370. {40} 0,0,0,0,0,0,0,0,0,0,0,0,0,
  371. {4D} Ord('C') or (Ord('N') shl 8) or (Ord('0') shl 16),
  372. Ord('K') or (Ord('O') shl 8) or (Ord('0') shl 16),
  373. Ord('T') or (Ord('W') shl 8) or (Ord('0') shl 16),
  374. Ord('T') or (Ord('H') shl 8) or (Ord('0') shl 16),
  375. {51} 0,0,0,0,0,
  376. {56} Ord('J') or (Ord('P') shl 8) or (Ord('1') shl 16),
  377. Ord('U') or (Ord('S') shl 8) or (Ord('0') shl 16),
  378. Ord('W') or (Ord('E') shl 8) or (Ord('0') shl 16),
  379. Ord('E') or (Ord('S') shl 8) or (Ord('0') shl 16),
  380. {5A} 0,0,0,0,
  381. // FoxPro
  382. {5E} Ord('D') or (Ord('E') shl 8),
  383. Ord('N') or (Ord('O') shl 8),
  384. Ord('N') or (Ord('O') shl 8),
  385. Ord('D') or (Ord('E') shl 8),
  386. Ord('N') or (Ord('O') shl 8),
  387. {63} 0,
  388. {64} Ord('C') or (Ord('Z') shl 8) or (Ord('0') shl 16),
  389. Ord('R') or (Ord('U') shl 8) or (Ord('0') shl 16),
  390. Ord('N') or (Ord('O') shl 8),
  391. Ord('I') or (Ord('C') shl 8) or (Ord('0') shl 16), // made this one up: iceland
  392. Ord('C') or (Ord('Z') shl 8) or (Ord('0') shl 16),
  393. {69} Ord('P') or (Ord('O') shl 8) or (Ord('1') shl 16),
  394. Ord('G') or (Ord('R') shl 8) or (Ord('0') shl 16),
  395. Ord('T') or (Ord('R') shl 8) or (Ord('0') shl 16),
  396. {6C} 0,0,0,0,
  397. {70} 0,0,0,0,0,0,0,0,
  398. {78} Ord('C') or (Ord('H') shl 8) or (Ord('0') shl 16), // made this one up: chinese hongkong
  399. Ord('K') or (Ord('O') shl 8) or (Ord('0') shl 16),
  400. Ord('C') or (Ord('S') shl 8) or (Ord('0') shl 16), // made this one up: chinese singapore
  401. Ord('J') or (Ord('P') shl 8) or (Ord('0') shl 16),
  402. Ord('T') or (Ord('H') shl 8) or (Ord('0') shl 16),
  403. Ord('R') or (Ord('E') shl 8) or (Ord('W') shl 16),
  404. Ord('A') or (Ord('R') shl 8) or (Ord('0') shl 16), // made this one up: arabic (default)
  405. {7F} 0,
  406. {80} 0,0,0,0,0,
  407. // dBase
  408. {85} Ord('R') or (Ord('E') shl 8) or (Ord('W') shl 16),
  409. Ord('G') or (Ord('R') shl 8) or (Ord('0') shl 16),
  410. Ord('S') or (Ord('L') shl 8) or (Ord('0') shl 16),
  411. Ord('T') or (Ord('R') shl 8) or (Ord('0') shl 16),
  412. {89} 0,0,0,0,0,
  413. {8E} DbfLocale_Bul868,
  414. {8F} 0,0,0,0,0,0,0,
  415. {96} Ord('R') or (Ord('U') shl 8) or (Ord('0') shl 16),
  416. Ord('C') or (Ord('Z') shl 8) or (Ord('0') shl 16),
  417. Ord('G') or (Ord('R') shl 8) or (Ord('0') shl 16),
  418. {99} 0,0,
  419. // FoxPro
  420. {9B} 0, //LANG_CZECH or (SUBLANG_DEFAULT shl 10) or (SORT_DEFAULT shl 16),
  421. 0, //LANG_CZECH or (SUBLANG_DEFAULT shl 10) or (SORT_DEFAULT shl 16),
  422. {9D} 0,0,0,
  423. {A0} 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  424. {B0} 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  425. {C0} 0,0,0,0,0,0,0,0,
  426. {C8} Ord('C') or (Ord('Z') shl 8) or (Ord('0') shl 16),
  427. Ord('R') or (Ord('U') shl 8) or (Ord('0') shl 16),
  428. Ord('T') or (Ord('R') shl 8) or (Ord('0') shl 16),
  429. Ord('G') or (Ord('R') shl 8) or (Ord('0') shl 16),
  430. {CC} 0,0,0,0,
  431. {D0} 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  432. {E0} 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  433. {F0} 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  434. );
  435. {
  436. DbfLocaleId_DAN_865 = Ord('D') or (Ord('A') shl 8) or (Ord('0') shl 16);
  437. DbfLocaleId_NLD_437 = Ord('N') or (Ord('L') shl 8) or (Ord('0') shl 16);
  438. DbfLocaleId_NLD_850 = Ord('N') or (Ord('L') shl 8) or (Ord('0') shl 16);
  439. DbfLocaleId_FIN_437 = Ord('F') or (Ord('I') shl 8) or (Ord('0') shl 16);
  440. DbfLocaleId_FIN_850 = Ord('F') or (Ord('I') shl 8) or (Ord('0') shl 16);
  441. DbfLocaleId_FRA_437 = Ord('F') or (Ord('R') shl 8) or (Ord('0') shl 16);
  442. DbfLocaleId_FRA_850 = Ord('F') or (Ord('R') shl 8) or (Ord('0') shl 16);
  443. DbfLocaleId_DEU_437 = Ord('D') or (Ord('E') shl 8) or (Ord('0') shl 16);
  444. DbfLocaleId_DEU_850 = Ord('D') or (Ord('E') shl 8) or (Ord('0') shl 16);
  445. DbfLocaleId_ITA_437 = Ord('I') or (Ord('T') shl 8) or (Ord('0') shl 16);
  446. DbfLocaleId_ITA_850 = Ord('I') or (Ord('T') shl 8) or (Ord('1') shl 16);
  447. DbfLocaleId_JPN_932 = Ord('J') or (Ord('P') shl 8) or (Ord('0') shl 16);
  448. DbfLocaleId_ESP_850 = Ord('E') or (Ord('S') shl 8) or (Ord('0') shl 16);
  449. DbfLocaleId_SVE_437 = Ord('S') or (Ord('V') shl 8) or (Ord('0') shl 16);
  450. DbfLocaleId_SVE_850 = Ord('S') or (Ord('V') shl 8) or (Ord('1') shl 16);
  451. DbfLocaleId_NOR_865 = Ord('N') or (Ord('O') shl 8) or (Ord('0') shl 16);
  452. DbfLocaleId_ESP_437 = Ord('E') or (Ord('S') shl 8) or (Ord('1') shl 16);
  453. DbfLocaleId_ENG_437 = Ord('U') or (Ord('K') shl 8) or (Ord('0') shl 16);
  454. DbfLocaleId_ENG_850 = Ord('U') or (Ord('K') shl 8) or (Ord('0') shl 16);
  455. DbfLocaleId_ENU_437 = Ord('U') or (Ord('S') shl 8) or (Ord('0') shl 16);
  456. DbfLocaleId_FRC_863 = Ord('C') or (Ord('F') shl 8) or (Ord('1') shl 16);
  457. DbfLocaleId_FRC_850 = Ord('C') or (Ord('F') shl 8) or (Ord('1') shl 16);
  458. // ...
  459. DbfLocaleId_CSY_852 = Ord('C') or (Ord('Z') shl 8) or (Ord('0') shl 16);
  460. DbfLocaleId_CSY_867 = Ord('C') or (Ord('Z') shl 8) or (Ord('0') shl 16);
  461. // ...
  462. DbfLocaleId_HUN_852 = Ord('H') or (Ord('D') shl 8) or (Ord('C') shl 16);
  463. DbfLocaleId_PLK_852 = Ord('P') or (Ord('O') shl 8) or (Ord('0') shl 16);
  464. DbfLocaleId_PTG_860 = Ord('P') or (Ord('T') shl 8) or (Ord('0') shl 16);
  465. DbfLocaleId_PTB_850 = Ord('P') or (Ord('T') shl 8) or (Ord('0') shl 16);
  466. DbfLocaleId_RUS_866 = Ord('R') or (Ord('U') shl 8) or (Ord('0') shl 16);
  467. // ...
  468. DbfLocaleId_ENU_850 = Ord('U') or (Ord('S') shl 8) or (Ord('0') shl 16);
  469. // ...
  470. DbfLocaleId_CHS_936 = Ord('C') or (Ord('N') shl 8) or (Ord('0') shl 16);
  471. DbfLocaleId_KOR_949 = Ord('K') or (Ord('O') shl 8) or (Ord('0') shl 16);
  472. DbfLocaleId_CHT_950 = Ord('T') or (Ord('W') shl 8) or (Ord('0') shl 16);
  473. DbfLocaleId_THA_874 = Ord('T') or (Ord('H') shl 8) or (Ord('0') shl 16);
  474. // ...
  475. DbfLocaleId_JPN_DIC_932 = Ord('J') or (Ord('P') shl 8) or (Ord('1') shl 16);
  476. DbfLocaleId_Ascii_Ansi = Ord('U') or (Ord('S') shl 8) or (Ord('0') shl 16);
  477. DbfLocaleId_WEurope_Ansi = Ord('W') or (Ord('E') shl 8) or (Ord('0') shl 16);
  478. DbfLocaleId_Spanish_Ansi = Ord('E') or (Ord('S') shl 8) or (Ord('0') shl 16);
  479. // ...
  480. DbfLocaleId_Hebrew = Ord('R') or (Ord('E') shl 8) or (Ord('W') shl 16);
  481. DbfLocaleId_ELL_437 = Ord('G') or (Ord('R') shl 8) or (Ord('0') shl 16);
  482. DbfLocaleId_SLO_852 = Ord('S') or (Ord('L') shl 8) or (Ord('0') shl 16);
  483. DbfLocaleId_TRK_857 = Ord('T') or (Ord('R') shl 8) or (Ord('0') shl 16);
  484. // ...
  485. DbfLocaleId_BUL_868 = 'BGDB868';
  486. }
  487. // VdBase 7 Language strings
  488. // 'DBWIN...' -> Charset 1252 (ansi)
  489. // 'DB999...' -> Code page 999, 9 any digit
  490. // 'DBHEBREW' -> Code page 1255 ??
  491. // 'FOX..999' -> Code page 999, 9 any digit
  492. // 'FOX..WIN' -> Charset 1252 (ansi)
  493. //*************************************************************************//
  494. // reverse convert routines
  495. //*************************************************************************//
  496. // Visual DBaseVII specific; the IsFoxPro means a FoxPro codepage, which DB7 supports
  497. function ConstructLangName(CodePage: Integer; Locale: LCID; IsFoxPro: Boolean): string;
  498. function ConstructLangId(CodePage: Integer; Locale: LCID; IsFoxPro: Boolean): Byte;
  499. // Visual DBaseVII specific
  500. function GetLangId_From_LangName(const LocaleStr: string): Byte;
  501. implementation
  502. uses
  503. SysUtils;
  504. type
  505. PCardinal = ^Cardinal;
  506. function ConstructLangName(CodePage: Integer; Locale: LCID; IsFoxPro: Boolean): string;
  507. var
  508. SubType: Cardinal;
  509. begin
  510. // ANSI?
  511. SubType := LangId_To_LocaleStr[ConstructLangId(CodePage, Locale, IsFoxPro)];
  512. // found?
  513. if SubType <> DbfLocale_NotFound then
  514. begin
  515. // foxpro or dbase?
  516. if IsFoxPro then
  517. begin
  518. Result := 'FOX' + PAnsiChar(@SubType);
  519. if CodePage = 1252 then
  520. Result := Result + 'WIN'
  521. else
  522. Result := Result + IntToStr(CodePage);
  523. end else begin
  524. if SubType = DbfLocale_Bul868 then
  525. begin
  526. // special case
  527. Result := 'BGDB868';
  528. end else begin
  529. // start with DB
  530. Result := 'DB';
  531. // add codepage
  532. if CodePage = 1252 then
  533. Result := Result + 'WIN'
  534. else
  535. Result := Result + IntToStr(CodePage);
  536. // add subtype
  537. Result := Result + PAnsiChar(@SubType);
  538. end;
  539. end;
  540. end;
  541. end;
  542. const
  543. // range of Dbase locales; these are INCLUSIVE (the rest are FoxPro)
  544. dBase_RegionCount = 4;
  545. dBase_Regions: array[0..dBase_RegionCount*2-1] of Byte =
  546. ($00, $00,
  547. $05, $5D,
  548. $69, $69, // a lonely dbf entry :-)
  549. $80, $90);
  550. function FindLangId(CodePage, DesiredLocale: Cardinal; LanguageIDToLocaleTable: PCardinal; IsFoxPro: Boolean): Byte;
  551. // DesiredLocale: pointer to lookup array: language ID=>locale
  552. var
  553. i, LangID, Region: Integer;
  554. begin
  555. Region := 0;
  556. if IsFoxPro then
  557. begin
  558. // scan for a language ID matching the given codepage;
  559. // default to Win1252 Western European codepage
  560. result:=$03;
  561. for i := 0 to high(VFPCodePage_LangID) div 2 do
  562. begin
  563. if CodePage=VFPCodePage_LangID[i*2] then
  564. begin
  565. result := Byte(VFPCodePage_LangID[1+i*2]);
  566. break;
  567. end;
  568. end;
  569. end
  570. else
  571. begin
  572. // DBase
  573. // scan for a language ID matching the given codepage
  574. result:=0;
  575. for LangID := 0 to $FF do
  576. begin
  577. // check if need to advance to next region
  578. if Region + 2 < dBase_RegionCount then
  579. if LangID >= dBase_Regions[Region + 2] then
  580. Inc(Region, 2);
  581. // it seems delphi does not properly understand pointers?
  582. // what a mess :-(
  583. if ((LangId_To_CodePage[LangID] = CodePage) or (CodePage = 0)) and
  584. (PCardinal(PAnsiChar(LanguageIDToLocaleTable)+(LangID*4))^ = DesiredLocale) then
  585. // Ignore (V)FP results
  586. if LangID <= dBase_Regions[Region+1] then
  587. result := Byte(LangID);
  588. end;
  589. end;
  590. end;
  591. function ConstructLangId(CodePage: Integer; Locale: LCID; IsFoxPro: Boolean): Byte;
  592. begin
  593. // locale: lower 16bits only, with default sorting
  594. Locale := (Locale and $FFFF) or (SORT_DEFAULT shl 16);
  595. if IsFoxPro then
  596. Result := FindLangID(CodePage, Locale, @VFPCodePage_LangID[0], true)
  597. else
  598. Result := FindLangId(CodePage, Locale, @LangId_To_Locale[0], false);
  599. // not found? try any codepage
  600. if Result = 0 then
  601. if IsFoxPro then
  602. Result := FindLangID(0, Locale, @VFPCodePage_LangID[0], true)
  603. else
  604. begin
  605. Result := FindLangId(0, Locale, @LangId_To_Locale[0], false);
  606. // Dbase: last resort; include foxpro codepages;
  607. // compatible with older tdbf but unknow whether this actually works
  608. if Result = 0 then
  609. Result := FindLangID(0, Locale, @VFPCodePage_LangID[0], true)
  610. end;
  611. end;
  612. function GetLangId_From_LangName(const LocaleStr: string): Byte;
  613. var
  614. CodePage, SubType: Integer;
  615. IsFoxPro: Boolean;
  616. CodePageStr: string;
  617. begin
  618. // determine foxpro/dbase
  619. IsFoxPro := CompareMem(PAnsiChar('FOX'), PAnsiChar(LocaleStr), 3);
  620. // get codepage/locale subtype
  621. if IsFoxPro then
  622. begin
  623. CodePageStr := Copy(LocaleStr, 6, 3);
  624. SubType := Integer(LocaleStr[4]) or (Integer(LocaleStr[5]) shl 8);
  625. end else begin
  626. CodePageStr := Copy(LocaleStr, 3, 3);
  627. SubType := Integer(LocaleStr[6]) or (Integer(LocaleStr[7]) shl 8) or (Integer(LocaleStr[8]) shl 16);
  628. end;
  629. // convert codepage string to codepage id
  630. if CodePageStr = 'WIN' then
  631. CodePage := 1252
  632. else if CodePageStr = 'REW' then // Hebrew
  633. CodePage := 1255
  634. else
  635. CodePage := StrToIntDef(CodePageStr,0); //fail to codepage 0
  636. // find lang id
  637. Result := FindLangId(CodePage, SubType, @LangId_To_LocaleStr[0], IsFoxPro);
  638. end;
  639. end.