"Fossies" - the Fresh Open Source Software Archive  

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

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

options.c  (scrot-1.6.tar.bz2):options.c  (scrot-1.7.tar.bz2)
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 <daltomi@disroot.org> Copyright 2019-2021 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 IFo Hancroft <contact@ifohancroft.com>
Copyright 2021 Peter Wu <peterwu@hotmail.com>
Copyright 2021 Wilson Smith <01wsmith+gh@gmail.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 38 skipping to change at line 42
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 "scrot.h"
#include "options.h" #include "options.h"
#include "scrot.h"
#include <assert.h> #include <assert.h>
#define MAX_LEN_WINDOW_CLASS_NAME 80 #define STR_LEN_MAX_FILENAME(msg, fileName) do { \
if (strlen((fileName)) > MAX_FILENAME) { \
errx(EXIT_FAILURE, #msg " filename too long, must be " \
"less than %d characters", MAX_FILENAME); \
} \
} while(0)
#define checkMaxOutputFileName(fileName) \
STR_LEN_MAX_FILENAME(output, (fileName))
#define checkMaxInputFileName(fileName) \
STR_LEN_MAX_FILENAME(input, (fileName))
enum {
MAX_LEN_WINDOW_CLASS_NAME = 80, //characters
MAX_FILENAME = 256, // characters
MAX_DISPLAY_NAME = 256, // characters
};
ScrotOptions opt = {
.quality = 75,
.lineStyle = LineSolid,
.lineWidth = 1,
.lineOpacity = SELECTION_OPACITY_DEFAULT,
.lineMode = LINE_MODE_S_CLASSIC,
.stackDirection = HORIZONTAL,
};
int optionsParseRequiredNumber(char const* str)
{
assert(NULL != str); // fix yout caller function,
// the user does not impose this behavior
char* end = NULL;
long ret = 0L;
errno = 0;
ret = strtol(str, &end, 10);
if (errno)
goto range_error;
if (str == end)
errx(EXIT_FAILURE, "the option is not a number: %s", end);
if (ret > INT_MAX || ret < INT_MIN) {
errno = ERANGE;
goto range_error;
}
static void scrot_parse_option_array(int argc, char **argv); return ret;
scrotoptions opt;
void range_error:
init_parse_options(int argc, char **argv) err(EXIT_FAILURE, "error strtol");
}
static int nonNegativeNumber(int number)
{ {
/* Set default options */ return (number < 0) ? 0 : number;
memset(&opt, 0, sizeof(scrotoptions)); }
opt.quality = 75; int optionsParseRequireRange(int n, int lo, int hi)
opt.overwrite = 0; {
opt.line_style = LineSolid; return (n < lo ? lo : n > hi ? hi : n);
opt.line_width = 1; }
opt.line_opacity = 100;
opt.line_mode = LINE_MODE_CLASSIC; bool optionsParseIsString(char const* const str)
{
return (str && (str[0] != '\0'));
}
static void optionsParseStack(char const* optarg)
{
// the suboption it's optional
if (!optarg) {
opt.stackDirection = HORIZONTAL;
return;
}
char const* value = strchr(optarg, '=');
/* Parse the cmdline args */ if (value)
scrot_parse_option_array(argc, argv); ++value;
else
value = optarg;
if (*value == 'v')
opt.stackDirection = VERTICAL;
else if (*value == 'h')
opt.stackDirection = HORIZONTAL;
else {
errx(EXIT_FAILURE, "option --stack: Unknown value for suboption '%s'",
value);
}
} }
int static void optionsParseSelection(char const* optarg)
options_parse_required_number(char *str)
{ {
char *end = NULL; // the suboption it's optional
int ret = 0; if (!optarg) {
errno = 0; opt.selection.mode = SELECTION_MODE_CAPTURE;
return;
}
if (str != NULL) { char const* value = strchr(optarg, '=');
ret = strtol(str, &end, 10);
}
if (str == end) { if (value)
fprintf(stderr, "the option is not a number: %s\n", end); ++value;
exit(EXIT_FAILURE); else
} value = optarg;
if (!strncmp(value, SELECTION_MODE_S_CAPTURE, SELECTION_MODE_L_CAPTURE)) {
opt.selection.mode = SELECTION_MODE_CAPTURE;
return; /* it has no parameter */
}
else if (!strncmp(value, SELECTION_MODE_S_HIDE, SELECTION_MODE_L_HIDE)) {
opt.selection.mode = SELECTION_MODE_HIDE;
value += SELECTION_MODE_L_HIDE;
}
else if (!strncmp(value, SELECTION_MODE_S_HOLE, SELECTION_MODE_L_HOLE)) {
opt.selection.mode = SELECTION_MODE_HOLE;
}
else if (!strncmp(value, SELECTION_MODE_S_BLUR, SELECTION_MODE_L_BLUR)) {
opt.selection.mode = SELECTION_MODE_BLUR;
opt.selection.paramNum = SELECTION_MODE_BLUR_DEFAULT;
value += SELECTION_MODE_L_BLUR;
}
else {
errx(EXIT_FAILURE, "option --select: Unknown value for suboption '%s'",
value);
}
if (errno) { if (opt.selection.mode & SELECTION_MODE_NOT_NEED_PARAM)
perror("strtol"); return;
exit(EXIT_FAILURE);
}
return ret; if (*value != SELECTION_MODE_SEPARATOR)
} return;
static void if (*(++value) == '\0')
options_parse_line(char *optarg) errx(EXIT_FAILURE, "option --select: Invalid parameter.");
{
enum {STYLE = 0, WIDTH, COLOR, OPACITY, MODE};
char *const token[] = { if (opt.selection.mode == SELECTION_MODE_BLUR) {
[STYLE] = "style", int const num = nonNegativeNumber(optionsParseRequiredNumber(value));
[WIDTH] = "width",
[COLOR] = "color",
[OPACITY] = "opacity",
[MODE] = "mode",
NULL
};
char *subopts = optarg; opt.selection.paramNum = optionsParseRequireRange(num,
char *value = NULL; SELECTION_MODE_BLUR_MIN, SELECTION_MODE_BLUR_MAX);
while (*subopts != '\0') { } else { // SELECTION_MODE_HIDE
switch(getsubopt(&subopts, token, &value)) {
case STYLE: checkMaxInputFileName(value);
opt.selection.paramStr = strdup(value);
}
}
if (value == NULL || *value == '\0') { static void optionsParseLine(char* optarg)
fprintf(stderr, "Missing value for " {
"suboption '%s'\n", token[STYLE]); enum {
exit(EXIT_FAILURE); Style = 0,
Width,
Color,
Opacity,
Mode
};
char* const token[] = {
[Style] = "style",
[Width] = "width",
[Color] = "color",
[Opacity] = "opacity",
[Mode] = "mode",
NULL
};
char* subopts = optarg;
char* value = NULL;
while (*subopts != '\0') {
switch (getsubopt(&subopts, token, &value)) {
case Style:
if (!optionsParseIsString(value)) {
errx(EXIT_FAILURE, "Missing value for suboption '%s'",
token[Style]);
} }
if (!strncmp(value, "dash", 4)) if (!strncmp(value, "dash", 4))
opt.line_style = LineOnOffDash; opt.lineStyle = LineOnOffDash;
else if (!strncmp(value, "solid", 5)) else if (!strncmp(value, "solid", 5))
opt.line_style = LineSolid; opt.lineStyle = LineSolid;
else { else {
fprintf(stderr, "Unknown value for " errx(EXIT_FAILURE, "Unknown value for suboption '%s': %s",
"suboption '%s': %s\n", token[STYLE], value); token[Style], value);
exit(EXIT_FAILURE);
} }
break; break;
case Width:
case WIDTH: if (!optionsParseIsString(value)) {
errx(EXIT_FAILURE, "Missing value for suboption '%s'",
if (value == NULL) { token[Width]);
fprintf(stderr, "Missing value for "
"suboption '%s'\n", token[WIDTH]);
exit(EXIT_FAILURE);
} }
opt.line_width = options_parse_required_number(value); opt.lineWidth = optionsParseRequiredNumber(value);
if (opt.line_width <= 0 || opt.line_width > 8){ if (opt.lineWidth <= 0 || opt.lineWidth > 8) {
fprintf(stderr, "Value of the range (1..8) for " errx(EXIT_FAILURE, "Value of the range (1..8) for "
"suboption '%s': %d\n", token[WIDTH], opt.line_width); "suboption '%s': %d", token[Width], opt.lineWidth);
exit(EXIT_FAILURE);
} }
break; break;
case Color:
case COLOR: if (!optionsParseIsString(value)) {
errx(EXIT_FAILURE, "Missing value for suboption '%s'",
if (value == NULL || *value == '\0') { token[Color]);
fprintf(stderr, "Missing value for "
"suboption '%s'\n", token[COLOR]);
exit(EXIT_FAILURE);
} }
opt.line_color = strdup(value); opt.lineColor = strdup(value);
break; break;
case Mode:
case MODE: if (!optionsParseIsString(value)) {
errx(EXIT_FAILURE, "Missing value for suboption '%s'",
if (value == NULL || *value == '\0') { token[Mode]);
fprintf(stderr, "Missing value for "
"suboption '%s'\n", token[MODE]);
exit(EXIT_FAILURE);
} }
bool isValidMode = (bool)(0 == strncmp(value, LINE_MODE_CLASSIC, LIN E_MODE_CLASSIC_LEN) ); bool isValidMode = !strncmp(value, LINE_MODE_S_CLASSIC, LINE_MODE_L_ CLASSIC);
isValidMode = isValidMode || (bool)(0 == strncmp(value, LINE_MODE_ED GE, LINE_MODE_EDGE_LEN)); isValidMode = isValidMode || !strncmp(value, LINE_MODE_S_EDGE, LINE_ MODE_L_EDGE);
if(isValidMode == false) { if (!isValidMode) {
fprintf(stderr, "Unknown value for " errx(EXIT_FAILURE, "Unknown value for suboption '%s': %s",
"suboption '%s': %s\n", token[MODE], value); token[Mode], value);
exit(EXIT_FAILURE);
} }
opt.line_mode = strdup(value); opt.lineMode = strdup(value);
break;
case Opacity:
if (!optionsParseIsString(value)) {
errx(EXIT_FAILURE, "Missing value for suboption '%s'",
token[Opacity]);
}
opt.lineOpacity = optionsParseRequiredNumber(value);
break;
default:
errx(EXIT_FAILURE, "No match found for token: '%s'", value);
break; break;
}
} /* while */
}
case OPACITY: static void optionsParseWindowClassName(const char* windowClassName)
{
assert(windowClassName != NULL);
if (value == NULL) { if (windowClassName[0] != '\0')
fprintf(stderr, "Missing value for " opt.windowClassName = strndup(windowClassName, MAX_LEN_WINDOW_CLASS_NAME
"suboption '%s'\n", token[OPACITY]); );
exit(EXIT_FAILURE); }
}
opt.line_opacity = options_parse_required_number(value); static bool accessFileOk(const char* const pathName)
{
errno = 0;
return (0 == access(pathName, W_OK));
}
if (opt.line_opacity < 10 || opt.line_opacity > 100){ static char* getPathOfStdout(void)
fprintf(stderr, "Value of the range (10..100) for " {
"suboption '%s': %d\n", token[OPACITY], opt.line_opacity); char path[16] = {"/dev/stdout"};
exit(EXIT_FAILURE); size_t const len = sizeof(path);
}
break; if (!accessFileOk(path)) {
default: snprintf(path, len, "/dev/fd/%d", STDOUT_FILENO);
fprintf(stderr, "No match found for token: '%s'\n", value);
exit(EXIT_FAILURE);
break;
}
} /* while */ if (!accessFileOk(path)) {
}
static void options_parse_window_class_name(const char* window_class_name) snprintf(path, len, "/proc/self/fd/%d", STDOUT_FILENO);
{
assert(window_class_name != NULL);
if (window_class_name[0] != '\0' && if (!accessFileOk(path)) {
strlen(window_class_name) < MAX_LEN_WINDOW_CLASS_NAME) // We quit because imlib2 will fail later anyway.
{ err(EXIT_FAILURE, "access to stdout failed");
opt.window_class_name = strdup(window_class_name); }
}
} }
return strndup(path, len);
} }
static void void optionsParse(int argc, char** argv)
scrot_parse_option_array(int argc, char **argv) {
{ static char stropts[] = "a:ofipbcd:e:hmq:s::t:uvzn:l:D:k::C:S:F:";
static char stropts[] = "a:ofpbcd:e:hmq:st:uv+:zn:l:D:kC:S:";
static struct option lopts[] = {
static struct option lopts[] = { /* actions */
/* actions */ { "help", no_argument, 0, 'h' },
{"help", 0, 0, 'h'}, /* okay */ { "version", no_argument, 0, 'v' },
{"version", 0, 0, 'v'}, /* okay */ { "count", no_argument, 0, 'c' },
{"count", 0, 0, 'c'}, { "focused", no_argument, 0, 'u' },
{"select", 0, 0, 's'}, { "focussed", no_argument, 0, 'u' }, /* macquarie dictionary has both sp
{"focused", 0, 0, 'u'}, ellings */
{"focussed", 0, 0, 'u'}, /* macquarie dictionary has both spellings */ { "border", no_argument, 0, 'b' },
{"border", 0, 0, 'b'}, { "multidisp", no_argument, 0, 'm' },
{"multidisp", 0, 0, 'm'}, { "silent", no_argument, 0, 'z' },
{"silent", 0, 0, 'z'}, { "pointer", no_argument, 0, 'p' },
{"pointer", 0, 0, 'p'}, { "ignorekeyboard", no_argument, 0, 'i' },
{"freeze", 0, 0, 'f'}, { "freeze", no_argument, 0, 'f' },
{"overwrite", 0, 0, 'o'}, { "overwrite", no_argument, 0, 'o' },
{"stack", 0, 0,'k'}, /* toggles */
/* toggles */ { "stack", optional_argument, 0, 'k' },
{"thumb", 1, 0, 't'}, { "select", optional_argument, 0, 's' },
{"delay", 1, 0, 'd'}, { "thumb", required_argument, 0, 't' },
{"quality", 1, 0, 'q'}, { "delay", required_argument, 0, 'd' },
{"exec", 1, 0, 'e'}, { "quality", required_argument, 0, 'q' },
{"debug-level", 1, 0, '+'}, { "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' },
{0, 0, 0, 0} { "file", required_argument, 0, 'F' },
}; { 0, 0, 0, 0 }
int optch = 0, cmdx = 0; };
int optch = 0, cmdx = 0;
/* Now to pass some optionarinos */
while ((optch = getopt_long(argc, argv, stropts, lopts, &cmdx)) != /* Now to pass some optionarinos */
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':
show_usage(); showUsage();
break; break;
case 'v': case 'v':
show_version(); showVersion();
break; break;
case 'b': case 'b':
opt.border = 1; opt.border = 1;
break; break;
case 'd': case 'd':
opt.delay = options_parse_required_number(optarg); opt.delay = nonNegativeNumber(optionsParseRequiredNumber(optarg));
break; break;
case 'e': case 'e':
opt.exec = strdup(optarg); opt.exec = strdup(optarg);
break; break;
case 'm': case 'm':
opt.multidisp = 1; opt.multidisp = 1;
break; break;
case 'q': case 'q':
opt.quality = options_parse_required_number(optarg); opt.quality = optionsParseRequiredNumber(optarg);
break; break;
case 's': case 's':
opt.select = 1; optionsParseSelection(optarg);
break; break;
case 'u': case 'u':
opt.focused = 1; opt.focused = 1;
break; break;
case '+':
opt.debug_level = options_parse_required_number(optarg);
break;
case 'c': case 'c':
opt.countdown = 1; opt.countdown = 1;
break; break;
case 't': case 't':
options_parse_thumbnail(optarg); optionsParseThumbnail(optarg);
break; break;
case 'z': case 'z':
opt.silent = 1; opt.silent = 1;
break; break;
case 'p': case 'p':
opt.pointer = 1; opt.pointer = 1;
break; break;
case 'i':
opt.ignoreKeyboard = 1;
break;
case 'f': case 'f':
opt.freeze = 1; opt.freeze = 1;
break; break;
case 'o': case 'o':
opt.overwrite = 1; opt.overwrite = 1;
break; break;
case 'a': case 'a':
options_parse_autoselect(optarg); optionsParseAutoselect(optarg);
break; break;
case 'D': case 'D':
options_parse_display(optarg); optionsParseDisplay(optarg);
break; break;
case 'n': case 'n':
options_parse_note(optarg); optionsParseNote(optarg);
break; break;
case 'l': case 'l':
options_parse_line(optarg); optionsParseLine(optarg);
break; break;
case 'k': case 'k':
opt.stack = 1; opt.stack = 1;
break; optionsParseStack(optarg);
break;
case 'C': case 'C':
options_parse_window_class_name(optarg); optionsParseWindowClassName(optarg);
break; break;
case 'S': case 'S':
opt.script = strdup(optarg); opt.script = strdup(optarg);
break; break;
case 'F':
optionsParseFileName(optarg);
break;
case '?': case '?':
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
default: default:
break; break;
} }
} }
/* Now the leftovers, which must be files */
while (optind < argc)
{
/* If recursive is NOT set, but the only argument is a directory
name, we grab all the files in there, but not subdirs */
if (!opt.output_file)
{
opt.output_file = argv[optind++];
if ( strlen(opt.output_file) > 256 ) { /* Now the leftovers, which must be files */
printf("output filename too long.\n"); while (optind < argc) {
exit(EXIT_FAILURE); /* If recursive is NOT set, but the only argument is a directory
} name, we grab all the files in there, but not subdirs */
if (!opt.outputFile) {
optionsParseFileName(argv[optind++]);
bool const redirectChar = ( opt.outputFile[0] == '-'
&& opt.outputFile[1] == '\0');
if (redirectChar) {
free(opt.outputFile);
opt.outputFile = getPathOfStdout();
opt.overwrite = 1;
opt.thumb = 0;
}
} else
warnx("unrecognised option %s", argv[optind++]);
}
/* So that we can safely be called again */
optind = 1;
}
char* optionsNameThumbnail(const char* name)
{
const char* const thumbSuffix = "-thumb";
const size_t thumbSuffixLength = 7;
const size_t newNameLength = strlen(name) + thumbSuffixLength;
char* newName = calloc(1, newNameLength);
if (!newName)
err(EXIT_FAILURE, "Unable to allocate thumbnail");
const char* const extension = strrchr(name, '.');
if (extension) {
/* We add one so length includes '\0'*/
const ptrdiff_t nameLength = (extension - name) + 1;
strlcpy(newName, name, nameLength);
strlcat(newName, thumbSuffix, newNameLength);
strlcat(newName, extension, newNameLength);
} else
snprintf(newName, newNameLength, "%s%s", name, thumbSuffix);
return newName;
}
void optionsParseAutoselect(char* optarg)
{
char* token;
const char tokenDelimiter[2] = ",";
int dimensions[4];
int i = 0;
if (strchr(optarg, ',')) { /* geometry dimensions must be in format x,y,w,h
*/
dimensions[i++] = optionsParseRequiredNumber(strtok(optarg, tokenDelimit
er));
while ((token = strtok(NULL, tokenDelimiter)))
dimensions[i++] = optionsParseRequiredNumber(token);
opt.autoselect = 1;
opt.autoselectX = dimensions[0];
opt.autoselectY = dimensions[1];
opt.autoselectW = dimensions[2];
opt.autoselectH = dimensions[3];
if (i != 4)
errx(EXIT_FAILURE, "option 'autoselect' require 4 arguments");
} else
errx(EXIT_FAILURE, "invalid format for option -- 'autoselect'");
}
void optionsParseDisplay(char* optarg)
{
opt.display = strndup(optarg, MAX_DISPLAY_NAME);
if (!opt.display)
err(EXIT_FAILURE, "Unable to allocate display");
}
void optionsParseThumbnail(char* optarg)
{
char* token;
if (strchr(optarg, 'x')) { /* We want to specify the geometry */
token = strtok(optarg, "x");
opt.thumbWidth = optionsParseRequiredNumber(token);
token = strtok(NULL, "x");
if (token) {
opt.thumbWidth = optionsParseRequiredNumber(optarg);
opt.thumbHeight = optionsParseRequiredNumber(token);
if (opt.thumbWidth < 0)
opt.thumbWidth = 1;
if (opt.thumbHeight < 0)
opt.thumbHeight = 1;
if (!opt.thumbWidth && !opt.thumbHeight)
opt.thumb = 0;
else
opt.thumb = 1;
}
} else {
opt.thumb = optionsParseRequiredNumber(optarg);
if (opt.thumb < 1)
opt.thumb = 1;
else if (opt.thumb > 100)
opt.thumb = 100;
}
}
if (opt.thumb) void optionsParseFileName(const char* optarg)
opt.thumb_file = name_thumbnail(opt.output_file); {
} checkMaxOutputFileName(optarg);
else opt.outputFile = strdup(optarg);
fprintf(stderr, "unrecognised option %s\n", argv[optind++]); }
}
void optionsParseNote(char* optarg)
/* So that we can safely be called again */ {
optind = 1; opt.note = strdup(optarg);
}
char *
name_thumbnail(char *name)
{
size_t length = 0;
char *new_title;
char *dot_pos;
size_t diff = 0;
length = strlen(name) + 7;
new_title = malloc(length);
if (! new_title) {
fprintf(stderr, "Unable to allocate thumbnail: %s", strerror(errno));
exit(EXIT_FAILURE);
}
dot_pos = strrchr(name, '.');
if (dot_pos)
{
diff = (dot_pos - name) / sizeof(char);
strncpy(new_title, name, diff);
strcat(new_title, "-thumb");
strcat(new_title, dot_pos);
}
else {
snprintf(new_title, length, "%s-thumb", name);
}
return new_title;
}
void
options_parse_autoselect(char *optarg)
{
char *tok;
const char tokdelim[2] = ",";
int dimensions[4];
int i=0;
if (strchr(optarg, ',')) /* geometry dimensions must be in format x,y,w,h *
/
{
dimensions[i++] = options_parse_required_number(strtok(optarg, tokdelim));
while ((tok = strtok(NULL, tokdelim)) )
dimensions[i++] = options_parse_required_number(tok);
opt.autoselect=1;
opt.autoselect_x=dimensions[0];
opt.autoselect_y=dimensions[1];
opt.autoselect_w=dimensions[2];
opt.autoselect_h=dimensions[3];
if (i != 4)
{
fprintf(stderr, "option 'autoselect' require 4 arguments\n");
exit(EXIT_FAILURE);
}
}
else {
fprintf(stderr, "invalid format for option -- 'autoselect'\n");
exit(EXIT_FAILURE);
}
}
void
options_parse_display(char *optarg)
{
#if SCROT_HAVE_STRNDUP
opt.display = strndup(optarg, 256);
#else
size_t length = 0;
char *new_display;
length = strlen(optarg) + 1;
if (length > 256) {
length = 256;
}
new_display = malloc(length);
if (! new_display) {
fprintf(stderr, "Unable to allocate display: %s", strerror(errno));
exit(EXIT_FAILURE);
}
strncpy(new_display, optarg, length);
opt.display=new_display;
#endif
}
void
options_parse_thumbnail(char *optarg)
{
char *tok;
if (strchr(optarg, 'x')) /* We want to specify the geometry */
{
tok = strtok(optarg, "x");
opt.thumb_width = options_parse_required_number(tok);
tok = strtok(NULL, "x");
if (tok)
{
opt.thumb_width = options_parse_required_number(optarg);
opt.thumb_height = options_parse_required_number(tok);
if (opt.thumb_width < 0)
opt.thumb_width = 1;
if (opt.thumb_height < 0)
opt.thumb_height = 1;
if (!opt.thumb_width && !opt.thumb_height)
opt.thumb = 0;
else
opt.thumb = 1;
}
}
else
{
opt.thumb = options_parse_required_number(optarg);
if (opt.thumb < 1)
opt.thumb = 1;
else if (opt.thumb > 100)
opt.thumb = 100;
}
}
void options_parse_note(char *optarg)
{
opt.note = strdup(optarg);
if (opt.note == NULL) return;
if (opt.note[0] == '\0') {
fprintf(stderr, "Required arguments for --note.");
exit(EXIT_FAILURE);
}
scrot_note_new(opt.note); if (!opt.note)
return;
if (opt.note[0] == '\0')
errx(EXIT_FAILURE, "Required arguments for --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 options_cmp_window_class_name(const char* target_class_name) int optionsCompareWindowClassName(const char* targetClassName)
{ {
assert(target_class_name != NULL); assert(targetClassName != NULL);
assert(opt.window_class_name != NULL); assert(opt.windowClassName != NULL);
return !!(!strncmp(target_class_name, opt.window_class_name, MAX_LEN_WINDOW_ return !!(!strncmp(targetClassName, opt.windowClassName, MAX_LEN_WINDOW_CLAS
CLASS_NAME - 1)); S_NAME - 1));
} }
void void showVersion(void)
show_version(void) {
{ printf(SCROT_PACKAGE " version " SCROT_VERSION "\n");
printf(SCROT_PACKAGE " version " SCROT_VERSION "\n"); exit(0);
exit(0); }
}
void showUsage(void)
void {
show_mini_usage(void) fputs(/* Check that everything lines up after any changes. */
{ "usage: " SCROT_PACKAGE " [-bcfhikmopsuvz] [-a X,Y,W,H] [-C NAME] [-D D
printf("Usage : " SCROT_PACKAGE " [OPTIONS]... FILE\nUse " SCROT_PACKAGE ISPLAY]"
" --help for detailed usage information\n"); "\n"
exit(0); " [-F FILE] [-d SEC] [-e CMD] [-l STYLE] [-n OPTS] [-q NUM]
} [-S CMD] \n"
" [-t NUM | GEOM] [FILE]\n",
void stdout);
show_usage(void) exit(0);
{
fprintf(stdout,
"Usage : " SCROT_PACKAGE " [OPTIONS]... [FILE]\n"
" Where FILE is the target file for the screenshot.\n"
" If FILE is not specified, a date-stamped file will be dropped in t
he\n"
" current directory.\n" " See man " SCROT_PACKAGE " for more detail
s\n"
" -h, --help display this help and exit\n"
" -v, --version output version information and exit\n"
" -D, --display Set DISPLAY target other than current\n"
" -a, --autoselect non-interactively choose a rectangle of
x,y,w,h\n"
" -b, --border When selecting a window, grab wm border
too\n"
" Use with --select to raise the focus of
the window.\n"
" -c, --count show a countdown before taking the shot\
n"
" -d, --delay NUM wait NUM seconds before taking a shot\n"
" -e, --exec APP run APP on the resulting screenshot\n"
" -q, --quality NUM Image quality (1-100) high value means\n
"
" high size, low compression. Default: 75.
\n"
" For lossless compression formats, like p
ng,\n"
" low quality means high compression.\n"
" -m, --multidisp For multiple heads, grab shot from each\
n"
" and join them together.\n"
" -s, --select interactively choose a window or rectang
le\n"
" with the mouse (use the arrow keys to re
size)\n"
" -u, --focused use the currently focused window\n"
" -t, --thumb NUM generate thumbnail too. NUM is the perce
ntage\n"
" of the original size for the thumbnail t
o be,\n"
" or the geometry in percent, e.g. 50x60 o
r 80x20.\n"
" -z, --silent Prevent beeping\n"
" -p, --pointer Capture the mouse pointer.\n"
" -f, --freeze Freeze the screen when the selection is
used: --select\n"
" -o, --overwrite By default " SCROT_PACKAGE " does not ov
erwrite the files, use this option to allow it.\n"
" -l, --line Indicates the style of the line when the
selection is used: --select\n"
" See SELECTION STYLE\n"
" -n, --note Draw a text note.\n"
" See NOTE FORMAT\n"
" -k, --stack Capture stack/overlapped windows and joi
n them together.\n"
" A running Composite Manager is needed.\n
"
" -C, --class NAME Window class name. Associative with opti
ons: -k\n"
" -S, --script CMD Imlib2 script commands\n"
"\n" " SPECIAL STRINGS\n"
" Both the --exec and filename parameters can take format specifiers
\n"
" that are expanded by " SCROT_PACKAGE " when encountered.\n"
" There are two types of format specifier. Characters preceded by a
'%%'\n"
" are interpreted by strftime(2). See man strftime for examples.\n"
" These options may be used to refer to the current date and time.\n
"
" The second kind are internal to " SCROT_PACKAGE
" and are prefixed by '$'\n"
" The following specifiers are recognised:\n"
" $a hostname\n"
" $f image path/filename (ignored when used in the f
ilename)\n"
" $m thumbnail path/filename\n"
" $n image name (ignored when used in the filename)\
n"
" $s image size (bytes) (ignored when used in the fi
lename)\n"
" $p image pixel size\n"
" $w image width\n"
" $h image height\n"
" $t image format (ignored when used in the filename
)\n"
" $$ prints a literal '$'\n"
" \\n prints a newline (ignored when used in the fil
ename)\n"
" Example:\n" " " SCROT_PACKAGE
" '%%Y-%%m-%%d_$wx$h_scrot.png' -e 'mv $f ~/images/shots/'\n"
" Creates a file called something like 2000-10-30_2560x1024_
scrot.png\n"
" and moves it to your images directory.\n" "\n"
"\n" " SELECTION STYLE\n"
" When using --select you can indicate the style of the line with --
line.\n"
" The following specifiers are recognised:\n"
" style=(solid,dash),width=(range 1 to 8),color=\"va
lue\",\n"
" opacity=(range 10 to 100),mode=(edge,classic)\n"
" The default style is:\n"
" mode=classic,style=solid,width=1,opacity=100\n"
" Mode 'edge' ignore : style, --freeze\n"
" Mode 'classic' ignore : opacity\n\n"
" The 'opacity' specifier is only effective if a Composite Manager i
s running.\n\n"
" For the color you can use a name or a hexadecimal value.\n"
" color=\"red\" or color=\"#ff0000\"\n"
" Example:\n" " " SCROT_PACKAGE
" --line style=dash,width=3,color=\"red\" --select\n\n"
"\n" " NOTE FORMAT\n"
" The following specifiers are recognised for the option --note\n"
" -f 'FontName/size'\n"
" -t 'text'\n"
" -x position (optional)\n"
" -y position (optional)\n"
" -c color(RGBA) (optional)\n"
" -a angle (optional)\n"
" Example:\n" " " SCROT_PACKAGE
" --note \"-f '/usr/share/fonts/TTF/DroidSans-Bold/40' -x 10 -y 20 -c
255,0,0,255 -t 'Hi'\"\n\n"
"This program is free software see the file COPYING for licensing inf
o.\n"
"Copyright Tom Gilbert 2000\n"
"Email bugs to <scrot_sucks@linuxbrit.co.uk>\n");
exit(0);
} }
 End of changes. 76 change blocks. 
527 lines changed or deleted 481 lines changed or added

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