guiconsole.c

来自「一个类似windows」· C语言 代码 · 共 1,107 行 · 第 1/3 页

C
1,107
字号
        ps.rcPaint.left < ps.rcPaint.right &&
        ps.rcPaint.top < ps.rcPaint.bottom)
    {
        GuiConsoleGetDataPointers(hWnd,
                                  &Console,
                                  &GuiData);
        if (Console != NULL && GuiData != NULL &&
            Console->ActiveBuffer != NULL)
        {
            EnterCriticalSection(&GuiData->Lock);

            GuiConsolePaint(Console,
                            GuiData,
                            hDC,
                            &ps.rcPaint);

            if (GuiData->Selection.left != -1)
            {
                RECT rc = GuiData->Selection;

                rc.left *= GuiData->CharWidth;
                rc.top *= GuiData->CharHeight;
                rc.right *= GuiData->CharWidth;
                rc.bottom *= GuiData->CharHeight;

                /* invert the selection */
                if (IntersectRect(&rc,
                                  &ps.rcPaint,
                                  &rc))
                {
                    PatBlt(hDC,
                           rc.left,
                           rc.top,
                           rc.right - rc.left,
                           rc.bottom - rc.top,
                           DSTINVERT);
                }
            }

            LeaveCriticalSection(&GuiData->Lock);
        }

        EndPaint(hWnd, &ps);
    }
}

static VOID FASTCALL
GuiConsoleHandleKey(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
  PCSRSS_CONSOLE Console;
  PGUI_CONSOLE_DATA GuiData;
  MSG Message;

  GuiConsoleGetDataPointers(hWnd, &Console, &GuiData);
  Message.hwnd = hWnd;
  Message.message = msg;
  Message.wParam = wParam;
  Message.lParam = lParam;

  if(msg == WM_CHAR || msg == WM_SYSKEYDOWN)
  {
    /* clear the selection */
    GuiConsoleUpdateSelection(hWnd, NULL, GuiData);
  }

  ConioProcessKey(&Message, Console, FALSE);
}

static VOID FASTCALL
GuiIntDrawRegion(PGUI_CONSOLE_DATA GuiData, HWND Wnd, RECT *Region)
{
  RECT RegionRect;

  RegionRect.left = Region->left * GuiData->CharWidth;
  RegionRect.top = Region->top * GuiData->CharHeight;
  RegionRect.right = (Region->right + 1) * GuiData->CharWidth;
  RegionRect.bottom = (Region->bottom + 1) * GuiData->CharHeight;

  InvalidateRect(Wnd, &RegionRect, FALSE);
}

static VOID STDCALL
GuiDrawRegion(PCSRSS_CONSOLE Console, RECT *Region)
{
  PGUI_CONSOLE_DATA GuiData = (PGUI_CONSOLE_DATA) Console->PrivateData;

  if (NULL != Console->hWindow && NULL != GuiData)
    {
      GuiIntDrawRegion(GuiData, Console->hWindow, Region);
    }
}

static VOID FASTCALL
GuiInvalidateCell(PGUI_CONSOLE_DATA GuiData, HWND Wnd, UINT x, UINT y)
{
  RECT CellRect;

  CellRect.left = x;
  CellRect.top = y;
  CellRect.right = x;
  CellRect.bottom = y;

  GuiIntDrawRegion(GuiData, Wnd, &CellRect);
}

