122 lines
3.0 KiB
C
122 lines
3.0 KiB
C
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <sys/ioctl.h>
|
|
#include <termios.h>
|
|
#include <unistd.h>
|
|
|
|
/* Fixed integer size type definitions. */
|
|
typedef __INT8_TYPE__ i8;
|
|
typedef __INT16_TYPE__ i16;
|
|
typedef __INT32_TYPE__ i32;
|
|
typedef __INT64_TYPE__ i64;
|
|
typedef __UINT8_TYPE__ u8;
|
|
typedef __UINT16_TYPE__ u16;
|
|
typedef __UINT32_TYPE__ u32;
|
|
typedef __UINT64_TYPE__ u64;
|
|
|
|
/* Variable integer sizes. */
|
|
typedef signed long long llong;
|
|
typedef unsigned char uchar;
|
|
typedef unsigned short ushort;
|
|
typedef unsigned int uint;
|
|
typedef unsigned long ulong;
|
|
typedef unsigned long long ullong;
|
|
|
|
static const char *formats[3] = {
|
|
"\033[1K" // Erase from start of the line to the cursor
|
|
"\033[%d;%dH" // Set cursor to row and column (origin 1,1)
|
|
"\033[9%dm%s", // Set colour and print text.
|
|
|
|
"\033[%d;%dH" // Set cursor to row and column (origin 1,1)
|
|
"\033[9%dm%s", // Set colour and print text.
|
|
|
|
"\033[%d;%dH" // Set cursor to row and column (origin 1,1)
|
|
"\033[1K" // Erase from start of the line to the cursor
|
|
"\033[9%dm%s", // Set colour and print text.
|
|
};
|
|
|
|
static const char *owo = "owo\0";
|
|
static const char *uwu = "uwu\0";
|
|
static const char *ovo = "ovo\0";
|
|
|
|
static void cursor_pos(int *row, int *col)
|
|
{
|
|
/* Disable echo and canonical mode,
|
|
* So LF isn't needed to continue execution, and so the value isn't printed. */
|
|
tcflag_t flag;
|
|
struct termios term;
|
|
tcgetattr(STDIN_FILENO, &term);
|
|
flag = term.c_lflag;
|
|
term.c_lflag &= ~(ICANON | ECHO); // Disable echo and canonical mode
|
|
tcsetattr(STDIN_FILENO, TCSANOW, &term);
|
|
|
|
/* Acquire the cursor position(s). */
|
|
fprintf(stderr, "\033[6n");
|
|
getchar(); // ESC
|
|
getchar(); // [
|
|
char c;
|
|
*row = 0;
|
|
*col = 0;
|
|
while ((c = getchar()) != ';')
|
|
*row = (*row * 10) + (c - '0');
|
|
while ((c = getchar()) != 'R')
|
|
*col = (*col * 10) + (c - '0');
|
|
|
|
/* Restore the previous flags. */
|
|
term.c_lflag = flag;
|
|
tcsetattr(STDIN_FILENO, TCSANOW, &term);
|
|
}
|
|
|
|
/*
|
|
* INFO: Beware the fmt parameter, since it may break. */
|
|
static void dvd(const char *fmt, const char *txt)
|
|
{
|
|
u8 colour = 0;
|
|
int x, dx = -1;
|
|
int y, dy = 1;
|
|
_Bool tmpx, tmpy;
|
|
cursor_pos(&y, &x);
|
|
fprintf(stderr, "\033[?25l"); // Hide cursor
|
|
|
|
ushort w, h;
|
|
{
|
|
struct winsize ws;
|
|
ioctl(STDERR_FILENO, TIOCGWINSZ, &ws);
|
|
w = ws.ws_col - 2;
|
|
h = ws.ws_row;
|
|
}
|
|
|
|
while (1) {
|
|
/* test for collisions. */
|
|
tmpx = (1 < x) & (x < w);
|
|
tmpy = (1 < y) & (y < h);
|
|
|
|
/* flip direction if that axis has collided. */
|
|
dx = tmpx ? dx : -dx;
|
|
dy = tmpy ? dy : -dy;
|
|
colour = (colour + !(tmpx & tmpy)) & 7; // increment colour on collisions
|
|
|
|
/* Write the message */
|
|
fprintf(stderr,
|
|
fmt,
|
|
y, x,
|
|
colour, txt);
|
|
|
|
/* Increment the co-ordinate, and ensure it remains within bounds. */
|
|
x += dx;
|
|
y += dy;
|
|
|
|
usleep(50 * 1000);
|
|
}
|
|
}
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
/* Perform slightly different actions, depending on arg0. */
|
|
if (!argc) return 1;
|
|
if (!strncmp(*argv, owo, 4)) dvd(formats[0], owo);
|
|
if (!strncmp(*argv, uwu, 4)) dvd(formats[1], uwu);
|
|
if (!strncmp(*argv, ovo, 4)) dvd(formats[2], ovo);
|
|
return 1;
|
|
}
|