Newer
Older
gib_imlib_free_image_and_decache(im);
return;
}
Birte Kristina Friesel
committed
char *build_caption_filename(feh_file * file, short create_dir)
{
char *caption_filename;
char *s, *dir, *caption_dir;
struct stat cdir_stat;
s = strrchr(file->filename, '/');
if (s) {
dir = estrdup(file->filename);
s = strrchr(dir, '/');
*s = '\0';
} else {
dir = estrdup(".");
}
caption_dir = estrjoin("/", dir, opt.caption_path, NULL);
D(("dir %s, cp %s, cdir %s\n", dir, opt.caption_path, caption_dir))
if (stat(caption_dir, &cdir_stat) == -1) {
Birte Kristina Friesel
committed
if (!create_dir)
return NULL;
if (mkdir(caption_dir, 0755) == -1)
eprintf("Failed to create caption directory %s:", caption_dir);
} else if (!S_ISDIR(cdir_stat.st_mode))
eprintf("Caption directory (%s) exists, but is not a directory.",
caption_dir);
free(caption_dir);
caption_filename = estrjoin("", dir, "/", opt.caption_path, "/", file->name, ".txt", NULL);
free(dir);
return caption_filename;
void feh_draw_caption(winwidget w)
static Imlib_Font fn = NULL;
int tw = 0, th = 0, ww, hh;
int x, y;
Imlib_Image im = NULL;
char *p;
gib_list *lines, *l;
static gib_style *caption_style = NULL;
feh_file *file;
if (!w->file) {
Birte Kristina Friesel
committed
return;
}
file = FEH_FILE(w->file->data);
if (!file->filename) {
Birte Kristina Friesel
committed
return;
}
if (!file->caption) {
char *caption_filename;
Birte Kristina Friesel
committed
caption_filename = build_caption_filename(file, 0);
if (caption_filename)
/* read caption from file */
file->caption = ereadfile(caption_filename);
else
file->caption = estrdup("");
free(caption_filename);
}
if (file->caption == NULL) {
/* caption file is not there, we want to cache that, otherwise we'll stat
* the damn file every time we render the image. Reloading an image will
* always cause the caption to be reread though so we're safe to do so.
* (Before this bit was added, when zooming a captionless image with
* captions enabled, the captions file would be stat()d like 30 times a
* second) - don't forget this function is called from
* winwidget_render_image().
*/
file->caption = estrdup("");
}
Birte Kristina Friesel
committed
if (*(file->caption) == '\0' && !w->caption_entry)
Birte Kristina Friesel
committed
return;
Birte Kristina Friesel
committed
caption_style = gib_style_new("caption");
caption_style->bits = gib_list_add_front(caption_style->bits,
gib_style_bit_new(0, 0, 0, 0, 0, 0));
caption_style->bits = gib_list_add_front(caption_style->bits,
gib_style_bit_new(1, 1, 0, 0, 0, 255));
fn = feh_load_font(w);
Birte Kristina Friesel
committed
if (*(file->caption) == '\0') {
p = estrdup("Caption entry mode - Hit ESC to cancel");
lines = feh_wrap_string(p, w->w, fn, NULL);
free(p);
} else
lines = feh_wrap_string(file->caption, w->w, fn, NULL);
if (!lines)
Birte Kristina Friesel
committed
return;
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
/* Work out how high/wide the caption is */
l = lines;
while (l) {
p = (char *) l->data;
gib_imlib_get_text_size(fn, p, caption_style, &ww, &hh, IMLIB_TEXT_TO_RIGHT);
if (ww > tw)
tw = ww;
th += hh;
if (l->next)
th += 1; /* line spacing */
l = l->next;
}
/* we don't want the caption overlay larger than our window */
if (th > w->h)
th = w->h;
if (tw > w->w)
tw = w->w;
im = imlib_create_image(tw, th);
if (!im)
eprintf("Couldn't create image. Out of memory?");
Birte Kristina Friesel
committed
feh_imlib_image_fill_text_bg(im, tw, th);
l = lines;
y = 0;
while (l) {
p = (char *) l->data;
gib_imlib_get_text_size(fn, p, caption_style, &ww, &hh, IMLIB_TEXT_TO_RIGHT);
x = (tw - ww) / 2;
Birte Kristina Friesel
committed
if (w->caption_entry && (*(file->caption) == '\0'))
gib_imlib_text_draw(im, fn, caption_style, x, y, p,
IMLIB_TEXT_TO_RIGHT, 255, 255, 127, 255);
else if (w->caption_entry)
gib_imlib_text_draw(im, fn, caption_style, x, y, p,
IMLIB_TEXT_TO_RIGHT, 255, 255, 0, 255);
else
gib_imlib_text_draw(im, fn, caption_style, x, y, p,
IMLIB_TEXT_TO_RIGHT, 255, 255, 255, 255);
y += hh + 1; /* line spacing */
l = l->next;
}
gib_imlib_render_image_on_drawable(w->bg_pmap, im, (w->w - tw) / 2, w->h - th, 1, 1, 0);
gib_imlib_free_image_and_decache(im);
gib_list_free_and_data(lines);
Birte Kristina Friesel
committed
return;
}
unsigned char reset_output = 0;
void feh_display_status(char stat)
static int i = 0;
static int init_len = 0;
int j = 0;
D(("filelist %p, filelist->next %p\n", filelist, filelist->next));
if (!stat) {
init_len = 0;
i = 0;
return;
}
if (!init_len)
init_len = gib_list_length(filelist);
if (i) {
if (reset_output) {
/* There's just been an error message. Unfortunate ;) */
for (j = 0; j < (((i % 50) + ((i % 50) / 10)) + 7); j++)
}
if (!(i % 50)) {
Birte Kristina Friesel
committed
int len = gib_list_length(filelist);
fprintf(stderr, " %5d/%d (%d)\n[%3d%%] ",
Birte Kristina Friesel
committed
i, init_len, len, ((int) ((float) i / init_len * 100)));
} else if ((!(i % 10)) && (!reset_output))
reset_output = 0;
} else
fprintf(stderr, "%c", stat);
fflush(stderr);
i++;
Birte Kristina Friesel
committed
return;
void feh_edit_inplace(winwidget w, int op)
{
Birte Kristina Friesel
committed
int tmp;
Imlib_Image old = NULL;
Imlib_Load_Error err = IMLIB_LOAD_ERROR_NONE;
if (!w->file || !w->file->data || !FEH_FILE(w->file->data)->filename)
Birte Kristina Friesel
committed
return;
imlib_context_set_image(w->im);
if (op == INPLACE_EDIT_FLIP)
imlib_image_flip_vertical();
else if (op == INPLACE_EDIT_MIRROR)
imlib_image_flip_horizontal();
else {
imlib_image_orientate(op);
tmp = w->im_w;
w->im_w = w->im_h;
w->im_h = tmp;
if (FEH_FILE(w->file->data)->info) {
FEH_FILE(w->file->data)->info->width = w->im_w;
FEH_FILE(w->file->data)->info->height = w->im_h;
}
}
winwidget_render_image(w, 1, 0);
return;
}
if (!strcmp(gib_imlib_image_format(w->im), "jpeg") &&
!path_is_url(FEH_FILE(w->file->data)->filename)) {
feh_edit_inplace_lossless(w, op);
feh_reload_image(w, 1, 1);
Birte Kristina Friesel
committed
return;
}
old = imlib_load_image_with_error_return(FEH_FILE(w->file->data)->filename, &err);
if ((old != NULL) && (err == IMLIB_LOAD_ERROR_NONE)) {
imlib_context_set_image(old);
if (op == INPLACE_EDIT_FLIP)
imlib_image_flip_vertical();
else if (op == INPLACE_EDIT_MIRROR)
imlib_image_flip_horizontal();
else
imlib_image_orientate(op);
gib_imlib_save_image_with_error_return(old,
FEH_FILE(w->file->data)->filename, &err);
gib_imlib_free_image(old);
if (err)
feh_imlib_print_load_error(FEH_FILE(w->file->data)->filename,
w, err);
feh_reload_image(w, 1, 1);
} else {
/*
* Image was opened using curl/magick or has been deleted after
* opening it
*/
imlib_context_set_image(w->im);
if (op == INPLACE_EDIT_FLIP)
imlib_image_flip_vertical();
else if (op == INPLACE_EDIT_MIRROR)
imlib_image_flip_horizontal();
else {
imlib_image_orientate(op);
tmp = w->im_w;
w->im_w = w->im_h;
w->im_h = tmp;
if (FEH_FILE(w->file->data)->info) {
FEH_FILE(w->file->data)->info->width = w->im_w;
FEH_FILE(w->file->data)->info->height = w->im_h;
}
}
im_weprintf(w, "unable to edit in place. Changes have not been saved.");
winwidget_render_image(w, 1, 0);
}
Birte Kristina Friesel
committed
return;
Birte Kristina Friesel
committed
gib_list *feh_wrap_string(char *text, int wrap_width, Imlib_Font fn, gib_style * style)
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
gib_list *ll, *lines = NULL, *list = NULL, *words;
gib_list *l = NULL;
char delim[2] = { '\n', '\0' };
int w, line_width;
int tw, th;
char *p, *pp;
char *line = NULL;
char *temp;
int space_width = 0, m_width = 0, t_width = 0, new_width = 0;
lines = gib_string_split(text, delim);
if (wrap_width) {
gib_imlib_get_text_size(fn, "M M", style, &t_width, NULL, IMLIB_TEXT_TO_RIGHT);
gib_imlib_get_text_size(fn, "M", style, &m_width, NULL, IMLIB_TEXT_TO_RIGHT);
space_width = t_width - (2 * m_width);
w = wrap_width;
l = lines;
while (l) {
line_width = 0;
p = (char *) l->data;
/* quick check to see if whole line fits okay */
gib_imlib_get_text_size(fn, p, style, &tw, &th, IMLIB_TEXT_TO_RIGHT);
if (tw <= w) {
list = gib_list_add_end(list, estrdup(p));
} else if (strlen(p) == 0) {
list = gib_list_add_end(list, estrdup(""));
} else if (!strcmp(p, " ")) {
list = gib_list_add_end(list, estrdup(" "));
} else {
words = gib_string_split(p, " ");
if (words) {
ll = words;
while (ll) {
pp = (char *) ll->data;
if (strcmp(pp, " ")) {
gib_imlib_get_text_size
(fn, pp, style, &tw, &th, IMLIB_TEXT_TO_RIGHT);
if (line_width == 0)
new_width = tw;
else
new_width = line_width + space_width + tw;
if (new_width <= w) {
/* add word to line */
if (line) {
int len;
len = strlen(line)
+ strlen(pp)
+ 2;
temp = emalloc(len);
snprintf(temp, len, "%s %s", line, pp);
free(line);
line = temp;
} else {
line = estrdup(pp);
}
line_width = new_width;
} else if (line_width == 0) {
/* can't fit single word in :/
increase width limit to width of word
and jam the bastard in anyhow */
w = tw;
line = estrdup(pp);
line_width = new_width;
} else {
/* finish this line, start next and add word there */
if (line) {
list = gib_list_add_end(list, estrdup(line));
free(line);
line = NULL;
}
line = estrdup(pp);
line_width = tw;
}
}
ll = ll->next;
}
if (line) {
/* finish last line */
list = gib_list_add_end(list, estrdup(line));
free(line);
line = NULL;
}
gib_list_free_and_data(words);
}
}
l = l->next;
}
gib_list_free_and_data(lines);
lines = list;
}
return lines;
void feh_edit_inplace_lossless(winwidget w, int op)
{
char *filename = FEH_FILE(w->file->data)->filename;
int len = strlen(filename) + 1;
char *file_str = emalloc(len);
int pid, status;
int devnull = -1;
Birte Kristina Friesel
committed
char op_name[] = "rotate"; /* message */
char op_op[] = "-rotate"; /* jpegtran option */
char op_value[] = "horizontal"; /* jpegtran option's value */
if (op == INPLACE_EDIT_FLIP) {
sprintf(op_name, "flip");
sprintf(op_op, "-flip");
sprintf(op_value, "vertical");
} else if (op == INPLACE_EDIT_MIRROR) {
sprintf(op_name, "mirror");
sprintf(op_op, "-flip");
} else
snprintf(op_value, 4, "%d", 90 * op);
snprintf(file_str, len, "%s", filename);
if ((pid = fork()) < 0) {
im_weprintf(w, "lossless %s: fork failed:", op_name);
free(file_str);
return;
}
else if (pid == 0) {
execlp("jpegtran", "jpegtran", "-copy", "all", op_op, op_value,
"-outfile", file_str, file_str, NULL);
Birte Kristina Friesel
committed
weprintf("lossless %s: Is 'jpegtran' installed? Failed to exec:", op_name);
_exit(1);
waitpid(pid, &status, 0);
if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
im_weprintf(w,
"lossless %s: Got exitcode %d from jpegtran."
" Commandline was: "
"jpegtran -copy all %s %s -outfile %s %s",
op_name, status >> 8, op_op, op_value, file_str, file_str);
Birte Kristina Friesel
committed
return;
}
if ((pid = fork()) < 0) {
im_weprintf(w, "lossless %s: fork failed while updating EXIF tags:", op_name);
}
else if (pid == 0) {
/* discard normal output */
devnull = open("/dev/null", O_WRONLY);
dup2(devnull, 1);
execlp("jpegexiforient", "jpegexiforient", "-1", file_str, NULL);
Birte Kristina Friesel
committed
weprintf("lossless %s: Failed to exec jpegexiforient:", op_name);
_exit(1);
}
else {
waitpid(pid, &status, 0);
if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
im_weprintf(w,
Birte Kristina Friesel
committed
"lossless %s: Failed to update EXIF orientation tag:"
" jpegexiforient returned %d",
op_name, status >> 8);
void feh_draw_actions(winwidget w)
static Imlib_Font fn = NULL;
int tw = 0, th = 0;
int th_offset = 0;
int max_tw = 0;
int line_th = 0;
Imlib_Image im = NULL;
int i = 0;
int num_actions = 0;
int cur_action = 0;
char *line;
/* Count number of defined actions. This method sucks a bit since it needs
* to be changed if the number of actions changes, but at least it doesn't
* miss actions 2 to 9 if action1 isn't defined
*/
for (i = 0; i < 10; i++) {
if (opt.actions[i])
num_actions++;
}
if (num_actions == 0)
return;
if ((!w->file) || (!FEH_FILE(w->file->data))
|| (!FEH_FILE(w->file->data)->filename))
Birte Kristina Friesel
committed
return;
fn = feh_load_font(w);
gib_imlib_get_text_size(fn, "defined actions:", NULL, &tw, &th, IMLIB_TEXT_TO_RIGHT);
/* Check for the widest line */
max_tw = tw;
for (i = 0; i < 10; i++) {
if (opt.actions[i]) {
line = emalloc(strlen(opt.action_titles[i]) + 5);
strcpy(line, "0: ");
line = strcat(line, opt.action_titles[i]);
gib_imlib_get_text_size(fn, line, NULL, &tw, &th, IMLIB_TEXT_TO_RIGHT);
free(line);
if (tw > max_tw)
max_tw = tw;
}
}
tw = max_tw;
tw += 3;
th += 3;
line_th = th;
th = (th * num_actions) + line_th;
/* This depends on feh_draw_filename internals...
* should be fixed some time
*/
th_offset = line_th * 2;
im = imlib_create_image(tw, th);
if (!im)
eprintf("Couldn't create image. Out of memory?");
Birte Kristina Friesel
committed
feh_imlib_image_fill_text_bg(im, tw, th);
gib_imlib_text_draw(im, fn, NULL, 2, 2, "defined actions:", IMLIB_TEXT_TO_RIGHT, 0, 0, 0, 255);
gib_imlib_text_draw(im, fn, NULL, 1, 1, "defined actions:", IMLIB_TEXT_TO_RIGHT, 255, 255, 255, 255);
for (i = 0; i < 10; i++) {
if (opt.action_titles[i]) {
cur_action++;
line = emalloc(strlen(opt.action_titles[i]) + 5);
sprintf(index, "%d", i);
strcpy(line, index);
strcat(line, ": ");
strcat(line, opt.action_titles[i]);
gib_imlib_text_draw(im, fn, NULL, 2,
(cur_action * line_th) + 2, line,
IMLIB_TEXT_TO_RIGHT, 0, 0, 0, 255);
gib_imlib_text_draw(im, fn, NULL, 1,
(cur_action * line_th) + 1, line,
IMLIB_TEXT_TO_RIGHT, 255, 255, 255, 255);
free(line);
}
}
gib_imlib_render_image_on_drawable(w->bg_pmap, im, 0, 0 + th_offset, 1, 1, 0);
gib_imlib_free_image_and_decache(im);
Birte Kristina Friesel
committed
return;