static VOID STDCALL
GuiWriteStream(PCSRSS_CONSOLE Console, RECT *Region, LONG CursorStartX, LONG CursorStartY,
               UINT ScrolledLines, CHAR *Buffer, UINT Length)
{
  PGUI_CONSOLE_DATA GuiData = (PGUI_CONSOLE_DATA) Console->PrivateData;
  PCSRSS_SCREEN_BUFFER Buff = Console->ActiveBuffer;
  LONG CursorEndX, CursorEndY;
  RECT ScrollRect;

  if (NULL == Console->hWindow || NULL == GuiData)
    {
      return;
    }

  if (0 != ScrolledLines)
    {
      ScrollRect.left = 0;
      ScrollRect.top = 0;
      ScrollRect.right = Console->Size.X * GuiData->CharWidth;
      ScrollRect.bottom = Region->top * GuiData->CharHeight;

      if (GuiData->Selection.left != -1)
      {
          /* scroll the selection */
          if (GuiData->Selection.top > ScrolledLines)
          {
              GuiData->Selection.top -= ScrolledLines;
              GuiData->Selection.bottom -= ScrolledLines;
          }
          else if (GuiData->Selection.bottom < ScrolledLines)
          {
              GuiData->Selection.left = -1;
          }
          else
          {
              GuiData->Selection.top = 0;
              GuiData->Selection.bottom -= ScrolledLines;
          }
      }

      ScrollWindowEx(Console->hWindow,
                     0,
                     -(ScrolledLines * GuiData->CharHeight),
                     &ScrollRect,
                     NULL,
                     NULL,
                     NULL,
                     SW_INVALIDATE);
    }

  GuiIntDrawRegion(GuiData, Console->hWindow, Region);

  if (CursorStartX < Region->left || Region->right < CursorStartX
      || CursorStartY < Region->top || Region->bottom < CursorStartY)
    {
      GuiInvalidateCell(GuiData, Console->hWindow, CursorStartX, CursorStartY);
    }

  ConioPhysicalToLogical(Buff, Buff->CurrentX, Buff->CurrentY,
                         &CursorEndX, &CursorEndY);
  if ((CursorEndX < Region->left || Region->right < CursorEndX
       || CursorEndY < Region->top || Region->bottom < CursorEndY)
      && (CursorEndX != CursorStartX || CursorEndY != CursorStartY))
    {
      GuiInvalidateCell(GuiData, Console->hWindow, CursorEndX, CursorEndY);
    }
}

static BOOL STDCALL
GuiSetCursorInfo(PCSRSS_CONSOLE Console, PCSRSS_SCREEN_BUFFER Buff)
{
  RECT UpdateRect;

  if (Console->ActiveBuffer == Buff)
    {
      ConioPhysicalToLogical(Buff, Buff->CurrentX, Buff->CurrentY,
                             &UpdateRect.left, &UpdateRect.top);
      UpdateRect.right = UpdateRect.left;
      UpdateRect.bottom = UpdateRect.top;
      ConioDrawRegion(Console, &UpdateRect);
    }

  return TRUE;
}

static BOOL STDCALL
GuiSetScreenInfo(PCSRSS_CONSOLE Console, PCSRSS_SCREEN_BUFFER Buff, UINT OldCursorX, UINT OldCursorY)
{
  RECT UpdateRect;

  if (Console->ActiveBuffer == Buff)
    {
      /* Redraw char at old position (removes cursor) */
      UpdateRect.left = OldCursorX;
      UpdateRect.top = OldCursorY;
      UpdateRect.right = OldCursorX;
      UpdateRect.bottom = OldCursorY;
      ConioDrawRegion(Console, &UpdateRect);
      /* Redraw char at new position (shows cursor) */
      ConioPhysicalToLogical(Buff, Buff->CurrentX, Buff->CurrentY,
                             &(UpdateRect.left), &(UpdateRect.top));
      UpdateRect.right = UpdateRect.left;
      UpdateRect.bottom = UpdateRect.top;
      ConioDrawRegion(Console, &UpdateRect);
    }

  return TRUE;
}

static VOID FASTCALL
GuiConsoleHandleTimer(HWND hWnd)
{
  PCSRSS_CONSOLE Console;
  PGUI_CONSOLE_DATA GuiData;
  RECT CursorRect;
  ULONG CursorX, CursorY;

  GuiConsoleGetDataPointers(hWnd, &Console, &GuiData);
  GuiData->CursorBlinkOn = ! GuiData->CursorBlinkOn;

  GuiConsoleGetLogicalCursorPos(Console->ActiveBuffer, &CursorX, &CursorY);
  CursorRect.left = CursorX;
  CursorRect.top = CursorY;
  CursorRect.right = CursorX;
  CursorRect.bottom = CursorY;
  GuiDrawRegion(Console, &CursorRect);
}

static VOID FASTCALL
GuiConsoleHandleClose(HWND hWnd)
{
  PCSRSS_CONSOLE Console;
  PGUI_CONSOLE_DATA GuiData;
  PLIST_ENTRY current_entry;
  PCSRSS_PROCESS_DATA current;

  GuiConsoleGetDataPointers(hWnd, &Console, &GuiData);

  EnterCriticalSection(&Console->Header.Lock);

  current_entry = Console->ProcessList.Flink;
  while (current_entry != &Console->ProcessList)
    {
      current = CONTAINING_RECORD(current_entry, CSRSS_PROCESS_DATA, ProcessEntry);
      current_entry = current_entry->Flink;

      ConioConsoleCtrlEvent(CTRL_CLOSE_EVENT, current);
    }

  LeaveCriticalSection(&Console->Header.Lock);
}

