note.c (scrot-1.6.tar.bz2) | : | note.c (scrot-1.7.tar.bz2) | ||
---|---|---|---|---|
/* note.c | /* note.c | |||
Copyright 2019-2020 Daniel T. Borelli <daltomi@disroot.org> | Copyright 2019-2021 Daniel T. Borelli <danieltborelli@gmail.com> | |||
Copyright 2021 Guilherme Janczak <guilherme.janczak@yandex.com> | ||||
Copyright 2021 IFo Hancroft <contact@ifohancroft.com> | ||||
Copyright 2021 Peter Wu <peterwu@hotmail.com> | ||||
Permission is hereby granted, free of charge, to any person obtaining a copy | Permission is hereby granted, free of charge, to any person obtaining a copy | |||
of this software and associated documentation files (the "Software"), to | of this software and associated documentation files (the "Software"), to | |||
deal in the Software without restriction, including without limitation the | deal in the Software without restriction, including without limitation the | |||
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or | rights to use, copy, modify, merge, publish, distribute, sublicense, and/or | |||
sell copies of the Software, and to permit persons to whom the Software is | sell copies of the Software, and to permit persons to whom the Software is | |||
furnished to do so, subject to the following conditions: | furnished to do so, subject to the following conditions: | |||
The above copyright notice and this permission notice shall be included in | The above copyright notice and this permission notice shall be included in | |||
all copies of the Software and its documentation and acknowledgment shall be | all copies of the Software and its documentation and acknowledgment shall be | |||
skipping to change at line 33 | skipping to change at line 36 | |||
*/ | */ | |||
/* This file is part of the scrot project. */ | /* This file is part of the scrot project. */ | |||
#include <assert.h> | #include <assert.h> | |||
#include <stdint.h> | #include <stdint.h> | |||
#include "scrot.h" | #include "scrot.h" | |||
scrotnote note; | enum { // default color | |||
DEF_COLOR_RED = 0, | ||||
DEF_COLOR_GREEN = 0, | ||||
DEF_COLOR_BLUE = 0, | ||||
DEF_COLOR_ALPHA = 255 | ||||
}; | ||||
static Imlib_Font imfont = NULL; | ScrotNote note; | |||
static void load_font(void); | static Imlib_Font imFont = NULL; | |||
static char *parse_text(char **tok, char *const end); | static void loadFont(void); | |||
static char *new_text(const char *src, const size_t len); | static char* parseText(char**, char* const); | |||
static inline void pfree(char **ptr) | static inline void pfree(char** ptr) | |||
{ | { | |||
free(*ptr); | free(*ptr); | |||
*ptr = NULL; | *ptr = NULL; | |||
} | } | |||
static inline void next_space(char **tok) | static inline void nextSpace(char** token) | |||
{ | { | |||
while (*++*tok == ' ' && **tok != '\0'); | while (*++*token == ' ' && **token != '\0') { } | |||
} | } | |||
static inline void next_not_space(char **tok) | static inline void nextNotSpace(char** token) | |||
{ | { | |||
while (*++*tok != ' ' && **tok != '\0'); | while (*++*token != ' ' && **token != '\0') { } | |||
} | } | |||
void scrot_note_new(char *format) | void scrotNoteNew(char* format) | |||
{ | { | |||
scrot_note_free(); | scrotNoteFree(); | |||
note = (scrotnote){NULL,NULL,0,0,0.0,{COLOR_OPTIONAL,0,0,0,0}}; | note = (ScrotNote) { | |||
NULL, NULL, 0, 0, 0.0, | ||||
{ DEF_COLOR_RED, DEF_COLOR_GREEN, | ||||
DEF_COLOR_BLUE, DEF_COLOR_ALPHA } | ||||
}; | ||||
char *const end = format + strlen(format); | char* const end = format + strlen(format); | |||
char *tok = strpbrk(format, "-"); | char* token = strpbrk(format, "-"); | |||
if ((NULL == tok) || (strlen(tok) == 1)) { | if (!token || (strlen(token) == 1)) { | |||
malformed: | ||||
malformed: | pfree(&format); | |||
errx(EXIT_FAILURE, "Error --note option : Malformed syntax."); | ||||
pfree(&format); | } | |||
fprintf(stderr, "Error --note option : Malformed syntax.\n"); | ||||
exit(EXIT_FAILURE); | ||||
} | ||||
while (tok != NULL) { | ||||
const char type = *++tok; | ||||
next_space(&tok); | ||||
switch(type) { | ||||
case 'f': { | ||||
note.font = parse_text(&tok, end); | ||||
if (NULL == note.font) { | ||||
fprintf(stderr, "Error --note option : Malformed syntax for -f\n"); | ||||
exit(EXIT_FAILURE); | ||||
} | ||||
char *number = strrchr(note.font, '/'); | ||||
if (NULL == number) { | ||||
fprintf(stderr, "Error --note option : Malformed syntax for -f, requi | ||||
red number.\n"); | ||||
exit(EXIT_FAILURE); | ||||
} | ||||
int fntsize = options_parse_required_number(++number); | ||||
if (fntsize < 6) | ||||
fprintf(stderr, "Warning: --note option: font size < 6\n"); | ||||
} | ||||
break; | ||||
case 'x': { | ||||
if ((1 != sscanf(tok, "%d", ¬e.x) || (note.x < 0))) { | ||||
fprintf(stderr, "Error --note option : Malformed syntax for -x\n"); | ||||
exit(EXIT_FAILURE); | ||||
} | ||||
next_not_space(&tok); | ||||
} | ||||
break; | ||||
case 'y': { | ||||
if ((1 != sscanf(tok, "%d", ¬e.y)) || (note.y < 0)) { | ||||
fprintf(stderr, "Error --note option : Malformed syntax for -y\n"); | ||||
exit(EXIT_FAILURE); | ||||
} | ||||
next_not_space(&tok); | ||||
} | ||||
break; | ||||
case 'a': { | ||||
if ((1 != sscanf(tok, "%lf", ¬e.angle))) { | ||||
fprintf(stderr, "Error --note option : Malformed syntax for -a\n"); | ||||
exit(EXIT_FAILURE); | ||||
} | ||||
next_not_space(&tok); | ||||
} | ||||
break; | ||||
case 't': | ||||
note.text = parse_text(&tok, end); | ||||
if (NULL == note.text) { | ||||
fprintf(stderr, "Error --note option : Malformed syntax for -t\n"); | ||||
exit(EXIT_FAILURE); | ||||
} | ||||
break; | ||||
case 'c': { | ||||
char *saveptr = NULL; | ||||
char *c = strtok_r(tok, ",", &saveptr); | ||||
int nclrs = 0; | ||||
note.color.status = COLOR_OK; | ||||
while (c) { | ||||
tok = c; | ||||
int color = options_parse_required_number(c); | ||||
if ((color < 0) || color > 255) { | ||||
fprintf(stderr, "Error --note option : color '%d' out of range 0.. | ||||
255\n", color); | ||||
note.color.status = COLOR_ERROR; | ||||
break; | ||||
} | ||||
switch(++nclrs) { | ||||
case 1 : note.color.r = color; break; | ||||
case 2 : note.color.g = color; break; | ||||
case 3 : note.color.b = color; break; | ||||
case 4 : note.color.a = color; break; | ||||
} | ||||
c = strtok_r(NULL, ",", &saveptr); | ||||
} | ||||
if (nclrs != 4) { | while (token) { | |||
fprintf(stderr, "Error --note option : Malformed syntax for -c\n"); | const char type = *++token; | |||
note.color.status = COLOR_ERROR; | char* savePtr = NULL; | |||
char* c; | ||||
nextSpace(&token); | ||||
switch (type) { | ||||
case 'f': | ||||
note.font = parseText(&token, end); | ||||
if (!note.font) | ||||
errx(EXIT_FAILURE, "Error --note option : Malformed syntax for - | ||||
f"); | ||||
char* number = strrchr(note.font, '/'); | ||||
if (!number) | ||||
errx(EXIT_FAILURE, "Error --note option : Malformed syntax for - | ||||
f, required number."); | ||||
int fontSize = optionsParseRequiredNumber(++number); | ||||
if (fontSize < 6) | ||||
warnx("Warning: --note option: font size < 6"); | ||||
break; | ||||
case 'x': | ||||
if ((1 != sscanf(token, "%d", ¬e.x) || (note.x < 0))) | ||||
errx(EXIT_FAILURE, "Error --note option : Malformed syntax for - | ||||
x"); | ||||
nextNotSpace(&token); | ||||
break; | ||||
case 'y': | ||||
if ((1 != sscanf(token, "%d", ¬e.y)) || (note.y < 0)) | ||||
errx(EXIT_FAILURE, "Error --note option : Malformed syntax for - | ||||
y"); | ||||
nextNotSpace(&token); | ||||
break; | ||||
case 'a': | ||||
if ((1 != sscanf(token, "%lf", ¬e.angle))) | ||||
errx(EXIT_FAILURE, "Error --note option : Malformed syntax for - | ||||
a"); | ||||
nextNotSpace(&token); | ||||
break; | ||||
case 't': | ||||
note.text = parseText(&token, end); | ||||
if (!note.text) | ||||
errx(EXIT_FAILURE, "Error --note option : Malformed syntax for - | ||||
t"); | ||||
break; | ||||
case 'c': | ||||
c = strtok_r(token, ",", &savePtr); | ||||
int numberColors = 0; | ||||
while (c) { | ||||
token = c; | ||||
int const color = optionsParseRequireRange( | ||||
optionsParseRequiredNumber(c), 0 ,255); | ||||
switch (++numberColors) { | ||||
case 1: | ||||
note.color.r = color; | ||||
break; | ||||
case 2: | ||||
note.color.g = color; | ||||
break; | ||||
case 3: | ||||
note.color.b = color; | ||||
break; | ||||
case 4: | ||||
note.color.a = color; | ||||
break; | ||||
} | ||||
c = strtok_r(NULL, ",", &savePtr); | ||||
} | ||||
if (numberColors > 4) | ||||
warnx("Warning --note option : Malformed syntax for -c"); | ||||
break; | ||||
default: | ||||
errx(EXIT_FAILURE, "Error --note option : unknown option: '-%c'", ty | ||||
pe); | ||||
} | } | |||
} | ||||
break; | ||||
default: | ||||
fprintf(stderr, "Error --note option : unknown option: '-%c'\n", type); | ||||
exit(EXIT_FAILURE); | ||||
} | ||||
tok = strpbrk(tok, "-"); | token = strpbrk(token, "-"); | |||
} | } | |||
if ((NULL == note.font) || (NULL == note.text)) | if (!note.font || !note.text) | |||
goto malformed; | goto malformed; | |||
load_font(); | loadFont(); | |||
} | } | |||
void scrot_note_free(void) | void scrotNoteFree(void) | |||
{ | { | |||
if (note.text) pfree(¬e.text); | if (note.text) | |||
if (note.font) pfree(¬e.font); | pfree(¬e.text); | |||
if (note.font) | ||||
pfree(¬e.font); | ||||
if (imfont) { | if (imFont) { | |||
imlib_context_set_font(imfont); | imlib_context_set_font(imFont); | |||
imlib_free_font(); | imlib_free_font(); | |||
} | } | |||
} | } | |||
void scrot_note_draw(Imlib_Image im) | void scrotNoteDraw(Imlib_Image im) | |||
{ | { | |||
if (NULL == im) return; | if (!im) | |||
return; | ||||
imlib_context_set_image(im); | imlib_context_set_image(im); | |||
imlib_context_set_font(imfont); | imlib_context_set_font(imFont); | |||
imlib_context_set_direction(IMLIB_TEXT_TO_ANGLE); | imlib_context_set_direction(IMLIB_TEXT_TO_ANGLE); | |||
imlib_context_set_angle(note.angle); | imlib_context_set_angle(note.angle); | |||
if (note.color.status == COLOR_OK) | imlib_context_set_color(note.color.r, | |||
imlib_context_set_color(note.color.r, | note.color.g, | |||
note.color.g, | note.color.b, | |||
note.color.b, | note.color.a); | |||
note.color.a); | ||||
imlib_text_draw(note.x, note.y, note.text); | imlib_text_draw(note.x, note.y, note.text); | |||
} | } | |||
void load_font(void) | void loadFont(void) | |||
{ | { | |||
imfont = imlib_load_font(note.font); | imFont = imlib_load_font(note.font); | |||
if (!imfont) { | if (!imFont) { | |||
fprintf(stderr, "Error --note option : Failed to load fontname: %s\n", not | warnx("Error --note option : Failed to load fontname: %s", note.font); | |||
e.font); | scrotNoteFree(); | |||
scrot_note_free(); | exit(EXIT_FAILURE); | |||
exit(EXIT_FAILURE); | } | |||
} | ||||
} | } | |||
char *parse_text(char **tok, char *const end) | char* parseText(char** token, char* const end) | |||
{ | { | |||
assert(NULL != *tok); | assert(NULL != *token); | |||
assert(NULL != end); | assert(NULL != end); | |||
if (**tok != '\'') return NULL; | ||||
(*tok)++; | ||||
char *begin = *tok; | ||||
while ((*tok != end) && **tok != '\'') { | if (**token != '\'') | |||
(*tok)++; | return NULL; | |||
} | ||||
ptrdiff_t len = (*tok - begin); | (*token)++; | |||
if (len == 0) return NULL; | ||||
return new_text(begin, len); | ||||
} | ||||
char *new_text(const char *src, const size_t len) | ||||
{ | ||||
assert(NULL != src); | ||||
char *text = malloc(len + 1); | char* begin = *token; | |||
assert(NULL != text); | while ((*token != end) && **token != '\'') | |||
(*token)++; | ||||
strncpy(text, src, len); | ptrdiff_t length = (*token - begin); | |||
text[len] = '\0'; | if (length == 0) | |||
return NULL; | ||||
return text; | return strndup(begin, length); | |||
} | } | |||
End of changes. 45 change blocks. | ||||
184 lines changed or deleted | 166 lines changed or added |