commit 7bd2407f7d44290ca008ff4d0680db7ab14245fe
parent 82302e135658f8e7e10ba2aabd93740c0e23fa24
Author: Martin J. Klöckner <64109770+klewer-martin@users.noreply.github.com>
Date: Mon, 11 Apr 2022 19:34:09 -0300
Merge pull request #3 from klewer-martin/SIGSEV
Fixed SIGSEV, added responsize window resize, added restart function
Diffstat:
M | Makefile | | | 2 | +- |
M | drw.c | | | 81 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------------- |
M | drw.h | | | 12 | ++++++++++-- |
M | main.c | | | 28 | ++++++++++++++++++++++------ |
M | sav.c | | | 2 | ++ |
M | sdl_extra.c | | | 56 | ++++++++++++++++++++++++++++++++++++-------------------- |
M | sdl_extra.h | | | 4 | +++- |
M | util.h | | | 6 | +++++- |
8 files changed, 137 insertions(+), 54 deletions(-)
diff --git a/Makefile b/Makefile
@@ -1,6 +1,6 @@
CC := cc
CLIBS := `sdl2-config --libs --cflags`
-CFLAGS := -lSDL2_ttf -lm -Werror -Wall -pedantic -ansi -std=c99 -g -pthread
+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
OBJS := $(SRCS:.c=.o)
diff --git a/drw.c b/drw.c
@@ -1,12 +1,12 @@
#include "drw.h"
void
-drw_element_color(SDL_Renderer *rend, int x, int y, int h, unsigned int col) {
+drw_element_color(Drw *drw, int x, int y, int h, unsigned int col) {
SDL_Rect rect;
unsigned char r, g, b, a;
- rect.x = x + X_BORDER; /* bottom left + x */
- rect.y = y - Y_BORDER; /* bottom */
+ rect.x = x + drw->x_border; /* bottom left + x */
+ rect.y = y - drw->y_border; /* bottom */
rect.w = RECT_WIDTH; /* fixed width */
rect.h = -h;
@@ -15,12 +15,12 @@ drw_element_color(SDL_Renderer *rend, int x, int y, int h, unsigned int col) {
b = (char)(col >> 8) & 0xFF;
a = (char)(col) & 0xFF;
- SDL_RenderDrawRect(rend, &rect);
- SDL_SetRenderDrawColor(rend, r, g, b, a);
- SDL_RenderFillRect(rend, &rect);
+ SDL_RenderDrawRect(drw->rend, &rect);
+ SDL_SetRenderDrawColor(drw->rend, r, g, b, a);
+ SDL_RenderFillRect(drw->rend, &rect);
- SDL_SetRenderDrawColor(rend, 0, 0, 0, 0);
- SDL_RenderDrawLine(rend, x + X_BORDER, y - Y_BORDER, x + X_BORDER, y - Y_BORDER - h);
+ SDL_SetRenderDrawColor(drw->rend, 0, 0, 0, 0);
+ SDL_RenderDrawLine(drw->rend, x + drw->x_border, y - drw->y_border, x + drw->x_border, y - drw->y_border - h);
}
void
@@ -34,9 +34,9 @@ drw_array_graph(Drw *drw, SAV *sav) {
size_t i;
for(i = x = 0; i < sav->arr->len; i++, x += RECT_WIDTH) {
- if(i == sav->sel) drw_element_color(drw->rend, x, h, sav->arr->v[i], SEL_COLOR);
- else if(i == sav->cmp) drw_element_color(drw->rend, x, h, sav->arr->v[i], CMP_COLOR);
- else drw_element_color(drw->rend, x, h, sav->arr->v[i], NORM_COLOR);
+ if(i == sav->sel) drw_element_color(drw, x, h, sav->arr->v[i], SEL_COLOR);
+ else if(i == sav->cmp) drw_element_color(drw, x, h, sav->arr->v[i], CMP_COLOR);
+ else drw_element_color(drw, x, h, sav->arr->v[i], NORM_COLOR);
}
drw_status_bar(drw, sav);
}
@@ -52,33 +52,41 @@ drw_status_bar(Drw *drw, SAV *sav) {
rect.h = -BAR_HEIGHT;
SDL_RenderDrawRect(drw->rend, &rect);
+
+ /* TODO: Make a variable to store statusbar background color */
SDL_SetRenderDrawColor(drw->rend, 0, 0, 0, 0); /* RGBA */
SDL_RenderFillRect(drw->rend, &rect);
- char status_text[drw-> w / drw->font_size];
+ 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, I: %ld",
+ algo_strings[sav->sel_algo], sav->arr->len, sav->cmps,
+ sav->swps, sav->its);
- if((sav->status == RUN) || (sav->status == UPDATE)) {
- /* sprintf(status_text, "Press SPACE to start sorting the array or ESC/q to quit"); */
- sprintf(status_text, "SORTING (%s sort) L: %ld, C: %ld, S: %ld, I: %ld",
- algo_strings[sav->sel_algo], sav->arr->len, sav->cmps, sav->swps, sav->its);
- drw_text(drw, status_text, 0, drw->h - drw->font_size - 5);
+ drw_text(drw, drw->bar_text, 0, drw->h - drw->font_size - 5);
} else if(sav->status == SORTED) {
- sprintf(status_text, "SORTED (%s sort) done in %.2fs, L: %ld, C: %ld, S: %ld, I: %ld",
+ snprintf(drw->bar_text, drw->bar_text_len - 2,
+ "SORTED (%s sort) done in %.2fs, L: %ld, C: %ld, S: %ld, I: %ld",
algo_strings[sav->sel_algo],
(double)(sav->tf - sav->ti) / CLOCKS_PER_SEC,
sav->arr->len, sav->cmps, sav->swps, sav->its);
- drw_text(drw, status_text, 0, drw->h - drw->font_size - 5);
+ 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) {
drw->text_surface = TTF_RenderText_Blended(drw->font, text, drw->text_color);
drw->text_texture = SDL_CreateTextureFromSurface(drw->rend, drw->text_surface);
- SDL_Rect text_rect = { 10 + x, drw->h - drw->font_size - 5, drw->text_surface->w, drw->text_surface->h };
+ drw->bar_text_rect.x = 10 + x;
+ drw->bar_text_rect.y = drw->h - drw->font_size - 5;
+ drw->bar_text_rect.w = drw->text_surface->w;
+ drw->bar_text_rect.h = drw->text_surface->h;
- SDL_RenderCopy(drw->rend, drw->text_texture, NULL, &text_rect);
+ SDL_RenderCopy(drw->rend, drw->text_texture, NULL, &drw->bar_text_rect);
}
status_t DRW_New(SDL_Renderer *rend, SDL_Window *win, Drw **drw) {
@@ -87,12 +95,18 @@ status_t DRW_New(SDL_Renderer *rend, SDL_Window *win, Drw **drw) {
TTF_Font *font = TTF_OpenFont(FONT_NAME, FONT_SIZE);
- if(!font) fprintf(stderr, "TTF_OpenFont: %s\n", TTF_GetError());
+ if(!font) {
+ fprintf(stderr, "TTF_OpenFont: %s\n", TTF_GetError());
+ return ERROR_OPENING_FONT;
+ }
(*drw)->rend = rend;
(*drw)->win = win;
(*drw)->font = font;
(*drw)->font_size = FONT_SIZE;
+ (*drw)->bar_border = 2;
+ (*drw)->x_border = X_BORDER;
+ (*drw)->y_border = Y_BORDER;
(*drw)->text_color.r = (char)(FONT_COLOR >> 16) & 0xFF;
(*drw)->text_color.g = (char)(FONT_COLOR >> 8) & 0xFF;
@@ -100,10 +114,31 @@ status_t DRW_New(SDL_Renderer *rend, SDL_Window *win, Drw **drw) {
SDL_GetWindowSize(win, &((*drw)->w), &((*drw)->h));
- return 0;
+ (*drw)->bar_rect.x = (*drw)->bar_border; /* top left + x */
+ (*drw)->bar_rect.y = (*drw)->h - (*drw)->bar_border; /* top left + y, (y < 0) */
+ (*drw)->bar_rect.w = (*drw)->w - (2 * (*drw)->bar_border); /* fixed width */
+ (*drw)->bar_rect.h = -BAR_HEIGHT;
+
+ /* sometimes SDL_GetWindowSize() fails */
+ if((*drw)->w < WIN_MIN_W)
+ (*drw)->w = WIN_MIN_W;
+ else if((*drw)->h < WIN_MIN_H)
+ (*drw)->h = WIN_MIN_H;
+
+ (*drw)->bar_text_len = (*drw)->w / (*drw)->font_size;
+ (*drw)->bar_text = (char *)malloc(sizeof(char) * (*drw)->bar_text_len);
+ if((*drw)->bar_text == NULL) return ERROR_MEMORY_ALLOC;
+
+ (*drw)->text_surface = NULL;
+ (*drw)->text_texture = NULL;
+
+ return OK;
}
void DRW_Destroy(Drw *drw) {
+ if(drw == NULL) return;
+
TTF_CloseFont(drw->font);
+ free(drw->bar_text);
free(drw);
}
diff --git a/drw.h b/drw.h
@@ -19,21 +19,29 @@
#define BAR_HEIGHT 14
+#define WIN_MIN_W 800
+#define WIN_MIN_H 600
+
+#define WINDOW_TITLE "SAV - Sorting Algorithms Visualized"
+
typedef struct {
SDL_Renderer *rend;
SDL_Window *win;
SDL_Surface *text_surface;
SDL_Texture *text_texture;
SDL_Color text_color;
+ SDL_Rect bar_rect, bar_text_rect;
TTF_Font *font;
- int w, h, font_size;
+ int w, h, font_size, bar_text_len, bar_border;
+ size_t x_border, y_border;
+ char *bar_text;
} Drw;
status_t DRW_New(SDL_Renderer *rend, SDL_Window *win, Drw **drw);
void DRW_Destroy(Drw *drw);
void drw_element(SDL_Renderer *rend, int x, int y, int h);
-void drw_element_color(SDL_Renderer *rend, int x, int y, int h, unsigned int col);
+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);
diff --git a/main.c b/main.c
@@ -29,6 +29,13 @@ 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;
@@ -37,16 +44,15 @@ main (void) {
SDL_Window *win;
pthread_t p1;
+ status_t st;
setup(&win, &rend);
- SAV_New(&sav);
- DRW_New(rend, win, &drw);
+ if((st = SAV_New(&sav)) != OK) goto end;
+ if((st = DRW_New(rend, win, &drw)) != OK) goto end;
/* assigns random values to array */
- srand((unsigned int)time(NULL));
- for(size_t i = 0; i < sav->arr->len; i++)
- while(!(sav->arr->v[i] = rand() % ARR_MAX));
+ shuffle(sav->arr);
/* start sorting thread */
pthread_create(&p1, NULL, &routine_wrapper, (void *)sav);
@@ -56,18 +62,28 @@ main (void) {
/* main loop */
while(sav->status != STOP) {
- check_events(&(sav->status));
+ 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) {
+ /* this state can only be achived if p1 ended */
+ shuffle(sav->arr);
+ sav->status = RUN;
+
+ /* let's call p1 again */
+ pthread_create(&p1, NULL, &routine_wrapper, (void *)sav);
+ }
}
+end:
pthread_join(p1, NULL);
SAV_Destroy(sav);
diff --git a/sav.c b/sav.c
@@ -29,6 +29,8 @@ status_t SAV_New(SAV **sav) {
}
void SAV_Destroy(SAV *sav) {
+ if(sav == NULL) return;
+
free(sav->arr->v);
free(sav->arr);
free(sav);
diff --git a/sdl_extra.c b/sdl_extra.c
@@ -1,27 +1,42 @@
#include "sdl_extra.h"
-#define WINDOW_TITLE "SAV - Sorting Algorithms Visualized"
-
void
-check_events(status_t *status) {
+check_events(Drw *drw, SAV *sav) {
SDL_Event event;
while (SDL_PollEvent(&event)) {
switch(event.type) {
- case SDL_QUIT: *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; */
- /* default: break; */
- /* } */
+ 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;
}
}
@@ -39,7 +54,7 @@ setup(SDL_Window **win, SDL_Renderer **rend) {
SDL_WINDOWPOS_UNDEFINED,
0,
0,
- SDL_WINDOW_OPENGL
+ SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_UTILITY
);
*rend = SDL_CreateRenderer(*win, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
@@ -49,6 +64,7 @@ setup(SDL_Window **win, SDL_Renderer **rend) {
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");
@@ -61,7 +77,7 @@ setup(SDL_Window **win, SDL_Renderer **rend) {
min_h = ((ARR_MAX) + (2 * Y_BORDER) + TOP_BORDER);
SDL_SetWindowMinimumSize(*win, min_w, min_h);
- SDL_SetWindowMaximumSize(*win, min_w, min_h);
+ /* SDL_SetWindowMaximumSize(*win, min_w, min_h); */
}
void
diff --git a/sdl_extra.h b/sdl_extra.h
@@ -15,8 +15,10 @@
/* } Sav; */
#include "util.h"
+#include "drw.h"
-void check_events(status_t *status);
+/* 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);
diff --git a/util.h b/util.h
@@ -4,7 +4,7 @@
#include <stdio.h>
#include <stdlib.h>
-#define ARR_LEN 150
+#define ARR_LEN 120
#define ARR_MAX 500
#define X_BORDER 40
@@ -14,11 +14,15 @@
#define RECT_WIDTH 6
typedef enum {
+ OK = 0,
RUN,
PAUSE,
UPDATE,
ERROR_MEMORY_ALLOC,
+ ERROR_OPENING_FONT,
+ ERROR_DRW,
SORTED,
+ RESTART,
STOP
} status_t;