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

cursor.c

Go to the documentation of this file.
00001 /*++ 00002 00003 Copyright (c) 1985 - 1999, Microsoft Corporation 00004 00005 Module Name: 00006 00007 cursor.c 00008 00009 Abstract: 00010 00011 This file implements the NT console server cursor routines. 00012 00013 Author: 00014 00015 Therese Stowell (thereses) 5-Dec-1990 00016 00017 Revision History: 00018 00019 --*/ 00020 00021 #include "precomp.h" 00022 #pragma hdrstop 00023 00024 //#define PROFILE_GDI 00025 #ifdef PROFILE_GDI 00026 LONG InvertCount; 00027 #define INVERT_CALL InvertCount++ 00028 #else 00029 #define INVERT_CALL 00030 #endif 00031 00032 VOID 00033 InvertPixels( 00034 IN PSCREEN_INFORMATION ScreenInfo 00035 ) 00036 00037 /*++ 00038 00039 Routine Description: 00040 00041 This routine inverts the cursor pixels, making it either visible or 00042 invisible. 00043 00044 Arguments: 00045 00046 ScreenInfo - pointer to screen info structure. 00047 00048 Return Value: 00049 00050 none. 00051 00052 --*/ 00053 00054 { 00055 #ifdef FE_SB 00056 if (CONSOLE_IS_DBCS_OUTPUTCP(ScreenInfo->Console)) { 00057 PCONVERSIONAREA_INFORMATION ConvAreaInfo; 00058 SMALL_RECT Region; 00059 SMALL_RECT CursorRegion; 00060 SMALL_RECT ClippedRegion; 00061 00062 #ifdef DBG_KATTR 00063 // BeginKAttrCheck(ScreenInfo); 00064 #endif 00065 00066 ConvAreaInfo = ScreenInfo->Console->ConsoleIme.ConvAreaRoot; 00067 CursorRegion.Left = CursorRegion.Right = ScreenInfo->BufferInfo.TextInfo.CursorPosition.X; 00068 CursorRegion.Top = CursorRegion.Bottom = ScreenInfo->BufferInfo.TextInfo.CursorPosition.Y; 00069 while (ConvAreaInfo) { 00070 00071 if ((ConvAreaInfo->ConversionAreaMode & (CA_HIDDEN+CA_HIDE_FOR_SCROLL))==0) { 00072 // 00073 // Do clipping region 00074 // 00075 Region.Left = ScreenInfo->Window.Left + 00076 ConvAreaInfo->CaInfo.rcViewCaWindow.Left + 00077 ConvAreaInfo->CaInfo.coordConView.X; 00078 Region.Right = Region.Left + 00079 (ConvAreaInfo->CaInfo.rcViewCaWindow.Right - 00080 ConvAreaInfo->CaInfo.rcViewCaWindow.Left); 00081 Region.Top = ScreenInfo->Window.Top + 00082 ConvAreaInfo->CaInfo.rcViewCaWindow.Top + 00083 ConvAreaInfo->CaInfo.coordConView.Y; 00084 Region.Bottom = Region.Top + 00085 (ConvAreaInfo->CaInfo.rcViewCaWindow.Bottom - 00086 ConvAreaInfo->CaInfo.rcViewCaWindow.Top); 00087 ClippedRegion.Left = max(Region.Left, ScreenInfo->Window.Left); 00088 ClippedRegion.Top = max(Region.Top, ScreenInfo->Window.Top); 00089 ClippedRegion.Right = min(Region.Right, ScreenInfo->Window.Right); 00090 ClippedRegion.Bottom = min(Region.Bottom, ScreenInfo->Window.Bottom); 00091 if (ClippedRegion.Right < ClippedRegion.Left || 00092 ClippedRegion.Bottom < ClippedRegion.Top) { 00093 ; 00094 } 00095 else { 00096 Region = ClippedRegion; 00097 ClippedRegion.Left = max(Region.Left, CursorRegion.Left); 00098 ClippedRegion.Top = max(Region.Top, CursorRegion.Top); 00099 ClippedRegion.Right = min(Region.Right, CursorRegion.Right); 00100 ClippedRegion.Bottom = min(Region.Bottom, CursorRegion.Bottom); 00101 if (ClippedRegion.Right < ClippedRegion.Left || 00102 ClippedRegion.Bottom < ClippedRegion.Top) { 00103 ; 00104 } 00105 else { 00106 return; 00107 } 00108 } 00109 } 00110 ConvAreaInfo = ConvAreaInfo->ConvAreaNext; 00111 } 00112 } 00113 #endif // FE_SB 00114 00115 { 00116 ULONG CursorYSize; 00117 POLYPATBLT PolyData; 00118 #ifdef FE_SB 00119 SHORT RowIndex; 00120 PROW Row; 00121 COORD TargetPoint; 00122 int iTrailing = 0; 00123 int iDBCursor = 1; 00124 #endif 00125 00126 INVERT_CALL; 00127 CursorYSize = ScreenInfo->BufferInfo.TextInfo.CursorYSize; 00128 if (ScreenInfo->BufferInfo.TextInfo.DoubleCursor) { 00129 if (ScreenInfo->BufferInfo.TextInfo.CursorSize > 50) 00130 CursorYSize = CursorYSize >> 1; 00131 else 00132 CursorYSize = CursorYSize << 1; 00133 } 00134 #ifdef FE_SB 00135 if (CONSOLE_IS_DBCS_OUTPUTCP(ScreenInfo->Console)) 00136 { 00137 TargetPoint = ScreenInfo->BufferInfo.TextInfo.CursorPosition; 00138 RowIndex = (ScreenInfo->BufferInfo.TextInfo.FirstRow+TargetPoint.Y) % ScreenInfo->ScreenBufferSize.Y; 00139 Row = &ScreenInfo->BufferInfo.TextInfo.Rows[RowIndex]; 00140 ASSERT(Row); 00141 00142 if ((Row->CharRow.KAttrs[TargetPoint.X] & ATTR_TRAILING_BYTE) && 00143 ScreenInfo->BufferInfo.TextInfo.CursorDBEnable) { 00144 00145 iTrailing = 1; 00146 iDBCursor = 2; 00147 } else if ((Row->CharRow.KAttrs[TargetPoint.X] & ATTR_LEADING_BYTE) && 00148 ScreenInfo->BufferInfo.TextInfo.CursorDBEnable) { 00149 00150 iDBCursor = 2; 00151 } 00152 } 00153 00154 PolyData.x = (ScreenInfo->BufferInfo.TextInfo.CursorPosition.X - 00155 ScreenInfo->Window.Left - iTrailing) * SCR_FONTSIZE(ScreenInfo).X; 00156 PolyData.y = (ScreenInfo->BufferInfo.TextInfo.CursorPosition.Y - 00157 ScreenInfo->Window.Top) * SCR_FONTSIZE(ScreenInfo).Y + 00158 (CURSOR_Y_OFFSET_IN_PIXELS(SCR_FONTSIZE(ScreenInfo).Y,CursorYSize)); 00159 PolyData.cx = SCR_FONTSIZE(ScreenInfo).X * iDBCursor; 00160 PolyData.cy = CursorYSize; 00161 #else 00162 PolyData.x = (ScreenInfo->BufferInfo.TextInfo.CursorPosition.X-ScreenInfo->Window.Left)*SCR_FONTSIZE(ScreenInfo).X; 00163 PolyData.y = (ScreenInfo->BufferInfo.TextInfo.CursorPosition.Y-ScreenInfo->Window.Top)*SCR_FONTSIZE(ScreenInfo).Y+(CURSOR_Y_OFFSET_IN_PIXELS(SCR_FONTSIZE(ScreenInfo).Y,CursorYSize)); 00164 PolyData.cx = SCR_FONTSIZE(ScreenInfo).X; 00165 PolyData.cy = CursorYSize; 00166 #endif 00167 PolyData.BrClr.hbr = GetStockObject(LTGRAY_BRUSH); 00168 00169 PolyPatBlt(ScreenInfo->Console->hDC, PATINVERT, &PolyData, 1, PPB_BRUSH); 00170 00171 GdiFlush(); 00172 } 00173 } 00174 00175 VOID 00176 ConsoleShowCursor( 00177 IN PSCREEN_INFORMATION ScreenInfo 00178 ) 00179 00180 /*++ 00181 00182 Routine Description: 00183 00184 This routine makes the cursor visible both in the data structures 00185 and on the screen. 00186 00187 Arguments: 00188 00189 ScreenInfo - pointer to screen info structure. 00190 00191 Return Value: 00192 00193 none. 00194 00195 --*/ 00196 00197 { 00198 if (ScreenInfo->Flags & CONSOLE_TEXTMODE_BUFFER) { 00199 ASSERT (ScreenInfo->BufferInfo.TextInfo.UpdatingScreen>0); 00200 if (--ScreenInfo->BufferInfo.TextInfo.UpdatingScreen == 0) { 00201 ScreenInfo->BufferInfo.TextInfo.CursorOn = FALSE; 00202 } 00203 } 00204 } 00205 00206 VOID 00207 ConsoleHideCursor( 00208 IN PSCREEN_INFORMATION ScreenInfo 00209 ) 00210 00211 /*++ 00212 00213 Routine Description: 00214 00215 This routine makes the cursor invisible both in the data structures 00216 and on the screen. 00217 00218 Arguments: 00219 00220 ScreenInfo - pointer to screen info structure. 00221 00222 Return Value: 00223 00224 none. 00225 00226 --*/ 00227 00228 { 00229 if (ScreenInfo->Flags & CONSOLE_TEXTMODE_BUFFER) { 00230 if (++ScreenInfo->BufferInfo.TextInfo.UpdatingScreen == 1) { 00231 if (ScreenInfo->BufferInfo.TextInfo.CursorVisible && 00232 ScreenInfo->BufferInfo.TextInfo.CursorOn && 00233 ScreenInfo->Console->CurrentScreenBuffer == ScreenInfo && 00234 !(ScreenInfo->Console->Flags & CONSOLE_IS_ICONIC)) { 00235 InvertPixels(ScreenInfo); 00236 ScreenInfo->BufferInfo.TextInfo.CursorOn = FALSE; 00237 } 00238 } 00239 } 00240 } 00241 00242 NTSTATUS 00243 SetCursorInformation( 00244 IN PSCREEN_INFORMATION ScreenInfo, 00245 ULONG Size, 00246 BOOLEAN Visible 00247 ) 00248 00249 /*++ 00250 00251 Routine Description: 00252 00253 This routine sets the cursor size and visibility both in the data structures 00254 and on the screen. 00255 00256 Arguments: 00257 00258 ScreenInfo - pointer to screen info structure. 00259 00260 Size - cursor size 00261 00262 Visible - cursor visibility 00263 00264 Return Value: 00265 00266 Status 00267 00268 --*/ 00269 00270 { 00271 if (ScreenInfo->Flags & CONSOLE_TEXTMODE_BUFFER) { 00272 ConsoleHideCursor(ScreenInfo); 00273 ScreenInfo->BufferInfo.TextInfo.CursorSize = Size; 00274 ScreenInfo->BufferInfo.TextInfo.CursorVisible = Visible; 00275 ScreenInfo->BufferInfo.TextInfo.CursorYSize = (WORD)CURSOR_SIZE_IN_PIXELS(SCR_FONTSIZE(ScreenInfo).Y,ScreenInfo->BufferInfo.TextInfo.CursorSize); 00276 #ifdef i386 00277 if ((!(ScreenInfo->Console->Flags & CONSOLE_VDM_REGISTERED)) && 00278 ScreenInfo->Console->FullScreenFlags & CONSOLE_FULLSCREEN_HARDWARE) { 00279 SetCursorInformationHW(ScreenInfo,Size,Visible); 00280 } 00281 #endif 00282 ConsoleShowCursor(ScreenInfo); 00283 } 00284 return STATUS_SUCCESS; 00285 } 00286 00287 NTSTATUS 00288 SetCursorMode( 00289 IN PSCREEN_INFORMATION ScreenInfo, 00290 BOOLEAN DoubleCursor 00291 ) 00292 00293 /*++ 00294 00295 Routine Description: 00296 00297 This routine sets a flag saying whether the cursor should be displayed 00298 with it's default size or it should be modified to indicate the 00299 insert/overtype mode has changed. 00300 00301 Arguments: 00302 00303 ScreenInfo - pointer to screen info structure. 00304 00305 DoubleCursor - should we indicated non-normal mode 00306 00307 Return Value: 00308 00309 Status 00310 00311 --*/ 00312 00313 { 00314 if ((ScreenInfo->Flags & CONSOLE_TEXTMODE_BUFFER) && 00315 (ScreenInfo->BufferInfo.TextInfo.DoubleCursor != DoubleCursor)) { 00316 ConsoleHideCursor(ScreenInfo); 00317 ScreenInfo->BufferInfo.TextInfo.DoubleCursor = DoubleCursor; 00318 #ifdef i386 00319 if ((!(ScreenInfo->Console->Flags & CONSOLE_VDM_REGISTERED)) && 00320 ScreenInfo->Console->FullScreenFlags & CONSOLE_FULLSCREEN_HARDWARE) { 00321 SetCursorInformationHW(ScreenInfo, 00322 ScreenInfo->BufferInfo.TextInfo.CursorSize, 00323 ScreenInfo->BufferInfo.TextInfo.CursorVisible); 00324 } 00325 #endif 00326 ConsoleShowCursor(ScreenInfo); 00327 } 00328 return STATUS_SUCCESS; 00329 } 00330 00331 VOID 00332 CursorTimerRoutine( 00333 IN PSCREEN_INFORMATION ScreenInfo 00334 ) 00335 00336 /*++ 00337 00338 Routine Description: 00339 00340 This routine is called when the timer in the console with the focus 00341 goes off. It blinks the cursor. 00342 00343 Arguments: 00344 00345 ScreenInfo - pointer to screen info structure. 00346 00347 Return Value: 00348 00349 none. 00350 00351 --*/ 00352 00353 { 00354 if (!(ScreenInfo->Console->Flags & CONSOLE_HAS_FOCUS)) 00355 return; 00356 00357 if (ScreenInfo->Flags & CONSOLE_TEXTMODE_BUFFER) { 00358 00359 // 00360 // Update the cursor pos in USER so accessibility will work 00361 // 00362 00363 if (ScreenInfo->BufferInfo.TextInfo.CursorMoved) { 00364 00365 CONSOLE_CARET_INFO ConsoleCaretInfo; 00366 00367 ScreenInfo->BufferInfo.TextInfo.CursorMoved = FALSE; 00368 ConsoleCaretInfo.hwnd = ScreenInfo->Console->hWnd; 00369 ConsoleCaretInfo.rc.left = (ScreenInfo->BufferInfo.TextInfo.CursorPosition.X - ScreenInfo->Window.Left) * SCR_FONTSIZE(ScreenInfo).X; 00370 ConsoleCaretInfo.rc.top = (ScreenInfo->BufferInfo.TextInfo.CursorPosition.Y - ScreenInfo->Window.Top) * SCR_FONTSIZE(ScreenInfo).Y; 00371 ConsoleCaretInfo.rc.right = ConsoleCaretInfo.rc.left + SCR_FONTSIZE(ScreenInfo).X; 00372 ConsoleCaretInfo.rc.bottom = ConsoleCaretInfo.rc.top + SCR_FONTSIZE(ScreenInfo).Y; 00373 NtUserConsoleControl(ConsoleSetCaretInfo, 00374 &ConsoleCaretInfo, 00375 sizeof(ConsoleCaretInfo)); 00376 } 00377 00378 // if the DelayCursor flag has been set, wait one more tick before toggle. 00379 // This is used to guarantee the cursor is on for a finite period of time 00380 // after a move and off for a finite period of time after a WriteString 00381 00382 if (ScreenInfo->BufferInfo.TextInfo.DelayCursor) { 00383 ScreenInfo->BufferInfo.TextInfo.DelayCursor = FALSE; 00384 return; 00385 } 00386 00387 // don't blink the cursor for remote sessions 00388 if (NtCurrentPeb()->SessionId > 0 && 00389 ScreenInfo->BufferInfo.TextInfo.CursorOn) { 00390 00391 return; 00392 } 00393 00394 if (ScreenInfo->BufferInfo.TextInfo.CursorVisible && 00395 !ScreenInfo->BufferInfo.TextInfo.UpdatingScreen) { 00396 InvertPixels(ScreenInfo); 00397 ScreenInfo->BufferInfo.TextInfo.CursorOn = !ScreenInfo->BufferInfo.TextInfo.CursorOn; 00398 } 00399 } 00400 } 00401 00402 #ifdef i386 00403 NTSTATUS 00404 SetCursorPositionHW( 00405 IN OUT PSCREEN_INFORMATION ScreenInfo, 00406 IN COORD Position 00407 ) 00408 00409 /*++ 00410 00411 Routine Description: 00412 00413 This routine moves the cursor. 00414 00415 Arguments: 00416 00417 ScreenInfo - Pointer to screen buffer information. 00418 00419 Position - Contains the new position of the cursor in screen buffer 00420 coordinates. 00421 00422 Return Value: 00423 00424 none. 00425 00426 --*/ 00427 00428 { 00429 #if defined(FE_SB) 00430 FSVIDEO_CURSOR_POSITION CursorPosition; 00431 SHORT RowIndex; 00432 PROW Row; 00433 COORD TargetPoint; 00434 00435 if (ScreenInfo->ConvScreenInfo) 00436 return STATUS_SUCCESS; 00437 00438 TargetPoint.X = Position.X; 00439 TargetPoint.Y = Position.Y; 00440 RowIndex = (ScreenInfo->BufferInfo.TextInfo.FirstRow+TargetPoint.Y) % ScreenInfo->ScreenBufferSize.Y; 00441 Row = &ScreenInfo->BufferInfo.TextInfo.Rows[RowIndex]; 00442 00443 if (!CONSOLE_IS_DBCS_OUTPUTCP(ScreenInfo->Console)) 00444 CursorPosition.dwType = CHAR_TYPE_SBCS; 00445 else if (Row->CharRow.KAttrs[TargetPoint.X] & ATTR_TRAILING_BYTE) 00446 CursorPosition.dwType = CHAR_TYPE_TRAILING; 00447 else if (Row->CharRow.KAttrs[TargetPoint.X] & ATTR_LEADING_BYTE) 00448 CursorPosition.dwType = CHAR_TYPE_LEADING; 00449 else 00450 CursorPosition.dwType = CHAR_TYPE_SBCS; 00451 00452 // set cursor position 00453 00454 CursorPosition.Coord.Column = Position.X - ScreenInfo->Window.Left; 00455 CursorPosition.Coord.Row = Position.Y - ScreenInfo->Window.Top; 00456 #else 00457 VIDEO_CURSOR_POSITION CursorPosition; 00458 00459 // set cursor position 00460 00461 CursorPosition.Column = Position.X - ScreenInfo->Window.Left; 00462 CursorPosition.Row = Position.Y - ScreenInfo->Window.Top; 00463 #endif 00464 00465 return GdiFullscreenControl(FullscreenControlSetCursorPosition, 00466 (PVOID)&CursorPosition, 00467 sizeof(CursorPosition), 00468 NULL, 00469 0); 00470 } 00471 #endif 00472 00473 NTSTATUS 00474 SetCursorPosition( 00475 IN OUT PSCREEN_INFORMATION ScreenInfo, 00476 IN COORD Position, 00477 IN BOOL TurnOn 00478 ) 00479 00480 /*++ 00481 00482 Routine Description: 00483 00484 This routine sets the cursor position in the data structures and on 00485 the screen. 00486 00487 Arguments: 00488 00489 ScreenInfo - pointer to screen info structure. 00490 00491 Position - new position of cursor 00492 00493 TurnOn - true if cursor should be left on, false if should be left off 00494 00495 Return Value: 00496 00497 Status 00498 00499 --*/ 00500 00501 { 00502 // 00503 // don't let cursorposition be set beyond edge of screen buffer 00504 // 00505 00506 if (Position.X >= ScreenInfo->ScreenBufferSize.X || 00507 Position.Y >= ScreenInfo->ScreenBufferSize.Y) { 00508 return STATUS_INVALID_PARAMETER; 00509 } 00510 ConsoleHideCursor(ScreenInfo); 00511 ScreenInfo->BufferInfo.TextInfo.CursorPosition = Position; 00512 #ifdef i386 00513 if ((!(ScreenInfo->Console->Flags & CONSOLE_VDM_REGISTERED)) && 00514 ScreenInfo->Console->FullScreenFlags & CONSOLE_FULLSCREEN_HARDWARE) { 00515 SetCursorPositionHW(ScreenInfo,Position); 00516 } 00517 #endif 00518 ConsoleShowCursor(ScreenInfo); 00519 00520 // if we have the focus, adjust the cursor state 00521 00522 if (ScreenInfo->Console->Flags & CONSOLE_HAS_FOCUS) { 00523 00524 if (TurnOn) { 00525 ScreenInfo->BufferInfo.TextInfo.DelayCursor = FALSE; 00526 CursorTimerRoutine(ScreenInfo); 00527 } else { 00528 ScreenInfo->BufferInfo.TextInfo.DelayCursor = TRUE; 00529 } 00530 ScreenInfo->BufferInfo.TextInfo.CursorMoved = TRUE; 00531 } 00532 00533 return STATUS_SUCCESS; 00534 } 00535 00536 #ifdef i386 00537 NTSTATUS 00538 SetCursorInformationHW( 00539 PSCREEN_INFORMATION ScreenInfo, 00540 ULONG Size, 00541 BOOLEAN Visible 00542 ) 00543 { 00544 VIDEO_CURSOR_ATTRIBUTES CursorAttr; 00545 ULONG FontSizeY; 00546 00547 if (ScreenInfo->BufferInfo.TextInfo.DoubleCursor) { 00548 if (Size > 50) 00549 Size = Size >> 1; 00550 else 00551 Size = Size << 1; 00552 } 00553 ASSERT (Size <= 100 && Size > 0); 00554 FontSizeY = CONSOLE_WINDOW_SIZE_Y(ScreenInfo) > 25 ? 8 : 16; 00555 CursorAttr.Height = (USHORT)CURSOR_PERCENTAGE_TO_TOP_SCAN_LINE(FontSizeY,Size); 00556 CursorAttr.Width = 31; 00557 CursorAttr.Enable = Visible; 00558 00559 return GdiFullscreenControl(FullscreenControlSetCursorAttributes, 00560 (PVOID)&CursorAttr, 00561 sizeof(CursorAttr), 00562 NULL, 00563 0); 00564 00565 } 00566 00567 00568 #endif

Generated on Sat May 15 19:39:38 2004 for test by doxygen 1.3.7