Sync with trunk r63637.

svn path=/branches/shell-experiments/; revision=63640
This commit is contained in:
David Quintana 2014-06-23 23:28:38 +00:00
commit 73d72624b0
410 changed files with 4745 additions and 12328 deletions

View file

@ -63,8 +63,8 @@ extern const FLOATOBJ gef16;
#define FLOATOBJ_16 {0x40000000, 0x00000006}
#define FLOATOBJ_1_16 {0x40000000, 0xfffffffe}
#define FLOATOBJ_Set0(fo) (fo)->ul1 = 0; (fo)->ul2 = 0;
#define FLOATOBJ_Set1(fo) (fo)->ul1 = 0x40000000; (fo)->ul2 = 2;
#define FLOATOBJ_Set0(fo) do { (fo)->ul1 = 0; (fo)->ul2 = 0; } while (0)
#define FLOATOBJ_Set1(fo) do { (fo)->ul1 = 0x40000000; (fo)->ul2 = 2; } while (0)
#else

View file

@ -382,7 +382,7 @@ EngLoadImageEx(
if (pldev->pGdiDriverInfo)
{
/* Check for match (case insensative) */
if (RtlEqualUnicodeString(&pldev->pGdiDriverInfo->DriverName, &strDriverName, 1))
if (RtlEqualUnicodeString(&pldev->pGdiDriverInfo->DriverName, &strDriverName, TRUE))
{
/* Image found in LDEV list */
break;

View file

@ -19,6 +19,8 @@
#include <ftoutln.h>
#include <ftwinfnt.h>
#include <gdi/eng/floatobj.h>
#define NDEBUG
#include <debug.h>
@ -3228,6 +3230,7 @@ GreExtTextOutW(
USHORT DxShift;
PMATRIX pmxWorldToDevice;
LONG fixAscender, fixDescender;
FLOATOBJ Scale;
// TODO: Write test-cases to exactly match real Windows in different
// bad parameters (e.g. does Windows check the DC or the RECT first?).
@ -3671,8 +3674,13 @@ GreExtTextOutW(
}
else
{
TextLeft += Dx[i<<DxShift] << 6;
DPRINT("New TextLeft2: %I64d\n", TextLeft);
Scale = pdcattr->mxWorldToDevice.efM11;
if (_FLOATOBJ_Equal0(&Scale))
FLOATOBJ_Set1(&Scale);
FLOATOBJ_MulLong(&Scale, Dx[i<<DxShift] << 6); // do the shift before multiplying to preserve precision
TextLeft += FLOATOBJ_GetLong(&Scale);
DPRINT("New TextLeft2: %I64d\n", TextLeft);
}
if (DxShift)

View file

@ -70,7 +70,6 @@ typedef enum _USERTHREADINFOCLASS
UserThreadWOWInformation,
UserThreadHungStatus,
UserThreadInitiateShutdown,
UserThreadEndShutdown,
UserThreadUseActiveDesktop,
UserThreadUseDesktop,
@ -3385,7 +3384,6 @@ typedef struct tagKMDDELPARAM
#define MSQ_STATE_MENUOWNER 0x4
#define MSQ_STATE_MOVESIZE 0x5
#define MSQ_STATE_CARET 0x6
#define TWOPARAM_ROUTINE_SETCARETPOS 0xfffd0060
#define TWOPARAM_ROUTINE_ROS_UPDATEUISTATE 0x1004
#define HWNDPARAM_ROUTINE_ROS_NOTIFYWINEVENT 0x1005

View file

@ -72,7 +72,7 @@ IntDesktopObjectParse(IN PVOID ParseObject,
/* Compare the name */
if (RtlEqualUnicodeString(RemainingName,
&DesktopName,
(Attributes & OBJ_CASE_INSENSITIVE)))
(Attributes & OBJ_CASE_INSENSITIVE) != 0))
{
/* We found a match. Did this come from a create? */
if (Context)

View file

@ -101,11 +101,13 @@ co_IntSendActivateMessages(PWND WindowPrev, PWND Window, BOOL MouseActivate, BOO
HANDLE OldTID, NewTID;
PTHREADINFO pti, ptiOld, ptiNew;
BOOL InAAPM = FALSE;
//ERR("SendActivateMessages\n");
pti = PsGetCurrentThreadWin32Thread();
if (Window)
{
UserRefObjectCo(Window, &Ref);
if (WindowPrev) UserRefObjectCo(WindowPrev, &RefPrev);
@ -163,8 +165,62 @@ co_IntSendActivateMessages(PWND WindowPrev, PWND Window, BOOL MouseActivate, BOO
ExFreePool(phwndTopLevel);
}
}
////
}
////
OldTID = WindowPrev ? IntGetWndThreadId(WindowPrev) : NULL;
NewTID = Window ? IntGetWndThreadId(Window) : NULL;
ptiOld = WindowPrev ? WindowPrev->head.pti : NULL;
ptiNew = Window ? Window->head.pti : NULL;
//ERR("SendActivateMessage Old -> %x, New -> %x\n", OldTID, NewTID);
if (!(pti->TIF_flags & TIF_INACTIVATEAPPMSG) &&
(!WindowPrev || OldTID != NewTID) )
{
PWND cWindow;
HWND *List, *phWnd;
List = IntWinListChildren(UserGetDesktopWindow());
if ( List )
{
if ( OldTID )
{
ptiOld->TIF_flags |= TIF_INACTIVATEAPPMSG;
// Note: Do not set pci flags, this does crash!
for (phWnd = List; *phWnd; ++phWnd)
{
cWindow = ValidateHwndNoErr(*phWnd);
if (cWindow && cWindow->head.pti == ptiOld)
{ // FALSE if the window is being deactivated,
// ThreadId that owns the window being activated.
//ERR("SendActivateMessage Old\n");
co_IntSendMessageNoWait(*phWnd, WM_ACTIVATEAPP, FALSE, (LPARAM)NewTID);
}
}
ptiOld->TIF_flags &= ~TIF_INACTIVATEAPPMSG;
}
if ( NewTID )
{ //// Prevents a resource crash due to reentrance!
InAAPM = TRUE;
pti->TIF_flags |= TIF_INACTIVATEAPPMSG;
////
for (phWnd = List; *phWnd; ++phWnd)
{
cWindow = ValidateHwndNoErr(*phWnd);
if (cWindow && cWindow->head.pti == ptiNew)
{ // TRUE if the window is being activated,
// ThreadId that owns the window being deactivated.
//ERR("SendActivateMessage New\n");
co_IntSendMessageNoWait(*phWnd, WM_ACTIVATEAPP, TRUE, (LPARAM)OldTID);
}
}
}
ExFreePoolWithTag(List, USERTAG_WINDOWLIST);
}
}
if (Window)
{
if (WindowPrev)
UserDerefObjectCo(WindowPrev); // Now allow the previous window to die.
@ -542,7 +598,7 @@ IntFindChildWindowToOwner(PWND Root, PWND Owner)
for(Child = Root->spwndChild; Child; Child = Child->spwndNext)
{
OwnerWnd = Child->spwndOwner;
OwnerWnd = Child->spwndOwner;
if(!OwnerWnd)
continue;

View file

@ -1369,7 +1369,7 @@ BOOL co_IntProcessMouseMessage(MSG* msg, BOOL* RemoveMessages, UINT first, UINT
}
else
{
pwndMsg = co_WinPosWindowFromPoint(NULL, &msg->pt, &hittest, TRUE);
pwndMsg = co_WinPosWindowFromPoint(NULL, &msg->pt, &hittest, FALSE);//TRUE);
}
TRACE("Got mouse message for %p, hittest: 0x%x\n", msg->hwnd, hittest);

View file

@ -2141,7 +2141,13 @@ NtUserInvalidateRect(
CONST RECT *lpUnsafeRect,
BOOL bErase)
{
return NtUserRedrawWindow(hWnd, lpUnsafeRect, NULL, RDW_INVALIDATE | (bErase? RDW_ERASE : 0));
UINT flags = RDW_INVALIDATE | (bErase ? RDW_ERASE : 0);
if (!hWnd)
{
flags = RDW_ALLCHILDREN | RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_ERASENOW;
lpUnsafeRect = NULL;
}
return NtUserRedrawWindow(hWnd, lpUnsafeRect, NULL, flags);
}
BOOL
@ -2151,6 +2157,11 @@ NtUserInvalidateRgn(
HRGN hRgn,
BOOL bErase)
{
if (!hWnd)
{
EngSetLastError( ERROR_INVALID_WINDOW_HANDLE );
return FALSE;
}
return NtUserRedrawWindow(hWnd, NULL, hRgn, RDW_INVALIDATE | (bErase? RDW_ERASE : 0));
}
@ -2197,11 +2208,13 @@ NtUserValidateRect(
HWND hWnd,
const RECT *lpRect)
{
if (hWnd)
UINT flags = RDW_VALIDATE;
if (!hWnd)
{
return NtUserRedrawWindow(hWnd, lpRect, NULL, RDW_VALIDATE );
flags = RDW_ALLCHILDREN | RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_ERASENOW;
lpRect = NULL;
}
return NtUserRedrawWindow(hWnd, lpRect, NULL, RDW_INVALIDATE|RDW_ERASE|RDW_ERASENOW|RDW_ALLCHILDREN);
return NtUserRedrawWindow(hWnd, lpRect, NULL, flags);
}
/* EOF */

View file

@ -451,7 +451,6 @@ NtUserCreateWindowStation(
/* Initialize the window station */
RtlZeroMemory(WindowStationObject, sizeof(WINSTATION_OBJECT));
KeInitializeSpinLock(&WindowStationObject->Lock);
InitializeListHead(&WindowStationObject->DesktopListHead);
Status = RtlCreateAtomTable(37, &WindowStationObject->AtomTable);
WindowStationObject->Name = WindowStationName;
@ -1203,7 +1202,6 @@ BuildDesktopNameList(
{
NTSTATUS Status;
PWINSTATION_OBJECT WindowStation;
KIRQL OldLevel;
PLIST_ENTRY DesktopEntry;
PDESKTOP DesktopObject;
DWORD EntryCount;
@ -1220,8 +1218,6 @@ BuildDesktopNameList(
return Status;
}
KeAcquireSpinLock(&WindowStation->Lock, &OldLevel);
/*
* Count the required size of buffer.
*/
@ -1242,7 +1238,6 @@ BuildDesktopNameList(
Status = MmCopyToCaller(pRequiredSize, &ReturnLength, sizeof(ULONG));
if (! NT_SUCCESS(Status))
{
KeReleaseSpinLock(&WindowStation->Lock, OldLevel);
ObDereferenceObject(WindowStation);
return STATUS_BUFFER_TOO_SMALL;
}
@ -1253,7 +1248,6 @@ BuildDesktopNameList(
*/
if (dwSize < ReturnLength)
{
KeReleaseSpinLock(&WindowStation->Lock, OldLevel);
ObDereferenceObject(WindowStation);
return STATUS_BUFFER_TOO_SMALL;
}
@ -1264,7 +1258,6 @@ BuildDesktopNameList(
Status = MmCopyToCaller(lpBuffer, &EntryCount, sizeof(DWORD));
if (! NT_SUCCESS(Status))
{
KeReleaseSpinLock(&WindowStation->Lock, OldLevel);
ObDereferenceObject(WindowStation);
return Status;
}
@ -1280,7 +1273,6 @@ BuildDesktopNameList(
Status = MmCopyToCaller(lpBuffer, DesktopName.Buffer, DesktopName.Length);
if (! NT_SUCCESS(Status))
{
KeReleaseSpinLock(&WindowStation->Lock, OldLevel);
ObDereferenceObject(WindowStation);
return Status;
}
@ -1288,7 +1280,6 @@ BuildDesktopNameList(
Status = MmCopyToCaller(lpBuffer, &NullWchar, sizeof(WCHAR));
if (! NT_SUCCESS(Status))
{
KeReleaseSpinLock(&WindowStation->Lock, OldLevel);
ObDereferenceObject(WindowStation);
return Status;
}
@ -1296,11 +1287,9 @@ BuildDesktopNameList(
}
/*
* Clean up
* Clean up and return
*/
KeReleaseSpinLock(&WindowStation->Lock, OldLevel);
ObDereferenceObject(WindowStation);
return STATUS_SUCCESS;
}

View file

@ -11,7 +11,6 @@ typedef struct _WINSTATION_OBJECT
{
DWORD dwSessionId;
KSPIN_LOCK Lock;
UNICODE_STRING Name;
LIST_ENTRY DesktopListHead;
PRTL_ATOM_TABLE AtomTable;

View file

@ -17,7 +17,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(user32);
#define MAX_WINDOWS 120
// Global variables
HWND switchdialog;
HWND switchdialog = NULL;
HFONT dialogFont;
int selectedWindow = 0;
BOOL isOpen = FALSE;
@ -334,19 +334,26 @@ void ProcessHotKey()
LRESULT WINAPI DoAppSwitch( WPARAM wParam, LPARAM lParam )
{
HWND hwnd;
HWND hwnd, hwndActive;
MSG msg;
BOOL Esc = FALSE;
INT Count = 0;
WCHAR Text[1024];
switchdialog = NULL;
// Already in the loop.
if (switchdialog) return 0;
hwndActive = GetActiveWindow();
// Nothing is active so exit.
if (!hwndActive) return 0;
// Capture current active window.
SetCapture( hwndActive );
switch (lParam)
{
case VK_TAB:
if( !CreateSwitcherWindow(User32Instance) ) return 0;
if( !GetDialogFont() ) return 0;
if( !CreateSwitcherWindow(User32Instance) ) goto Exit;
if( !GetDialogFont() ) goto Exit;
ProcessHotKey();
break;
@ -354,7 +361,7 @@ LRESULT WINAPI DoAppSwitch( WPARAM wParam, LPARAM lParam )
windowCount = 0;
Count = 0;
EnumWindowsZOrder(EnumerateCallback, 0);
if (windowCount < 2) return 0;
if (windowCount < 2) goto Exit;
if (wParam == SC_NEXTWINDOW)
Count = 1;
else
@ -373,7 +380,7 @@ LRESULT WINAPI DoAppSwitch( WPARAM wParam, LPARAM lParam )
break;
default:
return 0;
goto Exit;
}
// Main message loop:
while (1)
@ -471,6 +478,7 @@ LRESULT WINAPI DoAppSwitch( WPARAM wParam, LPARAM lParam )
}
}
Exit:
ReleaseCapture();
if (switchdialog) DestroyWindow(switchdialog);
switchdialog = NULL;
selectedWindow = 0;

View file

@ -636,8 +636,9 @@ static void TEXT_WordBreak (HDC hdc, WCHAR *str, unsigned int max_str,
DT_EDITCONTROL)
{
/* break the word after the last character that fits (there must be
* at least one; none is caught earlier).
*/
* at least one). */
if (!chars_fit)
++chars_fit;
*len_str = chars_fit;
*chars_used = chars_fit;

View file

@ -12,7 +12,7 @@
/* INCLUDES *******************************************************************/
#include <consrv.h>
#include <intrin.h>
#include <windowsx.h>
#define NDEBUG
@ -250,7 +250,8 @@ AppendMenuItems(HMENU hMenu,
} while (!(Items[i].uID == 0 && Items[i].SubMenu == NULL && Items[i].wCmdID == 0));
}
static VOID
//static
VOID
CreateSysMenu(HWND hWnd)
{
MENUITEMINFOW mii;
@ -301,7 +302,9 @@ Copy(PGUI_CONSOLE_DATA GuiData);
static VOID
Paste(PGUI_CONSOLE_DATA GuiData);
static VOID
UpdateSelection(PGUI_CONSOLE_DATA GuiData, PCOORD coord);
UpdateSelection(PGUI_CONSOLE_DATA GuiData,
PCOORD SelectionAnchor OPTIONAL,
PCOORD coord);
static VOID
Mark(PGUI_CONSOLE_DATA GuiData)
@ -309,30 +312,28 @@ Mark(PGUI_CONSOLE_DATA GuiData)
PCONSOLE_SCREEN_BUFFER ActiveBuffer = GuiData->ActiveBuffer;
/* Clear the old selection */
// UpdateSelection(GuiData, NULL);
GuiData->Selection.dwFlags = CONSOLE_NO_SELECTION;
/* Restart a new selection */
GuiData->dwSelectionCursor.X = ActiveBuffer->ViewOrigin.X;
GuiData->dwSelectionCursor.Y = ActiveBuffer->ViewOrigin.Y;
GuiData->Selection.dwSelectionAnchor = GuiData->dwSelectionCursor;
UpdateSelection(GuiData, &GuiData->Selection.dwSelectionAnchor);
GuiData->dwSelectionCursor = ActiveBuffer->ViewOrigin;
UpdateSelection(GuiData,
&GuiData->dwSelectionCursor,
&GuiData->dwSelectionCursor);
}
static VOID
SelectAll(PGUI_CONSOLE_DATA GuiData)
{
PCONSOLE_SCREEN_BUFFER ActiveBuffer = GuiData->ActiveBuffer;
COORD SelectionAnchor;
/* Clear the old selection */
// UpdateSelection(GuiData, NULL);
GuiData->Selection.dwFlags = CONSOLE_NO_SELECTION;
/*
* The selection area extends to the whole screen buffer's width.
*/
GuiData->Selection.dwSelectionAnchor.X = 0;
GuiData->Selection.dwSelectionAnchor.Y = 0;
SelectionAnchor.X = SelectionAnchor.Y = 0;
GuiData->dwSelectionCursor.X = ActiveBuffer->ScreenBufferSize.X - 1;
/*
@ -358,7 +359,7 @@ SelectAll(PGUI_CONSOLE_DATA GuiData)
/* Restart a new selection */
GuiData->Selection.dwFlags |= CONSOLE_MOUSE_SELECTION;
UpdateSelection(GuiData, &GuiData->dwSelectionCursor);
UpdateSelection(GuiData, &SelectionAnchor, &GuiData->dwSelectionCursor);
}
static LRESULT
@ -587,7 +588,8 @@ OnNcCreate(HWND hWnd, LPCREATESTRUCTW Create)
SetWindowLongPtrW(GuiData->hWindow, GWLP_USERDATA, (DWORD_PTR)GuiData);
SetTimer(GuiData->hWindow, CONGUI_UPDATE_TIMER, CONGUI_UPDATE_TIME, NULL);
CreateSysMenu(GuiData->hWindow);
// FIXME: HACK: Potential HACK for CORE-8129; see revision 63595.
//CreateSysMenu(GuiData->hWindow);
DPRINT("OnNcCreate - setting start event\n");
SetEvent(GuiData->hGuiInitEvent);
@ -678,18 +680,162 @@ SmallRectToRect(PGUI_CONSOLE_DATA GuiData, PRECT Rect, PSMALL_RECT SmallRect)
Rect->bottom = (SmallRect->Bottom + 1 - Buffer->ViewOrigin.Y) * HeightUnit;
}
VOID
GetSelectionBeginEnd(PCOORD Begin, PCOORD End,
PCOORD SelectionAnchor,
PSMALL_RECT SmallRect)
{
if (Begin == NULL || End == NULL) return;
*Begin = *SelectionAnchor;
End->X = (SelectionAnchor->X == SmallRect->Left) ? SmallRect->Right
/* Case X != Left, must be == Right */ : SmallRect->Left;
End->Y = (SelectionAnchor->Y == SmallRect->Top ) ? SmallRect->Bottom
/* Case Y != Top, must be == Bottom */ : SmallRect->Top;
/* Exchange Begin / End if Begin > End lexicographically */
if (Begin->Y > End->Y || (Begin->Y == End->Y && Begin->X > End->X))
{
End->X = _InterlockedExchange16(&Begin->X, End->X);
End->Y = _InterlockedExchange16(&Begin->Y, End->Y);
}
}
static HRGN
CreateSelectionRgn(PGUI_CONSOLE_DATA GuiData,
BOOL LineSelection,
PCOORD SelectionAnchor,
PSMALL_RECT SmallRect)
{
if (!LineSelection)
{
RECT rect;
SmallRectToRect(GuiData, &rect, SmallRect);
return CreateRectRgnIndirect(&rect);
}
else
{
HRGN SelRgn;
COORD Begin, End;
GetSelectionBeginEnd(&Begin, &End, SelectionAnchor, SmallRect);
if (Begin.Y == End.Y)
{
SMALL_RECT sr;
RECT r ;
sr.Left = Begin.X;
sr.Top = Begin.Y;
sr.Right = End.X;
sr.Bottom = End.Y;
// Debug thingie to see whether I can put this corner case
// together with the previous one.
if (SmallRect->Left != sr.Left ||
SmallRect->Top != sr.Top ||
SmallRect->Right != sr.Right ||
SmallRect->Bottom != sr.Bottom)
{
DPRINT1("\n"
"SmallRect = (%d, %d, %d, %d)\n"
"sr = (%d, %d, %d, %d)\n"
"\n",
SmallRect->Left, SmallRect->Top, SmallRect->Right, SmallRect->Bottom,
sr.Left, sr.Top, sr.Right, sr.Bottom);
}
SmallRectToRect(GuiData, &r, &sr);
SelRgn = CreateRectRgnIndirect(&r);
}
else
{
PCONSOLE_SCREEN_BUFFER ActiveBuffer = GuiData->ActiveBuffer;
HRGN rg1, rg2, rg3;
SMALL_RECT sr1, sr2, sr3;
RECT r1 , r2 , r3 ;
sr1.Left = Begin.X;
sr1.Top = Begin.Y;
sr1.Right = ActiveBuffer->ScreenBufferSize.X - 1;
sr1.Bottom = Begin.Y;
sr2.Left = 0;
sr2.Top = Begin.Y + 1;
sr2.Right = ActiveBuffer->ScreenBufferSize.X - 1;
sr2.Bottom = End.Y - 1;
sr3.Left = 0;
sr3.Top = End.Y;
sr3.Right = End.X;
sr3.Bottom = End.Y;
SmallRectToRect(GuiData, &r1, &sr1);
SmallRectToRect(GuiData, &r2, &sr2);
SmallRectToRect(GuiData, &r3, &sr3);
rg1 = CreateRectRgnIndirect(&r1);
rg2 = CreateRectRgnIndirect(&r2);
rg3 = CreateRectRgnIndirect(&r3);
CombineRgn(rg1, rg1, rg2, RGN_XOR);
CombineRgn(rg1, rg1, rg3, RGN_XOR);
DeleteObject(rg3);
DeleteObject(rg2);
SelRgn = rg1;
}
return SelRgn;
}
}
static VOID
UpdateSelection(PGUI_CONSOLE_DATA GuiData, PCOORD coord)
PaintSelectionRect(PGUI_CONSOLE_DATA GuiData, PPAINTSTRUCT pps)
{
HRGN rgnPaint = CreateRectRgnIndirect(&pps->rcPaint);
HRGN rgnSel = CreateSelectionRgn(GuiData, GuiData->LineSelection,
&GuiData->Selection.dwSelectionAnchor,
&GuiData->Selection.srSelection);
/* Invert the selection */
int ErrorCode = CombineRgn(rgnPaint, rgnPaint, rgnSel, RGN_AND);
if (ErrorCode != ERROR && ErrorCode != NULLREGION)
{
InvertRgn(pps->hdc, rgnPaint);
}
DeleteObject(rgnSel);
DeleteObject(rgnPaint);
}
static VOID
UpdateSelection(PGUI_CONSOLE_DATA GuiData,
PCOORD SelectionAnchor OPTIONAL,
PCOORD coord)
{
PCONSOLE Console = GuiData->Console;
RECT oldRect;
HRGN oldRgn = CreateSelectionRgn(GuiData, GuiData->LineSelection,
&GuiData->Selection.dwSelectionAnchor,
&GuiData->Selection.srSelection);
SmallRectToRect(GuiData, &oldRect, &GuiData->Selection.srSelection);
/* Update the anchor if needed (use the old one if NULL) */
if (SelectionAnchor)
GuiData->Selection.dwSelectionAnchor = *SelectionAnchor;
if (coord != NULL)
{
RECT newRect;
SMALL_RECT rc;
HRGN newRgn;
/*
* Pressing the Control key while selecting text, allows us to enter
* into line-selection mode, the selection mode of *nix terminals.
*/
BOOL OldLineSel = GuiData->LineSelection;
GuiData->LineSelection = !!(GetKeyState(VK_CONTROL) & 0x8000);
/* Exchange left/top with right/bottom if required */
rc.Left = min(GuiData->Selection.dwSelectionAnchor.X, coord->X);
@ -697,64 +843,72 @@ UpdateSelection(PGUI_CONSOLE_DATA GuiData, PCOORD coord)
rc.Right = max(GuiData->Selection.dwSelectionAnchor.X, coord->X);
rc.Bottom = max(GuiData->Selection.dwSelectionAnchor.Y, coord->Y);
SmallRectToRect(GuiData, &newRect, &rc);
newRgn = CreateSelectionRgn(GuiData, GuiData->LineSelection,
&GuiData->Selection.dwSelectionAnchor,
&rc);
if (GuiData->Selection.dwFlags & CONSOLE_SELECTION_NOT_EMPTY)
{
if (memcmp(&rc, &GuiData->Selection.srSelection, sizeof(SMALL_RECT)) != 0)
if (OldLineSel != GuiData->LineSelection ||
memcmp(&rc, &GuiData->Selection.srSelection, sizeof(SMALL_RECT)) != 0)
{
HRGN rgn1, rgn2;
/* Calculate the region that needs to be updated */
if ((rgn1 = CreateRectRgnIndirect(&oldRect)))
if (oldRgn && newRgn && CombineRgn(newRgn, newRgn, oldRgn, RGN_XOR) != ERROR)
{
if ((rgn2 = CreateRectRgnIndirect(&newRect)))
{
if (CombineRgn(rgn1, rgn2, rgn1, RGN_XOR) != ERROR)
{
InvalidateRgn(GuiData->hWindow, rgn1, FALSE);
}
DeleteObject(rgn2);
}
DeleteObject(rgn1);
InvalidateRgn(GuiData->hWindow, newRgn, FALSE);
}
}
}
else
{
InvalidateRect(GuiData->hWindow, &newRect, FALSE);
InvalidateRgn(GuiData->hWindow, newRgn, FALSE);
}
DeleteObject(newRgn);
GuiData->Selection.dwFlags |= CONSOLE_SELECTION_NOT_EMPTY;
GuiData->Selection.srSelection = rc;
GuiData->dwSelectionCursor = *coord;
if ((GuiData->Selection.dwFlags & CONSOLE_SELECTION_IN_PROGRESS) == 0)
{
LPWSTR SelectionType, WindowTitle = NULL;
SIZE_T Length = 0;
LPWSTR SelTypeStr = NULL , WindowTitle = NULL;
SIZE_T SelTypeStrLength = 0, Length = 0;
/* Clear the old selection */
if (GuiData->Selection.dwFlags & CONSOLE_SELECTION_NOT_EMPTY)
{
InvalidateRect(GuiData->hWindow, &oldRect, FALSE);
InvalidateRgn(GuiData->hWindow, oldRgn, FALSE);
}
if (GuiData->Selection.dwFlags & CONSOLE_MOUSE_SELECTION)
{
SelectionType = L"Selection - ";
}
else
{
SelectionType = L"Mark - ";
}
/*
* When passing a zero-length buffer size, LoadString(...) returns
* a read-only pointer buffer to the program's resource string.
*/
SelTypeStrLength =
LoadStringW(ConSrvDllInstance,
(GuiData->Selection.dwFlags & CONSOLE_MOUSE_SELECTION)
? IDS_SELECT_TITLE : IDS_MARK_TITLE,
(LPWSTR)&SelTypeStr, 0);
Length = Console->Title.Length + wcslen(SelectionType) + 1;
WindowTitle = ConsoleAllocHeap(0, Length * sizeof(WCHAR));
wcscpy(WindowTitle, SelectionType);
wcscat(WindowTitle, Console->Title.Buffer);
SetWindowText(GuiData->hWindow, WindowTitle);
ConsoleFreeHeap(WindowTitle);
/*
* Prepend the selection type string to the current console title
* if we succeeded in retrieving a valid localized string.
*/
if (SelTypeStr)
{
// 3 for " - " and 1 for NULL
Length = Console->Title.Length + (SelTypeStrLength + 3 + 1) * sizeof(WCHAR);
WindowTitle = ConsoleAllocHeap(0, Length);
wcsncpy(WindowTitle, SelTypeStr, SelTypeStrLength);
WindowTitle[SelTypeStrLength] = L'\0';
wcscat(WindowTitle, L" - ");
wcscat(WindowTitle, Console->Title.Buffer);
SetWindowText(GuiData->hWindow, WindowTitle);
ConsoleFreeHeap(WindowTitle);
}
GuiData->Selection.dwFlags |= CONSOLE_SELECTION_IN_PROGRESS;
ConioPause(Console, PAUSED_FROM_SELECTION);
@ -765,14 +919,17 @@ UpdateSelection(PGUI_CONSOLE_DATA GuiData, PCOORD coord)
/* Clear the selection */
if (GuiData->Selection.dwFlags & CONSOLE_SELECTION_NOT_EMPTY)
{
InvalidateRect(GuiData->hWindow, &oldRect, FALSE);
InvalidateRgn(GuiData->hWindow, oldRgn, FALSE);
}
GuiData->Selection.dwFlags = CONSOLE_NO_SELECTION;
ConioUnpause(Console, PAUSED_FROM_SELECTION);
/* Restore the console title */
SetWindowText(GuiData->hWindow, Console->Title.Buffer);
}
DeleteObject(oldRgn);
}
@ -826,15 +983,10 @@ OnPaint(PGUI_CONSOLE_DATA GuiData)
rcPaint.top,
SRCCOPY);
/* Draw the selection region if needed */
if (GuiData->Selection.dwFlags & CONSOLE_SELECTION_NOT_EMPTY)
{
SmallRectToRect(GuiData, &rcPaint, &GuiData->Selection.srSelection);
/* Invert the selection */
if (IntersectRect(&rcPaint, &ps.rcPaint, &rcPaint))
{
InvertRect(ps.hdc, &rcPaint);
}
PaintSelectionRect(GuiData, &ps);
}
LeaveCriticalSection(&GuiData->Lock);
@ -911,10 +1063,10 @@ OnKey(PGUI_CONSOLE_DATA GuiData, UINT msg, WPARAM wParam, LPARAM lParam)
goto Quit;
}
else if ( VirtualKeyCode == VK_ESCAPE ||
(VirtualKeyCode == 'C' && GetKeyState(VK_CONTROL) & 0x8000) )
(VirtualKeyCode == 'C' && (GetKeyState(VK_CONTROL) & 0x8000)) )
{
/* Cancel selection if ESC or Ctrl-C are pressed */
UpdateSelection(GuiData, NULL);
UpdateSelection(GuiData, NULL, NULL);
goto Quit;
}
@ -922,7 +1074,7 @@ OnKey(PGUI_CONSOLE_DATA GuiData, UINT msg, WPARAM wParam, LPARAM lParam)
{
/* Keyboard selection mode */
BOOL Interpreted = FALSE;
BOOL MajPressed = (GetKeyState(VK_SHIFT) & 0x8000);
BOOL MajPressed = !!(GetKeyState(VK_SHIFT) & 0x8000);
switch (VirtualKeyCode)
{
@ -1003,10 +1155,9 @@ OnKey(PGUI_CONSOLE_DATA GuiData, UINT msg, WPARAM wParam, LPARAM lParam)
if (Interpreted)
{
if (!MajPressed)
GuiData->Selection.dwSelectionAnchor = GuiData->dwSelectionCursor;
UpdateSelection(GuiData, &GuiData->dwSelectionCursor);
UpdateSelection(GuiData,
!MajPressed ? &GuiData->dwSelectionCursor : NULL,
&GuiData->dwSelectionCursor);
}
else if (!IsSystemKey(VirtualKeyCode))
{
@ -1023,7 +1174,7 @@ OnKey(PGUI_CONSOLE_DATA GuiData, UINT msg, WPARAM wParam, LPARAM lParam)
if (!IsSystemKey(VirtualKeyCode))
{
/* Clear the selection and send the key into the input buffer */
UpdateSelection(GuiData, NULL);
UpdateSelection(GuiData, NULL, NULL);
}
else
{
@ -1273,27 +1424,26 @@ OnMouse(PGUI_CONSOLE_DATA GuiData, UINT msg, WPARAM wParam, LPARAM lParam)
case WM_LBUTTONDOWN:
{
/* Clear the old selection */
// UpdateSelection(GuiData, NULL);
GuiData->Selection.dwFlags = CONSOLE_NO_SELECTION;
/* Restart a new selection */
GuiData->Selection.dwSelectionAnchor = PointToCoord(GuiData, lParam);
GuiData->dwSelectionCursor = PointToCoord(GuiData, lParam);
SetCapture(GuiData->hWindow);
GuiData->Selection.dwFlags |= CONSOLE_MOUSE_SELECTION | CONSOLE_MOUSE_DOWN;
UpdateSelection(GuiData, &GuiData->Selection.dwSelectionAnchor);
UpdateSelection(GuiData,
&GuiData->dwSelectionCursor,
&GuiData->dwSelectionCursor);
break;
}
case WM_LBUTTONUP:
{
// COORD c;
if (!(GuiData->Selection.dwFlags & CONSOLE_MOUSE_DOWN)) break;
// c = PointToCoord(GuiData, lParam);
// GuiData->dwSelectionCursor = PointToCoord(GuiData, lParam);
GuiData->Selection.dwFlags &= ~CONSOLE_MOUSE_DOWN;
// UpdateSelection(GuiData, &c);
// UpdateSelection(GuiData, NULL, &GuiData->dwSelectionCursor);
ReleaseCapture();
break;
@ -1305,10 +1455,7 @@ OnMouse(PGUI_CONSOLE_DATA GuiData, UINT msg, WPARAM wParam, LPARAM lParam)
if (GetType(Buffer) == TEXTMODE_BUFFER)
{
#ifdef IS_WHITESPACE
#undef IS_WHITESPACE
#endif
#define IS_WHITESPACE(c) \
#define IS_WORD_SEP(c) \
((c) == L'\0' || (c) == L' ' || (c) == L'\t' || (c) == L'\r' || (c) == L'\n')
PTEXTMODE_SCREEN_BUFFER TextBuffer = (PTEXTMODE_SCREEN_BUFFER)Buffer;
@ -1320,15 +1467,15 @@ OnMouse(PGUI_CONSOLE_DATA GuiData, UINT msg, WPARAM wParam, LPARAM lParam)
ptrL = ptrR = ConioCoordToPointer(TextBuffer, cL.X, cL.Y);
/* Enlarge the selection by checking for whitespace */
while ((0 < cL.X) && !IS_WHITESPACE(ptrL->Char.UnicodeChar)
&& !IS_WHITESPACE((ptrL-1)->Char.UnicodeChar))
while ((0 < cL.X) && !IS_WORD_SEP(ptrL->Char.UnicodeChar)
&& !IS_WORD_SEP((ptrL-1)->Char.UnicodeChar))
{
--cL.X;
--ptrL;
}
while ((cR.X < TextBuffer->ScreenBufferSize.X - 1) &&
!IS_WHITESPACE(ptrR->Char.UnicodeChar) &&
!IS_WHITESPACE((ptrR+1)->Char.UnicodeChar))
!IS_WORD_SEP(ptrR->Char.UnicodeChar) &&
!IS_WORD_SEP((ptrR+1)->Char.UnicodeChar))
{
++cR.X;
++ptrR;
@ -1338,11 +1485,8 @@ OnMouse(PGUI_CONSOLE_DATA GuiData, UINT msg, WPARAM wParam, LPARAM lParam)
* Update the selection started with the single
* left-click that preceded this double-click.
*/
GuiData->Selection.dwSelectionAnchor = cL;
GuiData->dwSelectionCursor = cR;
GuiData->Selection.dwFlags |= CONSOLE_MOUSE_SELECTION | CONSOLE_MOUSE_DOWN;
UpdateSelection(GuiData, &GuiData->dwSelectionCursor);
UpdateSelection(GuiData, &cL, &cR);
/* Ignore the next mouse move signal */
GuiData->IgnoreNextMouseSignal = TRUE;
@ -1370,13 +1514,12 @@ OnMouse(PGUI_CONSOLE_DATA GuiData, UINT msg, WPARAM wParam, LPARAM lParam)
case WM_MOUSEMOVE:
{
COORD c;
if (!(wParam & MK_LBUTTON)) break;
if (!(GuiData->Selection.dwFlags & CONSOLE_MOUSE_DOWN)) break;
c = PointToCoord(GuiData, lParam); /* TODO: Scroll buffer to bring c into view */
UpdateSelection(GuiData, &c);
// TODO: Scroll buffer to bring SelectionCursor into view
GuiData->dwSelectionCursor = PointToCoord(GuiData, lParam);
UpdateSelection(GuiData, NULL, &GuiData->dwSelectionCursor);
break;
}
@ -1546,7 +1689,7 @@ Copy(PGUI_CONSOLE_DATA GuiData)
}
/* Clear the selection */
UpdateSelection(GuiData, NULL);
UpdateSelection(GuiData, NULL, NULL);
}
VOID

View file

@ -65,6 +65,7 @@ typedef struct _GUI_CONSOLE_DATA
PCONSOLE_SCREEN_BUFFER ActiveBuffer; /* Pointer to the active screen buffer (then maybe the previous Console member is redundant?? Or not...) */
CONSOLE_SELECTION_INFO Selection; /* Contains information about the selection */
COORD dwSelectionCursor; /* Selection cursor position, most of the time different from Selection.dwSelectionAnchor */
BOOL LineSelection; /* TRUE if line-oriented selection (a la *nix terminals), FALSE if block-oriented selection (default on Windows) */
GUI_CONSOLE_INFO GuiInfo; /* GUI terminal settings */
} GUI_CONSOLE_DATA, *PGUI_CONSOLE_DATA;

View file

@ -34,7 +34,7 @@ GuiCopyFromGraphicsBuffer(PGRAPHICS_SCREEN_BUFFER Buffer,
selWidth = GuiData->Selection.srSelection.Right - GuiData->Selection.srSelection.Left + 1;
selHeight = GuiData->Selection.srSelection.Bottom - GuiData->Selection.srSelection.Top + 1;
DPRINT1("Selection is (%d|%d) to (%d|%d)\n",
DPRINT("Selection is (%d|%d) to (%d|%d)\n",
GuiData->Selection.srSelection.Left,
GuiData->Selection.srSelection.Top,
GuiData->Selection.srSelection.Right,

View file

@ -140,7 +140,8 @@ InvalidateCell(PGUI_CONSOLE_DATA GuiData,
VOID
SwitchFullScreen(PGUI_CONSOLE_DATA GuiData, BOOL FullScreen);
VOID
CreateSysMenu(HWND hWnd);
static LRESULT CALLBACK
GuiConsoleNotifyWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
@ -199,6 +200,9 @@ GuiConsoleNotifyWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
GuiConsoleMoveWindow(GuiData); // FIXME: This MUST be done via the CreateWindowExW call.
SendMessageW(GuiData->hWindow, PM_RESIZE_TERMINAL, 0, 0);
// FIXME: HACK: Potential HACK for CORE-8129; see revision 63595.
CreateSysMenu(GuiData->hWindow);
/* Switch to full-screen mode if necessary */
// FIXME: Move elsewhere, it cause misdrawings of the window.
if (GuiData->GuiInfo.FullScreen) SwitchFullScreen(GuiData, TRUE);
@ -533,8 +537,11 @@ GuiInitFrontEnd(IN OUT PFRONTEND This,
GuiData->CmdIdLow = GuiData->CmdIdHigh = 0;
/* Initialize the selection */
RtlZeroMemory(&GuiData->Selection, sizeof(CONSOLE_SELECTION_INFO));
RtlZeroMemory(&GuiData->Selection, sizeof(GuiData->Selection));
GuiData->Selection.dwFlags = CONSOLE_NO_SELECTION;
RtlZeroMemory(&GuiData->dwSelectionCursor, sizeof(GuiData->dwSelectionCursor));
GuiData->LineSelection = FALSE; // Default to block selection
// TODO: Retrieve the selection mode via the registry.
/*
* We need to wait until the GUI has been fully initialized

View file

@ -22,3 +22,9 @@ BEGIN
*/
IDS_TERMINAL_TITLE "ReactOS Console"
END
STRINGTABLE
BEGIN
IDS_MARK_TITLE "Mark"
IDS_SELECT_TITLE "Select"
END

View file

@ -24,3 +24,9 @@ BEGIN
*/
IDS_TERMINAL_TITLE "ReactOS Console"
END
STRINGTABLE
BEGIN
IDS_MARK_TITLE "Mark"
IDS_SELECT_TITLE "Select"
END

View file

@ -22,3 +22,9 @@ BEGIN
*/
IDS_TERMINAL_TITLE "ReactOS Eingabeaufforderung"
END
STRINGTABLE
BEGIN
IDS_MARK_TITLE "Mark"
IDS_SELECT_TITLE "Select"
END

View file

@ -22,3 +22,9 @@ BEGIN
*/
IDS_TERMINAL_TITLE "ReactOS Console"
END
STRINGTABLE
BEGIN
IDS_MARK_TITLE "Mark"
IDS_SELECT_TITLE "Select"
END

View file

@ -22,3 +22,9 @@ BEGIN
*/
IDS_TERMINAL_TITLE "ReactOS Console"
END
STRINGTABLE
BEGIN
IDS_MARK_TITLE "Mark"
IDS_SELECT_TITLE "Select"
END

View file

@ -24,3 +24,9 @@ BEGIN
*/
IDS_TERMINAL_TITLE "ReactOS Console"
END
STRINGTABLE
BEGIN
IDS_MARK_TITLE "Mark"
IDS_SELECT_TITLE "Select"
END

View file

@ -24,3 +24,9 @@ BEGIN
*/
IDS_TERMINAL_TITLE "ReactOS Console"
END
STRINGTABLE
BEGIN
IDS_MARK_TITLE "Marquage"
IDS_SELECT_TITLE "Sélection"
END

View file

@ -22,3 +22,9 @@ BEGIN
*/
IDS_TERMINAL_TITLE "ReactOS Console"
END
STRINGTABLE
BEGIN
IDS_MARK_TITLE "Mark"
IDS_SELECT_TITLE "Select"
END

View file

@ -22,3 +22,9 @@ BEGIN
*/
IDS_TERMINAL_TITLE "ReactOS Console"
END
STRINGTABLE
BEGIN
IDS_MARK_TITLE "Mark"
IDS_SELECT_TITLE "Select"
END

View file

@ -24,3 +24,9 @@ BEGIN
*/
IDS_TERMINAL_TITLE "ReactOS Console"
END
STRINGTABLE
BEGIN
IDS_MARK_TITLE "Mark"
IDS_SELECT_TITLE "Select"
END

View file

@ -22,3 +22,9 @@ BEGIN
*/
IDS_TERMINAL_TITLE "ReactOS Console"
END
STRINGTABLE
BEGIN
IDS_MARK_TITLE "Mark"
IDS_SELECT_TITLE "Select"
END

View file

@ -22,3 +22,9 @@ BEGIN
*/
IDS_TERMINAL_TITLE "ReactOS Console"
END
STRINGTABLE
BEGIN
IDS_MARK_TITLE "Mark"
IDS_SELECT_TITLE "Select"
END

View file

@ -4,6 +4,7 @@
* https://sourceforge.net/projects/reactospl
* Translation update by Olaf Siejka (Caemyr), Apr 2011
* UTF-8 conversion by Caemyr (May, 2011)
* Update by wojo664 (June 2014)
*/
LANGUAGE LANG_POLISH, SUBLANG_DEFAULT
@ -30,3 +31,9 @@ BEGIN
*/
IDS_TERMINAL_TITLE "Konsola ReactOS"
END
STRINGTABLE
BEGIN
IDS_MARK_TITLE "Zaznacz"
IDS_SELECT_TITLE "Wybierz"
END

View file

@ -24,3 +24,9 @@ BEGIN
*/
IDS_TERMINAL_TITLE "ReactOS Console"
END
STRINGTABLE
BEGIN
IDS_MARK_TITLE "Mark"
IDS_SELECT_TITLE "Select"
END

View file

@ -24,3 +24,9 @@ BEGIN
*/
IDS_TERMINAL_TITLE "Consola ReactOS"
END
STRINGTABLE
BEGIN
IDS_MARK_TITLE "Mark"
IDS_SELECT_TITLE "Select"
END

View file

@ -22,3 +22,9 @@ BEGIN
*/
IDS_TERMINAL_TITLE "ReactOS Console"
END
STRINGTABLE
BEGIN
IDS_MARK_TITLE "Mark"
IDS_SELECT_TITLE "Select"
END

View file

@ -27,3 +27,9 @@ BEGIN
*/
IDS_TERMINAL_TITLE "ReactOS Console"
END
STRINGTABLE
BEGIN
IDS_MARK_TITLE "Mark"
IDS_SELECT_TITLE "Select"
END

View file

@ -24,3 +24,9 @@ BEGIN
*/
IDS_TERMINAL_TITLE "ReactOS Console"
END
STRINGTABLE
BEGIN
IDS_MARK_TITLE "Mark"
IDS_SELECT_TITLE "Select"
END

View file

@ -24,3 +24,9 @@ BEGIN
*/
IDS_TERMINAL_TITLE "ReactOS Console"
END
STRINGTABLE
BEGIN
IDS_MARK_TITLE "Mark"
IDS_SELECT_TITLE "Select"
END

View file

@ -24,3 +24,9 @@ BEGIN
*/
IDS_TERMINAL_TITLE "ReactOS Console"
END
STRINGTABLE
BEGIN
IDS_MARK_TITLE "Mark"
IDS_SELECT_TITLE "Select"
END

View file

@ -22,3 +22,9 @@ BEGIN
*/
IDS_TERMINAL_TITLE "ReactOS Console"
END
STRINGTABLE
BEGIN
IDS_MARK_TITLE "Mark"
IDS_SELECT_TITLE "Select"
END

View file

@ -22,3 +22,9 @@ BEGIN
*/
IDS_TERMINAL_TITLE "ReactOS Console"
END
STRINGTABLE
BEGIN
IDS_MARK_TITLE "Mark"
IDS_SELECT_TITLE "Select"
END

View file

@ -18,17 +18,18 @@
#define ID_SYSTEM_DEFAULTS 0xFFF6
#define ID_SYSTEM_PROPERTIES 0xFFF7
#define NCPOPUP_MENU 103
#define IDS_EDIT 204
#define IDS_MARK 205
#define IDS_COPY 206
#define IDS_PASTE 207
#define IDS_SELECTALL 208
#define IDS_SCROLL 209
#define IDS_FIND 210
#define IDS_DEFAULTS 211
#define IDS_PROPERTIES 212
#define IDS_EDIT 204
#define IDS_MARK 205
#define IDS_COPY 206
#define IDS_PASTE 207
#define IDS_SELECTALL 208
#define IDS_SCROLL 209
#define IDS_FIND 210
#define IDS_DEFAULTS 211
#define IDS_PROPERTIES 212
#define IDS_MARK_TITLE 220
#define IDS_SELECT_TITLE 221
// Scrollbar resource ids. Unused.
/*

View file

@ -18,6 +18,10 @@
#include "guiterm.h"
/* GLOBALS ********************************************************************/
#define IS_WHITESPACE(c) ((c) == L'\0' || (c) == L' ' || (c) == L'\t')
/* FUNCTIONS ******************************************************************/
COLORREF PaletteRGBFromAttrib(PCONSOLE Console, WORD Attribute)
@ -31,38 +35,33 @@ COLORREF PaletteRGBFromAttrib(PCONSOLE Console, WORD Attribute)
return PALETTERGB(pe.peRed, pe.peGreen, pe.peBlue);
}
VOID
GuiCopyFromTextModeBuffer(PTEXTMODE_SCREEN_BUFFER Buffer,
PGUI_CONSOLE_DATA GuiData)
static VOID
CopyBlock(PTEXTMODE_SCREEN_BUFFER Buffer,
PSMALL_RECT Selection)
{
/*
* This function supposes that the system clipboard was opened.
*/
/*
* Pressing the Shift key while copying text, allows us to copy
* text without newline characters (inline-text copy mode).
*/
BOOL InlineCopyMode = (GetKeyState(VK_SHIFT) & 0x8000);
BOOL InlineCopyMode = !!(GetKeyState(VK_SHIFT) & 0x8000);
HANDLE hData;
PCHAR_INFO ptr;
LPWSTR data, dstPos;
ULONG selWidth, selHeight;
ULONG xPos, yPos, size;
ULONG xPos, yPos;
ULONG size;
selWidth = GuiData->Selection.srSelection.Right - GuiData->Selection.srSelection.Left + 1;
selHeight = GuiData->Selection.srSelection.Bottom - GuiData->Selection.srSelection.Top + 1;
DPRINT("Selection is (%d|%d) to (%d|%d)\n",
GuiData->Selection.srSelection.Left,
GuiData->Selection.srSelection.Top,
GuiData->Selection.srSelection.Right,
GuiData->Selection.srSelection.Bottom);
DPRINT("CopyBlock(%u, %u, %u, %u)\n",
Selection->Left, Selection->Top, Selection->Right, Selection->Bottom);
#ifdef IS_WHITESPACE
#undef IS_WHITESPACE
#endif
#define IS_WHITESPACE(c) ((c) == L'\0' || (c) == L' ' || (c) == L'\t')
/* Prevent against empty blocks */
if (Selection == NULL) return;
if (Selection->Left > Selection->Right || Selection->Top > Selection->Bottom)
return;
selWidth = Selection->Right - Selection->Left + 1;
selHeight = Selection->Bottom - Selection->Top + 1;
/* Basic size for one line... */
size = selWidth;
@ -75,6 +74,11 @@ GuiCopyFromTextModeBuffer(PTEXTMODE_SCREEN_BUFFER Buffer,
*/
size += (selWidth + (!InlineCopyMode ? 2 : 0)) * (selHeight - 1);
}
else
{
DPRINT1("This case must never happen, because selHeight is at least == 1\n");
}
size += 1; /* Null-termination */
size *= sizeof(WCHAR);
@ -97,8 +101,8 @@ GuiCopyFromTextModeBuffer(PTEXTMODE_SCREEN_BUFFER Buffer,
ULONG length = selWidth;
ptr = ConioCoordToPointer(Buffer,
GuiData->Selection.srSelection.Left,
GuiData->Selection.srSelection.Top + yPos);
Selection->Left,
Selection->Top + yPos);
/* Trim whitespace from the right */
while (length > 0)
@ -116,16 +120,15 @@ GuiCopyFromTextModeBuffer(PTEXTMODE_SCREEN_BUFFER Buffer,
* Sometimes, applications can put NULL chars into the screen-buffer
* (this behaviour is allowed). Detect this and replace by a space.
*/
dstPos[xPos] = (ptr[xPos].Char.UnicodeChar ? ptr[xPos].Char.UnicodeChar : L' ');
*dstPos++ = (ptr[xPos].Char.UnicodeChar ? ptr[xPos].Char.UnicodeChar : L' ');
}
dstPos += length;
/* Add newline characters if we are not in inline-text copy mode */
if (!InlineCopyMode)
{
if (yPos != (selHeight - 1))
{
wcscat(data, L"\r\n");
wcscat(dstPos, L"\r\n");
dstPos += 2;
}
}
@ -138,6 +141,127 @@ GuiCopyFromTextModeBuffer(PTEXTMODE_SCREEN_BUFFER Buffer,
SetClipboardData(CF_UNICODETEXT, hData);
}
static VOID
CopyLines(PTEXTMODE_SCREEN_BUFFER Buffer,
PCOORD Begin,
PCOORD End)
{
HANDLE hData;
PCHAR_INFO ptr;
LPWSTR data, dstPos;
ULONG NumChars, size;
ULONG xPos, yPos, xBeg, xEnd;
DPRINT("CopyLines((%u, %u) ; (%u, %u))\n",
Begin->X, Begin->Y, End->X, End->Y);
/* Prevent against empty blocks... */
if (Begin == NULL || End == NULL) return;
/* ... or malformed blocks */
if (Begin->Y > End->Y || (Begin->Y == End->Y && Begin->X > End->X)) return;
/* Compute the number of characters to copy */
if (End->Y == Begin->Y) // top == bottom
{
NumChars = End->X - Begin->X + 1;
}
else // if (End->Y > Begin->Y)
{
NumChars = Buffer->ScreenBufferSize.X - Begin->X;
if (End->Y >= Begin->Y + 2)
{
NumChars += (End->Y - Begin->Y - 1) * Buffer->ScreenBufferSize.X;
}
NumChars += End->X + 1;
}
size = (NumChars + 1) * sizeof(WCHAR); /* Null-terminated */
/* Allocate some memory area to be given to the clipboard, so it will not be freed here */
hData = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, size);
if (hData == NULL) return;
data = GlobalLock(hData);
if (data == NULL)
{
GlobalFree(hData);
return;
}
DPRINT("Copying %d characters\n", NumChars);
dstPos = data;
/*
* We need to walk per-lines, and not just looping in the big screen-buffer
* array, because of the way things are stored inside it. The downside is
* that it makes the code more complicated.
*/
for (yPos = Begin->Y; (yPos <= End->Y) && (NumChars > 0); yPos++)
{
xBeg = (yPos == Begin->Y ? Begin->X : 0);
xEnd = (yPos == End->Y ? End->X : Buffer->ScreenBufferSize.X - 1);
ptr = ConioCoordToPointer(Buffer, 0, yPos);
/* Copy only the characters, leave attributes alone */
for (xPos = xBeg; (xPos <= xEnd) && (NumChars-- > 0); xPos++)
{
/*
* Sometimes, applications can put NULL chars into the screen-buffer
* (this behaviour is allowed). Detect this and replace by a space.
*/
*dstPos++ = (ptr[xPos].Char.UnicodeChar ? ptr[xPos].Char.UnicodeChar : L' ');
}
}
DPRINT("Setting data <%S> to clipboard\n", data);
GlobalUnlock(hData);
EmptyClipboard();
SetClipboardData(CF_UNICODETEXT, hData);
}
VOID
GetSelectionBeginEnd(PCOORD Begin, PCOORD End,
PCOORD SelectionAnchor,
PSMALL_RECT SmallRect);
VOID
GuiCopyFromTextModeBuffer(PTEXTMODE_SCREEN_BUFFER Buffer,
PGUI_CONSOLE_DATA GuiData)
{
/*
* This function supposes that the system clipboard was opened.
*/
BOOL LineSelection = GuiData->LineSelection;
DPRINT("Selection is (%d|%d) to (%d|%d) in %s mode\n",
GuiData->Selection.srSelection.Left,
GuiData->Selection.srSelection.Top,
GuiData->Selection.srSelection.Right,
GuiData->Selection.srSelection.Bottom,
(LineSelection ? "line" : "block"));
if (!LineSelection)
{
CopyBlock(Buffer, &GuiData->Selection.srSelection);
}
else
{
COORD Begin, End;
GetSelectionBeginEnd(&Begin, &End,
&GuiData->Selection.dwSelectionAnchor,
&GuiData->Selection.srSelection);
CopyLines(Buffer, &Begin, &End);
}
}
VOID
GuiPasteToTextModeBuffer(PTEXTMODE_SCREEN_BUFFER Buffer,
PGUI_CONSOLE_DATA GuiData)

View file

@ -32,6 +32,7 @@ KeyboardHookProc(int nCode,
WPARAM wParam,
LPARAM lParam)
{
DPRINT1("KeyboardHookProc Processing!\n");
return CallNextHookEx(hhk, nCode, wParam, lParam);
}
/*** END - HACK from win32csr... ***/