installed pty
[VSoRC/.git] / node_modules / node-pty / deps / winpty / src / agent / Win32ConsoleBuffer.cc
diff --git a/node_modules/node-pty/deps/winpty/src/agent/Win32ConsoleBuffer.cc b/node_modules/node-pty/deps/winpty/src/agent/Win32ConsoleBuffer.cc
new file mode 100644 (file)
index 0000000..ed93f40
--- /dev/null
@@ -0,0 +1,193 @@
+// Copyright (c) 2011-2016 Ryan Prichard
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+
+#include "Win32ConsoleBuffer.h"
+
+#include <windows.h>
+
+#include "../shared/DebugClient.h"
+#include "../shared/StringBuilder.h"
+#include "../shared/WinptyAssert.h"
+
+std::unique_ptr<Win32ConsoleBuffer> Win32ConsoleBuffer::openStdout() {
+    return std::unique_ptr<Win32ConsoleBuffer>(
+        new Win32ConsoleBuffer(GetStdHandle(STD_OUTPUT_HANDLE), false));
+}
+
+std::unique_ptr<Win32ConsoleBuffer> Win32ConsoleBuffer::openConout() {
+    const HANDLE conout = CreateFileW(L"CONOUT$",
+                                      GENERIC_READ | GENERIC_WRITE,
+                                      FILE_SHARE_READ | FILE_SHARE_WRITE,
+                                      NULL, OPEN_EXISTING, 0, NULL);
+    ASSERT(conout != INVALID_HANDLE_VALUE);
+    return std::unique_ptr<Win32ConsoleBuffer>(
+        new Win32ConsoleBuffer(conout, true));
+}
+
+std::unique_ptr<Win32ConsoleBuffer> Win32ConsoleBuffer::createErrorBuffer() {
+    SECURITY_ATTRIBUTES sa = {};
+    sa.nLength = sizeof(sa);
+    sa.bInheritHandle = TRUE;
+    const HANDLE conout =
+        CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE,
+                                  FILE_SHARE_READ | FILE_SHARE_WRITE,
+                                  &sa,
+                                  CONSOLE_TEXTMODE_BUFFER,
+                                  nullptr);
+    ASSERT(conout != INVALID_HANDLE_VALUE);
+    return std::unique_ptr<Win32ConsoleBuffer>(
+        new Win32ConsoleBuffer(conout, true));
+}
+
+HANDLE Win32ConsoleBuffer::conout() {
+    return m_conout;
+}
+
+void Win32ConsoleBuffer::clearLines(
+        int row,
+        int count,
+        const ConsoleScreenBufferInfo &info) {
+    // TODO: error handling
+    const int width = info.bufferSize().X;
+    DWORD actual = 0;
+    if (!FillConsoleOutputCharacterW(
+            m_conout, L' ', width * count, Coord(0, row),
+            &actual) || static_cast<int>(actual) != width * count) {
+        trace("FillConsoleOutputCharacterW failed");
+    }
+    if (!FillConsoleOutputAttribute(
+            m_conout, kDefaultAttributes, width * count, Coord(0, row),
+            &actual) || static_cast<int>(actual) != width * count) {
+        trace("FillConsoleOutputAttribute failed");
+    }
+}
+
+void Win32ConsoleBuffer::clearAllLines(const ConsoleScreenBufferInfo &info) {
+    clearLines(0, info.bufferSize().Y, info);
+}
+
+ConsoleScreenBufferInfo Win32ConsoleBuffer::bufferInfo() {
+    // TODO: error handling
+    ConsoleScreenBufferInfo info;
+    if (!GetConsoleScreenBufferInfo(m_conout, &info)) {
+        trace("GetConsoleScreenBufferInfo failed");
+    }
+    return info;
+}
+
+Coord Win32ConsoleBuffer::bufferSize() {
+    return bufferInfo().bufferSize();
+}
+
+SmallRect Win32ConsoleBuffer::windowRect() {
+    return bufferInfo().windowRect();
+}
+
+bool Win32ConsoleBuffer::resizeBufferRange(const Coord &initialSize,
+                                           Coord &finalSize) {
+    if (SetConsoleScreenBufferSize(m_conout, initialSize)) {
+        finalSize = initialSize;
+        return true;
+    }
+    // The font might be too small to accommodate a very narrow console window.
+    // In that case, rather than simply give up, it's better to try wider
+    // buffer sizes until the call succeeds.
+    Coord size = initialSize;
+    while (size.X < 20) {
+        size.X++;
+        if (SetConsoleScreenBufferSize(m_conout, size)) {
+            finalSize = size;
+            trace("SetConsoleScreenBufferSize: initial size (%d,%d) failed, "
+                  "but wider size (%d,%d) succeeded",
+                  initialSize.X, initialSize.Y,
+                  finalSize.X, finalSize.Y);
+            return true;
+        }
+    }
+    trace("SetConsoleScreenBufferSize failed: "
+          "tried (%d,%d) through (%d,%d)",
+          initialSize.X, initialSize.Y,
+          size.X, size.Y);
+    return false;
+}
+
+void Win32ConsoleBuffer::resizeBuffer(const Coord &size) {
+    // TODO: error handling
+    if (!SetConsoleScreenBufferSize(m_conout, size)) {
+        trace("SetConsoleScreenBufferSize failed: size=(%d,%d)",
+              size.X, size.Y);
+    }
+}
+
+void Win32ConsoleBuffer::moveWindow(const SmallRect &rect) {
+    // TODO: error handling
+    if (!SetConsoleWindowInfo(m_conout, TRUE, &rect)) {
+        trace("SetConsoleWindowInfo failed");
+    }
+}
+
+Coord Win32ConsoleBuffer::cursorPosition() {
+    return bufferInfo().dwCursorPosition;
+}
+
+void Win32ConsoleBuffer::setCursorPosition(const Coord &coord) {
+    // TODO: error handling
+    if (!SetConsoleCursorPosition(m_conout, coord)) {
+        trace("SetConsoleCursorPosition failed");
+    }
+}
+
+void Win32ConsoleBuffer::read(const SmallRect &rect, CHAR_INFO *data) {
+    // TODO: error handling
+    SmallRect tmp(rect);
+    if (!ReadConsoleOutputW(m_conout, data, rect.size(), Coord(), &tmp) &&
+            isTracingEnabled()) {
+        StringBuilder sb(256);
+        auto outStruct = [&](const SMALL_RECT &sr) {
+            sb << "{L=" << sr.Left << ",T=" << sr.Top
+               << ",R=" << sr.Right << ",B=" << sr.Bottom << '}';
+        };
+        sb << "Win32ConsoleBuffer::read: ReadConsoleOutput failed: readRegion=";
+        outStruct(rect);
+        CONSOLE_SCREEN_BUFFER_INFO info = {};
+        if (GetConsoleScreenBufferInfo(m_conout, &info)) {
+            sb << ", dwSize=(" << info.dwSize.X << ',' << info.dwSize.Y
+               << "), srWindow=";
+            outStruct(info.srWindow);
+        } else {
+            sb << ", GetConsoleScreenBufferInfo also failed";
+        }
+        trace("%s", sb.c_str());
+    }
+}
+
+void Win32ConsoleBuffer::write(const SmallRect &rect, const CHAR_INFO *data) {
+    // TODO: error handling
+    SmallRect tmp(rect);
+    if (!WriteConsoleOutputW(m_conout, data, rect.size(), Coord(), &tmp)) {
+        trace("WriteConsoleOutput failed");
+    }
+}
+
+void Win32ConsoleBuffer::setTextAttribute(WORD attributes) {
+    if (!SetConsoleTextAttribute(m_conout, attributes)) {
+        trace("SetConsoleTextAttribute failed");
+    }
+}