/* INCLUDES *******************************************************************/
#include <consrv.h>
-
+#include <intrin.h>
#include <windowsx.h>
#define NDEBUG
PCONSOLE_PROCESS_DATA ProcessData;
CLIENT_ID ConsoleLeaderCID;
- ProcessData = CONTAINING_RECORD(GuiData->Console->ProcessList.Blink,
- CONSOLE_PROCESS_DATA,
- ConsoleLink);
+ ProcessData = ConDrvGetConsoleLeaderProcess(GuiData->Console);
ConsoleLeaderCID = ProcessData->Process->ClientId;
SetWindowLongPtrW(GuiData->hWindow, GWLP_CONSOLE_LEADER_PID,
(LONG_PTR)(ConsoleLeaderCID.UniqueProcess));
static VOID
CreateSysMenu(HWND hWnd)
{
+ MENUITEMINFOW mii;
+ WCHAR szMenuStringBack[255];
+ WCHAR *ptrTab;
HMENU hMenu = GetSystemMenu(hWnd, FALSE);
if (hMenu != NULL)
{
+ mii.cbSize = sizeof(mii);
+ mii.fMask = MIIM_STRING;
+ mii.dwTypeData = szMenuStringBack;
+ mii.cch = sizeof(szMenuStringBack)/sizeof(WCHAR);
+
+ GetMenuItemInfoW(hMenu, SC_CLOSE, FALSE, &mii);
+
+ ptrTab = wcschr(szMenuStringBack, '\t');
+ if (ptrTab)
+ {
+ *ptrTab = '\0';
+ mii.cch = wcslen(szMenuStringBack);
+
+ SetMenuItemInfoW(hMenu, SC_CLOSE, FALSE, &mii);
+ }
+
AppendMenuItems(hMenu, GuiConsoleMainMenuItems);
DrawMenuBar(hWnd);
}
{
INPUT_RECORD er;
+ DPRINT1("Menu item ID: %d\n", CmdId);
+
+ if (!ConDrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE)) return;
+
er.EventType = MENU_EVENT;
er.Event.MenuEvent.dwCommandId = CmdId;
-
- DPRINT("Menu item ID: %d\n", CmdId);
ConioProcessInputEvent(Console, &er);
+
+ LeaveCriticalSection(&Console->Lock);
}
static VOID
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)
{
- PCONSOLE Console = GuiData->Console;
PCONSOLE_SCREEN_BUFFER ActiveBuffer = GuiData->ActiveBuffer;
/* Clear the old selection */
- // UpdateSelection(GuiData, NULL);
- Console->Selection.dwFlags = CONSOLE_NO_SELECTION;
+ GuiData->Selection.dwFlags = CONSOLE_NO_SELECTION;
/* Restart a new selection */
- Console->dwSelectionCursor.X = ActiveBuffer->ViewOrigin.X;
- Console->dwSelectionCursor.Y = ActiveBuffer->ViewOrigin.Y;
- Console->Selection.dwSelectionAnchor = Console->dwSelectionCursor;
- UpdateSelection(GuiData, &Console->Selection.dwSelectionAnchor);
+ GuiData->dwSelectionCursor = ActiveBuffer->ViewOrigin;
+ UpdateSelection(GuiData,
+ &GuiData->dwSelectionCursor,
+ &GuiData->dwSelectionCursor);
}
static VOID
SelectAll(PGUI_CONSOLE_DATA GuiData)
{
- PCONSOLE Console = GuiData->Console;
PCONSOLE_SCREEN_BUFFER ActiveBuffer = GuiData->ActiveBuffer;
+ COORD SelectionAnchor;
/* Clear the old selection */
- // UpdateSelection(GuiData, NULL);
- Console->Selection.dwFlags = CONSOLE_NO_SELECTION;
+ GuiData->Selection.dwFlags = CONSOLE_NO_SELECTION;
/*
* The selection area extends to the whole screen buffer's width.
*/
- Console->Selection.dwSelectionAnchor.X = 0;
- Console->Selection.dwSelectionAnchor.Y = 0;
- Console->dwSelectionCursor.X = ActiveBuffer->ScreenBufferSize.X - 1;
+ SelectionAnchor.X = SelectionAnchor.Y = 0;
+ GuiData->dwSelectionCursor.X = ActiveBuffer->ScreenBufferSize.X - 1;
/*
* Determine whether the selection must extend to just some part
* We select all the characters from the first line
* to the line where the cursor is positioned.
*/
- Console->dwSelectionCursor.Y = ActiveBuffer->CursorPosition.Y;
+ GuiData->dwSelectionCursor.Y = ActiveBuffer->CursorPosition.Y;
}
else /* if (GetType(ActiveBuffer) == GRAPHICS_BUFFER) */
{
/*
* We select all the screen buffer area.
*/
- Console->dwSelectionCursor.Y = ActiveBuffer->ScreenBufferSize.Y - 1;
+ GuiData->dwSelectionCursor.Y = ActiveBuffer->ScreenBufferSize.Y - 1;
}
/* Restart a new selection */
- Console->Selection.dwFlags |= CONSOLE_MOUSE_SELECTION;
- UpdateSelection(GuiData, &Console->dwSelectionCursor);
+ GuiData->Selection.dwFlags |= CONSOLE_MOUSE_SELECTION;
+ UpdateSelection(GuiData, &SelectionAnchor, &GuiData->dwSelectionCursor);
}
static LRESULT
LRESULT Ret = TRUE;
PCONSOLE Console = GuiData->Console;
- if (!ConDrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE))
- {
- Ret = FALSE;
- goto Quit;
- }
-
/*
* In case the selected menu item belongs to the user-reserved menu id range,
* send to him a menu event and return directly. The user must handle those
if (GuiData->CmdIdLow <= (UINT)wParam && (UINT)wParam <= GuiData->CmdIdHigh)
{
SendMenuEvent(Console, (UINT)wParam);
- goto Unlock_Quit;
+ goto Quit;
}
/* ... otherwise, perform actions. */
break;
}
-Unlock_Quit:
- LeaveCriticalSection(&Console->Lock);
Quit:
if (!Ret)
Ret = DefWindowProcW(GuiData->hWindow, WM_SYSCOMMAND, wParam, lParam);
er.Event.FocusEvent.bSetFocus = SetFocus;
ConioProcessInputEvent(Console, &er);
+ LeaveCriticalSection(&Console->Lock);
+
if (SetFocus)
DPRINT1("TODO: Create console caret\n");
else
DPRINT1("TODO: Destroy console caret\n");
-
- LeaveCriticalSection(&Console->Lock);
}
static VOID
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, &Console->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(Console->Selection.dwSelectionAnchor.X, coord->X);
- rc.Top = min(Console->Selection.dwSelectionAnchor.Y, coord->Y);
- rc.Right = max(Console->Selection.dwSelectionAnchor.X, coord->X);
- rc.Bottom = max(Console->Selection.dwSelectionAnchor.Y, coord->Y);
+ rc.Left = min(GuiData->Selection.dwSelectionAnchor.X, coord->X);
+ rc.Top = min(GuiData->Selection.dwSelectionAnchor.Y, coord->Y);
+ 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 (Console->Selection.dwFlags & CONSOLE_SELECTION_NOT_EMPTY)
+ if (GuiData->Selection.dwFlags & CONSOLE_SELECTION_NOT_EMPTY)
{
- if (memcmp(&rc, &Console->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);
}
- Console->Selection.dwFlags |= CONSOLE_SELECTION_NOT_EMPTY;
- Console->Selection.srSelection = rc;
- Console->dwSelectionCursor = *coord;
+ DeleteObject(newRgn);
+
+ GuiData->Selection.dwFlags |= CONSOLE_SELECTION_NOT_EMPTY;
+ GuiData->Selection.srSelection = rc;
+ GuiData->dwSelectionCursor = *coord;
- if ((Console->Selection.dwFlags & CONSOLE_SELECTION_IN_PROGRESS) == 0)
+ 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 (Console->Selection.dwFlags & CONSOLE_SELECTION_NOT_EMPTY)
+ if (GuiData->Selection.dwFlags & CONSOLE_SELECTION_NOT_EMPTY)
{
- InvalidateRect(GuiData->hWindow, &oldRect, FALSE);
+ InvalidateRgn(GuiData->hWindow, oldRgn, FALSE);
}
- if (Console->Selection.dwFlags & CONSOLE_MOUSE_SELECTION)
- {
- SelectionType = L"Selection - ";
- }
- else
+ /*
+ * 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);
+
+ /*
+ * Prepend the selection type string to the current console title
+ * if we succeeded in retrieving a valid localized string.
+ */
+ if (SelTypeStr)
{
- SelectionType = L"Mark - ";
- }
+ // 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);
- 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);
+ SetWindowText(GuiData->hWindow, WindowTitle);
+ ConsoleFreeHeap(WindowTitle);
+ }
- Console->Selection.dwFlags |= CONSOLE_SELECTION_IN_PROGRESS;
+ GuiData->Selection.dwFlags |= CONSOLE_SELECTION_IN_PROGRESS;
ConioPause(Console, PAUSED_FROM_SELECTION);
}
}
else
{
/* Clear the selection */
- if (Console->Selection.dwFlags & CONSOLE_SELECTION_NOT_EMPTY)
+ if (GuiData->Selection.dwFlags & CONSOLE_SELECTION_NOT_EMPTY)
{
- InvalidateRect(GuiData->hWindow, &oldRect, FALSE);
+ InvalidateRgn(GuiData->hWindow, oldRgn, FALSE);
}
- Console->Selection.dwFlags = CONSOLE_NO_SELECTION;
+ GuiData->Selection.dwFlags = CONSOLE_NO_SELECTION;
ConioUnpause(Console, PAUSED_FROM_SELECTION);
+ /* Restore the console title */
SetWindowText(GuiData->hWindow, Console->Title.Buffer);
}
+
+ DeleteObject(oldRgn);
}
static VOID
OnPaint(PGUI_CONSOLE_DATA GuiData)
{
- BOOL Success = TRUE;
- PCONSOLE Console = GuiData->Console;
PCONSOLE_SCREEN_BUFFER ActiveBuffer;
PAINTSTRUCT ps;
RECT rcPaint;
- if (!ConDrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE))
- {
- Success = FALSE;
- goto Quit;
- }
ActiveBuffer = GuiData->ActiveBuffer;
BeginPaint(GuiData->hWindow, &ps);
rcPaint.top,
SRCCOPY);
- if (Console->Selection.dwFlags & CONSOLE_SELECTION_NOT_EMPTY)
+ /* Draw the selection region if needed */
+ if (GuiData->Selection.dwFlags & CONSOLE_SELECTION_NOT_EMPTY)
{
- SmallRectToRect(GuiData, &rcPaint, &Console->Selection.srSelection);
-
- /* Invert the selection */
- if (IntersectRect(&rcPaint, &ps.rcPaint, &rcPaint))
- {
- InvertRect(ps.hdc, &rcPaint);
- }
+ PaintSelectionRect(GuiData, &ps);
}
LeaveCriticalSection(&GuiData->Lock);
}
EndPaint(GuiData->hWindow, &ps);
-Quit:
- if (Success)
- LeaveCriticalSection(&Console->Lock);
- else
- DefWindowProcW(GuiData->hWindow, WM_PAINT, 0, 0);
-
return;
}
ActiveBuffer = GuiData->ActiveBuffer;
- if (Console->Selection.dwFlags & CONSOLE_SELECTION_IN_PROGRESS)
+ if (GuiData->Selection.dwFlags & CONSOLE_SELECTION_IN_PROGRESS)
{
WORD VirtualKeyCode = LOWORD(wParam);
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;
}
- if ((Console->Selection.dwFlags & CONSOLE_MOUSE_SELECTION) == 0)
+ if ((GuiData->Selection.dwFlags & CONSOLE_MOUSE_SELECTION) == 0)
{
/* Keyboard selection mode */
BOOL Interpreted = FALSE;
- BOOL MajPressed = (GetKeyState(VK_SHIFT) & 0x8000);
+ BOOL MajPressed = !!(GetKeyState(VK_SHIFT) & 0x8000);
switch (VirtualKeyCode)
{
case VK_LEFT:
{
Interpreted = TRUE;
- if (Console->dwSelectionCursor.X > 0)
- Console->dwSelectionCursor.X--;
+ if (GuiData->dwSelectionCursor.X > 0)
+ GuiData->dwSelectionCursor.X--;
break;
}
case VK_RIGHT:
{
Interpreted = TRUE;
- if (Console->dwSelectionCursor.X < ActiveBuffer->ScreenBufferSize.X - 1)
- Console->dwSelectionCursor.X++;
+ if (GuiData->dwSelectionCursor.X < ActiveBuffer->ScreenBufferSize.X - 1)
+ GuiData->dwSelectionCursor.X++;
break;
}
case VK_UP:
{
Interpreted = TRUE;
- if (Console->dwSelectionCursor.Y > 0)
- Console->dwSelectionCursor.Y--;
+ if (GuiData->dwSelectionCursor.Y > 0)
+ GuiData->dwSelectionCursor.Y--;
break;
}
case VK_DOWN:
{
Interpreted = TRUE;
- if (Console->dwSelectionCursor.Y < ActiveBuffer->ScreenBufferSize.Y - 1)
- Console->dwSelectionCursor.Y++;
+ if (GuiData->dwSelectionCursor.Y < ActiveBuffer->ScreenBufferSize.Y - 1)
+ GuiData->dwSelectionCursor.Y++;
break;
}
case VK_HOME:
{
Interpreted = TRUE;
- Console->dwSelectionCursor.X = 0;
- Console->dwSelectionCursor.Y = 0;
+ GuiData->dwSelectionCursor.X = 0;
+ GuiData->dwSelectionCursor.Y = 0;
break;
}
case VK_END:
{
Interpreted = TRUE;
- Console->dwSelectionCursor.Y = ActiveBuffer->ScreenBufferSize.Y - 1;
+ GuiData->dwSelectionCursor.Y = ActiveBuffer->ScreenBufferSize.Y - 1;
break;
}
case VK_PRIOR:
{
Interpreted = TRUE;
- Console->dwSelectionCursor.Y -= ActiveBuffer->ViewSize.Y;
- if (Console->dwSelectionCursor.Y < 0)
- Console->dwSelectionCursor.Y = 0;
+ GuiData->dwSelectionCursor.Y -= ActiveBuffer->ViewSize.Y;
+ if (GuiData->dwSelectionCursor.Y < 0)
+ GuiData->dwSelectionCursor.Y = 0;
break;
}
case VK_NEXT:
{
Interpreted = TRUE;
- Console->dwSelectionCursor.Y += ActiveBuffer->ViewSize.Y;
- if (Console->dwSelectionCursor.Y >= ActiveBuffer->ScreenBufferSize.Y)
- Console->dwSelectionCursor.Y = ActiveBuffer->ScreenBufferSize.Y - 1;
+ GuiData->dwSelectionCursor.Y += ActiveBuffer->ViewSize.Y;
+ if (GuiData->dwSelectionCursor.Y >= ActiveBuffer->ScreenBufferSize.Y)
+ GuiData->dwSelectionCursor.Y = ActiveBuffer->ScreenBufferSize.Y - 1;
break;
}
if (Interpreted)
{
- if (!MajPressed)
- Console->Selection.dwSelectionAnchor = Console->dwSelectionCursor;
-
- UpdateSelection(GuiData, &Console->dwSelectionCursor);
+ UpdateSelection(GuiData,
+ !MajPressed ? &GuiData->dwSelectionCursor : NULL,
+ &GuiData->dwSelectionCursor);
}
else if (!IsSystemKey(VirtualKeyCode))
{
if (!IsSystemKey(VirtualKeyCode))
{
/* Clear the selection and send the key into the input buffer */
- UpdateSelection(GuiData, NULL);
+ UpdateSelection(GuiData, NULL, NULL);
}
else
{
}
}
- if ((Console->Selection.dwFlags & CONSOLE_SELECTION_IN_PROGRESS) == 0)
+ if ((GuiData->Selection.dwFlags & CONSOLE_SELECTION_IN_PROGRESS) == 0)
{
MSG Message;
goto Quit;
}
- if ( (Console->Selection.dwFlags & CONSOLE_SELECTION_IN_PROGRESS) ||
+ if ( (GuiData->Selection.dwFlags & CONSOLE_SELECTION_IN_PROGRESS) ||
(Console->QuickEdit) )
{
switch (msg)
case WM_LBUTTONDOWN:
{
/* Clear the old selection */
- // UpdateSelection(GuiData, NULL);
- Console->Selection.dwFlags = CONSOLE_NO_SELECTION;
+ GuiData->Selection.dwFlags = CONSOLE_NO_SELECTION;
/* Restart a new selection */
- Console->Selection.dwSelectionAnchor = PointToCoord(GuiData, lParam);
+ GuiData->dwSelectionCursor = PointToCoord(GuiData, lParam);
SetCapture(GuiData->hWindow);
- Console->Selection.dwFlags |= CONSOLE_MOUSE_SELECTION | CONSOLE_MOUSE_DOWN;
- UpdateSelection(GuiData, &Console->Selection.dwSelectionAnchor);
+ GuiData->Selection.dwFlags |= CONSOLE_MOUSE_SELECTION | CONSOLE_MOUSE_DOWN;
+ UpdateSelection(GuiData,
+ &GuiData->dwSelectionCursor,
+ &GuiData->dwSelectionCursor);
break;
}
case WM_LBUTTONUP:
{
- // COORD c;
-
- if (!(Console->Selection.dwFlags & CONSOLE_MOUSE_DOWN)) break;
+ if (!(GuiData->Selection.dwFlags & CONSOLE_MOUSE_DOWN)) break;
- // c = PointToCoord(GuiData, lParam);
- Console->Selection.dwFlags &= ~CONSOLE_MOUSE_DOWN;
- // UpdateSelection(GuiData, &c);
+ // GuiData->dwSelectionCursor = PointToCoord(GuiData, lParam);
+ GuiData->Selection.dwFlags &= ~CONSOLE_MOUSE_DOWN;
+ // UpdateSelection(GuiData, NULL, &GuiData->dwSelectionCursor);
ReleaseCapture();
break;
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;
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;
* Update the selection started with the single
* left-click that preceded this double-click.
*/
- Console->Selection.dwSelectionAnchor = cL;
- Console->dwSelectionCursor = cR;
-
- Console->Selection.dwFlags |= CONSOLE_MOUSE_SELECTION | CONSOLE_MOUSE_DOWN;
- UpdateSelection(GuiData, &Console->dwSelectionCursor);
+ GuiData->Selection.dwFlags |= CONSOLE_MOUSE_SELECTION | CONSOLE_MOUSE_DOWN;
+ UpdateSelection(GuiData, &cL, &cR);
/* Ignore the next mouse move signal */
GuiData->IgnoreNextMouseSignal = TRUE;
case WM_RBUTTONDOWN:
case WM_RBUTTONDBLCLK:
{
- if (!(Console->Selection.dwFlags & CONSOLE_SELECTION_NOT_EMPTY))
+ if (!(GuiData->Selection.dwFlags & CONSOLE_SELECTION_NOT_EMPTY))
{
Paste(GuiData);
}
case WM_MOUSEMOVE:
{
- COORD c;
-
if (!(wParam & MK_LBUTTON)) break;
- if (!(Console->Selection.dwFlags & CONSOLE_MOUSE_DOWN)) 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;
}
}
/* Clear the selection */
- UpdateSelection(GuiData, NULL);
+ UpdateSelection(GuiData, NULL, NULL);
}
VOID
static VOID
OnMove(PGUI_CONSOLE_DATA GuiData)
{
- PCONSOLE Console = GuiData->Console;
RECT rcWnd;
- if (!ConDrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE)) return;
-
// TODO: Simplify the code.
// See: GuiConsoleNotifyWndProc() PM_CREATE_CONSOLE.
GetWindowRect(GuiData->hWindow, &rcWnd);
GuiData->GuiInfo.WindowOrigin.x = rcWnd.left;
GuiData->GuiInfo.WindowOrigin.y = rcWnd.top;
-
- LeaveCriticalSection(&Console->Lock);
}
/*
break;
}
+ /* Detect Alt-Esc/Space/Tab presses defer to DefWindowProc */
+ if ( (HIWORD(lParam) & KF_ALTDOWN) && (wParam == VK_ESCAPE || wParam == VK_SPACE || wParam == VK_TAB))
+ {
+ return DefWindowProcW(hWnd, msg, wParam, lParam);
+ }
OnKey(GuiData, msg, wParam, lParam);
break;
/* Enable or disable the Copy and Paste items */
EnableMenuItem(hMenu, ID_SYSTEM_EDIT_COPY , MF_BYCOMMAND |
- ((Console->Selection.dwFlags & CONSOLE_SELECTION_IN_PROGRESS) &&
- (Console->Selection.dwFlags & CONSOLE_SELECTION_NOT_EMPTY) ? MF_ENABLED : MF_GRAYED));
+ ((GuiData->Selection.dwFlags & CONSOLE_SELECTION_IN_PROGRESS) &&
+ (GuiData->Selection.dwFlags & CONSOLE_SELECTION_NOT_EMPTY) ? MF_ENABLED : MF_GRAYED));
// FIXME: Following whether the active screen buffer is text-mode
// or graphics-mode, search for CF_UNICODETEXT or CF_BITMAP formats.
EnableMenuItem(hMenu, ID_SYSTEM_EDIT_PASTE, MF_BYCOMMAND |
- (!(Console->Selection.dwFlags & CONSOLE_SELECTION_IN_PROGRESS) &&
+ (!(GuiData->Selection.dwFlags & CONSOLE_SELECTION_IN_PROGRESS) &&
IsClipboardFormatAvailable(CF_UNICODETEXT) ? MF_ENABLED : MF_GRAYED));
}
- if (ConDrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE))
- {
- SendMenuEvent(Console, WM_INITMENU);
- LeaveCriticalSection(&Console->Lock);
- }
+ SendMenuEvent(Console, WM_INITMENU);
break;
}
{
if (HIWORD(wParam) == 0xFFFF) // Allow all the menu flags
{
- if (ConDrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE))
- {
- SendMenuEvent(Console, WM_MENUSELECT);
- LeaveCriticalSection(&Console->Lock);
- }
+ SendMenuEvent(Console, WM_MENUSELECT);
}
break;
}
case PM_APPLY_CONSOLE_INFO:
{
- if (ConDrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE))
- {
- GuiApplyUserSettings(GuiData, (HANDLE)wParam, (BOOL)lParam);
- LeaveCriticalSection(&Console->Lock);
- }
+ GuiApplyUserSettings(GuiData, (HANDLE)wParam, (BOOL)lParam);
break;
}