Skip to content

Instantly share code, notes, and snippets.

@makerj
Created December 25, 2017 08:33
Show Gist options
  • Save makerj/74634823d8f959cbd78587da2093fe20 to your computer and use it in GitHub Desktop.
Save makerj/74634823d8f959cbd78587da2093fe20 to your computer and use it in GitHub Desktop.
shows xmas tree animation on linux terminal
/*
Copyright (C) 2017 junhee lee
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <stdint.h>
#include <ctype.h>
#include <locale.h>
#include <unistd.h>
#include <signal.h>
#include <sys/ioctl.h>
static struct winsize term;
static char** pane;
int term_init() {
ioctl(1, TIOCGWINSZ, &term);
printf("Termial window information\n");
printf("==========================\n");
printf("row: %d\n", term.ws_row);
printf("col: %d\n", term.ws_col);
printf("xpixel: %d\n", term.ws_xpixel);
printf("ypixel: %d\n", term.ws_ypixel);
if(term.ws_row < 30 || term.ws_col < 50) {
puts("Your terminal is too narrow to render tree");
return 1;
}
return 0;
}
void term_move(int row, int col) {
printf("\x1B[%d;%dH", row, col);
}
void term_cursor_visibility(bool show) {
if(show)
printf("\x1B[?25h");
else
printf("\x1B[?25l");
fflush(stdout);
}
void term_clear() {
term_move(0, 0);
for(int row = 0; row < term.ws_row; ++row)
for(int col = 0; col < term.ws_col; ++col)
putchar(' ');
fflush(stdout);
term_move(0, 0);
}
void term_reset(int signo) {
term_cursor_visibility(true);
exit(0);
}
char** pane_init() {
char** frame = (char**)calloc(term.ws_row, sizeof(char*));
for(int i = 0; i < term.ws_row; ++i) {
frame[i] = (char*)calloc(term.ws_col, sizeof(char*));
}
return frame;
}
void pane_copy(char** lhs, char** rhs) {
for(int row = 0; row < term.ws_row; ++row)
for(int col = 0; col < term.ws_col; ++col)
lhs[row][col] = rhs[row][col];
}
void pane_draw(char** pane) {
for(int row = 0; row < term.ws_row; ++row) {
// marquee
if(row == 28) {
char* line = pane[row];
int line_size = 45;
char last = pane[row][line_size - 1];
memmove(line + 1, line, line_size - 1);
line[0] = last;
}
// print pixel
for(int col = 0; col < term.ws_col; ++col) {
char c = pane[row][col];
if(c == '*') {
static int lastcolor = 0;
printf("\x1B[%dm%c\x1B[0m", lastcolor + 30, c);
lastcolor = (lastcolor + 1) % 10;
} else if(c == '+') {
printf("\x1B[%dm%c\x1B[0m", 32, c);
} else {
putchar(c);
}
}
}
fflush(stdout);
}
void pane_replace_char(char** pane, char old, char newer) {
for(int row = 0; row < term.ws_row; ++row)
for(int col = 0; col < term.ws_col; ++col)
if(pane[row][col] == old)
pane[row][col] = newer;
}
int main(int argc, char** argv) {
setlocale(LC_NUMERIC, "");
signal(SIGINT, term_reset);
int error = term_init();
if(error)
return error;
else
term_cursor_visibility(false);
term_clear();
pane = pane_init();
int r = 0;
strcpy(pane[r++], " ** \n");
strcpy(pane[r++], " + + \n");
strcpy(pane[r++], " ++ ++ \n");
strcpy(pane[r++], " ++ ++ \n");
strcpy(pane[r++], " ++ *+ ++ \n");
strcpy(pane[r++], " ++ + ++ \n");
strcpy(pane[r++], " ++ *+ ++ \n");
strcpy(pane[r++], " +++++++ + * +++++++ \n");
strcpy(pane[r++], " ++ + * * ++ \n");
strcpy(pane[r++], " ++ + + ++ \n");
strcpy(pane[r++], " ++ + ++ \n");
strcpy(pane[r++], " ++ + ++ \n");
strcpy(pane[r++], " ++ * + + ++ \n");
strcpy(pane[r++], " ++ * + + ++ \n");
strcpy(pane[r++], " +++++++ + + +++++++ \n");
strcpy(pane[r++], " ++ * + * + ++ \n");
strcpy(pane[r++], " ++ + * + ++ \n");
strcpy(pane[r++], " ++ + + * + ++ \n");
strcpy(pane[r++], "++ + + + ++\n");
strcpy(pane[r++], "+++++++ + + +++++++\n");
strcpy(pane[r++], " ++ * + + ++ \n");
strcpy(pane[r++], " ++ + * + + ++ \n");
strcpy(pane[r++], " ++ * + + * + ++ \n");
strcpy(pane[r++], " ++ +* + + ++ \n");
strcpy(pane[r++], "++ + * + + ++\n");
strcpy(pane[r++], "++++++++++++++++++++++++++++++++++++++++++++++\n");
strcpy(pane[r++], " \n");
strcpy(pane[r++], "2017.12.25 @makerj++++++++++++++++++++++++++++\n");
strcpy(pane[r++], " Merry Christmas for everyone ! \n");
strcpy(pane[r++], "++++++++++++++++++++++++++++++++++++++++++++++\n");
term_move(0, 0), pane_draw(pane);
for(int i = 0; ; ++i) {
term_move(0, 0), pane_draw(pane);
usleep(100 * 1000);
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment