⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 conio.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 5 页
字号:
    {
      Buff->CurrentY = 0;
    }
  ClearLineBuffer(Buff);
  UpdateRect->left = 0;
  UpdateRect->right = Buff->MaxX - 1;
  if (UpdateRect->top == (LONG)Buff->CurrentY)
    {
      if (++UpdateRect->top == Buff->MaxY)
        {
          UpdateRect->top = 0;
        }
    }
  UpdateRect->bottom = Buff->CurrentY;
}

static NTSTATUS FASTCALL
ConioWriteConsole(PCSRSS_CONSOLE Console, PCSRSS_SCREEN_BUFFER Buff,
                  CHAR *Buffer, DWORD Length, BOOL Attrib)
{
  UINT i;
  DWORD Offset;
  RECT UpdateRect;
  LONG CursorStartX, CursorStartY;
  UINT ScrolledLines;

  ConioPhysicalToLogical(Buff, Buff->CurrentX, Buff->CurrentY, &CursorStartX, &CursorStartY);
  UpdateRect.left = Buff->MaxX;
  UpdateRect.top = Buff->CurrentY;
  UpdateRect.right = -1;
  UpdateRect.bottom = Buff->CurrentY;
  ScrolledLines = 0;

  for (i = 0; i < Length; i++)
    {
      if (Buff->Mode & ENABLE_PROCESSED_OUTPUT)
        {
          /* --- LF --- */
          if (Buffer[i] == '\n')
            {
              Buff->CurrentX = 0;
              ConioNextLine(Buff, &UpdateRect, &ScrolledLines);
              continue;
            }
          /* --- BS --- */
          else if (Buffer[i] == '\b')
            {
              /* Only handle BS if we're not on the first pos of the first line */
              if (0 != Buff->CurrentX || Buff->ShowY != Buff->CurrentY)
                {
                  if (0 == Buff->CurrentX)
                    {
                      /* slide virtual position up */
                      Buff->CurrentX = Buff->MaxX - 1;
                      if (0 == Buff->CurrentY)
                        {
                          Buff->CurrentY = Buff->MaxY;
                        }
                      else
                        {
                          Buff->CurrentY--;
                        }
                      if ((0 == UpdateRect.top && UpdateRect.bottom < (LONG)Buff->CurrentY)
                          || (0 != UpdateRect.top && (LONG)Buff->CurrentY < UpdateRect.top))
                        {
                          UpdateRect.top = Buff->CurrentY;
                        }
                    }
                  else
                    {
                       Buff->CurrentX--;
                    }
                  Offset = 2 * ((Buff->CurrentY * Buff->MaxX) + Buff->CurrentX);
                  SET_CELL_BUFFER(Buff, Offset, ' ', Buff->DefaultAttrib);
                  UpdateRect.left = min(UpdateRect.left, (LONG) Buff->CurrentX);
                  UpdateRect.right = max(UpdateRect.right, (LONG) Buff->CurrentX);
                }
                continue;
            }
          /* --- CR --- */
          else if (Buffer[i] == '\r')
            {
              Buff->CurrentX = 0;
              UpdateRect.left = min(UpdateRect.left, (LONG) Buff->CurrentX);
              UpdateRect.right = max(UpdateRect.right, (LONG) Buff->CurrentX);
              continue;
            }
          /* --- TAB --- */
          else if (Buffer[i] == '\t')
            {
              UINT EndX;

              UpdateRect.left = min(UpdateRect.left, (LONG)Buff->CurrentX);
              EndX = (Buff->CurrentX + 8) & ~7;
              if (EndX > Buff->MaxX)
                {
                  EndX = Buff->MaxX;
                }
              Offset = 2 * (((Buff->CurrentY * Buff->MaxX)) + Buff->CurrentX);
              while (Buff->CurrentX < EndX)
                {
                  Buff->Buffer[Offset] = ' ';
                  Offset += 2;
                  Buff->CurrentX++;
                }
              UpdateRect.right = max(UpdateRect.right, (LONG) Buff->CurrentX - 1);
              if (Buff->CurrentX == Buff->MaxX)
                {
                  if (Buff->Mode & ENABLE_WRAP_AT_EOL_OUTPUT)
                    {
                      Buff->CurrentX = 0;
                      ConioNextLine(Buff, &UpdateRect, &ScrolledLines);
                    }
                  else
                    {
                      Buff->CurrentX--;
                    }
                }
              continue;
            }
        }
      UpdateRect.left = min(UpdateRect.left, (LONG)Buff->CurrentX);
      UpdateRect.right = max(UpdateRect.right, (LONG) Buff->CurrentX);
      Offset = 2 * (((Buff->CurrentY * Buff->MaxX)) + Buff->CurrentX);
      Buff->Buffer[Offset++] = Buffer[i];
      if (Attrib)
        {
          Buff->Buffer[Offset] = Buff->DefaultAttrib;
        }
      Buff->CurrentX++;
      if (Buff->CurrentX == Buff->MaxX)
        {
          if (Buff->Mode & ENABLE_WRAP_AT_EOL_OUTPUT)
            {
              Buff->CurrentX = 0;
              ConioNextLine(Buff, &UpdateRect, &ScrolledLines);
            }
          else
            {
              Buff->CurrentX = CursorStartX;
            }
        }
    }

  ConioPhysicalToLogical(Buff, UpdateRect.left, UpdateRect.top, &(UpdateRect.left),
                         &(UpdateRect.top));
  ConioPhysicalToLogical(Buff, UpdateRect.right, UpdateRect.bottom, &(UpdateRect.right),
                         &(UpdateRect.bottom));
  if (! ConioIsRectEmpty(&UpdateRect) && NULL != Console && Buff == Console->ActiveBuffer)
    {
      ConioWriteStream(Console, &UpdateRect, CursorStartX, CursorStartY, ScrolledLines,
                       Buffer, Length);
    }

  return STATUS_SUCCESS;
}

