f.tools.cc (fotoxx-23.0) | : | f.tools.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 69 | skipping to change at line 69 | |||
// Index Image Files menu function | // Index Image Files menu function | |||
// Dialog to get top image folders, thumbnails folder, indexed metadata items. | // Dialog to get top image folders, thumbnails folder, indexed metadata items. | |||
// Update the index config file and generate new image index. | // Update the index config file and generate new image index. | |||
namespace index_names | namespace index_names | |||
{ | { | |||
zdialog *zd_indexlog = 0; | zdialog *zd_indexlog = 0; | |||
xxrec_t *xxrec = 0, **xxrec_old = 0, **xxrec_new = 0; | xxrec_t *xxrec = 0, **xxrec_old = 0, **xxrec_new = 0; | |||
int8 *Xstatus = 0, *Tstatus = 0; | int8 *Xstatus = 0, *Tstatus = 0; | |||
int Xthread1, Xthread2, Tthread1, Tthread2; | int index_thread_busy, thumb_thread_busy; | |||
int Ffullindex = 0; | int FfullindexReq = 0; | |||
// user: force full re-index | // user: force full re-index | |||
int Fuserkill; | ||||
} | } | |||
// index menu function | // index menu function | |||
void m_index(GtkWidget *, cchar *) | void m_index(GtkWidget *, ch *) | |||
{ | { | |||
using namespace index_names; | using namespace index_names; | |||
void index_callbackfunc(GtkWidget *widget, int line, int pos, int kbkey); | void index_callbackfunc(GtkWidget *widget, int line, int pos, int kbkey); | |||
int index_dialog_event(zdialog *zd, cchar *event); | int index_dialog_event(zdialog *zd, ch *event); | |||
zdialog *zd; | zdialog *zd; | |||
FILE *fid; | FILE *fid; | |||
char buff[200], sthumbfolder[200]; | ch buff[200], sthumbfolder[200]; | |||
char *pp; | ch *pp; | |||
GtkWidget *widget; | GtkWidget *widget; | |||
int line, cc, zstat; | int line, cc, zstat; | |||
cchar *greet1 = "Folders for image files " | ch *greet1 = "Folders for image files " | |||
"(subfolders included automatically)."; | "(subfolders included automatically)."; | |||
cchar *greet2 = "Select to add, click on X to delete."; | ch *greet2 = "Select to add, click on X to delete."; | |||
cchar *greet3 = "folder for thumbnails"; | ch *greet3 = "folder for thumbnails"; | |||
cchar *greet4 = "extra metadata items to include in index"; | ch *greet4 = "extra metadata items to include in index"; | |||
cchar *greet5 = "force a full re-index of all image files"; | ch *greet5 = "force a full re-index of all image files"; | |||
cchar *termmess = "Index function terminated. \n" | ch *termmess = "Index function terminated. \n" | |||
"Indexing is required for search and map functions \n" | "Indexing is required for search and map functions \n" | |||
"and to make thumbnail gallery pages display fast. "; | "and to make thumbnail gallery pages display fast. "; | |||
F1_help_topic = "index files"; | F1_help_topic = "index files"; | |||
Plog(1,"m_index \n"); | Plog(1,"m_index \n"); | |||
m_viewmode(0,"0"); // no view mode | m_viewmode(0,"F"); | |||
if (Fblock(0,"blocked edits")) return; // check nothing pending | if (Fblock(0,"blocked edits")) return; // check nothing pending | |||
Ffullindex = 0; | FfullindexReq = 0; | |||
/*** | /*** | |||
______________________________________________________________ | ______________________________________________________________ | |||
| Index Image Files | | | Index Image Files | | |||
| | | | | | |||
| Folders for image files (subdirs included automatically). | | | Folders for image files (subdirs included automatically). | | |||
| [Select] Select to add, click on X to delete. | | | [Select] Select to add, click on X to delete. | | |||
| __________________________________________________________ | | | __________________________________________________________ | | |||
| | X /home/<user>/Pictures | | | | | X /home/<user>/Pictures | | | |||
| | X /home/<user>/... | | | | | X /home/<user>/... | | | |||
skipping to change at line 198 | skipping to change at line 197 | |||
} | } | |||
else textwidget_append(widget,0," X %s\n",buff); // stuff " X /dir1/dir2..." | else textwidget_append(widget,0," X %s\n",buff); // stuff " X /dir1/dir2..." | |||
} | } | |||
fclose(fid); | fclose(fid); | |||
} | } | |||
zdialog_resize(zd,500,500); // run dialog | zdialog_resize(zd,500,500); // run dialog | |||
zdialog_run(zd,index_dialog_event,"save"); | zdialog_run(zd,index_dialog_event,"save"); | |||
zstat = zdialog_wait(zd); // wait for completion | zstat = zdialog_wait(zd); // wait for completion | |||
while (zstat == 1) { | while (zstat == 1) { // [help] | |||
zd->zstat = 0; // keep dialog active | zd->zstat = 0; // keep dialog active | |||
m_help(0,"Help"); | m_help(0,"Help"); | |||
zstat = zdialog_wait(zd); | zstat = zdialog_wait(zd); | |||
} | } | |||
if (zstat != 2) // canceled | if (zstat != 2) // canceled | |||
{ | { | |||
zdialog_free(zd); | zdialog_free(zd); | |||
zmessageACK(Mwin,termmess); // index not finished | zmessageACK(Mwin,termmess); // index not finished | |||
return; | return; | |||
skipping to change at line 241 | skipping to change at line 240 | |||
zdialog_fetch(zd,"sthumbfolder",buff,200); // get thumbnails folder from dialog | zdialog_fetch(zd,"sthumbfolder",buff,200); // get thumbnails folder from dialog | |||
strTrim2(buff); // remove surrounding blanks | strTrim2(buff); // remove surrounding blanks | |||
cc = strlen(buff); | cc = strlen(buff); | |||
if (cc && buff[cc-1] == '/') buff[cc-1] = 0; // remove trailing '/' | if (cc && buff[cc-1] == '/') buff[cc-1] = 0; // remove trailing '/' | |||
fprintf(fid,"thumbnails: %s\n",buff); // thumbnails folder >> config file | fprintf(fid,"thumbnails: %s\n",buff); // thumbnails folder >> config file | |||
fclose(fid); | fclose(fid); | |||
zdialog_free(zd); // close dialog | zdialog_free(zd); // close dialog | |||
index_rebuild(2,1); // build image index and thumbnails | index_rebuild(2,1); // build image index and thumbnails | |||
// and keep dialog open | ||||
if (! Findexvalid) { | ||||
zmessageACK(Mwin,"no image index created"); | ||||
return; | ||||
} | ||||
if (navi::galleryname) zfree(navi::galleryname); | ||||
navi::galleryname = zstrdup(topfolders[0],"index-dialog"); | ||||
// set current gallery | ||||
return; | return; | |||
} | } | |||
// ----------------------------------------------------------------------------- - | // ----------------------------------------------------------------------------- - | |||
// mouse click function for top folders text window | // mouse click function for top folders text window | |||
// remove folder from list where "X" is clicked | // remove folder from list where "X" is clicked | |||
void index_callbackfunc(GtkWidget *widget, int line, int pos, int kbkey) | void index_callbackfunc(GtkWidget *widget, int line, int pos, int kbkey) | |||
{ | { | |||
GdkWindow *gdkwin; | GdkWindow *gdkwin; | |||
char *pp; | ch *pp; | |||
char *dirlist[maxtopfolders]; | ch *dirlist[maxtopfolders]; | |||
int ii, jj; | int ii, jj; | |||
if (kbkey == GDK_KEY_F1) { // key F1 pressed, show help | if (kbkey == GDK_KEY_F1) { // key F1 pressed, show help | |||
showz_docfile(Mwin,"userguide",F1_help_topic); | showz_docfile(Mwin,"userguide",F1_help_topic); | |||
return; | return; | |||
} | } | |||
gdkwin = gtk_widget_get_window(widget); // stop updates between clear and refresh | gdkwin = gtk_widget_get_window(widget); // stop updates between clear and refresh | |||
gdk_window_freeze_updates(gdkwin); | gdk_window_freeze_updates(gdkwin); | |||
skipping to change at line 297 | skipping to change at line 289 | |||
} | } | |||
gdk_window_thaw_updates(gdkwin); | gdk_window_thaw_updates(gdkwin); | |||
return; | return; | |||
} | } | |||
// ----------------------------------------------------------------------------- - | // ----------------------------------------------------------------------------- - | |||
// index dialog event and completion function | // index dialog event and completion function | |||
int index_dialog_event(zdialog *zd, cchar *event) | int index_dialog_event(zdialog *zd, ch *event) | |||
{ | { | |||
using namespace index_names; | using namespace index_names; | |||
int ii, nn, yn; | int ii, nn, yn; | |||
GtkWidget *widget; | GtkWidget *widget; | |||
char **flist, *pp, *sthumbfolder; | ch **flist, *pp, *sthumbfolder; | |||
zlist_t *mlist; | zlist_t *mlist; | |||
cchar *topmess = "Choose top image folders"; | ch *topmess = "Choose top image folders"; | |||
cchar *thumbmess = "Choose thumbnail folder"; | ch *thumbmess = "Choose thumbnail folder"; | |||
cchar *xmetamess = "All image files will be re-indexed. \n" | ch *xmetamess = "All image files will be re-indexed. \n" | |||
" Continue?"; | " Continue?"; | |||
if (strmatch(event,"escape")) zd->zstat = -2; // escape key | if (strmatch(event,"escape")) zd->zstat = -2; // escape key | |||
if (strmatch(event,"browsetop")) { // [browse] top folders | if (strmatch(event,"browsetop")) { // [browse] top folders | |||
flist = zgetfiles(topmess,MWIN,"folders",getenv("HOME")); // get top folders from user | flist = zgetfiles(topmess,MWIN,"folders",getenv("HOME")); // get top folders from user | |||
if (! flist) return 1; | if (! flist) return 1; | |||
widget = zdialog_gtkwidget(zd,"topfolders"); // add to dialog list | widget = zdialog_gtkwidget(zd,"topfolders"); // add to dialog list | |||
for (ii = 0; flist[ii]; ii++) { | for (ii = 0; flist[ii]; ii++) { | |||
textwidget_append2(widget,0," X %s\n",flist[ii]); // " X /dir1/dir2/..." | textwidget_append2(widget,0," X %s\n",flist[ii]); // " X /dir1/dir2/..." | |||
skipping to change at line 340 | skipping to change at line 332 | |||
zfree(sthumbfolder); | zfree(sthumbfolder); | |||
zfree(pp); | zfree(pp); | |||
} | } | |||
if (strmatch(event,"browsxmeta")) { // [select] | if (strmatch(event,"browsxmeta")) { // [select] | |||
yn = zmessageYN(Mwin,xmetamess); // add optional indexed metadata | yn = zmessageYN(Mwin,xmetamess); // add optional indexed metadata | |||
if (! yn) return 1; | if (! yn) return 1; | |||
mlist = zlist_from_file(meta_index_file); // index extra metadata items | mlist = zlist_from_file(meta_index_file); // index extra metadata items | |||
if (! mlist) mlist = zlist_new(0); | if (! mlist) mlist = zlist_new(0); | |||
nn = select_meta_keys(mlist,MXmax,1); // user edit | nn = select_meta_keys(mlist,xmetamaxkeys,1); // user edit | |||
if (nn) { | if (nn) { | |||
zlist_to_file(mlist,meta_index_file); // changes made, replace file | zlist_to_file(mlist,meta_index_file); // changes made, replace file | |||
Ffullindex = 1; // full index required | FfullindexReq = 1; // full index required | |||
} | } | |||
zlist_delete(mlist); | zlist_delete(mlist); | |||
} | } | |||
if (strmatch(event,"forcex")) { // force full re-index | if (strmatch(event,"forcex")) { // force full re-index | |||
zdialog_fetch(zd,"forcex",ii); | zdialog_fetch(zd,"forcex",ii); | |||
if (ii) Ffullindex = 1; | if (ii) FfullindexReq = 1; | |||
} | } | |||
if (! zd->zstat) return 1; // wait for completion | if (! zd->zstat) return 1; // wait for completion | |||
if (zd->zstat == 1) { // [help] | if (zd->zstat == 1) { // [help] | |||
zd->zstat = 0; | zd->zstat = 0; | |||
showz_docfile(Mwin,"userguide","index_files"); | showz_docfile(Mwin,"userguide","index_files"); | |||
return 1; | return 1; | |||
} | } | |||
return 1; // [proceed] or cancel status | return 1; // [proceed] or [cancel] status | |||
} | } | |||
// ----------------------------------------------------------------------------- - | // ----------------------------------------------------------------------------- - | |||
// Rebuild the image index from the index config data. | // Rebuild the image index from the index config data. | |||
// index level = 0/1/2 = no index / old files only / old + new files | // index level = 0/1/2 = no index / old files only / old + new files | |||
// Called from main() when Fotoxx is started (index level from user setting) | // Called from main() when Fotoxx is started (index level from user setting) | |||
// Called from menu function m_index() (index level = 2) | // Called from menu function m_index() (index level = 2) | |||
void index_rebuild(int indexlev, int keepopen) | void index_rebuild(int indexlev, int keepopen) | |||
{ | { | |||
using namespace index_names; | using namespace index_names; | |||
void index_rebuild_old(); | void index_rebuild_old(); | |||
int indexlog_dialog_event(zdialog *zd, cchar *event); | int indexlog_dialog_event(zdialog *zd, ch *event); | |||
int index_compare(cchar *rec1, cchar *rec2); | int index_compare(ch *rec1, ch *rec2); | |||
void *index_thread(void *); | void * thumb_thread(void *); | |||
void *thumb_thread(void *); | void * index_thread(void *); | |||
GtkWidget *wlog; | GtkWidget *wlog; | |||
FILE *fid; | FILE *fid; | |||
zlist_t *mlist; | zlist_t *mlist; | |||
char **topfol2, **misstop2; | ch **topfol2, **misstop2; | |||
int *topcc2, *misscc2; | int *topcc2, *misscc2; | |||
int ii, jj, nn; | int ii, jj, nn; | |||
int Ntop, Nthumb; | int Ntop, Nthumb; | |||
int ftf, NF, orec, orec2, nrec, xrec, comp; | int ftf, NF, orec, orec2, nrec, xrec, comp; | |||
int cc, cc1, cc2, err; | int cc, cc1, cc2, err; | |||
int Nnew, Nold; | int Nnew, Nold; | |||
int Xupdates, Tupdates, Tdeletes; | ch *pp, *pp1, *pp2; | |||
char *pp, *pp1, *pp2; | ch buff[XFCC+500]; | |||
char buff[XFCC+500]; | ch **flist, *file, *thumbfile; | |||
char **flist, *file, *thumbfile; | ||||
STATB statB; | STATB statB; | |||
double startime; | double startime; | |||
int Nraw, Nimage; | int Nraw, Nimage; | |||
double rawgb, imagegb; | double rawgb, imagegb; | |||
cchar *indexmess = "No image file index was found.\n" | ch *indexmess = "No image file index was found.\n" | |||
"An image file index will be created.\n" | "An image file index will be created.\n" | |||
"Your image files will not be changed.\n" | "Your image files will not be changed.\n" | |||
"This may need considerable time if you \n" | "This may need considerable time if you \n" | |||
"have many thousands of image files."; | "have many thousands of image files."; | |||
cchar *indexerr2 = "Thumbnails folder: %s \n" | ch *indexerr2 = "Thumbnails folder: %s \n" | |||
"Please remove."; | "Please remove."; | |||
cchar *thumberr = "Thumbnails folder: \n %s \n" | ch *thumberr = "Thumbnails folder: \n %s \n" | |||
"must be named .../thumbnails"; | "must be named .../thumbnails"; | |||
cchar *duperr = "Duplicate or nested folders: \n %s \n %s \n" | ch *duperr = "Duplicate or nested folders: \n %s \n %s \n" | |||
"Please remove."; | "Please remove."; | |||
if (Fblock("index","block edits")) return; // check pending, block | if (Fblock("index","block edits")) return; // check pending, block | |||
startime = get_seconds(); // index function start time | startime = get_seconds(); // index function start time | |||
Findexvalid = 0; | Findexvalid = 0; | |||
Fuserkill = 0; | ||||
// get current top image folders and thumbnails folder | // get current top image folders and thumbnails folder | |||
for (ii = 0; ii < Ntopfolders; ii++) // free prior | for (ii = 0; ii < Ntopfolders; ii++) // free prior | |||
zfree(topfolders[ii]); | zfree(topfolders[ii]); | |||
Ntop = Nthumb = 0; | Ntop = Nthumb = 0; | |||
fid = fopen(image_folders_file,"r"); // read index config file | fid = fopen(image_folders_file,"r"); // read index config file | |||
if (fid) { | if (fid) { | |||
skipping to change at line 547 | skipping to change at line 537 | |||
misstops[Nmisstops++] = topfolders[ii]; // into a separate list | misstops[Nmisstops++] = topfolders[ii]; // into a separate list | |||
else topfolders[jj++] = topfolders[ii]; // (poss. not mounted) | else topfolders[jj++] = topfolders[ii]; // (poss. not mounted) | |||
} | } | |||
Ntopfolders = jj; // valid top image folders | Ntopfolders = jj; // valid top image folders | |||
if (! Ntopfolders) { // none, must ask user | if (! Ntopfolders) { // none, must ask user | |||
zmessageACK(Mwin,indexmess); | zmessageACK(Mwin,indexmess); | |||
goto cleanup; | goto cleanup; | |||
} | } | |||
topfol2 = (char **) zmalloc(Ntopfolders * sizeof(char *),"top-folders"); // top folders with '/' appended | topfol2 = (ch **) zmalloc(Ntopfolders * sizeof(ch *),"top-folders"); // top folders with '/' appended | |||
topcc2 = (int *) zmalloc(Ntopfolders * sizeof(int),"top-folders"); // cc of same | topcc2 = (int *) zmalloc(Ntopfolders * sizeof(int),"top-folders"); // cc of same | |||
misstop2 = 0; | misstop2 = 0; | |||
misscc2 = 0; | misscc2 = 0; | |||
if (Nmisstops) { | if (Nmisstops) { | |||
misstop2 = (char **) zmalloc(Nmisstops * sizeof(char *),"top-folders"); // missing top folders with '/' | misstop2 = (ch **) zmalloc(Nmisstops * sizeof(ch *),"top-folders"); // missing top folders with '/' | |||
misscc2 = (int *) zmalloc(Nmisstops * sizeof(int),"top-folders"); // cc of same | misscc2 = (int *) zmalloc(Nmisstops * sizeof(int),"top-folders"); // cc of same | |||
} | } | |||
for (ii = 0; ii < Ntopfolders; ii++) { // save top folders with appended '/' | for (ii = 0; ii < Ntopfolders; ii++) { // save top folders with appended '/' | |||
topfol2[ii] = zstrdup(topfolders[ii],"top-folders",2); // for use with later comparisons | topfol2[ii] = zstrdup(topfolders[ii],"top-folders",2); // for use with later comparisons | |||
strcat(topfol2[ii],"/"); | strcat(topfol2[ii],"/"); | |||
topcc2[ii] = strlen(topfol2[ii]); | topcc2[ii] = strlen(topfol2[ii]); | |||
} | } | |||
for (ii = 0; ii < Nmisstops; ii++) { | for (ii = 0; ii < Nmisstops; ii++) { | |||
skipping to change at line 584 | skipping to change at line 574 | |||
Plog(1,"free disk space: %d GB \n",nn); | Plog(1,"free disk space: %d GB \n",nn); | |||
if (Nmisstops) | if (Nmisstops) | |||
for (ii = 0; ii < Nmisstops; ii++) // print missing top folders | for (ii = 0; ii < Nmisstops; ii++) // print missing top folders | |||
Plog(1," %s *** not mounted *** \n",misstops[ii]); | Plog(1," %s *** not mounted *** \n",misstops[ii]); | |||
Plog(1,"thumbnails folder: "); // print thumbnails folder | Plog(1,"thumbnails folder: "); // print thumbnails folder | |||
Plog(1,"%s \n",thumbfolder); | Plog(1,"%s \n",thumbfolder); | |||
xmeta_keys[0] = 0; | xmeta_keys[0] = 0; | |||
Plog(1,"extra metadata index: "); | ||||
mlist = zlist_from_file(meta_index_file); // get index extra metadata items | mlist = zlist_from_file(meta_index_file); // get index extra metadata items | |||
if (mlist) { | if (mlist) { | |||
Plog(1,"extra metadata index: "); // 23.1 | ||||
for (ii = 0; ii < zlist_count(mlist); ii++) { | for (ii = 0; ii < zlist_count(mlist); ii++) { | |||
xmeta_keys[ii] = zlist_get(mlist,ii); | xmeta_keys[ii] = zlist_get(mlist,ii); | |||
Plog(1,"%s, ",xmeta_keys[ii]); | Plog(1,"%s, ",xmeta_keys[ii]); | |||
} | } | |||
xmeta_keys[ii] = 0; | xmeta_keys[ii] = 0; | |||
Plog(1,"\n"); | Plog(1,"\n"); | |||
} | } | |||
Nblacklist = 0; | Nblacklist = 0; | |||
skipping to change at line 629 | skipping to change at line 619 | |||
Fblock("index",0); | Fblock("index",0); | |||
return; | return; | |||
} | } | |||
if (indexlev == 2) // update image index for all image files | if (indexlev == 2) // update image index for all image files | |||
Plog(1,"full image index: reports will be complete \n"); | Plog(1,"full image index: reports will be complete \n"); | |||
// create log window for reporting status and statistics | // create log window for reporting status and statistics | |||
if (zd_indexlog) zdialog_free(zd_indexlog); // make dialog for output log | if (zd_indexlog) zdialog_free(zd_indexlog); // make dialog for output log | |||
zd_indexlog = zdialog_new("build index",Mwin,"OK","Cancel",null); | zd_indexlog = zdialog_new("build index",Mwin,"Cancel",null); | |||
zdialog_add_widget(zd_indexlog,"frame","frame","dialog",0,"expand"); | zdialog_add_widget(zd_indexlog,"frame","frame","dialog",0,"expand"); | |||
zdialog_add_widget(zd_indexlog,"scrwin","scrwin","frame"); | zdialog_add_widget(zd_indexlog,"scrwin","scrwin","frame"); | |||
zdialog_add_widget(zd_indexlog,"text","text","scrwin"); | zdialog_add_widget(zd_indexlog,"text","text","scrwin"); | |||
wlog = zdialog_gtkwidget(zd_indexlog,"text"); | wlog = zdialog_gtkwidget(zd_indexlog,"text"); | |||
zdialog_resize(zd_indexlog,700,500); | zdialog_resize(zd_indexlog,700,500); | |||
zdialog_run(zd_indexlog,indexlog_dialog_event,0); | zdialog_run(zd_indexlog,indexlog_dialog_event,0); | |||
textwidget_append(wlog,0,"top image folders:\n"); // log top image folders | textwidget_append(wlog,0,"top image folders:\n"); // log top image folders | |||
for (ii = 0; ii < Ntopfolders; ii++) | for (ii = 0; ii < Ntopfolders; ii++) | |||
textwidget_append(wlog,0," %s\n",topfolders[ii]); | textwidget_append(wlog,0," %s\n",topfolders[ii]); | |||
if (Nmisstops) // log missing top image folders | if (Nmisstops) // log missing top image folders | |||
for (ii = 0; ii < Nmisstops; ii++) | for (ii = 0; ii < Nmisstops; ii++) | |||
textwidget_append(wlog,0," %s *** not mounted *** \n",misstops[ii]); | textwidget_append(wlog,0," %s *** not mounted *** \n",misstops[ii]); | |||
textwidget_append(wlog,0,"thumbnails folder: \n"); // log thumbnails folder | textwidget_append(wlog,0,"thumbnails folder: \n"); // log thumbnails folder | |||
textwidget_append(wlog,0," %s \n",thumbfolder); | textwidget_append(wlog,0," %s \n",thumbfolder); | |||
textwidget_scroll(wlog,-1); | textwidget_scroll(wlog,-1); | |||
if (Ffullindex) { // user: force full re-index | if (FfullindexReq) { // user: force full re-index | |||
Nold = 0; | Nold = 0; | |||
goto get_new_files; | goto get_new_files; | |||
} | } | |||
// read old image index file and build "old list" of index recs | // read old image index file and build "old list" of index recs | |||
textwidget_append2(wlog,0,"reading image index file ...\n"); | textwidget_append2(wlog,0,"reading image index file ...\n"); | |||
cc = maximages * sizeof(xxrec_t *); | cc = maximages * sizeof(xxrec_t *); | |||
xxrec_old = (xxrec_t **) zmalloc(cc,"xxrec-old"); // "old" image index recs | xxrec_old = (xxrec_t **) zmalloc(cc,"xxrec-old"); // "old" image index recs | |||
skipping to change at line 697 | skipping to change at line 687 | |||
quitxx(); | quitxx(); | |||
} | } | |||
} | } | |||
textwidget_append2(wlog,0,"image index records found: %d \n",Nold); | textwidget_append2(wlog,0,"image index records found: %d \n",Nold); | |||
Plog(1,"image index records found: %d \n",Nold); | Plog(1,"image index records found: %d \n",Nold); | |||
// sort old index recs in order of file name and file mod date | // sort old index recs in order of file name and file mod date | |||
if (Nold > 1) | if (Nold > 1) | |||
HeapSort4((char **) xxrec_old,Nold,index_compare); // smp sort | HeapSort4((ch **) xxrec_old,Nold,index_compare); // smp sort | |||
// replace older recs with newer recs that were appended to the file | // replace older recs with newer recs that were appended to the file | |||
// and are now sorted in file name sequence | // and are now sorted in file name sequence | |||
if (Nold > 1) | if (Nold > 1) | |||
{ | { | |||
for (orec = 0, orec2 = 1; orec2 < Nold; orec2++) | for (orec = 0, orec2 = 1; orec2 < Nold; orec2++) | |||
{ | { | |||
if (strmatch(xxrec_old[orec]->file,xxrec_old[orec2]->file)) // memory for replaced recs is lost | if (strmatch(xxrec_old[orec]->file,xxrec_old[orec2]->file)) // memory for replaced recs is lost | |||
xxrec_old[orec] = xxrec_old[orec2]; | xxrec_old[orec] = xxrec_old[orec2]; | |||
skipping to change at line 761 | skipping to change at line 751 | |||
if (flist) zfree(flist); | if (flist) zfree(flist); | |||
} | } | |||
textwidget_append2(wlog,0,"image files found: %d \n",Nnew); | textwidget_append2(wlog,0,"image files found: %d \n",Nnew); | |||
Plog(1,"image files found: %d \n",Nnew); | Plog(1,"image files found: %d \n",Nnew); | |||
// sort new index recs in order of file name and file mod date | // sort new index recs in order of file name and file mod date | |||
if (Nnew > 1) | if (Nnew > 1) | |||
HeapSort4((char **) xxrec_new,Nnew,index_compare); // smp sort | HeapSort4((ch **) xxrec_new,Nnew,index_compare); // smp sort | |||
// create image index table in memory | // create image index table in memory | |||
if (xxrec_tab) | if (xxrec_tab) | |||
{ | { | |||
for (ii = 0; ii < Nxxrec; ii++) // free memory for old xxrec_tab | for (ii = 0; ii < Nxxrec; ii++) // free memory for old xxrec_tab | |||
{ | { | |||
if (xxrec_tab[ii]->file) zfree(xxrec_tab[ii]->file); | if (xxrec_tab[ii]->file) zfree(xxrec_tab[ii]->file); | |||
if (xxrec_tab[ii]->tags) zfree(xxrec_tab[ii]->tags); | if (xxrec_tab[ii]->tags) zfree(xxrec_tab[ii]->tags); | |||
if (xxrec_tab[ii]->title) zfree(xxrec_tab[ii]->title); | if (xxrec_tab[ii]->title) zfree(xxrec_tab[ii]->title); | |||
skipping to change at line 858 | skipping to change at line 848 | |||
goto cleanup; | goto cleanup; | |||
} | } | |||
} | } | |||
Nxxrec = xrec; // final count | Nxxrec = xrec; // final count | |||
if (xxrec_new) zfree(xxrec_new); // free memory | if (xxrec_new) zfree(xxrec_new); // free memory | |||
if (xxrec_old) zfree(xxrec_old); | if (xxrec_old) zfree(xxrec_old); | |||
xxrec_new = xxrec_old = 0; | xxrec_new = xxrec_old = 0; | |||
for (ii = Xupdates = Tupdates = 0; ii < Nxxrec; ii++) { | for (ii = index_updates = thumb_updates = 0; ii < Nxxrec; ii++) { | |||
// count updates required | // count updates required | |||
if (Xstatus[ii] == 2) Xupdates++; | if (Xstatus[ii] == 2) index_updates++; | |||
// index rec updates | // index rec updates | |||
if (Tstatus[ii] == 2) Tupdates++; | if (Tstatus[ii] == 2) thumb_updates++; | |||
// thumbnail file updates | // thumbnail file updates | |||
} | } | |||
textwidget_append(wlog,0,"index updates needed: %d thumbnails: %d \n",Xupdat | textwidget_append(wlog,0,"index updates needed: %d thumbnails: %d \n", | |||
es,Tupdates); | index_updates,thumb_updates); | |||
Plog(1,"index updates needed: %d thumbnails: %d \n",Xupdates,Tupdates); | Plog(1,"index updates needed: %d thumbnails: %d \n", | |||
index_updates,thumb_updates); | ||||
textwidget_append2(wlog,0,"\n"); // scroll down | textwidget_append2(wlog,0,"\n"); // scroll down | |||
textwidget_scroll(wlog,-1); | textwidget_scroll(wlog,-1); | |||
// Process entries needing update in the new index table | // Process entries needing update in the new index table // 23.1 | |||
// (new files or files dated later than in old index table). | // (new files or files dated later than in old index table). | |||
// Get updated metadata from image file EXIF/IPTC data. | // Get updated metadata from image file metadata. | |||
// Add missing or update stale thumbnail file. | // Add missing or update stale thumbnail file. | |||
Xupdates = Tupdates = Tdeletes = 0; | zadd_locked(Ffuncbusy,+1); | |||
Xthread1 = Xthread2 = 0; | Fwatchescape = 1; | |||
Tthread1 = Tthread2 = 0; | // [esc] key can cancel | |||
Fescape = 0; | ||||
for (xrec = 0; xrec < Nxxrec; xrec++) | index_updates = thumb_updates = thumb_deletes = 0; | |||
// loop all index recs | ||||
{ | ||||
if (Fuserkill || Fshutdown) break; | ||||
// killed by user | ||||
if (Xstatus[xrec] == 2) { | index_thread_busy = 1; | |||
// update metadata | // initially busy | |||
Xupdates++; | start_detached_thread(index_thread,0); | |||
while (Xthread1 - Xthread2 == NST) zsleep(0.001); | // start metadata index thread | |||
// wait for free thread | ||||
Xthread1++; | ||||
start_detached_thread(index_thread,&Nval[xrec]); | ||||
} | ||||
if (Tstatus[xrec] == 2) { | while (index_thread_busy) { | |||
// update thumbnail | // while thread running | |||
Tupdates++; | if (Fescape) goto bailout; | |||
while (Tthread1 - Tthread2 == NWT) zsleep(0.001); | textwidget_replace(wlog,0,-1,"%d %d \n",index_updates,thumb_updates); | |||
// wait for free thread | // update log window | |||
Tthread1++; | zmainsleep(0.01); | |||
start_detached_thread(thumb_thread,&Nval[xrec]); | } | |||
} | ||||
if (Xstatus[xrec] == 2 || Tstatus[xrec] == 2) { | thumb_thread_busy = 1; | |||
// update counters | // initially busy | |||
file = xxrec_tab[xrec]->file; | start_detached_thread(thumb_thread,0); | |||
textwidget_replace(wlog,0,-1,"%d %d %s \n",Xupdates,Tupdates,file); | // start thumbnails thread | |||
// update log window | ||||
zmainsleep(0.001); | ||||
// show every update | ||||
} | ||||
if (Xupdates && Xupdates == 5000 * (Xupdates / 5000)) | while (thumb_thread_busy) { | |||
// update image index file | // while thread running | |||
{ | if (Fescape) goto bailout; | |||
// every 5000 updated recs. | textwidget_replace(wlog,0,-1,"%d %d \n",index_updates,thumb_updates); | |||
ftf = 1; | // update log window | |||
for (ii = 0; ii < xrec; ii++) | zmainsleep(0.01); | |||
write_xxrec_seq(xxrec_tab[ii],ftf); | ||||
write_xxrec_seq(null,ftf); | ||||
// close output | ||||
} | ||||
} | } | |||
while (Xthread2 != Xthread1) zsleep(0.01); | bailout: | |||
// wait for last threads to exit | ||||
while (Tthread2 != Tthread1) zsleep(0.01); | ||||
exif_server(0,0,0); // kill exiftool servers | zadd_locked(Ffuncbusy,-1); | |||
if (Fuserkill || Fshutdown) goto cleanup; | if (Fescape || Fshutdown) goto cleanup; // indexed function killed | |||
textwidget_replace(wlog,0,-1,"index updates: %d thumbnails: %d \n", // final statistics | textwidget_replace(wlog,0,-1,"index updates: %d thumbnails: %d \n", // final statistics | |||
Xupdates, Tupdates); | index_updates, thumb_updates); | |||
Plog(1,"index updates: %d thumbnail updates: %d, deletes: %d \n", | Plog(1,"index updates: %d thumbnail updates: %d, deletes: %d \n", | |||
Xupdates, Tupdates, Tdeletes); | index_updates, thumb_updates, thumb_deletes); | |||
// write updated index records to image index file | // write updated index records to image index file | |||
Plog(1,"writing updated image index file \n"); | Plog(1,"writing updated image index file \n"); | |||
if (Nxxrec) { | if (Nxxrec) { | |||
ftf = 1; | ftf = 1; | |||
for (ii = 0; ii < Nxxrec; ii++) | for (ii = 0; ii < Nxxrec; ii++) | |||
write_xxrec_seq(xxrec_tab[ii],ftf); | write_xxrec_seq(xxrec_tab[ii],ftf); | |||
write_xxrec_seq(null,ftf); // close output | write_xxrec_seq(null,ftf); // close output | |||
skipping to change at line 989 | skipping to change at line 967 | |||
if (err) { // ignore symlinks | if (err) { // ignore symlinks | |||
zmessageACK(Mwin,strerror(errno)); | zmessageACK(Mwin,strerror(errno)); | |||
NF = 0; | NF = 0; | |||
} | } | |||
textwidget_append2(wlog,0,"thumbnails found: %d \n",NF); | textwidget_append2(wlog,0,"thumbnails found: %d \n",NF); | |||
Plog(1,"thumbnails found: %d \n",NF); | Plog(1,"thumbnails found: %d \n",NF); | |||
textwidget_append2(wlog,0,"deleting orphan thumbnails ... \n"); | textwidget_append2(wlog,0,"deleting orphan thumbnails ... \n"); | |||
Tdeletes = 0; | thumb_deletes = 0; | |||
for (ii = 0; ii < NF; ii++) | for (ii = 0; ii < NF; ii++) | |||
{ | { | |||
thumbfile = flist[ii]; | thumbfile = flist[ii]; | |||
file = thumb2imagefile(thumbfile); // thumbnail corresponding file | file = thumb2imagefile(thumbfile); // thumbnail corresponding file | |||
if (file) { // exists, keep thumbnail | if (file) { // exists, keep thumbnail | |||
zfree(file); | zfree(file); | |||
zfree(thumbfile); | zfree(thumbfile); | |||
continue; | continue; | |||
} | } | |||
pp = thumbfile + strlen(thumbfolder); // corresponding file within | pp = thumbfile + strlen(thumbfolder); // corresponding file within | |||
for (jj = 0; jj < Nmisstops; jj++) // a missing top image folder? | for (jj = 0; jj < Nmisstops; jj++) // a missing top image folder? | |||
if (strmatchN(misstop2[jj],pp,misscc2[jj])) break; | if (strmatchN(misstop2[jj],pp,misscc2[jj])) break; | |||
if (jj < Nmisstops) continue; // yes, keep thumbnail | if (jj < Nmisstops) continue; // yes, keep thumbnail | |||
remove(thumbfile); // remove thumbnail file | remove(thumbfile); // remove thumbnail file | |||
zfree(thumbfile); | zfree(thumbfile); | |||
Tdeletes++; | thumb_deletes++; | |||
} | } | |||
if (flist) zfree(flist); | if (flist) zfree(flist); | |||
textwidget_append2(wlog,0,"thumbnails deleted: %d \n",Tdeletes); | textwidget_append2(wlog,0,"thumbnails deleted: %d \n",thumb_deletes); | |||
Plog(1,"thumbnails deleted: %d \n",Tdeletes); | Plog(1,"thumbnails deleted: %d \n",thumb_deletes); | |||
textwidget_append2(wlog,0,"%s\n","COMPLETED"); // index complete and OK | textwidget_append2(wlog,0,"%s\n","COMPLETED"); // index complete and OK | |||
textwidget_scroll(wlog,-1); | textwidget_scroll(wlog,-1); | |||
Plog(1,"index time: %.1f seconds \n",get_seconds() - startime); // log elapsed time | Plog(1,"index time: %.1f seconds \n",get_seconds() - startime); // log elapsed time | |||
if (Nxxrec) { | if (Nxxrec) { | |||
Findexvalid = 2; // image index is complete | Findexvalid = 2; // image index is complete | |||
Findexlev = 2; // fotoxx command: index new files | Findexlev = 2; // fotoxx command: index new files | |||
FMindexlev = 1; // file manager: old index only | FMindexlev = 1; // file manager: old index only | |||
FfullindexReq = 0; // cancel user full index reqest | ||||
} | } | |||
cleanup: // free allocated memory | cleanup: // free allocated memory | |||
if (Fshutdown) { | if (Fescape) { | |||
Fblock("index",0); | zsleep(1); | |||
return; | // user aborted | |||
// process terminating | Findexvalid = 0; | |||
} | } | |||
if (xxrec_old) zfree(xxrec_old); | if (xxrec_old) zfree(xxrec_old); | |||
if (xxrec_new) zfree(xxrec_new); | if (xxrec_new) zfree(xxrec_new); | |||
xxrec_old = xxrec_new = 0; | xxrec_old = xxrec_new = 0; | |||
if (Xstatus) zfree(Xstatus); | if (Xstatus) zfree(Xstatus); | |||
if (Tstatus) zfree(Tstatus); | if (Tstatus) zfree(Tstatus); | |||
Xstatus = Tstatus = 0; | Xstatus = Tstatus = 0; | |||
if (zd_indexlog && ! keepopen) // kill index log window | if (zd_indexlog && ! keepopen) // kill index log window | |||
zdialog_send_event(zd_indexlog,"exitlog"); | zdialog_send_event(zd_indexlog,"exitlog"); | |||
Ffullindex = 0; | Fwatchescape = Fescape = 0; | |||
// full re-index done | ||||
Fblock("index",0); // unblock | Fblock("index",0); // unblock | |||
return; | return; | |||
} | } | |||
// ----------------------------------------------------------------------------- - | // ----------------------------------------------------------------------------- - | |||
// thread process - create thumbnail file for given image file | // thumbnail thread - create thumbnail files for image files needing update | |||
namespace index_thumb_names | ||||
{ | ||||
int threads_started; | ||||
int threads_completed; | ||||
} | ||||
void * thumb_thread(void *arg) | ||||
// 23.1 | ||||
{ | ||||
using namespace index_names; | ||||
using namespace index_thumb_names; | ||||
void *thumb_thread2(void *); | ||||
int xrec; | ||||
thumb_thread_busy = 1; | ||||
thumb_updates = 0; | ||||
threads_started = threads_completed = 0; | ||||
void * thumb_thread(void *arg) | for (xrec = 0; xrec < Nxxrec; xrec++) | |||
{ | ||||
if (Tstatus[xrec] != 2) continue; | ||||
// thumbnail update not needed | ||||
while (threads_started - threads_completed >= NWT) zsleep(0.001); | ||||
if (Fescape) break; | ||||
// user kill | ||||
threads_started++; | ||||
start_detached_thread(thumb_thread2,&Nval[xrec]); | ||||
// update thumbnail file | ||||
thumb_updates++; | ||||
} | ||||
while (threads_started - threads_completed > 0) zsleep(0.001); | ||||
// wait for last thread | ||||
thumb_thread_busy = 0; | ||||
return 0; | ||||
} | ||||
void * thumb_thread2(void *arg) | ||||
{ | { | |||
using namespace index_names; | using namespace index_names; | |||
using namespace index_thumb_names; | ||||
int xrec; | int xrec; | |||
char *file; | ch *file; | |||
xrec = *((int *) arg); | xrec = *((int *) arg); | |||
file = xxrec_tab[xrec]->file; // image file to check | file = xxrec_tab[xrec]->file; // image file | |||
zfuncs::zappcrash_context1 = file; | zfuncs::zappcrash_context1 = file; | |||
update_thumbfile(file); | update_thumbfile(file); | |||
// do thumbnail update if needed | // do thumbnail update | |||
zadd_locked(Tthread2,+1); | threads_completed++; | |||
// completions | ||||
return 0; | return 0; | |||
} | } | |||
// ----------------------------------------------------------------------------- - | // ----------------------------------------------------------------------------- - | |||
// thread process - get image file metadata and build image index rec. | // index thread | |||
// get metadata for image files needing update and build image index record | ||||
// thread has no GTK calls | // thread has no GTK calls | |||
void * index_thread(void *arg) | void * index_thread(void *arg) | |||
{ | { | |||
using namespace index_names; | using namespace index_names; | |||
int xrec, err, ii, nkey, xcc, acc; | int cc, xcc, acc; | |||
int NF = 0, NK, ff, kk, fkk; | ||||
int ww, hh; | int ww, hh; | |||
char *file, *pp; | int xrec; | |||
ch **files = 0, *file; | ||||
float flati, flongi; | float flati, flongi; | |||
char xmetarec[MXmaxcc]; // max. extra metadata cc | ch xmetarec[xmetaXcc]; // max. extra metadata cc | |||
STATB statB; | STATB statB; | |||
xxrec_t **xxrecs = 0, *xxrec; | ||||
cchar *exifkeys[100] = { | ch *metadate = 0, *metatags = 0, *metarating = 0; | |||
"FileName", exif_date_key, iptc_keywords_key, | ch *metaww = 0, *metahh = 0, *metatitle = 0, *metadesc = 0; | |||
// first 12 keys are fixed | ch *metalocation = 0, *metacountry = 0, *metalat = 0, *metalong = 0; | |||
iptc_rating_key, exif_ww_key, exif_hh_key, | ||||
iptc_title_key, iptc_description_key, | ||||
exif_location_key, exif_country_key, | ||||
exif_lati_key, exif_longi_key }; | ||||
char *ppv[100], *exiffile = 0; | ||||
char *exifdate = 0, *iptctags = 0, *iptcrating = 0; | ||||
char *exifww = 0, *exifhh = 0, *iptctitle = 0, *iptcdesc = 0; | ||||
char *exiflocation = 0, *exifcountry = 0, *exiflat = 0, *exiflong = 0; | ||||
xrec = *((int *) arg); | ch *kname[100] = { | |||
file = xxrec_tab[xrec]->file; | meta_date_key, meta_tags_key, | |||
// image file | // first 11 keys are fixed | |||
zfuncs::zappcrash_context2 = file; | meta_rating_key, meta_ww_key, meta_hh_key, | |||
meta_title_key, meta_description_key, | ||||
meta_location_key, meta_country_key, | ||||
meta_lati_key, meta_longi_key }; | ||||
if (! regfile(file,&statB)) { | ch **kdata = 0; | |||
Plog(0,"index_thread: FNF %s \n",file); | ||||
goto exit_thread; | ||||
} | ||||
nkey = 12; | index_thread_busy = 1; | |||
// add keys for indexed metadata | ||||
for (ii = 0; ii < MXmax; ii++) { | if (! Nxxrec) goto exit_thread; | |||
// from exifkeys[12] | ||||
if (! xmeta_keys[ii]) break; | ||||
exifkeys[nkey] = xmeta_keys[ii]; | ||||
nkey++; | ||||
} | ||||
err = exif_get(file,exifkeys,ppv,nkey); | NK = 11; | |||
// get exif/iptc metadata | // add keys for indexed metadata | |||
if (err) { | for (kk = 0; kk < xmetamaxkeys; kk++) { | |||
Plog(0,"exif_get() failure: %s \n",file); | // from kname[12] | |||
// metadata unreadable | if (! xmeta_keys[kk]) break; | |||
goto exit_thread; | kname[NK] = xmeta_keys[kk]; | |||
NK++; | ||||
// total keys | ||||
} | } | |||
exiffile = ppv[0]; | cc = Nxxrec * sizeof(ch *); | |||
// base file name | // get list of files needing update | |||
pp = strrchr(file,'/'); | files = (ch**) zmalloc(cc,"index_thread"); | |||
if (! exiffile || ! strmatch(exiffile,pp+1)) { | xxrecs = (xxrec_t **) zmalloc(cc,"index_thread"); | |||
// image file has no metadata | ||||
Plog(0,"exif_get() no data: %s \n",file); | for (xrec = ff = 0; xrec < Nxxrec; xrec++) | |||
goto exit_thread; | { | |||
if (Xstatus[xrec] != 2) continue; | ||||
// index update not needed | ||||
xxrecs[ff] = xxrec_tab[xrec]; | ||||
files[ff] = xxrecs[ff]->file; | ||||
// image file | ||||
ff++; | ||||
} | } | |||
exifdate = ppv[1]; | NF = ff; | |||
// exif/iptc metadata returned | // file count | |||
iptctags = ppv[2]; | if (! NF) goto exit_thread; | |||
// 12 fixed keys | ||||
iptcrating = ppv[3]; | ||||
exifww = ppv[4]; | ||||
exifhh = ppv[5]; | ||||
iptctitle = ppv[6]; | ||||
iptcdesc = ppv[7]; | ||||
exiflocation = ppv[8]; | ||||
exifcountry = ppv[9]; | ||||
exiflat = ppv[10]; | ||||
exiflong = ppv[11]; | ||||
if (exifdate && strlen(exifdate) > 3) | cc = NF * NK * sizeof(ch *); | |||
// exif date (photo date) | // get space for returned key data | |||
exif_tagdate(exifdate,xxrec_tab[xrec]->pdate); | kdata = (ch **) zmalloc(cc,"index_thread"); | |||
if (iptcrating && strlen(iptcrating)) { | meta_getN(files,NF,kname,kdata,NK); | |||
// iptc rating '0' - '5' | // get metadata for all files | |||
xxrec_tab[xrec]->rating[0] = *iptcrating; | ||||
xxrec_tab[xrec]->rating[1] = 0; | ||||
} | ||||
else strcpy(xxrec_tab[xrec]->rating,"0"); | ||||
// not present | ||||
if (exifww && exifhh) { | for (ff = 0; ff < NF; ff++) | |||
convSI(exifww,ww); | // loop image files | |||
convSI(exifhh,hh); | { | |||
if (ww > 0 && hh > 0) { | if (Fescape) break; | |||
xxrec_tab[xrec]->ww = ww; | ||||
xxrec_tab[xrec]->hh = hh; | file = files[ff]; | |||
zfuncs::zappcrash_context1 = file; | ||||
if (! regfile(file,&statB)) { | ||||
Plog(0,"index_thread: FNF %s \n",file); | ||||
continue; | ||||
} | } | |||
} | ||||
xxrec_tab[xrec]->fsize = statB.st_size; // file size | xxrec = xxrecs[ff]; | |||
if (iptctags && strlen(iptctags)) { | fkk = ff * NK; | |||
// iptc tags | // key data for file ff | |||
xxrec_tab[xrec]->tags = iptctags; | ||||
iptctags = 0; | ||||
} | ||||
if (iptctitle && strlen(iptctitle)) { | metadate = kdata[fkk+0]; | |||
// iptc title | // meta metadata returned | |||
xxrec_tab[xrec]->title = iptctitle; | metatags = kdata[fkk+1]; | |||
iptctitle = 0; | // 11 fixed keys | |||
} | metarating = kdata[fkk+2]; | |||
metaww = kdata[fkk+3]; | ||||
metahh = kdata[fkk+4]; | ||||
metatitle = kdata[fkk+5]; | ||||
metadesc = kdata[fkk+6]; | ||||
metalocation = kdata[fkk+7]; | ||||
metacountry = kdata[fkk+8]; | ||||
metalat = kdata[fkk+9]; | ||||
metalong = kdata[fkk+10]; | ||||
if (metadate && strlen(metadate) > 3) | ||||
// photo date | ||||
meta_tagdate(metadate,xxrec->pdate); | ||||
if (metarating && strlen(metarating)) { | ||||
// rating '0' - '5' | ||||
xxrec->rating[0] = *metarating; | ||||
xxrec->rating[1] = 0; | ||||
} | ||||
else strcpy(xxrec->rating,"0"); | ||||
// not present | ||||
if (metaww && metahh) { | ||||
convSI(metaww,ww); | ||||
convSI(metahh,hh); | ||||
if (ww > 0 && hh > 0) { | ||||
xxrec->ww = ww; | ||||
xxrec->hh = hh; | ||||
} | ||||
} | ||||
if (iptcdesc && strlen(iptcdesc)) { | xxrec->fsize = statB.st_size; | |||
// iptc description | // file size | |||
xxrec_tab[xrec]->desc = iptcdesc; | ||||
iptcdesc = 0; | ||||
} | ||||
if (exiflocation && strlen(exiflocation)) { | if (metatags && strlen(metatags)) | |||
xxrec_tab[xrec]->location = exiflocation; | // tags | |||
exiflocation = 0; | xxrec->tags = zstrdup(metatags,"index_thread"); | |||
} | ||||
if (exifcountry && strlen(exifcountry)) { | if (metatitle && strlen(metatitle)) | |||
xxrec_tab[xrec]->country = exifcountry; | // title | |||
exifcountry = 0; | xxrec->title = zstrdup(metatitle,"index_thread"); | |||
} | ||||
if (exiflat && exiflong) { | if (metadesc && strlen(metadesc)) | |||
flati = atofz(exiflat); | // description | |||
flongi = atofz(exiflong); | xxrec->desc = zstrdup(metadesc,"index_thread"); | |||
if (flati < -90.0 || flati > 90.0) flati = flongi = 0; | ||||
if (flongi < -180.0 || flongi > 180.0) flati = flongi = 0; | ||||
xxrec_tab[xrec]->flati = flati; | ||||
xxrec_tab[xrec]->flongi = flongi; | ||||
} | ||||
xcc = 0; | if (metalocation && strlen(metalocation)) | |||
xxrec->location = zstrdup(metalocation,"index_thread"); | ||||
// location (city) | ||||
for (ii = 12; ii < nkey; ii++) | if (metacountry && strlen(metacountry)) | |||
// extra indexed metadata if any | // country | |||
{ | xxrec->country = zstrdup(metacountry,"index_thread"); | |||
if (! ppv[ii]) continue; | ||||
acc = strlen(exifkeys[ii]) + strlen(ppv[ii]) + 3; | if (metalat && metalong) { | |||
if (acc > 100 || acc + xcc > MXmaxcc-2) { | // geocoordinates | |||
// limit each key < 100, all < MXmaxcc | flati = atofz(metalat); | |||
Plog(0,"indexed metadata too big: %s %s \n",exifkeys[ii],file); | flongi = atofz(metalong); | |||
continue; | if (flati < -90.0 || flati > 90.0) flati = flongi = 0; | |||
if (flongi < -180.0 || flongi > 180.0) flati = flongi = 0; | ||||
xxrec->flati = flati; | ||||
xxrec->flongi = flongi; | ||||
} | } | |||
strcpy(xmetarec+xcc,exifkeys[ii]); | ||||
// construct series | ||||
xcc += strlen(exifkeys[ii]); | ||||
// "keyname=keydata^ " | ||||
xmetarec[xcc++] = '='; | ||||
strcpy(xmetarec+xcc,ppv[ii]); | ||||
xcc += strlen(ppv[ii]); | ||||
strcpy(xmetarec+xcc,"^ "); | ||||
xcc += 2; | ||||
zfree(ppv[ii]); | ||||
} | ||||
if (xcc > 0) zstrcopy(xxrec_tab[xrec]->xmeta,xmetarec,"xxrec-data"); | ||||
exit_thread: | ||||
if (! xxrec_tab[xrec]->pdate[0]) | ||||
// missing values are "null" | ||||
strcpy(xxrec_tab[xrec]->pdate,"null"); | ||||
if (! xxrec_tab[xrec]->tags) | ||||
xxrec_tab[xrec]->tags = zstrdup("null","xxrec-data"); | ||||
if (! xxrec_tab[xrec]->title) | ||||
xxrec_tab[xrec]->title = zstrdup("null","xxrec-data"); | ||||
if (! xxrec_tab[xrec]->desc) | ||||
xxrec_tab[xrec]->desc = zstrdup("null","xxrec-data"); | ||||
if (! xxrec_tab[xrec]->location) | ||||
xxrec_tab[xrec]->location = zstrdup("null","xxrec-data"); | ||||
if (! xxrec_tab[xrec]->country) | ||||
xxrec_tab[xrec]->country = zstrdup("null","xxrec-data"); | ||||
if (! xxrec_tab[xrec]->xmeta) | ||||
xxrec_tab[xrec]->xmeta = zstrdup("null","xxrec-data"); | ||||
if (exiffile) zfree(exiffile); | ||||
if (exifdate) zfree(exifdate); | ||||
// free EXIF data | ||||
if (iptcrating) zfree(iptcrating); | ||||
if (exifww) zfree(exifww); | ||||
if (exifhh) zfree(exifhh); | ||||
if (iptctags) zfree(iptctags); | ||||
if (iptctitle) zfree(iptctitle); | ||||
if (iptcdesc) zfree(iptcdesc); | ||||
if (exiflocation) zfree(exiflocation); | ||||
if (exifcountry) zfree(exifcountry); | ||||
if (exiflat) zfree(exiflat); | ||||
if (exiflong) zfree(exiflong); | ||||
zadd_locked(Xthread2,+1); | xcc = 0; | |||
for (kk = 11; kk < NK; kk++) | ||||
// extra indexed metadata if any | ||||
{ | ||||
if (! kdata[fkk+kk]) continue; | ||||
acc = strlen(kname[kk]) + strlen(kdata[fkk+kk]) + 3; | ||||
if (acc + xcc >= xmetaXcc-2) { | ||||
// limit key and data < xmetaXcc | ||||
Plog(0,"indexed metadata too big: %s %s \n",kname[kk],file); | ||||
break; | ||||
} | ||||
strcpy(xmetarec+xcc,kname[kk]); | ||||
// construct series | ||||
xcc += strlen(kname[kk]); | ||||
// "keyname=keydata^ " | ||||
xmetarec[xcc++] = '='; | ||||
strcpy(xmetarec+xcc,kdata[fkk+kk]); | ||||
xcc += strlen(kdata[fkk+kk]); | ||||
strcpy(xmetarec+xcc,"^ "); | ||||
xcc += 2; | ||||
} | ||||
if (xcc > 0) xxrec->xmeta = zstrdup(xmetarec,"index_thread"); | ||||
if (! xxrec->pdate[0]) | ||||
// missing values are "null" | ||||
strcpy(xxrec->pdate,"null"); | ||||
if (! xxrec->tags) | ||||
xxrec->tags = zstrdup("null","index_thread"); | ||||
if (! xxrec->title) | ||||
xxrec->title = zstrdup("null","index_thread"); | ||||
if (! xxrec->desc) | ||||
xxrec->desc = zstrdup("null","index_thread"); | ||||
if (! xxrec->location) | ||||
xxrec->location = zstrdup("null","index_thread"); | ||||
if (! xxrec->country) | ||||
xxrec->country = zstrdup("null","index_thread"); | ||||
if (! xxrec->xmeta) | ||||
xxrec->xmeta = zstrdup("null","index_thread"); | ||||
} | ||||
exit_thread: | ||||
if (xxrecs) zfree(xxrecs); | ||||
// free memory | ||||
if (files) zfree(files); | ||||
if (NF && NK) { | ||||
for (kk = 0; kk < NF * NK; kk++) | ||||
if (kdata[kk]) zfree(kdata[kk]); | ||||
zfree(kdata); | ||||
} | ||||
index_thread_busy = 0; | ||||
return 0; | return 0; | |||
} | } | |||
// ----------------------------------------------------------------------------- - | // ----------------------------------------------------------------------------- - | |||
// index log window dialog response function | // index log window dialog response function | |||
int indexlog_dialog_event(zdialog *zd, cchar *event) | int indexlog_dialog_event(zdialog *zd, ch *event) | |||
{ | { | |||
using namespace index_names; | using namespace index_names; | |||
int nn; | if (strmatch(event,"escape")) zd->zstat = -2; | |||
cchar *canmess = "Cancel image index function?"; | // 23.1 | |||
if (strmatch(event,"exitlog")) { // auto-kill from index_rebuild() | if (strmatch(event,"exitlog")) { // auto-kill from index_rebuild() | |||
zmainloop(); | zmainloop(); | |||
zsleep(0.5); | zsleep(0.5); | |||
zdialog_free(zd); | zdialog_free(zd); | |||
zd_indexlog = 0; | zd_indexlog = 0; | |||
return 1; | return 1; | |||
} | } | |||
if (! zd->zstat) return 1; // continue | if (! zd->zstat) return 1; // continue | |||
if (zd->zstat == 1 || zd->zstat == 2) { | ||||
// [ OK ] or [Cancel] button | ||||
if (Findexvalid) { | ||||
zdialog_free(zd); | ||||
// index completed, kill dialog | ||||
zd_indexlog = 0; | ||||
return 1; | ||||
} | ||||
nn = zdialog_choose(Mwin,"mouse",canmess,"No","Yes",null); | ||||
// incomplete, ask for confirmation | ||||
if (nn == 1) { | ||||
zd->zstat = 0; | ||||
// continue | ||||
return 1; | ||||
} | ||||
} | ||||
zdialog_free(zd); // cancel, kill index job | zdialog_free(zd); // cancel, kill index job | |||
zd_indexlog = 0; | zd_indexlog = 0; | |||
Fuserkill = 1; | if (Fwatchescape) Fescape = 1; // stop index process 23.1 | |||
return 1; | return 1; | |||
} | } | |||
// ----------------------------------------------------------------------------- - | // ----------------------------------------------------------------------------- - | |||
// sort compare function - compare index records and return | // sort compare function - compare index records and return | |||
// <0 0 >0 for rec1 < rec2 rec1 == rec2 rec1 > rec2 | // <0 0 >0 for rec1 < rec2 rec1 == rec2 rec1 > rec2 | |||
int index_compare(cchar *rec1, cchar *rec2) | int index_compare(ch *rec1, ch *rec2) | |||
{ | { | |||
xxrec_t *xxrec1 = (xxrec_t *) rec1; | xxrec_t *xxrec1 = (xxrec_t *) rec1; | |||
xxrec_t *xxrec2 = (xxrec_t *) rec2; | xxrec_t *xxrec2 = (xxrec_t *) rec2; | |||
int nn = strcmp(xxrec1->file,xxrec2->file); | int nn = strcmp(xxrec1->file,xxrec2->file); | |||
if (nn) return nn; | if (nn) return nn; | |||
nn = strcmp(xxrec1->fdate,xxrec2->fdate); | nn = strcmp(xxrec1->fdate,xxrec2->fdate); | |||
return nn; | return nn; | |||
} | } | |||
/******************************************************************************* */ | /******************************************************************************* */ | |||
// quick incremental index rebuild with no user interface | // quick incremental index rebuild with no user interface | |||
void m_quick_index(GtkWidget *, cchar *) | void m_quick_index(GtkWidget *, ch *) | |||
{ | { | |||
char *galleryname = 0; | ch *galleryname = 0; | |||
F1_help_topic = "quick index"; | F1_help_topic = "quick index"; | |||
Plog(1,"m_quick_index \n"); | Plog(1,"m_quick_index \n"); | |||
if (Fblock(0,"blocked edits")) return; // check nothing pending | if (Fblock(0,"blocked edits")) return; // check nothing pending | |||
if (navi::galleryname && navi::gallerytype == FOLDER) // save current gallery | if (navi::galleryname && navi::gallerytype == FOLDER) // save current gallery | |||
galleryname = zstrdup(navi::galleryname,"quick-index"); | galleryname = zstrdup(navi::galleryname,"quick-index"); | |||
skipping to change at line 1371 | skipping to change at line 1378 | |||
Ntab++; | Ntab++; | |||
if (Ntab == maximages) { | if (Ntab == maximages) { | |||
zmessageACK(Mwin,"exceeded max. images: %d",maximages); | zmessageACK(Mwin,"exceeded max. images: %d",maximages); | |||
quitxx(); | quitxx(); | |||
} | } | |||
} | } | |||
// sort index recs in order of file name and file mod date | // sort index recs in order of file name and file mod date | |||
if (Ntab) | if (Ntab) | |||
HeapSort4((char **) xxrec_tab,Ntab,index_compare); // smp sort | HeapSort4((ch **) xxrec_tab,Ntab,index_compare); // smp sort | |||
// replace older recs with newer (appended) recs now sorted together | // replace older recs with newer (appended) recs now sorted together | |||
if (Ntab) | if (Ntab) | |||
{ | { | |||
for (rec = 0, rec2 = 1; rec2 < Ntab; rec2++) | for (rec = 0, rec2 = 1; rec2 < Ntab; rec2++) | |||
{ | { | |||
if (strmatch(xxrec_tab[rec]->file,xxrec_tab[rec2]->file)) | if (strmatch(xxrec_tab[rec]->file,xxrec_tab[rec2]->file)) | |||
xxrec_tab[rec] = xxrec_tab[rec2]; | xxrec_tab[rec] = xxrec_tab[rec2]; | |||
else { | else { | |||
skipping to change at line 1400 | skipping to change at line 1407 | |||
Nxxrec = Ntab; | Nxxrec = Ntab; | |||
if (Nxxrec) Findexvalid = 1; // index OK but missing new files | if (Nxxrec) Findexvalid = 1; // index OK but missing new files | |||
return; | return; | |||
} | } | |||
/******************************************************************************* */ | /******************************************************************************* */ | |||
// move fotoxx home folder with all contained user files | // move fotoxx home folder with all contained user files | |||
// does not return. starts new session if OK. | // does not return. starts new session if OK. | |||
void m_move_fotoxx_home(GtkWidget *, cchar *) | void m_move_fotoxx_home(GtkWidget *, ch *) | |||
{ | { | |||
int yn, ii, nrecs, err; | int yn, ii, nrecs, err; | |||
zlist_t *zlist; | zlist_t *zlist; | |||
FILE *fid; | FILE *fid; | |||
char oldhome[200], newhome[200], thumbfolder[200]; | ch oldhome[200], newhome[200], thumbfolder[200]; | |||
char new_image_folders_file[200]; | ch new_image_folders_file[200]; | |||
char *pp, fotoxxhome[100]; | ch *pp, fotoxxhome[100]; | |||
cchar *mess1 = "Do you want to move Fotoxx home? \n" | ch *mess1 = "Do you want to move Fotoxx home? \n" | |||
" from: %s \n to: %s"; | " from: %s \n to: %s"; | |||
cchar *mess3 = "moving files ..."; | ch *mess3 = "moving files ..."; | |||
F1_help_topic = "move fotoxx home"; | F1_help_topic = "move fotoxx home"; | |||
Plog(1,"m_move_fotoxx_home \n"); | Plog(1,"m_move_fotoxx_home \n"); | |||
if (Fblock("move_home","block edits")) return; // check pending, block | if (Fblock("move_home","block edits")) return; // check pending, block | |||
strncpy0(oldhome,get_zhomedir(),200); // get present home folder | strncpy0(oldhome,get_zhomedir(),200); // get present home folder | |||
pp = oldhome + strlen(oldhome); // remove trailing '/' if present | pp = oldhome + strlen(oldhome); // remove trailing '/' if present | |||
skipping to change at line 1524 | skipping to change at line 1531 | |||
quitxx(); // exit this session | quitxx(); // exit this session | |||
return; | return; | |||
} | } | |||
/******************************************************************************* */ | /******************************************************************************* */ | |||
// user preferences and settings dialog | // user preferences and settings dialog | |||
namespace settings | namespace settings | |||
{ | { | |||
cchar *startopt[8][2] = { | ch *startopt[8][2] = { | |||
{ "recent", "Recent Files Gallery" }, // fotoxx startup view options | { "recent", "Recent Files Gallery" }, // fotoxx startup view options | |||
{ "newest", "Newest Files Gallery" }, | { "newest", "Newest Files Gallery" }, | |||
{ "specG", "Specific Gallery" }, | { "specG", "Specific Gallery" }, | |||
{ "album", "Album Gallery" }, | { "album", "Album Gallery" }, | |||
{ "prevG", "Previous Gallery" }, | { "prevG", "Previous Gallery" }, | |||
{ "prevF", "Previous File" }, | { "prevF", "Previous File" }, | |||
{ "specF", "Specific File" }, | { "specF", "Specific File" }, | |||
{ "blank", "Blank Window" } }; | { "blank", "Blank Window" } }; | |||
int NSO = 8; | int NSO = 8; | |||
cchar *tiffopt[4][2] = { // TIFF file compression options | ch *tiffopt[4][2] = { // TIFF file compression options | |||
{ "NONE", "1" }, | { "NONE", "1" }, | |||
{ "LZW", "5" }, | { "LZW", "5" }, | |||
{ "PACKBITS", "32773" }, | { "PACKBITS", "32773" }, | |||
{ "DEFLATE", "8" } }; | { "DEFLATE", "8" } }; | |||
int NTO = 4; | int NTO = 4; | |||
int Frestart; | int Frestart; | |||
} | } | |||
// menu function | // menu function | |||
void m_settings(GtkWidget *, cchar *) | void m_settings(GtkWidget *, ch *) | |||
{ | { | |||
using namespace settings; | using namespace settings; | |||
int settings_dialog_event(zdialog *zd, cchar *event); | int settings_dialog_event(zdialog *zd, ch *event); | |||
zdialog *zd; | zdialog *zd; | |||
int ii; | int ii; | |||
char txrgb[20], pct_scale[40]; | ch txrgb[20], pct_scale[40]; | |||
snprintf(pct_scale,40,"separation, %c of scale",'%'); // "separation, % of scale" | snprintf(pct_scale,40,"separation, %c of scale",'%'); // "separation, % of scale" | |||
/*** | /*** | |||
____________________________________________________________________ | ____________________________________________________________________ | |||
| Preferences and Settings | | | Preferences and Settings | | |||
| | | | | | |||
| Startup View | [ Previous File |v] [browse] | | | Startup View | [ Previous File |v] [browse] | | |||
| Background | F-view [###] G-view [###] | | | Background | F-view [###] G-view [###] | | |||
| Menu Style | (o) Icons (o) Text (o) Both Icon size [40] | | | Menu Style | (o) Icons (o) Text (o) Both Icon size [40] | | |||
skipping to change at line 1879 | skipping to change at line 1886 | |||
new_session("-x1"); // no re-index needed 23.0 | new_session("-x1"); // no re-index needed 23.0 | |||
zsleep(1); // delay before SIGTERM in quitxx() | zsleep(1); // delay before SIGTERM in quitxx() | |||
quitxx(); | quitxx(); | |||
} | } | |||
return; | return; | |||
} | } | |||
// settings dialog event function | // settings dialog event function | |||
int settings_dialog_event(zdialog *zd, cchar *event) // simplifications 22.16 | int settings_dialog_event(zdialog *zd, ch *event) // simplifications 22.16 | |||
{ | { | |||
using namespace settings; | using namespace settings; | |||
int ii, jj, nn; | int ii, jj, nn; | |||
char *pp, temp[200]; | ch *pp, temp[200]; | |||
cchar *ppc; | ch *ppc; | |||
char txrgb[20]; | ch txrgb[20]; | |||
GtkWidget *font_dialog; | GtkWidget *font_dialog; | |||
if (strmatch(event,"escape")) zd->zstat = -2; // escape key | if (strmatch(event,"escape")) zd->zstat = -2; // escape key | |||
if (zd->zstat) return 1; // [OK] or [x] | if (zd->zstat) return 1; // [OK] or [x] | |||
if (strmatch(event,"startopt")) // set startup view | if (strmatch(event,"startopt")) // set startup view | |||
{ | { | |||
zdialog_fetch(zd,"startopt",temp,200); | zdialog_fetch(zd,"startopt",temp,200); | |||
for (ii = 0; ii < NSO; ii++) { | for (ii = 0; ii < NSO; ii++) { | |||
if (strmatch(temp,startopt[ii][1])) | if (strmatch(temp,startopt[ii][1])) | |||
skipping to change at line 2189 | skipping to change at line 2196 | |||
/******************************************************************************* */ | /******************************************************************************* */ | |||
// keyboard shortcuts | // keyboard shortcuts | |||
namespace KBshortcutnames | namespace KBshortcutnames | |||
{ | { | |||
zdialog *zd; | zdialog *zd; | |||
int Nreserved = 21; // reserved shortcuts (hard coded) | int Nreserved = 21; // reserved shortcuts (hard coded) | |||
cchar *reserved[21] = { | ch *reserved[21] = { | |||
"+", "=", "-", "Z", "F1", "F2", "F3", "F4", "F10", "F11", | "K", "+", "=", "-", "Z", "F1", "F2", "F3", "F4", "F10", "F11", | |||
"Escape", "Delete", "Left", "Right", "Up", "Down", "Home", "End", | "Escape", "Delete", "Left", "Right", "Up", "Down", "Home", "End", | |||
"Page_Up", "Page_Down", "Open" }; | "Page_Up", "Page_Down" }; | |||
kbsutab_t kbsutab2[maxkbsu]; // KB shortcuts list during editing | kbsutab_t kbsutab2[maxkbsu]; // KB shortcuts list during editing | |||
int Nkbsu2; | int Nkbsu2; | |||
} | } | |||
// KB shortcuts menu function | // KB shortcuts menu function | |||
void m_KB_shortcuts(GtkWidget *, cchar *) | void m_KB_shortcuts(GtkWidget *, ch *) | |||
{ | { | |||
using namespace KBshortcutnames; | using namespace KBshortcutnames; | |||
int KBshorts_dialog_event(zdialog *zd, cchar *event); | int KBshorts_dialog_event(zdialog *zd, ch *event); | |||
void KB_shortcuts_edit(); | void KB_shortcuts_edit(); | |||
int zstat, ii; | int zstat, ii; | |||
GtkWidget *widget; | GtkWidget *widget; | |||
F1_help_topic = "KB shortcuts"; | F1_help_topic = "KB shortcuts"; | |||
Plog(1,"m_KB_shortcuts \n"); | Plog(1,"m_KB_shortcuts \n"); | |||
/*** | /*** | |||
____________________________________________ | ____________________________________________ | |||
| Keyboard Shortcuts | | | Keyboard Shortcuts | | |||
| | | | | | |||
| Reserved Shortcuts | | | Reserved Shortcuts | | |||
| K KB Shortcuts | | ||||
| + Zoom-in | | | + Zoom-in | | |||
| - Zoom-out | | | - Zoom-out | | |||
| Z Toggle 1x / fit window | | | Z Toggle 1x / fit window | | |||
| F1 User Guide, Context Help | | | F1 User Guide, Context Help | | |||
| F2/F3/F4 File/Gallery/Map View | | | F2/F3/F4 File/Gallery/Map View | | |||
| F10/F11 Full Screen / no menus | | | F10/F11 Full Screen / no menus | | |||
| Escape Quit dialog, Quit Fotoxx | | | Escape Quit dialog, Quit Fotoxx | | |||
| Delete Delete/Trash file | | | Delete Delete/Trash file | | |||
| Arrow keys Previous/Next file | | | Arrow keys Previous/Next file | | |||
| Page keys Gallery page up/down | | ||||
| Home/End Gallery start/end | | | Home/End Gallery start/end | | |||
| Page keys Gallery page up/down | | ||||
| | | | | | |||
| Custom Shortcuts | | | Custom Shortcuts | | |||
| F File View | | | F File View | | |||
| G Gallery View | | | G Gallery View | | |||
| M Map View | | | M Map View | | |||
| R Rename | | | R Rename | | |||
| K KB Shortcuts | | ||||
| T Trim/Rotate | | | T Trim/Rotate | | |||
| ... ... | | | ... ... | | |||
| | | | | | |||
| [edit] [cancel] | | | [edit] [cancel] | | |||
|____________________________________________| | |____________________________________________| | |||
***/ | ***/ | |||
zd = zdialog_new("Keyboard Shortcuts",Mwin,"Edit","Cancel",null); | zd = zdialog_new("Keyboard Shortcuts",Mwin,"Edit","Cancel",null); | |||
zdialog_add_widget(zd,"scrwin","scrlist","dialog",0,"space=5|expand"); | zdialog_add_widget(zd,"scrwin","scrlist","dialog",0,"space=5|expand"); | |||
zdialog_add_widget(zd,"text","shortlist","scrlist",0,"expand"); | zdialog_add_widget(zd,"text","shortlist","scrlist",0,"expand"); | |||
widget = zdialog_gtkwidget(zd,"shortlist"); // list fixed shortcuts | widget = zdialog_gtkwidget(zd,"shortlist"); // list fixed shortcuts | |||
textwidget_append(widget,1,"Reserved Shortcuts \n"); | textwidget_append(widget,1,"Reserved Shortcuts \n"); | |||
textwidget_append(widget,0," K KB shortcuts \n"); | ||||
textwidget_append(widget,0," + Zoom-in \n"); | textwidget_append(widget,0," + Zoom-in \n"); | |||
textwidget_append(widget,0," - Zoom-out \n"); | textwidget_append(widget,0," - Zoom-out \n"); | |||
textwidget_append(widget,0," Z Toggle 1x / fit window \n"); | textwidget_append(widget,0," Z Toggle 1x / fit window \n"); | |||
textwidget_append(widget,0," F1 User Guide, Context Help \n"); | textwidget_append(widget,0," F1 User Guide, Context Help \n"); | |||
textwidget_append(widget,0," F2/F3/F4 File/Gallery/Map View \n"); | textwidget_append(widget,0," F2/F3/F4 File/Gallery/Map View \n"); | |||
textwidget_append(widget,0," F10/F11 Full Screen / no menus \n"); | textwidget_append(widget,0," F10/F11 Full Screen / no menus \n"); | |||
textwidget_append(widget,0," Escape Quit dialog / Quit Fotoxx \n"); | textwidget_append(widget,0," Escape Quit dialog / Quit Fotoxx \n"); | |||
textwidget_append(widget,0," Delete Delete/Trash file \n"); | textwidget_append(widget,0," Delete Delete/Trash file \n"); | |||
textwidget_append(widget,0," Arrow keys Previous/Next file \n"); | textwidget_append(widget,0," Arrow keys Previous/Next file \n"); | |||
textwidget_append(widget,0," Page keys Gallery page up/down \n"); | textwidget_append(widget,0," Page keys Gallery page up/down \n"); | |||
skipping to change at line 2280 | skipping to change at line 2288 | |||
zdialog_resize(zd,400,600); | zdialog_resize(zd,400,600); | |||
zdialog_run(zd,KBshorts_dialog_event,"save"); | zdialog_run(zd,KBshorts_dialog_event,"save"); | |||
zstat = zdialog_wait(zd); | zstat = zdialog_wait(zd); | |||
zdialog_free(zd); | zdialog_free(zd); | |||
if (zstat == 1) KB_shortcuts_edit(); | if (zstat == 1) KB_shortcuts_edit(); | |||
return; | return; | |||
} | } | |||
// dialog event and completion function | // dialog event and completion function | |||
int KBshorts_dialog_event(zdialog *zd, cchar *event) | int KBshorts_dialog_event(zdialog *zd, ch *event) | |||
{ | { | |||
if (strmatch(event,"escape")) zd->zstat = -2; // escape key | if (strmatch(event,"escape")) zd->zstat = -2; // escape key | |||
if (zd->zstat) zdialog_destroy(zd); | if (zd->zstat) zdialog_destroy(zd); | |||
return 1; | return 1; | |||
} | } | |||
// KB shortcuts edit function | // KB shortcuts edit function | |||
void KB_shortcuts_edit() | void KB_shortcuts_edit() | |||
{ | { | |||
using namespace KBshortcutnames; | using namespace KBshortcutnames; | |||
void KBshorts_callbackfunc1(GtkWidget *widget, int line, int pos, int kbkey); | void KBshorts_callbackfunc1(GtkWidget *widget, int line, int pos, int kbkey); | |||
void KBshorts_callbackfunc2(GtkWidget *widget, int line, int pos, int kbkey); | void KBshorts_callbackfunc2(GtkWidget *widget, int line, int pos, int kbkey); | |||
int KBshorts_keyfunc(GtkWidget *dialog, GdkEventKey *event); | int KBshorts_keyfunc(GtkWidget *dialog, GdkEventKey *event); | |||
int KBshorts_edit_dialog_event(zdialog *zd, cchar *event); | int KBshorts_edit_dialog_event(zdialog *zd, ch *event); | |||
int ii; | int ii; | |||
GtkWidget *widget; | GtkWidget *widget; | |||
char *sortlist[maxkbsf]; // all eligible funcs, sorted | ch *sortlist[maxkbsf]; // all eligible funcs, sorted | |||
/*** | /*** | |||
_________________________________________________________________ | _________________________________________________________________ | |||
| Edit KB Shortcuts | | | Edit KB Shortcuts | | |||
|_________________________________________________________________| | |_________________________________________________________________| | |||
| Alt+G Grid Settings | Blur | | | Alt+G Grid Settings | Blur | | |||
| Alt+U Undo | Bookmarks | | | Alt+U Undo | Bookmarks | | |||
| Alt+R Redo | Captions | | | Alt+R Redo | Captions | | |||
| T Trim/Rotate | Color Depth | | | T Trim/Rotate | Color Depth | | |||
| V View Main | Color Sat | | | V View Main | Color Sat | | |||
skipping to change at line 2379 | skipping to change at line 2387 | |||
return; | return; | |||
} | } | |||
// mouse callback function to select existing shortcut from list | // mouse callback function to select existing shortcut from list | |||
// and stuff into dialog "shortfunc" | // and stuff into dialog "shortfunc" | |||
void KBshorts_callbackfunc1(GtkWidget *widget, int line, int pos, int kbkey) | void KBshorts_callbackfunc1(GtkWidget *widget, int line, int pos, int kbkey) | |||
{ | { | |||
using namespace KBshortcutnames; | using namespace KBshortcutnames; | |||
char *txline; | ch *txline; | |||
char shortkey[20]; | ch shortkey[20]; | |||
char shortfunc[60]; | ch shortfunc[60]; | |||
if (kbkey == GDK_KEY_F1) { // key F1 pressed, show help | if (kbkey == GDK_KEY_F1) { // key F1 pressed, show help | |||
showz_docfile(Mwin,"userguide",F1_help_topic); | showz_docfile(Mwin,"userguide",F1_help_topic); | |||
return; | return; | |||
} | } | |||
txline = textwidget_line(widget,line,1); // get clicked line | txline = textwidget_line(widget,line,1); // get clicked line | |||
if (! txline || ! *txline) return; | if (! txline || ! *txline) return; | |||
textwidget_highlight_line(widget,line); | textwidget_highlight_line(widget,line); | |||
skipping to change at line 2412 | skipping to change at line 2420 | |||
return; | return; | |||
} | } | |||
// mouse callback function to select new shortcut function from menu list | // mouse callback function to select new shortcut function from menu list | |||
// and stuff into dialog "shortfunc" | // and stuff into dialog "shortfunc" | |||
void KBshorts_callbackfunc2(GtkWidget *widget, int line, int pos, int kbkey) | void KBshorts_callbackfunc2(GtkWidget *widget, int line, int pos, int kbkey) | |||
{ | { | |||
using namespace KBshortcutnames; | using namespace KBshortcutnames; | |||
char *txline; | ch *txline; | |||
if (kbkey == GDK_KEY_F1) { // key F1 pressed, show help | if (kbkey == GDK_KEY_F1) { // key F1 pressed, show help | |||
showz_docfile(Mwin,"userguide",F1_help_topic); | showz_docfile(Mwin,"userguide",F1_help_topic); | |||
return; | return; | |||
} | } | |||
txline = textwidget_line(widget,line,1); // get clicked line | txline = textwidget_line(widget,line,1); // get clicked line | |||
if (! txline || ! *txline) return; | if (! txline || ! *txline) return; | |||
textwidget_highlight_line(widget,line); | textwidget_highlight_line(widget,line); | |||
skipping to change at line 2436 | skipping to change at line 2444 | |||
} | } | |||
// intercept KB key events, stuff into dialog "shortkey" | // intercept KB key events, stuff into dialog "shortkey" | |||
int KBshorts_keyfunc(GtkWidget *dialog, GdkEventKey *event) | int KBshorts_keyfunc(GtkWidget *dialog, GdkEventKey *event) | |||
{ | { | |||
using namespace KBshortcutnames; | using namespace KBshortcutnames; | |||
int Ctrl = 0, Alt = 0, Shift = 0; | int Ctrl = 0, Alt = 0, Shift = 0; | |||
int key, ii, cc; | int key, ii, cc; | |||
char keyname[20]; | ch keyname[20]; | |||
key = event->keyval; | key = event->keyval; | |||
if (event->state & GDK_CONTROL_MASK) Ctrl = 1; | if (event->state & GDK_CONTROL_MASK) Ctrl = 1; | |||
if (event->state & GDK_SHIFT_MASK) Shift = 1; | if (event->state & GDK_SHIFT_MASK) Shift = 1; | |||
if (event->state & GDK_MOD1_MASK) Alt = 1; | if (event->state & GDK_MOD1_MASK) Alt = 1; | |||
if (key == GDK_KEY_Escape) return 0; // pass escape (cancel) to zdialog | if (key == GDK_KEY_Escape) return 0; // pass escape (cancel) to zdialog | |||
if (key == GDK_KEY_F1) { // key is F1 (context help) | if (key == GDK_KEY_F1) { // key is F1 (context help) | |||
skipping to change at line 2485 | skipping to change at line 2493 | |||
} | } | |||
zdialog_stuff(zd,"shortkey",keyname); // stuff key name into dialog | zdialog_stuff(zd,"shortkey",keyname); // stuff key name into dialog | |||
zdialog_stuff(zd,"shortfunc","(no selection)"); // clear menu choice | zdialog_stuff(zd,"shortfunc","(no selection)"); // clear menu choice | |||
return 1; | return 1; | |||
} | } | |||
// dialog event and completion function | // dialog event and completion function | |||
int KBshorts_edit_dialog_event(zdialog *zd, cchar *event) | int KBshorts_edit_dialog_event(zdialog *zd, ch *event) | |||
{ | { | |||
using namespace KBshortcutnames; | using namespace KBshortcutnames; | |||
int KBshorts_edit_menufuncs_event(zdialog *zd, cchar *event); | int KBshorts_edit_menufuncs_event(zdialog *zd, ch *event); | |||
void KBshorts_callbackfunc2(GtkWidget *widget, int line, int pos, int kbkey); | void KBshorts_callbackfunc2(GtkWidget *widget, int line, int pos, int kbkey); | |||
int ii, jj; | int ii, jj; | |||
GtkWidget *widget; | GtkWidget *widget; | |||
char shortkey[20]; | ch shortkey[20]; | |||
char shortfunc[60]; | ch shortfunc[60]; | |||
FILE *fid = 0; | FILE *fid = 0; | |||
if (strmatch(event,"escape")) zd->zstat = -2; // escape key | if (strmatch(event,"escape")) zd->zstat = -2; // escape key | |||
if (! zd->zstat) return 1; // wait for completion | if (! zd->zstat) return 1; // wait for completion | |||
if (zd->zstat == 1) // add shortcut | if (zd->zstat == 1) // add shortcut | |||
{ | { | |||
zd->zstat = 0; // keep dialog active | zd->zstat = 0; // keep dialog active | |||
skipping to change at line 2611 | skipping to change at line 2619 | |||
zdialog_free(zd); // cancel or [x] | zdialog_free(zd); // cancel or [x] | |||
return 1; | return 1; | |||
} | } | |||
// Read KB_shortcuts file and load shortcuts table in memory. | // Read KB_shortcuts file and load shortcuts table in memory. | |||
// Called at fotoxx startup time. | // Called at fotoxx startup time. | |||
void KB_shortcuts_load() | void KB_shortcuts_load() | |||
{ | { | |||
int ii; | using namespace KBshortcutnames; | |||
char buff[200]; | ||||
char *pp1, *pp2; | int ii, jj; | |||
char *key, *menu; | ch buff[200]; | |||
ch *pp1, *pp2; | ||||
ch *key, *menu; | ||||
FILE *fid; | FILE *fid; | |||
for (ii = 0; ii < Nkbsu; ii++) { // clear shortcuts data | for (ii = 0; ii < Nkbsu; ii++) { // clear shortcuts data | |||
zfree(kbsutab[ii].key); | zfree(kbsutab[ii].key); | |||
zfree(kbsutab[ii].menu); | zfree(kbsutab[ii].menu); | |||
} | } | |||
Nkbsu = 0; | Nkbsu = 0; | |||
fid = fopen(KB_shortcuts_user,"r"); // read KB shortcuts file | fid = fopen(KB_shortcuts_user,"r"); // read KB shortcuts file | |||
if (! fid) return; | if (! fid) return; | |||
skipping to change at line 2637 | skipping to change at line 2647 | |||
{ | { | |||
pp1 = fgets_trim(buff,200,fid,1); // next record | pp1 = fgets_trim(buff,200,fid,1); // next record | |||
if (! pp1) break; | if (! pp1) break; | |||
if (*pp1 == '#') continue; // comment | if (*pp1 == '#') continue; // comment | |||
if (*pp1 <= ' ') continue; // blank | if (*pp1 <= ' ') continue; // blank | |||
pp2 = strchr(pp1,' '); | pp2 = strchr(pp1,' '); | |||
if (! pp2) continue; | if (! pp2) continue; | |||
if (pp2 - pp1 > 20) continue; | if (pp2 - pp1 > 20) continue; | |||
*pp2 = 0; | *pp2 = 0; | |||
key = zstrdup(pp1,"KB_shortcuts"); // shortcut key or combination | key = zstrdup(pp1,"KB_shortcuts"); // shortcut key or combination | |||
for (jj = 0; jj < Nreserved; jj++) | ||||
// outlaw reserved shortcut 23.1 | ||||
if (strmatchcase(key,reserved[jj])) break; | ||||
if (jj < Nreserved) { | ||||
Plog(0,"Reserved KB shortcut ignored: %s \n",key); | ||||
continue; | ||||
} | ||||
pp1 = pp2 + 1; | pp1 = pp2 + 1; | |||
while (*pp1 && *pp1 == ' ') pp1++; | while (*pp1 && *pp1 == ' ') pp1++; | |||
if (! *pp1) continue; | if (! *pp1) continue; | |||
menu = zstrdup(pp1,"KB_shortcuts"); // corresp. menu, English | menu = zstrdup(pp1,"KB_shortcuts"); // corresp. menu, English | |||
if (strstr(zdialog_button_shortcuts,menu)) // if a dialog button shortcut | if (strstr(zdialog_button_shortcuts,menu)) // if a dialog button shortcut | |||
zdialog_KB_addshortcut(key,menu); // register with zdialog | zdialog_KB_addshortcut(key,menu); // register with zdialog | |||
kbsutab[ii].key = key; // add to shortcuts table | kbsutab[ii].key = key; // add to shortcuts table | |||
kbsutab[ii].menu = menu; | kbsutab[ii].menu = menu; | |||
skipping to change at line 2663 | skipping to change at line 2681 | |||
return; | return; | |||
} | } | |||
// Merge user KB shortcuts with standard shortcuts in install package. | // Merge user KB shortcuts with standard shortcuts in install package. | |||
// Where user and standard shortcuts conflict, standard is kept. | // Where user and standard shortcuts conflict, standard is kept. | |||
// Called at fotoxx startup time if new release is detected. | // Called at fotoxx startup time if new release is detected. | |||
void KB_shortcuts_merge() | void KB_shortcuts_merge() | |||
{ | { | |||
int err, ii, jj, nnU, nnP; | int err, ii, jj, nnU, nnP; | |||
char *packitem, *useritem = 0; | ch *packitem, *useritem = 0; | |||
zlist_t *zlistPack, *zlistUser; | zlist_t *zlistPack, *zlistUser; | |||
zlistPack = zlist_from_file(KB_shortcuts_default); // get standard shortcuts | zlistPack = zlist_from_file(KB_shortcuts_default); // get standard shortcuts | |||
if (! zlistPack) { | if (! zlistPack) { | |||
Plog(0,"*** default KB shortcut file not found: %s \n",KB_shortcuts_defaul t); | Plog(0,"*** default KB shortcut file not found: %s \n",KB_shortcuts_defaul t); | |||
return; | return; | |||
} | } | |||
zlistUser = zlist_from_file(KB_shortcuts_user); // get user shortcuts | zlistUser = zlist_from_file(KB_shortcuts_user); // get user shortcuts | |||
if (! zlistUser) { | if (! zlistUser) { | |||
skipping to change at line 2713 | skipping to change at line 2731 | |||
// show a brightness distribution graph - live update as image is edited | // show a brightness distribution graph - live update as image is edited | |||
namespace RGB_dist_names | namespace RGB_dist_names | |||
{ | { | |||
GtkWidget *drawwin_dist, *drawwin_scale; // brightness distribution graph widgets | GtkWidget *drawwin_dist, *drawwin_scale; // brightness distribution graph widgets | |||
int RGBW[4] = { 1, 1, 1, 0 }; // " colors: red/green/blue/white (all) | int RGBW[4] = { 1, 1, 1, 0 }; // " colors: red/green/blue/white (all) | |||
} | } | |||
// menu function | // menu function | |||
void m_RGB_dist(GtkWidget *, cchar *menu) // menu function | void m_RGB_dist(GtkWidget *, ch *menu) // menu function | |||
{ | { | |||
using namespace RGB_dist_names; | using namespace RGB_dist_names; | |||
int show_RGB_dist_dialog_event(zdialog *zd, cchar *event); | int show_RGB_dist_dialog_event(zdialog *zd, ch *event); | |||
GtkWidget *frdist, *frscale, *widget; | GtkWidget *frdist, *frscale, *widget; | |||
zdialog *zd; | zdialog *zd; | |||
Plog(1,"m_RGB_dist \n"); | Plog(1,"m_RGB_dist \n"); | |||
m_viewmode(0,"F"); // file view mode | m_viewmode(0,"F"); // file view mode | |||
if (! curr_file) return; | if (! curr_file) return; | |||
skipping to change at line 2779 | skipping to change at line 2797 | |||
widget = zdialog_gtkwidget(zd,"dialog"); // stop focus on this window | widget = zdialog_gtkwidget(zd,"dialog"); // stop focus on this window | |||
gtk_window_set_accept_focus(GTK_WINDOW(widget),0); | gtk_window_set_accept_focus(GTK_WINDOW(widget),0); | |||
zd_RGB_dist = zd; | zd_RGB_dist = zd; | |||
return; | return; | |||
} | } | |||
// dialog event and completion function | // dialog event and completion function | |||
int show_RGB_dist_dialog_event(zdialog *zd, cchar *event) | int show_RGB_dist_dialog_event(zdialog *zd, ch *event) | |||
{ | { | |||
using namespace RGB_dist_names; | using namespace RGB_dist_names; | |||
if (strmatch(event,"escape")) zd->zstat = -2; // escape key | if (strmatch(event,"escape")) zd->zstat = -2; // escape key | |||
if (zd->zstat) { | if (zd->zstat) { | |||
zdialog_free(zd); | zdialog_free(zd); | |||
zd_RGB_dist = 0; | zd_RGB_dist = 0; | |||
return 1; | return 1; | |||
} | } | |||
skipping to change at line 2915 | skipping to change at line 2933 | |||
return; | return; | |||
} | } | |||
/******************************************************************************* */ | /******************************************************************************* */ | |||
// magnify image within a given radius of dragged mouse | // magnify image within a given radius of dragged mouse | |||
namespace magnify_names | namespace magnify_names | |||
{ | { | |||
int magnify_dialog_event(zdialog* zd, cchar *event); | int magnify_dialog_event(zdialog* zd, ch *event); | |||
void magnify_mousefunc(); | void magnify_mousefunc(); | |||
void magnify_dopixels(int ftf); | void magnify_dopixels(int ftf); | |||
float Xmag; // magnification, 1 - 5x | float Xmag; // magnification, 1 - 5x | |||
int Mx, My; // mouse location, image space | int Mx, My; // mouse location, image space | |||
int Mrad; // mouse radius | int Mrad; // mouse radius | |||
} | } | |||
// menu function | // menu function | |||
void m_magnify(GtkWidget *, cchar *) | void m_magnify(GtkWidget *, ch *) | |||
{ | { | |||
using namespace magnify_names; | using namespace magnify_names; | |||
cchar * mess = "Drag mouse on image. \n" | ch *mess = "Drag mouse on image. \n" | |||
"Left click to cancel."; | "Left click to cancel."; | |||
F1_help_topic = "magnify image"; | F1_help_topic = "magnify image"; | |||
Plog(1,"m_magnify \n"); | Plog(1,"m_magnify \n"); | |||
/*** | /*** | |||
__________________________ | __________________________ | |||
| Magnify Image | | | Magnify Image | | |||
| | | | | | |||
| Drag mouse on image. | | | Drag mouse on image. | | |||
skipping to change at line 2990 | skipping to change at line 3008 | |||
zdialog_send_event(zd,"Mrad"); // initializations | zdialog_send_event(zd,"Mrad"); // initializations | |||
zdialog_send_event(zd,"Xmag"); | zdialog_send_event(zd,"Xmag"); | |||
} | } | |||
takeMouse(magnify_mousefunc,dragcursor); // connect mouse function | takeMouse(magnify_mousefunc,dragcursor); // connect mouse function | |||
return; | return; | |||
} | } | |||
// dialog event and completion callback function | // dialog event and completion callback function | |||
int magnify_names::magnify_dialog_event(zdialog *zd, cchar *event) | int magnify_names::magnify_dialog_event(zdialog *zd, ch *event) | |||
{ | { | |||
using namespace magnify_names; | using namespace magnify_names; | |||
if (strmatch(event,"escape")) zd->zstat = -2; // escape key | if (strmatch(event,"escape")) zd->zstat = -2; // escape key | |||
if (strmatch(event,"kill")) zd->zstat = 1; // from slide show | if (strmatch(event,"kill")) zd->zstat = 1; // from slide show | |||
if (zd->zstat) { // terminate | if (zd->zstat) { // terminate | |||
zd_magnify = 0; | zd_magnify = 0; | |||
zdialog_free(zd); | zdialog_free(zd); | |||
freeMouse(); | freeMouse(); | |||
skipping to change at line 3201 | skipping to change at line 3219 | |||
} | } | |||
/******************************************************************************* */ | /******************************************************************************* */ | |||
// find all duplicated files and create corresponding gallery of duplicates | // find all duplicated files and create corresponding gallery of duplicates | |||
namespace duplicates_names | namespace duplicates_names | |||
{ | { | |||
int thumbsize; | int thumbsize; | |||
int Nfiles; | int Nfiles; | |||
char **files; | ch **files; | |||
int Fallfiles, Fgallery; | int Fallfiles, Fgallery; | |||
} | } | |||
// menu function | // menu function | |||
void m_duplicates(GtkWidget *, const char *) | void m_duplicates(GtkWidget *, ch *) | |||
{ | { | |||
using namespace duplicates_names; | using namespace duplicates_names; | |||
int duplicates_dialog_event(zdialog *zd, cchar *event); | int duplicates_dialog_event(zdialog *zd, ch *event); | |||
void duplicates_randomize(); | void duplicates_randomize(); | |||
PIXBUF *pxb; | PIXBUF *pxb; | |||
GError *gerror; | GError *gerror; | |||
uint8 *pixels, *pix1; | uint8 *pixels, *pix1; | |||
uint8 *pixelsii, *pixelsjj, *pixii, *pixjj; | uint8 *pixelsii, *pixelsjj, *pixii, *pixjj; | |||
FILE *fid = 0; | FILE *fid = 0; | |||
zdialog *zd; | zdialog *zd; | |||
int Ndups = 0; // image file and duplicate counts | int Ndups = 0; // image file and duplicate counts | |||
int thumbsize, pixdiff, pixcount; | int thumbsize, pixdiff, pixcount; | |||
int zstat, ii, jj, kk, cc, err, ndup; | int zstat, ii, jj, kk, cc, err, ndup; | |||
int ww, hh, rs, px, py; | int ww, hh, rs, px, py; | |||
int trgb, diff, sumdiff; | int trgb, diff, sumdiff; | |||
int percent; | int percent; | |||
char text[100], *pp; | ch text[100], *pp; | |||
char tempfile[200], albumfile[200]; | ch tempfile[200], albumfile[200]; | |||
typedef struct // thumbnail data | typedef struct // thumbnail data | |||
{ | { | |||
int trgb; // mean RGB sum | int trgb; // mean RGB sum | |||
int ww, hh, rs; // pixel dimensions | int ww, hh, rs; // pixel dimensions | |||
char *file; // file name | ch *file; // file name | |||
uint8 *pixels; // image pixels | uint8 *pixels; // image pixels | |||
} Tdata_t; | } Tdata_t; | |||
Tdata_t **Tdata = 0; | Tdata_t **Tdata = 0; | |||
F1_help_topic = "find duplicates"; | F1_help_topic = "find duplicates"; | |||
Plog(1,"m_duplicates \n"); | Plog(1,"m_duplicates \n"); | |||
if (Findexvalid == 0) { | if (Findexvalid == 0) { | |||
skipping to change at line 3315 | skipping to change at line 3333 | |||
zdialog_add_widget(zd,"label","Dpct","hbstats","0%","space=3"); | zdialog_add_widget(zd,"label","Dpct","hbstats","0%","space=3"); | |||
zdialog_add_widget(zd,"hbox","hbfolder","dialog",0,"space=3"); | zdialog_add_widget(zd,"hbox","hbfolder","dialog",0,"space=3"); | |||
zdialog_add_widget(zd,"label","currfolder","hbfolder"," ","space=8"); | zdialog_add_widget(zd,"label","currfolder","hbfolder"," ","space=8"); | |||
zdialog_add_widget(zd,"hbox","hbfile","dialog"); | zdialog_add_widget(zd,"hbox","hbfile","dialog"); | |||
zdialog_add_widget(zd,"label","currfile","hbfile"," ","space=8"); | zdialog_add_widget(zd,"label","currfile","hbfile"," ","space=8"); | |||
zdialog_stuff(zd,"allfiles",1); // default all files | zdialog_stuff(zd,"allfiles",1); // default all files | |||
Fallfiles = 1; | Fallfiles = 1; | |||
files = (char **) zmalloc(maximages * sizeof(char *),"duplicates"); | files = (ch **) zmalloc(maximages * sizeof(ch *),"duplicates"); | |||
for (ii = jj = 0; ii < Nxxrec; ii++) // count all files | for (ii = jj = 0; ii < Nxxrec; ii++) // count all files | |||
{ | { | |||
pp = xxrec_tab[ii]->file; | pp = xxrec_tab[ii]->file; | |||
pp = image2thumbfile(pp); // omit those without a thumbnail | pp = image2thumbfile(pp); // omit those without a thumbnail | |||
if (! pp) continue; | if (! pp) continue; | |||
files[jj++] = pp; | files[jj++] = pp; | |||
} | } | |||
Nfiles = jj; | Nfiles = jj; | |||
skipping to change at line 3347 | skipping to change at line 3365 | |||
} | } | |||
zdialog_fetch(zd,"thumbsize",thumbsize); // thumbnail size to use | zdialog_fetch(zd,"thumbsize",thumbsize); // thumbnail size to use | |||
zdialog_fetch(zd,"pixdiff",pixdiff); // pixel difference threshold | zdialog_fetch(zd,"pixdiff",pixdiff); // pixel difference threshold | |||
zdialog_fetch(zd,"pixcount",pixcount); // pixel count threshold | zdialog_fetch(zd,"pixcount",pixcount); // pixel count threshold | |||
cc = Nfiles * sizeof(Tdata_t); // allocate memory for thumbnail data | cc = Nfiles * sizeof(Tdata_t); // allocate memory for thumbnail data | |||
Tdata = (Tdata_t **) zmalloc(cc,"duplicates"); | Tdata = (Tdata_t **) zmalloc(cc,"duplicates"); | |||
zadd_locked(Ffuncbusy,+1); | zadd_locked(Ffuncbusy,+1); | |||
Fwatchescape = 1; | ||||
// killable with [esc] key | ||||
Fescape = 0; | ||||
for (ii = 0; ii < Nfiles; ii++) // screen out thumbnails not | for (ii = 0; ii < Nfiles; ii++) // screen out thumbnails not | |||
{ // matching an image file | { // matching an image file | |||
pp = thumb2imagefile(files[ii]); | pp = thumb2imagefile(files[ii]); | |||
if (pp) zfree(pp); | if (pp) zfree(pp); | |||
else { | else { | |||
zfree(files[ii]); | zfree(files[ii]); | |||
files[ii] = 0; | files[ii] = 0; | |||
} | } | |||
} | } | |||
for (ii = 0; ii < Nfiles; ii++) // read thumbnails into memory | for (ii = 0; ii < Nfiles; ii++) // read thumbnails into memory | |||
{ | { | |||
if (Fkillfunc) goto cleanup; | if (Fescape) goto cleanup; | |||
if (! files[ii]) continue; | if (! files[ii]) continue; | |||
Tdata[ii] = (Tdata_t *) zmalloc(sizeof(Tdata_t),"duplicates"); | Tdata[ii] = (Tdata_t *) zmalloc(sizeof(Tdata_t),"duplicates"); | |||
Tdata[ii]->file = files[ii]; // thumbnail file | Tdata[ii]->file = files[ii]; // thumbnail file | |||
files[ii] = 0; | files[ii] = 0; | |||
kk = thumbsize; | kk = thumbsize; | |||
gerror = 0; // read thumbnail >> pixbuf | gerror = 0; // read thumbnail >> pixbuf | |||
pxb = gdk_pixbuf_new_from_file_at_size(Tdata[ii]->file,kk,kk,&gerror); | pxb = gdk_pixbuf_new_from_file_at_size(Tdata[ii]->file,kk,kk,&gerror); | |||
skipping to change at line 3433 | skipping to change at line 3453 | |||
snprintf(tempfile,200,"%s/duplicate_images",temp_folder); // open file for gallery output | snprintf(tempfile,200,"%s/duplicate_images",temp_folder); // open file for gallery output | |||
fid = fopen(tempfile,"w"); | fid = fopen(tempfile,"w"); | |||
if (! fid) goto filerror; | if (! fid) goto filerror; | |||
Ndups = 0; // total duplicates | Ndups = 0; // total duplicates | |||
for (ii = 0; ii < Nfiles; ii++) // loop all thumbnails ii | for (ii = 0; ii < Nfiles; ii++) // loop all thumbnails ii | |||
{ | { | |||
zmainloop(); | zmainloop(); | |||
if (Fkillfunc) goto cleanup; | if (Fescape) goto cleanup; | |||
percent = 100.0 * (ii+1) / Nfiles; // show percent processed | percent = 100.0 * (ii+1) / Nfiles; // show percent processed | |||
snprintf(text,20,"%02d %c",percent,'%'); | snprintf(text,20,"%02d %c",percent,'%'); | |||
zdialog_stuff(zd,"Dpct",text); | zdialog_stuff(zd,"Dpct",text); | |||
if (! Tdata[ii]) continue; // removed from list | if (! Tdata[ii]) continue; // removed from list | |||
pp = strrchr(Tdata[ii]->file,'/'); | pp = strrchr(Tdata[ii]->file,'/'); | |||
if (! pp) continue; | if (! pp) continue; | |||
*pp = 0; | *pp = 0; | |||
skipping to change at line 3547 | skipping to change at line 3567 | |||
for (ii = 0; ii < Nfiles; ii++) { | for (ii = 0; ii < Nfiles; ii++) { | |||
if (! Tdata[ii]) continue; | if (! Tdata[ii]) continue; | |||
zfree(Tdata[ii]->file); | zfree(Tdata[ii]->file); | |||
zfree(Tdata[ii]->pixels); | zfree(Tdata[ii]->pixels); | |||
zfree(Tdata[ii]); | zfree(Tdata[ii]); | |||
} | } | |||
zfree(Tdata); | zfree(Tdata); | |||
} | } | |||
zadd_locked(Ffuncbusy,-1); | zadd_locked(Ffuncbusy,-1); | |||
Fkillfunc = 0; | Fwatchescape = Fescape = 0; | |||
Fblock("duplicates",0); | Fblock("duplicates",0); | |||
return; | return; | |||
filerror: | filerror: | |||
zmessageACK(Mwin,"file error: %s",strerror(errno)); | zmessageACK(Mwin,"file error: %s",strerror(errno)); | |||
goto cleanup; | goto cleanup; | |||
} | } | |||
// dialog event and completion function | // dialog event and completion function | |||
int duplicates_dialog_event(zdialog *zd, cchar *event) | int duplicates_dialog_event(zdialog *zd, ch *event) | |||
{ | { | |||
using namespace duplicates_names; | using namespace duplicates_names; | |||
double freemem, reqmem; | double freemem, reqmem; | |||
char text[20], *pp, *pp2; | ch text[20], *pp; | |||
int nn, ii, jj; | int nn, ii, jj; | |||
if (strmatch(event,"escape")) zd->zstat = -2; // escape key | if (strmatch(event,"escape")) zd->zstat = -2; // escape key | |||
if (strmatch(event,"allfiles")) | if (strmatch(event,"allfiles")) | |||
{ | { | |||
zdialog_fetch(zd,"allfiles",nn); | zdialog_fetch(zd,"allfiles",nn); | |||
Fallfiles = nn; | Fallfiles = nn; | |||
if (! Fallfiles) return 1; | if (! Fallfiles) return 1; | |||
skipping to change at line 3597 | skipping to change at line 3617 | |||
} | } | |||
if (strmatch(event,"gallery")) | if (strmatch(event,"gallery")) | |||
{ | { | |||
zdialog_fetch(zd,"gallery",nn); | zdialog_fetch(zd,"gallery",nn); | |||
Fgallery = nn; | Fgallery = nn; | |||
if (! Fgallery) return 1; | if (! Fgallery) return 1; | |||
for (ii = jj = 0; ii < navi::Gfiles; ii++) // scan current gallery | for (ii = jj = 0; ii < navi::Gfiles; ii++) // scan current gallery | |||
{ | { | |||
pp = gallery(0,"get",ii); | if (navi::Gindex[ii].folder) continue; | |||
if (! pp) break; | // skip folders 23.1 | |||
if (*pp == '!') { | pp = navi::Gindex[ii].file; | |||
// skip folders | pp = image2thumbfile(pp); | |||
zfree(pp); | // get corresp. thumbnail file | |||
continue; | if (! pp) continue; | |||
} | files[jj++] = pp; | |||
// save thumbnail | ||||
pp2 = image2thumbfile(pp); | ||||
// get corresp. thumbnail file | ||||
zfree(pp); | ||||
if (! pp2) continue; | ||||
files[jj++] = pp2; | ||||
// save thumbnail | ||||
} | } | |||
Nfiles = jj; | Nfiles = jj; | |||
snprintf(text,20,"%d",Nfiles); // file count >> dialog | snprintf(text,20,"%d",Nfiles); // file count >> dialog | |||
zdialog_stuff(zd,"filecount",text); | zdialog_stuff(zd,"filecount",text); | |||
return 1; | return 1; | |||
} | } | |||
if (strmatch(event,"calculate")) // calculate thumbnail size | if (strmatch(event,"calculate")) // calculate thumbnail size | |||
skipping to change at line 3640 | skipping to change at line 3654 | |||
if (thumbsize < 32) { | if (thumbsize < 32) { | |||
zmessageACK(Mwin,"too many files, cannot continue"); | zmessageACK(Mwin,"too many files, cannot continue"); | |||
return 1; | return 1; | |||
} | } | |||
zdialog_stuff(zd,"thumbsize",thumbsize); // stuff into dialog | zdialog_stuff(zd,"thumbsize",thumbsize); // stuff into dialog | |||
return 1; | return 1; | |||
} | } | |||
if (! zd->zstat) return 1; // wait for user input | if (! zd->zstat) return 1; // wait for user input | |||
if (zd->zstat != 1) Fkillfunc = 1; // [cancel] or [x] | if (zd->zstat != 1) Fescape = 1; // [cancel] or [x] | |||
return 1; // [proceed] | return 1; // [proceed] | |||
} | } | |||
// Make small random changes to all images. | // Make small random changes to all images. | |||
// Used for testing and benchmarking Find Duplicates. | // Used for testing and benchmarking Find Duplicates. | |||
void duplicates_randomize() | void duplicates_randomize() | |||
{ | { | |||
using namespace duplicates_names; | using namespace duplicates_names; | |||
char *file; | ch *file; | |||
int px, py; | int px, py; | |||
int ii, jj, kk; | int ii, jj, kk; | |||
float *pixel; | float *pixel; | |||
for (ii = 0; ii < Nxxrec; ii++) // loop all files | for (ii = 0; ii < Nxxrec; ii++) // loop all files | |||
{ | { | |||
if (drandz() > 0.95) continue; // leave 5% duplicates | if (drandz() > 0.95) continue; // leave 5% duplicates | |||
zmainloop(); // keep GTK alive | zmainloop(); // keep GTK alive | |||
skipping to change at line 3706 | skipping to change at line 3720 | |||
zdialog *zd; | zdialog *zd; | |||
int p1x, p1y, p2x, p2y; | int p1x, p1y, p2x, p2y; | |||
int dx, dy, dh; | int dx, dy, dh; | |||
int Npix; | int Npix; | |||
} | } | |||
void measure_image_mousefunc(); | void measure_image_mousefunc(); | |||
// menu function | // menu function | |||
void m_measure_image(GtkWidget *, cchar *) | void m_measure_image(GtkWidget *, ch *) | |||
{ | { | |||
using namespace measure_image_names; | using namespace measure_image_names; | |||
int measure_image_dialog_event(zdialog *zd, cchar *event); | int measure_image_dialog_event(zdialog *zd, ch *event); | |||
cchar *mess = "Click image to select pixels"; | ch *mess = "Click image to select pixels"; | |||
F1_help_topic = "measure image"; | F1_help_topic = "measure image"; | |||
Plog(1,"m_measure_image \n"); | Plog(1,"m_measure_image \n"); | |||
if (! curr_file) return; // no image file | if (! curr_file) return; // no image file | |||
m_viewmode(0,"F"); // file view mode | m_viewmode(0,"F"); // file view mode | |||
/*** | /*** | |||
skipping to change at line 3757 | skipping to change at line 3771 | |||
Npix = 0; // no clicked pixel positions yet | Npix = 0; // no clicked pixel positions yet | |||
p1x = p1y = p2x = p2y = 0; | p1x = p1y = p2x = p2y = 0; | |||
dx = dy = dh = 0; | dx = dy = dh = 0; | |||
return; | return; | |||
} | } | |||
// dialog event and completion function | // dialog event and completion function | |||
int measure_image_dialog_event(zdialog *zd, cchar *event) | int measure_image_dialog_event(zdialog *zd, ch *event) | |||
{ | { | |||
using namespace measure_image_names; | using namespace measure_image_names; | |||
if (zd->zstat) { // [OK] or [x] | if (zd->zstat) { // [OK] or [x] | |||
freeMouse(); // disconnect mouse function | freeMouse(); // disconnect mouse function | |||
zdialog_free(zd); // kill dialog | zdialog_free(zd); // kill dialog | |||
erase_toptext(102); // clear pixel labels | erase_toptext(102); // clear pixel labels | |||
Fpaint2(); | Fpaint2(); | |||
return 1; | return 1; | |||
} | } | |||
skipping to change at line 3781 | skipping to change at line 3795 | |||
return 1; | return 1; | |||
} | } | |||
// mouse function | // mouse function | |||
void measure_image_mousefunc() | void measure_image_mousefunc() | |||
{ | { | |||
using namespace measure_image_names; | using namespace measure_image_names; | |||
char text[100]; | ch text[100]; | |||
if (! LMclick) return; // left click | if (! LMclick) return; // left click | |||
LMclick = 0; | LMclick = 0; | |||
if (Npix == 0) { // first clicked pixel | if (Npix == 0) { // first clicked pixel | |||
Npix = 1; | Npix = 1; | |||
p1x = Mxclick; | p1x = Mxclick; | |||
p1y = Myclick; | p1y = Myclick; | |||
add_toptext(102,p1x,p1y,"A","Sans 8"); | add_toptext(102,p1x,p1y,"A","Sans 8"); | |||
skipping to change at line 3842 | skipping to change at line 3856 | |||
void show_RGB_mousefunc(); | void show_RGB_mousefunc(); | |||
int show_RGB_timefunc(void *); | int show_RGB_timefunc(void *); | |||
zdialog *RGBSzd; | zdialog *RGBSzd; | |||
int RGBSpixel[10][2]; // 0-9 clicked pixels + current mouse | int RGBSpixel[10][2]; // 0-9 clicked pixels + current mouse | |||
int RGBSnpix = 0; // no. clicked pixels, 0-9 | int RGBSnpix = 0; // no. clicked pixels, 0-9 | |||
int RGBSdelta = 0; // abs/delta mode | int RGBSdelta = 0; // abs/delta mode | |||
int RGBSlabels = 0; // pixel labels on/off | int RGBSlabels = 0; // pixel labels on/off | |||
void m_show_RGB(GtkWidget *, cchar *) | void m_show_RGB(GtkWidget *, ch *) | |||
{ | { | |||
int show_RGB_event(zdialog *zd, cchar *event); | int show_RGB_event(zdialog *zd, ch *event); | |||
cchar *mess = "Click image to select pixels."; | ch *mess = "Click image to select pixels."; | |||
cchar *header = " Pixel Red Green Blue"; | ch *header = " Pixel Red Green Blue"; | |||
char hbx[8] = "hbx", pixx[8] = "pixx"; | ch hbx[8] = "hbx", pixx[8] = "pixx"; | |||
// last char. is '0' to '9' | // last char. is '0' to '9' | |||
int ii; | int ii; | |||
F1_help_topic = "show RGB"; | F1_help_topic = "show RGB"; | |||
Plog(1,"m_show_RGB \n"); | Plog(1,"m_show_RGB \n"); | |||
m_viewmode(0,"F"); // file view mode | m_viewmode(0,"F"); // file view mode | |||
if (! curr_file) return; // no image file | if (! curr_file) return; // no image file | |||
if (! E0pxm && ! E1pxm && ! E3pxm) { | if (! E0pxm && ! E1pxm && ! E3pxm) { | |||
skipping to change at line 3925 | skipping to change at line 3939 | |||
zdialog_run(zd,show_RGB_event,"save"); // run dialog | zdialog_run(zd,show_RGB_event,"save"); // run dialog | |||
takeMouse(show_RGB_mousefunc,dotcursor); // connect mouse function | takeMouse(show_RGB_mousefunc,dotcursor); // connect mouse function | |||
g_timeout_add(200,show_RGB_timefunc,0); // start timer function, 200 ms | g_timeout_add(200,show_RGB_timefunc,0); // start timer function, 200 ms | |||
return; | return; | |||
} | } | |||
// dialog event function | // dialog event function | |||
int show_RGB_event(zdialog *zd, cchar *event) | int show_RGB_event(zdialog *zd, ch *event) | |||
{ | { | |||
if (zd->zstat) { | if (zd->zstat) { | |||
if (zd->zstat == 1) { // clear | if (zd->zstat == 1) { // clear | |||
zd->zstat = 0; // keep dialog active | zd->zstat = 0; // keep dialog active | |||
RGBSnpix = 0; // clicked pixel count = 0 | RGBSnpix = 0; // clicked pixel count = 0 | |||
erase_toptext(102); // erase labels on image | erase_toptext(102); // erase labels on image | |||
} | } | |||
else { // done or kill | else { // done or kill | |||
freeMouse(); // disconnect mouse function | freeMouse(); // disconnect mouse function | |||
zdialog_free(RGBSzd); // kill dialog | zdialog_free(RGBSzd); // kill dialog | |||
skipping to change at line 4008 | skipping to change at line 4022 | |||
RGBSpixel[ii][1] = Myposn; | RGBSpixel[ii][1] = Myposn; | |||
return; | return; | |||
} | } | |||
// timer function | // timer function | |||
// display RGB values for last 0-9 clicked pixels and current mouse position | // display RGB values for last 0-9 clicked pixels and current mouse position | |||
int show_RGB_timefunc(void *arg) | int show_RGB_timefunc(void *arg) | |||
{ | { | |||
char label[9][4] = { " A ", " B ", " C ", " D ", " E ", // labels A-I for last 0-9 clicked pixels | ch label[9][4] = { " A ", " B ", " C ", " D ", " E ", // labels A-I for last 0-9 clicked pixels | |||
" F ", " G ", " H ", " I " }; | " F ", " G ", " H ", " I " }; | |||
PXM *pxm = 0; | PXM *pxm = 0; | |||
int ii, jj, px, py; | int ii, jj, px, py; | |||
int ww, hh; | int ww, hh; | |||
float red3, green3, blue3; | float red3, green3, blue3; | |||
float *ppixa, *ppixb; | float *ppixa, *ppixb; | |||
char text[100], pixx[8] = "pixx"; | ch text[100], pixx[8] = "pixx"; | |||
static float priorvals[10][3]; // remembers prior pixel values | static float priorvals[10][3]; // remembers prior pixel values | |||
if (! RGBSzd) return 0; // user quit, cancel timer | if (! RGBSzd) return 0; // user quit, cancel timer | |||
if (! curr_file) return 0; | if (! curr_file) return 0; | |||
if (! E0pxm && ! E1pxm && ! E3pxm) { | if (! E0pxm && ! E1pxm && ! E3pxm) { | |||
E0pxm = PXM_load(curr_file,1); | E0pxm = PXM_load(curr_file,1); | |||
if (! E0pxm) return 0; // get poss. 16-bit file | if (! E0pxm) return 0; // get poss. 16-bit file | |||
curr_file_bpc = f_load_bpc; | curr_file_bpc = f_load_bpc; | |||
skipping to change at line 4135 | skipping to change at line 4149 | |||
priorvals[ii][2] = ppixa[2]; | priorvals[ii][2] = ppixa[2]; | |||
} | } | |||
return 1; | return 1; | |||
} | } | |||
/******************************************************************************* */ | /******************************************************************************* */ | |||
// popup window with characters and text for insertion into current edit widget | // popup window with characters and text for insertion into current edit widget | |||
void m_popup_text(GtkWidget *, cchar *menu) // 22.15 | void m_popup_text(GtkWidget *, ch *menu) // 22.15 | |||
{ | { | |||
F1_help_topic = "popup text"; | F1_help_topic = "popup text"; | |||
Plog(1,"m_popup_text \n"); | Plog(1,"m_popup_text \n"); | |||
zdialog_popup_text(popup_text_file,Mwin); | zdialog_popup_text(popup_text_file,Mwin); | |||
return; | return; | |||
} | } | |||
/******************************************************************************* */ | /******************************************************************************* */ | |||
// printer color calibration tool | // printer color calibration tool | |||
namespace calibprint | namespace calibprint | |||
{ | { | |||
int dialog_event(zdialog *zd, cchar *event); | int dialog_event(zdialog *zd, ch *event); | |||
void printchart(); | void printchart(); | |||
void scanchart(); | void scanchart(); | |||
void fixchart(); | void fixchart(); | |||
void processchart(); | void processchart(); | |||
// parameters for RGB step size of 23: 0 23 46 69 ... 253 (253 --> 255) | // parameters for RGB step size of 23: 0 23 46 69 ... 253 (253 --> 255) | |||
// NC colors per RGB dimension (12) (counting both 0 and 255) // step size from 16 to 23 | // NC colors per RGB dimension (12) (counting both 0 and 255) // step size from 16 to 23 | |||
// CS color step size (23) | // CS color step size (23) | |||
// TS tile size in pixels (70) | // TS tile size in pixels (70) | |||
// ROWS chart rows (50) ROWS x COLS must be >= NC*NC*NC | // ROWS chart rows (50) ROWS x COLS must be >= NC*NC*NC | |||
skipping to change at line 4179 | skipping to change at line 4193 | |||
#define COLS 35 | #define COLS 35 | |||
#define NC2 (NC*NC) | #define NC2 (NC*NC) | |||
#define NC3 (NC*NC*NC) | #define NC3 (NC*NC*NC) | |||
int RGBvals[NC]; | int RGBvals[NC]; | |||
int Ntiles = NC3; | int Ntiles = NC3; | |||
int chartww = COLS * TS; // chart image size | int chartww = COLS * TS; // chart image size | |||
int charthh = ROWS * TS; | int charthh = ROWS * TS; | |||
int margin = 80; // chart margins | int margin = 80; // chart margins | |||
char printchartfile[200]; | ch printchartfile[200]; | |||
char scanchartfile[200]; | ch scanchartfile[200]; | |||
} | } | |||
// menu function | // menu function | |||
void m_calibrate_printer(GtkWidget *, cchar *menu) | void m_calibrate_printer(GtkWidget *, ch *menu) | |||
{ | { | |||
using namespace calibprint; | using namespace calibprint; | |||
zdialog *zd; | zdialog *zd; | |||
cchar *title = "Calibrate Printer"; | ch *title = "Calibrate Printer"; | |||
F1_help_topic = "calibrate printer"; | F1_help_topic = "calibrate printer"; | |||
Plog(1,"m_calibrate_printer \n"); | Plog(1,"m_calibrate_printer \n"); | |||
m_viewmode(0,"F"); // file view mode | m_viewmode(0,"F"); // file view mode | |||
for (int ii = 0; ii < NC; ii++) // construct RGBvals table | for (int ii = 0; ii < NC; ii++) // construct RGBvals table | |||
RGBvals[ii] = CS * ii; | RGBvals[ii] = CS * ii; | |||
RGBvals[NC-1] = 255; // set last value = 255 | RGBvals[NC-1] = 255; // set last value = 255 | |||
skipping to change at line 4238 | skipping to change at line 4252 | |||
zdialog_stuff(zd,"processchart",0); | zdialog_stuff(zd,"processchart",0); | |||
zdialog_stuff(zd,"printimage",0); | zdialog_stuff(zd,"printimage",0); | |||
zdialog_resize(zd,250,0); | zdialog_resize(zd,250,0); | |||
zdialog_run(zd,dialog_event,"parent"); | zdialog_run(zd,dialog_event,"parent"); | |||
return; | return; | |||
} | } | |||
// dialog event and completion function | // dialog event and completion function | |||
int calibprint::dialog_event(zdialog *zd, cchar *event) | int calibprint::dialog_event(zdialog *zd, ch *event) | |||
{ | { | |||
using namespace calibprint; | using namespace calibprint; | |||
int nn; | int nn; | |||
F1_help_topic = "calibrate printer"; | F1_help_topic = "calibrate printer"; | |||
if (strmatch(event,"escape")) zd->zstat = -2; // escape key | if (strmatch(event,"escape")) zd->zstat = -2; // escape key | |||
if (! zd->zstat) return 1; // wait for [proceed] or [cancel] | if (! zd->zstat) return 1; // wait for [proceed] or [cancel] | |||
skipping to change at line 4375 | skipping to change at line 4389 | |||
"Save in %s/",printer_color_folder); | "Save in %s/",printer_color_folder); | |||
return; | return; | |||
} | } | |||
// edit and fix the color chart | // edit and fix the color chart | |||
void calibprint::fixchart() | void calibprint::fixchart() | |||
{ | { | |||
using namespace calibprint; | using namespace calibprint; | |||
char *pp; | ch *pp; | |||
zmessageACK(Mwin,"Open and edit the scanned color chart file. \n" | zmessageACK(Mwin,"Open and edit the scanned color chart file. \n" | |||
"Remove any skew or rotation from scanning. \n" | "Remove any skew or rotation from scanning. \n" | |||
"(Use the Fix Perspective function for this). \n" | "(Use the Fix Perspective function for this). \n" | |||
"Cut off the thin green margin ACCURATELY."); | "Cut off the thin green margin ACCURATELY."); | |||
pp = zgetfile("scanned color chart file",MWIN,"file",printer_color_folder,1); | pp = zgetfile("scanned color chart file",MWIN,"file",printer_color_folder,1); | |||
if (! pp) return; | if (! pp) return; | |||
strncpy0(scanchartfile,pp,200); | strncpy0(scanchartfile,pp,200); | |||
f_open(scanchartfile,0,0,1,0); | f_open(scanchartfile,0,0,1,0); | |||
skipping to change at line 4399 | skipping to change at line 4413 | |||
// process the scanned and fixed color chart | // process the scanned and fixed color chart | |||
void calibprint::processchart() | void calibprint::processchart() | |||
{ | { | |||
using namespace calibprint; | using namespace calibprint; | |||
PIXBUF *chartpxb; | PIXBUF *chartpxb; | |||
GError *gerror = 0; | GError *gerror = 0; | |||
uint8 *chartpixels, *pix1; | uint8 *chartpixels, *pix1; | |||
FILE *fid; | FILE *fid; | |||
char mapfile[200], *pp, *pp2; | ch mapfile[200], *pp, *pp2; | |||
int chartrs, chartnc, px, py; | int chartrs, chartnc, px, py; | |||
int ii, nn, row, col, rx, gx, bx; | int ii, nn, row, col, rx, gx, bx; | |||
int xlo, xhi, ylo, yhi; | int xlo, xhi, ylo, yhi; | |||
float fww, fhh; | float fww, fhh; | |||
int Rsum, Gsum, Bsum, Rout, Gout, Bout; | int Rsum, Gsum, Bsum, Rout, Gout, Bout; | |||
int r1, r2, ry, g1, g2, gy, b1, b2, by; | int r1, r2, ry, g1, g2, gy, b1, b2, by; | |||
int ERR1[NC][NC][NC][3], ERR2[NC][NC][NC][3]; | int ERR1[NC][NC][NC][3], ERR2[NC][NC][NC][3]; | |||
zmessageACK(Mwin,"Open the trimmed color chart file"); | zmessageACK(Mwin,"Open the trimmed color chart file"); | |||
skipping to change at line 4579 | skipping to change at line 4593 | |||
// Print the current image file with adjusted colors | // Print the current image file with adjusted colors | |||
// Also called from the file menu function m_print_calibrated() | // Also called from the file menu function m_print_calibrated() | |||
void print_calibrated() | void print_calibrated() | |||
{ | { | |||
using namespace calibprint; | using namespace calibprint; | |||
zdialog *zd; | zdialog *zd; | |||
int zstat; | int zstat; | |||
cchar *title = "Color map file to use"; | ch *title = "Color map file to use"; | |||
char mapfile[200]; | ch mapfile[200]; | |||
FILE *fid; | FILE *fid; | |||
PIXBUF *pixbuf; | PIXBUF *pixbuf; | |||
GError *gerror = 0; | GError *gerror = 0; | |||
uint8 *pixels, *pix1; | uint8 *pixels, *pix1; | |||
char *pp, *pp2, printfile[100]; | ch *pp, *pp2, printfile[200]; | |||
int ww, hh, rs, nc, px, py, nn, err; | int ww, hh, rs, nc, px, py, nn, err; | |||
int R1, G1, B1, R2, G2, B2; | int R1, G1, B1, R2, G2, B2; | |||
int RGB[NC][NC][NC][3], ERR[NC][NC][NC][3]; | int RGB[NC][NC][NC][3], ERR[NC][NC][NC][3]; | |||
int rr1, rr2, gg1, gg2, bb1, bb2; | int rr1, rr2, gg1, gg2, bb1, bb2; | |||
int rx, gx, bx; | int rx, gx, bx; | |||
int ii, Dr, Dg, Db; | int ii, Dr, Dg, Db; | |||
float W[8], w, Wsum, D, Dmax, F; | float W[8], w, Wsum, D, Dmax, F; | |||
float Er, Eg, Eb; | float Er, Eg, Eb; | |||
float max$; | float max$; | |||
skipping to change at line 4745 | skipping to change at line 4759 | |||
pix1[0] = R2; | pix1[0] = R2; | |||
pix1[1] = G2; | pix1[1] = G2; | |||
pix1[2] = B2; | pix1[2] = B2; | |||
} | } | |||
poptext_killnow(); | poptext_killnow(); | |||
zadd_locked(Ffuncbusy,-1); | zadd_locked(Ffuncbusy,-1); | |||
Fblock("print_calibrated",0); | Fblock("print_calibrated",0); | |||
snprintf(printfile,100,"%s/printfile.png",temp_folder); // save revised pixbuf to print file | snprintf(printfile,200,"%s/printfile.png",temp_folder); // save revised pixbuf to print file | |||
gdk_pixbuf_save(pixbuf,printfile,"png",&gerror,"compression","1",null); | gdk_pixbuf_save(pixbuf,printfile,"png",&gerror,"compression","1",null); | |||
if (gerror) { | if (gerror) { | |||
zmessageACK(Mwin,gerror->message); | zmessageACK(Mwin,gerror->message); | |||
return; | return; | |||
} | } | |||
g_object_unref(pixbuf); | g_object_unref(pixbuf); | |||
err = f_open(printfile,0,0,1,0); // open print file | err = f_open(printfile,0,0,1,0); // open print file | |||
if (err) return; | if (err) return; | |||
skipping to change at line 4767 | skipping to change at line 4781 | |||
zmessageACK(Mwin,"Image colors are converted for printing."); | zmessageACK(Mwin,"Image colors are converted for printing."); | |||
print_image_file(Mwin,printfile); | print_image_file(Mwin,printfile); | |||
return; | return; | |||
} | } | |||
/******************************************************************************* */ | /******************************************************************************* */ | |||
// setup x and y grid lines - count/spacing, enable/disable, offsets | // setup x and y grid lines - count/spacing, enable/disable, offsets | |||
void m_grid_settings(GtkWidget *widget, cchar *menu) | void m_grid_settings(GtkWidget *widget, ch *menu) | |||
{ | { | |||
int grid_settings_dialog_event(zdialog *zd, cchar *event); | int grid_settings_dialog_event(zdialog *zd, ch *event); | |||
zdialog *zd; | zdialog *zd; | |||
F1_help_topic = "grid settings"; | F1_help_topic = "grid settings"; | |||
Plog(1,"m_grid_settings \n"); | Plog(1,"m_grid_settings \n"); | |||
m_viewmode(0,"F"); // file view mode | m_viewmode(0,"F"); // file view mode | |||
/*** | /*** | |||
skipping to change at line 4848 | skipping to change at line 4862 | |||
zdialog_set_modal(zd); | zdialog_set_modal(zd); | |||
zdialog_run(zd,grid_settings_dialog_event,"parent"); | zdialog_run(zd,grid_settings_dialog_event,"parent"); | |||
zdialog_wait(zd); | zdialog_wait(zd); | |||
zdialog_free(zd); | zdialog_free(zd); | |||
return; | return; | |||
} | } | |||
// dialog event function | // dialog event function | |||
int grid_settings_dialog_event(zdialog *zd, cchar *event) | int grid_settings_dialog_event(zdialog *zd, ch *event) | |||
{ | { | |||
if (strmatch(event,"escape")) zd->zstat = -2; // escape key | if (strmatch(event,"escape")) zd->zstat = -2; // escape key | |||
if (zd->zstat) // done or cancel | if (zd->zstat) // done or cancel | |||
{ | { | |||
if (zd->zstat != 1) return 1; | if (zd->zstat != 1) return 1; | |||
if (gridsettings[GX] || gridsettings[GY]) | if (gridsettings[GX] || gridsettings[GY]) | |||
gridsettings[GON] = 1; | gridsettings[GON] = 1; | |||
else gridsettings[GON] = 0; | else gridsettings[GON] = 0; | |||
Fpaint2(); | Fpaint2(); | |||
skipping to change at line 4895 | skipping to change at line 4909 | |||
if (gridsettings[GX] || gridsettings[GY]) // if either grid enabled, show grid | if (gridsettings[GX] || gridsettings[GY]) // if either grid enabled, show grid | |||
gridsettings[GON] = 1; | gridsettings[GON] = 1; | |||
Fpaint2(); | Fpaint2(); | |||
return 1; | return 1; | |||
} | } | |||
// toggle grid lines on and off | // toggle grid lines on and off | |||
void m_toggle_grid(GtkWidget *, cchar *menu) | void m_toggle_grid(GtkWidget *, ch *menu) | |||
{ | { | |||
F1_help_topic = "grid settings"; | F1_help_topic = "grid settings"; | |||
Plog(1,"m_toggle_grid \n"); | Plog(1,"m_toggle_grid \n"); | |||
gridsettings[GON] = 1 - gridsettings[GON]; | gridsettings[GON] = 1 - gridsettings[GON]; | |||
if (gridsettings[GON]) | if (gridsettings[GON]) | |||
if (! gridsettings[GX] && ! gridsettings[GY]) // if grid on and x/y both off, | if (! gridsettings[GX] && ! gridsettings[GY]) // if grid on and x/y both off, | |||
gridsettings[GX] = gridsettings[GY] = 1; // set both grids on | gridsettings[GX] = gridsettings[GY] = 1; // set both grids on | |||
Fpaint2(); | Fpaint2(); | |||
return; | return; | |||
} | } | |||
/******************************************************************************* */ | /******************************************************************************* */ | |||
// choose color for foreground lines | // choose color for foreground lines | |||
// (area outline, mouse circle) | // (area outline, mouse circle) | |||
void m_line_color(GtkWidget *, cchar *menu) | void m_line_color(GtkWidget *, ch *menu) | |||
{ | { | |||
int line_color_dialog_event(zdialog *zd, cchar *event); | int line_color_dialog_event(zdialog *zd, ch *event); | |||
zdialog *zd; | zdialog *zd; | |||
F1_help_topic = "line color"; | F1_help_topic = "line color"; | |||
Plog(1,"m_line_color \n"); | Plog(1,"m_line_color \n"); | |||
m_viewmode(0,"F"); // file view mode | m_viewmode(0,"F"); // file view mode | |||
zd = zdialog_new("Line Color",Mwin,null); | zd = zdialog_new("Line Color",Mwin,null); | |||
skipping to change at line 4953 | skipping to change at line 4967 | |||
zdialog_stuff(zd,"Red",1); | zdialog_stuff(zd,"Red",1); | |||
if (LINE_COLOR[0] == GREEN[0] && LINE_COLOR[1] == GREEN[1] && LINE_COLOR[2] = = GREEN[2]) | if (LINE_COLOR[0] == GREEN[0] && LINE_COLOR[1] == GREEN[1] && LINE_COLOR[2] = = GREEN[2]) | |||
zdialog_stuff(zd,"Green",1); | zdialog_stuff(zd,"Green",1); | |||
zdialog_run(zd,line_color_dialog_event,"save"); // run dialog, parallel | zdialog_run(zd,line_color_dialog_event,"save"); // run dialog, parallel | |||
return; | return; | |||
} | } | |||
// dialog event and completion function | // dialog event and completion function | |||
int line_color_dialog_event(zdialog *zd, cchar *event) | int line_color_dialog_event(zdialog *zd, ch *event) | |||
{ | { | |||
if (strmatch(event,"escape")) zd->zstat = -2; // escape key | if (strmatch(event,"escape")) zd->zstat = -2; // escape key | |||
if (strmatch(event,"Black")) memcpy(LINE_COLOR,BLACK,3*sizeof(int)); // set selected color | if (strmatch(event,"Black")) memcpy(LINE_COLOR,BLACK,3*sizeof(int)); // set selected color | |||
if (strmatch(event,"White")) memcpy(LINE_COLOR,WHITE,3*sizeof(int)); | if (strmatch(event,"White")) memcpy(LINE_COLOR,WHITE,3*sizeof(int)); | |||
if (strmatch(event,"Red")) memcpy(LINE_COLOR,RED,3*sizeof(int)); | if (strmatch(event,"Red")) memcpy(LINE_COLOR,RED,3*sizeof(int)); | |||
if (strmatch(event,"Green")) memcpy(LINE_COLOR,GREEN,3*sizeof(int)); | if (strmatch(event,"Green")) memcpy(LINE_COLOR,GREEN,3*sizeof(int)); | |||
if (CEF && CEF->zd) zdialog_send_event(CEF->zd,"line_color"); | if (CEF && CEF->zd) zdialog_send_event(CEF->zd,"line_color"); | |||
Fpaint2(); | Fpaint2(); | |||
skipping to change at line 4978 | skipping to change at line 4992 | |||
/******************************************************************************* */ | /******************************************************************************* */ | |||
// dark_brite menu function | // dark_brite menu function | |||
// highlight darkest and brightest pixels | // highlight darkest and brightest pixels | |||
namespace darkbrite { | namespace darkbrite { | |||
float darklim = 0; | float darklim = 0; | |||
float brightlim = 255; | float brightlim = 255; | |||
} | } | |||
void m_darkbrite(GtkWidget *, const char *) | void m_darkbrite(GtkWidget *, ch *) | |||
{ | { | |||
using namespace darkbrite; | using namespace darkbrite; | |||
int darkbrite_dialog_event(zdialog* zd, const char *event); | int darkbrite_dialog_event(zdialog* zd, ch *event); | |||
cchar *title = "Darkest and Brightest Pixels"; | ch *title = "Darkest and Brightest Pixels"; | |||
F1_help_topic = "dark/bright pixels"; | F1_help_topic = "dark/bright pixels"; | |||
Plog(1,"m_darkbrite \n"); | Plog(1,"m_darkbrite \n"); | |||
m_viewmode(0,"F"); // file view mode | m_viewmode(0,"F"); // file view mode | |||
if (! curr_file) return; // no image file | if (! curr_file) return; // no image file | |||
/** | /** | |||
skipping to change at line 5033 | skipping to change at line 5047 | |||
zd_darkbrite = zd; // global pointer for Fpaint*() | zd_darkbrite = zd; // global pointer for Fpaint*() | |||
zdialog_send_event(zd,"limD"); // initz. NNN labels | zdialog_send_event(zd,"limD"); // initz. NNN labels | |||
zdialog_send_event(zd,"limB"); | zdialog_send_event(zd,"limB"); | |||
return; | return; | |||
} | } | |||
// darkbrite dialog event and completion function | // darkbrite dialog event and completion function | |||
int darkbrite_dialog_event(zdialog *zd, const char *event) // darkbrite dialog event function | int darkbrite_dialog_event(zdialog *zd, ch *event) // darkbrite dialog event function | |||
{ | { | |||
using namespace darkbrite; | using namespace darkbrite; | |||
if (strmatch(event,"escape")) zd->zstat = -2; // escape key | if (strmatch(event,"escape")) zd->zstat = -2; // escape key | |||
if (zd->zstat) | if (zd->zstat) | |||
{ | { | |||
zdialog_free(zd); | zdialog_free(zd); | |||
zd_darkbrite = 0; | zd_darkbrite = 0; | |||
Fpaint2(); | Fpaint2(); | |||
skipping to change at line 5083 | skipping to change at line 5097 | |||
else if (P > B) pix[0] = 0; // bright pixel = mostly green/blue | else if (P > B) pix[0] = 0; // bright pixel = mostly green/blue | |||
} | } | |||
return; | return; | |||
} | } | |||
/******************************************************************************* */ | /******************************************************************************* */ | |||
// monitor color and contrast test function | // monitor color and contrast test function | |||
void m_monitor_color(GtkWidget *, cchar *) | void m_monitor_color(GtkWidget *, ch *) | |||
{ | { | |||
char file[200]; | ch file[200]; | |||
int err; | int err; | |||
char *savecurrfile = 0; | ch *savecurrfile = 0; | |||
char *savegallery = 0; | ch *savegallery = 0; | |||
zdialog *zd; | zdialog *zd; | |||
cchar *message = "Brightness should show a gradual ramp \n" | ch *message = "Brightness should show a gradual ramp \n" | |||
"extending all the way to the edges."; | "extending all the way to the edges."; | |||
F1_help_topic = "monitor color"; | F1_help_topic = "monitor color"; | |||
Plog(1,"m_monitor_color \n"); | Plog(1,"m_monitor_color \n"); | |||
if (Fblock("monitor_color","block edits")) return; // check pending, block | if (Fblock("monitor_color","block edits")) return; // check pending, block | |||
if (curr_file) | if (curr_file) | |||
savecurrfile = zstrdup(curr_file,"monitor-color"); // save view mode | savecurrfile = zstrdup(curr_file,"monitor-color"); // save view mode | |||
skipping to change at line 5150 | skipping to change at line 5164 | |||
else gallery(topfolders[0],"init",0); | else gallery(topfolders[0],"init",0); | |||
Fblock("monitor_color",0); | Fblock("monitor_color",0); | |||
return; | return; | |||
} | } | |||
/******************************************************************************* */ | /******************************************************************************* */ | |||
// show resource consumption: CPU, memory, map tiles on disk | // show resource consumption: CPU, memory, map tiles on disk | |||
void m_resources(GtkWidget *, cchar *) | void m_resources(GtkWidget *, ch *) | |||
{ | { | |||
static zdialog *zd = 0; | static zdialog *zdpop = 0; | |||
time_t reptime1; | time_t reptime1; | |||
char reptime2[40]; | ch reptime2[40]; | |||
static double time0 = 0.0; | static double time0 = 0.0; | |||
double time1; | double time1; | |||
double mem = 0; | double mem = 0; | |||
char buff1[100], buff2[1000]; | ch buff1[100], buff2[1000]; | |||
char *pp = 0; | ch *pp = 0; | |||
FILE *fid; | FILE *fid; | |||
int MB, pagesize; | int MB, pagesize; | |||
int mega = 1024 * 1024; | int mega = 1024 * 1024; | |||
int nn, bs, tbs = 0, nf = 0; | int nn, bs, tbs = 0, nf = 0; | |||
F1_help_topic = "show resources"; | F1_help_topic = "show resources"; | |||
if (! zd || ! zdialog_valid(zd,"Resources")) | if (! zdpop || ! zdialog_valid(zdpop,"Resources")) | |||
zd = popup_report_open("Resources",Mwin,500,400,0,0,"OK",0); | zdpop = popup_report_open("Resources",Mwin,500,400,0,0,"OK",0); | |||
// rolling popup report 22.15 | // rolling popup report 22.15 | |||
reptime1 = time(0); // report current time, bold | reptime1 = time(0); // report current time, bold | |||
strncpy0(reptime2,ctime(&reptime1),40); // Day Mon dd hh:mm:ss yyyy | strncpy0(reptime2,ctime(&reptime1),40); // Day Mon dd hh:mm:ss yyyy | |||
reptime2[19] = 0; | reptime2[19] = 0; | |||
popup_report_write(zd,0,"\n%s\n",reptime2+11); // hh:mm:ss | popup_report_write(zdpop,0,"\n%s\n",reptime2+11); // hh:mm:ss | |||
time1 = CPUtime(); | time1 = CPUtime(); | |||
popup_report_write(zd,0,"CPU time: %.3f seconds \n", time1 - time0); | popup_report_write(zdpop,0,"CPU time: %.3f seconds \n", time1 - time0); | |||
time0 = time1; | time0 = time1; | |||
snprintf(buff1,100,"/proc/self/stat"); // read file /proc/self/stat | snprintf(buff1,100,"/proc/self/stat"); // read file /proc/self/stat | |||
fid = fopen(buff1,"r"); | fid = fopen(buff1,"r"); | |||
if (fid) { | if (fid) { | |||
pp = fgets(buff2,1000,fid); | pp = fgets(buff2,1000,fid); | |||
fclose(fid); | fclose(fid); | |||
} | } | |||
if (pp) { | if (pp) { | |||
pp = strchr(pp,')'); // closing ')' after (short) filename | pp = strchr(pp,')'); // closing ')' after (short) filename | |||
if (pp) { | if (pp) { | |||
parseprocrec(pp+1,22,&mem,null); // get real memory | parseprocrec(pp+1,22,&mem,null); // get real memory | |||
pagesize = sysconf(_SC_PAGESIZE); // system page size | pagesize = sysconf(_SC_PAGESIZE); // system page size | |||
MB = mem * pagesize / mega; | MB = mem * pagesize / mega; | |||
popup_report_write(zd,0,"real memory MB: %d \n",MB); | popup_report_write(zdpop,0,"real memory MB: %d \n",MB); | |||
} | } | |||
} | } | |||
fid = popen("find -H ~/.cache/champlain/ -type f -printf '%b\n'","r"); // count map tiles and space used | fid = popen("find -H ~/.cache/champlain/ -type f -printf '%b\n'","r"); // count map tiles and space used | |||
if (fid) { | if (fid) { | |||
while (true) { | while (true) { | |||
nn = fscanf(fid,"%d",&bs); | nn = fscanf(fid,"%d",&bs); | |||
if (nn == EOF) break; | if (nn == EOF) break; | |||
if (nn == 1) { | if (nn == 1) { | |||
nf += 1; | nf += 1; | |||
tbs += bs; | tbs += bs; | |||
} | } | |||
} | } | |||
pclose(fid); | pclose(fid); | |||
} | } | |||
tbs = tbs * 0.0004883; // 512 byte blocks to megabytes | tbs = tbs * 0.0004883; // 512 byte blocks to megabytes | |||
popup_report_write(zd,0,"map tiles: %d megabytes: %d \n",nf,tbs); | popup_report_write(zdpop,0,"map tiles: %d megabytes: %d \n",nf,tbs); | |||
popup_report_bottom(zd); | popup_report_bottom(zdpop); | |||
return; | return; | |||
} | } | |||
/******************************************************************************* */ | /******************************************************************************* */ | |||
// popup report of zmalloc() memory allocation per tag | // popup report of zmalloc() memory allocation per tag | |||
void m_zmalloc_report(GtkWidget *, cchar *) | void m_zmalloc_report(GtkWidget *, ch *) | |||
{ | { | |||
static zdialog *zd = 0; | static zdialog *zdpop = 0; | |||
if (! zd || ! zdialog_valid(zd,"zmalloc")) | if (! zdpop || ! zdialog_valid(zdpop,"zmalloc")) | |||
// open new popup report | // open new popup report | |||
zd = popup_report_open("zmalloc",Mwin,500,400,0,0,"OK",0); | zdpop = popup_report_open("zmalloc",Mwin,500,400,0,0,"OK",0); | |||
// 22.15 | // 22.15 | |||
zmalloc_report(zd); | zmalloc_report(zdpop); | |||
// generate report | // generate report | |||
popup_report_bottom(zd); | popup_report_bottom(zdpop); | |||
return; | return; | |||
} | } | |||
/******************************************************************************* */ | /******************************************************************************* */ | |||
// popup report of zmalloc() memory allocation per tag | // popup report of zmalloc() memory allocation per tag | |||
// report only tags showing increased allocation from prior max. | // report only tags showing increased allocation from prior max. | |||
void m_zmalloc_growth(GtkWidget *, cchar *) | void m_zmalloc_growth(GtkWidget *, ch *) | |||
{ | { | |||
static zdialog *zd = 0; | static zdialog *zdpop = 0; | |||
if (! zd || ! zdialog_valid(zd,"zmalloc growth")) | if (! zdpop || ! zdialog_valid(zdpop,"zmalloc growth")) | |||
// open new popup report | // open new popup report | |||
zd = popup_report_open("zmalloc growth",Mwin,500,400,0,0,"OK",0); | zdpop = popup_report_open("zmalloc growth",Mwin,500,400,0,0,"OK",0); | |||
// 22.15 | // 22.15 | |||
zmalloc_growth(zd); | zmalloc_growth(zdpop); | |||
// generate report | // generate report | |||
popup_report_bottom(zd); | popup_report_bottom(zdpop); | |||
return; | return; | |||
} | } | |||
/******************************************************************************* */ | /******************************************************************************* */ | |||
// toggle: show mouse events with popup text next to mouse pointer | // toggle: show mouse events with popup text next to mouse pointer | |||
void m_mouse_events(GtkWidget *, cchar *) // 22.15 | void m_mouse_events(GtkWidget *, ch *) // 22.15 | |||
{ | { | |||
Fmousevents = 1 - Fmousevents; | Fmousevents = 1 - Fmousevents; | |||
return; | return; | |||
} | } | |||
/******************************************************************************* */ | /******************************************************************************* */ | |||
// export files contained in the appimage container | // export files contained in the appimage container | |||
void m_appimage_files(GtkWidget *, cchar *) | void m_appimage_files(GtkWidget *, ch *) | |||
{ | { | |||
cchar *folder; | ch *folder; | |||
F1_help_topic = "appimage files"; | F1_help_topic = "appimage files"; | |||
Plog(1,"m_appimage_files \n"); | Plog(1,"m_appimage_files \n"); | |||
if (! getenv("HERE")) { | if (! getenv("HERE")) { | |||
zmessageACK(Mwin,"not an appimage build"); | zmessageACK(Mwin,"not an appimage build"); | |||
return; | return; | |||
} | } | |||
skipping to change at line 5287 | skipping to change at line 5301 | |||
zshell("log ack","cp -R $HERE/usr/share/doc/fotoxx/ %s",folder); | zshell("log ack","cp -R $HERE/usr/share/doc/fotoxx/ %s",folder); | |||
zshell("log ack","cp -R $HERE/usr/share/fotoxx/data/ %s",folder); | zshell("log ack","cp -R $HERE/usr/share/fotoxx/data/ %s",folder); | |||
return; | return; | |||
} | } | |||
/******************************************************************************* */ | /******************************************************************************* */ | |||
// uninstall appimage package | // uninstall appimage package | |||
void m_appimage_unstall(GtkWidget *, cchar *) | void m_appimage_unstall(GtkWidget *, ch *) | |||
{ | { | |||
F1_help_topic = "appimage uninstall"; | F1_help_topic = "appimage uninstall"; | |||
Plog(1,"m_appimage_unstall \n"); | Plog(1,"m_appimage_unstall \n"); | |||
if (! getenv("HERE")) { | if (! getenv("HERE")) { | |||
zmessageACK(Mwin,"not an appimage build"); | zmessageACK(Mwin,"not an appimage build"); | |||
return; | return; | |||
} | } | |||
skipping to change at line 5310 | skipping to change at line 5324 | |||
appimage_unstall(); // does not return | appimage_unstall(); // does not return | |||
return; | return; | |||
} | } | |||
/******************************************************************************* */ | /******************************************************************************* */ | |||
// zappcrash test - make a segment fault | // zappcrash test - make a segment fault | |||
// test with: $ fotoxx -m "zappcrash test" | // test with: $ fotoxx -m "zappcrash test" | |||
void m_zappcrash_test(GtkWidget *, cchar *) // 22.1 | void m_zappcrash_test(GtkWidget *, ch *) // 22.1 | |||
{ | { | |||
int *nulladdr = 0; | int *nulladdr = 0; | |||
zfuncs::zappcrash_context1 = "zappcrash test"; | zfuncs::zappcrash_context1 = "zappcrash test"; | |||
zfuncs::zappcrash_context2 = "zappcrash test"; | zfuncs::zappcrash_context2 = "zappcrash test"; | |||
printf("zappcrash test, ref. null address: %d \n",*nulladdr); | printf("zappcrash test, ref. null address: %d \n",*nulladdr); | |||
return; | return; | |||
} | } | |||
End of changes. 210 change blocks. | ||||
481 lines changed or deleted | 498 lines changed or added |