Skip to content

Commit cb106f5

Browse files
author
sleepntsheep
committed
feat: togglable progress bar and invert
1 parent 618227e commit cb106f5

File tree

3 files changed

+70
-32
lines changed

3 files changed

+70
-32
lines changed

config.h

+5-1
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,12 @@
22
#ifndef SSLIDE_CONFIG_H
33
#define SSLIDE_CONFIG_H
44

5+
static const SDL_Color bg = { 255, 255, 255, 255 };
6+
static const SDL_Color fg = { 0, 0, 0, 255 };
7+
static const int PROGRESSBAR_HEIGHT = 8;
8+
59
#define FONT_NSCALES 50
6-
#define FONT_STEP 6
10+
#define FONT_STEP 5
711
#define SSLIDE_BUFSIZE 4096 /* max line size */
812

913
#endif /* SSLIDE_CONFIG_H */

premake5.lua

+1-1
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,6 @@ filter "configurations:Release"
5252
filter "configurations:MinimalFont"
5353

5454
filter {}
55-
buildoptions { "-std=c99", "-Wall", "-Wextra", "-pedantic" }
55+
buildoptions { "-std=c17", "-Wall", "-Wextra", "-pedantic" }
5656
links { "SDL2", "SDL2_ttf", "SDL2_image" }
5757

sslide.c

+64-30
Original file line numberDiff line numberDiff line change
@@ -12,20 +12,23 @@
1212
#include <SDL2/SDL_ttf.h>
1313
#include <SDL2/SDL_video.h>
1414

15+
#include <stdarg.h>
1516
#include <stdio.h>
1617
#include <string.h>
1718
#include <stdlib.h>
1819
#include <stdbool.h>
1920
#define SHEEP_DYNARRAY_IMPLEMENTATION
2021
#include "dynarray.h"
22+
#ifndef NO_JSON_CONFIG
2123
#define SHEEP_SJSON_IMPLEMENTATION
2224
#include "sjson.h"
25+
#endif
2326
#define SHEEP_XMALLOC_IMPLEMENTATION
2427
#include "xmalloc.h"
2528
#include "config.h"
2629
#include "tinyfiledialogs.h"
2730

28-
#ifdef USE_UNIFONT
31+
#ifndef NO_UNIFONT
2932
#include "unifont.h"
3033
#else
3134
#include "font.h"
@@ -43,6 +46,20 @@
4346
#define PATH_MAX 4096
4447
#endif
4548

