Files
.dotfiles/.local/share/dvd.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;
}