"Fossies" - the Fresh Open Source Software Archive  

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

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

f.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

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