summaryrefslogtreecommitdiffstats
path: root/src/detection/terminalsize/terminalsize_windows.c
blob: 05888e78b8908608fa9a3567df1b3aeee5952293 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#include "terminalsize.h"
#include "common/io.h"

#include <windows.h>

bool ffDetectTerminalSize(FFTerminalSizeResult* result) {
    HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
    FF_AUTO_CLOSE_FD HANDLE hConout = INVALID_HANDLE_VALUE;
    {
        DWORD outputMode;
        if (!GetConsoleMode(hOutput, &outputMode)) {
            hConout = CreateFileW(L"CONOUT$", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, NULL);
            hOutput = hConout;
        }
    }
    {
        CONSOLE_SCREEN_BUFFER_INFO csbi;
        if (GetConsoleScreenBufferInfo(hOutput, &csbi)) {
            result->columns = (uint16_t) (csbi.srWindow.Right - csbi.srWindow.Left + 1);
            result->rows = (uint16_t) (csbi.srWindow.Bottom - csbi.srWindow.Top + 1);
        } else {
            // Windows Terminal doesn't report `\e` for some reason
            ffGetTerminalResponse("\e[18t", 2, "%*[^;];%hu;%hut", &result->rows, &result->columns);
        }
    }

    if (result->columns == 0 && result->rows == 0) {
        return false;
    }

    {
        CONSOLE_FONT_INFOEX cfi = { .cbSize = sizeof(cfi) };
        if (GetCurrentConsoleFontEx(hOutput, FALSE, &cfi)) // Only works for ConHost
        {
            result->width = result->columns * (uint16_t) cfi.dwFontSize.X;
            result->height = result->rows * (uint16_t) cfi.dwFontSize.Y;
        }
        if (result->width == 0 || result->height == 0) {
            // Windows Terminal doesn't report `\e` for some reason
            ffGetTerminalResponse("\e[14t", 2, "%*[^;];%hu;%hut", &result->height, &result->width);
        }
    }

    return result->columns > 0 && result->rows > 0;
}