Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

output.c

Go to the documentation of this file.
00001 /*++ 00002 00003 Copyright (c) 1985 - 1999, Microsoft Corporation 00004 00005 Module Name: 00006 00007 output.c 00008 00009 Abstract: 00010 00011 This file implements the video buffer management. 00012 00013 Author: 00014 00015 Therese Stowell (thereses) 6-Nov-1990 00016 00017 Revision History: 00018 00019 Notes: 00020 00021 ScreenBuffer data structure overview: 00022 00023 each screen buffer has an array of ROW structures. each ROW structure 00024 contains the data for one row of text. the data stored for one row of 00025 text is a character array and an attribute array. the character array 00026 is allocated the full length of the row from the heap, regardless of the 00027 non-space length. we also maintain the non-space length. the character 00028 array is initialized to spaces. the attribute 00029 array is run length encoded (i.e 5 BLUE, 3 RED). if there is only one 00030 attribute for the whole row (the normal case), it is stored in the ATTR_ROW 00031 structure. otherwise the attr string is allocated from the heap. 00032 00033 ROW - CHAR_ROW - CHAR string 00034 \ \ length of char string 00035 \ 00036 ATTR_ROW - ATTR_PAIR string 00037 \ length of attr pair string 00038 ROW 00039 ROW 00040 ROW 00041 00042 ScreenInfo->Rows points to the ROW array. ScreenInfo->Rows[0] is not 00043 necessarily the top row. ScreenInfo->BufferInfo.TextInfo.FirstRow contains the index of 00044 the top row. That means scrolling (if scrolling entire screen) 00045 merely involves changing the FirstRow index, 00046 filling in the last row, and updating the screen. 00047 00048 --*/ 00049 00050 #include "precomp.h" 00051 #pragma hdrstop 00052 00053 00054 //#define THERESES_DEBUG 1 00055 00056 //#define PROFILE_GDI 00057 #ifdef PROFILE_GDI 00058 LONG ScrollDCCount; 00059 LONG ExtTextOutCount; 00060 LONG TextColor=1; 00061 00062 #define SCROLLDC_CALL ScrollDCCount++ 00063 #define TEXTOUT_CALL ExtTextOutCount++ 00064 #define TEXTCOLOR_CALL TextColor++ 00065 #else 00066 #define SCROLLDC_CALL 00067 #define TEXTOUT_CALL 00068 #define TEXTCOLOR_CALL 00069 #endif 00070 00071 #define ITEM_MAX_SIZE 256 00072 00073 // BUGBUG get the real include file from progman 00074 typedef struct _PMIconData { 00075 DWORD dwResSize; 00076 DWORD dwVer; 00077 BYTE iResource; // icon resource 00078 } PMICONDATA, *LPPMICONDATA; 00079 00080 // 00081 // Screen dimensions 00082 // 00083 00084 int ConsoleFullScreenX; 00085 int ConsoleFullScreenY; 00086 int ConsoleCaptionY; 00087 int MinimumWidthX; 00088 SHORT VerticalScrollSize; 00089 SHORT HorizontalScrollSize; 00090 00091 SHORT VerticalClientToWindow; 00092 SHORT HorizontalClientToWindow; 00093 00094 PCHAR_INFO ScrollBuffer; 00095 ULONG ScrollBufferSize; 00096 CRITICAL_SECTION ScrollBufferLock; 00097 00098 // this value keeps track of the number of existing console windows. 00099 // if a window is created when this value is zero, the Face Names 00100 // must be reenumerated because no WM_FONTCHANGE message was processed 00101 // if there's no window. 00102 LONG gnConsoleWindows; 00103 00104 BOOL gfInitSystemMetrics; 00105 00106 BOOL UsePolyTextOut; 00107 00108 HRGN ghrgnScroll; 00109 LPRGNDATA gprgnData; 00110 00111 ULONG gucWheelScrollLines; 00112 00113 UINT guCaretBlinkTime; 00114 00115 #define GRGNDATASIZE (sizeof(RGNDATAHEADER) + (6 * sizeof(RECTL))) 00116 00117 00118 #define CharSizeOf(x) (sizeof(x) / sizeof(*x)) 00119 #define LockScrollBuffer() RtlEnterCriticalSection(&ScrollBufferLock) 00120 #define UnlockScrollBuffer() RtlLeaveCriticalSection(&ScrollBufferLock) 00121 00122 #define SetWindowConsole(hWnd, Console) SetWindowLongPtr((hWnd), GWLP_USERDATA, (LONG_PTR)(Console)) 00123 00124 #ifdef LATER 00125 #ifndef IS_IME_KBDLAYOUT 00126 #define IS_IME_KBDLAYOUT(hkl) ((((ULONG_PTR)(hkl)) & 0xf0000000) == 0xe0000000) 00127 #endif 00128 #endif 00129 00130 00131 void GetNonBiDiKeyboardLayout(HKL * phklActive); 00132 00133 VOID FreeConsoleBitmap(IN PSCREEN_INFORMATION ScreenInfo); 00134 00135 VOID 00136 ScrollIfNecessary( 00137 IN PCONSOLE_INFORMATION Console, 00138 IN PSCREEN_INFORMATION ScreenInfo 00139 ); 00140 00141 VOID 00142 ProcessResizeWindow( 00143 IN PSCREEN_INFORMATION ScreenInfo, 00144 IN PCONSOLE_INFORMATION Console, 00145 IN LPWINDOWPOS WindowPos 00146 ); 00147 00148 NTSTATUS 00149 AllocateScrollBuffer( 00150 DWORD Size 00151 ); 00152 00153 VOID FreeScrollBuffer ( VOID ); 00154 00155 VOID 00156 InternalUpdateScrollBars( 00157 IN PSCREEN_INFORMATION ScreenInfo 00158 ); 00159 00160 #if defined(FE_SB) 00161 BOOL 00162 SB_PolyTextOutCandidate( 00163 IN PSCREEN_INFORMATION ScreenInfo, 00164 IN PSMALL_RECT Region 00165 ); 00166 00167 VOID 00168 SB_ConsolePolyTextOut( 00169 IN PSCREEN_INFORMATION ScreenInfo, 00170 IN PSMALL_RECT Region 00171 ); 00172 #endif 00173 00174 00175 00176 VOID 00177 InitializeSystemMetrics( VOID ) 00178 { 00179 RECT WindowSize; 00180 00181 gfInitSystemMetrics = FALSE; 00182 SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &gucWheelScrollLines, FALSE); 00183 ConsoleFullScreenX = GetSystemMetrics(SM_CXFULLSCREEN); 00184 ConsoleFullScreenY = GetSystemMetrics(SM_CYFULLSCREEN); 00185 ConsoleCaptionY = GetSystemMetrics(SM_CYCAPTION); 00186 VerticalScrollSize = (SHORT)GetSystemMetrics(SM_CXVSCROLL); 00187 HorizontalScrollSize = (SHORT)GetSystemMetrics(SM_CYHSCROLL); 00188 WindowSize.left = WindowSize.top = 0; 00189 WindowSize.right = WindowSize.bottom = 50; 00190 AdjustWindowRectEx(&WindowSize, 00191 CONSOLE_WINDOW_FLAGS, 00192 FALSE, 00193 CONSOLE_WINDOW_EX_FLAGS 00194 ); 00195 VerticalClientToWindow = (SHORT)(WindowSize.right-WindowSize.left-50); 00196 HorizontalClientToWindow = (SHORT)(WindowSize.bottom-WindowSize.top-50); 00197 00198 #ifdef LATER 00199 gfIsIMEEnabled = !!GetSystemMetrics(SM_IMMENABLED); 00200 RIPMSG1(RIP_VERBOSE, "InitializeSystemMetrics: gfIsIMEEnabled=%d", gfIsIMEEnabled); 00201 #endif 00202 00203 guCaretBlinkTime = GetCaretBlinkTime(); 00204 } 00205 00206 VOID 00207 GetWindowLimits( 00208 IN PSCREEN_INFORMATION ScreenInfo, 00209 OUT PWINDOW_LIMITS WindowLimits 00210 ) 00211 { 00212 HMONITOR hMonitor; 00213 MONITORINFO MonitorInfo = {sizeof(MonitorInfo)}; 00214 COORD FontSize; 00215 00216 // 00217 // If the system metrics have changed or there aren't any console 00218 // windows around, reinitialize the global valeus. 00219 // 00220 00221 if (gfInitSystemMetrics || gnConsoleWindows == 0) { 00222 InitializeSystemMetrics(); 00223 } 00224 00225 if (ScreenInfo->Console && 00226 (ScreenInfo->Console->hWnd || !(ScreenInfo->Console->Flags & CONSOLE_AUTO_POSITION)) && 00227 ((hMonitor = MonitorFromRect(&ScreenInfo->Console->WindowRect, MONITOR_DEFAULTTOPRIMARY)) != NULL) && 00228 GetMonitorInfo(hMonitor, &MonitorInfo)) { 00229 WindowLimits->FullScreenSize.X = (SHORT)(MonitorInfo.rcWork.right - MonitorInfo.rcWork.left); 00230 WindowLimits->FullScreenSize.Y = (SHORT)(MonitorInfo.rcWork.bottom - MonitorInfo.rcWork.top - ConsoleCaptionY); 00231 } else { 00232 WindowLimits->FullScreenSize.X = (SHORT)ConsoleFullScreenX; 00233 WindowLimits->FullScreenSize.Y = (SHORT)ConsoleFullScreenY; 00234 } 00235 00236 if (ScreenInfo->Flags & CONSOLE_TEXTMODE_BUFFER) { 00237 FontSize = SCR_FONTSIZE(ScreenInfo); 00238 } else { 00239 FontSize.X = 1; 00240 FontSize.Y = 1; 00241 } 00242 00243 WindowLimits->MinimumWindowSize.X = ((MinimumWidthX - VerticalClientToWindow + FontSize.X - 1) / FontSize.X); 00244 WindowLimits->MinimumWindowSize.Y = 1; 00245 WindowLimits->MaximumWindowSize.X = min(WindowLimits->FullScreenSize.X/FontSize.X, ScreenInfo->ScreenBufferSize.X); 00246 WindowLimits->MaximumWindowSize.X = max(WindowLimits->MaximumWindowSize.X, WindowLimits->MinimumWindowSize.X); 00247 WindowLimits->MaximumWindowSize.Y = min(WindowLimits->FullScreenSize.Y/FontSize.Y, ScreenInfo->ScreenBufferSize.Y); 00248 WindowLimits->MaxWindow.X = WindowLimits->MaximumWindowSize.X*FontSize.X + VerticalClientToWindow; 00249 WindowLimits->MaxWindow.Y = WindowLimits->MaximumWindowSize.Y*FontSize.Y + HorizontalClientToWindow; 00250 } 00251 00252 VOID 00253 InitializeScreenInfo( VOID ) 00254 { 00255 HDC hDC; 00256 00257 InitializeMouseButtons(); 00258 MinimumWidthX = GetSystemMetrics(SM_CXMIN); 00259 00260 InitializeSystemMetrics(); 00261 00262 hDC = CreateDCW(L"DISPLAY",NULL,NULL,NULL); 00263 if (hDC != NULL) { 00264 UsePolyTextOut = GetDeviceCaps(hDC,TEXTCAPS) & TC_SCROLLBLT; 00265 DeleteDC(hDC); 00266 } 00267 } 00268 00269 NTSTATUS 00270 DoCreateScreenBuffer( 00271 IN PCONSOLE_INFORMATION Console, 00272 IN PCONSOLE_INFO ConsoleInfo 00273 ) 00274 00275 /*++ 00276 00277 this routine figures out what parameters to pass to CreateScreenBuffer, 00278 based on the data from STARTUPINFO and the defaults in win.ini, 00279 then calls CreateScreenBuffer. 00280 00281 --*/ 00282 00283 { 00284 CHAR_INFO Fill,PopupFill; 00285 COORD dwScreenBufferSize, dwWindowSize; 00286 NTSTATUS Status; 00287 int FontIndexWant; 00288 00289 if (ConsoleInfo->dwStartupFlags & STARTF_USESHOWWINDOW) { 00290 Console->wShowWindow = ConsoleInfo->wShowWindow; 00291 } else { 00292 Console->wShowWindow = SW_SHOWNORMAL; 00293 } 00294 00295 #if 0 00296 { 00297 00298 INT i; 00299 00300 DbgPrint("[Link Server Properties for %ws]\n", ConsoleTitle ); 00301 DbgPrint(" wFillAttribute = 0x%04X\n", ConsoleInfo->wFillAttribute ); 00302 DbgPrint(" wPopupFillAttribute = 0x%04X\n", ConsoleInfo->wPopupFillAttribute ); 00303 DbgPrint(" dwScreenBufferSize = (%d , %d)\n", ConsoleInfo->dwScreenBufferSize.X, ConsoleInfo->dwScreenBufferSize.Y ); 00304 DbgPrint(" dwWindowSize = (%d , %d)\n", ConsoleInfo->dwWindowSize.X, ConsoleInfo->dwWindowSize.Y ); 00305 DbgPrint(" dwWindowOrigin = (%d , %d)\n", ConsoleInfo->dwWindowOrigin.X, ConsoleInfo->dwWindowOrigin.Y ); 00306 DbgPrint(" nFont = %d\n", ConsoleInfo->nFont ); 00307 DbgPrint(" nInputBufferSize = %d\n", ConsoleInfo->nInputBufferSize ); 00308 DbgPrint(" dwFontSize = (%d , %d)\n", ConsoleInfo->dwFontSize.X, ConsoleInfo->dwFontSize.Y ); 00309 DbgPrint(" uFontFamily = 0x%08X\n", ConsoleInfo->uFontFamily ); 00310 DbgPrint(" uFontWeight = 0x%08X\n", ConsoleInfo->uFontWeight ); 00311 DbgPrint(" FaceName = %ws\n", ConsoleInfo->FaceName ); 00312 DbgPrint(" uCursorSize = %d\n", ConsoleInfo->uCursorSize ); 00313 DbgPrint(" bFullScreen = %s\n", ConsoleInfo->bFullScreen ? "TRUE" : "FALSE" ); 00314 DbgPrint(" bQuickEdit = %s\n", ConsoleInfo->bQuickEdit ? "TRUE" : "FALSE" ); 00315 DbgPrint(" bInsertMode = %s\n", ConsoleInfo->bInsertMode ? "TRUE" : "FALSE" ); 00316 DbgPrint(" bAutoPosition = %s\n", ConsoleInfo->bAutoPosition ? "TRUE" : "FALSE" ); 00317 DbgPrint(" uHistoryBufferSize = %d\n", ConsoleInfo->uHistoryBufferSize ); 00318 DbgPrint(" uNumHistoryBuffers = %d\n", ConsoleInfo->uNumberOfHistoryBuffers ); 00319 DbgPrint(" bHistoryNoDup = %s\n", ConsoleInfo->bHistoryNoDup ? "TRUE" : "FALSE" ); 00320 DbgPrint(" ColorTable = [" ); 00321 i=0; 00322 while( i < 16 ) 00323 { 00324 DbgPrint("\n "); 00325 DbgPrint("0x%08X ", ConsoleInfo->ColorTable[i++]); 00326 DbgPrint("0x%08X ", ConsoleInfo->ColorTable[i++]); 00327 DbgPrint("0x%08X ", ConsoleInfo->ColorTable[i++]); 00328 DbgPrint("0x%08X ", ConsoleInfo->ColorTable[i++]); 00329 } 00330 DbgPrint( "]\n\n" ); 00331 } 00332 #endif 00333 00334 // 00335 // Get values from consoleinfo (which was initialized through link) 00336 // 00337 00338 Fill.Attributes = ConsoleInfo->wFillAttribute; 00339 Fill.Char.UnicodeChar = (WCHAR)' '; 00340 PopupFill.Attributes = ConsoleInfo->wPopupFillAttribute; 00341 PopupFill.Char.UnicodeChar = (WCHAR)' '; 00342 00343 dwScreenBufferSize = ConsoleInfo->dwScreenBufferSize; 00344 if (!(ConsoleInfo->dwStartupFlags & STARTF_USECOUNTCHARS)) { 00345 if (Console->Flags & CONSOLE_NO_WINDOW) { 00346 dwScreenBufferSize.X = min(dwScreenBufferSize.X, 80); 00347 dwScreenBufferSize.Y = min(dwScreenBufferSize.Y, 25); 00348 } 00349 } 00350 if (dwScreenBufferSize.X == 0) 00351 dwScreenBufferSize.X = 1; 00352 if (dwScreenBufferSize.Y == 0) 00353 dwScreenBufferSize.Y = 1; 00354 00355 // 00356 // Grab font 00357 // 00358 #if defined(FE_SB) 00359 FontIndexWant = FindCreateFont(ConsoleInfo->uFontFamily, 00360 ConsoleInfo->FaceName, 00361 ConsoleInfo->dwFontSize, 00362 ConsoleInfo->uFontWeight, 00363 ConsoleInfo->uCodePage 00364 ); 00365 #else 00366 FontIndexWant = FindCreateFont(ConsoleInfo->uFontFamily, 00367 ConsoleInfo->FaceName, 00368 ConsoleInfo->dwFontSize, 00369 ConsoleInfo->uFontWeight); 00370 #endif 00371 00372 // 00373 // grab window size information 00374 // 00375 00376 dwWindowSize = ConsoleInfo->dwWindowSize; 00377 if (ConsoleInfo->dwStartupFlags & STARTF_USESIZE) { 00378 dwWindowSize.X /= FontInfo[FontIndexWant].Size.X; 00379 dwWindowSize.Y /= FontInfo[FontIndexWant].Size.Y; 00380 } else if (Console->Flags & CONSOLE_NO_WINDOW) { 00381 dwWindowSize.X = min(dwWindowSize.X, 80); 00382 dwWindowSize.Y = min(dwWindowSize.Y, 25); 00383 } 00384 if (dwWindowSize.X == 0) 00385 dwWindowSize.X = 1; 00386 if (dwWindowSize.Y == 0) 00387 dwWindowSize.Y = 1; 00388 00389 if (dwScreenBufferSize.X < dwWindowSize.X) 00390 dwScreenBufferSize.X = dwWindowSize.X; 00391 if (dwScreenBufferSize.Y < dwWindowSize.Y) 00392 dwScreenBufferSize.Y = dwWindowSize.Y; 00393 00394 Console->dwWindowOriginX = ConsoleInfo->dwWindowOrigin.X; 00395 Console->dwWindowOriginY = ConsoleInfo->dwWindowOrigin.Y; 00396 00397 if (ConsoleInfo->bAutoPosition) { 00398 Console->Flags |= CONSOLE_AUTO_POSITION; 00399 Console->dwWindowOriginX = CW_USEDEFAULT; 00400 } else { 00401 Console->WindowRect.left = Console->dwWindowOriginX; 00402 Console->WindowRect.top = Console->dwWindowOriginY; 00403 Console->WindowRect.right = Console->dwWindowOriginX + dwWindowSize.X * FontInfo[FontIndexWant].Size.X; 00404 Console->WindowRect.bottom = Console->dwWindowOriginY + dwWindowSize.Y * FontInfo[FontIndexWant].Size.Y; 00405 } 00406 00407 #ifdef i386 00408 if (FullScreenInitialized) { 00409 if (ConsoleInfo->bFullScreen) { 00410 Console->FullScreenFlags = CONSOLE_FULLSCREEN; 00411 } 00412 } 00413 #endif 00414 if (ConsoleInfo->bQuickEdit) { 00415 Console->Flags |= CONSOLE_QUICK_EDIT_MODE; 00416 } 00417 Console->Flags |= CONSOLE_USE_PRIVATE_FLAGS; 00418 00419 Console->InsertMode = (ConsoleInfo->bInsertMode != FALSE); 00420 Console->CommandHistorySize = (SHORT)ConsoleInfo->uHistoryBufferSize; 00421 Console->MaxCommandHistories = (SHORT)ConsoleInfo->uNumberOfHistoryBuffers; 00422 if (ConsoleInfo->bHistoryNoDup) { 00423 Console->Flags |= CONSOLE_HISTORY_NODUP; 00424 } else { 00425 Console->Flags &= ~CONSOLE_HISTORY_NODUP; 00426 } 00427 RtlCopyMemory(Console->ColorTable, ConsoleInfo->ColorTable, sizeof( Console->ColorTable )); 00428 00429 #if defined(FE_SB) 00430 // for FarEast version, we want get the code page from registry or shell32, 00431 // so we can specify console codepage by console.cpl or shell32 00432 // default codepage is OEMCP. scotthsu 00433 Console->CP = ConsoleInfo->uCodePage; 00434 Console->OutputCP = ConsoleInfo->uCodePage; 00435 #if 0 00436 if (CONSOLE_IS_DBCS_ENABLED()){ 00437 Console->fIsDBCSCP = !!IsAvailableFarEastCodePage(Console->CP); 00438 Console->fIsDBCSOutputCP = !!IsAvailableFarEastCodePage(Console->OutputCP); 00439 } 00440 else { 00441 Console->fIsDBCSCP = FALSE; 00442 Console->fIsDBCSOutputCP = FALSE; 00443 } 00444 #else 00445 Console->fIsDBCSCP = CONSOLE_IS_DBCS_ENABLED() && IsAvailableFarEastCodePage(Console->CP); 00446 Console->fIsDBCSOutputCP = CONSOLE_IS_DBCS_ENABLED() && IsAvailableFarEastCodePage(Console->OutputCP); 00447 #endif 00448 #endif 00449 #if defined(FE_IME) 00450 Console->ConsoleIme.ScrollWaitTimeout = guCaretBlinkTime * 2; 00451 #endif 00452 TryNewSize: 00453 Status = CreateScreenBuffer(&Console->ScreenBuffers, 00454 dwWindowSize, 00455 FontIndexWant, 00456 dwScreenBufferSize, 00457 Fill, 00458 PopupFill, 00459 Console, 00460 CONSOLE_TEXTMODE_BUFFER, 00461 NULL, 00462 NULL, 00463 NULL, 00464 ConsoleInfo->uCursorSize, 00465 ConsoleInfo->FaceName 00466 ); 00467 if (Status == STATUS_NO_MEMORY) { 00468 // 00469 // If we failed to create a large buffer, try again with a small one. 00470 // 00471 if (dwScreenBufferSize.X > 80 || dwScreenBufferSize.Y > 50) { 00472 dwScreenBufferSize.X = min(dwScreenBufferSize.X, 80); 00473 dwScreenBufferSize.Y = min(dwScreenBufferSize.Y, 50); 00474 dwWindowSize.X = min(dwWindowSize.X, dwScreenBufferSize.X); 00475 dwWindowSize.Y = min(dwWindowSize.Y, dwScreenBufferSize.Y); 00476 Console->Flags |= CONSOLE_DEFAULT_BUFFER_SIZE; 00477 goto TryNewSize; 00478 } 00479 } 00480 00481 return Status; 00482 } 00483 00484 NTSTATUS 00485 CreateScreenBuffer( 00486 OUT PSCREEN_INFORMATION *ScreenInformation, 00487 IN COORD dwWindowSize, 00488 IN DWORD nFont, 00489 IN COORD dwScreenBufferSize, 00490 IN CHAR_INFO Fill, 00491 IN CHAR_INFO PopupFill, 00492 IN PCONSOLE_INFORMATION Console, 00493 IN DWORD Flags, 00494 IN PCONSOLE_GRAPHICS_BUFFER_INFO GraphicsBufferInfo OPTIONAL, 00495 OUT PVOID *lpBitmap OPTIONAL, 00496 OUT HANDLE *hMutex OPTIONAL, 00497 IN UINT CursorSize, 00498 IN LPWSTR FaceName 00499 ) 00500 00501 /*++ 00502 00503 Routine Description: 00504 00505 This routine allocates and initializes the data associated with a screen 00506 buffer. It also creates a window. 00507 00508 Arguments: 00509 00510 ScreenInformation - the new screen buffer. 00511 00512 dwWindowSize - the initial size of screen buffer's window (in rows/columns) 00513 00514 nFont - the initial font to generate text with. 00515 00516 dwScreenBufferSize - the initial size of the screen buffer (in rows/columns). 00517 00518 Return Value: 00519 00520 00521 --*/ 00522 00523 { 00524 LONG i,j; 00525 PSCREEN_INFORMATION ScreenInfo; 00526 NTSTATUS Status; 00527 PWCHAR TextRowPtr; 00528 #if defined(FE_SB) 00529 PBYTE AttrRowPtr; 00530 #endif 00531 WINDOW_LIMITS WindowLimits; 00532 00533 DBGPRINT(("CreateScreenBuffer(\n" 00534 " OUT PSCREEN_INFORMATION = %lx\n" 00535 " dwWindowSize = (%d,%d)\n" 00536 " nFont = %x\n" 00537 " dwScreenBufferSize = (%d,%d)\n" 00538 " Fill\n" 00539 " PopupFill\n", 00540 ScreenInformation, 00541 dwWindowSize.X, dwWindowSize.Y, 00542 nFont, 00543 dwScreenBufferSize.X, dwScreenBufferSize.Y 00544 // Fill, 00545 // PopupFill 00546 )); 00547 DBGPRINT((" PCONSOLE_INFORMATION = %lx\n" 00548 " Flags = %lx\n" 00549 " GraphicsBufferInfo\n" 00550 " lpBitmap\n" 00551 " *hMutex\n" 00552 " ConsoleTitle \"%ls\"\n", 00553 Console, 00554 Flags, 00555 // GraphicsBufferInfo, 00556 // lpBitmap, 00557 // hMutex, 00558 Console->Title)); 00559 00560 /* 00561 * Make sure we have a valid font. Bail if no fonts are available. 00562 */ 00563 ASSERT(nFont < NumberOfFonts); 00564 if (NumberOfFonts == 0) { 00565 return STATUS_UNSUCCESSFUL; 00566 } 00567 00568 /* 00569 * CONSIDER (adams): Allocate and zero memory, so 00570 * initialization is only of non-zero members. 00571 */ 00572 ScreenInfo = (PSCREEN_INFORMATION)ConsoleHeapAlloc(MAKE_TAG( SCREEN_TAG ),sizeof(SCREEN_INFORMATION)); 00573 if (ScreenInfo == NULL) { 00574 return STATUS_NO_MEMORY; 00575 } 00576 ScreenInfo->Console = Console; 00577 if ((ScreenInfo->Flags = Flags) & CONSOLE_TEXTMODE_BUFFER) { 00578 00579 ASSERT(FontInfo[nFont].FaceName != NULL); 00580 00581 ScreenInfo->BufferInfo.TextInfo.ListOfTextBufferFont = NULL; 00582 00583 Status = StoreTextBufferFontInfo(ScreenInfo, 00584 nFont, 00585 FontInfo[nFont].Size, 00586 FontInfo[nFont].Family, 00587 FontInfo[nFont].Weight, 00588 FaceName ? FaceName : FontInfo[nFont].FaceName, 00589 Console->OutputCP); 00590 if (!NT_SUCCESS(Status)) { 00591 ConsoleHeapFree(ScreenInfo); 00592 return((ULONG) Status); 00593 } 00594 00595 DBGFONTS(("DoCreateScreenBuffer sets FontSize(%d,%d), FontNumber=%x, Family=%x\n", 00596 SCR_FONTSIZE(ScreenInfo).X, 00597 SCR_FONTSIZE(ScreenInfo).Y, 00598 SCR_FONTNUMBER(ScreenInfo), 00599 SCR_FAMILY(ScreenInfo))); 00600 00601 if (TM_IS_TT_FONT(FontInfo[nFont].Family)) { 00602 ScreenInfo->Flags &= ~CONSOLE_OEMFONT_DISPLAY; 00603 } else { 00604 ScreenInfo->Flags |= CONSOLE_OEMFONT_DISPLAY; 00605 } 00606 00607 ScreenInfo->ScreenBufferSize = dwScreenBufferSize; 00608 GetWindowLimits(ScreenInfo, &WindowLimits); 00609 dwScreenBufferSize.X = max(dwScreenBufferSize.X, WindowLimits.MinimumWindowSize.X); 00610 dwWindowSize.X = max(dwWindowSize.X, WindowLimits.MinimumWindowSize.X); 00611 00612 ScreenInfo->BufferInfo.TextInfo.ModeIndex = (ULONG)-1; 00613 #ifdef i386 00614 if (Console->FullScreenFlags & CONSOLE_FULLSCREEN) { 00615 COORD WindowSize; 00616 ScreenInfo->BufferInfo.TextInfo.WindowedWindowSize = dwWindowSize; 00617 ScreenInfo->BufferInfo.TextInfo.WindowedScreenSize = dwScreenBufferSize; 00618 ScreenInfo->BufferInfo.TextInfo.ModeIndex = MatchWindowSize(Console->OutputCP,dwWindowSize,&WindowSize); 00619 } 00620 #endif 00621 ScreenInfo->BufferInfo.TextInfo.FirstRow = 0; 00622 ScreenInfo->BufferInfo.TextInfo.Rows = (PROW)ConsoleHeapAlloc(MAKE_TAG( SCREEN_TAG ),dwScreenBufferSize.Y * sizeof(ROW)); 00623 if (ScreenInfo->BufferInfo.TextInfo.Rows == NULL) { 00624 RemoveTextBufferFontInfo(ScreenInfo); 00625 ConsoleHeapFree(ScreenInfo); 00626 return STATUS_NO_MEMORY; 00627 } 00628 ScreenInfo->BufferInfo.TextInfo.TextRows = (PWCHAR)ConsoleHeapAlloc(MAKE_TAG( SCREEN_TAG ),dwScreenBufferSize.X*dwScreenBufferSize.Y*sizeof(WCHAR)); 00629 if (ScreenInfo->BufferInfo.TextInfo.TextRows == NULL) { 00630 ConsoleHeapFree(ScreenInfo->BufferInfo.TextInfo.Rows); 00631 RemoveTextBufferFontInfo(ScreenInfo); 00632 ConsoleHeapFree(ScreenInfo); 00633 return STATUS_NO_MEMORY; 00634 } 00635 #if defined(FE_SB) 00636 if (! CreateDbcsScreenBuffer(Console, dwScreenBufferSize,&ScreenInfo->BufferInfo.TextInfo.DbcsScreenBuffer)) 00637 { 00638 ConsoleHeapFree(ScreenInfo->BufferInfo.TextInfo.TextRows); 00639 ConsoleHeapFree(ScreenInfo->BufferInfo.TextInfo.Rows); 00640 RemoveTextBufferFontInfo(ScreenInfo); 00641 ConsoleHeapFree(ScreenInfo); 00642 return STATUS_NO_MEMORY; 00643 } 00644 00645 AttrRowPtr=ScreenInfo->BufferInfo.TextInfo.DbcsScreenBuffer.KAttrRows; 00646 #endif 00647 for (i=0,TextRowPtr=ScreenInfo->BufferInfo.TextInfo.TextRows; 00648 i<dwScreenBufferSize.Y; 00649 i++,TextRowPtr+=dwScreenBufferSize.X) 00650 { 00651 ScreenInfo->BufferInfo.TextInfo.Rows[i].CharRow.Left = dwScreenBufferSize.X; 00652 ScreenInfo->BufferInfo.TextInfo.Rows[i].CharRow.OldLeft = INVALID_OLD_LENGTH; 00653 ScreenInfo->BufferInfo.TextInfo.Rows[i].CharRow.Right = 0; 00654 ScreenInfo->BufferInfo.TextInfo.Rows[i].CharRow.OldRight = INVALID_OLD_LENGTH; 00655 ScreenInfo->BufferInfo.TextInfo.Rows[i].CharRow.Chars = TextRowPtr; 00656 #if defined(FE_SB) 00657 ScreenInfo->BufferInfo.TextInfo.Rows[i].CharRow.KAttrs = AttrRowPtr; 00658 #endif 00659 for (j=0;j<dwScreenBufferSize.X;j++) { 00660 TextRowPtr[j] = (WCHAR)' '; 00661 } 00662 #if defined(FE_SB) 00663 if (AttrRowPtr) { 00664 RtlZeroMemory(AttrRowPtr, dwScreenBufferSize.X); 00665 AttrRowPtr+=dwScreenBufferSize.X; 00666 } 00667 #endif 00668 ScreenInfo->BufferInfo.TextInfo.Rows[i].AttrRow.Length = 1; 00669 ScreenInfo->BufferInfo.TextInfo.Rows[i].AttrRow.AttrPair.Length = dwScreenBufferSize.X; 00670 ScreenInfo->BufferInfo.TextInfo.Rows[i].AttrRow.AttrPair.Attr = Fill.Attributes; 00671 ScreenInfo->BufferInfo.TextInfo.Rows[i].AttrRow.Attrs = &ScreenInfo->BufferInfo.TextInfo.Rows[i].AttrRow.AttrPair; 00672 00673 } 00674 ScreenInfo->BufferInfo.TextInfo.CursorSize = CursorSize; 00675 ScreenInfo->BufferInfo.TextInfo.CursorPosition.X = 0; 00676 ScreenInfo->BufferInfo.TextInfo.CursorPosition.Y = 0; 00677 ScreenInfo->BufferInfo.TextInfo.CursorMoved = FALSE; 00678 ScreenInfo->BufferInfo.TextInfo.CursorVisible = TRUE; 00679 ScreenInfo->BufferInfo.TextInfo.CursorOn = FALSE; 00680 ScreenInfo->BufferInfo.TextInfo.CursorYSize = (WORD)CURSOR_SIZE_IN_PIXELS(SCR_FONTSIZE(ScreenInfo).Y,ScreenInfo->BufferInfo.TextInfo.CursorSize); 00681 ScreenInfo->BufferInfo.TextInfo.UpdatingScreen = 0; 00682 ScreenInfo->BufferInfo.TextInfo.DoubleCursor = FALSE; 00683 ScreenInfo->BufferInfo.TextInfo.DelayCursor = FALSE; 00684 ScreenInfo->BufferInfo.TextInfo.Flags = SINGLE_ATTRIBUTES_PER_LINE; 00685 ScreenInfo->ScreenBufferSize = dwScreenBufferSize; 00686 ScreenInfo->Window.Left = 0; 00687 ScreenInfo->Window.Top = 0; 00688 ScreenInfo->Window.Right = dwWindowSize.X - 1; 00689 ScreenInfo->Window.Bottom = dwWindowSize.Y - 1; 00690 if (ScreenInfo->Window.Right >= WindowLimits.MaximumWindowSize.X) { 00691 ScreenInfo->Window.Right = WindowLimits.MaximumWindowSize.X-1; 00692 dwWindowSize.X = CONSOLE_WINDOW_SIZE_X(ScreenInfo); 00693 } 00694 if (ScreenInfo->Window.Bottom >= WindowLimits.MaximumWindowSize.Y) { 00695 ScreenInfo->Window.Bottom = WindowLimits.MaximumWindowSize.Y-1; 00696 dwWindowSize.Y = CONSOLE_WINDOW_SIZE_Y(ScreenInfo); 00697 } 00698 ScreenInfo->WindowMaximizedX = (dwWindowSize.X == dwScreenBufferSize.X); 00699 ScreenInfo->WindowMaximizedY = (dwWindowSize.Y == dwScreenBufferSize.Y); 00700 #if defined(FE_SB) 00701 #if defined(_X86_) 00702 ScreenInfo->BufferInfo.TextInfo.MousePosition.X = 0; 00703 ScreenInfo->BufferInfo.TextInfo.MousePosition.Y = 0; 00704 #endif // i386 00705 00706 ScreenInfo->BufferInfo.TextInfo.CursorBlink = TRUE; 00707 ScreenInfo->BufferInfo.TextInfo.CursorDBEnable = TRUE; 00708 #endif 00709 00710 } 00711 else { 00712 Status = CreateConsoleBitmap(GraphicsBufferInfo, 00713 ScreenInfo, 00714 lpBitmap, 00715 hMutex 00716 ); 00717 if (!NT_SUCCESS(Status)) { 00718 ConsoleHeapFree(ScreenInfo); 00719 return Status; 00720 } 00721 ScreenInfo->WindowMaximizedX = TRUE; 00722 ScreenInfo->WindowMaximizedY = TRUE; 00723 } 00724 00725 ScreenInfo->WindowMaximized = FALSE; 00726 ScreenInfo->RefCount = 0; 00727 ScreenInfo->ShareAccess.OpenCount = 0; 00728 ScreenInfo->ShareAccess.Readers = 0; 00729 ScreenInfo->ShareAccess.Writers = 0; 00730 ScreenInfo->ShareAccess.SharedRead = 0; 00731 ScreenInfo->ShareAccess.SharedWrite = 0; 00732 ScreenInfo->CursorHandle = ghNormalCursor; 00733 ScreenInfo->CursorDisplayCount = 0; 00734 ScreenInfo->CommandIdLow = (UINT)-1; 00735 ScreenInfo->CommandIdHigh = (UINT)-1; 00736 ScreenInfo->dwUsage = SYSPAL_STATIC; 00737 ScreenInfo->hPalette = NULL; 00738 00739 ScreenInfo->OutputMode = ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT; 00740 00741 00742 ScreenInfo->ResizingWindow = 0; 00743 ScreenInfo->Next = NULL; 00744 ScreenInfo->Attributes = Fill.Attributes; 00745 ScreenInfo->PopupAttributes = PopupFill.Attributes; 00746 00747 ScreenInfo->WheelDelta = 0; 00748 00749 #if defined(FE_SB) 00750 ScreenInfo->WriteConsoleDbcsLeadByte[0] = 0; 00751 ScreenInfo->BisectFlag = 0; 00752 if (Flags & CONSOLE_TEXTMODE_BUFFER) { 00753 SetLineChar(ScreenInfo); 00754 } 00755 ScreenInfo->FillOutDbcsLeadChar = 0; 00756 ScreenInfo->ConvScreenInfo = NULL; 00757 #endif 00758 00759 *ScreenInformation = ScreenInfo; 00760 DBGOUTPUT(("SCREEN at %lx\n", ScreenInfo)); 00761 return STATUS_SUCCESS; 00762 } 00763 00764 VOID 00765 PositionConsoleWindow( 00766 IN PCONSOLE_INFORMATION Console, 00767 IN BOOL Initialize 00768 ) 00769 { 00770 GetWindowRect(Console->hWnd, &Console->WindowRect); 00771 00772 // 00773 // If this is an autoposition window being initialized, make sure it's 00774 // client area doesn't descend below the tray 00775 // 00776 00777 if (Initialize && (Console->Flags & CONSOLE_AUTO_POSITION)) { 00778 RECT ClientRect; 00779 LONG dx = 0; 00780 LONG dy = 0; 00781 HMONITOR hMonitor; 00782 MONITORINFO MonitorInfo = {sizeof(MonitorInfo)}; 00783 00784 hMonitor = MonitorFromRect(&Console->WindowRect, MONITOR_DEFAULTTONULL); 00785 if (hMonitor && GetMonitorInfo(hMonitor, &MonitorInfo)) { 00786 GetClientRect(Console->hWnd, &ClientRect); 00787 ClientToScreen(Console->hWnd, (LPPOINT)&ClientRect.left); 00788 ClientToScreen(Console->hWnd, (LPPOINT)&ClientRect.right); 00789 if (Console->WindowRect.right > MonitorInfo.rcWork.right) { 00790 dx = max(min((Console->WindowRect.right - MonitorInfo.rcWork.right), 00791 (Console->WindowRect.left - MonitorInfo.rcWork.left)), 00792 min((ClientRect.right - MonitorInfo.rcWork.right), 00793 (ClientRect.left - MonitorInfo.rcWork.left))); 00794 } 00795 if (Console->WindowRect.bottom > MonitorInfo.rcWork.bottom) { 00796 dy = max(min((Console->WindowRect.bottom - MonitorInfo.rcWork.bottom), 00797 (Console->WindowRect.top - MonitorInfo.rcWork.top)), 00798 min((ClientRect.bottom - MonitorInfo.rcWork.bottom), 00799 (ClientRect.top - MonitorInfo.rcWork.top))); 00800 } 00801 if (dx || dy) { 00802 SetWindowPos(Console->hWnd, 00803 NULL, 00804 Console->WindowRect.left - dx, 00805 Console->WindowRect.top - dy, 00806 0, 00807 0, 00808 SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER); 00809 } 00810 } 00811 } 00812 } 00813 00814 /* 00815 * Bug 273518 - joejo 00816 * 00817 * This will allow console windows to set foreground correctly on new 00818 * process' it launches, as opposed it just forcing foreground. 00819 */ 00820 NTSTATUS 00821 ConsoleSetActiveWindow( 00822 IN PCONSOLE_INFORMATION Console 00823 ) 00824 { 00825 HWND hWnd = Console->hWnd; 00826 HANDLE ConsoleHandle = Console->ConsoleHandle; 00827 00828 UnlockConsole(Console); 00829 SetActiveWindow(hWnd); 00830 return RevalidateConsole(ConsoleHandle, &Console); 00831 } 00832 00833 NTSTATUS 00834 CreateWindowsWindow( 00835 IN PCONSOLE_INFORMATION Console 00836 ) 00837 { 00838 PSCREEN_INFORMATION ScreenInfo; 00839 SIZE WindowSize; 00840 DWORD Style; 00841 THREAD_BASIC_INFORMATION ThreadInfo; 00842 HWND hWnd; 00843 00844 ScreenInfo = Console->ScreenBuffers; 00845 00846 // 00847 // figure out how big to make the window, given the desired client area 00848 // size. window is always created in textmode. 00849 // 00850 00851 ASSERT(ScreenInfo->Flags & CONSOLE_TEXTMODE_BUFFER); 00852 WindowSize.cx = CONSOLE_WINDOW_SIZE_X(ScreenInfo)*SCR_FONTSIZE(ScreenInfo).X + VerticalClientToWindow; 00853 WindowSize.cy = CONSOLE_WINDOW_SIZE_Y(ScreenInfo)*SCR_FONTSIZE(ScreenInfo).Y + HorizontalClientToWindow; 00854 Style = CONSOLE_WINDOW_FLAGS & ~WS_VISIBLE; 00855 if (!ScreenInfo->WindowMaximizedX) { 00856 WindowSize.cy += HorizontalScrollSize; 00857 } else { 00858 Style &= ~WS_HSCROLL; 00859 } 00860 if (!ScreenInfo->WindowMaximizedY) { 00861 WindowSize.cx += VerticalScrollSize; 00862 } else { 00863 Style &= ~WS_VSCROLL; 00864 } 00865 #ifdef THERESES_DEBUG 00866 DbgPrint("creating window with char size %d %d\n",CONSOLE_WINDOW_SIZE_X(ScreenInfo),CONSOLE_WINDOW_SIZE_Y(ScreenInfo)); 00867 DbgPrint(" pixel size %d %d\n",WindowSize.cx,WindowSize.cy); 00868 #endif 00869 00870 // 00871 // create the window. 00872 // 00873 00874 Console->WindowRect.left = Console->dwWindowOriginX; 00875 Console->WindowRect.top = Console->dwWindowOriginY; 00876 Console->WindowRect.right = WindowSize.cx + Console->dwWindowOriginX; 00877 Console->WindowRect.bottom = WindowSize.cy + Console->dwWindowOriginY; 00878 hWnd = CreateWindowEx(CONSOLE_WINDOW_EX_FLAGS, 00879 CONSOLE_WINDOW_CLASS, 00880 Console->Title, 00881 Style, 00882 Console->dwWindowOriginX, 00883 Console->dwWindowOriginY, 00884 WindowSize.cx, 00885 WindowSize.cy, 00886 (Console->Flags & CONSOLE_NO_WINDOW) ? HWND_MESSAGE : HWND_DESKTOP, 00887 NULL, 00888 ghInstance, 00889 NULL); 00890 if (hWnd == NULL) { 00891 NtSetEvent(Console->InitEvents[INITIALIZATION_FAILED],NULL); 00892 return STATUS_NO_MEMORY; 00893 } 00894 Console->hWnd = hWnd; 00895 00896 SetWindowConsole(hWnd, Console); 00897 00898 // 00899 // Stuff the client id into the window so USER can find it. 00900 // 00901 00902 if (NT_SUCCESS(NtQueryInformationThread(Console->ClientThreadHandle, 00903 ThreadBasicInformation, &ThreadInfo, 00904 sizeof(ThreadInfo), NULL))) { 00905 00906 SetConsolePid(Console->hWnd, HandleToUlong(ThreadInfo.ClientId.UniqueProcess)); 00907 SetConsoleTid(Console->hWnd, HandleToUlong(ThreadInfo.ClientId.UniqueThread)); 00908 } 00909 00910 // 00911 // Get the dc. 00912 // 00913 00914 Console->hDC = GetDC(Console->hWnd); 00915 00916 if (Console->hDC == NULL) { 00917 NtSetEvent(Console->InitEvents[INITIALIZATION_FAILED],NULL); 00918 DestroyWindow(Console->hWnd); 00919 Console->hWnd = NULL; 00920 return STATUS_NO_MEMORY; 00921 } 00922 Console->hMenu = GetSystemMenu(Console->hWnd,FALSE); 00923 00924 // 00925 // modify system menu to our liking. 00926 // 00927 00928 InitSystemMenu(Console); 00929 00930 gnConsoleWindows++; 00931 Console->InputThreadInfo->WindowCount++; 00932 00933 #if defined(FE_IME) 00934 SetUndetermineAttribute(Console); 00935 #endif 00936 #if defined(FE_SB) 00937 RegisterKeisenOfTTFont(ScreenInfo); 00938 #endif 00939 00940 // 00941 // Set up the hot key for this window 00942 // 00943 if ((Console->dwHotKey != 0) && !(Console->Flags & CONSOLE_NO_WINDOW)) { 00944 SendMessage(Console->hWnd, WM_SETHOTKEY, Console->dwHotKey, 0L); 00945 } 00946 00947 // 00948 // create icon 00949 // 00950 00951 if (Console->iIconId) { 00952 00953 // We have no icon, try and get one from progman. 00954 00955 PostMessage(HWND_BROADCAST, 00956 ProgmanHandleMessage, 00957 (WPARAM)Console->hWnd, 00958 1); 00959 } 00960 if (Console->hIcon == NULL) { 00961 Console->hIcon = ghDefaultIcon; 00962 Console->hSmIcon = ghDefaultSmIcon; 00963 } else if (Console->hIcon != ghDefaultIcon) { 00964 SendMessage(Console->hWnd, WM_SETICON, ICON_BIG, (LPARAM)Console->hIcon); 00965 SendMessage(Console->hWnd, WM_SETICON, ICON_SMALL, (LPARAM)Console->hSmIcon); 00966 } 00967 00968 SetBkMode(Console->hDC,OPAQUE); 00969 SetFont(ScreenInfo); 00970 SelectObject(Console->hDC, GetStockObject(DC_BRUSH)); 00971 SetScreenColors(ScreenInfo, ScreenInfo->Attributes, 00972 ScreenInfo->PopupAttributes, FALSE); 00973 if (Console->Flags & CONSOLE_NO_WINDOW) { 00974 ShowWindowAsync(Console->hWnd, SW_HIDE); 00975 #ifdef i386 00976 } else if (Console->FullScreenFlags != 0) { 00977 if (Console->wShowWindow == SW_SHOWMINNOACTIVE) { 00978 ShowWindowAsync(Console->hWnd, Console->wShowWindow); 00979 Console->FullScreenFlags = 0; 00980 Console->Flags |= CONSOLE_IS_ICONIC; 00981 } else { 00982 ConvertToFullScreen(Console); 00983 if (!NT_SUCCESS(ConsoleSetActiveWindow(Console))) { 00984 return STATUS_INVALID_HANDLE; 00985 } 00986 00987 ChangeDispSettings(Console, Console->hWnd,CDS_FULLSCREEN); 00988 } 00989 #endif 00990 } else { 00991 if (Console->wShowWindow != SW_SHOWNOACTIVATE && 00992 Console->wShowWindow != SW_SHOWMINNOACTIVE && 00993 Console->wShowWindow != SW_HIDE) { 00994 if (!NT_SUCCESS(ConsoleSetActiveWindow(Console))) { 00995 return STATUS_INVALID_HANDLE; 00996 } 00997 } else if (Console->wShowWindow == SW_SHOWMINNOACTIVE) { 00998 Console->Flags |= CONSOLE_IS_ICONIC; 00999 } 01000 ShowWindowAsync(Console->hWnd, Console->wShowWindow); 01001 } 01002 01003 //UpdateWindow(Console->hWnd); 01004 InternalUpdateScrollBars(ScreenInfo); 01005 if (!(Console->Flags & CONSOLE_IS_ICONIC) && 01006 (Console->FullScreenFlags == 0) ) { 01007 01008 PositionConsoleWindow(Console, TRUE); 01009 } 01010 01011 #if defined(FE_IME) 01012 if (CONSOLE_IS_IME_ENABLED() && !(Console->Flags & CONSOLE_NO_WINDOW)) { 01013 SetTimer(Console->hWnd, SCROLL_WAIT_TIMER, guCaretBlinkTime, NULL); 01014 } 01015 #endif 01016 NtSetEvent(Console->InitEvents[INITIALIZATION_SUCCEEDED],NULL); 01017 return STATUS_SUCCESS; 01018 } 01019 01020 NTSTATUS 01021 FreeScreenBuffer( 01022 IN PSCREEN_INFORMATION ScreenInfo 01023 ) 01024 01025 /*++ 01026 01027 Routine Description: 01028 01029 This routine frees the memory associated with a screen buffer. 01030 01031 Arguments: 01032 01033 ScreenInfo - screen buffer data to free. 01034 01035 Return Value: 01036 01037 Note: console handle table lock must be held when calling this routine 01038 01039 --*/ 01040 01041 { 01042 SHORT i; 01043 PCONSOLE_INFORMATION Console = ScreenInfo->Console; 01044 01045 ASSERT(ScreenInfo->RefCount == 0); 01046 if (ScreenInfo->Flags & CONSOLE_TEXTMODE_BUFFER) { 01047 for (i=0;i<ScreenInfo->ScreenBufferSize.Y;i++) { 01048 if (ScreenInfo->BufferInfo.TextInfo.Rows[i].AttrRow.Length > 1) { 01049 ConsoleHeapFree(ScreenInfo->BufferInfo.TextInfo.Rows[i].AttrRow.Attrs); 01050 } 01051 } 01052 ConsoleHeapFree(ScreenInfo->BufferInfo.TextInfo.TextRows); 01053 ConsoleHeapFree(ScreenInfo->BufferInfo.TextInfo.Rows); 01054 #if defined(FE_SB) 01055 DeleteDbcsScreenBuffer(&ScreenInfo->BufferInfo.TextInfo.DbcsScreenBuffer); 01056 #endif 01057 RemoveTextBufferFontInfo(ScreenInfo); 01058 } else { 01059 if (ScreenInfo->hPalette != NULL) { 01060 if (GetCurrentObject(Console->hDC, OBJ_PAL) == ScreenInfo->hPalette) { 01061 SelectPalette(Console->hDC, Console->hSysPalette, FALSE); 01062 } 01063 DeleteObject(ScreenInfo->hPalette); 01064 } 01065 FreeConsoleBitmap(ScreenInfo); 01066 } 01067 ConsoleHeapFree(ScreenInfo); 01068 return STATUS_SUCCESS; 01069 } 01070 01071 VOID 01072 FindAttrIndex( 01073 IN PATTR_PAIR String, 01074 IN SHORT Index, 01075 OUT PATTR_PAIR *IndexedAttr, 01076 OUT PSHORT CountOfAttr 01077 ) 01078 01079 /*++ 01080 01081 Routine Description: 01082 01083 This routine finds the nth attribute in a string. 01084 01085 Arguments: 01086 01087 String - attribute string 01088 01089 Index - which attribute to find 01090 01091 IndexedAttr - pointer to attribute within string 01092 01093 CountOfAttr - on output, contains corrected length of indexed attr. 01094 for example, if the attribute string was { 5, BLUE } and the requested 01095 index was 3, CountOfAttr would be 2. 01096 01097 Return Value: 01098 01099 none. 01100 01101 --*/ 01102 01103 { 01104 SHORT i; 01105 01106 for (i=0;i<Index;) { 01107 i += String->Length; 01108 String++; 01109 } 01110 01111 if (i>Index) { 01112 String--; 01113 *CountOfAttr = i-Index; 01114 } 01115 else { 01116 *CountOfAttr = String->Length; 01117 } 01118 *IndexedAttr = String; 01119 } 01120 01121 01122 01123 NTSTATUS 01124 MergeAttrStrings( 01125 IN PATTR_PAIR Source, 01126 IN WORD SourceLength, 01127 IN PATTR_PAIR Merge, 01128 IN WORD MergeLength, 01129 OUT PATTR_PAIR *Target, 01130 OUT LPWORD TargetLength, 01131 IN SHORT StartIndex, 01132 IN SHORT EndIndex, 01133 IN PROW Row, 01134 IN PSCREEN_INFORMATION ScreenInfo 01135 ) 01136 01137 /*++ 01138 01139 Routine Description: 01140 01141 This routine merges two run-length encoded attribute strings into 01142 a third. 01143 01144 for example, if the source string was { 4, BLUE }, the merge string 01145 was { 2, RED }, and the StartIndex and EndIndex were 1 and 2, 01146 respectively, the target string would be { 1, BLUE, 2, RED, 1, BLUE } 01147 and the target length would be 3. 01148 01149 Arguments: 01150 01151 Source - pointer to source attribute string 01152 01153 SourceLength - length of source. for example, the length of 01154 { 4, BLUE } is 1. 01155 01156 Merge - pointer to attribute string to insert into source 01157 01158 MergeLength - length of merge 01159 01160 Target - where to store pointer to resulting attribute string 01161 01162 TargetLength - where to store length of resulting attribute string 01163 01164 StartIndex - index into Source at which to insert Merge String. 01165 01166 EndIndex - index into Source at which to stop insertion of Merge String 01167 01168 Return Value: 01169 01170 none. 01171 01172 --*/ 01173 { 01174 PATTR_PAIR SrcAttr,TargetAttr,SrcEnd; 01175 PATTR_PAIR NewString; 01176 SHORT i; 01177 #if THERESES_DEBUG2 01178 #if DBG 01179 WORD AllocLength; 01180 01181 AllocLength = MergeLength + SourceLength + 1; 01182 #endif 01183 #endif 01184 01185 // 01186 // if just changing the attr for the whole row 01187 // 01188 01189 if (MergeLength == 1 && Row->AttrRow.Length == 1) { 01190 if (Row->AttrRow.Attrs->Attr == Merge->Attr) { 01191 *TargetLength = 1; 01192 *Target = &Row->AttrRow.AttrPair; 01193 return STATUS_SUCCESS; 01194 } 01195 if (StartIndex == 0 && EndIndex == (SHORT)(ScreenInfo->ScreenBufferSize.X-1)) { 01196 NewString = &Row->AttrRow.AttrPair; 01197 NewString->Attr = Merge->Attr; 01198 *TargetLength = 1; 01199 *Target = NewString; 01200 return STATUS_SUCCESS; 01201 } 01202 } 01203 01204 NewString = (PATTR_PAIR) ConsoleHeapAlloc(MAKE_TAG( SCREEN_TAG ),(SourceLength+MergeLength+1)*sizeof(ATTR_PAIR)); 01205 if (NewString == NULL) { 01206 return STATUS_NO_MEMORY; 01207 } 01208 01209 // 01210 // copy the source string, up to the start index. 01211 // 01212 01213 SrcAttr = Source; 01214 SrcEnd = Source + SourceLength; 01215 TargetAttr = NewString; 01216 i=0; 01217 if (StartIndex != 0) { 01218 while (i<StartIndex) { 01219 i += SrcAttr->Length; 01220 *TargetAttr++ = *SrcAttr++; 01221 } 01222 01223 // 01224 // back up to the last pair copied, in case the attribute in the first 01225 // pair in the merge string matches. also, adjust TargetAttr->Length 01226 // based on i, the attribute 01227 // counter, back to the StartIndex. i will be larger than the 01228 // StartIndex in the case where the last attribute pair copied had 01229 // a length greater than the number needed to reach StartIndex. 01230 // 01231 01232 TargetAttr--; 01233 if (i>StartIndex) { 01234 TargetAttr->Length -= i-StartIndex; 01235 } 01236 if (Merge->Attr == TargetAttr->Attr) { 01237 TargetAttr->Length += Merge->Length; 01238 MergeLength-=1; 01239 Merge++; 01240 } 01241 TargetAttr++; 01242 } 01243 01244 // 01245 // copy the merge string. 01246 // 01247 01248 RtlCopyMemory(TargetAttr,Merge,MergeLength*sizeof(ATTR_PAIR)); 01249 TargetAttr += MergeLength; 01250 01251 // 01252 // figure out where to resume copying the source string. 01253 // 01254 01255 while (i<=EndIndex) { 01256 ASSERT(SrcAttr != SrcEnd); 01257 i += SrcAttr->Length; 01258 SrcAttr++; 01259 } 01260 01261 // 01262 // if not done, copy the rest of the source 01263 // 01264 01265 if (SrcAttr != SrcEnd || i!=(SHORT)(EndIndex+1)) { 01266 01267 // 01268 // see if we've gone past the right attribute. if so, back up and 01269 // copy the attribute and the correct length. 01270 // 01271 01272 TargetAttr--; 01273 if (i>(SHORT)(EndIndex+1)) { 01274 SrcAttr--; 01275 if (TargetAttr->Attr == SrcAttr->Attr) { 01276 TargetAttr->Length += i-(EndIndex+1); 01277 } else { 01278 TargetAttr++; 01279 TargetAttr->Attr = SrcAttr->Attr; 01280 TargetAttr->Length = (SHORT)(i-(EndIndex+1)); 01281 } 01282 SrcAttr++; 01283 } 01284 01285 // 01286 // see if we can merge the source and target. 01287 // 01288 01289 else if (TargetAttr->Attr == SrcAttr->Attr) { 01290 TargetAttr->Length += SrcAttr->Length; 01291 i += SrcAttr->Length; 01292 SrcAttr++; 01293 } 01294 TargetAttr++; 01295 01296 // 01297 // copy the rest of the source 01298 // 01299 01300 if (SrcAttr < SrcEnd) { 01301 RtlCopyMemory(TargetAttr,SrcAttr,(SrcEnd-SrcAttr)*sizeof(ATTR_PAIR)); 01302 TargetAttr += SrcEnd - SrcAttr; 01303 } 01304 } 01305 01306 *TargetLength = (WORD)(TargetAttr - NewString); 01307 #if THERESES_DEBUG2 01308 #if DBG 01309 { SHORT j; 01310 WORD i; 01311 PATTR_PAIR NewAttr; 01312 PULONG Foo; 01313 j=0; 01314 NewAttr = NewString; 01315 for (i=0;i<*TargetLength;i++) { 01316 j+=NewAttr->Length; 01317 NewAttr++; 01318 } 01319 ASSERT (j == ScreenInfo->ScreenBufferSize.X); 01320 if (j != ScreenInfo->ScreenBufferSize.X) { 01321 DbgPrint("new length is %d\n",*TargetLength); 01322 DbgPrint("address of new attr string is %lx\n",NewString); 01323 } 01324 ASSERT (*TargetLength <= AllocLength); 01325 Foo = (PULONG)(NewString-4); 01326 ASSERT (*Foo & 1); 01327 Foo = (PULONG)(NewString-3); 01328 ASSERT (*Foo >= (*TargetLength * sizeof(ATTR_PAIR)) + 16); 01329 } 01330 #endif 01331 #endif 01332 *Target = NewString; 01333 if (*TargetLength == 1) { 01334 *Target = &Row->AttrRow.AttrPair; 01335 **Target = *NewString; 01336 ConsoleHeapFree(NewString); 01337 } 01338 return STATUS_SUCCESS; 01339 } 01340 01341 VOID 01342 ResetTextFlags( 01343 IN PSCREEN_INFORMATION ScreenInfo, 01344 IN SHORT StartY, 01345 IN SHORT EndY 01346 ) 01347 01348 /* 01349 this routine updates the text flags 01350 01351 #define SINGLE_ATTRIBUTES_PER_LINE 2 // only one attribute per line 01352 01353 */ 01354 01355 { 01356 SHORT RowIndex; 01357 PROW Row; 01358 SHORT i; 01359 01360 // 01361 // first see whether we wrote any lines with multiple attributes. if 01362 // we did, set the flags and bail out. also, remember if any of the 01363 // lines we wrote had attributes different from other lines. 01364 // 01365 01366 RowIndex = (ScreenInfo->BufferInfo.TextInfo.FirstRow+StartY) % ScreenInfo->ScreenBufferSize.Y; 01367 for (i=StartY;i<=EndY;i++) { 01368 Row = &ScreenInfo->BufferInfo.TextInfo.Rows[RowIndex]; 01369 if (Row->AttrRow.Length != 1) { 01370 ScreenInfo->BufferInfo.TextInfo.Flags &= ~SINGLE_ATTRIBUTES_PER_LINE; 01371 return; 01372 } 01373 if (++RowIndex == ScreenInfo->ScreenBufferSize.Y) { 01374 RowIndex = 0; 01375 } 01376 } 01377 01378 // all of the written lines have the same attribute. 01379 01380 if (ScreenInfo->BufferInfo.TextInfo.Flags & SINGLE_ATTRIBUTES_PER_LINE) { 01381 return; 01382 } 01383 01384 if (StartY == 0 && EndY == (ScreenInfo->ScreenBufferSize.Y-1)) { 01385 ScreenInfo->BufferInfo.TextInfo.Flags |= SINGLE_ATTRIBUTES_PER_LINE; 01386 return; 01387 } 01388 01389 RowIndex = ScreenInfo->BufferInfo.TextInfo.FirstRow; 01390 for (i=0;i<StartY;i++) { 01391 Row = &ScreenInfo->BufferInfo.TextInfo.Rows[RowIndex]; 01392 if (Row->AttrRow.Length != 1) { 01393 return; 01394 } 01395 if (++RowIndex == ScreenInfo->ScreenBufferSize.Y) { 01396 RowIndex = 0; 01397 } 01398 Row = &ScreenInfo->BufferInfo.TextInfo.Rows[RowIndex]; 01399 } 01400 RowIndex = (ScreenInfo->BufferInfo.TextInfo.FirstRow+EndY+1) % ScreenInfo->ScreenBufferSize.Y; 01401 for (i=EndY+1;i<ScreenInfo->ScreenBufferSize.Y;i++) { 01402 Row = &ScreenInfo->BufferInfo.TextInfo.Rows[RowIndex]; 01403 if (Row->AttrRow.Length != 1) { 01404 return; 01405 } 01406 if (++RowIndex == ScreenInfo->ScreenBufferSize.Y) { 01407 RowIndex = 0; 01408 } 01409 } 01410 ScreenInfo->BufferInfo.TextInfo.Flags |= SINGLE_ATTRIBUTES_PER_LINE; 01411 } 01412 01413 01414 VOID 01415 ReadRectFromScreenBuffer( 01416 IN PSCREEN_INFORMATION ScreenInfo, 01417 IN COORD SourcePoint, 01418 IN PCHAR_INFO Target, 01419 IN COORD TargetSize, 01420 IN PSMALL_RECT TargetRect 01421 ) 01422 01423 /*++ 01424 01425 Routine Description: 01426 01427 This routine copies a rectangular region from the screen buffer. 01428 no clipping is done. 01429 01430 Arguments: 01431 01432 ScreenInfo - pointer to screen info 01433 01434 SourcePoint - upper left coordinates of source rectangle 01435 01436 Target - pointer to target buffer 01437 01438 TargetSize - dimensions of target buffer 01439 01440 TargetRect - rectangle in source buffer to copy 01441 01442 Return Value: 01443 01444 none. 01445 01446 --*/ 01447 01448 { 01449 01450 PCHAR_INFO TargetPtr; 01451 SHORT i,j,k; 01452 SHORT XSize,YSize; 01453 BOOLEAN WholeTarget; 01454 SHORT RowIndex; 01455 PROW Row; 01456 PWCHAR Char; 01457 PATTR_PAIR Attr; 01458 SHORT CountOfAttr; 01459 01460 DBGOUTPUT(("ReadRectFromScreenBuffer\n")); 01461 01462 XSize = (SHORT)(TargetRect->Right - TargetRect->Left + 1); 01463 YSize = (SHORT)(TargetRect->Bottom - TargetRect->Top + 1); 01464 01465 TargetPtr = Target; 01466 WholeTarget = FALSE; 01467 if (XSize == TargetSize.X) { 01468 ASSERT (TargetRect->Left == 0); 01469 if (TargetRect->Top != 0) { 01470 TargetPtr = (PCHAR_INFO) 01471 ((PBYTE)Target + SCREEN_BUFFER_POINTER(TargetRect->Left, 01472 TargetRect->Top, 01473 TargetSize.X, 01474 sizeof(CHAR_INFO))); 01475 } 01476 WholeTarget = TRUE; 01477 } 01478 RowIndex = (ScreenInfo->BufferInfo.TextInfo.FirstRow+SourcePoint.Y) % ScreenInfo->ScreenBufferSize.Y; 01479 for (i=0;i<YSize;i++) { 01480 if (!WholeTarget) { 01481 TargetPtr = (PCHAR_INFO) 01482 ((PBYTE)Target + SCREEN_BUFFER_POINTER(TargetRect->Left, 01483 TargetRect->Top+i, 01484 TargetSize.X, 01485 sizeof(CHAR_INFO))); 01486 } 01487 01488 // 01489 // copy the chars and attrs from their respective arrays 01490 // 01491 01492 Row = &ScreenInfo->BufferInfo.TextInfo.Rows[RowIndex]; 01493 Char = &Row->CharRow.Chars[SourcePoint.X]; 01494 FindAttrIndex(Row->AttrRow.Attrs, 01495 SourcePoint.X, 01496 &Attr, 01497 &CountOfAttr 01498 ); 01499 k=0; 01500 #if defined(FE_SB) 01501 if (CONSOLE_IS_DBCS_OUTPUTCP(ScreenInfo->Console)) { 01502 PBYTE AttrP = &Row->CharRow.KAttrs[SourcePoint.X]; 01503 for (j=0;j<XSize;TargetPtr++) { 01504 BYTE AttrR; 01505 AttrR = *AttrP++; 01506 if (j==0 && AttrR & ATTR_TRAILING_BYTE) 01507 { 01508 TargetPtr->Char.UnicodeChar = UNICODE_SPACE; 01509 AttrR = 0; 01510 } 01511 else if (j+1 >= XSize && AttrR & ATTR_LEADING_BYTE) 01512 { 01513 TargetPtr->Char.UnicodeChar = UNICODE_SPACE; 01514 AttrR = 0; 01515 } 01516 else 01517 TargetPtr->Char.UnicodeChar = *Char; 01518 Char++; 01519 TargetPtr->Attributes = Attr->Attr | (WCHAR)(AttrR & ATTR_DBCSSBCS_BYTE) << 8; 01520 j+=1; 01521 if (++k==CountOfAttr && j<XSize) { 01522 Attr++; 01523 k=0; 01524 CountOfAttr = Attr->Length; 01525 } 01526 } 01527 } 01528 else{ 01529 #endif 01530 for (j=0;j<XSize;TargetPtr++) { 01531 TargetPtr->Char.UnicodeChar = *Char++; 01532 TargetPtr->Attributes = Attr->Attr; 01533 j+=1; 01534 if (++k==CountOfAttr && j<XSize) { 01535 Attr++; 01536 k=0; 01537 CountOfAttr = Attr->Length; 01538 } 01539 } 01540 #if defined(FE_SB) 01541 } 01542 #endif 01543 01544 if (++RowIndex == ScreenInfo->ScreenBufferSize.Y) { 01545 RowIndex = 0; 01546 } 01547 } 01548 } 01549 01550 VOID 01551 CopyRectangle( 01552 IN PSCREEN_INFORMATION ScreenInfo, 01553 IN PSMALL_RECT SourceRect, 01554 IN COORD TargetPoint 01555 ) 01556 01557 /*++ 01558 01559 Routine Description: 01560 01561 This routine copies a rectangular region from the screen buffer to 01562 the screen buffer. no clipping is done. 01563 01564 Arguments: 01565 01566 ScreenInfo - pointer to screen info 01567 01568 SourceRect - rectangle in source buffer to copy 01569 01570 TargetPoint - upper left coordinates of new location rectangle 01571 01572 Return Value: 01573 01574 none. 01575 01576 --*/ 01577 01578 { 01579 SMALL_RECT Target; 01580 COORD SourcePoint; 01581 COORD Size; 01582 DBGOUTPUT(("CopyRectangle\n")); 01583 01584 01585 LockScrollBuffer(); 01586 01587 SourcePoint.X = SourceRect->Left; 01588 SourcePoint.Y = SourceRect->Top; 01589 Target.Left = 0; 01590 Target.Top = 0; 01591 Target.Right = Size.X = SourceRect->Right - SourceRect->Left; 01592 Target.Bottom = Size.Y = SourceRect->Bottom - SourceRect->Top; 01593 Size.X++; 01594 Size.Y++; 01595 01596 if (ScrollBufferSize < (Size.X * Size.Y * sizeof(CHAR_INFO))) { 01597 FreeScrollBuffer(); 01598 if (!NT_SUCCESS(AllocateScrollBuffer(Size.X * Size.Y * sizeof(CHAR_INFO)))) { 01599 UnlockScrollBuffer(); 01600 return; 01601 } 01602 } 01603 01604 ReadRectFromScreenBuffer(ScreenInfo, 01605 SourcePoint, 01606 ScrollBuffer, 01607 Size, 01608 &Target 01609 ); 01610 01611 WriteRectToScreenBuffer((PBYTE)ScrollBuffer, 01612 Size, 01613 &Target, 01614 ScreenInfo, 01615 TargetPoint, 01616 0xFFFFFFFF // ScrollBuffer won't need conversion 01617 ); 01618 UnlockScrollBuffer(); 01619 } 01620 01621 01622 NTSTATUS 01623 ReadScreenBuffer( 01624 IN PSCREEN_INFORMATION ScreenInformation, 01625 OUT PCHAR_INFO Buffer, 01626 IN OUT PSMALL_RECT ReadRegion 01627 ) 01628 01629 /*++ 01630 01631 Routine Description: 01632 01633 This routine reads a rectangular region from the screen buffer. 01634 The region is first clipped. 01635 01636 Arguments: 01637 01638 ScreenInformation - Screen buffer to read from. 01639 01640 Buffer - Buffer to read into. 01641 01642 ReadRegion - Region to read. 01643 01644 Return Value: 01645 01646 01647 --*/ 01648 01649 { 01650 COORD TargetSize; 01651 COORD TargetPoint,SourcePoint; 01652 SMALL_RECT Target; 01653 01654 DBGOUTPUT(("ReadScreenBuffer\n")); 01655 // 01656 // calculate dimensions of caller's buffer. have to do this calculation 01657 // before clipping. 01658 // 01659 01660 TargetSize.X = (SHORT)(ReadRegion->Right - ReadRegion->Left + 1); 01661 TargetSize.Y = (SHORT)(ReadRegion->Bottom - ReadRegion->Top + 1); 01662 01663 if (TargetSize.X <= 0 || TargetSize.Y <= 0) { 01664 return STATUS_SUCCESS; 01665 } 01666 01667 // do clipping. 01668 01669 if (ReadRegion->Right > (SHORT)(ScreenInformation->ScreenBufferSize.X-1)) { 01670 ReadRegion->Right = (SHORT)(ScreenInformation->ScreenBufferSize.X-1); 01671 } 01672 if (ReadRegion->Bottom > (SHORT)(ScreenInformation->ScreenBufferSize.Y-1)) { 01673 ReadRegion->Bottom = (SHORT)(ScreenInformation->ScreenBufferSize.Y-1); 01674 } 01675 if (ReadRegion->Left < 0) { 01676 TargetPoint.X = -ReadRegion->Left; 01677 ReadRegion->Left = 0; 01678 } 01679 else { 01680 TargetPoint.X = 0; 01681 } 01682 if (ReadRegion->Top < 0) { 01683 TargetPoint.Y = -ReadRegion->Top; 01684 ReadRegion->Top = 0; 01685 } 01686 else { 01687 TargetPoint.Y = 0; 01688 } 01689 01690 SourcePoint.X = ReadRegion->Left; 01691 SourcePoint.Y = ReadRegion->Top; 01692 Target.Left = TargetPoint.X; 01693 Target.Top = TargetPoint.Y; 01694 Target.Right = TargetPoint.X + (ReadRegion->Right - ReadRegion->Left); 01695 Target.Bottom = TargetPoint.Y + (ReadRegion->Bottom - ReadRegion->Top); 01696 ReadRectFromScreenBuffer(ScreenInformation, 01697 SourcePoint, 01698 Buffer, 01699 TargetSize, 01700 &Target 01701 ); 01702 return STATUS_SUCCESS; 01703 } 01704 01705 NTSTATUS 01706 WriteScreenBuffer( 01707 IN PSCREEN_INFORMATION ScreenInformation, 01708 IN PCHAR_INFO Buffer, 01709 IN OUT PSMALL_RECT WriteRegion 01710 ) 01711 01712 /*++ 01713 01714 Routine Description: 01715 01716 This routine write a rectangular region to the screen buffer. 01717 The region is first clipped. 01718 01719 The region should contain Unicode or UnicodeOem chars. 01720 01721 Arguments: 01722 01723 ScreenInformation - Screen buffer to write to. 01724 01725 Buffer - Buffer to write from. 01726 01727 ReadRegion - Region to write. 01728 01729 Return Value: 01730 01731 01732 --*/ 01733 01734 { 01735 COORD SourceSize; 01736 COORD TargetPoint; 01737 SMALL_RECT SourceRect; 01738 01739 DBGOUTPUT(("WriteScreenBuffer\n")); 01740 // 01741 // calculate dimensions of caller's buffer. have to do this calculation 01742 // before clipping. 01743 // 01744 01745 SourceSize.X = (SHORT)(WriteRegion->Right - WriteRegion->Left + 1); 01746 SourceSize.Y = (SHORT)(WriteRegion->Bottom - WriteRegion->Top + 1); 01747 if (SourceSize.X <= 0 || SourceSize.Y <= 0) { 01748 return STATUS_SUCCESS; 01749 } 01750 01751 // do clipping. 01752 01753 if (WriteRegion->Left >= ScreenInformation->ScreenBufferSize.X || 01754 WriteRegion->Top >= ScreenInformation->ScreenBufferSize.Y) { 01755 return STATUS_SUCCESS; 01756 } 01757 01758 if (WriteRegion->Right > (SHORT)(ScreenInformation->ScreenBufferSize.X-1)) 01759 WriteRegion->Right = (SHORT)(ScreenInformation->ScreenBufferSize.X-1); 01760 SourceRect.Right = WriteRegion->Right - WriteRegion->Left; 01761 if (WriteRegion->Bottom > (SHORT)(ScreenInformation->ScreenBufferSize.Y-1)) 01762 WriteRegion->Bottom = (SHORT)(ScreenInformation->ScreenBufferSize.Y-1); 01763 SourceRect.Bottom = WriteRegion->Bottom - WriteRegion->Top; 01764 if (WriteRegion->Left < 0) { 01765 SourceRect.Left = -WriteRegion->Left; 01766 WriteRegion->Left = 0; 01767 } 01768 else { 01769 SourceRect.Left = 0; 01770 } 01771 if (WriteRegion->Top < 0) { 01772 SourceRect.Top = -WriteRegion->Top; 01773 WriteRegion->Top = 0; 01774 } 01775 else { 01776 SourceRect.Top = 0; 01777 } 01778 01779 TargetPoint.X = WriteRegion->Left; 01780 TargetPoint.Y = WriteRegion->Top; 01781 WriteRectToScreenBuffer((PBYTE)Buffer, 01782 SourceSize, 01783 &SourceRect, 01784 ScreenInformation, 01785 TargetPoint, 01786 0xFFFFFFFF 01787 ); 01788 return STATUS_SUCCESS; 01789 } 01790 01791 01792 01793 01794 NTSTATUS 01795 ReadOutputString( 01796 IN PSCREEN_INFORMATION ScreenInfo, 01797 OUT PVOID Buffer, 01798 IN COORD ReadCoord, 01799 IN ULONG StringType, 01800 IN OUT PULONG NumRecords // this value is valid even for error cases 01801 ) 01802 01803 /*++ 01804 01805 Routine Description: 01806 01807 This routine reads a string of characters or attributes from the 01808 screen buffer. 01809 01810 Arguments: 01811 01812 ScreenInfo - Pointer to screen buffer information. 01813 01814 Buffer - Buffer to read into. 01815 01816 ReadCoord - Screen buffer coordinate to begin reading from. 01817 01818 StringType 01819 01820 CONSOLE_ASCII - read a string of ASCII characters. 01821 CONSOLE_REAL_UNICODE - read a string of Real Unicode characters. 01822 CONSOLE_FALSE_UNICODE - read a string of False Unicode characters. 01823 CONSOLE_ATTRIBUTE - read a string of attributes. 01824 01825 NumRecords - On input, the size of the buffer in elements. On output, 01826 the number of elements read. 01827 01828 Return Value: 01829 01830 01831 --*/ 01832 01833 { 01834 ULONG NumRead; 01835 SHORT X,Y; 01836 SHORT RowIndex; 01837 SHORT CountOfAttr; 01838 PATTR_PAIR Attr; 01839 PROW Row; 01840 PWCHAR Char; 01841 SHORT j,k; 01842 PWCHAR TransBuffer = NULL; 01843 PWCHAR BufPtr; 01844 #if defined(FE_SB) 01845 PBYTE AttrP; 01846 PBYTE TransBufferA,BufPtrA; 01847 PCONSOLE_INFORMATION Console = ScreenInfo->Console; 01848 #endif 01849 01850 DBGOUTPUT(("ReadOutputString\n")); 01851 if (*NumRecords == 0) 01852 return STATUS_SUCCESS; 01853 NumRead = 0; 01854 X=ReadCoord.X; 01855 Y=ReadCoord.Y; 01856 if (X>=ScreenInfo->ScreenBufferSize.X || 01857 X<0 || 01858 Y>=ScreenInfo->ScreenBufferSize.Y || 01859 Y<0) { 01860 *NumRecords = 0; 01861 return STATUS_SUCCESS; 01862 } 01863 01864 RowIndex = (ScreenInfo->BufferInfo.TextInfo.FirstRow+ReadCoord.Y) % ScreenInfo->ScreenBufferSize.Y; 01865 01866 if (StringType == CONSOLE_ASCII) { 01867 TransBuffer = (PWCHAR)ConsoleHeapAlloc(MAKE_TAG( TMP_TAG ),*NumRecords * sizeof(WCHAR)); 01868 if (TransBuffer == NULL) { 01869 return STATUS_NO_MEMORY; 01870 } 01871 BufPtr = TransBuffer; 01872 } else { 01873 BufPtr = Buffer; 01874 } 01875 01876 #if defined(FE_SB) 01877 if (CONSOLE_IS_DBCS_OUTPUTCP(Console)) 01878 { 01879 TransBufferA = (PBYTE)ConsoleHeapAlloc(MAKE_TAG( TMP_DBCS_TAG ),*NumRecords * sizeof(BYTE)); 01880 if (TransBufferA == NULL) { 01881 if (TransBuffer != NULL) 01882 ConsoleHeapFree(TransBuffer); 01883 return STATUS_NO_MEMORY; 01884 } 01885 BufPtrA = TransBufferA; 01886 } 01887 #endif 01888 if ((StringType == CONSOLE_ASCII) || 01889 (StringType == CONSOLE_REAL_UNICODE) || 01890 (StringType == CONSOLE_FALSE_UNICODE)) { 01891 while (NumRead < *NumRecords) { 01892 01893 // 01894 // copy the chars from its array 01895 // 01896 01897 Row = &ScreenInfo->BufferInfo.TextInfo.Rows[RowIndex]; 01898 Char = &Row->CharRow.Chars[X]; 01899 #if defined(FE_SB) 01900 if (CONSOLE_IS_DBCS_OUTPUTCP(Console)) 01901 AttrP = &Row->CharRow.KAttrs[X]; 01902 #endif 01903 if ((ULONG)(ScreenInfo->ScreenBufferSize.X - X) > (*NumRecords - NumRead)) { 01904 RtlCopyMemory(BufPtr,Char,(*NumRecords - NumRead) * sizeof(WCHAR)); 01905 #if defined(FE_SB) 01906 if (CONSOLE_IS_DBCS_OUTPUTCP(Console)) 01907 RtlCopyMemory(BufPtrA,AttrP,(*NumRecords - NumRead) * sizeof(CHAR)); 01908 #endif 01909 NumRead += *NumRecords - NumRead; 01910 break; 01911 } 01912 RtlCopyMemory(BufPtr,Char,(ScreenInfo->ScreenBufferSize.X - X) * sizeof(WCHAR)); 01913 BufPtr = (PVOID)((PBYTE)BufPtr + ((ScreenInfo->ScreenBufferSize.X - X) * sizeof(WCHAR))); 01914 #if defined(FE_SB) 01915 if (CONSOLE_IS_DBCS_OUTPUTCP(Console)) { 01916 RtlCopyMemory(BufPtrA,AttrP,(ScreenInfo->ScreenBufferSize.X - X) * sizeof(CHAR)); 01917 BufPtrA = (PVOID)((PBYTE)BufPtrA + ((ScreenInfo->ScreenBufferSize.X - X) * sizeof(CHAR))); 01918 } 01919 #endif 01920 NumRead += ScreenInfo->ScreenBufferSize.X - X; 01921 if (++RowIndex == ScreenInfo->ScreenBufferSize.Y) { 01922 RowIndex = 0; 01923 } 01924 X = 0; 01925 Y++; 01926 if (Y>=ScreenInfo->ScreenBufferSize.Y) { 01927 break; 01928 } 01929 } 01930 #if defined(FE_SB) 01931 if (CONSOLE_IS_DBCS_OUTPUTCP(Console) && (NumRead)) { 01932 if (StringType == CONSOLE_ASCII) { 01933 Char = BufPtr = TransBuffer; 01934 } else { 01935 Char = BufPtr = Buffer; 01936 } 01937 AttrP = BufPtrA = TransBufferA; 01938 01939 if (*BufPtrA & ATTR_TRAILING_BYTE) 01940 { 01941 j = k = (SHORT)(NumRead - 1); 01942 BufPtr++; 01943 *Char++ = UNICODE_SPACE; 01944 BufPtrA++; 01945 NumRead = 1; 01946 } 01947 else { 01948 j = k = (SHORT)NumRead; 01949 NumRead = 0; 01950 } 01951 while (j--) { 01952 if (!(*BufPtrA & ATTR_TRAILING_BYTE)) { 01953 *Char++ = *BufPtr; 01954 NumRead++; 01955 } 01956 BufPtr++; 01957 BufPtrA++; 01958 } 01959 if (k && *(BufPtrA-1) & ATTR_LEADING_BYTE) 01960 { 01961 *(Char-1) = UNICODE_SPACE; 01962 } 01963 } 01964 #endif 01965 } else if (StringType == CONSOLE_ATTRIBUTE) { 01966 PWORD TargetPtr=BufPtr; 01967 while (NumRead < *NumRecords) { 01968 01969 // 01970 // copy the attrs from its array 01971 // 01972 01973 Row = &ScreenInfo->BufferInfo.TextInfo.Rows[RowIndex]; 01974 #if defined(FE_SB) 01975 if (CONSOLE_IS_DBCS_OUTPUTCP(Console)) 01976 AttrP = &Row->CharRow.KAttrs[X]; 01977 #endif 01978 FindAttrIndex(Row->AttrRow.Attrs, 01979 X, 01980 &Attr, 01981 &CountOfAttr 01982 ); 01983 k=0; 01984 for (j=X;j<ScreenInfo->ScreenBufferSize.X;TargetPtr++) { 01985 #if defined(FE_SB) 01986 if (!CONSOLE_IS_DBCS_OUTPUTCP(Console) ) 01987 *TargetPtr = Attr->Attr; 01988 else if ((j == X) && (*AttrP & ATTR_TRAILING_BYTE)) 01989 *TargetPtr = Attr->Attr; 01990 else if (*AttrP & ATTR_LEADING_BYTE){ 01991 if ((NumRead == *NumRecords-1)||(j == ScreenInfo->ScreenBufferSize.X-1)) 01992 *TargetPtr = Attr->Attr; 01993 else 01994 *TargetPtr = Attr->Attr | (WCHAR)(*AttrP & ATTR_DBCSSBCS_BYTE) << 8; 01995 } 01996 else 01997 *TargetPtr = Attr->Attr | (WCHAR)(*AttrP & ATTR_DBCSSBCS_BYTE) << 8; 01998 #else 01999 *TargetPtr = Attr->Attr; 02000 #endif 02001 NumRead++; 02002 j+=1; 02003 if (++k==CountOfAttr && j<ScreenInfo->ScreenBufferSize.X) { 02004 Attr++; 02005 k=0; 02006 CountOfAttr = Attr->Length; 02007 } 02008 if (NumRead == *NumRecords) { 02009 #if defined(FE_SB) 02010 if (CONSOLE_IS_DBCS_OUTPUTCP(Console)) 02011 ConsoleHeapFree(TransBufferA); 02012 #endif 02013 return STATUS_SUCCESS; 02014 } 02015 #if defined(FE_SB) 02016 if (CONSOLE_IS_DBCS_OUTPUTCP(Console)) 02017 AttrP++; 02018 #endif 02019 } 02020 if (++RowIndex == ScreenInfo->ScreenBufferSize.Y) { 02021 RowIndex = 0; 02022 } 02023 X = 0; 02024 Y++; 02025 if (Y>=ScreenInfo->ScreenBufferSize.Y) { 02026 break; 02027 } 02028 } 02029 } else { 02030 *NumRecords = 0; 02031 #if defined(FE_SB) 02032 if (CONSOLE_IS_DBCS_OUTPUTCP(Console)) 02033 ConsoleHeapFree(TransBufferA); 02034 #endif 02035 return STATUS_INVALID_PARAMETER; 02036 } 02037 02038 if (StringType == CONSOLE_ASCII) { 02039 UINT Codepage; 02040 #if defined(FE_SB) 02041 if ((ScreenInfo->Flags & CONSOLE_OEMFONT_DISPLAY) && 02042 !(ScreenInfo->Console->FullScreenFlags & CONSOLE_FULLSCREEN)) { 02043 if (ScreenInfo->Console->OutputCP != WINDOWSCP) 02044 Codepage = USACP; 02045 else 02046 Codepage = WINDOWSCP; 02047 } else { 02048 Codepage = ScreenInfo->Console->OutputCP; 02049 } 02050 #else 02051 if ((ScreenInfo->Flags & CONSOLE_OEMFONT_DISPLAY) && 02052 !(ScreenInfo->Console->FullScreenFlags & CONSOLE_FULLSCREEN)) { 02053 Codepage = WINDOWSCP; 02054 } else { 02055 Codepage = ScreenInfo->Console->OutputCP; 02056 } 02057 #endif 02058 #if defined(FE_SB) 02059 if ((NumRead == 1) && !CONSOLE_IS_DBCS_OUTPUTCP(Console)) 02060 #else 02061 if (NumRead == 1) 02062 #endif 02063 { 02064 *((PBYTE)Buffer) = WcharToChar(Codepage, *TransBuffer); 02065 } else { 02066 NumRead = ConvertOutputToOem(Codepage, TransBuffer, NumRead, Buffer, *NumRecords); 02067 } 02068 ConsoleHeapFree(TransBuffer); 02069 } else if (StringType == CONSOLE_REAL_UNICODE && 02070 (ScreenInfo->Flags & CONSOLE_OEMFONT_DISPLAY) && 02071 !(ScreenInfo->Console->FullScreenFlags & CONSOLE_FULLSCREEN)) { 02072 /* 02073 * Buffer contains false Unicode (UnicodeOem) only in Windowed 02074 * RasterFont mode, so in this case, convert it to real Unicode. 02075 */ 02076 FalseUnicodeToRealUnicode(Buffer, 02077 NumRead, 02078 ScreenInfo->Console->OutputCP 02079 ); 02080 } 02081 02082 #if defined(FE_SB) 02083 if (CONSOLE_IS_DBCS_OUTPUTCP(Console)) 02084 ConsoleHeapFree(TransBufferA); 02085 #endif 02086 *NumRecords = NumRead; 02087 return STATUS_SUCCESS; 02088 } 02089 02090 02091 02092 NTSTATUS 02093 GetScreenBufferInformation( 02094 IN PSCREEN_INFORMATION ScreenInfo, 02095 OUT PCOORD Size, 02096 OUT PCOORD CursorPosition, 02097 OUT PCOORD ScrollPosition, 02098 OUT PWORD Attributes, 02099 OUT PCOORD CurrentWindowSize, 02100 OUT PCOORD MaximumWindowSize 02101 ) 02102 02103 /*++ 02104 02105 Routine Description: 02106 02107 This routine returns data about the screen buffer. 02108 02109 Arguments: 02110 02111 ScreenInfo - Pointer to screen buffer information. 02112 02113 Size - Pointer to location in which to store screen buffer size. 02114 02115 CursorPosition - Pointer to location in which to store the cursor position. 02116 02117 ScrollPosition - Pointer to location in which to store the scroll position. 02118 02119 Attributes - Pointer to location in which to store the default attributes. 02120 02121 CurrentWindowSize - Pointer to location in which to store current window size. 02122 02123 MaximumWindowSize - Pointer to location in which to store maximum window size. 02124 02125 Return Value: 02126 02127 --*/ 02128 02129 { 02130 WINDOW_LIMITS WindowLimits; 02131 02132 *Size = ScreenInfo->ScreenBufferSize; 02133 *CursorPosition = ScreenInfo->BufferInfo.TextInfo.CursorPosition; 02134 ScrollPosition->X = ScreenInfo->Window.Left; 02135 ScrollPosition->Y = ScreenInfo->Window.Top; 02136 *Attributes = ScreenInfo->Attributes; 02137 CurrentWindowSize->X = (SHORT)CONSOLE_WINDOW_SIZE_X(ScreenInfo); 02138 CurrentWindowSize->Y = (SHORT)CONSOLE_WINDOW_SIZE_Y(ScreenInfo); 02139 if (ScreenInfo->Console->FullScreenFlags & CONSOLE_FULLSCREEN_HARDWARE) { 02140 MaximumWindowSize->X = min(80,ScreenInfo->ScreenBufferSize.X); 02141 #if defined(FE_SB) 02142 if (CONSOLE_IS_DBCS_OUTPUTCP(ScreenInfo->Console)) 02143 { 02144 MaximumWindowSize->Y = min(25,ScreenInfo->ScreenBufferSize.Y); 02145 } 02146 else 02147 { 02148 MaximumWindowSize->Y = min(50,ScreenInfo->ScreenBufferSize.Y); 02149 } 02150 #else 02151 MaximumWindowSize->Y = min(50,ScreenInfo->ScreenBufferSize.Y); 02152 #endif 02153 } else { 02154 GetWindowLimits(ScreenInfo, &WindowLimits); 02155 *MaximumWindowSize = WindowLimits.MaximumWindowSize; 02156 } 02157 return STATUS_SUCCESS; 02158 } 02159 02160 02161 VOID 02162 UpdateScrollBars( 02163 IN PSCREEN_INFORMATION ScreenInfo 02164 ) 02165 { 02166 if (!ACTIVE_SCREEN_BUFFER(ScreenInfo)) { 02167 return; 02168 } 02169 02170 if (ScreenInfo->Console->Flags & CONSOLE_UPDATING_SCROLL_BARS) 02171 return; 02172 ScreenInfo->Console->Flags |= CONSOLE_UPDATING_SCROLL_BARS; 02173 PostMessage(ScreenInfo->Console->hWnd, 02174 CM_UPDATE_SCROLL_BARS, 02175 (WPARAM)ScreenInfo, 02176 0 02177 ); 02178 } 02179 02180 VOID 02181 InternalUpdateScrollBars( 02182 IN PSCREEN_INFORMATION ScreenInfo 02183 ) 02184 { 02185 SCROLLINFO si; 02186 02187 ScreenInfo->Console->Flags &= ~CONSOLE_UPDATING_SCROLL_BARS; 02188 if (!ACTIVE_SCREEN_BUFFER(ScreenInfo)) { 02189 return; 02190 } 02191 02192 ScreenInfo->ResizingWindow++; 02193 02194 si.cbSize = sizeof(si); 02195 si.fMask = SIF_ALL; 02196 si.nPage = CONSOLE_WINDOW_SIZE_Y(ScreenInfo); 02197 si.nMin = 0; 02198 si.nMax = ScreenInfo->ScreenBufferSize.Y - 1; 02199 si.nPos = ScreenInfo->Window.Top; 02200 SetScrollInfo(ScreenInfo->Console->hWnd, SB_VERT, &si, TRUE); 02201 02202 si.cbSize = sizeof(si); 02203 si.fMask = SIF_ALL; 02204 si.nPage = CONSOLE_WINDOW_SIZE_X(ScreenInfo); 02205 si.nMin = 0; 02206 si.nMax = ScreenInfo->ScreenBufferSize.X - 1; 02207 si.nPos = ScreenInfo->Window.Left; 02208 SetScrollInfo(ScreenInfo->Console->hWnd, SB_HORZ, &si, TRUE); 02209 02210 ScreenInfo->ResizingWindow--; 02211 } 02212 02213 VOID 02214 ScreenBufferSizeChange( 02215 IN PSCREEN_INFORMATION ScreenInfo, 02216 IN COORD NewSize 02217 ) 02218 { 02219 INPUT_RECORD InputEvent; 02220 02221 InputEvent.EventType = WINDOW_BUFFER_SIZE_EVENT; 02222 InputEvent.Event.WindowBufferSizeEvent.dwSize = NewSize; 02223 WriteInputBuffer(ScreenInfo->Console, 02224 &ScreenInfo->Console->InputBuffer, 02225 &InputEvent, 02226 1 02227 ); 02228 } 02229 02230 NTSTATUS 02231 ResizeScreenBuffer( 02232 IN PSCREEN_INFORMATION ScreenInfo, 02233 IN COORD NewScreenSize, 02234 IN BOOL DoScrollBarUpdate 02235 ) 02236 02237 /*++ 02238 02239 Routine Description: 02240 02241 This routine resizes the screen buffer. 02242 02243 Arguments: 02244 02245 ScreenInfo - pointer to screen buffer info. 02246 02247 NewScreenSize - new size of screen. 02248 02249 Return Value: 02250 02251 --*/ 02252 02253 { 02254 SHORT i,j; 02255 BOOLEAN WindowMaximizedX,WindowMaximizedY; 02256 SHORT LimitX,LimitY; 02257 PWCHAR TextRows,TextRowPtr; 02258 BOOL UpdateWindow; 02259 SHORT TopRow,TopRowIndex; // new top row of screen buffer 02260 COORD CursorPosition; 02261 #if defined(FE_SB) 02262 DBCS_SCREEN_BUFFER NewDbcsScreenBuffer; 02263 PBYTE TextRowPtrA; 02264 #endif 02265 02266 // 02267 // Don't allow resize of graphics apps 02268 // 02269 02270 if (!(ScreenInfo->Flags & CONSOLE_TEXTMODE_BUFFER)) { 02271 return STATUS_UNSUCCESSFUL; 02272 } 02273 02274 TextRows = (PWCHAR)ConsoleHeapAlloc(MAKE_TAG( SCREEN_TAG ),NewScreenSize.X*NewScreenSize.Y*sizeof(WCHAR)); 02275 if (TextRows == NULL) { 02276 return STATUS_NO_MEMORY; 02277 } 02278 #if defined(FE_SB) 02279 if (! CreateDbcsScreenBuffer(ScreenInfo->Console,NewScreenSize,&NewDbcsScreenBuffer)) 02280 { 02281 ConsoleHeapFree(TextRows); 02282 return STATUS_NO_MEMORY; 02283 } 02284 #endif 02285 LimitX = (NewScreenSize.X < ScreenInfo->ScreenBufferSize.X) ? 02286 NewScreenSize.X : ScreenInfo->ScreenBufferSize.X; 02287 LimitY = (NewScreenSize.Y < ScreenInfo->ScreenBufferSize.Y) ? 02288 NewScreenSize.Y : ScreenInfo->ScreenBufferSize.Y; 02289 TopRow = 0; 02290 if (NewScreenSize.Y <= ScreenInfo->BufferInfo.TextInfo.CursorPosition.Y) { 02291 TopRow += ScreenInfo->BufferInfo.TextInfo.CursorPosition.Y - NewScreenSize.Y + 1; 02292 } 02293 TopRowIndex = (ScreenInfo->BufferInfo.TextInfo.FirstRow+TopRow) % ScreenInfo->ScreenBufferSize.Y; 02294 if (NewScreenSize.Y != ScreenInfo->ScreenBufferSize.Y) { 02295 PROW Temp; 02296 SHORT NumToCopy,NumToCopy2; 02297 02298 // 02299 // resize ROWs array. first alloc a new ROWs array. then copy the old 02300 // one over, resetting the FirstRow. 02301 // 02302 // 02303 02304 Temp = (PROW)ConsoleHeapAlloc(MAKE_TAG( SCREEN_TAG ),NewScreenSize.Y*sizeof(ROW)); 02305 if (Temp == NULL) { 02306 ConsoleHeapFree(TextRows); 02307 #if defined(FE_SB) 02308 DeleteDbcsScreenBuffer(&NewDbcsScreenBuffer); 02309 #endif 02310 return STATUS_NO_MEMORY; 02311 } 02312 NumToCopy = ScreenInfo->ScreenBufferSize.Y-TopRowIndex; 02313 if (NumToCopy > NewScreenSize.Y) 02314 NumToCopy = NewScreenSize.Y; 02315 RtlCopyMemory(Temp,&ScreenInfo->BufferInfo.TextInfo.Rows[TopRowIndex],NumToCopy*sizeof(ROW)); 02316 if (TopRowIndex!=0 && NumToCopy != NewScreenSize.Y) { 02317 NumToCopy2 = TopRowIndex; 02318 if (NumToCopy2 > (NewScreenSize.Y-NumToCopy)) 02319 NumToCopy2 = NewScreenSize.Y-NumToCopy; 02320 RtlCopyMemory(&Temp[NumToCopy], 02321 ScreenInfo->BufferInfo.TextInfo.Rows, 02322 NumToCopy2*sizeof(ROW) 02323 ); 02324 } 02325 for (i=0;i<LimitY;i++) { 02326 if (Temp[i].AttrRow.Length == 1) { 02327 Temp[i].AttrRow.Attrs = &Temp[i].AttrRow.AttrPair; 02328 } 02329 } 02330 02331 // 02332 // if the new screen buffer has fewer rows than the existing one, 02333 // free the extra rows. if the new screen buffer has more rows 02334 // than the existing one, allocate new rows. 02335 // 02336 02337 if (NewScreenSize.Y < ScreenInfo->ScreenBufferSize.Y) { 02338 i = (TopRowIndex+NewScreenSize.Y) % ScreenInfo->ScreenBufferSize.Y; 02339 for (j=NewScreenSize.Y;j<ScreenInfo->ScreenBufferSize.Y;j++) { 02340 if (ScreenInfo->BufferInfo.TextInfo.Rows[i].AttrRow.Length > 1) { 02341 ConsoleHeapFree(ScreenInfo->BufferInfo.TextInfo.Rows[i].AttrRow.Attrs); 02342 } 02343 if (++i == ScreenInfo->ScreenBufferSize.Y) { 02344 i = 0; 02345 } 02346 } 02347 } else if (NewScreenSize.Y > ScreenInfo->ScreenBufferSize.Y) { 02348 for (i=ScreenInfo->ScreenBufferSize.Y;i<NewScreenSize.Y;i++) { 02349 Temp[i].AttrRow.Length = 1; 02350 Temp[i].AttrRow.AttrPair.Length = NewScreenSize.X; 02351 Temp[i].AttrRow.AttrPair.Attr = ScreenInfo->Attributes; 02352 Temp[i].AttrRow.Attrs = &Temp[i].AttrRow.AttrPair; 02353 } 02354 } 02355 ScreenInfo->BufferInfo.TextInfo.FirstRow = 0; 02356 ConsoleHeapFree(ScreenInfo->BufferInfo.TextInfo.Rows); 02357 ScreenInfo->BufferInfo.TextInfo.Rows = Temp; 02358 } 02359 02360 // 02361 // Realloc each row. any horizontal growth results in the last 02362 // attribute in a row getting extended. 02363 // 02364 #if defined(FE_SB) 02365 TextRowPtrA=NewDbcsScreenBuffer.KAttrRows; 02366 #endif 02367 for (i=0,TextRowPtr=TextRows;i<LimitY;i++,TextRowPtr+=NewScreenSize.X) 02368 { 02369 RtlCopyMemory(TextRowPtr, 02370 ScreenInfo->BufferInfo.TextInfo.Rows[i].CharRow.Chars, 02371 LimitX*sizeof(WCHAR)); 02372 #if defined(FE_SB) 02373 if (TextRowPtrA) { 02374 RtlCopyMemory(TextRowPtrA, 02375 ScreenInfo->BufferInfo.TextInfo.Rows[i].CharRow.KAttrs, 02376 LimitX*sizeof(CHAR)); 02377 } 02378 #endif 02379 for (j=ScreenInfo->ScreenBufferSize.X;j<NewScreenSize.X;j++) { 02380 TextRowPtr[j] = (WCHAR)' '; 02381 } 02382 02383 if (ScreenInfo->BufferInfo.TextInfo.Rows[i].CharRow.Right > NewScreenSize.X) { 02384 ScreenInfo->BufferInfo.TextInfo.Rows[i].CharRow.OldRight = INVALID_OLD_LENGTH; 02385 ScreenInfo->BufferInfo.TextInfo.Rows[i].CharRow.Right = NewScreenSize.X; 02386 } 02387 ScreenInfo->BufferInfo.TextInfo.Rows[i].CharRow.Chars = TextRowPtr; 02388 #if defined(FE_SB) 02389 ScreenInfo->BufferInfo.TextInfo.Rows[i].CharRow.KAttrs = TextRowPtrA; 02390 if (TextRowPtrA) { 02391 if (NewScreenSize.X > ScreenInfo->ScreenBufferSize.X) 02392 RtlZeroMemory(TextRowPtrA+ScreenInfo->ScreenBufferSize.X, 02393 NewScreenSize.X-ScreenInfo->ScreenBufferSize.X); 02394 TextRowPtrA+=NewScreenSize.X; 02395 } 02396 #endif 02397 } 02398 for (;i<NewScreenSize.Y;i++,TextRowPtr+=NewScreenSize.X) 02399 { 02400 for (j=0;j<NewScreenSize.X;j++) { 02401 TextRowPtr[j] = (WCHAR)' '; 02402 } 02403 #if defined(FE_SB) 02404 if (TextRowPtrA) { 02405 RtlZeroMemory(TextRowPtrA, NewScreenSize.X); 02406 } 02407 #endif 02408 ScreenInfo->BufferInfo.TextInfo.Rows[i].CharRow.Chars = TextRowPtr; 02409 ScreenInfo->BufferInfo.TextInfo.Rows[i].CharRow.OldLeft = INVALID_OLD_LENGTH; 02410 ScreenInfo->BufferInfo.TextInfo.Rows[i].CharRow.OldRight = INVALID_OLD_LENGTH; 02411 ScreenInfo->BufferInfo.TextInfo.Rows[i].CharRow.Left = NewScreenSize.X; 02412 ScreenInfo->BufferInfo.TextInfo.Rows[i].CharRow.Right = 0; 02413 #if defined(FE_SB) 02414 ScreenInfo->BufferInfo.TextInfo.Rows[i].CharRow.KAttrs = TextRowPtrA; 02415 if (TextRowPtrA) { 02416 TextRowPtrA+=NewScreenSize.X; 02417 } 02418 #endif 02419 } 02420 ConsoleHeapFree(ScreenInfo->BufferInfo.TextInfo.TextRows); 02421 ScreenInfo->BufferInfo.TextInfo.TextRows = TextRows; 02422 #if defined(FE_SB) 02423 DeleteDbcsScreenBuffer(&ScreenInfo->BufferInfo.TextInfo.DbcsScreenBuffer); 02424 ScreenInfo->BufferInfo.TextInfo.DbcsScreenBuffer = NewDbcsScreenBuffer; 02425 #endif 02426 02427 if (NewScreenSize.X != ScreenInfo->ScreenBufferSize.X) { 02428 for (i=0;i<LimitY;i++) { 02429 PATTR_PAIR IndexedAttr; 02430 SHORT CountOfAttr; 02431 02432 if (NewScreenSize.X > ScreenInfo->ScreenBufferSize.X) { 02433 FindAttrIndex(ScreenInfo->BufferInfo.TextInfo.Rows[i].AttrRow.Attrs, 02434 (SHORT)(ScreenInfo->ScreenBufferSize.X-1), 02435 &IndexedAttr, 02436 &CountOfAttr 02437 ); 02438 ASSERT (IndexedAttr <= 02439 &ScreenInfo->BufferInfo.TextInfo.Rows[i].AttrRow.Attrs[ScreenInfo->BufferInfo.TextInfo.Rows[i].AttrRow.Length-1]); 02440 IndexedAttr->Length += NewScreenSize.X - ScreenInfo->ScreenBufferSize.X; 02441 } 02442 else { 02443 02444 FindAttrIndex(ScreenInfo->BufferInfo.TextInfo.Rows[i].AttrRow.Attrs, 02445 (SHORT)(NewScreenSize.X-1), 02446 &IndexedAttr, 02447 &CountOfAttr 02448 ); 02449 IndexedAttr->Length -= CountOfAttr-1; 02450 if (ScreenInfo->BufferInfo.TextInfo.Rows[i].AttrRow.Length != 1) { 02451 ScreenInfo->BufferInfo.TextInfo.Rows[i].AttrRow.Length = (SHORT)(IndexedAttr - ScreenInfo->BufferInfo.TextInfo.Rows[i].AttrRow.Attrs + 1); 02452 if (ScreenInfo->BufferInfo.TextInfo.Rows[i].AttrRow.Length != 1) { 02453 ScreenInfo->BufferInfo.TextInfo.Rows[i].AttrRow.Attrs = (PATTR_PAIR)ConsoleHeapReAlloc(MAKE_TAG( SCREEN_TAG ),ScreenInfo->BufferInfo.TextInfo.Rows[i].AttrRow.Attrs, 02454 ScreenInfo->BufferInfo.TextInfo.Rows[i].AttrRow.Length * sizeof(ATTR_PAIR)); 02455 } 02456 else { 02457 ScreenInfo->BufferInfo.TextInfo.Rows[i].AttrRow.AttrPair = *IndexedAttr; 02458 ConsoleHeapFree(ScreenInfo->BufferInfo.TextInfo.Rows[i].AttrRow.Attrs); 02459 ScreenInfo->BufferInfo.TextInfo.Rows[i].AttrRow.Attrs = &ScreenInfo->BufferInfo.TextInfo.Rows[i].AttrRow.AttrPair; 02460 } 02461 } 02462 } 02463 } 02464 } 02465 02466 // 02467 // if the screen buffer is resized smaller than the saved 02468 // window size, shrink the saved window size. 02469 // 02470 #ifdef i386 02471 if (ScreenInfo->Console->FullScreenFlags & CONSOLE_FULLSCREEN) { 02472 if (NewScreenSize.X < ScreenInfo->BufferInfo.TextInfo.WindowedWindowSize.X) { 02473 ScreenInfo->BufferInfo.TextInfo.WindowedWindowSize.X = NewScreenSize.X; 02474 } 02475 if (NewScreenSize.Y < ScreenInfo->BufferInfo.TextInfo.WindowedWindowSize.Y) { 02476 ScreenInfo->BufferInfo.TextInfo.WindowedWindowSize.Y = NewScreenSize.Y; 02477 } 02478 ScreenInfo->BufferInfo.TextInfo.WindowedScreenSize = NewScreenSize; 02479 } 02480 #endif 02481 02482 UpdateWindow = FALSE; 02483 02484 // 02485 // if the screen buffer shrunk beyond the boundaries of the window, 02486 // adjust the window origin. 02487 // 02488 02489 if (NewScreenSize.X > CONSOLE_WINDOW_SIZE_X(ScreenInfo)) { 02490 if (ScreenInfo->Window.Right >= NewScreenSize.X) { 02491 ScreenInfo->Window.Left -= ScreenInfo->Window.Right - NewScreenSize.X + 1; 02492 ScreenInfo->Window.Right -= ScreenInfo->Window.Right - NewScreenSize.X + 1; 02493 UpdateWindow = TRUE; 02494 } 02495 } else { 02496 ScreenInfo->Window.Left = 0; 02497 ScreenInfo->Window.Right = NewScreenSize.X - 1; 02498 UpdateWindow = TRUE; 02499 } 02500 if (NewScreenSize.Y > CONSOLE_WINDOW_SIZE_Y(ScreenInfo)) { 02501 if (ScreenInfo->Window.Bottom >= NewScreenSize.Y) { 02502 ScreenInfo->Window.Top -= ScreenInfo->Window.Bottom - NewScreenSize.Y + 1; 02503 ScreenInfo->Window.Bottom -= ScreenInfo->Window.Bottom - NewScreenSize.Y + 1; 02504 UpdateWindow = TRUE; 02505 } 02506 } else { 02507 ScreenInfo->Window.Top = 0; 02508 ScreenInfo->Window.Bottom = NewScreenSize.Y - 1; 02509 UpdateWindow = TRUE; 02510 } 02511 02512 #if defined(FE_SB) 02513 // Should be sets ScreenBufferSize before calls SetCursorPosition 02514 // because SetCursorPosition refer ScreenBufferSize. 02515 // Also, FE version refer in InvertPixels. 02516 // 02517 // kkntbug:11311 02518 ScreenInfo->ScreenBufferSize = NewScreenSize; 02519 #endif 02520 02521 // 02522 // adjust cursor position if it's no longer with screen buffer 02523 // 02524 02525 CursorPosition=ScreenInfo->BufferInfo.TextInfo.CursorPosition; 02526 if (CursorPosition.X >= NewScreenSize.X) { 02527 if (ScreenInfo->OutputMode & ENABLE_WRAP_AT_EOL_OUTPUT) { 02528 CursorPosition.X = 0; 02529 CursorPosition.Y += 1; 02530 } else { 02531 CursorPosition.X = NewScreenSize.X-1; 02532 } 02533 } 02534 if (CursorPosition.Y >= NewScreenSize.Y) { 02535 CursorPosition.Y = NewScreenSize.Y-1; 02536 } 02537 #if defined(FE_SB) 02538 // set cursor position Y is ZERO when expand screen buffer with IME open mode 02539 // from screen buffer is one line mode. 02540 // Because, One line screen buffer mode and IME open mode is set -1 as cursor position Y. 02541 if (ScreenInfo->Console->InputBuffer.ImeMode.Open && CursorPosition.Y < 0) { 02542 CursorPosition.Y = 0; 02543 } 02544 #endif 02545 if (CursorPosition.X != ScreenInfo->BufferInfo.TextInfo.CursorPosition.X || 02546 CursorPosition.Y != ScreenInfo->BufferInfo.TextInfo.CursorPosition.Y) { 02547 SetCursorPosition(ScreenInfo, 02548 CursorPosition, 02549 FALSE 02550 ); 02551 } 02552 02553 ASSERT (ScreenInfo->Window.Left >= 0); 02554 ASSERT (ScreenInfo->Window.Right < NewScreenSize.X); 02555 ASSERT (ScreenInfo->Window.Top >= 0); 02556 ASSERT (ScreenInfo->Window.Bottom < NewScreenSize.Y); 02557 02558 ScreenInfo->ScreenBufferSize = NewScreenSize; 02559 ResetTextFlags(ScreenInfo,0,(SHORT)(ScreenInfo->ScreenBufferSize.Y-1)); 02560 WindowMaximizedX = (CONSOLE_WINDOW_SIZE_X(ScreenInfo) == 02561 ScreenInfo->ScreenBufferSize.X); 02562 WindowMaximizedY = (CONSOLE_WINDOW_SIZE_Y(ScreenInfo) == 02563 ScreenInfo->ScreenBufferSize.Y); 02564 02565 #if defined(FE_IME) 02566 if (CONSOLE_IS_IME_ENABLED()) { 02567 if (!NT_SUCCESS(ConsoleImeMessagePump(ScreenInfo->Console, 02568 CONIME_NOTIFY_SCREENBUFFERSIZE, 02569 (WPARAM)ScreenInfo->Console->ConsoleHandle, 02570 (LPARAM)MAKELPARAM(NewScreenSize.X, NewScreenSize.Y) 02571 ))) { 02572 return STATUS_INVALID_HANDLE; 02573 } 02574 } 02575 02576 if ( (! ScreenInfo->ConvScreenInfo) && 02577 (CONSOLE_IS_DBCS_OUTPUTCP(ScreenInfo->Console))) 02578 { 02579 if (!NT_SUCCESS(ConsoleImeResizeModeSystemScreenBuffer(ScreenInfo->Console,NewScreenSize)) || 02580 !NT_SUCCESS(ConsoleImeResizeCompStrScreenBuffer(ScreenInfo->Console,NewScreenSize))) { 02581 /* 02582 * If something went wrong, just bail out. 02583 */ 02584 return STATUS_INVALID_HANDLE; 02585 } 02586 } 02587 #endif // FE_IME 02588 if (ScreenInfo->WindowMaximizedX != WindowMaximizedX || 02589 ScreenInfo->WindowMaximizedY != WindowMaximizedY) { 02590 ScreenInfo->WindowMaximizedX = WindowMaximizedX; 02591 ScreenInfo->WindowMaximizedY = WindowMaximizedY; 02592 UpdateWindow = TRUE; 02593 } 02594 if (UpdateWindow) { 02595 SetWindowSize(ScreenInfo); 02596 } 02597 02598 if (DoScrollBarUpdate) { 02599 UpdateScrollBars(ScreenInfo); 02600 } 02601 if (ScreenInfo->Console->InputBuffer.InputMode & ENABLE_WINDOW_INPUT) { 02602 ScreenBufferSizeChange(ScreenInfo,ScreenInfo->ScreenBufferSize); 02603 } 02604 02605 return STATUS_SUCCESS; 02606 } 02607 02608 NTSTATUS 02609 AllocateScrollBuffer( 02610 DWORD Size 02611 ) 02612 { 02613 ScrollBuffer = (PCHAR_INFO)ConsoleHeapAlloc(MAKE_TAG( SCREEN_TAG ),Size); 02614 if (ScrollBuffer == NULL) { 02615 ScrollBufferSize = 0; 02616 return STATUS_NO_MEMORY; 02617 } 02618 ScrollBufferSize = Size; 02619 return STATUS_SUCCESS; 02620 } 02621 02622 VOID 02623 FreeScrollBuffer( VOID ) 02624 { 02625 ConsoleHeapFree(ScrollBuffer); 02626 ScrollBuffer = NULL; 02627 ScrollBufferSize = 0; 02628 } 02629 02630 NTSTATUS 02631 InitializeScrollBuffer( VOID ) 02632 { 02633 NTSTATUS Status; 02634 02635 ghrgnScroll = CreateRectRgn(0,0,1,1); 02636 if (ghrgnScroll == NULL) { 02637 RIPMSG0(RIP_WARNING, "InitializeScrollBuffer: cannot allocate ghrgnScroll."); 02638 return STATUS_UNSUCCESSFUL; 02639 } 02640 gprgnData = (LPRGNDATA)ConsoleHeapAlloc(MAKE_TAG( SCREEN_TAG ),GRGNDATASIZE); 02641 if (gprgnData == NULL) { 02642 RIPMSG0(RIP_WARNING, "InitializeScrollBuffer: allocate gprgnData."); 02643 Status = STATUS_NO_MEMORY; 02644 goto error; 02645 } 02646 02647 Status = AllocateScrollBuffer(DefaultRegInfo.ScreenBufferSize.X * 02648 DefaultRegInfo.ScreenBufferSize.Y * 02649 sizeof(CHAR_INFO)); 02650 if (!NT_SUCCESS(Status)) { 02651 goto error; 02652 } 02653 02654 Status = RtlInitializeCriticalSectionAndSpinCount(&ScrollBufferLock, 02655 0x80000000); 02656 02657 error: 02658 if (!NT_SUCCESS(Status)) { 02659 RIPMSG0(RIP_WARNING, "InitializeScrollBuffer failed, cleaning up"); 02660 if (ghrgnScroll) { 02661 DeleteObject(ghrgnScroll); 02662 ghrgnScroll = NULL; 02663 } 02664 if (gprgnData) { 02665 ConsoleHeapFree(gprgnData); 02666 gprgnData = NULL; 02667 } 02668 } 02669 02670 return Status; 02671 } 02672 02673 VOID 02674 UpdateComplexRegion( 02675 IN PSCREEN_INFORMATION ScreenInfo, 02676 IN COORD FontSize 02677 ) 02678 { 02679 int iSize,i; 02680 LPRECT pRect; 02681 SMALL_RECT UpdateRegion; 02682 LPRGNDATA pRgnData; 02683 02684 if (ScreenInfo->Flags & CONSOLE_TEXTMODE_BUFFER) { 02685 ScreenInfo->BufferInfo.TextInfo.Flags &= ~TEXT_VALID_HINT; 02686 } 02687 pRgnData = gprgnData; 02688 02689 /* 02690 * the dreaded complex region. 02691 */ 02692 iSize = GetRegionData(ghrgnScroll, 0, NULL); 02693 if (iSize > GRGNDATASIZE) { 02694 pRgnData = (LPRGNDATA)ConsoleHeapAlloc(MAKE_TAG( TMP_TAG ),iSize); 02695 if (pRgnData == NULL) 02696 return; 02697 } 02698 02699 if (!GetRegionData(ghrgnScroll, iSize, pRgnData)) { 02700 ASSERT(FALSE); 02701 if (pRgnData != gprgnData) { 02702 ConsoleHeapFree(pRgnData); 02703 } 02704 return; 02705 } 02706 02707 pRect = (PRECT)&pRgnData->Buffer; 02708 02709 /* 02710 * Redraw each rectangle 02711 */ 02712 for(i=0;i<(int)pRgnData->rdh.nCount;i++,pRect++) { 02713 /* 02714 * ICK!!!!!! Convert to chars. This sucks. We know 02715 * this is only get to get converted back during 02716 * the textout call. 02717 */ 02718 UpdateRegion.Left = (SHORT)((pRect->left/FontSize.X)+ \ 02719 ScreenInfo->Window.Left); 02720 UpdateRegion.Right = (SHORT)(((pRect->right-1)/FontSize.X)+ \ 02721 ScreenInfo->Window.Left); 02722 UpdateRegion.Top = (SHORT)((pRect->top/FontSize.Y)+ \ 02723 ScreenInfo->Window.Top); 02724 UpdateRegion.Bottom = (SHORT)(((pRect->bottom-1)/FontSize.Y)+ \ 02725 ScreenInfo->Window.Top); 02726 /* 02727 * Fill the rectangle with goodies. 02728 */ 02729 WriteToScreen(ScreenInfo, &UpdateRegion); 02730 } 02731 if (pRgnData != gprgnData) { 02732 ConsoleHeapFree(pRgnData); 02733 } 02734 } 02735 02736 VOID 02737 ScrollScreen( 02738 IN PSCREEN_INFORMATION ScreenInfo, 02739 IN PSMALL_RECT ScrollRect, 02740 IN PSMALL_RECT MergeRect, 02741 IN COORD TargetPoint 02742 ) 02743 { 02744 RECT ScrollRectGdi; 02745 SMALL_RECT UpdateRegion; 02746 COORD FontSize; 02747 BOOL Success; 02748 RECT BoundingBox; 02749 #if defined(FE_SB) 02750 BYTE fBisect = 0; 02751 SMALL_RECT UpdateRect; 02752 SMALL_RECT TmpBisect; 02753 #endif 02754 02755 DBGOUTPUT(("ScrollScreen\n")); 02756 if (!ACTIVE_SCREEN_BUFFER(ScreenInfo)) { 02757 return; 02758 } 02759 if (ScreenInfo->Console->FullScreenFlags == 0 && 02760 !(ScreenInfo->Console->Flags & (CONSOLE_IS_ICONIC | CONSOLE_NO_WINDOW))) { 02761 #if defined(FE_SB) 02762 if (ScreenInfo->BisectFlag){ 02763 SMALL_RECT RedrawRect; 02764 if (ScrollRect->Top < TargetPoint.Y){ 02765 RedrawRect.Top = ScrollRect->Top; 02766 RedrawRect.Bottom = TargetPoint.Y+(ScrollRect->Bottom-ScrollRect->Top); 02767 } 02768 else{ 02769 RedrawRect.Top = TargetPoint.Y; 02770 RedrawRect.Bottom = ScrollRect->Bottom; 02771 } 02772 if (ScrollRect->Left < TargetPoint.X){ 02773 RedrawRect.Left = ScrollRect->Left; 02774 RedrawRect.Right = TargetPoint.X+(ScrollRect->Right-ScrollRect->Left); 02775 } 02776 else{ 02777 RedrawRect.Left = TargetPoint.X; 02778 RedrawRect.Right = ScrollRect->Right; 02779 } 02780 WriteToScreen(ScreenInfo,&RedrawRect); 02781 } 02782 else{ 02783 #endif 02784 ScrollRectGdi.left = ScrollRect->Left-ScreenInfo->Window.Left; 02785 ScrollRectGdi.right = (ScrollRect->Right-ScreenInfo->Window.Left+1); 02786 ScrollRectGdi.top = ScrollRect->Top-ScreenInfo->Window.Top; 02787 ScrollRectGdi.bottom = (ScrollRect->Bottom-ScreenInfo->Window.Top+1); 02788 if (ScreenInfo->Flags & CONSOLE_TEXTMODE_BUFFER) { 02789 FontSize = SCR_FONTSIZE(ScreenInfo); 02790 ScrollRectGdi.left *= FontSize.X; 02791 ScrollRectGdi.right *= FontSize.X; 02792 ScrollRectGdi.top *= FontSize.Y; 02793 ScrollRectGdi.bottom *= FontSize.Y; 02794 ASSERT (ScreenInfo->BufferInfo.TextInfo.UpdatingScreen>0); 02795 } else { 02796 FontSize.X = 1; 02797 FontSize.Y = 1; 02798 } 02799 SCROLLDC_CALL; 02800 LockScrollBuffer(); 02801 Success = (int)ScrollDC(ScreenInfo->Console->hDC, 02802 (TargetPoint.X-ScrollRect->Left)*FontSize.X, 02803 (TargetPoint.Y-ScrollRect->Top)*FontSize.Y, 02804 &ScrollRectGdi, 02805 NULL, 02806 ghrgnScroll, 02807 NULL); 02808 if (Success) { 02809 /* 02810 * Fetch our rectangles. If this is a simple rect then 02811 * we have already retrieved the rectangle. Otherwise 02812 * we need to call gdi to get the rectangles. We are 02813 * optimzied for speed rather than size. 02814 */ 02815 switch (GetRgnBox(ghrgnScroll, &BoundingBox)) { 02816 case SIMPLEREGION: 02817 UpdateRegion.Left = (SHORT)((BoundingBox.left / FontSize.X) + \ 02818 ScreenInfo->Window.Left); 02819 UpdateRegion.Right = (SHORT)(((BoundingBox.right-1) / FontSize.X) + \ 02820 ScreenInfo->Window.Left); 02821 UpdateRegion.Top = (SHORT)((BoundingBox.top / FontSize.Y) + \ 02822 ScreenInfo->Window.Top); 02823 UpdateRegion.Bottom = (SHORT)(((BoundingBox.bottom-1) / FontSize.Y) + \ 02824 ScreenInfo->Window.Top); 02825 #if defined(FE_SB) 02826 fBisect = ScreenInfo->BisectFlag; 02827 #endif 02828 WriteToScreen(ScreenInfo, &UpdateRegion); 02829 break; 02830 case COMPLEXREGION: 02831 UpdateComplexRegion(ScreenInfo, FontSize); 02832 break; 02833 } 02834 02835 if (MergeRect) { 02836 #if defined(FE_SB) 02837 if (fBisect) 02838 ScreenInfo->BisectFlag = fBisect; 02839 else 02840 fBisect = ScreenInfo->BisectFlag; 02841 #endif 02842 WriteToScreen(ScreenInfo, MergeRect); 02843 } 02844 #if defined(FE_SB) 02845 if (CONSOLE_IS_DBCS_OUTPUTCP(ScreenInfo->Console)) { 02846 UpdateRect.Left = TargetPoint.X; 02847 UpdateRect.Right = ScrollRect->Right + (TargetPoint.X-ScrollRect->Left); 02848 UpdateRect.Top = TargetPoint.Y; 02849 UpdateRect.Bottom = ScrollRect->Bottom + (TargetPoint.Y-ScrollRect->Top); 02850 if (UpdateRect.Left && 02851 UpdateRect.Right+1 < ScreenInfo->ScreenBufferSize.X && 02852 UpdateRect.Right-UpdateRect.Left <= 2) { 02853 TmpBisect.Left = UpdateRect.Left-1; 02854 TmpBisect.Right = UpdateRect.Right+1; 02855 TmpBisect.Top = UpdateRect.Top; 02856 TmpBisect.Bottom = UpdateRect.Bottom; 02857 WriteToScreen(ScreenInfo, &TmpBisect); 02858 } 02859 else { 02860 if (UpdateRect.Left) { 02861 TmpBisect.Left = UpdateRect.Left-1; 02862 TmpBisect.Right = UpdateRect.Left; 02863 TmpBisect.Top = UpdateRect.Top; 02864 TmpBisect.Bottom = UpdateRect.Bottom; 02865 WriteToScreen(ScreenInfo, &TmpBisect); 02866 } 02867 if (UpdateRect.Right+1 < ScreenInfo->ScreenBufferSize.X) { 02868 TmpBisect.Left = UpdateRect.Right; 02869 TmpBisect.Right = UpdateRect.Right+1; 02870 TmpBisect.Top = UpdateRect.Top; 02871 TmpBisect.Bottom = UpdateRect.Bottom; 02872 WriteToScreen(ScreenInfo, &TmpBisect); 02873 } 02874 } 02875 } 02876 #endif 02877 } else { 02878 #if defined(FE_SB) 02879 if (fBisect) 02880 ScreenInfo->BisectFlag = fBisect; 02881 else 02882 fBisect = ScreenInfo->BisectFlag; 02883 #endif 02884 WriteToScreen(ScreenInfo, &ScreenInfo->Window); 02885 } 02886 UnlockScrollBuffer(); 02887 #if defined(FE_SB) 02888 } 02889 #endif 02890 } 02891 #ifdef i386 02892 else if (ScreenInfo->Console->FullScreenFlags & CONSOLE_FULLSCREEN_HARDWARE) { 02893 #if defined(FE_SB) 02894 if (CONSOLE_IS_DBCS_OUTPUTCP(ScreenInfo->Console)) { 02895 if (! ScreenInfo->ConvScreenInfo) { 02896 if (ScreenInfo->Console->CurrentScreenBuffer == ScreenInfo) { 02897 ScrollHW(ScreenInfo, 02898 ScrollRect, 02899 MergeRect, 02900 TargetPoint 02901 ); 02902 } 02903 } 02904 else if (ScreenInfo->Console->CurrentScreenBuffer->Flags & CONSOLE_TEXTMODE_BUFFER) { 02905 ScrollHW(ScreenInfo, 02906 ScrollRect, 02907 MergeRect, 02908 TargetPoint 02909 ); 02910 } 02911 } 02912 else 02913 #endif 02914 ScrollHW(ScreenInfo, 02915 ScrollRect, 02916 MergeRect, 02917 TargetPoint 02918 ); 02919 } 02920 #endif 02921 } 02922 02923 02924 void CopyRow( 02925 PROW Row, 02926 PROW PrevRow) 02927 { 02928 if (PrevRow->AttrRow.Length != 1 || 02929 Row->AttrRow.Length != 1 || 02930 PrevRow->AttrRow.Attrs->Attr != Row->AttrRow.Attrs->Attr) { 02931 Row->CharRow.OldRight = INVALID_OLD_LENGTH; 02932 Row->CharRow.OldLeft = INVALID_OLD_LENGTH; 02933 } else { 02934 Row->CharRow.OldRight = PrevRow->CharRow.Right; 02935 Row->CharRow.OldLeft = PrevRow->CharRow.Left; 02936 } 02937 } 02938 02939 SHORT 02940 ScrollEntireScreen( 02941 IN PSCREEN_INFORMATION ScreenInfo, 02942 IN SHORT ScrollValue, 02943 IN BOOL UpdateRowIndex 02944 ) 02945 02946 02953 { 02954 SHORT RowIndex; 02955 int i; 02956 int new; 02957 int old; 02958 02959 ScreenInfo->BufferInfo.TextInfo.Flags |= TEXT_VALID_HINT; 02960 02961 // 02962 // store index of first row 02963 // 02964 02965 RowIndex = ScreenInfo->BufferInfo.TextInfo.FirstRow; 02966 02967 // 02968 // update the oldright and oldleft values 02969 // 02970 02971 new = (RowIndex + ScreenInfo->Window.Bottom + ScrollValue) % 02972 ScreenInfo->ScreenBufferSize.Y; 02973 old = (RowIndex + ScreenInfo->Window.Bottom) % 02974 ScreenInfo->ScreenBufferSize.Y; 02975 for (i = WINDOW_SIZE_Y(&ScreenInfo->Window) - 1; i >= 0; i--) { 02976 CopyRow( 02977 &ScreenInfo->BufferInfo.TextInfo.Rows[new], 02978 &ScreenInfo->BufferInfo.TextInfo.Rows[old]); 02979 if (--new < 0) 02980 new = ScreenInfo->ScreenBufferSize.Y - 1; 02981 if (--old < 0) 02982 old = ScreenInfo->ScreenBufferSize.Y - 1; 02983 } 02984 02985 // 02986 // update screen buffer 02987 // 02988 02989 if (UpdateRowIndex) { 02990 ScreenInfo->BufferInfo.TextInfo.FirstRow = 02991 (SHORT)((RowIndex + ScrollValue) % ScreenInfo->ScreenBufferSize.Y); 02992 } 02993 02994 return RowIndex; 02995 } 02996 02997 VOID 02998 StreamScrollRegion( 02999 IN PSCREEN_INFORMATION ScreenInfo 03000 ) 03001 03002 /*++ 03003 03004 Routine Description: 03005 03006 This routine is a special-purpose scroll for use by 03007 AdjustCursorPosition. 03008 03009 Arguments: 03010 03011 ScreenInfo - pointer to screen buffer info. 03012 03013 Return Value: 03014 03015 --*/ 03016 03017 { 03018 SHORT RowIndex; 03019 PROW Row; 03020 PWCHAR Char; 03021 RECT Rect; 03022 RECT BoundingBox; 03023 int ScreenWidth,ScrollHeight,ScreenHeight; 03024 COORD FontSize; 03025 SMALL_RECT UpdateRegion; 03026 BOOL Success; 03027 int i; 03028 #if defined(FE_SB) 03029 PBYTE AttrP; 03030 #endif 03031 PCONSOLE_INFORMATION Console = ScreenInfo->Console; 03032 03033 RowIndex = ScrollEntireScreen(ScreenInfo,1,TRUE); 03034 03035 Row = &ScreenInfo->BufferInfo.TextInfo.Rows[RowIndex]; 03036 03037 // 03038 // fill line with blanks 03039 // 03040 03041 Char = &Row->CharRow.Chars[Row->CharRow.Left]; 03042 for (i=Row->CharRow.Left;i<Row->CharRow.Right;i++) { 03043 *Char = (WCHAR)' '; 03044 Char++; 03045 } 03046 #if defined(FE_SB) 03047 if (CONSOLE_IS_DBCS_OUTPUTCP(Console)){ 03048 int LineWidth = Row->CharRow.Right - Row->CharRow.Left; 03049 AttrP = &Row->CharRow.KAttrs[Row->CharRow.Left]; 03050 if ( LineWidth > 0 ) 03051 RtlZeroMemory(AttrP, LineWidth); 03052 AttrP += LineWidth; 03053 Row->CharRow.OldRight = INVALID_OLD_LENGTH; 03054 Row->CharRow.OldLeft = INVALID_OLD_LENGTH; 03055 Console->ConsoleIme.ScrollWaitCountDown = Console->ConsoleIme.ScrollWaitTimeout; 03056 } 03057 #endif 03058 Row->CharRow.Right = 0; 03059 Row->CharRow.Left = ScreenInfo->ScreenBufferSize.X; 03060 03061 // 03062 // set up attributes 03063 // 03064 03065 if (Row->AttrRow.Length != 1) { 03066 ConsoleHeapFree(Row->AttrRow.Attrs); 03067 Row->AttrRow.Attrs = &Row->AttrRow.AttrPair; 03068 Row->AttrRow.AttrPair.Length = ScreenInfo->ScreenBufferSize.X; 03069 Row->AttrRow.Length = 1; 03070 } 03071 Row->AttrRow.AttrPair.Attr = ScreenInfo->Attributes; 03072 03073 // 03074 // update screen 03075 // 03076 03077 if (ACTIVE_SCREEN_BUFFER(ScreenInfo) && 03078 Console->FullScreenFlags == 0 && 03079 !(Console->Flags & (CONSOLE_IS_ICONIC | CONSOLE_NO_WINDOW))) { 03080 03081 ConsoleHideCursor(ScreenInfo); 03082 if (UsePolyTextOut) { 03083 WriteRegionToScreen(ScreenInfo, &ScreenInfo->Window); 03084 } else { 03085 FontSize = SCR_FONTSIZE(ScreenInfo); 03086 ScreenWidth = WINDOW_SIZE_X(&ScreenInfo->Window) * FontSize.X; 03087 ScreenHeight = WINDOW_SIZE_Y(&ScreenInfo->Window) * FontSize.Y; 03088 ScrollHeight = ScreenHeight - FontSize.Y; 03089 03090 Rect.left = 0; 03091 Rect.right = ScreenWidth; 03092 Rect.top = FontSize.Y; 03093 Rect.bottom = ScreenHeight; 03094 03095 // 03096 // find smallest bounding rectangle 03097 // 03098 03099 if (ScreenInfo->BufferInfo.TextInfo.Flags & TEXT_VALID_HINT) { 03100 SHORT MinLeft,MaxRight; 03101 MinLeft = ScreenInfo->ScreenBufferSize.X; 03102 MaxRight = 0; 03103 RowIndex = (ScreenInfo->BufferInfo.TextInfo.FirstRow+ScreenInfo->Window.Top) % ScreenInfo->ScreenBufferSize.Y; 03104 for (i=ScreenInfo->Window.Top+1;i<=ScreenInfo->Window.Bottom;i++) { 03105 Row = &ScreenInfo->BufferInfo.TextInfo.Rows[RowIndex]; 03106 if (Row->CharRow.OldLeft == INVALID_OLD_LENGTH) { 03107 MinLeft = 0; 03108 } else { 03109 if (MinLeft > min(Row->CharRow.Left,Row->CharRow.OldLeft)) { 03110 MinLeft = min(Row->CharRow.Left,Row->CharRow.OldLeft); 03111 } 03112 } 03113 if (Row->CharRow.OldRight == INVALID_OLD_LENGTH) { 03114 MaxRight = ScreenInfo->ScreenBufferSize.X-1; 03115 } else { 03116 if (MaxRight < max(Row->CharRow.Right,Row->CharRow.OldRight)) { 03117 MaxRight = max(Row->CharRow.Right,Row->CharRow.OldRight); 03118 } 03119 } 03120 if (++RowIndex == ScreenInfo->ScreenBufferSize.Y) { 03121 RowIndex = 0; 03122 } 03123 } 03124 Rect.left = MinLeft*FontSize.X; 03125 Rect.right = (MaxRight+1)*FontSize.X; 03126 } 03127 03128 LockScrollBuffer(); 03129 ASSERT (ScreenInfo->BufferInfo.TextInfo.UpdatingScreen>0); 03130 Success = (int)ScrollDC(Console->hDC, 03131 0, 03132 -FontSize.Y, 03133 &Rect, 03134 NULL, 03135 ghrgnScroll, 03136 NULL 03137 ); 03138 if (Success && ScreenInfo->Window.Top!=ScreenInfo->Window.Bottom) { 03139 #if defined(FE_SB) 03140 if (CONSOLE_IS_DBCS_OUTPUTCP(Console) && 03141 ScreenInfo->Attributes & (COMMON_LVB_GRID_HORIZONTAL + 03142 COMMON_LVB_GRID_LVERTICAL + 03143 COMMON_LVB_GRID_RVERTICAL + 03144 COMMON_LVB_REVERSE_VIDEO + 03145 COMMON_LVB_UNDERSCORE )){ 03146 UpdateRegion = ScreenInfo->Window; 03147 UpdateRegion.Top = UpdateRegion.Bottom; 03148 ScreenInfo->BufferInfo.TextInfo.Flags &= ~TEXT_VALID_HINT; 03149 WriteToScreen(ScreenInfo,&UpdateRegion); 03150 } 03151 else{ 03152 #endif 03153 switch (GetRgnBox(ghrgnScroll, &BoundingBox)) { 03154 case SIMPLEREGION: 03155 if (BoundingBox.left == 0 && 03156 BoundingBox.right == ScreenWidth && 03157 BoundingBox.top == ScrollHeight && 03158 BoundingBox.bottom == ScreenHeight) { 03159 03160 PatBlt(Console->hDC,0,ScrollHeight,ScreenWidth,FontSize.Y,PATCOPY); 03161 GdiFlush(); 03162 } else { 03163 UpdateRegion.Left = (SHORT)((BoundingBox.left/FontSize.X)+ScreenInfo->Window.Left); 03164 UpdateRegion.Right = (SHORT)(((BoundingBox.right-1)/FontSize.X)+ScreenInfo->Window.Left); 03165 UpdateRegion.Top = (SHORT)((BoundingBox.top/FontSize.Y)+ScreenInfo->Window.Top); 03166 UpdateRegion.Bottom = (SHORT)(((BoundingBox.bottom-1)/FontSize.Y)+ScreenInfo->Window.Top); 03167 WriteToScreen(ScreenInfo,&UpdateRegion); 03168 } 03169 break; 03170 case COMPLEXREGION: 03171 UpdateComplexRegion(ScreenInfo,FontSize); 03172 break; 03173 } 03174 #if defined(FE_SB) 03175 } 03176 #endif 03177 } else { 03178 WriteToScreen(ScreenInfo,&ScreenInfo->Window); 03179 } 03180 UnlockScrollBuffer(); 03181 } 03182 ConsoleShowCursor(ScreenInfo); 03183 } 03184 #ifdef i386 03185 else if (Console->FullScreenFlags & CONSOLE_FULLSCREEN_HARDWARE) { 03186 SMALL_RECT ScrollRect; 03187 COORD TargetPoint; 03188 03189 ScrollRect = ScreenInfo->Window; 03190 TargetPoint.Y = ScrollRect.Top; 03191 ScrollRect.Top += 1; 03192 TargetPoint.X = 0; 03193 #if defined(FE_SB) 03194 if (CONSOLE_IS_DBCS_OUTPUTCP(Console) ) { 03195 if (! ScreenInfo->ConvScreenInfo) { 03196 if (ScreenInfo->Console->CurrentScreenBuffer == ScreenInfo) { 03197 ScrollHW(ScreenInfo, 03198 &ScrollRect, 03199 NULL, 03200 TargetPoint 03201 ); 03202 } 03203 } 03204 else if (ScreenInfo->Console->CurrentScreenBuffer->Flags & CONSOLE_TEXTMODE_BUFFER) { 03205 ScrollHW(ScreenInfo, 03206 &ScrollRect, 03207 NULL, 03208 TargetPoint 03209 ); 03210 } 03211 } 03212 else 03213 #endif 03214 ScrollHW(ScreenInfo, 03215 &ScrollRect, 03216 NULL, 03217 TargetPoint 03218 ); 03219 ScrollRect.Top = ScrollRect.Bottom - 1; 03220 WriteRegionToScreenHW(ScreenInfo,&ScrollRect); 03221 } 03222 #endif 03223 } 03224 03225 NTSTATUS 03226 ScrollRegion( 03227 IN PSCREEN_INFORMATION ScreenInfo, 03228 IN OUT PSMALL_RECT ScrollRectangle, 03229 IN PSMALL_RECT ClipRectangle OPTIONAL, 03230 IN COORD DestinationOrigin, 03231 IN CHAR_INFO Fill 03232 ) 03233 03234 /*++ 03235 03236 Routine Description: 03237 03238 This routine copies ScrollRectangle to DestinationOrigin then 03239 fills in ScrollRectangle with Fill. The scroll region is 03240 copied to a third buffer, the scroll region is filled, then the 03241 original contents of the scroll region are copied to the destination. 03242 03243 Arguments: 03244 03245 ScreenInfo - pointer to screen buffer info. 03246 03247 ScrollRectangle - Region to copy 03248 03249 ClipRectangle - Optional pointer to clip region. 03250 03251 DestinationOrigin - Upper left corner of target region. 03252 03253 Fill - Character and attribute to fill source region with. 03254 03255 Return Value: 03256 03257 --*/ 03258 03259 { 03260 SMALL_RECT TargetRectangle, SourceRectangle; 03261 COORD TargetPoint; 03262 COORD Size; 03263 SMALL_RECT OurClipRectangle; 03264 SMALL_RECT ScrollRectangle2,ScrollRectangle3; 03265 NTSTATUS Status; 03266 PCONSOLE_INFORMATION Console = ScreenInfo->Console; 03267 03268 // here's how we clip: 03269 // 03270 // Clip source rectangle to screen buffer => S 03271 // Create target rectangle based on S => T 03272 // Clip T to ClipRegion => T 03273 // Create S2 based on clipped T => S2 03274 // Clip S to ClipRegion => S3 03275 // 03276 // S2 is the region we copy to T 03277 // S3 is the region to fill 03278 03279 if (Fill.Char.UnicodeChar == '\0' && Fill.Attributes == 0) { 03280 Fill.Char.UnicodeChar = (WCHAR)' '; 03281 Fill.Attributes = ScreenInfo->Attributes; 03282 } 03283 03284 // 03285 // clip the source rectangle to the screen buffer 03286 // 03287 03288 if (ScrollRectangle->Left < 0) { 03289 DestinationOrigin.X += -ScrollRectangle->Left; 03290 ScrollRectangle->Left = 0; 03291 } 03292 if (ScrollRectangle->Top < 0) { 03293 DestinationOrigin.Y += -ScrollRectangle->Top; 03294 ScrollRectangle->Top = 0; 03295 } 03296 if (ScrollRectangle->Right >= ScreenInfo->ScreenBufferSize.X) { 03297 ScrollRectangle->Right = (SHORT)(ScreenInfo->ScreenBufferSize.X-1); 03298 } 03299 if (ScrollRectangle->Bottom >= ScreenInfo->ScreenBufferSize.Y) { 03300 ScrollRectangle->Bottom = (SHORT)(ScreenInfo->ScreenBufferSize.Y-1); 03301 } 03302 03303 // 03304 // if source rectangle doesn't intersect screen buffer, return. 03305 // 03306 03307 if (ScrollRectangle->Bottom < ScrollRectangle->Top || 03308 ScrollRectangle->Right < ScrollRectangle->Left) { 03309 return STATUS_SUCCESS; 03310 } 03311 03312 // 03313 // clip the target rectangle 03314 // if a cliprectangle was provided, clip it to the screen buffer. 03315 // if not, set the cliprectangle to the screen buffer region. 03316 // 03317 03318 if (ClipRectangle) { 03319 03320 // 03321 // clip the cliprectangle. 03322 // 03323 03324 if (ClipRectangle->Left < 0) { 03325 ClipRectangle->Left = 0; 03326 } 03327 if (ClipRectangle->Top < 0) { 03328 ClipRectangle->Top = 0; 03329 } 03330 if (ClipRectangle->Right >= ScreenInfo->ScreenBufferSize.X) { 03331 ClipRectangle->Right = (SHORT)(ScreenInfo->ScreenBufferSize.X-1); 03332 } 03333 if (ClipRectangle->Bottom >= ScreenInfo->ScreenBufferSize.Y) { 03334 ClipRectangle->Bottom = (SHORT)(ScreenInfo->ScreenBufferSize.Y-1); 03335 } 03336 } 03337 else { 03338 OurClipRectangle.Left = 0; 03339 OurClipRectangle.Top = 0; 03340 OurClipRectangle.Right = (SHORT)(ScreenInfo->ScreenBufferSize.X-1); 03341 OurClipRectangle.Bottom = (SHORT)(ScreenInfo->ScreenBufferSize.Y-1); 03342 ClipRectangle = &OurClipRectangle; 03343 } 03344 03345 // 03346 // Create target rectangle based on S => T 03347 // Clip T to ClipRegion => T 03348 // Create S2 based on clipped T => S2 03349 // 03350 03351 ScrollRectangle2 = *ScrollRectangle; 03352 TargetRectangle.Left = DestinationOrigin.X; 03353 TargetRectangle.Top = DestinationOrigin.Y; 03354 TargetRectangle.Right = (SHORT)(DestinationOrigin.X + (ScrollRectangle2.Right - ScrollRectangle2.Left + 1) - 1); 03355 TargetRectangle.Bottom = (SHORT)(DestinationOrigin.Y + (ScrollRectangle2.Bottom - ScrollRectangle2.Top + 1) - 1); 03356 03357 if (TargetRectangle.Left < ClipRectangle->Left) { 03358 ScrollRectangle2.Left += ClipRectangle->Left - TargetRectangle.Left; 03359 TargetRectangle.Left = ClipRectangle->Left; 03360 } 03361 if (TargetRectangle.Top < ClipRectangle->Top) { 03362 ScrollRectangle2.Top += ClipRectangle->Top - TargetRectangle.Top; 03363 TargetRectangle.Top = ClipRectangle->Top; 03364 } 03365 if (TargetRectangle.Right > ClipRectangle->Right) { 03366 ScrollRectangle2.Right -= TargetRectangle.Right - ClipRectangle->Right; 03367 TargetRectangle.Right = ClipRectangle->Right; 03368 } 03369 if (TargetRectangle.Bottom > ClipRectangle->Bottom) { 03370 ScrollRectangle2.Bottom -= TargetRectangle.Bottom - ClipRectangle->Bottom; 03371 TargetRectangle.Bottom = ClipRectangle->Bottom; 03372 } 03373 03374 // 03375 // clip scroll rect to clipregion => S3 03376 // 03377 03378 ScrollRectangle3 = *ScrollRectangle; 03379 if (ScrollRectangle3.Left < ClipRectangle->Left) { 03380 ScrollRectangle3.Left = ClipRectangle->Left; 03381 } 03382 if (ScrollRectangle3.Top < ClipRectangle->Top) { 03383 ScrollRectangle3.Top = ClipRectangle->Top; 03384 } 03385 if (ScrollRectangle3.Right > ClipRectangle->Right) { 03386 ScrollRectangle3.Right = ClipRectangle->Right; 03387 } 03388 if (ScrollRectangle3.Bottom > ClipRectangle->Bottom) { 03389 ScrollRectangle3.Bottom = ClipRectangle->Bottom; 03390 } 03391 03392 // 03393 // if scroll rect doesn't intersect clip region, return. 03394 // 03395 03396 if (ScrollRectangle3.Bottom < ScrollRectangle3.Top || 03397 ScrollRectangle3.Right < ScrollRectangle3.Left) { 03398 return STATUS_SUCCESS; 03399 } 03400 03401 ConsoleHideCursor(ScreenInfo); 03402 03403 #if defined(FE_IME) 03404 Console->ConsoleIme.ScrollWaitCountDown = Console->ConsoleIme.ScrollWaitTimeout; 03405 #endif // FE_IME 03406 // 03407 // if target rectangle doesn't intersect screen buffer, skip scrolling 03408 // part. 03409 // 03410 03411 if (!(TargetRectangle.Bottom < TargetRectangle.Top || 03412 TargetRectangle.Right < TargetRectangle.Left)) { 03413 03414 // 03415 // if we can, don't use intermediate scroll region buffer. do this 03416 // by figuring out fill rectangle. NOTE: this code will only work 03417 // if CopyRectangle copies from low memory to high memory (otherwise 03418 // we would overwrite the scroll region before reading it). 03419 // 03420 03421 if (ScrollRectangle2.Right == TargetRectangle.Right && 03422 ScrollRectangle2.Left == TargetRectangle.Left && 03423 ScrollRectangle2.Top > TargetRectangle.Top && 03424 ScrollRectangle2.Top < TargetRectangle.Bottom) { 03425 03426 SMALL_RECT FillRect; 03427 SHORT LastRowIndex,OldRight,OldLeft; 03428 PROW Row; 03429 03430 TargetPoint.X = TargetRectangle.Left; 03431 TargetPoint.Y = TargetRectangle.Top; 03432 if (ScrollRectangle2.Right == (SHORT)(ScreenInfo->ScreenBufferSize.X-1) && 03433 ScrollRectangle2.Left == 0 && 03434 ScrollRectangle2.Bottom == (SHORT)(ScreenInfo->ScreenBufferSize.Y-1) && 03435 ScrollRectangle2.Top == 1 ) { 03436 LastRowIndex = ScrollEntireScreen(ScreenInfo,(SHORT)(ScrollRectangle2.Top-TargetRectangle.Top),TRUE); 03437 Row = &ScreenInfo->BufferInfo.TextInfo.Rows[LastRowIndex]; 03438 OldRight = Row->CharRow.OldRight; 03439 OldLeft = Row->CharRow.OldLeft; 03440 } else { 03441 LastRowIndex = -1; 03442 CopyRectangle(ScreenInfo, 03443 &ScrollRectangle2, 03444 TargetPoint 03445 ); 03446 } 03447 FillRect.Left = TargetRectangle.Left; 03448 FillRect.Right = TargetRectangle.Right; 03449 FillRect.Top = (SHORT)(TargetRectangle.Bottom+1); 03450 FillRect.Bottom = ScrollRectangle->Bottom; 03451 if (FillRect.Top < ClipRectangle->Top) { 03452 FillRect.Top = ClipRectangle->Top; 03453 } 03454 if (FillRect.Bottom > ClipRectangle->Bottom) { 03455 FillRect.Bottom = ClipRectangle->Bottom; 03456 } 03457 FillRectangle(Fill, 03458 ScreenInfo, 03459 &FillRect 03460 ); 03461 03462 // 03463 // After ScrollEntireScreen, the OldRight and OldLeft values 03464 // for the last row are set correctly. however, FillRectangle 03465 // resets them with the previous first row of the screen. 03466 // reset them here. 03467 // 03468 03469 if (LastRowIndex != -1) { 03470 Row->CharRow.OldRight = OldRight; 03471 Row->CharRow.OldLeft = OldLeft; 03472 } 03473 03474 // 03475 // update to screen, if we're not iconic. we're marked as 03476 // iconic if we're fullscreen, so check for fullscreen. 03477 // 03478 03479 if (!(Console->Flags & CONSOLE_IS_ICONIC) || 03480 Console->FullScreenFlags & CONSOLE_FULLSCREEN_HARDWARE) { 03481 ScrollScreen(ScreenInfo, 03482 &ScrollRectangle2, 03483 &FillRect, 03484 TargetPoint 03485 ); 03486 } 03487 } 03488 03489 // 03490 // if no overlap, don't need intermediate copy 03491 // 03492 03493 else if (ScrollRectangle3.Right < TargetRectangle.Left || 03494 ScrollRectangle3.Left > TargetRectangle.Right || 03495 ScrollRectangle3.Top > TargetRectangle.Bottom || 03496 ScrollRectangle3.Bottom < TargetRectangle.Top) { 03497 TargetPoint.X = TargetRectangle.Left; 03498 TargetPoint.Y = TargetRectangle.Top; 03499 CopyRectangle(ScreenInfo, 03500 &ScrollRectangle2, 03501 TargetPoint 03502 ); 03503 FillRectangle(Fill, 03504 ScreenInfo, 03505 &ScrollRectangle3 03506 ); 03507 03508 // 03509 // update to screen, if we're not iconic. we're marked as 03510 // iconic if we're fullscreen, so check for fullscreen. 03511 // 03512 03513 if (!(Console->Flags & CONSOLE_IS_ICONIC) || 03514 Console->FullScreenFlags & CONSOLE_FULLSCREEN_HARDWARE) { 03515 ScrollScreen(ScreenInfo, 03516 &ScrollRectangle2, 03517 &ScrollRectangle3, 03518 TargetPoint 03519 ); 03520 } 03521 } 03522 03523 // 03524 // for the case where the source and target rectangles overlap, we 03525 // copy the source rectangle, fill it, then copy it to the target. 03526 // 03527 03528 else { 03529 SMALL_RECT TargetRect; 03530 COORD SourcePoint; 03531 03532 LockScrollBuffer(); 03533 Size.X = (SHORT)(ScrollRectangle2.Right - ScrollRectangle2.Left + 1); 03534 Size.Y = (SHORT)(ScrollRectangle2.Bottom - ScrollRectangle2.Top + 1); 03535 if (ScrollBufferSize < (Size.X * Size.Y * sizeof(CHAR_INFO))) { 03536 FreeScrollBuffer(); 03537 Status = AllocateScrollBuffer(Size.X * Size.Y * sizeof(CHAR_INFO)); 03538 if (!NT_SUCCESS(Status)) { 03539 UnlockScrollBuffer(); 03540 ConsoleShowCursor(ScreenInfo); 03541 return Status; 03542 } 03543 } 03544 03545 TargetRect.Left = 0; 03546 TargetRect.Top = 0; 03547 TargetRect.Right = ScrollRectangle2.Right - ScrollRectangle2.Left; 03548 TargetRect.Bottom = ScrollRectangle2.Bottom - ScrollRectangle2.Top; 03549 SourcePoint.X = ScrollRectangle2.Left; 03550 SourcePoint.Y = ScrollRectangle2.Top; 03551 ReadRectFromScreenBuffer(ScreenInfo, 03552 SourcePoint, 03553 ScrollBuffer, 03554 Size, 03555 &TargetRect 03556 ); 03557 03558 FillRectangle(Fill, 03559 ScreenInfo, 03560 &ScrollRectangle3 03561 ); 03562 03563 SourceRectangle.Top = 0; 03564 SourceRectangle.Left = 0; 03565 SourceRectangle.Right = (SHORT)(Size.X-1); 03566 SourceRectangle.Bottom = (SHORT)(Size.Y-1); 03567 TargetPoint.X = TargetRectangle.Left; 03568 TargetPoint.Y = TargetRectangle.Top; 03569 WriteRectToScreenBuffer((PBYTE)ScrollBuffer, 03570 Size, 03571 &SourceRectangle, 03572 ScreenInfo, 03573 TargetPoint, 03574 0xFFFFFFFF 03575 ); 03576 UnlockScrollBuffer(); 03577 03578 // 03579 // update to screen, if we're not iconic. we're marked as 03580 // iconic if we're fullscreen, so check for fullscreen. 03581 // 03582 03583 if (!(Console->Flags & CONSOLE_IS_ICONIC) || 03584 Console->FullScreenFlags & CONSOLE_FULLSCREEN_HARDWARE) { 03585 03586 // 03587 // update regions on screen. 03588 // 03589 03590 ScrollScreen(ScreenInfo, 03591 &ScrollRectangle2, 03592 &ScrollRectangle3, 03593 TargetPoint 03594 ); 03595 } 03596 } 03597 } 03598 else { 03599 03600 // 03601 // do fill 03602 // 03603 03604 FillRectangle(Fill, 03605 ScreenInfo, 03606 &ScrollRectangle3 03607 ); 03608 03609 // 03610 // update to screen, if we're not iconic. we're marked as 03611 // iconic if we're fullscreen, so check for fullscreen. 03612 // 03613 03614 if (ACTIVE_SCREEN_BUFFER(ScreenInfo) && 03615 !(Console->Flags & CONSOLE_IS_ICONIC) || 03616 Console->FullScreenFlags & CONSOLE_FULLSCREEN_HARDWARE) { 03617 WriteToScreen(ScreenInfo,&ScrollRectangle3); 03618 } 03619 } 03620 ConsoleShowCursor(ScreenInfo); 03621 return STATUS_SUCCESS; 03622 } 03623 03624 03625 NTSTATUS 03626 SetWindowOrigin( 03627 IN PSCREEN_INFORMATION ScreenInfo, 03628 IN BOOLEAN Absolute, 03629 IN COORD WindowOrigin 03630 ) 03631 03632 /*++ 03633 03634 Routine Description: 03635 03636 This routine sets the window origin. 03637 03638 Arguments: 03639 03640 ScreenInfo - pointer to screen buffer info. 03641 03642 Absolute - if TRUE, WindowOrigin is specified in absolute screen 03643 buffer coordinates. if FALSE, WindowOrigin is specified in coordinates 03644 relative to the current window origin. 03645 03646 WindowOrigin - New window origin. 03647 03648 Return Value: 03649 03650 --*/ 03651 03652 { 03653 SMALL_RECT NewWindow; 03654 COORD WindowSize; 03655 RECT BoundingBox; 03656 BOOL Success; 03657 RECT ScrollRect; 03658 SMALL_RECT UpdateRegion; 03659 COORD FontSize; 03660 PCONSOLE_INFORMATION Console = ScreenInfo->Console; 03661 03662 // 03663 // calculate window size 03664 // 03665 03666 WindowSize.X = (SHORT)CONSOLE_WINDOW_SIZE_X(ScreenInfo); 03667 WindowSize.Y = (SHORT)CONSOLE_WINDOW_SIZE_Y(ScreenInfo); 03668 03669 // 03670 // if relative coordinates, figure out absolute coords. 03671 // 03672 03673 if (!Absolute) { 03674 if (WindowOrigin.X == 0 && WindowOrigin.Y == 0) { 03675 return STATUS_SUCCESS; 03676 } 03677 NewWindow.Left = ScreenInfo->Window.Left + WindowOrigin.X; 03678 NewWindow.Top = ScreenInfo->Window.Top + WindowOrigin.Y; 03679 } 03680 else { 03681 if (WindowOrigin.X == ScreenInfo->Window.Left && 03682 WindowOrigin.Y == ScreenInfo->Window.Top) { 03683 return STATUS_SUCCESS; 03684 } 03685 NewWindow.Left = WindowOrigin.X; 03686 NewWindow.Top = WindowOrigin.Y; 03687 } 03688 NewWindow.Right = (SHORT)(NewWindow.Left + WindowSize.X - 1); 03689 NewWindow.Bottom = (SHORT)(NewWindow.Top + WindowSize.Y - 1); 03690 03691 // 03692 // see if new window origin would extend window beyond extent of screen 03693 // buffer 03694 // 03695 03696 if (NewWindow.Left < 0 || NewWindow.Top < 0 || 03697 NewWindow.Right < 0 || NewWindow.Bottom < 0 || 03698 NewWindow.Right >= ScreenInfo->ScreenBufferSize.X || 03699 NewWindow.Bottom >= ScreenInfo->ScreenBufferSize.Y) { 03700 return STATUS_INVALID_PARAMETER; 03701 } 03702 03703 if (ScreenInfo->Flags & CONSOLE_TEXTMODE_BUFFER) { 03704 FontSize = SCR_FONTSIZE(ScreenInfo); 03705 ScreenInfo->BufferInfo.TextInfo.Flags &= ~TEXT_VALID_HINT; 03706 } else { 03707 FontSize.X = 1; 03708 FontSize.Y = 1; 03709 } 03710 ConsoleHideCursor(ScreenInfo); 03711 if (ACTIVE_SCREEN_BUFFER(ScreenInfo) && 03712 Console->FullScreenFlags == 0 && 03713 !(Console->Flags & (CONSOLE_IS_ICONIC | CONSOLE_NO_WINDOW))) { 03714 03715 InvertSelection(Console, TRUE); 03716 #if defined(FE_SB) 03717 if (CONSOLE_IS_DBCS_OUTPUTCP(Console) && 03718 !(Console->ConsoleIme.ScrollFlag & HIDE_FOR_SCROLL)) { 03719 ConsoleImeBottomLineUse(ScreenInfo,0); 03720 } 03721 #endif 03722 if ( ScreenInfo->Flags & CONSOLE_TEXTMODE_BUFFER 03723 && UsePolyTextOut 03724 && NewWindow.Left == ScreenInfo->Window.Left 03725 ) { 03726 ScrollEntireScreen(ScreenInfo, 03727 (SHORT)(NewWindow.Top - ScreenInfo->Window.Top), 03728 FALSE); 03729 ScreenInfo->Window = NewWindow; 03730 WriteRegionToScreen(ScreenInfo, &NewWindow); 03731 } else { 03732 #if defined(FE_SB) 03733 RECT ClipRect; 03734 #endif 03735 ScrollRect.left = 0; 03736 ScrollRect.right = CONSOLE_WINDOW_SIZE_X(ScreenInfo)*FontSize.X; 03737 ScrollRect.top = 0; 03738 #if defined(FE_SB) 03739 if (CONSOLE_IS_DBCS_OUTPUTCP(Console) && 03740 Console->InputBuffer.ImeMode.Open ) 03741 { 03742 if (ScreenInfo->Window.Top <= NewWindow.Top) 03743 ScrollRect.bottom = (CONSOLE_WINDOW_SIZE_Y(ScreenInfo)-1)*FontSize.Y; 03744 else 03745 ScrollRect.bottom = (CONSOLE_WINDOW_SIZE_Y(ScreenInfo)-2)*FontSize.Y; 03746 ClipRect = ScrollRect; 03747 ClipRect.bottom = (CONSOLE_WINDOW_SIZE_Y(ScreenInfo)-1)*FontSize.Y; 03748 } 03749 else 03750 #endif 03751 ScrollRect.bottom = CONSOLE_WINDOW_SIZE_Y(ScreenInfo)*FontSize.Y; 03752 03753 #if defined(FE_SB) 03754 if (CONSOLE_IS_DBCS_OUTPUTCP(Console) && 03755 ScrollRect.bottom == 0) { 03756 UpdateRegion.Left = 0; 03757 UpdateRegion.Top = 0; 03758 UpdateRegion.Right = CONSOLE_WINDOW_SIZE_X(ScreenInfo); 03759 UpdateRegion.Bottom = 0; 03760 WriteToScreen(ScreenInfo,&UpdateRegion); 03761 } 03762 else { 03763 #endif 03764 SCROLLDC_CALL; 03765 #if defined(FE_SB) 03766 if (CONSOLE_IS_DBCS_OUTPUTCP(Console) && 03767 Console->InputBuffer.ImeMode.Open ) 03768 { 03769 Success = ScrollDC(Console->hDC, 03770 (ScreenInfo->Window.Left-NewWindow.Left)*FontSize.X, 03771 (ScreenInfo->Window.Top-NewWindow.Top)*FontSize.Y, 03772 &ScrollRect, 03773 &ClipRect, 03774 NULL, 03775 &BoundingBox 03776 ); 03777 } 03778 else 03779 #endif 03780 Success = ScrollDC(Console->hDC, 03781 (ScreenInfo->Window.Left-NewWindow.Left)*FontSize.X, 03782 (ScreenInfo->Window.Top-NewWindow.Top)*FontSize.Y, 03783 &ScrollRect, 03784 NULL, 03785 NULL, 03786 &BoundingBox 03787 ); 03788 03789 if (Success) { 03790 UpdateRegion.Left = (SHORT)((BoundingBox.left/FontSize.X)+NewWindow.Left); 03791 UpdateRegion.Right = (SHORT)(((BoundingBox.right-1)/FontSize.X)+NewWindow.Left); 03792 UpdateRegion.Top = (SHORT)((BoundingBox.top/FontSize.Y)+NewWindow.Top); 03793 UpdateRegion.Bottom = (SHORT)(((BoundingBox.bottom-1)/FontSize.Y)+NewWindow.Top); 03794 } 03795 else { 03796 UpdateRegion = NewWindow; 03797 } 03798 03799 // 03800 // new window is ok. store it in screeninfo and refresh screen. 03801 // 03802 03803 ScreenInfo->Window = NewWindow; 03804 03805 WriteToScreen(ScreenInfo,&UpdateRegion); 03806 #if defined(FE_SB) 03807 } 03808 #endif 03809 } 03810 InvertSelection(Console, FALSE); 03811 } 03812 #ifdef i386 03813 else if (Console->FullScreenFlags & CONSOLE_FULLSCREEN_HARDWARE && 03814 ScreenInfo->Flags & CONSOLE_TEXTMODE_BUFFER) { 03815 03816 03817 // 03818 // keep mouse pointer on screen 03819 // 03820 03821 if (ScreenInfo->BufferInfo.TextInfo.MousePosition.X < NewWindow.Left) { 03822 ScreenInfo->BufferInfo.TextInfo.MousePosition.X = NewWindow.Left; 03823 } else if (ScreenInfo->BufferInfo.TextInfo.MousePosition.X > NewWindow.Right) { 03824 ScreenInfo->BufferInfo.TextInfo.MousePosition.X = NewWindow.Right; 03825 } 03826 03827 if (ScreenInfo->BufferInfo.TextInfo.MousePosition.Y < NewWindow.Top) { 03828 ScreenInfo->BufferInfo.TextInfo.MousePosition.Y = NewWindow.Top; 03829 } else if (ScreenInfo->BufferInfo.TextInfo.MousePosition.Y > NewWindow.Bottom) { 03830 ScreenInfo->BufferInfo.TextInfo.MousePosition.Y = NewWindow.Bottom; 03831 } 03832 ScreenInfo->Window = NewWindow; 03833 WriteToScreen(ScreenInfo,&ScreenInfo->Window); 03834 } 03835 #endif 03836 else { 03837 // we're iconic 03838 ScreenInfo->Window = NewWindow; 03839 } 03840 03841 #if defined(FE_SB) 03842 if (CONSOLE_IS_DBCS_OUTPUTCP(Console) ) { 03843 ConsoleImeResizeModeSystemView(Console,ScreenInfo->Window); 03844 ConsoleImeResizeCompStrView(Console,ScreenInfo->Window); 03845 } 03846 #endif 03847 ConsoleShowCursor(ScreenInfo); 03848 03849 if (ScreenInfo->Flags & CONSOLE_TEXTMODE_BUFFER) { 03850 ScreenInfo->BufferInfo.TextInfo.Flags |= TEXT_VALID_HINT; 03851 } 03852 03853 UpdateScrollBars(ScreenInfo); 03854 return STATUS_SUCCESS; 03855 } 03856 03857 NTSTATUS 03858 ResizeWindow( 03859 IN PSCREEN_INFORMATION ScreenInfo, 03860 IN PSMALL_RECT WindowDimensions, 03861 IN BOOL DoScrollBarUpdate 03862 ) 03863 03864 /*++ 03865 03866 Routine Description: 03867 03868 This routine changes the console data structures to reflect the specified 03869 window size change. it does not call the user component to update 03870 the screen. 03871 03872 Arguments: 03873 03874 ScreenInformation - the new screen buffer. 03875 03876 dwWindowSize - the initial size of screen buffer's window. 03877 03878 nFont - the initial font to generate text with. 03879 03880 dwScreenBufferSize - the initial size of the screen buffer. 03881 03882 Return Value: 03883 03884 03885 --*/ 03886 03887 { 03888 // 03889 // make sure there's something to do 03890 // 03891 03892 if (RtlEqualMemory(&ScreenInfo->Window, WindowDimensions, sizeof(SMALL_RECT))) { 03893 return STATUS_SUCCESS; 03894 } 03895 03896 if (WindowDimensions->Left < 0) { 03897 WindowDimensions->Right -= WindowDimensions->Left; 03898 WindowDimensions->Left = 0; 03899 } 03900 if (WindowDimensions->Top < 0) { 03901 WindowDimensions->Bottom -= WindowDimensions->Top; 03902 WindowDimensions->Top = 0; 03903 } 03904 03905 if (WindowDimensions->Right >= ScreenInfo->ScreenBufferSize.X) { 03906 WindowDimensions->Right = ScreenInfo->ScreenBufferSize.X; 03907 } 03908 if (WindowDimensions->Bottom >= ScreenInfo->ScreenBufferSize.Y) { 03909 WindowDimensions->Bottom = ScreenInfo->ScreenBufferSize.Y; 03910 } 03911 03912 ScreenInfo->Window = *WindowDimensions; 03913 ScreenInfo->WindowMaximizedX = (CONSOLE_WINDOW_SIZE_X(ScreenInfo) == ScreenInfo->ScreenBufferSize.X); 03914 ScreenInfo->WindowMaximizedY = (CONSOLE_WINDOW_SIZE_Y(ScreenInfo) == ScreenInfo->ScreenBufferSize.Y); 03915 03916 if (DoScrollBarUpdate) { 03917 UpdateScrollBars(ScreenInfo); 03918 } 03919 03920 if (!(ScreenInfo->Flags & CONSOLE_TEXTMODE_BUFFER)) { 03921 return STATUS_SUCCESS; 03922 } 03923 03924 if (ACTIVE_SCREEN_BUFFER(ScreenInfo)) { 03925 ScreenInfo->BufferInfo.TextInfo.Flags &= ~TEXT_VALID_HINT; 03926 } 03927 03928 #ifdef i386 03929 if (ScreenInfo->Console->FullScreenFlags & CONSOLE_FULLSCREEN_HARDWARE) { 03930 03931 // 03932 // keep mouse pointer on screen 03933 // 03934 03935 if (ScreenInfo->BufferInfo.TextInfo.MousePosition.X < WindowDimensions->Left) { 03936 ScreenInfo->BufferInfo.TextInfo.MousePosition.X = WindowDimensions->Left; 03937 } else if (ScreenInfo->BufferInfo.TextInfo.MousePosition.X > WindowDimensions->Right) { 03938 ScreenInfo->BufferInfo.TextInfo.MousePosition.X = WindowDimensions->Right; 03939 } 03940 03941 if (ScreenInfo->BufferInfo.TextInfo.MousePosition.Y < WindowDimensions->Top) { 03942 ScreenInfo->BufferInfo.TextInfo.MousePosition.Y = WindowDimensions->Top; 03943 } else if (ScreenInfo->BufferInfo.TextInfo.MousePosition.Y > WindowDimensions->Bottom) { 03944 ScreenInfo->BufferInfo.TextInfo.MousePosition.Y = WindowDimensions->Bottom; 03945 } 03946 } 03947 #endif 03948 03949 return(STATUS_SUCCESS); 03950 } 03951 03952 VOID 03953 SetWindowSize( 03954 IN PSCREEN_INFORMATION ScreenInfo 03955 ) 03956 { 03957 #if defined(FE_IME) 03958 if (ScreenInfo->ConvScreenInfo != NULL) 03959 return; 03960 #endif 03961 if (ScreenInfo->Console->Flags & CONSOLE_SETTING_WINDOW_SIZE) 03962 return; 03963 ScreenInfo->Console->Flags |= CONSOLE_SETTING_WINDOW_SIZE; 03964 PostMessage(ScreenInfo->Console->hWnd, 03965 CM_SET_WINDOW_SIZE, 03966 (WPARAM)ScreenInfo, 03967 0x47474747 03968 ); 03969 } 03970 03971 VOID 03972 UpdateWindowSize( 03973 IN PCONSOLE_INFORMATION Console, 03974 IN PSCREEN_INFORMATION ScreenInfo 03975 ) 03976 { 03977 LONG WindowStyle; 03978 03979 if (!(Console->Flags & CONSOLE_IS_ICONIC)) { 03980 InternalUpdateScrollBars(ScreenInfo); 03981 03982 WindowStyle = GetWindowLong(Console->hWnd, GWL_STYLE); 03983 if (ScreenInfo->WindowMaximized) { 03984 WindowStyle |= WS_MAXIMIZE; 03985 } else { 03986 WindowStyle &= ~WS_MAXIMIZE; 03987 } 03988 SetWindowLong(Console->hWnd, GWL_STYLE, WindowStyle); 03989 03990 SetWindowPos(Console->hWnd, NULL, 03991 0, 03992 0, 03993 Console->WindowRect.right-Console->WindowRect.left, 03994 Console->WindowRect.bottom-Console->WindowRect.top, 03995 SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_DRAWFRAME 03996 ); 03997 Console->ResizeFlags &= ~SCREEN_BUFFER_CHANGE; 03998 } else { 03999 Console->ResizeFlags |= SCREEN_BUFFER_CHANGE; 04000 } 04001 } 04002 04003 NTSTATUS 04004 InternalSetWindowSize( 04005 IN PCONSOLE_INFORMATION Console, 04006 IN PSCREEN_INFORMATION ScreenInfo, 04007 IN PSMALL_RECT Window 04008 ) 04009 { 04010 SIZE WindowSize; 04011 WORD WindowSizeX, WindowSizeY; 04012 04013 Console->Flags &= ~CONSOLE_SETTING_WINDOW_SIZE; 04014 if (Console->CurrentScreenBuffer == ScreenInfo) { 04015 if (Console->FullScreenFlags == 0) { 04016 // 04017 // Make sure our max screen sizes reflect reality 04018 // 04019 04020 if (gfInitSystemMetrics) { 04021 InitializeSystemMetrics(); 04022 } 04023 04024 // 04025 // figure out how big to make the window, given the desired client area 04026 // size. 04027 // 04028 04029 ScreenInfo->ResizingWindow++; 04030 WindowSizeX = WINDOW_SIZE_X(Window); 04031 WindowSizeY = WINDOW_SIZE_Y(Window); 04032 if (ScreenInfo->Flags & CONSOLE_TEXTMODE_BUFFER) { 04033 WindowSize.cx = WindowSizeX*SCR_FONTSIZE(ScreenInfo).X; 04034 WindowSize.cy = WindowSizeY*SCR_FONTSIZE(ScreenInfo).Y; 04035 } else { 04036 WindowSize.cx = WindowSizeX; 04037 WindowSize.cy = WindowSizeY; 04038 } 04039 WindowSize.cx += VerticalClientToWindow; 04040 WindowSize.cy += HorizontalClientToWindow; 04041 04042 if (WindowSizeY != 0) { 04043 if (!ScreenInfo->WindowMaximizedX) { 04044 WindowSize.cy += HorizontalScrollSize; 04045 } 04046 if (!ScreenInfo->WindowMaximizedY) { 04047 WindowSize.cx += VerticalScrollSize; 04048 } 04049 } 04050 04051 Console->WindowRect.right = Console->WindowRect.left + WindowSize.cx; 04052 Console->WindowRect.bottom = Console->WindowRect.top + WindowSize.cy; 04053 04054 UpdateWindowSize(Console,ScreenInfo); 04055 ScreenInfo->ResizingWindow--; 04056 } else if (Console->FullScreenFlags & CONSOLE_FULLSCREEN_HARDWARE) { 04057 WriteToScreen(ScreenInfo,&ScreenInfo->Window); 04058 } 04059 #if defined(FE_IME) 04060 if ( (ScreenInfo->Flags & CONSOLE_TEXTMODE_BUFFER) && 04061 (CONSOLE_IS_DBCS_OUTPUTCP(Console))) 04062 { 04063 ConsoleImeResizeModeSystemView(Console,Console->CurrentScreenBuffer->Window); 04064 ConsoleImeResizeCompStrView(Console,Console->CurrentScreenBuffer->Window); 04065 } 04066 #endif // FE_IME 04067 } 04068 return STATUS_SUCCESS; 04069 } 04070 04071 NTSTATUS 04072 SetActiveScreenBuffer( 04073 IN PSCREEN_INFORMATION ScreenInfo 04074 ) 04075 { 04076 PSCREEN_INFORMATION OldScreenInfo; 04077 PCONSOLE_INFORMATION Console = ScreenInfo->Console; 04078 04079 OldScreenInfo = Console->CurrentScreenBuffer; 04080 if (ScreenInfo->Flags & CONSOLE_TEXTMODE_BUFFER) { 04081 04082 #if !defined(_X86_) 04083 if (Console->FullScreenFlags & CONSOLE_FULLSCREEN) { 04084 return STATUS_INVALID_PARAMETER; 04085 } 04086 #endif 04087 Console->CurrentScreenBuffer = ScreenInfo; 04088 04089 if (Console->FullScreenFlags == 0) { 04090 04091 // 04092 // initialize cursor 04093 // 04094 04095 ScreenInfo->BufferInfo.TextInfo.CursorOn = FALSE; 04096 04097 // 04098 // set font 04099 // 04100 04101 SetFont(ScreenInfo); 04102 } 04103 #if defined(_X86_) 04104 else if (Console->FullScreenFlags & CONSOLE_FULLSCREEN_HARDWARE) { 04105 04106 if (!(Console->Flags & CONSOLE_VDM_REGISTERED)) { 04107 04108 if ( (!(OldScreenInfo->Flags & CONSOLE_TEXTMODE_BUFFER)) || 04109 (OldScreenInfo->BufferInfo.TextInfo.ModeIndex!=ScreenInfo->BufferInfo.TextInfo.ModeIndex)) { 04110 04111 // set video mode and font 04112 SetVideoMode(ScreenInfo); 04113 } 04114 04115 //set up cursor 04116 04117 SetCursorInformationHW(ScreenInfo, 04118 ScreenInfo->BufferInfo.TextInfo.CursorSize, 04119 ScreenInfo->BufferInfo.TextInfo.CursorVisible); 04120 SetCursorPositionHW(ScreenInfo, 04121 ScreenInfo->BufferInfo.TextInfo.CursorPosition); 04122 } 04123 04124 } 04125 #endif 04126 } 04127 else { 04128 Console->CurrentScreenBuffer = ScreenInfo; 04129 } 04130 04131 // 04132 // empty input buffer 04133 // 04134 04135 FlushAllButKeys(&Console->InputBuffer); 04136 04137 if (Console->FullScreenFlags == 0) { 04138 04139 SetScreenColors(ScreenInfo, ScreenInfo->Attributes, 04140 ScreenInfo->PopupAttributes, FALSE); 04141 04142 // 04143 // set window size 04144 // 04145 04146 SetWindowSize(ScreenInfo); 04147 04148 // 04149 // initialize the palette, if we have the focus and we're not fullscreen 04150 // 04151 04152 if (!(Console->Flags & CONSOLE_IS_ICONIC) && 04153 Console->FullScreenFlags == 0) { 04154 if (ScreenInfo->hPalette != NULL || OldScreenInfo->hPalette != NULL) { 04155 HPALETTE hPalette; 04156 BOOL bReset = FALSE; 04157 USERTHREAD_USEDESKTOPINFO utudi; 04158 04159 if (GetCurrentThreadId() != Console->InputThreadInfo->ThreadId) { 04160 bReset = TRUE; 04161 utudi.hThread = Console->InputThreadInfo->ThreadHandle; 04162 utudi.drdRestore.pdeskRestore = NULL; 04163 NtUserSetInformationThread(NtCurrentThread(), 04164 UserThreadUseDesktop, 04165 &utudi, sizeof(utudi)); 04166 } 04167 04168 if (ScreenInfo->hPalette == NULL) { 04169 hPalette = Console->hSysPalette; 04170 } else { 04171 hPalette = ScreenInfo->hPalette; 04172 } 04173 SelectPalette(Console->hDC, 04174 hPalette, 04175 FALSE); 04176 SetActivePalette(ScreenInfo); 04177 04178 if (bReset == TRUE) { 04179 utudi.hThread = NULL; 04180 NtUserSetInformationThread(NtCurrentThread(), 04181 UserThreadUseDesktop, &utudi, sizeof(utudi)); 04182 } 04183 } 04184 } 04185 } 04186 04187 #if defined(FE_IME) 04188 SetUndetermineAttribute(Console); 04189 #endif 04190 // 04191 // write data to screen 04192 // 04193 04194 ScreenInfo->BufferInfo.TextInfo.Flags &= ~TEXT_VALID_HINT; 04195 WriteToScreen(ScreenInfo,&ScreenInfo->Window); 04196 return STATUS_SUCCESS; 04197 } 04198 04199 VOID 04200 SetProcessFocus( 04201 IN PCSR_PROCESS Process, 04202 IN BOOL Foreground 04203 ) 04204 { 04205 if (Foreground) { 04206 CsrSetForegroundPriority(Process); 04207 } else { 04208 CsrSetBackgroundPriority(Process); 04209 } 04210 } 04211 04212 VOID 04213 SetProcessForegroundRights( 04214 IN PCSR_PROCESS Process, 04215 IN BOOL Foreground 04216 ) 04217 { 04218 USERTHREAD_FLAGS Flags; 04219 04220 Flags.dwMask = (W32PF_ALLOWSETFOREGROUND | W32PF_CONSOLEHASFOCUS); 04221 Flags.dwFlags = (Foreground ? (W32PF_ALLOWSETFOREGROUND | W32PF_CONSOLEHASFOCUS) : 0); 04222 04223 NtUserSetInformationProcess(Process->ProcessHandle, UserProcessFlags, &Flags, sizeof(Flags)); 04224 } 04225 04226 VOID 04227 ModifyConsoleProcessFocus( 04228 IN PCONSOLE_INFORMATION Console, 04229 IN BOOL Foreground 04230 ) 04231 { 04232 PCONSOLE_PROCESS_HANDLE ProcessHandleRecord; 04233 PLIST_ENTRY ListHead, ListNext; 04234 04235 ListHead = &Console->ProcessHandleList; 04236 ListNext = ListHead->Flink; 04237 while (ListNext != ListHead) { 04238 ProcessHandleRecord = CONTAINING_RECORD( ListNext, CONSOLE_PROCESS_HANDLE, ListLink ); 04239 ListNext = ListNext->Flink; 04240 { 04241 SetProcessFocus(ProcessHandleRecord->Process, Foreground); 04242 SetProcessForegroundRights(ProcessHandleRecord->Process, Foreground); 04243 } 04244 } 04245 } 04246 04247 VOID 04248 TrimConsoleWorkingSet( 04249 IN PCONSOLE_INFORMATION Console 04250 ) 04251 { 04252 PCONSOLE_PROCESS_HANDLE ProcessHandleRecord; 04253 PLIST_ENTRY ListHead, ListNext; 04254 04255 ListHead = &Console->ProcessHandleList; 04256 ListNext = ListHead->Flink; 04257 while (ListNext != ListHead) { 04258 ProcessHandleRecord = CONTAINING_RECORD( ListNext, CONSOLE_PROCESS_HANDLE, ListLink ); 04259 ListNext = ListNext->Flink; 04260 { 04261 SetProcessWorkingSetSize(ProcessHandleRecord->Process->ProcessHandle,(SIZE_T)-1,(SIZE_T)-1); 04262 } 04263 } 04264 } 04265 04266 NTSTATUS 04267 QueueConsoleMessage( 04268 PCONSOLE_INFORMATION Console, 04269 UINT Message, 04270 WPARAM wParam, 04271 LPARAM lParam 04272 ) 04273 04274 /*++ 04275 04276 Routine Description: 04277 04278 This inserts a message into the console's message queue and wakes up 04279 the console input thread to process it. 04280 04281 Arguments: 04282 04283 Console - Pointer to console information structure. 04284 04285 Message - Message to store in queue. 04286 04287 wParam - wParam to store in queue. 04288 04289 lParam - lParam to store in queue. 04290 04291 Return Value: 04292 04293 NTSTATUS - STATUS_SUCCESS if everything is OK. 04294 04295 --*/ 04296 04297 { 04298 PCONSOLE_MSG pConMsg; 04299 04300 ASSERT(ConsoleLocked(Console)); 04301 04302 pConMsg = (PCONSOLE_MSG)ConsoleHeapAlloc(MAKE_TAG( TMP_TAG ), sizeof(CONSOLE_MSG)); 04303 if (pConMsg == NULL) { 04304 return STATUS_NO_MEMORY; 04305 } 04306 04307 pConMsg->Message = Message; 04308 pConMsg->wParam = wParam; 04309 pConMsg->lParam = lParam; 04310 04311 InsertHeadList(&Console->MessageQueue, &pConMsg->ListLink); 04312 04313 if (!PostMessage(Console->hWnd, CM_CONSOLE_MSG, 0, 0)) { 04314 RemoveEntryList(&pConMsg->ListLink); 04315 ConsoleHeapFree(pConMsg); 04316 return STATUS_UNSUCCESSFUL; 04317 } 04318 04319 return STATUS_SUCCESS; 04320 } 04321 04322 BOOL 04323 UnqueueConsoleMessage( 04324 PCONSOLE_INFORMATION Console, 04325 UINT *pMessage, 04326 WPARAM *pwParam, 04327 LPARAM *plParam 04328 ) 04329 04330 /*++ 04331 04332 Routine Description: 04333 04334 This routine removes a message from the console's message queue. 04335 04336 Arguments: 04337 04338 Console - Pointer to console information structure. 04339 04340 pMessage - Pointer in which to return Message. 04341 04342 pwParam - Pointer in which to return wParam. 04343 04344 plParam - Pointer in which to return lParam. 04345 04346 Return Value: 04347 04348 BOOL - TRUE if message was found and FALSE otherwise. 04349 04350 --*/ 04351 04352 { 04353 PLIST_ENTRY pEntry; 04354 PCONSOLE_MSG pConMsg = NULL; 04355 04356 ASSERT(ConsoleLocked(Console)); 04357 04358 if (IsListEmpty(&Console->MessageQueue)) { 04359 return FALSE; 04360 } 04361 04362 pEntry = RemoveTailList(&Console->MessageQueue); 04363 pConMsg = CONTAINING_RECORD(pEntry, CONSOLE_MSG, ListLink); 04364 04365 *pMessage = pConMsg->Message; 04366 *pwParam = pConMsg->wParam; 04367 *plParam = pConMsg->lParam; 04368 04369 ConsoleHeapFree(pConMsg); 04370 04371 return TRUE; 04372 } 04373 04374 VOID 04375 CleanupConsoleMessages( 04376 PCONSOLE_INFORMATION Console 04377 ) 04378 04379 /*++ 04380 04381 Routine Description: 04382 04383 This routine cleans up any console messages still in the queue. 04384 04385 Arguments: 04386 04387 Console - Pointer to console information structure. 04388 04389 Return Value: 04390 04391 none. 04392 04393 --*/ 04394 04395 { 04396 UINT Message; 04397 WPARAM wParam; 04398 LPARAM lParam; 04399 04400 while (UnqueueConsoleMessage(Console, &Message, &wParam, &lParam)) { 04401 switch (Message) { 04402 case CM_MODE_TRANSITION: 04403 NtSetEvent((HANDLE)lParam, NULL); 04404 NtClose((HANDLE)lParam); 04405 break; 04406 case CM_SET_IME_CODEPAGE: 04407 case CM_SET_NLSMODE: 04408 case CM_GET_NLSMODE: 04409 if (wParam) { 04410 NtSetEvent((HANDLE)wParam, NULL); 04411 NtClose((HANDLE)wParam); 04412 } 04413 break; 04414 default: 04415 KdPrint(("CONSRV: CleanupConsoleMessages - unknown message %x\n", Message)); 04416 ASSERT(FALSE); 04417 break; 04418 } 04419 } 04420 } 04421 04422 VOID 04423 AbortCreateConsole( 04424 IN PCONSOLE_INFORMATION Console 04425 ) 04426 { 04427 // 04428 // Signal any process waiting for us that initialization failed 04429 // 04430 04431 NtSetEvent(Console->InitEvents[INITIALIZATION_FAILED],NULL); 04432 04433 // 04434 // Now clean up the console structure 04435 // 04436 04437 CloseHandle(Console->ClientThreadHandle); 04438 FreeInputBuffer(&Console->InputBuffer); 04439 ConsoleHeapFree(Console->Title); 04440 ConsoleHeapFree(Console->OriginalTitle); 04441 NtClose(Console->InitEvents[INITIALIZATION_SUCCEEDED]); 04442 NtClose(Console->InitEvents[INITIALIZATION_FAILED]); 04443 NtClose(Console->TerminationEvent); 04444 FreeAliasBuffers(Console); 04445 FreeCommandHistoryBuffers(Console); 04446 #if defined(FE_SB) 04447 FreeLocalEUDC(Console); 04448 DestroyFontCache(Console->FontCacheInformation); 04449 #endif 04450 DestroyConsole(Console); 04451 } 04452 04453 VOID 04454 DestroyWindowsWindow( 04455 IN PCONSOLE_INFORMATION Console 04456 ) 04457 { 04458 PSCREEN_INFORMATION Cur,Next; 04459 HWND hWnd = Console->hWnd; 04460 04461 gnConsoleWindows--; 04462 Console->InputThreadInfo->WindowCount--; 04463 04464 SetWindowConsole(hWnd, NULL); 04465 04466 KillTimer(Console->hWnd,CURSOR_TIMER); 04467 04468 if (Console->hWndProperties) { 04469 SendMessage(Console->hWndProperties, WM_CLOSE, 0, 0); 04470 } 04471 04472 // FE_SB 04473 if (Console->FonthDC) { 04474 ReleaseDC(NULL, Console->FonthDC); 04475 DeleteObject(Console->hBitmap); 04476 } 04477 DeleteEUDC(Console); 04478 04479 // FE_IME 04480 if (CONSOLE_IS_IME_ENABLED()) { 04481 if (!(Console->Flags & CONSOLE_NO_WINDOW)) { 04482 // v-HirShi Jul.4.1995 For console IME 04483 KillTimer(Console->hWnd, SCROLL_WAIT_TIMER); 04484 } 04485 ConsoleImeMessagePump(Console, 04486 CONIME_DESTROY, 04487 (WPARAM)Console->ConsoleHandle, 04488 (LPARAM)NULL 04489 ); 04490 } 04491 // end FE_IME 04492 // end FE_SB 04493 04494 CleanupConsoleMessages(Console); 04495 04496 ReleaseDC(NULL, Console->hDC); 04497 Console->hDC = NULL; 04498 04499 DestroyWindow(Console->hWnd); 04500 Console->hWnd = NULL; 04501 04502 // 04503 // Tell the worker thread that the window is destroyed. 04504 // 04505 04506 ReplyMessage(0); 04507 04508 // 04509 // Clear out any keyboard messages we have stored away. 04510 // 04511 04512 ClearKeyInfo(hWnd); 04513 04514 if (Console->hIcon != NULL && Console->hIcon != ghDefaultIcon) { 04515 DestroyIcon(Console->hIcon); 04516 } 04517 if (Console->hSmIcon != NULL && Console->hSmIcon != ghDefaultSmIcon) { 04518 DestroyIcon(Console->hSmIcon); 04519 } 04520 04521 // 04522 // must keep this thread handle around until after the destroywindow 04523 // call so that impersonation will work. 04524 // 04525 04526 CloseHandle(Console->ClientThreadHandle); 04527 04528 // 04529 // once the sendmessage returns, there will be no more input to 04530 // the console so we don't need to lock it. 04531 // also, we've freed the console handle, so no apis may access the console. 04532 // 04533 04534 // 04535 // free screen buffers 04536 // 04537 04538 for (Cur=Console->ScreenBuffers;Cur!=NULL;Cur=Next) { 04539 Next = Cur->Next; 04540 FreeScreenBuffer(Cur); 04541 } 04542 04543 FreeAliasBuffers(Console); 04544 FreeCommandHistoryBuffers(Console); 04545 04546 // 04547 // free input buffer 04548 // 04549 04550 FreeInputBuffer(&Console->InputBuffer); 04551 ConsoleHeapFree(Console->Title); 04552 ConsoleHeapFree(Console->OriginalTitle); 04553 NtClose(Console->InitEvents[INITIALIZATION_SUCCEEDED]); 04554 NtClose(Console->InitEvents[INITIALIZATION_FAILED]); 04555 NtClose(Console->TerminationEvent); 04556 if (Console->hWinSta != NULL) { 04557 CloseDesktop(Console->hDesk); 04558 CloseWindowStation(Console->hWinSta); 04559 } 04560 if (Console->VDMProcessHandle) 04561 CloseHandle(Console->VDMProcessHandle); 04562 ASSERT(!(Console->Flags & CONSOLE_VDM_REGISTERED)); 04563 /*if (Console->VDMBuffer != NULL) { 04564 NtUnmapViewOfSection(NtCurrentProcess(),Console->VDMBuffer); 04565 NtClose(Console->VDMBufferSectionHandle); 04566 }*/ 04567 #if defined(FE_SB) 04568 FreeLocalEUDC(Console); 04569 DestroyFontCache(Console->FontCacheInformation); 04570 #endif 04571 DestroyConsole(Console); 04572 } 04573 04574 VOID 04575 VerticalScroll( 04576 IN PCONSOLE_INFORMATION Console, 04577 IN PSCREEN_INFORMATION ScreenInfo, 04578 IN WORD ScrollCommand, 04579 IN WORD AbsoluteChange 04580 ) 04581 { 04582 COORD NewOrigin; 04583 04584 NewOrigin.X = ScreenInfo->Window.Left; 04585 NewOrigin.Y = ScreenInfo->Window.Top; 04586 switch (ScrollCommand) { 04587 case SB_LINEUP: 04588 NewOrigin.Y--; 04589 break; 04590 case SB_LINEDOWN: 04591 NewOrigin.Y++; 04592 break; 04593 case SB_PAGEUP: 04594 #if defined(FE_IME) 04595 // MSKK July.22.1993 KazuM 04596 // Plan of bottom line reservation for console IME. 04597 if ( ScreenInfo->Console->InputBuffer.ImeMode.Open ) 04598 { 04599 ASSERT(ScreenInfo->Flags & CONSOLE_TEXTMODE_BUFFER); 04600 if (!(ScreenInfo->Flags & CONSOLE_TEXTMODE_BUFFER)) { 04601 return; 04602 } 04603 NewOrigin.Y-=CONSOLE_WINDOW_SIZE_Y(ScreenInfo)-2; 04604 ScreenInfo->BufferInfo.TextInfo.Flags &= ~TEXT_VALID_HINT; 04605 ScreenInfo->BufferInfo.TextInfo.Flags |= CONSOLE_CONVERSION_AREA_REDRAW; 04606 } 04607 else 04608 #endif // FE_IME 04609 NewOrigin.Y-=CONSOLE_WINDOW_SIZE_Y(ScreenInfo)-1; 04610 break; 04611 case SB_PAGEDOWN: 04612 #if defined(FE_IME) 04613 // MSKK July.22.1993 KazuM 04614 // Plan of bottom line reservation for console IME. 04615 if ( ScreenInfo->Console->InputBuffer.ImeMode.Open ) 04616 { 04617 NewOrigin.Y+=CONSOLE_WINDOW_SIZE_Y(ScreenInfo)-2; 04618 ScreenInfo->BufferInfo.TextInfo.Flags &= ~TEXT_VALID_HINT; 04619 ScreenInfo->BufferInfo.TextInfo.Flags |= CONSOLE_CONVERSION_AREA_REDRAW; 04620 } 04621 else 04622 #endif // FE_IME 04623 NewOrigin.Y+=CONSOLE_WINDOW_SIZE_Y(ScreenInfo)-1; 04624 break; 04625 case SB_THUMBTRACK: 04626 Console->Flags |= CONSOLE_SCROLLBAR_TRACKING; 04627 NewOrigin.Y= AbsoluteChange; 04628 break; 04629 case SB_THUMBPOSITION: 04630 UnblockWriteConsole(Console, CONSOLE_SCROLLBAR_TRACKING); 04631 NewOrigin.Y= AbsoluteChange; 04632 break; 04633 case SB_TOP: 04634 NewOrigin.Y=0; 04635 break; 04636 case SB_BOTTOM: 04637 NewOrigin.Y=(WORD)(ScreenInfo->ScreenBufferSize.Y-CONSOLE_WINDOW_SIZE_Y(ScreenInfo)); 04638 break; 04639 04640 default: 04641 return; 04642 } 04643 04644 NewOrigin.Y = (WORD)(max(0,min((SHORT)NewOrigin.Y, 04645 (SHORT)ScreenInfo->ScreenBufferSize.Y-(SHORT)CONSOLE_WINDOW_SIZE_Y(ScreenInfo)))); 04646 SetWindowOrigin(ScreenInfo, 04647 (BOOLEAN)TRUE, 04648 NewOrigin 04649 ); 04650 } 04651 04652 VOID 04653 HorizontalScroll( 04654 IN PSCREEN_INFORMATION ScreenInfo, 04655 IN WORD ScrollCommand, 04656 IN WORD AbsoluteChange 04657 ) 04658 { 04659 COORD NewOrigin; 04660 04661 NewOrigin.X = ScreenInfo->Window.Left; 04662 NewOrigin.Y = ScreenInfo->Window.Top; 04663 switch (ScrollCommand) { 04664 case SB_LINEUP: 04665 NewOrigin.X--; 04666 break; 04667 case SB_LINEDOWN: 04668 NewOrigin.X++; 04669 break; 04670 case SB_PAGEUP: 04671 NewOrigin.X-=CONSOLE_WINDOW_SIZE_X(ScreenInfo)-1; 04672 break; 04673 case SB_PAGEDOWN: 04674 NewOrigin.X+=CONSOLE_WINDOW_SIZE_X(ScreenInfo)-1; 04675 break; 04676 case SB_THUMBTRACK: 04677 case SB_THUMBPOSITION: 04678 NewOrigin.X= AbsoluteChange; 04679 break; 04680 case SB_TOP: 04681 NewOrigin.X=0; 04682 break; 04683 case SB_BOTTOM: 04684 NewOrigin.X=(WORD)(ScreenInfo->ScreenBufferSize.X-CONSOLE_WINDOW_SIZE_X(ScreenInfo)); 04685 break; 04686 04687 default: 04688 return; 04689 } 04690 04691 NewOrigin.X = (WORD)(max(0,min((SHORT)NewOrigin.X, 04692 (SHORT)ScreenInfo->ScreenBufferSize.X-(SHORT)CONSOLE_WINDOW_SIZE_X(ScreenInfo)))); 04693 SetWindowOrigin(ScreenInfo, 04694 (BOOLEAN)TRUE, 04695 NewOrigin 04696 ); 04697 } 04698 04699 LRESULT APIENTRY 04700 ConsoleWindowProc( 04701 HWND hWnd, 04702 UINT Message, 04703 WPARAM wParam, 04704 LPARAM lParam 04705 ) 04706 { 04707 HDC hDC; 04708 PAINTSTRUCT ps; 04709 PCONSOLE_INFORMATION Console; 04710 PSCREEN_INFORMATION ScreenInfo; 04711 SMALL_RECT PaintRect; 04712 LRESULT Status; 04713 04714 Console = GetWindowConsole(hWnd); 04715 if (Console != NULL) { 04716 04717 // 04718 // Set up our thread so we can impersonate the client 04719 // while processing the message. 04720 // 04721 04722 CSR_SERVER_QUERYCLIENTTHREAD()->ThreadHandle = 04723 Console->ClientThreadHandle; 04724 04725 // 04726 // If the console is terminating, don't bother processing messages 04727 // other than CM_DESTROY_WINDOW. 04728 // 04729 if (Console->Flags & CONSOLE_TERMINATING) { 04730 LockConsole(Console); 04731 DestroyWindowsWindow(Console); 04732 return 0; 04733 } 04734 04735 // 04736 // Make sure the console pointer is still valid 04737 // 04738 ASSERT(NT_SUCCESS(ValidateConsole(Console))); 04739 04740 LockConsole(Console); 04741 04742 ScreenInfo = Console->CurrentScreenBuffer; 04743 } 04744 try { 04745 if (Console == NULL || ScreenInfo == NULL) { 04746 switch (Message) { 04747 case WM_GETMINMAXINFO: 04748 { 04749 // 04750 // createwindow issues a WM_GETMINMAXINFO 04751 // message before we have the windowlong set up 04752 // with the console pointer. we need to allow 04753 // the created window to be bigger than the 04754 // default size by the scroll size. 04755 // 04756 04757 LPMINMAXINFO lpmmi = (LPMINMAXINFO)lParam; 04758 lpmmi->ptMaxTrackSize.y += HorizontalScrollSize; 04759 lpmmi->ptMaxTrackSize.x += VerticalScrollSize; 04760 } 04761 break; 04762 04763 default: 04764 goto CallDefWin; 04765 } 04766 } else if (Message == ProgmanHandleMessage && lParam==0) { 04767 // NOTE: lParam will be 0 if progman is sending it and 04768 // 1 if console is sending it. 04769 Status = 0; 04770 // this is a workaround for a progman bug. progman 04771 // sends a progmanhandlemessage twice for each window 04772 // in the system each time one is requested (for one window). 04773 if ((HWND)wParam != hWnd && Console->bIconInit) { 04774 ATOM App,Topic; 04775 CHAR szItem[ITEM_MAX_SIZE+1]; 04776 PCHAR lpItem; 04777 ATOM aItem; 04778 HANDLE ConsoleHandle; 04779 04780 if (!(Console->Flags & CONSOLE_TERMINATING)) { 04781 ConsoleHandle = Console->ConsoleHandle; 04782 Console->hWndProgMan = (HWND)wParam; 04783 UnlockConsole(Console); 04784 App = GlobalAddAtomA("Shell"); 04785 Topic = GlobalAddAtomA("AppIcon"); 04786 SendMessage(Console->hWndProgMan, 04787 WM_DDE_INITIATE, 04788 (WPARAM)hWnd, 04789 MAKELONG(App,Topic) 04790 ); 04791 04792 // if console is still valid, continue getting icon. 04793 Status = RevalidateConsole(ConsoleHandle, &Console); 04794 if (NT_SUCCESS(Status)) { 04795 Console->bIconInit = FALSE; 04796 lpItem = _itoa((int)Console->iIconId,szItem,10); 04797 aItem = GlobalAddAtomA(lpItem); 04798 PostMessage(Console->hWndProgMan, 04799 WM_DDE_REQUEST, 04800 (WPARAM)hWnd, 04801 MAKELONG(CF_TEXT,aItem) 04802 ); 04803 } 04804 } 04805 } 04806 } else { 04807 Status = 0; 04808 switch (Message) { 04809 case WM_DROPFILES: 04810 DoDrop (wParam,Console); 04811 break; 04812 case WM_MOVE: 04813 if (!IsIconic(hWnd)) { 04814 PositionConsoleWindow(Console, (Console->WindowRect.left == CW_USEDEFAULT)); 04815 #if defined(FE_IME) 04816 if (CONSOLE_IS_DBCS_OUTPUTCP(Console)) 04817 { 04818 ConsoleImeResizeModeSystemView(Console,ScreenInfo->Window); 04819 ConsoleImeResizeCompStrView(Console,ScreenInfo->Window); 04820 } 04821 #endif // FE_IME 04822 } 04823 break; 04824 case WM_SIZE: 04825 04826 if (wParam != SIZE_MINIMIZED) { 04827 04828 // 04829 // both SetWindowPos and SetScrollRange cause WM_SIZE 04830 // messages to be issued. ignore them if we have already 04831 // figured out what size the window should be. 04832 // 04833 04834 if (!ScreenInfo->ResizingWindow) { 04835 #ifdef THERESES_DEBUG 04836 DbgPrint("WM_SIZE message "); 04837 if (wParam == SIZEFULLSCREEN) 04838 DbgPrint("SIZEFULLSCREEN\n"); 04839 else if (wParam == SIZENORMAL) 04840 DbgPrint("SIZENORMAL\n"); 04841 DbgPrint(" WindowSize is %d %d\n",CONSOLE_WINDOW_SIZE_X(ScreenInfo),CONSOLE_WINDOW_SIZE_Y(ScreenInfo)); 04842 #endif 04843 ScreenInfo->WindowMaximized = (wParam == SIZE_MAXIMIZED); 04844 04845 if (Console->ResizeFlags & SCREEN_BUFFER_CHANGE) { 04846 UpdateWindowSize(Console,ScreenInfo); 04847 } 04848 PositionConsoleWindow(Console, (Console->WindowRect.left == CW_USEDEFAULT)); 04849 #if defined(FE_IME) 04850 if (CONSOLE_IS_DBCS_OUTPUTCP(Console)) 04851 { 04852 ConsoleImeResizeModeSystemView(Console,ScreenInfo->Window); 04853 ConsoleImeResizeCompStrView(Console,ScreenInfo->Window); 04854 } 04855 #endif // FE_IME 04856 #ifdef THERESES_DEBUG 04857 DbgPrint(" WindowRect is now %d %d %d %d\n",Console->WindowRect.left, 04858 Console->WindowRect.top, 04859 Console->WindowRect.right, 04860 Console->WindowRect.bottom); 04861 #endif 04862 if (Console->ResizeFlags & SCROLL_BAR_CHANGE) { 04863 InternalUpdateScrollBars(ScreenInfo); 04864 Console->ResizeFlags &= ~SCROLL_BAR_CHANGE; 04865 } 04866 } 04867 } else { 04868 04869 // 04870 // Console is going iconic. Trim working set of all 04871 // processes in the console 04872 // 04873 04874 TrimConsoleWorkingSet(Console); 04875 04876 } 04877 04878 break; 04879 case WM_DDE_ACK: 04880 if (Console->bIconInit) { 04881 Console->hWndProgMan = (HWND)wParam; 04882 } 04883 break; 04884 case WM_DDE_DATA: 04885 { 04886 DDEDATA *lpDDEData; 04887 LPPMICONDATA lpIconData; 04888 HICON hIcon; 04889 HANDLE hDdeData; 04890 BOOL bRelease; 04891 WPARAM atomTemp; 04892 04893 UnpackDDElParam(WM_DDE_DATA, lParam, (WPARAM *)&hDdeData, &atomTemp); 04894 04895 if (hDdeData == NULL) { 04896 break; 04897 } 04898 lpDDEData = (DDEDATA *)GlobalLock(hDdeData); 04899 ASSERT(lpDDEData->cfFormat == CF_TEXT); 04900 lpIconData = (LPPMICONDATA)lpDDEData->Value; 04901 hIcon = CreateIconFromResourceEx(&lpIconData->iResource, 04902 0, TRUE, 0x30000, 0, 0, LR_DEFAULTSIZE); 04903 if (hIcon) { 04904 if (Console->hIcon != NULL && Console->hIcon != ghDefaultIcon) { 04905 DestroyIcon(Console->hIcon); 04906 } 04907 Console->hIcon = hIcon; 04908 SendMessage(hWnd, WM_SETICON, ICON_BIG, (LPARAM)hIcon); 04909 04910 if (Console->hSmIcon != NULL) { 04911 if (Console->hSmIcon != ghDefaultSmIcon) { 04912 DestroyIcon(Console->hSmIcon); 04913 } 04914 Console->hSmIcon = NULL; 04915 SendMessage(hWnd, WM_SETICON, ICON_SMALL, (LPARAM)NULL); 04916 } 04917 } 04918 04919 if (lpDDEData->fAckReq) { 04920 04921 PostMessage(Console->hWndProgMan, 04922 WM_DDE_ACK, 04923 (WPARAM)hWnd, 04924 ReuseDDElParam(lParam, WM_DDE_DATA, WM_DDE_ACK, 0x8000, atomTemp)); 04925 } 04926 04927 bRelease = lpDDEData->fRelease; 04928 GlobalUnlock(hDdeData); 04929 if (bRelease){ 04930 GlobalFree(hDdeData); 04931 } 04932 PostMessage(Console->hWndProgMan, 04933 WM_DDE_TERMINATE, 04934 (WPARAM)hWnd, 04935 0 04936 ); 04937 if (Console->Flags & CONSOLE_IS_ICONIC) { 04938 // force repaint of icon 04939 InvalidateRect(hWnd, NULL, TRUE); 04940 } 04941 } 04942 break; 04943 case WM_ACTIVATE: 04944 04945 // 04946 // if we're activated by a mouse click, remember it so 04947 // we don't pass the click on to the app. 04948 // 04949 04950 if (LOWORD(wParam) == WA_CLICKACTIVE) { 04951 Console->Flags |= CONSOLE_IGNORE_NEXT_MOUSE_INPUT; 04952 } 04953 goto CallDefWin; 04954 break; 04955 case WM_DDE_TERMINATE: 04956 break; 04957 // FE_IME 04958 case CM_CONIME_KL_ACTIVATE: 04959 ActivateKeyboardLayout((HKL)wParam, KLF_SETFORPROCESS); 04960 break; 04961 case WM_INPUTLANGCHANGEREQUEST: 04962 if (CONSOLE_IS_IME_ENABLED()) { 04963 ULONG ConimeMessage; 04964 LRESULT lResult; 04965 04966 if (wParam & INPUTLANGCHANGE_BACKWARD) { 04967 ConimeMessage = CONIME_INPUTLANGCHANGEREQUESTBACKWARD; 04968 } 04969 else if (wParam & INPUTLANGCHANGE_FORWARD) { 04970 ConimeMessage = CONIME_INPUTLANGCHANGEREQUESTFORWARD; 04971 } 04972 else { 04973 ConimeMessage = CONIME_INPUTLANGCHANGEREQUEST; 04974 } 04975 04976 if (!NT_SUCCESS(ConsoleImeMessagePumpWorker(Console, 04977 ConimeMessage, 04978 (WPARAM)Console->ConsoleHandle, 04979 (LPARAM)lParam, 04980 &lResult)) || 04981 !lResult) { 04982 04983 break; 04984 } 04985 } 04986 #ifdef LATER 04987 else if (IS_IME_KBDLAYOUT(lParam)) { 04988 // IME keyboard layout should be avoided 04989 // if the console is not IME enabled. 04990 break; 04991 } 04992 // Call the default window proc and let it handle 04993 // the keyboard layout activation. 04994 #endif 04995 goto CallDefWin; 04996 04997 break; 04998 // end FE_IME 04999 05000 case WM_INPUTLANGCHANGE: 05001 Console->hklActive = (HKL)lParam; 05002 // FE_IME 05003 if (CONSOLE_IS_IME_ENABLED()) { 05004 if (!NT_SUCCESS(ConsoleImeMessagePump(Console, 05005 CONIME_INPUTLANGCHANGE, 05006 (WPARAM)Console->ConsoleHandle, 05007 (LPARAM)Console->hklActive 05008 ))) { 05009 break; 05010 } 05011 else{ 05012 GetImeKeyState(Console, NULL) ; 05013 } 05014 } 05015 // end FE_IME 05016 goto CallDefWin; 05017 05018 break; 05019 05020 case WM_SETFOCUS: 05021 ModifyConsoleProcessFocus(Console, TRUE); 05022 SetConsoleReserveKeys(hWnd, Console->ReserveKeys); 05023 Console->Flags |= CONSOLE_HAS_FOCUS; 05024 05025 SetTimer(hWnd, CURSOR_TIMER, guCaretBlinkTime, NULL); 05026 HandleFocusEvent(Console,TRUE); 05027 if (!Console->hklActive) { 05028 SystemParametersInfo(SPI_GETDEFAULTINPUTLANG, 0, &Console->hklActive, FALSE); 05029 GetNonBiDiKeyboardLayout(&Console->hklActive); 05030 } 05031 ActivateKeyboardLayout(Console->hklActive, 0); 05032 // FE_IME 05033 if (CONSOLE_IS_IME_ENABLED()) { 05034 // v-HirShi Sep.15.1995 Support Console IME 05035 if (!NT_SUCCESS(ConsoleImeMessagePump(Console, 05036 CONIME_SETFOCUS, 05037 (WPARAM)Console->ConsoleHandle, 05038 (LPARAM)Console->hklActive 05039 ))) { 05040 break; 05041 } 05042 05043 if (Console->InputBuffer.hWndConsoleIME) 05044 { 05045 /* 05046 * open property window by ImmConfigureIME 05047 * never set focus on console window 05048 * so, set focus to property window 05049 */ 05050 HWND hwnd = GetLastActivePopup(Console->InputBuffer.hWndConsoleIME); 05051 if (hwnd != NULL) 05052 SetForegroundWindow(hwnd); 05053 } 05054 } 05055 // FE_IME 05056 break; 05057 case WM_KILLFOCUS: 05058 ModifyConsoleProcessFocus(Console, FALSE); 05059 SetConsoleReserveKeys(hWnd, CONSOLE_NOSHORTCUTKEY); 05060 Console->Flags &= ~CONSOLE_HAS_FOCUS; 05061 05062 if (ScreenInfo->Flags & CONSOLE_TEXTMODE_BUFFER) { 05063 ConsoleHideCursor(ScreenInfo); 05064 ScreenInfo->BufferInfo.TextInfo.UpdatingScreen -= 1; // counteract HideCursor 05065 } 05066 KillTimer(hWnd, CURSOR_TIMER); 05067 HandleFocusEvent(Console,FALSE); 05068 05069 // FE_IME 05070 if (CONSOLE_IS_IME_ENABLED()) { 05071 // v-HirShi Sep.16.1995 Support Console IME 05072 if (!NT_SUCCESS(ConsoleImeMessagePump(Console, 05073 CONIME_KILLFOCUS, 05074 (WPARAM)Console->ConsoleHandle, 05075 (LPARAM)NULL 05076 ))) { 05077 break; 05078 } 05079 } 05080 // end FE_IME 05081 break; 05082 case WM_PAINT: 05083 05084 // ICONIC bit is not set if we're fullscreen and don't 05085 // have the hardware 05086 05087 ConsoleHideCursor(ScreenInfo); 05088 hDC = BeginPaint(hWnd, &ps); 05089 if (Console->Flags & CONSOLE_IS_ICONIC || 05090 Console->FullScreenFlags == CONSOLE_FULLSCREEN) { 05091 RECT rc; 05092 UINT cxIcon, cyIcon; 05093 GetClientRect(hWnd, &rc); 05094 cxIcon = GetSystemMetrics(SM_CXICON); 05095 cyIcon = GetSystemMetrics(SM_CYICON); 05096 05097 rc.left = (rc.right - cxIcon) >> 1; 05098 rc.top = (rc.bottom - cyIcon) >> 1; 05099 05100 DrawIcon(hDC, rc.left, rc.top, Console->hIcon); 05101 } else { 05102 if (ScreenInfo->Flags & CONSOLE_TEXTMODE_BUFFER) { 05103 PaintRect.Left = (SHORT)((ps.rcPaint.left/SCR_FONTSIZE(ScreenInfo).X)+ScreenInfo->Window.Left); 05104 PaintRect.Right = (SHORT)((ps.rcPaint.right/SCR_FONTSIZE(ScreenInfo).X)+ScreenInfo->Window.Left); 05105 PaintRect.Top = (SHORT)((ps.rcPaint.top/SCR_FONTSIZE(ScreenInfo).Y)+ScreenInfo->Window.Top); 05106 PaintRect.Bottom = (SHORT)((ps.rcPaint.bottom/SCR_FONTSIZE(ScreenInfo).Y)+ScreenInfo->Window.Top); 05107 } else { 05108 PaintRect.Left = (SHORT)(ps.rcPaint.left+ScreenInfo->Window.Left); 05109 PaintRect.Right = (SHORT)(ps.rcPaint.right+ScreenInfo->Window.Left); 05110 PaintRect.Top = (SHORT)(ps.rcPaint.top+ScreenInfo->Window.Top); 05111 PaintRect.Bottom = (SHORT)(ps.rcPaint.bottom+ScreenInfo->Window.Top); 05112 } 05113 ScreenInfo->BufferInfo.TextInfo.Flags &= ~TEXT_VALID_HINT; 05114 WriteToScreen(ScreenInfo,&PaintRect); 05115 } 05116 EndPaint(hWnd,&ps); 05117 ConsoleShowCursor(ScreenInfo); 05118 break; 05119 case WM_CLOSE: 05120 if (!(Console->Flags & CONSOLE_NO_WINDOW) || 05121 !(Console->Flags & CONSOLE_WOW_REGISTERED)) { 05122 HandleCtrlEvent(Console,CTRL_CLOSE_EVENT); 05123 } 05124 break; 05125 case WM_ERASEBKGND: 05126 05127 // ICONIC bit is not set if we're fullscreen and don't 05128 // have the hardware 05129 05130 if (Console->Flags & CONSOLE_IS_ICONIC || 05131 Console->FullScreenFlags == CONSOLE_FULLSCREEN) { 05132 Message = WM_ICONERASEBKGND; 05133 goto CallDefWin; 05134 } 05135 break; 05136 case WM_SETTINGCHANGE: 05137 /* 05138 * See if the caret blink time was changed. If so, reset the 05139 * timer. 05140 */ 05141 if (wParam == SPI_SETKEYBOARDDELAY) { 05142 guCaretBlinkTime = GetCaretBlinkTime(); 05143 if (Console->Flags & CONSOLE_HAS_FOCUS) { 05144 KillTimer(hWnd, CURSOR_TIMER); 05145 SetTimer(hWnd, CURSOR_TIMER, guCaretBlinkTime, NULL); 05146 } 05147 } else { 05148 gfInitSystemMetrics = TRUE; 05149 } 05150 break; 05151 case WM_DISPLAYCHANGE: 05152 gfInitSystemMetrics = TRUE; 05153 break; 05154 case WM_SETCURSOR: 05155 if (lParam == -1) { 05156 05157 // 05158 // the app changed the cursor visibility or shape. 05159 // see if the cursor is in the client area. 05160 // 05161 05162 POINT Point; 05163 HWND hWndTmp; 05164 GetCursorPos(&Point); 05165 hWndTmp = WindowFromPoint(Point); 05166 if (hWndTmp == hWnd) { 05167 lParam = DefWindowProc(hWnd,WM_NCHITTEST,0,MAKELONG((WORD)Point.x, (WORD)Point.y)); 05168 } 05169 } 05170 if ((WORD)lParam == HTCLIENT) { 05171 if (ScreenInfo->CursorDisplayCount < 0) { 05172 SetCursor(NULL); 05173 } else { 05174 SetCursor(ScreenInfo->CursorHandle); 05175 } 05176 } else { 05177 goto CallDefWin; 05178 } 05179 break; 05180 case WM_GETMINMAXINFO: 05181 { 05182 LPMINMAXINFO lpmmi = (LPMINMAXINFO)lParam; 05183 COORD FontSize; 05184 WINDOW_LIMITS WindowLimits; 05185 05186 GetWindowLimits(ScreenInfo, &WindowLimits); 05187 if (ScreenInfo->Flags & CONSOLE_TEXTMODE_BUFFER) { 05188 FontSize = SCR_FONTSIZE(ScreenInfo); 05189 } else { 05190 FontSize.X = 1; 05191 FontSize.Y = 1; 05192 } 05193 lpmmi->ptMaxSize.x = lpmmi->ptMaxTrackSize.x = WindowLimits.MaxWindow.X; 05194 if (!ScreenInfo->WindowMaximizedY) { 05195 lpmmi->ptMaxTrackSize.x += VerticalScrollSize; 05196 lpmmi->ptMaxSize.x += VerticalScrollSize; 05197 } 05198 while (lpmmi->ptMaxSize.x > WindowLimits.FullScreenSize.X + VerticalClientToWindow) { 05199 lpmmi->ptMaxSize.x -= FontSize.X; 05200 } 05201 lpmmi->ptMaxSize.y = lpmmi->ptMaxTrackSize.y = WindowLimits.MaxWindow.Y; 05202 if (!ScreenInfo->WindowMaximizedX) { 05203 lpmmi->ptMaxTrackSize.y += HorizontalScrollSize; 05204 lpmmi->ptMaxSize.y += HorizontalScrollSize; 05205 } 05206 while (lpmmi->ptMaxSize.y > WindowLimits.FullScreenSize.Y + HorizontalClientToWindow) { 05207 lpmmi->ptMaxSize.y -= FontSize.Y; 05208 } 05209 lpmmi->ptMinTrackSize.x = WindowLimits.MinimumWindowSize.X * FontSize.X + VerticalClientToWindow; 05210 lpmmi->ptMinTrackSize.y = HorizontalClientToWindow; 05211 } 05212 break; 05213 case WM_QUERYDRAGICON: 05214 Status = (LRESULT)Console->hIcon; 05215 break; 05216 case WM_WINDOWPOSCHANGING: 05217 // ignore window pos changes if going fullscreen 05218 if (TRUE || (Console->FullScreenFlags == 0)) { 05219 LPWINDOWPOS WindowPos = (LPWINDOWPOS)lParam; 05220 DWORD fMinimized; 05221 05222 /* 05223 * This message is sent before a SetWindowPos() operation 05224 * occurs. We use it here to set/clear the CONSOLE_IS_ICONIC 05225 * bit appropriately... doing so in the WM_SIZE handler 05226 * is incorrect because the WM_SIZE comes after the 05227 * WM_ERASEBKGND during SetWindowPos() processing, and the 05228 * WM_ERASEBKGND needs to know if the console window is 05229 * iconic or not. 05230 */ 05231 fMinimized = IsIconic(hWnd); 05232 05233 if (fMinimized) { 05234 if (!(Console->Flags & CONSOLE_IS_ICONIC)) { 05235 Console->Flags |= CONSOLE_IS_ICONIC; 05236 05237 // 05238 // if the palette is something other than default, 05239 // select the default palette in. otherwise, the 05240 // screen will repaint twice each time the icon 05241 // is painted. 05242 // 05243 05244 if (ScreenInfo->hPalette != NULL && 05245 Console->FullScreenFlags == 0) { 05246 SelectPalette(Console->hDC, 05247 Console->hSysPalette, 05248 FALSE); 05249 UnsetActivePalette(ScreenInfo); 05250 } 05251 } 05252 } else { 05253 if (Console->Flags & CONSOLE_IS_ICONIC) { 05254 Console->Flags &= ~CONSOLE_IS_ICONIC; 05255 05256 // 05257 // if the palette is something other than default, 05258 // select the default palette in. otherwise, the 05259 // screen will repaint twice each time the icon 05260 // is painted. 05261 // 05262 05263 if (ScreenInfo->hPalette != NULL && 05264 Console->FullScreenFlags == 0) { 05265 SelectPalette(Console->hDC, 05266 ScreenInfo->hPalette, 05267 FALSE); 05268 SetActivePalette(ScreenInfo); 05269 } 05270 } 05271 } 05272 if (!ScreenInfo->ResizingWindow && 05273 (WindowPos->cx || WindowPos->cy) && 05274 !fMinimized) { 05275 ProcessResizeWindow(ScreenInfo,Console,WindowPos); 05276 } 05277 } 05278 break; 05279 case WM_CONTEXTMENU: 05280 if (DefWindowProc(hWnd, WM_NCHITTEST, 0, lParam) == HTCLIENT) { 05281 TrackPopupMenuEx(Console->hHeirMenu, 05282 TPM_RIGHTBUTTON, 05283 GET_X_LPARAM(lParam), 05284 GET_Y_LPARAM(lParam), 05285 hWnd, 05286 NULL); 05287 } else { 05288 goto CallDefWin; 05289 } 05290 break; 05291 case WM_NCLBUTTONDOWN: 05292 // allow user to move window even when bigger than the screen 05293 switch (wParam & 0x00FF) { 05294 case HTCAPTION: 05295 UnlockConsole(Console); 05296 Console = NULL; 05297 SetActiveWindow(hWnd); 05298 SendMessage(hWnd, WM_SYSCOMMAND, 05299 SC_MOVE | wParam, lParam); 05300 break; 05301 default: 05302 goto CallDefWin; 05303 } 05304 break; 05305 #if defined (FE_IME) 05306 // Sep.16.1995 Support Console IME 05307 case WM_KEYDOWN +CONIME_KEYDATA: 05308 case WM_KEYUP +CONIME_KEYDATA: 05309 case WM_CHAR +CONIME_KEYDATA: 05310 case WM_DEADCHAR +CONIME_KEYDATA: 05311 05312 case WM_SYSKEYDOWN +CONIME_KEYDATA: 05313 case WM_SYSKEYUP +CONIME_KEYDATA: 05314 case WM_SYSCHAR +CONIME_KEYDATA: 05315 case WM_SYSDEADCHAR+CONIME_KEYDATA: 05316 #endif 05317 case WM_KEYDOWN: 05318 case WM_KEYUP: 05319 case WM_CHAR: 05320 case WM_DEADCHAR: 05321 HandleKeyEvent(Console,hWnd,Message,wParam,lParam); 05322 break; 05323 case WM_SYSKEYDOWN: 05324 case WM_SYSKEYUP: 05325 case WM_SYSCHAR: 05326 case WM_SYSDEADCHAR: 05327 if (HandleSysKeyEvent(Console,hWnd,Message,wParam,lParam) && Console != NULL) { 05328 goto CallDefWin; 05329 } 05330 break; 05331 case WM_COMMAND: 05332 // 05333 // If this is an edit command from the context menu, treat 05334 // it like a sys command. 05335 // 05336 if ((wParam < cmCopy) || (wParam > cmSelectAll)) { 05337 break; 05338 } 05339 // FALL THRU 05340 case WM_SYSCOMMAND: 05341 if (wParam >= ScreenInfo->CommandIdLow && 05342 wParam <= ScreenInfo->CommandIdHigh) { 05343 HandleMenuEvent(Console,(DWORD)wParam); 05344 } else if (wParam == cmMark) { 05345 DoMark(Console); 05346 } else if (wParam == cmCopy) { 05347 DoCopy(Console); 05348 } else if (wParam == cmPaste) { 05349 DoPaste(Console); 05350 } else if (wParam == cmScroll) { 05351 DoScroll(Console); 05352 } else if (wParam == cmFind) { 05353 DoFind(Console); 05354 } else if (wParam == cmSelectAll) { 05355 DoSelectAll(Console); 05356 } else if (wParam == cmControl) { 05357 PropertiesDlgShow(Console, TRUE); 05358 } else if (wParam == cmDefaults) { 05359 PropertiesDlgShow(Console, FALSE); 05360 } else { 05361 05362 // if we're restoring, remove any 05363 // mouse events so app doesn't get them. 05364 05365 if (wParam == SC_RESTORE) { 05366 MSG RestoreMsg; 05367 SetCapture(hWnd); 05368 while (GetCapture() != NULL && 05369 (GetKeyState(VK_LBUTTON) & KEY_PRESSED)) { 05370 PeekMessage(&RestoreMsg, 05371 hWnd, 05372 WM_MOUSEFIRST, 05373 WM_MOUSELAST, 05374 PM_REMOVE 05375 ); 05376 } 05377 ReleaseCapture(); 05378 } 05379 05380 goto CallDefWin; 05381 } 05382 break; 05383 case WM_TIMER: 05384 #if defined(FE_IME) 05385 if (wParam == SCROLL_WAIT_TIMER) 05386 { 05387 ASSERT(CONSOLE_IS_IME_ENABLED()); 05388 if ((ScreenInfo->Console->ConsoleIme.ScrollFlag & (HIDE_FOR_SCROLL)) && 05389 (ScreenInfo->Console->ConsoleIme.ScrollWaitCountDown > 0) 05390 ) { 05391 if ((ScreenInfo->Console->ConsoleIme.ScrollWaitCountDown -= guCaretBlinkTime) <= 0) { 05392 ConsoleImeBottomLineInUse(ScreenInfo); 05393 } 05394 } 05395 break; 05396 } 05397 #endif // FE_IME 05398 CursorTimerRoutine(ScreenInfo); 05399 ScrollIfNecessary(Console,ScreenInfo); 05400 break; 05401 case WM_HSCROLL: 05402 HorizontalScroll(ScreenInfo, LOWORD(wParam), HIWORD(wParam)); 05403 break; 05404 case WM_VSCROLL: 05405 VerticalScroll(Console, ScreenInfo,LOWORD(wParam),HIWORD(wParam)); 05406 break; 05407 case WM_INITMENU: 05408 HandleMenuEvent(Console,WM_INITMENU); 05409 InitializeMenu(Console); 05410 break; 05411 case WM_MENUSELECT: 05412 if (HIWORD(wParam) == 0xffff) { 05413 HandleMenuEvent(Console,WM_MENUSELECT); 05414 } 05415 break; 05416 case WM_MOUSEMOVE: 05417 case WM_LBUTTONDOWN: 05418 case WM_LBUTTONUP: 05419 case WM_LBUTTONDBLCLK: 05420 case WM_RBUTTONDOWN: 05421 case WM_RBUTTONUP: 05422 case WM_RBUTTONDBLCLK: 05423 case WM_MBUTTONDOWN: 05424 case WM_MBUTTONUP: 05425 case WM_MBUTTONDBLCLK: 05426 case WM_MOUSEWHEEL: 05427 if (HandleMouseEvent(Console,ScreenInfo,Message,wParam,lParam)) { 05428 if (Message != WM_MOUSEWHEEL) { 05429 goto CallDefWin; 05430 } 05431 } else { 05432 break; 05433 } 05434 05435 /* 05436 * Don't handle zoom 05437 */ 05438 if (wParam & (MK_CONTROL)) { 05439 goto CallDefWin; 05440 } 05441 05442 Status = 1; 05443 if (gfInitSystemMetrics) { 05444 InitializeSystemMetrics(); 05445 } 05446 05447 ScreenInfo->WheelDelta -= (short)HIWORD(wParam); 05448 if (abs(ScreenInfo->WheelDelta) >= WHEEL_DELTA && 05449 gucWheelScrollLines > 0) { 05450 05451 COORD NewOrigin; 05452 SHORT dy; 05453 05454 NewOrigin.X = ScreenInfo->Window.Left; 05455 NewOrigin.Y = ScreenInfo->Window.Top; 05456 05457 /* 05458 * Limit a roll of one (1) WHEEL_DELTA to scroll one (1) page. 05459 * If in shift scroll mode then scroll one page at a time regardless. 05460 */ 05461 05462 if (!(wParam & MK_SHIFT)) 05463 dy = (int) min( 05464 (UINT) CONSOLE_WINDOW_SIZE_Y(ScreenInfo) - 1, 05465 gucWheelScrollLines); 05466 else 05467 dy = CONSOLE_WINDOW_SIZE_Y(ScreenInfo) - 1; 05468 05469 if (dy == 0) { 05470 dy++; 05471 } 05472 05473 dy *= (ScreenInfo->WheelDelta / WHEEL_DELTA); 05474 ScreenInfo->WheelDelta %= WHEEL_DELTA; 05475 05476 NewOrigin.Y += dy; 05477 if (NewOrigin.Y < 0) { 05478 NewOrigin.Y = 0; 05479 } else if (NewOrigin.Y + CONSOLE_WINDOW_SIZE_Y(ScreenInfo) > 05480 ScreenInfo->ScreenBufferSize.Y) { 05481 NewOrigin.Y = ScreenInfo->ScreenBufferSize.Y - 05482 CONSOLE_WINDOW_SIZE_Y(ScreenInfo); 05483 } 05484 05485 SetWindowOrigin(ScreenInfo, TRUE, NewOrigin); 05486 } 05487 break; 05488 05489 case WM_PALETTECHANGED: 05490 if (Console->FullScreenFlags == 0) { 05491 if (ScreenInfo->hPalette != NULL) { 05492 SetActivePalette(ScreenInfo); 05493 if (ScreenInfo->Flags & CONSOLE_GRAPHICS_BUFFER) { 05494 WriteRegionToScreenBitMap(ScreenInfo, 05495 &ScreenInfo->Window); 05496 } 05497 } else { 05498 SetScreenColors(ScreenInfo, ScreenInfo->Attributes, 05499 ScreenInfo->PopupAttributes, TRUE); 05500 } 05501 } 05502 break; 05503 #if defined(_X86_) 05504 case WM_FULLSCREEN: 05505 05506 // 05507 // This message is sent by the system to tell console that 05508 // the fullscreen state of a window has changed. 05509 // In some cases, this message will be sent in response to 05510 // a call from console to change to fullscreen (Atl-Enter) 05511 // or may also come directly from the system (switch of 05512 // focus from a windowed app to a fullscreen app). 05513 // 05514 05515 KdPrint(("CONSRV: WindowProc - WM_FULLSCREEN\n")); 05516 05517 Status = DisplayModeTransition(wParam,Console,ScreenInfo); 05518 #if defined(FE_IME) 05519 if (NT_SUCCESS(Status)) { 05520 Status = ImeWmFullScreen(wParam,Console,ScreenInfo); 05521 } 05522 #endif // FE_IME 05523 break; 05524 #endif 05525 case CM_SET_WINDOW_SIZE: 05526 if (lParam == 0x47474747) { 05527 Status = InternalSetWindowSize(Console, 05528 (PSCREEN_INFORMATION)wParam, 05529 &ScreenInfo->Window 05530 ); 05531 } 05532 break; 05533 case CM_BEEP: 05534 if (lParam == 0x47474747) { 05535 Beep(800, 200); 05536 } 05537 break; 05538 case CM_UPDATE_SCROLL_BARS: 05539 InternalUpdateScrollBars(ScreenInfo); 05540 break; 05541 case CM_UPDATE_TITLE: 05542 SetWindowText(hWnd,Console->Title); 05543 break; 05544 case CM_CONSOLE_MSG: 05545 if (!UnqueueConsoleMessage(Console, &Message, &wParam, &lParam)) { 05546 break; 05547 } 05548 switch (Message) { 05549 #if defined(_X86_) 05550 case CM_MODE_TRANSITION: 05551 05552 KdPrint(("CONSRV: WindowProc - CM_MODE_TRANSITION\n")); 05553 05554 if (wParam == FULLSCREEN) { 05555 if (Console->FullScreenFlags == 0) { 05556 ConvertToFullScreen(Console); 05557 Console->FullScreenFlags |= CONSOLE_FULLSCREEN; 05558 ChangeDispSettings(Console, hWnd, CDS_FULLSCREEN); 05559 } 05560 } else { 05561 if (Console->FullScreenFlags & CONSOLE_FULLSCREEN) { 05562 ConvertToWindowed(Console); 05563 Console->FullScreenFlags &= ~CONSOLE_FULLSCREEN; 05564 ChangeDispSettings(Console, hWnd, 0); 05565 05566 ShowWindow(hWnd, SW_RESTORE); 05567 } 05568 } 05569 05570 UnlockConsole(Console); 05571 Console = NULL; 05572 05573 NtSetEvent((HANDLE)lParam, NULL); 05574 NtClose((HANDLE)lParam); 05575 break; 05576 #endif 05577 #if defined (FE_IME) 05578 case CM_SET_IME_CODEPAGE: { 05579 if (! LOWORD(lParam)) 05580 { 05581 // Input code page 05582 Status = SetImeCodePage(Console); 05583 } 05584 else 05585 { 05586 // Output code page 05587 Status = SetImeOutputCodePage(Console, ScreenInfo, HIWORD(lParam)); 05588 } 05589 05590 if (wParam) { 05591 NtSetEvent((HANDLE)wParam, NULL); 05592 NtClose((HANDLE)wParam); 05593 } 05594 break; 05595 } 05596 case CM_SET_NLSMODE: 05597 Status = SetImeKeyState(Console, ImmConversionFromConsole((DWORD)lParam)); 05598 if (wParam) { 05599 NtSetEvent((HANDLE)wParam, NULL); 05600 NtClose((HANDLE)wParam); 05601 } 05602 break; 05603 case CM_GET_NLSMODE: 05604 if (Console->InputThreadInfo->hWndConsoleIME) 05605 { 05606 ASSERT(CONSOLE_IS_IME_ENABLED()); 05607 05608 if (!NT_SUCCESS(GetImeKeyState(Console, NULL))) { 05609 if (wParam) { 05610 NtSetEvent((HANDLE)wParam, NULL); 05611 NtClose((HANDLE)wParam); 05612 } 05613 break; 05614 } 05615 if (wParam) { 05616 NtSetEvent((HANDLE)wParam, NULL); 05617 NtClose((HANDLE)wParam); 05618 } 05619 } 05620 else if (lParam < 10) 05621 { 05622 /* 05623 * try get conversion mode until ready ConIME. 05624 */ 05625 Status = QueueConsoleMessage(Console, 05626 CM_GET_NLSMODE, 05627 wParam, 05628 lParam+1 05629 ); 05630 if (!NT_SUCCESS(Status)) { 05631 if (wParam) { 05632 NtSetEvent((HANDLE)wParam, NULL); 05633 NtClose((HANDLE)wParam); 05634 } 05635 } 05636 } 05637 else 05638 { 05639 if (wParam) { 05640 NtSetEvent((HANDLE)wParam, NULL); 05641 NtClose((HANDLE)wParam); 05642 } 05643 } 05644 break; 05645 #endif // FE_IME 05646 } 05647 break; 05648 05649 case CM_HIDE_WINDOW: 05650 ShowWindowAsync(hWnd, SW_MINIMIZE); 05651 break; 05652 case CM_PROPERTIES_START: 05653 Console->hWndProperties = (HWND)wParam; 05654 break; 05655 case CM_PROPERTIES_UPDATE: 05656 PropertiesUpdate(Console, (HANDLE)wParam); 05657 break; 05658 case CM_PROPERTIES_END: 05659 Console->hWndProperties = NULL; 05660 break; 05661 #if defined(FE_IME) 05662 case WM_COPYDATA: 05663 if (CONSOLE_IS_IME_ENABLED() && CONSOLE_IS_DBCS_OUTPUTCP(Console)) { 05664 Status = ImeControl(Console,(HWND)wParam,(PCOPYDATASTRUCT)lParam); 05665 } 05666 break; 05667 // v-HirShi Sep.18.1995 Support Console IME 05668 case WM_ENTERMENULOOP: 05669 if (Console->Flags & CONSOLE_HAS_FOCUS) { 05670 Console->InputBuffer.ImeMode.Unavailable = TRUE; 05671 if (CONSOLE_IS_IME_ENABLED()) { 05672 if (!NT_SUCCESS(ConsoleImeMessagePump(Console, 05673 CONIME_KILLFOCUS, 05674 (WPARAM)Console->ConsoleHandle, 05675 (LPARAM)NULL 05676 ))) { 05677 break; 05678 } 05679 } 05680 } 05681 break; 05682 05683 case WM_EXITMENULOOP: 05684 if (Console->Flags & CONSOLE_HAS_FOCUS) { 05685 if (CONSOLE_IS_IME_ENABLED()) { 05686 if (!NT_SUCCESS(ConsoleImeMessagePump(Console, 05687 CONIME_SETFOCUS, 05688 (WPARAM)Console->ConsoleHandle, 05689 (LPARAM)Console->hklActive 05690 ))) { 05691 break; 05692 } 05693 } 05694 Console->InputBuffer.ImeMode.Unavailable = FALSE; 05695 } 05696 break; 05697 05698 case WM_ENTERSIZEMOVE: 05699 if (Console->Flags & CONSOLE_HAS_FOCUS) { 05700 Console->InputBuffer.ImeMode.Unavailable = TRUE; 05701 } 05702 break; 05703 05704 case WM_EXITSIZEMOVE: 05705 if (Console->Flags & CONSOLE_HAS_FOCUS) { 05706 Console->InputBuffer.ImeMode.Unavailable = FALSE; 05707 } 05708 break; 05709 #endif // FE_IME 05710 CallDefWin: 05711 default: 05712 if (Console != NULL) { 05713 UnlockConsole(Console); 05714 Console = NULL; 05715 } 05716 Status = (DefWindowProc(hWnd,Message,wParam,lParam)); 05717 break; 05718 } 05719 } 05720 } finally { 05721 if (Console != NULL) { 05722 UnlockConsole(Console); 05723 Console = NULL; 05724 } 05725 } 05726 05727 return Status; 05728 } 05729 05730 05731 /* 05732 * Drag and Drop support functions for console window 05733 */ 05734 05735 /*++ 05736 05737 Routine Description: 05738 05739 This routine retrieves the filenames of dropped files. It was copied from 05740 shelldll API DragQueryFile. We didn't use DragQueryFile () because we don't 05741 want to load Shell32.dll in CSR 05742 05743 Arguments: 05744 Same as DragQueryFile 05745 05746 Return Value: 05747 05748 05749 --*/ 05750 UINT ConsoleDragQueryFile( 05751 IN HANDLE hDrop, 05752 IN PVOID lpFile, 05753 IN UINT cb 05754 ) 05755 { 05756 UINT i = 0; 05757 LPDROPFILESTRUCT lpdfs; 05758 BOOL fWide; 05759 05760 lpdfs = (LPDROPFILESTRUCT)GlobalLock(hDrop); 05761 05762 if (lpdfs && lpdfs != hDrop) 05763 { 05764 try { 05765 fWide = (LOWORD(lpdfs->pFiles) == sizeof(DROPFILES)); 05766 if (fWide) 05767 { 05768 // 05769 // This is a new (NT-compatible) HDROP 05770 // 05771 fWide = lpdfs->fWide; // Redetermine fWide from struct 05772 // since it is present. 05773 } 05774 05775 if (fWide) 05776 { 05777 LPWSTR lpList; 05778 05779 // 05780 // UNICODE HDROP 05781 // 05782 05783 lpList = (LPWSTR)((LPBYTE)lpdfs + lpdfs->pFiles); 05784 05785 i = lstrlenW(lpList); 05786 05787 if (!i) 05788 goto Exit; 05789 05790 cb--; 05791 if (cb < i) 05792 i = cb; 05793 05794 lstrcpynW((LPWSTR)lpFile, lpList, i + 1); 05795 } 05796 else 05797 { 05798 LPSTR lpList; 05799 05800 // 05801 // This is Win31-style HDROP or an ANSI NT Style HDROP 05802 // 05803 lpList = (LPSTR)((LPBYTE)lpdfs + lpdfs->pFiles); 05804 05805 i = lstrlenA(lpList); 05806 05807 if (!i) 05808 goto Exit; 05809 05810 cb--; 05811 if (cb < i) 05812 i = cb; 05813 05814 MultiByteToWideChar(CP_ACP, 0, lpList, -1, (LPWSTR)lpFile, cb); 05815 05816 } 05817 } except( EXCEPTION_EXECUTE_HANDLER ) { 05818 KdPrint(("CONSRV: WM_DROPFILES raised exception\n")); 05819 i = 0; 05820 } 05821 Exit: 05822 GlobalUnlock(hDrop); 05823 GlobalFree(hDrop); 05824 } 05825 05826 return(i); 05827 } 05828 05829 05830 05831 05832 /*++ 05833 05834 Routine Description: 05835 05836 This routine is called when ConsoleWindowProc receives a WM_DROPFILES 05837 message. It initially calls ConsoleDragQueryFile() to calculate the number 05838 of files dropped and then ConsoleDragQueryFile() is called 05839 to retrieve the filename. DoStringPaste() pastes the filename to the console 05840 window 05841 05842 Arguments: 05843 wParam - Identifies the structure containing the filenames of the 05844 dropped files. 05845 Console - Pointer to CONSOLE_INFORMATION structure 05846 05847 05848 Return Value: 05849 None 05850 05851 05852 --*/ 05853 void DoDrop (WPARAM wParam, 05854 PCONSOLE_INFORMATION Console) 05855 { 05856 WCHAR szPath[MAX_PATH]; 05857 BOOL fAddQuotes; 05858 05859 if (ConsoleDragQueryFile((HANDLE)wParam, szPath, CharSizeOf(szPath))) { 05860 fAddQuotes = (wcschr(szPath, L' ') != NULL); 05861 if (fAddQuotes) 05862 DoStringPaste(Console, L"\"", 1); 05863 DoStringPaste(Console, szPath, wcslen(szPath)); 05864 if (fAddQuotes) 05865 DoStringPaste(Console, L"\"", 1); 05866 } 05867 } 05868 05869 BOOL 05870 CreateDbcsScreenBuffer( 05871 IN PCONSOLE_INFORMATION Console, 05872 IN COORD dwScreenBufferSize, 05873 OUT PDBCS_SCREEN_BUFFER DbcsScreenBuffer 05874 ) 05875 { 05876 if (CONSOLE_IS_DBCS_OUTPUTCP(Console)) { 05877 DbcsScreenBuffer->TransBufferCharacter = 05878 (PWCHAR)ConsoleHeapAlloc( 05879 MAKE_TAG( SCREEN_DBCS_TAG ), 05880 (dwScreenBufferSize.X*dwScreenBufferSize.Y*sizeof(WCHAR))+sizeof(WCHAR)); 05881 if (DbcsScreenBuffer->TransBufferCharacter == NULL) { 05882 return FALSE; 05883 } 05884 05885 DbcsScreenBuffer->TransBufferAttribute = 05886 (PBYTE)ConsoleHeapAlloc( 05887 MAKE_TAG( SCREEN_DBCS_TAG ), 05888 (dwScreenBufferSize.X*dwScreenBufferSize.Y*sizeof(BYTE))+sizeof(BYTE)); 05889 if (DbcsScreenBuffer->TransBufferAttribute == NULL) { 05890 ConsoleHeapFree(DbcsScreenBuffer->TransBufferCharacter); 05891 return FALSE; 05892 } 05893 05894 DbcsScreenBuffer->TransWriteConsole = 05895 (PWCHAR)ConsoleHeapAlloc( 05896 MAKE_TAG( SCREEN_DBCS_TAG ), 05897 (dwScreenBufferSize.X*dwScreenBufferSize.Y*sizeof(WCHAR))+sizeof(WCHAR)); 05898 if (DbcsScreenBuffer->TransWriteConsole == NULL) { 05899 ConsoleHeapFree(DbcsScreenBuffer->TransBufferAttribute); 05900 ConsoleHeapFree(DbcsScreenBuffer->TransBufferCharacter); 05901 return FALSE; 05902 } 05903 05904 DbcsScreenBuffer->KAttrRows = 05905 (PBYTE)ConsoleHeapAlloc( 05906 MAKE_TAG( SCREEN_DBCS_TAG ), 05907 dwScreenBufferSize.X*dwScreenBufferSize.Y*sizeof(BYTE)); 05908 if (DbcsScreenBuffer->KAttrRows == NULL) { 05909 ConsoleHeapFree(DbcsScreenBuffer->TransWriteConsole); 05910 ConsoleHeapFree(DbcsScreenBuffer->TransBufferAttribute); 05911 ConsoleHeapFree(DbcsScreenBuffer->TransBufferCharacter); 05912 return FALSE; 05913 } 05914 } 05915 else { 05916 DbcsScreenBuffer->TransBufferCharacter = NULL; 05917 DbcsScreenBuffer->TransBufferAttribute = NULL; 05918 DbcsScreenBuffer->TransWriteConsole = NULL; 05919 DbcsScreenBuffer->KAttrRows = NULL; 05920 } 05921 05922 return TRUE; 05923 } 05924 05925 BOOL 05926 DeleteDbcsScreenBuffer( 05927 IN PDBCS_SCREEN_BUFFER DbcsScreenBuffer 05928 ) 05929 { 05930 if (DbcsScreenBuffer->KAttrRows) { 05931 ConsoleHeapFree(DbcsScreenBuffer->TransBufferCharacter); 05932 ConsoleHeapFree(DbcsScreenBuffer->TransBufferAttribute); 05933 ConsoleHeapFree(DbcsScreenBuffer->TransWriteConsole); 05934 ConsoleHeapFree(DbcsScreenBuffer->KAttrRows); 05935 } 05936 return TRUE; 05937 } 05938 05939 BOOL 05940 ReCreateDbcsScreenBufferWorker( 05941 IN PCONSOLE_INFORMATION Console, 05942 IN PSCREEN_INFORMATION ScreenInfo 05943 ) 05944 { 05945 SHORT i; 05946 PBYTE KAttrRowPtr; 05947 COORD dwScreenBufferSize; 05948 DBCS_SCREEN_BUFFER NewDbcsScreenBuffer; 05949 05950 ASSERT(ScreenInfo->Flags & CONSOLE_TEXTMODE_BUFFER); 05951 if (!(ScreenInfo->Flags & CONSOLE_TEXTMODE_BUFFER)) { 05952 return FALSE; 05953 } 05954 05955 dwScreenBufferSize = ScreenInfo->ScreenBufferSize; 05956 05957 if (!CreateDbcsScreenBuffer(Console, 05958 dwScreenBufferSize, 05959 &NewDbcsScreenBuffer)) { 05960 return FALSE; 05961 } 05962 05963 KAttrRowPtr = NewDbcsScreenBuffer.KAttrRows; 05964 for (i = 0; i < dwScreenBufferSize.Y; i++) { 05965 ScreenInfo->BufferInfo.TextInfo.Rows[i].CharRow.KAttrs = KAttrRowPtr; 05966 if (KAttrRowPtr) { 05967 RtlZeroMemory(KAttrRowPtr, dwScreenBufferSize.X); 05968 KAttrRowPtr += dwScreenBufferSize.X; 05969 } 05970 } 05971 ScreenInfo->BufferInfo.TextInfo.DbcsScreenBuffer = NewDbcsScreenBuffer; 05972 05973 return TRUE; 05974 } 05975 05976 05977 typedef struct _DBCS_SCREEN_BUFFER_TRACKER { 05978 DBCS_SCREEN_BUFFER data; 05979 #if DBG 05980 PSCREEN_INFORMATION pScreenInfo; 05981 #endif 05982 } DBCS_SCREEN_BUFFER_TRACKER, *PDBCS_SCREEN_BUFFER_TRACKER; 05983 05984 BOOL 05985 ReCreateDbcsScreenBuffer( 05986 IN PCONSOLE_INFORMATION pConsole, 05987 IN UINT OldCodePage) 05988 { 05989 BOOL fResult = FALSE; 05990 PDBCS_SCREEN_BUFFER_TRACKER pDbcsScreenBuffer; 05991 PSCREEN_INFORMATION pScreenInfo; 05992 UINT nScreen; 05993 UINT i; 05994 #if DBG 05995 UINT nScreenSave; 05996 #endif 05997 05998 // 05999 // If DbcsBuffers don't need to be modified, just bail out. 06000 // 06001 if (!IsAvailableFarEastCodePage(OldCodePage) == !CONSOLE_IS_DBCS_OUTPUTCP(pConsole) ) 06002 return TRUE; 06003 06004 // 06005 // Count the number of screens allocated. 06006 // 06007 for (nScreen = 0, pScreenInfo = pConsole->ScreenBuffers; pScreenInfo; pScreenInfo = pScreenInfo->Next) { 06008 // 06009 // Ignore graphic mode buffer. 06010 // 06011 if (pScreenInfo->Flags & CONSOLE_TEXTMODE_BUFFER) { 06012 ++nScreen; 06013 } 06014 } 06015 #if DBG 06016 nScreenSave = nScreen; 06017 #endif 06018 06019 // 06020 // Allocate the temporary buffer to store the old values 06021 // 06022 pDbcsScreenBuffer = ConsoleHeapAlloc(MAKE_TAG(TMP_DBCS_TAG), sizeof *pDbcsScreenBuffer * nScreen); 06023 if (pDbcsScreenBuffer == NULL) { 06024 RIPMSG0(RIP_WARNING, "ReCreateDbcsScreenBuffer: not enough memory."); 06025 return FALSE; 06026 } 06027 06028 // 06029 // Try to allocate or de-allocate the necessary DBCS buffers 06030 // 06031 for (nScreen = 0, pScreenInfo = pConsole->ScreenBuffers; pScreenInfo; pScreenInfo = pScreenInfo->Next) { 06032 ASSERT(nScreen < nScreenSave); // make sure ScreenBuffers are not changed 06033 06034 // 06035 // We only handle the text mode screen buffer. 06036 // 06037 if (pScreenInfo->Flags & CONSOLE_TEXTMODE_BUFFER) { 06038 // 06039 // Save the previous value just in case something goes bad. 06040 // 06041 #if DBG 06042 pDbcsScreenBuffer[nScreen].pScreenInfo = pScreenInfo; 06043 #endif 06044 pDbcsScreenBuffer[nScreen++].data = pScreenInfo->BufferInfo.TextInfo.DbcsScreenBuffer; 06045 06046 if (!ReCreateDbcsScreenBufferWorker(pConsole, pScreenInfo)) { 06047 // 06048 // If we fail to ReCreate the DbcsScreenBuffer, 06049 // free all allocation to this point, and restore the orginal. 06050 // 06051 RIPMSG0(RIP_WARNING, "ReCreateDbcsScreenBuffer: failed to recreate dbcs screen buffer."); 06052 06053 for (i = 0, pScreenInfo = pConsole->ScreenBuffers; i < nScreen; pScreenInfo = pScreenInfo->Next) { 06054 ASSERT(pScreenInfo); 06055 06056 if (pScreenInfo->Flags & CONSOLE_TEXTMODE_BUFFER) { 06057 ASSERT(pDbcsScreenBuffer[i].pScreenInfo == pScreenInfo); 06058 if (i < nScreen - 1) { 06059 ASSERT(pScreenInfo->BufferInfo.TextInfo.DbcsScreenBuffer.KAttrRows != pDbcsScreenBuffer[i].data.KAttrRows); 06060 DeleteDbcsScreenBuffer(&pScreenInfo->BufferInfo.TextInfo.DbcsScreenBuffer); 06061 } 06062 06063 pScreenInfo->BufferInfo.TextInfo.DbcsScreenBuffer = pDbcsScreenBuffer[i++].data; 06064 } 06065 } 06066 goto exit; 06067 } 06068 } 06069 } 06070 06071 // 06072 // All allocation succeeded. Now we can delete the old allocation. 06073 // 06074 for (i = 0; i < nScreen; ++i) { 06075 DeleteDbcsScreenBuffer(&pDbcsScreenBuffer[i].data); 06076 } 06077 06078 fResult = TRUE; 06079 06080 exit: 06081 ConsoleHeapFree(pDbcsScreenBuffer); 06082 06083 return fResult; 06084 } 06085 06086 // Checks if the primary language of this keyborad layout is BiDi or not. 06087 BOOL IsNotBiDILayout(HKL hkl) 06088 { 06089 BOOL bRet = TRUE; 06090 LANGID LangID = PRIMARYLANGID(HandleToUlong(hkl)); 06091 06092 if ( (LangID == LANG_ARABIC) || (LangID == LANG_HEBREW)) { 06093 bRet = FALSE; 06094 } 06095 return bRet; 06096 06097 } 06098 06099 void GetNonBiDiKeyboardLayout(HKL *phklActive) 06100 { 06101 HKL hkl = *phklActive; 06102 06103 if ( IsNotBiDILayout(hkl) ) 06104 return; 06105 06106 // Start with the default one. 06107 ActivateKeyboardLayout(hkl, 0); 06108 // We know that the default is not good, Activate the next. 06109 ActivateKeyboardLayout((HKL)HKL_NEXT, 0); 06110 06111 // Loop until you find a none BiDi one or endof list. 06112 while (hkl = GetKeyboardLayout(0)) 06113 { 06114 if ((hkl == *phklActive) || IsNotBiDILayout(hkl)) { 06115 *phklActive = hkl; 06116 break; 06117 } 06118 ActivateKeyboardLayout((HKL)HKL_NEXT, 0); 06119 } 06120 } 06121 06122 #if defined(FE_SB) 06123 06124 #define WWSB_NOFE 06125 #include "_output.h" 06126 #undef WWSB_NOFE 06127 #define WWSB_FE 06128 #include "_output.h" 06129 #undef WWSB_FE 06130 06131 #endif // FE_SB

Generated on Sat May 15 19:41:07 2004 for test by doxygen 1.3.7