Files
AVR/AVR Working Controller/ConsoleHandler.cpp
David 6d16d119cd Clean up unused options for soundscape.
Clean up console interface to be less likely to fail to define the width and height.
Update notes in the PDF.
Add the PDF for newer Yamaha even if I don't have one (and the protocol has significant differences).
2026-02-27 12:57:20 -06:00

243 lines
7.7 KiB
C++

// Something for later
//
// #include <windows.h>
// #include <stdio.h>
//
// void enable_ansi_escape_sequences(void) {
// HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
// DWORD mode = 0;
//
// if (!GetConsoleMode(hOut, &mode)) {
// return; // handle error if needed
// }
//
// mode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
//
// SetConsoleMode(hOut, mode);
// }
//
// int main() {
// enable_ansi_escape_sequences();
//
// printf("\x1b[32mGreen text\x1b[0m\n");
// printf("\x1b[31mRed text\x1b[0m\n");
//
// return 0;
// }
#include "stdafx.h"
#include <Windows.h>
#include <stdio.h>
#include <conio.h>
#include "ConsoleHandler.h"
// For special cursor positioning
static bool consoleInit = false;
static HANDLE hStdout, hStdin;
static CONSOLE_SCREEN_BUFFER_INFO csbi;
static WORD wOldColorAttrs; // Save the current console colors
static short consoleWidth = 0;
static short consoleHeight = 0;
static short scrollBot = 0; // set at init: consoleHeight - 1
static short scrollTop = 0; // set at init: consoleHeight - consoleScrollHeight - 1
void Console_SetColor(WORD color) {
SetConsoleTextAttribute(hStdout, color);
}
void Console_RestoreColor() {
SetConsoleTextAttribute(hStdout, wOldColorAttrs);
}
void Console_Init(short Left, short Top, short Width, short Height, short bottomScrollHeight) {
hStdin = GetStdHandle(STD_INPUT_HANDLE);
hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
if (!GetConsoleScreenBufferInfo(hStdout, &csbi)) {
fprintf(stderr, "Error: Unable to get console buffer info. Code: %lu\n", GetLastError());
exit(1);
}
wOldColorAttrs = csbi.wAttributes;
scrollBot = Height - 1;
scrollTop = Height - bottomScrollHeight - 1;
#if 1
COORD max = GetLargestConsoleWindowSize(hStdout);
SHORT w = (Width > max.X) ? max.X : Width;
SHORT h = (Height > max.Y) ? max.Y : Height;
SMALL_RECT win = { 0, 0, (SHORT)(w - 1), (SHORT)(h - 1) };
// Enlarge buffer first (for growth), then set window.
SetConsoleScreenBufferSize(hStdout, { w, h });
SetConsoleWindowInfo(hStdout, TRUE, &win);
#else
// Desired size (width x height)
COORD bufferSize = { 0, 0 };
bufferSize.X = (csbi.dwSize.X < Width) ? Width : csbi.dwSize.X; // columns
bufferSize.Y = (csbi.dwSize.Y < Height) ? Height : csbi.dwSize.Y; // rows
// Step 2: Set new buffer size
if (!SetConsoleScreenBufferSize(hStdout, bufferSize)) {
fprintf(stderr, "Error: Unable to set console buffer size. Code: %lu\n", GetLastError());
// figure out why ...
CONSOLE_SCREEN_BUFFER_INFOEX info;
info.cbSize = sizeof(info);
if (!GetConsoleScreenBufferInfoEx(hStdout, &info)) {
// handle error
}
fprintf(stderr, "Width[%u] > info.dwMaximumWindowSize.X[%u] || Height[%u] > info.dwMaximumWindowSize.Y[%u]\n",
Width, info.dwMaximumWindowSize.X, Height, info.dwMaximumWindowSize.Y);
fprintf(stderr, "Width[%u] < GetSystemMetrics(SM_CXMIN)[%u] || Height[%u] < GetSystemMetrics(SM_CYMIN)[%u]\n",
Width, GetSystemMetrics(SM_CXMIN), Height, GetSystemMetrics(SM_CYMIN));
exit(1);
}
// Step 3: Set final window size to match buffer
// The final window size we want to set
SMALL_RECT newWindow = { 0 };
newWindow.Left = 0;
newWindow.Top = 0;
newWindow.Right = bufferSize.X - 1;
newWindow.Bottom = bufferSize.Y - 1;
if (!SetConsoleWindowInfo(hStdout, TRUE, &newWindow)) {
fprintf(stderr, "Error: Unable to set console window size. Code: %lu\n", GetLastError());
CONSOLE_SCREEN_BUFFER_INFOEX info;
info.cbSize = sizeof(info);
if (!GetConsoleScreenBufferInfoEx(hStdout, &info)) {
// handle error
}
fprintf(stderr, "Width[%u] > info.dwMaximumWindowSize.X[%u] || Height[%u] > info.dwMaximumWindowSize.Y[%u]\n",
Width, info.dwMaximumWindowSize.X, Height, info.dwMaximumWindowSize.Y);
fprintf(stderr, "Width[%u] < GetSystemMetrics(SM_CXMIN)[%u] || Height[%u] < GetSystemMetrics(SM_CYMIN)[%u]\n",
Width, GetSystemMetrics(SM_CXMIN), Height, GetSystemMetrics(SM_CYMIN));
exit(1);
}
// end
Console_SetWindowPosition(Left, Top);
#endif
}
void Console_Close() {
SetConsoleTextAttribute(hStdout, wOldColorAttrs);
}
void Console_Cls() {
COORD coordScreen = { 0, 0 }; // home for the cursor
DWORD cCharsWritten;
DWORD dwConSize;
// Get the number of character cells in the current buffer.
if (!GetConsoleScreenBufferInfo(hStdout, &csbi)) {
return;
}
dwConSize = csbi.dwSize.X * csbi.dwSize.Y;
// Fill the entire screen with blanks.
if (!FillConsoleOutputCharacter(hStdout, // Handle to console screen buffer
(TCHAR)' ', // Character to write to the buffer
dwConSize, // Number of cells to write
coordScreen, // Coordinates of first cell
&cCharsWritten)) { // Receive number of characters written
return;
}
// Get the current text attribute.
if (!GetConsoleScreenBufferInfo(hStdout, &csbi)) {
return;
}
// Set the buffer's attributes accordingly.
if (!FillConsoleOutputAttribute(hStdout, // Handle to console screen buffer
csbi.wAttributes, // Character attributes to use
dwConSize, // Number of cells to set attribute
coordScreen, // Coordinates of first cell
&cCharsWritten)) { // Receive number of characters written
return;
}
// Put the cursor at its home coordinates.
SetConsoleCursorPosition(hStdout, coordScreen);
}
void Console_SetWindowPosition(int x, int y) {
HWND hwnd = GetConsoleWindow();
if (!hwnd) return;
// Move the window to (x,y) in screen coordinates without changing size or z-order
SetWindowPos(hwnd, HWND_TOP, x, y, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW);
}
void Console_Write(const char *text) {
DWORD written;
WriteConsole(hStdout, text, (DWORD)strlen(text), &written, nullptr);
}
void Console_WriteAt(short x, short y, const char *text) {
DWORD written;
if (hStdout) {
Console_SetCursor(x, y);
WriteConsole(hStdout, text, (DWORD)strlen(text), &written, nullptr);
} else {
printf("%s\n", text);
}
}
void Console_SetCursor(short x, short y) {
GetConsoleScreenBufferInfo(hStdout, &csbi);
csbi.dwCursorPosition.X = (short)((x < 0) ? csbi.srWindow.Right + x : x);
csbi.dwCursorPosition.Y = (short)((y < 0) ? csbi.srWindow.Bottom + 1 + y : y);
SetConsoleCursorPosition(hStdout, csbi.dwCursorPosition);
}
void Console_ScrollBottomRegion() {
short topLine = scrollTop + 1;
short bottomLine = scrollBot;
GetConsoleScreenBufferInfo(hStdout, &csbi);
if (topLine < 0) topLine = csbi.srWindow.Bottom + topLine;
if (bottomLine < 0) bottomLine = csbi.srWindow.Bottom + bottomLine;
SMALL_RECT scrollRect = { 0, topLine, csbi.dwMaximumWindowSize.X - 1, bottomLine };
COORD dest = { 0, topLine - 1 };
CHAR_INFO fill = { ' ', { FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE } };
ScrollConsoleScreenBuffer(hStdout, &scrollRect, &scrollRect, dest, &fill);
_putch('\r'); // Cursor to left margin
}
bool Console_AdvanceToNextLineIfNotRoomFor(short x, int scroll) {
bool advanced = false;
GetConsoleScreenBufferInfo(hStdout, &csbi);
if (csbi.dwCursorPosition.X + x > csbi.dwMaximumWindowSize.X) {
advanced = true;
if (scroll == 1) {
Console_ScrollBottomRegion();
} else {
csbi.dwCursorPosition.Y++;
}
Console_SetCursor(0, csbi.dwCursorPosition.Y);
}
return advanced;
}
// Console_SetCursorVisibility
//
// Set the state of the cursor and provide the prior state so it
// can be restored
//
// @param[in] bool the desired state, true is visible
// @returns the prior state, true is visible
//
bool Console_SetCursorVisibility(bool visible) {
CONSOLE_CURSOR_INFO cursorInfo;
bool priorState = true;
if (!GetConsoleCursorInfo(hStdout, &cursorInfo)) {
// printf("***** Error: Unable to get cursor info.\n");
return priorState;
}
priorState = cursorInfo.bVisible;
cursorInfo.bVisible = visible; // true = show, false = hide
if (!SetConsoleCursorInfo(hStdout, &cursorInfo)) {
// std::cerr << "Error: Unable to set cursor info.\n";
}
return priorState;
}