static VOID FASTCALL
GuiConsoleHandleNcDestroy(HWND hWnd)
{
  PCSRSS_CONSOLE Console;
  PGUI_CONSOLE_DATA GuiData;

  GuiConsoleGetDataPointers(hWnd, &Console, &GuiData);
  KillTimer(hWnd, 1);
  Console->PrivateData = NULL;
  DeleteCriticalSection(&GuiData->Lock);
  HeapFree(Win32CsrApiHeap, 0, GuiData);
}

static VOID FASTCALL
GuiConsoleLeftMouseDown(HWND hWnd, LPARAM lParam)
{
  PCSRSS_CONSOLE Console;
  PGUI_CONSOLE_DATA GuiData;
  POINTS pt;
  RECT rc;

  GuiConsoleGetDataPointers(hWnd, &Console, &GuiData);
  if (Console == NULL || GuiData == NULL) return;

  pt = MAKEPOINTS(lParam);

  rc.left = pt.x / GuiData->CharWidth;
  rc.top = pt.y / GuiData->CharHeight;
  rc.right = rc.left + 1;
  rc.bottom = rc.top + 1;

  GuiData->SelectionStart.x = rc.left;
  GuiData->SelectionStart.y = rc.top;

  SetCapture(hWnd);

  GuiData->MouseDown = TRUE;

  GuiConsoleUpdateSelection(hWnd, &rc, GuiData);
}

static VOID FASTCALL
GuiConsoleLeftMouseUp(HWND hWnd, LPARAM lParam)
{
  PCSRSS_CONSOLE Console;
  PGUI_CONSOLE_DATA GuiData;
  RECT rc;
  POINTS pt;

  GuiConsoleGetDataPointers(hWnd, &Console, &GuiData);
  if (Console == NULL || GuiData == NULL) return;
  if (GuiData->Selection.left == -1 || !GuiData->MouseDown) return;

  pt = MAKEPOINTS(lParam);

  rc.left = GuiData->SelectionStart.x;
  rc.top = GuiData->SelectionStart.y;
  rc.right = (pt.x >= 0 ? (pt.x / GuiData->CharWidth) + 1 : 0);
  rc.bottom = (pt.y >= 0 ? (pt.y / GuiData->CharHeight) + 1 : 0);

  /* exchange left/top with right/bottom if required */
  if(rc.left >= rc.right)
  {
    LONG tmp;
    tmp = rc.left;
    rc.left = max(rc.right - 1, 0);
    rc.right = tmp + 1;
  }
  if(rc.top >= rc.bottom)
  {
    LONG tmp;
    tmp = rc.top;
    rc.top = max(rc.bottom - 1, 0);
    rc.bottom = tmp + 1;
  }

  GuiData->MouseDown = FALSE;

  GuiConsoleUpdateSelection(hWnd, &rc, GuiData);

  ReleaseCapture();
}

static VOID FASTCALL
GuiConsoleMouseMove(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
  PCSRSS_CONSOLE Console;
  PGUI_CONSOLE_DATA GuiData;
  RECT rc;
  POINTS pt;

  if (!(wParam & MK_LBUTTON)) return;

  GuiConsoleGetDataPointers(hWnd, &Console, &GuiData);
  if (Console == NULL || GuiData == NULL || !GuiData->MouseDown) return;

  pt = MAKEPOINTS(lParam);

  rc.left = GuiData->SelectionStart.x;
  rc.top = GuiData->SelectionStart.y;
  rc.right = (pt.x >= 0 ? (pt.x / GuiData->CharWidth) + 1 : 0);
  if (Console->Size.X < rc.right)
  {
    rc.right = Console->Size.X;
  }
  rc.bottom = (pt.y >= 0 ? (pt.y / GuiData->CharHeight) + 1 : 0);
  if (Console->Size.Y < rc.bottom)
  {
    rc.bottom = Console->Size.Y;
  }

  /* exchange left/top with right/bottom if required */

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?