sav

Sorting Algorithms Visualized
Index Commits Files Refs README LICENSE
commit 9297432fd3f1fa015a2f57457a500d5247dff5ff
parent 7b58aefa91c06a7c6eaaf39914e208e8c192e6a3
Author: Martin J. Klöckner <64109770+klewer-martin@users.noreply.github.com>
Date:   Thu, 14 Apr 2022 00:28:16 -0300

Merge pull request #5 from klewer-martin/modules-reorganization

Modules reorganization
Diffstat:
MMakefile | 5+++--
Aarray.c | 13+++++++++++++
Aarray.h | 16++++++++++++++++
Mdrw.c | 62++++++++++++++++++++++++++++++++++++++++++--------------------
Mdrw.h | 17+++++++++--------
Mmain.c | 102+++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------------
Msav.c | 20+++++++++-----------
Msav.h | 17+++++++++++------
Msdl_extra.c | 71+++++++++++++++--------------------------------------------------------
Msdl_extra.h | 27++++++++++++---------------
Msort.c | 98++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------
Msort.h | 1-
Astatus.h | 20++++++++++++++++++++
Mutil.c | 4++--
Mutil.h | 27+--------------------------
15 files changed, 298 insertions(+), 202 deletions(-)
diff --git a/Makefile b/Makefile
@@ -1,8 +1,9 @@
 CC := cc
 CLIBS := `sdl2-config --libs --cflags`
 CFLAGS := -lSDL2_ttf -lm -Werror -pedantic -ansi -std=c99 -g -pthread
-SRCS := main.c sav.c util.c sort.c drw.c sdl_extra.c
+SRCS := main.c sav.c util.c sort.c drw.c sdl_extra.c array.c
 OBJS := $(SRCS:.c=.o)
+LIBS := array.h status.h
 
 TARGET := sav
 
@@ -10,7 +11,7 @@ TARGET := sav
 
 all: $(TARGET) clean
 
-$(TARGET): $(OBJS)
+$(TARGET): $(OBJS) $(HEADERS) $(LIBS)
     $(CC) $(CLIBS) $(CFLAGS) -o $@ $^
 
 %.o: %.c
