Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2651 lines
70 KiB

  1. /*
  2. * @doc INTERNAL
  3. *
  4. * @module w32sys.cpp - thin layer over Win32 services
  5. *
  6. * History: <nl>
  7. * 1/22/97 joseogl Created
  8. *
  9. * Copyright (c) 1995-2000 Microsoft Corporation. All rights reserved.
  10. */
  11. // This prevents the "W32->" prefix from being prepended to our identifiers.
  12. #define W32SYS_CPP
  13. #include "_common.h"
  14. #include "_host.h"
  15. #include "_font.h"
  16. #include "_edit.h"
  17. //
  18. //Cache of Type 1 data. See also clasifyc.cpp and rgbCharClass in
  19. //rtflex.cpp.
  20. // Used by GetStringTypeEx
  21. //
  22. const unsigned short rgctype1Ansi[256] = {
  23. 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, //0x00
  24. 0x0020, 0x0068, 0x0028, 0x0028, 0x0028, 0x0028, 0x0020, 0x0020, //0x08
  25. 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, //0x10
  26. 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, //0x18
  27. 0x0048, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, //0x20
  28. 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, //0x28
  29. 0x0084, 0x0084, 0x0084, 0x0084, 0x0084, 0x0084, 0x0084, 0x0084, //0x30
  30. 0x0084, 0x0084, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, //0x38
  31. 0x0010, 0x0181, 0x0181, 0x0181, 0x0181, 0x0181, 0x0181, 0x0101, //0x40
  32. 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, //0x48
  33. 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, //0x50
  34. 0x0101, 0x0101, 0x0101, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, //0x58
  35. 0x0010, 0x0182, 0x0182, 0x0182, 0x0182, 0x0182, 0x0182, 0x0102, //0x60
  36. 0x0102, 0x0102, 0x0102, 0x0102, 0x0102, 0x0102, 0x0102, 0x0102, //0x68
  37. 0x0102, 0x0102, 0x0102, 0x0102, 0x0102, 0x0102, 0x0102, 0x0102, //0x70
  38. 0x0102, 0x0102, 0x0102, 0x0010, 0x0010, 0x0010, 0x0010, 0x0020, //0x78
  39. 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, //0x80
  40. 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, //0x88
  41. 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, //0x90
  42. 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, //0x98
  43. 0x0048, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, //0xA0
  44. 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, //0xA8
  45. 0x0010, 0x0010, 0x0014, 0x0014, 0x0010, 0x0010, 0x0010, 0x0010, //0xB0
  46. 0x0010, 0x0014, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, //0xB8
  47. 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, //0xC0
  48. 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, //0xC8
  49. 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0010, //0xD0
  50. 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0102, //0xD8
  51. 0x0102, 0x0102, 0x0102, 0x0102, 0x0102, 0x0102, 0x0102, 0x0102, //0xE0
  52. 0x0102, 0x0102, 0x0102, 0x0102, 0x0102, 0x0102, 0x0102, 0x0102, //0xE8
  53. 0x0102, 0x0102, 0x0102, 0x0102, 0x0102, 0x0102, 0x0102, 0x0102, //0xF0
  54. 0x0102, 0x0102, 0x0102, 0x0102, 0x0102, 0x0102, 0x0102, 0x0102};//0xF8
  55. //
  56. //Cache of Type 3 data.
  57. //
  58. const unsigned short rgctype3Ansi[256] = {
  59. 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, //0x00
  60. 0x0000, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0000, 0x0000, //0x08
  61. 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, //0x10
  62. 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, //0x18
  63. 0x0048, 0x0048, 0x0448, 0x0048, 0x0448, 0x0048, 0x0048, 0x0440, //0x20
  64. 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0440, 0x0048, 0x0448, //0x28
  65. 0x0040, 0x0040, 0x0040, 0x0040, 0x0040, 0x0040, 0x0040, 0x0040, //0x30
  66. 0x0040, 0x0040, 0x0048, 0x0048, 0x0048, 0x0448, 0x0048, 0x0048, //0x38
  67. 0x0448, 0x8040, 0x8040, 0x8040, 0x8040, 0x8040, 0x8040, 0x8040, //0x40
  68. 0x8040, 0x8040, 0x8040, 0x8040, 0x8040, 0x8040, 0x8040, 0x8040, //0x48
  69. 0x8040, 0x8040, 0x8040, 0x8040, 0x8040, 0x8040, 0x8040, 0x8040, //0x50
  70. 0x8040, 0x8040, 0x8040, 0x0048, 0x0448, 0x0048, 0x0448, 0x0448, //0x58
  71. 0x0448, 0x8040, 0x8040, 0x8040, 0x8040, 0x8040, 0x8040, 0x8040, //0x60
  72. 0x8040, 0x8040, 0x8040, 0x8040, 0x8040, 0x8040, 0x8040, 0x8040, //0x68
  73. 0x8040, 0x8040, 0x8040, 0x8040, 0x8040, 0x8040, 0x8040, 0x8040, //0x70
  74. 0x8040, 0x8040, 0x8040, 0x0048, 0x0048, 0x0048, 0x0448, 0x0000, //0x78
  75. 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, //0x80
  76. 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, //0x88
  77. 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, //0x90
  78. 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, //0x98
  79. 0x0008, 0x0008, 0x0048, 0x0048, 0x0008, 0x0048, 0x0048, 0x0008, //0xA0
  80. 0x0408, 0x0008, 0x0400, 0x0008, 0x0048, 0x0408, 0x0008, 0x0448, //0xA8
  81. 0x0008, 0x0008, 0x0000, 0x0000, 0x0408, 0x0008, 0x0008, 0x0008, //0xB0
  82. 0x0408, 0x0000, 0x0400, 0x0008, 0x0000, 0x0000, 0x0000, 0x0008, //0xB8
  83. 0x8003, 0x8003, 0x8003, 0x8003, 0x8003, 0x8003, 0x8000, 0x8003, //0xC0
  84. 0x8003, 0x8003, 0x8003, 0x8003, 0x8003, 0x8003, 0x8003, 0x8003, //0xC8
  85. 0x8000, 0x8003, 0x8003, 0x8003, 0x8003, 0x8003, 0x8003, 0x0008, //0xD0
  86. 0x8003, 0x8003, 0x8003, 0x8003, 0x8003, 0x8003, 0x8000, 0x8000, //0xD8
  87. 0x8003, 0x8003, 0x8003, 0x8003, 0x8003, 0x8003, 0x8000, 0x8003, //0xE0
  88. 0x8003, 0x8003, 0x8003, 0x8003, 0x8003, 0x8003, 0x8003, 0x8003, //0xE8
  89. 0x8000, 0x8003, 0x8003, 0x8003, 0x8003, 0x8003, 0x8003, 0x8003, //0xF0
  90. 0x8003, 0x8003, 0x8003, 0x8003, 0x8003, 0x8003, 0x8000, 0x8003};//0xF8
  91. // Include the appropriate implementation.
  92. #include W32INCLUDE
  93. #if 0
  94. // Could be one of.
  95. // This list is here to allow the dependency generator to work.
  96. #include "w32win32.cpp"
  97. #include "w32wince.cpp"
  98. #endif
  99. ASSERTDATA
  100. /*
  101. * rgCodePage, rgCharSet, rgFontSig
  102. *
  103. * Locally used arrays that contain CodePage, CharSet, and FontSig info
  104. * and indexed by iCharRep, the character repertoire index. When a char
  105. * repertoire has a CharSet and CodePage, it has an entry in rgCharSet
  106. * and in rgCodePage. Unicode-only repertoires follow the CharSet
  107. * repertoires in the rgFontSig table. It is essential to keep these
  108. * three tables in sync and they used to be combined into a single table.
  109. * They are separate here to save on RAM.
  110. */
  111. static const WORD rgCodePage[] =
  112. {
  113. // 0 1 2 3 4 5 6 7 8 9
  114. 1252, 1250, 1251, 1253, 1254, 1255, 1256, 1257, 1258, 0,
  115. 42, 874, 932, 936, 949, 950, 437, 850, 10000
  116. };
  117. static const BYTE rgCharSet[] =
  118. {
  119. // 0 1 2 3
  120. ANSI_CHARSET, EASTEUROPE_CHARSET, RUSSIAN_CHARSET, GREEK_CHARSET,
  121. TURKISH_CHARSET, HEBREW_CHARSET, ARABIC_CHARSET, BALTIC_CHARSET,
  122. VIETNAMESE_CHARSET, DEFAULT_CHARSET, SYMBOL_CHARSET, THAI_CHARSET,
  123. SHIFTJIS_CHARSET, GB2312_CHARSET, HANGUL_CHARSET, CHINESEBIG5_CHARSET,
  124. PC437_CHARSET, OEM_CHARSET, MAC_CHARSET
  125. };
  126. #define CCHARSET ARRAY_SIZE(rgCharSet)
  127. #define CCODEPAGE ARRAY_SIZE(rgCodePage)
  128. #define LANG_PRC MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED)
  129. #define LANG_SINGAPORE MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SINGAPORE)
  130. const BYTE rgCharRepfromLID[] = {
  131. // Char Repertoire PLID primary language
  132. // --------------------------------------------
  133. DEFAULT_INDEX, // 00 - undefined
  134. ARABIC_INDEX, // 01 - Arabic
  135. RUSSIAN_INDEX, // 02 - Bulgarian
  136. ANSI_INDEX, // 03 - Catalan
  137. GB2312_INDEX, // 04 - PRC, Singapore (Taiwan, Hong Kong SAR, Macau SAR are 950)
  138. EASTEUROPE_INDEX, // 05 - Czech
  139. ANSI_INDEX, // 06 - Danish
  140. ANSI_INDEX, // 07 - German
  141. GREEK_INDEX, // 08 - Greek
  142. ANSI_INDEX, // 09 - English
  143. ANSI_INDEX, // 0A - Spanish
  144. ANSI_INDEX, // 0B - Finnish
  145. ANSI_INDEX, // 0C - French
  146. HEBREW_INDEX, // 0D - Hebrew
  147. EASTEUROPE_INDEX, // 0E - Hungarian
  148. ANSI_INDEX, // 0F - Icelandic
  149. ANSI_INDEX, // 10 - Italian
  150. SHIFTJIS_INDEX, // 11 - Japan
  151. HANGUL_INDEX, // 12 - Korea
  152. ANSI_INDEX, // 13 - Dutch
  153. ANSI_INDEX, // 14 - Norwegian
  154. EASTEUROPE_INDEX, // 15 - Polish
  155. ANSI_INDEX, // 16 - Portuguese
  156. DEFAULT_INDEX, // 17 - Rhaeto-Romanic
  157. EASTEUROPE_INDEX, // 18 - Romanian
  158. RUSSIAN_INDEX, // 19 - Russian
  159. EASTEUROPE_INDEX, // 1A - Croatian
  160. EASTEUROPE_INDEX, // 1B - Slovak
  161. EASTEUROPE_INDEX, // 1C - Albanian
  162. ANSI_INDEX, // 1D - Swedish
  163. THAI_INDEX, // 1E - Thai
  164. TURKISH_INDEX, // 1F - Turkish
  165. ARABIC_INDEX, // 20 - Urdu
  166. ANSI_INDEX, // 21 - Indonesian
  167. RUSSIAN_INDEX, // 22 - Ukranian
  168. RUSSIAN_INDEX, // 23 - Byelorussian
  169. EASTEUROPE_INDEX, // 24 - Slovenian
  170. BALTIC_INDEX, // 25 - Estonia
  171. BALTIC_INDEX, // 26 - Latvian
  172. BALTIC_INDEX, // 27 - Lithuanian
  173. DEFAULT_INDEX, // 28 - Tajik - Tajikistan (undefined)
  174. ARABIC_INDEX, // 29 - Farsi
  175. VIET_INDEX, // 2A - Vietnanese
  176. ARMENIAN_INDEX, // 2B - Armenian (Unicode only)
  177. TURKISH_INDEX, // 2C - Azeri (Latin, can be Cyrillic...)
  178. ANSI_INDEX, // 2D - Basque
  179. DEFAULT_INDEX, // 2E - Sorbian
  180. RUSSIAN_INDEX, // 2F - fyro Macedonian
  181. ANSI_INDEX, // 30 - Sutu
  182. ANSI_INDEX, // 31 - Tsonga
  183. ANSI_INDEX, // 32 - Tswana
  184. ANSI_INDEX, // 33 - Venda
  185. ANSI_INDEX, // 34 - Xhosa
  186. ANSI_INDEX, // 35 - Zulu
  187. ANSI_INDEX, // 36 - Africaans
  188. GEORGIAN_INDEX, // 37 - Georgian (Unicode only)
  189. ANSI_INDEX, // 38 - Faerose
  190. DEVANAGARI_INDEX, // 39 - Hindi (Indic)
  191. ANSI_INDEX, // 3A - Maltese
  192. ANSI_INDEX, // 3B - Sami
  193. ANSI_INDEX, // 3C - Gaelic
  194. HEBREW_INDEX, // 3D - Yiddish
  195. ANSI_INDEX, // 3E - Malaysian
  196. RUSSIAN_INDEX, // 3F - Kazakh
  197. ANSI_INDEX, // 40 - Kirghiz
  198. ANSI_INDEX, // 41 - Swahili
  199. ANSI_INDEX, // 42 - Turkmen
  200. TURKISH_INDEX, // 43 - Uzbek (Latin, can be Cyrillic...)
  201. ANSI_INDEX, // 44 - Tatar
  202. BENGALI_INDEX, // 45 - Bengali (Indic)
  203. GURMUKHI_INDEX, // 46 - Punjabi(Gurmukhi) (Indic)
  204. GUJARATI_INDEX, // 47 - Gujarati (Indic)
  205. ORIYA_INDEX, // 48 - Oriya (Indic)
  206. TAMIL_INDEX, // 49 - Tamil (Indic)
  207. TELUGU_INDEX, // 4A - Telugu (Indic)
  208. KANNADA_INDEX, // 4B - Kannada (Indic)
  209. MALAYALAM_INDEX, // 4C - Malayalam (Indic)
  210. BENGALI_INDEX, // 4D - Assamese (Indic)
  211. DEVANAGARI_INDEX, // 4E - Marathi (Indic)
  212. DEVANAGARI_INDEX, // 4F - Sanskrit (Indic)
  213. MONGOLIAN_INDEX, // 50 - Mongolian (Mongolia)
  214. TIBETAN_INDEX, // 51 - Tibetan (Tibet)
  215. ANSI_INDEX, // 52 - Welsh (Wales)
  216. KHMER_INDEX, // 53 - Khmer (Cambodia)
  217. LAO_INDEX, // 54 - Lao (Lao)
  218. MYANMAR_INDEX, // 55 - Burmese (Myanmar)
  219. ANSI_INDEX, // 56 - Gallego (Portugal)
  220. DEVANAGARI_INDEX, // 57 - Konkani (Indic)
  221. BENGALI_INDEX, // 58 - Manipuri (Indic)
  222. GURMUKHI_INDEX, // 59 - Sindhi (Indic)
  223. SYRIAC_INDEX, // 5A - Syriac (Syria)
  224. SINHALA_INDEX, // 5B - Sinhalese (Sri Lanka)
  225. CHEROKEE_INDEX, // 5C - Cherokee
  226. ABORIGINAL_INDEX, // 5D - Inuktitut
  227. ETHIOPIC_INDEX, // 5E - Amharic (Ethiopic)
  228. DEFAULT_INDEX, // 5F - Tamazight (Berber/Arabic) also Latin
  229. DEFAULT_INDEX, // 60 - Kashmiri
  230. DEVANAGARI_INDEX, // 61 - Nepali (Nepal)
  231. ANSI_INDEX, // 62 - Frisian (Netherlands)
  232. ARABIC_INDEX, // 63 - Pashto (Afghanistan)
  233. ANSI_INDEX, // 64 - Filipino
  234. THAANA_INDEX // 65 - Maldivian (Maldives (Thaana))
  235. };
  236. #define CLID ARRAY_SIZE(rgCharRepfromLID)
  237. #define lidAzeriCyrillic 0x82C
  238. #define lidSerbianCyrillic 0xC1A
  239. #define lidUzbekCyrillic 0x843
  240. // Our interface pointer
  241. CW32System *W32;
  242. CW32System::CW32System( )
  243. {
  244. if(GetVersion(&_dwPlatformId, &_dwMajorVersion, &_dwMinorVersion))
  245. {
  246. _fHaveAIMM = FALSE;
  247. _fHaveIMMEShare = FALSE;
  248. _fHaveIMMProcs = FALSE;
  249. _fLoadAIMM10 = FALSE;
  250. _pIMEShare = NULL;
  251. _icr3DDarkShadow = COLOR_WINDOWFRAME;
  252. if(_dwMajorVersion >= VERS4)
  253. _icr3DDarkShadow = COLOR_3DDKSHADOW;
  254. }
  255. _syslcid = GetSystemDefaultLCID();
  256. _ACP = ::GetACP();
  257. #ifndef NOMAGELLAN
  258. // BUG FIX #6089
  259. // we need this for backward compatibility of mouse wheel
  260. _MSMouseRoller = RegisterWindowMessageA(MSH_MOUSEWHEEL);
  261. #endif
  262. #ifndef NOFEPROCESSING
  263. // Register IME messages
  264. _MSIMEMouseMsg = RegisterWindowMessageA("MSIMEMouseOperation");
  265. _MSIMEDocFeedMsg = RegisterWindowMessageA("MSIMEDocumentFeed");
  266. _MSIMEQueryPositionMsg = RegisterWindowMessageA("MSIMEQueryPosition");
  267. _MSIMEServiceMsg = RegisterWindowMessageA("MSIMEService");
  268. // Check Reconvert messages unless we are running in NT5
  269. if (_dwPlatformId == VER_PLATFORM_WIN32_WINDOWS ||
  270. (_dwPlatformId == VER_PLATFORM_WIN32_NT && _dwMajorVersion <= 4))
  271. {
  272. _MSIMEReconvertMsg = RegisterWindowMessageA("MSIMEReconvert");
  273. _MSIMEReconvertRequestMsg = RegisterWindowMessageA("MSIMEReconvertRequest");
  274. }
  275. else
  276. {
  277. _MSIMEReconvertMsg = 0; // For reconversion
  278. _MSIMEReconvertRequestMsg = 0; // For reconversion request
  279. }
  280. #endif
  281. }
  282. CW32System::~CW32System()
  283. {
  284. if (_arTmpDisplayAttrib)
  285. {
  286. delete _arTmpDisplayAttrib;
  287. _arTmpDisplayAttrib = NULL;
  288. }
  289. FreeOle();
  290. if (_hdcScreen)
  291. DeleteDC(_hdcScreen);
  292. if (_hDefaultFont)
  293. DeleteObject(_hDefaultFont);
  294. }
  295. /////////////////////////////// Memory and CRT utility functions /////////////////////////////////
  296. extern "C" {
  297. #ifdef NOCRTOBJS
  298. // Havinf these functions defined here helps eliminate the dependency on the CRT
  299. // Some function definitions copied from CRT sources.
  300. // Typically, it is better to get the objs for these objects from the CRT
  301. // without dragging in the whole thing.
  302. /***
  303. *int memcmp(buf1, buf2, count) - compare memory for lexical order
  304. *
  305. *Purpose:
  306. * Compares count bytes of memory starting at buf1 and buf2
  307. * and find if equal or which one is first in lexical order.
  308. *
  309. *Entry:
  310. * void *buf1, *buf2 - pointers to memory sections to compare
  311. * size_t count - length of sections to compare
  312. *
  313. *Exit:
  314. * returns < 0 if buf1 < buf2
  315. * returns 0 if buf1 == buf2
  316. * returns > 0 if buf1 > buf2
  317. *
  318. *Exceptions:
  319. *
  320. *******************************************************************************/
  321. int __cdecl memcmp (
  322. const void * buf1,
  323. const void * buf2,
  324. size_t count
  325. )
  326. {
  327. if (!count)
  328. return(0);
  329. while ( --count && *(char *)buf1 == *(char *)buf2 ) {
  330. buf1 = (char *)buf1 + 1;
  331. buf2 = (char *)buf2 + 1;
  332. }
  333. return( *((unsigned char *)buf1) - *((unsigned char *)buf2) );
  334. }
  335. /***
  336. *char *memset(dst, val, count) - sets "count" bytes at "dst" to "val"
  337. *
  338. *Purpose:
  339. * Sets the first "count" bytes of the memory starting
  340. * at "dst" to the character value "val".
  341. *
  342. *Entry:
  343. * void *dst - pointer to memory to fill with val
  344. * int val - value to put in dst bytes
  345. * size_t count - number of bytes of dst to fill
  346. *
  347. *Exit:
  348. * returns dst, with filled bytes
  349. *
  350. *Exceptions:
  351. *
  352. *******************************************************************************/
  353. void * __cdecl memset (
  354. void *dst,
  355. int val,
  356. size_t count
  357. )
  358. {
  359. void *start = dst;
  360. while (count--) {
  361. *(char *)dst = (char)val;
  362. dst = (char *)dst + 1;
  363. }
  364. return(start);
  365. }
  366. /***
  367. *memcpy - Copy source buffer to destination buffer
  368. *
  369. *Purpose:
  370. * memcpy() copies a source memory buffer to a destination memory buffer.
  371. * This routine does NOT recognize overlapping buffers, and thus can lead
  372. * to propogation.
  373. *
  374. * For cases where propogation must be avoided, memmove() must be used.
  375. *
  376. *Entry:
  377. * void *dst = pointer to destination buffer
  378. * const void *src = pointer to source buffer
  379. * size_t count = number of bytes to copy
  380. *
  381. *Exit:
  382. * Returns a pointer to the destination buffer
  383. *
  384. *Exceptions:
  385. *******************************************************************************/
  386. void * __cdecl memcpy (
  387. void * dst,
  388. const void * src,
  389. size_t count
  390. )
  391. {
  392. void * ret = dst;
  393. /*
  394. * copy from lower addresses to higher addresses
  395. */
  396. while (count--) {
  397. *(char *)dst = *(char *)src;
  398. dst = (char *)dst + 1;
  399. src = (char *)src + 1;
  400. }
  401. return(ret);
  402. }
  403. void * __cdecl memmove(void *dst, const void *src, size_t count)
  404. {
  405. void * ret = dst;
  406. if (dst <= src || (char *)dst >= ((char *)src + count)) {
  407. /*
  408. * Non-Overlapping Buffers
  409. * copy from lower addresses to higher addresses
  410. */
  411. while (count--) {
  412. *(char *)dst = *(char *)src;
  413. dst = (char *)dst + 1;
  414. src = (char *)src + 1;
  415. }
  416. }
  417. else
  418. {
  419. /*
  420. * Overlapping Buffers
  421. * copy from higher addresses to lower addresses
  422. */
  423. dst = (char *)dst + count - 1;
  424. src = (char *)src + count - 1;
  425. while (count--) {
  426. *(char *)dst = *(char *)src;
  427. dst = (char *)dst - 1;
  428. src = (char *)src - 1;
  429. }
  430. }
  431. return(ret);
  432. }
  433. /***
  434. *strlen - return the length of a null-terminated string
  435. *
  436. *Purpose:
  437. * Finds the length in bytes of the given string, not including
  438. * the final null character.
  439. *
  440. *Entry:
  441. * const char * str - string whose length is to be computed
  442. *
  443. *Exit:
  444. * length of the string "str", exclusive of the final null byte
  445. *
  446. *Exceptions:
  447. *
  448. *******************************************************************************/
  449. size_t __cdecl strlen (
  450. const char * str
  451. )
  452. {
  453. const char *eos = str;
  454. while( *eos++ ) ;
  455. return( (int)(eos - str - 1) );
  456. }
  457. #endif
  458. #ifdef DEBUG
  459. // These functions are only used for RTF logging
  460. /***
  461. *strcmp - compare two strings, returning less than, equal to, or greater than
  462. *
  463. *Purpose:
  464. * STRCMP compares two strings and returns an integer
  465. * to indicate whether the first is less than the second, the two are
  466. * equal, or whether the first is greater than the second.
  467. *
  468. * Comparison is done byte by byte on an UNSIGNED basis, which is to
  469. * say that Null (0) is less than any other character (1-255).
  470. *
  471. *Entry:
  472. * const char * src - string for left-hand side of comparison
  473. * const char * dst - string for right-hand side of comparison
  474. *
  475. *Exit:
  476. * returns -1 if src < dst
  477. * returns 0 if src == dst
  478. * returns +1 if src > dst
  479. *
  480. *Exceptions:
  481. *
  482. *******************************************************************************/
  483. int __cdecl CW32System::strcmp (
  484. const char * src,
  485. const char * dst
  486. )
  487. {
  488. int ret = 0 ;
  489. while( ! (ret = *(unsigned char *)src - *(unsigned char *)dst) && *dst)
  490. ++src, ++dst;
  491. if ( ret < 0 )
  492. ret = -1 ;
  493. else if ( ret > 0 )
  494. ret = 1 ;
  495. return( ret );
  496. }
  497. /***
  498. *char *strcat(dst, src) - concatenate (append) one string to another
  499. *
  500. *Purpose:
  501. * Concatenates src onto the end of dest. Assumes enough
  502. * space in dest.
  503. *
  504. *Entry:
  505. * char *dst - string to which "src" is to be appended
  506. * const char *src - string to be appended to the end of "dst"
  507. *
  508. *Exit:
  509. * The address of "dst"
  510. *
  511. *Exceptions:
  512. *
  513. *******************************************************************************/
  514. char * __cdecl CW32System::strcat (
  515. char * dst,
  516. const char * src
  517. )
  518. {
  519. char * cp = dst;
  520. while( *cp )
  521. cp++; /* find end of dst */
  522. while( *cp++ = *src++ ) ; /* Copy src to end of dst */
  523. return( dst ); /* return dst */
  524. }
  525. char * __cdecl CW32System::strrchr (
  526. const char * string,
  527. int ch
  528. )
  529. {
  530. char *start = (char *)string;
  531. while (*string++) /* find end of string */
  532. ;
  533. /* search towards front */
  534. while (--string != start && *string != (char)ch)
  535. ;
  536. if (*string == (char)ch) /* char found ? */
  537. return( (char *)string );
  538. return(NULL);
  539. }
  540. #endif
  541. // This function in the runtime traps virtual method calls
  542. int __cdecl _purecall()
  543. {
  544. AssertSz(FALSE, "Fatal Error : Virtual method called in RichEdit");
  545. return 0;
  546. }
  547. // To avoid brionging in floating point lib
  548. extern int _fltused = 1;
  549. } // end of extern "C" block
  550. size_t CW32System::wcslen(const wchar_t *wcs)
  551. {
  552. const wchar_t *eos = wcs;
  553. while( *eos++ ) ;
  554. return( (size_t)(eos - wcs - 1) );
  555. }
  556. wchar_t * CW32System::wcscpy(wchar_t * dst, const wchar_t * src)
  557. {
  558. wchar_t * cp = dst;
  559. while( *cp++ = *src++ )
  560. ; /* Copy src over dst */
  561. return( dst );
  562. }
  563. int CW32System::wcscmp(const wchar_t * src, const wchar_t * dst)
  564. {
  565. int ret = 0;
  566. while( ! (ret = (int)(*src - *dst)) && *dst)
  567. ++src, ++dst;
  568. if ( ret < 0 )
  569. ret = -1 ;
  570. else if ( ret > 0 )
  571. ret = 1 ;
  572. return( ret );
  573. }
  574. int CW32System::wcsicmp(const wchar_t * src, const wchar_t * dst)
  575. {
  576. int ret = 0;
  577. wchar_t s,d;
  578. do
  579. {
  580. s = ((*src <= L'Z') && (*dst >= L'A'))
  581. ? *src - L'A' + L'a'
  582. : *src;
  583. d = ((*dst <= L'Z') && (*dst >= L'A'))
  584. ? *dst - L'A' + L'a'
  585. : *dst;
  586. src++;
  587. dst++;
  588. } while (!(ret = (int)(s - d)) && d);
  589. if ( ret < 0 )
  590. ret = -1 ;
  591. else if ( ret > 0 )
  592. ret = 1 ;
  593. return( ret );
  594. }
  595. wchar_t * CW32System::wcsncpy (wchar_t * dest, const wchar_t * source, size_t count)
  596. {
  597. wchar_t *start = dest;
  598. while (count && (*dest++ = *source++)) /* copy string */
  599. count--;
  600. if (count) /* pad out with zeroes */
  601. while (--count)
  602. *dest++ = L'\0';
  603. return(start);
  604. }
  605. int CW32System::wcsnicmp (const wchar_t * first, const wchar_t * last, size_t count)
  606. {
  607. wchar_t f,l;
  608. int result = 0;
  609. if ( count ) {
  610. do {
  611. f = ((*first <= L'Z') && (*first >= L'A'))
  612. ? *first - L'A' + L'a'
  613. : *first;
  614. l = ((*last <= L'Z') && (*last >= L'A'))
  615. ? *last - L'A' + L'a'
  616. : *last;
  617. first++;
  618. last++;
  619. } while ( (--count) && f && (f == l) );
  620. result = (int)(f - l);
  621. }
  622. return result;
  623. }
  624. unsigned long CW32System::strtoul(const char *nptr)
  625. {
  626. const char *p;
  627. char c;
  628. unsigned long number;
  629. unsigned digval;
  630. unsigned long maxval;
  631. p = nptr; /* p is our scanning pointer */
  632. number = 0; /* start with zero */
  633. c = *p++; /* read char */
  634. while ( c == ' ' || c == '\t' )
  635. c = *p++; /* skip whitespace */
  636. if (c == '-') {
  637. return 0;
  638. }
  639. /* if our number exceeds this, we will overflow on multiply */
  640. maxval = ULONG_MAX / 10;
  641. for (;;) { /* exit in middle of loop */
  642. /* convert c to value */
  643. digval = (unsigned char) c;
  644. if ( digval >= '0' && digval <= '9' )
  645. digval = c - '0';
  646. else
  647. return number;
  648. /* we now need to compute number = number * base + digval,
  649. but we need to know if overflow occured. This requires
  650. a tricky pre-check. */
  651. if (number < maxval || (number == maxval &&
  652. (unsigned long)digval <= ULONG_MAX % 10)) {
  653. /* we won't overflow, go ahead and multiply */
  654. number = number * 10 + digval;
  655. }
  656. else
  657. return 0;
  658. c = *p++; /* read next digit */
  659. }
  660. }
  661. // CW32System static members
  662. BYTE CW32System::_fLRMorRLM;
  663. BYTE CW32System::_fHaveIMMProcs;
  664. BYTE CW32System::_fHaveIMMEShare;
  665. BYTE CW32System::_fHaveAIMM;
  666. BYTE CW32System::_fLoadAIMM10;
  667. UINT CW32System::_fRegisteredXBox;
  668. DWORD CW32System::_dwPlatformId;
  669. LCID CW32System::_syslcid;
  670. DWORD CW32System::_dwMajorVersion;
  671. DWORD CW32System::_dwMinorVersion;
  672. INT CW32System::_icr3DDarkShadow;
  673. UINT CW32System::_MSIMEMouseMsg;
  674. UINT CW32System::_MSIMEReconvertMsg;
  675. UINT CW32System::_MSIMEReconvertRequestMsg;
  676. UINT CW32System::_MSIMEDocFeedMsg;
  677. UINT CW32System::_MSIMEQueryPositionMsg;
  678. UINT CW32System::_MSIMEServiceMsg;
  679. UINT CW32System::_MSMouseRoller;
  680. HDC CW32System::_hdcScreen;
  681. CIMEShare* CW32System::_pIMEShare;
  682. CTmpDisplayAttrArray* CW32System::_arTmpDisplayAttrib;
  683. // CW32System static system parameter members
  684. BOOL CW32System::_fSysParamsOk;
  685. BOOL CW32System::_fUsePalette;
  686. INT CW32System::_dupSystemFont;
  687. INT CW32System::_dvpSystemFont;
  688. INT CW32System::_ySysFontLeading;
  689. LONG CW32System::_xPerInchScreenDC;
  690. LONG CW32System::_yPerInchScreenDC;
  691. INT CW32System::_cxBorder;
  692. INT CW32System::_cyBorder;
  693. INT CW32System::_cxVScroll;
  694. INT CW32System::_cyHScroll;
  695. LONG CW32System::_dxSelBar;
  696. INT CW32System::_cxDoubleClk;
  697. INT CW32System::_cyDoubleClk;
  698. INT CW32System::_DCT;
  699. WORD CW32System::_nScrollInset;
  700. WORD CW32System::_nScrollDelay;
  701. WORD CW32System::_nScrollInterval;
  702. WORD CW32System::_nScrollHAmount;
  703. WORD CW32System::_nScrollVAmount;
  704. WORD CW32System::_nDragDelay;
  705. WORD CW32System::_nDragMinDist;
  706. WORD CW32System::_wDeadKey;
  707. WORD CW32System::_wKeyboardFlags;
  708. DWORD CW32System::_dwNumKeyPad;
  709. WORD CW32System::_fFEFontInfo;
  710. BYTE CW32System::_bDigitSubstMode;
  711. BYTE CW32System::_bCharSetSys;
  712. HCURSOR CW32System::_hcurSizeNS;
  713. HCURSOR CW32System::_hcurSizeWE;
  714. HCURSOR CW32System::_hcurSizeNWSE;
  715. HCURSOR CW32System::_hcurSizeNESW;
  716. LONG CW32System::_cLineScroll;
  717. HFONT CW32System::_hSystemFont;
  718. HFONT CW32System::_hDefaultFont;
  719. HKL CW32System::_hklCurrent;
  720. HKL CW32System::_hkl[NCHARREPERTOIRES];
  721. INT CW32System::_sysiniflags;
  722. UINT CW32System::_ACP;
  723. DWORD CW32System::_cRefs;
  724. #ifndef NODRAFTMODE
  725. CW32System::DraftModeFontInfo CW32System::_draftModeFontInfo;
  726. #endif
  727. /*
  728. * CW32System::MbcsFromUnicode(pstr, cch, pwstr, cwch, codepage, flags)
  729. *
  730. * @mfunc
  731. * Converts a string to MBCS from Unicode. If cwch equals -1, the string
  732. * is assumed to be NULL terminated. -1 is supplied as a default argument.
  733. *
  734. * @rdesc
  735. * If [pstr] is NULL or [cch] is 0, 0 is returned. Otherwise, the number
  736. * of characters converted, including the terminating NULL, is returned
  737. * (note that converting the empty string will return 1). If the
  738. * conversion fails, 0 is returned.
  739. *
  740. * @devnote
  741. * Modifies pstr
  742. */
  743. int CW32System::MbcsFromUnicode(
  744. LPSTR pstr, //@parm Buffer for MBCS string
  745. int cch, //@parm Size of MBCS buffer, incl space for NULL terminator
  746. LPCWSTR pwstr, //@parm Unicode string to convert
  747. int cwch, //@parm # chars in Unicode string, incl NULL terminator
  748. UINT codepage, //@parm Code page to use (CP_ACP is default)
  749. UN_FLAGS flags) //@parm Indicates if WCH_EMBEDDING should be handled specially
  750. {
  751. TRACEBEGIN(TRCSUBSYSWRAP, TRCSCOPEINTERN, "CW32System::MbcsFromUnicode");
  752. LONG i;
  753. LPWSTR pwstrtemp;
  754. CTempWcharBuf twcb;
  755. Assert(cch >= 0 && pwstr && (cwch == -1 || cwch > 0));
  756. if(!pstr || !cch)
  757. return 0;
  758. // If we have to convert WCH_EMBEDDINGs, scan through and turn
  759. // them into spaces. This is necessary for RichEdit 1.0 compatibity,
  760. // as WideCharToMultiByte will turn WCH_EMBEDDING into a '?'
  761. if(flags == UN_CONVERT_WCH_EMBEDDING)
  762. {
  763. if(cwch == -1)
  764. cwch = wcslen(pwstr) + 1;
  765. pwstrtemp = twcb.GetBuf(cwch);
  766. if(pwstrtemp)
  767. {
  768. for(i = 0; i < cwch; i++)
  769. {
  770. pwstrtemp[i] = pwstr[i];
  771. if(pwstr[i] == WCH_EMBEDDING)
  772. pwstrtemp[i] = L' ';
  773. }
  774. pwstr = pwstrtemp;
  775. }
  776. }
  777. return WCTMB(codepage, 0, pwstr, cwch, pstr, cch, NULL, NULL, NULL);
  778. }
  779. /*
  780. * CW32System::UnicodeFromMbcs(pwstr, cwch, pstr, cch, uiCodePage)
  781. *
  782. * @mfunc
  783. * Converts a string to Unicode from MBCS. If cch equals -1, the string
  784. * is assumed to be NULL terminated. -1 is supplied as a default
  785. * argument.
  786. *
  787. * @rdesc
  788. * If [pwstr] is NULL or [cwch] is 0, 0 is returned. Otherwise,
  789. * the number of characters converted, including the terminating
  790. * NULL, is returned (note that converting the empty string will
  791. * return 1). If the conversion fails, 0 is returned.
  792. *
  793. * @devnote
  794. * Modifies: [pwstr]
  795. */
  796. int CW32System::UnicodeFromMbcs(
  797. LPWSTR pwstr, //@parm Buffer for Unicode string
  798. int cwch, //@parm Size of Unicode buffer, incl space for NULL terminator
  799. LPCSTR pstr, //@parm MBCS string to convert
  800. int cch, //@parm # chars in MBCS string, incl NULL terminator
  801. UINT uiCodePage) //@parm Code page to use (CP_ACP is default)
  802. {
  803. TRACEBEGIN(TRCSUBSYSWRAP, TRCSCOPEINTERN, "CW32System::UnicodeFromMbcs");
  804. Assert(pstr && cwch >= 0 && (cch == -1 || cch >= 0));
  805. if(!pwstr || !cwch)
  806. return 0;
  807. if(cch >= 3 && IsUTF8BOM((BYTE *)pstr))
  808. {
  809. uiCodePage = CP_UTF8; // UTF-8 BOM file
  810. cch -= 3; // Eat the BOM
  811. pstr += 3;
  812. }
  813. return MBTWC(uiCodePage, 0, pstr, cch, pwstr, cwch, NULL);
  814. }
  815. /*
  816. * CW32System::TextHGlobalAtoW (hglobalA)
  817. *
  818. * @func
  819. * translates a unicode string contained in an hglobal and
  820. * wraps the ansi version in another hglobal
  821. *
  822. * @devnote
  823. * does *not* free the incoming hglobal
  824. */
  825. HGLOBAL CW32System::TextHGlobalAtoW(HGLOBAL hglobalA)
  826. {
  827. TRACEBEGIN(TRCSUBSYSWRAP, TRCSCOPEINTERN, "CW32System::TextHGlobalAtoW");
  828. if(!hglobalA)
  829. return NULL;
  830. HGLOBAL hnew;
  831. LPSTR pstr = (LPSTR)GlobalLock(hglobalA);
  832. DWORD dwSize = GlobalSize(hglobalA);
  833. LONG cbSize = (dwSize + 1) * sizeof(WCHAR);
  834. hnew = GlobalAlloc(GMEM_FIXED, cbSize);
  835. if(hnew)
  836. {
  837. LPWSTR pwstr = (LPWSTR)GlobalLock(hnew);
  838. UnicodeFromMbcs(pwstr, dwSize + 1, pstr);
  839. GlobalUnlock(hnew);
  840. }
  841. GlobalUnlock(hglobalA);
  842. return hnew;
  843. }
  844. /*
  845. * CW32System::TextHGlobalWtoA(hglobalW)
  846. *
  847. * @func
  848. * converts a unicode text hglobal into a newly allocated
  849. * allocated hglobal with ANSI data
  850. *
  851. * @devnote
  852. * does *NOT* free the incoming hglobal
  853. */
  854. HGLOBAL CW32System::TextHGlobalWtoA(
  855. HGLOBAL hglobalW )
  856. {
  857. TRACEBEGIN(TRCSUBSYSUTIL, TRCSCOPEINTERN, "CW32System::TextHGlobalWtoA");
  858. if(!hglobalW)
  859. return NULL;
  860. HGLOBAL hnew = NULL;
  861. LPWSTR pwstr = (LPWSTR)GlobalLock(hglobalW);
  862. DWORD dwSize = GlobalSize(hglobalW);
  863. LONG cbSize = (dwSize * 2) * sizeof(CHAR);
  864. hnew = GlobalAlloc(GMEM_FIXED, cbSize);
  865. if( hnew )
  866. {
  867. LPSTR pstr = (LPSTR)GlobalLock(hnew);
  868. MbcsFromUnicode(pstr, cbSize, pwstr );
  869. GlobalUnlock(hnew);
  870. }
  871. GlobalUnlock(hglobalW);
  872. return hnew;
  873. }
  874. /*
  875. * CW32System::CharRepFromLID (lid, fPlane2)
  876. *
  877. * @mfunc Maps a language ID to a character repertoire
  878. *
  879. * @rdesc returns character repertoire (writing system) corresponding to LID
  880. *
  881. * @devnote:
  882. * This routine takes advantage of the fact that except for Chinese,
  883. * the code page is determined uniquely by the primary language ID,
  884. * which is given by the low-order 10 bits of the lcid.
  885. */
  886. UINT CW32System::CharRepFromLID(
  887. WORD lid, //@parm Language ID to map to code page
  888. BOOL fPlane2) //@parm TRUE if plane-2 CharRep needed
  889. {
  890. UINT j = PRIMARYLANGID(lid); // j = primary language (PLID)
  891. if(j >= LANG_CROATIAN) // PLID = 0x1A
  892. {
  893. if (lid == lidSerbianCyrillic || // Special case for LID = 0xC1A
  894. lid == lidAzeriCyrillic ||
  895. lid == lidUzbekCyrillic)
  896. {
  897. return RUSSIAN_INDEX;
  898. }
  899. if(j >= CLID) // Most languages above table
  900. return ANSI_INDEX;
  901. }
  902. j = rgCharRepfromLID[j]; // Translate PLID to CharRep
  903. if(!IsFECharRep(j))
  904. return j;
  905. if(j == GB2312_INDEX && lid != LANG_PRC && lid != LANG_SINGAPORE)
  906. j = BIG5_INDEX; // Taiwan, Hong Kong SAR, Macau SAR
  907. return fPlane2 ? j + JPN2_INDEX - SHIFTJIS_INDEX : j;
  908. }
  909. /*
  910. * CW32System::GetLocaleCharRep ()
  911. *
  912. * @mfunc Maps an LCID for thread to a Char repertoire
  913. *
  914. * @rdesc returns Code Page
  915. */
  916. UINT CW32System::GetLocaleCharRep()
  917. {
  918. #ifdef DEBUG
  919. UINT cpg = W32->DebugDefaultCpg();
  920. if (cpg)
  921. return CharRepFromCodePage(cpg);
  922. #endif
  923. LCID lcid;
  924. #ifdef UNDER_CE
  925. lcid = ::GetSystemDefaultLCID();
  926. #else
  927. lcid = GetThreadLocale();
  928. #endif
  929. return CharRepFromLID(LOWORD(lcid));
  930. }
  931. /*
  932. * CW32System::GetKeyboardLCID ()
  933. *
  934. * @mfunc Gets LCID for keyboard active on current thread
  935. *
  936. * @rdesc returns Code Page
  937. */
  938. LCID CW32System::GetKeyboardLCID(DWORD dwMakeAPICall)
  939. {
  940. return (WORD)GetKeyboardLayout(dwMakeAPICall);
  941. }
  942. /*
  943. * CW32System::GetKeyboardCharRep ()
  944. *
  945. * @mfunc Gets Code Page for keyboard active on current thread
  946. *
  947. * @rdesc returns Code Page
  948. */
  949. UINT CW32System::GetKeyboardCharRep(DWORD dwMakeAPICall)
  950. {
  951. return CharRepFromLID((WORD)GetKeyboardLayout(dwMakeAPICall));
  952. }
  953. /*
  954. * CW32System::InitKeyboardFlags ()
  955. *
  956. * @mfunc
  957. * Initializes keyboard flags. Used when control gains focus. Note that
  958. * Win95 doesn't support VK_RSHIFT, so if either shift key is pressed
  959. * when focus is regained, it'll be assumed to be the left shift.
  960. */
  961. void CW32System::InitKeyboardFlags()
  962. {
  963. _wKeyboardFlags = 0;
  964. if(GetKeyState(VK_SHIFT) < 0)
  965. SetKeyboardFlag(GetKeyState(VK_RSHIFT) < 0 ? RSHIFT : LSHIFT);
  966. }
  967. /*
  968. * CW32System::GetKeyboardFlag (dwKeyMask, wKey)
  969. *
  970. * @mfunc
  971. * Return whether wKey is depressed. Check with OS for agreement.
  972. * If OS says it isn't depressed, reset our internal flags. In
  973. * any event, return TRUE/FALSE in agreement with the system (bad
  974. * client may have eaten keystrokes, thereby destabilizing our
  975. * internal keyboard state.
  976. *
  977. * @rdesc
  978. * TRUE iff wKey is depressed
  979. */
  980. BOOL CW32System::GetKeyboardFlag (
  981. WORD dwKeyMask, //@parm _wKeyboardFlags mask like ALT, CTRL, or SHIFT
  982. WORD wKey) //@parm VK_xxx like VK_MENU, VK_CONTROL, or VK_SHIFT
  983. {
  984. BOOL fFlag = (GetKeyboardFlags() & dwKeyMask) != 0;
  985. if(fFlag ^ ((GetKeyState(wKey) & 0x8000) != 0))
  986. {
  987. // System doesn't agree with our internal state
  988. // (bad client ate a WM_KEYDOWN)
  989. if(fFlag)
  990. {
  991. ResetKeyboardFlag(dwKeyMask);
  992. return FALSE;
  993. }
  994. // Don't set an internal _wKeyboardFlag since we check for it
  995. // anyhow and client might not send WM_KEYUP either
  996. return TRUE;
  997. }
  998. return fFlag;
  999. }
  1000. /*
  1001. * CW32System::IsAlef(ch)
  1002. *
  1003. * @func
  1004. * Used to determine if base character is a Arabic-type Alef.
  1005. *
  1006. * @rdesc
  1007. * TRUE iff the base character is an Arabic-type Alef.
  1008. *
  1009. * @comm
  1010. * AlefWithMaddaAbove, AlefWithHamzaAbove, AlefWithHamzaBelow,
  1011. * and Alef are valid matches.
  1012. */
  1013. BOOL CW32System::IsAlef(
  1014. WCHAR ch)
  1015. {
  1016. return IN_RANGE(0x622, ch, 0x627) && ch != 0x624 && ch != 0x626;
  1017. }
  1018. /*
  1019. * CW32System::IsBiDiLcid(lcid)
  1020. *
  1021. * @func
  1022. * Return TRUE if lcid corresponds to an RTL language
  1023. *
  1024. * @rdesc
  1025. * TRUE if lcid corresponds to an RTL language
  1026. */
  1027. BOOL CW32System::IsBiDiLcid(
  1028. LCID lcid)
  1029. {
  1030. return
  1031. PRIMARYLANGID(lcid) == LANG_ARABIC ||
  1032. PRIMARYLANGID(lcid) == LANG_HEBREW ||
  1033. PRIMARYLANGID(lcid) == LANG_URDU ||
  1034. PRIMARYLANGID(lcid) == LANG_FARSI;
  1035. }
  1036. /*
  1037. * CW32System::IsIndicLcid(lcid)
  1038. *
  1039. * @func
  1040. * Return TRUE if lcid corresponds to an Indic language
  1041. *
  1042. * @rdesc
  1043. * TRUE if lcid corresponds to an Indic language
  1044. */
  1045. BOOL CW32System::IsIndicLcid(
  1046. LCID lcid)
  1047. {
  1048. WORD wLangId = PRIMARYLANGID(lcid);
  1049. return
  1050. wLangId == LANG_HINDI ||
  1051. wLangId == LANG_KONKANI ||
  1052. wLangId == LANG_NEPALI ||
  1053. IN_RANGE(LANG_BENGALI, wLangId, LANG_SANSKRIT);
  1054. }
  1055. /*
  1056. * CW32System::IsIndicKbdInstalled()
  1057. *
  1058. * @func
  1059. * Return TRUE if any Indic kbd installed
  1060. */
  1061. bool CW32System::IsIndicKbdInstalled()
  1062. {
  1063. for (int i = INDIC_FIRSTINDEX; i <= INDIC_LASTINDEX; i++)
  1064. if (_hkl[i] != 0)
  1065. return true;
  1066. return false;
  1067. }
  1068. /*
  1069. * CW32System::IsComplexScriptLcid(lcid)
  1070. *
  1071. * @func
  1072. * Return TRUE if lcid corresponds to any complex script locales
  1073. *
  1074. */
  1075. BOOL CW32System::IsComplexScriptLcid(
  1076. LCID lcid)
  1077. {
  1078. return IsBiDiLcid(lcid) ||
  1079. PRIMARYLANGID(LANGIDFROMLCID(lcid)) == LANG_THAI ||
  1080. PRIMARYLANGID(LANGIDFROMLCID(lcid)) == LANG_VIETNAMESE ||
  1081. IsIndicLcid(lcid);
  1082. }
  1083. /*
  1084. * CW32System::IsBiDiDiacritic(ch)
  1085. *
  1086. * @func Used to determine if character is a Arabic or Hebrew diacritic.
  1087. *
  1088. * @rdesc TRUE iff character is a diacritic
  1089. */
  1090. BOOL CW32System::IsBiDiDiacritic(
  1091. WCHAR ch)
  1092. {
  1093. return IN_RANGE(0x64B, ch, 0x670) && (ch <= 0x652 || ch == 0x670) || // Arabic
  1094. IN_RANGE(0x591, ch, 0x5C4) && (ch != 0x5A2 && ch != 0x5BA && // Hebrew
  1095. ch != 0x5BE && ch != 0x5C0 && ch != 0x5C3);
  1096. }
  1097. /*
  1098. * CW32System::IsVietCdmSequenceValid(ch1, ch2)
  1099. *
  1100. * @mfunc
  1101. * Check if ch2 can follow ch1 in case ch2 is a combining diacritic mark (CDM).
  1102. * Main use is for Vietnamese users (Chau Vu provides the logic below).
  1103. *
  1104. * @rdesc
  1105. * TRUE if ch2 can follow ch1
  1106. */
  1107. BOOL CW32System::IsVietCdmSequenceValid(
  1108. WCHAR ch1,
  1109. WCHAR ch2)
  1110. {
  1111. if (!IN_RANGE(0x300, ch2, 0x323) || // Fast out
  1112. !IN_RANGE(0x300, ch2, 0x301) && ch2 != 0x303 && ch2 != 0x309 && ch2 != 0x323)
  1113. {
  1114. return TRUE; // Not Vietnamese tone mark
  1115. }
  1116. // � � �
  1117. static const BYTE vowels[] = {0xF4, 0xEA, 0xE2, 'y', 'u', 'o', 'i', 'e', 'a'};
  1118. for(int i = ARRAY_SIZE(vowels); i--; )
  1119. if((ch1 | 0x20) == vowels[i]) // Vietnamese tone mark follows
  1120. return TRUE; // vowel
  1121. return IN_RANGE(0x102, ch1, 0x103) || // A-breve, a-breve
  1122. IN_RANGE(0x1A0, ch1, 0x1A1) || // O-horn, o-horn
  1123. IN_RANGE(0x1AF, ch1, 0x1B0); // U-horn, u-horn
  1124. }
  1125. /*
  1126. * CW32System::IsFELCID(lcid)
  1127. *
  1128. * @mfunc
  1129. * Returns TRUE iff lcid is for a East Asia country/region.
  1130. *
  1131. * @rdesc
  1132. * TRUE iff lcid is for a East Asia country/region.
  1133. */
  1134. bool CW32System::IsFELCID(
  1135. LCID lcid)
  1136. {
  1137. switch(PRIMARYLANGID(LANGIDFROMLCID(lcid)))
  1138. {
  1139. case LANG_CHINESE:
  1140. case LANG_JAPANESE:
  1141. case LANG_KOREAN:
  1142. return true;
  1143. }
  1144. return false;
  1145. }
  1146. /*
  1147. * CW32System::IsFECharSet(bCharSet)
  1148. *
  1149. * @mfunc
  1150. * Returns TRUE iff charset may be for a East Asia country/region.
  1151. *
  1152. * @rdesc
  1153. * TRUE iff charset may be for a East Asia country/region.
  1154. *
  1155. */
  1156. BOOL CW32System::IsFECharSet(
  1157. BYTE bCharSet)
  1158. {
  1159. switch(bCharSet)
  1160. {
  1161. case CHINESEBIG5_CHARSET:
  1162. case SHIFTJIS_CHARSET:
  1163. case HANGEUL_CHARSET:
  1164. case JOHAB_CHARSET:
  1165. case GB2312_CHARSET:
  1166. return TRUE;
  1167. }
  1168. return FALSE;
  1169. }
  1170. /*
  1171. * CW32System::Is8BitCodePage(CodePage)
  1172. *
  1173. * @mfunc
  1174. * Returns TRUE iff the codepage is 8-bit
  1175. */
  1176. BOOL CW32System::Is8BitCodePage(
  1177. unsigned CodePage)
  1178. {
  1179. if(!CodePage)
  1180. CodePage = GetACP();
  1181. return IN_RANGE(1250, CodePage, 1258) || CodePage == 874;
  1182. }
  1183. /*
  1184. * CW32System::IsFECodePageFont(dwFontCodePageSig)
  1185. *
  1186. * @mfunc
  1187. * Returns TRUE iff the font codepage signature reveals only FE support
  1188. */
  1189. BOOL CW32System::IsFECodePageFont(
  1190. DWORD dwFontCodePageSig)
  1191. {
  1192. DWORD dwFE = 0x001e0000; // Shift-JIS + PRC + Hangeul + Taiwan
  1193. DWORD dwOthers = 0x000101fc; // The rest of the world except for Latin-1 and Latin-2
  1194. return (dwFontCodePageSig & dwFE) && !(dwFontCodePageSig & dwOthers);
  1195. }
  1196. /*
  1197. * CW32System::IsRTLChar(ch)
  1198. *
  1199. * @mfunc
  1200. * Returns TRUE iff ch Arabic or Hebrew
  1201. *
  1202. * @rdesc
  1203. * TRUE iff ch is Arabic or Hebrew
  1204. */
  1205. BOOL IsRTLChar(
  1206. WCHAR ch)
  1207. {
  1208. // Remark: what about Arabic Presentation Forms?
  1209. // (0xFB50 - 0xFDFF, 0xFE70 - 0xFEFF)
  1210. return IN_RANGE(0x590, ch, 0x6FF) || ch == RTLMARK;
  1211. }
  1212. /*
  1213. * CW32System::IsRTLCharSet(bCharSet)
  1214. *
  1215. * @mfunc
  1216. * Returns TRUE iff charset is Arabic or Hebrew
  1217. *
  1218. * @rdesc
  1219. * TRUE iff charset may be for Arabic or Hebrew
  1220. */
  1221. BOOL CW32System::IsRTLCharSet(
  1222. BYTE bCharSet)
  1223. {
  1224. return IN_RANGE(HEBREW_CHARSET, bCharSet, ARABIC_CHARSET);
  1225. }
  1226. typedef struct {
  1227. WCHAR codepoint;
  1228. WORD CharFlags;
  1229. BYTE runlength;
  1230. } Data_125X;
  1231. /*
  1232. * CW32System::GetCharFlags125x(ch)
  1233. *
  1234. * @mfunc
  1235. * Returns char flags for ch as defined in FontSigFromCharRep() for 125x
  1236. * codepages. Bit 0: 1252, bit 1: 1250, bit 2: 1251, else bit x:
  1237. * 125x (for 1253 - 1258).
  1238. *
  1239. * @rdesc
  1240. * 125x char flags for ch
  1241. */
  1242. QWORD CW32System::GetCharFlags125x(
  1243. WCHAR ch) //@parm Char to examine
  1244. {
  1245. static const WORD rgCpgMask[] = {
  1246. 0x1FF, // 0xA0
  1247. 0x131, // 0xA1
  1248. 0x1F1, // 0xA2
  1249. 0x1F9, // 0xA3
  1250. 0x1DF, // 0xA4
  1251. 0x179, // 0xA5
  1252. 0x1FF, // 0xA6
  1253. 0x1FF, // 0xA7
  1254. 0x1FB, // 0xA8
  1255. 0x1FF, // 0xA9
  1256. 0x111, // 0xAA
  1257. 0x1FF, // 0xAB
  1258. 0x1FF, // 0xAC
  1259. 0x1FF, // 0xAD
  1260. 0x1FF, // 0xAE
  1261. 0x1F1, // 0xAF
  1262. 0x1FF, // 0xB0
  1263. 0x1FF, // 0xB1
  1264. 0x1F9, // 0xB2
  1265. 0x1F9, // 0xB3
  1266. 0x1F3, // 0xB4
  1267. 0x1FF, // 0xB5
  1268. 0x1FF, // 0xB6
  1269. 0x1FF, // 0xB7
  1270. 0x1F3, // 0xB8
  1271. 0x1F1, // 0xB9
  1272. 0x111, // 0xBA
  1273. 0x1FF, // 0xBB
  1274. 0x1F1, // 0xBC
  1275. 0x1F9, // 0xBD
  1276. 0x1F1, // 0xBE
  1277. 0x131, // 0xBF
  1278. 0x111, // 0xC0
  1279. 0x113, // 0xC1
  1280. 0x113, // 0xC2
  1281. 0x011, // 0xC3
  1282. 0x193, // 0xC4
  1283. 0x191, // 0xC5
  1284. 0x191, // 0xC6
  1285. 0x113, // 0xC7
  1286. 0x111, // 0xC8
  1287. 0x193, // 0xC9
  1288. 0x111, // 0xCA
  1289. 0x113, // 0xCB
  1290. 0x011, // 0xCC
  1291. 0x113, // 0xCD
  1292. 0x113, // 0xCE
  1293. 0x111, // 0xCF
  1294. 0x001, // 0xD0
  1295. 0x111, // 0xD1
  1296. 0x011, // 0xD2
  1297. 0x193, // 0xD3
  1298. 0x113, // 0xD4
  1299. 0x091, // 0xD5
  1300. 0x193, // 0xD6
  1301. 0x1F3, // 0xD7
  1302. 0x191, // 0xD8
  1303. 0x111, // 0xD9
  1304. 0x113, // 0xDA
  1305. 0x111, // 0xDB
  1306. 0x193, // 0xDC
  1307. 0x003, // 0xDD
  1308. 0x001, // 0xDE
  1309. 0x193, // 0xDF
  1310. 0x151, // 0xE0
  1311. 0x113, // 0xE1
  1312. 0x153, // 0xE2
  1313. 0x011, // 0xE3
  1314. 0x193, // 0xE4
  1315. 0x191, // 0xE5
  1316. 0x191, // 0xE6
  1317. 0x153, // 0xE7
  1318. 0x151, // 0xE8
  1319. 0x1D3, // 0xE9
  1320. 0x151, // 0xEA
  1321. 0x153, // 0xEB
  1322. 0x011, // 0xEC
  1323. 0x113, // 0xED
  1324. 0x153, // 0xEE
  1325. 0x151, // 0xEF
  1326. 0x001, // 0xF0
  1327. 0x111, // 0xF1
  1328. 0x011, // 0xF2
  1329. 0x193, // 0xF3
  1330. 0x153, // 0xF4
  1331. 0x091, // 0xF5
  1332. 0x193, // 0xF6
  1333. 0x1F3, // 0xF7
  1334. 0x191, // 0xF8
  1335. 0x151, // 0xF9
  1336. 0x113, // 0xFA
  1337. 0x151, // 0xFB
  1338. 0x1D3, // 0xFC
  1339. 0x003, // 0xFD
  1340. 0x001, // 0xFE
  1341. 0x111 // 0xFF
  1342. };
  1343. static const Data_125X Table_125X[] = {
  1344. { 0x100, 0x080, 2},
  1345. { 0x102, 0x102, 2},
  1346. { 0x104, 0x082, 4},
  1347. { 0x10c, 0x082, 2},
  1348. { 0x10e, 0x002, 2},
  1349. { 0x110, 0x102, 2},
  1350. { 0x112, 0x080, 2},
  1351. { 0x116, 0x080, 2},
  1352. { 0x118, 0x082, 2},
  1353. { 0x11a, 0x002, 2},
  1354. { 0x11e, 0x010, 2},
  1355. { 0x122, 0x080, 2},
  1356. { 0x12a, 0x080, 2},
  1357. { 0x12e, 0x080, 2},
  1358. { 0x130, 0x010, 2},
  1359. { 0x136, 0x080, 2},
  1360. { 0x139, 0x002, 2},
  1361. { 0x13b, 0x080, 2},
  1362. { 0x13d, 0x002, 2},
  1363. { 0x141, 0x082, 4},
  1364. { 0x145, 0x080, 2},
  1365. { 0x147, 0x002, 2},
  1366. { 0x14c, 0x080, 2},
  1367. { 0x150, 0x002, 2},
  1368. { 0x152, 0x151, 2},
  1369. { 0x154, 0x002, 2},
  1370. { 0x156, 0x080, 2},
  1371. { 0x158, 0x002, 2},
  1372. { 0x15a, 0x082, 2},
  1373. { 0x15e, 0x012, 2},
  1374. { 0x160, 0x093, 2},
  1375. { 0x162, 0x002, 4},
  1376. { 0x16a, 0x080, 2},
  1377. { 0x16e, 0x002, 4},
  1378. { 0x172, 0x080, 2},
  1379. { 0x178, 0x111, 1},
  1380. { 0x179, 0x082, 4},
  1381. { 0x17d, 0x083, 2},
  1382. { 0x192, 0x179, 1},
  1383. { 0x1A0, 0x100, 2},
  1384. { 0x1AF, 0x100, 2},
  1385. { 0x2c6, 0x171, 1},
  1386. { 0x2c7, 0x082, 1},
  1387. { 0x2d8, 0x002, 1},
  1388. { 0x2d9, 0x082, 1},
  1389. { 0x2db, 0x082, 1},
  1390. { 0x2dc, 0x131, 1},
  1391. { 0x2dd, 0x002, 1},
  1392. { 0x300, 0x100, 2},
  1393. { 0x303, 0x100, 1},
  1394. { 0x309, 0x100, 1},
  1395. { 0x323, 0x100, 1},
  1396. { 0x384, 0x008, 3},
  1397. { 0x388, 0x008, 3},
  1398. { 0x38c, 0x008, 1},
  1399. { 0x38e, 0x008, 20},
  1400. { 0x3a3, 0x008, 44},
  1401. { 0x401, 0x004, 12},
  1402. { 0x40e, 0x004, 66},
  1403. { 0x451, 0x004, 12},
  1404. { 0x45e, 0x004, 2},
  1405. { 0x490, 0x004, 2},
  1406. { 0x5b0, 0x020, 20},
  1407. { 0x5d0, 0x020, 27},
  1408. { 0x5F0, 0x020, 5},
  1409. { 0x60c, 0x040, 1},
  1410. { 0x61b, 0x040, 1},
  1411. { 0x61f, 0x040, 1},
  1412. { 0x621, 0x040, 26},
  1413. { 0x640, 0x040, 19},
  1414. { 0x679, 0x040, 1},
  1415. { 0x67e, 0x040, 1},
  1416. { 0x686, 0x040, 1},
  1417. { 0x688, 0x040, 1},
  1418. { 0x691, 0x040, 1},
  1419. { 0x698, 0x040, 1},
  1420. { 0x6a9, 0x040, 1},
  1421. { 0x6af, 0x040, 1},
  1422. { 0x6ba, 0x040, 1},
  1423. { 0x6be, 0x040, 1},
  1424. { 0x6c1, 0x040, 1},
  1425. { 0x6d2, 0x040, 1},
  1426. {0x200c, 0x040, 2},
  1427. {0x200e, 0x060, 2},
  1428. {0x2013, 0x1ff, 2},
  1429. {0x2015, 0x008, 1},
  1430. {0x2018, 0x1ff, 3},
  1431. {0x201c, 0x1ff, 3},
  1432. {0x2020, 0x1ff, 3},
  1433. {0x2026, 0x1ff, 1},
  1434. {0x2030, 0x1ff, 1},
  1435. {0x2039, 0x1ff, 2},
  1436. {0x20AA, 0x020, 1},
  1437. {0x20AB, 0x100, 1},
  1438. {0x20AC, 0x1ff, 1},
  1439. {0x2116, 0x004, 1},
  1440. {0x2122, 0x1ff, 1}
  1441. };
  1442. // Easy check for ASCII
  1443. if(ch <= 0x7f)
  1444. return FLATIN1 | FLATIN2 | FCYRILLIC | FGREEK | FTURKISH |
  1445. FHEBREW | FARABIC | FBALTIC | FVIETNAMESE;
  1446. // Easy check for missing codes
  1447. if(ch > 0x2122)
  1448. return 0;
  1449. if(IN_RANGE(0xA0, ch, 0xFF))
  1450. return (QWORD)(DWORD)(rgCpgMask[ch - 0xA0] << 8);
  1451. // Perform binary search to find entry in table
  1452. int low = 0;
  1453. int high = ARRAY_SIZE(Table_125X) - 1;
  1454. int middle;
  1455. int midval;
  1456. int runlength;
  1457. while(low <= high)
  1458. {
  1459. middle = (high + low) / 2;
  1460. midval = Table_125X[middle].codepoint;
  1461. if(midval > ch)
  1462. high = middle - 1;
  1463. else
  1464. low = middle + 1;
  1465. runlength = Table_125X[middle].runlength;
  1466. if(ch >= midval && ch <= midval + runlength - 1)
  1467. return (QWORD)(DWORD)(Table_125X[middle].CharFlags << 8);
  1468. }
  1469. return 0;
  1470. }
  1471. /*
  1472. * CW32System::IsUTF8BOM(pstr)
  1473. *
  1474. * @mfunc
  1475. * Return TRUE if pstr points at a UTF-8 BOM
  1476. *
  1477. * @rdesc
  1478. * TRUE iff pstr points at a UTF-8 BOM
  1479. */
  1480. BOOL CW32System::IsUTF8BOM(
  1481. BYTE *pstr)
  1482. {
  1483. BYTE *pstrUtf8BOM = szUTF8BOM;
  1484. for(LONG i = 3; i--; )
  1485. if(*pstr++ != *pstrUtf8BOM++)
  1486. return FALSE;
  1487. return TRUE;
  1488. }
  1489. /*
  1490. * CW32System::GetTrailBytesCount(ach, cpg)
  1491. *
  1492. * @mfunc
  1493. * Returns number of trail bytes iff the byte ach is a lead byte for the code page cpg.
  1494. *
  1495. * @rdesc
  1496. * count of trail bytes if ach is lead byte for cpg
  1497. *
  1498. * @comm
  1499. * This is needed to support CP_UTF8 as well as DBCS.
  1500. * This function potentially doesn't support as many code pages as the
  1501. * Win32 IsDBCSLeadByte() function (and it might not be as up-to-date).
  1502. * An AssertSz() is included to compare the results when the code page
  1503. * is supported by the system.
  1504. *
  1505. * Reference: \\sparrow\sysnls\cptable\win9x. See code-page txt files
  1506. * in subdirectories windows\txt and others\txt.
  1507. */
  1508. int CW32System::GetTrailBytesCount(
  1509. BYTE ach,
  1510. UINT cpg)
  1511. {
  1512. if(ach < 0x81) // Smallest known lead
  1513. return 0; // byte = 0x81:
  1514. // early out
  1515. BOOL bDBLeadByte = FALSE; // Variable to check
  1516. // result with system
  1517. // ifdef DEBUG
  1518. if (cpg == CP_UTF8)
  1519. {
  1520. int cTrailBytes = 0; // Number of trail bytes for CP_UTF8(0 - 3)
  1521. if (ach >= 0x0F0) // Handle 4-byte form for 16 UTF-16 planes
  1522. cTrailBytes = 3; // above the BMP) expect:
  1523. // 11110bbb 10bbbbbb 10bbbbbb 10bbbbbb
  1524. else if (ach >= 0x0E0) // Need at least 3 bytes of form
  1525. cTrailBytes = 2; // 1110bbbb 10bbbbbb 10bbbbbb
  1526. else if (ach >= 0x0C0) // Need at least 2 bytes of form
  1527. cTrailBytes = 1; // 110bbbbb 10bbbbbb
  1528. return cTrailBytes;
  1529. }
  1530. else if(cpg > 950)
  1531. {
  1532. if(cpg < 1361) // E.g., the 125x's are
  1533. return 0; // SBCSs: early out
  1534. else if(cpg == 1361) // Korean Johab
  1535. bDBLeadByte = IN_RANGE(0x84, ach, 0xd3) || // 0x84 <= ach <= 0xd3
  1536. IN_RANGE(0xd8, ach, 0xde) || // 0xd8 <= ach <= 0xde
  1537. IN_RANGE(0xe0, ach, 0xf9); // 0xe0 <= ach <= 0xf9
  1538. else if(cpg == 10001) // Mac Japanese
  1539. goto JIS;
  1540. else if(cpg == 10002) // Mac Trad Chinese (Big5)
  1541. bDBLeadByte = ach <= 0xfe;
  1542. else if(cpg == 10003) // Mac Korean
  1543. bDBLeadByte = IN_RANGE(0xa1, ach, 0xac) || // 0xa1 <= ach <= 0xac
  1544. IN_RANGE(0xb0, ach, 0xc8) || // 0xb0 <= ach <= 0xc8
  1545. IN_RANGE(0xca, ach, 0xfd); // 0xca <= ach <= 0xfd
  1546. else if(cpg == 10008) // Mac Simplified Chinese
  1547. bDBLeadByte = IN_RANGE(0xa1, ach, 0xa9) || // 0xa1 <= ach <= 0xa9
  1548. IN_RANGE(0xb0, ach, 0xf7); // 0xb0 <= ach <= 0xf7
  1549. }
  1550. else if (cpg >= 932) // cpg <= 950
  1551. {
  1552. if(cpg == 950 || cpg == 949 || cpg == 936) // Chinese (Taiwan, HK),
  1553. bDBLeadByte = ach <= 0xfe; // Korean Ext Wansung,
  1554. // PRC GBK: 0x81 - 0xfe
  1555. else if(cpg == 932) // Japanese
  1556. JIS: bDBLeadByte = ach <= 0x9f || IN_RANGE(0xe0, ach, 0xfc);
  1557. }
  1558. #ifdef DEBUG
  1559. WCHAR ch;
  1560. static BYTE asz[2] = {0xe0, 0xe0}; // All code pages above
  1561. // if cpg == 0, fRet will FALSE but IsDBCSLeadByteEx may succeed.
  1562. if ( cpg && cpg != CP_SYMBOL && cpg != CP_UTF8)
  1563. {
  1564. // If system supports cpg, then fRet should agree with system result
  1565. AssertSz(MultiByteToWideChar(cpg, 0, (char *)asz, 2, &ch, 1) <= 0 ||
  1566. bDBLeadByte == IsDBCSLeadByteEx(cpg, ach),
  1567. "bDBLeadByte differs from IsDBCSLeadByteEx()");
  1568. }
  1569. #endif
  1570. return bDBLeadByte ? 1 : 0;
  1571. }
  1572. /*
  1573. * CW32System::CharSetFromCharRep(iCharRep)
  1574. *
  1575. * @func
  1576. * Map character repertoire index to bCharSet for GDI
  1577. */
  1578. BYTE CW32System::CharSetFromCharRep(
  1579. LONG iCharRep)
  1580. {
  1581. return (unsigned)iCharRep < CCHARSET ? rgCharSet[iCharRep] : DEFAULT_CHARSET;
  1582. }
  1583. /*
  1584. * CW32System::GetCharSet(nCP, piCharRep)
  1585. *
  1586. * @func
  1587. * Get character set for code page <p nCP>. Also returns script index
  1588. * in *piCharRep
  1589. *
  1590. * @rdesc
  1591. * CharSet for code page <p nCP>
  1592. */
  1593. BYTE CW32System::GetCharSet(
  1594. INT nCP, //@parm Code page or index
  1595. int *piCharRep) //@parm Out parm to receive index
  1596. {
  1597. TRACEBEGIN(TRCSUBSYSRTFR, TRCSCOPEINTERN, "GetCharSet");
  1598. if(nCP < CCHARSET) // nCP is already an index
  1599. {
  1600. nCP = max(nCP, 0);
  1601. if(piCharRep)
  1602. *piCharRep = nCP;
  1603. return rgCharSet[nCP];
  1604. }
  1605. Assert(CCODEPAGE == CCHARSET && CCODEPAGE == NCHARSETS);
  1606. for(int i = 0; i < CCODEPAGE && rgCodePage[i] != nCP; i++)
  1607. ;
  1608. if(i == CCODEPAGE) // Didn't find it
  1609. i = -1;
  1610. if (piCharRep)
  1611. *piCharRep = i;
  1612. return i >= 0 ? rgCharSet[i] : 0;
  1613. }
  1614. /*
  1615. * CW32System::MatchFECharRep(qwCharFlags, qwFontSig)
  1616. *
  1617. * @func
  1618. * Get a FE character set for a FE char
  1619. *
  1620. * @rdesc
  1621. * Char repertoire
  1622. */
  1623. BYTE CW32System::MatchFECharRep(
  1624. QWORD qwCharFlags, //@parm Char flags
  1625. QWORD qwFontSig) //@parm Font Signature
  1626. {
  1627. TRACEBEGIN(TRCSUBSYSRTFR, TRCSCOPEINTERN, "CW32System::MatchFECharSet");
  1628. if (qwCharFlags & qwFontSig & FFE) // Perfect match
  1629. goto Exit;
  1630. if (!(qwFontSig & FFE)) // Not a FE font
  1631. goto Exit;
  1632. if (qwCharFlags & (FCHINESE | FBIG5))
  1633. {
  1634. if (qwFontSig & FBIG5)
  1635. return BIG5_INDEX;
  1636. if (qwFontSig & FHANGUL)
  1637. return HANGUL_INDEX;
  1638. if (qwFontSig & FKANA)
  1639. return SHIFTJIS_INDEX;
  1640. }
  1641. Exit:
  1642. return CharRepFromFontSig(qwCharFlags);
  1643. }
  1644. /*
  1645. * CW32System::CodePageFromCharRep(iCharRep)
  1646. *
  1647. * @func
  1648. * Get code page for character repertoire <p iCharRep>
  1649. *
  1650. * @rdesc
  1651. * Code page for character repertoire <p iCharRep>
  1652. */
  1653. INT CW32System::CodePageFromCharRep(
  1654. LONG iCharRep) //@parm CharSet
  1655. {
  1656. TRACEBEGIN(TRCSUBSYSRTFR, TRCSCOPEINTERN, "GetCodePage");
  1657. return ((unsigned)iCharRep < CCODEPAGE) ? rgCodePage[iCharRep] : 0;
  1658. }
  1659. /*
  1660. * CW32System::FontSigFromCharRep(iCharRep)
  1661. *
  1662. * @func
  1663. * Get font signature bits for character repertoire <p iCharRep>.
  1664. *
  1665. * @rdesc
  1666. * Font signature mask for character repertoire <p bCharSet>
  1667. */
  1668. QWORD CW32System::FontSigFromCharRep(
  1669. LONG iCharRep)
  1670. {
  1671. TRACEBEGIN(TRCSUBSYSRTFR, TRCSCOPEINTERN, "CW32System::FontSigFromCharRep");
  1672. if(iCharRep <= BIG5_INDEX)
  1673. {
  1674. if (iCharRep != ANSI_INDEX)
  1675. return (DWORD)(FHILATIN1 << iCharRep);
  1676. return FLATIN1;
  1677. }
  1678. union
  1679. {
  1680. QWORD qw; // Endian-dependent way of
  1681. DWORD dw[2]; // avoiding 64-bit left shifts
  1682. };
  1683. qw = 0;
  1684. if(IN_RANGE(ARMENIAN_INDEX, iCharRep, NCHARREPERTOIRES))
  1685. {
  1686. dw[1] = (DWORD)(FARMENIAN >> 32) << (iCharRep - ARMENIAN_INDEX);
  1687. if(IN_RANGE(JPN2_INDEX, iCharRep, CHT2_INDEX))
  1688. dw[0] |= FSURROGATE;
  1689. }
  1690. else if(IN_RANGE(PC437_INDEX, iCharRep, MAC_INDEX))
  1691. dw[0] = FHILATIN1;
  1692. return qw;
  1693. }
  1694. /*
  1695. * CW32System::CharRepFontSig(qwFontSig, fFirstAvailable)
  1696. *
  1697. * @func
  1698. * Get char repertoire from font signature bit[s]. If fFirstAvailable
  1699. * = TRUE, then the CharRep corresponding to the lowest-order nonzero
  1700. * bit in qwFontSig is used. If fFirstAvailable is FALSE, the CharRep
  1701. * is that corresponding to qwFontSig provided qwFontSig is a single bit.
  1702. */
  1703. LONG CW32System::CharRepFontSig(
  1704. QWORD qwFontSig, //@parm Font signature to match
  1705. BOOL fFirstAvailable) //@parm TRUE matches 1st available; else exact
  1706. {
  1707. DWORD dw;
  1708. INT i;
  1709. union
  1710. {
  1711. QWORD qwFS; // Endian-dependent way of
  1712. DWORD dwFS[2]; // avoiding 64-bit shifts
  1713. };
  1714. DWORD *pdw = &dwFS[0];
  1715. qwFS = qwFontSig;
  1716. if(*pdw & 0x00FFFF00) // Check for everything less
  1717. { // math
  1718. dw = FHILATIN1;
  1719. for(i = ANSI_INDEX; i <= BIG5_INDEX; i++, dw <<= 1)
  1720. {
  1721. if(dw & *pdw)
  1722. return (fFirstAvailable || dw == *pdw) ? i : -1;
  1723. }
  1724. }
  1725. pdw++; // Endian dependent
  1726. if(*pdw) // High word of qw
  1727. {
  1728. dw = FARMENIAN >> 32;
  1729. for(i = ARMENIAN_INDEX; i <= NCHARREPERTOIRES; i++, dw <<= 1)
  1730. {
  1731. if(dw & *pdw)
  1732. return (fFirstAvailable || dw == *pdw) ? i : -1;
  1733. }
  1734. }
  1735. return fFirstAvailable || (qwFontSig & FASCII) ? ANSI_INDEX : -1;
  1736. }
  1737. /*
  1738. * CW32System::CharRepFromCharSet(bCharSet)
  1739. *
  1740. * @func
  1741. * Get character repertoire from bCharSet
  1742. *
  1743. * @rdesc
  1744. * character repertoire corresponding to <p bCharSet>
  1745. *
  1746. * @devnote
  1747. * Linear search
  1748. */
  1749. LONG CW32System::CharRepFromCharSet(
  1750. BYTE bCharSet)
  1751. {
  1752. TRACEBEGIN(TRCSUBSYSRTFR, TRCSCOPEINTERN, "CW32System::ScriptIndexFromCharSet");
  1753. Assert(CCHARSET == CCODEPAGE);
  1754. for (int i = 0; i < CCHARSET; i++)
  1755. {
  1756. if(rgCharSet[i] == bCharSet)
  1757. return i;
  1758. }
  1759. return -1; // Not found
  1760. }
  1761. /*
  1762. * CW32System::CharRepFromCodePage(CodePage)
  1763. *
  1764. * @func
  1765. * Get character repertoire from bCharSet
  1766. *
  1767. * @rdesc
  1768. * character repertoire corresponding to <p bCharSet>
  1769. *
  1770. * @devnote
  1771. * Linear search
  1772. */
  1773. INT CW32System::CharRepFromCodePage(
  1774. LONG CodePage)
  1775. {
  1776. TRACEBEGIN(TRCSUBSYSRTFR, TRCSCOPEINTERN, "CW32System::ScriptIndexFromCharSet");
  1777. for (int i = 0; i < CCODEPAGE; i++)
  1778. {
  1779. if(rgCodePage[i] == CodePage)
  1780. return i;
  1781. }
  1782. return -1; // Not found
  1783. }
  1784. /*
  1785. * CW32System::GetScreenDC()
  1786. *
  1787. * @mfunc
  1788. * Returns you a default screen DC which richedit caches for its lifetime.
  1789. *
  1790. * Note, you need to serialize access to DCs, so make sure its used in the
  1791. * renderer and measurer or otherwise protected by a CLock.
  1792. *
  1793. * @rdesc
  1794. * Screen HDC if succeeded.
  1795. */
  1796. HDC CW32System::GetScreenDC()
  1797. {
  1798. if (!_hdcScreen)
  1799. _hdcScreen = CreateIC(L"DISPLAY", NULL, NULL, NULL);
  1800. //Verify DC validity
  1801. Assert(GetDeviceCaps(_hdcScreen, LOGPIXELSX));
  1802. return _hdcScreen;
  1803. }
  1804. /*
  1805. * CW32System::GetTextMetrics(hdc, &lf, &tm)
  1806. *
  1807. * @mfunc
  1808. * CreateFontIndirect(lf), select into hdc, and get TEXTMETRICS
  1809. *
  1810. * @rdesc
  1811. * TRUE if succeeded and selected facename is same as lf.lfFaceName
  1812. */
  1813. BOOL CW32System::GetTextMetrics(
  1814. HDC hdc,
  1815. LOGFONT & lf,
  1816. TEXTMETRIC &tm)
  1817. {
  1818. HFONT hfont = CreateFontIndirect(&lf);
  1819. if(!hfont)
  1820. return FALSE;
  1821. HFONT hfontOld = SelectFont(hdc, hfont);
  1822. WCHAR szFaceName[LF_FACESIZE + 1];
  1823. BOOL fRet = GetTextFace(hdc, LF_FACESIZE, szFaceName) &&
  1824. !wcsicmp(lf.lfFaceName, szFaceName) &&
  1825. W32->GetTextMetrics(hdc, &tm);
  1826. SelectFont(hdc, hfontOld);
  1827. DeleteObject(hfont);
  1828. return fRet;
  1829. }
  1830. /*
  1831. * CW32System::ValidateStreamWparam(wparam)
  1832. *
  1833. * @mfunc
  1834. * Examine lparam to see if hiword is a valid codepage. If not set it
  1835. * to 0 and turn off SF_USECODEPAGE flag
  1836. *
  1837. * @rdesc
  1838. * Validated lparam
  1839. */
  1840. WPARAM CW32System::ValidateStreamWparam(
  1841. WPARAM wparam) //@parm EM_STREAMIN/OUT wparam
  1842. {
  1843. TRACEBEGIN(TRCSUBSYSRTFR, TRCSCOPEINTERN, "CW32System::ValidateStreamWparam");
  1844. if ((wparam & SF_USECODEPAGE) && !IsValidCodePage(HIWORD(wparam)) &&
  1845. HIWORD(wparam) != CP_UTF8 && HIWORD(wparam) != CP_UBE)
  1846. {
  1847. // Invalid codepage, so reset codepage parameters
  1848. wparam &= 0xFFFF & ~SF_USECODEPAGE;
  1849. }
  1850. return wparam;
  1851. }
  1852. /*
  1853. * CW32System::MECharClass(ch)
  1854. *
  1855. * @func
  1856. * return ME character type for purposes of CharSet stamping. Values
  1857. * are:
  1858. *
  1859. * 0: Arabic (specific RTL)
  1860. * 1: Hebrew (specific RTL)
  1861. * 2: RTL (generic RTL, e.g., RTL mark)
  1862. * 3: LTR
  1863. * 4: EOP or start/end of text
  1864. * 5: ASCII digit
  1865. * 6: punctuation and neutrals
  1866. *
  1867. * @rdesc
  1868. * ME character class
  1869. */
  1870. CC CW32System::MECharClass(
  1871. WCHAR ch)
  1872. {
  1873. AssertSz(CC_NEUTRAL > CC_ASCIIDIGIT && CC_ASCIIDIGIT > CC_EOP &&
  1874. CC_EOP > CC_LTR && CC_LTR > CC_RTL && CC_RTL > CC_ARABIC,
  1875. "CW32System::MECharClass: invalid CC values");
  1876. // Work down Unicode values from large to small. Use nested if
  1877. // statements to reduce the number executed.
  1878. // Remark: what about Arabic Presentation Forms?
  1879. // (0xFB50 - 0xFDFF, 0xFE70 - 0xFEFF)
  1880. if(ch >= 0x700)
  1881. {
  1882. if(IN_RANGE(ENQUAD, ch, RTLMARK))
  1883. { // ENQUAD thru RTLMARK
  1884. if(ch == RTLMARK) // Maybe add more Unicode general
  1885. return CC_RTL; // punctuation?
  1886. if(IN_RANGE(ZWNJ, ch, ZWJ)) // ZWNJ & ZWJ are handled as Arabic,
  1887. return CC_ARABIC; // even though they actually shouldn't
  1888. // affect layout.
  1889. if(ch < ZWNJ)
  1890. return CC_NEUTRAL; // Various blanks are neutral
  1891. }
  1892. return CC_LTR;
  1893. }
  1894. if(ch >= 0x40)
  1895. {
  1896. if(ch >= 0x590)
  1897. return (ch >= 0x600) ? CC_ARABIC : CC_HEBREW;
  1898. if(IN_RANGE(0x7B, (ch | 0x20), 0x7F) || ch == 0x60 || ch == 0x40)
  1899. return CC_NEUTRAL; // [\]^_{|}~`@
  1900. return CC_LTR;
  1901. }
  1902. if(ch >= 0x20)
  1903. {
  1904. if(IN_RANGE(0x30, ch, 0x39))
  1905. return CC_ASCIIDIGIT;
  1906. return CC_NEUTRAL;
  1907. }
  1908. Assert(ch < 0x20);
  1909. if((1 << ch) & 0x00003201) /* IsASCIIEOP(ch) || ch == TAB || !ch */
  1910. return CC_EOP;
  1911. return CC_LTR;
  1912. }
  1913. /*
  1914. * CW32System::MBTWC (CodePage, dwFlags, pstrMB, cchMB, pstrWC, cchWC, pfNoCodePage)
  1915. *
  1916. * @mfunc
  1917. * Convert MultiByte (MB) string pstrMB of length cchMB to WideChar (WC)
  1918. * string pstrWC of length cchWC according to the flags dwFlags and code
  1919. * page CodePage. If CodePage = SYMBOL_CODEPAGE
  1920. * (usually for SYMBOL_CHARSET strings),
  1921. * convert each byte in pstrMB to a wide char with a zero high byte
  1922. * and a low byte equal to the MultiByte string byte, i.e., no
  1923. * translation other than a zero extend into the high byte. Else call
  1924. * the Win32 MultiByteToWideChar() function.
  1925. *
  1926. * @rdesc
  1927. * Count of characters converted
  1928. */
  1929. int CW32System::MBTWC(
  1930. INT CodePage, //@parm Code page to use for conversion
  1931. DWORD dwFlags, //@parm Flags to guide conversion
  1932. LPCSTR pstrMB, //@parm MultiByte string to convert to WideChar
  1933. int cchMB, //@parm Count of chars (bytes) in pstrMB or -1
  1934. LPWSTR pstrWC, //@parm WideChar string to receive converted chars
  1935. int cchWC, //@parm Max count for pstrWC or 0 to get cch needed
  1936. LPBOOL pfNoCodePage) //@parm Out parm to receive whether code page is on system
  1937. {
  1938. BOOL fNoCodePage = FALSE; // Default code page is on OS
  1939. int cch = -1;
  1940. if(CodePage == CP_UTF8)
  1941. {
  1942. DWORD ch,ch1;
  1943. for(cch = 0; cchMB--; )
  1944. {
  1945. ch = ch1 = *(BYTE *)pstrMB++;
  1946. Assert(ch < 256);
  1947. if(ch > 127 && cchMB && IN_RANGE(0x80, *(BYTE *)pstrMB, 0xBF))
  1948. {
  1949. // Need at least 2 bytes of form 110bbbbb 10bbbbbb
  1950. ch1 = ((ch1 & 0x1F) << 6) + (*pstrMB++ & 0x3F);
  1951. cchMB--;
  1952. if(ch >= 0xE0 && cchMB && IN_RANGE(0x80, *(BYTE *)pstrMB, 0xBF))
  1953. {
  1954. // Need at least 3 bytes of form 1110bbbb 10bbbbbb 10bbbbbb
  1955. ch1 = (ch1 << 6) + (*pstrMB++ & 0x3F);
  1956. cchMB--;
  1957. if (ch >= 0xF0 && cchMB && IN_RANGE(0x80, *(BYTE *)pstrMB, 0xBF))
  1958. {
  1959. // Handle 4-byte form for 16 UTF-16 planes above the
  1960. // BMP) expect: 11110bbb 10bbbbbb 10bbbbbb 10bbbbbb
  1961. ch1 = ((ch1 & 0x7FFF) << 6) + (*(BYTE *)pstrMB++ & 0x3F)
  1962. - 0x10000; // Subtract offset for BMP
  1963. if(ch1 <= 0xFFFFF) // Fits in 20 bits
  1964. {
  1965. cch++; // Two 16-bit surrogate codes
  1966. if(cch < cchWC)
  1967. *pstrWC++ = UTF16_LEAD + (ch1 >> 10);
  1968. ch1 = (ch1 & 0x3FF) + UTF16_TRAIL;
  1969. cchMB--;
  1970. }
  1971. else ch1 = '?';
  1972. }
  1973. }
  1974. }
  1975. cch++;
  1976. if(cch < cchWC)
  1977. *pstrWC++ = ch1;
  1978. if(!ch)
  1979. break;
  1980. }
  1981. }
  1982. else if(CodePage != CP_SYMBOL) // Not SYMBOL_CHARSET
  1983. {
  1984. fNoCodePage = TRUE; // Default codepage isn't on OS
  1985. if(CodePage >= 0) // Might be..
  1986. {
  1987. cch = MultiByteToWideChar(
  1988. CodePage, dwFlags, pstrMB, cchMB, pstrWC, cchWC);
  1989. if(cch > 0)
  1990. fNoCodePage = FALSE; // Codepage is on OS
  1991. }
  1992. }
  1993. if(pfNoCodePage)
  1994. *pfNoCodePage = fNoCodePage;
  1995. if(cch <= 0)
  1996. {
  1997. // SYMBOL_CHARSET or conversion failed: bytes -> words with
  1998. // high bytes of 0. Return count for full conversion
  1999. if(cchWC <= 0)
  2000. return cchMB >= 0 ? cchMB : (strlen(pstrMB) + 1);
  2001. int cchMBMax = cchMB;
  2002. if(cchMB < 0) // If negative, use NULL termination
  2003. cchMBMax = tomForward; // of pstrMB
  2004. cchMBMax = min(cchMBMax, cchWC);
  2005. for(cch = 0; (cchMB < 0 ? *pstrMB : 1) && cch < cchMBMax; cch++)
  2006. {
  2007. *pstrWC++ = (unsigned char)*pstrMB++;
  2008. }
  2009. // NULL-terminate the WC string if the MB string was NULL-terminated,
  2010. // and if there is room in the WC buffer.
  2011. if(cchMB < 0 && cch < cchWC)
  2012. {
  2013. *pstrWC = 0;
  2014. cch++;
  2015. }
  2016. }
  2017. return cch;
  2018. }
  2019. /*
  2020. * CW32System::WCTMB (CodePage, dwFlags, pstrWC, cchWC, pstrMB, cchMB,
  2021. * pchDefault, pfUsedDef, pfNoCodePage, fTestCodePage)
  2022. *
  2023. * @mfunc
  2024. * Convert WideChar (WC) string pstrWC of length cchWC to MultiByte (MB)
  2025. * string pstrMB of length cchMB according to the flags dwFlags and code
  2026. * page CodePage. If CodePage = SYMBOL_CODEPAGE
  2027. * (usually for SYMBOL_CHARSET strings),
  2028. * convert each character in pstrWC to a byte, discarding the high byte.
  2029. * Else call the Win32 WideCharToMultiByte() function.
  2030. *
  2031. * @rdesc
  2032. * Count of bytes stored in target string pstrMB
  2033. */
  2034. int CW32System::WCTMB(
  2035. INT CodePage, //@parm Code page to use for conversion
  2036. DWORD dwFlags, //@parm Flags to guide conversion
  2037. LPCWSTR pstrWC, //@parm WideChar string to convert
  2038. int cchWC, //@parm Count for pstrWC or -1 to use NULL termination
  2039. LPSTR pstrMB, //@parm MultiByte string to receive converted chars
  2040. int cchMB, //@parm Count of chars (bytes) in pstrMB or 0
  2041. LPCSTR pchDefault, //@parm Default char to use if conversion fails
  2042. LPBOOL pfUsedDef, //@parm Out parm to receive whether default char used
  2043. LPBOOL pfNoCodePage, //@parm Out parm to receive whether code page is on system
  2044. BOOL fTestCodePage)//@parm Test CodePage could handle the pstrWC
  2045. {
  2046. int cch = -1; // No chars converted yet
  2047. BOOL fNoCodePage = FALSE; // Default code page is on OS
  2048. if(pfUsedDef) // Default that all chars can be
  2049. *pfUsedDef = FALSE; // converted
  2050. #ifndef WC_NO_BEST_FIT_CHARS
  2051. #define WC_NO_BEST_FIT_CHARS 0x400
  2052. #endif
  2053. if (_dwPlatformId == VER_PLATFORM_WIN32_NT &&
  2054. _dwMajorVersion > 4 && !dwFlags)
  2055. {
  2056. dwFlags = WC_NO_BEST_FIT_CHARS;
  2057. }
  2058. if(CodePage == CP_UTF8) // Convert to UTF8 since OS
  2059. { // doesn't (pre NT 5.0)
  2060. unsigned ch;
  2061. cch = 0; // No converted bytes yet
  2062. while(cchWC--)
  2063. {
  2064. ch = *pstrWC++; // Get Unicode char
  2065. if(ch <= 127) // It's ASCII
  2066. {
  2067. cch++;
  2068. if(cch < cchMB)
  2069. *pstrMB++ = ch; // One more converted byte
  2070. if(!ch) // Quit on NULL termination
  2071. break;
  2072. continue;
  2073. }
  2074. if(ch <= 0x7FF) // Need 2 bytes of form:
  2075. { // 110bbbbb 10bbbbbb
  2076. cch += 2;
  2077. if(cch < cchMB) // Store lead byte
  2078. *pstrMB++ = 0xC0 + (ch >> 6);
  2079. }
  2080. else if(IN_RANGE(UTF16_LEAD, ch, 0xDBFF))
  2081. { // Unicode surrogate pair
  2082. cch += 4; // Need 4 bytes of form:
  2083. if(cch < cchMB) // 11110bbb 10bbbbbb 10bbbbbb
  2084. { // 10bbbbbb
  2085. AssertSz(IN_RANGE(UTF16_TRAIL, *pstrWC, 0xDFFF),
  2086. "CW32System::WCTMB: illegal surrogate pair");
  2087. cchWC--;
  2088. ch = ((ch & 0x3FF) << 10) + (*pstrWC++ & 0x3FF) + 0x10000;
  2089. *pstrMB++ = 0xF0 + (ch >> 18);
  2090. *pstrMB++ = 0x80 + (ch >> 12 & 0x3F);
  2091. *pstrMB++ = 0x80 + (ch >> 6 & 0x3F);
  2092. }
  2093. }
  2094. else // Need 3 bytes of form:
  2095. { // 1110bbbb 10bbbbbb
  2096. cch += 3; // 10bbbbbb
  2097. if(cch < cchMB) // Store lead byte followed by
  2098. { // first trail byte
  2099. *pstrMB++ = 0xE0 + (ch >> 12);
  2100. *pstrMB++ = 0x80 + (ch >> 6 & 0x3F);
  2101. }
  2102. }
  2103. if(cch < cchMB) // Store final UTF-8 byte
  2104. *pstrMB++ = 0x80 + (ch & 0x3F);
  2105. }
  2106. }
  2107. else if(CodePage != CP_SYMBOL)
  2108. {
  2109. fNoCodePage = TRUE; // Default codepage not on OS
  2110. if(CodePage >= 0) // Might be...
  2111. {
  2112. cch = WideCharToMultiByte(CodePage, dwFlags,
  2113. pstrWC, cchWC, pstrMB, cchMB, pchDefault, pfUsedDef);
  2114. if(cch > 0)
  2115. fNoCodePage = FALSE; // Found codepage on system
  2116. }
  2117. }
  2118. if(pfNoCodePage)
  2119. *pfNoCodePage = fNoCodePage;
  2120. // Early exit if we are just testing for CodePage
  2121. if (fTestCodePage)
  2122. return cch;
  2123. // SYMBOL_CHARSET, fIsDBCS or conversion failed: low bytes of words ->
  2124. // bytes
  2125. if(cch <= 0)
  2126. {
  2127. // Return multibyte count for full conversion. cchWC is correct for
  2128. // single-byte charsets like the 125x's
  2129. if(cchMB <= 0)
  2130. {
  2131. return cchWC >= 0 ? cchWC : wcslen(pstrWC);
  2132. }
  2133. char chDefault = 0;
  2134. BOOL fUseDefaultChar = (pfUsedDef || pchDefault) && CodePage != CP_SYMBOL;
  2135. if(fUseDefaultChar)
  2136. {
  2137. // determine a default char for our home-grown conversion
  2138. if(pchDefault)
  2139. {
  2140. chDefault = *pchDefault;
  2141. }
  2142. else
  2143. {
  2144. static char chSysDef = 0;
  2145. static BOOL fGotSysDef = FALSE;
  2146. // 0x2022 is a math symbol with no conversion to ANSI
  2147. const WCHAR szCantConvert[] = { 0x2022 };
  2148. BOOL fUsedDef;
  2149. if(!fGotSysDef)
  2150. {
  2151. fGotSysDef = TRUE;
  2152. if(!(WideCharToMultiByte
  2153. (CP_ACP, 0, szCantConvert, 1, &chSysDef, 1, NULL,
  2154. &fUsedDef) == 1 && fUsedDef))
  2155. {
  2156. AssertSz(0, "WCTMB(): Unable to determine what the "
  2157. "system uses as its default replacement "
  2158. "character.");
  2159. chSysDef = '?';
  2160. }
  2161. }
  2162. chDefault = chSysDef;
  2163. }
  2164. }
  2165. int cchWCMax = cchWC;
  2166. // If negative, use NULL termination of pstrMB
  2167. if(cchWC < 0)
  2168. {
  2169. cchWCMax = tomForward;
  2170. }
  2171. cchWCMax = min(cchWCMax, cchMB);
  2172. for(cch = 0; (cchWC < 0 ? *pstrWC : 1) && cch < cchWCMax; cch++)
  2173. {
  2174. // TODO(BradO): Should this be 0x7F in some conversion cases?
  2175. if(fUseDefaultChar && *pstrWC > 0xFF)
  2176. {
  2177. if(pfUsedDef)
  2178. {
  2179. *pfUsedDef = TRUE;
  2180. }
  2181. *pstrMB = chDefault;
  2182. }
  2183. else
  2184. {
  2185. *pstrMB = (BYTE)*pstrWC;
  2186. }
  2187. pstrMB++;
  2188. pstrWC++;
  2189. }
  2190. if(cchWC < 0 && cch < cchMB)
  2191. {
  2192. *pstrMB = 0;
  2193. cch++;
  2194. }
  2195. }
  2196. return cch;
  2197. }
  2198. /*
  2199. * CW32System::VerifyFEString(cpg, pstrWC, cchWC, fTestInputCpg)
  2200. *
  2201. * @mfunc
  2202. * Verify if the input cpg can handle the pstrWC.
  2203. * If not, select another FE cpg.
  2204. *
  2205. * @rdesc
  2206. * New CodePage for the pstrWC
  2207. */
  2208. #define NUMBER_OF_CHARS 64
  2209. int CW32System::VerifyFEString(
  2210. INT cpg, //@parm cpg to format the pstrWC
  2211. LPCWSTR pstrWC, //@parm WideChar string to test
  2212. int cchWC, //@parm Count for pstrWC
  2213. BOOL fTestInputCpg) //@parm test the input cpg only
  2214. {
  2215. if (cchWC <=0)
  2216. return cpg;
  2217. int cpgNew = cpg;
  2218. BOOL fUsedDef;
  2219. int cchMB = cchWC * sizeof(WCHAR);
  2220. CTempCharBuf tcb;
  2221. char *pstrMB = tcb.GetBuf(cchMB);
  2222. CTempWcharBuf twcb;
  2223. WCHAR *pstrWchar = twcb.GetBuf(cchWC);
  2224. static int aiCpg[4] =
  2225. { CP_JAPAN, CP_KOREAN, CP_CHINESE_TRAD, CP_CHINESE_SIM };
  2226. if (pstrMB)
  2227. {
  2228. int cchConverted = WCTMB(cpg, 0, pstrWC, cchWC, pstrMB, cchMB, NULL,
  2229. &fUsedDef, NULL, TRUE);
  2230. if (cchConverted > 0 && !fUsedDef && IsFEFontInSystem(cpg))
  2231. {
  2232. cchConverted = MBTWC(cpg, 0, pstrMB, cchConverted, pstrWchar, cchWC, NULL);
  2233. if (cchConverted == cchWC)
  2234. goto Exit; // Found it
  2235. }
  2236. if (fTestInputCpg) // Only need to test the input cpg
  2237. cpgNew = -1; // Indicate cpg doesn't support the string
  2238. else
  2239. {
  2240. // If no conversion or if the default character is used or
  2241. // no such FE font in system,
  2242. // it means that this cpg may not be the right choice.
  2243. // Let's try other FE cpg.
  2244. for (int i=0; i < 4; i++)
  2245. {
  2246. if (cpg != aiCpg[i])
  2247. {
  2248. cchConverted = WCTMB(aiCpg[i], 0, pstrWC, cchWC, pstrMB, cchMB, NULL,
  2249. &fUsedDef, NULL, TRUE);
  2250. if (cchConverted > 0 && !fUsedDef && IsFEFontInSystem(aiCpg[i]))
  2251. {
  2252. cchConverted = MBTWC(aiCpg[i], 0, pstrMB, cchConverted, pstrWchar, cchWC, NULL);
  2253. if (cchConverted == cchWC)
  2254. {
  2255. cpgNew = aiCpg[i]; // Found it
  2256. break;
  2257. }
  2258. }
  2259. }
  2260. }
  2261. }
  2262. }
  2263. Exit:
  2264. return cpgNew;
  2265. }
  2266. int __cdecl CW32System::sprintf(char * buff, char *fmt, ...)
  2267. {
  2268. va_list marker;
  2269. va_start(marker, fmt);
  2270. int cb = W32->WvsprintfA(0x07FFFFFFF, buff, fmt, marker);
  2271. va_end(marker);
  2272. return cb;
  2273. }
  2274. /*
  2275. * CW32System::GetSizeCursor(void)
  2276. *
  2277. * @mfunc
  2278. * Get the sizing cursor (double arrow) specified by
  2279. * the resource id. If the cursors are not loaded
  2280. * load them and cache them.
  2281. * parameters:
  2282. * idcur - cursor resource id.
  2283. *
  2284. * @rdesc
  2285. * Handle to cursor or null if failure. Returns NULL if
  2286. * idcur is null.
  2287. */
  2288. HCURSOR CW32System::GetSizeCursor(
  2289. LPTSTR idcur)
  2290. {
  2291. if(!idcur )
  2292. return NULL;
  2293. //If any cursor isn't loaded, try loading it.
  2294. if(!_hcurSizeNS)
  2295. _hcurSizeNS = LoadCursor(NULL, IDC_SIZENS);
  2296. if(!_hcurSizeWE)
  2297. _hcurSizeWE = LoadCursor(NULL, IDC_SIZEWE);
  2298. if(!_hcurSizeNWSE)
  2299. _hcurSizeNWSE = LoadCursor(NULL, IDC_SIZENWSE);
  2300. if(!_hcurSizeNESW)
  2301. _hcurSizeNESW = LoadCursor(NULL, IDC_SIZENESW);
  2302. //Return cursor corresponding to id passed in.
  2303. if(idcur == IDC_SIZENS && _hcurSizeNS)
  2304. return _hcurSizeNS;
  2305. if(idcur == IDC_SIZEWE && _hcurSizeWE)
  2306. return _hcurSizeWE;
  2307. if(idcur == IDC_SIZENWSE && _hcurSizeNWSE)
  2308. return _hcurSizeNWSE;
  2309. if(idcur == IDC_SIZENESW && _hcurSizeNESW)
  2310. return _hcurSizeNESW;
  2311. AssertSz(FALSE, "Failure loading sizing cursor.");
  2312. return NULL;
  2313. }
  2314. /*
  2315. * Mirroring API (only in BiDi Win98 and NT5 upward)
  2316. *
  2317. * @mfunc Get/Set DC mirroring effect
  2318. *
  2319. */
  2320. DWORD WINAPI GetLayoutStub(HDC hdc)
  2321. {
  2322. return 0;
  2323. }
  2324. DWORD WINAPI SetLayoutStub(HDC hdc, DWORD dwLayout)
  2325. {
  2326. return 0;
  2327. }
  2328. DWORD WINAPI GetLayoutInit(HDC hdc)
  2329. {
  2330. #ifndef NOCOMPLEXSCRIPTS
  2331. CLock lock;
  2332. HINSTANCE hMod = ::GetModuleHandleA("GDI32.DLL");
  2333. Assert(hMod);
  2334. W32->_pfnGetLayout = (PFN_GETLAYOUT)GetProcAddress(hMod, "GetLayout");
  2335. if (!W32->_pfnGetLayout)
  2336. W32->_pfnGetLayout = &GetLayoutStub;
  2337. return W32->_pfnGetLayout(hdc);
  2338. #else
  2339. return 0;
  2340. #endif
  2341. }
  2342. DWORD WINAPI SetLayoutInit(HDC hdc, DWORD dwLayout)
  2343. {
  2344. #ifndef NOCOMPLEXSCRIPTS
  2345. CLock lock;
  2346. HINSTANCE hMod = ::GetModuleHandleA("GDI32.DLL");
  2347. Assert(hMod);
  2348. W32->_pfnSetLayout = (PFN_SETLAYOUT)GetProcAddress(hMod, "SetLayout");
  2349. if (!W32->_pfnSetLayout)
  2350. W32->_pfnSetLayout = &SetLayoutStub;
  2351. return W32->_pfnSetLayout(hdc, dwLayout);
  2352. #else
  2353. return 0;
  2354. #endif
  2355. }
  2356. PFN_GETLAYOUT CW32System::_pfnGetLayout = &GetLayoutInit;
  2357. PFN_SETLAYOUT CW32System::_pfnSetLayout = &SetLayoutInit;
  2358. ICustomTextOut *g_pcto;
  2359. STDAPI SetCustomTextOutHandlerEx(ICustomTextOut **ppcto, DWORD dwFlags)
  2360. {
  2361. g_pcto = *ppcto;
  2362. return S_OK;
  2363. }