diff --git a/MD_AnsiCons.c b/MD_AnsiCons.c new file mode 100644 index 0000000..4985f74 --- /dev/null +++ b/MD_AnsiCons.c @@ -0,0 +1,378 @@ +#include +#include +#include +#include +#include + +#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; +} diff --git a/MD_AnsiCons.h b/MD_AnsiCons.h new file mode 100644 index 0000000..57ef683 --- /dev/null +++ b/MD_AnsiCons.h @@ -0,0 +1,4 @@ +#pragma once +#include + +extern int ansi_write(FILE* fp, const char* buf, int len); \ No newline at end of file diff --git a/MD_Printf.c b/MD_Printf.c index b7780c1..9f6d3ca 100644 --- a/MD_Printf.c +++ b/MD_Printf.c @@ -4,12 +4,16 @@ #include #if defined(_MSC_VER) || defined(WIN32) #include +#include "MD_AnsiCons.h" #else #include #endif #include "MagiDoor.h" void md_putchar(char c) { +#if defined(_MSC_VER) || defined(WIN32) + ansi_write(stdout, &c, 1); +#endif if (mdcontrol.socket == -1) { write(STDOUT_FILENO, &c, 1); } else { diff --git a/buildwin.sh b/buildwin.sh index f2b71e8..9073cf6 100755 --- a/buildwin.sh +++ b/buildwin.sh @@ -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_Getc.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 rm *.o