Drawing on windows console

This commit is contained in:
Andrew Pamment 2020-05-20 17:24:44 +10:00
parent f7d4c2013c
commit 160dbcd50f
4 changed files with 387 additions and 1 deletions

378
MD_AnsiCons.c Normal file
View File

@ -0,0 +1,378 @@
#include <windows.h>
#include <stdarg.h>
#include <stdio.h>
#include <errno.h>
#include <io.h>
#ifndef FOREGROUND_MASK
# define FOREGROUND_MASK (FOREGROUND_RED|FOREGROUND_BLUE|FOREGROUND_GREEN)
#endif
#ifndef BACKGROUND_MASK
# define BACKGROUND_MASK (BACKGROUND_RED|BACKGROUND_BLUE|BACKGROUND_GREEN)
#endif
int ansi_write(FILE* fp, const char* buf, int len) {
static int first = 1;
static int state = 0;
static int n;
static int v[6];
static COORD saved_coord = { 0, 0 };
int type;
HANDLE handle = INVALID_HANDLE_VALUE;
static WORD attr;
DWORD written, csize;
CONSOLE_CURSOR_INFO cci;
CONSOLE_SCREEN_BUFFER_INFO csbi;
COORD coord;
const char* ptr = buf;
int w, h;
if (fp == stdout) {
type = 0;
}
else if (fp == stderr) {
type = 1;
}
else {
type = 0;
}
handle = (HANDLE)_get_osfhandle(fileno(fp));
GetConsoleScreenBufferInfo(handle, &csbi);
attr = csbi.wAttributes;
int z = 0;
for (z = 0; z < len; z++) {
if (state == 0) {
if (ptr[z] == '\033') {
state = 1;
continue;
}
else {
fputc(ptr[z], fp);
}
}
else if (state == 1) {
if (ptr[z] == '[') {
state = 2;
}
else {
state = 0;
}
} else if (state == 2) {
n = 0;
for (int j = 0; j < 6; j++) {
v[j] = 0;
}
state = 3;
}
if (state == 3) {
if (ptr[z] == ';') {
if (n < 6) {
n++;
}
continue;
} else if (isdigit(ptr[z])) {
if (n == 0) {
n = 1;
}
v[n-1] = v[n-1] * 10 + (ptr[z] - '0');
continue;
}
else {
state = 4;
}
}
if (state == 4) {
state = 0;
switch (ptr[z]) {
case 'h':
for (int i = 0; i < n; i++) {
switch (v[i]) {
case 3:
GetConsoleScreenBufferInfo(handle, &csbi);
w = csbi.dwSize.X;
h = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
csize = w * (h + 1);
coord.X = 0;
coord.Y = csbi.srWindow.Top;
FillConsoleOutputCharacter(handle, ' ', csize, coord, &written);
FillConsoleOutputAttribute(handle, csbi.wAttributes, csize, coord, &written);
SetConsoleCursorPosition(handle, csbi.dwCursorPosition);
csbi.dwSize.X = 132;
SetConsoleScreenBufferSize(handle, csbi.dwSize);
csbi.srWindow.Right = csbi.srWindow.Left + 131;
SetConsoleWindowInfo(handle, TRUE, &csbi.srWindow);
break;
case 5:
attr =
((attr & FOREGROUND_MASK) << 4) |
((attr & BACKGROUND_MASK) >> 4);
SetConsoleTextAttribute(handle, attr);
break;
case 9:
break;
case 25:
GetConsoleCursorInfo(handle, &cci);
cci.bVisible = TRUE;
SetConsoleCursorInfo(handle, &cci);
break;
case 47:
coord.X = 0;
coord.Y = 0;
SetConsoleCursorPosition(handle, coord);
break;
default:
break;
}
}
break;
case 'l':
for (int i = 0; i < n; i++) {
switch (v[i]) {
case 3:
GetConsoleScreenBufferInfo(handle, &csbi);
w = csbi.dwSize.X;
h = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
csize = w * (h + 1);
coord.X = 0;
coord.Y = csbi.srWindow.Top;
FillConsoleOutputCharacter(handle, ' ', csize, coord, &written);
FillConsoleOutputAttribute(handle, csbi.wAttributes, csize, coord, &written);
SetConsoleCursorPosition(handle, csbi.dwCursorPosition);
csbi.srWindow.Right = csbi.srWindow.Left + 79;
SetConsoleWindowInfo(handle, TRUE, &csbi.srWindow);
csbi.dwSize.X = 80;
SetConsoleScreenBufferSize(handle, csbi.dwSize);
break;
case 5:
attr =
((attr & FOREGROUND_MASK) << 4) |
((attr & BACKGROUND_MASK) >> 4);
SetConsoleTextAttribute(handle, attr);
break;
case 25:
GetConsoleCursorInfo(handle, &cci);
cci.bVisible = FALSE;
SetConsoleCursorInfo(handle, &cci);
break;
default:
break;
}
}
break;
case 'm':
for (int i = 0; i < n; i++) {
if (v[i] == -1 || v[i] == 0) {
attr &= ~(FOREGROUND_INTENSITY);
attr |= FOREGROUND_MASK;
attr &= ~(BACKGROUND_MASK);
}
else if (v[i] == 1)
attr |= FOREGROUND_INTENSITY;
else if (v[i] == 4)
attr |= FOREGROUND_INTENSITY;
else if (v[i] == 5)
attr |= FOREGROUND_INTENSITY;
else if (v[i] == 7)
attr =
((attr & FOREGROUND_MASK) << 4) |
((attr & BACKGROUND_MASK) >> 4);
else if (v[i] == 10)
; // symbol on
else if (v[i] == 11)
; // symbol off
else if (v[i] == 22)
attr &= ~FOREGROUND_INTENSITY;
else if (v[i] == 24)
attr &= ~FOREGROUND_INTENSITY;
else if (v[i] == 25)
attr &= ~FOREGROUND_INTENSITY;
else if (v[i] == 27)
attr =
((attr & FOREGROUND_MASK) << 4) |
((attr & BACKGROUND_MASK) >> 4);
else if (v[i] >= 30 && v[i] <= 37) {
attr = (attr & (BACKGROUND_MASK | FOREGROUND_INTENSITY));
if ((v[i] - 30) & 1)
attr |= FOREGROUND_RED;
if ((v[i] - 30) & 2)
attr |= FOREGROUND_GREEN;
if ((v[i] - 30) & 4)
attr |= FOREGROUND_BLUE;
}
//else if (v[i] == 39)
//attr = (~attr & BACKGROUND_MASK);
else if (v[i] >= 40 && v[i] <= 47) {
attr = (attr & (FOREGROUND_MASK | BACKGROUND_INTENSITY));
if ((v[i] - 40) & 1)
attr |= BACKGROUND_RED;
if ((v[i] - 40) & 2)
attr |= BACKGROUND_GREEN;
if ((v[i] - 40) & 4)
attr |= BACKGROUND_BLUE;
}
else if (v[i] >= 90 && v[i] <= 97) {
attr = (attr & BACKGROUND_MASK) | FOREGROUND_INTENSITY;
if ((v[i] - 90) & 1)
attr |= FOREGROUND_RED;
if ((v[i] - 90) & 2)
attr |= FOREGROUND_GREEN;
if ((v[i] - 90) & 4)
attr |= FOREGROUND_BLUE;
}
else if (v[i] >= 100 && v[i] <= 107) {
attr = (attr & FOREGROUND_MASK) | BACKGROUND_INTENSITY;
if ((v[i] - 100) & 1)
attr |= BACKGROUND_RED;
if ((v[i] - 100) & 2)
attr |= BACKGROUND_GREEN;
if ((v[i] - 100) & 4)
attr |= BACKGROUND_BLUE;
}
//else if (v[i] == 49)
//attr = (~attr & FOREGROUND_MASK);
}
SetConsoleTextAttribute(handle, attr);
break;
case 'K':
GetConsoleScreenBufferInfo(handle, &csbi);
coord = csbi.dwCursorPosition;
switch (v[0]) {
default:
case 0:
csize = csbi.dwSize.X - coord.X;
break;
case 1:
csize = coord.X;
coord.X = 0;
break;
case 2:
csize = csbi.dwSize.X;
coord.X = 0;
break;
}
FillConsoleOutputCharacter(handle, ' ', csize, coord, &written);
FillConsoleOutputAttribute(handle, attr, csize, coord, &written);
SetConsoleCursorPosition(handle, csbi.dwCursorPosition);
break;
case 'J':
GetConsoleScreenBufferInfo(handle, &csbi);
w = csbi.dwSize.X;
h = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
coord = csbi.dwCursorPosition;
switch (v[0]) {
default:
case 0:
csize = w * (h - coord.Y) - coord.X;
coord.X = 0;
break;
case 1:
csize = w * coord.Y + coord.X;
coord.X = 0;
coord.Y = csbi.srWindow.Top;
break;
case 2:
csize = w * (h + 1);
coord.X = 0;
coord.Y = csbi.srWindow.Top;
break;
}
FillConsoleOutputCharacter(handle, ' ', csize, coord, &written);
FillConsoleOutputAttribute(handle, attr, csize, coord, &written);
SetConsoleCursorPosition(handle, csbi.dwCursorPosition);
break;
case 'H':
GetConsoleScreenBufferInfo(handle, &csbi);
coord = csbi.dwCursorPosition;
if (v[0] != -1) {
if (v[1] != -1) {
coord.Y = csbi.srWindow.Top + v[0] - 1;
coord.X = v[1] - 1;
}
else
coord.X = v[0] - 1;
}
else {
coord.X = 0;
coord.Y = csbi.srWindow.Top;
}
if (coord.X < csbi.srWindow.Left)
coord.X = csbi.srWindow.Left;
else if (coord.X > csbi.srWindow.Right)
coord.X = csbi.srWindow.Right;
if (coord.Y < csbi.srWindow.Top)
coord.Y = csbi.srWindow.Top;
else if (coord.Y > csbi.srWindow.Bottom)
coord.Y = csbi.srWindow.Bottom;
SetConsoleCursorPosition(handle, coord);
break;
case 'A': // Move up
GetConsoleScreenBufferInfo(handle, &csbi);
coord = csbi.dwCursorPosition;
if (n > 0) {
coord.Y = coord.Y - v[0];
}
else {
coord.Y = coord.Y - 1;
}
if (coord.Y < csbi.srWindow.Top) coord.Y = csbi.srWindow.Top;
SetConsoleCursorPosition(handle, coord);
SetConsoleTextAttribute(handle, attr);
break;
case 'B': // Move down
GetConsoleScreenBufferInfo(handle, &csbi);
coord = csbi.dwCursorPosition;
if (n > 0) {
coord.Y = coord.Y + v[0];
}
else {
coord.Y = coord.Y + 1;
}
if (coord.Y > csbi.srWindow.Bottom) coord.Y = csbi.srWindow.Bottom;
SetConsoleCursorPosition(handle, coord);
SetConsoleTextAttribute(handle, attr);
break;
case 'C': // Move forward / right
GetConsoleScreenBufferInfo(handle, &csbi);
coord = csbi.dwCursorPosition;
if (n > 0) {
coord.X = coord.X + v[0];
}
else {
coord.X = coord.X + 1;
}
if (coord.X > csbi.srWindow.Right) coord.X = csbi.srWindow.Right;
SetConsoleCursorPosition(handle, coord);
SetConsoleTextAttribute(handle, attr);
break;
case 'D': // Move backward / left
GetConsoleScreenBufferInfo(handle, &csbi);
coord = csbi.dwCursorPosition;
if (n > 0) {
coord.X = coord.X - v[0];
}
else {
coord.X = coord.X - 1;
}
if (coord.X < csbi.srWindow.Left) coord.X = csbi.srWindow.Left;
SetConsoleCursorPosition(handle, coord);
SetConsoleTextAttribute(handle, attr);
break;
case 's':
GetConsoleScreenBufferInfo(handle, &csbi);
saved_coord = csbi.dwCursorPosition;
break;
case 'u':
SetConsoleCursorPosition(handle, saved_coord);
break;
default:
break;
}
}
}
return z;
}

