diff --git a/donut.c b/donut.c index 4ff1db3..f2f3a12 100644 --- a/donut.c +++ b/donut.c @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -20,6 +21,10 @@ #define STEP_ALPHA 0.016028534 #endif +volatile sig_atomic_t keep_running = 1; + +void sigint_handler(int sig) { keep_running = 0; } + // Clears the terminal void clear_terminal() { #if defined(_WIN32) @@ -34,43 +39,54 @@ void clear_terminal() { #endif } +// Frees up the heap +void cleanup(char **buffer, size_t term_size) { + if (buffer) { + for (size_t i = 0; i < term_size; ++i) { + free(buffer[i]); + } + free(buffer); + } + clear_terminal(); +} + // Function allocates memory for the frame buffer -char **allocate_memory(int term_size) { +char **allocate_memory(size_t term_size) { char **array = malloc(term_size * sizeof(char *)); - for (int i = 0; i < term_size; ++i) + for (size_t i = 0; i < term_size; ++i) array[i] = malloc(term_size * sizeof(char)); return array; } // Function gets the size of the terminal -int terminal_size() { - int term_size; +size_t terminal_size() { + size_t term_size; #if defined(_WIN32) CONSOLE_SCREEN_BUFFER_INFO c; GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &c); - int row = (int)(c.srWindow.Bottom - c.srWindow.Top + 1); - int col = (int)(c.srWindow.Right - c.srWindow.Left + 1); + size_t row = (size_t)(c.srWindow.Bottom - c.srWindow.Top + 1); + size_t col = (size_t)(c.srWindow.Right - c.srWindow.Left + 1); term_size = row < col ? row : col; #elif defined(__linux__) struct winsize w; ioctl(STDOUT_FILENO, TIOCGWINSZ, &w); - term_size = w.ws_row < w.ws_col ? (int)w.ws_row : (int)w.ws_col; + term_size = w.ws_row < w.ws_col ? (size_t)w.ws_row : (size_t)w.ws_col; #endif return term_size; } // Function dumps the frame into the terminal -void dump_frame(char **buffer, int term_size) { - for (int i = 0; i < term_size; ++i) { - for (int j = 0; j < term_size; ++j) +void dump_frame(char **buffer, size_t term_size) { + for (size_t i = 0; i < term_size; ++i) { + for (size_t j = 0; j < term_size; ++j) putchar(buffer[i][j]); putchar('\n'); } } // Function builds the frame and returns the frame buffer -char **build_frame(char **buffer, int term_size, int i, int scrn_dist) { +char **build_frame(char **buffer, size_t term_size, size_t i, size_t scrn_dist) { float x = i * STEP_ROT_X; // Rotational speed around the x axis float y = i * STEP_ROT_Y; // Rotational speed around the y axis @@ -80,13 +96,13 @@ char **build_frame(char **buffer, int term_size, int i, int scrn_dist) { float z_buffer[term_size][term_size]; // Declaring buffer for storing z coordinates // Initializing frame buffer and z buffer - for (int i = 0; i < term_size; ++i) - for (int j = 0; j < term_size; ++j) { + for (size_t i = 0; i < term_size; ++i) + for (size_t j = 0; j < term_size; ++j) { buffer[i][j] = ' '; z_buffer[i][j] = 0; } - // Loop uses theta to revolve a point around the center of the circle + // Loop uses theta to revolve a posize_t around the center of the circle // 6.283186 = 2 * Pi = 360° for (float theta = 0; theta < 6.283186; theta += STEP_THETA) { // Precomputing sines and cosines of theta @@ -112,21 +128,22 @@ char **build_frame(char **buffer, int term_size, int i, int scrn_dist) { float z_inv = 1 / z; // Calculating x and y coordinates of the 2D projection - int x_proj = (float)term_size / 2 + scrn_dist * z_inv * x; - int y_proj = (float)term_size / 2 - scrn_dist * z_inv * y; + size_t x_proj = (float)term_size / 2 + scrn_dist * z_inv * x; + size_t y_proj = (float)term_size / 2 - scrn_dist * z_inv * y; // Calculating luminous intensity - float lumi_int = cos_alpha * cos_theta * sin_y - cos_x * cos_theta * sin_alpha - sin_x * sin_theta + cos_y * (cos_x * sin_theta - cos_theta * sin_x * sin_alpha); + float lumi_size_t = cos_alpha * cos_theta * sin_y - cos_x * cos_theta * sin_alpha - sin_x * sin_theta + + cos_y * (cos_x * sin_theta - cos_theta * sin_x * sin_alpha); - /* Checking if surface is pointing away from the point of view - * Also checking if the point is closer than any other point + /* Checking if surface is pointing away from the posize_t of view + * Also checking if the posize_t is closer than any other point * previously plotted */ - if (lumi_int > 0 && z_inv > z_buffer[x_proj][y_proj]) { + if (lumi_size_t > 0 && z_inv > z_buffer[x_proj][y_proj]) { z_buffer[x_proj][y_proj] = z_inv; // Bringing the value of luminance between 0 to 11 - int lumi_idx = lumi_int * 8; + size_t lumi_idx = lumi_size_t * 8; /* Storing an appropriate character that represents the correct * amount of luminance @@ -155,46 +172,48 @@ Examples:\n\ prog_name, prog_name, prog_name); } -void runner(bool dynamic, bool limit, int frames) { +void runner(bool dynamic, bool limit, size_t frames) { + // Set up the signal handler + struct sigaction sa; + sa.sa_handler = sigint_handler; + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + sigaction(SIGINT, &sa, NULL); + // Allocating memory to the frame buffer according to terminal size - int term_size = terminal_size(); - int scrn_dist = term_size * 5 * 3 / (8 * (1 + 2)); + size_t term_size = terminal_size(); + size_t scrn_dist = term_size * 5 * 3 / (8 * (1 + 2)); char **buffer = allocate_memory(term_size); // Loop rotates the donut around both the axes - for (int i = 0; !limit || i < frames; ++i) { + for (size_t i = 0; (keep_running) && (!limit || i < frames); ++i) { if (dynamic && i % 32 == 0 && term_size - terminal_size() != 0) { // Frees the old frame buffer - for (int i = 0; i < term_size; ++i) { - free(buffer[i]); - } - free(buffer); - + cleanup(buffer, term_size); // Reallocates the frame buffer as per new terminal size term_size = terminal_size(); buffer = allocate_memory(term_size); - // Calculates screen distance based on terminal size scrn_dist = term_size * 5 * 3 / (8 * (1 + 2)); } - // Building the frame buffer = build_frame(buffer, term_size, i, scrn_dist); - // Dumping the frame into the terminal dump_frame(buffer, term_size); - // Clearing the frame from the terminal clear_terminal(); } + + // Clean up the heap + cleanup(buffer, term_size); } int main(int argc, char **argv) { bool limit = false; bool dynamic = false; - int frames = 0; + size_t frames = 0; if (argc > 1) { - for (int i = 1; i < argc; ++i) { + for (size_t i = 1; i < argc; ++i) { if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) { help(argv[0]); return EXIT_SUCCESS;