CSR_API(CsrReadConsole)
{
  PLIST_ENTRY CurrentEntry;
  ConsoleInput *Input;
  PUCHAR Buffer;
  PWCHAR UnicodeBuffer;
  ULONG i;
  ULONG nNumberOfCharsToRead, CharSize;
  PCSRSS_CONSOLE Console;
  NTSTATUS Status;

  DPRINT("CsrReadConsole\n");

  CharSize = (Request->Data.ReadConsoleRequest.Unicode ? sizeof(WCHAR) : sizeof(CHAR));

  /* truncate length to CSRSS_MAX_READ_CONSOLE_REQUEST */
  nNumberOfCharsToRead = min(Request->Data.ReadConsoleRequest.NrCharactersToRead, CSRSS_MAX_READ_CONSOLE / CharSize);
  Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
  Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);

  Buffer = Request->Data.ReadConsoleRequest.Buffer;
  UnicodeBuffer = (PWCHAR)Buffer;
  Status = ConioLockConsole(ProcessData, Request->Data.ReadConsoleRequest.ConsoleHandle,
                               &Console);
  if (! NT_SUCCESS(Status))
    {
      return Request->Status = Status;
    }
  Request->Data.ReadConsoleRequest.EventHandle = ProcessData->ConsoleEvent;
  for (i = 0; i < nNumberOfCharsToRead && Console->InputEvents.Flink != &Console->InputEvents; i++)
    {
      /* remove input event from queue */
      CurrentEntry = RemoveHeadList(&Console->InputEvents);
      if (IsListEmpty(&Console->InputEvents))
      {
         CHECKPOINT;
         ResetEvent(Console->ActiveEvent);
      }
      Input = CONTAINING_RECORD(CurrentEntry, ConsoleInput, ListEntry);

      /* only pay attention to valid ascii chars, on key down */
      if (KEY_EVENT == Input->InputEvent.EventType
          && Input->InputEvent.Event.KeyEvent.bKeyDown
          && Input->InputEvent.Event.KeyEvent.uChar.AsciiChar != '\0')
        {
          /*
           * backspace handling - if we are in charge of echoing it then we handle it here
           * otherwise we treat it like a normal char. 
           */
          if ('\b' == Input->InputEvent.Event.KeyEvent.uChar.AsciiChar && 0 
              != (Console->Mode & ENABLE_ECHO_INPUT))
            {
              /* echo if it has not already been done, and either we or the client has chars to be deleted */
              if (! Input->Echoed
                  && (0 !=  i || Request->Data.ReadConsoleRequest.nCharsCanBeDeleted))
                {
                  ConioWriteConsole(Console, Console->ActiveBuffer,
                                    &Input->InputEvent.Event.KeyEvent.uChar.AsciiChar, 1, TRUE);
                }
              if (0 != i)
                {
                  i -= 2;        /* if we already have something to return, just back it up by 2 */
                }
              else
                {            /* otherwise, return STATUS_NOTIFY_CLEANUP to tell client to back up its buffer */
                  Console->WaitingChars--;
                  ConioUnlockConsole(Console);
                  HeapFree(Win32CsrApiHeap, 0, Input);
                  Request->Data.ReadConsoleRequest.NrCharactersRead = 0;
                  Request->Status = STATUS_NOTIFY_CLEANUP;
                  return STATUS_NOTIFY_CLEANUP;
                  
                }
              Request->Data.ReadConsoleRequest.nCharsCanBeDeleted--;
              Input->Echoed = TRUE;   /* mark as echoed so we don't echo it below */
            }
          /* do not copy backspace to buffer */
          else
            {
              if(Request->Data.ReadConsoleRequest.Unicode)
                UnicodeBuffer[i] = Input->InputEvent.Event.KeyEvent.uChar.AsciiChar; /* FIXME */
              else
                Buffer[i] = Input->InputEvent.Event.KeyEvent.uChar.AsciiChar;
            }
          /* echo to screen if enabled and we did not already echo the char */
          if (0 != (Console->Mode & ENABLE_ECHO_INPUT)
              && ! Input->Echoed
              && '\r' != Input->InputEvent.Event.KeyEvent.uChar.AsciiChar)
            {
              ConioWriteConsole(Console, Console->ActiveBuffer,
                               &Input->InputEvent.Event.KeyEvent.uChar.AsciiChar, 1, TRUE);
            }
        }
      else
        {
          i--;
        }
      Console->WaitingChars--;
      HeapFree(Win32CsrApiHeap, 0, Input);
    }
  Request->Data.ReadConsoleRequest.NrCharactersRead = i;
  if (0 == i)
    {
      Request->Status = STATUS_PENDING;    /* we didn't read anything */
    }
  else if (0 != (Console->Mode & ENABLE_LINE_INPUT))
    {
      if (0 == Console->WaitingLines ||
          (Request->Data.ReadConsoleRequest.Unicode ? (L'\n' != UnicodeBuffer[i - 1]) : ('\n' != Buffer[i - 1])))
        {
          Request->Status = STATUS_PENDING; /* line buffered, didn't get a complete line */
        }
      else
        {
          Console->WaitingLines--;
          Request->Status = STATUS_SUCCESS; /* line buffered, did get a complete line */
        }
    }
  else
    {
      Request->Status = STATUS_SUCCESS;  /* not line buffered, did read something */
    }

  if (Request->Status == STATUS_PENDING)
    {
      Console->EchoCount = nNumberOfCharsToRead - i;
    }
  else
    {
      Console->EchoCount = 0;             /* if the client is no longer waiting on input, do not echo */
    }

  ConioUnlockConsole(Console);

  if (CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE) + i * CharSize > sizeof(CSR_API_MESSAGE))
    {
      Request->Header.u1.s1.TotalLength = CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE) + i * CharSize;
      Request->Header.u1.s1.DataLength = Request->Header.u1.s1.TotalLength - sizeof(PORT_MESSAGE);
    }

  return Request->Status;
}

VOID FASTCALL
ConioPhysicalToLogical(PCSRSS_SCREEN_BUFFER Buff,
                       ULONG PhysicalX,
                       ULONG PhysicalY,
                       LONG *LogicalX,
                       LONG *LogicalY)
{
   *LogicalX = PhysicalX;
   if (PhysicalY < Buff->ShowY)
     {
       *LogicalY = Buff->MaxY - Buff->ShowY + PhysicalY;
     }
   else
     {
       *LogicalY = PhysicalY - Buff->ShowY;
     }
}

BOOLEAN __inline ConioIsEqualRect(
  RECT *Rect1,
  RECT *Rect2)
{
  return ((Rect1->left == Rect2->left) && (Rect1->right == Rect2->right) &&
    (Rect1->top == Rect2->top) && (Rect1->bottom == Rect2->bottom));
}

BOOLEAN __inline ConioGetIntersection(
  RECT *Intersection,
  RECT *Rect1,
  RECT *Rect2)
{
  if (ConioIsRectEmpty(Rect1) ||
    (ConioIsRectEmpty(Rect2)) ||
    (Rect1->top > Rect2->bottom) ||
    (Rect1->left > Rect2->right) ||
    (Rect1->bottom < Rect2->top) ||
    (Rect1->right < Rect2->left))
  {
    /* The rectangles do not intersect */
    ConioInitRect(Intersection, 0, -1, 0, -1);
    return FALSE;
  }

  ConioInitRect(Intersection,
               max(Rect1->top, Rect2->top),
               max(Rect1->left, Rect2->left),
               min(Rect1->bottom, Rect2->bottom),
               min(Rect1->right, Rect2->right));

  return TRUE;
}

BOOLEAN __inline ConioGetUnion(
  RECT *Union,
  RECT *Rect1,
  RECT *Rect2)
{
  if (ConioIsRectEmpty(Rect1))
    {
      if (ConioIsRectEmpty(Rect2))
        {
          ConioInitRect(Union, 0, -1, 0, -1);
          return FALSE;
        }
      else
        {
          *Union = *Rect2;
        }
    }
  else if (ConioIsRectEmpty(Rect2))
    {
      *Union = *Rect1;
    }
  else
    {
      ConioInitRect(Union,
                   min(Rect1->top, Rect2->top),
                   min(Rect1->left, Rect2->left),
                   max(Rect1->bottom, Rect2->bottom),
                   max(Rect1->right, Rect2->right));
    }

  return TRUE;
}

BOOLEAN __inline ConioSubtractRect(
  RECT *Subtraction,
  RECT *Rect1,
  RECT *Rect2)
{
  RECT tmp;

  if (ConioIsRectEmpty(Rect1))
    {
      ConioInitRect(Subtraction, 0, -1, 0, -1);
      return FALSE;
    }
  *Subtraction = *Rect1;
  if (ConioGetIntersection(&tmp, Rect1, Rect2))
    {
      if (ConioIsEqualRect(&tmp, Subtraction))
        {
          ConioInitRect(Subtraction, 0, -1, 0, -1);
          return FALSE;
        }
      if ((tmp.top == Subtraction->top) && (tmp.bottom == Subtraction->bottom))

⌨️ 快捷键说明

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