"Fossies" - the Fresh Open Source Software Archive  

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

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

fotoxx.cc  (fotoxx-23.0):fotoxx.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 96 skipping to change at line 96
redo_all redo all edits for image redo_all redo all edits for image
save_undo save image in the undo stack save_undo save image in the undo stack
load_undo load image from the undo stack load_undo load image from the undo stack
takeMouse set mouse event function and special cursor takeMouse set mouse event function and special cursor
freeMouse remove mouse event function, set normal cursor freeMouse remove mouse event function, set normal cursor
thread_start start thread in idle state thread_start start thread in idle state
thread_signal signal thread that work is pending thread_signal signal thread that work is pending
thread_stop stop thread and wait for exit thread_stop stop thread and wait for exit
thread_wait wait for thread to become idle thread_wait wait for thread to become idle
thread_killed thread: query user kill action (quit immediately)
do_wthreads thread: start worker threads and wait do_wthreads thread: start worker threads and wait
progress_reset set/reset progress counter progress_reset set/reset progress counter
progress_add increment progress counter progress_add increment progress counter
progress_percent get progress percent completion 0-100 progress_percent get progress percent completion 0-100
save_params save parameters when fotoxx exits save_params save parameters when fotoxx exits
load_params load parameters at fotoxx startup load_params load parameters at fotoxx startup
free_resources free resources for the current image file free_resources free resources for the current image file
printlog log message to log file printlog log message to log file
skipping to change at line 119 skipping to change at line 118
#define EX // disable extern declarations #define EX // disable extern declarations
#include "fotoxx.h" // (variables in fotoxx.h are defined) #include "fotoxx.h" // (variables in fotoxx.h are defined)
/******************************************************************************* */ /******************************************************************************* */
// fotoxx main program // fotoxx main program
using namespace zfuncs; using namespace zfuncs;
int main(int argc, char *argv[]) // Fotoxx main program int main(int argc, ch *argv[]) // Fotoxx main program
{ {
char *temp, *pp; ch *temp, *pp;
char *pid, *pidlist; ch *pid, *pidlist;
int Fclone=0, cloxx=0, cloyy=0, cloww=0, clohh=0; int Fclone=0, cloxx=0, cloyy=0, cloww=0, clohh=0;
int Fblankwindow = 0; int Fblankwindow = 0;
int ii, cc, err; int ii, cc, err;
int Nperf, Neff; int Nperf, Neff;
int Pindexlev; int Pindexlev;
FTYPE ftype; FTYPE ftype;
FILE *fid; FILE *fid;
char filename[200], buff[200]; ch filename[200], buff[200];
double freememory; double freememory;
double startsecs = get_seconds(); // start time double startsecs = get_seconds(); // start time
Fwsl = 0; Fwsl = 0;
pp = getenv("WSL_DISTRO_NAME"); // set flag for alt. code paths WSL pp = getenv("WSL_DISTRO_NAME"); // set flag for alt. code paths WSL
if (pp && *pp) { if (pp && *pp) {
Fwsl = 1; Fwsl = 1;
Plog(0,"WSL %s\n",pp); Plog(0,"WSL %s\n",pp);
} }
zinitapp(Frelease,argc,argv); // initz. GTK application zinitapp(Frelease,argc,argv); // initz. GTK application
// initialize default values (saved parameters will override these) // initialize default values (saved parameters will override these)
Fdevmenu = 0; // no show developer menu 22.15 Fdevmenu = 0; // no show developer menu 22.15
Ffirsttime = 1; // first startup (params override) Ffirsttime = 1; // first startup (params override)
Floglevel = 1; // 0/1/2 = errs/infos/dialog inputs Floglevel = 1; // 0/1/2 = errs/infos/dialog inputs
Findexlev = 2; // direct exec: old index + search new Findexlev = 2; // direct exec: old index + search new
FMindexlev = 1; // file manager: old index only FMindexlev = 1; // file manager: old index only
Pindexlev = -1; // no -x index command parameter Pindexlev = -1; // no -x index command parameter
NWT = NST = 0; // edit and index thread count 22.35
xxrec_tab = 0; // no image index yet xxrec_tab = 0; // no image index yet
Nxxrec = Findexvalid = 0; Nxxrec = Findexvalid = 0;
Prelease = zstrdup("unknown","params"); // prev. release (params override) Prelease = zstrdup("unknown","params"); // prev. release (params override)
mwgeom[0] = mwgeom[1] = 20; // default main window geometry mwgeom[0] = mwgeom[1] = 20; // default main window geometry
mwgeom[2] = 1000; mwgeom[3] = 760; // small laptop 23.0 mwgeom[2] = 1000; mwgeom[3] = 760; // small laptop 23.0
*paneltext = 0; // no status bar text *paneltext = 0; // no status bar text
cropsizes[0] = zstrdup("1920x1080","params"); // default crop size memory cropsizes[0] = zstrdup("1920x1080","params"); // default crop size memory
cropsizes[1] = zstrdup("1600x900", "params"); cropsizes[1] = zstrdup("1600x900", "params");
cropsizes[2] = zstrdup("1440x900", "params"); cropsizes[2] = zstrdup("1440x900", "params");
skipping to change at line 232 skipping to change at line 230
Fmatchthumb = 0; // RAW loader match thumb color OFF Fmatchthumb = 0; // RAW loader match thumb color OFF
rawcommand = zstrdup("(custom RAW loader command)","params"); // custom RAW file loader command 22.35 rawcommand = zstrdup("(custom RAW loader command)","params"); // custom RAW file loader command 22.35
lens_mm = 35; // pano lens parameter lens_mm = 35; // pano lens parameter
colormapfile = zstrdup("undefined","params"); // printer calibration color map colormapfile = zstrdup("undefined","params"); // printer calibration color map
ss_KBkeys = zstrdup("BNPX","params"); // default slide show control keys ss_KBkeys = zstrdup("BNPX","params"); // default slide show control keys
Fcaps = 0; // show captions = off 22.20 Fcaps = 0; // show captions = off 22.20
Faskquit = 0; // ask to quit = NO Faskquit = 0; // ask to quit = NO
Fpaintedits = 0; // not paint edits mode Fpaintedits = 0; // not paint edits mode
Fmousevents = 0; // no show mouse events popup text 22.15 Fmousevents = 0; // no show mouse events popup text 22.15
Nblacklist = 0; // blacklist folders/files count Nblacklist = 0; // blacklist folders/files count
Ffuncbusy = 0;
// nothing busy 23.1
Fwatchescape = 0;
// nothing pending 23.1
Fescape = 0;
// no escape key pressed 23.1
imagefiletypes = zstrdup(".jpg .jpeg .png .tif .tiff .bmp .ico .ppm .gif .svg .xpm .tga " ,"params",40); imagefiletypes = zstrdup(".jpg .jpeg .png .tif .tiff .bmp .ico .ppm .gif .svg .xpm .tga " ,"params",40);
RAWfiletypes = zstrdup(".arw .srf .sr2 .crw .cr2 .cr3 .dng .mdc .mrw .nef .nr w .raw .rw2 .srw .mpo ", "params",40); RAWfiletypes = zstrdup(".arw .srf .sr2 .crw .cr2 .cr3 .dng .mdc .mrw .nef .nr w .raw .rw2 .srw .mpo ", "params",40);
VIDEOfiletypes = zstrdup(".mp4 .flv .mov .avi .wmv .mpeg .mpg .h264 .webm ", "params",40); VIDEOfiletypes = zstrdup(".mp4 .flv .mov .avi .wmv .mpeg .mpg .h264 .webm ", "params",40);
BLACK[0] = BLACK[1] = BLACK[2] = 0; // define RGB colors BLACK[0] = BLACK[1] = BLACK[2] = 0; // define RGB colors
WHITE[0] = WHITE[1] = WHITE[2] = 255; WHITE[0] = WHITE[1] = WHITE[2] = 255;
RED[0] = 255; RED[1] = RED[2] = 0; RED[0] = 255; RED[1] = RED[2] = 0;
GREEN[1] = 255; GREEN[0] = GREEN[2] = 0; GREEN[1] = 255; GREEN[0] = GREEN[2] = 0;
BLUE[2] = 255; BLUE[0] = BLUE[1] = 0; BLUE[2] = 255; BLUE[0] = BLUE[1] = 0;
memcpy(LINE_COLOR,RED,3*sizeof(int)); // initial foreground drawing color memcpy(LINE_COLOR,RED,3*sizeof(int)); // initial foreground drawing color
Nval = (int *) zmalloc(maximages * sizeof(int),"Nval"); // static integer values 0-maximages Nval = (int *) zmalloc(maximages * sizeof(int),"Nval"); // static integer values 0-maximages
for (int ii = 0; ii < maximages; ii++) Nval[ii] = ii; for (int ii = 0; ii < maximages; ii++) Nval[ii] = ii;
zshell("log","gsettings set org.gnome.mutter check-alive-timeout 10000"); // no-resonse timeout = 10 sec. 22.31 zshell(0,"gsettings set org.gnome.mutter check-alive-timeout 10000"); // no-resonse timeout = 10 sec. 22.31
// file and folder names in fotoxx home folder: /home/<user>/.fotoxx/* // file and folder names in fotoxx home folder: /home/<user>/.fotoxx/*
#define makehomefolder(name1,name2) \ #define makehomefolder(name1,name2) \
snprintf(name1,200,"%s/"#name2,get_zhomedir()); \ snprintf(name1,200,"%s/"#name2,get_zhomedir()); \
if (! dirfile(name1)) mkdir(name1,0750); if (! dirfile(name1)) mkdir(name1,0750);
makehomefolder(index_folder,image_index_E) // image index folder, this release
makehomefolder(albums_folder,albums) makehomefolder(albums_folder,albums)
makehomefolder(custom_kernel_folder,custom_kernel) makehomefolder(custom_kernel_folder,custom_kernel)
makehomefolder(file_maps_folder,file_maps) makehomefolder(scripts_folder,custom_scripts)
// 22.30 makehomefolder(file_maps_folder,file_maps)
makehomefolder(index_folder,image_index_E)
// image index folder, this release
makehomefolder(image_table_maps_folder,image_table_maps)
makehomefolder(markup_folder,markup) makehomefolder(markup_folder,markup)
makehomefolder(mashup_folder,mashup) makehomefolder(mashup_folder,mashup)
makehomefolder(image_table_maps_folder,image_table_maps)
makehomefolder(palettes_folder,palettes) makehomefolder(palettes_folder,palettes)
makehomefolder(pattern_folder,patterns) makehomefolder(pattern_folder,patterns)
makehomefolder(printer_color_folder,printer_color) makehomefolder(printer_color_folder,printer_color)
makehomefolder(retouch_folder,retouch) makehomefolder(retouch_folder,retouch)
makehomefolder(saved_areas_folder,saved_areas) makehomefolder(saved_areas_folder,saved_areas)
makehomefolder(saved_curves_folder,saved_curves) makehomefolder(saved_curves_folder,saved_curves)
makehomefolder(scripts_folder,custom_scripts)
makehomefolder(search_settings_folder,saved_searches) makehomefolder(search_settings_folder,saved_searches)
makehomefolder(slideshow_folder,slideshows) makehomefolder(slideshow_folder,slideshows)
makehomefolder(slideshow_trans_folder,slideshow_trans) makehomefolder(slideshow_trans_folder,slideshow_trans)
snprintf(blacklist_file,199,"%s/blacklist",get_zhomedir());
// blacklist folders and files
snprintf(capskeys_file,199,"%s/capskeys",get_zhomedir());
// metadata keys for image captions 22.20
snprintf(gallerymem_file,199,"%s/gallery_memory",get_zhomedir());
// recent gallery memory
snprintf(image_folders_file,199,"%s/image_folders",index_folder); // top image and thumbnail folders snprintf(image_folders_file,199,"%s/image_folders",index_folder); // top image and thumbnail folders
snprintf(image_index_file,199,"%s/image_index",index_folder); // image index file snprintf(image_index_file,199,"%s/image_index",index_folder); // image index file
snprintf(KB_shortcuts_user,199,"%s/KB_shortcuts_E",get_zhomedir());
// KB shortcuts - user defined
snprintf(KB_shortcuts_default,199,"%s/KB_shortcuts_E",get_zdatadir());
// KB shortcuts - fotoxx defaults
snprintf(meta_index_file,199,"%s/meta_index",index_folder); // index extra metadata items snprintf(meta_index_file,199,"%s/meta_index",index_folder); // index extra metadata items
snprintf(tags_defined_file,199,"%s/tags_defined",get_zhomedir());
// defined tags file
snprintf(recentfiles_file,199,"%s/recent_files",get_zhomedir());
// recent files file
snprintf(gallerymem_file,199,"%s/gallery_memory",get_zhomedir());
// recent gallery memory
snprintf(searchresults_file,199,"%s/search_results",get_zhomedir());
// output of image search function
snprintf(meta_picklist_file,199,"%s/meta_picklist_E",get_zhomedir()); // metadata picklist file snprintf(meta_picklist_file,199,"%s/meta_picklist_E",get_zhomedir()); // metadata picklist file
snprintf(meta_report_items_file,199,"%s/meta_report_items",get_zhomedir()); // metadata batch report items
snprintf(meta_view_extras_file,199,"%s/meta_view_extra",get_zhomedir()); // view_meta extra items picklist snprintf(meta_view_extras_file,199,"%s/meta_view_extra",get_zhomedir()); // view_meta extra items picklist
snprintf(meta_report_items_file,199,"%s/meta_report_items",get_zhomedir());
// keynames for metadata report
snprintf(KB_shortcuts_user,199,"%s/KB_shortcuts_E",get_zhomedir());
// KB shortcuts - user defined
snprintf(KB_shortcuts_default,199,"%s/KB_shortcuts_E",get_zdatadir());
// KB shortcuts - fotoxx defaults
snprintf(blacklist_file,199,"%s/blacklist",get_zhomedir());
// blacklist folders and files
snprintf(popup_text_file,199,"%s/popup_text",get_zhomedir()); // popup text for edit widget insertion snprintf(popup_text_file,199,"%s/popup_text",get_zhomedir()); // popup text for edit widget insertion
snprintf(capskeys_file,199,"%s/capskeys",get_zhomedir()); snprintf(recentfiles_file,199,"%s/recent_files",get_zhomedir());
// metadata keys for image captions 22.20 // recent files file
snprintf(searchresults_file,199,"%s/search_results",get_zhomedir());
// output of image search function
snprintf(tags_defined_file,199,"%s/tags_defined",get_zhomedir());
// defined tags file
// delete fotoxx temp files if owner process is no longer running // delete fotoxx temp files if owner process is no longer running
pidlist = 0; pidlist = 0;
snprintf(buff,200,"pidof %s",argv[0]); // get active fotoxx PIDs snprintf(buff,200,"pidof %s",argv[0]); // get active fotoxx PIDs
fid = popen(buff,"r"); fid = popen(buff,"r");
if (fid) { if (fid) {
pp = fgets_trim(buff,200,fid); pp = fgets_trim(buff,200,fid);
if (pp) pidlist = zstrdup(pp,"params"); if (pp) pidlist = zstrdup(pp,"params");
pclose(fid); pclose(fid);
} }
if (! pidlist) pidlist = zstrdup("none","params"); if (! pidlist) pidlist = zstrdup("none","params");
snprintf(temp_folder,200,"%s/temp/temp-*",get_zhomedir()); // get existing /.../temp/temp-xxxxx snprintf(temp_folder,200,"%s/temp/temp-*",get_zhomedir()); // get existing /.../temp/temp-xxxxx
snprintf(buff,200,"find %s -type d 2>/dev/null",temp_folder); snprintf(buff,200,"find %s -type d 2>/dev/null",temp_folder);
fid = popen(buff,"r"); fid = popen(buff,"r");
while ((pp = fgets_trim(buff,200,fid))) { // loop temp folders while ((pp = fgets_trim(buff,200,fid))) { // loop temp folders
pid = strrchr(pp,'-'); // -xxxxx (pid) pid = strrchr(pp,'-'); // -xxxxx (pid)
if (! pid) continue; if (! pid) continue;
if (strstr(pidlist,pid+1)) continue; // PID still active, do not delete if (strstr(pidlist,pid+1)) continue; // PID still active, do not delete
zshell("log","rm -R -f -v %s",pp); // delete folder and contents zshell("ack","rm -R -f %s",pp); // delete folder and contents
} }
pclose(fid); pclose(fid);
zfree(pidlist); zfree(pidlist);
// set up temp folder /.../temp/temp-xxxx/ where xxxx is owner PID // set up temp folder /.../temp/temp-xxxx/ where xxxx is owner PID
snprintf(temp_folder,200,"%s/temp/temp-%d",get_zhomedir(),getpid()); snprintf(temp_folder,200,"%s/temp/temp-%d",get_zhomedir(),getpid());
err = zshell("log ack","mkdir -p -m 0750 %s",temp_folder); err = zshell("ack","mkdir -p -m 0750 %s",temp_folder);
if (err) quitxx(); if (err) quitxx();
Plog(1,"temp files: %s \n",temp_folder); Plog(1,"temp files: %s \n",temp_folder);
snprintf(URS_filename,100,"%s/undo_nn",temp_folder); // file name template for undo/redo files snprintf(URS_filename,200,"%s/undo_nn",temp_folder); // file name template for undo/redo files
// determine if file maps have been downloaded // determine if file maps have been downloaded
snprintf(filename,200,"%s/maps_index",file_maps_folder); // check if file maps index exists 22.30 snprintf(filename,200,"%s/maps_index",file_maps_folder); // check if file maps index exists 22.30
if (regfile(filename)) if (regfile(filename))
Plog(1,"file maps installed at %s \n",file_maps_folder); Plog(1,"file maps installed at %s \n",file_maps_folder);
else Plog(1,"file maps not installed \n"); else Plog(1,"file maps not installed \n");
// restore parameters from last session // restore parameters from last session
load_params(); load_params();
// get command line parameters // get command line parameters
for (ii = 1; ii < argc; ii++) for (ii = 1; ii < argc; ii++)
{ {
char *pp = argv[ii]; ch *pp = argv[ii];
if (strmatch(pp,"-home")) ii++; // -home homedir skip, see above if (strmatch(pp,"-home")) ii++; // -home homedir skip, see above
else if (strmatchV(pp,"-help","-h",0)) // -h -help show user guide else if (strmatchV(pp,"-help","-h",0)) // -h -help show user guide
showz_docfile(Mwin,"userguide","command parameters"); showz_docfile(Mwin,"userguide","command parameters");
else if (strmatchV(pp,"-clone","-c",0) && argc > ii+4) { // -c -clone clone new instance else if (strmatchV(pp,"-clone","-c",0) && argc > ii+4) { // -c -clone clone new instance
Fclone = 1; Fclone = 1;
cloxx = atoi(argv[ii+1]); // window position and size cloxx = atoi(argv[ii+1]); // window position and size
cloyy = atoi(argv[ii+2]); // passed from parent instance cloyy = atoi(argv[ii+2]); // passed from parent instance
cloww = atoi(argv[ii+3]); cloww = atoi(argv[ii+3]);
clohh = atoi(argv[ii+4]); clohh = atoi(argv[ii+4]);
skipping to change at line 432 skipping to change at line 433
Ftinycomputer = 1; Ftinycomputer = 1;
Plog(0,"computer has inadequate memory \n"); Plog(0,"computer has inadequate memory \n");
} }
Plog(1,"image size limits for reasonable performance: \n"); Plog(1,"image size limits for reasonable performance: \n");
Plog(1," view: %.0f megapixels \n",(freememory-1000)/6); // F + preview, 3 bytes/pixel each Plog(1," view: %.0f megapixels \n",(freememory-1000)/6); // F + preview, 3 bytes/pixel each
Plog(1," edit: %.0f megapixels \n",(freememory-1000)/64); // + E0/E1/E3/ER, 16 bytes/pixel each Plog(1," edit: %.0f megapixels \n",(freememory-1000)/64); // + E0/E1/E3/ER, 16 bytes/pixel each
err = get_smp_counts(Nperf,Neff); // get CPU perf. and eff. cores 22.40 err = get_smp_counts(Nperf,Neff); // get CPU perf. and eff. cores 22.40
Plog(1,"Pcores: %d Ecores: %d \n",Nperf,Neff); Plog(1,"Pcores: %d Ecores: %d \n",Nperf,Neff);
if (err) NWT = 4;
else NWT = Nperf;
if (NWT > max_threads) NWT = max_threads;
// max. edit function threads
NST = 2 * NWT;
// max. metadata server threads
if (NST > maxNST) NST = maxNST;
// compile time limit
Plog(1,"using %d edit threads and %d metadata search threads \n",NWT,NST);
// get locale specific name for /home/<user>/Desktop // get locale specific name for /home/<user>/Desktop
strcpy(desktopname,"Desktop"); strcpy(desktopname,"Desktop");
snprintf(filename,200,"%s/.config/user-dirs.dirs",getenv("HOME")); snprintf(filename,200,"%s/.config/user-dirs.dirs",getenv("HOME"));
fid = fopen(filename,"r"); fid = fopen(filename,"r");
if (fid) { if (fid) {
while (true) { while (true) {
pp = fgets_trim(buff,200,fid); pp = fgets_trim(buff,200,fid);
skipping to change at line 676 skipping to change at line 669
} }
/******************************************************************************* */ /******************************************************************************* */
// Check that necessary outboard programs are installed. // Check that necessary outboard programs are installed.
// List optional programs for added capabilities. // List optional programs for added capabilities.
// Return 0/1 if all required programs are/not installed. // Return 0/1 if all required programs are/not installed.
int check_outboards(int fshow) // 22.1 int check_outboards(int fshow) // 22.1
{ {
zdialog *zd; zdialog *zdpop;
int err; int err;
cchar *YN[13] = { "No", "No", "No", "No", "No", "No", "No", "No", "No", "N o", "No", "No", "No" }; ch *YN[13] = { "No", "No", "No", "No", "No", "No", "No", "No", "No", "N o", "No", "No", "No" };
err = zshell(0,"which exiftool >/dev/null 2>&1"); // check for exiftool err = zshell(0,"which exiftool >/dev/null 2>&1"); // check for exiftool
if (! err) { Fexiftool = 1; YN[0] = "Yes"; } if (! err) { Fexiftool = 1; YN[0] = "Yes"; }
err = zshell(0,"which dcraw >/dev/null 2>&1"); // check for Dcraw err = zshell(0,"which dcraw >/dev/null 2>&1"); // check for Dcraw
if (! err) { Fdcraw = 1; YN[1] = "Yes"; } if (! err) { Fdcraw = 1; YN[1] = "Yes"; }
err = zshell(0,"which addr2line >/dev/null 2>&1"); // check for addr2line err = zshell(0,"which addr2line >/dev/null 2>&1"); // check for addr2line
if (! err) { Faddr2line = 1; YN[2] = "Yes"; } if (! err) { Faddr2line = 1; YN[2] = "Yes"; }
skipping to change at line 721 skipping to change at line 714
if (! err) { Fdarktablecli = 1; YN[10] = "Yes"; } if (! err) { Fdarktablecli = 1; YN[10] = "Yes"; }
err = zshell(0,"which growisofs >/dev/null 2>&1"); // check for growisofs err = zshell(0,"which growisofs >/dev/null 2>&1"); // check for growisofs
if (! err) { Fgrowisofs = 1; YN[11] = "Yes"; } if (! err) { Fgrowisofs = 1; YN[11] = "Yes"; }
err = zshell(0,"which vlc >/dev/null 2>&1"); // check for vlc 22.31 err = zshell(0,"which vlc >/dev/null 2>&1"); // check for vlc 22.31
if (! err) { Fvlc = 1; YN[12] = "Yes"; } if (! err) { Fvlc = 1; YN[12] = "Yes"; }
if (fshow || ! Fdcraw || ! Fexiftool || ! Faddr2line) // show table if first install or 22.31 if (fshow || ! Fdcraw || ! Fexiftool || ! Faddr2line) // show table if first install or 22.31
{ // any required programs missing { // any required programs missing
zd = popup_report_open("Outboard Programs",Mwin,900,400,1,0,"OK",0); zdpop = popup_report_open("Outboard Programs",Mwin,900,400,1,0,"OK",0);
popup_report_write(zd,1, "PROGRAM PURPOSE REQUIRED INSTALLED popup_report_write(zdpop,1, "PROGRAM PURPOSE REQUIRED INSTAL
PACKAGE (DEBIAN NAME) \n"); LED PACKAGE (DEBIAN NAME) \n");
popup_report_write(zd,0, "exiftool metadata YES %-3s popup_report_write(zdpop,0, "exiftool metadata YES %-3
libimage-exiftool-perl \n",YN[0]); s libimage-exiftool-perl \n",YN[0]);
popup_report_write(zd,0, "dcraw RAW files YES %-3s popup_report_write(zdpop,0, "dcraw RAW files YES %-3
dcraw \n",YN[1]); s dcraw \n",YN[1]);
popup_report_write(zd,0, "addr2line crash report YES %-3s popup_report_write(zdpop,0, "addr2line crash report YES %-3
binutils \n",YN[2]); s binutils \n",YN[2]);
popup_report_write(zd,0, "ffmpeg video files No %-3s popup_report_write(zdpop,0, "ffmpeg video files No %-3
ffmpeg \n",YN[3]); s ffmpeg \n",YN[3]);
popup_report_write(zd,0, "dwebp .webp files No %-3s popup_report_write(zdpop,0, "dwebp .webp files No %-3
wepb \n",YN[4]); s wepb \n",YN[4]);
popup_report_write(zd,0, "heif-convert .heic files No %-3s popup_report_write(zdpop,0, "heif-convert .heic files No %-3
libheif-examples \n",YN[5]); s libheif-examples \n",YN[5]);
popup_report_write(zd,0, "opj_decompress .jp2 files No %-3s popup_report_write(zdpop,0, "opj_decompress .jp2 files No %-3
libopenjp2-tools \n",YN[6]); s libopenjp2-tools \n",YN[6]);
popup_report_write(zd,0, "rawtherapee RAW editor No %-3s popup_report_write(zdpop,0, "rawtherapee RAW editor No %-3
rawtherapee \n",YN[7]); s rawtherapee \n",YN[7]);
popup_report_write(zd,0, "rawtherapee-cli RAW convert No %-3s popup_report_write(zdpop,0, "rawtherapee-cli RAW convert No %-3
rawtherapee \n",YN[8]); s rawtherapee \n",YN[8]);
popup_report_write(zd,0, "darktable RAW editor No %-3s popup_report_write(zdpop,0, "darktable RAW editor No %-3
darktable \n",YN[9]); s darktable \n",YN[9]);
popup_report_write(zd,0, "darktable-cli RAW convert No %-3s popup_report_write(zdpop,0, "darktable-cli RAW convert No %-3
darktable \n",YN[10]); s darktable \n",YN[10]);
popup_report_write(zd,0, "growisofs write DVD/BR No %-3s popup_report_write(zdpop,0, "growisofs write DVD/BR No %-3
growisofs \n",YN[11]); s growisofs \n",YN[11]);
popup_report_write(zd,0, "vlc media play No %-3s popup_report_write(zdpop,0, "vlc media play No %-3
vlc \n",YN[12]); s vlc \n",YN[12]);
if (! Fdcraw || ! Fexiftool || ! Faddr2line) // 22.31 if (! Fdcraw || ! Fexiftool || ! Faddr2line) // 22.31
{ {
popup_report_write(zd,0,"\n"); popup_report_write(zdpop,0,"\n");
popup_report_write(zd,1,"Please install the following programs using yo popup_report_write(zdpop,1,"Please install the following programs using
ur package manager: \n"); your package manager: \n");
if (! Fdcraw) popup_report_write(zd,0," dcraw \n"); if (! Fdcraw) popup_report_write(zdpop,0," dcraw \n");
if (! Fexiftool) popup_report_write(zd,0," exiftool \n"); if (! Fexiftool) popup_report_write(zdpop,0," exiftool \n");
if (! Faddr2line) popup_report_write(zd,0," addr2line \n"); if (! Faddr2line) popup_report_write(zdpop,0," addr2line \n");
} }
zdialog_wait(zd); zdialog_wait(zdpop);
} }
// list optional programs and installation status // list optional programs and installation status
if (! Fexiftool) Plog(0,"exiftool not installed (REQUIRED) \n"); if (! Fexiftool) Plog(0,"exiftool not installed (REQUIRED) \n");
if (! Fdcraw) Plog(0,"dcraw not installed (REQUIRED) \n"); if (! Fdcraw) Plog(0,"dcraw not installed (REQUIRED) \n");
if (! Faddr2line) Plog(0,"addr2line not installed (REQUIRED) \n"); // now required 22.30 if (! Faddr2line) Plog(0,"addr2line not installed (REQUIRED) \n"); // now required 22.30
skipping to change at line 793 skipping to change at line 786
if (Fdcraw + Fexiftool + Faddr2line < 3) return 1; // all required programs not installed if (Fdcraw + Fexiftool + Faddr2line < 3) return 1; // all required programs not installed
return 0; // required programs are installed return 0; // required programs are installed
} }
/******************************************************************************* */ /******************************************************************************* */
// Fotoxx first startup - initial user decision about indexing // Fotoxx first startup - initial user decision about indexing
void first_startup() void first_startup()
{ {
char thumbfolder[200]; ch thumbfolder[200];
zdialog *zd; zdialog *zd;
int yn, zstat, nn, err; int yn, zstat, nn, err;
cchar *defer1 = " Defer image file indexing:"; ch *defer1 = " Defer image file indexing:";
cchar *defer2 = " • Fotoxx will start immediately \n" ch *defer2 = " • Fotoxx will start immediately \n"
" • View and edit image files will work normally \n" " • View and edit image files will work normally \n"
" • Image search, batch and map functions will not work \n" " • Image search, batch and map functions will not work \n"
" • Thumbnail galleries will be slow"; " • Thumbnail galleries will be slow";
cchar *index1 = " Index image files now:"; ch *index1 = " Index image files now:";
cchar *index2 = " • Initial indexing may need considerable time \n" ch *index2 = " • Initial indexing may need considerable time \n"
" • Subsequent startups will be fast \n" " • Subsequent startups will be fast \n"
" • Full functionality will be available \n" " • Full functionality will be available \n"
" • Thumbnail galleries will be fast"; " • Thumbnail galleries will be fast";
cchar *info = " Indexing time depends on the number of image files and the \n" ch *info = " Indexing time depends on the number of image files and the \n"
" speed of your computer. This can be a few hundred to a few \n" " speed of your computer. This can be a few hundred to a few \n"
" thousand per minute. After indexing is done, startup time \n" " thousand per minute. After indexing is done, startup time \n"
" should be quite fast. You can change index options later, \n" " should be quite fast. You can change index options later, \n"
" using these menus: Tools > Index, Tools > Settings. \n" " using these menus: Tools > Index, Tools > Settings. \n"
" \n" " \n"
" WARNING: Some image collections include corrupted files \n " " WARNING: Some image collections include corrupted files \n "
" that can cause Fotoxx or a library function to crash. \n" " that can cause Fotoxx or a library function to crash. \n"
" Delete or move the file elsewhere and start Fotoxx again." ; " Delete or move the file elsewhere and start Fotoxx again." ;
if (Ftinycomputer) { if (Ftinycomputer) {
skipping to change at line 936 skipping to change at line 929
int state_event(GtkWidget *, GdkEvent *event) // main window state changed int state_event(GtkWidget *, GdkEvent *event) // main window state changed
{ {
int state = ((GdkEventWindowState *) event)->new_window_state; // track window fullscreen status int state = ((GdkEventWindowState *) event)->new_window_state; // track window fullscreen status
if (state & GDK_WINDOW_STATE_FULLSCREEN) Ffullscreen = 1; if (state & GDK_WINDOW_STATE_FULLSCREEN) Ffullscreen = 1;
else if (state & GDK_WINDOW_STATE_MAXIMIZED) Ffullscreen = 1; else if (state & GDK_WINDOW_STATE_MAXIMIZED) Ffullscreen = 1;
else Ffullscreen = 0; else Ffullscreen = 0;
return 0; return 0;
} }
void drop_event(int mousex, int mousey, char *file) // file drag-drop event void drop_event(int mousex, int mousey, ch *file) // file drag-drop event
{ {
if (! file) return; if (! file) return;
Plog(1,"drag-drop file: %s \n",file); Plog(1,"drag-drop file: %s \n",file);
f_open(file,0,0,1); f_open(file,0,0,1);
return; return;
} }
/******************************************************************************* * /******************************************************************************* *
check for mutual exclusion function (blocked) and/or unsaved image edits check for mutual exclusion function (blocked) and/or unsaved image edits
skipping to change at line 969 skipping to change at line 962
null blocking function done: remove block null blocking function done: remove block
returns: returns:
0 not blocked, no unsaved edits (or user discards), success 0 not blocked, no unsaved edits (or user discards), success
1 blocking function is active, cannot block again 1 blocking function is active, cannot block again
2 unsaved edits, image or metadata, and user says to keep 2 unsaved edits, image or metadata, and user says to keep
if both 1 and 2 are true, 1 is returned if both 1 and 2 are true, 1 is returned
****/ ****/
int Fblock(cchar *fname, cchar *arglist) int Fblock(cch *fname, ch *arglist)
{ {
static int Fblockactive = 0; // blocking function is active static int Fblockactive = 0; // blocking function is active
int Funsavededits, choice; int Funsavededits, choice;
int Fblock = 0, Fblocked = 0, Fedits = 0, Fquiet = 0; int Fblock = 0, Fblocked = 0, Fedits = 0, Fquiet = 0;
cchar *modmess = "This action will discard changes to current image"; ch *modmess = "This action will discard changes to current image";
cchar *activemess = "prior function still active"; ch *activemess = "prior function still active";
if (fname) Plog(1,"Fblock(%s,%s)\n",fname,arglist); if (fname) Plog(2,"Fblock(%s,%s)\n",fname,arglist);
Funsavededits = 0; Funsavededits = 0;
if (CEF && CEF->Fmods && ! CEF->Fsaved) Funsavededits = 1; // active edits unsaved if (CEF && CEF->Fmods && ! CEF->Fsaved) Funsavededits = 1; // active edits unsaved
if (URS_pos > 0 && URS_saved[URS_pos] == 0) Funsavededits = 1; // completed edits unsaved if (URS_pos > 0 && URS_saved[URS_pos] == 0) Funsavededits = 1; // completed edits unsaved
if (Fmetamod) Funsavededits = 1; // metadata edits unsaved if (Fmetamod) Funsavededits = 1; // metadata edits unsaved
if (! arglist) { // (null) = blocking function done if (! arglist) { // (null) = blocking function done
if (! Fblockactive && ! Funsavededits) // should not happen if (! Fblockactive && ! Funsavededits) // should not happen
Plog(1,"Fblock(0): not blocked \n"); Plog(2,"Fblock(0): not blocked \n");
Fblockactive = 0; // unblock Fblockactive = 0; // unblock
return 0; // OK return return 0; // OK return
} }
if (strstr(arglist,"blocked")) Fblocked = 1; if (strstr(arglist,"blocked")) Fblocked = 1;
if (! Fblocked && strstr(arglist,"block")) Fblock = 1; // stop substring match if (! Fblocked && strstr(arglist,"block")) Fblock = 1; // stop substring match
if (strstr(arglist,"edits")) Fedits = 1; if (strstr(arglist,"edits")) Fedits = 1;
if (strstr(arglist,"quiet")) Fquiet = 1; if (strstr(arglist,"quiet")) Fquiet = 1;
if (Fblockactive && Fblock) { // block + already blocked if (Fblockactive && Fblock) { // block + already blocked
skipping to change at line 1056 skipping to change at line 1049
} }
/******************************************************************************* */ /******************************************************************************* */
// update F window top panel with current status information // update F window top panel with current status information
// called from timer function // called from timer function
void update_Fpanel() void update_Fpanel()
{ {
static double time1 = 0, time2, cpu1 = 0, cpu2, cpuload; static double time1 = 0, time2, cpu1 = 0, cpu2, cpuload;
char *pp, text1[300], text2[200]; ch *pp, text1[300], text2[200];
char digitblank[4] = " "; ch digitblank[4] = " ";
// digit blank: 0x2007 0x00 // digit blank: 0x2007 0x00
static char ptext1[300] = ""; static ch ptext1[300] = "";
int ww, hh, scale, bpc; int ww, hh, scale, bpc;
static int ftf = 1; static int ftf = 1;
double file_MB = 1.0 / MEGA * curr_file_size; double file_MB = 1.0 / MEGA * curr_file_size;
static cchar *reduced, *areaactive, *dialogopen; static ch *reduced, *areaactive, *dialogopen;
static cchar *blocked, *modified; static ch *blocked, *modified;
if (! main_thread()) return; // thread caller if (! main_thread()) return; // thread caller
if (! Fpanelshow) return; // panel currently hidden if (! Fpanelshow) return; // panel currently hidden
if (ftf) { if (ftf) {
ftf = 0; ftf = 0;
reduced = "(reduced)"; reduced = "(reduced)";
areaactive = "area active"; areaactive = "area active";
dialogopen = "dialog open"; dialogopen = "dialog open";
skipping to change at line 1150 skipping to change at line 1143
if (sa_stat == 3) strncatv(text1,300," ",areaactive,0); if (sa_stat == 3) strncatv(text1,300," ",areaactive,0);
if (zfuncs::zdialog_busy) strncatv(text1,300," ",dialogopen,0); if (zfuncs::zdialog_busy) strncatv(text1,300," ",dialogopen,0);
if (Fblock(0,"blocked quiet")) strncatv(text1,300," ",blocked,0); // blocking function active if (Fblock(0,"blocked quiet")) strncatv(text1,300," ",blocked,0); // blocking function active
if (CEF && CEF->Fmods) strncatv(text1,300," ",modified,0); // image is modified if (CEF && CEF->Fmods) strncatv(text1,300," ",modified,0); // image is modified
if (*paneltext) strncatv(text1,300," ",paneltext,0); // application text if (*paneltext) strncatv(text1,300," ",paneltext,0); // application text
if (curr_file) { if (curr_file) {
pp = strrchr(curr_file,'/'); // add filename.jpg pp = strrchr(curr_file,'/'); // add filename.jpg
if (pp && Ffullscreen && ! Ffuncbusy && ! Fthreadbusy) { if (pp && Ffullscreen && ! Ffuncbusy) {
strncpy0(text2,pp+1,100); strncpy0(text2,pp+1,100);
strncatv(text1,300," ",text2,0); strncatv(text1,300," ",text2,0);
} }
} }
if (! strmatch(text1,ptext1)) { // if text changed, update panel bar if (! strmatch(text1,ptext1)) { // if text changed, update panel bar
gtk_label_set_label(GTK_LABEL(Fpanlab),text1); gtk_label_set_label(GTK_LABEL(Fpanlab),text1);
gtk_widget_show_all(Fpanel); gtk_widget_show_all(Fpanel);
strcpy(ptext1,text1); strcpy(ptext1,text1);
} }
// Show BUSY label if Ffuncbusy or Fthreadbusy active. // Show BUSY label if Ffuncbusy active.
// Show progress counter if progress_percent() > 0 // Show progress counter if progress_percent() > 0
// added to top panel: xx% or BUSY if no xx% // added to top panel: xx% or BUSY if no xx%
update_busy: update_busy:
static GtkWidget *busylabel = 0, *donelabel = 0; static GtkWidget *busylabel = 0, *donelabel = 0;
static cchar *busytext = "<span font=\"bold\" fgcolor=\"red\" > BUSY </s static ch busytext[] = "<span font=\"bold\" fgcolor=\"red\" > BUSY </
pan>"; span>";
static char donetext[] = "<span font=\"bold\" fgcolor=\"red\" > xx% </s static ch donetext[] = "<span font=\"bold\" fgcolor=\"red\" > xx% </s
pan>"; pan>";
static char *doneposn = 0; static ch *doneposn = 0;
GtkWidget *FGpanel; GtkWidget *FGpanel;
int pct; int pct;
char nn[4]; ch nn[4];
if (! doneposn) doneposn = strstr(donetext,"xx%"); // get position to insert % done if (! doneposn) doneposn = (ch *) strstr(donetext,"xx%"); // get position to insert % done
if (FGWM == 'F') FGpanel = Fpanel; if (FGWM == 'F') FGpanel = Fpanel;
else if (FGWM == 'G') FGpanel = Gpanel; else if (FGWM == 'G') FGpanel = Gpanel;
else return; else return;
pct = progress_percent(); // show progress in top panel pct = progress_percent(); // show progress in top panel
if (pct > 0) { if (pct > 0) {
if (pct > 99) pct = 99; if (pct > 99) pct = 99;
snprintf(nn,4,"%02d",pct); snprintf(nn,4,"%02d",pct);
memcpy(doneposn,nn,2); memcpy(doneposn,nn,2);
skipping to change at line 1202 skipping to change at line 1195
if (busylabel) gtk_widget_destroy(busylabel); if (busylabel) gtk_widget_destroy(busylabel);
busylabel = 0; busylabel = 0;
gtk_widget_show_all(FGpanel); gtk_widget_show_all(FGpanel);
return; return;
} }
else { else {
if (donelabel) gtk_widget_destroy(donelabel); if (donelabel) gtk_widget_destroy(donelabel);
donelabel = 0; donelabel = 0;
} }
if (Ffuncbusy || Fthreadbusy) { // add " BUSY" to top panel if (Ffuncbusy) { // add " BUSY" to top panel
if (! busylabel) { if (! busylabel) {
busylabel = gtk_label_new(null); busylabel = gtk_label_new(null);
gtk_label_set_markup(GTK_LABEL(busylabel),busytext); gtk_label_set_markup(GTK_LABEL(busylabel),busytext);
gtk_box_pack_start(GTK_BOX(FGpanel),busylabel,0,0,5); gtk_box_pack_start(GTK_BOX(FGpanel),busylabel,0,0,5);
} }
} }
else { else {
if (busylabel) gtk_widget_destroy(busylabel); if (busylabel) gtk_widget_destroy(busylabel);
busylabel = 0; busylabel = 0;
} }
skipping to change at line 1717 skipping to change at line 1710
// F/W view - window mouse event function - capture buttons and drag movements // F/W view - window mouse event function - capture buttons and drag movements
void mouse_event(GtkWidget *widget, GdkEventButton *event, void *) void mouse_event(GtkWidget *widget, GdkEventButton *event, void *)
{ {
void mouse_convert(int xpos1, int ypos1, int &xpos2, int &ypos2); void mouse_convert(int xpos1, int ypos1, int &xpos2, int &ypos2);
int button, time, type, scroll; int button, time, type, scroll;
static int bdtime = 0, butime = 0; static int bdtime = 0, butime = 0;
static int dragstart = 0, mdragx0, mdragy0; static int dragstart = 0, mdragx0, mdragy0;
char *pp; ch *pp;
#define GAPR GDK_AXIS_PRESSURE #define GAPR GDK_AXIS_PRESSURE
if (! Cdrawin) return; if (! Cdrawin) return;
if (! gdkwin) return; if (! gdkwin) return;
if (! Cstate || ! Cstate->fpxb) return; // no image if (! Cstate || ! Cstate->fpxb) return; // no image
type = event->type; type = event->type;
button = event->button; // button, 1/2/3 = left/center/right button = event->button; // button, 1/2/3 = left/center/right
time = event->time; time = event->time;
skipping to change at line 1894 skipping to change at line 1887
/******************************************************************************* */ /******************************************************************************* */
// set new image zoom level or magnification // set new image zoom level or magnification
// zoom: meaning: // zoom: meaning:
// in zoom-in in steps // in zoom-in in steps
// out zoom-out in steps // out zoom-out in steps
// fit zoom to fit window (image < window >> 1x) // fit zoom to fit window (image < window >> 1x)
// fit+ zoom to fit window (image < window >> fit window) // fit+ zoom to fit window (image < window >> fit window)
// toggle toggle 1x and fit window (Z-key) (image < window >> fit window ) // toggle toggle 1x and fit window (Z-key) (image < window >> fit window )
void m_zoom(GtkWidget *, cchar *zoom) void m_zoom(GtkWidget *, ch *zoom)
{ {
int fww, fhh; int fww, fhh;
float scalew, scaleh, fitscale, fzoom2; float scalew, scaleh, fitscale, fzoom2;
float Czoom, Gzoom = 0, pixels; float Czoom, Gzoom = 0, pixels;
if (! Cdrawin) return; if (! Cdrawin) return;
if (! gdkwin) return; if (! gdkwin) return;
if (! Cstate || ! Cstate->fpxb) return; // no image if (! Cstate || ! Cstate->fpxb) return; // no image
Plog(2,"m_zoom\n"); Plog(2,"m_zoom\n");
skipping to change at line 1989 skipping to change at line 1982
// GDK key symbols: /usr/include/gtk-3.0/gdk/gdkkeysyms.h // GDK key symbols: /usr/include/gtk-3.0/gdk/gdkkeysyms.h
namespace crop_names { void KBfunc(int key); } // keyboard functions called from here namespace crop_names { void KBfunc(int key); } // keyboard functions called from here
namespace perspective { void KBfunc(int key); } namespace perspective { void KBfunc(int key); }
namespace mashup { void KBfunc(int key); } namespace mashup { void KBfunc(int key); }
namespace view360 { void KB_func(int key); } namespace view360 { void KB_func(int key); }
int KBpress(GtkWidget *, GdkEventKey *event, void *) // keyboard key was pressed int KBpress(GtkWidget *, GdkEventKey *event, void *) // keyboard key was pressed
{ {
int ii, jj, cc; int ii, jj, cc;
char shortkey[20] = ""; ch shortkey[20] = "";
cchar *KBchar = 0, *action = 0; ch *KBchar = 0, *action = 0;
char *pp, *file = 0, *qfile; ch *pp, *file = 0, *qfile;
static int Fshowmenu = 1; // 22.35 static int Fshowmenu = 1; // 22.35
KBkey = event->keyval; // input key KBkey = event->keyval; // input key
KBchar = gdk_keyval_name(KBkey); // graphic char. for key KBchar = gdk_keyval_name(KBkey); // graphic char. for key
Plog(2,"KB key: %s \n",KBchar); Plog(2,"KB key: %s \n",KBchar);
if ((KBkey & 0xfff0) == 0xffe0) return 1; // Ctrl/Shift/Alt key if ((KBkey & 0xfff0) == 0xffe0) return 1; // Ctrl/Shift/Alt key
KBcontrolkey = KBshiftkey = KBaltkey = 0; // look for combination keys KBcontrolkey = KBshiftkey = KBaltkey = 0; // look for combination keys
if (event->state & GDK_CONTROL_MASK) KBcontrolkey = 1; if (event->state & GDK_CONTROL_MASK) KBcontrolkey = 1;
skipping to change at line 2043 skipping to change at line 2036
if (Fslideshow) { // slide show active if (Fslideshow) { // slide show active
ss_KBfunc(KBkey); // pass key to slide show ss_KBfunc(KBkey); // pass key to slide show
return 1; return 1;
} }
if (Fview360) { // view360 active if (Fview360) { // view360 active
view360::KB_func(KBkey); // pass key to view360 view360::KB_func(KBkey); // pass key to view360
return 1; return 1;
} }
if (KBkey == GDK_KEY_Escape) { if (KBkey == GDK_KEY_Escape) {
// ESC key // [esc] key pressed
Plog(0,"escape key \n"); Plog(0,"escape key \n");
// 22.31 if (Fwatchescape) Fescape = 1;
if (Fescape) Fescape++; // tell pending function to quit 23.1
// killable function active, escalate
else if (Ffullscreen) win_unfullscreen(); // full-screen mode, shrink else if (Ffullscreen) win_unfullscreen(); // full-screen mode, shrink
else if (FGWM != 'F') m_viewmode(0,"F"); else if (FGWM != 'F') m_viewmode(0,"F");
// file view mode if not already 22.1 // file view mode if not already
else if (Fwsl) return 1; else if (Fwsl) return 1;
// Win 11 bug - escape persists 22.31 // Win 11 bug - escape persists
else m_quit(0,0); // quit fotoxx else m_quit(0,0); // quit fotoxx
return 1; // ESC also terminates dialogs return 1; // ESC also terminates dialogs
} }
if (KBkey == GDK_KEY_F10) { // F10: fullscreen toggle with menu if (KBkey == GDK_KEY_F10) { // F10: fullscreen toggle with menu
if (! Ffullscreen) win_fullscreen(0); // toggle full-screen mode and back if (! Ffullscreen) win_fullscreen(0); // toggle full-screen mode and back
else win_unfullscreen(); else win_unfullscreen();
Fshowmenu = 1; Fshowmenu = 1;
return 1; return 1;
} }
skipping to change at line 2076 skipping to change at line 2069
} }
if (KBkey == GDK_KEY_p) // P key, play video file if (KBkey == GDK_KEY_p) // P key, play video file
{ // (OK to also use P in shortcuts) { // (OK to also use P in shortcuts)
if (! curr_file) return 1; if (! curr_file) return 1;
if (image_file_type(curr_file) == VIDEO) if (image_file_type(curr_file) == VIDEO)
{ {
file = zescape_quotes(curr_file); file = zescape_quotes(curr_file);
cc = strlen(file) + 4; cc = strlen(file) + 4;
qfile = (char *) zmalloc(cc,"KBpress"); qfile = (ch *) zmalloc(cc,"KBpress");
strncatv(qfile,cc,"\"",file,"\"",0); strncatv(qfile,cc,"\"",file,"\"",0);
zshell("ack",video_command,qfile); // video-command "curr_file" zshell("ack",video_command,qfile); // video-command "curr_file"
zfree(file); zfree(file);
zfree(qfile); zfree(qfile);
return 1; return 1;
} }
pp = strrchr(curr_file,'.'); // play animated GIF file pp = strrchr(curr_file,'.'); // play animated GIF file
if (pp && strstr(".gif .GIF",pp)) { if (pp && strstr(".gif .GIF",pp)) {
play_gif(curr_file); play_gif(curr_file);
skipping to change at line 2110 skipping to change at line 2103
if (KBkey == GDK_KEY_KP_Add) KBkey = GDK_KEY_plus; // numeric keypad works the same 22.30 if (KBkey == GDK_KEY_KP_Add) KBkey = GDK_KEY_plus; // numeric keypad works the same 22.30
if (KBkey == GDK_KEY_KP_Subtract) KBkey = GDK_KEY_plus; // with/without num-lock if (KBkey == GDK_KEY_KP_Subtract) KBkey = GDK_KEY_plus; // with/without num-lock
if (KBkey == GDK_KEY_KP_7) KBkey = GDK_KEY_Home; if (KBkey == GDK_KEY_KP_7) KBkey = GDK_KEY_Home;
if (KBkey == GDK_KEY_KP_8) KBkey = GDK_KEY_Up; if (KBkey == GDK_KEY_KP_8) KBkey = GDK_KEY_Up;
if (KBkey == GDK_KEY_KP_9) KBkey = GDK_KEY_Page_Up; if (KBkey == GDK_KEY_KP_9) KBkey = GDK_KEY_Page_Up;
if (KBkey == GDK_KEY_KP_4) KBkey = GDK_KEY_Left; if (KBkey == GDK_KEY_KP_4) KBkey = GDK_KEY_Left;
if (KBkey == GDK_KEY_KP_6) KBkey = GDK_KEY_Right; if (KBkey == GDK_KEY_KP_6) KBkey = GDK_KEY_Right;
if (KBkey == GDK_KEY_KP_1) KBkey = GDK_KEY_End; if (KBkey == GDK_KEY_KP_1) KBkey = GDK_KEY_End;
if (KBkey == GDK_KEY_KP_2) KBkey = GDK_KEY_Down; if (KBkey == GDK_KEY_KP_2) KBkey = GDK_KEY_Down;
if (KBkey == GDK_KEY_KP_3) KBkey = GDK_KEY_Page_Down; if (KBkey == GDK_KEY_KP_3) KBkey = GDK_KEY_Page_Down;
if (KBkey == GDK_KEY_KP_Enter) KBkey = GDK_KEY_Return;
if (KBkey == GDK_KEY_Delete) action = (char *) "Delete"; if (KBkey == GDK_KEY_Delete) action = "Delete";
// reserved shortcuts // reserved shortcuts
if (KBkey == GDK_KEY_Left) action = (char *) "Left"; if (KBkey == GDK_KEY_Left) action = "Left";
if (KBkey == GDK_KEY_Right) action = (char *) "Right"; if (KBkey == GDK_KEY_Right) action = "Right";
if (KBkey == GDK_KEY_Up) action = (char *) "Up"; if (KBkey == GDK_KEY_Up) action = "Up";
if (KBkey == GDK_KEY_Down) action = (char *) "Down"; if (KBkey == GDK_KEY_Down) action = "Down";
if (KBkey == GDK_KEY_Home) action = (char *) "Home"; if (KBkey == GDK_KEY_Home) action = "Home";
if (KBkey == GDK_KEY_End) action = (char *) "End"; if (KBkey == GDK_KEY_End) action = "End";
if (KBkey == GDK_KEY_Page_Up) action = (char *) "Page_Up"; if (KBkey == GDK_KEY_Page_Up) action = "Page_Up";
if (KBkey == GDK_KEY_Page_Down) action = (char *) "Page_Down"; if (KBkey == GDK_KEY_Page_Down) action = "Page_Down";
if (KBkey == GDK_KEY_plus) action = (char *) "Zoom+"; if (KBkey == GDK_KEY_plus) action = "Zoom+";
if (KBkey == GDK_KEY_minus) action = (char *) "Zoom-"; if (KBkey == GDK_KEY_minus) action = "Zoom-";
if (KBkey == GDK_KEY_z) action = (char *) "toggle-zoom"; if (KBkey == GDK_KEY_z) action = "toggle-zoom";
if (KBkey == GDK_KEY_Return) action = (char *) "Open"; if (KBkey == GDK_KEY_k) action = "KB Shortcuts";
// 22.30 // 23.1
if (! action) // custom shortcut if (! action) // custom shortcut
{ {
if (KBkey >= GDK_KEY_F2 && KBkey <= GDK_KEY_F9) { // input key is F2 to F9 if (KBkey >= GDK_KEY_F2 && KBkey <= GDK_KEY_F9) { // input key is F2 to F9
ii = KBkey - GDK_KEY_F1; ii = KBkey - GDK_KEY_F1;
strcpy(shortkey,"F1"); // convert to "F2" etc. strcpy(shortkey,"F1"); // convert to "F2" etc.
shortkey[1] += ii; shortkey[1] += ii;
} }
if (! *shortkey && KBkey < 256) // single ascii character if (! *shortkey && KBkey < 256) // single ascii character
skipping to change at line 2164 skipping to change at line 2156
else Plog(0,"shortcut key not found: %s \n",shortkey); else Plog(0,"shortcut key not found: %s \n",shortkey);
return 1; return 1;
} }
if (zstrstr(zdialog_button_shortcuts,action)) { // ignore [OK] [cancel] etc. if (zstrstr(zdialog_button_shortcuts,action)) { // ignore [OK] [cancel] etc.
Plog(0,"dialog button shortcut, ignored \n"); Plog(0,"dialog button shortcut, ignored \n");
return 1; return 1;
} }
if (FGWM == 'G') { // G view mode if (FGWM == 'G') { // G view mode
navi::KBaction(action); // pass KB action to gallery navi::KBaction((ch *) action); // pass KB action to gallery
return 1; return 1;
} }
if (strmatch(action,"Show Hidden")) return 1; // hidden fles - only in G view if (strmatch(action,"Show Hidden")) return 1; // hidden fles - only in G view
if (FGWM == 'M') { // map view mode if (FGWM == 'M') { // file map view mode
ii = strmatchV(action,"File View","Gallery",0); // allow only view mode changes ii = strmatchV(action,"File View","Gallery",0); // allow only view mode changes
if (! ii) { if (! ii) {
if (strlen(shortkey) == 1) if (strlen(shortkey) == 1)
Plog(0,"key ignored: %c %s \n",toupper(*shortkey),action); Plog(0,"key ignored: %c %s \n",toupper(*shortkey),action);
else Plog(0,"key ignored: %s %s \n",shortkey,action); else Plog(0,"key ignored: %s %s \n",shortkey,action);
return 1; return 1;
} }
} }
if (KBcapture) return 1; // let current function handle it if (KBcapture) return 1; // let current function handle it
skipping to change at line 2297 skipping to change at line 2289
while (Ffullscreen) zmainloop(); while (Ffullscreen) zmainloop();
return; return;
} }
/******************************************************************************* */ /******************************************************************************* */
// update information in main window title bar // update information in main window title bar
namespace meta_names namespace meta_names
{ {
extern char meta_pdate[16]; // image (photo) date, yyyymmddhhmmss extern ch meta_pdate[16]; // image (photo) date, yyyymmddhhmmss
} }
void set_mwin_title() void set_mwin_title()
{ {
GTYPE gtype; GTYPE gtype;
int cc, fposn, Gfiles, Gimages; int cc, fposn, Gfiles, Gimages;
char *pp, titlebar[250]; ch *pp, titlebar[250];
char pdate[12], ptime[12], pdatetime[24]; ch pdate[12], ptime[12], pdatetime[24];
char fname[100], gname[100], ffolder[100]; ch fname[100], gname[100], ffolder[100];
if (FGWM != 'F') return; if (FGWM != 'F') return;
if (! curr_file || *curr_file != '/') { if (! curr_file || *curr_file != '/') {
gtk_window_set_title(MWIN,Frelease); // include fotoxx release gtk_window_set_title(MWIN,Frelease); // include fotoxx release
return; return;
} }
pp = (char *) strrchr(curr_file,'/'); pp = (ch *) strrchr(curr_file,'/');
strncpy0(fname,pp+1,99); // file name strncpy0(fname,pp+1,99); // file name
cc = pp - curr_file; cc = pp - curr_file;
if (cc < 99) strncpy0(ffolder,curr_file,cc+2); // get folder/path/ if short enough if (cc < 99) strncpy0(ffolder,curr_file,cc+2); // get folder/path/ if short enough
else { else {
strncpy(ffolder,curr_file,96); // or use /folder/path... strncpy(ffolder,curr_file,96); // or use /folder/path...
strcpy(ffolder+95,"..."); strcpy(ffolder+95,"...");
} }
Gfiles = navi::Gfiles; // total gallery files (incl. folders) Gfiles = navi::Gfiles; // total gallery files (incl. folders)
Gimages = navi::Gimages; // total image files Gimages = navi::Gimages; // total image files
skipping to change at line 2737 skipping to change at line 2729
return; return;
} }
/******************************************************************************* */ /******************************************************************************* */
// maintain a set of text strings written over the image in the window. // maintain a set of text strings written over the image in the window.
// add a new text string to the list. // add a new text string to the list.
// multiple text strings can be added with the same ID. // multiple text strings can be added with the same ID.
// px and py are image space. // px and py are image space.
void add_toptext(int ID, int px, int py, cchar *text, cchar *font) void add_toptext(int ID, int px, int py, ch *text, ch *font)
{ {
if (Ntoptext == maxtoptext) { if (Ntoptext == maxtoptext) {
Plog(0,"*** maxtoptext exceeded \n"); Plog(0,"*** maxtoptext exceeded \n");
return; return;
} }
int ii = Ntoptext++; int ii = Ntoptext++;
toptext[ii].ID = ID; toptext[ii].ID = ID;
toptext[ii].px = px; toptext[ii].px = px;
toptext[ii].py = py; toptext[ii].py = py;
skipping to change at line 2800 skipping to change at line 2792
else toptext[jj++] = toptext[ii]; else toptext[jj++] = toptext[ii];
} }
Ntoptext = jj; Ntoptext = jj;
return; return;
} }
// draw overlay text on window, black on white background // draw overlay text on window, black on white background
// coordinates are image space // coordinates are image space
void draw_text(int px, int py, cchar *text, cchar *font, cairo_t *cr) void draw_text(int px, int py, ch *text, ch *font, cairo_t *cr)
{ {
static PangoFontDescription *pangofont = 0; static PangoFontDescription *pangofont = 0;
static PangoLayout *pangolayout = 0; static PangoLayout *pangolayout = 0;
static char priorfont[60] = ""; static ch priorfont[60] = "";
int ww, hh; int ww, hh;
int crflag = 0; int crflag = 0;
if (! Cdrawin) return; if (! Cdrawin) return;
if (! gdkwin) return; if (! gdkwin) return;
px = Mscale * px - Morgx + Dorgx; // image to window space px = Mscale * px - Morgx + Dorgx; // image to window space
py = Mscale * py - Morgy + Dorgy; py = Mscale * py - Morgy + Dorgy;
if (! strmatch(font,priorfont)) { // change font if (! strmatch(font,priorfont)) { // change font
skipping to change at line 3206 skipping to change at line 3198
// Create E1 (edit input) and E3 (edit output) pixmaps from // Create E1 (edit input) and E3 (edit output) pixmaps from
// previous edit (E0) or image file (new E0). // previous edit (E0) or image file (new E0).
int edit_setup(editfunc &EF) int edit_setup(editfunc &EF)
{ {
int yn, rww, rhh, ftype; int yn, rww, rhh, ftype;
int Fpreview; int Fpreview;
if (! curr_file) return 0; // no image file if (! curr_file) return 0; // no image file
if (! Fpxb) return 0; // not loaded yet if (! Fpxb) return 0; // not loaded yet
if (FGWM != 'F') m_viewmode(0,"F"); // insure file view mode m_viewmode(0,"F"); // insure file view mode
ftype = image_file_type(curr_file); ftype = image_file_type(curr_file);
if (ftype != IMAGE && ftype != RAW) { // file type not editable if (ftype != IMAGE && ftype != RAW) { // file type not editable
zmessageACK(Mwin,"File type cannot be edited"); zmessageACK(Mwin,"File type cannot be edited");
return 0; return 0;
} }
if (! edit_wwhhOK(Fpxb->ww,Fpxb->hh)) return 0; // image too big if (! edit_wwhhOK(Fpxb->ww,Fpxb->hh)) return 0; // image too big
if (! EF.menuname) zappcrash("no edit menu name"); // should not happen if (! EF.menuname) zappcrash("no edit menu name"); // should not happen
skipping to change at line 3444 skipping to change at line 3436
Fzoom = 0; Fzoom = 0;
CEF->Fpreview = 0; CEF->Fpreview = 0;
return; return;
} }
/******************************************************************************* */ /******************************************************************************* */
// format edit history data for current edit function // format edit history data for current edit function
// example: edit_addhist("parm1: %d parm2: %.3f",parm1,parm2); // example: edit_addhist("parm1: %d parm2: %.3f",parm1,parm2);
void edit_addhist(cchar *format, ...) void edit_addhist(ch *format, ...)
{ {
va_list arglist; va_list arglist;
char edit_hist[xhistcc]; ch edit_hist[edithistXcc];
if (! CEF) zappcrash("edit_addhist() no CEF"); if (! CEF) zappcrash("edit_addhist() no CEF");
va_start(arglist,format); va_start(arglist,format);
vsnprintf(edit_hist,xhistcc,format,arglist); vsnprintf(edit_hist,edithistXcc,format,arglist);
strncpy0(CEF->edit_hist,edit_hist,xhistcc); strncpy0(CEF->edit_hist,edit_hist,edithistXcc);
return; return;
} }
/******************************************************************************* */ /******************************************************************************* */
// edit undo, redo, reset functions // edit undo, redo, reset functions
// these apply within an active edit function // these apply within an active edit function
void edit_undo() void edit_undo()
{ {
skipping to change at line 3514 skipping to change at line 3506
undo / redo menu buttons undo / redo menu buttons
******************************************************************************** */ ******************************************************************************** */
// [undo/redo] menu function // [undo/redo] menu function
// Reinstate a prior edit step as long as an edited image remains current. // Reinstate a prior edit step as long as an edited image remains current.
// Call m_undo() / m_redo() if left / right mouse click on menu. // Call m_undo() / m_redo() if left / right mouse click on menu.
// If A key is pressed, call undo_all() or redo_all(). // If A key is pressed, call undo_all() or redo_all().
// If middle mouse button is clicked, pop-up a list of all edit steps // If middle mouse button is clicked, pop-up a list of all edit steps
// and choose a step to go back to. // and choose a step to go back to.
void m_undo_redo(GtkWidget *, cchar *) void m_undo_redo(GtkWidget *, ch *)
{ {
void undo_redo_choice(GtkWidget *, cchar *menu); void undo_redo_choice(GtkWidget *, ch *menu);
GtkWidget *popmenu; GtkWidget *popmenu;
int button = zfuncs::vmenuclickbutton; int button = zfuncs::vmenuclickbutton;
char menuitem[40], flag; ch menuitem[40], flag;
F1_help_topic = "undo/redo button"; F1_help_topic = "undo/redo button";
Plog(1,"m_undo_redo \n"); Plog(1,"m_undo_redo \n");
if (! curr_file) return; if (! curr_file) return;
if (FGWM != 'F') return; if (FGWM != 'F') return;
if (button == 1) { if (button == 1) {
if (KBkey == GDK_KEY_a) undo_all(); // undo all steps if (KBkey == GDK_KEY_a) undo_all(); // undo all steps
skipping to change at line 3543 skipping to change at line 3535
if (button == 2) // go back to selected edit step if (button == 2) // go back to selected edit step
{ {
if (URS_max == 0) return; if (URS_max == 0) return;
popmenu = create_popmenu(); popmenu = create_popmenu();
for (int ii = 0; ii < 30; ii++) { // insert all edit steps for (int ii = 0; ii < 30; ii++) { // insert all edit steps
if (ii > URS_max) break; if (ii > URS_max) break;
if (ii == URS_pos) flag = '*'; // flag step matching current status if (ii == URS_pos) flag = '*'; // flag step matching current status
else flag = ' '; else flag = ' ';
snprintf(menuitem,40,"%d %s %c",ii,URS_menu[ii],flag); snprintf(menuitem,40,"%d %s %c",ii,URS_menu[ii],flag);
add_popmenu_item(popmenu,menuitem,undo_redo_choice,(char *) &Nval[ii],0 ); add_popmenu_item(popmenu,menuitem,undo_redo_choice,(ch *) &Nval[ii],0);
} }
popup_menu(Mwin,popmenu); popup_menu(Mwin,popmenu);
} }
if (button == 3) { if (button == 3) {
if (KBkey == GDK_KEY_a) redo_all(); // redo all steps if (KBkey == GDK_KEY_a) redo_all(); // redo all steps
else m_redo(0,0); // redo one step else m_redo(0,0); // redo one step
} }
return; return;
} }
// popup menu response function // popup menu response function
void undo_redo_choice(GtkWidget *, cchar *menu) void undo_redo_choice(GtkWidget *, ch *menu)
{ {
int nn = *((int *) menu); int nn = *((int *) menu);
if (nn < 0 || nn > URS_max) return; if (nn < 0 || nn > URS_max) return;
URS_pos = nn; URS_pos = nn;
if (E0pxm) PXM_free(E0pxm); if (E0pxm) PXM_free(E0pxm);
E0pxm = load_undo(URS_pos); E0pxm = load_undo(URS_pos);
Fpaintnow(); Fpaintnow();
return; return;
} }
// [undo] menu function - reinstate previous edit in undo/redo stack // [undo] menu function - reinstate previous edit in undo/redo stack
void m_undo(GtkWidget *, cchar *) void m_undo(GtkWidget *, ch *)
{ {
Plog(1,"m_undo \n"); Plog(1,"m_undo \n");
if (! curr_file) return; if (! curr_file) return;
if (FGWM != 'F') return; if (FGWM != 'F') return;
if (CEF) { // undo active edit if (CEF) { // undo active edit
edit_undo(); edit_undo();
return; return;
} }
skipping to change at line 3593 skipping to change at line 3585
if (URS_pos == 0) return; // undo past edit if (URS_pos == 0) return; // undo past edit
URS_pos--; URS_pos--;
if (E0pxm) PXM_free(E0pxm); if (E0pxm) PXM_free(E0pxm);
E0pxm = load_undo(URS_pos); E0pxm = load_undo(URS_pos);
Fpaintnow(); Fpaintnow();
return; return;
} }
// [redo] menu function - reinstate next edit in undo/redo stack // [redo] menu function - reinstate next edit in undo/redo stack
void m_redo(GtkWidget *, cchar *) void m_redo(GtkWidget *, ch *)
{ {
Plog(1,"m_redo \n"); Plog(1,"m_redo \n");
if (! curr_file) return; if (! curr_file) return;
if (FGWM != 'F') return; if (FGWM != 'F') return;
if (CEF) { // redo active edit if (CEF) { // redo active edit
edit_redo(); edit_redo();
return; return;
} }
skipping to change at line 3649 skipping to change at line 3641
E0pxm = load_undo(URS_pos); E0pxm = load_undo(URS_pos);
Fpaintnow(); Fpaintnow();
return; return;
} }
// Save E0 to undo/redo file stack // Save E0 to undo/redo file stack
// stack position = URS_pos // stack position = URS_pos
void save_undo() void save_undo()
{ {
char *pp, buff[24]; ch *pp, buff[24];
FILE *fid; FILE *fid;
int ww, hh, nc, nn; int ww, hh, nc, nn;
uint cc1, cc2; uint cc1, cc2;
uint ccmax = 128 * MEGA; uint ccmax = 128 * MEGA;
int diskmb; int diskmb;
ww = E0pxm->ww; ww = E0pxm->ww;
hh = E0pxm->hh; hh = E0pxm->hh;
nc = E0pxm->nc; nc = E0pxm->nc;
skipping to change at line 3683 skipping to change at line 3675
if (! fid) goto writefail; if (! fid) goto writefail;
snprintf(buff,24,"fotoxx %05d %05d %d",ww,hh,nc); // write header snprintf(buff,24,"fotoxx %05d %05d %d",ww,hh,nc); // write header
nn = fwrite(buff,20,1,fid); nn = fwrite(buff,20,1,fid);
if (nn != 1) goto writefail; if (nn != 1) goto writefail;
cc1 = ww * hh * nc * sizeof(float); // write ww * hh RGB(A) pixels cc1 = ww * hh * nc * sizeof(float); // write ww * hh RGB(A) pixels
cc2 = 0; cc2 = 0;
while (cc1) { while (cc1) {
if (cc1 <= ccmax) { if (cc1 <= ccmax) {
pp = (char *) E0pxm->pixels; pp = (ch *) E0pxm->pixels;
nn = fwrite(pp+cc2,cc1,1,fid); nn = fwrite(pp+cc2,cc1,1,fid);
if (nn != 1) goto writefail; if (nn != 1) goto writefail;
break; break;
} }
else { else {
pp = (char *) E0pxm->pixels; pp = (ch *) E0pxm->pixels;
nn = fwrite(pp+cc2,ccmax,1,fid); nn = fwrite(pp+cc2,ccmax,1,fid);
if (nn != 1) goto writefail; if (nn != 1) goto writefail;
cc1 -= ccmax; cc1 -= ccmax;
cc2 += ccmax; cc2 += ccmax;
} }
} }
fclose(fid); fclose(fid);
if (URS_pos == 0) { // stack posn. 0 = original image if (URS_pos == 0) { // stack posn. 0 = original image
strcpy(URS_menu[0],"original"); // function name for original image strcpy(URS_menu[0],"original"); // function name for original image
URS_saved[0] = 1; // original image already on disk URS_saved[0] = 1; // original image already on disk
} }
else { // stack position else { // stack position
if (! CEF_valid()) return; // must have an edit function if (! CEF_valid()) return; // must have an edit function
strncpy0(URS_menu[URS_pos],CEF->menuname,32); // edit function menu name strncpy0(URS_menu[URS_pos],CEF->menuname,32); // edit function menu name
strncpy0(URS_parms[URS_pos],CEF->edit_hist,xhistcc); // edit history text strncpy0(URS_parms[URS_pos],CEF->edit_hist,edithistXcc); // edit history text
URS_saved[URS_pos] = 0; // not yet saved to disk URS_saved[URS_pos] = 0; // not yet saved to disk
} }
return; return;
writefail: writefail:
zmessageACK(Mwin,"undo/redo stack write failure: %s",strerror(errno)); zmessageACK(Mwin,"undo/redo stack write failure: %s",strerror(errno));
quitxx(); quitxx();
} }
// Load PXM from undo/redo image file stack // Load PXM from undo/redo image file stack
// stack position = URS_pos // stack position = URS_pos
PXM * load_undo(int posn) PXM * load_undo(int posn)
{ {
char *pp, buff[24]; ch *pp, buff[24];
FILE *fid; FILE *fid;
int ww, hh, nc, nn; int ww, hh, nc, nn;
uint cc1, cc2; uint cc1, cc2;
uint ccmax = 128 * MEGA; // reduced from 256 uint ccmax = 128 * MEGA; // reduced from 256
PXM *pxm; PXM *pxm;
pp = strstr(URS_filename,"undo_"); pp = strstr(URS_filename,"undo_");
if (! pp) goto err1; if (! pp) goto err1;
snprintf(pp+5,3,"%02d",posn); snprintf(pp+5,3,"%02d",posn);
skipping to change at line 3749 skipping to change at line 3741
nn = sscanf(buff,"fotoxx %d %d %d",&ww,&hh,&nc); nn = sscanf(buff,"fotoxx %d %d %d",&ww,&hh,&nc);
if (nn != 3) goto err4; if (nn != 3) goto err4;
pxm = PXM_make(ww,hh,nc); pxm = PXM_make(ww,hh,nc);
if (! pxm) quitxx(); if (! pxm) quitxx();
cc1 = ww * hh * nc * sizeof(float); // bytes to read cc1 = ww * hh * nc * sizeof(float); // bytes to read
cc2 = 0; // bytes done cc2 = 0; // bytes done
while (cc1) { while (cc1) {
if (cc1 <= ccmax) { if (cc1 <= ccmax) {
pp = (char *) pxm->pixels; // read entire (remaining) file pp = (ch *) pxm->pixels; // read entire (remaining) file
nn = fread(pp+cc2,cc1,1,fid); nn = fread(pp+cc2,cc1,1,fid);
if (nn != 1) goto err3; if (nn != 1) goto err3;
break; break;
} }
else { else {
pp = (char *) pxm->pixels; // read max. part of file pp = (ch *) pxm->pixels; // read max. part of file
nn = fread(pp+cc2,ccmax,1,fid); nn = fread(pp+cc2,ccmax,1,fid);
if (nn != 1) goto err3; if (nn != 1) goto err3;
cc1 -= ccmax; cc1 -= ccmax;
cc2 += ccmax; cc2 += ccmax;
} }
} }
fclose(fid); fclose(fid);
return pxm; return pxm;
skipping to change at line 3868 skipping to change at line 3860
// main thread: wait for working thread to finish current work and become idle // main thread: wait for working thread to finish current work and become idle
void thread_wait() void thread_wait()
{ {
if (! main_thread()) zappcrash("thread_wait(): called from thread"); if (! main_thread()) zappcrash("thread_wait(): called from thread");
if (! userfunc) zappcrash("thread_wait(): no thread active"); if (! userfunc) zappcrash("thread_wait(): no thread active");
while (Fthread_busy || Fthread_pend) zmainsleep(0.002); while (Fthread_busy || Fthread_pend) zmainsleep(0.002);
return; return;
} }
// thread: query user kill action - exit immediately if user kills
int thread_killed()
{
if (! userfunc) zappcrash("thread_killed(): no thread active");
return Fthread_stop;
}
// thread: wait for work or exit request // thread: wait for work or exit request
void * Fthreadfunc(void *) void * Fthreadfunc(void *)
{ {
while (true) while (true)
{ {
if (Fthread_stop) { // stop thread if (Fthread_stop) { // stop thread
Fthread_busy = 0; Fthread_busy = 0;
Fthread_pend = 0; Fthread_pend = 0;
userfunc = 0; userfunc = 0;
pthread_exit(0); // exit thread pthread_exit(0); // exit thread
} }
if (Fthread_pend) { // new work requested if (Fthread_pend) { // new work requested
Fthread_busy = 1; // thread is working Fthread_busy = 1; // thread is working
Fthread_pend = 0; // all pending requests will be done Fthread_pend = 0; // all pending requests will be done
paintlock(1); // window paint blocked paintlock(1); // window paint blocked
zadd_locked(Fthreadbusy,+1); // top panel busy indicator zadd_locked(Ffuncbusy,+1); // top panel busy indicator
userfunc(0); // execute thread function userfunc(0); // execute thread function
zadd_locked(Fthreadbusy,-1); zadd_locked(Ffuncbusy,-1);
paintlock(0); // window paint allowed paintlock(0); // window paint allowed
Fthread_busy = 0; Fthread_busy = 0;
continue; // loop without delay continue; // loop without delay
} }
zsleep(0.01); // idle loop if pend = stop = 0 zsleep(0.01); // idle loop if pend = stop = 0
} }
} }
/******************************************************************************* */ /******************************************************************************* */
// thread: start worker threads (per processor core) and wait for completion // thread: start worker threads (per processor core) and wait for completion
// threadfunc: void * func(void *index) // threadfunc: void * func(void *index)
// start Nt threads and wait for all to exit // start Nt threads and wait for all to exit
void do_wthreads(threadfunc func, int Nt) void do_wthreads(threadfunc func, int Nt)
{ {
pthread_t tid[max_threads]; pthread_t tid[40];
zadd_locked(Fthreadbusy,+1); zadd_locked(Ffuncbusy,+1);
for (int ii = 0; ii < Nt; ii++) for (int ii = 0; ii < Nt; ii++)
tid[ii] = start_Jthread(func, &Nval[ii]); tid[ii] = start_Jthread(func, &Nval[ii]);
for (int ii = 0; ii < Nt; ii++) for (int ii = 0; ii < Nt; ii++)
wait_Jthread(tid[ii]); wait_Jthread(tid[ii]);
zadd_locked(Fthreadbusy,-1); zadd_locked(Ffuncbusy,-1);
return; return;
} }
/******************************************************************************* */ /******************************************************************************* */
// functions to track progress of long computations in multiple threads // functions to track progress of long computations in multiple threads
// initialize: progress_reset(goal) // initialize: progress_reset(goal)
// threads: progress_add(thread,value) // threads: progress_add(thread,value)
// get progress: pct = progress_percent() 0-100 percent // get progress: pct = progress_percent() 0-100 percent
// reset to idle: progress_reset(0) // reset to idle: progress_reset(0)
double progress_goal; // goal value double progress_goal; // goal value
double progress_done[max_threads]; // progress per thread double progress_done[NWT]; // progress per thread
// reset thread counters and set new goal value (0 = inactive) // reset thread counters and set new goal value (0 = inactive)
void progress_reset(double goal) void progress_reset(double goal)
{ {
for (int ii = 0; ii < NWT; ii++) for (int ii = 0; ii < NWT; ii++)
progress_done[ii] = 0; progress_done[ii] = 0;
progress_goal = goal; progress_goal = goal;
return; return;
} }
skipping to change at line 3976 skipping to change at line 3960
progress += progress_done[ii]; progress += progress_done[ii];
pct = 100.0 * progress / progress_goal; pct = 100.0 * progress / progress_goal;
return pct; return pct;
} }
/******************************************************************************* */ /******************************************************************************* */
// table for loading and saving adjustable parameters between sessions // table for loading and saving adjustable parameters between sessions
typedef struct { typedef struct {
char name[20]; ch name[20];
char type[12]; ch type[12];
int count; int count;
void *location; void *location;
} param; } param;
#define Nparms 52 #define Nparms 51
param paramTab[Nparms] = { param paramTab[Nparms] = {
// name type count location // name type count location
{ "fotoxx release", "char", 1, &Prelease }, { "fotoxx release", "char", 1, &Prelease },
{ "first time", "int", 1, &Ffirsttime }, { "first time", "int", 1, &Ffirsttime },
{ "log level", "int", 1, &Floglevel }, { "log level", "int", 1, &Floglevel },
{ "window geometry", "int", 4, &mwgeom }, { "window geometry", "int", 4, &mwgeom },
{ "thumbnail size", "int", 1, &navi::thumbsize }, { "thumbnail size", "int", 1, &navi::thumbsize },
{ "menu style", "char", 1, &menu_style }, { "menu style", "char", 1, &menu_style },
{ "icon size", "int", 1, &iconsize }, { "icon size", "int", 1, &iconsize },
{ "F-base-color", "int", 3, &FBrgb }, { "F-base-color", "int", 3, &FBrgb },
{ "G-base-color", "int", 3, &GBrgb }, { "G-base-color", "int", 3, &GBrgb },
{ "menu font color", "int", 3, &MFrgb }, { "menu font color", "int", 3, &MFrgb },
{ "menu background", "int", 3, &MBrgb }, { "menu background", "int", 3, &MBrgb },
{ "index level", "int", 1, &Findexlev }, { "index level", "int", 1, &Findexlev },
{ "FM index level", "int", 1, &FMindexlev }, { "FM index level", "int", 1, &FMindexlev },
{ "max. threads", "int", 1, &NWT }, // 22.35
{ "dialog font", "char", 1, &dialog_font }, { "dialog font", "char", 1, &dialog_font },
{ "drag option", "int", 1, &Fdragopt }, { "drag option", "int", 1, &Fdragopt },
{ "zoom count", "int", 1, &zoomcount }, { "zoom count", "int", 1, &zoomcount },
{ "map_dotsize", "int", 1, &map_dotsize }, { "map_dotsize", "int", 1, &map_dotsize },
{ "overlay text cc", "int", 2, &ovtxcc }, { "overlay text cc", "int", 2, &ovtxcc },
{ "last version", "int", 1, &Flastversion }, { "last version", "int", 1, &Flastversion },
{ "Image Position", "char", 1, &ImagePosn }, { "Image Position", "char", 1, &ImagePosn },
{ "curve node dist %", "float", 1, &splcurve_minx }, { "curve node dist %", "float", 1, &splcurve_minx },
{ "start display", "char", 1, &startdisplay }, { "start display", "char", 1, &startdisplay },
{ "start album", "char", 1, &startalbum }, { "start album", "char", 1, &startalbum },
skipping to change at line 4043 skipping to change at line 4026
{ "SS KB keys", "char", 1, &ss_KBkeys }, { "SS KB keys", "char", 1, &ss_KBkeys },
{ "line color", "int", 3, &LINE_COLOR }, { "line color", "int", 3, &LINE_COLOR },
{ "Faskquit", "int", 1, &Faskquit }, { "Faskquit", "int", 1, &Faskquit },
{ "printer color map", "char", 1, &colormapfile } }; { "printer color map", "char", 1, &colormapfile } };
// save parameters to file /.../.fotoxx/parameters // save parameters to file /.../.fotoxx/parameters
void save_params() void save_params()
{ {
FILE *fid; FILE *fid;
char buff[1050], text[1000]; ch buff[1050], text[1000];
// limit for character data cc // limit for character data cc
char *name, *type; ch *name, *type;
int count; int count;
void *location; void *location;
char **charloc; ch **charloc;
int *intloc; int *intloc;
float *floatloc; float *floatloc;
Plog(1,"save_params()\n"); Plog(1,"save_params()\n");
snprintf(buff,199,"%s/parameters",get_zhomedir()); // open output file snprintf(buff,199,"%s/parameters",get_zhomedir()); // open output file
fid = fopen(buff,"w"); fid = fopen(buff,"w");
if (! fid) return; if (! fid) return;
for (int ii = 0; ii < Nparms; ii++) // write table of state data for (int ii = 0; ii < Nparms; ii++) // write table of state data
{ {
name = paramTab[ii].name; name = paramTab[ii].name;
type = paramTab[ii].type; type = paramTab[ii].type;
count = paramTab[ii].count; count = paramTab[ii].count;
location = paramTab[ii].location; location = paramTab[ii].location;
charloc = (char **) location; charloc = (ch **) location;
intloc = (int *) location; intloc = (int *) location;
floatloc = (float *) location; floatloc = (float *) location;
fprintf(fid,"%-20s %-8s %02d ",name,type,count); // write parm name, type, count fprintf(fid,"%-20s %-8s %02d ",name,type,count); // write parm name, type, count
for (int kk = 0; kk < count; kk++) // write "value" "value" ... for (int kk = 0; kk < count; kk++) // write "value" "value" ...
{ {
if (strmatch(type,"char")) { if (strmatch(type,"char")) {
if (! *charloc) strcpy(text,"null"); // missing, use "null" if (! *charloc) strcpy(text,"null"); // missing, use "null"
else repl_1str(*charloc++,text,"\n","\\n"); // replace newlines with "\n" else repl_1str(*charloc++,text,"\n","\\n"); // replace newlines with "\n"
skipping to change at line 4100 skipping to change at line 4083
} }
// load parameters from file /.../.fotoxx/parameters // load parameters from file /.../.fotoxx/parameters
void load_params() void load_params()
{ {
FILE *fid; FILE *fid;
int ii, err, pcount; int ii, err, pcount;
int Idata; int Idata;
float Fdata; float Fdata;
char buff[1000], text[1000], *pp; ch buff[1000], text[1000], *pp;
char name[20], type[12], count[8], data[1000]; ch name[20], type[12], count[8], data[1000];
void *location; void *location;
char **charloc; ch **charloc;
int *intloc; int *intloc;
float *floatloc; float *floatloc;
Plog(1,"load_params()\n"); Plog(1,"load_params()\n");
snprintf(buff,199,"%s/parameters",get_zhomedir()); // open parameters file snprintf(buff,199,"%s/parameters",get_zhomedir()); // open parameters file
fid = fopen(buff,"r"); fid = fopen(buff,"r");
if (! fid) return; // none, defaults are used if (! fid) return; // none, defaults are used
while (true) // read parameters while (true) // read parameters
skipping to change at line 4146 skipping to change at line 4129
{ {
if (! strmatch(name,paramTab[ii].name)) continue; // parm name if (! strmatch(name,paramTab[ii].name)) continue; // parm name
if (! strmatch(type,paramTab[ii].type)) continue; // parm type if (! strmatch(type,paramTab[ii].type)) continue; // parm type
if (paramTab[ii].count != pcount) continue; // parm count if (paramTab[ii].count != pcount) continue; // parm count
break; break;
} }
if (ii == Nparms) continue; // not found, ignore file param if (ii == Nparms) continue; // not found, ignore file param
location = paramTab[ii].location; // get parameter memory location location = paramTab[ii].location; // get parameter memory location
charloc = (char **) location; charloc = (ch **) location;
intloc = (int *) location; intloc = (int *) location;
floatloc = (float *) location; floatloc = (float *) location;
for (ii = 1; ii <= pcount; ii++) // get parameter value(s) for (ii = 1; ii <= pcount; ii++) // get parameter value(s)
{ {
if (strmatch(type,"char") && pcount == 1) { // one quoted string with possible if (strmatch(type,"char") && pcount == 1) { // one quoted string with possible
pp = strrchr(data,'"'); // embedded blanks and quotes pp = strrchr(data,'"'); // embedded blanks and quotes
if (pp) *pp = 0; if (pp) *pp = 0;
pp = data + 1; pp = data + 1;
if (strlen(pp) == 0) break; if (strlen(pp) == 0) break;
repl_1str(pp,text,"\\n","\n"); // replace "\n" with real newlines repl_1str(pp,text,"\\n","\n"); // replace "\n" with real newlines
*charloc++ = zstrdup(text,"params"); *charloc++ = zstrdup(text,"params");
break; break;
} }
pp = (char *) substring(data,' ',ii); pp = (ch *) substring(data,' ',ii);
if (! pp) break; if (! pp) break;
if (strmatch(type,"char")) { if (strmatch(type,"char")) {
repl_1str(pp,text,"\\n","\n"); // replace "\n" with real newlines repl_1str(pp,text,"\\n","\n"); // replace "\n" with real newlines
*charloc++ = zstrdup(text,"params"); *charloc++ = zstrdup(text,"params");
} }
if (strmatch(type,"int")) { if (strmatch(type,"int")) {
err = convSI(pp,Idata); err = convSI(pp,Idata);
if (err) continue; if (err) continue;
skipping to change at line 4189 skipping to change at line 4172
*floatloc++ = Fdata; *floatloc++ = Fdata;
} }
} }
} }
fclose(fid); fclose(fid);
for (ii = 0; ii < Nparms; ii++) // set null strings to "null" for (ii = 0; ii < Nparms; ii++) // set null strings to "null"
{ {
if (! strmatch(paramTab[ii].type,"char")) continue; if (! strmatch(paramTab[ii].type,"char")) continue;
charloc = (char **) paramTab[ii].location; charloc = (ch **) paramTab[ii].location;
pcount = paramTab[ii].count; pcount = paramTab[ii].count;
for (int jj = 0; jj < pcount; jj++) for (int jj = 0; jj < pcount; jj++)
if (! charloc[jj]) if (! charloc[jj])
charloc[jj] = zstrdup("null","params",20); charloc[jj] = zstrdup("null","params",20);
} }
if (curr_file && ! *curr_file) curr_file = 0; // no current file >> null if (curr_file && ! *curr_file) curr_file = 0; // no current file >> null
zoomratio = pow( 2.0, 1.0 / zoomcount); // set zoom ratio from zoom count zoomratio = pow( 2.0, 1.0 / zoomcount); // set zoom ratio from zoom count
 End of changes. 97 change blocks. 
202 lines changed or deleted 183 lines changed or added

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