"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "src/options.c" between
scrot-1.7.tar.bz2 and scrot-1.8.tar.gz

About: scrot (SCReenshOT) is a simple command line screen capture utility using imlib2 to grab and save images.

options.c  (scrot-1.7.tar.bz2):options.c  (scrot-1.8)
skipping to change at line 12 skipping to change at line 12
Copyright 1999-2000 Tom Gilbert <tom@linuxbrit.co.uk, Copyright 1999-2000 Tom Gilbert <tom@linuxbrit.co.uk,
gilbertt@linuxbrit.co.uk, gilbertt@linuxbrit.co.uk,
scrot_sucks@linuxbrit.co.uk> scrot_sucks@linuxbrit.co.uk>
Copyright 2008 William Vera <billy@billy.com.mx> Copyright 2008 William Vera <billy@billy.com.mx>
Copyright 2009 George Danchev <danchev@spnet.net> Copyright 2009 George Danchev <danchev@spnet.net>
Copyright 2009 James Cameron <quozl@us.netrek.org> Copyright 2009 James Cameron <quozl@us.netrek.org>
Copyright 2010 Ibragimov Rinat <ibragimovrinat@mail.ru> Copyright 2010 Ibragimov Rinat <ibragimovrinat@mail.ru>
Copyright 2017 Stoney Sauce <stoneysauce@gmail.com> Copyright 2017 Stoney Sauce <stoneysauce@gmail.com>
Copyright 2019 Daniel Lublin <daniel@lublin.se> Copyright 2019 Daniel Lublin <daniel@lublin.se>
Copyright 2019-2021 Daniel T. Borelli <danieltborelli@gmail.com> Copyright 2019-2022 Daniel T. Borelli <danieltborelli@gmail.com>
Copyright 2019 Jade Auer <jade@trashwitch.dev> Copyright 2019 Jade Auer <jade@trashwitch.dev>
Copyright 2020 Sean Brennan <zettix1@gmail.com> Copyright 2020 Sean Brennan <zettix1@gmail.com>
Copyright 2021 Christopher R. Nelson <christopher.nelson@languidnights.com> Copyright 2021 Christopher R. Nelson <christopher.nelson@languidnights.com>
Copyright 2021 Guilherme Janczak <guilherme.janczak@yandex.com> Copyright 2021-2023 Guilherme Janczak <guilherme.janczak@yandex.com>
Copyright 2021 IFo Hancroft <contact@ifohancroft.com> Copyright 2021 IFo Hancroft <contact@ifohancroft.com>
Copyright 2021 Peter Wu <peterwu@hotmail.com> Copyright 2021 Peter Wu <peterwu@hotmail.com>
Copyright 2021 Wilson Smith <01wsmith+gh@gmail.com> Copyright 2021 Wilson Smith <01wsmith+gh@gmail.com>
Copyright 2022 Zev Weiss <zev@bewilderbeest.net>
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 42 skipping to change at line 43
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/ */
#include <assert.h>
#include <err.h>
#include <errno.h>
#include <getopt.h>
#include <limits.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "config.h"
#include "note.h"
#include "options.h" #include "options.h"
#include "scrot.h" #include "scrot.h"
#include <assert.h> #include "scrot_selection.h"
#include "util.h"
#define STR_LEN_MAX_FILENAME(msg, fileName) do { \ #define STR_LEN_MAX_FILENAME(msg, fileName) do { \
if (strlen((fileName)) > MAX_FILENAME) { \ if (strlen((fileName)) > MAX_FILENAME) { \
errx(EXIT_FAILURE, #msg " filename too long, must be " \ errx(EXIT_FAILURE, #msg " filename too long, must be " \
"less than %d characters", MAX_FILENAME); \ "less than %d characters", MAX_FILENAME); \
} \ } \
} while(0) } while(0)
#define checkMaxOutputFileName(fileName) \ #define checkMaxOutputFileName(fileName) \
STR_LEN_MAX_FILENAME(output, (fileName)) STR_LEN_MAX_FILENAME(output, (fileName))
#define checkMaxInputFileName(fileName) \ #define checkMaxInputFileName(fileName) \
STR_LEN_MAX_FILENAME(input, (fileName)) STR_LEN_MAX_FILENAME(input, (fileName))
enum { enum {
MAX_LEN_WINDOW_CLASS_NAME = 80, //characters MAX_LEN_WINDOW_CLASS_NAME = 80, //characters
MAX_FILENAME = 256, // characters MAX_FILENAME = 256, // characters
MAX_DISPLAY_NAME = 256, // characters MAX_DISPLAY_NAME = 256, // characters
}; };
ScrotOptions opt = { struct ScrotOptions opt = {
.quality = 75, .quality = 75,
.lineStyle = LineSolid, .lineStyle = LineSolid,
.lineWidth = 1, .lineWidth = 1,
.lineOpacity = SELECTION_OPACITY_DEFAULT, .lineOpacity = SELECTION_OPACITY_DEFAULT,
.lineMode = LINE_MODE_S_CLASSIC, .lineMode = LINE_MODE_S_CLASSIC,
.stackDirection = HORIZONTAL, .stackDirection = HORIZONTAL,
.monitor = -1,
}; };
int optionsParseRequiredNumber(char const* str) static void showUsage(void);
{ static void showVersion(void);
assert(NULL != str); // fix yout caller function, static void optionsParseThumbnail(char *);
// the user does not impose this behavior
char* end = NULL; /* optionsParseNum: "string to number" function.
long ret = 0L; *
errno = 0; * Parses the string representation of an integer in str, and simultaneously
* ensures that it is >= min and <= max.
ret = strtol(str, &end, 10); *
* Returns the integer and sets *errmsg to NULL on success.
if (errno) * Returns 0 and sets *errmsg to a pointer to a string containing the
goto range_error; * reason why the number can't be parsed on error.
*
if (str == end) * usage:
errx(EXIT_FAILURE, "the option is not a number: %s", end); * char *errmsg;
* unsigned int nonnegative;
if (ret > INT_MAX || ret < INT_MIN) { * if ((nonnegative = optionsParseNum(optarg, 0, UINT_MAX, &errmsg)) == NULL)
errno = ERANGE; * errx(EXIT_FAILURE, "-n: '%s' is %s", optarg, errmsg);
goto range_error; */
long long optionsParseNum(const char *str, long long min, long long max,
const char *errmsg[static 1])
{
char *end = NULL;
long long rval;
int saved_errno = errno;
if (str == NULL) {
*errmsg = "missing";
return 0;
} }
*errmsg = NULL;
return ret; errno = 0;
rval = strtoll(str, &end, 10);
range_error: if (errno == ERANGE) {
err(EXIT_FAILURE, "error strtol"); *errmsg = "not representable";
} } else if (*str == '\0') {
*errmsg = "the null string";
static int nonNegativeNumber(int number) } else if (*end != '\0') {
{ *errmsg = "not a number";
return (number < 0) ? 0 : number; } else if (rval < min) {
} /*
* rval could be set to 0 due to strtoll() returning error and this
* could be smaller than min or larger than max. To make sure we don't
* return the wrong error message, put min/max checks after everything
* else.
*/
*errmsg = min == 0 ? "negative" : "too small";
} else if (rval > max) {
*errmsg = "too large";
}
errno = saved_errno;
int optionsParseRequireRange(int n, int lo, int hi) return (*errmsg ? 0 : rval);
{
return (n < lo ? lo : n > hi ? hi : n);
} }
bool optionsParseIsString(char const* const str) static bool optionsParseIsString(const char *const str)
{ {
return (str && (str[0] != '\0')); return (str && (str[0] != '\0'));
} }
static void optionsParseStack(char const* optarg) static void optionsParseStack(const char *optarg)
{ {
// the suboption it's optional // the suboption it's optional
if (!optarg) { if (!optarg) {
opt.stackDirection = HORIZONTAL; opt.stackDirection = HORIZONTAL;
return; return;
} }
char const* value = strchr(optarg, '='); const char *value = strchr(optarg, '=');
if (value) if (value)
++value; ++value;
else else
value = optarg; value = optarg;
if (*value == 'v') if (*value == 'v')
opt.stackDirection = VERTICAL; opt.stackDirection = VERTICAL;
else if (*value == 'h') else if (*value == 'h')
opt.stackDirection = HORIZONTAL; opt.stackDirection = HORIZONTAL;
else { else {
errx(EXIT_FAILURE, "option --stack: Unknown value for suboption '%s'", errx(EXIT_FAILURE, "option --stack: Unknown value for suboption '%s'",
value); value);
} }
} }
static void optionsParseSelection(char const* optarg) static void optionsParseSelection(const char *optarg)
{ {
// the suboption it's optional // the suboption it's optional
if (!optarg) { if (!optarg) {
opt.selection.mode = SELECTION_MODE_CAPTURE; opt.selection.mode = SELECTION_MODE_CAPTURE;
return; return;
} }
char const* value = strchr(optarg, '='); const char *value = strchr(optarg, '=');
if (value) if (value)
++value; ++value;
else else
value = optarg; value = optarg;
if (!strncmp(value, SELECTION_MODE_S_CAPTURE, SELECTION_MODE_L_CAPTURE)) { if (!strncmp(value, SELECTION_MODE_S_CAPTURE, SELECTION_MODE_L_CAPTURE)) {
opt.selection.mode = SELECTION_MODE_CAPTURE; opt.selection.mode = SELECTION_MODE_CAPTURE;
return; /* it has no parameter */ return; /* it has no parameter */
} }
skipping to change at line 186 skipping to change at line 220
if (opt.selection.mode & SELECTION_MODE_NOT_NEED_PARAM) if (opt.selection.mode & SELECTION_MODE_NOT_NEED_PARAM)
return; return;
if (*value != SELECTION_MODE_SEPARATOR) if (*value != SELECTION_MODE_SEPARATOR)
return; return;
if (*(++value) == '\0') if (*(++value) == '\0')
errx(EXIT_FAILURE, "option --select: Invalid parameter."); errx(EXIT_FAILURE, "option --select: Invalid parameter.");
if (opt.selection.mode == SELECTION_MODE_BLUR) { if (opt.selection.mode == SELECTION_MODE_BLUR) {
int const num = nonNegativeNumber(optionsParseRequiredNumber(value)); const char *errmsg;
opt.selection.paramNum = optionsParseNum(value,
opt.selection.paramNum = optionsParseRequireRange(num, SELECTION_MODE_BLUR_MIN, SELECTION_MODE_BLUR_MAX, &errmsg);
SELECTION_MODE_BLUR_MIN, SELECTION_MODE_BLUR_MAX); if (errmsg)
errx(EXIT_FAILURE, "option --select: '%s' is %s", value, errmsg);
} else { // SELECTION_MODE_HIDE } else { // SELECTION_MODE_HIDE
checkMaxInputFileName(value); checkMaxInputFileName(value);
opt.selection.paramStr = strdup(value); opt.selection.paramStr = estrdup(value);
} }
} }
static void optionsParseLine(char* optarg) static void optionsParseLine(char *optarg)
{ {
enum { enum {
Style = 0, Style = 0,
Width, Width,
Color, Color,
Opacity, Opacity,
Mode Mode
}; };
char* const token[] = { char *const token[] = {
[Style] = "style", [Style] = "style",
[Width] = "width", [Width] = "width",
[Color] = "color", [Color] = "color",
[Opacity] = "opacity", [Opacity] = "opacity",
[Mode] = "mode", [Mode] = "mode",
NULL NULL
}; };
char* subopts = optarg; char *subopts = optarg;
char* value = NULL; char *value = NULL;
const char *errmsg;
while (*subopts != '\0') { while (*subopts != '\0') {
switch (getsubopt(&subopts, token, &value)) { switch (getsubopt(&subopts, token, &value)) {
case Style: case Style:
if (!optionsParseIsString(value)) { if (!optionsParseIsString(value)) {
errx(EXIT_FAILURE, "Missing value for suboption '%s'", errx(EXIT_FAILURE, "Missing value for suboption '%s'",
token[Style]); token[Style]);
} }
if (!strncmp(value, "dash", 4)) if (!strncmp(value, "dash", 4))
opt.lineStyle = LineOnOffDash; opt.lineStyle = LineOnOffDash;
else if (!strncmp(value, "solid", 5)) else if (!strncmp(value, "solid", 5))
opt.lineStyle = LineSolid; opt.lineStyle = LineSolid;
else { else {
errx(EXIT_FAILURE, "Unknown value for suboption '%s': %s", errx(EXIT_FAILURE, "Unknown value for suboption '%s': %s",
token[Style], value); token[Style], value);
} }
break; break;
case Width: case Width:
if (!optionsParseIsString(value)) { opt.lineWidth = optionsParseNum(value, 1, 8, &errmsg);
errx(EXIT_FAILURE, "Missing value for suboption '%s'", if (errmsg) {
token[Width]); if (value == NULL)
} value = "(null)";
errx(EXIT_FAILURE, "option --line: suboption '%s': '%s' is %s",
opt.lineWidth = optionsParseRequiredNumber(value); token[Width], value, errmsg);
if (opt.lineWidth <= 0 || opt.lineWidth > 8) {
errx(EXIT_FAILURE, "Value of the range (1..8) for "
"suboption '%s': %d", token[Width], opt.lineWidth);
} }
break; break;
case Color: case Color:
if (!optionsParseIsString(value)) { if (!optionsParseIsString(value)) {
errx(EXIT_FAILURE, "Missing value for suboption '%s'", errx(EXIT_FAILURE, "Missing value for suboption '%s'",
token[Color]); token[Color]);
} }
opt.lineColor = strdup(value); opt.lineColor = estrdup(value);
break; break;
case Mode: case Mode:
if (!optionsParseIsString(value)) { if (!optionsParseIsString(value)) {
errx(EXIT_FAILURE, "Missing value for suboption '%s'", errx(EXIT_FAILURE, "Missing value for suboption '%s'",
token[Mode]); token[Mode]);
} }
bool isValidMode = !strncmp(value, LINE_MODE_S_CLASSIC, LINE_MODE_L_ CLASSIC); bool isValidMode = !strncmp(value, LINE_MODE_S_CLASSIC, LINE_MODE_L_ CLASSIC);
isValidMode = isValidMode || !strncmp(value, LINE_MODE_S_EDGE, LINE_ MODE_L_EDGE); isValidMode = isValidMode || !strncmp(value, LINE_MODE_S_EDGE, LINE_ MODE_L_EDGE);
if (!isValidMode) { if (!isValidMode) {
errx(EXIT_FAILURE, "Unknown value for suboption '%s': %s", errx(EXIT_FAILURE, "Unknown value for suboption '%s': %s",
token[Mode], value); token[Mode], value);
} }
opt.lineMode = strdup(value); opt.lineMode = estrdup(value);
break; break;
case Opacity: case Opacity:
if (!optionsParseIsString(value)) { opt.lineOpacity = optionsParseNum(value,
errx(EXIT_FAILURE, "Missing value for suboption '%s'", SELECTION_OPACITY_MIN, SELECTION_OPACITY_MAX, &errmsg);
token[Opacity]); if (errmsg) {
if (value == NULL)
value = "(null)";
errx(EXIT_FAILURE, "option --line: suboption %s: '%s' is %s",
token[Opacity], value, errmsg);
} }
opt.lineOpacity = optionsParseRequiredNumber(value);
break; break;
default: default:
errx(EXIT_FAILURE, "No match found for token: '%s'", value); errx(EXIT_FAILURE, "No match found for token: '%s'", value);
break; break;
} }
} /* while */ } /* while */
} }
static void optionsParseWindowClassName(const char* windowClassName) static void optionsParseWindowClassName(const char *windowClassName)
{ {
assert(windowClassName != NULL); assert(windowClassName != NULL);
if (windowClassName[0] != '\0') if (windowClassName[0] != '\0')
opt.windowClassName = strndup(windowClassName, MAX_LEN_WINDOW_CLASS_NAME ); opt.windowClassName = strndup(windowClassName, MAX_LEN_WINDOW_CLASS_NAME );
} }
static bool accessFileOk(const char* const pathName) static bool accessFileOk(const char *const pathName)
{ {
errno = 0; errno = 0;
return (0 == access(pathName, W_OK)); return (0 == access(pathName, W_OK));
} }
static char* getPathOfStdout(void) static char *getPathOfStdout(void)
{ {
char path[16] = {"/dev/stdout"}; char path[16] = {"/dev/stdout"};
size_t const len = sizeof(path); const size_t len = sizeof(path);
if (!accessFileOk(path)) { if (!accessFileOk(path)) {
snprintf(path, len, "/dev/fd/%d", STDOUT_FILENO); snprintf(path, len, "/dev/fd/%d", STDOUT_FILENO);
if (!accessFileOk(path)) { if (!accessFileOk(path)) {
snprintf(path, len, "/proc/self/fd/%d", STDOUT_FILENO); snprintf(path, len, "/proc/self/fd/%d", STDOUT_FILENO);
if (!accessFileOk(path)) { if (!accessFileOk(path)) {
// We quit because imlib2 will fail later anyway. // We quit because imlib2 will fail later anyway.
err(EXIT_FAILURE, "access to stdout failed"); err(EXIT_FAILURE, "access to stdout failed");
} }
} }
} }
return strndup(path, len); return strndup(path, len);
} }
void optionsParse(int argc, char** argv) void optionsParse(int argc, char *argv[])
{ {
static char stropts[] = "a:ofipbcd:e:hmq:s::t:uvzn:l:D:k::C:S:F:"; static char stropts[] = "a:ofipbcd:e:hmq:s::t:uvzn:l:D:k::C:S:F:M:";
static struct option lopts[] = { static struct option lopts[] = {
/* actions */ /* actions */
{ "help", no_argument, 0, 'h' }, { "help", no_argument, 0, 'h' },
{ "version", no_argument, 0, 'v' }, { "version", no_argument, 0, 'v' },
{ "count", no_argument, 0, 'c' }, { "count", no_argument, 0, 'c' },
{ "focused", no_argument, 0, 'u' }, { "focused", no_argument, 0, 'u' },
{ "focussed", no_argument, 0, 'u' }, /* macquarie dictionary has both sp ellings */ { "focussed", no_argument, 0, 'u' }, /* macquarie dictionary has both sp ellings */
{ "border", no_argument, 0, 'b' }, { "border", no_argument, 0, 'b' },
{ "multidisp", no_argument, 0, 'm' }, { "multidisp", no_argument, 0, 'm' },
skipping to change at line 358 skipping to change at line 392
{ "delay", required_argument, 0, 'd' }, { "delay", required_argument, 0, 'd' },
{ "quality", required_argument, 0, 'q' }, { "quality", required_argument, 0, 'q' },
{ "exec", required_argument, 0, 'e' }, { "exec", required_argument, 0, 'e' },
{ "autoselect", required_argument, 0, 'a' }, { "autoselect", required_argument, 0, 'a' },
{ "display", required_argument, 0, 'D' }, { "display", required_argument, 0, 'D' },
{ "note", required_argument, 0, 'n' }, { "note", required_argument, 0, 'n' },
{ "line", required_argument, 0, 'l' }, { "line", required_argument, 0, 'l' },
{ "class", required_argument, 0, 'C' }, { "class", required_argument, 0, 'C' },
{ "script", required_argument, 0, 'S' }, { "script", required_argument, 0, 'S' },
{ "file", required_argument, 0, 'F' }, { "file", required_argument, 0, 'F' },
{ "monitor", required_argument, 0, 'M'},
{ 0, 0, 0, 0 } { 0, 0, 0, 0 }
}; };
int optch = 0, cmdx = 0; int optch = 0, cmdx = 0;
const char *errmsg;
/* Now to pass some optionarinos */ /* Now to pass some optionarinos */
while ((optch = getopt_long(argc, argv, stropts, lopts, &cmdx)) != EOF) { while ((optch = getopt_long(argc, argv, stropts, lopts, &cmdx)) != EOF) {
switch (optch) { switch (optch) {
case 0: case 0:
break; break;
case 'h': case 'h':
showUsage(); showUsage();
break; break;
case 'v': case 'v':
showVersion(); showVersion();
break; break;
case 'b': case 'b':
opt.border = 1; opt.border = 1;
break; break;
case 'd': case 'd':
opt.delay = nonNegativeNumber(optionsParseRequiredNumber(optarg)); opt.delay = optionsParseNum(optarg, 0, INT_MAX, &errmsg);
if (errmsg) {
errx(EXIT_FAILURE, "option --delay: '%s' is %s", optarg,
errmsg);
}
break; break;
case 'e': case 'e':
opt.exec = strdup(optarg); opt.exec = estrdup(optarg);
break; break;
case 'm': case 'm':
opt.multidisp = 1; opt.multidisp = 1;
break; break;
case 'q': case 'q':
opt.quality = optionsParseRequiredNumber(optarg); opt.quality = optionsParseNum(optarg, 1, 100, &errmsg);
if (errmsg) {
errx(EXIT_FAILURE, "option --quality: '%s' is %s", optarg,
errmsg);
}
break; break;
case 's': case 's':
optionsParseSelection(optarg); optionsParseSelection(optarg);
break; break;
case 'u': case 'u':
opt.focused = 1; opt.focused = 1;
break; break;
case 'c': case 'c':
opt.countdown = 1; opt.countdown = 1;
break; break;
skipping to change at line 435 skipping to change at line 479
optionsParseLine(optarg); optionsParseLine(optarg);
break; break;
case 'k': case 'k':
opt.stack = 1; opt.stack = 1;
optionsParseStack(optarg); optionsParseStack(optarg);
break; break;
case 'C': case 'C':
optionsParseWindowClassName(optarg); optionsParseWindowClassName(optarg);
break; break;
case 'S': case 'S':
opt.script = strdup(optarg); opt.script = estrdup(optarg);
break; break;
case 'F': case 'F':
optionsParseFileName(optarg); optionsParseFileName(optarg);
break; break;
case 'M':
opt.monitor = optionsParseNum(optarg, 0, INT_MAX, &errmsg);
if (errmsg) {
errx(EXIT_FAILURE, "option --monitor: '%s' is %s", optarg,
errmsg);
}
break;
case '?': case '?':
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
default: default:
break; break;
} }
} }
/* Now the leftovers, which must be files */ /* Now the leftovers, which must be files */
while (optind < argc) { while (optind < argc) {
/* If recursive is NOT set, but the only argument is a directory /* If recursive is NOT set, but the only argument is a directory
name, we grab all the files in there, but not subdirs */ name, we grab all the files in there, but not subdirs */
if (!opt.outputFile) { if (!opt.outputFile) {
optionsParseFileName(argv[optind++]); optionsParseFileName(argv[optind++]);
bool const redirectChar = ( opt.outputFile[0] == '-' const bool redirectChar = ( opt.outputFile[0] == '-'
&& opt.outputFile[1] == '\0'); && opt.outputFile[1] == '\0');
if (redirectChar) { if (redirectChar) {
free(opt.outputFile); free(opt.outputFile);
opt.outputFile = getPathOfStdout(); opt.outputFile = getPathOfStdout();
opt.overwrite = 1; opt.overwrite = 1;
opt.thumb = 0; opt.thumbWorP = 0;
} }
} else } else
warnx("unrecognised option %s", argv[optind++]); warnx("unrecognised option %s", argv[optind++]);
} }
/* So that we can safely be called again */ /* So that we can safely be called again */
optind = 1; optind = 1;
} }
char* optionsNameThumbnail(const char* name) static void showUsage(void)
{ {
const char* const thumbSuffix = "-thumb"; fputs(/* Check that everything lines up after any changes. */
"usage: " PACKAGE " [-bcfhimopuvz] [-a X,Y,W,H] [-C NAME] [-D DISPLAY]\
n"
" [-d SEC] [-e CMD] [-F FILE] [-k OPT] [-l STYLE] [-M NUM]\
n"
" [-n OPTS] [-q NUM] [-S CMD] [-s OPTS] [-t NUM | GEOM] [FI
LE]\n",
stdout);
exit(0);
}
static void showVersion(void)
{
printf(PACKAGE " version " VERSION "\n");
exit(0);
}
char *optionsNameThumbnail(const char *name)
{
const char *const thumbSuffix = "-thumb";
const size_t thumbSuffixLength = 7; const size_t thumbSuffixLength = 7;
const size_t newNameLength = strlen(name) + thumbSuffixLength; const size_t newNameLength = strlen(name) + thumbSuffixLength;
char* newName = calloc(1, newNameLength); char *newName = calloc(1, newNameLength);
if (!newName) if (!newName)
err(EXIT_FAILURE, "Unable to allocate thumbnail"); err(EXIT_FAILURE, "Unable to allocate thumbnail");
const char* const extension = strrchr(name, '.'); const char *const extension = strrchr(name, '.');
if (extension) { if (extension) {
/* We add one so length includes '\0'*/ /* We add one so length includes '\0'*/
const ptrdiff_t nameLength = (extension - name) + 1; const ptrdiff_t nameLength = (extension - name) + 1;
strlcpy(newName, name, nameLength); strlcpy(newName, name, nameLength);
strlcat(newName, thumbSuffix, newNameLength); strlcat(newName, thumbSuffix, newNameLength);
strlcat(newName, extension, newNameLength); strlcat(newName, extension, newNameLength);
} else } else
snprintf(newName, newNameLength, "%s%s", name, thumbSuffix); snprintf(newName, newNameLength, "%s%s", name, thumbSuffix);
return newName; return newName;
} }
void optionsParseAutoselect(char* optarg) void optionsParseAutoselect(char *optarg)
{ {
char* token; char *token;
const char tokenDelimiter[2] = ","; int *dimensions[] = {&opt.autoselectX, &opt.autoselectY, &opt.autoselectW,
int dimensions[4]; &opt.autoselectH, NULL /* Sentinel. */};
int i = 0; int i = 0;
int min;
const char *errmsg;
if (strchr(optarg, ',')) { /* geometry dimensions must be in format x,y,w,h /* Geometry dimensions must be in format x,y,w,h */
*/ token = strtok(optarg, ",");
dimensions[i++] = optionsParseRequiredNumber(strtok(optarg, tokenDelimit for (; token != NULL; token = strtok(NULL, ",")) {
er)); if (dimensions[i] == NULL)
while ((token = strtok(NULL, tokenDelimiter))) errx(EXIT_FAILURE, "option --autoselect: too many dimensions");
dimensions[i++] = optionsParseRequiredNumber(token);
opt.autoselect = 1; min = i >= 2; /* X,Y offsets may be 0. Width and height may not. */
opt.autoselectX = dimensions[0]; *dimensions[i] = optionsParseNum(token, min, INT_MAX, &errmsg);
opt.autoselectY = dimensions[1]; if (errmsg) {
opt.autoselectW = dimensions[2]; errx(EXIT_FAILURE, "option --autoselect: '%s' is %s", token,
opt.autoselectH = dimensions[3]; errmsg);
}
i++;
if (i != 4) opt.autoselect = 1;
errx(EXIT_FAILURE, "option 'autoselect' require 4 arguments"); }
} else if (i < 4)
errx(EXIT_FAILURE, "invalid format for option -- 'autoselect'"); errx(EXIT_FAILURE, "option --autoselect: too few dimensions");
} }
void optionsParseDisplay(char* optarg) void optionsParseDisplay(char *optarg)
{ {
opt.display = strndup(optarg, MAX_DISPLAY_NAME); opt.display = strndup(optarg, MAX_DISPLAY_NAME);
if (!opt.display) if (!opt.display)
err(EXIT_FAILURE, "Unable to allocate display"); err(EXIT_FAILURE, "Unable to allocate display");
} }
void optionsParseThumbnail(char* optarg) static void optionsParseThumbnail(char *optarg)
{ {
char* token; char *height;
const char *errmsg;
if (strchr(optarg, 'x')) { /* We want to specify the geometry */ if ((height = strchr(optarg, 'x')) != NULL) { /* optarg is a resolution. */
token = strtok(optarg, "x"); /* optarg holds the width, height holds the height. */
opt.thumbWidth = optionsParseRequiredNumber(token); *height++ = '\0';
token = strtok(NULL, "x");
if (token) { opt.thumbWorP = optionsParseNum(optarg, 1, INT_MAX, &errmsg);
opt.thumbWidth = optionsParseRequiredNumber(optarg); if (errmsg) {
opt.thumbHeight = optionsParseRequiredNumber(token); errx(EXIT_FAILURE, "option --thumb: resolution width '%s' is %s",
optarg, errmsg);
if (opt.thumbWidth < 0) }
opt.thumbWidth = 1;
if (opt.thumbHeight < 0) opt.thumbH = optionsParseNum(height, 1, INT_MAX, &errmsg);
opt.thumbHeight = 1; if (errmsg) {
errx(EXIT_FAILURE, "option --thumb: resolution height '%s' is %s",
if (!opt.thumbWidth && !opt.thumbHeight) height, errmsg);
opt.thumb = 0; }
else } else { /* optarg is a percentage. */
opt.thumb = 1; opt.thumbWorP = optionsParseNum(optarg, 1, INT_MAX, &errmsg);
if (errmsg) {
errx(EXIT_FAILURE, "option --thumb: percentage '%s' is %s", optarg,
errmsg);
} }
} else {
opt.thumb = optionsParseRequiredNumber(optarg);
if (opt.thumb < 1)
opt.thumb = 1;
else if (opt.thumb > 100)
opt.thumb = 100;
} }
} }
void optionsParseFileName(const char* optarg) void optionsParseFileName(const char *optarg)
{ {
checkMaxOutputFileName(optarg); checkMaxOutputFileName(optarg);
opt.outputFile = strdup(optarg); opt.outputFile = estrdup(optarg);
} }
void optionsParseNote(char* optarg) void optionsParseNote(char *optarg)
{ {
opt.note = strdup(optarg); if (opt.note)
free(opt.note);
opt.note = estrdup(optarg);
if (!opt.note) if (!opt.note)
return; return;
if (opt.note[0] == '\0') if (opt.note[0] == '\0')
errx(EXIT_FAILURE, "Required arguments for --note."); errx(EXIT_FAILURE, "Required arguments for --note.");
scrotNoteNew(opt.note); scrotNoteNew(opt.note);
} }
/* /*
Return: Return:
0 : It does not match 0 : It does not match
1 : If it matches 1 : If it matches
*/ */
int optionsCompareWindowClassName(const char* targetClassName) int optionsCompareWindowClassName(const char *targetClassName)
{ {
assert(targetClassName != NULL); assert(targetClassName != NULL);
assert(opt.windowClassName != NULL); assert(opt.windowClassName != NULL);
return !!(!strncmp(targetClassName, opt.windowClassName, MAX_LEN_WINDOW_CLAS S_NAME - 1)); return !!(!strncmp(targetClassName, opt.windowClassName, MAX_LEN_WINDOW_CLAS S_NAME - 1));
} }
void showVersion(void)
{
printf(SCROT_PACKAGE " version " SCROT_VERSION "\n");
exit(0);
}
void showUsage(void)
{
fputs(/* Check that everything lines up after any changes. */
"usage: " SCROT_PACKAGE " [-bcfhikmopsuvz] [-a X,Y,W,H] [-C NAME] [-D D
ISPLAY]"
"\n"
" [-F FILE] [-d SEC] [-e CMD] [-l STYLE] [-n OPTS] [-q NUM]
[-S CMD] \n"
" [-t NUM | GEOM] [FILE]\n",
stdout);
exit(0);
}
 End of changes. 61 change blocks. 
133 lines changed or deleted 208 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)