master
cpp 100 lines 2.34 KB
Raw
1 /*++
2
3 Copyright (c) Microsoft. All rights reserved.
4
5 Module Name:
6
7 OutputChannel.cpp
8
9 Abstract:
10
11 Implementation of OutputChannel.
12
13 --*/
14 #include "precomp.h"
15 #include "OutputChannel.h"
16
17 #include <algorithm>
18 #include <cerrno>
19
20 namespace wsl::windows::wslc {
21
22 OutputChannel::OutputChannel(HANDLE consoleHandle, FILE* fallbackFile)
23 {
24 DWORD mode = 0;
25 if (consoleHandle != INVALID_HANDLE_VALUE && consoleHandle != nullptr && GetConsoleMode(consoleHandle, &mode))
26 {
27 m_consoleHandle = consoleHandle;
28 m_vtMode.emplace(consoleHandle);
29 }
30 else
31 {
32 WI_ASSERT(fallbackFile != nullptr);
33 m_file = fallbackFile;
34 }
35 }
36
37 OutputChannel::OutputChannel(FILE* file, bool vtOverride) : m_file(file), m_vtOverride(vtOverride)
38 {
39 WI_ASSERT(file != nullptr);
40 }
41
42 void OutputChannel::WriteString(std::wstring_view text) const
43 {
44 if (text.empty())
45 {
46 return;
47 }
48
49 if (m_consoleHandle != nullptr)
50 {
51 DWORD written = 0;
52 LOG_IF_WIN32_BOOL_FALSE(WriteConsoleW(m_consoleHandle, text.data(), static_cast<DWORD>(text.size()), &written, nullptr));
53 return;
54 }
55
56 if (fwprintf(m_file, L"%.*ls", static_cast<int>(text.size()), text.data()) < 0)
57 {
58 const int err = errno;
59 LOG_HR_MSG(HRESULT_FROM_WIN32(ERROR_WRITE_FAULT), "fwprintf to redirected output failed (errno=%d)", err);
60 }
61 }
62
63 void OutputChannel::Flush() const
64 {
65 if (m_file != nullptr && fflush(m_file) != 0)
66 {
67 const int err = errno;
68 LOG_HR_MSG(HRESULT_FROM_WIN32(ERROR_WRITE_FAULT), "fflush of redirected output failed (errno=%d)", err);
69 }
70 }
71
72 std::optional<int> OutputChannel::GetConsoleWidth() const
73 {
74 if (m_consoleHandle == nullptr)
75 {
76 return std::nullopt;
77 }
78
79 CONSOLE_SCREEN_BUFFER_INFO info{};
80 if (!GetConsoleScreenBufferInfo(m_consoleHandle, &info))
81 {
82 return std::nullopt;
83 }
84
85 // (Right - Left + 1) is the visible width; subtract one more as an autowrap guard.
86 return std::max(0, static_cast<int>(info.srWindow.Right) - static_cast<int>(info.srWindow.Left));
87 }
88
89 bool OutputChannel::IsVTEnabled() const noexcept
90 {
91 if (m_consoleHandle != nullptr)
92 {
93 DWORD mode = 0;
94 return GetConsoleMode(m_consoleHandle, &mode) && WI_IsFlagSet(mode, ENABLE_VIRTUAL_TERMINAL_PROCESSING);
95 }
96
97 return m_vtOverride;
98 }
99
100 } // namespace wsl::windows::wslc