"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "f.file.cc" between
fotoxx-23.0.tar.gz and fotoxx-23.1.tar.gz

About: fotoxx is a program for photo editing and collection management.

f.file.cc  (fotoxx-23.0):f.file.cc  (fotoxx-23.1)
/******************************************************************************* * /******************************************************************************* *
Fotoxx edit photos and manage collections Fotoxx - edit photos and manage collections
Copyright 2007-2023 Michael Cornelison Copyright 2007-2023 Michael Cornelison
source code URL: https://kornelix.net source code URL: https://kornelix.net
contact: mkornelix@gmail.com contact: mkornelix@gmail.com
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. See https://www.gnu.org/licenses (at your option) any later version. See https://www.gnu.org/licenses
skipping to change at line 93 skipping to change at line 93
#define EX extern // disable extern declarations #define EX extern // disable extern declarations
#include "fotoxx.h" // (variables in fotoxx.h are refs) #include "fotoxx.h" // (variables in fotoxx.h are refs)
/******************************************************************************* */ /******************************************************************************* */
// start a new parallel session of fotoxx // start a new parallel session of fotoxx
// new window is slightly down and right from old window // new window is slightly down and right from old window
// args = optional command line args // args = optional command line args
// current file is appended if it exists // current file is appended if it exists
void m_new_session(GtkWidget *, cchar *) void m_new_session(GtkWidget *, ch *)
{ {
char *pp; ch *pp;
int cc; int cc;
F1_help_topic = "new session"; F1_help_topic = "new session";
Plog(1,"m_new_session \n"); Plog(1,"m_new_session \n");
if (curr_file) { if (curr_file) {
cc = strlen(curr_file); cc = strlen(curr_file);
pp = (char *) zmalloc(cc+100,"new-session"); pp = (ch *) zmalloc(cc+100,"new-session");
repl_1str(curr_file,pp+1,"\"","\\\""); // replace embedded " with \" 22.30 repl_1str(curr_file,pp+1,"\"","\\\""); // replace embedded " with \" 22.30
pp[0] = '"'; pp[0] = '"';
cc = strlen(pp); // add " at both ends cc = strlen(pp); // add " at both ends
pp[cc] = '"'; pp[cc] = '"';
pp[cc+1] = 0; pp[cc+1] = 0;
new_session(pp); new_session(pp);
zfree(pp); zfree(pp);
} }
else new_session(0); else new_session(0);
return; return;
} }
// callable new session function // callable new session function
void new_session(cchar *args) void new_session(ch *args)
{ {
int cc, xx, yy, ww, hh; int cc, xx, yy, ww, hh;
char progexe[300]; ch progexe[300];
// do before new session: // do before new session:
zdialog_inputs("save"); // save dialog inputs zdialog_inputs("save"); // save dialog inputs
zdialog_geometry("save"); // save dialogs position/size zdialog_geometry("save"); // save dialogs position/size
gallery_memory("save"); // save recent gallery positions gallery_memory("save"); // save recent gallery positions
save_params(); // save state for next session save_params(); // save state for next session
gtk_window_get_position(MWIN,&xx,&yy); // get window position and size gtk_window_get_position(MWIN,&xx,&yy); // get window position and size
gtk_window_get_size(MWIN,&ww,&hh); gtk_window_get_size(MWIN,&ww,&hh);
xx += 100; // shift down and right xx += 100; // shift down and right
yy += 100; yy += 100;
skipping to change at line 151 skipping to change at line 151
if (! args) args = ""; if (! args) args = "";
zshell("log ack","%s -c %d %d %d %d %s &",progexe,xx,yy,ww,hh,args); zshell("log ack","%s -c %d %d %d %d %s &",progexe,xx,yy,ww,hh,args);
return; return;
} }
/******************************************************************************* */ /******************************************************************************* */
// find and open an image file using a file open dialog // find and open an image file using a file open dialog
void m_open_file(GtkWidget *, cchar *) void m_open_file(GtkWidget *, ch *)
{ {
int err; int err;
F1_help_topic = "open image file"; F1_help_topic = "open image file";
Plog(1,"m_open_file \n"); Plog(1,"m_open_file \n");
if (Fblock(0,"blocked edits")) return; // check nothing pending if (Fblock(0,"blocked edits")) return; // check nothing pending
err = f_open(0,0,0,1,0); err = f_open(0,0,0,1,0);
if (err) return; if (err) return;
m_viewmode(0,"F"); // file view mode m_viewmode(0,"F"); // file view mode
return; return;
} }
/******************************************************************************* */ /******************************************************************************* */
// open the previous file opened (not the same as toolbar [prev] button) // open the previous file opened (not the same as toolbar [prev] button)
// repeated use will alternate the two most recent files // repeated use will alternate the two most recent files
void m_cycle2files(GtkWidget *, cchar *) void m_cycle2files(GtkWidget *, ch *)
{ {
FILE *fid; FILE *fid;
char *file, buff[XFCC]; ch *file, buff[XFCC];
int Nth = 0, err; int Nth = 0, err;
float gzoom; float gzoom;
F1_help_topic = "cycle 2"; F1_help_topic = "cycle 2";
Plog(1,"m_cycle2files \n"); Plog(1,"m_cycle2files \n");
if (Fblock(0,"blocked edits")) return; // check nothing pending if (Fblock(0,"blocked edits")) return; // check nothing pending
m_viewmode(0,"F"); m_viewmode(0,"F");
skipping to change at line 213 skipping to change at line 213
Cstate->fzoom = gzoom; // keep same image scale Cstate->fzoom = gzoom; // keep same image scale
Fpaint2(); Fpaint2();
return; return;
} }
/******************************************************************************* */ /******************************************************************************* */
// open the 2nd previous file opened // open the 2nd previous file opened
// repeated use will alternate the 3 most recent files // repeated use will alternate the 3 most recent files
void m_cycle3files(GtkWidget *, cchar *) void m_cycle3files(GtkWidget *, ch *)
{ {
FILE *fid; FILE *fid;
char *file, buff[XFCC]; ch *file, buff[XFCC];
int Nth = 0, err; int Nth = 0, err;
float gzoom; float gzoom;
F1_help_topic = "cycle 3"; F1_help_topic = "cycle 3";
Plog(1,"m_cycle3files \n"); Plog(1,"m_cycle3files \n");
if (Fblock(0,"blocked edits")) return; // check nothing pending if (Fblock(0,"blocked edits")) return; // check nothing pending
m_viewmode(0,"F"); m_viewmode(0,"F");
skipping to change at line 267 skipping to change at line 267
namespace view360 namespace view360
{ {
void show(); void show();
void * show_thread(void *arg); void * show_thread(void *arg);
void mouse(); void mouse();
void KB_func(int key); void KB_func(int key);
void quit(); void quit();
PXB *filepxb, *viewpxb; PXB *filepxb, *viewpxb;
PIXBUF *viewpixbuf; PIXBUF *viewpixbuf;
char *filename = 0; ch *filename = 0;
int Frecalc; int Frecalc;
int fww, fhh; // file dimensions int fww, fhh; // file dimensions
int dww, dhh; // window dimensions int dww, dhh; // window dimensions
int pdww, pdhh; int pdww, pdhh;
int cx, cy; int cx, cy;
float *Fx, *Fy, zoom; float *Fx, *Fy, zoom;
zdialog *zd; zdialog *zd;
} }
// menu function // menu function
void m_view360(GtkWidget *, const char *) void m_view360(GtkWidget *, ch *)
{ {
using namespace view360; using namespace view360;
F1_help_topic = "view 360° pano"; F1_help_topic = "view 360° pano";
Plog(1,"m_view360 \n"); Plog(1,"m_view360 \n");
if (Fblock("view360","block edits")) return; // check pend, block if (Fblock("view360","block edits")) return; // check pend, block
if (clicked_file) { // use clicked file if present if (clicked_file) { // use clicked file if present
skipping to change at line 546 skipping to change at line 546
gdk_window_thaw_updates(gdkwin); gdk_window_thaw_updates(gdkwin);
Fpaint2(); Fpaint2();
} }
/******************************************************************************* */ /******************************************************************************* */
// rename menu function // rename menu function
// activate rename dialog, stuff data from current or clicked file // activate rename dialog, stuff data from current or clicked file
// dialog remains active when new file is opened // dialog remains active when new file is opened
char rename_old[200] = ""; ch rename_old[200] = "";
// base names only // base names only
char rename_new[200] = ""; ch rename_new[200] = "";
char rename_prev[200] = ""; ch rename_prev[200] = "";
char *rename_file = 0; ch *rename_file = 0;
void m_rename(GtkWidget *, cchar *menu) void m_rename(GtkWidget *, ch *menu)
{ {
int rename_dialog_event(zdialog *zd, cchar *event); int rename_dialog_event(zdialog *zd, ch *event);
char *pdir, *pfile, *pext; ch *pdir, *pfile, *pext;
F1_help_topic = "rename"; F1_help_topic = "rename";
Plog(1,"m_rename \n"); Plog(1,"m_rename \n");
if (rename_file) zfree(rename_file); if (rename_file) zfree(rename_file);
rename_file = 0; rename_file = 0;
if (clicked_file) { // use clicked file if present if (clicked_file) { // use clicked file if present
rename_file = clicked_file; rename_file = clicked_file;
skipping to change at line 630 skipping to change at line 630
strncpy0(rename_old,pfile,199); strncpy0(rename_old,pfile,199);
strncpy0(rename_new,pfile,199); strncpy0(rename_new,pfile,199);
zdialog_stuff(zd,"oldname",rename_old); // current file name zdialog_stuff(zd,"oldname",rename_old); // current file name
zdialog_stuff(zd,"newname",rename_new); // entered file name (same) zdialog_stuff(zd,"newname",rename_new); // entered file name (same)
return; return;
} }
// dialog event and completion callback function // dialog event and completion callback function
int rename_dialog_event(zdialog *zd, cchar *event) int rename_dialog_event(zdialog *zd, ch *event)
{ {
char *pp, *pdir, *pfile, *pext, suffix[16]; ch *pp, *pdir, *pfile, *pext, suffix[16];
char *newfile = 0, *nextfile = 0, namever[200]; ch *newfile = 0, *nextfile = 0, namever[200];
int nseq, digits, ccp, ccn, ccx, err, Fkeep; int nseq, digits, ccp, ccn, ccx, err, Fkeep;
if (strmatch(event,"escape")) zd->zstat = -2; // escape key if (strmatch(event,"escape")) zd->zstat = -2; // escape key
if (strmatch(event,"prev")) // previous name >> new name if (strmatch(event,"prev")) // previous name >> new name
{ {
if (! *rename_prev) return 1; if (! *rename_prev) return 1;
if (! rename_file) return 1; if (! rename_file) return 1;
pp = strrchr(rename_prev,'.'); pp = strrchr(rename_prev,'.');
skipping to change at line 709 skipping to change at line 709
parsefile(rename_file,&pdir,&pfile,&pext); // existing /folders/file.ext parsefile(rename_file,&pdir,&pfile,&pext); // existing /folders/file.ext
zdialog_fetch(zd,"newname",rename_new,194); // new file name from user zdialog_fetch(zd,"newname",rename_new,194); // new file name from user
ccp = strlen(pdir); // length of /folders/ ccp = strlen(pdir); // length of /folders/
ccn = strlen(rename_new); // length of file ccn = strlen(rename_new); // length of file
if (pext) ccx = strlen(pext); // length of .ext if (pext) ccx = strlen(pext); // length of .ext
else ccx = 0; else ccx = 0;
newfile = (char *) zmalloc(ccp + ccn + ccx + 1,"rename"); // put it all together newfile = (ch *) zmalloc(ccp + ccn + ccx + 1,"rename"); // put it all together
strncpy(newfile,rename_file,ccp); // /folders.../newfilename.ext strncpy(newfile,rename_file,ccp); // /folders.../newfilename.ext
strcpy(newfile+ccp,rename_new); strcpy(newfile+ccp,rename_new);
if (ccx) strcpy(newfile+ccp+ccn,pext); if (ccx) strcpy(newfile+ccp+ccn,pext);
if (regfile(newfile)) { // check if new name exists if (regfile(newfile)) { // check if new name exists
zmessageACK(Mwin,"output file exists"); zmessageACK(Mwin,"output file exists");
zfree(newfile); zfree(newfile);
newfile = 0; newfile = 0;
return 1; return 1;
} }
if (FGWM == 'F') if (FGWM == 'F')
nextfile = gallery(0,"get",curr_file_posn+1); // save next file, before rename nextfile = gallery(0,"getR",curr_file_posn+1); // save next file, before rename 23.1
else nextfile = 0; else nextfile = 0;
if (Fblock("rename","block edits")) return 1; // check pend, block if (Fblock("rename","block edits")) return 1; // check pend, block
err = rename(rename_file,newfile); // rename the file err = rename(rename_file,newfile); // rename the file
if (err) { if (err) {
zmessageACK(Mwin,"file error: %s",strerror(errno)); zmessageACK(Mwin,"file error: %s",strerror(errno));
Fblock("rename",0); Fblock("rename",0);
goto KILL; goto KILL;
} }
skipping to change at line 764 skipping to change at line 764
} }
Fblock("rename",0); Fblock("rename",0);
zdialog_fetch(zd,"keepopen",Fkeep); zdialog_fetch(zd,"keepopen",Fkeep);
if (Fkeep) { // keep dialog open if (Fkeep) { // keep dialog open
if (FGWM == 'F' && nextfile) { if (FGWM == 'F' && nextfile) {
f_open(nextfile); // will call m_rename() f_open(nextfile); // will call m_rename()
gtk_window_present(MWIN); // keep focus on main window gtk_window_present(MWIN); // keep focus on main window
} }
if (nextfile) zfree(nextfile);
nextfile = 0;
if (newfile) zfree(newfile); if (newfile) zfree(newfile);
newfile = 0; newfile = 0;
return 1; return 1;
} }
else { // close dialog else { // close dialog
f_open(newfile); // open renamed file f_open(newfile); // open renamed file
goto KILL; goto KILL;
} }
KILL: KILL:
if (nextfile) zfree(nextfile);
nextfile = 0;
if (newfile) zfree(newfile); if (newfile) zfree(newfile);
newfile = 0; newfile = 0;
zdialog_free(zd); // kill dialog zdialog_free(zd); // kill dialog
zd_rename = 0; zd_rename = 0;
return 1; return 1;
} }
/******************************************************************************* */ /******************************************************************************* */
// show and change file permissions // show and change file permissions
char *permissions_file = 0; ch *permissions_file = 0;
void m_permissions(GtkWidget *, cchar *menu) void m_permissions(GtkWidget *, ch *menu)
{ {
int permissions_dialog_event(zdialog *zd, cchar *event); int permissions_dialog_event(zdialog *zd, ch *event);
char permissions[100]; ch permissions[100];
cchar *pp; ch *pp;
STATB statB; STATB statB;
int ftype; int ftype;
F1_help_topic = "permissions"; F1_help_topic = "permissions";
Plog(1,"m_permissions \n"); Plog(1,"m_permissions \n");
if (FGWM != 'F' && FGWM != 'G') return; if (FGWM != 'F' && FGWM != 'G') return;
if (permissions_file) zfree(permissions_file); if (permissions_file) zfree(permissions_file);
skipping to change at line 907 skipping to change at line 903
if (pp) zdialog_stuff(zd,"permgrp",pp); if (pp) zdialog_stuff(zd,"permgrp",pp);
pp = substring(permissions,',',3); pp = substring(permissions,',',3);
if (pp) zdialog_stuff(zd,"permoth",pp); if (pp) zdialog_stuff(zd,"permoth",pp);
return; return;
} }
// dialog event and completion callback function // dialog event and completion callback function
int permissions_dialog_event(zdialog *zd, cchar *event) int permissions_dialog_event(zdialog *zd, ch *event)
{ {
int Fkeep; int Fkeep;
mode_t mode; mode_t mode;
char permown[20], permgrp[20], permoth[20]; ch permown[20], permgrp[20], permoth[20];
char permissions[100]; ch permissions[100];
if (strmatch(event,"escape")) zd->zstat = -2; // escape key if (strmatch(event,"escape")) zd->zstat = -2; // escape key
if (zd->zstat == 0) return 1; // wait for dialog finished if (zd->zstat == 0) return 1; // wait for dialog finished
if (zd->zstat != 1) goto KILL; // [cancel] or [x] if (zd->zstat != 1) goto KILL; // [cancel] or [x]
zdialog_fetch(zd,"permown",permown,20); // [apply] zdialog_fetch(zd,"permown",permown,20); // [apply]
zdialog_fetch(zd,"permgrp",permgrp,20); // construct permissions string zdialog_fetch(zd,"permgrp",permgrp,20); // construct permissions string
zdialog_fetch(zd,"permoth",permoth,20); // e.g. "read+write, read only, no access" zdialog_fetch(zd,"permoth",permoth,20); // e.g. "read+write, read only, no access"
snprintf(permissions,100,"%s, %s, %s",permown,permgrp,permoth); snprintf(permissions,100,"%s, %s, %s",permown,permgrp,permoth);
skipping to change at line 948 skipping to change at line 944
return 1; return 1;
} }
/******************************************************************************* */ /******************************************************************************* */
// Remove alpha channel if present // Remove alpha channel if present
// RGB pixels are reduced according to alpha channel value // RGB pixels are reduced according to alpha channel value
// RGBout = RGBin * (alpha/255) // RGBout = RGBin * (alpha/255)
// Transparent margins (e.g. panorama images) will become black. // Transparent margins (e.g. panorama images) will become black.
void m_remove_alpha(GtkWidget *, cchar *) void m_remove_alpha(GtkWidget *, ch *)
{ {
int remove_alpha_dialog_event(zdialog *zd, cchar *event); int remove_alpha_dialog_event(zdialog *zd, ch *event);
int ftype; int ftype;
char *pp; ch *pp;
F1_help_topic = "remove alpha"; F1_help_topic = "remove alpha";
Plog(1,"m_remove_alpha \n"); Plog(1,"m_remove_alpha \n");
if (FGWM != 'F') return; if (FGWM != 'F') return;
if (! curr_file) return; if (! curr_file) return;
ftype = image_file_type(curr_file); ftype = image_file_type(curr_file);
if (ftype != IMAGE) return; if (ftype != IMAGE) return;
skipping to change at line 1020 skipping to change at line 1016
else else
zdialog_stuff(zd,"labpresent","not present"); zdialog_stuff(zd,"labpresent","not present");
zdialog_present(zd); zdialog_present(zd);
return; return;
} }
// dialog event and completion function // dialog event and completion function
int remove_alpha_dialog_event(zdialog *zd, cchar *event) int remove_alpha_dialog_event(zdialog *zd, ch *event)
{ {
int zstat = zd->zstat; int zstat = zd->zstat;
if (! E0pxm) goto KILL; if (! E0pxm) goto KILL;
if (strmatch(event,"escape")) zstat = -2; // escape key if (strmatch(event,"escape")) zstat = -2; // escape key
if (! zstat) return 1; // wait for dialog completion if (! zstat) return 1; // wait for dialog completion
if (zstat == 1) // [remove] if (zstat == 1) // [remove]
skipping to change at line 1072 skipping to change at line 1068
// Fack: failure will cause a popup ACK dialog. // Fack: failure will cause a popup ACK dialog.
// fzoom: keep current zoom level and position, otherwise fit window. // fzoom: keep current zoom level and position, otherwise fit window.
// //
// Following are set: curr_file_type, curr_file_bpc, curr_file_size. // Following are set: curr_file_type, curr_file_bpc, curr_file_size.
// Returns: 0 = OK, +N = error. // Returns: 0 = OK, +N = error.
// errors: 1 reentry // errors: 1 reentry
// 2 curr. edit function cannot be restarted or canceled // 2 curr. edit function cannot be restarted or canceled
// 3 file not found or user cancel // 3 file not found or user cancel
// 4 unsupported file type or PXB_load() failure // 4 unsupported file type or PXB_load() failure
int f_open(cchar *filespec, int Nth, int Fkeep, int Fack, int fzoom) int f_open(ch *filespec, int Nth, int Fkeep, int Fack, int fzoom)
{ {
PXB *tempxb = 0; PXB *tempxb = 0;
int fposn, retcode = 0; int fposn, retcode = 0;
FTYPE ftype; FTYPE ftype;
static int Freent = 0; static int Freent = 0;
char *pp, *file; ch *pp, *file;
void (*editfunc)(GtkWidget *, cchar *); void (*editfunc)(GtkWidget *, ch *);
if (Freent++) { // stop re-entry if (Freent++) { // stop re-entry
Plog(0,"f_open() re-entry \n"); Plog(0,"f_open() re-entry \n");
goto ret1; goto ret1;
} }
poptext_killnow(); // kill pending popup message poptext_killnow(); // kill pending popup message
if (CEF && ! CEF->Frestart) goto ret2; // edit function not restartable if (CEF && ! CEF->Frestart) goto ret2; // edit function not restartable
skipping to change at line 1150 skipping to change at line 1146
curr_file = file; // new current file curr_file = file; // new current file
Fpxb = tempxb; // pixmap for current image Fpxb = tempxb; // pixmap for current image
strcpy(curr_file_type,f_load_type); // set curr_file_xxx from f_load_xxx strcpy(curr_file_type,f_load_type); // set curr_file_xxx from f_load_xxx
curr_file_bpc = f_load_bpc; curr_file_bpc = f_load_bpc;
curr_file_size = f_load_size; curr_file_size = f_load_size;
load_filemeta(curr_file); // load metadata used by fotoxx load_filemeta(curr_file); // load metadata used by fotoxx
Fexif_edithist = 0; // no edit history data loaded Fmeta_edithist = 0; // no edit history data loaded
Fupright = Flevel = 0; // file not uprighted or levelled Fupright = Flevel = 0; // file not uprighted or levelled
if (ftype == RAW) Fupright = 1; // assume RAW loaders do upright if (ftype == RAW) Fupright = 1; // assume RAW loaders do upright
fposn = file_position(file,Nth); // file position in gallery list fposn = file_position(file,Nth); // file position in gallery list
if (fposn < 0) { // not there if (fposn < 0) { // not there
gallery(curr_file,"init",0); // generate new gallery list gallery(curr_file,"init",0); // generate new gallery list
gallery(0,"sort",-2); // recall sort and position gallery(0,"sort",-2); // recall sort and position
gallery(curr_file,"paint",0); // position at curr. file gallery(curr_file,"paint",0); // position at curr. file
fposn = file_position(curr_file,0); // position and count in gallery list fposn = file_position(curr_file,0); // position and count in gallery list
skipping to change at line 1176 skipping to change at line 1172
zoomx = zoomy = 0; // no zoom center zoomx = zoomy = 0; // no zoom center
} }
add_recent_file(curr_file); // most recent file opened add_recent_file(curr_file); // most recent file opened
if (zd_rename) m_rename(0,0); // update active rename dialog if (zd_rename) m_rename(0,0); // update active rename dialog
if (zd_permissions) m_permissions(0,0); // " permissions dialog if (zd_permissions) m_permissions(0,0); // " permissions dialog
if (zd_remove_alpha) m_remove_alpha(0,0); // " remove_alpha dialog if (zd_remove_alpha) m_remove_alpha(0,0); // " remove_alpha dialog
if (zd_copymove) m_copy_move(0,0); // " copy/move dialog if (zd_copymove) m_copy_move(0,0); // " copy/move dialog
if (zd_deltrash) m_delete_trash(0,0); // " delete/trash dialog if (zd_deltrash) m_delete_trash(0,0); // " delete/trash dialog
if (zd_metaview) meta_view(0); // " EXIF/IPTC data view window if (zd_metaview) meta_view(0); // " metadata view window
if (zd_editmeta) m_meta_edit_main(0,0); // " edit metadata dialog if (zd_editmeta) m_meta_edit_main(0,0); // " edit metadata dialog
if (zd_editanymeta) m_meta_edit_any(0,0); // " edit any metadata dialog if (zd_editanymeta) m_meta_edit_any(0,0); // " edit any metadata dialog
if (zd_deletemeta) m_meta_delete(0,0); // " delete metadata dialog if (zd_deletemeta) m_meta_delete(0,0); // " delete metadata dialog
if (Fcaps) meta_show_caps(1); // show captions on current image if (Fcaps) meta_show_caps(1); // show captions on current image
if (editfunc) editfunc(0,0); // restart edit function if (editfunc) editfunc(0,0); // restart edit function
if (ftype == VIDEO) // offer to play video file if (ftype == VIDEO) // offer to play video file
zmessage_post_bold(Mwin,"20/30",3,"VIDEO press P to play"); zmessage_post_bold(Mwin,"20/30",3,"VIDEO press P to play");
skipping to change at line 1246 skipping to change at line 1242
} }
curr_file_posn = fposn; // keep track of file position curr_file_posn = fposn; // keep track of file position
strcpy(curr_file_type,f_save_type); // set curr_file_xxx from f_save_xxx strcpy(curr_file_type,f_save_type); // set curr_file_xxx from f_save_xxx
curr_file_bpc = f_save_bpc; curr_file_bpc = f_save_bpc;
curr_file_size = f_save_size; curr_file_size = f_save_size;
zoomx = zoomy = 0; // no zoom center zoomx = zoomy = 0; // no zoom center
if (FGWM == 'F') set_mwin_title(); // set win title from curr_file info if (FGWM == 'F') set_mwin_title(); // set win title from curr_file info
if (zd_metaview) meta_view(0); // update EXIF/IPTC view window if (zd_metaview) meta_view(0); // update meta view window
return 0; return 0;
} }
/******************************************************************************* * /******************************************************************************* *
Remove a file and clean up index, thumbnails, gallery, curr_file. Remove a file and clean up index, thumbnails, gallery, curr_file.
Albums must be handled separately via album_purge_replace(). Albums must be handled separately via album_purge_replace().
'opt' is "delete" or "trash". 'opt' is "delete" or "trash".
trash logic: Move target file to ~/Desktop/ first, then move to trash. trash logic: Move target file to ~/Desktop/ first, then move to trash.
Gnome trash fails for files on mounted volumes. Gnome trash fails for files on mounted volumes.
Returns 0 if OK, else error code. Returns 0 if OK, else error code.
****/ ****/
int f_remove(cchar *file, cchar *opt) int f_remove(ch *file, ch *opt)
{ {
int err, Nth; int err, Nth;
char *currfile = 0; ch *cfile = 0;
char trashfile[400] = "~/Desktop/"; ch trashfile[400] = "~/Desktop/";
cchar *pp; ch *pp;
GFile *gfile; GFile *gfile;
GError *gerror = 0; GError *gerror = 0;
int gstat; int gstat;
if (*opt == 'd') // delete if (*opt == 'd') // delete
{ {
err = remove(file); err = remove(file);
if (err && errno != ENOENT) { // OK if already deleted if (err && errno != ENOENT) { // OK if already deleted
zmessageACK(Mwin,"delete %s \n %s",file,strerror(errno)); zmessageACK(Mwin,"delete %s \n %s",file,strerror(errno));
return err; return err;
skipping to change at line 1318 skipping to change at line 1314
} }
delete_image_index(file); // delete file in image index delete_image_index(file); // delete file in image index
delete_thumbfile(file); // delete thumbnail file and cache delete_thumbfile(file); // delete thumbnail file and cache
Nth = file_position(file,0); // find in gallery list Nth = file_position(file,0); // find in gallery list
if (Nth >= 0) gallery(0,"delete",Nth); // delete from gallery list if (Nth >= 0) gallery(0,"delete",Nth); // delete from gallery list
if (curr_file && strmatch(file,curr_file)) { // current file was removed if (curr_file && strmatch(file,curr_file)) { // current file was removed
free_resources(); free_resources();
currfile = gallery(0,"get",curr_file_posn); cfile = gallery(0,"getR",curr_file_posn);
// new current file = next // new current file = next 23.1
if (currfile) { if (cfile) f_open(cfile);
f_open(currfile);
zfree(currfile);
}
else { else {
Nth = curr_file_posn - 1; Nth = curr_file_posn - 1;
if (Nth >= navi::Gfolders && Nth < navi::Gfiles) { // no next, try previous 22.35 if (Nth >= navi::Gfolders && Nth < navi::Gfiles) { // no next, try previous 22.35
currfile = gallery(0,"get",curr_file_posn - 1); cfile = gallery(0,"getR",curr_file_posn - 1);
if (currfile) { // 23.1
f_open(currfile); if (cfile) f_open(cfile);
zfree(currfile);
}
} }
} }
} }
if (! currfile && FGWM == 'F') m_blank_window(0,0); // 22.35 if (! cfile && FGWM == 'F') m_blank_window(0,0); // 22.35
return 0; return 0;
} }
/******************************************************************************* */ /******************************************************************************* */
// Function to preload image files hopefully ahead of need. // Function to preload image files hopefully ahead of need.
// Usage: f_preload(next) // Usage: f_preload(next)
// next = -1 / +1 to read previous / next image file in curr. gallery // next = -1 / +1 to read previous / next image file in curr. gallery
// preload_file will be non-zero if and when preload_pxb is available. // preload_file will be non-zero if and when preload_pxb is available.
void f_preload(int next, int Flast) void f_preload(int next, int Flast)
{ {
int fd; int fd;
char *file; ch *file;
if (! curr_file) return; if (! curr_file) return;
file = prev_next_file(next,Flast); file = prev_next_file(next,Flast);
if (! file) return; if (! file) return;
if (strmatch(file,curr_file)) { if (strmatch(file,curr_file)) return;
zfree(file);
return;
}
fd = open(file,O_RDONLY); fd = open(file,O_RDONLY);
if (fd >= 0) { if (fd >= 0) {
posix_fadvise(fd,0,0,POSIX_FADV_WILLNEED); // preload file in kernel cache posix_fadvise(fd,0,0,POSIX_FADV_WILLNEED); // preload file in kernel cache
close(fd); close(fd);
} }
zfree(file);
return; return;
} }
/******************************************************************************* */ /******************************************************************************* */
// Open previous or next file in current gallery list, // Open previous or next file in current gallery list,
// or jump to previous or next gallery when at the limits. // or jump to previous or next gallery when at the limits.
// index is -1 / +1 for prev / next file. // index is -1 / +1 for prev / next file.
// Fjump: jump to last file version, jump to prev/next folder. // Fjump: jump to last file version, jump to prev/next folder.
void x_prev_next(int index, int Fjump) void x_prev_next(int index, int Fjump)
{ {
using namespace navi; using namespace navi;
char *newfile = 0, *newgallery = 0; ch *newfile = 0, *newgallery = 0;
int err, Nth = 0; int err, Nth = 0;
static int xbusy = 0, jumpswitch = 0; static int xbusy = 0, jumpswitch = 0;
static zdialog *zd = 0; static zdialog *zd = 0;
cchar *mess1 = "Previous gallery"; ch *mess1 = "Previous gallery";
cchar *mess2 = "Next gallery"; ch *mess2 = "Next gallery";
cchar *mess3 = "Start of gallery"; ch *mess3 = "Start of gallery";
cchar *mess4 = "End of gallery"; ch *mess4 = "End of gallery";
if (! curr_file) return; if (! curr_file) return;
if (FGWM != 'F' && FGWM != 'G') return; if (FGWM != 'F' && FGWM != 'G') return;
if (zd && zdialog_valid2(zd,"post")) zdialog_free(zd); // clear prior popup message if (zd && zdialog_valid2(zd,"post")) zdialog_free(zd); // clear prior popup message
zd = 0; zd = 0;
if (Fblock(0,"blocked edits")) return; // check nothing pending if (Fblock(0,"blocked edits")) return; // check nothing pending
if (xbusy) return; // avoid "function busy" if (xbusy) return; // avoid "function busy"
skipping to change at line 1427 skipping to change at line 1413
if (index == -1) zd = zmessage_post_bold(Mwin,"5/5",3,mess3,0); // notify gallery start/end if (index == -1) zd = zmessage_post_bold(Mwin,"5/5",3,mess3,0); // notify gallery start/end
if (index == +1) zd = zmessage_post_bold(Mwin,"5/5",3,mess4,0); if (index == +1) zd = zmessage_post_bold(Mwin,"5/5",3,mess4,0);
jumpswitch = 0; jumpswitch = 0;
} }
if (Fjump && jumpswitch) { // jump to prev/next gallery if (Fjump && jumpswitch) { // jump to prev/next gallery
jumpswitch = 0; jumpswitch = 0;
newgallery = prev_next_gallery(index); newgallery = prev_next_gallery(index);
if (! newgallery) goto returnx; if (! newgallery) goto returnx;
gallery(newgallery,"init",0); // load gallery gallery(newgallery,"init",0); // load gallery
zfree(newgallery);
gallery(0,"sort",-2); // preserve sort gallery(0,"sort",-2); // preserve sort
if (Gfiles - Gfolders > 0) { // at least one image file present if (Gfiles - Gfolders > 0) { // at least one image file present
if (index == +1) Nth = Gfolders; // get first or last image file if (index == +1) Nth = Gfolders; // get first or last image file
if (index == -1) Nth = Gfiles - 1; if (index == -1) Nth = Gfiles - 1;
newfile = gallery(0,"get",Nth); newfile = gallery(0,"getR",Nth); // 23.1
err = f_open(newfile,Nth,0,1,0); // open image or RAW file err = f_open(newfile,Nth,0,1,0); // open image or RAW file
if (! err) gallery(newfile,"paint",Nth); if (! err) gallery(newfile,"paint",Nth);
if (! err) f_preload(index,Fjump); // preload next image if (! err) f_preload(index,Fjump); // preload next image
goto returnx; goto returnx;
} }
else { // no image files in gallery else { // no image files in gallery
gallery(0,"paint",0); gallery(0,"paint",0);
m_viewmode(0,"G"); m_viewmode(0,"G");
free_resources(); free_resources();
} }
} }
else if (Fjump) jumpswitch = 1; // hesitate once, jump next time else if (Fjump) jumpswitch = 1; // hesitate once, jump next time
returnx: returnx:
if (newfile) zfree(newfile);
if (newgallery) zfree(newgallery);
zmainloop(); // refresh window (holding arrow key) zmainloop(); // refresh window (holding arrow key)
xbusy = 0; xbusy = 0;
return; return;
} }
void m_prev(GtkWidget *, cchar *menu) void m_prev(GtkWidget *, ch *menu)
{ {
Plog(1,"m_prev \n"); Plog(1,"m_prev \n");
if (menu) x_prev_next(-1,1); // jump option if (menu) x_prev_next(-1,1); // jump option
else x_prev_next(-1,0); // search from curr_file -1 else x_prev_next(-1,0); // search from curr_file -1
return; // to first file return; // to first file
} }
void m_next(GtkWidget *, cchar *menu) void m_next(GtkWidget *, ch *menu)
{ {
Plog(1,"m_next \n"); Plog(1,"m_next \n");
if (menu) x_prev_next(+1,1); // jump option if (menu) x_prev_next(+1,1); // jump option
else x_prev_next(+1,0); // search from curr_file +1 else x_prev_next(+1,0); // search from curr_file +1
return; // to last file return; // to last file
} }
void m_prev_next(GtkWidget *, cchar *menu) // left/right mouse click >> void m_prev_next(GtkWidget *, ch *menu) // left/right mouse click >>
{ // previous/next image file { // previous/next image file
int button = zfuncs::vmenuclickbutton; int button = zfuncs::vmenuclickbutton;
if (button == 1) m_prev(0,0); if (button == 1) m_prev(0,0);
else m_next(0,0); else m_next(0,0);
return; return;
} }
/******************************************************************************* */ /******************************************************************************* */
// zoom in/out - left/right mouse click on zoom button or F-view image // zoom in/out - left/right mouse click on zoom button or F-view image
void m_zoom_menu(GtkWidget *, cchar *menu) // left/right mouse click void m_zoom_menu(GtkWidget *, ch *menu) // left/right mouse click
{ {
F1_help_topic = "zoom"; F1_help_topic = "zoom";
int button = zfuncs::vmenuclickbutton; int button = zfuncs::vmenuclickbutton;
if (FGWM == 'G') { // G view, larger/smaller thumbnails if (FGWM == 'G') { // G view, larger/smaller thumbnails
if (button == 1) navi::menufuncx(0,"Zoom+"); if (button == 1) navi::menufuncx(0,"Zoom+");
else navi::menufuncx(0,"Zoom-"); else navi::menufuncx(0,"Zoom-");
} }
skipping to change at line 1505 skipping to change at line 1490
else m_zoom(0,"Zoom-"); else m_zoom(0,"Zoom-");
} }
return; return;
} }
/******************************************************************************* */ /******************************************************************************* */
// create a new blank image file with desired background color // create a new blank image file with desired background color
void m_blank_image(GtkWidget *, cchar *pname) void m_blank_image(GtkWidget *, ch *pname)
{ {
char color[20], fname[100], fext[8], *filespec; ch color[20], fname[100], fext[8], *filespec;
int zstat, err, cc, ww, hh, RGB[3]; int zstat, err, cc, ww, hh, RGB[3];
zdialog *zd; zdialog *zd;
cchar *pp; ch *pp;
char *curr_folder = 0; ch *curr_folder = 0;
F1_help_topic = "blank image"; F1_help_topic = "blank image";
Plog(1,"m_blank_image \n"); Plog(1,"m_blank_image \n");
if (navi::gallerytype == FOLDER) curr_folder = navi::galleryname; if (navi::gallerytype == FOLDER) curr_folder = navi::galleryname;
else curr_folder = topfolders[0]; else curr_folder = topfolders[0];
if (! curr_folder) { if (! curr_folder) {
Plog(0,"no top image folders defined \n"); // should not happen Plog(0,"no top image folders defined \n"); // should not happen
return; return;
skipping to change at line 1618 skipping to change at line 1603
Fblock("blank_image",0); Fblock("blank_image",0);
return; return;
} }
// function to create a new blank image file // function to create a new blank image file
// file extension must be one of: .jpg .tif .png // file extension must be one of: .jpg .tif .png
// RGB args are in the range 0 - 255 // RGB args are in the range 0 - 255
// if file exists it is overwritten // if file exists it is overwritten
// returns 0 if OK, 1 if file exists, +N if error // returns 0 if OK, 1 if file exists, +N if error
int create_blank_file(cchar *file, int ww, int hh, int RGB[3]) int create_blank_file(ch *file, int ww, int hh, int RGB[3])
{ {
cchar *pp; ch *pp;
cchar *fext; ch *fext;
int cstat; int cstat;
PXB *tempxb; PXB *tempxb;
GError *gerror = 0; GError *gerror = 0;
uint8 *pixel; uint8 *pixel;
if (regfile(file)) { if (regfile(file)) {
zmessageACK(Mwin,"output file exists"); // file already exists zmessageACK(Mwin,"output file exists"); // file already exists
return 1; return 1;
} }
skipping to change at line 1666 skipping to change at line 1651
} }
PXB_free(tempxb); PXB_free(tempxb);
return 0; return 0;
} }
/******************************************************************************* */ /******************************************************************************* */
// blank or restore window // blank or restore window
void m_blank_window(GtkWidget *, cchar *menu) void m_blank_window(GtkWidget *, ch *menu)
{ {
static int Fblank = 0; static int Fblank = 0;
static char *savefile = 0; static ch *savefile = 0;
F1_help_topic = "blank window"; F1_help_topic = "blank window";
Plog(1,"m_blank_window \n"); Plog(1,"m_blank_window \n");
if (FGWM != 'F') m_viewmode(0,"F"); // insure file view mode if (FGWM != 'F') m_viewmode(0,"F"); // insure file view mode
if (Fblock("blank_window","block edits")) return; // check pend, block if (Fblock("blank_window","block edits")) return; // check pend, block
if (! Fblank) if (! Fblank)
skipping to change at line 1703 skipping to change at line 1688
Fblank = 1 - Fblank; Fblank = 1 - Fblank;
Fblock("blank_window",0); Fblock("blank_window",0);
return; return;
} }
/******************************************************************************* */ /******************************************************************************* */
// animate given GIF file if possible // animate given GIF file if possible
void play_gif(cchar *file) void play_gif(ch *file)
{ {
int gif_animations_dialog_event(zdialog *, cchar *event); int gif_animations_dialog_event(zdialog *, ch *event);
FILE *fid; FILE *fid;
char command[300], buff[20] = "", *pp = 0; ch command[300], buff[20] = "", *pp = 0;
zdialog *zd; zdialog *zd;
GtkWidget *image; GtkWidget *image;
GdkPixbufAnimation *animation; GdkPixbufAnimation *animation;
snprintf(command,300,"exiftool -s3 -framecount \"%s\"",file); snprintf(command,300,"exiftool -s3 -framecount \"%s\"",file);
fid = popen(command,"r"); fid = popen(command,"r");
if (fid) { if (fid) {
pp = fgets(buff,20,fid); pp = fgets(buff,20,fid);
pclose(fid); pclose(fid);
} }
skipping to change at line 1734 skipping to change at line 1719
animation = gdk_pixbuf_animation_new_from_file(curr_file,0); animation = gdk_pixbuf_animation_new_from_file(curr_file,0);
gtk_image_set_from_animation(GTK_IMAGE(image),animation); gtk_image_set_from_animation(GTK_IMAGE(image),animation);
zdialog_run(zd,gif_animations_dialog_event,"desktop"); zdialog_run(zd,gif_animations_dialog_event,"desktop");
zdialog_can_focus(zd,0); zdialog_can_focus(zd,0);
return; return;
} }
// dialog event and completion function // dialog event and completion function
int gif_animations_dialog_event(zdialog *zd, cchar *event) int gif_animations_dialog_event(zdialog *zd, ch *event)
{ {
if (strmatch(event,"escape")) zd->zstat = -2; // escape key if (strmatch(event,"escape")) zd->zstat = -2; // escape key
if (zd->zstat) zdialog_free(zd); if (zd->zstat) zdialog_free(zd);
return 1; return 1;
} }
/******************************************************************************* */ /******************************************************************************* */
// copy or move an image file to a new location // copy or move an image file to a new location
namespace copymove_names namespace copymove_names
{ {
char *sorcfile = 0; ch *sorcfile = 0;
// source file full name // source file full name
char *destname = 0; ch *destname = 0;
// destination file base name // destination file base name
char *destfile = 0; ch *destfile = 0;
// destination file full name // destination file full name
char *nextfile = 0; ch *nextfile = 0;
// next file in source gallery // next file in source gallery
} }
// menu function // menu function
void m_copy_move(GtkWidget *, cchar *) // overhauled 22.14 void m_copy_move(GtkWidget *, ch *) // overhauled 22.14
{ {
using namespace copymove_names; using namespace copymove_names;
int copymove_dialog_event(zdialog *zd, cchar *event); int copymove_dialog_event(zdialog *zd, ch *event);
cchar *title = "Copy or Move Image File"; ch *title = "Copy or Move Image File";
char *pp; ch *pp;
F1_help_topic = "copy/move"; F1_help_topic = "copy/move";
Plog(1,"m_copy_move \n"); Plog(1,"m_copy_move \n");
if (sorcfile) zfree(sorcfile); if (sorcfile) zfree(sorcfile);
sorcfile = 0; sorcfile = 0;
if (clicked_file) { // use clicked file if present if (clicked_file) { // use clicked file if present
sorcfile = clicked_file; sorcfile = clicked_file;
skipping to change at line 1864 skipping to change at line 1849
return; return;
} }
if (copymove_loc) zdialog_stuff(zd,"copymove_loc",copymove_loc); // last used copy-to location 22.18 if (copymove_loc) zdialog_stuff(zd,"copymove_loc",copymove_loc); // last used copy-to location 22.18
return; return;
} }
// dialog event and completion callback function // dialog event and completion callback function
int copymove_dialog_event(zdialog *zd, cchar *event) int copymove_dialog_event(zdialog *zd, ch *event)
{ {
using namespace copymove_names; using namespace copymove_names;
int Fcopy, Fmove, Fnext; int Fcopy, Fmove, Fnext;
char *pp, *pext; ch *pp, *pext;
char copyloc[XFCC]; ch copyloc[XFCC];
int cc, err, Fkeep, Nth; int cc, err, Fkeep, Nth;
if (strmatch(event,"escape")) zd->zstat = -2; // escape key if (strmatch(event,"escape")) zd->zstat = -2; // escape key
if (strmatch(event,"Browse")) { // browse for new location if (strmatch(event,"Browse")) { // browse for new location
pp = zgetfile("Select folder",MWIN,"folder",copymove_loc); pp = zgetfile("Select folder",MWIN,"folder",copymove_loc);
if (! pp) return 1; if (! pp) return 1;
if (copymove_loc) zfree(copymove_loc); // save new copymove location 22.18 if (copymove_loc) zfree(copymove_loc); // save new copymove location 22.18
copymove_loc = pp; copymove_loc = pp;
zdialog_stuff(zd,"copymove_loc",copymove_loc); zdialog_stuff(zd,"copymove_loc",copymove_loc);
skipping to change at line 1918 skipping to change at line 1903
zdialog_fetch(zd,"copymove_loc",copyloc,XFCC); // get move-to location from dialog zdialog_fetch(zd,"copymove_loc",copyloc,XFCC); // get move-to location from dialog
if (! dirfile(copyloc)) { // check for valid folder if (! dirfile(copyloc)) { // check for valid folder
zmessageACK(Mwin,"new location is not a folder"); zmessageACK(Mwin,"new location is not a folder");
return 1; return 1;
} }
zstrcopy(copymove_loc,copyloc,"copy-move"); // save new copymove location 22.18 zstrcopy(copymove_loc,copyloc,"copy-move"); // save new copymove location 22.18
if (destname) zfree(destname); if (destname) zfree(destname);
destname = (char *) zmalloc(200,"copy-move"); // get dest file name destname = (ch *) zmalloc(200,"copy-move"); // get dest file name
zdialog_fetch(zd,"destname",destname,190); zdialog_fetch(zd,"destname",destname,190);
if (*destname <= ' ' || strchr(destname,'/')) { // 22.18 if (*destname <= ' ' || strchr(destname,'/')) { // 22.18
zmessageACK(Mwin,"new file name is invalid"); zmessageACK(Mwin,"new file name is invalid");
return 1; return 1;
} }
pext = strrchr(destname,'.'); // find dest file .ext pext = strrchr(destname,'.'); // find dest file .ext
if (! pext || strlen(pext) > 8) if (! pext || strlen(pext) > 8)
pext = destname + strlen(destname); // try to skip over '.' in file name pext = destname + strlen(destname); // try to skip over '.' in file name
if (strlen(pext) > 3 && pext[1] == 'v') if (strlen(pext) > 3 && pext[1] == 'v')
pext = destname + strlen(destname); // try to skip over version number pext = destname + strlen(destname); // try to skip over version number
*pext = 0; *pext = 0;
pp = strrchr(sorcfile,'.'); pp = strrchr(sorcfile,'.');
if (pp && strlen(pp) < 9) strcpy(pext,pp); // copy source file .ext to dest file if (pp && strlen(pp) < 9) strcpy(pext,pp); // copy source file .ext to dest file
cc = strlen(copymove_loc) + strlen(destname) + 2; // new file = copymove_loc/destname.ext cc = strlen(copymove_loc) + strlen(destname) + 2; // new file = copymove_loc/destname.ext
if (destfile) zfree(destfile); if (destfile) zfree(destfile);
destfile = (char *) zmalloc(cc,"copy-move"); destfile = (ch *) zmalloc(cc,"copy-move");
*destfile = 0; *destfile = 0;
strncatv(destfile,cc,copymove_loc,"/",destname,0); strncatv(destfile,cc,copymove_loc,"/",destname,0);
if (strmatch(sorcfile,destfile)) { // block copy to self if (strmatch(sorcfile,destfile)) { // block copy to self
zmessageACK(Mwin,"cannot copy a file to itself"); zmessageACK(Mwin,"cannot copy a file to itself");
return 1; return 1;
} }
if (regfile(destfile)) { // if new file exists if (regfile(destfile)) { // if new file exists
int yn = zmessageYN(Mwin,"output file exists, overwrite?"); // optionally overwrite file int yn = zmessageYN(Mwin,"output file exists, overwrite?"); // optionally overwrite file
skipping to change at line 2021 skipping to change at line 2006
} }
else gtk_window_present(MWIN); // keep focus on main window else gtk_window_present(MWIN); // keep focus on main window
return 1; return 1;
} }
/******************************************************************************* */ /******************************************************************************* */
// copy selected image file to the desktop // copy selected image file to the desktop
void m_copyto_desktop(GtkWidget *, cchar *) void m_copyto_desktop(GtkWidget *, ch *)
{ {
char *file, *pp, newfile[XFCC]; ch *file, *pp, newfile[XFCC];
int err; int err;
F1_help_topic = "copy to desktop"; F1_help_topic = "copy to desktop";
Plog(1,"m_copyto_desktop \n"); Plog(1,"m_copyto_desktop \n");
if (FGWM != 'F' && FGWM != 'G') return; if (FGWM != 'F' && FGWM != 'G') return;
file = clicked_file; file = clicked_file;
if (! file) file = curr_file; if (! file) file = curr_file;
if (! file) return; if (! file) return;
snprintf(newfile,100,"%s/%s",getenv("HOME"),desktopname); // locale specific desktop name snprintf(newfile,XFCC,"%s/%s",getenv("HOME"),desktopname); // locale specific desktop name
pp = strrchr(file,'/'); pp = strrchr(file,'/');
if (! pp) return; if (! pp) return;
strncatv(newfile,XFCC,pp,0); // new desktop file name strncatv(newfile,XFCC,pp,0); // new desktop file name
if (regfile(newfile)) { // check if file exists if (regfile(newfile)) { // check if file exists
int yn = zmessageYN(Mwin,"output file exists, overwrite?"); // confirm overwrite int yn = zmessageYN(Mwin,"output file exists, overwrite?"); // confirm overwrite
if (! yn) goto cleanup; if (! yn) goto cleanup;
} }
if (curr_file && strmatch(file,curr_file) // current file is copied if (curr_file && strmatch(file,curr_file) // current file is copied
skipping to change at line 2070 skipping to change at line 2055
cleanup: cleanup:
if (clicked_file) zfree(clicked_file); if (clicked_file) zfree(clicked_file);
clicked_file = 0; clicked_file = 0;
return; return;
} }
/******************************************************************************* */ /******************************************************************************* */
// copy selected image file to the clipboard // copy selected image file to the clipboard
void m_copyto_clip(GtkWidget *, cchar *) void m_copyto_clip(GtkWidget *, ch *)
{ {
int file_copytoclipboard(char *file); int file_copytoclipboard(ch *file);
char tempfile[200]; ch tempfile[200];
int err; int err;
F1_help_topic = "copy to clipboard"; F1_help_topic = "copy to clipboard";
Plog(1,"m_copyto_clip \n"); Plog(1,"m_copyto_clip \n");
if (FGWM != 'F' && FGWM != 'G') return; if (FGWM != 'F' && FGWM != 'G') return;
if (clicked_file) { if (clicked_file) {
file_copytoclipboard(clicked_file); // get file behind thumbnail file_copytoclipboard(clicked_file); // get file behind thumbnail
skipping to change at line 2111 skipping to change at line 2096
remove(tempfile); remove(tempfile);
return; return;
} }
// copy an image file to the clipboard (as pixbuf) // copy an image file to the clipboard (as pixbuf)
// any prior clipboard image is replaced // any prior clipboard image is replaced
// supports copy/paste to other apps (not used within fotoxx) // supports copy/paste to other apps (not used within fotoxx)
// returns 1 if OK, else 0 // returns 1 if OK, else 0
int file_copytoclipboard(char *file) int file_copytoclipboard(ch *file)
{ {
GtkClipboard *clipboard; GtkClipboard *clipboard;
PIXBUF *pixbuf; PIXBUF *pixbuf;
GError *gerror = 0; GError *gerror = 0;
pixbuf = gdk_pixbuf_new_from_file(file,&gerror); pixbuf = gdk_pixbuf_new_from_file(file,&gerror);
if (! pixbuf) return 0; if (! pixbuf) return 0;
clipboard = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD); clipboard = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD);
if (! clipboard) return 0; if (! clipboard) return 0;
skipping to change at line 2138 skipping to change at line 2123
g_object_unref(pixbuf); g_object_unref(pixbuf);
return 1; return 1;
} }
/******************************************************************************* */ /******************************************************************************* */
// Delete or Trash an image file. // Delete or Trash an image file.
// Use the Linux standard trash function. // Use the Linux standard trash function.
// If not available, show diagnostic and do nothing. // If not available, show diagnostic and do nothing.
char *deltrash_file = 0; ch *deltrash_file = 0;
void m_delete_trash(GtkWidget *, cchar *) // combined delete/trash function void m_delete_trash(GtkWidget *, ch *) // combined delete/trash function
{ {
int delete_trash_dialog_event(zdialog *zd, cchar *event); int delete_trash_dialog_event(zdialog *zd, ch *event);
cchar *title = "Delete/Trash Image File"; ch *title = "Delete/Trash Image File";
F1_help_topic = "delete/trash"; F1_help_topic = "delete/trash";
Plog(1,"m_delete_trash \n"); Plog(1,"m_delete_trash \n");
if (FGWM != 'F' && FGWM != 'G') return; if (FGWM != 'F' && FGWM != 'G') return;
if (deltrash_file) zfree(deltrash_file); if (deltrash_file) zfree(deltrash_file);
deltrash_file = 0; deltrash_file = 0;
skipping to change at line 2194 skipping to change at line 2179
zdialog_add_widget(zd,"hbox","hb2","dialog",0,"space=3"); zdialog_add_widget(zd,"hbox","hb2","dialog",0,"space=3");
zdialog_add_widget(zd,"check","keepopen","hb2","keep this dialog open","sp ace=3"); zdialog_add_widget(zd,"check","keepopen","hb2","keep this dialog open","sp ace=3");
zdialog_resize(zd,300,0); zdialog_resize(zd,300,0);
zdialog_restore_inputs(zd); zdialog_restore_inputs(zd);
zdialog_run(zd,delete_trash_dialog_event,"parent"); // run dialog zdialog_run(zd,delete_trash_dialog_event,"parent"); // run dialog
} }
if (deltrash_file) if (deltrash_file)
{ {
char *pp = strrchr(deltrash_file,'/'); ch *pp = strrchr(deltrash_file,'/');
if (pp) pp++; if (pp) pp++;
else pp = deltrash_file; else pp = deltrash_file;
zdialog_stuff(zd_deltrash,"file",pp); zdialog_stuff(zd_deltrash,"file",pp);
if (FGWM == 'G') f_open(deltrash_file,0,0,1,0); // show or highlight gallery 22.18 if (FGWM == 'G') f_open(deltrash_file,0,0,1,0); // show or highlight gallery 22.18
} }
else zdialog_stuff(zd_deltrash,"file",""); else zdialog_stuff(zd_deltrash,"file","");
return; return;
} }
// dialog event and completion callback function // dialog event and completion callback function
int delete_trash_dialog_event(zdialog *zd, cchar *event) int delete_trash_dialog_event(zdialog *zd, ch *event)
{ {
int err = 0, yn = 0; int err = 0, yn = 0;
int ftype, Fkeep; int ftype, Fkeep;
STATB statB; STATB statB;
cchar *opt = 0; ch *opt = 0;
char *pp; ch *pp;
if (strmatch(event,"escape")) zd->zstat = -2; // escape key if (strmatch(event,"escape")) zd->zstat = -2; // escape key
if (zd->zstat == 0) return 1; // wait for dialog finished if (zd->zstat == 0) return 1; // wait for dialog finished
if (zd->zstat == 1) goto PREP; // [delete] button if (zd->zstat == 1) goto PREP; // [delete] button
if (zd->zstat == 2) goto PREP; // [trash] button if (zd->zstat == 2) goto PREP; // [trash] button
goto EXIT; // [cancel] or [x] goto EXIT; // [cancel] or [x]
PREP: PREP:
skipping to change at line 2286 skipping to change at line 2271
gallery(0,"sort",-2); // recall sort and position gallery(0,"sort",-2); // recall sort and position
gallery(0,"paint",-1); // paint gallery(0,"paint",-1); // paint
} }
if (FGWM == 'F') m_next(0,0); // file view mode, open next image if (FGWM == 'F') m_next(0,0); // file view mode, open next image
zdialog_fetch(zd,"keepopen",Fkeep); // keep going if wanted zdialog_fetch(zd,"keepopen",Fkeep); // keep going if wanted
if (! Fkeep) goto EXIT; if (! Fkeep) goto EXIT;
zd->zstat = 0; // keep dialog active zd->zstat = 0; // keep dialog active
gtk_window_present(MWIN); // keep focus on main window 22.14 gtk_window_present(MWIN); // keep focus on main window 22.14
zdialog_stuff(zd_deltrash,"file",""); // set no next file in dialog zdialog_stuff(zd_deltrash,"file",""); // set no next file in dialog
if (deltrash_file) zfree(deltrash_file); if (deltrash_file) zfree(deltrash_file);
deltrash_file = 0; deltrash_file = 0;
if (! curr_file) goto EXIT; // no current file if (! curr_file) goto EXIT; // no current file
deltrash_file = zstrdup(curr_file,"delete-trash"); // default delete new current file 22.30 deltrash_file = zstrdup(curr_file,"delete-trash"); // default delete new current file 22.30
pp = strrchr(deltrash_file,'/'); pp = strrchr(deltrash_file,'/');
if (pp) pp++; if (pp) pp++;
skipping to change at line 2321 skipping to change at line 2306
/******************************************************************************* */ /******************************************************************************* */
// Select an Adobe document file and convert all pages into jpeg image files. // Select an Adobe document file and convert all pages into jpeg image files.
// The image files are named InputFileName-N.jpg where N is the page number. // The image files are named InputFileName-N.jpg where N is the page number.
// File types recognized: // File types recognized:
// .pdf portable document format // .pdf portable document format
// .ps .eps postscript // .ps .eps postscript
// .psd photoshop image file // .psd photoshop image file
void m_convert_adobe(GtkWidget *, cchar *) // 22.20 void m_convert_adobe(GtkWidget *, ch *) // 22.20
{ {
char *pp, *infile = 0, *outfile = 0; ch *pp, *infile = 0, *outfile = 0;
zdialog *zd = 0; zdialog *zd = 0;
int err; int err;
F1_help_topic = "convert adobe"; F1_help_topic = "convert adobe";
Plog(1,"convert adobe \n"); Plog(1,"convert adobe \n");
if (Fblock(0,"blocked edits")) return; // check nothing pending if (Fblock(0,"blocked edits")) return; // check nothing pending
pp = 0; pp = 0;
skipping to change at line 2397 skipping to change at line 2382
if (zd) zdialog_free(zd); if (zd) zdialog_free(zd);
if (infile) zfree(infile); if (infile) zfree(infile);
if (outfile) zfree(outfile); if (outfile) zfree(outfile);
return; return;
} }
/******************************************************************************* */ /******************************************************************************* */
// set current file as desktop wallpaper (GNOME only) // set current file as desktop wallpaper (GNOME only)
void m_wallpaper(GtkWidget *, cchar *) void m_wallpaper(GtkWidget *, ch *)
{ {
cchar * key = "gsettings set org.gnome.desktop.background"; ch * key = "gsettings set org.gnome.desktop.background";
cchar * id = "picture-uri"; ch * id = "picture-uri";
F1_help_topic = "set wallpaper"; F1_help_topic = "set wallpaper";
Plog(1,"m_wallpaper \n"); Plog(1,"m_wallpaper \n");
if (! curr_file) return; if (! curr_file) return;
zshell("ack","%s %s \"file://%s\" ",key,id,curr_file); zshell("ack","%s %s \"file://%s\" ",key,id,curr_file);
return; return;
} }
/******************************************************************************* */ /******************************************************************************* */
// print image file // print image file
void m_print(GtkWidget *, cchar *) // use GTK print void m_print(GtkWidget *, ch *) // use GTK print
{ {
int print_addgrid(PXB *Ppxb); int print_addgrid(PXB *Ppxb);
int pstat; int pstat;
char *printfile = 0; ch *printfile = 0;
PXB *Ppxb = 0; PXB *Ppxb = 0;
GError *gerror = 0; GError *gerror = 0;
F1_help_topic = "print"; F1_help_topic = "print";
Plog(1,"m_print \n"); Plog(1,"m_print \n");
if (FGWM != 'F' && FGWM != 'G') return; if (FGWM != 'F' && FGWM != 'G') return;
if (clicked_file) Ppxb = PXB_load(clicked_file,1); // clicked thumbnail if (clicked_file) Ppxb = PXB_load(clicked_file,1); // clicked thumbnail
skipping to change at line 2521 skipping to change at line 2506
memset(pix,0,9); memset(pix,0,9);
} }
} }
return 1; return 1;
} }
// print calibrated image // print calibrated image
// menu function calling print_calibrated() in f.tools.cc // menu function calling print_calibrated() in f.tools.cc
void m_print_calibrated(GtkWidget *, cchar *) void m_print_calibrated(GtkWidget *, ch *)
{ {
Plog(1,"m_print_calibrated \n"); Plog(1,"m_print_calibrated \n");
if (FGWM != 'F' && FGWM != 'G') return; if (FGWM != 'F' && FGWM != 'G') return;
print_calibrated(); print_calibrated();
return; return;
} }
/******************************************************************************* */ /******************************************************************************* */
// Quit menu function // Quit menu function
// Click on window [x] button (delete event) also comes here. // Click on window [x] button (delete event) also comes here.
// User can bail out if unsaved edit, open dialog, running function, or second thoughts. // User can bail out if unsaved edit, open dialog, running function, or second thoughts.
void m_quit(GtkWidget *, cchar *) void m_quit(GtkWidget *, ch *)
{ {
zdialog *zd; zdialog *zd;
int yn, nn, ii; int yn, nn, ii;
char quitmess[100] = ""; ch quitmess[100] = "";
Plog(1,"m_quit \n"); Plog(1,"m_quit \n");
if (Fblock("quit","edits")) return; // unsaved edits, user bailout if (Fblock("quit","edits")) return; // unsaved edits, user bailout
if (zfuncs::zdialog_busy) { if (zfuncs::zdialog_busy) {
for (int ii = 0; ii < zfuncs::zdialog_count; ii++) { // loop pending dialogs for (int ii = 0; ii < zfuncs::zdialog_count; ii++) { // loop pending dialogs
zd = zfuncs::zdialog_list[ii]; zd = zfuncs::zdialog_list[ii];
if (strmatch(zd->title,"userguide")) continue; // omit this dialog if (strmatch(zd->title,"userguide")) continue; // omit this dialog
zdialog_show(zd,1); // un-hide minimized dialog zdialog_show(zd,1); // un-hide minimized dialog
yn = zmessageYN(Mwin,"Kill active dialog? %s",zd->title); // allow user bailout yn = zmessageYN(Mwin,"Kill active dialog? %s",zd->title); // allow user bailout
if (! yn) return; if (! yn) return;
zdialog_send_event(zd,"cancel"); zdialog_send_event(zd,"escape"); // kill dialog 23.1
zmainsleep(0.1); zmainsleep(0.1);
} }
} }
if (Fblock(0,"blocked quiet") || Ffuncbusy) { // something is still running if (Fblock(0,"blocked quiet") || Ffuncbusy) { // something is still running
yn = zmessageYN(Mwin,"Kill busy function?"); yn = zmessageYN(Mwin,"Kill busy function?");
if (! yn) return; if (! yn) return;
Fescape = 2; Fescape = 1;
// tell it to exit // tell it to exit
for (ii = 0; ii < 20; ii++) { // allow 2 secs. for (ii = 0; ii < 20; ii++) { // allow 2 secs.
if (Fblock(0,"blocked quiet") || Ffuncbusy) if (Fblock(0,"blocked quiet") || Ffuncbusy)
zmainsleep(0.1); zmainsleep(0.1);
else break; else break;
} }
if (ii == 20) Plog(1,"busy function will be killed \n"); if (ii == 20) Plog(0,"busy function will be killed \n");
// still running // still running
else Plog(1,"busy function quit \n");
Fescape = 0;
} }
if (! Faskquit) goto quitxx; // no "ask to quit" option if (! Faskquit) goto quitxx; // no "ask to quit" option
strncatv(quitmess,100," ","Quit Fotoxx?"," ",0); strncatv(quitmess,100," ","Quit Fotoxx?"," ",0);
nn = zdialog_choose2(Mwin,"parent",quitmess,"Yes","No",0); // get button or KB key input nn = zdialog_choose2(Mwin,"parent",quitmess,"Yes","No",0); // get button or KB key input
if (nn == 1) goto quitxx; // [Yes] button if (nn == 1) goto quitxx; // [Yes] button
if (nn == 2 || nn == -1) return; // [No] or [x] button if (nn == 2 || nn == -1) return; // [No] or [x] button
nn = toupper(nn); nn = toupper(nn);
skipping to change at line 2598 skipping to change at line 2582
quitxx: quitxx:
Plog(1,"Quit Fotoxx\n"); Plog(1,"Quit Fotoxx\n");
quitxx(); // does not return quitxx(); // does not return
} }
// used also for main window destroy event // used also for main window destroy event
// does not return // does not return
void quitxx() void quitxx()
{ {
Fshutdown++; Fshutdown = 1;
Fescape = 1;
// stop long-running funcs
gtk_window_get_position(MWIN,&mwgeom[0],&mwgeom[1]); // save main window position and size gtk_window_get_position(MWIN,&mwgeom[0],&mwgeom[1]); // save main window position and size
gtk_window_get_size(MWIN,&mwgeom[2],&mwgeom[3]); // for next session gtk_window_get_size(MWIN,&mwgeom[2],&mwgeom[3]); // for next session
zdialog_inputs("save"); // save dialog inputs zdialog_inputs("save"); // save dialog inputs
zdialog_geometry("save"); // save dialogs position/size zdialog_geometry("save"); // save dialogs position/size
gallery_memory("save"); // save recent gallery positions gallery_memory("save"); // save recent gallery positions
free_resources(); // free memory free_resources(); // free memory
showz_docfile(0,0,"quit"); // close userguide window showz_docfile(0,0,"quit"); // close userguide window
zshell(0,"rm -R -f %s",temp_folder); // delete temp files zshell(0,"rm -R -f %s",temp_folder); // delete temp files
save_params(); // save state for next session save_params(); // save state for next session
fflush(null); // flush stdout, stderr fflush(null); // flush stdout, stderr
zexit(0,"Fotoxx exit"); zexit(0,"Fotoxx exit");
} }
/******************************************************************************* */ /******************************************************************************* */
// help menu function // help menu function
void m_help(GtkWidget *, cchar *menu) void m_help(GtkWidget *, ch *menu)
{ {
Plog(1,"m_help \n"); Plog(1,"m_help \n");
F1_help_topic = "help menu"; F1_help_topic = "help menu";
if (! *menu) { if (! *menu) {
showz_docfile(Mwin,"userguide","help menu"); showz_docfile(Mwin,"userguide","help menu");
return; return;
} }
skipping to change at line 2679 skipping to change at line 2664
if (strmatch(menu,"Home Page")) if (strmatch(menu,"Home Page"))
showz_html("https://kornelix.net"); showz_html("https://kornelix.net");
return; return;
} }
/******************************************************************************* */ /******************************************************************************* */
// save (modified) image file to disk // save (modified) image file to disk
void m_file_save(GtkWidget *, cchar *menu) void m_file_save(GtkWidget *, ch *menu)
{ {
int file_save_dialog_event(zdialog *zd, cchar *event); int file_save_dialog_event(zdialog *zd, ch *event);
cchar *pp; ch *pp;
zdialog *zd; zdialog *zd;
F1_help_topic = "file save"; F1_help_topic = "file save";
Plog(1,"m_file_save \n"); Plog(1,"m_file_save \n");
if (FGWM != 'F' && FGWM != 'G') return; if (FGWM != 'F' && FGWM != 'G') return;
if (! curr_file) { if (! curr_file) {
if (zd_filesave) zdialog_free(zd_filesave); if (zd_filesave) zdialog_free(zd_filesave);
skipping to change at line 2753 skipping to change at line 2738
pp = strrchr(curr_file,'/'); pp = strrchr(curr_file,'/');
if (pp) zdialog_stuff(zd,"filename",pp+1); if (pp) zdialog_stuff(zd,"filename",pp+1);
zdialog_run(zd,file_save_dialog_event,"mouse"); zdialog_run(zd,file_save_dialog_event,"mouse");
return; return;
} }
// dialog event and completion function // dialog event and completion function
int file_save_dialog_event(zdialog *zd, cchar *event) int file_save_dialog_event(zdialog *zd, ch *event)
{ {
char *RP = 0, *newfilename = 0; ch *RP = 0, *newfilename = 0;
char temp[8]; ch temp[8];
int err; int err;
if (strmatch(event,"escape")) zd->zstat = -2; // escape key if (strmatch(event,"escape")) zd->zstat = -2; // escape key
if (zd->zstat) goto retx; // cancel if (zd->zstat) goto retx; // cancel
if (! zstrstr("newvers newfile replace",event)) return 1; // ignore other events if (! zstrstr("newvers newfile replace",event)) return 1; // ignore other events
if (Fblock(0,"blocked")) return 1; // check nothing pending if (Fblock(0,"blocked")) return 1; // check nothing pending
if (strmatch(event,"newvers")) // save as new version if (strmatch(event,"newvers")) // save as new version
{ {
skipping to change at line 2821 skipping to change at line 2806
retx: retx:
if (RP) zfree(RP); if (RP) zfree(RP);
if (newfilename) zfree(newfilename); if (newfilename) zfree(newfilename);
zdialog_free(zd); // kill dialog zdialog_free(zd); // kill dialog
zd_filesave = 0; zd_filesave = 0;
return 1; return 1;
} }
// menu entry for KB shortcut Save File (replace) // menu entry for KB shortcut Save File (replace)
void m_file_save_replace(GtkWidget *, cchar *menu) void m_file_save_replace(GtkWidget *, ch *menu)
{ {
int err; int err;
char *RP; ch *RP;
Plog(1,"m_file_save_replace \n"); Plog(1,"m_file_save_replace \n");
RP = f_realpath(curr_file); // use real path RP = f_realpath(curr_file); // use real path
if (! RP) { if (! RP) {
zmessageACK(Mwin,"file not found: %s",curr_file); zmessageACK(Mwin,"file not found: %s",curr_file);
return; return;
} }
err = f_save(RP,curr_file_type,curr_file_bpc,0,1); // save file err = f_save(RP,curr_file_type,curr_file_bpc,0,1); // save file
if (! err) f_open_saved(); // open saved file with edit hist if (! err) f_open_saved(); // open saved file with edit hist
zfree(RP); zfree(RP);
return; return;
} }
// menu entry for KB shortcut Save File Version // menu entry for KB shortcut Save File Version
void m_file_save_version(GtkWidget *, cchar *menu) void m_file_save_version(GtkWidget *, ch *menu)
{ {
char *newfilename = 0, *RP = 0; ch *newfilename = 0, *RP = 0;
char newfiletype[8]; ch newfiletype[8];
int err; int err;
Plog(1,"m_file_save_version \n"); Plog(1,"m_file_save_version \n");
RP = f_realpath(curr_file); // use real path RP = f_realpath(curr_file); // use real path
if (! RP) { if (! RP) {
zmessageACK(Mwin,"file not found: %s",curr_file); zmessageACK(Mwin,"file not found: %s",curr_file);
return; return;
} }
skipping to change at line 2876 skipping to change at line 2861
} }
/******************************************************************************* */ /******************************************************************************* */
// Save current image to specified file (same or new). // Save current image to specified file (same or new).
// Update image index file and thumbnail file. // Update image index file and thumbnail file.
// Set f_save_type, f_save_bpc, f_save_size // Set f_save_type, f_save_bpc, f_save_size
// Returns 0 if OK, else +N. // Returns 0 if OK, else +N.
// If Fack is true, failure will cause a popup ACK dialog. // If Fack is true, failure will cause a popup ACK dialog.
int f_save(char *outfile, cchar *outype, int outbpc, int qual, int Fack) int f_save(ch *outfile, ch *outype, int outbpc, int qual, int Fack)
{ {
cchar *exifkey[5], *exifdata[5]; ch *metakey[5], *metadata[5];
char *ppv[1], *tempfile, *pext, *outfile2; ch *ppv[1], *tempfile, *pext, *outfile2;
int nkeys, err, cc1, cc2, cc3, ii; int nkeys, err, cc1, cc2, cc3, ii;
int Fmod, Fcopy, Ftransp, Fnewfile; int Fmod, Fcopy, Ftransp, Fnewfile;
int px, py; int px, py;
void (*editfunc)(GtkWidget *, cchar *); void (*editfunc)(GtkWidget *, ch *);
STATB statB; STATB statB;
cchar *warnalpha = "Transparency map will be lost.\n" ch *warnalpha = "Transparency map will be lost.\n"
"save to TIFF or PNG file to retain."; "save to TIFF or PNG file to retain.";
if (! curr_file) return 1; if (! curr_file) return 1;
if (strmatch(outype,"RAW")) { // disallow saving as RAW type if (strmatch(outype,"RAW")) { // disallow saving as RAW type
zmessageACK(Mwin,"cannot save as RAW type"); zmessageACK(Mwin,"cannot save as RAW type");
return 1; return 1;
} }
Fmod = 0; Fmod = 0;
skipping to change at line 2991 skipping to change at line 2976
if (! strstr("tif png",outype)) outbpc = 8; // force bpc 8 if 16 not supported if (! strstr("tif png",outype)) outbpc = 8; // force bpc 8 if 16 not supported
err = PXM_save(E0pxm,tempfile,outbpc,qual,Fack); err = PXM_save(E0pxm,tempfile,outbpc,qual,Fack);
if (err) { if (err) {
remove(tempfile); // failure, clean up remove(tempfile); // failure, clean up
zfree(tempfile); zfree(tempfile);
zfree(outfile2); zfree(outfile2);
return 1; return 1;
} }
cc1 = 0; // exif_edithist[] text cc cc1 = 0; // meta_edithist[] text cc
if (Fexif_edithist) cc1 = exif_edithist_cc0; // exif_edithist at file open if (Fmeta_edithist) cc1 = meta_edithist_cc0; // meta_edithist at file open
else { else {
exifkey[0] = exif_edithist_key; metakey[0] = (ch *) meta_edithist_key;
exif_get(curr_file,&exifkey[0],ppv,1); meta_get1(curr_file,metakey,ppv,1);
// get edits made before // get edits made before
if (ppv[0]) { // this file was opened if (ppv[0]) { // this file was opened
strncpy0(exif_edithist,ppv[0],exif_maxcc-2); strncpy0(meta_edithist,ppv[0],metadataXcc-2);
zfree(ppv[0]); zfree(ppv[0]);
cc1 = strlen(exif_edithist); cc1 = strlen(meta_edithist);
exif_edithist_cc0 = cc1; meta_edithist_cc0 = cc1;
// edit hist cc when file was opened // edit hist cc when file was opened
} // (not updated for new edits) } // (not updated for new edits)
Fexif_edithist = 1; // history is loaded Fmeta_edithist = 1; // history is loaded
} }
for (ii = 1; ii <= URS_pos; ii++) // append edits from undo/redo stack for (ii = 1; ii <= URS_pos; ii++) // append edits from undo/redo stack
{ // (omit index 0 = initial image) { // (omit index 0 = initial image)
cc2 = strlen(URS_menu[ii]); cc2 = strlen(URS_menu[ii]);
cc3 = strlen(URS_parms[ii]); cc3 = strlen(URS_parms[ii]);
if (cc1 + 7 + cc2 + cc3 + 5 > exif_maxcc) break; if (cc1 + 7 + cc2 + cc3 + 5 > metadataXcc) break;
// no more room // no more room
strcpy(exif_edithist+cc1,Frelease); strcpy(meta_edithist+cc1,Frelease);
cc1 += strlen(Frelease); // append "Fotoxx-nn.n:Menu:parms|" cc1 += strlen(Frelease); // append "Fotoxx-nn.n:Menu:parms|"
exif_edithist[cc1] = ';'; meta_edithist[cc1] = ';';
cc1++; cc1++;
strcpy(exif_edithist+cc1,URS_menu[ii]); strcpy(meta_edithist+cc1,URS_menu[ii]);
cc1 += cc2; cc1 += cc2;
if (cc3) { if (cc3) {
strcpy(exif_edithist+cc1,": "); strcpy(meta_edithist+cc1,": ");
cc1 += 2; cc1 += 2;
strcpy(exif_edithist+cc1,URS_parms[ii]); strcpy(meta_edithist+cc1,URS_parms[ii]);
cc1 += cc3; cc1 += cc3;
} }
exif_edithist[cc1++] = '|'; meta_edithist[cc1++] = '|';
} }
if (CEF && CEF->Fmods) // append active edit function if (CEF && CEF->Fmods) // append active edit function
{ {
cc2 = strlen(CEF->menuname); cc2 = strlen(CEF->menuname);
cc3 = strlen(CEF->edit_hist); // 23.0 cc3 = strlen(CEF->edit_hist); // 23.0
if (cc1 + 7 + cc2 + cc3 + 5 < exif_maxcc) { if (cc1 + 7 + cc2 + cc3 + 5 < metadataXcc) {
strcpy(exif_edithist+cc1,"Fotoxx:"); strcpy(meta_edithist+cc1,"Fotoxx:");
cc1 += 7; // append "Fotoxx:Menu:parms|" cc1 += 7; // append "Fotoxx:Menu:parms|"
strcpy(exif_edithist+cc1,CEF->menuname); strcpy(meta_edithist+cc1,CEF->menuname);
if (cc3) { if (cc3) {
cc1 += cc2; cc1 += cc2;
strcpy(exif_edithist+cc1,": "); strcpy(meta_edithist+cc1,": ");
cc1 += 2; cc1 += 2;
strcpy(exif_edithist+cc1,CEF->edit_hist); strcpy(meta_edithist+cc1,CEF->edit_hist);
cc1 += cc3; cc1 += cc3;
} }
exif_edithist[cc1++] = '|'; meta_edithist[cc1++] = '|';
} }
} }
exif_edithist[cc1] = 0; meta_edithist[cc1] = 0;
nkeys = 0; nkeys = 0;
if (Fupright) { // image was uprighted if (Fupright) { // image was uprighted
exifkey[nkeys] = exif_orientation_key; metakey[nkeys] = meta_orientation_key;
// remove EXIF orientation // remove metadata orientation
exifdata[nkeys] = ""; metadata[nkeys] = "";
nkeys++; nkeys++;
} }
if (Flevel) { // image was levelled if (Flevel) { // image was levelled
exifkey[nkeys] = exif_rollangle_key; metakey[nkeys] = meta_rollangle_key;
// remove EXIF rollangle // remove metadata rollangle
exifdata[nkeys] = "0"; metadata[nkeys] = "0"; // ""
// "" fails, use "0" fails, use "0"
nkeys++; nkeys++;
} }
if (cc1) { // prior and/or curr. edit history if (cc1) { // prior and/or curr. edit history
exifkey[nkeys] = exif_edithist_key; metakey[nkeys] = meta_edithist_key;
// add to EXIF // add to metadata
exifdata[nkeys] = exif_edithist; metadata[nkeys] = meta_edithist;
nkeys++; nkeys++;
} }
err = exif_copy(curr_file,tempfile,exifkey,exifdata,nkeys); // copy all EXIF/IPTC data to err = meta_copy(curr_file,tempfile,metakey,metadata,nkeys); // copy all metadata to
if (err) { // temp file with above revisions if (err) { // temp file with above revisions
if (Fack) zmessageACK(Mwin,"Unable to copy EXIF/IPTC data"); if (Fack) zmessageACK(Mwin,"Unable to copy metadata");
else Plog(1,"Unable to copy EXIF/IPTC data \n"); else Plog(1,"Unable to copy metadata \n");
} }
err = rename(tempfile,outfile2); // rename temp file to output file err = rename(tempfile,outfile2); // rename temp file to output file
if (err) { if (err) {
if (Fack) zmessageACK(Mwin,strerror(err)); if (Fack) zmessageACK(Mwin,strerror(err));
remove(tempfile); // delete temp file remove(tempfile); // delete temp file
zfree(tempfile); zfree(tempfile);
zfree(outfile2); zfree(outfile2);
return 2; // could not save return 2; // could not save
} }
skipping to change at line 3136 skipping to change at line 3121
/******************************************************************************* */ /******************************************************************************* */
// save (modified) image to new file name or type // save (modified) image to new file name or type
// confirm if overwrite of existing file // confirm if overwrite of existing file
// returns 0 if OK, 1 if cancel or error // returns 0 if OK, 1 if cancel or error
GtkWidget *saveas_fchooser; GtkWidget *saveas_fchooser;
int f_save_as() int f_save_as()
{ {
int f_save_as_dialog_event(zdialog *zd, cchar *event); int f_save_as_dialog_event(zdialog *zd, ch *event);
zdialog *zd; zdialog *zd;
char *save_folder = 0; ch *save_folder = 0;
cchar *type; ch *type;
char *newfile, *fname; ch *newfile, *fname;
char *outfile = 0, *outfile2 = 0, *pp, *pext; ch *outfile = 0, *outfile2 = 0, *pp, *pext;
char permissions[100]; ch permissions[100];
int ii, zstat, err, bpc; int ii, zstat, err, bpc;
int jpgqual = jpeg_def_quality; int jpgqual = jpeg_def_quality;
int mkcurr = 0; int mkcurr = 0;
STATB statB; STATB statB;
mode_t mode; mode_t mode;
/*** /***
_____________________________________________________ _____________________________________________________
| Save as New File Name or Type | | Save as New File Name or Type |
| ________________________________________________ | | ________________________________________________ |
skipping to change at line 3346 skipping to change at line 3331
} }
if (mkcurr) f_open_saved(); // open saved file with edit hist 22.1 if (mkcurr) f_open_saved(); // open saved file with edit hist 22.1
zfree(outfile); zfree(outfile);
return 0; return 0;
} }
// dialog event and completion function // dialog event and completion function
int f_save_as_dialog_event(zdialog *zd, cchar *event) int f_save_as_dialog_event(zdialog *zd, ch *event)
{ {
int ii, err; int ii, err;
char *filespec, *filename, *pp; ch *filespec, *filename, *pp;
char oldperms[100], newperms[100]; ch oldperms[100], newperms[100];
char ext[4]; ch ext[4];
if (strmatch(event,"escape")) zd->zstat = -2; // escape key if (strmatch(event,"escape")) zd->zstat = -2; // escape key
if (zd->zstat) return 1; // [ OK ] or [cancel] if (zd->zstat) return 1; // [ OK ] or [cancel]
if (strmatch(event,"jpgqual")) { // if jpg quality edited, set jpg .ext if (strmatch(event,"jpgqual")) { // if jpg quality edited, set jpg .ext
zdialog_stuff(zd,"jpg",1); zdialog_stuff(zd,"jpg",1);
event = "jpg"; event = "jpg";
} }
skipping to change at line 3418 skipping to change at line 3403
} }
/******************************************************************************* */ /******************************************************************************* */
// get real path for filename possibly having symlinks // get real path for filename possibly having symlinks
// all folders in input filename path must exist // all folders in input filename path must exist
// final file name need not exist (f_save() caller) // final file name need not exist (f_save() caller)
// returns real path or null if error // returns real path or null if error
// returned path is subject for zfree() // returned path is subject for zfree()
char * f_realpath(cchar * infile) ch * f_realpath(ch * infile)
{ {
int cc; int cc;
char *pp, *RP, *outfile; ch *pp, *RP, *outfile;
char tempfile[XFCC]; ch tempfile[XFCC];
RP = realpath(infile,null); // try full file path RP = realpath(infile,null); // try full file path
if (RP) { if (RP) {
outfile = zstrdup(RP,"realpath"); // OK outfile = zstrdup(RP,"realpath"); // OK
free(RP); free(RP);
return outfile; return outfile;
} }
strcpy(tempfile,infile); // fail, try folders only strcpy(tempfile,infile); // fail, try folders only
pp = strrchr(tempfile + 2,'/'); pp = strrchr(tempfile + 2,'/');
skipping to change at line 3453 skipping to change at line 3438
return outfile; return outfile;
} }
/******************************************************************************* */ /******************************************************************************* */
// get the root name of an image file, without version and extension // get the root name of an image file, without version and extension
// /.../filename.V03.png --> /.../filename // /.../filename.V03.png --> /.../filename
// returned root name has extra length to add .vNN.exxxxt // returned root name has extra length to add .vNN.exxxxt
// returned root name is subject for zfree() // returned root name is subject for zfree()
char * file_rootname(cchar *file) ch * file_rootname(ch *file)
{ {
char *rootname, *pp1, *pp2; ch *rootname, *pp1, *pp2;
rootname = zstrdup(file,"rootname",16); rootname = zstrdup(file,"rootname",16);
pp1 = strrchr(rootname,'/'); // find file .ext pp1 = strrchr(rootname,'/'); // find file .ext
if (! pp1) pp1 = rootname; if (! pp1) pp1 = rootname;
pp2 = strrchr(pp1,'.'); // pp2 --> .ext or ending null pp2 = strrchr(pp1,'.'); // pp2 --> .ext or ending null
if (! pp2) pp2 = pp1 + strlen(pp1); if (! pp2) pp2 = pp1 + strlen(pp1);
if (pp2[-4] == '.' && pp2[-3] == 'v' && // look for .vNN.ext if (pp2[-4] == '.' && pp2[-3] == 'v' && // look for .vNN.ext
pp2[-2] >= '0' && pp2[-2] <= '9' && pp2[-2] >= '0' && pp2[-2] <= '9' &&
pp2[-1] >= '0' && pp2[-1] <= '9') pp2 -= 4; // pp2 --> .ext or .vNN.ext pp2[-1] >= '0' && pp2[-1] <= '9') pp2 -= 4; // pp2 --> .ext or .vNN.ext
skipping to change at line 3478 skipping to change at line 3463
return rootname; return rootname;
} }
/******************************************************************************* */ /******************************************************************************* */
// return base name for given file = original file name /.../filename.ext // return base name for given file = original file name /.../filename.ext
// returns null if base file does not exist. // returns null if base file does not exist.
// returned base name has extra length to add .vNN.exxxxt // returned base name has extra length to add .vNN.exxxxt
// returned base name is subject for zfree() // returned base name is subject for zfree()
char * file_basename(cchar *file) ch * file_basename(ch *file)
{ {
char *rootname, **flist, *pp = 0; ch *rootname, **flist, *pp = 0;
int ii, cc, nf; int ii, cc, nf;
flist = file_all_versions(file,nf); // get base file and all versions flist = file_all_versions(file,nf); // get base file and all versions
if (! nf) return 0; if (! nf) return 0;
rootname = file_rootname(file); rootname = file_rootname(file);
cc = strlen(rootname); cc = strlen(rootname);
zfree(rootname); zfree(rootname);
for (ii = 0; ii < nf; ii++) for (ii = 0; ii < nf; ii++)
skipping to change at line 3514 skipping to change at line 3499
return pp; return pp;
} }
/******************************************************************************* */ /******************************************************************************* */
// Get all versions of a given file name in sequence, including base file. // Get all versions of a given file name in sequence, including base file.
// Returned list of file names is subject for zfree() // Returned list of file names is subject for zfree()
// (each returned flist[*] member and flist itself) // (each returned flist[*] member and flist itself)
// returns null if nothing found // returns null if nothing found
char ** file_all_versions(cchar *file, int &NF) ch ** file_all_versions(ch *file, int &NF)
{ {
int file_comp_versions(cchar *f1, cchar *f2); int file_comp_versions(ch *f1, ch *f2);
char **flist1, **flist2, *rootname; ch **flist1, **flist2, *rootname;
char *pext, *pvers; ch *pext, *pvers;
int ii, jj, err, cc1, cc2; int ii, jj, err, cc1, cc2;
rootname = file_rootname(file); // /.../fname.vNN.ext --> /.../fname rootname = file_rootname(file); // /.../fname.vNN.ext --> /.../fname
if (! rootname) return 0; if (! rootname) return 0;
cc1 = strlen(rootname); // file cc without .vNN.ext cc1 = strlen(rootname); // file cc without .vNN.ext
strcpy(rootname + cc1,".*"); strcpy(rootname + cc1,".*");
err = zfind(rootname,flist1,NF); // find /.../fname.* err = zfind(rootname,flist1,NF); // find /.../fname.*
zfree(rootname); zfree(rootname);
if (err || NF < 1) return 0; if (err || NF < 1) return 0;
flist2 = (char **) zmalloc(NF * sizeof(char *),"file-vers"); // scan for valid versions flist2 = (ch **) zmalloc(NF * sizeof(ch *),"file-vers"); // scan for valid versions
for (ii = jj = 0; ii < NF; ii++) // validate fname.ext or fname.vNN.ext 22.20 for (ii = jj = 0; ii < NF; ii++) // validate fname.ext or fname.vNN.ext 22.20
{ {
if (image_file_type(flist1[ii]) > VIDEO) continue; // not image file if (image_file_type(flist1[ii]) > VIDEO) continue; // not image file
pext = strrchr(flist1[ii],'.'); // get file .ext pext = strrchr(flist1[ii],'.'); // get file .ext
if (! pext) continue; if (! pext) continue;
cc2 = pext - flist1[ii]; // file cc without .ext cc2 = pext - flist1[ii]; // file cc without .ext
if (cc2 > cc1) { // version present? .vNN.ext if (cc2 > cc1) { // version present? .vNN.ext
cc2 -= 4; cc2 -= 4;
skipping to change at line 3570 skipping to change at line 3555
if (NF > 99) { // screen out problem file if (NF > 99) { // screen out problem file
zmessageACK(Mwin,"file: %s \n exceed 99 versions",file); zmessageACK(Mwin,"file: %s \n exceed 99 versions",file);
zfree(flist2); zfree(flist2);
return 0; return 0;
} }
HeapSort(flist2,NF,file_comp_versions); // sort in base, version order HeapSort(flist2,NF,file_comp_versions); // sort in base, version order
return flist2; return flist2;
} }
int file_comp_versions(cchar *f1, cchar *f2) int file_comp_versions(ch *f1, ch *f2)
{ {
f1 = strrchr(f1,'.'); // find .ext in file f1 f1 = strrchr(f1,'.'); // find .ext in file f1
if (! f1) return -1; // f1 has no .ext if (! f1) return -1; // f1 has no .ext
f2 = strrchr(f2,'.'); f2 = strrchr(f2,'.');
if (! f2) return +1; // f2 has no .ext if (! f2) return +1; // f2 has no .ext
f1 -= 4; // point to '.v' in filename.vNN.ext f1 -= 4; // point to '.v' in filename.vNN.ext
if (! strmatchN(f1,".v",2)) return -1; // f1 not a version if (! strmatchN(f1,".v",2)) return -1; // f1 not a version
f2 -= 4; f2 -= 4;
if (! strmatchN(f2,".v",2)) return +1; // f2 not a version if (! strmatchN(f2,".v",2)) return +1; // f2 not a version
return strcmp(f1,f2); // compare versions return strcmp(f1,f2); // compare versions
} }
/******************************************************************************* */ /******************************************************************************* */
// Get next available version /.../filename.vNN.ext for given file. // Get next available version /.../filename.vNN.ext for given file.
// Returns "/.../filename.v01.ext" if no versions are found. // Returns "/.../filename.v01.ext" if no versions are found.
// Returns null if bad file name or 99 versions already exist. // Returns null if bad file name or 99 versions already exist.
// Returned file name is subject for zfree(). // Returned file name is subject for zfree().
char * file_new_version(cchar *file) ch * file_new_version(ch *file)
{ {
char *retname, *pp, pext[8]; ch *retname, *pp, pext[8];
char **flist = 0; ch **flist = 0;
int ii, cc, NF = 0, vers; int ii, cc, NF = 0, vers;
pp = (char *) strrchr(file,'/'); // find .ext for file pp = (ch *) strrchr(file,'/'); // find .ext for file
if (! pp) return 0; if (! pp) return 0;
pp = strrchr(pp,'.'); pp = strrchr(pp,'.');
if (pp) strncpy0(pext,pp,8); if (pp) strncpy0(pext,pp,8);
else strcpy(pext,".jpg"); else strcpy(pext,".jpg");
flist = file_all_versions(file,NF); // get base file and all versions flist = file_all_versions(file,NF); // get base file and all versions
if (! NF) { // nothing exists if (! NF) { // nothing exists
retname = file_rootname(file); // get /.../filename retname = file_rootname(file); // get /.../filename
retname = zstrdup(retname,"new-version",12); retname = zstrdup(retname,"new-version",12);
cc = strlen(retname); cc = strlen(retname);
skipping to change at line 3655 skipping to change at line 3640
return retname; return retname;
} }
/******************************************************************************* */ /******************************************************************************* */
// Get the newest version /.../filename.vNN.ext for the given file. // Get the newest version /.../filename.vNN.ext for the given file.
// Returns unversioned file /.../filename.ext if found by itself. // Returns unversioned file /.../filename.ext if found by itself.
// Returns null if bad file name. // Returns null if bad file name.
// Returned file name is subject for zfree(). // Returned file name is subject for zfree().
char * file_newest_version(cchar *file) ch * file_newest_version(ch *file)
{ {
char *retname; ch *retname;
char **flist; ch **flist;
int ii, NF; int ii, NF;
flist = file_all_versions(file,NF); // get base file and all versions flist = file_all_versions(file,NF); // get base file and all versions
if (! NF) return 0; if (! NF) return 0;
retname = zstrdup(flist[NF-1],"new-version",12); // get last version found retname = zstrdup(flist[NF-1],"new-version",12); // get last version found
for (ii = 0; ii < NF; ii++) // free memory for (ii = 0; ii < NF; ii++) // free memory
zfree(flist[ii]); zfree(flist[ii]);
zfree(flist); zfree(flist);
return retname; return retname;
} }
/******************************************************************************* */ /******************************************************************************* */
// Get the prior version /.../filename.vNN.ext for the given file. // Get the prior version /.../filename.vNN.ext for the given file.
// Returns unversioned file /.../filename.ext if no prior .vNN found. // Returns unversioned file /.../filename.ext if no prior .vNN found.
// Returns null if bad file name or no prior version. // Returns null if bad file name or no prior version.
char * file_prior_version(cchar *file) ch * file_prior_version(ch *file)
{ {
char *retname; ch *retname;
char **flist; ch **flist;
int ii, NF; int ii, NF;
flist = file_all_versions(file,NF); // get base file and all versions flist = file_all_versions(file,NF); // get base file and all versions
if (! NF) return 0; if (! NF) return 0;
for (ii = 0; ii < NF; ii++) // find input file in list for (ii = 0; ii < NF; ii++) // find input file in list
if (strmatch(file,flist[ii])) break; if (strmatch(file,flist[ii])) break;
if (ii == 0) return 0; // input is base file (no prior) if (ii == 0) return 0; // input is base file (no prior)
if (ii == NF) return 0; // should not happen if (ii == NF) return 0; // should not happen
skipping to change at line 3707 skipping to change at line 3692
zfree(flist[ii]); zfree(flist[ii]);
zfree(flist); zfree(flist);
return retname; return retname;
} }
/******************************************************************************* * /******************************************************************************* *
Find all image files within given path. Find all image files within given path.
int find_imagefiles(cchar *folder, int flags, char **&flist, int &NF) int find_imagefiles(ch *folder, int flags, ch **&flist, int &NF)
folder folder path to search folder folder path to search
flags sum of the following: flags sum of the following:
1 include image files (+RAW +video) 1 include image files (+RAW +video)
2 include thumbnails 2 include thumbnails
4 include hidden files 4 include hidden files
8 include folders 8 include folders
16 recurse folders 16 recurse folders
32 omit symlinks 32 omit symlinks
NF count of files returned NF count of files returned
flist list of files returned flist list of files returned
Returns 0 if OK, +N if error (errno is set). Returns 0 if OK, +N if error (errno is set).
flist and flist[*] are subjects for zfree(). flist and flist[*] are subjects for zfree().
******************************************************************************** */ ******************************************************************************** */
namespace find_imagefiles_names namespace find_imagefiles_names
{ {
char **fif_filelist; // list of filespecs returned ch **fif_filelist; // list of filespecs returned
int fif_max; // filelist slots allocated int fif_max; // filelist slots allocated
int fif_count; // filelist slots filled int fif_count; // filelist slots filled
} }
int find_imagefiles(cchar *folder, int flags, char **&flist, int &NF, int Finit) int find_imagefiles(ch *folder, int flags, ch **&flist, int &NF, int Finit)
{ {
using namespace find_imagefiles_names; using namespace find_imagefiles_names;
int globflags, Fimages, Fthumbs, Fdirs, Frecurse, Fnolinks; int globflags, Fimages, Fthumbs, Fdirs, Frecurse, Fnolinks;
int err1, err2, cc; int err1, err2, cc;
FTYPE ftype; FTYPE ftype;
char *file, *mfolder, **templist; ch *file, *mfolder, **templist;
glob_t globdata; glob_t globdata;
STATB statB; STATB statB;
if (Finit) { // initial call if (Finit) { // initial call
spinlock(1); // prevent reentrance spinlock(1); // prevent reentrance
fif_max = fif_count = 0; fif_max = fif_count = 0;
} }
globflags = GLOB_NOSORT; globflags = GLOB_NOSORT;
Fimages = Fthumbs = Fdirs = Frecurse = Fnolinks = 0; Fimages = Fthumbs = Fdirs = Frecurse = Fnolinks = 0;
skipping to change at line 3806 skipping to change at line 3791
if (ftype == OTHER) continue; // unknown file type if (ftype == OTHER) continue; // unknown file type
if (ftype == FDIR && ! Fdirs) continue; if (ftype == FDIR && ! Fdirs) continue;
if (ftype == THUMB && ! Fthumbs) continue; if (ftype == THUMB && ! Fthumbs) continue;
if (ftype == IMAGE || ftype == RAW || ftype == VIDEO) if (ftype == IMAGE || ftype == RAW || ftype == VIDEO)
if (! Fimages) continue; if (! Fimages) continue;
if (fif_count == fif_max) { // output list is full if (fif_count == fif_max) { // output list is full
if (fif_max == 0) { if (fif_max == 0) {
fif_max = 1000; // initial space, 1000 files fif_max = 1000; // initial space, 1000 files
cc = fif_max * sizeof(char *); cc = fif_max * sizeof(ch *);
fif_filelist = (char **) zmalloc(cc,"find-files"); fif_filelist = (ch **) zmalloc(cc,"find-files");
} }
else { else {
templist = fif_filelist; // expand by 2x each time needed templist = fif_filelist; // expand by 2x each time needed
cc = fif_max * sizeof(char *); cc = fif_max * sizeof(ch *);
fif_filelist = (char **) zmalloc(cc+cc,"find-files"); fif_filelist = (ch **) zmalloc(cc+cc,"find-files");
memcpy(fif_filelist,templist,cc); memcpy(fif_filelist,templist,cc);
memset(fif_filelist+fif_max,0,cc); memset(fif_filelist+fif_max,0,cc);
zfree(templist); zfree(templist);
fif_max *= 2; fif_max *= 2;
} }
} }
fif_filelist[fif_count] = zstrdup(file,"find-files"); // add file to output list fif_filelist[fif_count] = zstrdup(file,"find-files"); // add file to output list
fif_count += 1; fif_count += 1;
} }
skipping to change at line 3847 skipping to change at line 3832
} }
errno = err2; // return err1 and preserve errno errno = err2; // return err1 and preserve errno
return err1; return err1;
} }
/******************************************************************************* */ /******************************************************************************* */
// test if a file exists, is a regular file // test if a file exists, is a regular file
int regfile(cchar *file, struct stat *statb) int regfile(ch *file, struct stat *statb)
{ {
STATB statB; STATB statB;
int err; int err;
err = stat(file,&statB); err = stat(file,&statB);
if (err) return 0; if (err) return 0;
if (! S_ISREG(statB.st_mode)) return 0; if (! S_ISREG(statB.st_mode)) return 0;
if (statb) *statb = statB; if (statb) *statb = statB;
return 1; return 1;
} }
// test if a file exists, is a directory/folder // test if a file exists, is a directory/folder
int dirfile(cchar *file, struct stat *statb) int dirfile(ch *file, struct stat *statb)
{ {
STATB statB; STATB statB;
int err; int err;
err = stat(file,&statB); err = stat(file,&statB);
if (err) return 0; if (err) return 0;
if (! S_ISDIR(statB.st_mode)) return 0; if (! S_ISDIR(statB.st_mode)) return 0;
if (statb) *statb = statB; if (statb) *statb = statB;
return 1; return 1;
} }
// test if file exists, is a regular file, and read or write permission // test if file exists, is a regular file, and read or write permission
// rw: 'r' or read or 'w' for write or ' ' for file exists only // rw: 'r' or read or 'w' for write or ' ' for file exists only
// returns 0 if file does not exist, is not a regular file, or access is not pe rmitted // returns 0 if file does not exist, is not a regular file, or access is not pe rmitted
// returns 1 if all is OK // returns 1 if all is OK
int hasperm(cchar *file, cchar rw) int hasperm(ch *file, ch rw)
{ {
STATB statB; STATB statB;
if (! regfile(file,&statB)) return 0; if (! regfile(file,&statB)) return 0;
if (rw == 'r' && ! (S_IRUSR & statB.st_mode)) return 0; if (rw == 'r' && ! (S_IRUSR & statB.st_mode)) return 0;
if (rw == 'w' && ! (S_IWUSR & statB.st_mode)) return 0; if (rw == 'w' && ! (S_IWUSR & statB.st_mode)) return 0;
return 1; return 1;
} }
/******************************************************************************* */ /******************************************************************************* */
// Show a permissions setting, edit and return changed permissions. // Show a permissions setting, edit and return changed permissions.
// 'fname' is a file name or permission category, e.g. 'default' // 'fname' is a file name or permission category, e.g. 'default'
// Permissions are strings: "read+write", "read only", "no access". // Permissions are strings: "read+write", "read only", "no access".
// 'p1' and 'p2' are input and output permissions strings, which are // 'p1' and 'p2' are input and output permissions strings, which are
// any combination of three of the above strings, comma separated, // any combination of three of the above strings, comma separated,
// which define the access permissions for user, group, other. // which define the access permissions for user, group, other.
// p1 and p2 are char[100] strings to allow for fat translations. // p1 and p2 are char[100] strings to allow for fat translations.
// Returns 1 if user cancel or error, 0 if changes were made OK. // Returns 1 if user cancel or error, 0 if changes were made OK.
int set_permissions(GtkWidget *parent, cchar *fname, cchar *p1, char *p2) int set_permissions(GtkWidget *parent, ch *fname, ch *p1, ch *p2)
{ {
char operm[50], gperm[50], wperm[50]; ch operm[50], gperm[50], wperm[50];
const char *pp; ch *pp;
zdialog *zd; zdialog *zd;
int zstat; int zstat;
/*** /***
________________________________ ________________________________
| permissions | | permissions |
| | | |
| owner [read+write |v] | | owner [read+write |v] |
| group [read only |v] | | group [read only |v] |
| other [no access |v] | | other [no access |v] |
skipping to change at line 3976 skipping to change at line 3961
snprintf(p2,100,"%s, %s, %s",operm,gperm,wperm); // output permissions snprintf(p2,100,"%s, %s, %s",operm,gperm,wperm); // output permissions
zdialog_free(zd); zdialog_free(zd);
return 0; // normal return return 0; // normal return
} }
// convert between permission formats // convert between permission formats
// string: "read+write, read only, no access" // string: "read+write, read only, no access"
// mode_t: bitmap of permissions, e.g. 0640 // mode_t: bitmap of permissions, e.g. 0640
int conv_permissions(cchar *perms, mode_t &mode) // string permissions to mode_t int conv_permissions(ch *perms, mode_t &mode) // string permissions to mode_t
{ {
int err = 0; int err = 0;
cchar *pp; ch *pp;
mode = 0; mode = 0;
pp = substring(perms,',',1); pp = substring(perms,',',1);
if (pp) { if (pp) {
if (strmatch(pp,"read+write")) mode += S_IRUSR + S_IWUSR; if (strmatch(pp,"read+write")) mode += S_IRUSR + S_IWUSR;
else if (strmatch(pp,"read only")) mode += S_IRUSR; else if (strmatch(pp,"read only")) mode += S_IRUSR;
else if (strmatch(pp,"no access")); else if (strmatch(pp,"no access"));
else err = 1; else err = 1;
} }
skipping to change at line 4013 skipping to change at line 3998
if (strmatch(pp,"read+write")) mode += S_IROTH + S_IWOTH; if (strmatch(pp,"read+write")) mode += S_IROTH + S_IWOTH;
else if (strmatch(pp,"read only")) mode += S_IROTH; else if (strmatch(pp,"read only")) mode += S_IROTH;
else if (strmatch(pp,"no access")); else if (strmatch(pp,"no access"));
else err = 1; else err = 1;
} }
else err = 1; else err = 1;
return err; return err;
} }
int conv_permissions(mode_t mode, char *perms) // mode_t to string permissions int conv_permissions(mode_t mode, ch *perms) // mode_t to string permissions
{ {
int err = 0; int err = 0;
*perms = 0; *perms = 0;
if (mode & S_IRUSR && mode & S_IWUSR) strcat(perms,"read+write"); if (mode & S_IRUSR && mode & S_IWUSR) strcat(perms,"read+write");
else if (mode & S_IRUSR) strcat(perms,"read only"); else if (mode & S_IRUSR) strcat(perms,"read only");
else strcat(perms,"no access"); else strcat(perms,"no access");
strcat(perms,", "); strcat(perms,", ");
 End of changes. 175 change blocks. 
251 lines changed or deleted 238 lines changed or added

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