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.

2928 lines
82 KiB

  1. /*++
  2. Copyright (c) 1985 - 1999, Microsoft Corporation
  3. Module Name:
  4. dbcs.c
  5. Abstract:
  6. Author:
  7. KazuM Mar.05.1992
  8. Revision History:
  9. --*/
  10. #include "precomp.h"
  11. #pragma hdrstop
  12. #pragma alloc_text(FE_TEXT, CheckBisectStringA)
  13. #pragma alloc_text(FE_TEXT, BisectWrite)
  14. #pragma alloc_text(FE_TEXT, BisectClipbrd)
  15. #pragma alloc_text(FE_TEXT, BisectWriteAttr)
  16. #pragma alloc_text(FE_TEXT, IsDBCSLeadByteConsole)
  17. #pragma alloc_text(FE_TEXT, TextOutEverything)
  18. #pragma alloc_text(FE_TEXT, TextOutCommonLVB)
  19. #ifdef i386
  20. #pragma alloc_text(FE_TEXT, RealUnicodeToNEC_OS2_Unicode)
  21. #pragma alloc_text(FE_TEXT, InitializeNEC_OS2_CP)
  22. #endif
  23. #pragma alloc_text(FE_TEXT, ProcessCreateConsoleIME)
  24. #pragma alloc_text(FE_TEXT, InitConsoleIMEStuff)
  25. #pragma alloc_text(FE_TEXT, WaitConsoleIMEStuff)
  26. #pragma alloc_text(FE_TEXT, ConSrvRegisterConsoleIME)
  27. #pragma alloc_text(FE_TEXT, RemoveConsoleIME)
  28. #pragma alloc_text(FE_TEXT, ConsoleImeMessagePump)
  29. #pragma alloc_text(FE_TEXT, RegisterKeisenOfTTFont)
  30. #pragma alloc_text(FE_TEXT, ImmConversionToConsole)
  31. #pragma alloc_text(FE_TEXT, ImmConversionFromConsole)
  32. #pragma alloc_text(FE_TEXT, TranslateUnicodeToOem)
  33. #if defined(FE_SB)
  34. SINGLE_LIST_ENTRY gTTFontList; // This list contain TTFONTLIST data.
  35. #if defined(i386)
  36. ULONG gdwMachineId;
  37. #endif
  38. LPTHREAD_START_ROUTINE ConsoleIMERoutine; // client side console IME routine
  39. CRITICAL_SECTION ConIMEInitWindowsLock;
  40. #if defined(i386)
  41. /*
  42. * NEC PC-98 OS/2 OEM character set
  43. * When FormatID is 0 or 80, Convert SBCS (00h-1Fh) font.
  44. */
  45. PCPTABLEINFO pGlyph_NEC_OS2_CP;
  46. PUSHORT pGlyph_NEC_OS2_Table;
  47. #endif // i386
  48. #if defined(FE_IME)
  49. #if defined(i386)
  50. NTSTATUS
  51. ImeWmFullScreen(
  52. IN BOOL Foreground,
  53. IN PCONSOLE_INFORMATION Console,
  54. IN PSCREEN_INFORMATION ScreenInfo
  55. )
  56. {
  57. NTSTATUS Status = STATUS_SUCCESS;
  58. if(Foreground) {
  59. ULONG ModeIndex;
  60. PCONVERSIONAREA_INFORMATION ConvAreaInfo;
  61. if (!NT_SUCCESS(ConsoleImeMessagePump(Console,
  62. CONIME_SETFOCUS,
  63. (WPARAM)Console->ConsoleHandle,
  64. (LPARAM)Console->hklActive
  65. ))) {
  66. return STATUS_INVALID_HANDLE;
  67. }
  68. if (ConvAreaInfo = Console->ConsoleIme.ConvAreaRoot) {
  69. if (!(ScreenInfo->Flags & CONSOLE_GRAPHICS_BUFFER)) {
  70. ModeIndex = ScreenInfo->BufferInfo.TextInfo.ModeIndex;
  71. } else if (!(Console->CurrentScreenBuffer->Flags & CONSOLE_GRAPHICS_BUFFER)) {
  72. ModeIndex = Console->CurrentScreenBuffer->BufferInfo.TextInfo.ModeIndex;
  73. } else {
  74. ModeIndex = 0;
  75. }
  76. do {
  77. #ifdef FE_SB
  78. // Check code for must CONSOLE_TEXTMODE_BUFFER !!
  79. if (!(ConvAreaInfo->ScreenBuffer->Flags & CONSOLE_GRAPHICS_BUFFER)) {
  80. ConvAreaInfo->ScreenBuffer->BufferInfo.TextInfo.ModeIndex = ModeIndex;
  81. } else {
  82. UserAssert(FALSE);
  83. }
  84. #else
  85. ConvAreaInfo->ScreenBuffer->BufferInfo.TextInfo.ModeIndex = ModeIndex;
  86. #endif
  87. } while (ConvAreaInfo = ConvAreaInfo->ConvAreaNext);
  88. }
  89. } else {
  90. if (!NT_SUCCESS(ConsoleImeMessagePump(Console,
  91. CONIME_KILLFOCUS,
  92. (WPARAM)Console->ConsoleHandle,
  93. (LPARAM)Console->hklActive))) {
  94. return STATUS_INVALID_HANDLE;
  95. }
  96. }
  97. return Status;
  98. }
  99. #endif // i386
  100. NTSTATUS
  101. GetImeKeyState(
  102. IN PCONSOLE_INFORMATION Console,
  103. IN PDWORD pdwConversion
  104. )
  105. /*++
  106. Routine Description:
  107. This routine get IME mode for KEY_EVENT_RECORD.
  108. Arguments:
  109. ConsoleInfo - Pointer to console information structure.
  110. Return Value:
  111. --*/
  112. {
  113. DWORD dwDummy;
  114. /*
  115. * If pdwConversion is NULL, the caller doesn't want the result -- but
  116. * for code efficiency, let it point to the dummy dword variable, so
  117. * that we don't have to care from here.
  118. */
  119. if (pdwConversion == NULL) {
  120. pdwConversion = &dwDummy;
  121. }
  122. if (Console->InputBuffer.ImeMode.Disable) {
  123. *pdwConversion = 0;
  124. } else {
  125. PINPUT_THREAD_INFO InputThreadInfo;
  126. InputThreadInfo = TlsGetValue(InputThreadTlsIndex);
  127. if (InputThreadInfo != NULL) {
  128. LRESULT lResult;
  129. /*
  130. * We're being called on the Console Input Thread, so we're
  131. * clear to pump messages.
  132. */
  133. if (!NT_SUCCESS(ConsoleImeMessagePumpWorker(Console,
  134. CONIME_GET_NLSMODE,
  135. (WPARAM)Console->ConsoleHandle,
  136. (LPARAM)0,
  137. &lResult))) {
  138. *pdwConversion = IME_CMODE_DISABLE;
  139. return STATUS_INVALID_HANDLE;
  140. }
  141. *pdwConversion = (DWORD)lResult;
  142. if (Console->InputBuffer.ImeMode.ReadyConversion == FALSE) {
  143. Console->InputBuffer.ImeMode.ReadyConversion = TRUE;
  144. }
  145. } else {
  146. /*
  147. * We're being called from an LPC worker thread, so we cannot
  148. * pump messages.
  149. */
  150. if (Console->InputBuffer.ImeMode.ReadyConversion == FALSE) {
  151. *pdwConversion = 0;
  152. return STATUS_SUCCESS;
  153. }
  154. *pdwConversion = Console->InputBuffer.ImeMode.Conversion;
  155. }
  156. if (*pdwConversion & IME_CMODE_OPEN) {
  157. Console->InputBuffer.ImeMode.Open = TRUE;
  158. } else {
  159. Console->InputBuffer.ImeMode.Open = FALSE;
  160. }
  161. if (*pdwConversion & IME_CMODE_DISABLE) {
  162. Console->InputBuffer.ImeMode.Disable = TRUE;
  163. } else {
  164. Console->InputBuffer.ImeMode.Disable = FALSE;
  165. }
  166. Console->InputBuffer.ImeMode.Conversion = *pdwConversion;
  167. }
  168. return STATUS_SUCCESS;
  169. }
  170. NTSTATUS
  171. SetImeKeyState(
  172. IN PCONSOLE_INFORMATION Console,
  173. IN DWORD fdwConversion
  174. )
  175. /*++
  176. Routine Description:
  177. This routine get IME mode for KEY_EVENT_RECORD.
  178. Arguments:
  179. Console - Pointer to console information structure.
  180. fdwConversion - IME conversion status.
  181. Return Value:
  182. --*/
  183. {
  184. PCONVERSIONAREA_INFORMATION ConvAreaInfo;
  185. if ( (fdwConversion & IME_CMODE_DISABLE) && (! Console->InputBuffer.ImeMode.Disable) ) {
  186. Console->InputBuffer.ImeMode.Disable = TRUE;
  187. if ( Console->InputBuffer.ImeMode.Open ) {
  188. ConvAreaInfo = Console->ConsoleIme.ConvAreaMode;
  189. if (ConvAreaInfo)
  190. ConvAreaInfo->ConversionAreaMode |= CA_HIDDEN;
  191. ConvAreaInfo = Console->ConsoleIme.ConvAreaSystem;
  192. if (ConvAreaInfo)
  193. ConvAreaInfo->ConversionAreaMode |= CA_HIDDEN;
  194. if (Console->InputBuffer.ImeMode.Open && CONSOLE_IS_DBCS_OUTPUTCP(Console))
  195. ConsoleImePaint(Console, Console->ConsoleIme.ConvAreaRoot);
  196. }
  197. }
  198. else if ( (! (fdwConversion & IME_CMODE_DISABLE)) && Console->InputBuffer.ImeMode.Disable) {
  199. Console->InputBuffer.ImeMode.Disable = FALSE;
  200. if ( fdwConversion & IME_CMODE_OPEN ) {
  201. ConvAreaInfo = Console->ConsoleIme.ConvAreaMode;
  202. if (ConvAreaInfo)
  203. ConvAreaInfo->ConversionAreaMode &= ~CA_HIDDEN;
  204. ConvAreaInfo = Console->ConsoleIme.ConvAreaSystem;
  205. if (ConvAreaInfo)
  206. ConvAreaInfo->ConversionAreaMode &= ~CA_HIDDEN;
  207. if (Console->InputBuffer.ImeMode.Open && CONSOLE_IS_DBCS_OUTPUTCP(Console))
  208. ConsoleImePaint(Console, Console->ConsoleIme.ConvAreaRoot);
  209. }
  210. }
  211. else if ( (fdwConversion & IME_CMODE_DISABLE) && (Console->InputBuffer.ImeMode.Disable) ) {
  212. return STATUS_SUCCESS;
  213. }
  214. if ( (fdwConversion & IME_CMODE_OPEN) && (! Console->InputBuffer.ImeMode.Open)) {
  215. Console->InputBuffer.ImeMode.Open = TRUE;
  216. }
  217. else if ( (! (fdwConversion & IME_CMODE_OPEN)) && Console->InputBuffer.ImeMode.Open) {
  218. Console->InputBuffer.ImeMode.Open = FALSE;
  219. }
  220. Console->InputBuffer.ImeMode.Conversion = fdwConversion;
  221. if (Console->InputBuffer.ImeMode.ReadyConversion == FALSE)
  222. Console->InputBuffer.ImeMode.ReadyConversion = TRUE;
  223. if (!NT_SUCCESS(ConsoleImeMessagePump(Console,
  224. CONIME_SET_NLSMODE,
  225. (WPARAM)Console->ConsoleHandle,
  226. (LPARAM)fdwConversion
  227. ))) {
  228. return STATUS_INVALID_HANDLE;
  229. }
  230. return STATUS_SUCCESS;
  231. }
  232. NTSTATUS
  233. SetImeCodePage(
  234. IN PCONSOLE_INFORMATION Console
  235. )
  236. {
  237. DWORD CodePage = Console->OutputCP;
  238. DWORD fdwConversion;
  239. if (!CONSOLE_IS_DBCS_CP(Console))
  240. {
  241. if (!NT_SUCCESS(GetImeKeyState(Console, &fdwConversion))) {
  242. return STATUS_INVALID_HANDLE;
  243. }
  244. fdwConversion |= IME_CMODE_DISABLE;
  245. }
  246. else {
  247. fdwConversion = Console->InputBuffer.ImeMode.Conversion & ~IME_CMODE_DISABLE;
  248. }
  249. if (!NT_SUCCESS(SetImeKeyState(Console, fdwConversion))) {
  250. return STATUS_INVALID_HANDLE;
  251. }
  252. if (CONSOLE_IS_IME_ENABLED()) {
  253. if (!NT_SUCCESS(ConsoleImeMessagePump(Console,
  254. CONIME_NOTIFY_CODEPAGE,
  255. (WPARAM)Console->ConsoleHandle,
  256. (LPARAM)MAKELPARAM(FALSE, CodePage)
  257. ))) {
  258. return STATUS_INVALID_HANDLE;
  259. }
  260. }
  261. return STATUS_SUCCESS;
  262. }
  263. NTSTATUS
  264. SetImeOutputCodePage(
  265. IN PCONSOLE_INFORMATION Console,
  266. IN PSCREEN_INFORMATION ScreenInfo,
  267. IN DWORD PrevCodePage
  268. )
  269. {
  270. DWORD CodePage = Console->OutputCP;
  271. // Output code page
  272. if ((ScreenInfo->Flags & CONSOLE_TEXTMODE_BUFFER) &&
  273. (IsAvailableFarEastCodePage(CodePage) || IsAvailableFarEastCodePage(PrevCodePage)))
  274. {
  275. ConvertToCodePage(Console, PrevCodePage);
  276. AdjustFont(Console, CodePage);
  277. }
  278. // load special ROM font, if necessary
  279. #ifdef i386
  280. if ( (Console->FullScreenFlags & CONSOLE_FULLSCREEN_HARDWARE) &&
  281. !(ScreenInfo->Flags & CONSOLE_GRAPHICS_BUFFER))
  282. {
  283. SetROMFontCodePage(CodePage,
  284. ScreenInfo->BufferInfo.TextInfo.ModeIndex);
  285. SetCursorInformationHW(ScreenInfo,
  286. ScreenInfo->BufferInfo.TextInfo.CursorSize,
  287. ScreenInfo->BufferInfo.TextInfo.CursorVisible);
  288. WriteRegionToScreenHW(ScreenInfo,
  289. &ScreenInfo->Window);
  290. }
  291. #endif
  292. if (CONSOLE_IS_IME_ENABLED()) {
  293. if (!NT_SUCCESS(ConsoleImeMessagePump(Console,
  294. CONIME_NOTIFY_CODEPAGE,
  295. (WPARAM)Console->ConsoleHandle,
  296. (LPARAM)MAKELPARAM(TRUE, CodePage)
  297. ))) {
  298. return STATUS_INVALID_HANDLE;
  299. }
  300. }
  301. return STATUS_SUCCESS;
  302. }
  303. #endif // FE_IME
  304. VOID
  305. SetLineChar(
  306. IN PSCREEN_INFORMATION ScreenInfo
  307. )
  308. /*++
  309. Routine Description:
  310. This routine setup of line character code.
  311. Arguments:
  312. ScreenInfo - Pointer to screen information structure.
  313. Return Value:
  314. none.
  315. --*/
  316. {
  317. if (CONSOLE_IS_DBCS_OUTPUTCP(ScreenInfo->Console))
  318. {
  319. if (OEMCP == JAPAN_CP || OEMCP == KOREAN_CP)
  320. {
  321. /*
  322. * This is Japanese/Korean case,
  323. * These characters maps grid of half width.
  324. * so, same as U+2500.
  325. */
  326. ScreenInfo->LineChar[UPPER_LEFT_CORNER] = 0x0001;
  327. ScreenInfo->LineChar[UPPER_RIGHT_CORNER] = 0x0002;
  328. ScreenInfo->LineChar[HORIZONTAL_LINE] = 0x0006;
  329. ScreenInfo->LineChar[VERTICAL_LINE] = 0x0005;
  330. ScreenInfo->LineChar[BOTTOM_LEFT_CORNER] = 0x0003;
  331. ScreenInfo->LineChar[BOTTOM_RIGHT_CORNER] = 0x0004;
  332. }
  333. else
  334. {
  335. /*
  336. * This is FE case,
  337. * FE don't uses U+2500 because these grid characters
  338. * maps to full width.
  339. */
  340. ScreenInfo->LineChar[UPPER_LEFT_CORNER] = L'+';
  341. ScreenInfo->LineChar[UPPER_RIGHT_CORNER] = L'+';
  342. ScreenInfo->LineChar[HORIZONTAL_LINE] = L'-';
  343. ScreenInfo->LineChar[VERTICAL_LINE] = L'|';
  344. ScreenInfo->LineChar[BOTTOM_LEFT_CORNER] = L'+';
  345. ScreenInfo->LineChar[BOTTOM_RIGHT_CORNER] = L'+';
  346. }
  347. }
  348. else {
  349. ScreenInfo->LineChar[UPPER_LEFT_CORNER] = 0x250c;
  350. ScreenInfo->LineChar[UPPER_RIGHT_CORNER] = 0x2510;
  351. ScreenInfo->LineChar[HORIZONTAL_LINE] = 0x2500;
  352. ScreenInfo->LineChar[VERTICAL_LINE] = 0x2502;
  353. ScreenInfo->LineChar[BOTTOM_LEFT_CORNER] = 0x2514;
  354. ScreenInfo->LineChar[BOTTOM_RIGHT_CORNER] = 0x2518;
  355. }
  356. }
  357. BOOL
  358. CheckBisectStringA(
  359. IN DWORD CodePage,
  360. IN PCHAR Buffer,
  361. IN DWORD NumBytes,
  362. IN LPCPINFO lpCPInfo
  363. )
  364. /*++
  365. Routine Description:
  366. This routine check bisected on Ascii string end.
  367. Arguments:
  368. CodePage - Value of code page.
  369. Buffer - Pointer to Ascii string buffer.
  370. NumBytes - Number of Ascii string.
  371. Return Value:
  372. TRUE - Bisected character.
  373. FALSE - Correctly.
  374. --*/
  375. {
  376. UNREFERENCED_PARAMETER(CodePage);
  377. while(NumBytes) {
  378. if (IsDBCSLeadByteConsole(*Buffer,lpCPInfo)) {
  379. if (NumBytes <= 1)
  380. return TRUE;
  381. else {
  382. Buffer += 2;
  383. NumBytes -= 2;
  384. }
  385. }
  386. else {
  387. Buffer++;
  388. NumBytes--;
  389. }
  390. }
  391. return FALSE;
  392. }
  393. VOID
  394. BisectWrite(
  395. IN SHORT StringLength,
  396. IN COORD TargetPoint,
  397. IN PSCREEN_INFORMATION ScreenInfo
  398. )
  399. /*++
  400. Routine Description:
  401. This routine write buffer with bisect.
  402. Arguments:
  403. Return Value:
  404. --*/
  405. {
  406. SHORT RowIndex;
  407. PROW Row;
  408. PROW RowPrev;
  409. PROW RowNext;
  410. #if DBG && defined(DBG_KATTR)
  411. BeginKAttrCheck(ScreenInfo);
  412. #endif
  413. #ifdef FE_SB
  414. //
  415. // This buffer must be in textmode.
  416. //
  417. UserAssert(!(ScreenInfo->Flags & CONSOLE_GRAPHICS_BUFFER));
  418. #endif
  419. RowIndex = (ScreenInfo->BufferInfo.TextInfo.FirstRow+TargetPoint.Y) % ScreenInfo->ScreenBufferSize.Y;
  420. Row = &ScreenInfo->BufferInfo.TextInfo.Rows[RowIndex];
  421. if (RowIndex > 0) {
  422. RowPrev = &ScreenInfo->BufferInfo.TextInfo.Rows[RowIndex-1];
  423. } else {
  424. RowPrev = &ScreenInfo->BufferInfo.TextInfo.Rows[ScreenInfo->ScreenBufferSize.Y-1];
  425. }
  426. if (RowIndex+1 < ScreenInfo->ScreenBufferSize.Y) {
  427. RowNext = &ScreenInfo->BufferInfo.TextInfo.Rows[RowIndex+1];
  428. } else {
  429. RowNext = &ScreenInfo->BufferInfo.TextInfo.Rows[0];
  430. }
  431. //
  432. // Check start position of strings
  433. //
  434. if (Row->CharRow.KAttrs[TargetPoint.X] & ATTR_TRAILING_BYTE)
  435. {
  436. if (TargetPoint.X == 0) {
  437. RowPrev->CharRow.Chars[ScreenInfo->ScreenBufferSize.X-1] = UNICODE_SPACE;
  438. RowPrev->CharRow.KAttrs[ScreenInfo->ScreenBufferSize.X-1] = 0;
  439. ScreenInfo->BisectFlag |= BISECT_TOP;
  440. }
  441. else {
  442. Row->CharRow.Chars[TargetPoint.X-1] = UNICODE_SPACE;
  443. Row->CharRow.KAttrs[TargetPoint.X-1] = 0;
  444. ScreenInfo->BisectFlag |= BISECT_LEFT;
  445. }
  446. }
  447. //
  448. // Check end position of strings
  449. //
  450. if (TargetPoint.X+StringLength < ScreenInfo->ScreenBufferSize.X) {
  451. if (Row->CharRow.KAttrs[TargetPoint.X+StringLength] & ATTR_TRAILING_BYTE)
  452. {
  453. Row->CharRow.Chars[TargetPoint.X+StringLength] = UNICODE_SPACE;
  454. Row->CharRow.KAttrs[TargetPoint.X+StringLength] = 0;
  455. ScreenInfo->BisectFlag |= BISECT_RIGHT;
  456. }
  457. }
  458. else if (TargetPoint.Y+1 < ScreenInfo->ScreenBufferSize.Y) {
  459. if (RowNext->CharRow.KAttrs[0] & ATTR_TRAILING_BYTE)
  460. {
  461. RowNext->CharRow.Chars[0] = UNICODE_SPACE;
  462. RowNext->CharRow.KAttrs[0] = 0;
  463. ScreenInfo->BisectFlag |= BISECT_BOTTOM;
  464. }
  465. }
  466. }
  467. VOID
  468. BisectClipbrd(
  469. IN SHORT StringLength,
  470. IN COORD TargetPoint,
  471. IN PSCREEN_INFORMATION ScreenInfo,
  472. OUT PSMALL_RECT SmallRect
  473. )
  474. /*++
  475. Routine Description:
  476. This routine check bisect for clipboard process.
  477. Arguments:
  478. Return Value:
  479. --*/
  480. {
  481. SHORT RowIndex;
  482. PROW Row;
  483. PROW RowNext;
  484. #if DBG && defined(DBG_KATTR)
  485. BeginKAttrCheck(ScreenInfo);
  486. #endif
  487. #ifdef FE_SB
  488. //
  489. // This buffer must be in textmode.
  490. //
  491. UserAssert(!(ScreenInfo->Flags & CONSOLE_GRAPHICS_BUFFER));
  492. #endif
  493. RowIndex = (ScreenInfo->BufferInfo.TextInfo.FirstRow+TargetPoint.Y) % ScreenInfo->ScreenBufferSize.Y;
  494. Row = &ScreenInfo->BufferInfo.TextInfo.Rows[RowIndex];
  495. if (RowIndex+1 < ScreenInfo->ScreenBufferSize.Y) {
  496. RowNext = &ScreenInfo->BufferInfo.TextInfo.Rows[RowIndex+1];
  497. } else {
  498. RowNext = &ScreenInfo->BufferInfo.TextInfo.Rows[0];
  499. }
  500. //
  501. // Check start position of strings
  502. //
  503. UserAssert(CONSOLE_IS_DBCS_OUTPUTCP(ScreenInfo->Console));
  504. if (Row->CharRow.KAttrs[TargetPoint.X] & ATTR_TRAILING_BYTE) {
  505. if (TargetPoint.X == 0) {
  506. SmallRect->Left++;
  507. } else {
  508. SmallRect->Left--;
  509. }
  510. }
  511. //
  512. // Check end position of strings
  513. //
  514. if (TargetPoint.X+StringLength < ScreenInfo->ScreenBufferSize.X) {
  515. if (Row->CharRow.KAttrs[TargetPoint.X+StringLength] & ATTR_TRAILING_BYTE)
  516. {
  517. SmallRect->Right++;
  518. }
  519. }
  520. else if (TargetPoint.Y+1 < ScreenInfo->ScreenBufferSize.Y) {
  521. if (RowNext->CharRow.KAttrs[0] & ATTR_TRAILING_BYTE)
  522. {
  523. SmallRect->Right--;
  524. }
  525. }
  526. }
  527. VOID
  528. BisectWriteAttr(
  529. IN SHORT StringLength,
  530. IN COORD TargetPoint,
  531. IN PSCREEN_INFORMATION ScreenInfo
  532. )
  533. /*++
  534. Routine Description:
  535. This routine write buffer with bisect.
  536. Arguments:
  537. Return Value:
  538. --*/
  539. {
  540. SHORT RowIndex;
  541. PROW Row;
  542. PROW RowNext;
  543. #if DBG && defined(DBG_KATTR)
  544. BeginKAttrCheck(ScreenInfo);
  545. #endif
  546. #ifdef FE_SB
  547. //
  548. // This buffer must be in textmode.
  549. //
  550. UserAssert(!(ScreenInfo->Flags & CONSOLE_GRAPHICS_BUFFER));
  551. #endif
  552. RowIndex = (ScreenInfo->BufferInfo.TextInfo.FirstRow+TargetPoint.Y) % ScreenInfo->ScreenBufferSize.Y;
  553. Row = &ScreenInfo->BufferInfo.TextInfo.Rows[RowIndex];
  554. if (RowIndex+1 < ScreenInfo->ScreenBufferSize.Y) {
  555. RowNext = &ScreenInfo->BufferInfo.TextInfo.Rows[RowIndex+1];
  556. } else {
  557. RowNext = &ScreenInfo->BufferInfo.TextInfo.Rows[0];
  558. }
  559. //
  560. // Check start position of strings
  561. //
  562. if (Row->CharRow.KAttrs[TargetPoint.X] & ATTR_TRAILING_BYTE){
  563. if (TargetPoint.X == 0) {
  564. ScreenInfo->BisectFlag |= BISECT_TOP;
  565. }
  566. else {
  567. ScreenInfo->BisectFlag |= BISECT_LEFT;
  568. }
  569. }
  570. //
  571. // Check end position of strings
  572. //
  573. if (TargetPoint.X+StringLength < ScreenInfo->ScreenBufferSize.X) {
  574. if (Row->CharRow.KAttrs[TargetPoint.X+StringLength] & ATTR_TRAILING_BYTE){
  575. ScreenInfo->BisectFlag |= BISECT_RIGHT;
  576. }
  577. }
  578. else if (TargetPoint.Y+1 < ScreenInfo->ScreenBufferSize.Y) {
  579. if (RowNext->CharRow.KAttrs[0] & ATTR_TRAILING_BYTE){
  580. ScreenInfo->BisectFlag |= BISECT_BOTTOM;
  581. }
  582. }
  583. }
  584. /***************************************************************************\
  585. * BOOL IsConsoleFullWidth(HDC hDC,DWORD CodePage,WCHAR wch)
  586. *
  587. * Determine if the given Unicode char is fullwidth or not.
  588. *
  589. * Return:
  590. * FASLE : half width. Uses 1 column per one character
  591. * TRUE : full width. Uses 2 columns per one character
  592. *
  593. * History:
  594. * 04-08-92 ShunK Created.
  595. * Jul-27-1992 KazuM Added Screen Information and Code Page Information.
  596. * Jan-29-1992 V-Hirots Substruct Screen Information.
  597. * Oct-06-1996 KazuM Not use RtlUnicodeToMultiByteSize and WideCharToMultiByte
  598. * Because 950 only defined 13500 chars,
  599. * and unicode defined almost 18000 chars.
  600. * So there are almost 4000 chars can not be mapped to big5 code.
  601. \***************************************************************************/
  602. BOOL IsConsoleFullWidth(
  603. IN HDC hDC,
  604. IN DWORD CodePage,
  605. IN WCHAR wch
  606. )
  607. {
  608. INT Width;
  609. TEXTMETRIC tmi;
  610. if (!IsAvailableFarEastCodePage(CodePage)) {
  611. return FALSE;
  612. }
  613. if (0x20 <= wch && wch <= 0x7e) {
  614. /* ASCII */
  615. return FALSE;
  616. } else if (0x3041 <= wch && wch <= 0x3094) {
  617. /* Hiragana */
  618. return TRUE;
  619. } else if (0x30a1 <= wch && wch <= 0x30f6) {
  620. /* Katakana */
  621. return TRUE;
  622. } else if (0x3105 <= wch && wch <= 0x312c) {
  623. /* Bopomofo */
  624. return TRUE;
  625. } else if (0x3131 <= wch && wch <= 0x318e) {
  626. /* Hangul Elements */
  627. return TRUE;
  628. } else if (0xac00 <= wch && wch <= 0xd7a3) {
  629. /* Korean Hangul Syllables */
  630. return TRUE;
  631. } else if (0xff01 <= wch && wch <= 0xff5e) {
  632. /* Fullwidth ASCII variants */
  633. return TRUE;
  634. } else if (0xff61 <= wch && wch <= 0xff9f) {
  635. /* Halfwidth Katakana variants */
  636. return FALSE;
  637. } else if ( (0xffa0 <= wch && wch <= 0xffbe) ||
  638. (0xffc2 <= wch && wch <= 0xffc7) ||
  639. (0xffca <= wch && wch <= 0xffcf) ||
  640. (0xffd2 <= wch && wch <= 0xffd7) ||
  641. (0xffda <= wch && wch <= 0xffdc)) {
  642. /* Halfwidth Hangule variants */
  643. return FALSE;
  644. } else if (0xffe0 <= wch && wch <= 0xffe6) {
  645. /* Fullwidth symbol variants */
  646. return TRUE;
  647. } else if (0x4e00 <= wch && wch <= 0x9fa5) {
  648. /* Han Ideographic */
  649. return TRUE;
  650. } else if (0xf900 <= wch && wch <= 0xfa2d) {
  651. /* Han Compatibility Ideographs */
  652. return TRUE;
  653. } else {
  654. BOOL ret;
  655. /* Unknown character */
  656. ret = GetTextMetricsW(hDC, &tmi);
  657. if (!ret) {
  658. RIPMSGF1(RIP_WARNING,
  659. "GetTextMetricsW failed with error 0x%x",
  660. GetLastError());
  661. return FALSE;
  662. }
  663. if (IS_ANY_DBCS_CHARSET(tmi.tmCharSet)) {
  664. tmi.tmMaxCharWidth /= 2;
  665. }
  666. ret = GetCharWidth32(hDC, wch, wch, &Width);
  667. if (!ret) {
  668. RIPMSGF1(RIP_WARNING,
  669. "GetCharWidth32 failed with error 0x%x",
  670. GetLastError());
  671. return FALSE;
  672. }
  673. if (Width == tmi.tmMaxCharWidth) {
  674. return FALSE;
  675. } else if (Width == tmi.tmMaxCharWidth*2) {
  676. return TRUE;
  677. }
  678. }
  679. UserAssert(FALSE);
  680. return FALSE;
  681. }
  682. /*++
  683. Routine Description:
  684. This routine remove DBCS padding code.
  685. Arguments:
  686. Dst - Pointer to destination.
  687. Src - Pointer to source.
  688. NumBytes - Number of string.
  689. OS2OemFormat -
  690. Return Value:
  691. --*/
  692. DWORD
  693. RemoveDbcsMark(
  694. IN PWCHAR Dst,
  695. IN PWCHAR Src,
  696. IN DWORD NumBytes,
  697. IN PCHAR SrcA,
  698. IN BOOL OS2OemFormat
  699. )
  700. {
  701. PWCHAR Tmp = Dst;
  702. if (NumBytes == 0 || NumBytes >= 0xffffffff)
  703. return( 0 );
  704. #if defined(i386)
  705. if (OS2OemFormat) {
  706. RealUnicodeToNEC_OS2_Unicode(Src, NumBytes);
  707. }
  708. #endif
  709. if (SrcA) {
  710. while (NumBytes--)
  711. {
  712. if (!(*SrcA++ & ATTR_TRAILING_BYTE))
  713. *Dst++ = *Src;
  714. Src++;
  715. }
  716. return (ULONG)(Dst - Tmp);
  717. }
  718. else {
  719. RtlCopyMemory(Dst,Src,NumBytes * sizeof(WCHAR)) ;
  720. return(NumBytes) ;
  721. }
  722. #if !defined(i386)
  723. UNREFERENCED_PARAMETER(OS2OemFormat);
  724. #endif
  725. }
  726. /*++
  727. Routine Description:
  728. This routine remove DBCS padding code for cell format.
  729. Arguments:
  730. Dst - Pointer to destination.
  731. Src - Pointer to source.
  732. NumBytes - Number of string.
  733. Return Value:
  734. --*/
  735. DWORD
  736. RemoveDbcsMarkCell(
  737. IN PCHAR_INFO Dst,
  738. IN PCHAR_INFO Src,
  739. IN DWORD NumBytes
  740. )
  741. {
  742. PCHAR_INFO Tmp = Dst;
  743. DWORD TmpByte;
  744. TmpByte = NumBytes;
  745. while (NumBytes--) {
  746. if (!(Src->Attributes & COMMON_LVB_TRAILING_BYTE)){
  747. *Dst = *Src;
  748. Dst->Attributes &= ~COMMON_LVB_SBCSDBCS;
  749. Dst++;
  750. }
  751. Src++;
  752. }
  753. NumBytes = (ULONG)(TmpByte - (Dst - Tmp));
  754. RtlZeroMemory(Dst, NumBytes * sizeof(CHAR_INFO));
  755. Dst += NumBytes;
  756. return (ULONG)(Dst - Tmp);
  757. }
  758. DWORD
  759. RemoveDbcsMarkAll(
  760. IN PSCREEN_INFORMATION ScreenInfo,
  761. IN PROW Row,
  762. IN PSHORT LeftChar,
  763. IN PRECT TextRect,
  764. IN int *TextLeft,
  765. IN PWCHAR Buffer,
  766. IN SHORT NumberOfChars
  767. )
  768. {
  769. BOOL OS2OemFormat = FALSE;
  770. #if defined(i386)
  771. if ((ScreenInfo->Console->Flags & CONSOLE_OS2_REGISTERED) &&
  772. (ScreenInfo->Console->Flags & CONSOLE_OS2_OEM_FORMAT) &&
  773. (ScreenInfo->Console->OutputCP == OEMCP)) {
  774. OS2OemFormat = TRUE;
  775. }
  776. #endif // i386
  777. if (NumberOfChars <= 0)
  778. return NumberOfChars;
  779. if ( !CONSOLE_IS_DBCS_OUTPUTCP(ScreenInfo->Console))
  780. {
  781. return RemoveDbcsMark(Buffer,
  782. &Row->CharRow.Chars[*LeftChar],
  783. NumberOfChars,
  784. NULL,
  785. OS2OemFormat
  786. );
  787. }
  788. else if ( *LeftChar > ScreenInfo->Window.Left && Row->CharRow.KAttrs[*LeftChar] & ATTR_TRAILING_BYTE)
  789. {
  790. TextRect->left -= SCR_FONTSIZE(ScreenInfo).X;
  791. --*LeftChar;
  792. if (TextLeft)
  793. *TextLeft = TextRect->left;
  794. return RemoveDbcsMark(Buffer,
  795. &Row->CharRow.Chars[*LeftChar],
  796. NumberOfChars+1,
  797. &Row->CharRow.KAttrs[*LeftChar],
  798. OS2OemFormat
  799. );
  800. }
  801. else if (*LeftChar == ScreenInfo->Window.Left && Row->CharRow.KAttrs[*LeftChar] & ATTR_TRAILING_BYTE)
  802. {
  803. *Buffer = UNICODE_SPACE;
  804. return RemoveDbcsMark(Buffer+1,
  805. &Row->CharRow.Chars[*LeftChar+1],
  806. NumberOfChars-1,
  807. &Row->CharRow.KAttrs[*LeftChar+1],
  808. OS2OemFormat
  809. ) + 1;
  810. }
  811. else
  812. {
  813. return RemoveDbcsMark(Buffer,
  814. &Row->CharRow.Chars[*LeftChar],
  815. NumberOfChars,
  816. &Row->CharRow.KAttrs[*LeftChar],
  817. OS2OemFormat
  818. );
  819. }
  820. }
  821. BOOL
  822. IsDBCSLeadByteConsole(
  823. IN BYTE AsciiChar,
  824. IN LPCPINFO lpCPInfo
  825. )
  826. {
  827. int i;
  828. i = 0;
  829. while (lpCPInfo->LeadByte[i]) {
  830. if (lpCPInfo->LeadByte[i] <= AsciiChar && AsciiChar <= lpCPInfo->LeadByte[i+1])
  831. return TRUE;
  832. i += 2;
  833. }
  834. return FALSE;
  835. }
  836. NTSTATUS
  837. AdjustFont(
  838. IN PCONSOLE_INFORMATION Console,
  839. IN UINT CodePage
  840. )
  841. {
  842. PSCREEN_INFORMATION ScreenInfo = Console->CurrentScreenBuffer;
  843. ULONG FontIndex;
  844. static const COORD NullCoord = {0, 0};
  845. TEXT_BUFFER_FONT_INFO TextFontInfo;
  846. NTSTATUS Status;
  847. Status = FindTextBufferFontInfo(ScreenInfo,
  848. CodePage,
  849. &TextFontInfo);
  850. if (NT_SUCCESS(Status)) {
  851. FontIndex = FindCreateFont(TextFontInfo.Family,
  852. TextFontInfo.FaceName,
  853. TextFontInfo.FontSize,
  854. TextFontInfo.Weight,
  855. CodePage);
  856. }
  857. else {
  858. FontIndex = FindCreateFont(0,
  859. SCR_FACENAME(ScreenInfo),
  860. NullCoord, // sets new font by FontSize=0
  861. 0,
  862. CodePage);
  863. }
  864. #ifdef i386
  865. if (! (Console->FullScreenFlags & CONSOLE_FULLSCREEN)) {
  866. SetScreenBufferFont(Console->CurrentScreenBuffer,FontIndex, CodePage);
  867. }
  868. else {
  869. BOOL fChange = FALSE;
  870. if ((Console->FullScreenFlags & CONSOLE_FULLSCREEN_HARDWARE) &&
  871. (GetForegroundWindow() == Console->hWnd) )
  872. {
  873. ChangeDispSettings(Console, Console->hWnd, 0);
  874. fChange = TRUE;
  875. }
  876. SetScreenBufferFont(Console->CurrentScreenBuffer,FontIndex, CodePage);
  877. ConvertToFullScreen(Console);
  878. if (fChange &&
  879. (GetForegroundWindow() == Console->hWnd))
  880. ChangeDispSettings(Console, Console->hWnd, CDS_FULLSCREEN);
  881. }
  882. #else
  883. SetScreenBufferFont(Console->CurrentScreenBuffer,FontIndex, CodePage);
  884. #endif
  885. return STATUS_SUCCESS;
  886. }
  887. NTSTATUS
  888. ConvertToCodePage(
  889. IN PCONSOLE_INFORMATION Console,
  890. IN UINT PrevCodePage
  891. )
  892. {
  893. PSCREEN_INFORMATION Cur;
  894. if (Console->OutputCP != OEMCP && PrevCodePage == OEMCP)
  895. {
  896. for (Cur=Console->ScreenBuffers;Cur!=NULL;Cur=Cur->Next) {
  897. if (Cur->Flags & CONSOLE_GRAPHICS_BUFFER) {
  898. continue;
  899. }
  900. ConvertOutputOemToNonOemUnicode(
  901. Cur->BufferInfo.TextInfo.TextRows,
  902. Cur->BufferInfo.TextInfo.DbcsScreenBuffer.KAttrRows,
  903. Cur->ScreenBufferSize.X * Cur->ScreenBufferSize.Y,
  904. Console->OutputCP);
  905. if ((Cur->Flags & CONSOLE_OEMFONT_DISPLAY) &&
  906. ((Console->FullScreenFlags & CONSOLE_FULLSCREEN) == 0)) {
  907. RealUnicodeToFalseUnicode(
  908. Cur->BufferInfo.TextInfo.TextRows,
  909. Cur->ScreenBufferSize.X * Cur->ScreenBufferSize.Y,
  910. Console->OutputCP);
  911. }
  912. }
  913. if (Console->CurrentScreenBuffer->Flags & CONSOLE_TEXTMODE_BUFFER) {
  914. PCONVERSIONAREA_INFORMATION ConvAreaInfo;
  915. ConvAreaInfo = Console->ConsoleIme.ConvAreaRoot;
  916. while (ConvAreaInfo) {
  917. Cur = ConvAreaInfo->ScreenBuffer;
  918. if (!(Cur->Flags & CONSOLE_GRAPHICS_BUFFER)) {
  919. ConvertOutputOemToNonOemUnicode(
  920. Cur->BufferInfo.TextInfo.TextRows,
  921. Cur->BufferInfo.TextInfo.DbcsScreenBuffer.KAttrRows,
  922. Cur->ScreenBufferSize.X * Cur->ScreenBufferSize.Y,
  923. Console->OutputCP);
  924. if ((Cur->Flags & CONSOLE_OEMFONT_DISPLAY) &&
  925. ((Console->FullScreenFlags & CONSOLE_FULLSCREEN) == 0)) {
  926. RealUnicodeToFalseUnicode(
  927. Cur->BufferInfo.TextInfo.TextRows,
  928. Cur->ScreenBufferSize.X * Cur->ScreenBufferSize.Y,
  929. Console->OutputCP);
  930. }
  931. }
  932. ConvAreaInfo = ConvAreaInfo->ConvAreaNext;
  933. }
  934. Console->CurrentScreenBuffer->BufferInfo.TextInfo.Flags &= ~TEXT_VALID_HINT;
  935. }
  936. #ifdef FE_SB
  937. else {
  938. UserAssert(FALSE);
  939. }
  940. #endif
  941. SetWindowSize(Console->CurrentScreenBuffer);
  942. WriteToScreen(Console->CurrentScreenBuffer,&Console->CurrentScreenBuffer->Window);
  943. }
  944. return STATUS_SUCCESS;
  945. }
  946. NTSTATUS
  947. ConvertOutputOemToNonOemUnicode(
  948. IN OUT LPWSTR Source,
  949. IN OUT PBYTE KAttrRows,
  950. IN int SourceLength, // in chars
  951. IN UINT Codepage
  952. )
  953. {
  954. NTSTATUS Status;
  955. LPSTR pTemp;
  956. LPWSTR pwTemp;
  957. ULONG TempLength;
  958. ULONG Length;
  959. BOOL NormalChars;
  960. int i;
  961. if (SourceLength == 0 )
  962. return STATUS_SUCCESS;
  963. NormalChars = TRUE;
  964. for (i=0;i<SourceLength;i++) {
  965. if (Source[i] > 0x7f) {
  966. NormalChars = FALSE;
  967. break;
  968. }
  969. }
  970. if (NormalChars) {
  971. return STATUS_SUCCESS;
  972. }
  973. pTemp = ConsoleHeapAlloc(TMP_TAG, SourceLength);
  974. if (pTemp == NULL) {
  975. return STATUS_NO_MEMORY;
  976. }
  977. pwTemp = ConsoleHeapAlloc(TMP_TAG, SourceLength * sizeof(WCHAR));
  978. if (pwTemp == NULL) {
  979. ConsoleHeapFree(pTemp);
  980. return STATUS_NO_MEMORY;
  981. }
  982. TempLength = RemoveDbcsMark(pwTemp,
  983. Source,
  984. SourceLength,
  985. KAttrRows,
  986. FALSE);
  987. Status = RtlUnicodeToOemN(pTemp,
  988. (ULONG)ConsoleHeapSize(pTemp),
  989. &Length,
  990. pwTemp,
  991. TempLength * sizeof(WCHAR)
  992. );
  993. if (!NT_SUCCESS(Status)) {
  994. ConsoleHeapFree(pTemp);
  995. ConsoleHeapFree(pwTemp);
  996. return Status;
  997. }
  998. MultiByteToWideChar(Codepage,
  999. 0,
  1000. pTemp,
  1001. Length,
  1002. Source,
  1003. SourceLength
  1004. );
  1005. ConsoleHeapFree(pTemp);
  1006. ConsoleHeapFree(pwTemp);
  1007. if (!NT_SUCCESS(Status)) {
  1008. return Status;
  1009. } else {
  1010. if (KAttrRows) {
  1011. RtlZeroMemory(KAttrRows, SourceLength);
  1012. }
  1013. return STATUS_SUCCESS;
  1014. }
  1015. }
  1016. VOID
  1017. TextOutEverything(
  1018. IN PCONSOLE_INFORMATION Console,
  1019. IN PSCREEN_INFORMATION ScreenInfo,
  1020. IN SHORT LeftWindowPos,
  1021. IN OUT PSHORT RightWindowPos,
  1022. IN OUT PSHORT CountOfAttr,
  1023. IN SHORT CountOfAttrOriginal,
  1024. IN OUT PBOOL DoubleColorDBCS,
  1025. IN BOOL LocalEUDCFlag,
  1026. IN PROW Row,
  1027. IN PATTR_PAIR Attr,
  1028. IN SHORT LeftTextPos,
  1029. IN SHORT RightTextPos,
  1030. IN int WindowRectLeft,
  1031. IN RECT WindowRect,
  1032. IN SHORT NumberOfChars
  1033. )
  1034. /*++
  1035. Routine Description:
  1036. This routine text out everything.
  1037. Arguments:
  1038. Return Value:
  1039. --*/
  1040. {
  1041. int j = LeftWindowPos;
  1042. int TextLeft = WindowRectLeft;
  1043. RECT TextRect = WindowRect;
  1044. SHORT LeftChar = LeftTextPos;
  1045. SHORT RightChar = RightTextPos;
  1046. BOOL DoubleColorDBCSBefore;
  1047. BOOL LocalEUDCFlagBefore;
  1048. PEUDC_INFORMATION EudcInfo;
  1049. int RightPos = j + *CountOfAttr - 1;
  1050. int RightText = LeftChar + *CountOfAttr - 1;
  1051. BOOL OS2OemFormat = FALSE;
  1052. #ifdef FE_SB
  1053. //
  1054. // This buffer must be in textmode.
  1055. //
  1056. UserAssert(!(ScreenInfo->Flags & CONSOLE_GRAPHICS_BUFFER));
  1057. #endif
  1058. #if defined(i386)
  1059. if ((ScreenInfo->Console->Flags & CONSOLE_OS2_REGISTERED) &&
  1060. (ScreenInfo->Console->Flags & CONSOLE_OS2_OEM_FORMAT) &&
  1061. (ScreenInfo->Console->OutputCP == OEMCP)) {
  1062. OS2OemFormat = TRUE;
  1063. }
  1064. #endif // i386
  1065. #if DBG && defined(DBG_KATTR)
  1066. BeginKAttrCheck(ScreenInfo);
  1067. #endif
  1068. RightText = min(RightText,(ScreenInfo->ScreenBufferSize.X-1));
  1069. LocalEUDCFlagBefore = LocalEUDCFlag ;
  1070. EudcInfo = (PEUDC_INFORMATION)Console->EudcInformation;
  1071. DoubleColorDBCSBefore = *DoubleColorDBCS ;
  1072. if (DoubleColorDBCSBefore){
  1073. RECT TmpRect;
  1074. if (Console->FonthDC == NULL) {
  1075. Console->FonthDC = CreateCompatibleDC(Console->hDC);
  1076. Console->hBitmap = CreateBitmap(DEFAULT_FONTSIZE, DEFAULT_FONTSIZE, BITMAP_PLANES, BITMAP_BITS_PIXEL, NULL);
  1077. SelectObject(Console->FonthDC, Console->hBitmap);
  1078. }
  1079. if (LocalEUDCFlagBefore){
  1080. if (EudcInfo->hDCLocalEudc == NULL) {
  1081. EudcInfo->hDCLocalEudc = CreateCompatibleDC(Console->hDC);
  1082. EudcInfo->hBmpLocalEudc = CreateBitmap(EudcInfo->LocalEudcSize.X,
  1083. EudcInfo->LocalEudcSize.Y,
  1084. BITMAP_PLANES, BITMAP_BITS_PIXEL, NULL);
  1085. SelectObject(EudcInfo->hDCLocalEudc, EudcInfo->hBmpLocalEudc);
  1086. }
  1087. GetFitLocalEUDCFont(Console,
  1088. Row->CharRow.Chars[LeftChar-1]);
  1089. BitBlt(Console->hDC,
  1090. TextRect.left,
  1091. TextRect.top,
  1092. SCR_FONTSIZE(ScreenInfo).X,
  1093. SCR_FONTSIZE(ScreenInfo).Y,
  1094. EudcInfo->hDCLocalEudc,
  1095. SCR_FONTSIZE(ScreenInfo).X,
  1096. 0,
  1097. SRCCOPY
  1098. );
  1099. TextRect.left += SCR_FONTSIZE(ScreenInfo).X;
  1100. TextLeft += SCR_FONTSIZE(ScreenInfo).X;
  1101. TextRect.right += SCR_FONTSIZE(ScreenInfo).X;
  1102. (*CountOfAttr)++;
  1103. NumberOfChars = 0;
  1104. }
  1105. else{
  1106. TmpRect.left = 0;
  1107. TmpRect.top = 0;
  1108. TmpRect.right = SCR_FONTSIZE(ScreenInfo).X;
  1109. TmpRect.bottom = SCR_FONTSIZE(ScreenInfo).Y;
  1110. SelectObject(Console->FonthDC,
  1111. FontInfo[SCR_FONTNUMBER(ScreenInfo)].hFont
  1112. );
  1113. ExtTextOutW(Console->FonthDC,
  1114. 0,
  1115. 0,
  1116. ETO_OPAQUE,
  1117. &TmpRect,
  1118. &Row->CharRow.Chars[LeftChar-1],
  1119. 1,
  1120. NULL
  1121. );
  1122. BitBlt(Console->hDC,
  1123. TextRect.left,
  1124. TextRect.top,
  1125. SCR_FONTSIZE(ScreenInfo).X,
  1126. SCR_FONTSIZE(ScreenInfo).Y,
  1127. Console->FonthDC,
  1128. SCR_FONTSIZE(ScreenInfo).X,
  1129. 0,
  1130. SRCCOPY
  1131. );
  1132. TextRect.left += SCR_FONTSIZE(ScreenInfo).X;
  1133. TextLeft += SCR_FONTSIZE(ScreenInfo).X;
  1134. NumberOfChars = (SHORT)RemoveDbcsMark(ScreenInfo->BufferInfo.TextInfo.DbcsScreenBuffer.TransBufferCharacter,
  1135. &Row->CharRow.Chars[LeftChar+1],
  1136. NumberOfChars-1,
  1137. &Row->CharRow.KAttrs[LeftChar+1],
  1138. OS2OemFormat);
  1139. }
  1140. }
  1141. else {
  1142. NumberOfChars = (SHORT)RemoveDbcsMarkAll(ScreenInfo,
  1143. Row,
  1144. &LeftChar,
  1145. &TextRect,
  1146. &TextLeft,
  1147. ScreenInfo->BufferInfo.TextInfo.DbcsScreenBuffer.TransBufferCharacter,
  1148. NumberOfChars);
  1149. }
  1150. *DoubleColorDBCS = FALSE ;
  1151. if ((NumberOfChars != 0) && (Row->CharRow.KAttrs[RightText] & ATTR_LEADING_BYTE)){
  1152. if (RightPos >= ScreenInfo->Window.Right)
  1153. *(ScreenInfo->BufferInfo.TextInfo.DbcsScreenBuffer.TransBufferCharacter+NumberOfChars-1) = UNICODE_SPACE;
  1154. else if(TextRect.right <= ScreenInfo->Window.Right * SCR_FONTSIZE(ScreenInfo).X) {
  1155. *DoubleColorDBCS = TRUE;
  1156. TextRect.right += SCR_FONTSIZE(ScreenInfo).X;
  1157. if((j == *RightWindowPos)&&
  1158. (*RightWindowPos < ScreenInfo->Window.Right))
  1159. *RightWindowPos++;
  1160. }
  1161. }
  1162. if( TextRect.left < TextRect.right){
  1163. ExtTextOutW(Console->hDC,
  1164. TextLeft,
  1165. TextRect.top,
  1166. ETO_OPAQUE,
  1167. &TextRect,
  1168. ScreenInfo->BufferInfo.TextInfo.DbcsScreenBuffer.TransBufferCharacter,
  1169. NumberOfChars,
  1170. NULL
  1171. );
  1172. }
  1173. if (LocalEUDCFlagBefore){
  1174. DWORD dwFullWidth = (IsConsoleFullWidth(Console->hDC,
  1175. Console->OutputCP,
  1176. Row->CharRow.Chars[RightText+1]) ? 2 : 1);
  1177. if (EudcInfo->hDCLocalEudc == NULL) {
  1178. EudcInfo->hDCLocalEudc = CreateCompatibleDC(Console->hDC);
  1179. EudcInfo->hBmpLocalEudc = CreateBitmap(EudcInfo->LocalEudcSize.X,
  1180. EudcInfo->LocalEudcSize.Y,
  1181. BITMAP_PLANES, BITMAP_BITS_PIXEL, NULL);
  1182. SelectObject(EudcInfo->hDCLocalEudc, EudcInfo->hBmpLocalEudc);
  1183. }
  1184. GetFitLocalEUDCFont(Console,
  1185. Row->CharRow.Chars[RightText+1]);
  1186. BitBlt(Console->hDC, // hdcDest
  1187. TextRect.right, // nXDest
  1188. TextRect.top, // nYDest
  1189. SCR_FONTSIZE(ScreenInfo).X * dwFullWidth, // nWidth
  1190. SCR_FONTSIZE(ScreenInfo).Y, // nHeight
  1191. EudcInfo->hDCLocalEudc, // hdcSrc
  1192. 0, // nXSrc
  1193. 0, // nYSrc
  1194. SRCCOPY
  1195. );
  1196. TextRect.right += (SCR_FONTSIZE(ScreenInfo).X * dwFullWidth);
  1197. (*CountOfAttr) += (SHORT)dwFullWidth;
  1198. if (CountOfAttrOriginal < *CountOfAttr ){
  1199. *DoubleColorDBCS = TRUE ;
  1200. (*CountOfAttr)--;
  1201. TextRect.right -= SCR_FONTSIZE(ScreenInfo).X;
  1202. }
  1203. }
  1204. if (DoubleColorDBCSBefore){
  1205. TextRect.left -= SCR_FONTSIZE(ScreenInfo).X;
  1206. }
  1207. TextOutCommonLVB(Console, Attr->Attr, TextRect);
  1208. }
  1209. VOID
  1210. TextOutCommonLVB(
  1211. IN PCONSOLE_INFORMATION Console,
  1212. IN WORD Attributes,
  1213. IN RECT CommonLVBRect
  1214. )
  1215. {
  1216. HBRUSH hbrSave;
  1217. HGDIOBJ hbr;
  1218. int GridX;
  1219. if (Attributes & (COMMON_LVB_GRID_HORIZONTAL |
  1220. COMMON_LVB_GRID_LVERTICAL |
  1221. COMMON_LVB_GRID_RVERTICAL |
  1222. COMMON_LVB_UNDERSCORE )
  1223. )
  1224. {
  1225. if(Attributes & COMMON_LVB_UNDERSCORE){
  1226. if(Attributes & COMMON_LVB_REVERSE_VIDEO)
  1227. hbr = CreateSolidBrush(ConvertAttrToRGB(Console, LOBYTE(Attributes >> 4)));
  1228. else
  1229. hbr = CreateSolidBrush(ConvertAttrToRGB(Console, LOBYTE(Attributes)));
  1230. hbrSave = SelectObject(Console->hDC, hbr);
  1231. PatBlt(Console->hDC,
  1232. CommonLVBRect.left,
  1233. CommonLVBRect.bottom-1,
  1234. CommonLVBRect.right-CommonLVBRect.left,
  1235. 1,
  1236. PATCOPY
  1237. );
  1238. SelectObject(Console->hDC, hbrSave);
  1239. DeleteObject(hbr);
  1240. }
  1241. if(Attributes & (COMMON_LVB_GRID_HORIZONTAL | COMMON_LVB_GRID_LVERTICAL | COMMON_LVB_GRID_RVERTICAL)){
  1242. hbr = CreateSolidBrush(ConvertAttrToRGB(Console, 0x0007));
  1243. hbrSave = SelectObject(Console->hDC, hbr);
  1244. if(Attributes & COMMON_LVB_GRID_HORIZONTAL){
  1245. PatBlt(Console->hDC,
  1246. CommonLVBRect.left,
  1247. CommonLVBRect.top,
  1248. CommonLVBRect.right-CommonLVBRect.left,
  1249. 1,
  1250. PATCOPY
  1251. );
  1252. }
  1253. if(Attributes & COMMON_LVB_GRID_LVERTICAL){
  1254. for ( GridX = CommonLVBRect.left ;
  1255. GridX < CommonLVBRect.right ;
  1256. GridX += CON_FONTSIZE(Console).X){
  1257. PatBlt(Console->hDC,
  1258. GridX,
  1259. CommonLVBRect.top,
  1260. 1,
  1261. CON_FONTSIZE(Console).Y,
  1262. PATCOPY
  1263. );
  1264. }
  1265. }
  1266. if(Attributes & COMMON_LVB_GRID_RVERTICAL){
  1267. for ( GridX = CommonLVBRect.left + CON_FONTSIZE(Console).X-1 ;
  1268. GridX < CommonLVBRect.right ;
  1269. GridX += CON_FONTSIZE(Console).X){
  1270. PatBlt(Console->hDC,
  1271. GridX,
  1272. CommonLVBRect.top,
  1273. 1,
  1274. CON_FONTSIZE(Console).Y,
  1275. PATCOPY
  1276. );
  1277. }
  1278. }
  1279. SelectObject(Console->hDC, hbrSave);
  1280. DeleteObject(hbr);
  1281. }
  1282. }
  1283. }
  1284. NTSTATUS
  1285. MakeAltRasterFont(
  1286. UINT CodePage,
  1287. COORD DefaultFontSize,
  1288. COORD *AltFontSize,
  1289. BYTE *AltFontFamily,
  1290. ULONG *AltFontIndex,
  1291. LPWSTR AltFaceName
  1292. )
  1293. {
  1294. DWORD i;
  1295. DWORD Find;
  1296. ULONG FontIndex;
  1297. COORD FontSize = DefaultFontSize;
  1298. COORD FontDelta;
  1299. BOOL fDbcsCharSet = IsAvailableFarEastCodePage(CodePage);
  1300. FontIndex = 0;
  1301. Find = (DWORD)-1;
  1302. for (i=0; i < NumberOfFonts; i++)
  1303. {
  1304. if (!TM_IS_TT_FONT(FontInfo[i].Family) &&
  1305. IS_ANY_DBCS_CHARSET(FontInfo[i].tmCharSet) == fDbcsCharSet
  1306. )
  1307. {
  1308. FontDelta.X = (SHORT)abs(FontSize.X - FontInfo[i].Size.X);
  1309. FontDelta.Y = (SHORT)abs(FontSize.Y - FontInfo[i].Size.Y);
  1310. if (Find > (DWORD)(FontDelta.X + FontDelta.Y))
  1311. {
  1312. Find = (DWORD)(FontDelta.X + FontDelta.Y);
  1313. FontIndex = i;
  1314. }
  1315. }
  1316. }
  1317. *AltFontIndex = FontIndex;
  1318. wcscpy(AltFaceName, FontInfo[*AltFontIndex].FaceName);
  1319. *AltFontSize = FontInfo[*AltFontIndex].Size;
  1320. *AltFontFamily = FontInfo[*AltFontIndex].Family;
  1321. DBGFONTS(("MakeAltRasterFont : AltFontIndex = %ld\n", *AltFontIndex));
  1322. return STATUS_SUCCESS;
  1323. }
  1324. NTSTATUS
  1325. InitializeDbcsMisc(
  1326. VOID)
  1327. {
  1328. HANDLE hkRegistry = NULL;
  1329. NTSTATUS Status;
  1330. WCHAR awchValue[512];
  1331. WCHAR awchData[512];
  1332. BYTE Buffer[512];
  1333. DWORD Length;
  1334. DWORD dwIndex;
  1335. LPWSTR pwsz;
  1336. static BOOL bDBCSInitialized = FALSE;
  1337. if (bDBCSInitialized) {
  1338. return STATUS_SUCCESS;
  1339. } else {
  1340. bDBCSInitialized = TRUE;
  1341. }
  1342. UserAssert(gTTFontList.Next == NULL);
  1343. UserAssert(gRegFullScreenCodePage.Next == NULL);
  1344. /*
  1345. * Get TrueType Font Face name from registry.
  1346. */
  1347. Status = MyRegOpenKey(NULL,
  1348. MACHINE_REGISTRY_CONSOLE_TTFONT,
  1349. &hkRegistry);
  1350. if (!NT_SUCCESS(Status)) {
  1351. RIPMSG2(RIP_VERBOSE,
  1352. "NtOpenKey(%ws) failed with status 0x%x",
  1353. MACHINE_REGISTRY_CONSOLE_TTFONT,
  1354. Status);
  1355. } else {
  1356. LPTTFONTLIST pTTFontList;
  1357. for (dwIndex = 0; ; dwIndex++) {
  1358. Status = MyRegEnumValue(hkRegistry,
  1359. dwIndex,
  1360. sizeof(awchValue),
  1361. (LPWSTR)&awchValue,
  1362. sizeof(awchData),
  1363. (PBYTE)&awchData);
  1364. if (!NT_SUCCESS(Status)) {
  1365. break;
  1366. }
  1367. pTTFontList = ConsoleHeapAlloc(SCREEN_DBCS_TAG, sizeof(TTFONTLIST));
  1368. if (pTTFontList == NULL) {
  1369. break;
  1370. }
  1371. pTTFontList->List.Next = NULL;
  1372. pTTFontList->CodePage = ConvertStringToDec(awchValue, NULL);
  1373. pwsz = awchData;
  1374. if (*pwsz == BOLD_MARK) {
  1375. pTTFontList->fDisableBold = TRUE;
  1376. pwsz++;
  1377. } else {
  1378. pTTFontList->fDisableBold = FALSE;
  1379. }
  1380. wcscpy(pTTFontList->FaceName1, pwsz);
  1381. pwsz += wcslen(pwsz) + 1;
  1382. if (*pwsz == BOLD_MARK) {
  1383. pTTFontList->fDisableBold = TRUE;
  1384. pwsz++;
  1385. }
  1386. wcscpy(pTTFontList->FaceName2, pwsz);
  1387. PushEntryList(&gTTFontList, &(pTTFontList->List));
  1388. }
  1389. NtClose(hkRegistry);
  1390. }
  1391. /*
  1392. * Get Full Screen from registry.
  1393. */
  1394. Status = MyRegOpenKey(NULL,
  1395. MACHINE_REGISTRY_CONSOLE_FULLSCREEN,
  1396. &hkRegistry);
  1397. if (!NT_SUCCESS(Status)) {
  1398. RIPMSG2(RIP_VERBOSE,
  1399. "NtOpenKey(%ws) failed with status 0x%x",
  1400. MACHINE_REGISTRY_CONSOLE_FULLSCREEN,
  1401. Status);
  1402. } else {
  1403. /*
  1404. * InitialPalette
  1405. */
  1406. Status = MyRegQueryValueEx(hkRegistry,
  1407. MACHINE_REGISTRY_INITIAL_PALETTE,
  1408. sizeof( Buffer ), Buffer, &Length);
  1409. if (NT_SUCCESS(Status) && Length > sizeof(DWORD)) {
  1410. DWORD PaletteLength = ((LPDWORD)Buffer)[0];
  1411. PUSHORT Palette;
  1412. if (PaletteLength * sizeof(USHORT) >= (Length - sizeof(DWORD))) {
  1413. Palette = ConsoleHeapAlloc(BUFFER_TAG, Length);
  1414. if (Palette != NULL) {
  1415. RtlCopyMemory(Palette, Buffer, Length);
  1416. RegInitialPalette = Palette;
  1417. }
  1418. }
  1419. }
  1420. /*
  1421. * ColorBuffer.
  1422. */
  1423. Status = MyRegQueryValueEx(hkRegistry,
  1424. MACHINE_REGISTRY_COLOR_BUFFER,
  1425. sizeof(Buffer),
  1426. Buffer,
  1427. &Length);
  1428. if (NT_SUCCESS(Status) && Length > sizeof(DWORD)) {
  1429. DWORD ColorBufferLength = ((LPDWORD)Buffer)[0];
  1430. PUCHAR Color;
  1431. if (ColorBufferLength * sizeof(DWORD) >= (Length - sizeof(DWORD))) {
  1432. Color = ConsoleHeapAlloc(BUFFER_TAG, Length);
  1433. if (Color != NULL) {
  1434. RtlCopyMemory(Color, Buffer, Length);
  1435. RegColorBuffer = Color;
  1436. }
  1437. }
  1438. }
  1439. /*
  1440. * ColorBufferNoTranslate.
  1441. */
  1442. Status = MyRegQueryValueEx(hkRegistry,
  1443. MACHINE_REGISTRY_COLOR_BUFFER_NO_TRANSLATE,
  1444. sizeof(Buffer),
  1445. Buffer,
  1446. &Length);
  1447. if (NT_SUCCESS(Status) && Length > sizeof(DWORD)) {
  1448. DWORD ColorBufferLength = ((LPDWORD)Buffer)[0];
  1449. PUCHAR Color;
  1450. if (ColorBufferLength * sizeof(DWORD) >= (Length - sizeof(DWORD))) {
  1451. Color = ConsoleHeapAlloc(BUFFER_TAG, Length);
  1452. if (Color != NULL) {
  1453. RtlCopyMemory(Color, Buffer, Length);
  1454. RegColorBufferNoTranslate = Color;
  1455. }
  1456. }
  1457. }
  1458. /*
  1459. * ModeFontPairs
  1460. */
  1461. Status = MyRegQueryValueEx(hkRegistry,
  1462. MACHINE_REGISTRY_MODE_FONT_PAIRS,
  1463. sizeof(Buffer),
  1464. Buffer,
  1465. &Length);
  1466. if (NT_SUCCESS(Status) && Length > sizeof(DWORD)) {
  1467. DWORD NumOfEntries = ((LPDWORD)Buffer)[0];
  1468. PMODE_FONT_PAIR ModeFont;
  1469. if (NumOfEntries * sizeof(MODE_FONT_PAIR) >= (Length - sizeof(DWORD))) {
  1470. ModeFont = ConsoleHeapAlloc(BUFFER_TAG, Length);
  1471. if (ModeFont != NULL) {
  1472. Length -= sizeof(DWORD);
  1473. RtlCopyMemory(ModeFont, &Buffer[sizeof(DWORD)], Length);
  1474. RegModeFontPairs = ModeFont;
  1475. NUMBER_OF_MODE_FONT_PAIRS = NumOfEntries;
  1476. }
  1477. }
  1478. }
  1479. /*
  1480. * FullScreen\CodePage
  1481. */
  1482. {
  1483. HANDLE hkRegCP = NULL;
  1484. Status = MyRegOpenKey(hkRegistry,
  1485. MACHINE_REGISTRY_FS_CODEPAGE,
  1486. &hkRegCP);
  1487. if (!NT_SUCCESS(Status)) {
  1488. RIPMSG2(RIP_VERBOSE,
  1489. "NtOpenKey(%ws) failed with status 0x%x",
  1490. MACHINE_REGISTRY_FS_CODEPAGE,
  1491. Status);
  1492. } else {
  1493. PFS_CODEPAGE pFsCodePage;
  1494. for (dwIndex = 0; ; dwIndex++) {
  1495. Status = MyRegEnumValue(hkRegCP,
  1496. dwIndex,
  1497. sizeof(awchValue),
  1498. (LPWSTR)&awchValue,
  1499. sizeof(awchData),
  1500. (PBYTE)&awchData);
  1501. if (!NT_SUCCESS(Status)) {
  1502. break;
  1503. }
  1504. pFsCodePage = ConsoleHeapAlloc(BUFFER_TAG, sizeof(FS_CODEPAGE));
  1505. if (pFsCodePage == NULL) {
  1506. break;
  1507. }
  1508. pFsCodePage->List.Next = NULL;
  1509. pFsCodePage->CodePage = ConvertStringToDec(awchValue, NULL);
  1510. PushEntryList(&gRegFullScreenCodePage, &(pFsCodePage->List));
  1511. }
  1512. NtClose(hkRegCP);
  1513. }
  1514. }
  1515. NtClose(hkRegistry);
  1516. }
  1517. #if defined(i386)
  1518. Status = NtGetMachineIdentifierValue(&gdwMachineId);
  1519. if (!NT_SUCCESS(Status)) {
  1520. gdwMachineId = MACHINEID_MS_PCAT;
  1521. }
  1522. #endif
  1523. Status = RtlInitializeCriticalSectionAndSpinCount(&ConIMEInitWindowsLock,
  1524. 0x80000000);
  1525. return Status;
  1526. }
  1527. /*
  1528. * This routine converts a unicode string from the real unicode characters
  1529. * to the NEC OS/2 unicode characters.
  1530. */
  1531. #if defined(i386)
  1532. NTSTATUS
  1533. RealUnicodeToNEC_OS2_Unicode(
  1534. IN OUT LPWSTR Source,
  1535. IN int SourceLength // in chars
  1536. )
  1537. {
  1538. NTSTATUS Status;
  1539. LPSTR Temp;
  1540. ULONG TempLength;
  1541. ULONG Length;
  1542. CHAR StackBuffer[STACK_BUFFER_SIZE];
  1543. BOOL NormalChars;
  1544. int i;
  1545. DBGCHARS(("RealUnicodeToNEC_OS2_Unicode U->ACP:???->U %.*ls\n",
  1546. SourceLength > 10 ? 10 : SourceLength, Source));
  1547. NormalChars = TRUE;
  1548. if (pGlyph_NEC_OS2_CP == NULL || pGlyph_NEC_OS2_CP->MultiByteTable == NULL) {
  1549. DBGCHARS(("RealUnicodeToNEC_OS2_Unicode xfer buffer null\n"));
  1550. return STATUS_SUCCESS; // there's nothing we can do
  1551. }
  1552. /*
  1553. * Test for characters < 0x20. If none are found, we don't have any
  1554. * conversion to do!
  1555. */
  1556. for (i = 0; i < SourceLength; i++) {
  1557. if ((USHORT)(Source[i]) < 0x20) {
  1558. NormalChars = FALSE;
  1559. break;
  1560. }
  1561. }
  1562. if (NormalChars) {
  1563. return STATUS_SUCCESS;
  1564. }
  1565. TempLength = SourceLength;
  1566. if (TempLength > STACK_BUFFER_SIZE) {
  1567. Temp = ConsoleHeapAlloc(TMP_TAG, TempLength);
  1568. if (Temp == NULL) {
  1569. return STATUS_NO_MEMORY;
  1570. }
  1571. } else {
  1572. Temp = StackBuffer;
  1573. }
  1574. Status = RtlUnicodeToMultiByteN(Temp,
  1575. TempLength,
  1576. &Length,
  1577. Source,
  1578. SourceLength * sizeof(WCHAR));
  1579. if (!NT_SUCCESS(Status)) {
  1580. if (TempLength > STACK_BUFFER_SIZE) {
  1581. ConsoleHeapFree(Temp);
  1582. }
  1583. return Status;
  1584. }
  1585. UserAssert(pGlyph_NEC_OS2_CP != NULL && pGlyph_NEC_OS2_CP->MultiByteTable != NULL);
  1586. Status = RtlCustomCPToUnicodeN(pGlyph_NEC_OS2_CP,
  1587. Source,
  1588. SourceLength * sizeof(WCHAR),
  1589. &Length,
  1590. Temp,
  1591. TempLength);
  1592. if (TempLength > STACK_BUFFER_SIZE) {
  1593. ConsoleHeapFree(Temp);
  1594. }
  1595. if (!NT_SUCCESS(Status)) {
  1596. return Status;
  1597. } else {
  1598. return STATUS_SUCCESS;
  1599. }
  1600. }
  1601. BOOL
  1602. InitializeNEC_OS2_CP(
  1603. VOID
  1604. )
  1605. {
  1606. PPEB pPeb;
  1607. pPeb = NtCurrentPeb();
  1608. if ((pPeb == NULL) || (pPeb->OemCodePageData == NULL)) {
  1609. return FALSE;
  1610. }
  1611. /*
  1612. * Fill in the CPTABLEINFO struct
  1613. */
  1614. if (pGlyph_NEC_OS2_CP == NULL) {
  1615. pGlyph_NEC_OS2_CP = ConsoleHeapAlloc(SCREEN_DBCS_TAG, sizeof(CPTABLEINFO));
  1616. if (pGlyph_NEC_OS2_CP == NULL) {
  1617. return FALSE;
  1618. }
  1619. }
  1620. RtlInitCodePageTable(pPeb->OemCodePageData, pGlyph_NEC_OS2_CP);
  1621. /*
  1622. * Make a copy of the MultiByteToWideChar table
  1623. */
  1624. if (pGlyph_NEC_OS2_Table == NULL) {
  1625. pGlyph_NEC_OS2_Table = ConsoleHeapAlloc(SCREEN_DBCS_TAG, 256 * sizeof(USHORT));
  1626. if (pGlyph_NEC_OS2_Table == NULL) {
  1627. return FALSE;
  1628. }
  1629. }
  1630. RtlCopyMemory(pGlyph_NEC_OS2_Table, pGlyph_NEC_OS2_CP->MultiByteTable, 256 * sizeof(USHORT));
  1631. /*
  1632. * Modify the first 0x20 bytes so that they are glyphs.
  1633. */
  1634. MultiByteToWideChar(CP_OEMCP, MB_USEGLYPHCHARS,
  1635. "\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20"
  1636. "\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x1E\x1F\x1C\x07",
  1637. 0x20, pGlyph_NEC_OS2_Table, 0x20);
  1638. /*
  1639. * Point the Custom CP at the glyph table
  1640. */
  1641. pGlyph_NEC_OS2_CP->MultiByteTable = pGlyph_NEC_OS2_Table;
  1642. return TRUE;
  1643. }
  1644. #endif // i386
  1645. BYTE
  1646. CodePageToCharSet(
  1647. UINT CodePage
  1648. )
  1649. {
  1650. CHARSETINFO csi;
  1651. if (!TranslateCharsetInfo(IntToPtr(CodePage), &csi, TCI_SRCCODEPAGE)) {
  1652. csi.ciCharset = OEM_CHARSET;
  1653. }
  1654. return (BYTE)csi.ciCharset;
  1655. }
  1656. BOOL
  1657. IsAvailableFarEastCodePage(
  1658. UINT CodePage
  1659. )
  1660. {
  1661. BYTE CharSet = CodePageToCharSet(CodePage);
  1662. return IS_ANY_DBCS_CHARSET(CharSet);
  1663. }
  1664. LPTTFONTLIST
  1665. SearchTTFont(
  1666. LPWSTR pwszFace,
  1667. BOOL fCodePage,
  1668. UINT CodePage
  1669. )
  1670. {
  1671. PSINGLE_LIST_ENTRY pTemp = gTTFontList.Next;
  1672. if (pwszFace) {
  1673. while (pTemp != NULL) {
  1674. LPTTFONTLIST pTTFontList = (LPTTFONTLIST)pTemp;
  1675. if (wcscmp(pwszFace, pTTFontList->FaceName1) == 0 ||
  1676. wcscmp(pwszFace, pTTFontList->FaceName2) == 0) {
  1677. if (fCodePage) {
  1678. if (pTTFontList->CodePage == CodePage) {
  1679. return pTTFontList;
  1680. } else {
  1681. return NULL;
  1682. }
  1683. } else {
  1684. return pTTFontList;
  1685. }
  1686. }
  1687. pTemp = pTemp->Next;
  1688. }
  1689. }
  1690. return NULL;
  1691. }
  1692. BOOL
  1693. IsAvailableTTFont(
  1694. LPWSTR pwszFace
  1695. )
  1696. {
  1697. if (SearchTTFont(pwszFace, FALSE, 0)) {
  1698. return TRUE;
  1699. } else {
  1700. return FALSE;
  1701. }
  1702. }
  1703. BOOL
  1704. IsAvailableTTFontCP(
  1705. LPWSTR pwszFace,
  1706. UINT CodePage
  1707. )
  1708. {
  1709. if (SearchTTFont(pwszFace, TRUE, CodePage)) {
  1710. return TRUE;
  1711. } else {
  1712. return FALSE;
  1713. }
  1714. }
  1715. LPWSTR
  1716. GetAltFaceName(
  1717. LPWSTR pwszFace
  1718. )
  1719. {
  1720. LPTTFONTLIST pTTFontList;
  1721. pTTFontList = SearchTTFont(pwszFace, FALSE, 0);
  1722. if (pTTFontList != NULL) {
  1723. if (wcscmp(pwszFace, pTTFontList->FaceName1) == 0) {
  1724. return pTTFontList->FaceName2;
  1725. }
  1726. if (wcscmp(pwszFace, pTTFontList->FaceName2) == 0) {
  1727. return pTTFontList->FaceName1;
  1728. }
  1729. return NULL;
  1730. } else {
  1731. return NULL;
  1732. }
  1733. }
  1734. BOOL
  1735. IsAvailableFsCodePage(
  1736. UINT CodePage
  1737. )
  1738. {
  1739. PSINGLE_LIST_ENTRY pTemp = gRegFullScreenCodePage.Next;
  1740. while (pTemp != NULL) {
  1741. PFS_CODEPAGE pFsCodePage = (PFS_CODEPAGE)pTemp;
  1742. if (pFsCodePage->CodePage == CodePage) {
  1743. return TRUE;
  1744. }
  1745. pTemp = pTemp->Next;
  1746. }
  1747. return FALSE;
  1748. }
  1749. #if defined(FE_IME)
  1750. /*
  1751. * Console IME executing logic.
  1752. *
  1753. * KERNEL32:ConDllInitialize
  1754. * If Reason is DLL_PROCESS_ATTACH
  1755. * |
  1756. * V
  1757. * WINSRV:ConsoleClientConnectRoutine
  1758. * |
  1759. * V
  1760. * SetUpConsole
  1761. * |
  1762. * V
  1763. * AllocateConsole
  1764. * PostThreadMessage(CM_CREATE_CONSOLE_WINDOW)
  1765. * |
  1766. * V
  1767. * UnlockConsoleHandleTable
  1768. * InitConsoleIMEStuff
  1769. * |
  1770. * V
  1771. * If never register console IME
  1772. * hThread = InternalCreateCallbackThread(ConsoleIMERoutine)
  1773. * QueueThreadMessage(CM_WAIT_CONIME_PROCESS)
  1774. * |
  1775. * V
  1776. * QueueThreadMessage(CM_CONIME_CREATE)
  1777. * |
  1778. * V
  1779. * KERNEL32:NtWaitForMultipleObjects(InitEvents)
  1780. *
  1781. *
  1782. * WINSRV:InputThread
  1783. * |
  1784. * V
  1785. * GetMessage
  1786. * Receive CM_CREATE_CONSOLE_WINDOW
  1787. * |
  1788. * V
  1789. * ProcessCreateConsoleWindow
  1790. * |
  1791. * V
  1792. * CreateWindowsWindow
  1793. * |
  1794. * V
  1795. * CreateWindowEx
  1796. * NtSetEvent(InitEvents)
  1797. * |
  1798. * V
  1799. * GetMessage
  1800. * Receive CM_WAIT_CONIME_PROCESS (this case is never register console IME)
  1801. * |
  1802. * V
  1803. * WaitConsoleIMEStuff
  1804. * If never register console IME
  1805. * NtWaitForSingleObject(hThread, 20 sec)
  1806. *
  1807. *
  1808. * KERNEL32:ConsoleIMERoutine
  1809. * |
  1810. * V
  1811. * hEvent = CreateEvent(CONSOLEIME_EVENT)
  1812. * If not exist named event
  1813. * CreateProcess(conime.exe)
  1814. * WaitForSingleObject(hEvent, 10 sec)
  1815. * If WAIT_TIMEOUT
  1816. * TerminateProcess
  1817. * |
  1818. * V
  1819. * TerminateThread(hThread)
  1820. *
  1821. *
  1822. * CONIME:WinMain
  1823. * |
  1824. * V
  1825. * CreateWindow
  1826. * RegisterConsoleIME
  1827. * |
  1828. * V
  1829. * WINSRV:ConSrvRegisterConsoleIME
  1830. * |
  1831. * V
  1832. * QueueThreadMessage(CM_SET_CONSOLEIME_WINDOW)
  1833. * |
  1834. * V
  1835. * AttachThreadInput
  1836. * SetEvent(CONSOLEIME_EVENT)
  1837. *
  1838. *
  1839. * WINSRV:InputThread
  1840. * |
  1841. * V
  1842. * GetMessage
  1843. * Receive CM_CONIME_CREATE
  1844. * |
  1845. * V
  1846. * ProcessCreateConsoleIME
  1847. * If available hWndConsoleIME
  1848. * hIMC = SendMessage(console IME, CONIME_CREATE)
  1849. * Else
  1850. * PostMessage(CM_CONIME_CREATE)
  1851. * |
  1852. * V
  1853. * GetMessage
  1854. * Receive CM_SET_CONSOLEIME_WINDOW
  1855. * TlsGetValue()->hWndConsoleIME = wParam
  1856. *
  1857. *
  1858. * TerminateProcess of Console IME
  1859. * WINSRV:ConsoleClientDisconnectRoutine
  1860. * |
  1861. * V
  1862. * RemoveConsoleIME
  1863. */
  1864. VOID
  1865. ProcessCreateConsoleIME(
  1866. IN LPMSG lpMsg,
  1867. DWORD dwConsoleThreadId)
  1868. {
  1869. NTSTATUS Status;
  1870. HANDLE ConsoleHandle = (HANDLE)lpMsg->wParam;
  1871. PCONSOLE_INFORMATION pConsole;
  1872. HWND hwndConIme;
  1873. Status = RevalidateConsole(ConsoleHandle, &pConsole);
  1874. if (!NT_SUCCESS(Status)) {
  1875. return;
  1876. }
  1877. hwndConIme = pConsole->InputThreadInfo->hWndConsoleIME;
  1878. if (pConsole->InputThreadInfo->hWndConsoleIME != NULL) {
  1879. LRESULT lResult;
  1880. Status = ConsoleImeMessagePumpWorker(pConsole,
  1881. CONIME_CREATE,
  1882. (WPARAM)pConsole->ConsoleHandle,
  1883. (LPARAM)pConsole->hWnd,
  1884. &lResult);
  1885. if (!NT_SUCCESS(Status)) {
  1886. goto TerminateConsoleIme;
  1887. }
  1888. if (lResult) {
  1889. if (!CONSOLE_IS_DBCS_CP(pConsole)) {
  1890. pConsole->InputBuffer.ImeMode.Disable = TRUE;
  1891. }
  1892. CreateConvAreaModeSystem(pConsole);
  1893. if ((pConsole->Flags & CONSOLE_HAS_FOCUS) ||
  1894. (pConsole->FullScreenFlags & CONSOLE_FULLSCREEN_HARDWARE)) {
  1895. Status = ConsoleImeMessagePump(pConsole,
  1896. CONIME_SETFOCUS,
  1897. (WPARAM)pConsole->ConsoleHandle,
  1898. (LPARAM)pConsole->hklActive);
  1899. if (!NT_SUCCESS(Status)) {
  1900. goto TerminateConsoleIme;
  1901. }
  1902. }
  1903. if (pConsole->CurrentScreenBuffer->Flags & CONSOLE_TEXTMODE_BUFFER) {
  1904. Status = ConsoleImeMessagePump(pConsole,
  1905. CONIME_NOTIFY_SCREENBUFFERSIZE,
  1906. (WPARAM)pConsole->ConsoleHandle,
  1907. MAKELPARAM(pConsole->CurrentScreenBuffer->ScreenBufferSize.X,
  1908. pConsole->CurrentScreenBuffer->ScreenBufferSize.Y));
  1909. if (!NT_SUCCESS(Status)) {
  1910. goto TerminateConsoleIme;
  1911. }
  1912. }
  1913. Status = ConsoleImeMessagePump(pConsole,
  1914. CONIME_NOTIFY_CODEPAGE,
  1915. (WPARAM)pConsole->ConsoleHandle,
  1916. MAKELPARAM(FALSE, pConsole->CP));
  1917. if (!NT_SUCCESS(Status)) {
  1918. goto TerminateConsoleIme;
  1919. }
  1920. Status = ConsoleImeMessagePump(pConsole,
  1921. CONIME_NOTIFY_CODEPAGE,
  1922. (WPARAM)pConsole->ConsoleHandle,
  1923. MAKELPARAM(TRUE, pConsole->OutputCP));
  1924. if (!NT_SUCCESS(Status)) {
  1925. goto TerminateConsoleIme;
  1926. }
  1927. Status = GetImeKeyState(pConsole, NULL);
  1928. if (!NT_SUCCESS(Status)) {
  1929. goto TerminateConsoleIme;
  1930. }
  1931. }
  1932. } else if (lpMsg->lParam) {
  1933. /*
  1934. * This case, First = TRUE
  1935. * Again post message of CM_CONIME_CREATE.
  1936. * Becase hWndConsoleIME available when CM_SET_CONSOLEIME_WINDOW message
  1937. * and it message will be run after this.
  1938. */
  1939. Status = QueueThreadMessage(dwConsoleThreadId,
  1940. CM_CONIME_CREATE,
  1941. (WPARAM)ConsoleHandle,
  1942. FALSE);
  1943. if (!NT_SUCCESS(Status)) {
  1944. RIPMSG1(RIP_WARNING,
  1945. "QueueThreadMessage(CM_CONIME_CREATE) failed (0x%x)",
  1946. Status);
  1947. }
  1948. }
  1949. UnlockConsole(pConsole);
  1950. return;
  1951. TerminateConsoleIme:
  1952. RIPMSG1(RIP_WARNING,
  1953. "ProcessCreateConsoleIme failing with status 0x%x",
  1954. Status);
  1955. if (IsWindow(hwndConIme)) {
  1956. PostMessage(hwndConIme, CONIME_DESTROY, (WPARAM)ConsoleHandle, (LPARAM)NULL);
  1957. }
  1958. UnlockConsole(pConsole);
  1959. }
  1960. NTSTATUS
  1961. InitConsoleIMEStuff(
  1962. HDESK hDesktop,
  1963. DWORD dwConsoleThreadId,
  1964. PCONSOLE_INFORMATION Console
  1965. )
  1966. {
  1967. NTSTATUS Status = STATUS_SUCCESS;
  1968. CONSOLE_REGISTER_CONSOLEIME RegConIMEInfo;
  1969. HANDLE hThread = NULL;
  1970. BOOL First = FALSE;
  1971. if (!gfLoadConIme) {
  1972. RIPMSG0(RIP_WARNING, "InitConsoleIMEStuff is skipping conime loading");
  1973. return STATUS_UNSUCCESSFUL; // the return value does not really matter...
  1974. }
  1975. RtlEnterCriticalSection(&ConIMEInitWindowsLock);
  1976. RegConIMEInfo.hdesk = hDesktop;
  1977. RegConIMEInfo.dwThreadId = 0;
  1978. RegConIMEInfo.dwAction = REGCONIME_QUERY;
  1979. NtUserConsoleControl(ConsoleRegisterConsoleIME, &RegConIMEInfo, sizeof(RegConIMEInfo));
  1980. if (RegConIMEInfo.dwThreadId == 0) {
  1981. /*
  1982. * Create a Remote Thread on client side.
  1983. * This remote thread do create a console IME process.
  1984. */
  1985. hThread = InternalCreateCallbackThread(CONSOLE_CLIENTPROCESSHANDLE(),
  1986. (ULONG_PTR)ConsoleIMERoutine,
  1987. (ULONG_PTR)0);
  1988. if (hThread == NULL) {
  1989. RIPMSGF1(RIP_WARNING,
  1990. "CreateRemoteThread failed with error 0x%x",
  1991. GetLastError());
  1992. } else {
  1993. /*
  1994. * CM_WAIT_CONIME_PROCESS
  1995. * This message wait for ready to go console IME process.
  1996. */
  1997. Status = QueueThreadMessage(dwConsoleThreadId,
  1998. CM_WAIT_CONIME_PROCESS,
  1999. (WPARAM)hDesktop,
  2000. (LPARAM)hThread
  2001. );
  2002. if (!NT_SUCCESS(Status)) {
  2003. RIPMSG1(RIP_WARNING, "QueueThreadMessage(CM_WAIT_CONIME_PROCESS) failed (%08x)\n", Status);
  2004. } else {
  2005. First = TRUE;
  2006. }
  2007. }
  2008. }
  2009. Status = QueueThreadMessage(dwConsoleThreadId,
  2010. CM_CONIME_CREATE,
  2011. (WPARAM)Console->ConsoleHandle,
  2012. (LPARAM)First);
  2013. if (!NT_SUCCESS(Status)) {
  2014. RIPMSGF1(RIP_WARNING,
  2015. "QueueThreadMessage(CM_CONIME_CREATE) failed with status 0x%x",
  2016. Status);
  2017. }
  2018. RtlLeaveCriticalSection(&ConIMEInitWindowsLock);
  2019. return Status;
  2020. }
  2021. NTSTATUS
  2022. WaitConsoleIMEStuff(
  2023. HDESK hDesktop,
  2024. HANDLE hThread
  2025. )
  2026. {
  2027. NTSTATUS Status = STATUS_SUCCESS;
  2028. CONSOLE_REGISTER_CONSOLEIME RegConIMEInfo;
  2029. RtlEnterCriticalSection(&ConIMEInitWindowsLock);
  2030. RegConIMEInfo.hdesk = hDesktop;
  2031. RegConIMEInfo.dwThreadId = 0;
  2032. RegConIMEInfo.dwAction = REGCONIME_QUERY;
  2033. NtUserConsoleControl(ConsoleRegisterConsoleIME, &RegConIMEInfo, sizeof(RegConIMEInfo));
  2034. RtlLeaveCriticalSection(&ConIMEInitWindowsLock);
  2035. if (RegConIMEInfo.dwThreadId == 0) {
  2036. int cLoops;
  2037. LARGE_INTEGER li;
  2038. /*
  2039. * Do wait for ready to go console IME process.
  2040. *
  2041. * This wait code should after the CreateWindowsWindow
  2042. * because doesn't finish DLL attach on client side
  2043. * for wait a Console->InitEvents.
  2044. */
  2045. cLoops = 80;
  2046. li.QuadPart = (LONGLONG)-10000 * 250;
  2047. while (cLoops--) {
  2048. /*
  2049. * Sleep for a second.
  2050. */
  2051. Status = NtWaitForSingleObject(hThread, FALSE, &li);
  2052. if (Status != STATUS_TIMEOUT) {
  2053. break;
  2054. }
  2055. RtlEnterCriticalSection(&ConIMEInitWindowsLock);
  2056. RegConIMEInfo.hdesk = hDesktop;
  2057. RegConIMEInfo.dwThreadId = 0;
  2058. RegConIMEInfo.dwAction = REGCONIME_QUERY;
  2059. NtUserConsoleControl(ConsoleRegisterConsoleIME, &RegConIMEInfo, sizeof(RegConIMEInfo));
  2060. RtlLeaveCriticalSection(&ConIMEInitWindowsLock);
  2061. if (RegConIMEInfo.dwThreadId != 0) {
  2062. break;
  2063. }
  2064. }
  2065. }
  2066. NtClose(hThread);
  2067. return Status;
  2068. }
  2069. NTSTATUS
  2070. ConSrvRegisterConsoleIME(
  2071. PCSR_PROCESS Process,
  2072. HDESK hDesktop,
  2073. HWINSTA hWinSta,
  2074. HWND hWndConsoleIME,
  2075. DWORD dwConsoleIMEThreadId,
  2076. DWORD dwAction,
  2077. DWORD *dwConsoleThreadId
  2078. )
  2079. {
  2080. NTSTATUS Status;
  2081. CONSOLE_REGISTER_CONSOLEIME RegConIMEInfo;
  2082. PCONSOLE_PER_PROCESS_DATA ProcessData;
  2083. RtlEnterCriticalSection(&ConIMEInitWindowsLock);
  2084. ProcessData = CONSOLE_FROMPROCESSPERPROCESSDATA(Process);
  2085. RegConIMEInfo.hdesk = hDesktop;
  2086. RegConIMEInfo.dwThreadId = 0;
  2087. RegConIMEInfo.dwAction = REGCONIME_QUERY;
  2088. NtUserConsoleControl(ConsoleRegisterConsoleIME, &RegConIMEInfo, sizeof(RegConIMEInfo));
  2089. if (RegConIMEInfo.dwConsoleInputThreadId == 0) {
  2090. Status = STATUS_UNSUCCESSFUL;
  2091. goto ErrorExit;
  2092. }
  2093. if (RegConIMEInfo.dwThreadId == 0) {
  2094. /*
  2095. * Never registered console ime thread.
  2096. */
  2097. if (dwAction == REGCONIME_REGISTER) {
  2098. /*
  2099. * register
  2100. */
  2101. RegConIMEInfo.hdesk = hDesktop;
  2102. RegConIMEInfo.dwThreadId = dwConsoleIMEThreadId;
  2103. RegConIMEInfo.dwAction = dwAction;
  2104. Status = NtUserConsoleControl(ConsoleRegisterConsoleIME, &RegConIMEInfo, sizeof(RegConIMEInfo));
  2105. if (NT_SUCCESS(Status)) {
  2106. Status = QueueThreadMessage(RegConIMEInfo.dwConsoleInputThreadId,
  2107. CM_SET_CONSOLEIME_WINDOW,
  2108. (WPARAM)hWndConsoleIME,
  2109. 0);
  2110. if (!NT_SUCCESS(Status)) {
  2111. RIPMSGF1(RIP_WARNING,
  2112. "QueueThreadMessage failed with status 0x%x",
  2113. Status);
  2114. Status = STATUS_UNSUCCESSFUL;
  2115. goto ErrorExit;
  2116. }
  2117. ProcessData->hDesk = hDesktop;
  2118. ProcessData->hWinSta = hWinSta;
  2119. if (dwConsoleThreadId) {
  2120. *dwConsoleThreadId = RegConIMEInfo.dwConsoleInputThreadId;
  2121. }
  2122. }
  2123. } else {
  2124. Status = STATUS_UNSUCCESSFUL;
  2125. goto ErrorExit;
  2126. }
  2127. } else {
  2128. /*
  2129. * Do registered console ime thread.
  2130. */
  2131. if (dwAction == REGCONIME_UNREGISTER || dwAction == REGCONIME_TERMINATE) {
  2132. /*
  2133. * unregister
  2134. */
  2135. RegConIMEInfo.hdesk = hDesktop;
  2136. RegConIMEInfo.dwThreadId = dwConsoleIMEThreadId;
  2137. RegConIMEInfo.dwAction = dwAction;
  2138. Status = NtUserConsoleControl(ConsoleRegisterConsoleIME, &RegConIMEInfo, sizeof(RegConIMEInfo));
  2139. if (NT_SUCCESS(Status)) {
  2140. Status = QueueThreadMessage(RegConIMEInfo.dwConsoleInputThreadId,
  2141. CM_SET_CONSOLEIME_WINDOW,
  2142. (WPARAM)NULL,
  2143. 0);
  2144. if (!NT_SUCCESS(Status)) {
  2145. RIPMSGF1(RIP_WARNING,
  2146. "QueueThreadMessage failed with status 0x%x",
  2147. Status);
  2148. Status = STATUS_UNSUCCESSFUL;
  2149. goto ErrorExit;
  2150. }
  2151. CloseDesktop(ProcessData->hDesk);
  2152. CloseWindowStation(ProcessData->hWinSta);
  2153. ProcessData->hDesk = NULL;
  2154. ProcessData->hWinSta = NULL;
  2155. if (dwConsoleThreadId) {
  2156. *dwConsoleThreadId = RegConIMEInfo.dwConsoleInputThreadId;
  2157. }
  2158. }
  2159. } else {
  2160. Status = STATUS_UNSUCCESSFUL;
  2161. goto ErrorExit;
  2162. }
  2163. }
  2164. ErrorExit:
  2165. if (!NT_SUCCESS(Status)) {
  2166. CloseDesktop(hDesktop);
  2167. CloseWindowStation(hWinSta);
  2168. }
  2169. RtlLeaveCriticalSection(&ConIMEInitWindowsLock);
  2170. return Status;
  2171. }
  2172. VOID
  2173. RemoveConsoleIME(
  2174. PCSR_PROCESS Process,
  2175. DWORD dwConsoleIMEThreadId
  2176. )
  2177. {
  2178. NTSTATUS Status;
  2179. CONSOLE_REGISTER_CONSOLEIME RegConIMEInfo;
  2180. PCONSOLE_PER_PROCESS_DATA ProcessData;
  2181. ProcessData = CONSOLE_FROMPROCESSPERPROCESSDATA(Process);
  2182. //
  2183. // This is console IME process
  2184. //
  2185. RtlEnterCriticalSection(&ConIMEInitWindowsLock);
  2186. RegConIMEInfo.hdesk = ProcessData->hDesk;
  2187. RegConIMEInfo.dwThreadId = 0;
  2188. RegConIMEInfo.dwAction = REGCONIME_QUERY;
  2189. NtUserConsoleControl(ConsoleRegisterConsoleIME, &RegConIMEInfo, sizeof(RegConIMEInfo));
  2190. if (RegConIMEInfo.dwConsoleInputThreadId == 0) {
  2191. Status = STATUS_UNSUCCESSFUL;
  2192. } else if (dwConsoleIMEThreadId == RegConIMEInfo.dwThreadId) {
  2193. /*
  2194. * Unregister console IME
  2195. */
  2196. Status = ConSrvRegisterConsoleIME(Process,
  2197. ProcessData->hDesk,
  2198. ProcessData->hWinSta,
  2199. NULL,
  2200. dwConsoleIMEThreadId,
  2201. REGCONIME_TERMINATE,
  2202. NULL);
  2203. }
  2204. RtlLeaveCriticalSection(&ConIMEInitWindowsLock);
  2205. }
  2206. /*
  2207. * Console IME message pump.
  2208. *
  2209. * Note for NT5 --- this function is build on bogus assumptions
  2210. * (also has some nasty workaround for sloppy conime).
  2211. * There's a chance that pConsole goes away while sendmessage
  2212. * is processed by conime.
  2213. * Keep in mind, anybody who calls this function should validate
  2214. * the return status as appropriate.
  2215. */
  2216. NTSTATUS
  2217. ConsoleImeMessagePumpWorker(
  2218. PCONSOLE_INFORMATION Console,
  2219. UINT Message,
  2220. WPARAM wParam,
  2221. LPARAM lParam,
  2222. LRESULT* lplResult)
  2223. {
  2224. HWND hWndConsoleIME = Console->InputThreadInfo->hWndConsoleIME;
  2225. LRESULT fNoTimeout;
  2226. PINPUT_THREAD_INFO InputThreadInfo;
  2227. *lplResult = 0;
  2228. if (hWndConsoleIME == NULL) {
  2229. return STATUS_SUCCESS;
  2230. }
  2231. InputThreadInfo = TlsGetValue(InputThreadTlsIndex);
  2232. if (InputThreadInfo != NULL) {
  2233. HWND hWnd = Console->hWnd;
  2234. /*
  2235. * We're being called on the Console Input Thread, so we can pump
  2236. * messages safely.
  2237. */
  2238. fNoTimeout = SendMessageTimeout(hWndConsoleIME,
  2239. Message,
  2240. wParam,
  2241. lParam,
  2242. SMTO_ABORTIFHUNG | SMTO_NORMAL,
  2243. CONIME_SENDMSG_TIMEOUT,
  2244. lplResult);
  2245. if (fNoTimeout) {
  2246. return STATUS_SUCCESS;
  2247. }
  2248. if ((Console = GetWindowConsole(hWnd)) == NULL ||
  2249. (Console->Flags & CONSOLE_TERMINATING)) {
  2250. //
  2251. // This console is terminated. ConsoleImeMessagePump gives up
  2252. // SendMessage to conime.
  2253. //
  2254. return STATUS_INVALID_HANDLE;
  2255. }
  2256. //
  2257. // Timeout return from SendMessageTimeout or hung hWndConsoleIME.
  2258. //
  2259. }
  2260. /*
  2261. * We're being called from an LPC worker thread, so we cannot safely
  2262. * pump messages.
  2263. */
  2264. PostMessage(hWndConsoleIME, Message, wParam, lParam);
  2265. return STATUS_SUCCESS;
  2266. }
  2267. NTSTATUS
  2268. ConsoleImeMessagePump(
  2269. PCONSOLE_INFORMATION Console,
  2270. UINT Message,
  2271. WPARAM wParam,
  2272. LPARAM lParam
  2273. )
  2274. {
  2275. LRESULT lResultDummy;
  2276. return ConsoleImeMessagePumpWorker(Console, Message, wParam, lParam, &lResultDummy);
  2277. }
  2278. #endif // FE_IME
  2279. BOOL
  2280. RegisterKeisenOfTTFont(
  2281. IN PSCREEN_INFORMATION ScreenInfo
  2282. )
  2283. {
  2284. NTSTATUS Status;
  2285. COORD FontSize;
  2286. DWORD BuffSize;
  2287. LPSTRINGBITMAP StringBitmap;
  2288. WCHAR wChar;
  2289. WCHAR wCharBuf[2];
  2290. ULONG ulNumFonts;
  2291. DWORD dwFonts;
  2292. PCONSOLE_INFORMATION Console = ScreenInfo->Console;
  2293. GetNumFonts(&ulNumFonts);
  2294. for (dwFonts = 0; dwFonts < ulNumFonts; dwFonts++) {
  2295. if (!TM_IS_TT_FONT(FontInfo[dwFonts].Family) &&
  2296. IS_ANY_DBCS_CHARSET(FontInfo[dwFonts].tmCharSet)) {
  2297. GetFontSize(dwFonts, &FontSize);
  2298. BuffSize = CalcBitmapBufferSize(FontSize,BYTE_ALIGN);
  2299. StringBitmap = ConsoleHeapAlloc(TMP_DBCS_TAG, sizeof(STRINGBITMAP) + BuffSize);
  2300. if (StringBitmap == NULL) {
  2301. RIPMSGF1(RIP_WARNING,
  2302. "Cannot allocate 0n%d bytes",
  2303. sizeof(STRINGBITMAP) + BuffSize);
  2304. return FALSE;
  2305. }
  2306. if (SelectObject(Console->hDC,FontInfo[dwFonts].hFont)==0) {
  2307. goto error_return;
  2308. }
  2309. for (wChar=0; wChar < UNICODE_SPACE; wChar++) {
  2310. wCharBuf[0] = wChar;
  2311. wCharBuf[1] = TEXT('\0');
  2312. if (GetStringBitmapW(Console->hDC,
  2313. wCharBuf,
  2314. 1,
  2315. sizeof(STRINGBITMAP) + BuffSize,
  2316. (BYTE*)StringBitmap) == 0) {
  2317. goto error_return;
  2318. }
  2319. FontSize.X = (WORD)StringBitmap->uiWidth;
  2320. FontSize.Y = (WORD)StringBitmap->uiHeight;
  2321. Status = RegisterLocalEUDC(Console,wChar,FontSize,StringBitmap->ajBits);
  2322. if (!NT_SUCCESS(Status)) {
  2323. error_return:
  2324. ConsoleHeapFree(StringBitmap);
  2325. return FALSE;
  2326. }
  2327. }
  2328. ConsoleHeapFree(StringBitmap);
  2329. }
  2330. ((PEUDC_INFORMATION)(Console->EudcInformation))->LocalKeisenEudcMode = TRUE;
  2331. }
  2332. return TRUE;
  2333. }
  2334. ULONG
  2335. TranslateUnicodeToOem(
  2336. IN PCONSOLE_INFORMATION Console,
  2337. IN PWCHAR UnicodeBuffer,
  2338. IN ULONG UnicodeCharCount,
  2339. OUT PCHAR AnsiBuffer,
  2340. IN ULONG AnsiByteCount,
  2341. OUT PINPUT_RECORD DbcsLeadInpRec
  2342. )
  2343. {
  2344. ULONG i,j;
  2345. PWCHAR TmpUni;
  2346. BYTE AsciiDbcs[2];
  2347. ULONG NumBytes;
  2348. TmpUni = ConsoleHeapAlloc(TMP_DBCS_TAG, UnicodeCharCount * sizeof(WCHAR));
  2349. if (TmpUni == NULL) {
  2350. return 0;
  2351. }
  2352. memcpy(TmpUni, UnicodeBuffer, UnicodeCharCount * sizeof(WCHAR));
  2353. AsciiDbcs[1] = 0;
  2354. for (i = 0, j = 0; i < UnicodeCharCount; i++, j++) {
  2355. if (IsConsoleFullWidth(Console->hDC,Console->CP,TmpUni[i])) {
  2356. NumBytes = sizeof(AsciiDbcs);
  2357. ConvertToOem(Console->CP,
  2358. &TmpUni[i],
  2359. 1,
  2360. &AsciiDbcs[0],
  2361. NumBytes);
  2362. if (IsDBCSLeadByteConsole(AsciiDbcs[0],&Console->CPInfo)) {
  2363. if (j < AnsiByteCount - 1) { // -1 is safe DBCS in buffer
  2364. AnsiBuffer[j] = AsciiDbcs[0];
  2365. j++;
  2366. AnsiBuffer[j] = AsciiDbcs[1];
  2367. AsciiDbcs[1] = 0;
  2368. } else if (j == AnsiByteCount - 1) {
  2369. AnsiBuffer[j] = AsciiDbcs[0];
  2370. j++;
  2371. break;
  2372. } else {
  2373. AsciiDbcs[1] = 0;
  2374. break;
  2375. }
  2376. } else {
  2377. AnsiBuffer[j] = AsciiDbcs[0];
  2378. AsciiDbcs[1] = 0;
  2379. }
  2380. } else {
  2381. ConvertToOem(Console->CP,
  2382. &TmpUni[i],
  2383. 1,
  2384. &AnsiBuffer[j],
  2385. 1);
  2386. }
  2387. }
  2388. if (DbcsLeadInpRec) {
  2389. if (AsciiDbcs[1]) {
  2390. DbcsLeadInpRec->EventType = KEY_EVENT;
  2391. DbcsLeadInpRec->Event.KeyEvent.uChar.AsciiChar = AsciiDbcs[1];
  2392. } else {
  2393. RtlZeroMemory(DbcsLeadInpRec,sizeof(INPUT_RECORD));
  2394. }
  2395. }
  2396. ConsoleHeapFree(TmpUni);
  2397. return j;
  2398. }
  2399. DWORD
  2400. ImmConversionToConsole(
  2401. DWORD fdwConversion
  2402. )
  2403. {
  2404. DWORD dwNlsMode;
  2405. if (GetKeyState(VK_KANA) & KEY_TOGGLED) {
  2406. fdwConversion = (fdwConversion & ~IME_CMODE_LANGUAGE) | (IME_CMODE_NATIVE | IME_CMODE_KATAKANA);
  2407. }
  2408. dwNlsMode = 0;
  2409. if (fdwConversion & IME_CMODE_NATIVE) {
  2410. if (fdwConversion & IME_CMODE_KATAKANA)
  2411. dwNlsMode |= NLS_KATAKANA;
  2412. else
  2413. dwNlsMode |= NLS_HIRAGANA;
  2414. } else {
  2415. dwNlsMode |= NLS_ALPHANUMERIC;
  2416. }
  2417. if (fdwConversion & IME_CMODE_FULLSHAPE) {
  2418. dwNlsMode |= NLS_DBCSCHAR;
  2419. }
  2420. if (fdwConversion & IME_CMODE_ROMAN) {
  2421. dwNlsMode |= NLS_ROMAN;
  2422. }
  2423. if (fdwConversion & IME_CMODE_OPEN) {
  2424. dwNlsMode |= NLS_IME_CONVERSION;
  2425. }
  2426. if (fdwConversion & IME_CMODE_DISABLE) {
  2427. dwNlsMode |= NLS_IME_DISABLE;
  2428. }
  2429. return dwNlsMode;
  2430. }
  2431. DWORD
  2432. ImmConversionFromConsole(
  2433. DWORD dwNlsMode
  2434. )
  2435. {
  2436. DWORD fdwConversion;
  2437. fdwConversion = 0;
  2438. if (dwNlsMode & (NLS_KATAKANA | NLS_HIRAGANA)) {
  2439. fdwConversion |= IME_CMODE_NATIVE;
  2440. if (dwNlsMode & NLS_KATAKANA)
  2441. fdwConversion |= IME_CMODE_KATAKANA;
  2442. }
  2443. if (dwNlsMode & NLS_DBCSCHAR) {
  2444. fdwConversion |= IME_CMODE_FULLSHAPE;
  2445. }
  2446. if (dwNlsMode & NLS_ROMAN) {
  2447. fdwConversion |= IME_CMODE_ROMAN;
  2448. }
  2449. if (dwNlsMode & NLS_IME_CONVERSION) {
  2450. fdwConversion |= IME_CMODE_OPEN;
  2451. }
  2452. if (dwNlsMode & NLS_IME_DISABLE) {
  2453. fdwConversion |= IME_CMODE_DISABLE;
  2454. }
  2455. return fdwConversion;
  2456. }
  2457. #if DBG && defined(DBG_KATTR)
  2458. VOID
  2459. BeginKAttrCheck(
  2460. IN PSCREEN_INFORMATION ScreenInfo
  2461. )
  2462. {
  2463. SHORT RowIndex;
  2464. PROW Row;
  2465. SHORT i;
  2466. RowIndex = (ScreenInfo->BufferInfo.TextInfo.FirstRow) % ScreenInfo->ScreenBufferSize.Y;
  2467. Row = &ScreenInfo->BufferInfo.TextInfo.Rows[RowIndex];
  2468. for (i=0;i<ScreenInfo->ScreenBufferSize.Y;i++) {
  2469. UserAssert(Row->CharRow.KAttrs);
  2470. if (++RowIndex == ScreenInfo->ScreenBufferSize.Y) {
  2471. RowIndex = 0;
  2472. }
  2473. }
  2474. }
  2475. #endif
  2476. #endif