diff --git a/array.c b/array.c
@@ -0,0 +1,13 @@
+#include "array.h"
+
+#include <stdio.h>
+#include <time.h>
+
+void
+shuffle(Arr *arr) {
+    srand((unsigned int)time(NULL));
+    for(size_t i = 0; i < arr->len; i++)
+        while(!(arr->v[i] = rand() % ARR_MAX));
+
+    printf("ARRAY: Shuffling array done\n");
+}
diff --git a/array.h b/array.h
@@ -0,0 +1,16 @@
+#ifndef __ARRAY_H__
+#define __ARRAY_H__
+
+#include <stdlib.h>
+
+#define ARR_LEN        128
+#define ARR_MAX        500
+
+typedef struct {
+    int *v;
+    size_t len;
+} Arr;
+
+void shuffle(Arr *arr);
+
+#endif
diff --git a/drw.c b/drw.c
@@ -57,27 +57,38 @@ drw_status_bar(Drw *drw, SAV *sav) {
     SDL_SetRenderDrawColor(drw->rend, 0, 0, 0, 0); /* RGBA */
     SDL_RenderFillRect(drw->rend, &rect);
 
-    if(sav->status == UPDATE) {
-        /* sprintf(drw->bar_text, "Press SPACE to start sorting the array or ESC/q to quit"); */
-        snprintf(drw->bar_text, drw->bar_text_len - 2,
-                "SORTING (%s sort)     L: %ld, C: %ld, S: %ld",
-                algo_strings[sav->sel_algo], sav->arr->len, sav->cmps,
-                sav->swps);
-
-        drw_text(drw, drw->bar_text, 0, drw->h - drw->font_size - 5);
-    } else if(sav->status == SORTED) {
-        snprintf(drw->bar_text, drw->bar_text_len - 2,
-                "SORTED (%s sort) done in %.2fs, L: %ld, C: %ld, S: %ld, extra storage used: %ld Bytes",
-                algo_strings[sav->sel_algo],
-                (double)(sav->tf - sav->ti) / CLOCKS_PER_SEC,
-                sav->arr->len, sav->cmps, sav->swps, sav->B_used);
-
+    if((sav->status == RUN) || (sav->status == UPDATE) || (sav->status == START)) {
+        if(sav->sort_status == SORTED) {
+            snprintf(drw->bar_text, drw->bar_text_len - 2,
+                    "SORTED (%s sort) done in %.2fs, L: %ld, C: %ld, S: %ld, extra storage used: %ld Bytes",
+                    algo_strings[sav->sort_algo],
+                    (double)(sav->tf - sav->ti) / CLOCKS_PER_SEC,
+                    sav->arr->len, sav->cmps, sav->swps, sav->B_used);
+        } else if(sav->sort_status == PAUSE) {
+            if(sav->status == START) {
+                snprintf(drw->bar_text, drw->bar_text_len - 2,
+                        "Welcome to sorting algorithms visualized - (%s sort selected) press SPACE to start sorting",
+                        algo_strings[sav->sort_algo], sav->arr->len, sav->cmps,
+                        sav->swps);
+            } else {
+                snprintf(drw->bar_text, drw->bar_text_len - 2,
+                        "PAUSED (%s sort) press SPACE to resume",
+                        algo_strings[sav->sort_algo], sav->arr->len, sav->cmps,
+                        sav->swps);
+            }
+        } else {
+            snprintf(drw->bar_text, drw->bar_text_len - 2,
+                    "SORTING (%s sort)     L: %ld, C: %ld, S: %ld",
+                    algo_strings[sav->sort_algo], sav->arr->len, sav->cmps,
+                    sav->swps);
+        }
         drw_text(drw, drw->bar_text, 0, drw->h - drw->font_size - 5);
     }
     memset(drw->bar_text, 0, sizeof(char) * drw->bar_text_len);
 }
 
-void drw_text(Drw *drw, char *text, int x, int y) {
+void
+drw_text(Drw *drw, char *text, int x, int y) {
     drw->text_surface = TTF_RenderText_Blended(drw->font, text, drw->text_color);
     drw->text_texture = SDL_CreateTextureFromSurface(drw->rend, drw->text_surface);
 
@@ -89,13 +100,22 @@ void drw_text(Drw *drw, char *text, int x, int y) {
     SDL_RenderCopy(drw->rend, drw->text_texture, NULL, &drw->bar_text_rect);
 }
 
-status_t DRW_New(SDL_Renderer *rend, SDL_Window *win, Drw **drw) {
+status_t
+Drw_new(Drw **drw) {
+    SDL_Renderer *rend;
+    SDL_Window *win;
+    TTF_Font *font;
+
     if((*drw = (Drw *)malloc(sizeof(Drw))) == NULL)
         return ERROR_MEMORY_ALLOC;
 
-    TTF_Font *font = TTF_OpenFont(FONT_NAME, FONT_SIZE);
+    SDL_setup(&win, &rend);
+    (*drw)->rend = rend;
+    (*drw)->win = win;
 
-    if(!font) {
+    font = TTF_OpenFont(FONT_NAME, FONT_SIZE);
+
+    if(font == NULL) {
         fprintf(stderr, "TTF_OpenFont: %s\n", TTF_GetError());
         return ERROR_OPENING_FONT;
     }
@@ -145,10 +165,12 @@ status_t DRW_New(SDL_Renderer *rend, SDL_Window *win, Drw **drw) {
     return OK;
 }
 
-void DRW_Destroy(Drw *drw) {
+void
+Drw_destroy(Drw *drw) {
     if(drw == NULL) return;
 
     TTF_CloseFont(drw->font);
+    SDL_cleanup(drw->win, drw->rend);
     free(drw->bar_text);
     free(drw);
 }
diff --git a/drw.h b/drw.h
@@ -6,14 +6,13 @@
 
 #include "sav.h"
 #include "util.h"
-#include "sort.h"
+#include "sdl_extra.h"
 
 #define SEL_COLOR    0x00FF0000 // RGBA (A not used rn)
 #define CMP_COLOR    0x00FFFF00
 #define NORM_COLOR    0xFF000000
 
 #define FONT_SIZE    12
-/* #define FONT_NAME    "/usr/share/fonts/termite-style/Ubuntu.ttf" */
 #define FONT_NAME    "/home/mk/.local/share/fonts/VictorMono-Bold.ttf"
 #define FONT_COLOR    0xBBBBBB
 
@@ -22,7 +21,10 @@
 #define WIN_MIN_W    800
 #define WIN_MIN_H    600
 
-#define WINDOW_TITLE "SAV - Sorting Algorithms Visualized"
+#define X_BORDER    40
+#define Y_BORDER    40
+#define TOP_BORDER    50
+#define RECT_WIDTH    5
 
 typedef struct {
     SDL_Renderer *rend;
@@ -37,15 +39,14 @@ typedef struct {
     char *bar_text;
 } Drw;
 
-status_t DRW_New(SDL_Renderer *rend, SDL_Window *win, Drw **drw);
-void DRW_Destroy(Drw *drw);
+status_t Drw_new(Drw **drw);
+void Drw_destroy(Drw *drw);
 
 void drw_element(SDL_Renderer *rend, int x, int y, int h);
 void drw_element_color(Drw *drw, int x, int y, int h, unsigned int col);
-void drw_array_graph(Drw *drw, SAV *sav);
-void drw_status_bar(Drw *drw, SAV *sav);
 void drw_text(Drw *drw, char *text, int x, int y);
 
-void loading_animation(Drw *drw, SAV *sav);
+void drw_array_graph(Drw *drw, SAV *sav);
+void drw_status_bar(Drw *drw, SAV *sav);
 
 #endif // __DRAW_H__
diff --git a/main.c b/main.c
@@ -5,18 +5,22 @@
 #include "sort.h"
 #include "util.h"
 #include "sdl_extra.h"
+#include "array.h"
+
+void check_events(Drw *, SAV *);
+void *routine_wrapper(void *);
 
 void *
 routine_wrapper(void *arg) {
     SAV *sav = (SAV *)arg;
 
-    switch(sav->sel_algo) {
+    switch(sav->sort_algo) {
         case BUBBLE_SORT:  bubble_sort(sav); break;
         case INSERTION_SORT: insertion_sort(sav); break;
         case MERGE_SORT: merge_sort_wrapper(sav); break;
         case QUICK_SORT: quick_sort_wrapper(sav); break;
         default:  {
-            fprintf(stderr, "\"sel_algo\" not set. exiting\n");
+            fprintf(stderr, "\"sort_algo\" not set. exiting\n");
             sav->status = STOP;
             break;
         }
@@ -24,68 +28,98 @@ routine_wrapper(void *arg) {
     return NULL;
 }
 
-void
-shuffle(Arr *arr) {
-    srand((unsigned int)time(NULL));
-    for(size_t i = 0; i < arr->len; i++)
-        while(!(arr->v[i] = rand() % ARR_MAX));
-}
-
 int
 main (void) {
     SAV *sav;
     Drw *drw;
-    SDL_Renderer *rend;
-    SDL_Window *win;
 
     pthread_t p1;
     status_t st;
 
-    setup(&win, &rend);
-
-    if((st = SAV_New(&sav)) != OK) goto end;
-    if((st = DRW_New(rend, win, &drw)) != OK) goto end;
+    if((st = SAV_new(&sav)) != OK) goto end;
+    if((st = Drw_new(&drw)) != OK) goto end;
 
     /* assigns random values to array */
     shuffle(sav->arr);
 
+    /* selecting the sorting algorithms */
+    sav->sort_algo = BUBBLE_SORT;
+
     /* start sorting thread */
     pthread_create(&p1, NULL, &routine_wrapper, (void *)sav);
 
-    /* selecting the sorting algorithms */
-    sav->sel_algo = QUICK_SORT;
 
-    sav->status = RUN;
+    sav->status = START;
+    sav->sort_status = PAUSE;
 
     /* main loop */
     while(sav->status != STOP) {
         check_events(drw, sav);
-        if(sav->status == UPDATE) {
-            drw_array_graph(drw, sav);
-            sav->status = RUN;
-            SDL_RenderPresent(rend);
-        }
-        if(sav->status == SORTED) {
-            /* p1 ended */
-            drw_array_graph(drw, sav);
-            SDL_RenderPresent(rend);
-        }
-        if(sav->status == RESTART) {
+
+        drw_array_graph(drw, sav);
+        drw_status_bar(drw, sav);
+        SDL_RenderPresent(drw->rend);
+
+        if((sav->sort_status == SORTED) && (sav->status == RESTART)) {
             /* this state can only be achived if p1 ended */
             shuffle(sav->arr);
             sav->status = RUN;
+            sav->sort_status = RUN;
 
             /* let's call p1 again */
             pthread_create(&p1, NULL, &routine_wrapper, (void *)sav);
         }
     }
 
-end:
+    end:
     pthread_join(p1, NULL);
 
-    SAV_Destroy(sav);
-    DRW_Destroy(drw);
-
-    cleanup(win, rend);
+    SAV_destroy(sav);
+    Drw_destroy(drw);
     return 0;
 }
+
+void
+check_events(Drw *drw, SAV *sav) {
+    SDL_Event event;
+    while (SDL_PollEvent(&event)) {
+        switch(event.type) {
+        case SDL_QUIT:
+            sav->status = sav->sort_status = STOP;
+            break;
+        case SDL_KEYDOWN:
+            switch(event.key.keysym.scancode) {
+            case SDL_SCANCODE_R:
+                if(sav->sort_status == SORTED) sav->status = RESTART;
+                break;
+            /* case SDL_SCANCODE_S: */
+            /*     shuffle(sav->arr); */
+            /*     break; */
+            case SDL_SCANCODE_SPACE:
+                printf("status: %d, sort_status: %d\n", sav->status, sav->sort_status);
+                /* if(sav->status == START) sav->status = sav->sort_status = RUN; */
+                if(sav->sort_status == PAUSE) sav->status = sav->sort_status = RUN;
+                else if(sav->sort_status == RUN) sav->sort_status = PAUSE;
+
+                break;
+            default: break;
+           }
+        case SDL_WINDOWEVENT:
+            switch(event.window.event) {
+            case SDL_WINDOWEVENT_RESIZED:
+                SDL_Log("Window resized to %dx%d", event.window.data1, event.window.data2);
+                drw->w = event.window.data1;
+                drw->h = event.window.data2;
+
+                /* set new window borders */
+                drw->x_border = (drw->w / 2) - ((sav->arr->len * RECT_WIDTH) / 2);
+                drw->y_border = (drw->h / 2) - (ARR_MAX / 2);
+
+                break;
+            default: break;
+           }
+        default: break;
+        }
+    }
+}
+
diff --git a/sav.c b/sav.c
@@ -1,9 +1,4 @@
-#include <stdlib.h>
-#include <unistd.h>
-#include <stdbool.h>
-
-#include "drw.h"
-#include "util.h"
+#include "sav.h"
 
 char *algo_strings[SORT_MAX_ALGORITHMS] = {
     "bubble",
@@ -12,14 +7,16 @@ char *algo_strings[SORT_MAX_ALGORITHMS] = {
     "quick"
 };
 
-status_t SAV_New(SAV **sav) {
+status_t
+SAV_new(SAV **sav) {
     if((*sav = (SAV *)malloc(sizeof(SAV))) == NULL)
         return ERROR_MEMORY_ALLOC;
 
-    (*sav)->sel = (*sav)->cmps = (*sav)->swps = (*sav)->its = (*sav)->B_used = 0;
-    (*sav)->cmp = ARR_MAX + 1;
+    (*sav)->sel = (*sav)->cmp = ARR_MAX + 1;
+    (*sav)->cmps = (*sav)->swps = (*sav)->its = (*sav)->B_used = 0;
     (*sav)->status = RUN;
-    (*sav)->sel_algo = SORT_MAX_ALGORITHMS;
+    (*sav)->sort_status = PAUSE;
+    (*sav)->sort_algo = SORT_MAX_ALGORITHMS;
 
     if(((*sav)->arr = (Arr *)malloc(sizeof(Arr))) == NULL)
         return ERROR_MEMORY_ALLOC;
@@ -35,7 +32,8 @@ status_t SAV_New(SAV **sav) {
     return 0;
 }
 
-void SAV_Destroy(SAV *sav) {
+void
+SAV_destroy(SAV *sav) {
     if(sav == NULL) return;
 
     free(sav->arr->v);
diff --git a/sav.h b/sav.h
@@ -1,11 +1,15 @@
 #ifndef __SAV_H__
 #define __SAV_H__
 
-#include "util.h"
-
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdbool.h>
 #include <time.h>
 #include <SDL2/SDL.h>
 
+#include "util.h"
+#include "array.h"
+
 typedef enum {
     BUBBLE_SORT = 0,
     INSERTION_SORT,
@@ -19,12 +23,13 @@ typedef struct {
     size_t sel, cmp, cmps, swps, its, B_used;
     clock_t ti, tf;
     status_t status;
-    sort_t sel_algo;
-} SAV;
+    status_t sort_status;
+    sort_t sort_algo;
+} SAV; 
 
 extern char *algo_strings[SORT_MAX_ALGORITHMS];
 
-status_t SAV_New(SAV **sav);
-void SAV_Destroy(SAV *sav);
+status_t SAV_new(SAV **sav);
+void SAV_destroy(SAV *sav);
 
 #endif
diff --git a/sdl_extra.c b/sdl_extra.c
@@ -1,72 +1,26 @@
 #include "sdl_extra.h"
 
-void
-check_events(Drw *drw, SAV *sav) {
-    SDL_Event event;
-    while (SDL_PollEvent(&event)) {
-        switch(event.type) {
-        case SDL_QUIT: sav->status = STOP; break;
-        case SDL_KEYDOWN:
-            switch(event.key.keysym.scancode) {
-            /* case SDL_SCANCODE_EQUALS: */ 
-            /*     if(speed > SPEED_MAX) speed -= SPEED_STEP; */
-            /*     break; */
-            /* case SDL_SCANCODE_MINUS: */
-            /*     if(speed < SPEED_MIN) speed += SPEED_STEP; */
-            /*     break; */
-            /* case SDL_SCANCODE_P: */
-            /*     if(status == PAUSE) *status = RUN; */
-            /*     else *status = PAUSE; */
-            /*     break; */
-            case SDL_SCANCODE_R:
-                if(sav->status == SORTED) sav->status = RESTART;
-                else break;
-            default: break;
-           }
-        case SDL_WINDOWEVENT:
-            switch(event.window.event) {
-            case SDL_WINDOWEVENT_RESIZED:
-                SDL_Log("Window resized to %dx%d", event.window.data1, event.window.data2);
-                drw->w = event.window.data1;
-                drw->h = event.window.data2;
-
-                /* set new window borders */
-                drw->x_border = (drw->w / 2) - ((sav->arr->len * RECT_WIDTH) / 2);
-                drw->y_border = (drw->h / 2) - (ARR_MAX / 2);
-
-                break;
-            default: break;
-           }
-        default: break;
-        }
-    }
-}
-
-void
-setup(SDL_Window **win, SDL_Renderer **rend) {
+status_t
+SDL_setup(SDL_Window **win, SDL_Renderer **rend) {
     int min_w, min_h;
 
     SDL_Init(SDL_INIT_VIDEO);
 
     *win = SDL_CreateWindow(
-        WINDOW_TITLE,
+        WIN_TITLE,
         SDL_WINDOWPOS_UNDEFINED,
         SDL_WINDOWPOS_UNDEFINED,
         0,
         0,
-        SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_UTILITY
+        SDL_WINDOW_RESIZABLE | SDL_WINDOW_UTILITY
     );
 
     *rend = SDL_CreateRenderer(*win, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
 
-    if(TTF_Init()==-1) {
-        printf("TTF_Init: %s\n", TTF_GetError());
-        exit(2);
-    }
-
-    /* TODO: return error codes */
-    if (*win == NULL) end("SDL: window cannot be created");
-    else if (*rend == NULL) end("SDL: renderer cannot be created");
+    if ((*win == NULL) || (rend == NULL))
+        return ERROR_NULL_POINTER;
+    else if(TTF_Init() == -1)
+        return ERROR_SDL_FONT_INIT;
 
     SDL_SetRenderDrawColor(*rend, 32, 32, 32, 0);
     SDL_RenderClear(*rend);
@@ -78,12 +32,17 @@ setup(SDL_Window **win, SDL_Renderer **rend) {
 
     SDL_SetWindowMinimumSize(*win, min_w, min_h);
     /* SDL_SetWindowMaximumSize(*win, min_w, min_h); */
+    return OK;
 }
 
-void
-cleanup(SDL_Window *win, SDL_Renderer *rend) {
+status_t
+SDL_cleanup(SDL_Window *win, SDL_Renderer *rend) {
+    if((win == NULL) || (rend == NULL))
+        return ERROR_NULL_POINTER;
+
     SDL_DestroyRenderer(rend);
     SDL_DestroyWindow(win);
     TTF_Quit();
     SDL_Quit();
+    return OK;
 }
diff --git a/sdl_extra.h b/sdl_extra.h
@@ -1,26 +1,23 @@
 #ifndef __SDL_EXTRA_H__
 #define __SDL_EXTRA_H__
 
-#include <stdbool.h>
 #include <SDL2/SDL.h>
 #include <SDL2/SDL_ttf.h>
-/* #include <SDL2/SDL_video.h> */
-/* #include <SDL2/SDL_image.h> */
 
-/* typedef struct { */
-/*     status_t status; */
-/*     int speed; */
-/*     size_t sel, cmp, swap; */
-/*     void (*sort)(int *arr, size_t len); */
-/* } Sav; */
-
-#include "util.h"
+#include "array.h"
+#include "status.h"
 #include "drw.h"
+#include "sav.h"
+
+#define X_BORDER    40
+#define Y_BORDER    40
+#define TOP_BORDER    50
+#define RECT_WIDTH    5
+
+#define WIN_TITLE "SAV: Sorting Algorithms Visualized"
 
-/* void check_events(status_t *status); */
-void check_events(Drw *drw, SAV *sav);
-void setup(SDL_Window **win, SDL_Renderer **rend);
-void cleanup(SDL_Window *win, SDL_Renderer *rend);
+status_t SDL_setup(SDL_Window **win, SDL_Renderer **rend);
+status_t SDL_cleanup(SDL_Window *win, SDL_Renderer *rend);
 
 #endif
 
diff --git a/sort.c b/sort.c
@@ -4,11 +4,16 @@
 
 #include "sort.h"
 
+#define DELAY    5
+
 void
 insertion_sort(SAV *sav) {
     int key;
     size_t i, j;
 
+    if((sav->sort_status == STOP) || (sav->status == STOP)) return;
+    while(sav->sort_status == PAUSE);
+
     sav->ti = clock();
     for(i = 1; i < sav->arr->len; i++, sav->its++) {
         sav->cmps += 1;
@@ -23,29 +28,43 @@ insertion_sort(SAV *sav) {
             sav->cmp = j;
             sav->its++;
 
-            /* wait 'til main thread updates graphics */
-            wait_main_thread(&(sav->status));
-            if(sav->status == STOP) break;
+            /* Delay */
+            for(size_t i = 0; i < DELAY; i++) {
+                if((sav->sort_status == STOP) || (sav->status == STOP))
+                    goto end;
+
+                SDL_Delay(1);
+            }
+            while(sav->sort_status == PAUSE);
         }
         sav->arr->v[j + 1] = key;
         sav->sel = i;
         sav->cmp = j;
         sav->swps += 1;
 
-        /* wait 'til main thread updates graphics */
-        wait_main_thread(&(sav->status));
-        if(sav->status == STOP) break;
+        /* Delay */
+        for(size_t i = 0; i < DELAY; i++) {
+            if((sav->sort_status == STOP) || (sav->status == STOP))
+                goto end;
+
+            SDL_Delay(1);
+        }
+        while(sav->sort_status == PAUSE);
     }
+    end:
 
     sav->tf = clock();
 
-    if(sav->status != STOP) sav->status = SORTED;
+    if(sav->status != STOP) sav->sort_status = SORTED;
 }
 
 void
 bubble_sort(SAV *sav) {
     size_t i, j;
 
+    if((sav->sort_status == STOP) || (sav->status == STOP)) return;
+    while(sav->sort_status == PAUSE);
+
     sav->ti = clock();
     for(i = 0; i < sav->arr->len - 1; i++, sav->its++) {
         for(j = 0; j < (sav->arr->len - 1 - i); j++, sav->its++) {
@@ -57,21 +76,38 @@ bubble_sort(SAV *sav) {
                 sav->swps += 1;
             }
 
-            /* wait 'til main thread updates graphics */
-            wait_main_thread(&(sav->status));
-            if(sav->status == STOP) break;
+            /* Delay */
+            for(size_t i = 0; i < DELAY; i++) {
+                if((sav->sort_status == STOP) || (sav->status == STOP))
+                    goto end;
+
+                SDL_Delay(1);
+            }
+            while(sav->sort_status == PAUSE);
         }
-        wait_main_thread(&(sav->status));
-        if(sav->status == STOP) break;
+
+        /* Delay */
+        for(size_t i = 0; i < DELAY; i++) {
+            if((sav->sort_status == STOP) || (sav->status == STOP))
+                goto end;
+
+            SDL_Delay(1);
+        }
+        while(sav->sort_status == PAUSE);
     }
+    end:
+
     sav->tf = clock();
-    if(sav->status != STOP) sav->status = SORTED;
+    if(sav->status != STOP) sav->sort_status = SORTED;
 }
 
 void
 merge(SAV *sav, int low, int middle, int high) {
     size_t n1, n2, i, j, k;
 
+    if((sav->sort_status == STOP) || (sav->status == STOP)) return;
+    while(sav->sort_status == PAUSE);
+
     n1 = middle - low;
     n2 = high - middle;
 
@@ -97,9 +133,17 @@ merge(SAV *sav, int low, int middle, int high) {
         sav->cmps += 1;
         sav->its += 1;
 
-        wait_main_thread(&(sav->status));
-        if(sav->status == STOP) return;
+        while(sav->sort_status == PAUSE);
+
+        /* Delay */
+        for(size_t i = 0; i < DELAY; i++) {
+            if((sav->sort_status == STOP) || (sav->status == STOP))
+                goto end;
+
+            SDL_Delay(1);
+        }
     }
+    end:
 
     while(i < n1)
         sav->arr->v[k++] = B[i++];
@@ -112,6 +156,11 @@ void
 merge_sort(SAV *sav, int low, int high) {
     if(sav == NULL) return;
 
+    if((sav->sort_status == STOP) || (sav->status == STOP))
+        return;
+
+    while(sav->sort_status == PAUSE);
+
     int middle;
 
     middle = ((high + low) / 2);
@@ -134,7 +183,7 @@ void merge_sort_wrapper(SAV *sav) {
     merge_sort(sav, 0, sav->arr->len);
     sav->tf = clock();
     sav->sel = sav->arr->len + 1;
-    if(sav->status != STOP) sav->status = SORTED;
+    if(sav->status != STOP) sav->sort_status = SORTED;
 }
 
 void
@@ -143,7 +192,7 @@ quick_sort_partition(SAV *sav, int low, int *middle, int high) {
 
     pivot = high;
     sav->sel = pivot;
-    printf("SORT: pivot: %d\n", pivot);
+    /* printf("SORT: pivot: %d\n", pivot); */
 
     for(i = j = low; j < high; j++, sav->cmps += 1) {
         if(sav->arr->v[j] < sav->arr->v[pivot]) {
@@ -151,9 +200,15 @@ quick_sort_partition(SAV *sav, int low, int *middle, int high) {
             sav->swps += 1;
         }
 
-        wait_main_thread(&(sav->status));
-        if(sav->status == STOP) return;
+        if(sav->status != STOP) sav->status = UPDATE;
+        while(sav->sort_status == PAUSE);
+
+        for(size_t i = 0; i < 5; i++) {
+            if(sav->sort_status == STOP) goto end;
+            SDL_Delay(1);
+        }
     }
+    end:
 
     swap(&(sav->arr->v[i]), &(sav->arr->v[pivot]));
     sav->swps += 1;
@@ -164,8 +219,8 @@ void
 quick_sort(SAV *sav, int low, int high) {
     int pivot;
 
-    wait_main_thread(&(sav->status));
     if(sav->status == STOP) return;
+    while(sav->sort_status == PAUSE);
 
     if ((high - low) > 0) {
         quick_sort_partition(sav, low, &pivot, high);
@@ -178,6 +233,7 @@ void
 quick_sort_wrapper(SAV *sav) {
     sav->ti = clock();
     quick_sort(sav, 0, sav->arr->len - 1);
-    sav->status = SORTED;
+    printf("SORT: sorting array done\n");
+    if(sav->sort_status != STOP) sav->sort_status = SORTED;
     sav->tf = clock();
 }
diff --git a/sort.h b/sort.h
@@ -5,7 +5,6 @@
 #include <stdbool.h>
 
 #include "sav.h"
-#include "util.h"
 
 void bubble_sort(SAV *);
 void insertion_sort(SAV *);
diff --git a/status.h b/status.h
@@ -0,0 +1,20 @@
+#ifndef __STATUS_H__
+#define __STATUS_H__
+
+typedef enum {
+    OK = 0,
+    RUN,
+    PAUSE,
+    UPDATE,
+    ERROR_MEMORY_ALLOC,
+    ERROR_OPENING_FONT,
+    ERROR_SDL_FONT_INIT,
+    ERROR_NULL_POINTER,
+    ERROR_DRW,
+    SORTED,
+    START,
+    RESTART,
+    STOP
+} status_t;
+
+#endif
diff --git a/util.c b/util.c
@@ -2,10 +2,10 @@
 
 void
 wait_main_thread(status_t *st) {
-    if(*st != STOP) *st = UPDATE;
+    if((*st != STOP) && (*st != PAUSE)) *st = UPDATE;
 
     /* wait 'til main thread changes st value to RUN */
-    while(*st == UPDATE);
+    while((*st == UPDATE) || (*st == PAUSE));
 }
 
 void
diff --git a/util.h b/util.h
@@ -4,32 +4,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 
-#define ARR_LEN        128
-#define ARR_MAX        500
-
-#define X_BORDER    40
-#define Y_BORDER    40
-#define TOP_BORDER    50
-
-#define RECT_WIDTH    5
-
-typedef enum {
-    OK = 0,
-    RUN,
-    PAUSE,
-    UPDATE,
-    ERROR_MEMORY_ALLOC,
-    ERROR_OPENING_FONT,
-    ERROR_DRW,
-    SORTED,
-    RESTART,
-    STOP
-} status_t;
-
-typedef struct {
-    int *v;
-    size_t len;
-} Arr;
+#include "status.h"
 
 void end(const char *msg);
 void swap(int *a, int *b);