test: clipbrd.c Source File

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

# clipbrd.c

Go to the documentation of this file.

    00001 /*++
    00002
    00003 Copyright (c) 1985 - 1999, Microsoft Corporation
    00004
    00005 Module Name:
    00006
    00007     clipbrd.c
    00008
    00009 Abstract:
    00010
    00011         This file implements the clipboard functions.
    00012
    00013 Author:
    00014
    00015     Therese Stowell (thereses) Jan-24-1992
    00016
    00017 --*/
    00018
    00019 #include "precomp.h"
    00020 #pragma hdrstop
    00021
    00022 /*++
    00023
    00024     Here's the pseudocode for various clipboard operations
    00025
    00026     init keyboard select (mark)
    00027     ---------------------------
    00028     if (already selecting)
    00029         cancel selection
    00030     init flags
    00031     hidecursor
    00032     createcursor
    00033     init select rect
    00034     set win text
    00035
    00036     convert to mouse select (select)
    00037     --------------------------------
    00038     set flags
    00039     destroy cursor
    00040     showcursor
    00041     invert old select rect
    00042     init select rect
    00043     invert select rect
    00044     set win text
    00045
    00046     re-init mouse select
    00047     --------------------
    00048     invert old select rect
    00049     init select rect
    00050     invert select rect
    00051
    00052     cancel mouse select
    00053     -------------------
    00054     set flags
    00055     reset win text
    00056     invert old select rect
    00057
    00058     cancel key select
    00059     -----------------
    00060     set flags
    00061     reset win text
    00062     destroy cursor
    00063     showcursor
    00064     invert old select rect
    00065
    00066 --*/
    00067
    00068
    00069 BOOL
    00070 MyInvert(
    00071     IN PCONSOLE_INFORMATION Console,
    00072     IN PSMALL_RECT SmallRect
    00073     )
    00074
    00075 /*++
    00076
    00077     invert a rect
    00078
    00079 --*/
    00080
    00081 {
    00082     RECT Rect;
    00083     PSCREEN_INFORMATION ScreenInfo;
    00084 #ifdef FE_SB
    00085     SMALL_RECT SmallRect2;
    00086     COORD TargetPoint;
    00087     SHORT StringLength;
    00088 #endif  // FE_SB
    00089
    00090     ScreenInfo = Console->CurrentScreenBuffer;
    00091 #ifdef FE_SB
    00092     if (CONSOLE_IS_DBCS_OUTPUTCP(Console) &&
    00093             ScreenInfo->Flags & CONSOLE_TEXTMODE_BUFFER) {
    00094         for (SmallRect2.Top=SmallRect->Top; SmallRect2.Top <= SmallRect->Bottom;SmallRect2.Top++) {
    00095             SmallRect2.Bottom = SmallRect2.Top;
    00096             SmallRect2.Left = SmallRect->Left;
    00097             SmallRect2.Right = SmallRect->Right;
    00098
    00099             TargetPoint.X = SmallRect2.Left;
    00100             TargetPoint.Y = SmallRect2.Top;
    00101             StringLength = SmallRect2.Right - SmallRect2.Left + 1;
    00102             BisectClipbrd(StringLength,TargetPoint,ScreenInfo,&SmallRect2);
    00103
    00104             if (SmallRect2.Left <= SmallRect2.Right) {
    00105                 Rect.left = SmallRect2.Left-ScreenInfo->Window.Left;
    00106                 Rect.top = SmallRect2.Top-ScreenInfo->Window.Top;
    00107                 Rect.right = SmallRect2.Right+1-ScreenInfo->Window.Left;
    00108                 Rect.bottom = SmallRect2.Bottom+1-ScreenInfo->Window.Top;
    00109                 Rect.left *= SCR_FONTSIZE(ScreenInfo).X;
    00110                 Rect.top *= SCR_FONTSIZE(ScreenInfo).Y;
    00111                 Rect.right *= SCR_FONTSIZE(ScreenInfo).X;
    00112                 Rect.bottom *= SCR_FONTSIZE(ScreenInfo).Y;
    00113                 PatBlt(Console->hDC,
    00114                        Rect.left,
    00115                        Rect.top,
    00116                        Rect.right  - Rect.left,
    00117                        Rect.bottom - Rect.top,
    00118                        DSTINVERT
    00119                       );
    00120             }
    00121         }
    00122     } else
    00123 #endif  // FE_SB
    00124     {
    00125         Rect.left = SmallRect->Left-ScreenInfo->Window.Left;
    00126         Rect.top = SmallRect->Top-ScreenInfo->Window.Top;
    00127         Rect.right = SmallRect->Right+1-ScreenInfo->Window.Left;
    00128         Rect.bottom = SmallRect->Bottom+1-ScreenInfo->Window.Top;
    00129 #ifdef FE_SB
    00130         if (!CONSOLE_IS_DBCS_OUTPUTCP(Console) &&
    00131                 ScreenInfo->Flags & CONSOLE_TEXTMODE_BUFFER)
    00132 #else
    00133         if (ScreenInfo->Flags & CONSOLE_TEXTMODE_BUFFER)
    00134 #endif
    00135         {
    00136             Rect.left *= SCR_FONTSIZE(ScreenInfo).X;
    00137             Rect.top *= SCR_FONTSIZE(ScreenInfo).Y;
    00138             Rect.right *= SCR_FONTSIZE(ScreenInfo).X;
    00139             Rect.bottom *= SCR_FONTSIZE(ScreenInfo).Y;
    00140         }
    00141
    00142         PatBlt(Console->hDC,
    00143                   Rect.left,
    00144                   Rect.top,
    00145                   Rect.right  - Rect.left,
    00146                   Rect.bottom - Rect.top,
    00147                   DSTINVERT
    00148                  );
    00149     }
    00150
    00151     return(TRUE);
    00152 }
    00153
    00154 VOID
    00155 InvertSelection(
    00156     IN PCONSOLE_INFORMATION Console,
    00157     BOOL Inverting
    00158     )
    00159 {
    00160     BOOL Inverted;
    00161     if (Console->Flags & CONSOLE_SELECTING &&
    00162         Console->SelectionFlags & CONSOLE_SELECTION_NOT_EMPTY) {
    00163         Inverted = (Console->SelectionFlags & CONSOLE_SELECTION_INVERTED) ? TRUE : FALSE;
    00164         if (Inverting == Inverted) {
    00165             return;
    00166         }
    00167         if (Inverting) {
    00168             Console->SelectionFlags |= CONSOLE_SELECTION_INVERTED;
    00169         } else {
    00170             Console->SelectionFlags &= ~CONSOLE_SELECTION_INVERTED;
    00171         }
    00172         MyInvert(Console,&Console->SelectionRect);
    00173     }
    00174
    00175 }
    00176
    00177 VOID
    00178 ExtendSelection(
    00179     IN PCONSOLE_INFORMATION Console,
    00180     IN COORD CursorPosition
    00181     )
    00182
    00183 /*++
    00184
    00185     This routine extends a selection region.
    00186
    00187 --*/
    00188
    00189 {
    00190     SMALL_RECT OldSelectionRect;
    00191     HRGN OldRegion,NewRegion,CombineRegion;
    00192     COORD FontSize;
    00193     PSCREEN_INFORMATION ScreenInfo = Console->CurrentScreenBuffer;
    00194
    00195     if (CursorPosition.X < 0) {
    00196         CursorPosition.X = 0;
    00197     } else if (CursorPosition.X >= ScreenInfo->ScreenBufferSize.X) {
    00198         CursorPosition.X = ScreenInfo->ScreenBufferSize.X-1;
    00199     }
    00200
    00201     if (CursorPosition.Y < 0) {
    00202         CursorPosition.Y = 0;
    00203     } else if (CursorPosition.Y >= ScreenInfo->ScreenBufferSize.Y) {
    00204         CursorPosition.Y = ScreenInfo->ScreenBufferSize.Y-1;
    00205     }
    00206
    00207     if (!(Console->SelectionFlags & CONSOLE_SELECTION_NOT_EMPTY)) {
    00208
    00209         if (ScreenInfo->Flags & CONSOLE_TEXTMODE_BUFFER) {
    00210             // scroll if necessary to make cursor visible.
    00211             MakeCursorVisible(ScreenInfo, CursorPosition);
    00212             ASSERT(!(Console->SelectionFlags & CONSOLE_MOUSE_SELECTION));
    00213
    00214             //
    00215             // if the selection rect hasn't actually been started,
    00216             // the selection cursor is still blinking.  turn it off.
    00217             //
    00218
    00219             ConsoleHideCursor(ScreenInfo);
    00220         }
    00221         Console->SelectionFlags |= CONSOLE_SELECTION_NOT_EMPTY;
    00222         Console->SelectionRect.Left =Console->SelectionRect.Right = Console->SelectionAnchor.X;
    00223         Console->SelectionRect.Top = Console->SelectionRect.Bottom = Console->SelectionAnchor.Y;
    00224
    00225         // invert the cursor corner
    00226
    00227 #ifdef FE_SB
    00228         if (!CONSOLE_IS_DBCS_OUTPUTCP(Console) &&
    00229                 ScreenInfo->Flags & CONSOLE_TEXTMODE_BUFFER)
    00230 #else
    00231         if (ScreenInfo->Flags & CONSOLE_TEXTMODE_BUFFER)
    00232 #endif
    00233         {
    00234             MyInvert(Console,&Console->SelectionRect);
    00235         }
    00236     } else {
    00237
    00238         if (ScreenInfo->Flags & CONSOLE_TEXTMODE_BUFFER) {
    00239             // scroll if necessary to make cursor visible.
    00240             MakeCursorVisible(ScreenInfo,CursorPosition);
    00241         }
    00242 #ifdef FE_SB
    00243         //
    00244         // uninvert old selection
    00245         //
    00246         if (CONSOLE_IS_DBCS_OUTPUTCP(Console)) {
    00247             MyInvert(Console, &Console->SelectionRect);
    00248         }
    00249 #endif  // FE_SB
    00250     }
    00251
    00252     //
    00253     // update selection rect
    00254     //
    00255
    00256     OldSelectionRect = Console->SelectionRect;
    00257     if (CursorPosition.X <= Console->SelectionAnchor.X) {
    00258         Console->SelectionRect.Left = CursorPosition.X;
    00259         Console->SelectionRect.Right = Console->SelectionAnchor.X;
    00260     } else if (CursorPosition.X > Console->SelectionAnchor.X) {
    00261         Console->SelectionRect.Right = CursorPosition.X;
    00262         Console->SelectionRect.Left = Console->SelectionAnchor.X;
    00263     }
    00264     if (CursorPosition.Y <= Console->SelectionAnchor.Y) {
    00265         Console->SelectionRect.Top = CursorPosition.Y;
    00266         Console->SelectionRect.Bottom = Console->SelectionAnchor.Y;
    00267     } else if (CursorPosition.Y > Console->SelectionAnchor.Y) {
    00268         Console->SelectionRect.Bottom = CursorPosition.Y;
    00269         Console->SelectionRect.Top = Console->SelectionAnchor.Y;
    00270     }
    00271
    00272     //
    00273     // change inverted selection
    00274     //
    00275 #ifdef FE_SB
    00276     if (CONSOLE_IS_DBCS_OUTPUTCP(Console)) {
    00277         MyInvert(Console, &Console->SelectionRect);
    00278     } else
    00279 #endif
    00280     {
    00281         if (ScreenInfo->Flags & CONSOLE_TEXTMODE_BUFFER) {
    00282             FontSize = CON_FONTSIZE(Console);
    00283         } else {
    00284             FontSize.X = 1;
    00285             FontSize.Y = 1;
    00286         }
    00287         CombineRegion = CreateRectRgn(0,0,0,0);
    00288         OldRegion = CreateRectRgn((OldSelectionRect.Left-ScreenInfo->Window.Left)*FontSize.X,
    00289                                   (OldSelectionRect.Top-ScreenInfo->Window.Top)*FontSize.Y,
    00290                                   (OldSelectionRect.Right-ScreenInfo->Window.Left+1)*FontSize.X,
    00291                                   (OldSelectionRect.Bottom-ScreenInfo->Window.Top+1)*FontSize.Y
    00292                                  );
    00293         NewRegion = CreateRectRgn((Console->SelectionRect.Left-ScreenInfo->Window.Left)*FontSize.X,
    00294                                   (Console->SelectionRect.Top-ScreenInfo->Window.Top)*FontSize.Y,
    00295                                   (Console->SelectionRect.Right-ScreenInfo->Window.Left+1)*FontSize.X,
    00296                                   (Console->SelectionRect.Bottom-ScreenInfo->Window.Top+1)*FontSize.Y
    00297                                  );
    00298         CombineRgn(CombineRegion,OldRegion,NewRegion,RGN_XOR);
    00299
    00300         InvertRgn(Console->hDC,CombineRegion);
    00301         DeleteObject(OldRegion);
    00302         DeleteObject(NewRegion);
    00303         DeleteObject(CombineRegion);
    00304     }
    00305 }
    00306
    00307 VOID
    00308 CancelMouseSelection(
    00309     IN PCONSOLE_INFORMATION Console
    00310     )
    00311
    00312 /*++
    00313
    00314     This routine terminates a mouse selection.
    00315
    00316 --*/
    00317
    00318 {
    00319     //
    00320     // turn off selection flag
    00321     //
    00322
    00323     Console->Flags &= ~CONSOLE_SELECTING;
    00324
    00325     SetWinText(Console,msgSelectMode,FALSE);
    00326
    00327     //
    00328     // invert old select rect.  if we're selecting by mouse, we
    00329     // always have a selection rect.
    00330     //
    00331
    00332     MyInvert(Console,&Console->SelectionRect);
    00333
    00334     ReleaseCapture();
    00335 }
    00336
    00337 VOID
    00338 CancelKeySelection(
    00339     IN PCONSOLE_INFORMATION Console,
    00340     IN BOOL JustCursor
    00341     )
    00342
    00343 /*++
    00344
    00345     This routine terminates a key selection.
    00346
    00347 --*/
    00348
    00349 {
    00350     PSCREEN_INFORMATION ScreenInfo;
    00351
    00352     if (!JustCursor) {
    00353
    00354         //
    00355         // turn off selection flag
    00356         //
    00357
    00358         Console->Flags &= ~CONSOLE_SELECTING;
    00359
    00360         SetWinText(Console,msgMarkMode,FALSE);
    00361     }
    00362
    00363     //
    00364     // invert old select rect, if we have one.
    00365     //
    00366
    00367     ScreenInfo = Console->CurrentScreenBuffer;
    00368     if (Console->SelectionFlags & CONSOLE_SELECTION_NOT_EMPTY) {
    00369         MyInvert(Console,&Console->SelectionRect);
    00370     } else {
    00371         ConsoleHideCursor(ScreenInfo);
    00372     }
    00373
    00374     // restore text cursor
    00375
    00376     if (ScreenInfo->Flags & CONSOLE_TEXTMODE_BUFFER) {
    00377         SetCursorInformation(ScreenInfo,
    00378                              Console->TextCursorSize,
    00379                              Console->TextCursorVisible
    00380                             );
    00381         SetCursorPosition(ScreenInfo,
    00382                           Console->TextCursorPosition,
    00383                           TRUE
    00384                          );
    00385     }
    00386     ConsoleShowCursor(ScreenInfo);
    00387 }
    00388
    00389 VOID
    00390 ConvertToMouseSelect(
    00391     IN PCONSOLE_INFORMATION Console,
    00392     IN COORD MousePosition
    00393     )
    00394
    00395 /*++
    00396
    00397     This routine converts to a mouse selection from a key selection.
    00398
    00399 --*/
    00400
    00401 {
    00402     Console->SelectionFlags |= CONSOLE_MOUSE_SELECTION | CONSOLE_MOUSE_DOWN;
    00403
    00404     //
    00405     // undo key selection
    00406     //
    00407
    00408     CancelKeySelection(Console,TRUE);
    00409
    00410     Console->SelectionFlags |= CONSOLE_SELECTION_NOT_EMPTY;
    00411
    00412     //
    00413     // invert new selection
    00414     //
    00415
    00416     Console->SelectionAnchor = MousePosition;
    00417     Console->SelectionRect.Left =Console->SelectionRect.Right = Console->SelectionAnchor.X;
    00418     Console->SelectionRect.Top = Console->SelectionRect.Bottom = Console->SelectionAnchor.Y;
    00419     MyInvert(Console,&Console->SelectionRect);
    00420
    00421     //
    00422     // update title bar
    00423     //
    00424
    00425     SetWinText(Console,msgMarkMode,FALSE);
    00426     SetWinText(Console,msgSelectMode,TRUE);
    00427
    00428     //
    00429     // capture mouse movement
    00430     //
    00431
    00432     SetCapture(Console->hWnd);
    00433 }
    00434
    00435
    00436 VOID
    00437 ClearSelection(
    00438     IN PCONSOLE_INFORMATION Console
    00439     )
    00440 {
    00441     if (Console->Flags & CONSOLE_SELECTING) {
    00442         if (Console->SelectionFlags & CONSOLE_MOUSE_SELECTION) {
    00443             CancelMouseSelection(Console);
    00444         } else {
    00445             CancelKeySelection(Console,FALSE);
    00446         }
    00447         UnblockWriteConsole(Console, CONSOLE_SELECTING);
    00448     }
    00449 }
    00450
    00451 VOID
    00452 StoreSelection(
    00453     IN PCONSOLE_INFORMATION Console
    00454     )
    00455
    00456 /*++
    00457
    00458  StoreSelection - Store selection (if present) into the Clipboard
    00459
    00460 --*/
    00461
    00462 {
    00463     PCHAR_INFO Selection,CurCharInfo;
    00464     COORD SourcePoint;
    00465     COORD TargetSize;
    00466     SMALL_RECT TargetRect;
    00467     PWCHAR CurChar,CharBuf;
    00468     HANDLE ClipboardDataHandle;
    00469     SHORT i,j;
    00470     BOOL Success;
    00471     PSCREEN_INFORMATION ScreenInfo;
    00472     BOOL bFalseUnicode;
    00473     BOOL bMungeData;
    00474 #if defined(FE_SB)
    00475     COORD TargetSize2;
    00476     PWCHAR TmpClipboardData;
    00477     SMALL_RECT SmallRect2;
    00478     COORD TargetPoint;
    00479     SHORT StringLength;
    00480     WCHAR wchCARRIAGERETURN;
    00481     WCHAR wchLINEFEED;
    00482     int iExtra = 0;
    00483     int iFeReserve = 1;
    00484 #endif
    00485
    00486     //
    00487     // See if there is a selection to get
    00488     //
    00489
    00490     if (!(Console->SelectionFlags & CONSOLE_SELECTION_NOT_EMPTY)) {
    00491         return;
    00492     }
    00493
    00494     //
    00495     // read selection rectangle.  clip it first.
    00496     //
    00497
    00498     ScreenInfo = Console->CurrentScreenBuffer;
    00499     if (Console->SelectionRect.Left < 0) {
    00500         Console->SelectionRect.Left = 0;
    00501     }
    00502     if (Console->SelectionRect.Top < 0) {
    00503         Console->SelectionRect.Top = 0;
    00504     }
    00505     if (Console->SelectionRect.Right >= ScreenInfo->ScreenBufferSize.X) {
    00506         Console->SelectionRect.Right = (SHORT)(ScreenInfo->ScreenBufferSize.X-1);
    00507     }
    00508     if (Console->SelectionRect.Bottom >= ScreenInfo->ScreenBufferSize.Y) {
    00509         Console->SelectionRect.Bottom = (SHORT)(ScreenInfo->ScreenBufferSize.Y-1);
    00510     }
    00511
    00512     TargetSize.X = WINDOW_SIZE_X(&Console->SelectionRect);
    00513     TargetSize.Y = WINDOW_SIZE_Y(&Console->SelectionRect);
    00514     if (ScreenInfo->Flags & CONSOLE_TEXTMODE_BUFFER) {
    00515 #if defined(FE_SB)
    00516
    00517         if (CONSOLE_IS_DBCS_CP(Console)) {
    00518             iExtra = 4 ;     // 4 is for DBCS lead or tail extra
    00519             iFeReserve = 2 ; // FE does this for safety
    00520             TmpClipboardData = (PWCHAR)ConsoleHeapAlloc(MAKE_TAG( TMP_DBCS_TAG ),(sizeof(WCHAR) * TargetSize.Y * (TargetSize.X + iExtra) + sizeof(WCHAR)));
    00521             if (TmpClipboardData == NULL) {
    00522                 return;
    00523             }
    00524         } else {
    00525             TmpClipboardData = NULL;
    00526         }
    00527
    00528         Selection = (PCHAR_INFO)ConsoleHeapAlloc(MAKE_TAG( TMP_TAG ),sizeof(CHAR_INFO) * (TargetSize.X + iExtra) * TargetSize.Y * iFeReserve);
    00529         if (Selection == NULL)
    00530         {
    00531             if (TmpClipboardData)
    00532                 ConsoleHeapFree(TmpClipboardData);
    00533             return;
    00534         }
    00535 #else
    00536         Selection = (PCHAR_INFO)ConsoleHeapAlloc(MAKE_TAG( TMP_TAG ),sizeof(CHAR_INFO) * TargetSize.X * TargetSize.Y);
    00537         if (Selection == NULL)
    00538             return;
    00539 #endif
    00540
    00541 #if defined(FE_SB)
    00542     if (!CONSOLE_IS_DBCS_CP(Console)) {
    00543 #endif
    00544
    00545 #ifdef i386
    00546         if ((Console->FullScreenFlags & CONSOLE_FULLSCREEN) &&
    00547             (Console->Flags & CONSOLE_VDM_REGISTERED)) {
    00548             ReadRegionFromScreenHW(ScreenInfo,
    00549                                    &Console->SelectionRect,
    00550                                    Selection);
    00551             CurCharInfo = Selection;
    00552             for (i=0; i<TargetSize.Y; i++) {
    00553                 for (j=0; j<TargetSize.X; j++,CurCharInfo++) {
    00554                     CurCharInfo->Char.UnicodeChar = SB_CharToWcharGlyph(Console->OutputCP, CurCharInfo->Char.AsciiChar);
    00555                 }
    00556             }
    00557         } else {
    00558 #endif
    00559             SourcePoint.X = Console->SelectionRect.Left;
    00560             SourcePoint.Y = Console->SelectionRect.Top;
    00561             TargetRect.Left = TargetRect.Top = 0;
    00562             TargetRect.Right = (SHORT)(TargetSize.X-1);
    00563             TargetRect.Bottom = (SHORT)(TargetSize.Y-1);
    00564             ReadRectFromScreenBuffer(ScreenInfo,
    00565                                      SourcePoint,
    00566                                      Selection,
    00567                                      TargetSize,
    00568                                      &TargetRect);
    00569 #ifdef i386
    00570         }
    00571 #endif
    00572
    00573         // extra 2 per line is for CRLF, extra 1 is for null
    00574         ClipboardDataHandle = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE,
    00575                 (TargetSize.Y * (TargetSize.X + 2) + 1) * sizeof(WCHAR));
    00576         if (ClipboardDataHandle == NULL) {
    00577             ConsoleHeapFree(Selection);
    00578             return;
    00579         }
    00580 #if defined(FE_SB)
    00581     }
    00582 #endif
    00583
    00584         //
    00585         // convert to clipboard form
    00586         //
    00587
    00588 #if defined(FE_SB)
    00589         if (CONSOLE_IS_DBCS_CP(Console)) {
    00590             if ((ScreenInfo->Flags & CONSOLE_OEMFONT_DISPLAY) &&
    00591                     !(Console->FullScreenFlags & CONSOLE_FULLSCREEN)) {
    00592                 /*
    00593                  * False Unicode is obtained, so we will have to convert it to
    00594                  * Real Unicode, in which case we can't put CR or LF in now, since
    00595                  * they will be converted into 0x266A and 0x25d9.  Temporarily
    00596                  * mark the CR/LF positions with 0x0000 instead.
    00597                  */
    00598                 wchCARRIAGERETURN = 0x0000;
    00599                 wchLINEFEED = 0x0000;
    00600             } else {
    00601                 wchCARRIAGERETURN = UNICODE_CARRIAGERETURN;
    00602                 wchLINEFEED = UNICODE_LINEFEED;
    00603             }
    00604
    00605             CurChar = TmpClipboardData;
    00606             bMungeData = (GetKeyState(VK_SHIFT) & KEY_PRESSED) == 0;
    00607             for (i=0;i<TargetSize.Y;i++) {
    00608                 PWCHAR pwchLineStart = CurChar;
    00609
    00610                 SourcePoint.X = Console->SelectionRect.Left;
    00611                 SourcePoint.Y = Console->SelectionRect.Top + i;
    00612                 TargetSize2.X = TargetSize.X;
    00613                 TargetSize2.Y = 1;
    00614
    00615                 SmallRect2.Left = SourcePoint.X;
    00616                 SmallRect2.Top = SourcePoint.Y;
    00617                 SmallRect2.Right = SourcePoint.X + TargetSize2.X - 1;
    00618                 SmallRect2.Bottom = SourcePoint.Y;
    00619                 TargetPoint = SourcePoint;
    00620                 StringLength = TargetSize2.X;
    00621                 BisectClipbrd(StringLength,TargetPoint,ScreenInfo,&SmallRect2);
    00622
    00623                 SourcePoint.X = SmallRect2.Left;
    00624                 SourcePoint.Y = SmallRect2.Top;
    00625                 TargetSize2.X = SmallRect2.Right - SmallRect2.Left + 1;
    00626                 TargetSize2.Y = 1;
    00627                 TargetRect.Left = TargetRect.Top = TargetRect.Bottom = 0;
    00628                 TargetRect.Right = (SHORT)(TargetSize2.X-1);
    00629
    00630                 ReadRectFromScreenBuffer(ScreenInfo,
    00631                                          SourcePoint,
    00632                                          Selection,
    00633                                          TargetSize2,
    00634                                          &TargetRect);
    00635
    00636                 CurCharInfo = Selection;
    00637                 for (j=0;j<TargetSize2.X;j++,CurCharInfo++) {
    00638                     if (!(CurCharInfo->Attributes & COMMON_LVB_TRAILING_BYTE))
    00639                         *CurChar++ = CurCharInfo->Char.UnicodeChar;
    00640                 }
    00641                 // trim trailing spaces
    00642                 if (bMungeData) {
    00643                     CurChar--;
    00644                     while ((CurChar >= pwchLineStart) && (*CurChar == UNICODE_SPACE))
    00645                         CurChar--;
    00646                     CurChar++;
    00647                     *CurChar++ = wchCARRIAGERETURN;
    00648                     *CurChar++ = wchLINEFEED;
    00649                 }
    00650             }
    00651         }
    00652         else {
    00653 #endif
    00654         CurCharInfo = Selection;
    00655         CurChar = CharBuf = GlobalLock(ClipboardDataHandle);
    00656         bFalseUnicode = ((ScreenInfo->Flags & CONSOLE_OEMFONT_DISPLAY) &&
    00657                 !(Console->FullScreenFlags & CONSOLE_FULLSCREEN));
    00658         bMungeData = (GetKeyState(VK_SHIFT) & KEY_PRESSED) == 0;
    00659         for (i=0;i<TargetSize.Y;i++) {
    00660             PWCHAR pwchLineStart = CurChar;
    00661
    00662             for (j=0;j<TargetSize.X;j++,CurCharInfo++,CurChar++) {
    00663                 *CurChar = CurCharInfo->Char.UnicodeChar;
    00664                 if (*CurChar == 0) {
    00665                     *CurChar = UNICODE_SPACE;
    00666                 }
    00667             }
    00668             // trim trailing spaces
    00669             if (bMungeData) {
    00670                 CurChar--;
    00671                 while ((CurChar >= pwchLineStart) && (*CurChar == UNICODE_SPACE))
    00672                     CurChar--;
    00673                 CurChar++;
    00674             }
    00675
    00676             if (bFalseUnicode) {
    00677                 FalseUnicodeToRealUnicode(pwchLineStart,
    00678                         (ULONG)(CurChar - pwchLineStart), Console->OutputCP);
    00679             }
    00680             if (bMungeData) {
    00681                 *CurChar++ = UNICODE_CARRIAGERETURN;
    00682                 *CurChar++ = UNICODE_LINEFEED;
    00683             }
    00684         }
    00685 #if defined(FE_SB)
    00686         }
    00687 #endif
    00688         if (bMungeData) {
    00689             if (TargetSize.Y)
    00690                 CurChar -= 2;   // don't put CRLF on last line
    00691         }
    00692         *CurChar = '\0';    // null terminate
    00693
    00694 #if defined(FE_SB)
    00695         if (CONSOLE_IS_DBCS_CP(Console)) {
    00696             // extra 4 is for CRLF and DBCS Reserved, extra 1 is for null
    00697             ClipboardDataHandle = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE,
    00698                     (sizeof(WCHAR) * TargetSize.Y * (TargetSize.X+(4*sizeof(WCHAR)))) +
    00699                                                         (1*sizeof(WCHAR)));
    00700             if (ClipboardDataHandle == NULL) {
    00701                 ConsoleHeapFree(Selection);
    00702                 ConsoleHeapFree(TmpClipboardData);
    00703                 return;
    00704             }
    00705
    00706             CharBuf = GlobalLock(ClipboardDataHandle);
    00707             RtlCopyMemory(CharBuf,TmpClipboardData,ConsoleHeapSize(TmpClipboardData));
    00708             CurChar = CharBuf + (CurChar - TmpClipboardData);
    00709
    00710             if (wchCARRIAGERETURN == 0x0000) {
    00711                 /*
    00712                  * We have False Unicode, so we temporarily represented CRLFs with
    00713                  * 0x0000s to avoid undesirable conversions (above).
    00714                  * Convert to Real Unicode and restore real CRLFs.
    00715                  */
    00716                 PWCHAR pwch;
    00717                 FalseUnicodeToRealUnicode(CharBuf,
    00718                                     (ULONG)(CurChar - CharBuf),
    00719                                     Console->OutputCP
    00720                                    );
    00721                 for (pwch = CharBuf; pwch < CurChar; pwch++) {
    00722                     if ((*pwch == 0x0000) && (pwch[1] == 0x0000)) {
    00723                         *pwch++ = UNICODE_CARRIAGERETURN;
    00724                         *pwch = UNICODE_LINEFEED;
    00725                     }
    00726                 }
    00727             }
    00728         }
    00729 #endif
    00730
    00731         GlobalUnlock(ClipboardDataHandle);
    00732 #if defined(FE_SB)
    00733         if (TmpClipboardData)
    00734             ConsoleHeapFree(TmpClipboardData);
    00735 #endif
    00736         ConsoleHeapFree(Selection);
    00737         Success = OpenClipboard(Console->hWnd);
    00738         if (!Success) {
    00739             GlobalFree(ClipboardDataHandle);
    00740             return;
    00741         }
    00742
    00743         Success = EmptyClipboard();
    00744         if (!Success) {
    00745             GlobalFree(ClipboardDataHandle);
    00746             return;
    00747         }
    00748
    00749         SetClipboardData(CF_UNICODETEXT,ClipboardDataHandle);
    00750         CloseClipboard();   // Close clipboard
    00751     } else {
    00752         HBITMAP hBitmapTarget, hBitmapOld;
    00753         HDC hDCMem;
    00754         HPALETTE hPaletteOld;
    00755         int Height;
    00756
    00757         NtWaitForSingleObject(ScreenInfo->BufferInfo.GraphicsInfo.hMutex,
    00758                               FALSE, NULL);
    00759
    00760         hDCMem = CreateCompatibleDC(Console->hDC);
    00761         hBitmapTarget = CreateCompatibleBitmap(Console->hDC,
    00762                                                   TargetSize.X,
    00763                                                   TargetSize.Y);
    00764         if (hBitmapTarget) {
    00765             hBitmapOld = SelectObject(hDCMem, hBitmapTarget);
    00766             if (ScreenInfo->hPalette) {
    00767                 hPaletteOld = SelectPalette(hDCMem,
    00768                                              ScreenInfo->hPalette,
    00769                                              FALSE);
    00770             }
    00771             MyInvert(Console,&Console->SelectionRect);
    00772
    00773             // if (DIB is a top-down)
    00774             //      ySrc = abs(height) - rect.bottom - 1;
    00775             // else
    00776             //      ySrc = rect.Bottom.
    00777             //
    00778             Height = ScreenInfo->BufferInfo.GraphicsInfo.lpBitMapInfo->bmiHeader.biHeight;
    00779
    00780             StretchDIBits(hDCMem, 0, 0,
    00781                         TargetSize.X, TargetSize.Y,
    00782                         Console->SelectionRect.Left + ScreenInfo->Window.Left,
    00783                         (Height < 0) ? -Height - (Console->SelectionRect.Bottom + ScreenInfo->Window.Top) -  1
    00784                         : Console->SelectionRect.Bottom + ScreenInfo->Window.Top,
    00785                         TargetSize.X, TargetSize.Y,
    00786                         ScreenInfo->BufferInfo.GraphicsInfo.BitMap,
    00787                         ScreenInfo->BufferInfo.GraphicsInfo.lpBitMapInfo,
    00788                         ScreenInfo->BufferInfo.GraphicsInfo.dwUsage,
    00789                         SRCCOPY);
    00790             MyInvert(Console,&Console->SelectionRect);
    00791             if (ScreenInfo->hPalette) {
    00792                 SelectPalette(hDCMem, hPaletteOld, FALSE);
    00793             }
    00794             SelectObject(hDCMem, hBitmapOld);
    00795             OpenClipboard(Console->hWnd);
    00796             EmptyClipboard();
    00797             SetClipboardData(CF_BITMAP,hBitmapTarget);
    00798             CloseClipboard();
    00799         }
    00800         DeleteDC(hDCMem);
    00801         NtReleaseMutant(ScreenInfo->BufferInfo.GraphicsInfo.hMutex, NULL);
    00802     }
    00803
    00804 }
    00805
    00806 VOID
    00807 DoCopy(
    00808     IN PCONSOLE_INFORMATION Console
    00809     )
    00810 {
    00811     StoreSelection(Console);        // store selection in clipboard
    00812     ClearSelection(Console);        // clear selection in console
    00813 }
    00814
    00815 /*++
    00816
    00817 Routine Description:
    00818
    00819     This routine pastes given Unicode string into the console window.
    00820
    00821 Arguments:
    00822     Console  -   Pointer to CONSOLE_INFORMATION structure
    00823     pwStr    -   Unicode string that is pasted to the console window
    00824     DataSize -   Size of the Unicode String in characters
    00825
    00826
    00827 Return Value:
    00828     None
    00829
    00830
    00831 --*/
    00832
    00833
    00834 VOID
    00835 DoStringPaste(
    00836     IN PCONSOLE_INFORMATION Console,
    00837     IN PWCHAR pwStr,
    00838     IN UINT DataSize
    00839     )
    00840 {
    00841     PINPUT_RECORD StringData,CurRecord;
    00842     PWCHAR CurChar;
    00843     WCHAR Char;
    00844     DWORD i;
    00845     DWORD ChunkSize,j;
    00846     ULONG EventsWritten;
    00847
    00848
    00849     if(!pwStr) {
    00850        return;
    00851     }
    00852
    00853     if (DataSize > DATA_CHUNK_SIZE) {
    00854         ChunkSize = DATA_CHUNK_SIZE;
    00855     } else {
    00856         ChunkSize = DataSize;
    00857     }
    00858
    00859     //
    00860     // allocate space to copy data.
    00861     //
    00862
    00863     StringData = (PINPUT_RECORD)ConsoleHeapAlloc(MAKE_TAG( TMP_TAG ),ChunkSize*sizeof(INPUT_RECORD)*8); // 8 is maximum number of events per char
    00864     if (StringData == NULL) {
    00865         return;
    00866     }
    00867
    00868     //
    00869     // transfer data to the input buffer in chunks
    00870     //
    00871
    00872     CurChar = pwStr;   // LATER remove this
    00873     for (j = 0; j < DataSize; j += ChunkSize) {
    00874         if (ChunkSize > DataSize - j) {
    00875             ChunkSize = DataSize - j;
    00876         }
    00877         CurRecord = StringData;
    00878         for (i = 0, EventsWritten = 0; i < ChunkSize; i++) {
    00879             // filter out LF if not first char and preceded by CR
    00880             Char = *CurChar;
    00881             if (Char != UNICODE_LINEFEED || (i==0 && j==0) || (*(CurChar-1)) != UNICODE_CARRIAGERETURN) {
    00882                 SHORT KeyState;
    00883                 BYTE KeyFlags;
    00884                 BOOL AltGr=FALSE;
    00885                 BOOL Shift=FALSE;
    00886
    00887                 if (Char == 0) {
    00888                     j = DataSize;
    00889                     break;
    00890                 }
    00891
    00892                 KeyState = VkKeyScan(Char);
    00893 #if defined(FE_SB)
    00894                 if (CONSOLE_IS_DBCS_ENABLED() &&
    00895                     (KeyState == -1)) {
    00896                     WORD CharType;
    00897                     //
    00898                     // Determine DBCS character because these character doesn't know by VkKeyScan.
    00899                     // GetStringTypeW(CT_CTYPE3) & C3_ALPHA can determine all linguistic characters.
    00900                     // However, this is not include symbolic character for DBCS.
    00901                     // IsConsoleFullWidth can help for DBCS symbolic character.
    00902                     //
    00903                     GetStringTypeW(CT_CTYPE3,&Char,1,&CharType);
    00904                     if ((CharType & C3_ALPHA) ||
    00905                         IsConsoleFullWidth(Console->hDC,Console->OutputCP,Char)) {
    00906                         KeyState = 0;
    00907                     }
    00908                 }
    00909 #endif
    00910
    00911                 // if VkKeyScanW fails (char is not in kbd layout), we must
    00912                 // emulate the key being input through the numpad
    00913
    00914                 if (KeyState == -1) {
    00915                     CHAR CharString[4];
    00916                     UCHAR OemChar;
    00917                     PCHAR pCharString;
    00918
    00919                     ConvertToOem(Console->OutputCP,
    00920                                  &Char,
    00921                                  1,
    00922                                  &OemChar,
    00923                                  1
    00924                                 );
    00925
    00926                     _itoa(OemChar, CharString, 10);
    00927
    00928                     EventsWritten++;
    00929                     LoadKeyEvent(CurRecord,TRUE,0,VK_MENU,0x38,LEFT_ALT_PRESSED);
    00930                     CurRecord++;
    00931
    00932                     for (pCharString=CharString;*pCharString;pCharString++) {
    00933                         WORD wVirtualKey, wScancode;
    00934                         EventsWritten++;
    00935                         wVirtualKey = *pCharString-'0'+VK_NUMPAD0;
    00936                         wScancode = (WORD)MapVirtualKey(wVirtualKey, 0);
    00937                         LoadKeyEvent(CurRecord,TRUE,0,wVirtualKey,wScancode,LEFT_ALT_PRESSED);
    00938                         CurRecord++;
    00939                         EventsWritten++;
    00940                         LoadKeyEvent(CurRecord,FALSE,0,wVirtualKey,wScancode,LEFT_ALT_PRESSED);
    00941                         CurRecord++;
    00942                     }
    00943
    00944                     EventsWritten++;
    00945                     LoadKeyEvent(CurRecord,FALSE,Char,VK_MENU,0x38,0);
    00946                     CurRecord++;
    00947                 } else {
    00948                     KeyFlags = HIBYTE(KeyState);
    00949
    00950                     // handle yucky alt-gr keys
    00951                     if ((KeyFlags & 6) == 6) {
    00952                         AltGr=TRUE;
    00953                         EventsWritten++;
    00954                         LoadKeyEvent(CurRecord,TRUE,0,VK_MENU,0x38,ENHANCED_KEY | LEFT_CTRL_PRESSED | RIGHT_ALT_PRESSED);
    00955                         CurRecord++;
    00956                     } else if (KeyFlags & 1) {
    00957                         Shift=TRUE;
    00958                         EventsWritten++;
    00959                         LoadKeyEvent(CurRecord,TRUE,0,VK_SHIFT,0x2a,SHIFT_PRESSED);
    00960                         CurRecord++;
    00961                     }
    00962
    00963                     EventsWritten++;
    00964                     LoadKeyEvent(CurRecord,
    00965                                  TRUE,
    00966                                  Char,
    00967                                  LOBYTE(KeyState),
    00968                                  (WORD)MapVirtualKey(CurRecord->Event.KeyEvent.wVirtualKeyCode,0),
    00969                                  0);
    00970                     if (KeyFlags & 1)
    00971                         CurRecord->Event.KeyEvent.dwControlKeyState |= SHIFT_PRESSED;
    00972                     if (KeyFlags & 2)
    00973                         CurRecord->Event.KeyEvent.dwControlKeyState |= LEFT_CTRL_PRESSED;
    00974                     if (KeyFlags & 4)
    00975                         CurRecord->Event.KeyEvent.dwControlKeyState |= RIGHT_ALT_PRESSED;
    00976                     CurRecord++;
    00977
    00978                     EventsWritten++;
    00979                     *CurRecord = *(CurRecord-1);
    00980                     CurRecord->Event.KeyEvent.bKeyDown = FALSE;
    00981                     CurRecord++;
    00982
    00983                     // handle yucky alt-gr keys
    00984                     if (AltGr) {
    00985                         EventsWritten++;
    00986                         LoadKeyEvent(CurRecord,FALSE,0,VK_MENU,0x38,ENHANCED_KEY);
    00987                         CurRecord++;
    00988                     } else if (Shift) {
    00989                         EventsWritten++;
    00990                         LoadKeyEvent(CurRecord,FALSE,0,VK_SHIFT,0x2a,0);
    00991                         CurRecord++;
    00992                     }
    00993                 }
    00994             }
    00995             CurChar++;
    00996         }
    00997         EventsWritten = WriteInputBuffer(Console,
    00998                                          &Console->InputBuffer,
    00999                                          StringData,
    01000                                          EventsWritten
    01001                                          );
    01002     }
    01003     ConsoleHeapFree(StringData);
    01004     return;
    01005 }
    01006
    01007 VOID
    01008 DoPaste(
    01009     IN PCONSOLE_INFORMATION Console
    01010     )
    01011
    01012 /*++
    01013
    01014   Perform paste request into old app by sucking out clipboard
    01015         contents and writing them to the console's input buffer
    01016
    01017 --*/
    01018
    01019 {
    01020     BOOL Success;
    01021     HANDLE ClipboardDataHandle;
    01022
    01023     if (Console->Flags & CONSOLE_SCROLLING) {
    01024         return;
    01025     }
    01026
    01027     //
    01028     // Get paste data from clipboard
    01029     //
    01030
    01031     Success = OpenClipboard(Console->hWnd);
    01032     if (!Success)
    01033         return;
    01034
    01035     if (Console->CurrentScreenBuffer->Flags & CONSOLE_TEXTMODE_BUFFER) {
    01036         PWCHAR pwstr;
    01037
    01038         ClipboardDataHandle = GetClipboardData(CF_UNICODETEXT);
    01039         if (ClipboardDataHandle == NULL) {
    01040             CloseClipboard();   // Close clipboard
    01041             return;
    01042         }
    01043         pwstr = GlobalLock(ClipboardDataHandle);
    01044         DoStringPaste(Console,pwstr,(ULONG)GlobalSize(ClipboardDataHandle)/sizeof(WCHAR));
    01045         GlobalUnlock(ClipboardDataHandle);
    01046
    01047     } else {
    01048         HBITMAP hBitmapSource,hBitmapTarget;
    01049         HDC hDCMemSource,hDCMemTarget;
    01050         BITMAP bm;
    01051         PSCREEN_INFORMATION ScreenInfo;
    01052
    01053         hBitmapSource = GetClipboardData(CF_BITMAP);
    01054         if (hBitmapSource) {
    01055
    01056             ScreenInfo = Console->CurrentScreenBuffer;
    01057             NtWaitForSingleObject(ScreenInfo->BufferInfo.GraphicsInfo.hMutex,
    01058                                   FALSE, NULL);
    01059
    01060             hBitmapTarget = CreateDIBitmap(Console->hDC,
    01061                                      &ScreenInfo->BufferInfo.GraphicsInfo.lpBitMapInfo->bmiHeader,
    01062                                      CBM_INIT,
    01063                                      ScreenInfo->BufferInfo.GraphicsInfo.BitMap,
    01064                                      ScreenInfo->BufferInfo.GraphicsInfo.lpBitMapInfo,
    01065                                      ScreenInfo->BufferInfo.GraphicsInfo.dwUsage
    01066                                     );
    01067             if (hBitmapTarget) {
    01068                 hDCMemTarget = CreateCompatibleDC ( Console->hDC );
    01069                 hDCMemSource = CreateCompatibleDC ( Console->hDC );
    01070                 SelectObject( hDCMemTarget, hBitmapTarget );
    01071                 SelectObject( hDCMemSource, hBitmapSource );
    01072                 GetObjectW(hBitmapSource, sizeof (BITMAP), (LPSTR) &bm);
    01073                 BitBlt ( hDCMemTarget, 0, 0, bm.bmWidth, bm.bmHeight,
    01074                      hDCMemSource, 0, 0, SRCCOPY);
    01075                 GetObjectW(hBitmapTarget, sizeof (BITMAP), (LPSTR) &bm);
    01076
    01077                 // copy the bits from the DC to memory
    01078
    01079                 GetDIBits(hDCMemTarget, hBitmapTarget, 0, bm.bmHeight,
    01080                           ScreenInfo->BufferInfo.GraphicsInfo.BitMap,
    01081                           ScreenInfo->BufferInfo.GraphicsInfo.lpBitMapInfo,
    01082                           ScreenInfo->BufferInfo.GraphicsInfo.dwUsage);
    01083                 DeleteDC(hDCMemSource);
    01084                 DeleteDC(hDCMemTarget);
    01085                 DeleteObject(hBitmapTarget);
    01086                 InvalidateRect(Console->hWnd,NULL,FALSE); // force repaint
    01087             }
    01088             NtReleaseMutant(ScreenInfo->BufferInfo.GraphicsInfo.hMutex, NULL);
    01089         }
    01090     }
    01091     CloseClipboard();
    01092     return;
    01093 }
    01094
    01095 VOID
    01096 InitSelection(
    01097     IN PCONSOLE_INFORMATION Console
    01098     )
    01099
    01100 /*++
    01101
    01102     This routine initializes the selection process.  It is called
    01103     when the user selects the Mark option from the system menu.
    01104
    01105 --*/
    01106
    01107 {
    01108     COORD Position;
    01109     PSCREEN_INFORMATION ScreenInfo;
    01110
    01111     //
    01112     // if already selecting, cancel selection.
    01113     //
    01114
    01115     if (Console->Flags & CONSOLE_SELECTING) {
    01116         if (Console->SelectionFlags & CONSOLE_MOUSE_SELECTION) {
    01117             CancelMouseSelection(Console);
    01118         } else {
    01119             CancelKeySelection(Console,FALSE);
    01120         }
    01121     }
    01122
    01123     //
    01124     // set flags
    01125     //
    01126
    01127     Console->Flags |= CONSOLE_SELECTING;
    01128     Console->SelectionFlags = 0;
    01129
    01130     //
    01131     // save old cursor position and
    01132     // make console cursor into selection cursor.
    01133     //
    01134
    01135     ScreenInfo = Console->CurrentScreenBuffer;
    01136     Console->TextCursorPosition = ScreenInfo->BufferInfo.TextInfo.CursorPosition;
    01137     Console->TextCursorVisible = (BOOLEAN)ScreenInfo->BufferInfo.TextInfo.CursorVisible;
    01138     Console->TextCursorSize =   ScreenInfo->BufferInfo.TextInfo.CursorSize;
    01139     ConsoleHideCursor(ScreenInfo);
    01140     SetCursorInformation(ScreenInfo,
    01141                          100,
    01142                          TRUE
    01143                         );
    01144     Position.X = ScreenInfo->Window.Left;
    01145     Position.Y = ScreenInfo->Window.Top;
    01146     SetCursorPosition(ScreenInfo,
    01147                       Position,
    01148                       TRUE
    01149                      );
    01150     ConsoleShowCursor(ScreenInfo);
    01151
    01152     //
    01153     // init select rect
    01154     //
    01155
    01156     Console->SelectionAnchor = Position;
    01157
    01158     //
    01159     // set win text
    01160     //
    01161
    01162     SetWinText(Console,msgMarkMode,TRUE);
    01163
    01164 }
    01165
    01166 VOID
    01167 DoMark(
    01168     IN PCONSOLE_INFORMATION Console
    01169     )
    01170 {
    01171     InitSelection(Console);        // initialize selection
    01172 }
    01173
    01174 VOID
    01175 DoSelectAll(
    01176     IN PCONSOLE_INFORMATION Console
    01177     )
    01178 {
    01179     COORD Position;
    01180     COORD WindowOrigin;
    01181     PSCREEN_INFORMATION ScreenInfo;
    01182
    01183     // clear any old selections
    01184     if (Console->Flags & CONSOLE_SELECTING) {
    01185         ClearSelection(Console);
    01186     }
    01187
    01188     // save the old window position
    01189     ScreenInfo = Console->CurrentScreenBuffer;
    01190     WindowOrigin.X = ScreenInfo->Window.Left;
    01191     WindowOrigin.Y = ScreenInfo->Window.Top;
    01192
    01193     // initialize selection
    01194     Console->Flags |= CONSOLE_SELECTING;
    01195     Console->SelectionFlags = CONSOLE_MOUSE_SELECTION | CONSOLE_SELECTION_NOT_EMPTY;
    01196     Console->SelectionAnchor.X = Console->SelectionRect.Left = Console->SelectionRect.Right = 0;
    01197     Console->SelectionAnchor.Y = Console->SelectionRect.Top = Console->SelectionRect.Bottom = 0;
    01198     MyInvert(Console,&Console->SelectionRect);
    01199     SetWinText(Console,msgSelectMode,TRUE);
    01200
    01201     // extend selection
    01202     Position.X = ScreenInfo->ScreenBufferSize.X - 1;
    01203     Position.Y = ScreenInfo->BufferInfo.TextInfo.CursorPosition.Y;
    01204     ExtendSelection(Console, Position);
    01205
    01206     // restore the old window position
    01207     SetWindowOrigin(ScreenInfo, TRUE, WindowOrigin);
    01208 }
    01209
    01210 VOID
    01211 DoScroll(
    01212     IN PCONSOLE_INFORMATION Console
    01213     )
    01214 {
    01215     if (!(Console->Flags & CONSOLE_SCROLLING)) {
    01216         SetWinText(Console,msgScrollMode,TRUE);
    01217         Console->Flags |= CONSOLE_SCROLLING;
    01218     }
    01219 }
    01220
    01221 VOID
    01222 ClearScroll(
    01223     IN PCONSOLE_INFORMATION Console
    01224     )
    01225 {
    01226     SetWinText(Console,msgScrollMode,FALSE);
    01227     Console->Flags &= ~CONSOLE_SCROLLING;
    01228 }
    01229
    01230 VOID
    01231 ScrollIfNecessary(
    01232     IN PCONSOLE_INFORMATION Console,
    01233     IN PSCREEN_INFORMATION ScreenInfo
    01234     )
    01235 {
    01236     POINT CursorPos;
    01237     RECT ClientRect;
    01238     COORD MousePosition;
    01239
    01240     if (Console->Flags & CONSOLE_SELECTING &&
    01241         Console->SelectionFlags & CONSOLE_MOUSE_DOWN) {
    01242         if (!GetCursorPos(&CursorPos)) {
    01243             return;
    01244         }
    01245         if (!GetClientRect(Console->hWnd,&ClientRect)) {
    01246             return;
    01247         }
    01248         MapWindowPoints(Console->hWnd,NULL,(LPPOINT)&ClientRect,2);
    01249         if (!(PtInRect(&ClientRect,CursorPos))) {
    01250             ScreenToClient(Console->hWnd,&CursorPos);
    01251             MousePosition.X = (SHORT)CursorPos.x;
    01252             MousePosition.Y = (SHORT)CursorPos.y;
    01253             if (ScreenInfo->Flags & CONSOLE_TEXTMODE_BUFFER) {
    01254                 MousePosition.X /= SCR_FONTSIZE(ScreenInfo).X;
    01255                 MousePosition.Y /= SCR_FONTSIZE(ScreenInfo).Y;
    01256             }
    01257             MousePosition.X += ScreenInfo->Window.Left;
    01258             MousePosition.Y += ScreenInfo->Window.Top;
    01259
    01260             ExtendSelection(Console,
    01261                             MousePosition
    01262                            );
    01263         }
    01264     }
    01265 }