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 |