49+
#define die(...) _die(__LINE__, __VA_ARGS__)
50+
51+
static void _die(int line_number, const char * format, ...)
52+
{
53+
va_list vargs;
54+
va_start (vargs, format);
55+
fprintf (stderr, "%d: ", line_number);
56+
vfprintf (stderr, format, vargs);
57+
fprintf (stderr, ".\n");
58+
va_end (vargs);
59+
exit (1);
60+
}
61+
62+
4663
enum FrameType {
4764
FRAMETEXT,
4865
FRAMEIMAGE,
@@ -71,16 +88,18 @@ static SDL_Renderer *rend;
7188
static TTF_Font *fonts[FONT_NSCALES+1];
7289
static int fontsheight[FONT_NSCALES+1];
7390
static const int linespacing = 3;
74-
static const SDL_Color bg = { 255, 255, 255, 255 };
75-
static const SDL_Color fg = { 0, 0, 0, 255 };
7691
static Slide slide;
7792
static char *fontpath = NULL;
7893
/* work directory, if reading from file
7994
* this is directory which that file is in
8095
* else if reading from stdin it's NULL */
8196
static char *slidewd = NULL;
97+
static bool progressbar = true;
98+
static bool invert = false;
8299

100+
#ifndef NO_JSON_CONFIG
83101
void readconfig();
102+
#endif
84103
void loadfonts();
85104
Slide parse_slide_from_file(FILE *in);
86105
int getfontsize(Frame frame, int *width, int *height);
@@ -94,7 +113,7 @@ void loadfonts() {
94113
if (fontpath == NULL) {
95114
fontrw = SDL_RWFromMem(font_ttf, font_ttf_len);
96115
if (fontrw == NULL) {
97-
fprintf(stderr, "FontRwop: %s\n", SDL_GetError());
116+
die("FontRwop: %s", SDL_GetError());
98117
}
99118
}
100119
for (int i = 1; i <= FONT_NSCALES; i++) {
@@ -105,7 +124,7 @@ void loadfonts() {
105124
fonts[i] = TTF_OpenFont(fontpath, i * FONT_STEP);
106125
}
107126
if (fonts[i] == NULL) {
108-
fprintf(stderr, "Open Font fail %d: %s\n", i, SDL_GetError());
127+
fprintf(stderr, "Open Font fail (size: %d): %s\n", i, SDL_GetError());
109128
}
110129
fontsheight[i] = TTF_FontHeight(fonts[i]);
111130
}
@@ -151,8 +170,7 @@ void init() {
151170
SDL_Init(SDL_INIT_VIDEO);
152171
TTF_Init();
153172
if (IMG_Init(IMG_INIT_AVIF | IMG_INIT_JPG | IMG_INIT_PNG | IMG_INIT_WEBP) < 1) {
154-
fprintf(stderr, "IMG_Init Failed: %s", IMG_GetError());
155-
exit(1);
173+
die("Img_INIT: %s", IMG_GetError());
156174
}
157175
win = SDL_CreateWindow("Slide", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, w, h, SDL_WINDOW_RESIZABLE);
158176
rend = SDL_CreateRenderer(win, -1, 0);
@@ -195,7 +213,7 @@ void drawframe(Frame frame) {
195213

196214
for (size_t i = 0; i < arrlen(frame.lines); i++) {
197215
SDL_Surface *textsurface = TTF_RenderUTF8_Blended(fonts[fontsize],
198-
frame.lines[i], fg);
216+
frame.lines[i], invert ? bg : fg);
199217
SDL_Texture *texttexture = SDL_CreateTextureFromSurface(rend, textsurface);
200218
int linew, lineh;
201219
SDL_QueryTexture(texttexture, NULL, NULL, &linew, &lineh);
@@ -233,20 +251,31 @@ void drawframe(Frame frame) {
233251
}
234252

235253
void drawpage(Page page) {
236-
SDL_SetRenderDrawColor(rend, bg.r, bg.g, bg.b, bg.a);
254+
SDL_Color realbg = invert ? fg : bg;
255+
SDL_SetRenderDrawColor(rend, realbg.r, realbg.g, realbg.b, realbg.a);
237256
SDL_RenderClear(rend);
238257
for (size_t i = 0; i < arrlen(page); i++) {
239258
drawframe(page[i]);
240259
}
241-
SDL_RenderPresent(rend);
260+
}
261+
262+
void drawprogressbar(float progress /* value between 0 and 1 */) {
263+
SDL_Rect bar = {
264+
.x = 0,
265+
.y = h - PROGRESSBAR_HEIGHT,
266+
.w = progress * w,
267+
.h = PROGRESSBAR_HEIGHT,
268+
};
269+
SDL_Color realfg = invert ? bg : fg;
270+
SDL_SetRenderDrawColor(rend, realfg.r, realfg.g, realfg.b, realfg.a);
271+
SDL_RenderFillRect(rend, &bar);
242272
}
243273

244274
void run() {
245275
size_t pagei = 0;
246276
SDL_Event event;
247-
drawpage(slide[pagei]);
248277

249-
while (1) {
278+
while (true) {
250279
bool redraw = false;
251280
/* event loop */
252281
while (SDL_PollEvent(&event)) {
@@ -279,6 +308,14 @@ void run() {
279308
pagei = arrlen(slide) - 1;
280309
redraw = true;
281310
break;
311+
case SDLK_i:
312+
invert ^= true;
313+
redraw = true;
314+
break;
315+
case SDLK_p:
316+
progressbar ^= true;
317+
redraw = true;
318+
break;
282319
default:
283320
break;
284321
}
@@ -306,6 +343,10 @@ void run() {
306343

307344
if (redraw) {
308345
drawpage(slide[pagei]);
346+
if (progressbar) {
347+
drawprogressbar((float)(pagei+1)/arrlen(slide));
348+
}
349+
SDL_RenderPresent(rend);
309350
}
310351
SDL_Delay(15);
311352
}
@@ -327,8 +368,7 @@ int main(int argc, char **argv) {
327368
if (srcfile != NULL /* not reading from stdin */) {
328369
fin = fopen(srcfile, "r");
329370
if (fin == NULL) {
330-
fprintf(stderr, "Failed opening file\n");
331-
exit(1);
371+
die("Failed opening file %s", srcfile);
332372
}
333373
/* basename() is not portable */
334374
char *sep = srcfile + strlen(srcfile);
@@ -347,7 +387,9 @@ int main(int argc, char **argv) {
347387
}
348388
}
349389

390+
#ifndef NO_JSON_CONFIG
350391
readconfig();
392+
#endif
351393
init();
352394
loadfonts();
353395
slide = parse_slide_from_file(fin);
@@ -374,8 +416,7 @@ Slide parse_slide_from_file(FILE *in) {
374416

375417
if (ret == NULL /* EOF */) {
376418
if (arrlen(slide) == 0) {
377-
fprintf(stderr, "Error parsing: Slide has no page, make sure every page is terminated");
378-
exit(1);
419+
die("Slide has no page, make sure every page is terminated");
379420
}
380421
/* didn't add page to slide, must free now to prevent memory leak */
381422
arrfree(page);
@@ -387,29 +428,25 @@ Slide parse_slide_from_file(FILE *in) {
387428
break;
388429
}
389430
if (buf[0] != ';') {
390-
fprintf(stderr, "Wrong slide format: no geometry before frame");
391-
exit(1);
431+
die("No geometry before frame");
392432
}
393433
if (buf[1] == 'f') {
394434
frame.x = frame.y = 0;
395435
frame.w = frame.h = 100;
396436
} else if (sscanf(buf, ";%d;%d;%d;%d", &frame.x, &frame.y, &frame.w, &frame.h) != 4) {
397-
fprintf(stderr, "Wrong slide format: Geometry need to be in ;x;y;w;h");
398-
exit(1);
437+
die("Geometry need to be in ;x;y;w;h");
399438
}
400439

401440
while (fgets(buf, sizeof buf, in) != NULL /* EOF */) {
402441
if (buf[0] == '%') {
403442
if (frame.type == FRAMEIMAGE) {
404-
fprintf(stderr, "Only one image per frame is allowed!");
405-
exit(1);
443+
die("Only one image per frame is allowed");
406444
}
407445
char *newline = strchr(buf, '\n');
408446
if (newline != NULL) {
409447
*newline = '\x0';
410448
} else {
411-
fprintf(stderr, "Error parsing");
412-
exit(1);
449+
die("Error parsing");
413450
}
414451
char filename[PATH_MAX] = { 0 };
415452
if (in == stdin
@@ -432,7 +469,6 @@ Slide parse_slide_from_file(FILE *in) {
432469
frame.image.texture = IMG_LoadTexture(rend, filename);
433470
if (frame.image.texture == NULL) {
434471
fprintf(stderr, "Failed loading image %s: %s", filename, SDL_GetError());
435-
exit(1);
436472
}
437473
int imgw, imgh;
438474
SDL_QueryTexture(frame.image.texture, NULL, NULL, &imgw, &imgh);
@@ -446,8 +482,7 @@ Slide parse_slide_from_file(FILE *in) {
446482
continue;
447483
}
448484
if (frame.type == FRAMEIMAGE) {
449-
fprintf(stderr, "Text and image in same frame is not allowed!");
450-
exit(1);
485+
die("Text and image is same frame is not allowed");
451486
}
452487
frame.type = FRAMETEXT;
453488
int blen = strlen(buf);
@@ -466,11 +501,11 @@ Slide parse_slide_from_file(FILE *in) {
466501
return slide;
467502
}
468503

504+
#ifndef NO_JSON_CONFIG
469505
void readconfig() {
470506
char configpath[PATH_MAX] = { 0 };
471507
strcpy(configpath, gethomedir());
472508
strcat(configpath, "/.sslide.json");
473-
puts(configpath);
474509
FILE *configfile = fopen(configpath, "ab+");
475510
fseek(configfile, 0L, SEEK_END);
476511
size_t fsize = ftell(configfile);
@@ -489,11 +524,10 @@ void readconfig() {
489524
}
490525
sjson_free(json);
491526
free(content);
492-
return;
493527
bad:
494-
fprintf(stderr, "No/Bad config file, Skipping\n");
495528
return;
496529
}
530+
#endif
497531

498532
char *gethomedir() {
499533
char *ret = NULL;

0 commit comments

Comments
 (0)