4
MD_AnsiCons.h Normal file
View File

@ -0,0 +1,4 @@
#pragma once
#include <stdio.h>
extern int ansi_write(FILE* fp, const char* buf, int len);

View File

@ -4,12 +4,16 @@
#include <unistd.h> #include <unistd.h>
#if defined(_MSC_VER) || defined(WIN32) #if defined(_MSC_VER) || defined(WIN32)
#include <winsock2.h> #include <winsock2.h>
#include "MD_AnsiCons.h"
#else #else
#include <sys/socket.h> #include <sys/socket.h>
#endif #endif
#include "MagiDoor.h" #include "MagiDoor.h"
void md_putchar(char c) { void md_putchar(char c) {
#if defined(_MSC_VER) || defined(WIN32)
ansi_write(stdout, &c, 1);
#endif
if (mdcontrol.socket == -1) { if (mdcontrol.socket == -1) {
write(STDOUT_FILENO, &c, 1); write(STDOUT_FILENO, &c, 1);
} else { } else {

View File

@ -3,7 +3,7 @@ i686-w64-mingw32-gcc -c MD_Init.c
i686-w64-mingw32-gcc -c MD_Printf.c i686-w64-mingw32-gcc -c MD_Printf.c
i686-w64-mingw32-gcc -c MD_Getc.c i686-w64-mingw32-gcc -c MD_Getc.c
i686-w64-mingw32-gcc -c MD_Sendfile.c i686-w64-mingw32-gcc -c MD_Sendfile.c
i686-w64-mingw32-gcc -c MD_AnsiCons.c
i686-w64-mingw32-gcc -shared -o mdoor.dll *.o -lws2_32 -Wl,--out-implib,libmdoor.a i686-w64-mingw32-gcc -shared -o mdoor.dll *.o -lws2_32 -Wl,--out-implib,libmdoor.a
rm *.o rm *.o