"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "src/main.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.

main.c  (scrot-1.6.tar.bz2):main.c  (scrot-1.7.tar.bz2)
/* main.c /* main.c
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 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-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 blockparole Copyright 2020 blockparole
Copyright 2020 Cungsten Tarbide <ctarbide@tuta.io> Copyright 2020 Cungsten Tarbide <ctarbide@tuta.io>
Copyright 2020 Hinigatsu <hinigatsu@protonmail.com> Copyright 2020 Hinigatsu <hinigatsu@protonmail.com>
Copyright 2020 nothub Copyright 2020 nothub
Copyright 2020 Sean Brennan <zettix1@gmail.com> Copyright 2020 Sean Brennan <zettix1@gmail.com>
Copyright 2021 c0dev0id <sh+github@codevoid.de> Copyright 2021 c0dev0id <sh+github@codevoid.de>
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 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 42 skipping to change at line 44
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 "scrot.h"
#include "options.h"
#include "slist.h"
#include <assert.h> #include <assert.h>
/* atexit register func. */ /* atexit register func. */
static void uninit_x_and_imlib(void) static void uninitXAndImlib(void)
{ {
if (disp) { if (opt.note)
XCloseDisplay(disp); scrotNoteFree();
disp = NULL;
} if (disp) {
XCloseDisplay(disp);
disp = NULL;
}
} }
// It assumes that the local variable 'main.c:Imlib_Image image' is in context // It assumes that the local variable 'main.c:Imlib_Image image' is in context
static void apply_filter_if_required(void) static void applyFilterIfRequired(void)
{ {
if (opt.script != NULL) { if (opt.script)
imlib_apply_filter(opt.script); imlib_apply_filter(opt.script);
} }
}
int
main(int argc,
char **argv)
{
Imlib_Image image;
Imlib_Image thumbnail;
Imlib_Load_Error err;
char *filename_im = NULL, *filename_thumb = NULL;
char *have_extension = NULL;
time_t t;
struct tm *tm;
init_parse_options(argc, argv);
init_x_and_imlib(opt.display, 0);
atexit(uninit_x_and_imlib);
if (!opt.output_file) {
opt.output_file = strdup("%Y-%m-%d-%H%M%S_$wx$h_scrot.png");
opt.thumb_file = strdup("%Y-%m-%d-%H%M%S_$wx$h_scrot-thumb.png");
} else {
scrot_have_file_extension(opt.output_file, &have_extension);
}
if (opt.focused)
image = scrot_grab_focused();
else if (opt.select)
image = scrot_sel_and_grab_image();
else if (opt.autoselect)
image = scrot_grab_autoselect();
else
{
scrot_do_delay();
if (opt.multidisp) {
image = scrot_grab_shot_multi();
} else if (opt.stack) {
image = scrot_grab_stack_windows();
} else {
image = scrot_grab_shot();
}
}
if (opt.note != NULL) int main(int argc, char** argv)
scrot_note_draw(image); {
Imlib_Image image;
Imlib_Image thumbnail;
Imlib_Load_Error imErr;
char* filenameIM = NULL;
char* filenameThumb = NULL;
if (!image) { char* haveExtension = NULL;
fprintf(stderr, "no image grabbed: %s", strerror(errno));
exit(EXIT_FAILURE);
}
time(&t); /* Get the time directly after the screenshot */
tm = localtime(&t);
imlib_context_set_image(image);
imlib_image_attach_data_value("quality", NULL, opt.quality, NULL);
if (!have_extension) {
imlib_image_set_format("png");
}
filename_im = im_printf(opt.output_file, tm, NULL, NULL, image);
scrot_check_if_overwrite_file(&filename_im);
apply_filter_if_required();
imlib_save_image_with_error_return(filename_im, &err);
if (err) {
fprintf(stderr, "Saving to file %s failed: %s\n", filename_im, strerror(errn
o));
exit(EXIT_FAILURE);
}
if (opt.thumb)
{
int cwidth, cheight;
int twidth, theight;
cwidth = imlib_image_get_width();
cheight = imlib_image_get_height();
/* Geometry based thumb size */
if (opt.thumb_width || opt.thumb_height)
{
if (!opt.thumb_width)
{
twidth = cwidth * opt.thumb_height / cheight;
theight = opt.thumb_height;
}
else if (!opt.thumb_height)
{
twidth = opt.thumb_width;
theight = cheight * opt.thumb_width / cwidth;
}
else
{
twidth = opt.thumb_width;
theight = opt.thumb_height;
}
}
else
{
twidth = cwidth * opt.thumb / 100;
theight = cheight * opt.thumb / 100;
}
imlib_context_set_anti_alias(1); time_t t;
thumbnail = struct tm* tm;
imlib_create_cropped_scaled_image(0, 0, cwidth, cheight,
twidth, theight); optionsParse(argc, argv);
if (thumbnail == NULL) {
fprintf(stderr, "Unable to create scaled Image: %s\n", strerror(errno)); initXAndImlib(opt.display, 0);
exit(EXIT_FAILURE);
} atexit(uninitXAndImlib);
else
{ if (!opt.outputFile) {
if (opt.note != NULL) opt.outputFile = strdup("%Y-%m-%d-%H%M%S_$wx$h_scrot.png");
scrot_note_draw(image); opt.thumbFile = strdup("%Y-%m-%d-%H%M%S_$wx$h_scrot-thumb.png");
} else {
if (opt.thumb)
opt.thumbFile = optionsNameThumbnail(opt.outputFile);
scrotHaveFileExtension(opt.outputFile, &haveExtension);
}
if (opt.focused)
image = scrotGrabFocused();
else if (opt.selection.mode & SELECTION_MODE_ANY)
image = scrotSelectionSelectMode();
else if (opt.autoselect)
image = scrotGrabAutoselect();
else {
scrotDoDelay();
if (opt.multidisp)
image = scrotGrabShotMulti();
else if (opt.stack)
image = scrotGrabStackWindows();
else
image = scrotGrabShot();
}
if (!image)
err(EXIT_FAILURE, "no image grabbed");
if (opt.note)
scrotNoteDraw(image);
time(&t); /* Get the time directly after the screenshot */
tm = localtime(&t);
scrot_have_file_extension(opt.thumb_file, &have_extension); imlib_context_set_image(image);
imlib_image_attach_data_value("quality", NULL, opt.quality, NULL);
if (!have_extension) { if (!haveExtension)
imlib_context_set_image(thumbnail);
imlib_image_set_format("png"); imlib_image_set_format("png");
}
filename_thumb = im_printf(opt.thumb_file, tm, NULL, NULL, thumbnail); filenameIM = imPrintf(opt.outputFile, tm, NULL, NULL, image);
scrot_check_if_overwrite_file(&filename_thumb); scrotCheckIfOverwriteFile(&filenameIM);
apply_filter_if_required(); applyFilterIfRequired();
imlib_save_image_with_error_return(filenameIM, &imErr);
if (imErr)
err(EXIT_FAILURE, "Saving to file %s failed", filenameIM);
if (opt.thumb) {
int cwidth, cheight;
int twidth, theight;
cwidth = imlib_image_get_width();
cheight = imlib_image_get_height();
/* Geometry based thumb size */
if (opt.thumbWidth || opt.thumbHeight) {
if (!opt.thumbWidth) {
twidth = cwidth * opt.thumbHeight / cheight;
theight = opt.thumbHeight;
} else if (!opt.thumbHeight) {
twidth = opt.thumbWidth;
theight = cheight * opt.thumbWidth / cwidth;
} else {
twidth = opt.thumbWidth;
theight = opt.thumbHeight;
}
} else {
twidth = cwidth * opt.thumb / 100;
theight = cheight * opt.thumb / 100;
}
imlib_context_set_anti_alias(1);
thumbnail = imlib_create_cropped_scaled_image(0, 0, cwidth, cheight,
twidth, theight);
if (!thumbnail)
err(EXIT_FAILURE, "unable to create thumbnail");
else {
scrotHaveFileExtension(opt.thumbFile, &haveExtension);
imlib_context_set_image(thumbnail);
if (!haveExtension)
imlib_image_set_format("png");
filenameThumb = imPrintf(opt.thumbFile, tm, NULL, NULL, thumbnail);
scrotCheckIfOverwriteFile(&filenameThumb);
imlib_save_image_with_error_return(filenameThumb, &imErr);
imlib_free_image_and_decache();
if (imErr)
err(EXIT_FAILURE, "Saving thumbnail %s failed", filenameThumb);
}
}
if (opt.exec)
scrotExecApp(image, tm, filenameIM, filenameThumb);
imlib_context_set_image(image);
imlib_free_image_and_decache();
return 0;
}
imlib_save_image_with_error_return(filename_thumb, &err); void scrotDoDelay(void)
if (err) { {
fprintf(stderr, "Saving thumbnail %s failed: %s\n", filename_thumb, stre if (opt.delay) {
rror(errno)); if (opt.countdown) {
exit(EXIT_FAILURE); int i;
}
printf("Taking shot in %d.. ", opt.delay);
fflush(stdout);
sleep(1);
for (i = opt.delay - 1; i > 0; i--) {
printf("%d.. ", i);
fflush(stdout);
sleep(1);
}
printf("0.\n");
fflush(stdout);
} else
sleep(opt.delay);
} }
}
if (opt.exec)
scrot_exec_app(image, tm, filename_im, filename_thumb);
imlib_free_image_and_decache();
return 0;
}
void
scrot_do_delay(void)
{
if (opt.delay) {
if (opt.countdown) {
int i;
printf("Taking shot in %d.. ", opt.delay);
fflush(stdout);
sleep(1);
for (i = opt.delay - 1; i > 0; i--) {
printf("%d.. ", i);
fflush(stdout);
sleep(1);
}
printf("0.\n");
fflush(stdout);
} else
sleep(opt.delay);
}
} }
size_t scrot_have_file_extension(char const *filename, char **ext) size_t scrotHaveFileExtension(char const* filename, char** ext)
{ {
*ext = strrchr(filename, '.'); *ext = strrchr(filename, '.');
if (*ext) { if (*ext)
return strlen(*ext); return strlen(*ext);
}
return 0; return 0;
} }
void scrot_check_if_overwrite_file(char **filename) void scrotCheckIfOverwriteFile(char** filename)
{ {
char *curfile = *filename; if (opt.overwrite)
return;
if (opt.overwrite == 1) return; if (access(*filename, F_OK) == -1)
return;
if (access(curfile, F_OK) == -1) return; const size_t maxCounter = 999;
size_t counter = 0;
char* ext = NULL;
size_t extLength = 0;
const size_t slen = strlen(*filename);
size_t nalloc = slen + 4 + 1; // _000 + NUL byte
char fmt[5];
char* newName = NULL;
const size_t max_counter = 999; extLength = scrotHaveFileExtension(*filename, &ext);
size_t counter = 0;
char *ext = NULL;
size_t ext_len = 0;
const size_t slen = strlen(curfile);
size_t nalloc = slen + 4 + 1; // _000 + NUL byte
char fmt[5];
char *newname = NULL;
ext_len = scrot_have_file_extension(curfile, &ext); if (ext)
nalloc += extLength; // .ext
if (ext) newName = calloc(nalloc, sizeof(*newName));
nalloc += ext_len; // .ext memcpy(newName, *filename, slen);
newname = calloc(nalloc, sizeof(char)); do {
char* ptr = newName + slen;
if (ext) snprintf(fmt, sizeof(fmt), "_%03zu", counter++);
// exclude ext
memcpy(newname, curfile, slen - ext_len);
else
memcpy(newname, curfile, slen);
do { if(ext) {
snprintf(fmt, 5, "_%03zu", counter++); ptr -= extLength;
memcpy(ptr, fmt, sizeof(fmt));
memcpy(ptr + sizeof(fmt) - 1, ext, extLength);
} else
memcpy(ptr, fmt, sizeof(fmt));
} while ((counter < maxCounter) && !access(newName, F_OK));
if (!ext) { assert(newName[nalloc - 1] == '\0');
strncpy(newname + slen, fmt, 5);
} else {
strncpy((newname + slen) - ext_len, fmt, 5);
strncat(newname, ext, ext_len);
}
curfile = newname;
} while ((counter < max_counter) && (access(curfile, F_OK) == 0));
free(*filename); free(*filename);
*filename = newname; *filename = newName;
if (counter == max_counter) { if (counter == maxCounter) {
fprintf(stderr, "scrot can no longer generate new file names.\n" errx(EXIT_FAILURE, "scrot can no longer generate new file names.\n"
"The last attempt is %s\n", newname); "The last attempt is %s", newName);
free(newname); }
exit(EXIT_FAILURE);
}
} }
int scrot_match_window_class_name(Window target) int scrotMatchWindowClassName(Window target)
{ {
assert(disp != NULL); assert(disp != NULL);
const int NOT_MATCH = 0; const int NOT_MATCH = 0;
const int MATCH = 1; const int MATCH = 1;
/* By default all class names match since window_class_name by default is NU LL*/ /* By default all class names match since windowClassName by default is NULL */
int retval = MATCH; int retval = MATCH;
if (opt.window_class_name == NULL) { if (!opt.windowClassName)
return retval; return retval;
}
XClassHint classHint; XClassHint classHint;
retval = NOT_MATCH; // window_class_name != NULL, by default NOT_MATCH retval = NOT_MATCH; // windowClassName != NULL, by default NOT_MATCH
if (XGetClassHint(disp, target, &classHint) != BadWindow) { if (XGetClassHint(disp, target, &classHint) != BadWindow) {
retval = options_cmp_window_class_name(classHint.res_class); retval = optionsCompareWindowClassName(classHint.res_class);
XFree(classHint.res_name); XFree(classHint.res_name);
XFree(classHint.res_class); XFree(classHint.res_class);
} }
return retval; return retval;
} }
void void scrotGrabMousePointer(const Imlib_Image image,
scrot_grab_mouse_pointer(const Imlib_Image image, const int xOffset, const int yOffset)
const int ix_off, const int iy_off) {
{ XFixesCursorImage* xcim = XFixesGetCursorImage(disp);
XFixesCursorImage *xcim = XFixesGetCursorImage(disp);
if (!xcim) {
const unsigned short width = xcim->width; warnx("Failed to get mouse cursor image.");
const unsigned short height = xcim->height; return;
const int x = (xcim->x - xcim->xhot) - ix_off; }
const int y = (xcim->y - xcim->yhot) - iy_off;
DATA32 *pixels = NULL; const unsigned short width = xcim->width;
const unsigned short height = xcim->height;
const int x = (xcim->x - xcim->xhot) - xOffset;
const int y = (xcim->y - xcim->yhot) - yOffset;
DATA32* pixels = NULL;
#ifdef __i386__ #ifdef __i386__
pixels = (DATA32*)xcim->pixels; pixels = (DATA32*)xcim->pixels;
#else #else
DATA32 data[width * height * 4]; DATA32 data[width * height * 4];
unsigned int i; unsigned int i;
for (i = 0; i < (width * height); i++) for (i = 0; i < (width * height); i++)
((DATA32*)data)[i] = (DATA32)xcim->pixels[i]; data[i] = (DATA32)xcim->pixels[i];
pixels = data; pixels = data;
#endif #endif
Imlib_Image imcursor = imlib_create_image_using_data(width, height, pixels); Imlib_Image imcursor = imlib_create_image_using_data(width, height, pixels);
XFree(xcim); XFree(xcim);
if (!imcursor) { if (!imcursor)
fprintf(stderr, "scrot_grab_mouse_pointer: Failed create image using data.\ errx(EXIT_FAILURE, "scrotGrabMousePointer: Failed create image using dat
n"); a.");
exit(EXIT_FAILURE);
}
imlib_context_set_image(imcursor); imlib_context_set_image(imcursor);
imlib_image_set_has_alpha(1); imlib_image_set_has_alpha(1);
imlib_context_set_image(image); imlib_context_set_image(image);
imlib_blend_image_onto_image(imcursor, 0, 0, 0, width, height, x, y, width, he imlib_blend_image_onto_image(imcursor, 0, 0, 0, width, height, x, y, width,
ight); height);
imlib_context_set_image(imcursor); imlib_context_set_image(imcursor);
imlib_free_image(); imlib_free_image();
} }
Imlib_Image Imlib_Image scrotGrabShot(void)
scrot_grab_shot(void)
{ {
Imlib_Image im; Imlib_Image im;
if (! opt.silent) XBell(disp, 0); if (!opt.silent)
XBell(disp, 0);
im = im = imlib_create_image_from_drawable(0, 0, 0, scr->width,
imlib_create_image_from_drawable(0, 0, 0, scr->width, scr->height, 1);
scr->height, 1); if (opt.pointer)
if (opt.pointer == 1) scrotGrabMousePointer(im, 0, 0);
scrot_grab_mouse_pointer(im, 0, 0);
return im; return im;
} }
void void scrotExecApp(Imlib_Image image, struct tm* tm,
scrot_exec_app(Imlib_Image image, struct tm *tm, char* filenameIM, char* filenameThumb)
char *filename_im, char *filename_thumb)
{ {
char *execstr; char* execStr;
int ret; int ret;
execstr = im_printf(opt.exec, tm, filename_im, filename_thumb, image); execStr = imPrintf(opt.exec, tm, filenameIM, filenameThumb, image);
errno = 0; errno = 0;
ret = system(execstr); ret = system(execStr);
if (ret == -1) { if (ret == -1)
fprintf(stderr, "The child process could not be created: %s\n", strerror(err warn("The child process could not be created");
no)); else if (WEXITSTATUS(ret) == 127)
} else if (WEXITSTATUS(ret) == 127) { warnx("scrot could not execute the command: %s", execStr);
fprintf(stderr, "scrot could not execute the command: %s.\n", execstr);
}
exit(0); exit(0);
} }
Imlib_Image Imlib_Image scrotGrabFocused(void)
scrot_grab_focused(void)
{ {
Imlib_Image im = NULL; Imlib_Image im = NULL;
int rx = 0, ry = 0, rw = 0, rh = 0; int rx = 0, ry = 0, rw = 0, rh = 0;
Window target = None; Window target = None;
int ignored; int ignored;
scrot_do_delay(); scrotDoDelay();
XGetInputFocus(disp, &target, &ignored); XGetInputFocus(disp, &target, &ignored);
if (!scrot_get_geometry(target, &rx, &ry, &rw, &rh)) return NULL; if (!scrotGetGeometry(target, &rx, &ry, &rw, &rh))
scrot_nice_clip(&rx, &ry, &rw, &rh); return NULL;
im = imlib_create_image_from_drawable(0, rx, ry, rw, rh, 1); scrotNiceClip(&rx, &ry, &rw, &rh);
if (opt.pointer == 1) im = imlib_create_image_from_drawable(0, rx, ry, rw, rh, 1);
scrot_grab_mouse_pointer(im, rx, ry); if (opt.pointer)
return im; scrotGrabMousePointer(im, rx, ry);
return im;
} }
Imlib_Image Imlib_Image scrotGrabAutoselect(void)
scrot_sel_and_grab_image(void)
{ {
Imlib_Image im = NULL; Imlib_Image im = NULL;
static int xfd = 0; int rx = opt.autoselectX, ry = opt.autoselectY, rw = opt.autoselectW, rh = o
static int fdsize = 0; pt.autoselectH;
XEvent ev;
fd_set fdset;
int count = 0, done = 0;
int rx = 0, ry = 0, rw = 0, rh = 0, btn_pressed = 0;
Window target = None;
Status ret;
scrot_selection_create(); scrotDoDelay();
scrotNiceClip(&rx, &ry, &rw, &rh);
xfd = ConnectionNumber(disp); im = imlib_create_image_from_drawable(0, rx, ry, rw, rh, 1);
fdsize = xfd + 1; if (opt.pointer)
scrotGrabMousePointer(im, rx, ry);
return im;
}
ret = XGrabKeyboard(disp, root, False, GrabModeAsync, GrabModeAsync, CurrentTi /* Clip rectangle nicely */
me); void scrotNiceClip(int* rx, int* ry, int* rw, int* rh)
if (ret == AlreadyGrabbed) { {
int attempts = 20; if (*rx < 0) {
struct timespec delay = {0, 50 * 1000L * 1000L}; *rw += *rx;
do { *rx = 0;
nanosleep(&delay, NULL);
ret = XGrabKeyboard(disp, root, False, GrabModeAsync, GrabModeAsync, Curre
ntTime);
} while (--attempts > 0 && ret == AlreadyGrabbed);
}
if (ret != GrabSuccess) {
fprintf(stderr, "failed to grab keyboard\n");
scrot_selection_destroy();
exit(EXIT_FAILURE);
}
while (1) {
/* handle events here */
while (!done && XPending(disp)) {
XNextEvent(disp, &ev);
switch (ev.type) {
case MotionNotify:
if (btn_pressed) {
scrot_selection_motion_draw(rx, ry, ev.xbutton.x, ev.xbutton.y);
}
break;
case ButtonPress:
btn_pressed = 1;
rx = ev.xbutton.x;
ry = ev.xbutton.y;
target = scrot_get_window(disp, ev.xbutton.subwindow, ev.xbutton.x, ev
.xbutton.y);
if (target == None)
target = root;
break;
case ButtonRelease:
done = 1;
break;
case KeyPress:
if (!btn_pressed) {
key_abort_shot:
fprintf(stderr, "Key was pressed, aborting shot\n");
done = 2;
break;
}
KeySym *keysym = NULL;
int keycode; /*dummy*/
keysym = XGetKeyboardMapping(disp, ev.xkey.keycode, 1, &keycode);
if (keysym == NULL) break;
switch (*keysym) {
case XK_Right:
if (++rx > scr->width) rx = scr->width;
break;
case XK_Left:
if (--rx < 0 ) rx = 0;
break;
case XK_Down:
if (++ry > scr->height) ry = scr->height;
break;
case XK_Up:
if (--ry < 0 ) ry = 0;
break;
default:
goto key_abort_shot;
}
XFree(keysym);
scrot_selection_motion_draw(rx, ry, ev.xbutton.x, ev.xbutton.y);
break;
case KeyRelease:
/* ignore */
break;
default:
break;
}
} }
if (done) if (*ry < 0) {
break; *rh += *ry;
*ry = 0;
/* now block some */
FD_ZERO(&fdset);
FD_SET(xfd, &fdset);
errno = 0;
count = select(fdsize, &fdset, NULL, NULL, NULL);
if ((count < 0)
&& ((errno == ENOMEM) || (errno == EINVAL) || (errno == EBADF))) {
fprintf(stderr, "Connection to X display lost\n");
scrot_selection_destroy();
exit(EXIT_FAILURE);
} }
} if ((*rx + *rw) > scr->width)
scrot_selection_draw(); *rw = scr->width - *rx;
if ((*ry + *rh) > scr->height)
XUngrabKeyboard(disp, CurrentTime); *rh = scr->height - *ry;
}
bool const isAreaSelect = (bool)(scrot_selection_get_rect()->w > 5);
scrot_selection_destroy(); static Bool scrotXEventVisibility(Display* dpy, XEvent* ev, XPointer arg)
{
(void)dpy; // unused
Window* win = (Window*)arg;
return (ev->xvisibility.window == *win);
}
if (done < 2) { /* Get geometry of window and use that */
scrot_do_delay(); int scrotGetGeometry(Window target, int* rx, int* ry, int* rw, int* rh)
if (isAreaSelect) { {
/* if a rect has been drawn, it's an area selection */ Window child;
rw = ev.xbutton.x - rx; XWindowAttributes attr;
rh = ev.xbutton.y - ry; int stat, frames = 0;
if ((ev.xbutton.x + 1) == WidthOfScreen(scr)) {
++rw;
}
if ((ev.xbutton.y + 1) == HeightOfScreen(scr)) {
++rh;
}
if (rw < 0) {
rx += rw;
rw = 0 - rw;
}
if (rh < 0) {
ry += rh;
rh = 0 - rh;
}
// Not record pointer if there is a selection area because it is busy on t
hat,
// unless the delay option is used
if (opt.delay == 0) {
opt.pointer = 0;
}
} else { /* Get windowmanager frame of window */
/* else it's a window click */ if (target != root) {
if (!scrot_get_geometry(target, &rx, &ry, &rw, &rh)) return NULL; unsigned int d;
int x;
int status;
status = XGetGeometry(disp, target, &root, &x, &x, &d, &d, &d, &d);
if (status) {
Window rt, *children, parent;
XEvent ev;
for (;;) {
/* Find window manager frame. */
status = XQueryTree(disp, target, &rt, &parent, &children, &d);
if (status && (children != None))
XFree(children);
if (!status || (parent == None) || (parent == rt))
break;
target = parent;
++frames;
}
/* Get client window. */
if (!opt.border)
target = scrotGetClientWindow(disp, target);
XRaiseWindow(disp, target);
/* Give the WM time to update the hidden area of the window.
Some windows never send the event, a time limit is placed.
*/
XSelectInput(disp, target, FocusChangeMask);
struct timespec delay = {0, 10000000L}; // 10ms
for (short i = 0; i < 30; ++i) {
if (XCheckIfEvent(disp, &ev, &scrotXEventVisibility, (XPointer)&
target))
break;
nanosleep(&delay, NULL);
}
}
} }
scrot_nice_clip(&rx, &ry, &rw, &rh); stat = XGetWindowAttributes(disp, target, &attr);
if (!stat || (attr.map_state != IsViewable))
return 0;
*rw = attr.width;
*rh = attr.height;
XTranslateCoordinates(disp, target, root, 0, 0, rx, ry, &child);
if (! opt.silent) XBell(disp, 0); /* Special case when the TWM emulates the border directly on the window. */
im = imlib_create_image_from_drawable(0, rx, ry, rw, rh, 1); if (opt.border == 1 && frames < 2 && attr.border_width > 0) {
*rw += attr.border_width * 2;
if (opt.pointer == 1) *rh += attr.border_width * 2;
scrot_grab_mouse_pointer(im, rx, ry); *rx -= attr.border_width;
} *ry -= attr.border_width;
return im; }
} return 1;
Imlib_Image
scrot_grab_autoselect(void)
{
Imlib_Image im = NULL;
int rx = opt.autoselect_x, ry = opt.autoselect_y, rw = opt.autoselect_w, rh =
opt.autoselect_h;
scrot_do_delay();
scrot_nice_clip(&rx, &ry, &rw, &rh);
im = imlib_create_image_from_drawable(0, rx, ry, rw, rh, 1);
if (opt.pointer == 1)
scrot_grab_mouse_pointer(im, rx, ry);
return im;
}
/* clip rectangle nicely */
void
scrot_nice_clip(int *rx,
int *ry,
int *rw,
int *rh)
{
if (*rx < 0) {
*rw += *rx;
*rx = 0;
}
if (*ry < 0) {
*rh += *ry;
*ry = 0;
}
if ((*rx + *rw) > scr->width)
*rw = scr->width - *rx;
if ((*ry + *rh) > scr->height)
*rh = scr->height - *ry;
} }
static Bool scrot_xevent_visibility(Display *dpy, XEvent *ev, XPointer arg) Window scrotGetWindow(Display* display, Window window, int x, int y)
{ {
(void) dpy; // unused Window source, target;
Window *win = (Window*)arg;
return (ev->xvisibility.window == *win);
}
/* get geometry of window and use that */ int status, xOffset, yOffset;
int
scrot_get_geometry(Window target, source = root;
int *rx, target = window;
int *ry, if (window == None)
int *rw, window = root;
int *rh) while (1) {
{ status = XTranslateCoordinates(display, source, window, x, y, &xOffset,
Window child; &yOffset, &target);
XWindowAttributes attr; if (!status)
int stat, frames = 0;
/* get windowmanager frame of window */
if (target != root) {
unsigned int d;
int x;
int status;
status = XGetGeometry(disp, target, &root, &x, &x, &d, &d, &d, &d);
if (status != 0) {
Window rt, *children, parent;
XEvent ev;
for (;;) {
/* Find window manager frame. */
status = XQueryTree(disp, target, &rt, &parent, &children, &d);
if (status && (children != None)) {
XFree((char *) children);
}
if (!status || (parent == None) || (parent == rt)) {
break; break;
} if (target == None)
target = parent;
++frames;
}
/* Get client window. */
if (!opt.border) {
target = scrot_get_client_window(disp, target);
}
XRaiseWindow(disp, target);
/* Give the WM time to update the hidden area of the window.
Some windows never send the event, a time limit is placed.
*/
XSelectInput(disp, target, FocusChangeMask);
for(short i = 0; i < 30; ++i) {
if (XCheckIfEvent(disp, &ev, &scrot_xevent_visibility, (XPointer)&target
) == True) {
break; break;
} source = window;
usleep(2000); window = target;
} x = xOffset;
y = yOffset;
} }
}
stat = XGetWindowAttributes(disp, target, &attr);
if ((stat == False) || (attr.map_state != IsViewable))
return 0;
*rw = attr.width;
*rh = attr.height;
XTranslateCoordinates(disp, target, root, 0, 0, rx, ry, &child);
/* Special case when the TWM emulates the border directly on the window. */
if (opt.border == 1 && frames < 2 && attr.border_width > 0) {
*rw += attr.border_width * 2;
*rh += attr.border_width * 2;
*rx -= attr.border_width;
*ry -= attr.border_width;
}
return 1;
}
Window
scrot_get_window(Display * display,
Window window,
int x,
int y)
{
Window source, target;
int status, x_offset, y_offset;
source = root;
target = window;
if (window == None)
window = root;
while (1) {
status =
XTranslateCoordinates(display, source, window, x, y, &x_offset,
&y_offset, &target);
if (status != True)
break;
if (target == None) if (target == None)
break; target = window;
source = window; return target;
window = target;
x = x_offset;
y = y_offset;
}
if (target == None)
target = window;
return (target);
} }
char * char* imPrintf(char* str, struct tm* tm, char* filenameIM, char* filenameThumb,
im_printf(char *str, struct tm *tm, Imlib_Image im)
char *filename_im, {
char *filename_thumb, char* c;
Imlib_Image im) char buf[20];
{ char ret[4096];
char *c; char strf[4096];
char buf[20]; char* tmp;
char ret[4096]; struct stat st;
char strf[4096];
char *tmp;
struct stat st;
ret[0] = '\0';
if (strftime(strf, 4095, str, tm) == 0) {
fprintf(stderr, "strftime returned 0\n");
exit(EXIT_FAILURE);
}
imlib_context_set_image(im);
for (c = strf; *c != '\0'; c++) {
if (*c == '$') {
c++;
switch (*c) {
case 'a':
gethostname(buf, sizeof(buf));
strcat(ret, buf);
break;
case 'f':
if (filename_im)
strcat(ret, filename_im);
break;
case 'm': /* t was already taken, so m as in mini */
if (filename_thumb)
strcat(ret, filename_thumb);
break;
case 'n':
if (filename_im) {
tmp = strrchr(filename_im, '/');
if (tmp)
strcat(ret, tmp + 1);
else
strcat(ret, filename_im);
}
break;
case 'w':
snprintf(buf, sizeof(buf), "%d", imlib_image_get_width());
strcat(ret, buf);
break;
case 'h':
snprintf(buf, sizeof(buf), "%d", imlib_image_get_height());
strcat(ret, buf);
break;
case 's':
if (filename_im) {
if (!stat(filename_im, &st)) {
int size;
size = st.st_size;
snprintf(buf, sizeof(buf), "%d", size);
strcat(ret, buf);
} else
strcat(ret, "[err]");
}
break;
case 'p':
snprintf(buf, sizeof(buf), "%d",
imlib_image_get_width() *
imlib_image_get_height());
strcat(ret, buf);
break;
case 't':
tmp = imlib_image_format();
if (tmp) {
strcat(ret, tmp);
}
break;
case '$':
strcat(ret, "$");
break;
default:
strncat(ret, c, 1);
break;
}
} else if (*c == '\\') {
c++;
switch (*c) {
case 'n':
if (filename_im)
strcat(ret, "\n");
break;
default:
strncat(ret, c, 1);
break;
}
} else {
const size_t len = strlen(ret);
ret[len] = *c;
ret[len + 1] = '\0';
}
}
return strdup(ret);
}
Window ret[0] = '\0';
scrot_get_client_window(Display * display,
Window target)
{
Atom state;
Atom type = None;
int format, status;
unsigned char *data;
unsigned long after, items;
Window client;
state = XInternAtom(display, "WM_STATE", True); if (strftime(strf, 4095, str, tm) == 0)
if (state == None) errx(EXIT_FAILURE, "strftime returned 0");
return target;
status =
XGetWindowProperty(display, target, state, 0L, 0L, False,
(Atom) AnyPropertyType, &type, &format, &items, &after,
&data);
if ((status == Success) && (type != None))
return target;
client = scrot_find_window_by_property(display, target, state);
if (!client)
return target;
return client;
}
Window imlib_context_set_image(im);
scrot_find_window_by_property(Display * display, for (c = strf; *c != '\0'; c++) {
const Window window, if (*c == '$') {
const Atom property) c++;
{ switch (*c) {
Atom type = None; case 'a':
int format, status; gethostname(buf, sizeof(buf));
unsigned char *data; strlcat(ret, buf, sizeof(ret));
unsigned int i, number_children; break;
unsigned long after, number_items; case 'f':
Window child = None, *children, parent, root; if (filenameIM)
strlcat(ret, filenameIM, sizeof(ret));
status = break;
XQueryTree(display, window, &root, &parent, &children, &number_children); case 'm': /* t was already taken, so m as in mini */
if (!status) if (filenameThumb)
return None; strlcat(ret, filenameThumb, sizeof(ret));
for (i = 0; (i < number_children) && (child == None); i++) { break;
status = case 'n':
XGetWindowProperty(display, children[i], property, 0L, 0L, False, if (filenameIM) {
(Atom) AnyPropertyType, &type, &format, tmp = strrchr(filenameIM, '/');
&number_items, &after, &data); if (tmp)
if (data) strlcat(ret, tmp + 1, sizeof(ret));
XFree(data); else
if ((status == Success) && (type != (Atom) NULL)) strlcat(ret, filenameIM, sizeof(ret));
child = children[i]; }
} break;
for (i = 0; (i < number_children) && (child == None); i++) case 'w':
child = scrot_find_window_by_property(display, children[i], property); snprintf(buf, sizeof(buf), "%d", imlib_image_get_width());
if (children != None) strlcat(ret, buf, sizeof(ret));
XFree(children); break;
return (child); case 'h':
} snprintf(buf, sizeof(buf), "%d", imlib_image_get_height());
strlcat(ret, buf, sizeof(ret));
Imlib_Image break;
scrot_grab_stack_windows(void) case 's':
{ if (filenameIM) {
if (XGetSelectionOwner(disp, XInternAtom(disp, "_NET_WM_CM_S0", False)) == N if (!stat(filenameIM, &st)) {
one) { int size;
fprintf(stderr, "Composite Manager is not running, required to use this
option.\n"); size = st.st_size;
exit(EXIT_FAILURE); snprintf(buf, sizeof(buf), "%d", size);
strlcat(ret, buf, sizeof(ret));
} else
strlcat(ret, "[err]", sizeof(ret));
}
break;
case 'p':
snprintf(buf, sizeof(buf), "%d",
imlib_image_get_width() * imlib_image_get_height());
strlcat(ret, buf, sizeof(ret));
break;
case 't':
tmp = imlib_image_format();
if (tmp)
strlcat(ret, tmp, sizeof(ret));
break;
case '$':
strlcat(ret, "$", sizeof(ret));
break;
default:
snprintf(buf, sizeof(buf), "%.1s", c);
strlcat(ret, buf, sizeof(ret));
break;
}
} else if (*c == '\\') {
c++;
switch (*c) {
case 'n':
if (filenameIM)
strlcat(ret, "\n", sizeof(ret));
break;
default:
snprintf(buf, sizeof(buf), "%.1s", c);
strlcat(ret, buf, sizeof(ret));
break;
}
} else {
const size_t length = strlen(ret);
ret[length] = *c;
ret[length + 1] = '\0';
}
} }
return strdup(ret);
}
unsigned long nitems_return; Window scrotGetClientWindow(Display* display, Window target)
unsigned long bytes_after_return; {
unsigned char *prop_return; Atom state;
long long_offset = 0L; Atom type = None;
long long_length = ~0L; int format, status;
Bool delete = False; unsigned char* data;
int actual_format_return; unsigned long after, items;
Atom actual_type_return; Window client;
Scrot_Imlib_List *list_images = NULL;
Imlib_Image im = NULL; state = XInternAtom(display, "WM_STATE", True);
XImage *ximage = NULL; if (state == None)
return target;
status = XGetWindowProperty(display, target, state, 0L, 0L, False,
AnyPropertyType, &type, &format, &items, &after,
&data);
if ((status == Success) && (type != None))
return target;
client = scrotFindWindowByProperty(display, target, state);
if (!client)
return target;
return client;
}
Window scrotFindWindowByProperty(Display* display, const Window window, const At
om property)
{
Atom type = None;
int format, status;
unsigned char* data;
unsigned int i, numberChildren;
unsigned long after, numberItems;
Window child = None, *children, parent, rootReturn;
status = XQueryTree(display, window, &rootReturn, &parent, &children, &numbe
rChildren);
if (!status)
return None;
for (i = 0; (i < numberChildren) && (child == None); i++) {
status = XGetWindowProperty(display, children[i], property, 0L, 0L, Fals
e,
AnyPropertyType, &type, &format,
&numberItems, &after, &data);
if (data)
XFree(data);
if ((status == Success) && type)
child = children[i];
}
for (i = 0; (i < numberChildren) && (child == None); i++)
child = scrotFindWindowByProperty(display, children[i], property);
if (children != None)
XFree(children);
return (child);
}
Imlib_Image scrotGrabStackWindows(void)
{
if (XGetSelectionOwner(disp, XInternAtom(disp, "_NET_WM_CM_S0", False)) == N
one)
errx(EXIT_FAILURE, "option --stack: Composite Manager is not running, re
quired to use this option.");
unsigned long numberItemsReturn;
unsigned long bytesAfterReturn;
unsigned char* propReturn;
long offset = 0L;
long length = ~0L;
Bool delete = False;
int actualFormatReturn;
Atom actualTypeReturn;
Imlib_Image im = NULL;
XImage* ximage = NULL;
XWindowAttributes attr; XWindowAttributes attr;
unsigned long i = 0; unsigned long i = 0;
#define EWMH_CLIENT_LIST "_NET_CLIENT_LIST" // spec EWMH #define EWMH_CLIENT_LIST "_NET_CLIENT_LIST" // spec EWMH
Atom atom_prop = XInternAtom(disp, EWMH_CLIENT_LIST, False); Atom atomProp = XInternAtom(disp, EWMH_CLIENT_LIST, False);
Atom atom_type = AnyPropertyType; Atom atomType = AnyPropertyType;
int result = XGetWindowProperty(disp, root, atom_prop, long_offset, long_len int result = XGetWindowProperty(disp, root, atomProp, offset, length,
gth, delete, atomType, &actualTypeReturn, &actualFormatReturn,
delete, atom_type, &actual_type_return, &actual_ &numberItemsReturn, &bytesAfterReturn, &propReturn);
format_return,
&nitems_return, &bytes_after_return, &prop_retur
n);
if (result != Success || nitems_return == 0) {
fprintf(stderr, "Failed XGetWindowProperty: " EWMH_CLIENT_LIST "\n");
exit(EXIT_FAILURE);
}
XCompositeRedirectSubwindows(disp, root, CompositeRedirectAutomatic); if (result != Success || numberItemsReturn == 0)
errx(EXIT_FAILURE, "option --stack: Failed XGetWindowProperty: " EWMH_CL
IENT_LIST);
for (i = 0; i < nitems_return; i++) { initializeScrotList(images);
Window win = *((Window*)prop_return + i); XCompositeRedirectSubwindows(disp, root, CompositeRedirectAutomatic);
if (0 == XGetWindowAttributes(disp, win, &attr)) { for (i = 0; i < numberItemsReturn; i++) {
fprintf(stderr, "Failed XGetWindowAttributes\n"); Window win = *((Window*)propReturn + i);
exit(EXIT_FAILURE);
} if (!XGetWindowAttributes(disp, win, &attr))
errx(EXIT_FAILURE, "option --stack: Failed XGetWindowAttributes");
/* Only visible windows */ /* Only visible windows */
if (attr.map_state != IsViewable) { if (attr.map_state != IsViewable)
continue; continue;
}
if (!scrot_match_window_class_name(win)) { if (!scrotMatchWindowClassName(win))
continue; continue;
}
ximage = XGetImage(disp, win, 0, 0, attr.width, attr.height, AllPlanes, ZPixmap); ximage = XGetImage(disp, win, 0, 0, attr.width, attr.height, AllPlanes, ZPixmap);
if (ximage == NULL) { if (!ximage)
fprintf(stderr, "Failed XGetImage: Window id 0x%lx.\n", win); errx(EXIT_FAILURE, "option --stack: Failed XGetImage: Window id 0x%l
exit(EXIT_FAILURE); x", win);
}
im = imlib_create_image_from_ximage(ximage, NULL, attr.x, attr.y, attr.w idth, attr.height, 1); im = imlib_create_image_from_ximage(ximage, NULL, attr.x, attr.y, attr.w idth, attr.height, 1);
XFree(ximage); XFree(ximage);
list_images = append_to_scrot_imlib(list_images, im); appendToScrotList(images, im);
} }
return stalk_image_concat(list_images); return stalkImageConcat(&images, opt.stackDirection);
} }
Imlib_Image Imlib_Image scrotGrabShotMulti(void)
scrot_grab_shot_multi(void)
{ {
int screens; int screens = ScreenCount(disp);
int i; if (screens < 2)
char *dispstr, *subdisp; return scrotGrabShot();
char newdisp[255];
Scrot_Imlib_List *images = NULL; int i;
Imlib_Image ret = NULL; char* dispStr;
char* subDisp;
screens = ScreenCount(disp); char newDisp[255];
if (screens < 2) Imlib_Image ret = NULL;
return scrot_grab_shot();
initializeScrotList(images);
subdisp = strdup(DisplayString(disp));
subDisp = strdup(DisplayString(disp));
for (i = 0; i < screens; i++) {
dispstr = strchr(subdisp, ':'); for (i = 0; i < screens; i++) {
if (dispstr) { dispStr = strchr(subDisp, ':');
dispstr = strchr(dispstr, '.'); if (dispStr) {
if (NULL != dispstr) dispStr = strchr(dispStr, '.');
*dispstr = '\0'; if (dispStr)
*dispStr = '\0';
}
snprintf(newDisp, sizeof(newDisp), "%s.%d", subDisp, i);
initXAndImlib(newDisp, i);
ret = imlib_create_image_from_drawable(0, 0, 0, scr->width,
scr->height, 1);
appendToScrotList(images, ret);
}
free(subDisp);
return stalkImageConcat(&images, HORIZONTAL);
}
Imlib_Image stalkImageConcat(ScrotList* images, enum Direction const dir)
{
if (isEmptyScrotList(images))
return NULL;
int total = 0, max = 0;
int x = 0, y = 0, w , h;
Imlib_Image ret, im;
ScrotListNode* image = NULL;
bool const vertical = (dir == VERTICAL) ? true : false;
forEachScrotList(images, image) {
im = (Imlib_Image) image->data;
imlib_context_set_image(im);
h = imlib_image_get_height();
w = imlib_image_get_width();
if (!vertical) {
if (h > max)
max = h;
total += w;
} else {
if (w > max)
max = w;
total += h;
}
} }
snprintf(newdisp, sizeof(newdisp), "%s.%d", subdisp, i); if (!vertical) {
init_x_and_imlib(newdisp, i); w = total;
ret = h = max;
imlib_create_image_from_drawable(0, 0, 0, scr->width, } else {
scr->height, 1); w = max;
images = append_to_scrot_imlib(images, ret); h = total;
} }
free(subdisp); ret = imlib_create_image(w, h);
ret = stalk_image_concat(images);
return ret;
}
Imlib_Image
stalk_image_concat(Scrot_Imlib_List * images)
{
int tot_w = 0, max_h = 0, w, h;
int x = 0;
Scrot_Imlib_List *l, *item;
Imlib_Image ret, im;
if (is_scrot_imlib_list_empty(images))
return NULL;
l = images;
while (l) {
im = (Imlib_Image) l->data;
imlib_context_set_image(im);
h = imlib_image_get_height();
w = imlib_image_get_width();
if (h > max_h)
max_h = h;
tot_w += w;
l = l->next;
}
ret = imlib_create_image(tot_w, max_h);
imlib_context_set_image(ret);
imlib_context_set_color(255, 0, 0, 0);
imlib_image_fill_rectangle(0, 0, tot_w, max_h);
l = images;
while (l) {
im = (Imlib_Image) l->data;
item = l;
l = l->next;
imlib_context_set_image(im);
h = imlib_image_get_height();
w = imlib_image_get_width();
imlib_context_set_image(ret); imlib_context_set_image(ret);
imlib_context_set_anti_alias(0); imlib_context_set_color(0, 0, 0, 255);
imlib_context_set_dither(1); imlib_image_fill_rectangle(0, 0, w, h);
imlib_context_set_blend(0);
imlib_context_set_angle(0); image = firstScrotList(images);
imlib_blend_image_onto_image(im, 0, 0, 0, w, h, x, 0, w, h); while (image) {
x += w; im = (Imlib_Image) image->data;
imlib_context_set_image(im); imlib_context_set_image(im);
imlib_free_image_and_decache(); h = imlib_image_get_height();
free(item); w = imlib_image_get_width();
} imlib_context_set_image(ret);
return ret; imlib_context_set_anti_alias(0);
imlib_context_set_dither(1);
imlib_context_set_blend(0);
imlib_context_set_angle(0);
imlib_blend_image_onto_image(im, 0, 0, 0, w, h, x, y, w, h);
(!vertical) ? (x += w) : (y += h);
imlib_context_set_image(im);
imlib_free_image_and_decache();
nextAndFreeScrotList(image);
}
return ret;
} }
 End of changes. 104 change blocks. 
873 lines changed or deleted 644 lines changed or added

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