# This is a shell archive. Save it in a file, remove anything before # this line, and then unpack it by entering "sh file". Note, it may # create directories; files and directories will be owned by you and # have default permissions. # # This archive contains: # # fotoxx # fotoxx/Makefile # fotoxx/distinfo # fotoxx/pkg-descr # fotoxx/pkg_plist # fotoxx/files # fotoxx/files/patch-fotoxx-11.03.cc # fotoxx/files/patch-zfuncs.cc # fotoxx/files/patch-zfuncs.h # fotoxx/files/patch-Makefile # fotoxx/files/patch-dependencies.sh # echo c - fotoxx mkdir -p fotoxx > /dev/null 2>&1 echo x - fotoxx/Makefile sed 's/^X//' >fotoxx/Makefile << 'a7a7113a4a864c099ebfea8c91c52886' X# New ports collection makefile for: fotoxx-11.03 X# Date created: 28 March 2011 X# Whom: Rod Person X# X# $FreeBSD$ X# X XPORTNAME= fotoxx XPORTVERSION= 11.03 XCATEGORIES= graphics XMASTER_SITES= http://kornelix.squarespace.com/downloads/ \ X http://www.rodperson.com/DL/ X XMAINTAINER= rodperson@rodperson.com XCOMMENT= Application to organize and edit image collections X XLIB_DEPENDS= gtk-x11-2.0.0:${PORTSDIR}/x11-toolkits/gtk20 XRUN_DEPENDS= xdg-open:${PORTSDIR}/devel/xdg-utils \ X ufraw-batch:${PORTSDIR}/graphics/ufraw \ X exiftool:${PORTSDIR}/graphics/p5-Image-ExifTool X XUSE_GMAKE= yes XALL_TARGET?= fotoxx manpage X X#MAN1= fotoxx.1 X X.include a7a7113a4a864c099ebfea8c91c52886 echo x - fotoxx/distinfo sed 's/^X//' >fotoxx/distinfo << 'cc791d39a2063923dac3fff6b235a2f8' XSHA256 (fotoxx-11.03.tar.gz) = c23e6b7c5517d1509b14a270bd2ad2af6fd2de613e55e79104f77d1748492577 XSIZE (fotoxx-11.03.tar.gz) = 1152890 cc791d39a2063923dac3fff6b235a2f8 echo x - fotoxx/pkg-descr sed 's/^X//' >fotoxx/pkg-descr << '6aa331b371e2c653814f451be1bbcc96' X Fotoxx is a graphical menu-driven program which operates in X its own window. Organize and administer a collection of images, X edit images, search images, image utility functions. 6aa331b371e2c653814f451be1bbcc96 echo x - fotoxx/pkg_plist sed 's/^X//' >fotoxx/pkg_plist << '5972549f0cdb64adef8fd465e0c6ea1e' Xbin/fotoxx Xshare/fotoxx/icons/arrow.png Xshare/fotoxx/icons/busy.png Xshare/fotoxx/icons/drag.png Xshare/fotoxx/icons/draw.png Xshare/fotoxx/icons/first-page.png Xshare/fotoxx/icons/folder.png Xshare/fotoxx/icons/folder256.png Xshare/fotoxx/icons/fotoxx.png Xshare/fotoxx/icons/gallery.png Xshare/fotoxx/icons/help.png Xshare/fotoxx/icons/last-page.png Xshare/fotoxx/icons/next-page.png Xshare/fotoxx/icons/next-row.png Xshare/fotoxx/icons/next.png Xshare/fotoxx/icons/open.png Xshare/fotoxx/icons/prev-page.png Xshare/fotoxx/icons/prev-row.png Xshare/fotoxx/icons/prev.png Xshare/fotoxx/icons/print.png Xshare/fotoxx/icons/quit.png Xshare/fotoxx/icons/redo.png Xshare/fotoxx/icons/save.png Xshare/fotoxx/icons/saveas.png Xshare/fotoxx/icons/trash.png Xshare/fotoxx/icons/undo.png Xshare/fotoxx/icons/zoom+.png Xshare/fotoxx/icons/zoom-.png Xshare/doc/fotoxx/userguide-en.html Xshare/doc/fotoxx/freshmeat Xshare/doc/fotoxx/fotoxx.man Xshare/doc/fotoxx/TRANSLATIONS Xshare/doc/fotoxx/README Xshare/doc/fotoxx/COPYING Xshare/doc/fotoxx/CHANGES Xshare/doc/fotoxx/images/HDF-paint.jpg Xshare/doc/fotoxx/images/HDR-adjust.jpg Xshare/doc/fotoxx/images/annotate.jpg Xshare/doc/fotoxx/images/brightness-color.jpg Xshare/doc/fotoxx/images/brightness-ramp.png Xshare/doc/fotoxx/images/edit-tags.jpg Xshare/doc/fotoxx/images/expand-brightness.png Xshare/doc/fotoxx/images/gallery image selection.jpg Xshare/doc/fotoxx/images/manage-tags.jpg Xshare/doc/fotoxx/images/navigation.jpeg Xshare/doc/fotoxx/images/pano-dialog.jpeg Xshare/doc/fotoxx/images/rename.jpeg Xshare/doc/fotoxx/images/save-as.jpeg Xshare/doc/fotoxx/images/search-images.jpg Xshare/doc/fotoxx/images/select-area.png Xshare/doc/fotoxx/images/select-whole-image.jpg Xshare/doc/fotoxx/images/select_edit.jpg Xshare/doc/fotoxx/images/sharpen.jpeg Xshare/doc/fotoxx/images/smart-erase.png Xshare/doc/fotoxx/images/stack.png Xshare/doc/fotoxx/images/tone-mapping.png Xshare/doc/fotoxx/images/trim.jpg Xshare/doc/fotoxx/images/watermark.jpg Xlocales/de/fotoxx.po Xlocales/de/zfuncs.po Xlocales/en/fotoxx.po Xlocales/en/zfuncs.po Xlocales/es/fotoxx.po Xlocales/es/zfuncs.po Xlocales/fr/fotoxx.po Xlocales/fr/fotoxx.po.old Xlocales/fr/zfuncs.po Xlocales/gl/fotoxx.po Xlocales/gl/zfuncs.po Xlocales/it/fotoxx.po Xlocales/it/zfuncs.po Xlocales/nl/fotoxx.po Xlocales/nl/zfuncs.po Xlocales/pt/fotoxx.po Xlocales/pt/zfuncs.po Xlocales/ru/fotoxx.po Xlocales/ru/zfuncs.po Xlocales/sv/fotoxx.po Xlocales/sv/zfuncs.po Xlocales/zh_CN/fotoxx.po Xlocales/zh_CN/zfuncs.po 5972549f0cdb64adef8fd465e0c6ea1e echo c - fotoxx/files mkdir -p fotoxx/files > /dev/null 2>&1 echo x - fotoxx/files/patch-fotoxx-11.03.cc sed 's/^X//' >fotoxx/files/patch-fotoxx-11.03.cc << '4a06c996efb3d58a12c308fc01279d3d' X--- fotoxx-11.03.cc.orig 2011-02-28 11:04:24.000000000 -0500 X+++ fotoxx-11.03.cc 2011-03-10 18:54:17.000000000 -0500 X@@ -5,7 +5,7 @@ X Copyright 2007 2008 2009 2010 2011 Michael Cornelison X source URL: kornelix.squarespace.com X contact: kornelix2@googlemail.com X- X+ X This program is free software: you can redistribute it and/or modify X it under the terms of the GNU General Public License as published by X the Free Software Foundation, either version 3 of the License, or X@@ -24,6 +24,11 @@ X #include X #include "zfuncs.h" X X+ X+//Including the next two allows the use of getpwuid() instead of cuserid() X+#include X+#include X+ X #define fversion "Fotoxx v.11.03 2011.03.01" // version and date X #define fversioncc 16 // cc to use for window title bar X #define flicense "Free software - GNU General Public License v.3" X@@ -96,6 +101,11 @@ X #define tagdelim1 ',' // delimiter for new tags v.11.02 X #define tagdelim2 ", " // delimiter + blank v.11.02 X X+#define WEXITSTATUS(w)((w)>>8) // fixes the WEXITSTATUS not declared on FreeBSD X+ X+ X+ X+ X namespace image_navi { // zfuncs: image_gallery() etc. X extern int xwinW, xwinH; // image gallery window size X extern int thumbsize; // thumbnail image size X@@ -107,6 +117,9 @@ X extern char zicondir[200]; X } X X+const int CWDBUFFERSIZE = 4096; X+ X+ X GtkWidget *mWin, *drWin, *mVbox; // main and drawing window X GtkWidget *mMbar, *mTbar, *STbar; // menu bar, tool bar, status bar X GdkGC *gdkgc = 0; // GDK graphics context X@@ -237,7 +250,7 @@ X int toparcx,toparcy,toparcw,toparch; // of image in window X int ptoparcx,ptoparcy,ptoparcw,ptoparch; X X-int Fgrid[2]; // x and y gridlines on / off X+int Fgrid[2]; // x and y gridlines on / off X int gridspace[2] = { 50, 50 }; // x and y grid line spacing X int gridcount[2] = { 0, 0 }; // grid line counts (alternative) X X@@ -352,7 +365,7 @@ X X // Image Information functions (EXIF, IPTC, etc.) X X-void m_edit_comments(GtkWidget *, cchar *); // edit user comments X+void m_edit_comments(GtkWidget *, cchar *); // edit user comments X void m_edit_caption(GtkWidget *, cchar *); // edit caption X void m_edit_tags(GtkWidget *, cchar *); // edit tags dialog X void m_manage_tags(GtkWidget *, cchar *); // manage tags dialog X@@ -378,15 +391,15 @@ X void m_select_hide(GtkWidget *, cchar *); // show area outline X void m_select_enable(GtkWidget *, cchar *); // hide area outline X void m_select_disable(GtkWidget *, cchar *); // disable area X-void m_select_invert(GtkWidget *, cchar *); // invert area X-void m_select_delete(GtkWidget *, cchar *); // delete area X+void m_select_invert(GtkWidget *, cchar *); // invert area X+void m_select_delete(GtkWidget *, cchar *); // delete area X void m_select_copy(GtkWidget *, cchar *); // copy area, save in memory X void m_select_paste(GtkWidget *, cchar *); // paste saved area into image X void m_select_open(GtkWidget *, cchar *); // open an area file, save in memory X void m_select_save(GtkWidget *, cchar *); // save area to a file X void m_select_whole_image(GtkWidget *, cchar *); // select whole image area X void m_select_edit(GtkWidget *, cchar *); // select and edit in parallel X- X+ X // image edit functions X X void m_whitebal(GtkWidget *, cchar *); // adjust white balance X@@ -559,11 +572,11 @@ X char lang[8] = "", *pp; X int Fclone = 0, ww, hh; X GdkScreen *screen; X- X+ X gtk_init(&argc,&argv); // initz. GTK X X initz_appfiles("fotoxx",null); // get app directories X- X+ X printf(fversion "\n"); // print fotoxx version X if (argc > 1 && strEqu(argv[1],"-v")) return 0; X X@@ -584,7 +597,7 @@ X X mWin = gtk_window_new(GTK_WINDOW_TOPLEVEL); // create main window X gtk_window_set_title(MWIN,fversion); X- X+ X mVbox = gtk_vbox_new(0,0); // add vert. packing box X gtk_container_add(GTK_CONTAINER(mWin),mVbox); X X@@ -714,7 +727,7 @@ X add_submenu_item(mPlugins,plugins[ii],m_run_plugin); X *pp = ' '; X } X- X+ X mTbar = create_toolbar(mVbox); // toolbar buttons X add_toolbar_button(mTbar, ZTX("Gallery"), ZTX("Image Gallery"), "gallery.png", m_gallery); X add_toolbar_button(mTbar, ZTX("Open"), ZTX("Open Image File"), "open.png", m_open); X@@ -729,7 +742,7 @@ X add_toolbar_button(mTbar, ZTX("Trash"), ZTX("Move Image to Trash"), "trash.png", m_trash); X add_toolbar_button(mTbar, ZTX("Quit"), ZTX("Quit fotoxx"), "quit.png", m_quit); X add_toolbar_button(mTbar, ZTX("Help"), ZTX("Fotoxx Essentials"), "help.png", m_help); X- X+ X drWin = gtk_drawing_area_new(); // add drawing window X gtk_box_pack_start(GTK_BOX(mVbox),drWin,1,1,0); X X@@ -749,7 +762,7 @@ X X G_SIGNAL(mWin,"key-press-event",KBpress,0) // connect KB events X G_SIGNAL(mWin,"key-release-event",KBrelease,0) X- X+ X drag_drop_connect(drWin,m_open_drag); // connect drag-drop event X X gtk_window_set_position(MWIN,GTK_WIN_POS_CENTER); X@@ -779,7 +792,7 @@ X gdk_rgb_find_color(colormap,&gray); X gdk_rgb_find_color(colormap,&red); X gdk_rgb_find_color(colormap,&green); X- X+ X gdk_gc_set_foreground(gdkgc,&black); X gdk_gc_set_background(gdkgc,&gray); X gdk_window_set_background(drWin->window,&gray); // v.11.01 X@@ -794,7 +807,7 @@ X busycursor = zmakecursor("busy.png"); // cursor for function busy X if (! busycursor) X busycursor = gdk_cursor_new(GDK_WATCH); X- X+ X gtk_init_add((GtkFunction) gtkinitfunc,0); // set initz. call from gtk_main() X gtk_main(); // start processing window events X return 0; X@@ -809,9 +822,10 @@ X { X int err, flag, npid; X char procfile[20], *ppv; X+ char *cwd = new char[CWDBUFFERSIZE]; X cchar *pp, *pp2; X struct stat statb; X- X+ X Baddall = ZTX("Add All"); X Bamount = ZTX("Amount"); X Bapply = ZTX("Apply"); X@@ -880,7 +894,7 @@ X if (! err) Fxdgopen = 1; X err = system("ufraw-batch --version"); // check for ufraw-batch v.10.7 X if (! err) Fufraw = 1; X- X+ X if (! FinitThumbs) { // beg user if thumbnails never rebuilt X printf("rebuild thumbnails is needed \n"); X zmessage_help(mWin,"rebuild_thumbs", // v.11.01.1 X@@ -899,7 +913,7 @@ X search_index_file = zmalloc(200,"searchindexfile"); // search index file v.11.02 X *search_index_file = 0; X strncatv(search_index_file,199,get_zuserdir(),"/search_index",null); // /home/user/.fotoxx/search_index X- X+ X err = stat(tags_index_file,&statb); X if ( ! err) { // rename tags_index to search_index X rename(tags_index_file,search_index_file); // v.11.02 X@@ -932,7 +946,7 @@ X X *undo_files = 0; // setup undo filespec template X strncatv(undo_files,199,get_zuserdir(),"/",PIDstring,"_undo_nn",null); // /home/user/.fotoxx/pppppp_undo_nn X- X+ X editlog = pvlist_create(maxedits); // history log of image edits done X for (int ii = 0; ii < maxedits; ii++) // pre-load all pvlist entries v.10.2 X pvlist_append(editlog,"nothing"); X@@ -964,9 +978,9 @@ X mutex_init(&Fpixmap_lock,0); // setup lock for edit pixmaps X X TIFFSetWarningHandler(tiffwarninghandler); // intercept TIFF warning messages X- X+ X g_timeout_add(100,gtimefunc,0); // start periodic function (100 ms) v.11.03 X- X+ X if (curr_file) { X ppv = realpath(curr_file,0); // add cwd if needed v.10.7 X if (ppv) { X@@ -975,7 +989,7 @@ X free(ppv); X } X } X- X+ X if (curr_file) { X err = f_open(curr_file,1); // open initial file X if (err) { X@@ -984,9 +998,9 @@ X curr_file = 0; X } X } X- X+ X if (! curr_file) { // set curr. directory anyway v.11.01 X- ppv = get_current_dir_name(); X+ ppv = getcwd(cwd, CWDBUFFERSIZE); //get_current_dir_name(); X curr_dirk = strdupz(ppv,0,"curr_dirk"); X free(ppv); X err = chdir(curr_dirk); X@@ -1013,7 +1027,7 @@ X } X X update_statusbar(); // update every cycle v.11.03 X- X+ X if (Fslideshow) slideshow_next("timer"); // show next image if time is up X X if (Ffuncbusy && ! fbusy) { // function busy and default cursor v.10.12 X@@ -1028,7 +1042,7 @@ X if (zdedit) zdialog_set_cursor(zdedit,busycursor); // and also for dialog box X } X } X- X+ X if (! Ffuncbusy && fbusy) { // no function busy X if (fbusy == 2) { // if hourglass cursor X gdk_window_set_cursor(mWin->window,0); // restore normal cursors v.10.12 X@@ -1036,13 +1050,13 @@ X } X fbusy = 0; // reset toggle X } X- X+ X if (threadmessage && ! zdmessage) // display message in behalf of thread process X zdmessage = zmessage_post(mWin,threadmessage); // (avoid use of GTK in threads) v.11.03 X X if (zdmessage && ! threadmessage) X zdialog_free(zdmessage); X- X+ X if (zdmessage && zdmessage->sentinel != zdsentinel) { X zdmessage = 0; X threadmessage = 0; X@@ -1063,9 +1077,9 @@ X char text1[300], text2[100]; X int ii, ww, hh, scale, bpc, done; X double file_MB = 1.0 / mega * curr_file_size; X- X+ X *text1 = *text2 = 0; X- X+ X time2 = get_seconds(); // compute process cpu load v.11.03 X X if (time2 - time1 > 0.5) { // reduce jitter X@@ -1076,9 +1090,9 @@ X } X X sprintf(text1,"CPU %03.0f%c",cpuload,'%'); // CPU 023% X- X+ X if (! curr_file) return; X- X+ X if (E3pxm16) { X ww = E3ww; X hh = E3hh; X@@ -1104,17 +1118,17 @@ X sprintf(text2," %d%c",scale,'%'); X strcat(text1,text2); X X- if (Pundo) // edit undo stack depth X+ if (Pundo) // edit undo stack depth X { X snprintf(text2,99," edits: %d",Pundo); X strcat(text1,text2); X } X- X+ X if (Fmenulock) strcat(text1," menu locked"); X if (Factivearea) strcat(text1," area active"); // v.11.01 X- X+ X if (SB_goal) { // progress monitor v.9.6 X- for (ii = done = 0; ii < 8; ii++) X+ for (ii = done = 0; ii < 8; ii++) X done += SB_done[ii]; // counter per thread v.11.03 X done = 100.0 * done / SB_goal; X snprintf(text2,99," progress %d%c",done,'%'); X@@ -1124,7 +1138,7 @@ X strcat(text1," "); // application text v.10.7 X strcat(text1,SB_text); X stbar_message(STbar,text1); X- X+ X return; X } X X@@ -1188,9 +1202,9 @@ X int px2, py2, ww2, hh2, dx, dy; X uint16 *pix2, *pix3; X uint8 *pxm8area; X- X+ X if (! Dpxm16) zappcrash("mwpaint3() no Dpxm16"); // v.10.12 X- X+ X px2 = px3 - Iorgx; // map modified area into Dpxm16 X py2 = py3 - Iorgy; X ww2 = ww3; X@@ -1228,7 +1242,7 @@ X py2 = py2 * Mscale - 1; X ww2 = ww2 * Mscale + 1 / Mscale + 2; X hh2 = hh2 * Mscale + 1 / Mscale + 2; X- X+ X if (px2 < 0) px2 = 0; // stay within image edge X if (py2 < 0) py2 = 0; X if (px2 + ww2 > dww) ww2 = dww - px2; X@@ -1272,7 +1286,7 @@ X Wrepaint++; // cannot, come back later X return 1; X } X- X+ X if (Irefresh) { // image was updated v.10.10.2 X refresh++; X Irefresh = 0; X@@ -1280,7 +1294,7 @@ X X if (Dww != pdww || Dhh != pdhh) { // window size changed X refresh++; // image refresh needed X- pdww = Dww; X+ pdww = Dww; X pdhh = Dhh; X } X X@@ -1302,7 +1316,7 @@ X zoomx = zoomy = 0; X } X else Mscale = Fzoom; // scale to Fzoom level X- X+ X if (Mscale != pscale) refresh++; // scale changed, image refresh needed X X if (Mscale > pscale) { // zoom increased X@@ -1310,7 +1324,7 @@ X Iorgy += ihh * 0.5 * (1.0 - pscale / Mscale); X } X pscale = Mscale; X- X+ X iww = Dww / Mscale; // image space fitting in window X if (iww > Iww) iww = Iww; X ihh = Dhh / Mscale; X@@ -1349,18 +1363,18 @@ X Dorgy = 0.5 * (Dhh - Ihh * Mscale); X } X else Dorgy = 0; X- X+ X if (Iorgx + iww > Iww) Iorgx = Iww - iww; // set limits X if (Iorgy + ihh > Ihh) Iorgy = Ihh - ihh; X if (Iorgx < 0) Iorgx = 0; X if (Iorgy < 0) Iorgy = 0; X- X+ X if (Iorgx != piorgx || Iorgy != piorgy) { // image origin changed X refresh++; // image refresh needed X piorgx = Iorgx; X piorgy = Iorgy; X } X- X+ X if (refresh) // image refresh is needed v.10.10.2 X { X if (E3pxm16) { // edit in progress X@@ -1376,7 +1390,7 @@ X Dpxm8 = PXM_rescale(pxmtemp,dww,dhh); X PXM_free(pxmtemp); X } X- X+ X wrect.x = wrect.y = 0; // stop flicker X wrect.width = Dww; X wrect.height = Dhh; X@@ -1448,12 +1462,12 @@ X } X Mxdown = Mydown = Mxdrag = Mydrag = Mdrag = Mbutton = 0; // forget buttons and drag X } X- X+ X if (type == GDK_MOTION_NOTIFY && Mdrag) { // drag underway X Mxdrag = Mxposn; X Mydrag = Myposn; X } X- X+ X if (mouseCBfunc) { // pass to handler function X if (mbusy) return; X mbusy++; // stop re-entrance v.10.8 X@@ -1490,7 +1504,7 @@ X if (xpos < 0) xpos = 0; // if outside image put at edge X if (ypos < 0) ypos = 0; X X- if (E3pxm16) { X+ if (E3pxm16) { X if (xpos >= E3ww) xpos = E3ww-1; X if (ypos >= E3hh) ypos = E3hh-1; X } X@@ -1498,7 +1512,7 @@ X if (xpos >= Fww) xpos = Fww-1; X if (ypos >= Fhh) ypos = Fhh-1; X } X- X+ X return; X } X X@@ -1522,17 +1536,17 @@ X { X int angle = 0; X PXM *pxm; X- X+ X KBkey = event->keyval; X X if (KBcapture) return 1; // let function handle it X X if (KBkey == 65507) KBcontrolkey = 0; // Ctrk key released X- X+ X if (KBcontrolkey) { X if (KBkey == GDK_s) m_save(0,0); // Ctrl-* shortcuts X- if (KBkey == GDK_S) m_saveas(0,0); X- if (KBkey == GDK_q) m_quit(0,0); X+ if (KBkey == GDK_S) m_saveas(0,0); X+ if (KBkey == GDK_q) m_quit(0,0); X if (KBkey == GDK_Q) m_quit(0,0); X } X X@@ -1557,7 +1571,7 @@ X if (KBkey == GDK_minus) m_zoom(null, (char *) "-"); X if (KBkey == GDK_KP_Add) m_zoom(null, (char *) "+"); // keypad + X if (KBkey == GDK_KP_Subtract) m_zoom(null, (char *) "-"); // keypad - X- X+ X if (KBkey == GDK_Z) m_zoom(null, (char *) "Z"); // Z key: zoom to 100% X if (KBkey == GDK_z) m_zoom(null, (char *) "Z"); X X@@ -1591,10 +1605,10 @@ X else zmalloc_log(0); X zmalloc_report(); // v.10.8 X } X- X+ X if (KBkey == GDK_T || KBkey == GDK_t) m_trim(0,0); // Key T = Trim function v.10.3.1 X if (KBkey == GDK_B || KBkey == GDK_b) m_tune(0,0); // Key B = brightness/color v.10.3.1 X- X+ X KBkey = 0; X return 1; X } X@@ -1607,15 +1621,15 @@ X void paint_gridlines() // revised v.10.10.2 X { X int px, py, stepx, stepy; X- X+ X if (! Fpxm8) return; // no image X- X+ X stepx = gridspace[0]; // space between grid lines X stepy = gridspace[1]; X X if (gridcount[0]) stepx = dww / (1 + gridcount[0]); // if line counts specified, v.10.11 X if (gridcount[1]) stepy = dhh / ( 1 + gridcount[1]); // set spacing accordingly X- X+ X gdk_gc_set_foreground(gdkgc,&white); // white lines X X if (Fgrid[0]) X@@ -1629,14 +1643,14 @@ X gdk_gc_set_foreground(gdkgc,&black); // adjacent black lines X fg_color = black; // v.10.12 X X- if (Fgrid[0]) X+ if (Fgrid[0]) X for (px = Dorgx+stepx+1; px < Dorgx+dww; px += stepx) X gdk_draw_line(drWin->window,gdkgc,px,Dorgy,px,Dorgy+dhh); X X if (Fgrid[1]) X for (py = Dorgy+stepy+1; py < Dorgy+dhh; py += stepy) X gdk_draw_line(drWin->window,gdkgc,Dorgx,py,Dorgx+dww,py); X- X+ X return; X } X X@@ -1655,7 +1669,7 @@ X if (arg == 2 || arg == 3) // erase old lines X for (ii = 0; ii < Nptoplines; ii++) X erase_line(ptoplinex1[ii],ptopliney1[ii],ptoplinex2[ii],ptopliney2[ii]); X- X+ X if (arg == 1 || arg == 3) // draw new lines X for (ii = 0; ii < Ntoplines; ii++) X draw_line(toplinex1[ii],topliney1[ii],toplinex2[ii],topliney2[ii]); X@@ -1700,7 +1714,7 @@ X gdk_draw_arc(drWin->window,gdkgc,0,arcx,arcy,arcw,arch,0,64*360); // draw arc X gdk_gc_set_function(gdkgc,GDK_COPY); X } X- X+ X if (Ftoparc && (arg == 1 || arg == 3)) { // draw new arc X arcx = int((toparcx-Iorgx) * Mscale + Dorgx + 0.5); // image to window space X arcy = int((toparcy-Iorgy) * Mscale + Dorgy + 0.5); X@@ -1716,7 +1730,7 @@ X Ftoparc = ptoparc = 0; // forget arcs X return; X } X- X+ X ptoparc = Ftoparc; // save for future erase X ptoparcx = toparcx; X ptoparcy = toparcy; X@@ -1735,14 +1749,14 @@ X { X void draw_line_pixel(double pxm, double pym); X X- double x1, y1, x2, y2; X+ double x1, y1, x2, y2; X double pxm, pym, slope; X- X+ X x1 = Mscale * (ix1-Iorgx); // image to window space X y1 = Mscale * (iy1-Iorgy); X x2 = Mscale * (ix2-Iorgx); X y2 = Mscale * (iy2-Iorgy); X- X+ X if (abs(y2 - y1) > abs(x2 - x1)) { X slope = 1.0 * (x2 - x1) / (y2 - y1); X if (y2 > y1) { X@@ -1784,18 +1798,18 @@ X { X int pxn, pyn; X static int flip = 0; X- X+ X pxn = int(px); X pyn = int(py); X- X+ X if (pxn < 0 || pxn > dww-1) return; X if (pyn < 0 || pyn > dhh-1) return; X- X+ X if (++flip > 4) flip = -5; // black/white line v.10.10 X if (flip < 0) gdk_gc_set_foreground(gdkgc,&black); X else gdk_gc_set_foreground(gdkgc,&white); X gdk_draw_point(drWin->window, gdkgc, pxn + Dorgx, pyn + Dorgy); X- X+ X return; X } X X@@ -1806,16 +1820,16 @@ X { X void erase_line_pixel(double pxm, double pym); X X- double x1, y1, x2, y2; X+ double x1, y1, x2, y2; X double pxm, pym, slope; X- X+ X if (! Dpxm8) zappcrash("Dpxm8 = 0"); // v.10.3 X X x1 = Mscale * (ix1-Iorgx); X y1 = Mscale * (iy1-Iorgy); X x2 = Mscale * (ix2-Iorgx); X y2 = Mscale * (iy2-Iorgy); X- X+ X if (abs(y2 - y1) > abs(x2 - x1)) { X slope = 1.0 * (x2 - x1) / (y2 - y1); X if (y2 > y1) { X@@ -1853,16 +1867,16 @@ X void erase_line_pixel(double px, double py) X { X int pxn, pyn; X- X+ X pxn = int(px); X pyn = int(py); X- X+ X if (pxn < 0 || pxn > dww-1) return; X if (pyn < 0 || pyn > dhh-1) return; X X uint8 *pixel = (uint8 *) Dpxm8->bmp + (pyn * dww + pxn) * 3; X- gdk_draw_rgb_image(drWin->window, gdkgc, pxn + Dorgx, pyn + Dorgy, X- 1, 1, NODITHER, pixel, dww * 3); X+ gdk_draw_rgb_image(drWin->window, gdkgc, pxn + Dorgx, pyn + Dorgy, X+ 1, 1, NODITHER, pixel, dww * 3); X return; X } X X@@ -1873,7 +1887,7 @@ X { X int qx, qy; X static int pqx, pqy; X- X+ X qx = Mscale * (px-Iorgx) + 0.5; // image to window space X qy = Mscale * (py-Iorgy) + 0.5; X X@@ -1881,7 +1895,7 @@ X X pqx = qx; X pqy = qy; X- X+ X if (color != &fg_color) { X fg_color = *color; X gdk_gc_set_foreground(gdkgc,&fg_color); X@@ -1933,7 +1947,7 @@ X int spccurve_adjust(void *, GdkEventButton *event, spcdat *); // curve editing function X int spccurve_draw(void *, void *, spcdat *); // curve drawing function X int spccurve_generate(spcdat *, int spc); // generate data from anchor points X-inline X+inline X double spccurve_yval(spcdat *, int spc, double xval); // get curve y-value X int spccurve_load(spcdat *sd); // load curve from a file X int spccurve_save(spcdat *sd); // save curve to a file X@@ -1954,11 +1968,11 @@ X X gtk_widget_add_events(sd->drawarea,GDK_BUTTON_PRESS_MASK); // connect mouse events to drawing area X gtk_widget_add_events(sd->drawarea,GDK_BUTTON_RELEASE_MASK); X- gtk_widget_add_events(sd->drawarea,GDK_BUTTON1_MOTION_MASK); X+ gtk_widget_add_events(sd->drawarea,GDK_BUTTON1_MOTION_MASK); X G_SIGNAL(sd->drawarea,"motion-notify-event",spccurve_adjust,sd) X G_SIGNAL(sd->drawarea,"button-press-event",spccurve_adjust,sd) X G_SIGNAL(sd->drawarea,"expose-event",spccurve_draw,sd) X- X+ X return sd; X } X X@@ -1973,7 +1987,7 @@ X int minspc, minap; X double mxval, myval, cxval, cyval; X double dist2, mindist2 = 0; X- X+ X mx = int(event->x); // mouse position in drawing area X my = int(event->y); X evtype = event->type; X@@ -1990,17 +2004,17 @@ X Fdrag = 0; X return 0; X } X- X+ X ww = sd->drawarea->allocation.width; // drawing area size X hh = sd->drawarea->allocation.height; X- X+ X if (mx < 0) mx = 0; // limit edge excursions X if (mx > ww) mx = ww; X if (my < 0) my = 0; X if (my > hh) my = hh; X- X+ X if (evtype == GDK_BUTTON_PRESS) Fdrag = 0; // left or right click X- X+ X if (Fdrag) // continuation of drag X { X if (sd->vert[spc]) { X@@ -2014,9 +2028,9 @@ X X if (ap < sd->nap[spc]-1 && sd->apx[spc][ap+1] - mxval < 0.05) // disallow < 0.05 from next X return 0; X- if (ap > 0 && mxval - sd->apx[spc][ap-1] < 0.05) return 0; // or prior anchor point X+ if (ap > 0 && mxval - sd->apx[spc][ap-1] < 0.05) return 0; // or prior anchor point X } X- X+ X else // mouse click or new drag begin X { X minspc = minap = -1; // find closest curve/anchor point X@@ -2037,7 +2051,7 @@ X { X cxval = sd->apx[spc][ap]; X cyval = sd->apy[spc][ap]; X- dist2 = (mxval-cxval)*(mxval-cxval) X+ dist2 = (mxval-cxval)*(mxval-cxval) X + (myval-cyval)*(myval-cyval); X if (dist2 < mindist2) { X mindist2 = dist2; // remember closest anchor point X@@ -2051,7 +2065,7 @@ X spc = minspc; X ap = minap; X } X- X+ X if (evtype == GDK_BUTTON_PRESS && button == 3) // right click, remove anchor point X { X if (sqrt(mindist2) > 0.05) return 0; // not close enough X@@ -2082,9 +2096,9 @@ X { // move this anchor point to mouse X if (ap < sd->nap[spc]-1 && sd->apx[spc][ap+1] - mxval < 0.05) X return 0; // disallow < 0.05 from next X- if (ap > 0 && mxval - sd->apx[spc][ap-1] < 0.05) return 0; // or prior anchor point X+ if (ap > 0 && mxval - sd->apx[spc][ap-1] < 0.05) return 0; // or prior anchor point X } X- X+ X else // none close, add new anchor point X { X minspc = -1; // find closest curve to mouse X@@ -2149,7 +2163,7 @@ X spccurve_generate(sd,spc); // regenerate data for modified curve X spccurve_draw(0,0,sd); // regen and redraw all curves X sd->spcfunc(spc); // call user function X- X+ X if (evtype == GDK_MOTION_NOTIFY) Fdrag = 1; // remember drag is underway X return 0; X } X@@ -2162,7 +2176,7 @@ X { X int ww, hh, px, py, qx, qy, spc, ap; X double xval, yval; X- X+ X ww = sd->drawarea->allocation.width; // drawing area size X hh = sd->drawarea->allocation.height; X if (ww < 50 || hh < 50) return 0; X@@ -2170,7 +2184,7 @@ X gdk_window_clear(sd->drawarea->window); // clear window X gdk_gc_set_foreground(gdkgc,&black); X fg_color = black; X- X+ X for (spc = 0; spc < sd->Nspc; spc++) X { X if (sd->vert[spc]) // vert. curve X@@ -2182,7 +2196,7 @@ X px = ww * yval + 0.49; // "almost" round - erratic floating point X gdk_draw_point(sd->drawarea->window,gdkgc,px,py); // causes "bumps" in a flat curve X } X- X+ X for (ap = 0; ap < sd->nap[spc]; ap++) // draw boxes at anchor points X { X xval = sd->apx[spc][ap]; X@@ -2206,7 +2220,7 @@ X py = hh - hh * yval + 0.49; // almost round - erratic FP in Intel CPUs X gdk_draw_point(sd->drawarea->window,gdkgc,px,py); // causes "bumps" in a flat curve X } X- X+ X for (ap = 0; ap < sd->nap[spc]; ap++) // draw boxes at anchor points X { X xval = sd->apx[spc][ap]; X@@ -2259,10 +2273,10 @@ X { X int ii; X double x1, x2, y1, y2, y3; X- X+ X if (xval <= 0) return sd->yval[spc][0]; X if (xval >= 0.999) return sd->yval[spc][999]; X- X+ X x2 = 1000.0 * xval; X ii = int(x2); X x1 = ii; X@@ -2293,7 +2307,7 @@ X fid = fopen(pfile,"r"); X zfree(pfile); X if (! fid) goto fail; X- X+ X nn = fscanf(fid,"%d ",&Nspc); // no. of curves X if (nn != 1) goto fail; X if (Nspc < 1 || Nspc > 10) goto fail; X@@ -2306,7 +2320,7 @@ X if (vert[ii] < 0 || vert[ii] > 1) goto fail; X if (nap[ii] < 2 || nap[ii] > 50) goto fail; X X- for (jj = 0; jj < nap[ii]; jj++) // anchor point values X+ for (jj = 0; jj < nap[ii]; jj++) // anchor point values X { X nn = fscanf(fid,"%lf/%lf ",&apx[ii][jj],&apy[ii][jj]); X if (nn != 2) goto fail; X@@ -2314,16 +2328,16 @@ X if (apy[ii][jj] < 0 || apy[ii][jj] > 1) goto fail; X } X } X- X+ X fclose(fid); X- X+ X sd->Nspc = Nspc; // copy curve data to caller's arg X X for (ii = 0; ii < Nspc; ii++) X { X sd->vert[ii] = vert[ii]; X sd->nap[ii] = nap[ii]; X- X+ X for (jj = 0; jj < nap[ii]; jj++) X { X sd->apx[ii][jj] = apx[ii][jj]; X@@ -2333,11 +2347,11 @@ X X for (ii = 0; ii < Nspc; ii++) // generate curve data from anchor points X spccurve_generate(sd,ii); X- X+ X if (sd->drawarea) spccurve_draw(0,0,sd); // regen and redraw all curves X X return 1; X- X+ X fail: X if (fid) fclose(fid); X zmessageACK(mWin,ZTX("curve file is invalid")); X@@ -2374,17 +2388,17 @@ X fid = fopen(pfile,"w"); X zfree(pfile); X if (! fid) return 0; X- X+ X fprintf(fid,"%d \n",sd->Nspc); // no. of curves X X for (ii = 0; ii < sd->Nspc; ii++) // loop each curve X { X fprintf(fid,"%d %d \n",sd->vert[ii],sd->nap[ii]); // vertical flag, no. anchor points X- for (jj = 0; jj < sd->nap[ii]; jj++) // anchor point values X+ for (jj = 0; jj < sd->nap[ii]; jj++) // anchor point values X fprintf(fid,"%.4f/%.4f ",sd->apx[ii][jj],sd->apy[ii][jj]); X fprintf(fid,"\n"); X } X- X+ X fclose(fid); X return 0; X } X@@ -2425,10 +2439,12 @@ X X void m_gallery(GtkWidget *, cchar *) X { X+ char *cwd = new char[CWDBUFFERSIZE]; X+ X if (curr_file) X image_gallery(curr_file,"paint1",0,m_gallery2,mWin); // overlay main window v.10.9 X else { X- char *pp = get_current_dir_name(); X+ char *pp = getcwd(cwd, CWDBUFFERSIZE); //get_current_dir_name(); X if (pp) { X image_gallery(pp,"paint1",0,m_gallery2,mWin); // use current directory v.10.9 X free(pp); X@@ -2485,7 +2501,7 @@ X void m_previous(GtkWidget *, cchar *) X { X int ii, err; X- X+ X zfuncs::F1_help_topic = "open_previous_file"; X X for (ii = 1; ii < Nrecentfiles; ii++) // v.10.12 X@@ -2514,11 +2530,11 @@ X X if (! recentfiles[0]) return; X if (! menulock(1)) return; X- X+ X snprintf(filespec,199,"%s/recent_files",get_zuserdir()); // create file of recent files X fid = fopen(filespec,"w"); X if (! fid) return; X- X+ X for (ii = 0; ii < Nrecentfiles; ii++) X { X if (! recentfiles[ii]) continue; X@@ -2528,7 +2544,7 @@ X } X X fclose(fid); X- X+ X image_gallery(filespec,"initF",0,recentfile2,mWin); // generate gallery of recent files X image_gallery(recentfiles[0],"paint1"); // show new image gallery window X X@@ -2580,9 +2596,9 @@ X if (flock && Fmenulock) return 1; // v.10.5 X if (mod_keep()) return 2; // unsaved edits X X- if (filespec) X+ if (filespec) X file = strdupz(filespec,0,"curr_file"); // use passed filespec X- else X+ else X { // no passed file X file = zgetfile1(ZTX("Open Image File"),"open",curr_file); // dialog to get filespec X if (! file) return 3; // canceled X@@ -2604,11 +2620,11 @@ X Fpxm8 = temp8; // pixmap for current image X Fww = Fpxm8->ww; X Fhh = Fpxm8->hh; X- X+ X strcpy(curr_file_type,f_load_type); // set curr_file_xxx from f_load_xxx X curr_file_bpc = f_load_bpc; X curr_file_size = f_load_size; X- X+ X set_curr_file(file); // setup new current file v.10.9 X X zfree(file); X@@ -2708,21 +2724,21 @@ X // save (modified) image to same file - no confirmation of overwrite. X X void m_save(GtkWidget *, cchar *) X-{ X+{ X if (! curr_file) return; X X zfuncs::F1_help_topic = "save_file"; X- X+ X strcpy(jpeg_quality,def_jpeg_quality); // default jpeg save quality X X if (strEqu(curr_file_type,"other")) // if gif, bmp, etc. use jpg v.11.03 X strcpy(curr_file_type,"jpg"); X X f_save(curr_file,curr_file_type,curr_file_bpc); // save file X- X+ X strcpy(curr_file_type,f_save_type); // update curr_file_xxx from f_save_xxx X curr_file_size = f_save_size; X- X+ X return; X } X X@@ -2752,7 +2768,7 @@ X X fdialog = gtk_dialog_new_with_buttons(ZTX("Save File"), // build file save dialog X MWIN, GTK_DIALOG_MODAL, X- GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, X+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, X GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, null); X gtk_window_set_default_size(GTK_WINDOW(fdialog),600,500); X X@@ -2764,7 +2780,7 @@ X gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(saveas_fchooser),curr_file); X char *fname = strrchr(curr_file,'/') + 1; X gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(saveas_fchooser),fname); X- X+ X hbox = gtk_hbox_new(0,0); X gtk_container_add(GTK_CONTAINER(GTK_DIALOG(fdialog)->vbox),hbox); X gtk_box_set_child_packing(GTK_BOX(GTK_DIALOG(fdialog)->vbox),hbox,0,0,10,GTK_PACK_END); X@@ -2785,7 +2801,7 @@ X gtk_box_pack_start(GTK_BOX(hbox),jqlab,0,0,0); X gtk_box_pack_start(GTK_BOX(hbox),jqval,0,0,3); X gtk_box_pack_end(GTK_BOX(hbox),newvers,0,0,10); // [x] new version X- X+ X G_SIGNAL(tiff8,"pressed",saveas_radiobutt,0) // connect file type radio buttons X G_SIGNAL(tiff16,"pressed",saveas_radiobutt,1) // to handler function X G_SIGNAL(png,"pressed",saveas_radiobutt,2) X@@ -2794,7 +2810,7 @@ X X gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(jpeg),1); // set default file type = jpeg X gtk_entry_set_text(GTK_ENTRY(jqval),def_jpeg_quality); // default jpeg save quality X- X+ X if (strEqu(curr_file_type,"png")) // default matches file type X gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(png),1); // if png or tiff X if (strEqu(curr_file_type,"tiff")) X@@ -2837,7 +2853,7 @@ X } X sprintf(jpeg_quality,"%d",ii); X } X- X+ X pext = strrchr(outfile,'/'); // locate file .ext X if (pext) pext = strrchr(pext,'.'); X if (pext && ! strstr(exts,pext)) pext = 0; // keep .ext and append new v.10.12.1 X@@ -2929,7 +2945,7 @@ X X void saveas_kbkey(void *, GdkEventKey *event) // v.10.5 X { X- if (event->keyval == GDK_F1) X+ if (event->keyval == GDK_F1) X showz_userguide(zfuncs::F1_help_topic); X return; X } X@@ -2948,7 +2964,7 @@ X char *prev_file = 0; X X zfuncs::F1_help_topic = "create"; X- X+ X if (mod_keep()) return; // unsaved edits X if (! menulock(1)) return; // lock menus X X@@ -2956,7 +2972,7 @@ X X // width [____] height [____] (pixels) X // color [____] X- X+ X zd = zdialog_new(ZTX("Create Blank Image"),mWin,Bdone,Bcancel,null); X zdialog_add_widget(zd,"hbox","hbz","dialog",0,"space=5"); X zdialog_add_widget(zd,"label","space","hbz",0,"space=3"); X@@ -2971,7 +2987,7 @@ X zdialog_add_widget(zd,"label","space","hbc",0,"space=3"); X zdialog_add_widget(zd,"label","labc","hbc",ZTX("color")); X zdialog_add_widget(zd,"colorbutt","color","hbc","200|200|200"); X- X+ X create_dialog_event(zd,"init"); X zdialog_run(zd,create_dialog_event); X zstat = zdialog_wait(zd); X@@ -3006,7 +3022,7 @@ X if (pp) green = atoi(pp); X pp = strField(color,"|",3); X if (pp) blue = atoi(pp); X- X+ X mutex_lock(&Fpixmap_lock); X X PXM_free(Fpxm8); X@@ -3031,7 +3047,7 @@ X X set_curr_file(file); X zfree(file); X- X+ X Fzoom = 0; // scale to window X mwpaint2(); // repaint window X return 0; X@@ -3054,7 +3070,7 @@ X GFile *gfile = 0; X cchar *gerrmess = ZTX("Linux standard trash is not supported. \n" X "Desktop trash folder will be created."); X- X+ X zfuncs::F1_help_topic = "trash"; // v.10.8 X X if (! curr_file) return; // nothing to trash X@@ -3074,7 +3090,7 @@ X trstat.st_mode |= S_IWUSR; X chmod(curr_file,trstat.st_mode); X } X- X+ X if (trashworks) // try Linux standard trash X { X gfile = g_file_new_for_path(curr_file); X@@ -3113,7 +3129,7 @@ X return; X } X } X- X+ X delete_search_index(curr_file); // delete in search index file X image_gallery(curr_file,"delete"); // delete in gallery list v.10.9.1 X image_gallery(0,"paint2"); // refresh gallery window if active X@@ -3135,11 +3151,11 @@ X void m_rename(GtkWidget *, cchar *) X { X int rename_dialog_event(zdialog *zd, cchar *event); X- X+ X char *pdir, *pfile, *pext; X X if (! curr_file) return; X- X+ X zfuncs::F1_help_topic = "rename"; // v.10.8 X X if (! zdrename) // restart dialog X@@ -3182,12 +3198,12 @@ X char *pp, *pdir, *pfile, *pext, *pnew, *pold; X int nseq, digits, ccp, ccn, ccx, err; X struct stat statb; X- X+ X if (zd->zstat) { // complete X zdialog_free(zdrename); // kill dialog X return 0; X } X- X+ X if (strEqu(event,"Bold")) // reset to current file name X zdialog_stuff(zd,"Enew",rename_old); X X@@ -3232,14 +3248,14 @@ X strncpy(pnew,curr_file,ccp); // /directories/file.ext X strcpy(pnew+ccp,rename_new); X if (ccx) strcpy(pnew+ccp+ccn,pext); X- X+ X err = stat(pnew,&statb); // check if new name exists X if (! err) { X zmessageACK(mWin,ZTX("The target file already exists")); X zfree(pnew); X return 0; X } X- X+ X snprintf(command,ccc,"cp -p \"%s\" \"%s\"",curr_file,pnew); // copy to new file -p v.10.3 X err = system(command); X if (err) { X@@ -3257,7 +3273,7 @@ X pold = strdupz(curr_file,0,"curr_file"); // save file name to be deleted X delete_search_index(pold); // delete in search index v.9.7 X err = remove(pold); // delete file v.11.03 X- X+ X image_gallery(pold,"delete"); // update gallery v.10.9.1 X image_gallery(pnew,"insert"); X image_gallery(0,"paint2"); // refresh gallery window if active X@@ -3267,7 +3283,7 @@ X X m_next(0,0); // move to curr_file + 1 X } X- X+ X return 0; X } X X@@ -3282,7 +3298,7 @@ X void m_batchrename(GtkWidget *, cchar *) // new v.9.7 X { X int batchrename_dialog_event(zdialog *zd, cchar *event); X- X+ X zdialog *zd; X X if (zdrename) return; // interactive rename is active X@@ -3308,10 +3324,10 @@ X X batchrename_filelist = 0; X batchrename_filecount = 0; X- X+ X zdialog_run(zd,batchrename_dialog_event); // run dialog X zdialog_wait(zd); // wait for completion X- X+ X zdialog_free(zd); X menulock(0); X return; X@@ -3330,11 +3346,11 @@ X char *pdir, *pfile, *pext; X cchar *errmess = ZTX("base name / sequence / increment not reasonable"); X struct stat statb; X- X+ X if (strEqu(event,"files")) // select images to rename X { X if (flist) { // free prior list X- for (ii = 0; flist[ii]; ii++) X+ for (ii = 0; flist[ii]; ii++) X zfree(flist[ii]); X zfree(flist); X } X@@ -3350,7 +3366,7 @@ X sprintf(countmess,"%d files selected",batchrename_filecount); X zdialog_stuff(zd,"labcount",countmess); X } X- X+ X if (! zd->zstat) return 0; // dialog active X X if (zd->zstat != 1) goto cleanup; // dialog canceled X@@ -3365,7 +3381,7 @@ X zmessageACK(mWin,errmess); X return 0; X } X- X+ X write_popup_text("open","Renaming files",500,200,mWin); // status monitor popup window v.10.3 X X for (ii = 0; flist[ii]; ii++) X@@ -3430,7 +3446,7 @@ X cleanup: X X if (batchrename_filecount) { X- for (ii = 0; flist[ii]; ii++) X+ for (ii = 0; flist[ii]; ii++) X zfree(flist[ii]); X zfree(flist); X } X@@ -3440,7 +3456,7 @@ X X X /**************************************************************************/ X- X+ X // open a previously saved collection of image files, X // make this the current file list and open thumbnail gallery X X@@ -3477,13 +3493,13 @@ X X flist = image_gallery_getfiles(0,mWin); // get collection file list from user X if (! flist) return; X- X+ X pp = zgetfile1(ZTX("save collection"),"save",collections_dirk); // get file to save collection X if (! pp) goto cleanup; X X fid = fopen(pp,"w"); // open collection file X if (! fid) goto cleanup; X- X+ X for (int ii = 0; flist[ii]; ii++) // write collection file list X fprintf(fid,"%s\n",flist[ii]); X X@@ -3511,21 +3527,21 @@ X PXM *printimage, *pxmtemp; X X zfuncs::F1_help_topic = "print"; X- X+ X if (! curr_file) return; // no image file X- X+ X printfile = strdupz(get_zuserdir(),20,"printfile"); // make temp print file: X strcat(printfile,"/printfile.tif"); // ~/.fotoxx/printfile.tif v.11.03 X- X+ X if (Fpxm16) printimage = PXM_convbpc(Fpxm16); X else printimage = PXM_copy(Fpxm8); X- X+ X pxmtemp = print_addgrid(printimage); // add grid lines if wanted v.11.01 X if (pxmtemp) { X PXM_free(printimage); X printimage = pxmtemp; X } X- X+ X err = PXBwrite(printimage,printfile); X PXM_free(printimage); X X@@ -3533,7 +3549,7 @@ X zfree(printfile); // v.10.3 X return; X } X- X+ X print_imagefile(printfile); // GTK print utility in zfuncs.cc X zfree(printfile); X return; X@@ -3547,25 +3563,25 @@ X PXM *temp8; X uint8 *pixel; X int px, py, ww, hh, row, stepx, stepy; X- X+ X if (! Fgrid[0] && ! Fgrid[1]) return 0; X X temp8 = f_load(curr_file,8); X if (! temp8) return 0; X- X+ X ww = temp8->ww; X hh = temp8->hh; X row = ww * 3; X X stepx = gridspace[0]; // space between grid lines X stepy = gridspace[1]; X- X+ X stepx = stepx / Mscale; // window scale to image scale X stepy = stepy / Mscale; X- X+ X if (gridcount[0]) stepx = ww / (1 + gridcount[0]); // if line counts specified, X if (gridcount[1]) stepy = hh / ( 1 + gridcount[1]); // set spacing accordingly X- X+ X if (Fgrid[0]) { X for (px = stepx; px < ww-1; px += stepx) X for (py = 0; py < hh; py++) X@@ -3626,13 +3642,13 @@ X char zoom; X double scalew, scaleh, fitscale; X double scales[11] = { 0.125, 0.176, 0.25, 0.354, 0.5, 0.71, 1.0, 1.41, 2.0, 2.83, 4.0 }; X- X+ X if (strnEqu(menu,"Zoom",4)) zoom = menu[4]; // get + or - X else zoom = *menu; X- X+ X Dww = drWin->allocation.width; // drawing window size X Dhh = drWin->allocation.height; X- X+ X if (E3pxm16) { // bugfix X iww = E3ww; X ihh = E3hh; X@@ -3649,7 +3665,7 @@ X else fitscale = scaleh; X } X else fitscale = 1.0; // if image < window use 100% X- X+ X if (zoom == '+') { // zoom bigger X if (! Fzoom) Fzoom = fitscale / 1.2; X Fzoom = Fzoom * sqrt(2.0); // new scale: 41% bigger X@@ -3666,9 +3682,9 @@ X if (Fzoom != 0) Fzoom = 0; // toggle 100% and fit window X else Fzoom = 1; X } X- X+ X if (! Fzoom) zoomx = zoomy = 0; // no req. zoom center X- X+ X mwpaint2(); // refresh window X return; X } X@@ -3684,7 +3700,7 @@ X int red, green, blue; X int row, col, row1, row2; X int ww = 800, hh = 500; X- X+ X if (mod_keep()) return; // unsaved edits X if (! menulock(1)) return; X X@@ -3706,7 +3722,7 @@ X row1 = 4 * red + 2 * green + blue; // row 0 to 7 X row1 = row1 * hh / 8; // stripe, 1/8 of image X row2 = row1 + hh / 8; X- X+ X for (row = row1; row < row2; row++) X for (col = 0; col < ww; col++) X { X@@ -3739,7 +3755,7 @@ X zfuncs::F1_help_topic = "monitor_gamma"; X X showz_html(fgammachart); // display gamma chart from web X- X+ X zd = zdialog_new(ZTX("Monitor Gamma"),mWin,Bdone,null); X zdialog_add_widget(zd,"hbox","hb1","dialog"); X zdialog_add_widget(zd,"vbox","vb1","hb1",0,"homog|space=5"); X@@ -3752,7 +3768,7 @@ X zdialog_add_widget(zd,"hscale","green","vb2","0.6|1.4|0.02|1.0","expand"); X zdialog_add_widget(zd,"hscale","blue","vb2","0.6|1.4|0.02|1.0","expand"); X zdialog_add_widget(zd,"hscale","all","vb2","0.6|1.4|0.02|1.0","expand"); X- X+ X zdialog_resize(zd,200,0); X zdialog_run(zd,mongamma_event); X X@@ -3771,7 +3787,7 @@ X zdialog_free(zd); X return 0; X } X- X+ X if (strEqu(event,"all")) { X zdialog_fetch(zd,"all",allgamma); X zdialog_stuff(zd,"red",allgamma); X@@ -3779,7 +3795,7 @@ X zdialog_stuff(zd,"blue",allgamma); X sprintf(command,"xgamma -quiet -gamma %.2f",allgamma); X } X- X+ X else { X zdialog_fetch(zd,"red",redgamma); X zdialog_fetch(zd,"green",greengamma); X@@ -3787,7 +3803,7 @@ X sprintf(command,"xgamma -quiet -rgamma %.2f -ggamma %.2f -bgamma %.2f", X redgamma, greengamma, bluegamma); X } X- X+ X err = system(command); X if (err) zmessageACK(mWin,"error: %s",wstrerror(err)); X X@@ -3835,7 +3851,7 @@ X G_SIGNAL(winhistoB,"expose-event",histogram_paint,0) X X gtk_widget_show_all(winhisto); X- X+ X return; X } X X@@ -3853,7 +3869,7 @@ X uint8 *pix8; X uint16 *pix16; X double bright; X- X+ X if (! winhisto) return; X if (! Dpxm8) return; X X@@ -3864,7 +3880,7 @@ X brdist[bin] = 0; X X mutex_lock(&Fpixmap_lock); X- X+ X if (Factivearea && E3pxm16) // compute brightness distribution v.11.02 X { // for selected area being edited X for (int ii = 0; ii < Fww * Fhh; ii++) X@@ -3877,8 +3893,8 @@ X brdist[int(bright / 256 * nbins)]++; // 0 to nbins X } X } X- X- else X+ X+ else X { X for (py = 0; py < dhh; py++) // compute brightness distribution X for (px = 0; px < dww; px++) // for image in visible window X@@ -3957,7 +3973,7 @@ X ww = ww / 2 - 20; X hh = hh - 50; X gdk_window_move_resize(mWin->window,ww+20,10,ww,hh); X- X+ X snprintf(command,ccc,"fotoxx -c %d %d -l %s",ww,hh,zfuncs::zlanguage); X if (curr_file) strncatv(command,ccc," \"",curr_file,"\"",null); X strcat(command," &"); X@@ -3985,7 +4001,7 @@ X zdialog *zd; X int zstat, secs; X cchar *esc_message = ZTX("press ESC to exit"); X- X+ X zfuncs::F1_help_topic = "slide_show"; // v.10.8 X X if (! Fslideshow) // start slide show X@@ -4004,7 +4020,7 @@ X X if (ss_interval < 9999) X zdialog_stuff(zd,"secs",ss_interval); X- X+ X zdialog_cb_app(zd,"trans",ZTX("arrow keys")); // put options into combo box X zdialog_cb_app(zd,"trans",ZTX("instant")); X zdialog_cb_app(zd,"trans",ZTX("fade-in")); X@@ -4049,7 +4065,7 @@ X ss_pxmold = PXM_make(ss_ww,ss_hh,8); // make 3 screen-size pixmaps X ss_pxmnew = PXM_make(ss_ww,ss_hh,8); X ss_pxmmix = PXM_make(ss_ww,ss_hh,8); X- X+ X ss_newfile = strdupz(curr_file); // start with current image X ss_oldfile = 0; X X@@ -4071,7 +4087,7 @@ X gtk_widget_show_all(GTK_WIDGET(mMbar)); X gtk_widget_show_all(GTK_WIDGET(mTbar)); X gtk_widget_show_all(GTK_WIDGET(STbar)); X- X+ X if (ss_newfile) zfree(ss_newfile); // free memory X if (ss_oldfile) zfree(ss_oldfile); X ss_newfile = ss_oldfile = 0; X@@ -4084,7 +4100,7 @@ X X Fblowup = Fslideshow; X Fzoom = 0; // fit image to window X- mwpaint2(); X+ mwpaint2(); X return; X } X X@@ -4108,7 +4124,7 @@ X double secs; X char *pp = 0; X int Fkey, rnum; X- X+ X if (ss_busy) return; // come back later X X if (ss_escape) { X@@ -4123,7 +4139,7 @@ X Fkey = 0; X } X else Fkey = 1; // keyboard trigger X- X+ X if (strEqu(mode,"prev")) // get previous or next image file X pp = image_gallery(ss_newfile,"prev"); X if (strEqu(mode,"next")) X@@ -4136,8 +4152,8 @@ X if (ss_oldfile) zfree(ss_oldfile); X ss_oldfile = ss_newfile; X ss_newfile = pp; X- X- ss_loadimage(ss_oldfile,ss_pxmold); X+ X+ ss_loadimage(ss_oldfile,ss_pxmold); X ss_loadimage(ss_newfile,ss_pxmnew); X X mutex_lock(&Fpixmap_lock); // block other window updates X@@ -4191,7 +4207,7 @@ X PXM *pxmtemp1, *pxmtemp2; X double wscale, hscale, scale; X uint8 *pix1, *pix2; X- X+ X cc = ss_ww * ss_hh * 3; // clear output pixmap to bright gray X memset(pxmout->bmp,gray,cc); X X@@ -4200,16 +4216,16 @@ X X fww = pxmtemp1->ww; // image size X fhh = pxmtemp1->hh; X- X+ X wscale = 1.0 * ss_ww / fww; // find scale to fit in window X hscale = 1.0 * ss_hh / fhh; X if (wscale < hscale) scale = wscale; // use greatest ww/hh ratio X else scale = hscale; X fww = fww * scale; X fhh = fhh * scale; X- X+ X pxmtemp2 = PXM_rescale(pxmtemp1,fww,fhh); // rescale image to fit window X- X+ X orgx = 0.5 * (ss_ww - fww); // origin of image in window X orgy = 0.5 * (ss_hh - fhh); X X@@ -4225,7 +4241,7 @@ X X PXM_free(pxmtemp1); X PXM_free(pxmtemp2); X- X+ X return; X } X X@@ -4249,10 +4265,10 @@ X int ii, jj, kk, px, py; X double newpart, oldpart; X uint8 *pix1, *pix2, *pix3; X- X+ X PXM_free(ss_pxmmix); X ss_pxmmix = PXM_copy(ss_pxmold); X- X+ X for (ii = 0; ii <= 100; ii += 10) X { X newpart = 0.01 * ii; X@@ -4271,7 +4287,7 @@ X pix3[1] = newpart * pix2[1] + oldpart * pix1[1]; X pix3[2] = newpart * pix2[2] + oldpart * pix1[2]; X } X- X+ X pix3 = PXMpix8(ss_pxmmix,0,0); X gdk_draw_rgb_image(drWin->window, gdkgc, 0, 0, ss_ww, ss_hh, NODITHER, pix3, ss_ww*3); X } X@@ -4292,19 +4308,19 @@ X X PXM_free(ss_pxmmix); X ss_pxmmix = PXM_copy(ss_pxmold); X- X+ X for (px = 0; px < ss_ww; px++) X { X pix1 = PXMpix8(ss_pxmnew,px,0); X pix3 = PXMpix8(ss_pxmmix,px,0); X- X+ X for (py = 0; py < ss_hh; py++) X { X memmove(pix3,pix1,3); X pix1 += ss_ww * 3; X pix3 += ss_ww * 3; X } X- X+ X pix3 = PXMpix8(ss_pxmmix,px,0); X gdk_draw_rgb_image(drWin->window, gdkgc, px, 0, 1, ss_hh, NODITHER, pix3, ss_ww*3); X } X@@ -4322,7 +4338,7 @@ X int py; X uint8 *pix3; X double delay = 0.5 / ss_hh; X- X+ X for (py = 0; py < ss_hh; py++) X { X pix3 = PXMpix8(ss_pxmnew,0,py); X@@ -4369,7 +4385,7 @@ X int louver, Nlouvers = 20; X int louversize = ss_hh / Nlouvers; X double delay = 1.0 / louversize; X- X+ X for (py1 = 0; py1 < louversize; py1++) // y-row within each louver X { X for (louver = 0; louver < Nlouvers; louver++) // louver, first to last X@@ -4398,7 +4414,7 @@ X int row, col, Nrow, Ncol; // rows and columns X int boxww, boxhh; X double delay; X- X+ X Ncol = 20; // 20 columns X boxww = boxhh = ss_ww / Ncol; // square boxes X Nrow = ss_hh / boxhh; // corresp. rows X@@ -4415,7 +4431,7 @@ X pix3 = PXMpix8(ss_pxmnew,0,py2); X gdk_draw_rgb_image(drWin->window, gdkgc, 0, py2, ss_ww, 1, NODITHER, pix3, ss_ww*3); X } X- X+ X px1 = py1; X X for (col = 0; col < Ncol; col++) X@@ -4425,7 +4441,7 @@ X pix3 = PXMpix8(ss_pxmnew,px2,0); X gdk_draw_rgb_image(drWin->window, gdkgc, px2, 0, 1, ss_hh, NODITHER, pix3, ss_ww*3); X } X- X+ X zsleep(delay); X } X X@@ -4470,11 +4486,11 @@ X X pix3 = PXMpix8(ss_pxmnew,px1,py1); X gdk_draw_rgb_image(drWin->window, gdkgc, px1, py1, ww2+1, hh1+1, NODITHER, pix3, ss_ww*3); X- X+ X zmainloop(); X zsleep(delay); X } X- X+ X pix3 = PXMpix8(ss_pxmnew,0,0); X gdk_draw_rgb_image(drWin->window, gdkgc, 0, 0, ss_ww, ss_hh, NODITHER, pix3, ss_ww * 3); X return; X@@ -4498,7 +4514,7 @@ X b = a * ss_hh / ss_ww; // from tiny to >> image size X a2 = a * a; X b2 = b * b; X- X+ X for (py = -b; py <= +b; py += 2) // py from top of ellipse to bottom X { X if (py < -hh2 || py > +hh2) continue; X@@ -4508,7 +4524,7 @@ X if (px > ww2) px = ww2; X ww = 2 * px; // length of line thru ellipse X px1 = int(ww2 - px); // relocate origin X- py1 = int(py + hh2); X+ py1 = int(py + hh2); X pix3 = PXMpix8(ss_pxmnew,px1,py1); X gdk_draw_rgb_image(drWin->window, gdkgc, px1, py1, ww, 2, NODITHER, pix3, ss_ww*3); X } X@@ -4516,7 +4532,7 @@ X zmainloop(); X zsleep(delay); X } X- X+ X pix3 = PXMpix8(ss_pxmnew,0,0); X gdk_draw_rgb_image(drWin->window, gdkgc, 0, 0, ss_ww, ss_hh, NODITHER, pix3, ss_ww * 3); X return; X@@ -4533,7 +4549,7 @@ X void m_showRGB(GtkWidget *, cchar *) // menu function X { X int RGB_dialog_event(zdialog *zd, cchar *event); X- X+ X cchar *rgbmess = ZTX("click on window to show RGB"); X cchar *format = "Pixel: 0 0 RGB: 0.0 0.0 0.0"; X X@@ -4584,13 +4600,13 @@ X char text[60]; X uint8 *ppix8; X uint16 *ppix16; X- X+ X if (LMclick) // left mouse click X { X LMclick = 0; X px = Mxclick; // click position X py = Myclick; X- X+ X if (E3pxm16) { // use current image being edited X if (px < 0 || px > E3ww-1 || // outside image area X py < 0 || py > E3hh-1) return; X@@ -4603,7 +4619,7 @@ X } X X else if (Fpxm16) { // use edited image X- if (px < 0 || px > Fww-1 || X+ if (px < 0 || px > Fww-1 || X py < 0 || py > Fhh-1) return; X ppix16 = PXMpix(Fpxm16,px,py); X red = ppix16[0] / 256.0; X@@ -4614,7 +4630,7 @@ X } X X else { // use 8 bpc image X- if (px < 0 || px > Fww-1 || X+ if (px < 0 || px > Fww-1 || X py < 0 || py > Fhh-1) return; X ppix8 = (uint8 *) Fpxm8->bmp + (py * Fww + px) * 3; X red = ppix8[0]; X@@ -4623,12 +4639,12 @@ X fbright = pixbright(ppix8); X fred = pixred(ppix8); X } X- X+ X snprintf(text,59,"Pixel: %d %d RGB: %6.3f %6.3f %6.3f", // show pixel and RGB colors X px, py, red, green, blue); X zdialog_stuff(zdRGB,"labrgb",text); X } X- X+ X return; X } X X@@ -4642,11 +4658,11 @@ X int gridlines_dialog_event(zdialog *zd, cchar *event); X X zdialog *zd; X- X+ X zfuncs::F1_help_topic = "grid_lines"; // v.10.8 X X zd = zdialog_new(ZTX("Grid Lines"),mWin,Bdone,Bcancel,null); X- X+ X zdialog_add_widget(zd,"hbox","hb0","dialog",0,"space=10"); X zdialog_add_widget(zd,"vbox","vb1","hb0"); X zdialog_add_widget(zd,"vbox","vb2","hb0"); X@@ -4702,12 +4718,12 @@ X zdialog_fetch(zd,"xgrid",Fgrid[0]); X mwpaint2(); X } X- X+ X if (strEqu(event,"ygrid")) { X zdialog_fetch(zd,"ygrid",Fgrid[1]); X mwpaint2(); X } X- X+ X if (strEqu(event,"spacex")) { X zdialog_fetch(zd,"spacex",gridspace[0]); X if (Fgrid[0]) mwpaint2(); X@@ -4747,9 +4763,9 @@ X int ii, zstat, radb; X char text[20]; X zdialog *zd; X- X+ X zfuncs::F1_help_topic = "lens_parms"; // v.10.8 X- X+ X if (! lens4_name[0] || strEqu(lens4_name[0],"undefined")) { X lens4_name[0] = strdupz("lens_1",lens_cc); // default lens parameters X lens4_name[1] = strdupz("lens_2",lens_cc); X@@ -4792,7 +4808,7 @@ X zdialog_add_widget(zd,"entry","bow1","vb4","0.0","scc=6"); X zdialog_add_widget(zd,"entry","bow2","vb4","0.0","scc=6"); X zdialog_add_widget(zd,"entry","bow3","vb4","0.0","scc=6"); X- X+ X for (ii = 0; ii < 4; ii++) // stuff lens data into dialog X { X snprintf(text,20,"name%d",ii); X@@ -4805,7 +4821,7 @@ X X snprintf(text,20,"radb%d",curr_lens); // current lens = selected X zdialog_stuff(zd,text,1); X- X+ X zdialog_run(zd,0); // run dialog, get inputs X zstat = zdialog_wait(zd); X X@@ -4813,7 +4829,7 @@ X zdialog_free(zd); // canceled X return; X } X- X+ X for (ii = 0; ii < 4; ii++) // fetch lens data (revisions) X { X snprintf(text,20,"name%d",ii); X@@ -4827,7 +4843,7 @@ X zdialog_fetch(zd,text,radb); X if (radb) curr_lens = ii; X } X- X+ X zdialog_free(zd); X return; X } X@@ -4844,10 +4860,10 @@ X char lang1[8], *pp; X X cchar *langs[12] = { "en English", "de German", "es Spanish", // english first X- "fr French", "gl Galacian", "it Italian", X- "nl Dutch", "pt Portuguese", "ru_RU Russian", X+ "fr French", "gl Galacian", "it Italian", X+ "nl Dutch", "pt Portuguese", "ru_RU Russian", X "sv Swedish", "zh_CN Chinese", null }; X- X+ X cchar *title = ZTX("Available Translations"); X X zfuncs::F1_help_topic = "language"; // v.10.8 X@@ -4863,7 +4879,7 @@ X cc = strlen(zfuncs::zlanguage); // current language X for (ii = 0; langs[ii]; ii++) // match on lc_RC X if (strnEqu(zfuncs::zlanguage,langs[ii],cc)) break; X- if (! langs[ii]) X+ if (! langs[ii]) X for (ii = 0; langs[ii]; ii++) // failed, match on lc alone X if (strnEqu(zfuncs::zlanguage,langs[ii],2)) break; X if (! langs[ii]) ii = 0; // failed, default english X@@ -4882,7 +4898,7 @@ X X if (zstat != 1) return; // user cancel X if (! val) return; // no selection X- X+ X strncpy0(lang1,langs[ii],8); X pp = strchr(lang1,' '); // isolate lc_RC part X *pp = 0; X@@ -4899,7 +4915,7 @@ X X // create desktop icon / launcher X X-void m_launcher(GtkWidget *, cchar *) X+void m_launcher(GtkWidget *, cchar *) X { X zfuncs::F1_help_topic = "launcher"; // v.10.8 X zmake_launcher("Graphics","Image Editor"); X@@ -4933,7 +4949,7 @@ X X raw_files = zgetfileN(ZTX("Select RAW files to convert"),"openN",curr_dirk); X if (! raw_files) goto rawdone; X- X+ X for (ii = 0; raw_files[ii]; ii++); // count selected files X raw_filecount = ii; X X@@ -4941,7 +4957,7 @@ X X write_popup_text("open","Converting RAW files",500,200,mWin); // status monitor popup window X write_popup_text("write","converting ..."); // v.10.9 X- X+ X while (true) X { X zmainloop(); // v.10.9 X@@ -4969,7 +4985,7 @@ X rawdone: X X if (raw_files) { X- for (ii = 0; raw_files[ii]; ii++) X+ for (ii = 0; raw_files[ii]; ii++) X zfree(raw_files[ii]); X zfree(raw_files); X } X@@ -4994,7 +5010,7 @@ X pp = strrchr(rawfile,'.'); X pp = outfile + (pp - rawfile); X strcpy(pp,".tiff"); X- X+ X // try new ufraw command format first, then old command if error // --wb v.10.9 X X snprintf(command,ccc,"ufraw-batch --wb=camera --out-type=tiff --out-depth=16" X@@ -5006,7 +5022,7 @@ X " --overwrite --output=\"%s\" \"%s\" ",outfile, rawfile); X err = system(command); X } X- X+ X while (raw_outfile) zsleep(0.1); // wait for prior bugfix v.10.9 X X if (err) { X@@ -5024,7 +5040,7 @@ X X /**************************************************************************/ X X-// burn images to CD/DVD X+// burn images to CD/DVD X X void m_burn(GtkWidget *, cchar *) X { X@@ -5032,7 +5048,7 @@ X char **filelist, *imagefile, *bcommand; X X if (! menulock(1)) return; // lock menus X- X+ X zfuncs::F1_help_topic = "burn"; // v.10.8 X X filelist = image_gallery_getfiles(0,mWin); // get list of files to burn v.10.9 X@@ -5040,7 +5056,7 @@ X menulock(0); X return; X } X- X+ X cc = 0; X for (ii = 0; filelist[ii]; ii++) // get memory for brasero command line X cc += strlen(filelist[ii]) + 4; X@@ -5060,7 +5076,7 @@ X cc += 1; X zfree(imagefile); X } X- X+ X zfree(filelist); X X strcat(bcommand," &"); // brasero command in background X@@ -5111,7 +5127,7 @@ X X zdialog_stuff(zd,"maxw",emailsize[0]); X zdialog_stuff(zd,"maxh",emailsize[1]); X- X+ X zdialog_run(zd,email_dialog_event); // run dialog X zdialog_wait(zd); // wait for completion X X@@ -5135,11 +5151,11 @@ X if (strEqu(event,"files")) // select images to resize X { X if (flist) { // free prior list X- for (ii = 0; flist[ii]; ii++) X+ for (ii = 0; flist[ii]; ii++) X zfree(flist[ii]); X zfree(flist); X } X- X+ X flist = image_gallery_getfiles(0,mWin); // get list of files to resize v.10.9 X X if (flist) // count files selected X@@ -5149,11 +5165,11 @@ X sprintf(countmess,"%d files selected",ii); // update dialog X zdialog_stuff(zd,"fcount",countmess); X } X- X+ X if (! zd->zstat) return 0; // dialog still busy X X if (zd->zstat != 1) goto cleanup; // dialog canceled X- X+ X if (! flist) { // no files selected X zd->zstat = 0; // keep dialog active X return 0; X@@ -5169,7 +5185,7 @@ X } X X *tempdir = 0; // temp directory: /tmp//fotoxx/email X- strncatv(tempdir,99,"/tmp/",cuserid(null),"/fotoxx/email",null); X+ strncatv(tempdir,99,"/tmp/",getpwuid(null),"/fotoxx/email",null); X X sprintf(command,"mkdir -p %s",tempdir); // (re)create directory X err = system(command); X@@ -5180,7 +5196,7 @@ X X sprintf(command,"rm -f %s/*.jpg",tempdir); // purge prior file list X err = system(command); X- X+ X write_popup_text("open","preparing files",500,200,mWin); // status monitor popup window X X strcpy(command,"xdg-email"); // e-mail command: xdg-email X@@ -5206,19 +5222,19 @@ X if (pfile[jj] >= '0' && pfile[jj] <= '9') continue; X kk--; // omit others X } X- X+ X pfile[kk] = 0; X X pext = strrchr(pfile,'.'); // find .ext if there is one X if (! pext) pext = pfile + strlen(pfile); X if (strlen(pext) > 5) pext = pext + strlen(pext); X- X+ X sprintf(sequence,"-%d",ii+1); // replace with sequence number X strcpy(pext,sequence); // filename-nn X X pext = pext + strlen(pext); // add .jpg extension X strcpy(pext,".jpg"); // filename-nn.jpg X- X+ X write_popup_text("write",newfile); // log progress X zmainloop(); X X@@ -5227,7 +5243,7 @@ X printf("f_load error: %s \n",oldfile); X continue; X } X- X+ X ww = pxmin->ww; X hh = pxmin->hh; X X@@ -5241,13 +5257,13 @@ X pxmout = PXM_rescale(pxmin,ww,hh); // rescale file X X PXBwrite(pxmout,newfile); // write to new file X- X+ X PXM_free(pxmin); X PXM_free(pxmout); X- X+ X err = strncatv(command,1990," --attach ","\"",newfile,"\"",null); // --attach /tmp//fotoxx/filename.jpg X zfree(newfile); X- X+ X if (err) { X zmessageACK(mWin,ZTX("too many files")); X goto cleanup; X@@ -5259,7 +5275,7 @@ X X emailsize[0] = maxw; // save preferred size X emailsize[1] = maxh; X- X+ X strcat(command," &"); // wait for email completion X printf("system: %s \n",command); X err = system(command); X@@ -5267,7 +5283,7 @@ X cleanup: X X if (flist) { // free memory X- for (ii = 0; flist[ii]; ii++) X+ for (ii = 0; flist[ii]; ii++) X zfree(flist[ii]); X zfree(flist); X flist = 0; X@@ -5303,7 +5319,7 @@ X zdialog_add_widget(zd,"hbox","hb3","dialog",0,"space=5"); X zdialog_add_widget(zd,"radio","rb1","hb3",ZTX("full rebuild"),"space=5"); X zdialog_add_widget(zd,"radio","rb2","hb3",ZTX("incremental"),"space=10"); X- X+ X if (topdirk) zdialog_stuff(zd,"topdirk",topdirk); X zdialog_stuff(zd,"rb1",0); X zdialog_stuff(zd,"rb2",1); X@@ -5316,7 +5332,7 @@ X return; X } X X- pp = zmalloc(maxfcc); X+ pp = zmalloc(maxfcc); X zdialog_fetch(zd,"topdirk",pp,maxfcc-1); // get top directory X if (topdirk) zfree(topdirk); X topdirk = strdupz(pp,0,"topdirk"); X@@ -5328,7 +5344,7 @@ X zdialog_free(zd); X X if (! menulock(1)) return; X- X+ X Ffuncbusy++; // v.11.01 X X if (Ffull) // full rebuild v.11.02 X@@ -5366,7 +5382,7 @@ X X while (filespec1) X { X- if (image_file_type(filespec1) == 2) X+ if (image_file_type(filespec1) == 2) X { X if (! thumbdirk) { // when first image file found, X thumbdirk = strdupz(subdirk,20); // create .thumbnails if needed X@@ -5381,7 +5397,7 @@ X snprintf(SB_text,199,"%5d %s",++fcount,filespec1); // update status bar v.11.03 X zmainloop(); X } X- X+ X filespec2 = image_gallery(filespec1,"next"); // next image file X zfree(filespec1); X filespec1 = filespec2; X@@ -5403,7 +5419,7 @@ X int rebuild_thumbs_dialog_event(zdialog *zd, cchar *event) X { X char *pp; X- X+ X if (! strEqu(event,"browse")) return 0; X pp = zgetfile1(ZTX("Select top image directory"),"folder",topdirk); // get topmost directory X if (! pp) return 0; X@@ -5444,7 +5460,7 @@ X char *subdirk, *pp, **ppv; X char *filespec1, *filespec2; X char *imagedate, *imagetags, *imagestars, *imagecomms, *imagecapt; X- cchar *exifkeys[5] = { exif_date_key, exif_tags_key, exif_rating_key, X+ cchar *exifkeys[5] = { exif_date_key, exif_tags_key, exif_rating_key, X exif_comment_key, exif_caption_key }; X cchar *ppc, *mode; X int Nold, Nnew, orec, nrec, comp; X@@ -5457,12 +5473,12 @@ X zmessageACK(mWin,Bexiftoolmissing); X return; X } X- X+ X if (! menu) { X mode = "full"; X goto begin; X } X- X+ X zd = zdialog_new(ZTX("Rebuild Search Index"),mWin,Bproceed,Bcancel,null); X zdialog_add_widget(zd,"hbox","hb1","dialog",0,"space=5"); X zdialog_add_widget(zd,"label","lab1","hb1",ZTX("Top Image Directory:")); X@@ -5472,7 +5488,7 @@ X zdialog_add_widget(zd,"hbox","hb3","dialog",0,"space=5"); X zdialog_add_widget(zd,"radio","rb1","hb3",ZTX("full rebuild"),"space=5"); X zdialog_add_widget(zd,"radio","rb2","hb3",ZTX("incremental"),"space=10"); X- X+ X if (topdirk) zdialog_stuff(zd,"topdirk",topdirk); X zdialog_stuff(zd,"rb1",0); X zdialog_stuff(zd,"rb2",1); X@@ -5485,12 +5501,12 @@ X return; X } X X- pp = zmalloc(maxfcc); X+ pp = zmalloc(maxfcc); X zdialog_fetch(zd,"topdirk",pp,maxfcc-1); X if (topdirk) zfree(topdirk); X topdirk = strdupz(pp,0,"topdirk"); X zfree(pp); X- X+ X zdialog_fetch(zd,"rb1",zstat); X if (zstat) mode = "full"; X else mode = "incr"; X@@ -5501,19 +5517,19 @@ X X if (! menulock(1)) return; X Ffuncbusy++; // v.11.01 X- X+ X xrec_old = (tag_index_rec *) zmalloc(max_images * sizeof(tag_index_rec),"xrec_old"); X xrec_new = (tag_index_rec *) zmalloc(max_images * sizeof(tag_index_rec),"xrec_new"); X- X+ X // if incremental mode, read current search index file and build "old list" of tags X X if (strEqu(mode,"incr")) // bugfix v.10.9 X fid = fopen(search_index_file,"r"); X else fid = 0; X- X+ X orec = Nold = 0; X X- if (fid) X+ if (fid) X { X while (true) // read all search index records X { X@@ -5522,9 +5538,9 @@ X X if (strnEqu(pp,"file: ",6)) // start new file entry X { X- if (++Nold == max_images) X+ if (++Nold == max_images) X zappcrash("more than %d image files: %d",max_images); X- X+ X orec = Nold - 1; X X xrec_old[orec].file = strdupz(pp+6,0,"xrec_old.file"); X@@ -5537,7 +5553,7 @@ X xrec_old[orec].capt = 0; X xrec_old[orec].update = '0'; X } X- X+ X if (strnEqu(pp,"date: ",6)) X { X ppc = strField(pp,' ',2); X@@ -5545,10 +5561,10 @@ X ppc = strField(pp,' ',3); X if (ppc) strncpy0(xrec_old[orec].filedate,ppc,16); X } X- X+ X if (strnEqu(pp,"tags: ",6)) X xrec_old[orec].tags = strdupz(pp+6,0,"xrec_old.tags"); X- X+ X if (strnEqu(pp,"stars: ",7)) X xrec_old[orec].stars = *(pp+7); X X@@ -5558,12 +5574,12 @@ X if (strnEqu(pp,"capt: ",6)) X xrec_old[orec].capt = strdupz(pp+6,0,"xrec_old.capt"); // v.10.12 X } X- X+ X fclose(fid); X } X X printf("%d current tag records found \n",Nold); X- X+ X // find all image files and create "new list" with no tags X X snprintf(command,ccc,"find \"%s\" -type d",topdirk); // find directories under top directory X@@ -5588,7 +5604,7 @@ X { X err = stat(filespec1,&statb); X if (err) continue; X- if (++Nnew == max_images) X+ if (++Nnew == max_images) X zappcrash("more than %d image files: %d",max_images); X nrec = Nnew - 1; X xrec_new[nrec].file = strdupz(filespec1,0,"xrec_new.file"); // filespec X@@ -5602,7 +5618,7 @@ X xrec_new[nrec].comms = 0; // comments = empty X xrec_new[nrec].capt = 0; // caption = empty v.10.12 X } X- X+ X filespec2 = image_gallery(filespec1,"next"); // next image file X zfree(filespec1); X filespec1 = filespec2; X@@ -5610,7 +5626,7 @@ X X zfree(subdirk); X } X- X+ X printf("found %d image files \n",Nnew); X X // merge and compare lists X@@ -5625,7 +5641,7 @@ X X if (orec == Nold) comp = +1; X else comp = strcmp(xrec_old[orec].file, xrec_new[nrec].file); // compare filespecs X- X+ X if (comp > 0) nrec++; X else if (comp < 0) orec++; X else // matching filespecs X@@ -5669,13 +5685,13 @@ X imagestars = ppv[2]; X imagecomms = ppv[3]; X imagecapt = ppv[4]; X- X+ X if (imagedate && strlen(imagedate)) { // image date X if (strlen(imagedate) > 9) imagedate[10] = 0; // truncate to yyyy:mm:dd X strcpy(xrec_new[nrec].imagedate,imagedate); X } X else strcpy(xrec_new[nrec].imagedate,"null "); X- X+ X if (imagetags && strlen(imagetags)) // image tags X xrec_new[nrec].tags = strdupz(imagetags,0,"xrec_new.tags"); X else xrec_new[nrec].tags = strdupz("null"tagdelim2,0,"xrec_new.tags"); // v.11.02 X@@ -5714,9 +5730,9 @@ X fprintf(fid,"capt: %s""\n",xrec_new[nrec].capt); X fprintf(fid,"\n"); X } X- X+ X fclose(fid); X- X+ X for (nrec = 0; nrec < Nnew; nrec++) // release new list memory X { X zfree(xrec_new[nrec].file); X@@ -5727,7 +5743,7 @@ X X Ffuncbusy--; X menulock(0); X- X+ X printf("rebuild tags: processed %d image files \n",Nnew); X zmessageACK(mWin,ZTX("completed")); X return; X@@ -5739,7 +5755,7 @@ X int rebuild_search_index_dialog_event(zdialog *zd, cchar *event) X { X char *pp; X- X+ X if (! strEqu(event,"browse")) return 0; X pp = zgetfile1(ZTX("Select top image directory"),"folder",topdirk); // get topmost directory X if (! pp) return 0; X@@ -5778,7 +5794,7 @@ X cchar *tagskey[1] = { exif_tags_key }, *pnewtags[1]; X char **poldtags, *oldtags, *newtags; X struct stat statb; X- X+ X zfuncs::F1_help_topic = "fix_tag_delim"; X X if (! Fexiftool) { // exiftool is required X@@ -5792,7 +5808,7 @@ X zdialog_add_widget(zd,"hbox","hb2","dialog"); X zdialog_add_widget(zd,"entry","topdirk","hb2","??","scc=40|space=5"); X zdialog_add_widget(zd,"button","browse","hb2",Bbrowse,"space=5"); X- X+ X if (topdirk) zdialog_stuff(zd,"topdirk",topdirk); X X zdialog_run(zd,fix_tag_delim_dialog_event); X@@ -5845,11 +5861,11 @@ X Nfiles++; // none X goto nextfile; X } X- X+ X newtags = zmalloc(tagFcc,"newtags"); X *newtags = 0; X tcc = 0; X- X+ X for (ii = 1; ; ii++) X { X pp = strField(oldtags,tagdelims,ii); // get each tag X@@ -5864,7 +5880,7 @@ X strcpy(newtags + tcc, tagdelim2); // add delim + blank X tcc += 2; X } X- X+ X pnewtags[0] = newtags; // add Keywords tag X exif_put(filespec1,tagskey,pnewtags,1); // update EXIF data X X@@ -5883,11 +5899,11 @@ X X zfree(subdirk); X } X- X+ X printf("fix tag delimiters: processed %d image files \n",Nfiles); X Ffuncbusy--; X menulock(0); X- // create new search index X+ // create new search index X zmessageACK(mWin,ZTX("new search index will now be created")); X m_rebuild_search_index(0,0); X X@@ -5901,7 +5917,7 @@ X zmessageACK(mWin,ZTX("new defined tags file will now be created")); X X strcpy(oldfile,tags_defined_file); X- strcat(oldfile,"_old"); X+ strcat(oldfile,"_old"); X sprintf(command,"cp %s %s", tags_defined_file, oldfile); X err = system(command); X if (err) { X@@ -5925,10 +5941,10 @@ X fclose(fid1); X fclose(fid2); X } X- X+ X zmessageACK(mWin,ZTX("thumbnail images will now be updated")); X m_rebuild_thumbs(0,0); X- X+ X return; X } X X@@ -5938,7 +5954,7 @@ X int fix_tag_delim_dialog_event(zdialog *zd, cchar *event) X { X char *pp; X- X+ X if (zd->zstat == 1) { X zd->zstat = 0; X showz_userguide("fix_tag_delim"); X@@ -5950,7 +5966,7 @@ X zdialog_stuff(zd,"topdirk",pp); X zfree(pp); X } X- X+ X return 0; X } X X@@ -6011,11 +6027,11 @@ X zmessageACK(mWin,Bexiftoolmissing); X return; X } X- X+ X if (! curr_file) return; X X if (! zdeditcomm) // popup dialog if not already v.10.8 X- { X+ { X zdeditcomm = zdialog_new(ZTX("Edit Comments"),mWin,Bapply,Bcancel,null); X zdialog_add_widget(zdeditcomm,"hbox","hbtext","dialog"); X zdialog_add_widget(zdeditcomm,"frame","frame","hbtext",0,"expand"); X@@ -6023,7 +6039,7 @@ X zdialog_resize(zdeditcomm,300,0); X zdialog_run(zdeditcomm,edit_comments_dialog_event); X } X- X+ X load_filetags(curr_file); // get current comments X repl_1str(tags_comments,text,"\\n","\n"); // replace "\n" with real newlines X zdialog_stuff(zdeditcomm,"text",text); // stuff into dialog X@@ -6037,9 +6053,9 @@ X int edit_comments_dialog_event(zdialog *zd, cchar *event) X { X char text[tagFcc]; X- X+ X if (! zd->zstat) return 0; X- X+ X else if (zd->zstat == 1) // save text X { X zd->zstat = 0; // keep dialog active X@@ -6070,11 +6086,11 @@ X zmessageACK(mWin,Bexiftoolmissing); X return; X } X- X+ X if (! curr_file) return; X X if (! zdeditcapt) // popup dialog if not already v.10.8 X- { X+ { X zdeditcapt = zdialog_new(ZTX("Edit Caption"),mWin,Bapply,Bcancel,null); X zdialog_add_widget(zdeditcapt,"hbox","hbtext","dialog"); X zdialog_add_widget(zdeditcapt,"frame","frame","hbtext",0,"expand"); X@@ -6082,7 +6098,7 @@ X zdialog_resize(zdeditcapt,300,0); X zdialog_run(zdeditcapt,edit_caption_dialog_event); X } X- X+ X load_filetags(curr_file); // get current caption X repl_1str(tags_caption,text,"\\n","\n"); // replace "\n" with real newlines X zdialog_stuff(zdeditcapt,"text",text); // stuff into dialog X@@ -6098,7 +6114,7 @@ X char text[tagFcc]; X X if (! zd->zstat) return 0; X- X+ X else if (zd->zstat == 1) // save text X { X zd->zstat = 0; // keep dialog active X@@ -6131,10 +6147,10 @@ X zmessageACK(mWin,Bexiftoolmissing); X return; X } X- X+ X if (! curr_file) return; X X- if (! zdedittags) // (re) start tag edit dialog X+ if (! zdedittags) // (re) start tag edit dialog X { X zdedittags = zdialog_new(ZTX("Edit Tags"),mWin,Bapply,Bcancel,null); X X@@ -6184,7 +6200,7 @@ X X zdialog_resize(zdedittags,0,500); // run dialog X zdialog_run(zdedittags,edittags_dialog_event); X- X+ X edittags_fixwidget(zdedittags,"filetags"); // setup for mouse tag selection X edittags_fixwidget(zdedittags,"recentags"); X edittags_fixwidget(zdedittags,"deftags"); X@@ -6238,7 +6254,7 @@ X if (event->type != GDK_BUTTON_PRESS) return; X mpx = int(event->x); // mouse click position X mpy = int(event->y); X- X+ X get_mouse_tag(widget,mpx,mpy,widgetname); // tags_cliktag = clicked tag in list X if (! *tags_cliktag) return; X X@@ -6258,7 +6274,7 @@ X add_recentag(tags_cliktag); // and to recent tags X zdialog_stuff(zdedittags,"recentags",tags_recentags); X } X- X+ X *tags_cliktag = 0; X return; X } X@@ -6269,7 +6285,7 @@ X int edittags_dialog_event(zdialog *zd, cchar *event) X { X int err; X- X+ X if (zd->zstat) { X if (zd->zstat == 1) { // [apply] X save_filetags(curr_file); // save tag changes X@@ -6280,7 +6296,7 @@ X zdialog_free(zdedittags); // cancel - kill dialog X return 0; X } X- X+ X if (strEqu(event,"date")) { // image date revised X err = zdialog_fetch(zd,"date",tags_date,11); X if (err) return 1; X@@ -6288,7 +6304,7 @@ X if (strlen(tags_date) == 6) strcat(tags_date,"01"); // yyyymm >> yyyymm01 X Ftagschanged++; X } X- X+ X if (strEqu(event,"prdate")) { // repeat last date used X if (*tags_prdate) { X zdialog_stuff(zd,"date",tags_prdate); X@@ -6301,7 +6317,7 @@ X tags_stars = event[5]; // '0' to '5' X Ftagschanged++; X } X- X+ X if (strEqu(event,"tags-changed")) // get new defined tags data X deftags_stuff(zdedittags); // v.11.02 X X@@ -6344,7 +6360,7 @@ X X zdialog_resize(zdmanagetags,0,400); // run dialog X zdialog_run(zdmanagetags,managetags_dialog_event); X- X+ X managetags_fixwidget(zdmanagetags,"deftags"); // setup for mouse tag selection X X load_deftags(); // stuff defined tags into dialog X@@ -6384,15 +6400,15 @@ X if (event->type != GDK_BUTTON_PRESS) return; X mpx = int(event->x); // mouse click position X mpy = int(event->y); X- X+ X cc = get_mouse_tag(widget,mpx,mpy,widgetname); // tags_cliktag = clicked tag in list X- X+ X if (! cc) { X if (*tags_clikcatg) // selected category >> dialog widget X zdialog_stuff(zdmanagetags,"catg",tags_clikcatg); X return; X } X- X+ X zdialog_stuff(zdmanagetags,"tag",tags_cliktag); // selected tag >> dialog widget X return; X } X@@ -6404,12 +6420,12 @@ X { X char tag[tagcc], catg[tagcc]; X int changed = 0; X- X+ X if (zd->zstat) { X zdialog_free(zdmanagetags); X return 0; X } X- X+ X if (strEqu(event,"create")) { // add new tag to defined tags X zdialog_fetch(zd,"catg",catg,tagcc); X zdialog_fetch(zd,"tag",tag,tagcc); X@@ -6423,7 +6439,7 @@ X changed++; X } X X- if (changed) { X+ if (changed) { X save_deftags(); // save tag updates to file X deftags_stuff(zdmanagetags); // update dialog "deftags" window X if (zdedittags) // and edit tags window if active X@@ -6451,7 +6467,7 @@ X gtk_text_view_get_iter_at_location(widget,&iter,tbx,tby); X offset = gtk_text_iter_get_offset(&iter); // graphic position in widget text X X- ptext = 0; X+ ptext = 0; X if (strEqu(widgetname,"filetags")) ptext = tags_filetags; // get corresponding text X if (strEqu(widgetname,"recentags")) ptext = tags_recentags; X if (strEqu(widgetname,"batchAddTags")) ptext = tags_batchAddTags; X@@ -6495,11 +6511,11 @@ X printf("bad utf8 characters: %s \n",tag2); X return 3; X } X- X+ X while ((pp1 = strpbrk(tag2,tagdelims":"))) *pp1 = '-'; // replace problem characters X X strcpy(tag,tag2); // replace tag with sanitized version X- X+ X pp1 = taglist; X cc1 = strlen(tag); X X@@ -6533,12 +6549,12 @@ X int ii, ftcc, atcc, found; X char *temptags; X cchar *pp; X- X+ X temptags = strdupz(taglist,0,"temptags"); X- X+ X *taglist = 0; X ftcc = found = 0; X- X+ X for (ii = 1; ; ii++) X { X pp = strField(temptags,tagdelims,ii); // next tag X@@ -6549,7 +6565,7 @@ X return 1-found; X } X if (*pp == ' ') continue; X- X+ X if (strcaseEqu(pp,tag)) { // skip matching tag X found = 1; X continue; X@@ -6605,7 +6621,7 @@ X char tagsbuff[tagGcc]; X char *pp1, *pp2; X char ptags[tagntc][tagcc]; X- X+ X if (Floaded) return; // use memory tags if already there v.11.02 X Floaded++; X X@@ -6652,19 +6668,19 @@ X if (! pp1) break; X if (strnNeq(tagsbuff,"tags: ",6)) continue; X pp1 = pp1 + 6; X- X+ X while (true) X { X while (*pp1 && strchr(tagdelims" ",*pp1)) pp1++; // next image tag start X if (! *pp1) break; X pp2 = strpbrk(pp1,tagdelims); // end X- if (! pp2) pp2 = pp1 + strlen(pp1); X+ if (! pp2) pp2 = pp1 + strlen(pp1); X cc = pp2 - pp1; X if (cc > tagcc-1) { X pp1 = pp2; // bugfix v.10.9 X continue; // ignore huge tag X } X- X+ X strncpy0(tag,pp1,cc+1); // look for tag in defined tags X err = find_deftag(tag); X if (! err) { // found X@@ -6690,7 +6706,7 @@ X err = fclose(fid); X if (err) goto filetagserr; X if (catoverflow) goto cattoobig; X- X+ X // parse all the tags in each category and sort in ascending order X X for (ii = 0; ii < ncats; ii++) X@@ -6715,7 +6731,7 @@ X tcc += cc; X while (*pp1 == ' ') pp1++; X } X- X+ X ntags = jj; X if (ntags == tagntc) goto cattoobig; X HeapSort((char *) ptags,tagcc,ntags,tags_Ucomp); X@@ -6739,10 +6755,10 @@ X strcpy(pp2,tagdelim2); X pp2 += 2; X } X- X+ X *pp2 = 0; X } X- X+ X // sort the categories in ascending order X // leave "nocatg" at the end X X@@ -6763,7 +6779,7 @@ X zmessLogACK(mWin,"more than %d categories",maxtagcats); X fclose(fid); X return; X- X+ X cattoobig: X zmessLogACK(mWin,"category %s is too big",catg); X fclose(fid); X@@ -6802,14 +6818,14 @@ X for (ii = 0; ii < maxtagcats; ii++) X { X if (! tags_deftags[ii+1]) break; // omit last category, "nocatg" X- err = fprintf(fid,"%s\n",tags_deftags[ii]); // each record: X+ err = fprintf(fid,"%s\n",tags_deftags[ii]); // each record: X if (err < 0) goto deftagserr; // category: tag1, tag2, ... tagN, X } X X err = fclose(fid); X if (err) goto deftagserr; X return; X- X+ X deftagserr: X zmessLogACK(mWin,"tags_defined file error: %s",strerror(errno)); X return; X@@ -6834,7 +6850,7 @@ X X for (ii = 0; ii < maxtagcats; ii++) X { X- pp = tags_deftags[ii]; // category: tag1, tag2, ... tagN, X+ pp = tags_deftags[ii]; // category: tag1, tag2, ... tagN, X if (! pp) return 1; // not found X X while (pp) X@@ -6860,7 +6876,7 @@ X int ii, cc, cc1, cc2; X char tag1[tagcc], tag2[tagcc]; X char *pp1, *pp2; X- X+ X strncpy0(tag1,tag,tagcc); // remove leading and trailing blanks X cc = strTrim2(tag2,tag1); X if (! cc) return 4; X@@ -6871,7 +6887,7 @@ X } X X while ((pp1 = strpbrk(tag2,tagdelims":"))) *pp1 = '-'; // replace problem characters X- X+ X strcpy(tag,tag2); // replace tag with sanitized version X X del_deftag(tag); // delete if already there X@@ -6927,7 +6943,7 @@ X } X X X-// delete tag from defined tags list, tags_deftags[] X+// delete tag from defined tags list, tags_deftags[] X // return: 0 = found and deleted, 1 = not found X X int del_deftag(char *tag) X@@ -6956,12 +6972,12 @@ X pp += cc; X } X } X- X+ X found: X for (pp1 = pp, pp2 = pp+cc; *pp2; pp1++, pp2++) // eliminate tag, delim, blank X *pp1 = *pp2; X *pp1 = 0; X- X+ X return 0; X } X X@@ -6977,7 +6993,7 @@ X int ii, cc; X char catgname[tagcc+3]; X char *pp1, *pp2; X- X+ X widget = zdialog_widget(zd,"deftags"); X wclear(widget); X X@@ -6995,7 +7011,7 @@ X if (*pp2) wprintx(widget,0,pp2,"monospace 8"); X wprintx(widget,0,"\n"); X } X- X+ X textbuff = gtk_text_view_get_buffer(GTK_TEXT_VIEW(widget)); X gtk_text_buffer_get_bounds(textbuff,&iter1,&iter2); X pp1 = gtk_text_buffer_get_text(textbuff,&iter1,&iter2,0); X@@ -7007,7 +7023,7 @@ X X /**************************************************************************/ X X-// image file EXIF data >> tags_date, tags_stars, tags_filetags, X+// image file EXIF data >> tags_date, tags_stars, tags_filetags, X // tags_comments, tags_caption in memory X X void load_filetags(cchar *file) X@@ -7016,13 +7032,13 @@ X X int ii, jj, cc; X char *pp; X- cchar *exifkeys[5] = { exif_date_key, exif_tags_key, exif_rating_key, X+ cchar *exifkeys[5] = { exif_date_key, exif_tags_key, exif_rating_key, X exif_comment_key, exif_caption_key }; X char **ppv, *imagedate, *imagetags, *imagestars, *imagecomms, *imagecapt; X X *tags_filetags = *tags_date = *tags_comments = *tags_caption = 0; X tags_stars = '0'; X- X+ X ppv = exif_get(file,exifkeys,5); // stars rating added v.10.0 X imagedate = ppv[0]; X imagetags = ppv[1]; X@@ -7059,7 +7075,7 @@ X if (tags_stars < '0' || tags_stars > '5') tags_stars = '0'; X zfree(imagestars); X } X- X+ X if (imagecomms) { // v.10.11 X strncpy0(tags_comments,imagecomms,tagFcc); X zfree(imagecomms); X@@ -7081,8 +7097,8 @@ X void save_filetags(cchar *file) X { X void tag_exifdate(cchar *tagdate, char *exifdate); X- X- cchar *exifkeys[5] = { exif_date_key, exif_tags_key, exif_rating_key, X+ X+ cchar *exifkeys[5] = { exif_date_key, exif_tags_key, exif_rating_key, X exif_comment_key, exif_caption_key }; X cchar *exifdata[5]; X char imagedate[24], sstars[4]; X@@ -7095,7 +7111,7 @@ X tag_exifdate(tags_date,imagedate); // yyyymmdd >> EXIF date/time X strcpy(tags_prdate,tags_date); X } X- X+ X sstars[0] = tags_stars; // string for stars rating X sstars[1] = 0; X X@@ -7130,21 +7146,21 @@ X X fidw = fopen(temp_search_index_file,"w"); // write temp tag file (new) X if (! fidw) goto tagserror; X- X+ X fidr = fopen(search_index_file,"r"); // read tag file (old) X- X+ X if (fidr) X- { X+ { X while (true) // copy search index file to temp X { // file, omitting this image file X ppv = fgets_trim(buff,tagrecl,fidr); X if (! ppv) break; X- X+ X if (strnEqu(buff,"file: ",6)) { // start of next file entry X if (strEqu(buff+6,file)) fcopy = 0; // my file, skip this entry X else fcopy = 1; X } X- X+ X if (fcopy) fprintf(fidw,"%s\n",buff); // copy data for other file entries X } X X@@ -7177,9 +7193,9 @@ X if (*tags_filetags) // output filetags X err = fprintf(fidw,"tags: %s\n",tags_filetags); X else err = fprintf(fidw,"tags: null" tagdelim2 "\n"); // "null" tag if none v.11.02 X- X+ X err = fprintf(fidw,"stars: %c\n",tags_stars); // output stars rating X- X+ X if (*tags_comments) // output user comments X err = fprintf(fidw,"comms: %s\n",tags_comments); X else err = fprintf(fidw,"comms: null \n"); // "null" if none X@@ -7192,12 +7208,12 @@ X X err = fclose(fidw); // close temp file X if (err) goto tagserror; X- X+ X err = rename(temp_search_index_file,search_index_file); // replace tags file with temp file X if (err) goto tagserror; X X return; X- X+ X tagserror: X zmessLogACK(mWin,ZTX("search index file error: %s"),strerror(errno)); X return; X@@ -7221,10 +7237,10 @@ X X fidr = fopen(search_index_file,"r"); // read tag file X if (! fidr) return; X- X+ X fidw = fopen(temp_search_index_file,"w"); // write temp tag file X if (! fidw) goto tagserror; X- X+ X while (true) // copy search index file to temp X { // file, omitting this image file X ppv = fgets_trim(indexbuff,tagrecl,fidr); X@@ -7241,7 +7257,7 @@ X fprintf(fidw,"%s\n",captbuff); X fprintf(fidw,"\n"); X } X- X+ X if (! ppv) break; // EOF X X ftf = 0; X@@ -7252,7 +7268,7 @@ X strcpy(commsbuff,"comms: null "); X strcpy(captbuff,"capt: null "); X } X- X+ X if (strnEqu(indexbuff,"date: ",6)) // copy whatever is found X strncpy0(datebuff,indexbuff,tagrecl); X X@@ -7274,7 +7290,7 @@ X X err = fclose(fidw); X if (err) goto tagserror; X- X+ X err = rename(temp_search_index_file,search_index_file); // replace tags file with temp file X if (err) goto tagserror; X X@@ -7298,12 +7314,12 @@ X { X void batchAddTags_fixwidget(zdialog *zd, cchar * widgetname); X int batchAddTags_dialog_event(zdialog *zd, cchar *event); X- X+ X char *ptag, **flist, *file; X int ii, jj, err; X X zfuncs::F1_help_topic = "batch_add_tags"; // v.10.8 X- X+ X if (! Fexiftool) { // exiftool is required X zmessageACK(mWin,Bexiftoolmissing); X return; X@@ -7343,7 +7359,7 @@ X X zdialog_resize(zdbatchAddTags,400,400); // run dialog X zdialog_run(zdbatchAddTags,batchAddTags_dialog_event); X- X+ X batchAddTags_fixwidget(zdbatchAddTags,"batchAddTags"); // setup for mouse tag selection X batchAddTags_fixwidget(zdbatchAddTags,"deftags"); X X@@ -7375,7 +7391,7 @@ X if (! ptag) break; X if (*ptag == ' ') continue; X err = add_tag(ptag,tags_filetags,tagFcc); X- if (err == 2) X+ if (err == 2) X zmessageACK(mWin,ZTX("%s \n too many tags"),file); X } X X@@ -7384,13 +7400,13 @@ X X write_popup_text("write","COMPLETED"); X write_popup_text("close",0); X- X+ X cleanup: X X zdialog_free(zdbatchAddTags); X X if (batchAddTags_filecount) { X- for (ii = 0; flist[ii]; ii++) X+ for (ii = 0; flist[ii]; ii++) X zfree(flist[ii]); X zfree(flist); X } X@@ -7438,7 +7454,7 @@ X del_tag(tags_cliktag,tags_batchAddTags); // remove tag from tags_batchAddTags X zdialog_stuff(zdbatchAddTags,"batchAddTags",tags_batchAddTags); // update dialog widgets X } X- X+ X if (strEqu(widgetname,"deftags")) { X add_tag(tags_cliktag,tags_batchAddTags,tagMcc); // add defined tag to tags_batchAddTags X zdialog_stuff(zdbatchAddTags,"batchAddTags",tags_batchAddTags); X@@ -7467,7 +7483,7 @@ X if (strEqu(event,"files")) // select images to add tags X { X if (flist) { // free prior list X- for (ii = 0; flist[ii]; ii++) X+ for (ii = 0; flist[ii]; ii++) X zfree(flist[ii]); X zfree(flist); X } X@@ -7479,14 +7495,14 @@ X for (ii = 0; flist[ii]; ii++); X else ii = 0; X batchAddTags_filecount = ii; X- X+ X sprintf(countmess,"%d files selected",batchAddTags_filecount); X zdialog_stuff(zd,"labcount",countmess); X } X- X+ X return 0; X } X- X+ X X /**************************************************************************/ X X@@ -7497,14 +7513,14 @@ X void m_batchDelTag(GtkWidget *, cchar *) // new v.10.9 X { X int batchDelTag_dialog_event(zdialog *zd, cchar *event); X- X+ X char **flist, *file; X char deltag[tagcc], reptag[tagcc]; X int ii, err; X zdialog *zd; X X zfuncs::F1_help_topic = "batch_delete_tag"; X- X+ X if (! Fexiftool) { // exiftool is required X zmessageACK(mWin,Bexiftoolmissing); X return; X@@ -7526,7 +7542,7 @@ X zdialog_add_widget(zd,"hbox","hb3","dialog",0,"space=5"); X zdialog_add_widget(zd,"button","files","hb3",Bselectfiles,"space=10"); X zdialog_add_widget(zd,"label","labcount","hb3","0 files selected","space=10"); X- X+ X zdialog_add_widget(zd,"hbox","hb4","dialog",0,"space=5"); X zdialog_add_widget(zd,"check","allfiles","hb4",ZTX("search all files"),"space=10"); X X@@ -7539,7 +7555,7 @@ X X flist = batchDelTag_filelist; // get selected files X if (! flist) goto cleanup; X- X+ X zdialog_fetch(zd,"deltag",deltag,tagcc); // get tag to delete X strTrim2(deltag); // remove leading and trailing blanks X strToLower(deltag); // use lower case for matching X@@ -7567,22 +7583,22 @@ X X if (*reptag) { // add replacement tag, if defined X err = add_tag(reptag,tags_filetags,tagFcc); X- if (err == 2) X+ if (err == 2) X zmessageACK(mWin,ZTX("%s \n too many tags"),file); X } X X save_filetags(file); // save tag changes X } X- X+ X write_popup_text("write","COMPLETED"); X write_popup_text("close",0); X- X+ X cleanup: X X zdialog_free(zd); X X if (flist) { X- for (ii = 0; flist[ii]; ii++) X+ for (ii = 0; flist[ii]; ii++) X zfree(flist[ii]); X zfree(flist); X } X@@ -7604,7 +7620,7 @@ X char filebuff[tagrecl], tagsbuff[tagrecl]; X char *ppv, *file, *tags, countmess[32]; X cchar *ppf; X- X+ X zdialog_fetch(zd,"deltag",deltag,tagcc); // get tag to delete X strTrim2(deltag); // remove leading and trailing blanks X strToLower(deltag); // use lower case for matching X@@ -7616,20 +7632,20 @@ X zd->zstat = 0; // keep dialog active X goto finish; X } X- X+ X if (! *deltag) { X zmessageACK(mWin,ZTX("no tag specified")); // v.11.01 X zd->zstat = 0; X goto finish; X } X- X+ X return 0; X } X X if (strEqu(event,"deltag")) // tag changed X { X if (flist) { // clear file list v.11.01 X- for (ii = 0; flist[ii]; ii++) X+ for (ii = 0; flist[ii]; ii++) X zfree(flist[ii]); X zfree(flist); X flist = 0; X@@ -7647,7 +7663,7 @@ X } X X if (flist) { // free prior list X- for (ii = 0; flist[ii]; ii++) X+ for (ii = 0; flist[ii]; ii++) X zfree(flist[ii]); X zfree(flist); X flist = 0; X@@ -7657,11 +7673,11 @@ X zdialog_stuff(zd,"allfiles",0); // reset "all files" checkbox v.11.01 X goto finish; X } X- X+ X if (strEqu(event,"allfiles")) X { X if (flist) { // clear file list X- for (ii = 0; flist[ii]; ii++) X+ for (ii = 0; flist[ii]; ii++) X zfree(flist[ii]); X zfree(flist); X flist = 0; X@@ -7669,7 +7685,7 @@ X X zdialog_fetch(zd,"allfiles",allfiles); // get checkbox "all files" X if (! allfiles) goto finish; // was unselected X- X+ X if (! *deltag) { X zmessageACK(mWin,ZTX("specify tag")); // v.11.01 X goto finish; X@@ -7696,7 +7712,7 @@ X X ppv = fgets_trim(tagsbuff,tagrecl,fidr); // next record X if (! ppv) break; X- if (! strnEqu(ppv,"date: ",6)) continue; // date: yyyy:mm:dd X+ if (! strnEqu(ppv,"date: ",6)) continue; // date: yyyy:mm:dd X X ppv = fgets_trim(tagsbuff,tagrecl,fidr); // next record X if (! ppv) break; X@@ -7704,7 +7720,7 @@ X X tags = ppv + 6; X strToLower(tags); // use lower case for matching X- X+ X for (ii = 1; ; ii++) // step thru file tags X { X ppf = strField(tags,tagdelims,ii); X@@ -7712,9 +7728,9 @@ X if (*ppf == ' ') continue; X if (strEqu(ppf,deltag)) break; // look for my tag X } X- X+ X if (! ppf) continue; // tag not found X- X+ X flist[nfiles] = strdupz(file,0,"batchDelTag"); X nfiles++; X if (nfiles == max_images-1) break; X@@ -7731,13 +7747,13 @@ X if (flist) // count files in list X for (ii = 0; flist[ii]; ii++); X else ii = 0; X- X+ X sprintf(countmess,"%d files selected",ii); // stuff file count into dialog X zdialog_stuff(zd,"labcount",countmess); X- X+ X return 0; X } X- X+ X X /**************************************************************************/ X X@@ -7781,7 +7797,7 @@ X ***/ X X zdsearchtags = zdialog_new(ZTX("Search Tags, Comments, File Names"),mWin,Bproceed,Bcancel,null); X- X+ X zdialog_add_widget(zdsearchtags,"hbox","hb1","dialog",0,"space=5"); X zdialog_add_widget(zdsearchtags,"vbox","vb1","hb1",0,"homog|space=3"); X zdialog_add_widget(zdsearchtags,"vbox","vb2","hb1",0,"homog|space=3|expand"); X@@ -7832,7 +7848,7 @@ X X searchtags_fixwidget(zdsearchtags,"deftags"); // setup tag selection via mouse X searchtags_fixwidget(zdsearchtags,"searchtags"); X- X+ X zdialog_stuff(zdsearchtags,"datefrom",searchDateFrom); // stuff previous date range X zdialog_stuff(zdsearchtags,"dateto",searchDateTo); X zdialog_stuff(zdsearchtags,"starsfrom",searchStarsFrom); X@@ -7840,7 +7856,7 @@ X zdialog_stuff(zdsearchtags,"searchtags",tags_searchtags); // stuff previous search tags X zdialog_stuff(zdsearchtags,"searchtext",tags_searchtext); // stuff previous search text X zdialog_stuff(zdsearchtags,"searchfiles",tags_searchfiles); // stuff previous search files X- X+ X zdialog_stuff(zdsearchtags,"alltags",0); // default any tags, text, files X zdialog_stuff(zdsearchtags,"anytags",1); X zdialog_stuff(zdsearchtags,"alltext",0); X@@ -7850,7 +7866,7 @@ X X load_deftags(); // stuff defined tags into dialog X deftags_stuff(zdsearchtags); X- X+ X return; X } X X@@ -7881,7 +7897,7 @@ X void searchtags_mouse(GtkTextView *widget, GdkEventButton *event, cchar *widgetname) X { X int mpx, mpy, cc; X- X+ X if (event->type != GDK_BUTTON_PRESS) return; X mpx = int(event->x); // mouse click position X mpy = int(event->y); X@@ -7898,7 +7914,7 @@ X del_tag(tags_cliktag,tags_searchtags); // remove tag from searchtags X zdialog_stuff(zdsearchtags,"searchtags",tags_searchtags); // update dialog widgets X } X- X+ X return; X } X X@@ -7921,12 +7937,12 @@ X struct stat statbuf; X X if (! zd->zstat) return 0; // wait for completion X- X+ X if (zd->zstat != 1) { X zdialog_free(zdsearchtags); // cancel X return 0; X } X- X+ X zd->zstat = 0; // keep dialog active v.10.12 X X zdialog_fetch(zd,"datefrom",searchDateFrom,10); // get search date range X@@ -7965,7 +7981,7 @@ X X Fstars = 0; X if (*searchStarsFrom || *searchStarsTo) Fstars = 1; // stars was given X- X+ X Ffiles = 0; X if (! blank_null(tags_searchfiles)) Ffiles = 1; // search /path*/file* was given X X@@ -7995,7 +8011,7 @@ X X fidr = fopen(search_index_file,"r"); // read search index file X if (! fidr) goto nodeftags; X- X+ X snprintf(resultsfile,199,"%s/search_results",get_zuserdir()); X fidw = fopen(resultsfile,"w"); // search results output file X if (! fidw) goto writerror; X@@ -8003,7 +8019,7 @@ X nfiles = 0; // matching files found X Faccept = 0; // no previous file X Freject = 1; X- X+ X while (true) X { X ppv = fgets_trim(indexbuff,tagrecl,fidr); // read next index file record X@@ -8020,7 +8036,7 @@ X fprintf(fidw,"%s\n",filebuff); // output matching filespec X nfiles++; X } X- X+ X if (! ppv) break; // EOF X X Faccept = Freject = 0; // initz. match and fail counts X@@ -8034,7 +8050,7 @@ X err=stat(filebuff,&statbuf); // check file exists X if (err) Freject++; X if (! S_ISREG(statbuf.st_mode)) Freject++; X- X+ X if (! Freject && Ffiles) // file name match is wanted X { X strToLower(lcfile,filebuff); X@@ -8048,7 +8064,7 @@ X else nfail++; X } X if (nmatch == 0) Freject++; // no match to any file X- if (Fallfiles && nfail) Freject++; // no match to all files X+ if (Fallfiles && nfail) Freject++; // no match to all files X if (! Freject) Faccept++; X } X } X@@ -8082,7 +8098,7 @@ X ppf = strField(tags,tagdelims,iif); X if (! ppf) { nfail++; break; } // count matches and fails X if (*ppf == ' ') continue; X- if (MatchWild(pps,ppf) == 0) { nmatch++; break; } // wildcard match X+ if (MatchWild(pps,ppf) == 0) { nmatch++; break; } // wildcard match X } X } X X@@ -8115,7 +8131,7 @@ X strncatv(textbuff,tagrecl,indexbuff+5,null); // save combined comments & caption X } X X- else X+ else X { X if (strlen(indexbuff) > 1) X printf("unknown tags record: %s \n",indexbuff); X@@ -8123,15 +8139,15 @@ X } X X fclose(fidr); X- X+ X err = fclose(fidw); X if (err) goto writerror; X- X+ X if (! nfiles) { X zmessageACK(mWin,ZTX("No matching images found")); X return 0; X } X- X+ X zdialog_free(zdsearchtags); // cancel dialog X X image_gallery(resultsfile,"initF",0,m_gallery2,mWin); // generate gallery of matching files X@@ -8160,22 +8176,22 @@ X X strToLower(textbuff); X nmatch = nfail = 0; X- X+ X for (iis = 1; ; iis++) // step thru search words X { X pps = strField(tags_searchtext,' ',iis); // (blank delimited, wildcards) X if (! pps) break; X if (*pps == ' ') continue; X- X+ X for (iif = 1; ; iif++) // step thru comments/captions (words) X { X ppf = strField(textbuff,text_delims,iif); X if (! ppf) { nfail++; break; } X if (*ppf == ' ') continue; X- if (MatchWild(pps,ppf) == 0) { nmatch++; break; } // wildcard match X+ if (MatchWild(pps,ppf) == 0) { nmatch++; break; } // wildcard match X } X } X- X+ X if (nmatch == 0) return 0; // no match to any word X if (Fmall && nfail) return 0; // no match to all words X return 1; X@@ -8183,7 +8199,7 @@ X X X /************************************************************************** X- functions to view and edit metadata: EXIF, IPTC, etc. X+ functions to view and edit metadata: EXIF, IPTC, etc. X ***************************************************************************/ X X // menu function and popup dialog to show EXIF data X@@ -8216,9 +8232,9 @@ X zmessageACK(mWin,Bexiftoolmissing); X return; X } X- X+ X if (! curr_file) return; X- X+ X if (arg > 0) length = arg; // change short/long report mode X X if (! zdexifview) // popup dialog if not already X@@ -8237,12 +8253,12 @@ X if (length == 1) // short report X { X snprintf(command,ccc,"exiftool -common -%s -%s -%s -%s -%s -%s \"%s\" ", X- exif_tags_key, exif_rating_key, exif_log_key, exif_comment_key, X+ exif_tags_key, exif_rating_key, exif_log_key, exif_comment_key, X exif_caption_key, exif_focal_length_key, curr_file); X } X- else X+ else X snprintf(command,ccc,"exiftool -e \"%s\" ",curr_file); // long, output everything X- X+ X widget = zdialog_widget(zdexifview,"exifdata"); // widget for output X wclear(widget); X X@@ -8278,18 +8294,18 @@ X char **pp2; X X int exif_edit_dialog_event(zdialog *zd, cchar *event); X- X+ X zfuncs::F1_help_topic = "edit_info"; // v.10.8 X X if (! Fexiftool) { // exiftool is required X zmessageACK(mWin,Bexiftoolmissing); X return; X } X- X+ X if (! curr_file) return; X X if (! zdexifedit) // popup dialog if not already v.10.8 X- { X+ { X zdexifedit = zdialog_new(ZTX("Edit Info"),mWin,Bfetch,Bsave,Bcancel,null); X zdialog_add_widget(zdexifedit,"vbox","hb1","dialog"); X zdialog_add_widget(zdexifedit,"hbox","hbkey","dialog",0,"space=5"); X@@ -8306,7 +8322,7 @@ X X if (*keyname) // update live dialog v.10.8 X { X- pp1[0] = keyname; // look for key data X+ pp1[0] = keyname; // look for key data X pp2 = exif_get(curr_file,pp1,1); X if (pp2[0]) { X strncpy0(keydata,pp2[0],999); X@@ -8328,9 +8344,9 @@ X cchar *pp1[1], *pp2[1]; X char **pp3; X int err; X- X+ X if (! zd->zstat) return 0; X- X+ X zdialog_fetch(zd,"keyname",keyname,40); X zdialog_fetch(zd,"keydata",keydata,1000); X strCompress(keyname); // remove blanks v.10.8 X@@ -8373,7 +8389,7 @@ X void m_exif_delete(GtkWidget *, cchar *menu) // new v.10.2 X { X int exif_delete_dialog_event(zdialog *zd, cchar *event); X- X+ X zdialog *zd; X X zfuncs::F1_help_topic = "delete_info"; // v.10.8 X@@ -8382,7 +8398,7 @@ X zmessageACK(mWin,Bexiftoolmissing); X return; X } X- X+ X if (! curr_file) return; X X zd = zdialog_new(ZTX("Delete Info"),mWin,Bapply,Bcancel,null); X@@ -8403,14 +8419,14 @@ X { X int kall, key1, err; X char keyname[40]; X- X+ X if (! zd->zstat) return 0; X X if (zd->zstat != 1) { // canceled X zdialog_free(zd); X return 1; X } X- X+ X zd->zstat = 0; // dialog remains active X X zdialog_fetch(zd,"kall",kall); X@@ -8423,10 +8439,10 @@ X else if (key1) X snprintf(command,ccc,"exiftool -m -q -overwrite_original -%s= \"%s\"",keyname,curr_file); X else return 1; X- X+ X err = system(command); X if (err) zmessageACK(mWin,"%s",wstrerror(err)); X- X+ X if (zdexifview) exif_view(0); // update exif view if active X X return 1; X@@ -8440,13 +8456,13 @@ X // if a key is missing, corresponding pointer is null X // returned strings belong to caller, are subject for zfree() X // up to 9 keynames may be requested per call X-// EXIF command: X+// EXIF command: X // exiftool -keyname1 -keyname2 ... "file" X-// command output: X+// command output: X // keyname1: keyvalue1 X // keyname2: keyvalue2 X // ... X-// The overhead for this call is about 0.1 seconds elapsed on a X+// The overhead for this call is about 0.1 seconds elapsed on a X // 2.67 GHz computer with a 10,000 rpm disk. X X char ** exif_get(cchar *file, cchar **keys, int nkeys) X@@ -8455,11 +8471,11 @@ X static char *rettext[10]; X int contx = 0, err, ii; X uint cc; X- X+ X if (nkeys < 1 || nkeys > 9) zappcrash("exif_get nkeys: %d",nkeys); X X strcpy(command,"exiftool -m -q -S -fast"); X- X+ X for (ii = 0; ii < nkeys; ii++) X { X rettext[ii] = null; X@@ -8477,13 +8493,13 @@ X { X cc = strlen(keys[ii]); X if (strncasecmp(pp,keys[ii],cc) == 0) // ignore case bugfix v.10.2 X- if (strlen(pp) > cc+2) X+ if (strlen(pp) > cc+2) X rettext[ii] = strdupz(pp+cc+2,0,"exif_data"); // check not empty X } X X zfree(pp); X } X- X+ X err = command_status(contx); X if (err) printf(" exif_get: %s \n",wstrerror(err)); // v.10.8 X X@@ -8495,7 +8511,7 @@ X X // create or change EXIF metadata for given image file and key(s) X // up to 9 keys may be processed X-// EXIF command: X+// EXIF command: X // exiftool -overwrite_original -keyname="keyvalue" ... "file" X // X // NOTE: exiftool replaces \n (newline) in "keyvalue" with "." (period) v.10.12 X@@ -8504,12 +8520,12 @@ X { X int ii, err; X char *pp; X- X+ X if (nkeys < 1 || nkeys > 9) zappcrash("exif_put nkeys: %d",nkeys); X- X+ X for (ii = 0; ii < nkeys; ii++) X if (! text[ii]) text[ii] = ""; // if null pointer use empty string X- X+ X for (ii = 0; ii < nkeys; ii++) // replace imbedded " with \" X if (strchr(text[ii],'"')) { // else exiftool command fails X pp = strdupz(text[ii],20,"exif_put"); // bugfix v.10.12 X@@ -8519,7 +8535,7 @@ X } X X strcpy(command,"exiftool -m -q -overwrite_original"); X- X+ X for (ii = 0; ii < nkeys; ii++) X strncatv(command,ccc," -",keys[ii],"=\"",text[ii],"\"",null); // "-exif:" replaced with "-" v.10.0 X strncatv(command,ccc," \"",file,"\"",null); X@@ -8542,7 +8558,7 @@ X X strcpy(command,"exiftool -m -q -tagsfromfile"); // exiftool -m -q -tagsfromfile "file1" X strncatv(command,ccc," \"",file1,"\"",null); X- X+ X strncatv(command,ccc," -all -icc_profile",null); // -all -icc_profile X X for (ii = 0; ii < nkeys; ii++) // -keyname="keyvalue" ... (options) X@@ -8550,7 +8566,7 @@ X strncatv(command,ccc," -",keys[ii],"=\"",text[ii],"\"",null); X X strncatv(command,ccc," \"",file2,"\""," -overwrite_original",null); // "file2" -overwrite_original X- X+ X err = system(command); X if (err) printf(" exiftool: %s \n",wstrerror(err)); X return err; X@@ -8562,13 +8578,13 @@ X // convert between EXIF and fotoxx tag date formats X // EXIF date: yyyy:mm:dd hh:mm:ss[.ss] X // tag date: yyyymmdd X-// X+// X X void exif_tagdate(cchar *exifdate, char *tagdate) X { X time_t tnow; X struct tm *snow; X- X+ X if (! exifdate || strlen(exifdate) < 10) { // bad EXIF date, use current date X tnow = time(0); X snow = localtime(&tnow); X@@ -8578,7 +8594,7 @@ X return; X } X X- strncpy(tagdate,exifdate,4); // convert X+ strncpy(tagdate,exifdate,4); // convert X strncpy(tagdate+4,exifdate+5,2); X strncpy(tagdate+6,exifdate+8,2); X tagdate[8] = 0; X@@ -8590,7 +8606,7 @@ X int cc; X time_t tnow; X struct tm *snow; X- X+ X if (! tagdate || strlen(tagdate) < 4) { X tnow = time(0); X snow = localtime(&tnow); X@@ -8690,9 +8706,9 @@ X X if (! curr_file) return; // no image X if (zdsela) return; // already active X- X+ X if (Fpreview) edit_fullsize(); // use full-size image X- X+ X if (! Fpxm16) { // create Fpxm16 if not already X mutex_lock(&Fpixmap_lock); X Fpxm16 = f_load(curr_file,16); X@@ -8712,7 +8728,7 @@ X | [x] my mouse Blend Width [__] | X | [Show] [Hide] [Color] [Finish] [Enable] [Disable] [Invert] [Delete] [Done] | X |_____________________________________________________________________________| X- X+ X ***/ X X zdsela = zdialog_new(title,mWin,null); X@@ -8791,7 +8807,7 @@ X int select_dialog_event(zdialog *zd, cchar *event) X { X int ii, cc, mymouse; X- X+ X if (strEqu(event,"done") || zd->zstat) // done or cancel X { X freeMouse(); // disconnect mouse function v.10.12 X@@ -8799,7 +8815,7 @@ X zdialog_free(zdsela); // kill dialog X return 0; X } X- X+ X if (! sa_pixseq) { // start new area if none v.10.8 X cc = Fww * Fhh; X sa_pixseq = (uint16 *) zmalloc(2*cc,"pixseq"); X@@ -8824,7 +8840,7 @@ X X if (strEqu(event,"colormatch")) // color match range, 0 to 99.9 X zdialog_fetch(zdsela,"colormatch",sa_colormatch); X- X+ X if (strEqu(event,"firewall")) // color select firewall on/off v.10.11 X zdialog_fetch(zdsela,"firewall",sa_firewall); X X@@ -8852,7 +8868,7 @@ X else sa_pixRGB = &red; X sa_show(1); X } X- X+ X if (strstr("finish delete enable disable invert blendwidth",event)) { X paint_toparc(2); // erase radius circle X gdk_window_set_cursor(drWin->window,null); // normal cursor v.11.03 X@@ -8863,7 +8879,7 @@ X if (strEqu(event,"enable")) sa_enable(); // enable area X if (strEqu(event,"disable")) sa_disable(); // disable area X if (strEqu(event,"invert")) sa_invert(); // invert area X- X+ X if (strEqu(event,"blendwidth") && Factivearea) { // blend width changed X sa_edgecalc(); // edge calc. unless already X if (sa_calced && zdedit) { // edit is active X@@ -8913,7 +8929,7 @@ X mwpaint2(); X return; X } X- X+ X if (Mxdrag || Mydrag) // mouse drag X { X if (Mxdown != mdx0 || Mydown != mdy0) { // new drag initiated X@@ -8931,11 +8947,11 @@ X my2 = Mydrag; X sa_geom2 = 1; X } X- X+ X if (! sa_geom2) return; X- X+ X sa_nextseq(); X- X+ X if (sa_mode == 1) // draw rectangle X { X sa_draw_line(mx1,my1,mx2,my1); X@@ -8943,11 +8959,11 @@ X sa_draw_line(mx2,my2,mx1,my2); X sa_draw_line(mx1,my2,mx1,my1); X } X- X+ X if (sa_mode == 2) // draw ellipse X { X double a, b, a2, b2; X- double x, y, x2, y2, cx, cy; X+ double x, y, x2, y2, cx, cy; X int px, py; X X a = abs(mx2 - mx1) / 2.0; // ellipse constants from X@@ -8956,7 +8972,7 @@ X b2 = b * b; X cx = (mx1 + mx2) / 2.0; // center of ellipse X cy = (my1 + my2) / 2.0; X- X+ X for (y = -b; y < b; y++) // step through y values X { X y2 = y * y; X@@ -8981,7 +8997,7 @@ X sa_draw1pix(px,py); X } X } X- X+ X mwpaint2(); X return; X } X@@ -9000,7 +9016,7 @@ X X sa_thresh = 4.0 / Mscale + 1; // mouse pixel distance threshold X click = newseq = 0; X- X+ X if (LMclick || Mxdrag || Mydrag) // left mouse click or mouse drag X { X if (LMclick) // left mouse click X@@ -9028,7 +9044,7 @@ X drag++; X click = 0; X } X- X+ X if (Mbutton == 3) // right mouse >> erase X { X while (true) { X@@ -9046,7 +9062,7 @@ X zmessageACK(mWin,ZTX("exceed %d edits"),sa_maxseq); // cannot continue X return; X } X- X+ X if (sa_currseq == 0 && newseq) // 1st pixel(s) of 1st sequence X { X sa_nextseq(); // set next (1st) sequence no. v.10.8 X@@ -9055,12 +9071,12 @@ X sa_endpy[sa_currseq] = my2; X return; X } X- X+ X if (click) { X mx1 = sa_endpx[sa_currseq]; // prior sequence end pixel X my1 = sa_endpy[sa_currseq]; // (before this click) X } X- X+ X if (drag) { X if (newseq) thresh = 2 * sa_thresh; // new drag threshold X else thresh = 5 * sa_thresh; // continuation drag threshold X@@ -9076,10 +9092,10 @@ X sa_nextseq(); // set next sequence no. v.10.8 X drag = 1; // drag length within sequence X } X- X+ X if (sa_mode == 4) sa_follow_edge(mx1,my1,mx2,my2); // follow edge or draw line X else sa_draw_line(mx1,my1,mx2,my2); // from end pixel to mouse X- X+ X sa_endpx[sa_currseq] = mx2; // set end pixel for this sequence X sa_endpy[sa_currseq] = my2; X } X@@ -9090,7 +9106,7 @@ X sa_unselect_pixels(); // remove latest selection v.10.8 X mwpaint2(); X } X- X+ X return; X } X X@@ -9131,7 +9147,7 @@ X } X } X } X- X+ X if (npx + npy) return sqrt(mindist) + 0.5; X return 0; X } X@@ -9139,19 +9155,19 @@ X X // draw a line between two given pixels X // add all in-line pixels to sa_pixseq[] X- X+ X void sa_draw_line(int px1, int py1, int px2, int py2) X { X void sa_draw1pix(int px, int py); X X int pxm, pym; X double slope; X- X+ X if (px1 == px2 && py1 == py2) { // only one pixel X sa_draw1pix(px1,py1); X return; X } X- X+ X if (abs(py2 - py1) > abs(px2 - px1)) { X slope = 1.0 * (px2 - px1) / (py2 - py1); X if (py2 > py1) { X@@ -9207,24 +9223,24 @@ X void sa_follow_edge(int px1, int py1, int px2, int py2) // v.10.8 X { X double sa_get_contrast(int px, int py); X- X+ X double px3, py3, px4, py4, px5, py5, px6, py6; X double dx, dy, dist, contrast, maxcontrast; X- X+ X px3 = px1; // p3 progresses from p1 to p2 X py3 = py1; X- X+ X while (true) X { X dx = px2 - px3; X dy = py2 - py3; X- X+ X dist = sqrt(dx * dx + dy * dy); // last segment X if (dist < 3) break; X- X+ X px4 = px3 + dx / dist; // p4 = p3 moved toward p2 X py4 = py3 + dy / dist; X- X+ X maxcontrast = 0; X px6 = px4; X py6 = py4; X@@ -9241,13 +9257,13 @@ X maxcontrast = contrast; X } X } X- X+ X sa_draw_line(px3,py3,px6,py6); // draw p3 to p6 X X px3 = px6; // next p3 X py3 = py6; X } X- X+ X sa_draw_line(px3,py3,px2,py2); X return; X } X@@ -9263,10 +9279,10 @@ X double red, green, blue; X double contrast, maxcontrast = 0; X double f65k = 1.0 / 65535.0; X- X+ X if (px < 1 || px > Fww-2) return 0; // avoid edge pixels X if (py < 1 || py > Fhh-2) return 0; X- X+ X for (ii = 0; ii < 4; ii++) // compare pixels around target X { // e.g. (px-1,py) to (px+1,py) X qx = map[ii][0]; X@@ -9280,7 +9296,7 @@ X contrast = 1.0 - contrast; // max. contrast = 1.0 X if (contrast > maxcontrast) maxcontrast = contrast; X } X- X+ X return maxcontrast; X } X X@@ -9293,7 +9309,7 @@ X X int cc; X static int mxdown, mydown, drag = 0; X- X+ X sa_radius = sa_colorradius; // use mouse radius X sa_radius2 = sa_radius * sa_radius; X X@@ -9305,7 +9321,7 @@ X X if (sa_stackdirec) zfree(sa_stackdirec); // allocate pixel search stack X if (sa_stackii) zfree(sa_stackii); X- cc = Fww * Fhh; X+ cc = Fww * Fhh; X sa_stackdirec = zmalloc(cc,"stack.direc"); X sa_stackii = (int *) zmalloc(4*cc,"stack.ii"); X sa_maxstack = cc; X@@ -9368,7 +9384,7 @@ X double match1, match2, ff = 1.0 / 65536.0; X double dred, dgreen, dblue; X char direc; X- X+ X match1 = 0.01 * sa_colormatch; // color match level, 0.01 to 1.0 X X px = sa_mousex; X@@ -9392,7 +9408,7 @@ X if (py < 0 || py >= Fhh) continue; X X matchpix = PXMpix(Fpxm16,px,py); // get color at mouse position X- X+ X for (ii = 0; ii < sa_Nmatch; ii++) // see if color is already included X { X dred = ff * abs(sa_matchRGB[ii][0] - matchpix[0]); // 0 = perfect match X@@ -9401,8 +9417,8 @@ X match2 = (1.0 - dred) * (1.0 - dgreen) * (1.0 - dblue); // 1 = perfect match X if (match2 >= match1) break; // matches close enough X } X- X- if (ii == sa_Nmatch) { // no close match X+ X+ if (ii == sa_Nmatch) { // no close match X sa_matchRGB[ii][0] = matchpix[0]; // add new match color to list X sa_matchRGB[ii][1] = matchpix[1]; X sa_matchRGB[ii][2] = matchpix[2]; X@@ -9410,7 +9426,7 @@ X if (sa_Nmatch == 1000) goto startsearch; // capacity limit X } X } X- X+ X startsearch: X X sa_Ncurrseq = 0; // count newly selected pixels X@@ -9434,7 +9450,7 @@ X kk = sa_Nstack - 1; // get last pixel in stack X ii = sa_stackii[kk]; X direc = sa_stackdirec[kk]; X- X+ X py = ii / Fww; // reconstruct px, py X px = ii - Fww * py; X X@@ -9442,7 +9458,7 @@ X sa_Nstack--; X continue; X } X- X+ X if (sa_Nstack > 1) { X ii = sa_Nstack - 2; // get prior pixel in stack X ii = sa_stackii[ii]; X@@ -9474,7 +9490,7 @@ X X if (npx < 0 || npx >= Fww) continue; // pixel off the edge X if (npy < 0 || npy >= Fhh) continue; X- X+ X ii = npy * Fww + npx; X if (sa_pixselc[ii]) continue; // already in current selection v.10.8 X X@@ -9517,7 +9533,7 @@ X void sa_radius_mousefunc() X { X int ii, px, py, rx, ry; X- X+ X sa_radius = sa_mouseradius; // pixel selection radius X sa_radius2 = sa_radius * sa_radius; X X@@ -9536,7 +9552,7 @@ X sa_nextseq(); // set next sequence no. v.10.8 X return; // (if some pixels mapped) X } X- X+ X for (rx = -sa_radius; rx <= sa_radius; rx++) // loop every pixel in radius X for (ry = -sa_radius; ry <= sa_radius; ry++) X { X@@ -9547,7 +9563,7 @@ X if (py < 0 || py >= Fhh) continue; X X ii = Fww * py + px; X- X+ X if (Mbutton == 3) // right mouse button X sa_pixseq[ii] = 0; // remove pixel from select area X X@@ -9584,24 +9600,24 @@ X void sa_unselect_pixels() X { X if (! sa_currseq) return; // no pixels mapped, do nothing X- X+ X for (int ii = 0; ii < Fww * Fhh; ii++) X { X if (sa_pixseq[ii] != sa_currseq) continue; // unmap current selection X sa_pixseq[ii] = 0; X } X- X+ X if (sa_currseq > sa_initseq) { // reduce sequence no. v.10.8 X sa_currseq--; X sa_Ncurrseq = 1; // unknown but > 0 X } X else sa_Ncurrseq = 0; // initial sequence no. reached X- X+ X return; X } X X X-// Finish select area - map pixels enclosed by edge pixels X+// Finish select area - map pixels enclosed by edge pixels X // into sa_pixisin[ii]: 0/1/2 = outside/edge/inside, ii=py*Fww+px X // total count = sa_Npixel X X@@ -9622,7 +9638,7 @@ X X sa_Npixel = Factivearea = 0; // area disabled, unfinished X sa_hole = 0; // no hole detected yet X- X+ X sa_show(1); // show outline X X sa_minx = Fww - 1; X@@ -9649,7 +9665,7 @@ X if (sa_miny < 0) sa_miny = 0; X sa_maxy += 10; X if (sa_maxy > Fhh-1) sa_maxy = Fhh - 1; X- X+ X if (sa_pixisin) zfree(sa_pixisin); // allocate pixisin[] X cc = Fww * Fhh * 2; X sa_pixisin = (uint16 *) zmalloc(cc,"pixisin"); X@@ -9667,13 +9683,13 @@ X } X X if (npix < 20) return; // ridiculous X- X+ X for (py = sa_miny; py <= sa_maxy; py++) // find edge pixels X for (px = sa_minx; px <= sa_maxx; px++) X { X ii = py * Fww + px; X if (! sa_pixisin[ii]) continue; X- X+ X if (px == 0 || px == Fww-1 || py == 0 || py == Fhh-1) // edge of image X goto edgepix1; X X@@ -9703,11 +9719,11 @@ X if (sa_stackii) zfree(sa_stackii); X sa_stackii = (int *) zmalloc(cc*4,"stack.ii"); X sa_maxstack = cc; X- X+ X safinzd = zdialog_new(ZTX("finish area"),mWin,Bdone,Bcancel,null); // dialog for user to click inside X zdialog_add_widget(safinzd,"label","fmess","dialog",fmess); // all enclosed areas X zdialog_add_widget(safinzd,"label","smess","dialog","status:"); X- X+ X takeMouse(safinzd,sa_finish_mousefunc,dragcursor); // connect mouse function v.11.03 X X zdialog_run(safinzd,sa_finish_dialog_event); // run dialog, parallel X@@ -9740,7 +9756,7 @@ X kk = sa_Nstack - 1; // get last pixel in stack X ii = sa_stackii[kk]; X direc = sa_stackdirec[kk]; X- X+ X py = ii / Fww; // reconstruct px, py X px = ii - Fww * py; X X@@ -9759,7 +9775,7 @@ X ppx = px - 1; // if only one, assume prior = left X ppy = py; X } X- X+ X if (direc == 'r') { // push next right pixel into stack X npx = px + px - ppx; X npy = py + py - ppy; X@@ -9814,7 +9830,7 @@ X mwpaint2(); X return 0; X } X- X+ X if (! sa_pixisin) return 0; // bugfix v.11.01 X X npix = 0; X@@ -9826,7 +9842,7 @@ X if (! sa_pixisin[ii]) continue; // outside of selected area X X npix++; X- X+ X if (px == 0 || px == Fww-1 || py == 0 || py == Fhh-1) // on edge of image v.10.12 X goto edgepix; X X@@ -9909,7 +9925,7 @@ X void sa_show(int flag) X { X int px, py, ii, kk; X- X+ X if (! sa_pixseq) return; // no area X if (sa_mode == 7) return; // a whole image area X if (Fpreview) return; // preview mode, area ignored X@@ -9920,13 +9936,13 @@ X mwpaint2(); // erase area outline v.10.8 X return; X } X- X+ X for (py = 0; py < Fhh; py++) // find pixels in area bugfix v.10.9 X for (px = 0; px < Fww; px++) X { X ii = py * Fww + px; X if (! sa_pixseq[ii]) continue; // outside of area X- X+ X if (px == 0 || px == Fww-1) goto edgepixel; // edge of image = edge pixel v.10.12 X if (py == 0 || py == Fhh-1) goto edgepixel; X X@@ -9988,7 +10004,7 @@ X { X ii = py * Fww + px; X jj = sa_pixisin[ii]; // 0/1/2+ = outside/edge/inside X- X+ X if (px == 0 || px == Fww-1 || py == 0 || py == Fhh-1) { // pixel on image edge v.10.12 X if (jj == 0) { X sa_pixisin[ii] = sa_pixseq[ii] = 1; // outside pixel >> edge pixel X@@ -10007,11 +10023,11 @@ X kk++; // count X } X } X- X+ X sa_Npixel = kk; // new select area pixel count X sa_calced = sa_blend = 0; // edge calculation missing X if (zdsela) zdialog_stuff(zdsela,"blendwidth",0); // reset blend width v.11.01 X- X+ X sa_minx = Fww - 1; // new enclosing rectangle bugfix v.11.01 X sa_maxx = 0; X sa_miny = Fhh - 1; X@@ -10064,7 +10080,7 @@ X void sa_edgecalc() X { X using namespace sa_edgecalc_names; X- X+ X int edgecalc_dialog_event(zdialog*, cchar *event); X void * edgecalc_thread(void *); X X@@ -10076,11 +10092,11 @@ X if (! Factivearea) sa_finish(); // finish if needed X if (! Factivearea) return; // no finished area X if (sa_mode == 7) return; // a whole image area X- X+ X for (ii = nn = 0; ii < Fww * Fhh; ii++) // count edge pixels in select area X if (sa_pixisin[ii] == 1) nn++; X if (! nn) return; // none, area is entire image? v.10.9 X- X+ X zd = zdialog_new(ZTX("Area Edge Calc"),mWin,Bcancel,null); // start dialog for user cancel X zdialog_add_widget(zd,"label","lab1","dialog",zectext,"space=10"); X zdialog_run(zd,edgecalc_dialog_event); X@@ -10089,7 +10105,7 @@ X cc = Fww * Fhh * 2; // allocate memory for calculations X sa_edgedist = (uint16 *) zmalloc(cc,"edge.dist"); X memset(sa_edgedist,0,cc); X- X+ X sa_edgepx = (uint16 *) zmalloc(nn*2,"edge.px"); // allocate memory X sa_edgepy = (uint16 *) zmalloc(nn*2,"edge.py"); X X@@ -10109,13 +10125,13 @@ X X SB_goal = sa_Npixel; X for (ii = 0; ii < 8; ii++) SB_done[ii] = 0; // v.11.03 X- X+ X for (ii = 0; ii < Nwt; ii++) // start worker threads to calculate X start_wt(edgecalc_thread,&wtnx[ii]); // sa_pixisin[] edge distances X wait_wts(); // wait for completion X X SB_goal = 0; // v.9.6 X- X+ X zdialog_free(zd); // kill dialog X zfree(sa_edgedist); // free memory X zfree(sa_edgepx); X@@ -10147,7 +10163,7 @@ X void * edgecalc_thread(void *arg) // worker thread function X { X using namespace sa_edgecalc_names; X- X+ X void edgecalc_f1(int px, int py, int index); X void edgecalc_f2(int px, int py, int index); X X@@ -10165,7 +10181,7 @@ X edgecalc_f1(px,py,index); // calculate edge distance X if (Fkillfunc) exit_wt(); X } X- X+ X for (ii = index; ii < Fww * Fhh; ii += Nwt) // do all pixels v.9.6 X { X if (! sa_pixisin[ii]) continue; X@@ -10189,18 +10205,18 @@ X X X // Find the nearest edge pixel for a given pixel. X-// For all pixels in a line from the given pixel to the edge pixel, X+// For all pixels in a line from the given pixel to the edge pixel, X // the same edge pixel can be used to compute edge distance. X X void edgecalc_f1(int px1, int py1, int index) X { X using namespace sa_edgecalc_names; X- X+ X int ii, px2, py2; X uint dist2, mindist2; X int epx, epy, pxm, pym, dx, dy, inc; X double slope; X- X+ X mindist2 = 2000000000; X epx = epy = 0; X X@@ -10217,7 +10233,7 @@ X epy = py2; X } X } X- X+ X if (abs(epy - py1) > abs(epx - px1)) { // find all pixels along a line X slope = 1.0 * (epx - px1) / (epy - py1); // to the edge pixel X if (epy > py1) inc = 1; X@@ -10257,7 +10273,7 @@ X void edgecalc_f2(int px1, int py1, int index) // calculate 1 pixel X { X using namespace sa_edgecalc_names; X- X+ X int ii, kk, px2, py2; X uint dist2, mindist2; X int epx, epy, dx, dy; X@@ -10320,7 +10336,7 @@ X if (! Factivearea) return; X sa_edgecalc(); // do edge calc if not already X sa_show(0); X- X+ X pxmin = Fww; X pxmax = 0; X pymin = Fhh; X@@ -10336,17 +10352,17 @@ X if (py > pymax) pymax = py; X if (py < pymin) pymin = py; X } X- X+ X PXM_free(sacp_image16); // free prior if any X PXM_free(sacp_info16); X PXM_free(sacpR_image16); X PXM_free(sacpR_info16); X- X+ X sacp_ww = pxmax - pxmin + 1; // new area image PXM X sacp_hh = pymax - pymin + 1; X sacp_image16 = PXM_make(sacp_ww,sacp_hh,16); X sacp_info16 = PXM_make(sacp_ww,sacp_hh,16); // new info PXM X- X+ X for (ii = 0; ii < Fww * Fhh; ii++) // find pixels in select area X { X if (! sa_pixisin[ii]) continue; // 0/1/2+ = outside/edge/inside edge distance X@@ -10388,7 +10404,7 @@ X if (! sacp_image16) return; // nothing to paste X sa_delete(); // delete select area if present X if (! edit_setup("paste",0,0)) return; // setup edit for paste X- X+ X sacp_resize = 1.0; // size = 1x X sacp_blend = 1; // edge blend = 1 X sacp_angle = 0; // angle = 0 X@@ -10400,9 +10416,9 @@ X sacpR_hh = sacp_hh; // (initially 1x, 0 rotation) X sacpR_image16 = PXM_copy(sacp_image16); X sacpR_info16 = PXM_copy(sacp_info16); X- X+ X sacp_porg = 0; // no image paste location yet X- X+ X zdedit = zdialog_new(ZTX("Paste Image"),mWin,Bdone,Bcancel,null); X zdialog_add_widget(zdedit,"hbox","hb0","dialog",0,"space=8"); X zdialog_add_widget(zdedit,"label","lab1","hb0",dragmess,"space=8"); X@@ -10440,7 +10456,7 @@ X X X // Dialog event and completion callback function X-// Get dialog values and convert image. When done, commit edited image X+// Get dialog values and convert image. When done, commit edited image X // (with pasted area) and set up a new select area for the pasted area, X // allowing further editing of the area. X X@@ -10452,7 +10468,7 @@ X X int mymouse, ww, hh; X PXM *pxm_temp; X- X+ X if (zd->zstat) // dialog completed X { X freeMouse(); // disconnect mouse X@@ -10462,7 +10478,7 @@ X sa_delete(); X return 0; X } X- X+ X edit_done(); // commit the edit (pasted image) X select_paste_makearea(); // make equivalent select area X PXM_free(sacpR_image16); // free memory X@@ -10479,7 +10495,7 @@ X X if (strstr(event,"%") || strstr(event,"°")) // new size or angle X { X- if (strEqu(event,"+.1%")) sacp_resize *= 1.001; X+ if (strEqu(event,"+.1%")) sacp_resize *= 1.001; X if (strEqu(event,"+1%")) sacp_resize *= 1.01; X if (strEqu(event,"+10%")) sacp_resize *= 1.10; X if (strEqu(event,"-.1%")) sacp_resize *= 0.999001; X@@ -10531,13 +10547,13 @@ X int cc, ii; X int px1, py1, px2, py2; X uint16 *pix1, *pix2; X- X+ X sa_delete(); // delete old area X X cc = 2 * Fww * Fhh; X sa_pixseq = (uint16 *) zmalloc(cc,"pixseq"); // pixel map for new area X memset(sa_pixseq,0,cc); X- X+ X for (py1 = 0; py1 < sacpR_hh; py1++) // map non-transparent pixels X for (px1 = 0; px1 < sacpR_ww; px1++) // into sa_pixseq[] X { X@@ -10566,7 +10582,7 @@ X X int mx1, my1, mx2, my2; X static int mdx0, mdy0, mdx1, mdy1; X- X+ X if (LMclick) { // left mouse click X LMclick = 0; X sacp_orgx = Mxclick - sacpR_ww / 2; // position image at mouse v.10.11 X@@ -10579,7 +10595,7 @@ X if (Mxposn < sacp_orgx || Mxposn > sacp_orgx + sacpR_ww || // mouse outside select area X Myposn < sacp_orgy || Myposn > sacp_orgy + sacpR_hh) X gdk_window_set_cursor(drWin->window,0); // set normal cursor v.11.03 X- else X+ else X gdk_window_set_cursor(drWin->window,dragcursor); // set drag cursor v.11.03 X X if (Mxdrag + Mydrag == 0) return; // no drag underway X@@ -10595,12 +10611,12 @@ X my2 = Mydrag; X mdx1 = mx2; // next drag start X mdy1 = my2; X- X+ X sacp_orgx += (mx2 - mx1); // move position of select area X sacp_orgy += (my2 - my1); // by mouse drag amount X select_paste_pixmap(); // re-copy area to new position X X- return; X+ return; X } X X X@@ -10611,7 +10627,7 @@ X int px1, py1, px3, py3, opac, dist; X uint16 *pix1, *pix3; X double f1, f2; X- X+ X if (sacp_porg) // prior area overlap rectangle X { X for (py1 = 0; py1 < sacp_phh; py1++) // restore original image pixels v.10.11 X@@ -10628,8 +10644,8 @@ X pix3[2] = pix1[2]; X } X } X- X- for (py1 = 0; py1 < sacpR_hh; py1++) // copy paste area pixels to new X+ X+ for (py1 = 0; py1 < sacpR_hh; py1++) // copy paste area pixels to new X for (px1 = 0; px1 < sacpR_ww; px1++) // image overlap rectangle X { X pix1 = PXMpix(sacpR_info16,px1,py1); // opacity and edge distance X@@ -10690,7 +10706,7 @@ X pfile2 = strdupz(pfile1,0,"select_open"); X pp = strrchr(pfile2,'.'); X strcpy(pp,".info"); X- X+ X PXM_free(sacp_image16); // free prior if any X PXM_free(sacp_info16); X X@@ -10728,7 +10744,7 @@ X if (! Factivearea) sa_finish(); // finish select area if not already X if (Factivearea) m_select_copy(0,0); // copy select area to memory X if (! sacp_image16) return; // no active area, none in memory X- X+ X pp = zgetfile1(ZTX("save select area to a file"),"save",saved_areas_dirk); X if (! pp) return; X X@@ -10853,7 +10869,7 @@ X double px, py, xval, yval; X uint8 *pixel; X spcdat *sd = Mspcdat; X- X+ X if (zd->zstat) { // done, kill dialog X zfree(Mspcdat); // free curve edit memory X Mspcdat = 0; X@@ -10878,7 +10894,7 @@ X sa_blend = 255; // "blend width" = 255 X Factivearea = 1; // area is active X } X- X+ X if (strEqu(event,"load")) { // load saved curve v.11.02 X spccurve_load(sd); X if (zdedit) zdialog_send_event(zdedit,"blendwidth"); // notify edit dialog X@@ -10975,7 +10991,7 @@ X if (! curr_file) return; // no image X if (zdsela) return; // select area already active X if (Fpreview) edit_fullsize(); // use full-size image X- X+ X if (! Fpxm16) { // create Fpxm16 if not already X mutex_lock(&Fpixmap_lock); X Fpxm16 = f_load(curr_file,16); X@@ -10992,7 +11008,7 @@ X | [x] my mouse [reset] | X | [done] | X |____________________________________________| X- X+ X ***/ X X zdsela = zdialog_new(title,mWin,Bdone,null); X@@ -11008,7 +11024,7 @@ X zdialog_add_widget(zdsela,"hbox","hbr","dialog",0,"space=5"); X zdialog_add_widget(zdsela,"check","mymouse","hbr",ZTX("my mouse"),"space=5"); X zdialog_add_widget(zdsela,"button","reset","hbr",ZTX("reset"),"space=20"); X- X+ X select_edit_radius = 50; X select_edit_cpower = 50; X select_edit_epower = 0; X@@ -11069,10 +11085,10 @@ X X if (strEqu(event,"edge")) X zdialog_fetch(zd,"edge",select_edit_epower); // set mouse edge power X- X+ X if (strEqu(event,"reset")) X sa_delete(); // reset select area X- X+ X return 1; X } X X@@ -11084,12 +11100,12 @@ X int ii, cc, px, py, rx, ry; X int radius, radius2, cpower, epower; X int rad, rad2, power; X- X+ X if (! zdedit) { // no active edit X freeMouse(); X return; X } X- X+ X if (! sa_pixisin) // area deleted X { X cc = Fww * Fhh * 2; // allocate pixisin[] for new area X@@ -11125,7 +11141,7 @@ X X if (Mbutton != 1 && Mbutton != 3) // button released X return; X- X+ X for (rx = -radius; rx <= radius; rx++) // loop every pixel in radius X for (ry = -radius; ry <= radius; ry++) X { X@@ -11139,7 +11155,7 @@ X ii = Fww * py + px; X rad = sqrt(rad2); X power = cpower + rad / radius * (epower - cpower); // power at pixel radius X- X+ X if (Mbutton == 1) // left mouse button X { // increase edit power X sa_pixisin[ii] += power; X@@ -11177,7 +11193,7 @@ X cchar *wbhelp = ZTX("Click white or gray image location"); X X zfuncs::F1_help_topic = "white_balance"; // v.10.8 X- X+ X if (! edit_setup("whitebal",1,2)) return; // setup edit: preview X X zdedit = zdialog_new(wbtitle,mWin,Bdone,Bcancel,null); X@@ -11210,7 +11226,7 @@ X else edit_cancel(); // cancel or destroy X return 0; X } X- X+ X if (strEqu(event,"undo")) edit_undo(); // v.10.2 X if (strEqu(event,"redo")) edit_redo(); // v.10.3 X if (strEqu(event,"blendwidth")) signal_thread(); // v.10.3 X@@ -11224,18 +11240,18 @@ X double red, green, blue, rgbmean; X char work[40]; X uint16 *ppix16; X- X+ X if (! LMclick) return; X- X+ X LMclick = 0; X px = Mxclick; // mouse click position X py = Myclick; X- X+ X if (px < 2) px = 2; // pull back from edge X if (px > E3ww-3) px = E3ww-3; X if (py < 2) py = 2; X if (py > E3hh-3) py = E3hh-3; X- X+ X red = green = blue = 0; X X for (dy = -2; dy <= 2; dy++) // 5x5 block around mouse position X@@ -11246,8 +11262,8 @@ X green += ppix16[1]; X blue += ppix16[2]; X } X- X- red = red / 25.0; // mean RGB levels X+ X+ red = red / 25.0; // mean RGB levels X green = green / 25.0; X blue = blue / 25.0; X rgbmean = (red + green + blue) / 3.0; X@@ -11263,7 +11279,7 @@ X X snprintf(work,40,"%7.3f %7.3f %7.3f",red/256,green/256,blue/256); X zdialog_stuff(zdedit,"rgb",work); X- X+ X return; X } X X@@ -11277,7 +11293,7 @@ X while (true) X { X thread_idle_loop(); // wait for work or exit request X- X+ X for (int ii = 0; ii < Nwt; ii++) // start worker threads X start_wt(whitebal_wthread,&wtnx[ii]); X wait_wts(); // wait for completion X@@ -11310,11 +11326,11 @@ X X pix1 = PXMpix(E1pxm16,px,py); // input pixel X pix3 = PXMpix(E3pxm16,px,py); // output pixel X- X+ X red1 = pix1[0]; X green1 = pix1[1]; X blue1 = pix1[2]; X- X+ X red3 = whitebal_red * red1; // change color ratios X green3 = whitebal_green * green1; X blue3 = whitebal_blue * blue1; X@@ -11326,11 +11342,11 @@ X green3 = dnew * green3 + dold * green1; X blue3 = dnew * blue3 + dold * blue1; X } X- X+ X brmax = red3; // brmax = brightest color X if (green3 > brmax) brmax = green3; X if (blue3 > brmax) brmax = blue3; X- X+ X if (brmax > 65535) { // if overflow, reduce X brmax = 65535 / brmax; X red3 = red3 * brmax; X@@ -11342,7 +11358,7 @@ X pix3[1] = green3; X pix3[2] = blue3; X } X- X+ X exit_wt(); X return 0; // not executed, stop gcc warning X } X@@ -11388,12 +11404,12 @@ X else edit_cancel(); X return 0; X } X- X+ X if (strEqu(event,"b&wpos")) mode = 1; X if (strEqu(event,"b&wneg")) mode = 2; X if (strEqu(event,"colpos")) mode = 3; X if (strEqu(event,"colneg")) mode = 4; X- X+ X edit_zapredo(); // delete redo copy X X for (py = 0; py < E3hh; py++) X@@ -11404,28 +11420,28 @@ X red = pix1[0]; X green = pix1[1]; X blue = pix1[2]; X- X+ X if (mode == 1) // black and white positive X red = green = blue = (red + green + blue) / 3; X- X+ X else if (mode == 2) // black and white negative X red = green = blue = 65535 - (red + green + blue) / 3; X- X+ X if (mode == 3) { /** do nothing **/ } // color positive X- X+ X if (mode == 4) { // color negative X red = 65535 - red; X green = 65535 - green; X- blue = 65535 - blue; X+ blue = 65535 - blue; X } X- X+ X pix3 = PXMpix(E3pxm16,px,py); X X pix3[0] = red; X pix3[1] = green; X pix3[2] = blue; X } X- X+ X Fmodified = 1; X mwpaint2(); X X@@ -11449,7 +11465,7 @@ X cchar *title = ZTX("Flatten Brightness Distribution"); X X zfuncs::F1_help_topic = "flatten"; // v.10.8 X- X+ X if (! edit_setup("flatten",1,2)) return; // setup edit: preview, select area OK X X zdedit = zdialog_new(title,mWin,Bdone,Bcancel,null); X@@ -11459,7 +11475,7 @@ X X zdialog_resize(zdedit,300,0); X zdialog_run(zdedit,flatten_dialog_event); // run dialog - parallel X- X+ X flatten_value = 0; X start_thread(flatten_thread,0); // start working thread X return; X@@ -11476,7 +11492,7 @@ X else edit_cancel(); // cancel or destroy X return 0; X } X- X+ X if (strEqu(event,"undo")) edit_undo(); // v.10.2 X if (strEqu(event,"redo")) edit_redo(); // v.10.3 X if (strEqu(event,"blendwidth")) signal_thread(); // v.10.3 X@@ -11485,7 +11501,7 @@ X zdialog_fetch(zd,"flatten",flatten_value); // get slider value X signal_thread(); // trigger update thread X } X- X+ X return 1; X } X X@@ -11521,7 +11537,7 @@ X flatten_brdist[int(bright1)]++; X npix++; X } X- X+ X for (ii = 1; ii < 65536; ii++) // cumulative brightness distribution X flatten_brdist[ii] += flatten_brdist[ii-1]; // 0 ... npix X X@@ -11539,15 +11555,15 @@ X bright1 = pixbright(pix1); X flatten_brdist[int(bright1)]++; X } X- X+ X for (ii = 1; ii < 65536; ii++) // cumulative brightness distribution X flatten_brdist[ii] += flatten_brdist[ii-1]; // 0 ... (ww1 * hh1) X X for (ii = 0; ii < 65536; ii++) X- flatten_brdist[ii] = flatten_brdist[ii] // multiplier per brightness level X+ flatten_brdist[ii] = flatten_brdist[ii] // multiplier per brightness level X / (E1ww * E1hh) * 65536.0 / (ii + 1); X } X- X+ X for (ii = 0; ii < Nwt; ii++) // start worker threads X start_wt(flatten_wthread,&wtnx[ii]); X wait_wts(); // wait for completion X@@ -11580,7 +11596,7 @@ X X pix1 = PXMpix(E1pxm16,px,py); // input pixel X pix3 = PXMpix(E3pxm16,px,py); // output pixel X- X+ X fnew = 0.01 * flatten_value; // 0.0 - 1.0 how much to flatten X fold = 1.0 - fnew; // 1.0 - 0.0 how much to retain X X@@ -11644,9 +11660,9 @@ X X cchar *title = ZTX("Adjust Brightness and Color"); X zfuncs::F1_help_topic = "tune"; // v.10.8 X- X+ X if (! edit_setup("britecolor",1,2)) return; // setup edit: preview X- X+ X /*** X -------------------------------------------- X | | X@@ -11702,7 +11718,7 @@ X zdialog_add_widget(zdedit,"hbox","hbhist","vb22",0,"space=6"); X zdialog_add_widget(zdedit,"label","space","hbhist",0,"space=10"); X zdialog_add_widget(zdedit,"button","histo","hbhist",ZTX("histogram")); X- X+ X GtkWidget *frame = zdialog_widget(zdedit,"fr1"); // setup for curve editing X spcdat *sd = spccurve_init(frame,tune_curve_update); // v.11.01 X Espcdat = sd; X@@ -11725,7 +11741,7 @@ X tune_spc = 1; // default curve = brightness X X zdialog_stuff(zdedit,"radbri",1); // stuff default selection X- X+ X zdialog_resize(zdedit,0,420); X zdialog_run(zdedit,tune_dialog_event); // run dialog - parallel X start_thread(tune_thread,0); // start working thread X@@ -11742,14 +11758,14 @@ X double px, py; X spcdat *sd = Espcdat; X spcdat sdtemp; X- X+ X if (zd->zstat) X { X if (zd->zstat == 1) edit_done(); // done X else edit_cancel(); // cancel or destroy X return 0; X } X- X+ X if (strEqu(event,"undo")) edit_undo(); // v.10.2 X if (strEqu(event,"redo")) edit_redo(); // v.10.3 X if (strEqu(event,"blendwidth")) signal_thread(); // v.10.3 X@@ -11765,7 +11781,7 @@ X } X Fupdate++; X } X- X+ X ii = tune_spc; // current active curve X X if (strnEqu(event,"b ",2)) { // button to move entire curve X@@ -11785,7 +11801,7 @@ X tune_spc_moved[ii] = 1; X Fupdate++; X } X- X+ X if (strEqu(event,"reset1")) { // reset current curve X sd->nap[0] = 3; X sd->apx[0][0] = 0.01; // 3 anchor points, flatline X@@ -11797,8 +11813,8 @@ X Fupdate++; X tune_spc_moved[ii] = 0; X } X- X- if (strEqu(event,"resetA")) X+ X+ if (strEqu(event,"resetA")) X { X for (jj = 0; jj < 6; jj++) { // reset all curves X sd->nap[jj] = 3; X@@ -11855,7 +11871,7 @@ X if (Fupdate) // curve has changed X { X spccurve_generate(sd,0); // regenerate curve 0 X- X+ X ii = tune_spc; // active curve X sd->nap[ii] = sd->nap[0]; // copy curve 0 to active curve X for (jj = 0; jj < sd->nap[0]; jj++) { X@@ -11868,7 +11884,7 @@ X spccurve_draw(0,0,sd); // draw curve X signal_thread(); // trigger image update X } X- X+ X return 1; X } X X@@ -11889,7 +11905,7 @@ X sd->yval[ii][jj] = sd->yval[0][jj]; X X tune_spc_moved[ii] = 1; X- X+ X signal_thread(); // trigger image update X return; X } X@@ -11900,11 +11916,11 @@ X void * tune_thread(void *) X { X void * tune_wthread(void *arg); X- X+ X while (true) X { X thread_idle_loop(); // wait for work or exit request X- X+ X for (int ii = 0; ii < Nwt; ii++) // start worker threads X start_wt(tune_wthread,&wtnx[ii]); X wait_wts(); // wait for completion X@@ -11940,7 +11956,7 @@ X double red1, green1, blue1, red3, green3, blue3; X double xval, brmax, brmean, brout, brightness; X spcdat *sd = Espcdat; X- X+ X if (Factivearea) { // select area active X ii = py * Fww + px; X dist = sa_pixisin[ii]; // distance from edge X@@ -11949,7 +11965,7 @@ X X pix1 = PXMpix(E1pxm16,px,py); // input pixel X pix3 = PXMpix(E3pxm16,px,py); // output pixel X- X+ X red1 = red3 = pix1[0]; // input and output RGB values X green1 = green3 = pix1[1]; X blue1 = blue3 = pix1[2]; X@@ -11970,7 +11986,7 @@ X if (tune_spc_moved[1]) // curve has been edited X { X brout = spccurve_yval(sd,1,xval); // brightness factor, 0 - 1 X- X+ X brmax = red3; // brmax = brightest color X if (green3 > brmax) brmax = green3; X if (blue3 > brmax) brmax = blue3; X@@ -11980,7 +11996,7 @@ X green3 = green3 * brout; // remove limit check v.10.9 X blue3 = blue3 * brout; // (result is better) X } X- X+ X /* ------------------------------------------------------------------------ X X color saturation curve values: X@@ -12029,11 +12045,11 @@ X } X X /* ------------------------------------------------------------------------ X- X+ X if working within a select area, blend changes over distance from edge X X */ X- X+ X double dold, dnew; X X if (Factivearea && dist < sa_blend) { X@@ -12045,7 +12061,7 @@ X } X X /* ------------------------------------------------------------------------ X- X+ X prevent clipping and set output RGB values X X */ X@@ -12057,7 +12073,7 @@ X pix3[0] = int(red3); X pix3[1] = int(green3); X pix3[2] = int(blue3); X- X+ X return; X } X X@@ -12071,7 +12087,7 @@ X int brramp_dialog_event(zdialog* zd, cchar *event); X void brramp_curvedit(int spc); X void * brramp_thread(void *); X- X+ X zfuncs::F1_help_topic = "brightness_ramp"; // v.10.8 X X if (! edit_setup("briteramp",1,2)) return; // setup edit: preview, select area OK X@@ -12140,7 +12156,7 @@ X else edit_cancel(); X return 1; X } X- X+ X if (strEqu(event,"undo")) edit_undo(); // v.10.2 X if (strEqu(event,"redo")) edit_redo(); // v.10.3 X if (strEqu(event,"blendwidth")) signal_thread(); // v.10.3 X@@ -12174,7 +12190,7 @@ X void * brramp_thread(void *arg) X { X void * brramp_wthread(void *); X- X+ X while (true) X { X thread_idle_loop(); // wait for work or exit request X@@ -12210,7 +12226,7 @@ X else { X spanw = E3ww; // else over entire image X spanh = E3hh; X- } X+ } X X for (py3 = index; py3 < E3hh; py3 += Nwt) // loop output pixels X for (px3 = 0; px3 < E3ww; px3++) X@@ -12226,14 +12242,14 @@ X dispx = px3 / spanw; // left > right = 0 to 1 X dispy = py3 / spanh; // top > bottom = 0 to 1 X } X- X+ X hramp = spccurve_yval(sd,0,dispx) - 0.5; // -0.5 to +0.5 X vramp = spccurve_yval(sd,1,dispy) - 0.5; // -0.5 to +0.5 X tramp = 1.0 + hramp + vramp; X X pix1 = PXMpix(E1pxm16,px3,py3); // input pixel X pix3 = PXMpix(E3pxm16,px3,py3); // output pixel X- X+ X red1 = pix1[0]; X green1 = pix1[1]; X blue1 = pix1[2]; X@@ -12277,7 +12293,7 @@ X { X int xbrange_dialog_event(zdialog *zd, cchar *event); X void * xbrange_thread(void *); X- X+ X zfuncs::F1_help_topic = "expand_brightness"; // v.10.8 X X cchar *title = ZTX("Expand Brightness Range"); X@@ -12297,11 +12313,11 @@ X X zdialog_resize(zdedit,300,0); X zdialog_run(zdedit,xbrange_dialog_event); // run dialog, parallel X- X+ X m_histogram(0,0); // show brightness distribution v.11.02 X X xbrangeD = xbrangeB = 0; // initial clip = 0 X- X+ X start_thread(xbrange_thread,0); // start working thread X return; X } X@@ -12345,7 +12361,7 @@ X double dark, bright, b1, b3, bf; X double pval1, pval3, f1, f2; X uint16 *pix1, *pix3; X- X+ X while (true) X { X thread_idle_loop(); // wait for work or exit request X@@ -12373,12 +12389,12 @@ X else if (b1 > bright) // clip bright pixels X b3 = bright; X else b3 = b1; X- X+ X if (b3 > dark) b3 = b3 - dark; // expand the rest X b3 = b3 * (65535.0 / (bright - dark)); X X bf = b3 / (b1 + 1); // brightness ratio X- X+ X for (rgb = 0; rgb < 3; rgb++) // loop 3 RGB colors X { X pval1 = pix1[rgb]; X@@ -12444,7 +12460,7 @@ X | | X | curve drawing area | X | | X- |_____________________________| X+ |_____________________________| X low contrast high X X Amplify ========[]========= X@@ -12497,7 +12513,7 @@ X Tmap_brmap1[ii] = pixbright(pix1); X } X X- for (ii = 0; ii < 100; ii++) X+ for (ii = 0; ii < 100; ii++) X condist[ii] = 0; X X for (py = 1; py < Fhh; py++) // map contrast distribution X@@ -12509,7 +12525,7 @@ X jj = 0.00152 * fabsf(Tmap_brmap1[ii] - Tmap_brmap1[ii-Fww]); X condist[jj]++; X } X- X+ X sum = 0; X limit = 0.99 * 2 * (Fww-1) * (Fhh-1); // find 99th percentile contrast X X@@ -12517,7 +12533,7 @@ X sum += condist[ii]; X if (sum > limit) break; X } X- X+ X Tmap_contrast99 = 65535.0 * ii / 100.0; // 0 to 65535 X if (Tmap_contrast99 < 1000) Tmap_contrast99 = 1000; // rescale low-contrast image v.10.9 X X@@ -12566,7 +12582,7 @@ X spccurve_save(sd); X return 0; X } X- X+ X return 0; X } X X@@ -12586,9 +12602,9 @@ X { X void * Tmap_wthread1(void *arg); X void * Tmap_wthread2(void *arg); X- X+ X int ii; X- X+ X while (true) X { X thread_idle_loop(); // wait for work or exit request X@@ -12605,11 +12621,11 @@ X for (ii = 0; ii < Nwt; ii++) // start working threads2 X start_wt(Tmap_wthread2,&wtnx[ii]); X wait_wts(); // wait for completion X- X+ X SB_goal = 0; X X Fmodified = 1; X- mwpaint2(); X+ mwpaint2(); X } X X return 0; // not executed, stop g++ warning X@@ -12634,19 +12650,19 @@ X py1 = 1; py2 = E3hh; pyinc = 1; X pii = - 1 - E3ww; X } X- X+ X else if (bii == 1) { // direction SW X px1 = E3ww-2; px2 = 0; pxinc = -1; X py1 = 1; py2 = E3hh; pyinc = 1; X pii = + 1 - E3ww; X } X- X+ X else if (bii == 2) { // direction NE X px1 = 1; px2 = E3ww; pxinc = 1; X py1 = E3hh-2; py2 = 0; pyinc = -1; X pii = - 1 + E3ww; X } X- X+ X else { /* bii == 3 */ // direction NW X px1 = E3ww-2; px2 = 0; pxinc = -1; X py1 = E3hh-2; py2 = 0; pyinc = -1; X@@ -12682,10 +12698,10 @@ X X b3 = Tmap_brmap3[bii][ii+pii] + grad; // pixel brightness = prior + gradient X b3 = (1.0 - amplify) * b1 + amplify * b3; // constrain: push b3 toward b1 v.11.02 X- X+ X if (b3 > 65535) b3 = 65535; // constrain X if (b3 < 10) b3 = 10; X- X+ X Tmap_brmap3[bii][ii] = b3; // new pixel brightness X } X X@@ -12721,9 +12737,9 @@ X b1 = Tmap_brmap1[ii]; // initial pixel brightness X b3 = Tmap_brmap3[0][ii] + Tmap_brmap3[1][ii] // new brightness = average of four X + Tmap_brmap3[2][ii] + Tmap_brmap3[3][ii]; // calculated brightness surfaces X- X+ X bf = 0.25 * b3 / (b1 + 1); // brightness ratio X- X+ X for (rgb = 0; rgb < 3; rgb++) // loop 3 RGB colors X { X pval1 = pix1[rgb]; X@@ -12846,7 +12862,7 @@ X if (ii < 0) ii = redeye_createF(px,py); // or create new type F X redeye_darken(ii); // darken red-eye X } X- X+ X if (RMclick) // right mouse click X { X RMclick = 0; X@@ -12866,7 +12882,7 @@ X if (ww < 2) ww = 2; X if (hh < 2) hh = 2; X if (px < 1) px = 1; // keep within image area X- if (py < 1) py = 1; X+ if (py < 1) py = 1; X if (px + ww > E3ww-1) ww = E3ww-1 - px; X if (py + hh > E3hh-1) hh = E3hh-1 - py; X ii = redeye_find(px,py); // find existing red-eye X@@ -12890,10 +12906,10 @@ X double Tsum, Rsum, R2sum, Tavg, Ravg, R2avg; X double sumx, sumy, sumr; X uint16 *ppix; X- X+ X cx0 = cx; X cy0 = cy; X- X+ X for (loops = 0; loops < 8; loops++) X { X cx1 = cx; X@@ -12923,7 +12939,7 @@ X R2npix++; X } X } X- X+ X Tsum += Rsum; X Tnpix += Rnpix; X Tavg = Tsum / Tnpix; // avg. redness over 0-rad X@@ -12932,11 +12948,11 @@ X if (R2avg > Ravg || Ravg > Tavg) continue; X if ((Ravg - R2avg) < 0.2 * (Tavg - Ravg)) break; // 0.1 --> 0.2 X } X- X+ X sumx = sumy = sumr = 0; X rad = int(1.2 * rad + 1); X if (rad > radlim) rad = radlim; X- X+ X for (py = cy-rad; py <= cy+rad; py++) // compute center of gravity for X for (px = cx-rad; px <= cx+rad; px++) // pixels within rad of (cx,cy) X { X@@ -13020,8 +13036,8 @@ X thresh = redmem[ii].thresh; X tstep = redmem[ii].tstep; X clicks = redmem[ii].clicks++; X- X- if (thresh == 0) // 1st click X+ X+ if (thresh == 0) // 1st click X { X redeye_distr(ii); // get pixel redness distribution X thresh = redmem[ii].thresh; // initial redness threshhold X@@ -13052,7 +13068,7 @@ X } X X X-// Build a distribution of redness for a red-eye. Use this information X+// Build a distribution of redness for a red-eye. Use this information X // to set initial threshhold and step size for stepwise darkening. X X void redeye_distr(int ii) X@@ -13062,14 +13078,14 @@ X double rd, maxred, minred, redpart, dbase, dstep; X char type; X uint16 *ppix; X- X+ X type = redmem[ii].type; X cx = redmem[ii].cx; X cy = redmem[ii].cy; X ww = redmem[ii].ww; X hh = redmem[ii].hh; X rad = redmem[ii].rad; X- X+ X maxred = 0; X minred = 100; X X@@ -13089,7 +13105,7 @@ X if (redpart > maxred) maxred = redpart; X if (redpart < minred) minred = redpart; X } X- X+ X dbase = minred; X dstep = (maxred - minred) / 19.99; X X@@ -13113,7 +13129,7 @@ X ++dbins[bin]; X ++npix; X } X- X+ X bsum = 0; X blim = int(0.5 * npix); X X@@ -13136,10 +13152,10 @@ X { X for (int ii = 0; ii < Nredmem; ii++) X { X- if (cx > redmem[ii].cx - 2 * redmem[ii].rad && X+ if (cx > redmem[ii].cx - 2 * redmem[ii].rad && X cx < redmem[ii].cx + 2 * redmem[ii].rad && X- cy > redmem[ii].cy - 2 * redmem[ii].rad && X- cy < redmem[ii].cy + 2 * redmem[ii].rad) X+ cy > redmem[ii].cy - 2 * redmem[ii].rad && X+ cy < redmem[ii].cy + 2 * redmem[ii].rad) X return ii; // found X } X return -1; // not found X@@ -13166,11 +13182,11 @@ X pix3[1] = pix1[1]; X pix3[2] = pix1[2]; X } X- X- for (ii++; ii < Nredmem; ii++) X+ X+ for (ii++; ii < Nredmem; ii++) X redmem[ii-1] = redmem[ii]; X Nredmem--; X- X+ X Ftoparc = 0; X return; X } X@@ -13214,7 +13230,7 @@ X zdialog_add_widget(zdedit,"button","apply","hb2",Bapply,"space=5"); X X zdialog_run(zdedit,blur_dialog_event); // start dialog X- X+ X blur_radius = 0.5; X start_thread(blur_thread,0); // start working thread X return; X@@ -13231,7 +13247,7 @@ X else edit_cancel(); // cancel or destroy X return 1; X } X- X+ X if (strEqu(event,"undo")) edit_undo(); // v.10.2 X if (strEqu(event,"redo")) edit_redo(); // v.10.3 X if (strEqu(event,"blendwidth")) signal_thread(); // v.10.3 X@@ -13255,7 +13271,7 @@ X int dx, dy; X double rad, rad2; X double m, d, w, sum; X- X+ X while (true) X { X thread_idle_loop(); // wait for work or exit request X@@ -13287,7 +13303,7 @@ X for (dx = 0; dx <= rad+1; dx++) // make weights add up to 1.0 X for (dy = 0; dy <= rad+1; dy++) X blur_weight[dx][dy] = blur_weight[dx][dy] / sum; X- X+ X if (Factivearea) SB_goal = sa_Npixel; X else SB_goal = E3ww * E3hh; X for (int ii = 0; ii < 8; ii++) SB_done[ii] = 0; // v.11.03 X@@ -13311,7 +13327,7 @@ X X int index = *((int *) arg); X int px, py; X- X+ X for (py = index; py < E3hh-1; py += Nwt) // loop all image pixels X for (px = 0; px < E3ww-1; px++) X { X@@ -13340,11 +13356,11 @@ X X pix1 = PXMpix(E1pxm16,px,py); // source pixel X pix3 = PXMpix(E3pxm16,px,py); // target pixel X- X+ X rad = blur_radius; X red = green = blue = 0; X weight2 = 0.0; X- X+ X if (Factivearea) // select area active X { X for (dy = -rad-1; dy <= rad+1; dy++) // loop neighbor pixels within radius X@@ -13363,7 +13379,7 @@ X green += pixN[1] * weight1; X blue += pixN[2] * weight1; X } X- X+ X red = red / weight2; // weighted average X green = green / weight2; X blue = blue / weight2; X@@ -13406,7 +13422,7 @@ X pix3[1] = int(green); X pix3[2] = int(blue); X } X- X+ X return; X } X X@@ -13436,7 +13452,7 @@ X X if (! edit_setup("sharp",0,2)) return; // setup edit: no preview X X- zdedit = zdialog_new(ZTX("Sharpen Image"),mWin,Bdone,Bcancel,null); X+ zdedit = zdialog_new(ZTX("Sharpen Image"),mWin,Bdone,Bcancel,null); X X zdialog_add_widget(zdedit,"hbox","hb1","dialog",0,"space=5"); X zdialog_add_widget(zdedit,"vbox","vb11","hb1",0,"space=5"); X@@ -13493,7 +13509,7 @@ X else edit_cancel(); X return 0; X } X- X+ X if (strEqu(event,"undo")) edit_undo(); // v.10.2 X if (strEqu(event,"redo")) edit_redo(); // v.10.3 X if (strEqu(event,"blendwidth")) signal_thread(); // v.10.3 X@@ -13527,7 +13543,7 @@ X int sharp_ED(); X int sharp_UM(); X int sharp_GR(); X- X+ X while (true) X { X thread_idle_loop(); // wait for work or exit request X@@ -13539,7 +13555,7 @@ X Ffuncbusy--; X X Fmodified = 1; X- mwpaint2(); X+ mwpaint2(); X } X X return 0; // not executed, stop g++ warning X@@ -13555,9 +13571,9 @@ X int sharp_thresh1 = 100; // initial threshold X double sharp_thresh2 = 0.01 * sharp_ED_reduce; // decline rate X int ii, px, py, thresh, cycles; X- X+ X thresh = sharp_thresh1; X- X+ X if (Factivearea) SB_goal = sa_Npixel; // v.9.6 X else SB_goal = E3ww * E3hh; X SB_goal *= sharp_ED_cycles; X@@ -13590,7 +13606,7 @@ X int dy[4] = { -1, -1, -1, 0 }; X int pv2, pv2u, pv2d, pv2uu, pv2dd, pvdiff; X double f1, f2; X- X+ X if (Factivearea) { // select area active X ii = py * Fww + px; X dist = sa_pixisin[ii]; // distance from edge X@@ -13629,16 +13645,16 @@ X pix3u = pix3; // avoid up/down/up jaggies X pv2u = pv2; X } X- X+ X if (pv2dd <= pv2d) { X pix3d = pix3; X pv2d = pv2; X } X- X+ X if (pv2u > 256) pv2u -= 256; X if (pv2d < 65279) pv2d += 256; X } X- X+ X else if (pv2u > pv2 && pv2 > pv2d) // slope down, monotone X { X pix3uu = pix3u + (dy[dd] * E3ww + dx[dd]) * 3; X@@ -13650,7 +13666,7 @@ X pix3u = pix3; X pv2u = pv2; X } X- X+ X if (pv2dd >= pv2d) { X pix3d = pix3; X pv2d = pv2; X@@ -13685,13 +13701,13 @@ X int sharp_UM() X { X void * sharp_UM_wthread(void *arg); X- X+ X int ii; X- X- if (sharp_UM_Fcalc) { // speedup v.9.6 X+ X+ if (sharp_UM_Fcalc) { // speedup v.9.6 X sharp_UM_Fcalc = 0; X brhood_calc(sharp_UM_radius,'f'); X- } X+ } X X if (Factivearea) SB_goal = sa_Npixel; // v.9.6 X else SB_goal = E3ww * E3hh; X@@ -13712,7 +13728,7 @@ X X int index = *((int *) arg); X int px, py; X- X+ X for (py = index; py < E3hh; py += Nwt) // loop all image3 pixels X for (px = 0; px < E3ww; px++) X sharp_pixel_UM(px,py,index); X@@ -13729,7 +13745,7 @@ X double mean, incr, ratio, f1, f2; X int rgb, cval1, cval3; X uint16 *pix1, *pix3; X- X+ X if (Factivearea) { // select area active X ii = py * Fww + px; X dist = sa_pixisin[ii]; // distance from edge X@@ -13758,17 +13774,17 @@ X cval3 = ratio * cval1; X if (cval3 < 0) cval3 = 0; X if (cval3 > 65535) cval3 = 65535; X- X+ X if (Factivearea && dist < sa_blend) { // select area is active, X f1 = 1.0 * dist / sa_blend; // blend changes over sa_blend X f2 = 1.0 - f1; X cval3 = f1 * cval3 + f2 * cval1; X } X- X+ X pix3[rgb] = cval3; X } X- X- SB_done[index]++; X+ X+ SB_done[index]++; X return; X } X X@@ -13778,7 +13794,7 @@ X int sharp_GR() X { X uint16 *pix1, *pix3; X- int ii, px, py, dist = 0, rgb; X+ int ii, px, py, dist = 0, rgb; X double amount, thresh; X double b1, b1x, b1y, b3x, b3y, b3, bf; X double pval, f1, f2; X@@ -13805,7 +13821,7 @@ X b1 = pixbright(pix1); // pixel brightness, 0 - 64K X b1x = b1 - pixbright(pix1 - 3); // brightness gradient (x,y) X b1y = b1 - pixbright(pix1 - 3 * E1ww); X- X+ X if (abs(b1x + b1y) < thresh) // moderate brightness change for X f1 = abs(b1x + b1y) / thresh; // pixels below threshold gradient X else f1 = 1.0; // v.10.9 X@@ -13823,18 +13839,18 @@ X bf = b3 / b1; // ratio of brightness change X if (bf < 0) bf = 0; X if (bf > 4) bf = 4; X- X+ X for (rgb = 0; rgb < 3; rgb++) // loop 3 RGB colors X { X pval = bf * pix3[rgb]; // apply factor X if (pval > 65535) pval = 65535; X- X+ X if (Factivearea && dist < sa_blend) { // select area is active, X f1 = 1.0 * dist / sa_blend; // blend changes over sa_blend X f2 = 1.0 - f1; X pval = int(f1 * pval + f2 * pix1[rgb]); X } X- X+ X pix3[rgb] = pval; X } X X@@ -13876,7 +13892,7 @@ X zdialog_add_widget(zdedit,"label","labrad","hb2",Bradius,"space=5"); X zdialog_add_widget(zdedit,"spin","radius","hb2","1|9|1|4","space=5"); X zdialog_add_widget(zdedit,"button","reduce","hb2",Breduce,"space=5"); X- X+ X zdialog_cb_app(zdedit,"method",ZTX("flatten outliers by color (1)")); X zdialog_cb_app(zdedit,"method",ZTX("flatten outliers by color (2)")); X zdialog_cb_app(zdedit,"method",ZTX("set median brightness by color")); X@@ -13906,10 +13922,10 @@ X if (strEqu(event,"redo")) edit_redo(); // v.10.3 X if (strEqu(event,"blendwidth")) signal_thread(); // trigger update thread X X- if (strEqu(event,"radius")) X+ if (strEqu(event,"radius")) X zdialog_fetch(zd,"radius",denoise_radius); X X- if (strEqu(event,"method")) X+ if (strEqu(event,"method")) X { X zdialog_fetch(zd,"method",method,39); X X@@ -13932,10 +13948,10 @@ X denoise_method = 5; X denoise_radius = 4; X } X- X+ X zdialog_stuff(zd,"radius",denoise_radius); X } X- X+ X if (strEqu(event,"reduce")) signal_thread(); // trigger update thread X X return 1; X@@ -13947,7 +13963,7 @@ X void * denoise_thread(void *) X { X void * denoise_wthread(void *arg); X- X+ X int ii; X X while (true) X@@ -13986,7 +14002,7 @@ X void denoise_func2(uint16 *pix3, uint16 *pix9); X void denoise_func4(uint16 *pix3, uint16 *pix9); X void denoise_func5(uint16 *pix3, uint16 *pix9); X- X+ X int index = *((int *) arg); X int ii, px, py, rad, dist = 0; X double f1, f2; X@@ -14028,7 +14044,7 @@ X } X X X-// flatten outliers within radius, by color X+// flatten outliers within radius, by color X // an outlier is the max or min value within a radius X X void denoise_func1(uint16 *pix3, uint16 *pix9) X@@ -14054,20 +14070,20 @@ X if (pixN[2] < min2) min2 = pixN[2]; X if (pixN[2] > max2) max2 = pixN[2]; X } X- X+ X if (pix3[0] <= min0 && min0 < 65279) pix9[0] = min0 + 256; // if outlier, flatten a little X if (pix3[0] >= max0 && max0 > 256) pix9[0] = max0 - 256; X if (pix3[1] <= min1 && min1 < 65279) pix9[1] = min1 + 256; X if (pix3[1] >= max1 && max1 > 256) pix9[1] = max1 - 256; X if (pix3[2] <= min2 && min2 < 65279) pix9[2] = min2 + 256; X if (pix3[2] >= max2 && max2 > 256) pix9[2] = max2 - 256; X- X+ X return; X } X X X // flatten outliers X-// An outlier pixel has an RGB value outside one sigma of X+// An outlier pixel has an RGB value outside one sigma of X // the mean for all pixels within a given radius of the pixel. X X void denoise_func2(uint16 *pix3, uint16 *pix9) X@@ -14094,12 +14110,12 @@ X sum += val; X sum2 += val * val; X } X- X+ X mean = nn1 * sum; X variance = nn1 * (sum2 - 2.0 * mean * sum) + mean * mean; X sigma = sqrt(variance); X X- val = pix3[rgb]; X+ val = pix3[rgb]; X if (val > mean + sigma) { // move value to mean +/- sigma X val = mean + sigma; X pix9[rgb] = val; X@@ -14109,7 +14125,7 @@ X pix9[rgb] = val; X } X } X- X+ X return; X } X X@@ -14173,7 +14189,7 @@ X if (pixN[2] < min2) min2 = pixN[2]; X if (pixN[2] > max2) max2 = pixN[2]; X } X- X+ X if (pix3[0] < min0 && pix9[0] < 65279) pix9[0] += 256; // if central pixel is outlier, X if (pix3[0] > max0 && pix9[0] > 256) pix9[0] -= 256; // moderate its values X if (pix3[1] < min1 && pix9[1] < 65279) pix9[1] += 256; X@@ -14188,7 +14204,7 @@ X X /**************************************************************************/ X X-// Smart Erase menu function - Replace pixels inside a select area X+// Smart Erase menu function - Replace pixels inside a select area X // with a reflection of pixels outside the area. X X void m_smart_erase(GtkWidget *, const char *) X@@ -14199,9 +14215,9 @@ X "2. Erase 3. Repeat"); X X zfuncs::F1_help_topic = "smart_erase"; X- X+ X if (! edit_setup("smart_erase",0,2)) return; // setup edit X- X+ X /* _____________________________ X | | X | 1. Select and finish area | X@@ -14230,21 +14246,21 @@ X { X void smart_erase_func(int mode); X void smart_erase_blur(double radius); X- X+ X double radius; X- X+ X if (zd->zstat) { X if (zd->zstat == 1) edit_done(); X else edit_cancel(); X return 0; X } X- X+ X if (strEqu(event,"erase")) { // do smart erase X smart_erase_func(1); X zdialog_fetch(zd,"blur",radius); // + optional blur X if (radius > 0) smart_erase_blur(radius); X } X- X+ X if (strEqu(event,"undo1")) // dialog undo, undo last erase X smart_erase_func(2); X X@@ -14253,7 +14269,7 @@ X X if (strEqu(event,"redo")) // toolbar redo, redo all erases X edit_redo(); X- X+ X return 0; X } X X@@ -14273,7 +14289,7 @@ X zmessage_help(mWin,"smart_erase","Select area first"); X return; X } X- X+ X for (py = sa_miny; py <= sa_maxy; py++) // loop all pixels in area X for (px = sa_minx; px <= sa_maxx; px++) X { X@@ -14290,11 +14306,11 @@ X } X X mwpaint2(); // update window X- X+ X if (mode == 2) return; // mode = erase, done X X sa_edgecalc(); // do edge calculation if needed X- X+ X cc = Fww * Fhh; // allocate pixel done map X pmap = (char *) zmalloc(cc,"smart_erase.pmap"); X memset(pmap,0,cc); X@@ -14328,7 +14344,7 @@ X sx = px + slope * (sy - py); X ii = sy * Fww + sx; X pmap[ii] = 1; X- tx = qx + (sx - px) + slope * inc; // tx/ty = parallel line from qx/qy X+ tx = qx + (sx - px) + slope * inc; // tx/ty = parallel line from qx/qy X ty = qy + (sy - py) + inc; X if (tx < 0 || tx > Fww-1) break; X if (ty < 0 || ty > Fhh-1) break; X@@ -14344,7 +14360,7 @@ X slope = 1.0 * (qy - py) / (qx - px); X if (qx > px) inc = 1; X else inc = -1; X- for (sx = px; sx != qx+inc; sx += inc) X+ for (sx = px; sx != qx+inc; sx += inc) X { X sy = py + slope * (sx - px); X ii = sy * Fww + sx; X@@ -14381,9 +14397,9 @@ X double red, green, blue; X double weight1, weight2; X uint16 *pix9, *pix3, *pixN; X- X+ X if (! Factivearea) return 0; X- X+ X rad = radius - 0.2; X rad2 = rad * rad; X X@@ -14411,9 +14427,9 @@ X for (dx = 0; dx <= rad+1; dx++) // make weights add up to 1.0 X for (dy = 0; dy <= rad+1; dy++) X blur_weight[dx][dy] = blur_weight[dx][dy] / sum; X- X+ X E9pxm16 = PXM_copy(E3pxm16); // copy edited image X- X+ X for (py = sa_miny; py < sa_maxy; py++) // loop all pixels in area X for (px = sa_minx; px < sa_maxx; px++) X { X@@ -14422,11 +14438,11 @@ X X pix9 = PXMpix(E9pxm16,px,py); // source pixel X pix3 = PXMpix(E3pxm16,px,py); // target pixel X- X+ X rad = radius; X red = green = blue = 0; X weight2 = 0.0; X- X+ X for (dy = -rad-1; dy <= rad+1; dy++) // loop neighbor pixels within radius X for (dx = -rad-1; dx <= rad+1; dx++) X { X@@ -14441,7 +14457,7 @@ X green += pixN[1] * weight1; X blue += pixN[2] * weight1; X } X- X+ X red = red / weight2; // weighted average X green = green / weight2; X blue = blue / weight2; X@@ -14480,7 +14496,7 @@ X zfuncs::F1_help_topic = "trim_image"; // v.10.8 X X if (! edit_setup("trim",0,0)) return; // setup edit X- X+ X if (! trimbuttons[0] || strEqu(trimbuttons[0],"undefined")) { X trimbuttons[0] = strdupz("1:1",8); // default trim buttons v.10.10.2 X trimbuttons[1] = strdupz("2:1",8); X@@ -14510,7 +14526,7 @@ X trimy1 = 0.1 * E3hh; X trimy2 = 0.9 * E3hh; X } X- X+ X trimpx1 = trimpy1 = 0; // prior trim rectangle X trimpx2 = E3ww; // = 100% of image X trimpy2 = E3hh; X@@ -14568,7 +14584,7 @@ X char text[40]; X cchar *pp; X int ii; X- X+ X if (zd->zstat) // dialog complete X { X freeMouse(); // disconnect mouse function v.10.12 X@@ -14608,16 +14624,16 @@ X zdialog_stuff(zd,"lock",1); // assume lock is wanted X trimR = ratio; X } X- X+ X if (strEqu(event,"invert")) // invert ratio button X if (trimR) ratio = 1.0 / trimR; X- X+ X if (! ratio) return 0; X trimR = ratio; // bugfix v.10.10.3 X X if (trimx2 - trimx1 > trimy2 - trimy1) X trimy2 = trimy1 + (trimx2 - trimx1) / trimR; // adjust smaller dimension X- else X+ else X trimx2 = trimx1 + (trimy2 - trimy1) * trimR; X X if (trimy2 > E3hh) { // if off the bottom edge, X@@ -14649,22 +14665,22 @@ X double r1, r2, ratio; X cchar *pp; X int ii, zstat; X- X+ X zdedit = zdialog_new(ZTX("Trim Buttons"),mWin,Bdone,Bcancel,null); // start dialog X zdialog_add_widget(zdedit,"hbox","hbb","dialog",0,"homog|space=5"); X zdialog_add_widget(zdedit,"hbox","hbr","dialog",0,"homog|space=5"); X- X+ X strcpy(blab,"butt-0"); X strcpy(rlab,"ratio-0"); X- X- for (ii = 0; ii < 6; ii++) X+ X+ for (ii = 0; ii < 6; ii++) X { X blab[5] = '0' + ii; X rlab[6] = '0' + ii; X zdialog_add_widget(zdedit,"entry",blab,"hbb",trimbuttons[ii],"scc=6"); X zdialog_add_widget(zdedit,"entry",rlab,"hbr",trimratios[ii],"scc=6"); X } X- X+ X zdialog_run(zdedit); X zstat = zdialog_wait(zdedit); X X@@ -14713,7 +14729,7 @@ X int dx, dy, dd, d1, d2, d3, d4; X char text[40]; X double drr; X- X+ X if (LMclick || Mxdrag || Mydrag) // mouse click or drag X { X if (LMclick) { X@@ -14730,7 +14746,7 @@ X Mxdown = Mxdrag; // reset drag origin X Mydown = Mydrag; X } X- X+ X if (Mxdrag || Mydrag) { X moveall = 1; X dd = 0.1 * (trimx2 - trimx1); // test if mouse is in the broad X@@ -14753,25 +14769,25 @@ X dx = mpx - trimx1; X dy = mpy - trimy1; X d1 = sqrt(dx*dx + dy*dy); X- X+ X dx = mpx - trimx2; X dy = mpy - trimy1; X d2 = sqrt(dx*dx + dy*dy); X- X+ X dx = mpx - trimx2; X dy = mpy - trimy2; X d3 = sqrt(dx*dx + dy*dy); X- X+ X dx = mpx - trimx1; X dy = mpy - trimy2; X d4 = sqrt(dx*dx + dy*dy); X- X+ X corner = 1; // NW X dd = d1; X if (d2 < dd) { corner = 2; dd = d2; } // NE X if (d3 < dd) { corner = 3; dd = d3; } // SE X if (d4 < dd) { corner = 4; dd = d4; } // SW X- X+ X if (corner == 1) { trimx1 = mpx; trimy1 = mpy; } // move this corner to mouse X if (corner == 2) { trimx2 = mpx; trimy1 = mpy; } X if (corner == 3) { trimx2 = mpx; trimy2 = mpy; } X@@ -14818,7 +14834,7 @@ X X snprintf(text,39,"%d x %d (R=%.2f)",trimsize[0],trimsize[1],trimR); // stuff starting trim size >> dialog X zdialog_stuff(zdedit,"labwhr",text); X- X+ X trim_trim(0); // show trim area in image X } X X@@ -14835,7 +14851,7 @@ X int nx1, ny1, nx2, ny2; // inner trim rectangle X int px, py, px1, py1, px2, py2; X uint16 *pix1, *pix3; X- X+ X if (mode == 1) // do the final trim X { X mutex_lock(&Fpixmap_lock); X@@ -14843,7 +14859,7 @@ X E3pxm16 = PXM_make(trimsize[0],trimsize[1],16); // new pixmap with requested size X E3ww = trimsize[0]; X E3hh = trimsize[1]; X- X+ X for (py1 = trimy1; py1 < trimy2; py1++) // copy pixels X for (px1 = trimx1; px1 < trimx2; px1++) X { X@@ -14861,7 +14877,7 @@ X mwpaint2(); // update window X return; X } X- X+ X if (trimpx1 < trimx1) ox1 = trimpx1; // outer rectangle X else ox1 = trimx1; X if (trimpy1 < trimy1) oy1 = trimpy1; X@@ -14879,19 +14895,19 @@ X else nx2 = trimx2; X if (trimpy2 < trimy2) ny2 = trimpy2; X else ny2 = trimy2; X- X- trimpx1 = trimx1; // set prior trim rectangle X+ X+ trimpx1 = trimx1; // set prior trim rectangle X trimpy1 = trimy1; // from current trim rectangle X trimpx2 = trimx2; X trimpy2 = trimy2; X- X+ X if (ox1 > 0) ox1--; X if (oy1 > 0) oy1--; X if (ox2 < E3ww) ox2++; X if (oy2 < E3hh) oy2++; X X for (py = oy1; py < ny1; py++) // top band of pixels X- for (px = ox1; px < ox2; px++) X+ for (px = ox1; px < ox2; px++) X { X pix1 = PXMpix(E1pxm16,px,py); X pix3 = PXMpix(E3pxm16,px,py); X@@ -14971,8 +14987,8 @@ X X // Resize (rescale) image X // X-// Output pixels are composites of input pixels, e.g. 2/3 size means X-// that 3x3 input pixels are mapped into 2x2 output pixels, and an X+// Output pixels are composites of input pixels, e.g. 2/3 size means X+// that 3x3 input pixels are mapped into 2x2 output pixels, and an X // image size of 1000 x 600 becomes 667 x 400. X X int editresize[2] = { 1600, 1200 }; // edit resize width, height X@@ -15023,7 +15039,7 @@ X zdialog_stuff(zdedit,"hpix",resize_hh0); X zdialog_stuff(zdedit,"lock",1); X X- start_thread(resize_thread,0); // start working thread X+ start_thread(resize_thread,0); // start working thread X X zdialog_run(zdedit,resize_dialog_event); // run dialog X zdialog_wait(zdedit); // wait for completion X@@ -15038,7 +15054,7 @@ X { X int lock; X double wpct1, hpct1; X- X+ X if (zd->zstat) // dialog complete X { X if (zd->zstat != 1) { // user cancel X@@ -15095,15 +15111,15 @@ X X if (strEqu(event,"hpct")) // height % - set pixel height X resize_hh1 = int(hpct1 / 100.0 * resize_hh0 + 0.5); X- X+ X if (lock && event[0] == 'w') // preserve width/height ratio X resize_hh1 = int(resize_ww1 * (1.0 * resize_hh0 / resize_ww0) + 0.5); X- if (lock && event[0] == 'h') X+ if (lock && event[0] == 'h') X resize_ww1 = int(resize_hh1 * (1.0 * resize_ww0 / resize_hh0) + 0.5); X- X+ X hpct1 = 100.0 * resize_hh1 / resize_hh0; // set percents to match pixels X wpct1 = 100.0 * resize_ww1 / resize_ww0; X- X+ X zdialog_stuff(zd,"wpix",resize_ww1); // index all widget values X zdialog_stuff(zd,"hpix",resize_hh1); X zdialog_stuff(zd,"wpct",wpct1); X@@ -15119,11 +15135,11 @@ X void * resize_thread(void *) // v.10.12 X { X Fmodified = 0; X- X+ X while (true) X { X thread_idle_loop(); // wait for signal X- X+ X mutex_lock(&Fpixmap_lock); X PXM_free(E3pxm16); X E3pxm16 = PXM_rescale(Fpxm16,resize_ww1,resize_hh1); // rescale the edit image X@@ -15194,7 +15210,7 @@ X zdialog_stuff(zd,"copyexif",0); X zdialog_stuff(zd,"maxw",batchresize[0]); // v.10.9 X zdialog_stuff(zd,"maxh",batchresize[1]); X- X+ X zdialog_run(zd,batchresize_dialog_event); // run dialog X zdialog_wait(zd); // wait for completion X X@@ -15220,11 +15236,11 @@ X if (strEqu(event,"files")) // select images to resize X { X if (flist) { // free prior list X- for (ii = 0; flist[ii]; ii++) X+ for (ii = 0; flist[ii]; ii++) X zfree(flist[ii]); X zfree(flist); X } X- X+ X flist = image_gallery_getfiles(0,mWin); // get list of files to resize v.10.9 X X if (flist) // count files selected X@@ -15234,7 +15250,7 @@ X sprintf(countmess,"%d files selected",ii); // update dialog X zdialog_stuff(zd,"fcount",countmess); X } X- X+ X if (strEqu(event,"browse")) X { X ploc = zgetfile1(ZTX("Select directory"),"folder",curr_dirk); // get directory v.10.9 X@@ -15247,7 +15263,7 @@ X if (! zd->zstat) return 0; // dialog still busy X X if (zd->zstat != 1) goto cleanup; // dialog canceled X- X+ X if (! flist) { // no files selected X zd->zstat = 0; // keep dialog active X return 0; X@@ -15290,7 +15306,7 @@ X zd->zstat = 0; X return 0; X } X- X+ X write_popup_text("open","Resizing files",500,200,mWin); // status monitor popup window X X lcc = strlen(location); X@@ -15309,13 +15325,13 @@ X newfile = strdupz(location,fcc+9,"batchresize.new"); X strcpy(newfile+lcc,pfile); // new file at location X } X- X+ X pfile = strrchr(newfile,'/'); // force .jpg extension v.10.9 X pext = strrchr(pfile,'.'); X if (! pext) pext = pfile + strlen(pfile); X if (strlen(pext) > 5) pext = pext + strlen(pext); X strcpy(pext,".jpg"); X- X+ X write_popup_text("write",newfile); // report progress X zmainloop(); X X@@ -15328,10 +15344,10 @@ X continue; X } X } X- X+ X tempfile = strdupz(newfile,12,"batchresize.temp"); // temp file needed for EXIF copy X strcat(tempfile,"-temp.jpg"); // v.10.9 X- X+ X f_open(oldfile,0); // read old file X X wscale = hscale = 1.0; X@@ -15347,7 +15363,7 @@ X X if (Freplace || Fcopyexif) // copy EXIF if files replaced X exif_copy(oldfile,tempfile,0,0,0); // or if requested for export X- X+ X snprintf(command,ccc,"cp -p \"%s\" \"%s\" ",tempfile,newfile); // copy tempfile to newfile X err = system(command); X if (err) write_popup_text("write",wstrerror(err)); X@@ -15364,14 +15380,14 @@ X X write_popup_text("write","COMPLETED"); X write_popup_text("close",0); X- X+ X batchresize[0] = maxw; // save preferred size v.10.9 X batchresize[1] = maxh; X X cleanup: X X if (flist) { // free memory X- for (ii = 0; flist[ii]; ii++) X+ for (ii = 0; flist[ii]; ii++) X zfree(flist[ii]); X zfree(flist); X flist = 0; X@@ -15418,13 +15434,13 @@ X X if (! edit_setup("annotate",0,1)) return; // setup edit X X- if (! annotate_text) X+ if (! annotate_text) X annotate_text = strdupz("enter text",0,"annotate"); X X if (! annotate_font || strEqu(annotate_font,"undefined")) X annotate_font = strdupz("FreeMono Bold Italic 44",4,"annotate"); // default font and size X else annotate_font = strdupz(annotate_font,4,"annotate"); // add extra space bugfix v.11.02 X- X+ X X if (! annotate_color[0] || strEqu(annotate_color[0],"undefined")) { // default colors X annotate_color[0] = strdupz("255|0|0",0,"annotate"); // text X@@ -15432,7 +15448,7 @@ X annotate_color[2] = strdupz("0|255|0",0,"annotate"); // text outline X annotate_towidth = 6; // outline width X } X- X+ X pp = annotate_color[0]; // insure at least 20 bytes X annotate_color[0] = strdupz(pp,20,"annotate"); X zfree(pp); X@@ -15471,26 +15487,26 @@ X zdialog_add_widget(zdedit,"label","space","hbfont","","space=5"); X zdialog_add_widget(zdedit,"label","labangle","hbfont",ZTX("Angle"),"space=3"); X zdialog_add_widget(zdedit,"spin","angle","hbfont","-180|180|0.2|0","space=3"); X- X+ X zdialog_add_widget(zdedit,"hsep","hs1","dialog",0,"space=3"); X zdialog_add_widget(zdedit,"hbox","hbcol","dialog",0,"space=3"); X zdialog_add_widget(zdedit,"vbox","vbcol1","hbcol",0,"homog|space=8"); X zdialog_add_widget(zdedit,"vbox","vbcol2","hbcol",0,"homog|space=8"); X zdialog_add_widget(zdedit,"vbox","vbcol3","hbcol",0,"homog|space=8"); X zdialog_add_widget(zdedit,"vbox","vbcol4","hbcol",0,"homog|space=8"); X- X+ X zdialog_add_widget(zdedit,"label","labcol","vbcol1",ZTX("Font Colors")); X zdialog_add_widget(zdedit,"label","labcol","vbcol1",ZTX("Transparency")); X zdialog_add_widget(zdedit,"label","space","vbcol1"); X- X+ X zdialog_add_widget(zdedit,"colorbutt","fgcolor","vbcol2","0|0|0"); X zdialog_add_widget(zdedit,"spin","fgtrans","vbcol2","0|100|1|0"); X zdialog_add_widget(zdedit,"label","space","vbcol2"); X- X+ X zdialog_add_widget(zdedit,"colorbutt","bgcolor","vbcol3","255|255|255"); X zdialog_add_widget(zdedit,"spin","bgtrans","vbcol3","0|100|1|0"); X zdialog_add_widget(zdedit,"label","labw","vbcol3",ZTX("Width")); X- X+ X zdialog_add_widget(zdedit,"colorbutt","tocolor","vbcol4","255|0|0"); X zdialog_add_widget(zdedit,"spin","totrans","vbcol4","0|100|1|0"); X zdialog_add_widget(zdedit,"spin","towidth","vbcol4","0|9|1|0"); X@@ -15537,12 +15553,12 @@ X while (*pp != ' ') pp--; X if (pp > annotate_font) { X size = atoi(pp); X- if (size >= 6 && size <= 99) X+ if (size >= 6 && size <= 99) X zdialog_stuff(zd,"size",size); X } X- X+ X annotate_gettext(); // build text buffer from annotation data X- X+ X return; X } X X@@ -15554,7 +15570,7 @@ X GtkWidget *font_dialog; X int size, mymouse; X char *pp, text[1000]; X- X+ X if (zd->zstat) X { X freeMouse(); // disconnect mouse function v.10.12 X@@ -15562,7 +15578,7 @@ X else edit_cancel(); // Cancel or kill X return 0; X } X- X+ X if (strEqu(event,"mymouse")) { // toggle mouse capture v.10.12 X zdialog_fetch(zd,"mymouse",mymouse); X if (mymouse) takeMouse(zd,annotate_mousefunc,dragcursor); // connect mouse function v.11.03 X@@ -15575,7 +15591,7 @@ X annotate_text = 0; X if (*text) annotate_text = strdupz(text,0,"annotate"); X } X- X+ X if (strEqu(event,"font")) { // new font X font_dialog = gtk_font_selection_dialog_new(ZTX("select font")); X gtk_font_selection_dialog_set_font_name(GTK_FONT_SELECTION_DIALOG(font_dialog),annotate_font); X@@ -15606,7 +15622,7 @@ X annotate_save(); X return 1; X } X- X+ X if (strEqu(event,"size")) { // new font size X zdialog_fetch(zd,"size",size); X pp = annotate_font + strlen(annotate_font); // "fontname NN" X@@ -15616,31 +15632,31 @@ X X if (strEqu(event,"angle")) X zdialog_fetch(zd,"angle",annotate_angle); X- X+ X if (strEqu(event,"fgcolor")) // foreground (text) color X zdialog_fetch(zd,"fgcolor",annotate_color[0],20); X- X+ X if (strEqu(event,"bgcolor")) // background color X zdialog_fetch(zd,"bgcolor",annotate_color[1],20); X- X+ X if (strEqu(event,"tocolor")) // text outline color X zdialog_fetch(zd,"tocolor",annotate_color[2],20); X- X+ X if (strEqu(event,"fgtrans")) // foreground transparency X zdialog_fetch(zd,"fgtrans",annotate_trans[0]); X- X+ X if (strEqu(event,"bgtrans")) // background transparency X zdialog_fetch(zd,"bgtrans",annotate_trans[1]); X X if (strEqu(event,"totrans")) // text outline transparency X zdialog_fetch(zd,"totrans",annotate_trans[2]); X- X+ X if (strEqu(event,"towidth")) // text outline width X zdialog_fetch(zd,"towidth",annotate_towidth); X X annotate_gettext(); // rebuild text buffer X annotate_write(); // write on image X- zmainloop(); X+ zmainloop(); X X return 1; X } X@@ -15658,14 +15674,14 @@ X annotate_py = Myclick; X annotate_write(); // write text on image X } X- X+ X if (RMclick) { // right mouse click X RMclick = 0; X annotate_mode = 2; // erase text on image X annotate_write(); X annotate_px = annotate_py = -1; // no location on image X } X- X+ X if (Mxdrag || Mydrag) // mouse dragged X { X if (! dragging && annotate_mode) dragging = 1; X@@ -15694,7 +15710,7 @@ X X static int orgx1 = 0, orgy1 = 0, ww1 = 0, hh1 = 0; // old text image overlap rectangle X int orgx2, orgy2, ww2, hh2; // new overlap rectangle X- X+ X if (annotate_mode) // re-write or erase X { X for (py3 = orgy1; py3 < orgy1 + hh1; py3++) // erase prior text image X@@ -15708,7 +15724,7 @@ X pix33[1] = pix31[1]; X pix33[2] = pix31[2]; X } X- X+ X Fmodified = 0; X } X X@@ -15716,14 +15732,14 @@ X annotate_mode = 0; // next time is a 1st write X mwpaint3(orgx1,orgy1,ww1,hh1); // update window X return; X- } X+ } X X if (! annotate_text) { // no text to write X annotate_mode = 0; // next time is a 1st write X mwpaint3(orgx1,orgy1,ww1,hh1); // update window X return; X } X- X+ X if (annotate_px < 0 || annotate_py < 0) { // no image position to write X annotate_mode = 0; // next time is a 1st write X mwpaint3(orgx1,orgy1,ww1,hh1); // update window X@@ -15750,19 +15766,19 @@ X pix1 = PXMpix8(annotate_pxm,px1,py1); // copy-from text pixel X pix2 = PXMpix8(annotate_pxm_transp,px1,py1); // copy-from transparency X pix3 = PXMpix(E3pxm16,px3,py3); // copy-to image pixel X- X+ X e3part = pix2[0] * f256; // image part visible through text X- X+ X pix3[0] = (pix1[0] << 8) + e3part * pix3[0]; // combine text part + image part X pix3[1] = (pix1[1] << 8) + e3part * pix3[1]; X pix3[2] = (pix1[2] << 8) + e3part * pix3[2]; X } X- X+ X mwpaint3(orgx1,orgy1,ww1,hh1); // restore prior overlap rectangle X mwpaint3(orgx2,orgy2,ww2,hh2); // update new overlap rectangle X X Fmodified = 1; X- X+ X orgx1 = orgx2; // remember overlap rectangle X orgy1 = orgy2; // for next call X X@@ -15817,7 +15833,7 @@ X gdk_rgb_find_color(colormap,&black); X gdk_rgb_find_color(colormap,&white); X } X- X+ X pfont = pango_font_description_from_string(font); // make layout with text X playout = gtk_widget_create_pango_layout(drWin,null); X pango_layout_set_font_description(playout,pfont); X@@ -15837,7 +15853,7 @@ X hh = gdk_pixbuf_get_height(pixbuf); X rs = gdk_pixbuf_get_rowstride(pixbuf); X ppix = gdk_pixbuf_get_pixels(pixbuf); X- X+ X pxm_temp1 = PXM_make(ww,hh,8); X X for (py = 0; py < hh; py++) // copy pixbuf to PXM X@@ -15853,7 +15869,7 @@ X g_object_unref(pixmap); X g_object_unref(gdkgc); X g_object_unref(pixbuf); X- X+ X pxm_temp2 = annotate_outline(pxm_temp1); // add text outline color if any X if (pxm_temp2) { X PXM_free(pxm_temp1); X@@ -15910,20 +15926,20 @@ X X fgpart = pix1[0] * f256; // white part = text foreground, 0 - 1 X bgpart = 1.0 - fgpart; // rest = text background part, 1 - 0 X- X+ X if (pix1[1]) // use text outline color X { X fgpart = fgpart * (1.0 - totrans); // reduce for transparencies X- bgpart = bgpart * (1.0 - bgtrans); X+ bgpart = bgpart * (1.0 - bgtrans); X red = tored * fgpart + bgred * bgpart; // red part for text outline + background X green = togreen * fgpart + bggreen * bgpart; // same for green X blue = toblue * fgpart + bgblue * bgpart; // same for blue X } X- X+ X else // use text foreground color X { X fgpart = fgpart * (1.0 - fgtrans); // reduce for transparencies X- bgpart = bgpart * (1.0 - bgtrans); X+ bgpart = bgpart * (1.0 - bgtrans); X red = fgred * fgpart + bgred * bgpart; // red part for text + text background X green = fggreen * fgpart + bggreen * bgpart; // same for green X blue = fgblue * fgpart + bgblue * bgpart; // same for blue X@@ -15935,7 +15951,7 @@ X X pix3[0] = 255 * (1.0 - fgpart - bgpart); // image part visible through text X } X- X+ X ww = ww * fontsize / 99.0 + 0.5; // resize from size 99 font X hh = hh * fontsize / 99.0 + 0.5; // to requested font size X PXM_free(pxm_temp1); X@@ -15943,7 +15959,7 @@ X PXM_free(pxm_temp2); X PXM_free(annotate_pxm); X annotate_pxm = pxm_temp1; X- X+ X pxm_temp1 = PXM_rescale(pxm_temp3,ww,hh); // resize transparency map X PXM_free(pxm_temp3); X PXM_free(annotate_pxm_transp); X@@ -15966,16 +15982,16 @@ X toww = annotate_towidth; // text outline color width X if (toww == 0) return 0; // zero X toww2 = 2 * toww; X- X+ X ww1 = pxm1->ww; // input PXM dimensions X hh1 = pxm1->hh; X- X+ X ww2 = ww1 + toww2; // output PXM with added margins X hh2 = hh1 + toww2; X pxm2 = PXM_make(ww2,hh2,8); X- X+ X memset(pxm2->bmp,0,ww2*hh2*3); // clear output to black X- X+ X for (py1 = 0; py1 < hh1; py1++) // copy input to output, X for (px1 = 0; px1 < ww1; px1++) // displaced for margins X { X@@ -15985,18 +16001,18 @@ X pix2[1] = pix1[1]; X pix2[2] = pix1[2]; X } X- X+ X for (py1 = 0; py1 < hh1; py1++) X for (px1 = 0; px1 < ww1-toww-2; px1++) // horizontal forward scan X { X pix1 = PXMpix8(pxm1,px1,py1); X diff = (pix1+6)[0] - pix1[0]; X if (diff < 200) continue; X- X+ X px2 = px1 + toww; X py2 = py1 + toww; X pix2 = PXMpix8(pxm2,px2-toww/2,py2); X- X+ X for (ii = 0; ii < toww + 1; ii++) X { X pix2[0] = pix1[0]; X@@ -16012,11 +16028,11 @@ X pix1 = PXMpix8(pxm1,px1,py1); X diff = (pix1-6)[0] - pix1[0]; X if (diff < 200) continue; X- X+ X px2 = px1 + toww; X py2 = py1 + toww; X pix2 = PXMpix8(pxm2,px2+toww/2,py2); X- X+ X for (ii = 0; ii < toww + 1; ii++) X { X pix2[0] = pix1[0]; X@@ -16032,11 +16048,11 @@ X pix1 = PXMpix8(pxm1,px1,py1); X diff = (pix1+6*ww1)[0] - pix1[0]; X if (diff < 200) continue; X- X+ X px2 = px1 + toww; X py2 = py1 + toww; X pix2 = PXMpix8(pxm2,px2,py2-toww/2); X- X+ X for (ii = 0; ii < toww + 1; ii++) X { X if (pix2[0] < pix1[0]) pix2[0] = pix1[0]; X@@ -16052,11 +16068,11 @@ X pix1 = PXMpix8(pxm1,px1,py1); X diff = (pix1-6*ww1)[0] - pix1[0]; X if (diff < 200) continue; X- X+ X px2 = px1 + toww; X py2 = py1 + toww; X pix2 = PXMpix8(pxm2,px2,py2+toww/2); X- X+ X for (ii = 0; ii < toww + 1; ii++) X { X if (pix2[0] < pix1[0]) pix2[0] = pix1[0]; X@@ -16081,7 +16097,7 @@ X X file = zgetfile1(dialogtitle,"open",annotations_dirk); // get input file from user X if (! file) return; X- X+ X fid = fopen(file,"r"); // open for read X if (! fid) { X zmessageACK(mWin,"%s",strerror(errno)); X@@ -16093,20 +16109,20 @@ X { X pp = fgets_trim(buff,1200,fid,1); X if (! pp) break; X- X+ X if (strnEqu(pp,"annotate_text ",15)) { X if (annotate_text) zfree(annotate_text); X cc = strlen(pp+15) + 100; X annotate_text = zmalloc(cc,"annotate"); X repl_1str(pp+15,annotate_text,"\\n","\n"); // replace "\n" with real newline char. X } X- X+ X if (strnEqu(pp,"annotate_font ",15)) X strcpy(annotate_font,pp+15); X- X+ X if (strnEqu(pp,"annotate_angle ",16)) X convSD(pp+16,annotate_angle,-180,+180); X- X+ X if (strnEqu(pp,"annotate_fgcolor ",18)) X strcpy(annotate_color[0],pp+18); X X@@ -16135,7 +16151,7 @@ X zfree(file); X return; X } X- X+ X strcpy(annotate_file,file); // update current file X zfree(file); X X@@ -16154,14 +16170,14 @@ X X file = zgetfile1(dialogtitle,"save",annotations_dirk); // get output file from user X if (! file) return; X- X+ X fid = fopen(file,"w"); // open for write X if (! fid) { X zmessageACK(mWin,"%s",strerror(errno)); X zfree(file); X return; X } X- X+ X repl_1str(annotate_text,text,"\n","\\n"); // replace newlines with "\n" X X fprintf(fid,"annotate_text %s \n", text); X@@ -16176,14 +16192,14 @@ X fprintf(fid,"annotate_towidth %d \n", annotate_towidth); X X fprintf(fid,"\n"); X- X+ X err = fclose(fid); X if (err) { X zmessageACK(mWin,"file I/O error %s",file); X zfree(file); X return; X } X- X+ X strcpy(annotate_file,file); // update current file X zfree(file); X X@@ -16205,7 +16221,7 @@ X int rotate_dialog_event(zdialog *zd, cchar *event); X void * rotate_thread(void *); X void rotate_mousefunc(); X- X+ X cchar *rotmess = ZTX("Use buttons or drag right edge with mouse"); X X zfuncs::F1_help_topic = "rotate"; // v.10.8 X@@ -16248,7 +16264,7 @@ X int err, trim = 0; X double incr; X char text[20]; X- X+ X if (zd->zstat) // dialog complete X { X freeMouse(); // disconnect mouse function v.10.12 X@@ -16263,7 +16279,7 @@ X rotate_angle = rotate_delta = rotate_trim = 0; X return 0; X } X- X+ X if (strEqu(event,"undo")) edit_undo(); // v.10.2 X if (strEqu(event,"redo")) edit_redo(); // v.10.3 X X@@ -16273,7 +16289,7 @@ X else zdialog_stuff(zd,"trim",ZTX("Trim")); X trim = 1; // v.10.3 X } X- X+ X if (strpbrk(event,"+-")) { X err = convSD(event,incr); // button name is increment to use X if (err) return 0; X@@ -16307,7 +16323,7 @@ X mpx0 = Mxdown; // new drag started X mpy0 = mpy1 = Mydown; X } X- X+ X mpy2 = Mydrag; X dist = mpy2 - mpy1; // drag distance X mpy1 = mpy2; // reset origin for next time X@@ -16327,7 +16343,7 @@ X int wwcut, hhcut, ww, hh; X double trim_angle, radians; X uint16 *pix3, *pix9; X- X+ X while (true) X { X thread_idle_loop(); // wait for work or exit request X@@ -16335,9 +16351,9 @@ X mutex_lock(&Fpixmap_lock); X Ffuncbusy++; // v.11.01 X X- rotate_angle += rotate_delta; // accum. net rotation X+ rotate_angle += rotate_delta; // accum. net rotation X rotate_delta = 0; // from dialog widget X- X+ X if (rotate_angle >= 360) rotate_angle -=360; X if (rotate_angle <= -360) rotate_angle +=360; X if (fabs(rotate_angle) < 0.01) rotate_angle = 0; X@@ -16349,7 +16365,7 @@ X E3hh = E1hh; X Fmodified = 0; X } X- X+ X if (rotate_angle) { X PXM_free(E3pxm16); X E3pxm16 = PXM_rotate(E1pxm16,rotate_angle); // E3 is rotated E1 X@@ -16369,7 +16385,7 @@ X hh = E3pxm16->hh - 2 * hhcut; X if (ww > 0 && hh > 0) { X E9pxm16 = PXM_make(ww,hh,16); X- X+ X for (py3 = hhcut; py3 < E3hh-hhcut; py3++) // E9 = trimmed E3 X for (px3 = wwcut; px3 < E3ww-wwcut; px3++) X { X@@ -16389,7 +16405,7 @@ X E3hh = hh; X } X } X- X+ X Ffuncbusy--; X mutex_unlock(&Fpixmap_lock); X mwpaint2(); // update window X@@ -16447,11 +16463,11 @@ X { X int px, py; X uint16 *pix3, *pix9; X- X+ X edit_zapredo(); // delete redo copy v.10.3 X X E9pxm16 = PXM_copy(E3pxm16); X- X+ X for (py = 0; py < E3hh; py++) X for (px = 0; px < E3ww; px++) X { X@@ -16461,7 +16477,7 @@ X pix9[1] = pix3[1]; X pix9[2] = pix3[2]; X } X- X+ X mutex_lock(&Fpixmap_lock); X PXM_free(E3pxm16); // image9 >> image3 X E3pxm16 = E9pxm16; X@@ -16478,11 +16494,11 @@ X { X int px, py; X uint16 *pix3, *pix9; X- X+ X edit_zapredo(); // delete redo copy v.10.3 X X E9pxm16 = PXM_copy(E3pxm16); X- X+ X for (py = 0; py < E3hh; py++) X for (px = 0; px < E3ww; px++) X { X@@ -16492,7 +16508,7 @@ X pix9[1] = pix3[1]; X pix9[2] = pix3[2]; X } X- X+ X mutex_lock(&Fpixmap_lock); X PXM_free(E3pxm16); // image9 >> image3 X E3pxm16 = E9pxm16; X@@ -16543,7 +16559,7 @@ X unbend_horz = unbend_vert = 0; X X takeMouse(zdedit,unbend_mousefunc,dragcursor); // connect mouse function v.11.03 X- X+ X start_thread(unbend_thread,0); // start working thread X signal_thread(); X X@@ -16586,23 +16602,23 @@ X X // unbend mouse function // adjustable axes X X-void unbend_mousefunc() X+void unbend_mousefunc() X { X cchar *close; X double dist1, dist2; X double mpx = 0, mpy = 0; X- X+ X if (LMclick) { // left mouse click X LMclick = 0; X mpx = Mxclick; X mpy = Myclick; X } X- X+ X if (Mxdrag || Mydrag) { // mouse dragged X mpx = Mxdrag; X mpy = Mydrag; X } X- X+ X if (! mpx && ! mpy) return; X X mpx = 1.0 * mpx / E3ww; // scale mouse position 0 to 1 X@@ -16642,13 +16658,13 @@ X dist1 = dist2; X close = "bottom"; X } X- X+ X if (strEqu(close,"left")) unbend_y1 = mpy; // set new axis end-point X if (strEqu(close,"right")) unbend_y2 = mpy; X if (strEqu(close,"top")) unbend_x1 = mpx; X if (strEqu(close,"bottom")) unbend_x2 = mpx; X X- signal_thread(); // trigger thread X+ signal_thread(); // trigger thread X X return ; X } X@@ -16685,7 +16701,7 @@ X toplinex2[1] = unbend_vx2; X topliney2[1] = unbend_vy2; X } X- X+ X for (int ii = 0; ii < Nwt; ii++) // start worker threads X start_wt(unbend_wthread,&wtnx[ii]); X wait_wts(); // wait for completion X@@ -16696,7 +16712,7 @@ X return 0; // not executed, stop g++ warning X } X X- X+ X void * unbend_wthread(void *arg) // worker thread function X { X int index = *((int *) arg); X@@ -16707,7 +16723,7 @@ X X vert = int(unbend_vert * 0.01 * E3hh); // convert unbend % to pixels X horz = int(unbend_horz * 0.003 * E3ww); X- X+ X vx1 = unbend_vx1; X vx2 = unbend_vx2; X hy1 = unbend_hy1; X@@ -16735,7 +16751,7 @@ X } X else pix3[0] = pix3[1] = pix3[2] = 0; X } X- X+ X exit_wt(); X return 0; // not executed, avoid gcc warning X } X@@ -16756,13 +16772,13 @@ X void m_warp_area(GtkWidget *, cchar *) X { X int WarpA_dialog_event(zdialog *zd, cchar *event); X- X+ X cchar *WarpA_message = ZTX( X " Select an area to warp using select area function. \n" X " Press [start warp] and pull area with mouse. \n" X " Make multiple mouse pulls until satisfied. \n" X- " When finished, select another area or press [done]."); X- X+ " When finished, select another area or press [done]."); X+ X int px, py, ii; X X zfuncs::F1_help_topic = "warp_area"; X@@ -16782,7 +16798,7 @@ X X WarpAx = (float *) zmalloc(E3ww * E3hh * sizeof(float),"warp.ax"); // get memory for pixel displacements X WarpAy = (float *) zmalloc(E3ww * E3hh * sizeof(float),"warp.ay"); X- X+ X NWarpA = 0; // no warp data X WarpA_started = 0; X X@@ -16792,7 +16808,7 @@ X ii = py * E3ww + px; X WarpAx[ii] = WarpAy[ii] = 0.0; X } X- X+ X return; X } X X@@ -16820,7 +16836,7 @@ X zfree(WarpAy); X return 0; X } X- X+ X if (strEqu(event,"swarp")) // start warp X { X if (! Factivearea || sa_mode == 7) { // no select area active v.11.01 X@@ -16831,7 +16847,7 @@ X takeMouse(zd,WarpA_mousefunc,dragcursor); // connect mouse function v.11.03 X WarpA_started = 1; X } X- X+ X if (! WarpA_started) { X zdialog_stuff(zd,"mymouse",0); X return 0; X@@ -16871,7 +16887,7 @@ X } X X NWarpA = 0; // erase undo memory X- mwpaint2(); X+ mwpaint2(); X } X X return 1; X@@ -16895,8 +16911,8 @@ X warped = 1; X return; X } X- X- else if (warped) X+ X+ else if (warped) X { X warped = 0; X WarpA_warpfunc(wdx,wdy,wdw,wdh,1); // drag done, add to warp memory X@@ -16920,7 +16936,7 @@ X WarpAmem[3][ii] = wdh; X NWarpA++; X } X- X+ X return; X } X X@@ -16934,7 +16950,7 @@ X uint16 vpix[3], *pix3; X X edit_zapredo(); // delete redo copy v.10.3 X- X+ X for (py = sa_miny; py <= sa_maxy; py++) // loop all pixels in area v.10.11 X for (px = sa_minx; px <= sa_maxx; px++) X { X@@ -16952,7 +16968,7 @@ X X dispx = -wdw * mag; // warp = drag * magnification X dispy = -wdh * mag; X- X+ X jj = py * E3ww + px; X X if (acc) { // mouse drag done, X@@ -17004,8 +17020,8 @@ X cchar *WarpC_message = ZTX( X " Pull an image position using the mouse. \n" X " Make multiple mouse pulls until satisfied. \n" X- " When finished, press [done]."); X- X+ " When finished, press [done]."); X+ X int px, py, ii; X X zfuncs::F1_help_topic = "warp_curved"; X@@ -17024,17 +17040,17 @@ X X WarpCx = (float *) zmalloc(E3ww * E3hh * sizeof(float),"warp.ix"); // get memory for pixel displacements X WarpCy = (float *) zmalloc(E3ww * E3hh * sizeof(float),"warp.iy"); X- X+ X for (py = 0; py < E3hh; py++) // no pixel displacements X for (px = 0; px < E3ww; px++) X { X ii = py * E3ww + px; X WarpCx[ii] = WarpCy[ii] = 0.0; X } X- X+ X WarpCww = E3ww; // preview dimensions X WarpChh = E3hh; X- X+ X takeMouse(zdedit,WarpC_mousefunc,dragcursor); // connect mouse function v.11.03 X return; X } X@@ -17055,7 +17071,7 @@ X if (strEqu(event,"undo")) edit_undo(); // v.10.2 X if (strEqu(event,"redo")) edit_redo(); // v.10.3 X X- if (strEqu(event,"undlast")) X+ if (strEqu(event,"undlast")) X { X if (NWarpC == 1) event = "undall"; X else if (NWarpC) { // undo most recent drag X@@ -17081,7 +17097,7 @@ X } X edit_reset(); // restore image 1 v.10.3 X } X- X+ X return 1; X X complete: X@@ -17090,7 +17106,7 @@ X X if (zd->zstat != 1) edit_cancel(); X else if (NWarpC == 0) edit_cancel(); X- else X+ else X { X edit_fullsize(); // get full-size E1/E3 X X@@ -17141,8 +17157,8 @@ X WarpCdrag = 1; X return; X } X- X- else if (WarpCdrag) X+ X+ else if (WarpCdrag) X { X WarpCdrag = 0; X WarpC_warpfunc(wdx,wdy,wdw,wdh,1); // drag done, add to memory X@@ -17166,7 +17182,7 @@ X WarpCmem[3][ii] = wdh; X NWarpC++; X } X- X+ X return; X } X X@@ -17180,14 +17196,14 @@ X double mag, dispx, dispy; X double d1, d2, d3, d4; X uint16 vpix[3], *pix3; X- X+ X edit_zapredo(); // delete redo copy v.10.3 X- X+ X d1 = (mx-0) * (mx-0) + (my-0) * (my-0); // distance, mouse to 4 corners X d2 = (E3ww-mx) * (E3ww-mx) + (my-0) * (my-0); X d3 = (E3ww-mx) * (E3ww-mx) + (E3hh-my) * (E3hh-my); X d4 = (mx-0) * (mx-0) + (E3hh-my) * (E3hh-my); X- X+ X if (d2 > d1) d1 = d2; // d1 = greatest v.10.11 X if (d3 > d1) d1 = d3; X if (d4 > d1) d1 = d4; X@@ -17203,7 +17219,7 @@ X X dispx = -mw * mag; // displacement = drag * mag X dispy = -mh * mag; X- X+ X ii = py * E3ww + px; X X if (acc) { // drag done, accumulate drag sum X@@ -17253,8 +17269,8 @@ X cchar *WarpL_message = ZTX( X " Pull an image position using the mouse. \n" X " Make multiple mouse pulls until satisfied. \n" X- " When finished, press [done]."); X- X+ " When finished, press [done]."); X+ X int px, py, ii; X X zfuncs::F1_help_topic = "warp_linear"; X@@ -17273,17 +17289,17 @@ X X WarpLx = (float *) zmalloc(E3ww * E3hh * sizeof(float),"warp.ix"); // get memory for pixel displacements X WarpLy = (float *) zmalloc(E3ww * E3hh * sizeof(float),"warp.iy"); X- X+ X for (py = 0; py < E3hh; py++) // no pixel displacements X for (px = 0; px < E3ww; px++) X { X ii = py * E3ww + px; X WarpLx[ii] = WarpLy[ii] = 0.0; X } X- X+ X WarpLww = E3ww; // preview dimensions X WarpLhh = E3hh; X- X+ X takeMouse(zdedit,WarpL_mousefunc,dragcursor); // connect mouse function v.11.03 X return; X } X@@ -17304,7 +17320,7 @@ X if (strEqu(event,"undo")) edit_undo(); // v.10.2 X if (strEqu(event,"redo")) edit_redo(); // v.10.3 X X- if (strEqu(event,"undlast")) X+ if (strEqu(event,"undlast")) X { X if (NWarpL == 1) event = "undall"; X else if (NWarpL) { // undo most recent drag X@@ -17339,7 +17355,7 @@ X X if (zd->zstat != 1) edit_cancel(); X else if (NWarpL == 0) edit_cancel(); X- else X+ else X { X edit_fullsize(); // get full-size E1/E3 X X@@ -17390,8 +17406,8 @@ X WarpLdrag = 1; X return; X } X- X- else if (WarpLdrag) X+ X+ else if (WarpLdrag) X { X WarpLdrag = 0; X WarpL_warpfunc(wdx,wdy,wdw,wdh,1); // drag done, add to memory X@@ -17415,7 +17431,7 @@ X WarpLmem[3][ii] = wdh; X NWarpL++; X } X- X+ X return; X } X X@@ -17429,18 +17445,18 @@ X double mag, dispx, dispy; X double d1, d2, d3, d4; X uint16 vpix[3], *pix3; X- X+ X edit_zapredo(); // delete redo copy v.10.3 X- X+ X d1 = (mx-0) * (mx-0) + (my-0) * (my-0); // distance, mouse to 4 corners X d2 = (E3ww-mx) * (E3ww-mx) + (my-0) * (my-0); X d3 = (E3ww-mx) * (E3ww-mx) + (E3hh-my) * (E3hh-my); X d4 = (mx-0) * (mx-0) + (E3hh-my) * (E3hh-my); X- X+ X if (d2 > d1) d1 = d2; // d1 = greatest v.10.11 X if (d3 > d1) d1 = d3; X if (d4 > d1) d1 = d4; X- X+ X d1 = sqrt(d1); X X for (py = 0; py < E3hh; py++) // process all pixels X@@ -17452,7 +17468,7 @@ X X dispx = -mw * mag; // displacement = drag * mag X dispy = -mh * mag; X- X+ X ii = py * E3ww + px; X X if (acc) { // drag done, accumulate drag sum X@@ -17482,10 +17498,10 @@ X X /**************************************************************************/ X X-// warp/distort whole image using affine transform X+// warp/distort whole image using affine transform X // (straight lines remain straight) X X-double WarpF_old[3][2]; // 3 original image points X+double WarpF_old[3][2]; // 3 original image points X double WarpF_new[3][2]; // corresponding warped points X double WarpF_coeff[6]; // transform coefficients X double WarpF_Icoeff[6]; // inverse transform coefficients X@@ -17504,8 +17520,8 @@ X cchar *WarpF_message = ZTX( X " Pull on an image corner using the mouse. \n" X " Make multiple mouse pulls until satisfied. \n" X- " When finished, press [done]."); X- X+ " When finished, press [done]."); X+ X zfuncs::F1_help_topic = "warp_affine"; X X if (! edit_setup("warp_affine",1,0)) return; // setup edit: use preview X@@ -17540,8 +17556,8 @@ X freeMouse(); // disconnect mouse X X if (zd->zstat != 1) edit_cancel(); X- X- else X+ X+ else X { X ww = E3ww; // preview image dimensions X hh = E3hh; X@@ -17549,7 +17565,7 @@ X edit_fullsize(); // get full-size images X X scale = 1.0 * (E3ww + E3hh) / (ww + hh); // preview to full-size scale factor X- X+ X WarpF_old[0][0] = WarpF_old[0][0] * scale; // re-scale new and old points X WarpF_old[0][1] = WarpF_old[0][1] * scale; X WarpF_old[1][0] = WarpF_old[1][0] * scale; X@@ -17563,7 +17579,7 @@ X WarpF_new[1][1] = WarpF_new[1][1] * scale; X WarpF_new[2][0] = WarpF_new[2][0] * scale; X WarpF_new[2][1] = WarpF_new[2][1] * scale; X- X+ X WarpF_warpfunc(); // warp full-size image X edit_done(); X } X@@ -17580,7 +17596,7 @@ X double x1o, y1o, x2o, y2o, x3o, y3o; X double x1n, y1n, x2n, y2n, x3n, y3n; X double a, b, c, d, e, f; X- X+ X if (Mxdrag + Mydrag == 0) return; X X mdx1 = Mxdown; // mouse drag origin X@@ -17590,7 +17606,7 @@ X X Mxdown = Mxdrag; // reset origin for next time X Mydown = Mydrag; X- X+ X x1n = mdx1; // point 1 = drag origin X y1n = mdy1; X x2n = E3ww - x1n; // point 2 = mirror of point1 X@@ -17617,7 +17633,7 @@ X d = WarpF_Icoeff[3]; X e = WarpF_Icoeff[4]; X f = WarpF_Icoeff[5]; X- X+ X x1o = a * x1n + b * y1n + c; // compute old from current positions X y1o = d * x1n + e * y1n + f; X x2o = a * x2n + b * y2n + c; X@@ -17625,7 +17641,7 @@ X x3o = a * x3n + b * y3n + c; X y3o = d * x3n + e * y3n + f; X } X- X+ X WarpF_old[0][0] = x1o; // set up 3 old points and corresponding X WarpF_old[0][1] = y1o; // new points for affine translation X WarpF_old[1][0] = x2o; X@@ -17638,13 +17654,13 @@ X x2n = E3ww - x1n; // point 2 new = mirror of point1 new X y2n = E3hh - y1n; X X- WarpF_new[0][0] = x1n; // 3 new points X+ WarpF_new[0][0] = x1n; // 3 new points X WarpF_new[0][1] = y1n; X WarpF_new[1][0] = x2n; X WarpF_new[1][1] = y2n; X WarpF_new[2][0] = x3n; X WarpF_new[2][1] = y3n; X- X+ X WarpF_warpfunc(); // do the warp X X return; X@@ -17659,19 +17675,19 @@ X int px3, py3, vstat; X double px1, py1; X uint16 vpix1[3], *pix3; X- X+ X edit_zapredo(); // delete redo copy v.10.3 X X WarpF_affine(WarpF_old, WarpF_new, WarpF_coeff); // get coefficients for forward transform X WarpF_invert(WarpF_coeff, WarpF_Icoeff); // get coefficients for reverse transform X- X+ X a = WarpF_Icoeff[0]; // coefficients to map output pixels X b = WarpF_Icoeff[1]; // to corresponding input pixels X c = WarpF_Icoeff[2]; X d = WarpF_Icoeff[3]; X e = WarpF_Icoeff[4]; X f = WarpF_Icoeff[5]; X- X+ X for (py3 = 0; py3 < E3hh; py3++) // loop all output pixels X for (px3 = 0; px3 < E3ww; px3++) X { X@@ -17699,14 +17715,14 @@ X X Compute affine transformation of an image (warp image). X X- Given 3 new (warped) positions for 3 image points, derive the X+ Given 3 new (warped) positions for 3 image points, derive the X coefficients of the translation function to warp the entire image. X X Inputs: X pold[3][2] (x,y) coordinates for 3 points in original image X pnew[3][2] (x,y) coordinates for same points in warped image X- X- Output: X+ X+ Output: X coeff[6] coefficients of translation function which can be used X to convert all image points to their warped positions X X@@ -17724,7 +17740,7 @@ X double x21, y21, x22, y22, x23, y23; // moved points X double a, b, c, d, e, f; // coefficients X double A1, A2, B1, B2, C1, C2; X- X+ X x11 = pold[0][0]; X y11 = pold[0][1]; X x12 = pold[1][0]; X@@ -17738,25 +17754,25 @@ X y22 = pnew[1][1]; X x23 = pnew[2][0]; X y23 = pnew[2][1]; X- X+ X A1 = x11 - x12; X A2 = x12 - x13; X B1 = y11 - y12; X B2 = y12 - y13; X C1 = x21 - x22; X C2 = x22 - x23; X- X+ X a = (B1 * C2 - B2 * C1) / (A2 * B1 - A1 * B2); X b = (A1 * C2 - A2 * C1) / (A1 * B2 - A2 * B1); X c = x23 - a * x13 - b * y13; X- X+ X C1 = y21 - y22; X C2 = y22 - y23; X- X+ X d = (B1 * C2 - B2 * C1) / (A2 * B1 - A1 * B2); X e = (A1 * C2 - A2 * C1) / (A1 * B2 - A2 * B1); X f = y23 - d * x13 - e * y13; X- X+ X coeff[0] = a; X coeff[1] = b; X coeff[2] = c; X@@ -17765,7 +17781,7 @@ X coeff[5] = f; X X return; X-} X+} X X X /************************************************************************** X@@ -17775,7 +17791,7 @@ X Input: X coeff[6] coefficients of translation function to convert X image points to their warped positions X- Output: X+ Output: X Icoeff[6] coefficients of translation function to convert X warped image points to their original positions X X@@ -17790,23 +17806,23 @@ X void WarpF_invert(double coeff[6], double Icoeff[6]) X { X double a, b, c, d, e, f, Z; X- X+ X a = coeff[0]; X b = coeff[1]; X c = coeff[2]; X d = coeff[3]; X e = coeff[4]; X f = coeff[5]; X- X+ X Z = 1.0 / (a * e - b * d); X- X+ X Icoeff[0] = e * Z; X Icoeff[1] = - b * Z; X Icoeff[2] = Z * (b * f - c * e); X Icoeff[3] = - d * Z; X Icoeff[4] = a * Z; X Icoeff[5] = Z * (c * d - a * f); X- X+ X return; X } X X@@ -17824,7 +17840,7 @@ X void * colordep_thread(void *); X X cchar *colmess = ZTX("Set color depth to 1-16 bits"); X- X+ X zfuncs::F1_help_topic = "color_depth"; // v.10.8 X X if (! edit_setup("colordepth",1,2)) return; // setup edit: preview X@@ -17835,7 +17851,7 @@ X zdialog_add_widget(zdedit,"spin","colors","hb1","1|16|1|16","space=5"); X X zdialog_run(zdedit,colordep_dialog_event); // run dialog - parallel X- X+ X colordep_depth = 16; X start_thread(colordep_thread,0); // start working thread X return; X@@ -17861,7 +17877,7 @@ X zdialog_fetch(zd,"colors",colordep_depth); X signal_thread(); X } X- X+ X return 0; X } X X@@ -17874,14 +17890,14 @@ X uint16 m1, m2, val1, val3; X uint16 *pix1, *pix3; X double fmag, f1, f2; X- X+ X while (true) X { X thread_idle_loop(); // wait for work or exit request X- X+ X m1 = 0xFFFF << (16 - colordep_depth); // 5 > 1111100000000000 X m2 = 0x8000 >> colordep_depth; // 5 > 0000010000000000 X- X+ X fmag = 65535.0 / m1; X X for (py = 0; py < E3hh; py++) X@@ -17895,7 +17911,7 @@ X X pix1 = PXMpix(E1pxm16,px,py); // input pixel X pix3 = PXMpix(E3pxm16,px,py); // output pixel X- X+ X for (rgb = 0; rgb < 3; rgb++) X { X val1 = pix1[rgb]; X@@ -17987,7 +18003,7 @@ X X zdialog_resize(zdedit,300,0); X zdialog_run(zdedit,draw_dialog_event); // run dialog - parallel X- X+ X start_thread(draw_thread,0); // start working thread X return; X } X@@ -18009,7 +18025,7 @@ X if (strEqu(event,"redo")) edit_redo(); // v.10.3 X if (strEqu(event,"blendwidth")) signal_thread(); // v.10.3 X X- if (strcmpv(event,"contrast","threshold","pixcon","chalk",null)) X+ if (strcmpv(event,"contrast","threshold","pixcon","chalk",null)) X { X zdialog_fetch(zd,"contrast",draw_contrast); // get slider values X zdialog_fetch(zd,"threshold",draw_threshold); X@@ -18030,21 +18046,21 @@ X X int ii; X double threshold, contrast, trf; X- X+ X while (true) X { X thread_idle_loop(); // wait for work or exit request X X threshold = 0.01 * draw_threshold; // range 0 to 1 X contrast = 0.01 * draw_contrast; // range 0 to 1 X- X+ X for (ii = 0; ii < 256; ii++) // brightness transfer function X { X trf = 1.0 - 0.003906 * (256 - ii) * contrast; // ramp-up from 0-1 to 1 X if (ii < 256 * threshold) trf = 0; // 0 if below threshold X draw_trfunc[ii] = trf; X } X- X+ X for (ii = 0; ii < Nwt; ii++) // start worker threads X start_wt(draw_wthread,&wtnx[ii]); X wait_wts(); // wait for completion X@@ -18092,17 +18108,17 @@ X dist = sa_pixisin[ii]; // distance from edge X if (! dist) return; // outside pixel X } X- X+ X pix1 = PXMpix(E1pxm16,px,py); // input pixel X pix3 = PXMpix(E3pxm16,px,py); // output pixel X- X+ X red1 = pix1[0]; X green1 = pix1[1]; X blue1 = pix1[2]; X- X+ X bright1 = ((red1 + green1 + blue1) / 3) >> 8; // old brightness 0-255 X bright2 = bright1 * draw_trfunc[bright1]; // new brightness 0-255 X- X+ X ii = py * E1ww + px; X if (draw_pixcon_map[ii] < pixcon) bright2 = 255; X X@@ -18123,7 +18139,7 @@ X pix3[0] = red3; X pix3[1] = green3; X pix3[2] = blue3; X- X+ X return; X } X X@@ -18143,20 +18159,20 @@ X cchar *title = ZTX("Add Image Outlines"); X X zfuncs::F1_help_topic = "outlines"; X- X+ X if (! edit_setup("outlines",0,2)) return; // setup edit: no preview, select area OK X X zdedit = zdialog_new(title,mWin,Bdone,Bcancel,null); X zdialog_add_widget(zdedit,"hbox","hb1","dialog",0,"space=5"); X zdialog_add_widget(zdedit,"label","lab1","hb1",ZTX("outline threshold"),"space=5"); X- zdialog_add_widget(zdedit,"hscale","olth","hb1","0|100|1|90","expand|space=5"); X+ zdialog_add_widget(zdedit,"hscale","olth","hb1","0|100|1|90","expand|space=5"); X zdialog_add_widget(zdedit,"hbox","hb2","dialog",0,"space=5"); X zdialog_add_widget(zdedit,"label","lab2","hb2",ZTX("outline width"),"space=5"); X zdialog_add_widget(zdedit,"hscale","olww","hb2","0|100|1|50","expand|space=5"); X zdialog_add_widget(zdedit,"hbox","hb3","dialog",0,"space=5"); X zdialog_add_widget(zdedit,"label","lab3","hb3",ZTX("image brightness"),"space=5"); X zdialog_add_widget(zdedit,"hscale","imbr","hb3","0|100|1|10","expand|space=5"); X- X+ X outlines_olth = 90; X outlines_olww = 50; X outlines_imbr = 10; X@@ -18181,7 +18197,7 @@ X PXM_free(E9pxm16); X return 0; X } X- X+ X if (strEqu(event,"olth")) { X zdialog_fetch(zd,"olth",outlines_olth); // get outline threshold 0-100 X signal_thread(); X@@ -18191,12 +18207,12 @@ X zdialog_fetch(zd,"olww",outlines_olww); // get outline width 0-100 X signal_thread(); X } X- X+ X if (strEqu(event,"imbr")) { X zdialog_fetch(zd,"imbr",outlines_imbr); // get image brightness 0-100 X signal_thread(); X } X- X+ X if (strEqu(event,"undo")) edit_undo(); X if (strEqu(event,"redo")) edit_redo(); X if (strEqu(event,"blendwidth")) signal_thread(); X@@ -18210,7 +18226,7 @@ X void * outlines_thread(void *) X { X void * outlines_wthread(void *arg); X- X+ X int px, py, ww, hh; X double olww, red3, green3, blue3; X double red3h, red3v, green3h, green3v, blue3h, blue3v; X@@ -18220,14 +18236,14 @@ X while (true) X { X thread_idle_loop(); // wait for work or exit request X- X+ X olww = 0.01 * outlines_olww; // outline width, 0 - 1.0 X olww = 1.0 - olww; // 1.0 - 0 X olww = 0.8 * olww + 0.2; // 1.0 - 0.2 X X ww = Fww * olww + 0.5; // create smaller outline image X hh = Fhh * olww + 0.5; X- X+ X if (! E9pxm16 || ww != E9pxm16->ww) // initial or changed outline brightness X { X PXM_free(E8pxm16); X@@ -18241,7 +18257,7 @@ X { X pix8 = PXMpix(E8pxm16,px,py); // input pixel X pix9 = PXMpix(E9pxm16,px,py); // output pixel X- X+ X pixa = pix8-3*ww-3; // 8 neighboring pixels are used X pixb = pix8-3*ww; // to get edge brightness using X pixc = pix8-3*ww+3; // a Sobel filter X@@ -18250,18 +18266,18 @@ X pixf = pix8+3*ww-3; X pixg = pix8+3*ww; X pixh = pix8+3*ww+3; X- X+ X red3h = -pixa[0] -2 * pixb[0] -pixc[0] + pixf[0] + 2 * pixg[0] + pixh[0]; X red3v = -pixa[0] -2 * pixd[0] -pixf[0] + pixc[0] + 2 * pixe[0] + pixh[0]; X green3h = -pixa[1] -2 * pixb[1] -pixc[1] + pixf[1] + 2 * pixg[1] + pixh[1]; X green3v = -pixa[1] -2 * pixd[1] -pixf[1] + pixc[1] + 2 * pixe[1] + pixh[1]; X blue3h = -pixa[2] -2 * pixb[2] -pixc[2] + pixf[2] + 2 * pixg[2] + pixh[2]; X blue3v = -pixa[2] -2 * pixd[2] -pixf[2] + pixc[2] + 2 * pixe[2] + pixh[2]; X- X+ X red3 = (abs(red3h) + abs(red3v)) / 2; // average vertical and horizontal brightness X green3 = (abs(green3h) + abs(green3v)) / 2; X blue3 = (abs(blue3h) + abs(blue3v)) / 2; X- X+ X if (red3 > 65535) red3 = 65535; X if (green3 > 65535) green3 = 65535; X if (blue3 > 65535) blue3 = 65535; X@@ -18271,7 +18287,7 @@ X pix9[2] = blue3; X } X } X- X+ X PXM_free(E8pxm16); // scale back to full-size X E8pxm16 = PXM_rescale(E9pxm16,Fww,Fhh); X X@@ -18294,7 +18310,7 @@ X double olth, imbr, br8, dold, dnew; X double red1, green1, blue1, red3, green3, blue3; X uint16 *pix1, *pix8, *pix3; X- X+ X olth = 0.01 * outlines_olth; // outline threshold, 0 - 1.0 X olth = 1.0 - olth; // 1.0 - 0 X imbr = 0.01 * outlines_imbr; // image brightness, 0 - 1.0 X@@ -18307,15 +18323,15 @@ X dist = sa_pixisin[ii]; // distance from edge X if (! dist) continue; // pixel outside area X } X- X+ X pix1 = PXMpix(E1pxm16,px,py); // input image pixel X pix8 = PXMpix(E8pxm16,px,py); // input outline pixel X pix3 = PXMpix(E3pxm16,px,py); // output image pixel X- X+ X red1 = pix1[0]; // input image pixel X green1 = pix1[1]; X blue1 = pix1[2]; X- X+ X br8 = pixbright(pix8); // outline brightness X br8 = br8 / 65536.0; // scale 0 - 1.0 X X@@ -18329,7 +18345,7 @@ X green3 = green1 * imbr; X blue3 = blue1 * imbr; X } X- X+ X if (Factivearea && dist < sa_blend) { // select area is active, X dnew = 1.0 * dist / sa_blend; // blend changes over sa_blend X dold = 1.0 - dnew; X@@ -18337,12 +18353,12 @@ X green3 = dnew * green3 + dold * green1; X blue3 = dnew * blue3 + dold * blue1; X } X- X+ X pix3[0] = red3; X pix3[1] = green3; X pix3[2] = blue3; X } X- X+ X exit_wt(); X return 0; // not executed, stop gcc warning X } X@@ -18376,7 +18392,7 @@ X zdialog_add_widget(zdedit,"check","color","hb1",ZTX("color"),"space=8"); X X zdialog_run(zdedit,emboss_dialog_event); // run dialog - parallel X- X+ X start_thread(emboss_thread,0); // start working thread X return; X } X@@ -18417,11 +18433,11 @@ X X int ii, dx, dy, rad; X double depth, kern, coeff; X- X+ X while (true) X { X thread_idle_loop(); // wait for work or exit request X- X+ X rad = emboss_radius; X depth = emboss_depth; X X@@ -18433,7 +18449,7 @@ X kern = coeff * (dx + dy); X emboss_kernel[dx+rad][dy+rad] = kern; X } X- X+ X emboss_kernel[rad][rad] = 1; // kernel center cell = 1 X X for (ii = 0; ii < Nwt; ii++) // start worker threads X@@ -18471,7 +18487,7 @@ X int rgb, dx, dy, rad; X uint16 *pix1, *pix3, *pixN; X double sumpix, kern, dold, dnew; X- X+ X if (Factivearea) { // select area active X ii = py * Fww + px; X dist = sa_pixisin[ii]; // distance from edge X@@ -18482,23 +18498,23 @@ X X if (px < rad || py < rad) return; X if (px > E3ww-rad-1 || py > E3hh-rad-1) return; X- X+ X pix1 = PXMpix(E1pxm16,px,py); // input pixel X pix3 = PXMpix(E3pxm16,px,py); // output pixel X- X- if (emboss_color) X+ X+ if (emboss_color) X { X for (rgb = 0; rgb < 3; rgb++) X- { X+ { X sumpix = 0; X- X+ X for (dy = -rad; dy <= rad; dy++) // loop surrounding block of pixels X for (dx = -rad; dx <= rad; dx++) X { X pixN = pix1 + (dy * E1ww + dx) * 3; X kern = emboss_kernel[dx+rad][dy+rad]; X sumpix += kern * pixN[rgb]; X- X+ X bright1 = pix1[rgb]; X bright3 = sumpix; X if (bright3 < 0) bright3 = 0; X@@ -18514,11 +18530,11 @@ X } X } X } X- X+ X else // use gray scale X { X sumpix = 0; X- X+ X for (dy = -rad; dy <= rad; dy++) // loop surrounding block of pixels X for (dx = -rad; dx <= rad; dx++) X { X@@ -18526,12 +18542,12 @@ X kern = emboss_kernel[dx+rad][dy+rad]; X sumpix += kern * (pixN[0] + pixN[1] + pixN[2]); X } X- X+ X bright1 = 0.3333 * (pix1[0] + pix1[1] + pix1[2]); X bright3 = 0.3333 * sumpix; X if (bright3 < 0) bright3 = 0; X if (bright3 > 65535) bright3 = 65535; X- X+ X if (Factivearea && dist < sa_blend) { // select area is active, X dnew = 1.0 * dist / sa_blend; // blend changes over sa_blend X dold = 1.0 - dnew; X@@ -18603,13 +18619,13 @@ X if (strNeq(event,"apply")) return 0; X X zdialog_fetch(zd,"size",tile_size); // get tile size X- zdialog_fetch(zd,"gap",tile_gap); // get tile gap X+ zdialog_fetch(zd,"gap",tile_gap); // get tile gap X X if (tile_size < 2) { X edit_reset(); // restore original image X return 0; X } X- X+ X signal_thread(); // trigger working thread X return 1; X } X@@ -18628,7 +18644,7 @@ X while (true) X { X thread_idle_loop(); // wait for work or exit request X- X+ X Ffuncbusy++; // v.11.01 X X sg = tile_size + tile_gap; X@@ -18656,12 +18672,12 @@ X green = (green / sumpix); X blue = (blue / sumpix); X } X- X+ X for (qy = py; qy < py + sg; qy++) // set color for pixels in block X for (qx = px; qx < px + sg; qx++) X { X if (qy > E1hh-1 || qx > E1ww-1) continue; X- X+ X jj = (qy * E1ww + qx) * 3; X X if (qx-px < gg || qy-py < gg) { X@@ -18790,25 +18806,25 @@ X double f64K = 1.0 / 65536.0; X double fpi = 1.0 / 3.14159; X double dcx, dcy, qcx, qcy, qdist2; X- X+ X while (true) X { X thread_idle_loop(); // wait for work or exit request X- X- mutex_lock(&Fpixmap_lock); X X- Ffuncbusy++; // v.11.01 X- X+ mutex_lock(&Fpixmap_lock); X+ X+ Ffuncbusy++; // v.11.01 X+ X ds = dot_size; // dot size and tile size X X cc = E3ww * E3hh * 6; // clear output image to black X memset(E3pxm16->bmp,0,cc); X- X- px1 = 0; // limits for tiles X+ X+ px1 = 0; // limits for tiles X px2 = Fww - ds; X py1 = 0; X py2 = Fhh - ds; X- X+ X if (Factivearea) { // reduce for active area X px1 = sa_minx; X px2 = sa_maxx; X@@ -18817,7 +18833,7 @@ X if (px2 > Fww - ds) px2 = Fww - ds; X if (py2 > Fhh - ds) py2 = Fhh - ds; X } X- X+ X shift1 = 0; X X for (py = py1; py < py2; py += ds) // loop all tiles in input image X@@ -18838,37 +18854,37 @@ X blue += pix1[2]; X sumpix++; X } X- X+ X red = (red / sumpix); // mean RGB levels, 0 to 64K X green = (green / sumpix); X blue = (blue / sumpix); X- X+ X maxrgb = red; // max. mean RGB level, 0 to 64K X if (green > maxrgb) maxrgb = green; X if (blue > maxrgb) maxrgb = blue; X if (maxrgb < 100) continue; // very dark tile X- X+ X relmax = f64K * maxrgb; // max. RGB as 0 to 0.999 X- X+ X radius = ds * sqrt(fpi * relmax); // radius of dot with maximized color X radius = radius * 0.7; // deliberate reduction X if (radius < 0.5) continue; X- X+ X red = 65535.0 * red / maxrgb; // dot color, maximized X green = 65535.0 * green / maxrgb; X blue = 65535.0 * blue / maxrgb; X X dcx = px + 0.5 * ds; // center of dot / tile X dcy = py + 0.5 * ds; X- X+ X qx1 = dcx - radius; // pixels within dot radius of center X qx2 = dcx + radius; X qy1 = dcy - radius; X qy2 = dcy + radius; X- X+ X radius2a = (radius + 0.5) * (radius + 0.5); X radius2b = (radius - 0.5) * (radius - 0.5); X- X+ X for (qy = qy1; qy <= qy2; qy++) // loop all pixels within dot radius X for (qx = qx1; qx <= qx2; qx++) X { X@@ -18885,12 +18901,12 @@ X } X } X } X- X+ X if (Factivearea) // select area active X { X pix1 = (uint16 *) E1pxm16->bmp; X pix3 = (uint16 *) E3pxm16->bmp; X- X+ X for (ii = 0; ii < Fww * Fhh; ii++) // loop all pixels X { X dist = sa_pixisin[ii]; X@@ -18907,7 +18923,7 @@ X } X } X X- mutex_unlock(&Fpixmap_lock); X+ mutex_unlock(&Fpixmap_lock); X X Ffuncbusy--; X Fmodified = 1; X@@ -18923,7 +18939,7 @@ X // convert image to simulate a painting X // processing a 10 megapixel image needs 140 MB of main memory X X-namespace paint_names X+namespace paint_names X { X int color_depth; X int group_area; X@@ -19010,7 +19026,7 @@ X signal_thread(); // do the work X wait_thread_idle(); X } X- X+ X return 0; X } X X@@ -19084,7 +19100,7 @@ X } X } X } X- X+ X else // process entire image X { X for (py = 0; py < E3hh; py++) // loop all pixels X@@ -19092,7 +19108,7 @@ X { X pix1 = PXMpix(E1pxm16,px,py); // input pixel X pix3 = PXMpix(E3pxm16,px,py); // output pixel X- X+ X for (rgb = 0; rgb < 3; rgb++) X { X val1 = pix1[rgb]; X@@ -19126,19 +19142,19 @@ X cc2 = cc1 * sizeof(int); X pixgroup = (int *) zmalloc(cc2,"pixgroup"); // maps pixel to assigned group X memset(pixgroup,0,cc2); X- X+ X if (Factivearea) cc1 = sa_Npixel; X X cc2 = cc1 * sizeof(spixstack); X pixstack = (spixstack *) zmalloc(cc2,"pixstack"); // memory stack for pixel search X memset(pixstack,0,cc2); X- X+ X cc2 = cc1 * sizeof(int); X groupcount = (int *) zmalloc(cc2,"groupcount"); // counts pixels per group X memset(groupcount,0,cc2); X- X+ X group = 0; X- X+ X for (py = 0; py < E3hh; py++) // loop all pixels X for (px = 0; px < E3ww; px++) X { X@@ -19165,7 +19181,7 @@ X px = pixstack[kk].px; X py = pixstack[kk].py; X direc = pixstack[kk].direc; X- X+ X if (direc == 'x') { X Nstack--; X continue; X@@ -19201,7 +19217,7 @@ X X if (npx < 0 || npx >= E3ww) continue; // pixel off the edge X if (npy < 0 || npy >= E3hh) continue; X- X+ X kk = npy * E3ww + npx; X X if (Factivearea) X@@ -19212,7 +19228,7 @@ X pix3 = PXMpix(E3pxm16,npx,npy); X if (pix3[0] != gcolor[0] || pix3[1] != gcolor[1] // not same color as group X || pix3[2] != gcolor[2]) continue; X- X+ X pixgroup[kk] = group; // assign pixel to group X ++groupcount[group]; X X@@ -19222,9 +19238,9 @@ X pixstack[kk].direc = 'r'; // direction = right X } X } X- X+ X return; X-} X+} X X X // merge small pixel groups into adjacent larger groups with best color match X@@ -19248,10 +19264,10 @@ X } snewgroup; X X snewgroup *newgroup; X- X+ X nccc = (group + 1) * sizeof(snewgroup); X newgroup = (snewgroup *) zmalloc(nccc,"newgroup"); X- X+ X if (Factivearea) // process select area X { X while (true) X@@ -19281,7 +19297,7 @@ X kk = E3ww * npy + npx; X if (! sa_pixisin[kk]) continue; // pixel outside area X if (pixgroup[kk] == group) continue; // already in same group X- X+ X pixN = PXMpix(E3pxm16,npx,npy); // match color of group neighbor X fred = ff * abs(pix3[0] - pixN[0]); // to color of group X fgreen = ff * abs(pix3[1] - pixN[1]); X@@ -19311,7 +19327,7 @@ X group = pixgroup[kk]; // test for new group assignment X group2 = newgroup[group].group; X if (! group2) continue; X- X+ X if (groupcount[group] > groupcount[group2]) continue; // accept only bigger new group X X pixgroup[kk] = group2; // make new group assignment X@@ -19325,7 +19341,7 @@ X X mcount++; X } X- X+ X if (mcount == 0) break; X } X } X@@ -19352,7 +19368,7 @@ X X if (npx < 0 || npx >= E3ww) continue; // off the edge X if (npy < 0 || npy >= E3hh) continue; X- X+ X kk = E3ww * npy + npx; X if (pixgroup[kk] == group) continue; // in same group X X@@ -19382,7 +19398,7 @@ X group = pixgroup[kk]; // test for new group assignment X group2 = newgroup[group].group; X if (! group2) continue; X- X+ X if (groupcount[group] > groupcount[group2]) continue; // accept only bigger new group X X pixgroup[kk] = group2; // make new group assignment X@@ -19396,7 +19412,7 @@ X X mcount++; X } X- X+ X if (mcount == 0) break; X } X } X@@ -19418,9 +19434,9 @@ X X int ii, kk, px, py, cc; X uint16 *pix3, *pixL, *pixA; X- X+ X if (! borders) return; X- X+ X cc = E3ww * E3hh; X char * pixblack = zmalloc(cc,"pixblack"); X memset(pixblack,0,cc); X@@ -19437,7 +19453,7 @@ X pix3 = PXMpix(E3pxm16,px,py); X pixL = PXMpix(E3pxm16,px-1,py); X pixA = PXMpix(E3pxm16,px,py-1); X- X+ X if (pix3[0] != pixL[0] || pix3[1] != pixL[1] || pix3[2] != pixL[2]) X { X kk = ii - 1; X@@ -19468,7 +19484,7 @@ X pix3[0] = pix3[1] = pix3[2] = 0; X } X } X- X+ X else X { X for (py = 1; py < E3hh; py++) // loop all pixels X@@ -19477,7 +19493,7 @@ X pix3 = PXMpix(E3pxm16,px,py); // output pixel X pixL = PXMpix(E3pxm16,px-1,py); // pixel to left X pixA = PXMpix(E3pxm16,px,py-1); // pixel above X- X+ X if (pix3[0] != pixL[0] || pix3[1] != pixL[1] || pix3[2] != pixL[2]) X { X kk = E3ww * py + px-1; // have horiz. transition X@@ -19505,7 +19521,7 @@ X pix3[0] = pix3[1] = pix3[2] = 0; X } X } X- X+ X zfree(pixblack); X return; X } X@@ -19518,7 +19534,7 @@ X int ii, px, py, rgb, dist; X uint16 *pix1, *pix3; X double f1, f2; X- X+ X if (Factivearea && sa_blend > 0) X { X for (ii = 0; ii < Fww * Fhh; ii++) // find pixels in select area X@@ -19570,7 +19586,7 @@ X uint16 npix; // no. pixels in this block X uint16 px, py; // center pixel (radius org.) X uint16 radius; // radius of pixel block X- uint16 pixel[][3]; // array of pixel[npix][3] X+ uint16 pixel[][3]; // array of pixel[npix][3] X } pixed_savepix; X X pixed_savepix **pixed_undopixmem = 0; // array of *pixed_savepix X@@ -19621,9 +19637,9 @@ X X snprintf(undomemmessage,99,pixed_undomemmessage,0,'%'); // stuff undo memory status X zdialog_stuff(zdedit,"labmem",undomemmessage); X- X+ X pixed_RGB[0] = pixed_RGB[1] = pixed_RGB[2] = 100; // initialize color X- X+ X pixed_mode = 1; // mode = pick color X X pixed_undopixmem = 0; // no undo data X@@ -19644,9 +19660,9 @@ X cchar *pp; X int radius, dx, dy, brad, mymouse; X double rad, kern, trcent, tredge; X- X+ X if (zd->zstat) goto complete; X- X+ X if (strEqu(event,"mymouse")) { // toggle mouse capture v.10.12 X zdialog_fetch(zd,"mymouse",mymouse); X if (mymouse) // connect mouse function v.11.03 X@@ -19664,8 +19680,8 @@ X if (brad) pixed_mode = 2; X zdialog_fetch(zd,"radio3",brad); // erase X if (brad) pixed_mode = 3; X- X- if (strEqu(event,"color")) X+ X+ if (strEqu(event,"color")) X { X zdialog_fetch(zd,"color",color,19); // get color from color wheel X pp = strField(color,"|",1); X@@ -19675,7 +19691,7 @@ X pp = strField(color,"|",3); X if (pp) pixed_RGB[2] = atoi(pp); X } X- X+ X if (strstr("radius trcent tredge",event)) // get new brush attributes X { X zdialog_fetch(zd,"radius",radius); // radius X@@ -19694,7 +19710,7 @@ X for (dx = -radius; dx <= radius; dx++) X { X rad = sqrt(dx*dx + dy*dy); X- kern = (radius - rad) / radius; // 1 ... 0 X+ kern = (radius - rad) / radius; // 1 ... 0 X kern = kern * (trcent - tredge) + tredge; // trcent ... tredge X if (rad > radius) kern = 1; X if (kern < 0) kern = 0; X@@ -19702,7 +19718,7 @@ X pixed_kernel[dx+radius][dy+radius] = kern; X } X } X- X+ X if (strEqu(event,"undlast")) // undo last edit (click or drag) X pixed_undo1(); X X@@ -19734,7 +19750,7 @@ X int px, py; X char color[20]; X uint16 *ppix3; X- X+ X if (LMclick) // left mouse click X { X LMclick = 0; X@@ -19756,14 +19772,14 @@ X pixed_dopixels(px,py); // do 1 block of pixels X } X } X- X- if (RMclick) X+ X+ if (RMclick) X { X RMclick = 0; X paint_toparc(2); X pixed_undo1(); // undo last paint v.10.11 X } X- X+ X if (Mxdrag || Mydrag) // drag in progress X { X px = Mxdrag; X@@ -19778,14 +19794,14 @@ X paint_toparc(2); X pixed_dopixels(px,py); // do 1 block of pixels X } X- X+ X toparcx = Mxposn - pixed_radius; // define brush outline circle X toparcy = Myposn - pixed_radius; X toparcw = toparch = 2 * pixed_radius; X if (pixed_mode == 1) Ftoparc = 0; X else Ftoparc = 1; X if (Ftoparc) paint_toparc(3); X- X+ X return; X } X X@@ -19802,7 +19818,7 @@ X double kern; X X edit_zapredo(); // delete redo copy v.10.3 X- X+ X pixed_saveundo(px,py); // save pixels for poss. undo v.10.12.1 X X red = 256 * pixed_RGB[0]; X@@ -19816,16 +19832,16 @@ X { X qx = px + dx; X qy = py + dy; X- X+ X if (qx < 0 || qx > E3ww-1) continue; X if (qy < 0 || qy > E3hh-1) continue; X- X+ X if (Factivearea) { // select area active v.10.11 X ii = qy * E3ww + qx; X dist = sa_pixisin[ii]; X if (! dist) continue; // pixel is outside area X } X- X+ X kern = pixed_kernel[dx+radius][dy+radius]; X ppix1 = PXMpix(E1pxm16,qx,qy); // original image pixel X ppix3 = PXMpix(E3pxm16,qx,qy); // edited image pixel X@@ -19871,8 +19887,8 @@ X pixed_undototpix = 0; X pixed_undototmem = 0; X } X- X- if (pixed_undototmem > pixed_undomaxmem) X+ X+ if (pixed_undototmem > pixed_undomaxmem) X { X zmessageACK(mWin,ZTX("Undo memory limit has been reached. \n" X "Save work with [done], then resume editing.")); X@@ -19890,12 +19906,12 @@ X if (py + dy < 0 || py + dy > E3hh-1) continue; X npix++; X } X- X+ X ppixsave1 = (pixed_savepix *) zmalloc(npix*6+12,"pixed.pixsave"); // allocate memory for block X pixed_undopixmem[pixed_undototpix] = ppixsave1; X pixed_undototpix += 1; X pixed_undototmem += npix * 6 + 12; X- X+ X ppixsave1->seq = pixed_undoseq; // save pixel block poop X ppixsave1->npix = npix; X ppixsave1->px = px; X@@ -19936,9 +19952,9 @@ X uint16 *ppix3; X pixed_savepix *ppixsave1; X char undomemmessage[100]; X- X+ X pindex = pixed_undototpix; X- X+ X while (pindex > 0) X { X --pindex; X@@ -19972,7 +19988,7 @@ X pixed_undototmem -= (npix * 6 + 12); X --pixed_undototpix; X } X- X+ X if (pixed_undoseq > 0) --pixed_undoseq; X X mempercent = int(100.0 * pixed_undototmem / pixed_undomaxmem); // update undo memory status X@@ -19992,17 +20008,17 @@ X char undomemmessage[100]; X X pindex = pixed_undototpix; X- X+ X while (pindex > 0) X { X --pindex; X ppixsave1 = pixed_undopixmem[pindex]; X zfree(ppixsave1); X } X- X+ X if (pixed_undopixmem) zfree(pixed_undopixmem); X pixed_undopixmem = 0; X- X+ X pixed_undoseq = 0; X pixed_undototpix = 0; X pixed_undototmem = 0; X@@ -20084,7 +20100,7 @@ X pxm = f_load(cimFile[imx],16); // will diagnose errors X if (! pxm) return 0; X cimPXMf[imx] = pxm; X- X+ X cim_fixblue(pxm); X } X X@@ -20104,7 +20120,7 @@ X hh = pxm->hh; X X for (py = 0; py < hh; py++) X- for (px = 0; px < ww; px++) X+ for (px = 0; px < ww; px++) X { X pixel = PXMpix(pxm,px,py); X if (! pixel[2]) pixel[2] = 1; X@@ -20119,13 +20135,13 @@ X void cim_scale_image(int im, PXM** pxmout) // v.10.7 X { X int ww, hh; X- X+ X ww = cimScale * cimPXMf[im]->ww; X hh = cimScale * cimPXMf[im]->hh; X X- PXM_free(pxmout[im]); X+ PXM_free(pxmout[im]); X pxmout[im] = PXM_rescale(cimPXMf[im],ww,hh); X- X+ X cim_fixblue(pxmout[im]); X X return; X@@ -20149,7 +20165,7 @@ X x2 = cimOffs[im2].xf; X y2 = cimOffs[im2].yf; X t2 = cimOffs[im2].tf; X- X+ X xoff = (x2 - x1) * cos(t1) + (y2 - y1) * sin(t1); // offset of im2 relative to im1 X yoff = (y2 - y1) * cos(t1) - (x2 - x1) * sin(t1); X toff = t2 - t1; X@@ -20164,7 +20180,7 @@ X hh1 = pxm1->hh; X ww2 = pxm2->ww; X hh2 = pxm2->hh; X- X+ X cimOv1xlo = 0; // lowest x overlap X if (xoff > 0) cimOv1xlo = xoff; X X@@ -20176,23 +20192,23 @@ X X cimOv1yhi = hh1-1; // highest y overlap X if (cimOv1yhi > yoff + hh2-1) cimOv1yhi = yoff + hh2-1; X- X+ X if (toff < 0) cimOv1xlo -= toff * (cimOv1yhi - cimOv1ylo); // reduce for theta offset X if (toff < 0) cimOv1yhi += toff * (cimOv1xhi - cimOv1xlo); X if (toff > 0) cimOv1xhi -= toff * (cimOv1yhi - cimOv1ylo); X if (toff > 0) cimOv1ylo += toff * (cimOv1xhi - cimOv1xlo); X- X+ X cimOv1xlo += cimShrink + 2; // account for void areas from X- cimOv1xhi += - cimShrink - 2; // image shrinkage from X+ cimOv1xhi += - cimShrink - 2; // image shrinkage from X cimOv1ylo += cimShrink + 2; // cim_curve_image() X cimOv1yhi += - cimShrink - 2; X- X+ X if (cimBlend > 0 && cimBlend < (cimOv1xhi - cimOv1xlo)) { // reduce x range to cimBlend v.10.8 X pxM = (cimOv1xhi + cimOv1xlo) / 2; X cimOv1xlo = pxM - cimBlend / 2; X cimOv1xhi = pxM + cimBlend / 2; X } X- X+ X cimOv2xlo = costf * (cimOv1xlo - xoff) + sintf * (cimOv1ylo - yoff); // overlap area in im2 coordinates X cimOv2xhi = costf * (cimOv1xhi - xoff) + sintf * (cimOv1yhi - yoff); X cimOv2ylo = costf * (cimOv1ylo - yoff) + sintf * (cimOv1xlo - xoff); X@@ -20232,17 +20248,17 @@ X double a1, a2, b1, b2, bratio = 1; X double r256 = 1.0 / 256.0; X PXM *pxm1, *pxm2; X- X+ X pxm1 = pxmx[im1]; X pxm2 = pxmx[im2]; X- X+ X x1 = cimOffs[im1].xf; // im1, im2 absolute offsets X y1 = cimOffs[im1].yf; X t1 = cimOffs[im1].tf; X x2 = cimOffs[im2].xf; X y2 = cimOffs[im2].yf; X t2 = cimOffs[im2].tf; X- X+ X xoff = (x2 - x1) * cos(t1) + (y2 - y1) * sin(t1); // offset of im2 relative to im1 X yoff = (y2 - y1) * cos(t1) - (x2 - x1) * sin(t1); X toff = t2 - t1; X@@ -20268,16 +20284,16 @@ X if (! vstat2) continue; // does not exist X X ++npix; // count overlapping pixels X- X+ X for (rgb = 0; rgb < 3; rgb++) // accumulate distributions X { // by color in 256 bins X ++brdist1[rgb][int(r256*pix1[rgb])]; X ++brdist2[rgb][int(r256*vpix2[rgb])]; X } X } X- X+ X npix1 = npix / 256; // 1/256th of total pixels X- X+ X for (rgb = 0; rgb < 3; rgb++) // get brlev1[rgb][N] = mean bright X for (ii = jj = 0; jj < 256; jj++) // for Nth group of image1 pixels X { // for color rgb X@@ -20359,7 +20375,7 @@ X if (bratio > 5) bratio = 5; X Bratios1[rgb][ii] = bratio; X } X- X+ X for (ii = 0; ii < 65536; ii++) // convert brightness ratios into X { // conversion factors X jj = ii / 256; X@@ -20370,12 +20386,12 @@ X cimRGBmf2[rgb][ii] = sqrt(Bratios2[rgb][jj]) * ii; // can be applied to both images X } X } X- X+ X return; X } X X X-// Use color match data from cim_match_colors() to X+// Use color match data from cim_match_colors() to X // modify images so the colors match. X X void cim_adjust_colors(PXM *pxm, int fwhich) // v.10.7 X@@ -20384,7 +20400,7 @@ X int red, green, blue, max; X uint16 *pix; X double f1; X- X+ X ww = pxm->ww; X hh = pxm->hh; X X@@ -20418,7 +20434,7 @@ X green = green * f1; X blue = blue * f1; X } X- X+ X if (! blue) blue = 1; // avoid 0 v.10.7 X X pix[0] = red; X@@ -20446,7 +20462,7 @@ X uchar *Hcon, *Vcon; X uint16 *pix1, *pix2; X PXM *pxm; X- X+ X pxm = cimPXMw[im1]; X ww = pxm->ww; X hh = pxm->hh; X@@ -20456,12 +20472,12 @@ X memset(cimRedpix,0,ww*hh); X X cimRedImage = im1; // image with red pixels X- X+ X ov1xlo = cimOv1xlo + cimSearchRange; // stay within x/y search range X ov1xhi = cimOv1xhi - cimSearchRange; // so that red pixels persist X ov1ylo = cimOv1ylo + cimSearchRange; // over offset changes X ov1yhi = cimOv1yhi - cimSearchRange; X- X+ X for (yzone = 0; yzone < 4; yzone++) // loop 16 zones v.10.8 X for (xzone = 0; xzone < 4; xzone++) X { X@@ -20469,15 +20485,15 @@ X pxH = ov1xlo + 0.25 * (xzone+1) * (ov1xhi - ov1xlo); X pyL = ov1ylo + 0.25 * yzone * (ov1yhi - ov1ylo); X pyH = ov1ylo + 0.25 * (yzone+1) * (ov1yhi - ov1ylo); X- X+ X npix = (pxH - pxL) * (pyH - pyL); // zone pixels X Hcon = (uchar *) zmalloc(npix,"redpix.hcon"); // horizontal pixel contrast 0-255 X Vcon = (uchar *) zmalloc(npix,"redpix.vcon"); // vertical pixel contrast 0-255 X- X+ X ii = 4 * yzone + xzone; X samp = cimSampSize * 0.01 * zsamp[ii]; // sample size for zone X if (samp > 0.1 * npix) samp = 0.1 * npix; // limit to 10% of zone pixels X- X+ X for (py = pyL; py < pyH; py++) // scan image pixels in zone X for (px = pxL; px < pxH; px++) X { X@@ -20527,13 +20543,13 @@ X ++Hdist[Hcon[ii]]; X ++Vdist[Vcon[ii]]; X } X- X+ X for (npix = 0, ii = 255; ii > 0; ii--) // find minimum contrast needed to get X { // enough pixels for sample size X npix += Hdist[ii]; // (horizontal contrast pixels) X- if (npix > samp) break; X+ if (npix > samp) break; X } X- Hmin = ii; X+ Hmin = ii; X X for (npix = 0, ii = 255; ii > 0; ii--) // (verticle contrast pixels) X { X@@ -20581,7 +20597,7 @@ X } X } X } X- X+ X return; X } X X@@ -20599,25 +20615,25 @@ X double R1, R2, G, T, bow; X PXM *pxmin, *pxmout; X uint16 vpix[3], *pix; X- X+ X pxmin = cimPXMs[im]; // input and output image X ww = pxmin->ww; // 200 X hh = pxmin->hh; X ww2 = 0.5 * ww; // 100 X hh2 = 0.5 * hh; X- X+ X if (hh > ww) S = S * ww / hh; // vertical format X F = F / S; // 28 / 35 // scale to image dimensions X S = ww2; // 100 X F = F * ww; // 160 X R1 = F; // cylinder tangent to image plane X- X+ X bow = -lens_bow * 0.01 / hh2 / hh2; // lens bow % to fraction X- if (hh > ww) X+ if (hh > ww) X bow = -lens_bow * 0.01 / ww2 / ww2; X X pxmout = PXM_make(ww,hh,16); // temp. output PXM X- X+ X for (py = 0; py < hh; py++) // cylindrical projection v.11.03 X for (px = 0; px < ww; px++) X { X@@ -20633,7 +20649,7 @@ X dy += hh2; X vstat = vpixel(pxmin,dx,dy,vpix); // input virtual pixel X pix = PXMpix(pxmout,px,py); // output real pixel X- if (vstat) { X+ if (vstat) { X pix[0] = vpix[0]; X pix[1] = vpix[1]; X pix[2] = vpix[2]; X@@ -20646,7 +20662,7 @@ X if (pix[2]) break; X } X cimShrink = px-1; // = 0 if no curvature X- X+ X PXM_free(pxmin); // replace input with output PXM X cimPXMs[im] = pxmout; X X@@ -20670,10 +20686,10 @@ X using namespace cim_warp_image_names; X X void * cim_warp_image_wthread(void *arg); X- X+ X pxmin = cimPXMs[im]; // input and output pixmaps X pxmout = cimPXMw[im]; X- X+ X ww = pxmin->ww; X hh = pxmin->hh; X wwi = 1.0 / ww; X@@ -20692,13 +20708,13 @@ X pxmout = PXM_copy(pxmin); X cimPXMw[im] = pxmout; X } X- X+ X if (pxmout->ww != ww || pxmout->hh != hh) { // or if not my size X PXM_free(pxmout); X pxmout = PXM_copy(pxmin); X cimPXMw[im] = pxmout; X } X- X+ X for (int ii = 0; ii < Nwt; ii++) // start worker threads X start_wt(cim_warp_image_wthread,&wtnx[ii]); X wait_wts(); // wait for completion X@@ -20715,7 +20731,7 @@ X int pxm, pym, vstat; X uint16 vpix[3], *pixm; X double px, py, dx, dy, coeff; X- X+ X for (pym = index; pym < hh; pym += Nwt) // loop all pixels for this thread X for (pxm = 0; pxm < ww; pxm++) X { X@@ -20748,21 +20764,21 @@ X vstat = vpixel(pxmin,px,py,vpix); // input virtual pixel X pixm = PXMpix(pxmout,pxm,pym); // output real pixel X X- if (vstat) { X+ if (vstat) { X pixm[0] = vpix[0]; X pixm[1] = vpix[1]; X pixm[2] = vpix[2]; X } X else pixm[0] = pixm[1] = pixm[2] = 0; X } X- X+ X exit_wt(); X return 0; // not executed, avoid gcc warning X } X X X // warp image for pano, left side corners only, reduced warp range X-// input: cimPXMs[im] (curved) X+// input: cimPXMs[im] (curved) X // output: cimPXMw[im] (warped) X // fblend: 0 = process entire image X // 1 = process left half only X@@ -20776,10 +20792,10 @@ X double ww2i, hh2i, pxs, pys, xdisp, ydisp; X double wx0, wy0, wx3, wy3; X PXM *pxmin, *pxmout; X- X+ X pxmin = cimPXMs[im]; // input and output pixmaps X pxmout = cimPXMw[im]; X- X+ X ww = pxmin->ww; X hh = pxmin->hh; X X@@ -20787,13 +20803,13 @@ X pxmout = PXM_copy(pxmin); X cimPXMw[im] = pxmout; X } X- X+ X if (pxmout->ww != ww || pxmout->hh != hh) { // or if not my size X PXM_free(pxmout); X pxmout = PXM_copy(pxmin); X cimPXMw[im] = pxmout; X } X- X+ X ww2 = ww / 2; X hh2 = hh / 2; X X@@ -20808,7 +20824,7 @@ X X pxL = 0; // entire image v.10.8 X pxH = ww; X- X+ X if (fblend == 1) // left half X pxH = ww2; X X@@ -20816,15 +20832,15 @@ X pxL = cimOv2xlo; // limit to overlap/blend width X pxH = cimOv2xhi; X } X- X+ X for (pym = 0; pym < hh; pym++) // loop all output pixels X for (pxm = pxL; pxm < pxH; pxm++) X { X pixm = PXMpix(pxmout,pxm,pym); // output pixel X- X+ X xdisp = (pxm - ww2) * ww2i; // -1 ... 0 ... +1 X ydisp = (pym - hh2) * ww2i; // -hh/ww ... 0 ... +hh/ww X- X+ X if (xdisp > 0) { // right half, no warp X pxs = pxm; X pys = pym; X@@ -20840,7 +20856,7 @@ X X vstat = vpixel(pxmin,pxs,pys,vpix); // input virtual pixel X X- if (vstat) { X+ if (vstat) { X pixm[0] = vpix[0]; X pixm[1] = vpix[1]; X pixm[2] = vpix[2]; X@@ -20872,7 +20888,7 @@ X double wxL, wxH, wyL, wyH; X double match, matchB; X cimoffs offsets0, offsetsB; X- X+ X offsets0 = cimOffs[im2]; // initial offsets X offsetsB = offsets0; // = best offsets so far X matchB = cim_match_images(im1,im2); // = best image match level X@@ -20882,18 +20898,18 @@ X for (pass = 1; pass <=2; pass++) // main pass and 2nd pass v.10.8 X { X xyrange = cimSearchRange; // x/y search range and step X- xystep = cimSearchStep; X+ xystep = cimSearchStep; X X trange = xyrange / (cimOv1yhi - cimOv1ylo); // angle range, radians X tstep = trange * xystep / xyrange; X- X+ X if (pass == 2) { X xyrange = xyrange / 4; // 2nd pass, 1/4 range and 1/2 step X xystep = xystep / 2; // v.10.8 X trange = trange / 4; X tstep = tstep / 2; X } X- X+ X // search x/y/t range for best match X X xfL = cimOffs[im2].xf - xyrange; X@@ -20917,10 +20933,10 @@ X sprintf(SB_text,"align: %d match: %.5f",cimNsearch++,matchB); // update status bar X zmainloop(); X } X- X+ X cimOffs[im2] = offsetsB; // restore best match X cim_show_images(0,0); X- X+ X // warp corners and search for best match X X wrange = cimWarpRange; // corner warp range and step X@@ -20931,12 +20947,12 @@ X wrange = wrange / 4; X wstep = wstep / 2; X } X- X+ X cstep = 1; X if (cimPano) cstep = 3; // NW and SW corners only X- X+ X matchB = cim_match_images(im1,im2); // initial image match level X- X+ X for (ii = 0; ii < 4; ii += cstep) // modify one corner at a time X { X wxL = cimOffs[im2].wx[ii] - wrange; X@@ -20960,7 +20976,7 @@ X X cimOffs[im2] = offsetsB; // restore best match X } X- X+ X if (cimPano) cim_warp_image_pano(im2,1); X else cim_warp_image(im2); // apply corner warps X cim_show_images(0,0); X@@ -20990,7 +21006,7 @@ X reddiff = ff * fabs(red1-red2); // 0 = perfect match X greendiff = ff * fabs(green1-green2); // 1 = total mismatch X bluediff = ff * fabs(blue1-blue2); X- X+ X match = (1.0 - reddiff) * (1.0 - greendiff) * (1.0 - bluediff); // 1 = perfect match X return match; X } X@@ -21013,14 +21029,14 @@ X double xoff, yoff, toff, costf, sintf, coeff; X double match, cmatch, maxcmatch; X PXM *pxm1, *pxm2; X- X+ X x1 = cimOffs[im1].xf; // im1, im2 absolute offsets X y1 = cimOffs[im1].yf; X t1 = cimOffs[im1].tf; X x2 = cimOffs[im2].xf; X y2 = cimOffs[im2].yf; X t2 = cimOffs[im2].tf; X- X+ X xoff = (x2 - x1) * cos(t1) + (y2 - y1) * sin(t1); // offset of im2 relative to im1 X yoff = (y2 - y1) * cos(t1) - (x2 - x1) * sin(t1); X toff = t2 - t1; X@@ -21040,11 +21056,11 @@ X pxm1 = cimPXMs[im1]; // base image X pxm2 = cimPXMs[im2]; // comparison image (virtual warps) X X- ww = pxm1->ww; X+ ww = pxm1->ww; X hh = pxm1->hh; X ww2 = ww / 2; X hh2 = hh / 2; X- X+ X wwi = 1.0 / ww; X hhi = 1.0 / hh; X ww2i = 1.0 / ww2; X@@ -21052,7 +21068,7 @@ X X cmatch = 0; X maxcmatch = 1; X- X+ X if (cimPano) X { X for (py1 = cimOv1ylo; py1 < cimOv1yhi; py1++) // loop overlapping pixels X@@ -21066,12 +21082,12 @@ X X px2 = costf * (px1 - xoff) + sintf * (py1 - yoff); // corresponding image2 pixel X py2 = costf * (py1 - yoff) - sintf * (px1 - xoff); X- X+ X dx = dy = 0.0; // corner warp X X xdisp = (px2 - ww2) * ww2i; // -1 ... 0 ... +1 X ydisp = (py2 - hh2) * ww2i; // -hh/ww ... 0 ... +hh/ww X- X+ X if (xdisp > 0) // right half, no warp X dx = dy = 0; X X@@ -21087,7 +21103,7 @@ X X px2 += dx; // source pixel location X py2 += dy; // after corner warps X- X+ X vstat = vpixel(pxm2,px2,py2,vpix2); X if (! vstat) continue; X X@@ -21096,7 +21112,7 @@ X maxcmatch += 1.0; X } X } X- X+ X else X { X for (py1 = cimOv1ylo; py1 < cimOv1yhi; py1++) // loop overlapping pixels X@@ -21110,7 +21126,7 @@ X X px2 = costf * (px1 - xoff) + sintf * (py1 - yoff); // corresponding image2 pixel X py2 = costf * (py1 - yoff) - sintf * (px1 - xoff); X- X+ X dx = dy = 0.0; // corner warp X X coeff = (1.0 - py2 * hhi - px2 * wwi); // corner 0 NW X@@ -21136,7 +21152,7 @@ X X px2 += dx; // source pixel location X py2 += dy; // after corner warps X- X+ X vstat = vpixel(pxm2,px2,py2,vpix2); X if (! vstat) continue; X X@@ -21145,7 +21161,7 @@ X maxcmatch += 1.0; X } X } X- X+ X return cmatch / maxcmatch; X } X X@@ -21171,15 +21187,15 @@ X int ww, hh, wwmax, hhmin, hhmax, bmid; X double xf, yf, tf; X uint16 *pix3; X- X+ X mutex_lock(&Fpixmap_lock); // stop window updates X- X+ X fblendd = fblend; // blend 50/50 or gradual ramp X X im1 = cimShowIm1; // two images to show X im2 = cimShowIm2; X iminc = im2 - im1; // v.10.9 X- X+ X if (cimShowAll) { // show all images v.10.9 X im1 = 0; X im2 = cimNF-1; X@@ -21192,7 +21208,7 @@ X } X X if (fnew) PXM_free(E3pxm16); // force new output pixmap X- X+ X if (! E3pxm16) // allocate output pixmap X { X xf = cimOffs[im1].xf; // shift all images to left margin X@@ -21200,7 +21216,7 @@ X cimOffs[imx].xf -= xf; X X wwmax = cimPXMw[im2]->ww + cimOffs[im2].xf; // ww extent of last image X- X+ X hhmin = cimOffs[im1].yf; X hhmax = 0; X X@@ -21219,7 +21235,7 @@ X for (imx = im1; imx <= im2; imx += iminc) // align to top edge X cimOffs[imx].yf -= hhmin; X hhmax = hhmax - hhmin; X- X+ X if (cimPano) { X for (imx = im1; imx <= im2; imx += iminc) // deliberate margins v.11.03 X cimOffs[imx].yf += 10; X@@ -21257,7 +21273,7 @@ X start_wt(cim_show_images_wthread,&wtnx[ii]); X wait_wts(); // wait for completion X X- if (cimRedpix) X+ if (cimRedpix) X { X imx = cimRedImage; // paint red pixels for current image X ww = cimPXMw[imx]->ww; // being aligned X@@ -21297,7 +21313,7 @@ X int red3, green3, blue3; X double f1, f2, px, py; X uint16 vpix[3], *pix3; X- X+ X red1 = green1 = blue1 = 0; X X f1 = f2 = 0.5; // to use if no fblend flag X@@ -21306,7 +21322,7 @@ X for (px3 = 0; px3 < E3ww; px3++) // loop E3 columns X { X vstat1 = vstat2 = 0; X- X+ X for (imx = imy = im1; imx <= im2; imx += iminc) // find which images overlap this pixel X { X if (px3 < wwlo[imx] || px3 > wwhi[imx]) continue; X@@ -21330,14 +21346,14 @@ X break; X } X } X- X+ X imx = imy; // first of 1 or 2 overlapping images X X if (vstat1) { X if (! vstat2) { X red3 = red1; // use image1 pixel X green3 = green1; X- blue3 = blue1; X+ blue3 = blue1; X } X else { // use blended image1 + image2 pixels X if (fblendd) { X@@ -21382,7 +21398,7 @@ X wwmin = hhmin = 0; X wwmax = E3ww; X hhmax = E3hh; X- X+ X for (imx = 0; imx < cimNF; imx++) // loop all images X { X ww = cimPXMw[imx]->ww; // image size X@@ -21392,12 +21408,12 @@ X tf = cimOffs[imx].tf; X sintf = sin(tf); X costf = cos(tf); X- X+ X for (ii = 0; ii < 8; ii++) // 8 points around image rectangle X { X px = ww * edgex[ii] / 2; // coordinates before warping X py = hh * edgey[ii] / 2; X- X+ X if (edgex[ii] != 1 && edgey[ii] != 1) { // if a corner X jj = ii / 2; X wx = cimOffs[imx].wx[jj]; // corner warp X@@ -21410,7 +21426,7 @@ X X px3 = xf + px * costf - py * sintf; // map px/py to output image px3/py3 X py3 = yf + py * costf + px * sintf; X- X+ X if (edgex[ii] != 1) { X if (px3 < ww/2 && px3 > wwmin) wwmin = px3; // remember px3/py3 extremes X if (px3 > ww/2 && px3 < wwmax) wwmax = px3; X@@ -21422,7 +21438,7 @@ X } X } X } X- X+ X wwmin += 2; // compensate rounding X wwmax -= 2; X hhmin += 2; X@@ -21433,7 +21449,7 @@ X X if (ww < 0.7 * E3ww) return; // sanity check X if (hh < 0.7 * E3hh) return; X- X+ X E9pxm16 = PXM_make(ww,hh,16); X X for (py3 = hhmin; py3 < hhmax; py3++) // E9 = trimmed E3 X@@ -21468,7 +21484,7 @@ X { X printf(" imx %d x/y/t: %.1f %.1f %.4f w0: %.1f %.1f w1: %.1f %.1f w2: %.1f %.1f w3: %.1f %.1f \n", X imx, cimOffs[imx].xf, cimOffs[imx].yf, cimOffs[imx].tf, X- cimOffs[imx].wx[0], cimOffs[imx].wy[0], cimOffs[imx].wx[1], cimOffs[imx].wy[1], X+ cimOffs[imx].wx[0], cimOffs[imx].wy[0], cimOffs[imx].wx[1], cimOffs[imx].wy[1], X cimOffs[imx].wx[2], cimOffs[imx].wy[2], cimOffs[imx].wx[3], cimOffs[imx].wy[3]); X } X X@@ -21490,11 +21506,11 @@ X double HDRsampSize = 6000; // pixel sample size 11.03 X X double HDRinitSearchRange = 8.0; // initial search range, +/- pixels X-double HDRinitSearchStep = 1.0; // initial search step, pixels X+double HDRinitSearchStep = 1.0; // initial search step, pixels X double HDRinitWarpRange = 3.0; // initial corner warp range, +/- pixels X-double HDRinitWarpStep = 0.67; // initial corner warp step, pixels X+double HDRinitWarpStep = 0.67; // initial corner warp step, pixels X double HDRsearchRange = 2.0; // normal search range, +/- pixels X-double HDRsearchStep = 0.67; // normal search step, pixels X+double HDRsearchStep = 0.67; // normal search step, pixels X double HDRwarpRange = 2.0; // normal corner warp range, +/- pixels X double HDRwarpStep = 0.67; // normal corner warp step, pixels X X@@ -21519,7 +21535,7 @@ X double pixsum, fnorm = 3.0 / 65536.0; X uint16 *pixel; X PXM *pxmtemp; X- X+ X zfuncs::F1_help_topic = "HDR"; // help topic X X if (mod_keep()) return; // warn unsaved changes X@@ -21530,7 +21546,7 @@ X cimPXMf[imx] = cimPXMs[imx] = cimPXMw[imx] = 0; X } X X- cimNF = 0; X+ cimNF = 0; X HDRbright = 0; X X flist = zgetfileN(ZTX("Select 2 to 9 files"),"openN",curr_file); // select images to combine X@@ -21545,12 +21561,12 @@ X cimNF = imx; // file count X for (imx = 0; imx < cimNF; imx++) X cimFile[imx] = strdupz(flist[imx],0,"HDR.file"); // set up file list X- X+ X if (! cim_load_files()) goto cleanup; // load and check all files X X ww = cimPXMf[0]->ww; X hh = cimPXMf[0]->hh; X- X+ X for (imx = 1; imx < cimNF; imx++) // check image compatibility X { X diffw = abs(ww - cimPXMf[imx]->ww); X@@ -21563,7 +21579,7 @@ X goto cleanup; X } X } X- X+ X free_resources(); // ready to commit X X err = f_open(cimFile[0],0); // curr_file = 1st file in list X@@ -21598,14 +21614,14 @@ X cimPXMf[imx] = pxmtemp; X } X } X- X+ X start_thread(HDR_align_thread,0); // align each pair of images X wrapup_thread(0); // wait for completion X if (HDRstat != 1) goto cancel; X X HDR_brightness(); // compute pixel brightness levels X if (HDRstat != 1) goto cancel; X- X+ X HDR_tweak(); // combine images based on user inputs X if (HDRstat != 1) goto cancel; X X@@ -21630,7 +21646,7 @@ X if (cimPXMs[imx]) PXM_free(cimPXMs[imx]); X if (cimPXMw[imx]) PXM_free(cimPXMw[imx]); X } X- X+ X if (HDRbright) zfree(HDRbright); X *SB_text = 0; X X@@ -21649,7 +21665,7 @@ X double R, maxtf, mintf, midtf; X double xoff, yoff, toff, dxoff, dyoff; X cimoffs offsets[10]; // x/y/t offsets after alignment X- X+ X Fzoom = 0; // fit to window if big X Fblowup = 1; // scale up to window if small X Ffuncbusy++; // v.11.01 X@@ -21694,7 +21710,7 @@ X cim_adjust_colors(cimPXMs[im2],2); X X cim_warp_image(im1); // make warped images to show X- cim_warp_image(im2); X+ cim_warp_image(im2); X X cimShowIm1 = im1; // show two images with 50/50 blend X cimShowIm2 = im2; X@@ -21739,13 +21755,13 @@ X offsets[im2].xf = cimOffs[im2].xf - cimOffs[im1].xf; // save im2 offsets from im1 X offsets[im2].yf = cimOffs[im2].yf - cimOffs[im1].yf; X offsets[im2].tf = cimOffs[im2].tf - cimOffs[im1].tf; X- X+ X for (ii = 0; ii < 4; ii++) { X offsets[im2].wx[ii] = cimOffs[im2].wx[ii] - cimOffs[im1].wx[ii]; X offsets[im2].wy[ii] = cimOffs[im2].wy[ii] - cimOffs[im1].wy[ii]; X } X } X- X+ X for (imx = 0; imx < cimNF; imx++) // offsets[*] >> cimOffs[*] X cimOffs[imx] = offsets[imx]; X X@@ -21775,7 +21791,7 @@ X if (toff < mintf) mintf = toff; X } X midtf = 0.5 * (maxtf + mintf); X- X+ X for (imx = 0; imx < cimNF; imx++) X cimOffs[imx].tf -= midtf; X X@@ -21825,15 +21841,15 @@ X sintf[imx] = sin(cimOffs[imx].tf); X costf[imx] = cos(cimOffs[imx].tf); X } X- X+ X ww = E3pxm16->ww; X hh = E3pxm16->hh; X X HDRbright = (float *) zmalloc(ww*hh*sizeof(int),"hdr.brightmem"); // get memory for brightness array X- X+ X minbright = 1.0; X maxbright = 0.0; X- X+ X for (py3 = 0; py3 < hh; py3++) // step through all output pixels X for (px3 = 0; px3 < ww; px3++) X { X@@ -21849,12 +21865,12 @@ X py = costf[imx] * (py3 - yoff) - sintf[imx] * (px3 - xoff); X vstat = vpixel(cimPXMw[imx],px,py,vpix); X if (! vstat) break; X- X+ X red += fnorm * vpix[0]; // sum input pixels X green += fnorm * vpix[1]; X blue += fnorm * vpix[2]; X } X- X+ X if (! vstat) { // pixel outside some image X pix3 = PXMpix(E3pxm16,px3,py3); // output pixel = black X pix3[0] = pix3[1] = pix3[2] = 0; X@@ -21862,11 +21878,11 @@ X HDRbright[kk] = 0; X continue; X } X- X+ X bright = (red + green + blue) / (3 * cimNF); // mean pixel brightness, 0.0 to 1.0 X kk = py3 * ww + px3; X HDRbright[kk] = bright; X- X+ X if (bright > maxbright) maxbright = bright; X if (bright < minbright) minbright = bright; X X@@ -21875,8 +21891,8 @@ X pix3[1] = green * 65535.0 / cimNF; X pix3[2] = blue * 65535.0 / cimNF; X } X- X- norm = 0.999 / (maxbright - minbright); // normalize to range 0.0 to 0.999 X+ X+ norm = 0.999 / (maxbright - minbright); // normalize to range 0.0 to 0.999 X X for (int ii = 0; ii < ww * hh; ii++) X HDRbright[ii] = (HDRbright[ii] - minbright) * norm; X@@ -21896,7 +21912,7 @@ X X int imx; X double cww = 1.0 / (cimNF-1); X- X+ X HDRzd = zdialog_new(ZTX("Adjust Image Contributions"),mWin,Bdone,Bcancel,null); X zdialog_add_widget(HDRzd,"frame","brframe","dialog",0,"expand|space=2"); X zdialog_add_widget(HDRzd,"hbox","hb1","dialog",0); X@@ -21917,7 +21933,7 @@ X Espcdat = sd; X X sd->Nspc = cimNF; // no. curves = no. files X- X+ X for (imx = 0; imx < cimNF; imx++) // set up initial response curve X { // anchor points X sd->vert[imx] = 0; X@@ -21928,7 +21944,7 @@ X sd->apy[imx][1] = 0.1 + imx * 0.8 * cww; X spccurve_generate(sd,imx); X } X- X+ X start_thread(HDR_combine_thread,0); // start working thread X signal_thread(); X X@@ -21968,7 +21984,7 @@ X zdialog_free(HDRzd); X if (HDRstat == 1) cim_trim(); // cut-off edges v.10.9 X } X- X+ X return 1; X } X X@@ -21977,8 +21993,8 @@ X X void HDR_curvedit(int spc) X { X- cchar *pp; X- X+ cchar *pp; X+ X pp = strrchr(cimFile[spc],'/'); X zdialog_stuff(HDRzd,"labf2",pp+1); X signal_thread(); X@@ -21999,7 +22015,7 @@ X while (true) X { X thread_idle_loop(); // wait for work or exit request X- X+ X for (imx = 0; imx < cimNF; imx++) // loop input images X { X ii = sd->nap[imx]; // get low and high anchor points X@@ -22033,7 +22049,7 @@ X for (ii = 0; ii < Nwt; ii++) // start worker threads v.10.7 X start_wt(HDR_combine_wthread,&wtnx[ii]); X wait_wts(); // wait for completion X- X+ X mutex_unlock(&Fpixmap_lock); X mwpaint2(); // update window X } X@@ -22065,14 +22081,14 @@ X ii = py3 * ww + px3; X bright = HDRbright[ii]; // mean brightness, 0.0 to 1.0 X ii = 1000 * bright; X- X+ X red = green = blue = 0; X- X+ X for (imx = 0; imx < cimNF; imx++) // loop input images X { X factor = HDR_respfac[imx][ii]; // image contribution to this pixel X if (! factor) continue; // none X- X+ X xoff = cimOffs[imx].xf; X yoff = cimOffs[imx].yf; X X@@ -22086,14 +22102,14 @@ X green += factor * vpix[1]; X blue += factor * vpix[2]; X } X- X+ X pix3 = PXMpix(E3pxm16,px3,py3); // output pixel X X pix3[0] = red; // = sum of input pixel contributions X pix3[1] = green; X pix3[2] = blue; X } X- X+ X exit_wt(); X return 0; // not executed X } X@@ -22103,15 +22119,15 @@ X X Make an HDF (high depth of field) image from several images of the same X subject with different focus settings. Combine the images and allow the X- user to "paint" the output composite image using the mouse and choosing X- the sharpest input image for each area of the output image. The result X+ user to "paint" the output composite image using the mouse and choosing X+ the sharpest input image for each area of the output image. The result X is an image with a depth of field that exceeds the camera capability. X- X- The images are aligned at the center, but small differences in camera X- position (hand-held photos) will cause parallax errors that prevent X+ X+ The images are aligned at the center, but small differences in camera X+ position (hand-held photos) will cause parallax errors that prevent X perfect alignment of the images. Also, the images with nearer focus X will be slightly larger than those with farther focus. These problems X- can be compensated by dragging and warping the images using the mouse. v.10.7 X+ can be compensated by dragging and warping the images using the mouse. v.10.7 X X **************************************************************************/ X X@@ -22142,7 +22158,7 @@ X char **flist; X int imx, err, ww, hh; X double diffw, diffh; X- X+ X zfuncs::F1_help_topic = "HDF"; // help topic X X if (mod_keep()) return; // warn unsaved changes X@@ -22153,7 +22169,7 @@ X cimPXMf[imx] = cimPXMs[imx] = cimPXMw[imx] = 0; X } X X- cimNF = 0; X+ cimNF = 0; X X flist = zgetfileN(ZTX("Select 2 to 9 files"),"openN",curr_file); // select images to combine X if (! flist) return; X@@ -22167,12 +22183,12 @@ X cimNF = imx; // file count X for (imx = 0; imx < cimNF; imx++) X cimFile[imx] = strdupz(flist[imx],0,"HDF.file"); // set up file list X- X+ X if (! cim_load_files()) goto cleanup; // load and check all files X X ww = cimPXMf[0]->ww; X hh = cimPXMf[0]->hh; X- X+ X for (imx = 1; imx < cimNF; imx++) // check image compatibility X { X diffw = abs(ww - cimPXMf[imx]->ww); X@@ -22221,7 +22237,7 @@ X if (cimPXMs[imx]) PXM_free(cimPXMs[imx]); X if (cimPXMw[imx]) PXM_free(cimPXMw[imx]); X } X- X+ X *SB_text = 0; X return; X } X@@ -22238,21 +22254,21 @@ X double R, maxtf, mintf, midtf; X double xoff, yoff, toff, dxoff, dyoff; X cimoffs offsets[10]; // x/y/t offsets after alignment X- X+ X Fzoom = 0; // fit to window if big X Fblowup = 1; // scale up to window if small X Ffuncbusy++; // v.11.01 X X for (imx = 0; imx < cimNF; imx++) // bugfix v.10.8 X memset(&offsets[imx],0,sizeof(cimoffs)); X- X+ X for (im1 = 0; im1 < cimNF-1; im1++) // loop each pair of images X { X im2 = im1 + 1; X X memset(&cimOffs[im1],0,sizeof(cimoffs)); // initial image offsets = 0 X memset(&cimOffs[im2],0,sizeof(cimoffs)); X- X+ X ww = cimPXMf[im1]->ww; // image dimensions X hh = cimPXMf[im1]->hh; X X@@ -22294,7 +22310,7 @@ X cim_get_redpix(im1); // get high-contrast pixels X X cim_align_image(im1,im2); // align im2 to im1 X- X+ X zfree(cimRedpix); // clear red pixels X cimRedpix = 0; X X@@ -22324,7 +22340,7 @@ X cimWarpRange = HDFwarpRange; // align corner warp range X cimWarpStep = HDFwarpStep; // align corner warp step size X } X- X+ X offsets[im2].xf = cimOffs[im2].xf - cimOffs[im1].xf; // save im2 offsets from im1 X offsets[im2].yf = cimOffs[im2].yf - cimOffs[im1].yf; X offsets[im2].tf = cimOffs[im2].tf - cimOffs[im1].tf; X@@ -22337,7 +22353,7 @@ X X for (imx = 0; imx < cimNF; imx++) // offsets[*] >> cimOffs[*] X cimOffs[imx] = offsets[imx]; X- X+ X cimOffs[0].xf = cimOffs[0].yf = cimOffs[0].tf = 0; // image 0 at (0,0,0) X X for (im1 = 0; im1 < cimNF-1; im1++) // absolute offsets for image 1 to last X@@ -22364,7 +22380,7 @@ X if (toff < mintf) mintf = toff; X } X midtf = 0.5 * (maxtf + mintf); X- X+ X for (imx = 0; imx < cimNF; imx++) X cimOffs[imx].tf -= midtf; X X@@ -22431,7 +22447,7 @@ X labN[0] = '1' + imx; X zdialog_add_widget(HDFzd,"radio",imageN,"hbim",labN); X } X- X+ X zdialog_stuff(HDFzd,"paint",1); // paint button on X zdialog_stuff(HDFzd,"warp",0); // warp button off X zdialog_stuff(HDFzd,"image1",1); // initial image = 1st X@@ -22441,7 +22457,7 @@ X HDFradius = 100; // paint radius X X takeMouse(HDFzd,HDF_mousefunc,0); // connect mouse function v.10.12 X- X+ X cc = E3ww * E3hh; // allocate pixel map X HDFpixmap = zmalloc(cc,"HDF.pixmap"); X memset(HDFpixmap,cimNF,cc); // initial state, blend all images X@@ -22452,7 +22468,7 @@ X HDFwarpx[imx] = (float *) zmalloc(ww * hh * sizeof(float),"hdf.warp"); X HDFwarpy[imx] = (float *) zmalloc(ww * hh * sizeof(float),"hdf.warp"); X } X- X+ X start_thread(HDF_combine_thread,0); // start working thread X signal_thread(); X X@@ -22468,7 +22484,7 @@ X int HDF_tweak_dialog_event(zdialog *zd, cchar *event) // v.10.7 X { X int imx, nn, mymouse; X- X+ X if (zd->zstat) // dialog finish X { X paint_toparc(2); // stop brush outline X@@ -22486,27 +22502,27 @@ X zfree(HDFwarpy[imx]); X } X } X- X+ X if (strEqu(event,"paint")) { // set paint mode X zdialog_fetch(zd,"paint",nn); X if (! nn) return 1; X HDFmode = 0; X gdk_window_set_cursor(drWin->window,0); // no drag cursor v.11.03 X } X- X+ X if (strEqu(event,"warp")) { // set warp mode X zdialog_fetch(zd,"warp",nn); X if (! nn) return 1; X HDFmode = 1; X paint_toparc(2); // stop brush outline X zdialog_fetch(zd,"mymouse",mymouse); X- if (mymouse) X+ if (mymouse) X gdk_window_set_cursor(drWin->window,dragcursor); // set drag cursor v.11.03 X } X- X+ X if (strnEqu(event,"image",5)) { // image radio button X nn = event[5] - '0'; // 1 to cimNF X- if (nn > 0 && nn <= cimNF) X+ if (nn > 0 && nn <= cimNF) X HDFimage = nn - 1; // 0 to cimNF-1 X signal_thread(); X } X@@ -22518,7 +22534,7 @@ X zdialog_fetch(zd,"mymouse",mymouse); X if (mymouse) { X takeMouse(zd,HDF_mousefunc,0); // connect mouse function X- if (HDFmode == 1) X+ if (HDFmode == 1) X gdk_window_set_cursor(drWin->window,dragcursor); // warp mode, drag cursor v.11.03 X signal_thread(); X } X@@ -22547,7 +22563,7 @@ X int ii, px, py, ww, hh; X double mag, dispx, dispy, d1, d2; X PXM *pxm1, *pxm2; X- X+ X if (HDFmode == 0) goto paint; X if (HDFmode == 1) goto warp; X return; X@@ -22572,7 +22588,7 @@ X mx = Mxdrag; X my = Mydrag; X } X- X+ X else return; X X if (mx < 0 || mx > E3ww-1 || my < 0 || my > E3hh-1) // mouse outside image area X@@ -22598,7 +22614,7 @@ X X imx = py3 * E3ww + px3; // update pixmap to selected image X HDFpixmap[imx] = HDFimage; X- X+ X imx = HDFimage; X xoff = cimOffs[imx].xf; X yoff = cimOffs[imx].yf; X@@ -22634,16 +22650,16 @@ X mx = Mxdrag; X my = Mydrag; X } X- X+ X else return; X X if (mx < 0 || mx > E3ww-1 || my < 0 || my > E3hh-1) // mouse outside image area X return; X X- imx = my * E3ww + mx; // if pixel has been painted, X+ imx = my * E3ww + mx; // if pixel has been painted, X imx = HDFpixmap[imx]; // select corresp. image to warp X if (imx == cimNF) return; // else no action v.10.8 X- X+ X if (imx != HDFimage) { X HDFimage = imx; // update selected image and X imageN[5] = '1' + imx; // dialog radio button X@@ -22663,7 +22679,7 @@ X Mydown = Mydrag; X X d1 = ww * ww + hh * hh; X- X+ X for (py = 0; py < hh; py++) // process all output pixels X for (px = 0; px < ww; px++) X { X@@ -22675,7 +22691,7 @@ X X dispx = -dx * mag; // displacement = drag * mag X dispy = -dy * mag; X- X+ X ii = py * ww + px; X HDFwarpx[imx][ii] += dispx; // add this drag to prior sum X HDFwarpy[imx][ii] += dispy; X@@ -22703,7 +22719,7 @@ X void * HDF_combine_thread(void *) // v.10.7 X { X void * HDF_combine_wthread(void *); X- X+ X while (true) X { X thread_idle_loop(); // wait for work or exit request X@@ -22741,7 +22757,7 @@ X for (px3 = 1; px3 < E3ww-1; px3++) X { X pix3 = PXMpix(E3pxm16,px3,py3); X- X+ X imx = py3 * E3ww + px3; X imx = HDFpixmap[imx]; X X@@ -22759,7 +22775,7 @@ X } X else pix3[0] = pix3[1] = pix3[2] = 0; X } X- X+ X else // use blend of all images X { X red = green = blue = 0; X@@ -22777,7 +22793,7 @@ X blue += vpix1[2]; X } X } X- X+ X pix3[0] = red / cimNF; X pix3[1] = green / cimNF; X pix3[2] = blue / cimNF; X@@ -22793,11 +22809,11 @@ X X Stack/Paint function X Combine multiple images of one subject taken at different times from X- (almost) the same camera position. Align the images and allow the user X- to choose which input image to use for each area of the output image, X+ (almost) the same camera position. Align the images and allow the user X+ to choose which input image to use for each area of the output image, X by "painting" with the mouse. Use this to remove tourists and cars that X move in and out of a scene being photographed. X- X+ X **************************************************************************/ X X int STPstat; // 1 = OK, 0 = failed or canceled X@@ -22827,7 +22843,7 @@ X char **flist; X int imx, err, ww, hh; X double diffw, diffh; X- X+ X zfuncs::F1_help_topic = "stack_paint"; // help topic X X if (mod_keep()) return; // warn unsaved changes X@@ -22838,7 +22854,7 @@ X cimPXMf[imx] = cimPXMs[imx] = cimPXMw[imx] = 0; X } X X- cimNF = 0; X+ cimNF = 0; X X flist = zgetfileN(ZTX("Select 2 to 9 files"),"openN",curr_file); // select images to combine X if (! flist) return; X@@ -22852,12 +22868,12 @@ X cimNF = imx; // file count X for (imx = 0; imx < cimNF; imx++) X cimFile[imx] = strdupz(flist[imx],0,"STP.file"); // set up file list X- X+ X if (! cim_load_files()) goto cleanup; // load and check all files X X ww = cimPXMf[0]->ww; X hh = cimPXMf[0]->hh; X- X+ X for (imx = 1; imx < cimNF; imx++) // check image compatibility X { X diffw = abs(ww - cimPXMf[imx]->ww); X@@ -22906,7 +22922,7 @@ X if (cimPXMs[imx]) PXM_free(cimPXMs[imx]); X if (cimPXMw[imx]) PXM_free(cimPXMw[imx]); X } X- X+ X *SB_text = 0; X return; X } X@@ -22923,21 +22939,21 @@ X double R, maxtf, mintf, midtf; X double xoff, yoff, toff, dxoff, dyoff; X cimoffs offsets[10]; // x/y/t offsets after alignment X- X+ X Fzoom = 0; // fit to window if big X Fblowup = 1; // scale up to window if small X Ffuncbusy++; X X for (imx = 0; imx < cimNF; imx++) X memset(&offsets[imx],0,sizeof(cimoffs)); X- X+ X for (im1 = 0; im1 < cimNF-1; im1++) // loop each pair of images X { X im2 = im1 + 1; X X memset(&cimOffs[im1],0,sizeof(cimoffs)); // initial image offsets = 0 X memset(&cimOffs[im2],0,sizeof(cimoffs)); X- X+ X ww = cimPXMf[im1]->ww; // image dimensions X hh = cimPXMf[im1]->hh; X X@@ -22979,7 +22995,7 @@ X cim_get_redpix(im1); // get high-contrast pixels X X cim_align_image(im1,im2); // align im2 to im1 X- X+ X zfree(cimRedpix); // clear red pixels X cimRedpix = 0; X X@@ -23009,7 +23025,7 @@ X cimWarpRange = STPwarpRange; // align corner warp range X cimWarpStep = STPwarpStep; // align corner warp step size X } X- X+ X offsets[im2].xf = cimOffs[im2].xf - cimOffs[im1].xf; // save im2 offsets from im1 X offsets[im2].yf = cimOffs[im2].yf - cimOffs[im1].yf; X offsets[im2].tf = cimOffs[im2].tf - cimOffs[im1].tf; X@@ -23022,7 +23038,7 @@ X X for (imx = 0; imx < cimNF; imx++) // offsets[*] >> cimOffs[*] X cimOffs[imx] = offsets[imx]; X- X+ X cimOffs[0].xf = cimOffs[0].yf = cimOffs[0].tf = 0; // image 0 at (0,0,0) X X for (im1 = 0; im1 < cimNF-1; im1++) // absolute offsets for image 1 to last X@@ -23049,7 +23065,7 @@ X if (toff < mintf) mintf = toff; X } X midtf = 0.5 * (maxtf + mintf); X- X+ X for (imx = 0; imx < cimNF; imx++) X cimOffs[imx].tf -= midtf; X X@@ -23104,14 +23120,14 @@ X labN[0] = '1' + imx; X zdialog_add_widget(STPzd,"radio",imageN,"hbim",labN); X } X- X+ X zdialog_stuff(STPzd,"image1",1); // initial image = 1st X X STPimage = 0; // initial image X STPradius = 100; // paint radius X X takeMouse(STPzd,STP_mousefunc,0); // connect mouse function X- X+ X cc = E3ww * E3hh; // allocate pixel map X STPpixmap = zmalloc(cc,"STP.pixmap"); X memset(STPpixmap,cimNF,cc); // initial state, blend all images X@@ -23131,7 +23147,7 @@ X int STP_tweak_dialog_event(zdialog *zd, cchar *event) // v.11.02 X { X int nn, mymouse; X- X+ X if (zd->zstat) // dialog finish X { X paint_toparc(2); // stop brush outline X@@ -23144,10 +23160,10 @@ X zdialog_free(STPzd); X zfree(STPpixmap); // free pixel map X } X- X+ X if (strnEqu(event,"image",5)) { // image radio button X nn = event[5] - '0'; // 1 to cimNF X- if (nn > 0 && nn <= cimNF) X+ if (nn > 0 && nn <= cimNF) X STPimage = nn - 1; // 0 to cimNF-1 X signal_thread(); X } X@@ -23182,7 +23198,7 @@ X int mx, my, dx, dy, px3, py3, ww; X double px1, py1; X double xoff, yoff, sintf[10], costf[10]; X- X+ X radius = STPradius; // paintbrush radius X radius2 = radius * radius; X X@@ -23201,7 +23217,7 @@ X mx = Mxdrag; X my = Mydrag; X } X- X+ X else return; X X if (mx < 0 || mx > E3ww-1 || my < 0 || my > E3hh-1) // mouse outside image area X@@ -23227,7 +23243,7 @@ X X imx = py3 * E3ww + px3; // update pixmap to selected image X STPpixmap[imx] = STPimage; X- X+ X imx = STPimage; X xoff = cimOffs[imx].xf; X yoff = cimOffs[imx].yf; X@@ -23258,7 +23274,7 @@ X void * STP_combine_thread(void *) // v.11.02 X { X void * STP_combine_wthread(void *); X- X+ X while (true) X { X thread_idle_loop(); // wait for work or exit request X@@ -23296,7 +23312,7 @@ X for (px3 = 1; px3 < E3ww-1; px3++) X { X pix3 = PXMpix(E3pxm16,px3,py3); X- X+ X imx = py3 * E3ww + px3; X imx = STPpixmap[imx]; X X@@ -23314,7 +23330,7 @@ X } X else pix3[0] = pix3[1] = pix3[2] = 0; X } X- X+ X else // use blend of all images X { X red = green = blue = 0; X@@ -23332,7 +23348,7 @@ X blue += vpix1[2]; X } X } X- X+ X pix3[0] = red / cimNF; X pix3[1] = green / cimNF; X pix3[2] = blue / cimNF; X@@ -23347,7 +23363,7 @@ X /************************************************************************** X X Stack/Noise function X- Combine multiple photos of the same subject and average the X+ Combine multiple photos of the same subject and average the X pixels for noise reduction. X X **************************************************************************/ X@@ -23381,7 +23397,7 @@ X char **flist; X int imx, err, ww, hh; X double diffw, diffh; X- X+ X zfuncs::F1_help_topic = "stack_noise"; // help topic X X if (mod_keep()) return; // warn unsaved changes X@@ -23392,7 +23408,7 @@ X cimPXMf[imx] = cimPXMs[imx] = cimPXMw[imx] = 0; X } X X- cimNF = 0; X+ cimNF = 0; X X flist = zgetfileN(ZTX("Select 2 to 9 files"),"openN",curr_file); // select images to combine X if (! flist) return; X@@ -23406,12 +23422,12 @@ X cimNF = imx; // file count X for (imx = 0; imx < cimNF; imx++) X cimFile[imx] = strdupz(flist[imx],0,"STN.file"); // set up file list X- X+ X if (! cim_load_files()) goto cleanup; // load and check all files X X ww = cimPXMf[0]->ww; X hh = cimPXMf[0]->hh; X- X+ X for (imx = 1; imx < cimNF; imx++) // check image compatibility X { X diffw = abs(ww - cimPXMf[imx]->ww); X@@ -23460,7 +23476,7 @@ X if (cimPXMs[imx]) PXM_free(cimPXMs[imx]); X if (cimPXMw[imx]) PXM_free(cimPXMw[imx]); X } X- X+ X *SB_text = 0; X return; X } X@@ -23476,11 +23492,11 @@ X int imx, im1, im2, ww, hh, ii, nn; X double R, maxtf, mintf, midtf; X double xoff, yoff, toff, dxoff, dyoff; X- X+ X Fzoom = 0; // fit to window if big X Fblowup = 1; // scale up to window if small X Ffuncbusy++; // v.11.01 X- X+ X for (imx = 1; imx < cimNF; imx++) // loop 2nd to last image X { X im1 = 0; // images to align X@@ -23488,7 +23504,7 @@ X X memset(&cimOffs[im1],0,sizeof(cimoffs)); // initial image offsets = 0 X memset(&cimOffs[im2],0,sizeof(cimoffs)); X- X+ X ww = cimPXMf[im1]->ww; // image dimensions X hh = cimPXMf[im1]->hh; X X@@ -23530,7 +23546,7 @@ X cim_get_redpix(im1); // get high-contrast pixels X X cim_align_image(im1,im2); // align im2 to im1 X- X+ X zfree(cimRedpix); // clear red pixels X cimRedpix = 0; X X@@ -23570,7 +23586,7 @@ X if (toff < mintf) mintf = toff; X } X midtf = 0.5 * (maxtf + mintf); X- X+ X for (imx = 0; imx < cimNF; imx++) X cimOffs[imx].tf -= midtf; X X@@ -23615,17 +23631,17 @@ X zdialog_add_widget(zd,"hbox","hb2","dialog",0,"space=3"); X zdialog_add_widget(zd,"check","exlow","hb2","omit low pixel","space=3"); X zdialog_add_widget(zd,"check","exhigh","hb2","omit high pixel","space=3"); X- X+ X zdialog_stuff(zd,"average",1); // default = average X zdialog_stuff(zd,"median",0); X zdialog_stuff(zd,"exlow",0); X zdialog_stuff(zd,"exhigh",0); X- X+ X STN_average = 1; X STN_median = 0; X STN_exlow = 0; X STN_exhigh = 0; X- X+ X start_thread(STN_combine_thread,0); // start working thread X signal_thread(); X X@@ -23648,27 +23664,27 @@ X zdialog_free(zd); X if (STN_stat == 1) cim_trim(); // trim edges v.10.9 X } X- X+ X if (strEqu(event,"average")) { X zdialog_fetch(zd,"average",STN_average); X signal_thread(); X } X- X+ X if (strEqu(event,"median")) { X zdialog_fetch(zd,"median",STN_median); X signal_thread(); X } X- X+ X if (strEqu(event,"exlow")) { X zdialog_fetch(zd,"exlow",STN_exlow); X signal_thread(); X } X- X+ X if (strEqu(event,"exhigh")) { X zdialog_fetch(zd,"exhigh",STN_exhigh); X signal_thread(); X } X- X+ X return 1; X } X X@@ -23710,7 +23726,7 @@ X X // input layers 0 1 2 3 4 5 6 7 8 9 10 X int nsx[11][2] = { {0,0}, {0,0}, {0,1}, {1,1}, {1,2}, {2,2}, {2,3}, {2,4}, {2,5}, {3,5}, {3,6} }; X- X+ X for (imx = 0; imx < cimNF; imx++) // pre-calculate trig funcs X { X sintf[imx] = sin(cimOffs[imx].tf); X@@ -23735,9 +23751,9 @@ X ns++; X } X } X- X+ X if (! ns) continue; X- X+ X if (STN_exlow || STN_exhigh || STN_median) { // RGB values must be sorted X HeapSort(Rlist,ns); X HeapSort(Glist,ns); X@@ -23750,7 +23766,7 @@ X { X ns1 = 0; // low and high RGB values X ns2 = ns - 1; X- X+ X if (STN_exlow) { // exclude low X ns1++; X if (ns1 > ns2) ns1--; X@@ -23760,7 +23776,7 @@ X ns2--; X if (ns1 > ns2) ns2++; X } X- X+ X for (ii = ns1; ii <= ns2; ii++) // sum remaining RGB levels X { X red += Rlist[ii]; X@@ -23774,12 +23790,12 @@ X green = green / ns; X blue = blue / ns; X } X- X+ X if (STN_median) // use median input pixels X { X ns1 = nsx[ns][0]; // middle group of pixels X ns2 = nsx[ns][1]; X- X+ X for (ii = ns1; ii <= ns2; ii++) X { X red += Rlist[ii]; X@@ -23854,7 +23870,7 @@ X cimFile[imx] = 0; X cimPXMf[imx] = cimPXMs[imx] = cimPXMw[imx] = 0; X } X- cimNF = 0; X+ cimNF = 0; X X flist = zgetfileN(ZTX("Select 2 to 4 files"),"openN",curr_file); // select images to combine X if (! flist) return; X@@ -23868,7 +23884,7 @@ X cimNF = imx; // file count X for (imx = 0; imx < cimNF; imx++) X cimFile[imx] = strdupz(flist[imx],0,"pano.file"); // set up file list X- X+ X if (! cim_load_files()) goto cleanup; // load and check all files X X free_resources(); // ready to commit X@@ -23879,7 +23895,7 @@ X if (! edit_setup("pano",0,0)) goto cleanup; // setup edit, no preview X X cimShowAll = 1; // for cim_show_images(), show all v.10.9 X- X+ X pano_prealign(); // manual pre-alignment X if (panStat != 1) goto cancel; X X@@ -23910,7 +23926,7 @@ X if (cimPXMs[imx]) PXM_free(cimPXMs[imx]); X if (cimPXMw[imx]) PXM_free(cimPXMw[imx]); X } X- X+ X *SB_text = 0; X return; X } X@@ -23945,13 +23961,13 @@ X *lensname = 0; X strncatv(lensname,40,"(",lens4_name[curr_lens],")",null); X } X- X+ X for (imx = 0; imx < 10; imx++) // set all alignment offsets = 0 X memset(&cimOffs[imx],0,sizeof(cimoffs)); X- X+ X for (imx = ww = 0; imx < cimNF; imx++) // sum image widths X ww += cimPXMf[imx]->ww; X- X+ X cimScale = 1.4 * panPreAlignSize / ww; // set alignment image scale X if (cimScale > 1.0) cimScale = 1.0; // (* 0.7 after overlaps) X X@@ -23962,7 +23978,7 @@ X cim_curve_image(imx); X cimPXMw[imx] = PXM_copy(cimPXMs[imx]); // copy to cimPXMw[*] X } X- X+ X cimOffs[0].xf = cimOffs[0].yf = 0; // first image at (0,0) X X for (imx = 1; imx < cimNF; imx++) // position images with 30% overlap X@@ -23970,7 +23986,7 @@ X cimOffs[imx].xf = cimOffs[imx-1].xf + 0.7 * cimPXMw[imx-1]->ww; X cimOffs[imx].yf = cimOffs[imx-1].yf; X } X- X+ X Fzoom = 0; // scale image to fit window X Fblowup = 1; // magnify small image to window size X X@@ -24019,7 +24035,7 @@ X zdialog_fetch(zd,"spmm",lens_mm); // get revised lens data X zdialog_fetch(zd,"spbow",lens_bow); X } X- X+ X if (strEqu(event,"resize")) // allocate new E3 image X cim_show_images(1,0); X X@@ -24039,7 +24055,7 @@ X X zdialog_free(panozd); // kill dialog X wrapup_thread(0); // wait for thread X- X+ X if (! panStat) return 0; // canceled X X for (imx = 0; imx < cimNF-1; imx++) // check for enough overlap X@@ -24074,7 +24090,7 @@ X int ww, hh, rotate, midx; X double lens_mm0, lens_bow0; X double dx, dy, t1, t2, dt; X- X+ X imm = ww = hh = rotate = xoff = yoff = 0; // stop compiler warnings X X lens_mm0 = lens_mm; // to detect changes X@@ -24088,14 +24104,14 @@ X while (true) // loop and align until done X { X zsleep(0.05); // logic simplified X- X+ X if (panStat == 2) { // dialog search button X panStat = -1; // back to busy status X pano_autolens(); X } X- X+ X if (panStat != -1) break; // quit signal from dialog X- X+ X if (lens_mm != lens_mm0 || lens_bow != lens_bow0) { // change in lens parameters X lens_mm0 = lens_mm; X lens_bow0 = lens_bow; X@@ -24110,7 +24126,7 @@ X cim_show_images(1,0); // combine and show images X continue; X } X- X+ X if (KBkey) { // KB input X if (KBkey == GDK_Left) cimOffs[imm].xf -= 0.5; // tweak alignment offsets X if (KBkey == GDK_Right) cimOffs[imm].xf += 0.5; X@@ -24137,7 +24153,7 @@ X mx0 = mx; // set drag origin X my0 = my; X minsep = 9999; X- X+ X for (imx = 0; imx < cimNF; imx++) // find image with midpoint X { // closest to mouse x X lox = cimOffs[imx].xf; X@@ -24149,7 +24165,7 @@ X imm = imx; // image to drag or rotate X } X } X- X+ X xoff = cimOffs[imm].xf; X yoff = cimOffs[imm].yf; X ww = cimPXMw[imm]->ww; X@@ -24158,12 +24174,12 @@ X rotate = 0; // if drag at bottom edge, X if (my > yoff + 0.85 * hh) rotate = 1; // set rotate flag X } X- X+ X if (mx != mx0 || my != my0) // drag is progressing X { X dx = mx - mx0; // mouse movement X dy = my - my0; X- X+ X if (rotate && my0 > yoff && my > yoff) // rotation X { X if (imm > 0) { X@@ -24196,7 +24212,7 @@ X for (im1 = 0; im1 < cimNF-1; im1++) // track image order changes X { X im2 = im1 + 1; X- if (cimOffs[im2].xf < cimOffs[im1].xf) X+ if (cimOffs[im2].xf < cimOffs[im1].xf) X { X ftemp = cimFile[im2]; // switch filespecs X cimFile[im2] = cimFile[im1]; X@@ -24219,7 +24235,7 @@ X } X } X } X- X+ X KBcapture = Mcapture = 0; X thread_exit(); X return 0; // not executed, stop g++ warning X@@ -24277,7 +24293,7 @@ X srand48(time(0) + randcount++); X lens_mm = lens_mmB + mm_range * (drand48() - 0.5); // new random lens factors X lens_bow = lens_bowB + bow_range * (drand48() - 0.5); // within search range X- X+ X for (imx = 0; imx <= 1; imx++) { // re-curve images X cim_scale_image(imx,cimPXMs); X cim_curve_image(imx); X@@ -24289,11 +24305,11 @@ X cim_show_images(0,0); // combine and show images X X squeeze = 0.97; // search range reduction v.10.7 X- X+ X for (int ii = 0; ii < 1000; ii++) // loop random x/y/t alignments X- { X+ { X rnum = drand48(); X- if (rnum < 0.33) // random change some alignment offset X+ if (rnum < 0.33) // random change some alignment offset X cimOffs[1].xf = offsetsB.xf + xf_range * (drand48() - 0.5); X else if (rnum < 0.67) X cimOffs[1].yf = offsetsB.yf + yf_range * (drand48() - 0.5); X@@ -24318,14 +24334,14 @@ X X if (panStat != -1) goto done; // user kill X } X- X+ X if (xf_range < xf_rfinal) goto done; // finished X X sprintf(SB_text,"align: %d match: %.5f lens: %.1f %.2f", // update status bar X cimNsearch, matchB, lens_mmB, lens_bowB); X zmainloop(); X X- mm_range = squeeze * mm_range; // reduce search range if no X+ mm_range = squeeze * mm_range; // reduce search range if no X if (mm_range < 0.02 * lens_mmB) mm_range = 0.02 * lens_mmB; // improvements were found X bow_range = squeeze * bow_range; X if (bow_range < 0.1 * lens_bowB) bow_range = 0.1 * lens_bowB; X@@ -24341,7 +24357,7 @@ X X lens_mm = lens_mmB; // save best lens params found X lens_bow = lens_bowB; X- if (panStat == -1 && panozd) { // unless killed X+ if (panStat == -1 && panozd) { // unless killed X zdialog_stuff(panozd,"spmm",lens_mm); X zdialog_stuff(panozd,"spbow",lens_bow); X } X@@ -24364,7 +24380,7 @@ X double R, dx, dy, dt; X double overlap; X cimoffs offsets0; X- X+ X Fzoom = 0; // scale E3 to fit window X Fblowup = 1; // magnify small image to window size X Ffuncbusy++; // v.11.01 X@@ -24414,7 +24430,7 @@ X cimOffs[imx].xf = cimOffs[imx].xf * cimScale; X cimOffs[imx].yf = cimOffs[imx].yf * cimScale; X } X- X+ X cimSearchRange = panInitSearchRange; // initial align search range X cimSearchStep = panInitSearchStep; // initial align search step X cimWarpRange = panInitWarpRange; // initial align corner warp range X@@ -24424,7 +24440,7 @@ X cimSampSize = panSampSize; // pixel sample size for align/compare X cimNsearch = 0; // reset align search counter X cimPano = 1; // pano mode for cim_align_image() X- X+ X while (true) // loop, increasing image size X { X for (imx = 0; imx < cimNF; imx++) { // prepare images X@@ -24432,7 +24448,7 @@ X cim_curve_image(imx); // curve based on lens params X cim_warp_image_pano(imx,1); // apply corner warps X } X- X+ X cim_show_images(1,0); // show with 50/50 blend in overlaps X X for (im1 = 0; im1 < cimNF-1; im1++) // fine-align each image with left neighbor X@@ -24446,7 +24462,7 @@ X goto fail; X } X cim_get_redpix(im1); // get high-contrast pixels X- X+ X cim_align_image(im1,im2); // search for best offsets and warps X X zfree(cimRedpix); // clear red pixels X@@ -24455,7 +24471,7 @@ X dx = cimOffs[im2].xf - offsets0.xf; // changes from initial offsets X dy = cimOffs[im2].yf - offsets0.yf; X dt = cimOffs[im2].tf - offsets0.tf; X- X+ X for (imx = im2+1; imx < cimNF; imx++) // propagate to following images X { X cimOffs[imx].xf += dx; X@@ -24465,7 +24481,7 @@ X cimOffs[imx].yf += ww * dt; X } X } X- X+ X if (cimScale == 1.0) goto success; // done X X R = panImageIncrease; // next larger image size X@@ -24493,11 +24509,11 @@ X X cimBlend = cimBlend * panBlendDecrease * R; // blend width, reduced X ww = cimPXMf[0]->ww * cimScale; X- if (cimBlend < panFinalBlend * ww) X+ if (cimBlend < panFinalBlend * ww) X cimBlend = panFinalBlend * ww; // stay above minimum X } X X-success: X+success: X panStat = 1; X goto align_done; X fail: X@@ -24516,13 +24532,13 @@ X void pano_tweak() // v.10.7 X { X int pano_tweak_event(zdialog *zd, cchar *event); // dialog event function X- X+ X cchar *tweaktitle = ZTX("Match Brightness and Color"); X char imageN[8] = "imageN"; X int imx; X- X+ X cimBlend = 1; // init. blend width X- X+ X panozd = zdialog_new(tweaktitle,mWin,Bdone,Bcancel,null); X X zdialog_add_widget(panozd,"hbox","hbim","dialog",0,"space=5"); X@@ -24539,7 +24555,7 @@ X zdialog_add_widget(panozd,"label","labbr","hbbri",Bbrightness,"space=5"); // X zdialog_add_widget(panozd,"spin","bright","hbbri","50|200|0.1|100"); // -------------------------- X zdialog_add_widget(panozd,"button","brapp","hbbri",Bapply,"space=10"); // X- zdialog_add_widget(panozd,"hsep","hsep","dialog",0,"space=5"); // blend width [___] [apply] X+ zdialog_add_widget(panozd,"hsep","hsep","dialog",0,"space=5"); // blend width [___] [apply] X zdialog_add_widget(panozd,"hbox","hbc3","dialog",0,"space=5"); // X zdialog_add_widget(panozd,"button","auto","hbc3",ZTX("auto color"),"space=5"); // [done] [cancel] X zdialog_add_widget(panozd,"button","file","hbc3",ZTX("file color"),"space=5"); X@@ -24548,12 +24564,12 @@ X zdialog_add_widget(panozd,"label","labbl","hbblen",Bblendwidth,"space=5"); X zdialog_add_widget(panozd,"spin","blend","hbblen","0|300|1|1"); X zdialog_add_widget(panozd,"button","blapp","hbblen",Bapply,"space=15"); X- X+ X for (imx = 0; imx < cimNF; imx++) { // add radio button per image X imageN[5] = '0' + imx; X zdialog_add_widget(panozd,"radio",imageN,"hbim",0,"space=5"); X } X- X+ X zdialog_stuff(panozd,"image0",1); // pre-select 1st image X zdialog_resize(panozd,300,0); X X@@ -24573,7 +24589,7 @@ X double red1, green1, blue1; X int nn, im0, imx, im1, im2, ww, hh, px, py; X uint16 *pixel; X- X+ X if (zd->zstat) // dialog complete X { X if (zd->zstat == 1) panStat = 1; // done X@@ -24599,24 +24615,24 @@ X red = red * bright; // adjust RGB brightness X green = green * bright; X blue = blue * bright; X- X+ X bright = (red + green + blue) / 3; X zdialog_stuff(zd,"red",red); // force back into consistency X zdialog_stuff(zd,"green",green); X zdialog_stuff(zd,"blue",blue); X zdialog_stuff(zd,"bright",bright); X- X+ X if (strEqu(event,"brapp")) // apply color & brightness changes X { X red = red / 100; // normalize 0.5 ... 2.0 X green = green / 100; X blue = blue / 100; X- X+ X cim_warp_image_pano(im0,0); // refresh cimPXMw from cimPXMs X X ww = cimPXMw[im0]->ww; X hh = cimPXMw[im0]->hh; X- X+ X for (py = 0; py < hh; py++) // loop all image pixels X for (px = 0; px < ww; px++) X { X@@ -24635,18 +24651,18 @@ X green1 = green1 * bright; X blue1 = blue1 * bright; X } X- X+ X if (blue1 < 1) blue1 = 1; // avoid 0 v.10.7 X X pixel[0] = red1; X pixel[1] = green1; X pixel[2] = blue1; X } X- X+ X cimBlend = 1; X cim_show_images(0,0); // combine and show with 50/50 blend X } X- X+ X if (strEqu(event,"auto")) // auto match color of selected image X { X for (im1 = im0; im1 < cimNF-1; im1++) // from selected image to last image X@@ -24677,7 +24693,7 @@ X cim_show_images(0,0); X } X } X- X+ X if (strEqu(event,"file")) // use original file colors X { X if (! cim_load_files()) return 1; X@@ -24692,7 +24708,7 @@ X cimBlend = 1; X cim_show_images(0,0); X } X- X+ X if (strEqu(event,"blapp")) // apply new blend width X { X zdialog_fetch(zd,"blend",cimBlend); // can be zero X@@ -24717,9 +24733,9 @@ X int ii, jj, err; X char *pp = 0, pluginfile[200]; X PXM *pxmtemp; X- X+ X zfuncs::F1_help_topic = "plugins"; X- X+ X for (ii = 0; ii < Nplugins; ii++) // search plugins for menu name X { X pp = strstr(plugins[ii]," = "); X@@ -24729,13 +24745,13 @@ X *pp = ' '; X if (jj) break; X } X- X+ X if (ii == Nplugins) { X zmessageACK(mWin,"plugin menu not found %s",menu); X return; X } X X- pp += 3; X+ pp += 3; X if (strlen(pp) < 3) { X zmessageACK(mWin,"no plugin command"); X return; X@@ -24747,7 +24763,7 @@ X if (! edit_setup(menu,0,0)) return; // setup edit, no preview, no select area X X snprintf(pluginfile,199,"%s/plugfile.tif",get_zuserdir()); // /home/user/.fotoxx/plugfile.tif X- X+ X TIFFwrite(E1pxm16,pluginfile); // E1 >> plugin_file X X strcat(command," "); // construct: command /.../plugin_file & X@@ -24760,14 +24776,14 @@ X edit_cancel(); X return; X } X- X+ X pxmtemp = TIFFread(pluginfile); // read command output file X if (! pxmtemp) { X zmessageACK(mWin,"plugin failed"); X edit_cancel(); X return; X } X- X+ X PXM_free(E3pxm16); // plugin_file >> E3 X if (pxmtemp->bpc == 16) E3pxm16 = pxmtemp; X else { X@@ -24778,7 +24794,7 @@ X Fmodified = 1; X edit_done(); X return; X-} X+} X X X // edit plugins menu X@@ -24790,9 +24806,9 @@ X int ii; X char *pp; X zdialog *zd; X- X+ X zfuncs::F1_help_topic = "plugins"; X- X+ X zd = zdialog_new("Edit Plugins",mWin,ZTX("Add"),ZTX("Remove"),Bdone,null); X zdialog_add_widget(zd,"hbox","hbm","dialog",0,"space=5"); X zdialog_add_widget(zd,"label","labm","hbm","menu name","space=5"); X@@ -24809,7 +24825,7 @@ X zdialog_cb_app(zd,"menu",plugins[ii]); X *pp = ' '; X } X- X+ X zdialog_run(zd,edit_plugins_event); X return; X } X@@ -24821,11 +24837,11 @@ X { X int ii, jj, cc, zstat; X char menu[40], *pp = 0; X- X+ X zdialog_fetch(zd,"menu",menu,40); // selected menu X zdialog_fetch(zd,"command",command,ccc); X- X- if (strEqu(event,"menu")) X+ X+ if (strEqu(event,"menu")) X { X for (ii = 0; ii < Nplugins; ii++) X { X@@ -24836,20 +24852,20 @@ X *pp = ' '; X if (jj) break; X } X- X+ X if (ii == Nplugins) return 0; X X pp += 3; X if (strlen(pp) < 3) return 0; X strncpy0(command,pp,ccc); X zdialog_stuff(zd,"command",command); // stuff corresp. command in dialog X- X+ X return 0; X } X- X+ X zstat = zd->zstat; X if (! zstat) return 0; X- X+ X if (zstat == 1) // add new plugin X { X if (strlen(menu) < 3 || strlen(command) < 3) return 0; X@@ -24867,7 +24883,7 @@ X X zmessageACK(mWin,ZTX("Restart Fotoxx to update plugin menu")); X } X- X+ X if (zstat == 2) // remove current plugin X { X for (ii = 0; ii < Nplugins; ii++) X@@ -24879,21 +24895,21 @@ X *pp = ' '; X if (jj) break; X } X- X+ X if (ii == Nplugins) return 0; X- X+ X Nplugins--; // remove plugin record X for (jj = ii; jj < Nplugins; jj++) X plugins[jj] = plugins[jj+1]; X- X+ X zmessageACK(mWin,ZTX("Restart Fotoxx to update plugin menu")); X } X- X+ X if (zstat == 3) { // done X zdialog_free(zd); X return 0; X } X- X+ X return 0; X } X X@@ -24919,7 +24935,7 @@ X thread function X thread_idle_loop() wait for pending work, exit if commanded X thread_exit() exit thread unconditionally X- X+ X thread_status (thread ownership X 0 no thread is running X 1 thread is running and idle (no work) X@@ -24964,7 +24980,7 @@ X X if (! curr_file) return 0; // no image file X if (! menulock(1)) return 0; // lock menu X- X+ X if (! Fexiftool && ! Fexifwarned) { X zmessageACK(mWin,ZTX("exiftool is not installed \n" // warn if starting to edit X "edited images will lose EXIF data")); // and exiftool is missing v.9.9 X@@ -24987,7 +25003,7 @@ X sa_delete(); X zdialog_free(zdsela); X } X- X+ X if (uprev && uarea == 2 && sa_stat && ! Factivearea) { // select area exists and can be used, X yn = zmessageYN(mWin,ZTX("Select area not active.\n" // but not active, ask user v.10.1 X "Continue?")); X@@ -24996,7 +25012,7 @@ X return 0; X } X } X- X+ X Fpreview = 0; // use preview image if supported X if (uprev && ! (uarea == 2 && Factivearea)) { // and select area will not be used X sa_show(0); // hide area if present X@@ -25012,7 +25028,7 @@ X sa_show(0); // and bring it back when done v.9.7 X Fshowarea = 1; X } X- X+ X mutex_lock(&Fpixmap_lock); // lock pixmaps X X if (! Fpxm16) Fpxm16 = f_load(curr_file,16); // create Fpxm16 if not already X@@ -25030,7 +25046,7 @@ X X E1ww = E3ww = E1pxm16->ww; X E1hh = E3hh = E1pxm16->hh; X- X+ X if (Pundo == 0) { X edit_function = "initial"; // initial image >> undo stack v.10.2 X save_undo(); X@@ -25064,7 +25080,7 @@ X if (Espcdat) zfree(Espcdat); // free spline curves data v.11.01 X Espcdat = 0; X } X- X+ X mutex_lock(&Fpixmap_lock); X PXM_free(E1pxm16); // free edit pixmaps E1, E3 X PXM_free(E3pxm16); X@@ -25079,12 +25095,12 @@ X mwpaint2(); // refresh window X edit_action = 0; X return; X-} X+} X X X /**************************************************************************/ X X-// process edit dialog [done] X+// process edit dialog [done] X // E3pxm16 >> Fpxm16 >> Fpxm8 X X void edit_done() X@@ -25125,7 +25141,7 @@ X PXM_free(E3pxm16); X PXM_free(ERpxm16); // free redo copy v.10.3 X E1ww = E3ww = ERww = 0; X- X+ X Fmodified = Fpreview = 0; // reset flags X Ntoplines = Nptoplines; // no overlay lines X paint_toparc(2); // no brush outline X@@ -25147,7 +25163,7 @@ X if (thread_status == 2) return; // bugfix, thread busy v.10.2 X if (edit_action) return; X edit_action++; X- X+ X mutex_lock(&Fpixmap_lock); X PXM_free(ERpxm16); // make redo copy v.10.3 X ERpxm16 = E3pxm16; X@@ -25280,18 +25296,18 @@ X { X char *pp, buff[24]; X int fid, cc, cc2; X- X+ X pp = strstr(undo_files,"_undo_"); X if (! pp) zappcrash("undo/redo stack corrupted 1"); X snprintf(pp+6,3,"%02d",Pundo); X- X+ X fid = open(undo_files,O_WRONLY|O_CREAT|O_TRUNC,0640); X if (! fid) zappcrash("undo/redo stack corrupted 2"); X X snprintf(buff,24," %05d %05d fotoxx ",Fww,Fhh); X cc = write(fid,buff,20); X if (cc != 20) zappcrash("undo/redo stack corrupted 3"); X- X+ X cc = Fww * Fhh * 6; X cc2 = write(fid,Fpxm16->bmp,cc); X if (cc2 != cc) zappcrash("undo/redo stack corrupted 4"); X@@ -25314,10 +25330,10 @@ X pp = strstr(undo_files,"_undo_"); X if (! pp) zappcrash("undo/redo stack corrupted 1"); X snprintf(pp+6,3,"%02d",Pundo); X- X+ X fid = open(undo_files,O_RDONLY); X if (! fid) zappcrash("undo/redo stack corrupted 2"); X- X+ X *fotoxx = 0; X cc = read(fid,buff,20); X sscanf(buff," %d %d %8s ",&ww, &hh, fotoxx); X@@ -25331,12 +25347,12 @@ X cc2 = read(fid,Fpxm16->bmp,cc); X if (cc2 != cc) zappcrash("undo/redo stack corrupted 5"); X close(fid); X- X+ X PXM_free(Fpxm8); X Fpxm8 = PXM_convbpc(Fpxm16); X Fww = ww; X Fhh = hh; X- X+ X edit_function = pvlist_get(editlog,Pundo); // last edit func not un-done v.10.2 X X mutex_unlock(&Fpixmap_lock); X@@ -25377,7 +25393,7 @@ X zmainloop(); X zsleep(0.01); X } X- X+ X return; X } X X@@ -25417,7 +25433,7 @@ X if (thread_pend > thread_done) break; // wait for work request X zsleep(0.01); X } X- X+ X thread_hiwater = thread_pend; // set high-water mark X thread_status = 2; // thread is working X return; // loop to thread X@@ -25457,7 +25473,7 @@ X X void wait_wts() // wait for all working threads done X { X- while (wthreads_busy) X+ while (wthreads_busy) X { X zmainloop(); X zsleep(0.01); X@@ -25475,11 +25491,11 @@ X X void m_help(GtkWidget *, cchar *menu) X { X- if (strEqu(menu,ZTX("About"))) X+ if (strEqu(menu,ZTX("About"))) X zmessageACK(mWin,"%s \n%s \n%s \n\n%s \n\n%s \n\n%s", X fversion,flicense,fhomepage,fcredits,ftranslators,fcontact); X- X- if (strEqu(menu,ZTX("User Guide"))) X+ X+ if (strEqu(menu,ZTX("User Guide"))) X showz_userguide(); X X if (strEqu(menu,ZTX("Help"))) // toolbar button v.10.4 X@@ -25493,7 +25509,7 @@ X X if (strEqu(menu,ZTX("Translate"))) X showz_translations(); X- X+ X if (strEqu(menu,ZTX("Home Page"))) X showz_html(fhomepage); X X@@ -25554,15 +25570,15 @@ X char **charloc; X int *intloc; X double *doubleloc; X- X+ X gtk_window_get_size(MWIN,&Dww,&Dhh); // prevent shrinkage X X snprintf(buff,199,"%s/parameters",get_zuserdir()); // open output file X fid = fopen(buff,"w"); X if (! fid) return; X- X+ X fprintf(fid,"%s \n",fversion); // write fotoxx version X- X+ X for (int ii = 0; ii < Nparms; ii++) // write table of state data X { X name = paramTab[ii].name; X@@ -25592,28 +25608,28 @@ X X fprintf(fid,"\n"); // write EOR X } X- X+ X fprintf(fid,"\n"); X fclose(fid); // close file X X snprintf(buff,199,"%s/recent_files",get_zuserdir()); // open file for recent files list X fid = fopen(buff,"w"); X if (! fid) return; X- X+ X for (int ii = 0; ii < Nrecentfiles; ii++) // save list of recent files X if (recentfiles[ii]) X fprintf(fid,"%s \n",recentfiles[ii]); X- X+ X fclose(fid); X X snprintf(buff,199,"%s/plugins",get_zuserdir()); // open file for plugins v.11.03 X fid = fopen(buff,"w"); X if (! fid) return; X- X+ X for (int ii = 0; ii < Nplugins; ii++) // save plugins X if (plugins[ii]) X fprintf(fid,"%s \n",plugins[ii]); X- X+ X fclose(fid); X X return; X@@ -25633,7 +25649,7 @@ X char **charloc; X int *intloc; X double *doubleloc; X- X+ X for (ii = 0; ii < Nparms; ii++) // set string parameters to "undefined" X { // v.10.11 X if (strNeq(paramTab[ii].type,"char")) continue; X@@ -25650,7 +25666,7 @@ X pp = fgets_trim(buff,499,fid,1); // get last fotoxx version X if (pp && strNeq(pp,fversion)) // bugfix v.10.11 X printf("version change: %s %s \n",pp,fversion); X- X+ X while (true) // read parameters X { X pp = fgets_trim(buff,999,fid,1); X@@ -25662,17 +25678,17 @@ X X strncpy0(name,pp,20); // parm name X strTrim2(name); X- X+ X strncpy0(type,pp+22,8); // parm type X strTrim2(type); X- X+ X strncpy0(count,pp+32,4); // parm count X strTrim2(count); X err = convSI(count,pcount); X- X+ X strncpy0(data,pp+38,1000); // parm value(s) X strTrim2(data); X- X+ X for (ii = 0; ii < Nparms; ii++) // match file record to param table X { X if (strNeq(name,paramTab[ii].name)) continue; // parm name X@@ -25683,7 +25699,7 @@ X charloc = (char **) location; X intloc = (int *) location; X doubleloc = (double *) location; X- X+ X for (int kk = 1; kk <= pcount; kk++) X { X pp = (char *) strField(data,' ',kk); X@@ -25731,7 +25747,7 @@ X X for (ii = 0; ii < maxplugins; ii++) // plugins list = empty v.11.03 X plugins[ii] = 0; X- X+ X plugins[0] = strdupz("Gimp = gimp"); // if empty, default Gimp plugin X Nplugins = 1; X X@@ -25739,7 +25755,7 @@ X fid = fopen(buff,"r"); X X if (fid) X- { X+ { X for (ii = 0; ii < maxplugins; ii++) // read list of plugins X { X pp = fgets_trim(buff,499,fid,1); X@@ -25791,7 +25807,7 @@ X /**************************************************************************/ X X // Compute the mean brightness of all pixel neighborhoods, // new v.9.6 X-// using a Guassian or a flat distribution for the weightings. X+// using a Guassian or a flat distribution for the weightings. X // If a select area is active, only inside pixels are calculated. X // The flat method is 10-100x faster. X X@@ -25807,7 +25823,7 @@ X X int rad, rad2, dx, dy, cc, ii; X double kern; X- X+ X brhood_radius = radius; X brhood_method = method; X X@@ -25863,7 +25879,7 @@ X ii = py * E1ww + px; // use only inside pixels X if (! sa_pixisin[ii]) continue; X } X- X+ X bsum = bsamp = 0; X X for (qy = py-rad; qy <= py+rad; qy++) // computed weighted sum of brightness X@@ -25901,10 +25917,10 @@ X continue; X } X } X- X+ X if (px == 0) Fstart = 1; X- X- if (Fstart) X+ X+ if (Fstart) X { X Fstart = 0; X bsum = bsamp = 0; X@@ -25951,7 +25967,7 @@ X if (drandz() < 0.0001) zsleep(0.001); // trigger sorry kernel scheduler X } X } X- X+ X exit_wt(); X return 0; // not executed, avoid gcc warning X } X@@ -25976,7 +25992,7 @@ X int ignore; X X mutex_lock(&Fpixmap_lock); // lock pixmaps X- X+ X strcpy(command,"rm -f "); // delete all undo files X strcat(command,undo_files); X pp = strstr(command,"_undo_"); // /home/user/.fotoxx/pppppp_undo_* X@@ -25986,12 +26002,12 @@ X Fmodified = Pundo = Pumax = Fsaved = 0; // reset undo/redo stack X Ntoplines = Nptoplines; // no image overlay lines X paint_toparc(2); // no brush outline X- X+ X if (Fshutdown) { // stop here if shutdown mode X mutex_unlock(&Fpixmap_lock); X return; X } X- X+ X if (curr_file) { X freeMouse(); // free mouse v.10.12 X sa_delete(); // delete select area X@@ -26004,7 +26020,7 @@ X SB_goal = 0; // v.9.2 X *SB_text = 0; // v.10.7 X } X- X+ X if (brhood_brightness) zfree(brhood_brightness); // free brightness map v.9.6 X brhood_brightness = 0; X X@@ -26031,7 +26047,7 @@ X uint16 *ppix, *pix0, *pix1, *pix2, *pix3; X double f0, f1, f2, f3; X double red, green, blue; X- X+ X ww = pxm->ww; X hh = pxm->hh; X ppix = (uint16 *) pxm->bmp; X@@ -26041,7 +26057,7 @@ X X if (px0 < 1 || py0 < 1) return 0; // void edge pixels X if (px0 > ww-3 || py0 > hh-3) return 0; X- X+ X pix0 = ppix + (py0 * ww + px0) * 3; // 4 pixels based at (px0,py0) X pix1 = pix0 + ww * 3; X pix2 = pix0 + 3; X@@ -26051,16 +26067,16 @@ X f1 = (px0+1 - px) * (py - py0); // in each of the 4 pixels X f2 = (px - px0) * (py0+1 - py); X f3 = (px - px0) * (py - py0); X- X+ X red = f0 * pix0[0] + f1 * pix1[0] + f2 * pix2[0] + f3 * pix3[0]; // sum the weighted inputs X green = f0 * pix0[1] + f1 * pix1[1] + f2 * pix2[1] + f3 * pix3[1]; X blue = f0 * pix0[2] + f1 * pix1[2] + f2 * pix2[2] + f3 * pix3[2]; X- X+ X vpix[0] = red; X vpix[1] = green; X vpix[2] = blue; X- X- if (blue < 1) { // v.10.7 X+ X+ if (blue < 1) { // v.10.7 X if (blue < 0.9) return 0; // mostly void X vpix[2] = 1; // avoid 0.999 to integer 0 X } X@@ -26111,7 +26127,7 @@ X if (! S_ISREG(fstat.st_mode)) return 0; // not a regular file X if (image_file_type(filespec) != 2) return 0; // not a supported image type X f_load_size = fstat.st_size; // disk file bytes X- X+ X pext = strrchr(filespec,'/'); X if (! pext) pext = filespec; X X@@ -26122,17 +26138,17 @@ X X pext = strrchr(pext,'.'); X if (! pext) pext = ""; X- X+ X if (strstr(".jpg .jpeg .JPG .JPEG",pext)) strcpy(f_load_type,"jpg"); X else if (strstr(".tif .tiff .TIF .TIFF",pext)) strcpy(f_load_type,"tif"); X else if (strstr(".png .PNG",pext)) strcpy(f_load_type,"png"); X else strcpy(f_load_type,"other"); X- X+ X if (strEqu(f_load_type,"tif")) // use tiff lib to read tiff file X pxm1 = TIFFread(filespec); X else pxm1 = PXBread(filespec); // use pixbuf lib for others X if (! pxm1) return 0; // (both set f_load_bpc = file bpc) X- X+ X if (pxm1->bpc != bpc) { X pxm2 = PXM_convbpc(pxm1); // convert to requested bpc X PXM_free(pxm1); // 8 <--> 16 X@@ -26159,10 +26175,10 @@ X char *pp, *tempfile, *pext; X int nkeys, err = 1, cc1, cc2; X struct stat fstat; X- X+ X if ((bpc != 8 && bpc != 16) || ! strstr("jpg tif png",type)) // check args X zappcrash("f_save: %s %d",type,bpc); X- X+ X Ffuncbusy++; // v.11.01 X X pext = strrchr(outfile,'/'); // force compatible file extension X@@ -26248,7 +26264,7 @@ X strcpy(funcslist+cc1+cc2," "); X cc1 += cc2 + 1; X } X- X+ X exifdata[1] = funcslist; // EXIF log key, fotoxx edits done X nkeys = 2; X } X@@ -26257,14 +26273,14 @@ X err = exif_copy(curr_file,tempfile,exifkey,exifdata,nkeys); // copy all EXIF data to temp file X if (err) zmessageACK(mWin,"Unable to copy EXIF"); // with above revisions X } X- X+ X snprintf(command,ccc,"cp -f \"%s\" \"%s\" ",tempfile,outfile); // copy temp file to output file X err = system(command); X if (err) zmessageACK(mWin,"Unable to save image: %s",wstrerror(err)); X X remove(tempfile); // delete temp file v.11.02 X zfree(tempfile); X- X+ X save_filetags(outfile); // save tag changes if any X if (strNeq(outfile,curr_file)) // if save to new file, v.10.5 X update_search_index(outfile); // update search index file X@@ -26272,7 +26288,7 @@ X Fsaved = Pundo; // update which mods are saved to disk X X add_recent_file(outfile); // first in recent files list X- X+ X strcpy(f_save_type,type); // update f_save_xxx data X f_save_bpc = bpc; X X@@ -26283,7 +26299,7 @@ X } X X f_save_size = fstat.st_size; X- X+ X Ffuncbusy--; X mwpaint2(); // v.11.03 X return 0; X@@ -26292,7 +26308,7 @@ X X /**************************************************************************/ X X-// Read from TIFF file using TIFF library. X+// Read from TIFF file using TIFF library. X // Use native TIFF file bits/pixel. X X PXM * TIFFread(cchar *filespec) // overhauled v.10.8.1 X@@ -26302,10 +26318,10 @@ X char *tiffbuff; X uint8 *tiff8, *pxm8; X uint16 *tiff16, *pxm16; X- uint16 bpc, nch, fmt; X+ uint16 bpc, nch, fmt; X int ww, hh, rps, stb, nst; // int not uint v.11.03 X int tiffstat, row, col, strip, cc; X- X+ X tiff = TIFFOpen(filespec,"r"); X if (! tiff) { X zmessageACK(mWin,ZTX("TIFF open failure")); X@@ -26322,13 +26338,13 @@ X nst = TIFFNumberOfStrips(tiff); // number of strips X X // printf("ww %d hh %d nch %d bpc %d rps %d stb %d nst %d fmt %d \n",ww,hh,nch,bpc,rps,stb,nst,fmt); X- X+ X if (! (bpc <= 8 || bpc == 16)) { // check for supported bits/color X zmessageACK(mWin,ZTX("TIFF bits/color=%d not supported"),bpc); X TIFFClose(tiff); X return 0; X } X- X+ X f_load_bpc = bpc; // for f_load(), file bpc 1/8/16 v.10.12 X X if (bpc <= 8) // use universal TIFF reader X@@ -26369,10 +26385,10 @@ X // 16 bits per color X X stb += 1000000; // reduce risk of crash v.10.8.2 X- tiffbuff = zmalloc(stb,"tiffbuff"); // read encoded strips X+ tiffbuff = zmalloc(stb,"tiffbuff"); // read encoded strips X X pxm = PXM_make(ww,hh,16); X- X+ X for (strip = 0; strip < nst; strip++) X { X cc = TIFFReadEncodedStrip(tiff,strip,tiffbuff,stb); X@@ -26383,9 +26399,9 @@ X PXM_free(pxm); X return 0; X } X- X+ X if (cc == 0) break; X- X+ X tiff16 = (uint16 *) tiffbuff; X pxm16 = (uint16 *) pxm->bmp; X row = strip * rps; X@@ -26408,7 +26424,7 @@ X } X X X-// Write to TIFF file using TIFF library. X+// Write to TIFF file using TIFF library. X // File bpc is taken from PXM (8 or 16). X // returns 0 if OK, +N if error. X X@@ -26419,15 +26435,15 @@ X uint16 *tiff16, *pxm16; X int tiffstat = 0; X int ww, hh, row, col, rowcc; // int not uint v.11.03 X- int bpc, nch, pm = 2, pc = 1, comp = 5; X+ int bpc, nch, pm = 2, pc = 1, comp = 5; X char *tiffbuff; X- X+ X tiff = TIFFOpen(filespec,"w"); X if (! tiff) { X zmessageACK(mWin,ZTX("TIFF open failure")); X return 1; X } X- X+ X ww = pxm->ww; X hh = pxm->hh; X bpc = pxm->bpc; X@@ -26439,7 +26455,7 @@ X TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, pm); // RGB X TIFFSetField(tiff, TIFFTAG_PLANARCONFIG, pc); X TIFFSetField(tiff, TIFFTAG_COMPRESSION, comp); // LZW X- X+ X rowcc = TIFFScanlineSize(tiff); X tiffbuff = (char*) zmalloc(rowcc,"tiffbuff"); X X@@ -26460,7 +26476,7 @@ X } X } X X- if (bpc == 16) X+ if (bpc == 16) X { X tiff16 = (uint16 *) tiffbuff; X pxm16 = (uint16 *) pxm->bmp + row * ww * 3; X@@ -26481,7 +26497,7 @@ X X TIFFClose(tiff); X zfree(tiffbuff); X- X+ X if (tiffstat == 1) return 0; X zmessageACK(mWin,ZTX("TIFF write failure")); X return 2; X@@ -26509,7 +26525,7 @@ X PXM *pxm; X int ww, hh, px, py, nch, rowst; X uint8 *bmp1, *bmp2, *pix1, *pix2; X- X+ X pxb = gdk_pixbuf_new_from_file(filespec,&gerror); X if (! pxb) { X printf("%s \n",gerror->message); // v.10.8 X@@ -26522,7 +26538,7 @@ X nch = gdk_pixbuf_get_n_channels(pxb); X rowst = gdk_pixbuf_get_rowstride(pxb); X bmp1 = gdk_pixbuf_get_pixels(pxb); X- X+ X pxm = PXM_make(ww,hh,8); X bmp2 = (uint8 *) pxm->bmp; X X@@ -26540,7 +26556,7 @@ X pix2 += 3; X } X } X- X+ X f_load_bpc = 8; // file bits per color for f_load() X g_object_unref(pxb); // (any value on disk becomes 8) X return pxm; X@@ -26563,7 +26579,7 @@ X ww = pxm->ww; X hh = pxm->hh; X bpc = pxm->bpc; X- X+ X pxb = gdk_pixbuf_new(RGBCOLOR,0,8,ww,hh); X if (! pxb) zappcrash("pixbuf allocation failure"); X X@@ -26589,7 +26605,7 @@ X } X } X } X- X+ X if (bpc == 16) X { X for (py = 0; py < hh; py++) X@@ -26607,12 +26623,12 @@ X } X } X } X- X+ X pext = strrchr(filespec,'/'); X if (! pext) pext = filespec; X pext = strrchr(pext,'.'); X if (! pext) pext = ""; X- X+ X if (strstr(".png .PNG",pext)) X pxbstat = gdk_pixbuf_save(pxb,filespec,"png",&gerror,null); X else pxbstat = gdk_pixbuf_save(pxb,filespec,"jpeg",&gerror,"quality",jpeg_quality,null); X@@ -26635,7 +26651,7 @@ X { X if (ww < 1 || hh < 1 || (bpc != 8 && bpc != 16)) X zappcrash("PXM_make() %d %d %d",ww,hh,bpc); X- X+ X PXM *pxm = (PXM *) zmalloc(sizeof(PXM),"PXM_make"); X pxm->ww = ww; X pxm->hh = hh; X@@ -26652,7 +26668,7 @@ X void PXM_free(PXM *&pxm) X { X if (! pxm) return; X- if (! strEqu(pxm->wmi,"rgbrgb")) X+ if (! strEqu(pxm->wmi,"rgbrgb")) X zappcrash("PXM_free(), bad PXM"); X strcpy(pxm->wmi,"xxxxxx"); X zfree(pxm->bmp); X@@ -26694,8 +26710,8 @@ X pxm2 = PXM_make(ww2,hh2,8); X bmp1 = (uint8 *) pxm1->bmp; X bmp2 = (uint8 *) pxm2->bmp; X- X- for (py1 = orgy, py2 = 0; py2 < hh2; py1++, py2++) X+ X+ for (py1 = orgy, py2 = 0; py2 < hh2; py1++, py2++) X { X for (px1 = orgx, px2 = 0; px2 < ww2; px1++, px2++) X { X@@ -26716,8 +26732,8 @@ X pxm2 = PXM_make(ww2,hh2,16); X bmp3 = (uint16 *) pxm1->bmp; X bmp4 = (uint16 *) pxm2->bmp; X- X- for (py1 = orgy, py2 = 0; py2 < hh2; py1++, py2++) X+ X+ for (py1 = orgy, py2 = 0; py2 < hh2; py1++, py2++) X { X for (px1 = orgx, px2 = 0; px2 < ww2; px1++, px2++) X { X@@ -26732,7 +26748,7 @@ X } X } X } X- X+ X return pxm2; X } X X@@ -26755,8 +26771,8 @@ X pxm2 = PXM_make(ww,hh,16); X bmp8 = (uint8 *) pxm1->bmp; X bmp16 = (uint16 *) pxm2->bmp; X- X- for (py = 0; py < hh; py++) X+ X+ for (py = 0; py < hh; py++) X { X pix8 = bmp8 + py * ww * 3; X pix16 = bmp16 + py * ww * 3; X@@ -26777,8 +26793,8 @@ X pxm2 = PXM_make(ww,hh,8); X bmp8 = (uint8 *) pxm2->bmp; X bmp16 = (uint16 *) pxm1->bmp; X- X- for (py = 0; py < hh; py++) X+ X+ for (py = 0; py < hh; py++) X { X pix8 = bmp8 + py * ww * 3; X pix16 = bmp16 + py * ww * 3; X@@ -26813,9 +26829,9 @@ X ww1 = pxm1->ww; X hh1 = pxm1->hh; X bpc = pxm1->bpc; X- X+ X pxm2 = PXM_make(ww2,hh2,bpc); X- X+ X if (bpc == 8) { X bmp1 = (uint8 *) pxm1->bmp; X bmp2 = (uint8 *) pxm2->bmp; X@@ -26827,17 +26843,17 @@ X bmp4 = (uint16 *) pxm2->bmp; X bmp16_rescale(bmp3,bmp4,ww1,hh1,ww2,hh2); X } X- X+ X return pxm2; X } X X X // Copy and rescale a modified area within a PXM-16 image into the X-// corresponding area of a PXM-8 image previously rescaled from the X-// PXM-16 image. Keep the same mapping of input to output pixels, so X-// that the modified area fits seamlessly into the PXM-8 image. Used X+// corresponding area of a PXM-8 image previously rescaled from the X+// PXM-16 image. Keep the same mapping of input to output pixels, so X+// that the modified area fits seamlessly into the PXM-8 image. Used X // when a section of an image is edited and the window image is updated. X-// X+// X // pxm1 PXM-16 image with changed area to rescale and copy X // pxm2 existing rescaled PXM-8 copy of pxm1 X // org1x, org1y pxm1 origin of area to copy (top left corner) X@@ -26859,8 +26875,8 @@ X float red, green, blue; X float *pxmap, *pymap; X X- bmp1 = (uint16 *) pxm1->bmp; X- bmp2 = (uint8 *) pxm2->bmp; X+ bmp1 = (uint16 *) pxm1->bmp; X+ bmp2 = (uint8 *) pxm2->bmp; X ww1 = pxm1->ww; X hh1 = pxm1->hh; X ww2 = pxm2->ww; X@@ -26868,14 +26884,14 @@ X X scalex = 1.0 * ww1 / ww2; // compute x and y scales X scaley = 1.0 * hh1 / hh2; X- X+ X if (scalex <= 1) maxmapx = 2; // compute max input pixels X else maxmapx = int(scalex + 2); // mapping into output pixels X maxmapx += 1; // for both dimensions X if (scaley <= 1) maxmapy = 2; // (pixels may not be square) X else maxmapy = int(scaley + 2); X maxmapy += 1; X- X+ X pymap = (float *) zmalloc(hh2 * maxmapy * sizeof(float)); // maps overlap of < maxmap input X pxmap = (float *) zmalloc(ww2 * maxmapx * sizeof(float)); // pixels per output pixel X X@@ -26893,7 +26909,7 @@ X for (py1 = pyl, pym = 0; py1 < py1b; py1++, pym++) // loop overlapping input pixels X { X if (py1 < py1a) { // compute amount of overlap X- if (py1+1 < py1b) fy = py1+1 - py1a; // 0.0 to 1.0 X+ if (py1+1 < py1b) fy = py1+1 - py1a; // 0.0 to 1.0 X else fy = scaley; X } X else if (py1+1 > py1b) fy = py1b - py1; X@@ -26905,7 +26921,7 @@ X ii = py2 * maxmapy + pym; // set an end marker after X pymap[ii] = -1; // last overlapping pixel X } X- X+ X for (px2 = 0; px2 < ww2; px2++) // do same for x-pixels X { X px1a = px2 * scalex; X@@ -26929,7 +26945,7 @@ X ii = px2 * maxmapx + pxm; X pxmap[ii] = -1; X } X- X+ X org2x = org1x / scalex; // compute output image rectangle X end2x = (org1x + ww1a) / scalex + 1; // containing any part of input area X if (org2x < 0) org2x = 0; // revised v.10.12 X@@ -26994,7 +27010,7 @@ X X PXM *pxm2 = 0; X int bpc; X- X+ X bpc = pxm1->bpc; X if (bpc == 8) pxm2 = PXM_rotate8(pxm1,angle); X if (bpc == 16) pxm2 = PXM_rotate16(pxm1,angle); X@@ -27007,12 +27023,12 @@ X Rescale 8 bpc image (3 x 8 bits per color) to new width and height. X The scale ratios may be different for width and height. X X- Method: X+ Method: X The input and output images are overlayed, stretching or shrinking the X output pixels as needed. The contribution of each input pixel overlapping X an output pixel is proportional to the area of the output pixel covered by X the input pixel. The contributions of all overlaping input pixels are added. X- The work is spread among Nwt threads to reduce the elapsed time on modern X+ The work is spread among Nwt threads to reduce the elapsed time on modern X computers having multiple SMP processors. X X Example: if the output image is 40% of the input image, then: X@@ -27050,7 +27066,7 @@ X float scalex, scaley; X float px1a, py1a, px1b, py1b; X float fx, fy; X- X+ X pixmap1 = pixmap1x; X pixmap2 = pixmap2x; X ww1 = ww1x; X@@ -27062,14 +27078,14 @@ X X scalex = 1.0 * ww1 / ww2; // compute x and y scales X scaley = 1.0 * hh1 / hh2; X- X+ X if (scalex <= 1) maxmapx = 2; // compute max input pixels X else maxmapx = int(scalex + 2); // mapping into output pixels X maxmapx += 1; // for both dimensions X if (scaley <= 1) maxmapy = 2; // (pixels may not be square) X else maxmapy = int(scaley + 2); X maxmapy += 1; X- X+ X pymap = (float *) zmalloc(hh2 * maxmapy * sizeof(float)); // maps overlap of < maxmap input X pxmap = (float *) zmalloc(ww2 * maxmapx * sizeof(float)); // pixels per output pixel X X@@ -27087,7 +27103,7 @@ X for (py1 = pyl, pym = 0; py1 < py1b; py1++, pym++) // loop overlapping input pixels X { X if (py1 < py1a) { // compute amount of overlap X- if (py1+1 < py1b) fy = py1+1 - py1a; // 0.0 to 1.0 X+ if (py1+1 < py1b) fy = py1+1 - py1a; // 0.0 to 1.0 X else fy = scaley; X } X else if (py1+1 > py1b) fy = py1b - py1; X@@ -27099,7 +27115,7 @@ X ii = py2 * maxmapy + pym; // set an end marker after X pymap[ii] = -1; // last overlapping pixel X } X- X+ X for (px2 = 0; px2 < ww2; px2++) // do same for x-pixels X { X px1a = px2 * scalex; X@@ -27128,7 +27144,7 @@ X busy[ii] = 1; X start_detached_thread(bmp8_rescale_thread,&wtnx[ii]); X } X- X+ X for (ii = 0; ii < Nwt; ii++) // wait for all done X while (busy[ii]) zsleep(0.004); X X@@ -27196,7 +27212,7 @@ X /************************************************************************** X X Rescale 16 bpc image (3 x 16 bits per color) to new width and height. X- Identical to bmp8_rescale except for the following: X+ Identical to bmp8_rescale except for the following: X uint8 >> uint16 X xxx8 >> xxx16 X X@@ -27230,7 +27246,7 @@ X float scalex, scaley; X float px1a, py1a, px1b, py1b; X float fx, fy; X- X+ X pixmap1 = pixmap1x; X pixmap2 = pixmap2x; X ww1 = ww1x; X@@ -27242,14 +27258,14 @@ X X scalex = 1.0 * ww1 / ww2; // compute x and y scales X scaley = 1.0 * hh1 / hh2; X- X+ X if (scalex <= 1) maxmapx = 2; // compute max input pixels X else maxmapx = int(scalex + 2); // mapping into output pixels X maxmapx += 1; // for both dimensions X if (scaley <= 1) maxmapy = 2; // (pixels may not be square) X else maxmapy = int(scaley + 2); X maxmapy += 1; X- X+ X pymap = (float *) zmalloc(hh2 * maxmapy * sizeof(float)); // maps overlap of < maxmap input X pxmap = (float *) zmalloc(ww2 * maxmapx * sizeof(float)); // pixels per output pixel X X@@ -27267,7 +27283,7 @@ X for (py1 = pyl, pym = 0; py1 < py1b; py1++, pym++) // loop overlapping input pixels X { X if (py1 < py1a) { // compute amount of overlap X- if (py1+1 < py1b) fy = py1+1 - py1a; // 0.0 to 1.0 X+ if (py1+1 < py1b) fy = py1+1 - py1a; // 0.0 to 1.0 X else fy = scaley; X } X else if (py1+1 > py1b) fy = py1b - py1; X@@ -27279,7 +27295,7 @@ X ii = py2 * maxmapy + pym; // set an end marker after X pymap[ii] = -1; // last overlapping pixel X } X- X+ X for (px2 = 0; px2 < ww2; px2++) // do same for x-pixels X { X px1a = px2 * scalex; X@@ -27308,7 +27324,7 @@ X busy[ii] = 1; X start_detached_thread(bmp16_rescale_thread,&wtnx[ii]); X } X- X+ X for (ii = 0; ii < Nwt; ii++) // wait for all done X while (busy[ii]) zsleep(0.004); X X@@ -27389,9 +27405,9 @@ X Angle is in degrees. Positive direction is clockwise. X Speed is about 3 million pixels/sec/thread for a 2.4 GHz CPU. X Loss of resolution is less than 1 pixel. X- X+ X Work is divided among Nwt threads to gain speed. X- X+ X v.9.3: affine transform instead of trig functions, for speed X X ***************************************************************************/ X@@ -27416,7 +27432,7 @@ X X int cc, ii; X PXM *pxm2; X- X+ X ww1 = pxm1->ww; X hh1 = pxm1->hh; X pixmap1 = (uint8 *) pxm1->bmp; X@@ -27425,7 +27441,7 @@ X while (angle < -180) angle += 360; // normalize, -180 to +180 X while (angle > 180) angle -= 360; X angle = angle * pi / 180; // radians, -pi to +pi X- X+ X if (fabs(angle) < 0.001) { // angle = 0 within my precision X pxm2 = PXM_make(ww1,hh1,8); // return a copy of the input X pixmap2 = (uint8 *) pxm2->bmp; X@@ -27436,7 +27452,7 @@ X X ww2 = int(ww1*fabs(cos(angle)) + hh1*fabs(sin(angle))); // rectangle containing rotated image X hh2 = int(ww1*fabs(sin(angle)) + hh1*fabs(cos(angle))); X- X+ X pxm2 = PXM_make(ww2,hh2,8); X pixmap2 = (uint8 *) pxm2->bmp; X X@@ -27469,7 +27485,7 @@ X b = sin(angle); X d = - sin(angle); X e = cos(angle); X- X+ X for (py2 = index; py2 < hh2; py2 += Nwt) // loop through output pixels X for (px2 = 0; px2 < ww2; px2++) // outer loop y X { X@@ -27478,7 +27494,7 @@ X X px0 = int(px1); // pixel containing (px1,py1) X py0 = int(py1); X- X+ X if (px1 < 0 || px0 >= ww1-1 || py1 < 0 || py0 >= hh1-1) { // if outside input pixel array X pix2 = pixmap2 + (py2 * ww2 + px2) * 3; // output is black X pix2[0] = pix2[1] = pix2[2] = 0; X@@ -27494,17 +27510,17 @@ X f1 = (px0+1 - px1) * (py1 - py0); // in each of the 4 pixels X f2 = (px1 - px0) * (py0+1 - py1); X f3 = (px1 - px0) * (py1 - py0); X- X+ X red = f0 * pix0[0] + f1 * pix1[0] + f2 * pix2[0] + f3 * pix3[0]; // sum the weighted inputs X green = f0 * pix0[1] + f1 * pix1[1] + f2 * pix2[1] + f3 * pix3[1]; X blue = f0 * pix0[2] + f1 * pix1[2] + f2 * pix2[2] + f3 * pix3[2]; X- X+ X pix2 = pixmap2 + (py2 * ww2 + px2) * 3; // output pixel X pix2[0] = int(red); X pix2[1] = int(green); X pix2[2] = int(blue); X } X- X+ X zadd_locked(busy,-1); X return 0; X } X@@ -27517,7 +27533,7 @@ X Identical to PXM_rotate8() except for: X uint8 >> uint16 X rotpxm8 >> rotpxm16 X- 8 >> 16 X+ 8 >> 16 X X **********/ X X@@ -27541,7 +27557,7 @@ X X int cc, ii; X PXM *pxm2; X- X+ X ww1 = pxm1->ww; X hh1 = pxm1->hh; X pixmap1 = (uint16 *) pxm1->bmp; X@@ -27550,7 +27566,7 @@ X while (angle < -180) angle += 360; // normalize, -180 to +180 X while (angle > 180) angle -= 360; X angle = angle * pi / 180; // radians, -pi to +pi X- X+ X if (fabs(angle) < 0.001) { // angle = 0 within my precision X pxm2 = PXM_make(ww1,hh1,16); // return a copy of the input X pixmap2 = (uint16 *) pxm2->bmp; X@@ -27561,7 +27577,7 @@ X X ww2 = int(ww1*fabs(cos(angle)) + hh1*fabs(sin(angle))); // rectangle containing rotated image X hh2 = int(ww1*fabs(sin(angle)) + hh1*fabs(cos(angle))); X- X+ X pxm2 = PXM_make(ww2,hh2,16); X pixmap2 = (uint16 *) pxm2->bmp; X X@@ -27594,7 +27610,7 @@ X b = sin(angle); X d = - sin(angle); X e = cos(angle); X- X+ X for (py2 = index; py2 < hh2; py2 += Nwt) // loop through output pixels X for (px2 = 0; px2 < ww2; px2++) // outer loop y X { X@@ -27603,7 +27619,7 @@ X X px0 = int(px1); // pixel containing (px1,py1) X py0 = int(py1); X- X+ X if (px1 < 0 || px0 >= ww1-1 || py1 < 0 || py0 >= hh1-1) { // if outside input pixel array X pix2 = pixmap2 + (py2 * ww2 + px2) * 3; // output is black X pix2[0] = pix2[1] = pix2[2] = 0; X@@ -27619,17 +27635,17 @@ X f1 = (px0+1 - px1) * (py1 - py0); // in each of the 4 pixels X f2 = (px1 - px0) * (py0+1 - py1); X f3 = (px1 - px0) * (py1 - py0); X- X+ X red = f0 * pix0[0] + f1 * pix1[0] + f2 * pix2[0] + f3 * pix3[0]; // sum the weighted inputs X green = f0 * pix0[1] + f1 * pix1[1] + f2 * pix2[1] + f3 * pix3[1]; X blue = f0 * pix0[2] + f1 * pix1[2] + f2 * pix2[2] + f3 * pix3[2]; X- X+ X pix2 = pixmap2 + (py2 * ww2 + px2) * 3; // output pixel X pix2[0] = int(red); X pix2[1] = int(green); X pix2[2] = int(blue); X } X- X+ X zadd_locked(busy,-1); X return 0; X } 4a06c996efb3d58a12c308fc01279d3d echo x - fotoxx/files/patch-zfuncs.cc sed 's/^X//' >fotoxx/files/patch-zfuncs.cc << 'f71ad47b5e1ace4342b0c1104a5ad99e' X--- zfuncs.cc.orig 2011-02-28 11:04:24.000000000 -0500 X+++ zfuncs.cc 2011-04-05 08:38:08.000000000 -0400 X@@ -4,7 +4,7 @@ X Copyright 2006 2007 2008 2009 2010 2011 Michael Cornelison X source URL: kornelix.squarespace.com X contact: kornelix2@googlemail.com X- X+ X This program is free software: you can redistribute it and/or modify X it under the terms of the GNU General Public License as published by X the Free Software Foundation, either version 3 of the License, or X@@ -23,6 +23,14 @@ X // zfuncs.cpp version v.4.0 X X #include "zfuncs.h" X+#include X+#include X+#include X+#include X+#include X+ X+ X+#define WEXITSTATUS(w)((w)>>8) // fixes the WEXITSTATUS not declared on FreeBSD X X X /************************************************************************** X@@ -103,15 +111,15 @@ X fid2 = popen(command,"r"); // and line number X pfunc = fgets(buff,300,fid2); X pclose(fid2); X- if (pfunc) pfunc = strrchr(pfunc,'/'); // remove directories X+ if (pfunc) pfunc = strrchr(pfunc,'/'); // remove directories X if (pfunc) pfunc++; X- } X+ } X X fprintf(fid1," %s %s \n",stackents[ii],pfunc); // write to text file X } X X fclose(fid1); X- X+ X err = system("xdg-open zappcrash"); // display in editor X abort(); X } X@@ -177,7 +185,7 @@ X X gettimeofday(&time1,0); X return time1.tv_sec + 0.000001 * time1.tv_usec - 946684800.0; X-} X+} X X X /**************************************************************************/ X@@ -318,7 +326,7 @@ X unsigned isecs, nsecs; X timespec tsecs; X X- if (dsecs == 0.0) return; X+ if (dsecs == 0.0) return; X isecs = unsigned(dsecs); X nsecs = unsigned(1000000000.0 * (dsecs - isecs)); X tsecs.tv_sec = isecs; X@@ -361,7 +369,7 @@ X memset(puser,0,bytes); X strncpy(psen2,"sen2",4); X zmalloc_tot += bytes; X- X+ X zmalloc_tabulate(ptag,bytes); // track usage by tag v.3.7 X X if (zmalloc_logcount) { X@@ -388,10 +396,10 @@ X X if (strncmp("sen1",psen1,4)) // check sentinels X zappcrash("zfree: invalid address %p",puser); X- if (strncmp("sen2",psen2,4)) X+ if (strncmp("sen2",psen2,4)) X zappcrash("zfree: buffer overflow |%s|%s|",ptag,puser); // v.3.9 X *psen1 = *psen2 = 0; // destroy sentinels v.3.8 X- X+ X zmalloc_tot -= bytes; X X zmalloc_tabulate(ptag,-bytes); // track usage by tag v.3.7 X@@ -430,7 +438,7 @@ X memset(zmalloc_count, 0, 1000 * sizeof(uint)); X memset(zmalloc_bytes, 0, 1000 * sizeof(uint)); X } X- X+ X ii = zmalloc_hashtab->Find(ptag); X if (ii < 0) ii = zmalloc_hashtab->Add(ptag); X if (ii < 0) zappcrash("zmalloc hash table full"); X@@ -452,7 +460,7 @@ X char tag[20]; X X printf("\n zmalloc total memory: %u \n",zmalloc_tot); X- X+ X while (true) X { X ii = zmalloc_hashtab->GetNext(first,tag); X@@ -463,7 +471,7 @@ X count = zmalloc_count[ii]; // added, v.3.8 X if (bytes) printf(" %-20s %8d %d \n",tag,count,bytes); X } X- X+ X return; X } X X@@ -487,17 +495,17 @@ X FILE *fid; X va_list arglist; X char buff[1000], *prec; X- X+ X if (contx == 0) // start new command X { X- for (contx = 1; contx < 10; contx++) X+ for (contx = 1; contx < 10; contx++) X if (CO_contx[contx] == 0) break; X if (contx == 10) zappcrash("command_output(), parallel usage > 9"); X- X+ X va_start(arglist,command); // format command X vsnprintf(buff,999,command,arglist); X va_end(arglist); X- X+ X fid = popen(buff,"r"); // execute command, output to FID X if (fid == 0) { X CO_status[contx] = errno; // failed to start X@@ -545,11 +553,11 @@ X pid = atoi(buff); X if (! pid) return 5; X X- if (strEqu(signal,"pause")) nsignal = SIGSTOP; X- if (strEqu(signal,"resume")) nsignal = SIGCONT; X- if (strEqu(signal,"kill")) nsignal = SIGKILL; X+ if (strEqu(signal,"pause")) nsignal = SIGSTOP; X+ if (strEqu(signal,"resume")) nsignal = SIGCONT; X+ if (strEqu(signal,"kill")) nsignal = SIGKILL; X X- err = kill(pid,nsignal); X+ err = kill(pid,nsignal); X return err; X } X X@@ -565,14 +573,14 @@ X { X char xtcommand[500]; X int err; X- X+ X if (strcmp(sucomm,"sudo") == 0) X { X snprintf(xtcommand,499,"xterm -geometry 40x3 -e sudo -S %s",command); X err = system(xtcommand); X return err; X } X- X+ X if (strcmp(sucomm,"su") == 0) X { X snprintf(xtcommand,499,"xterm -geometry 40x3 -e su -c %s",command); X@@ -604,7 +612,7 @@ X { X contx = 0; X found = 0; X- X+ X while (true) X { X buff = command_output(contx,"whereis %s",prog); X@@ -624,9 +632,9 @@ X X prog = va_arg(arglist,cchar *); X } X- X+ X va_end(arglist); X- X+ X if (Nmiss) { X for (int ii = 0; ii < Nmiss; ii++) X strncatv(errmessage,199,missprogs[ii]," ",null); X@@ -647,7 +655,7 @@ X { X int cc; X char *pp; X- X+ X pp = fgets(buff,maxcc,fid); X if (! pp) return pp; X cc = strlen(buff); X@@ -667,7 +675,7 @@ X { X int cc1, cc2; X cchar *pp1, *pp2; // v.2.15 X- X+ X if (! file1 || ! file2) return 0; X pp1 = strrchr(file1,'/'); X pp2 = strrchr(file2,'/'); X@@ -687,7 +695,7 @@ X Parse a pathname (filespec) and return its components. X Returned strings are allocated in static memory (no zfree needed). X Missing components are returned as null pointers. X- X+ X input ppath outputs X X /name1/name2/ directory /name1/name2/ with no file X@@ -697,7 +705,7 @@ X otherwise returns file name2.xxx and no ext X X returns 0 if no error, else 1 X- X+ X ***************************************************************************/ X X int parsefile(cchar *ppath, char **pdirk, char **pfile, char **pext) // v.2.15 X@@ -708,23 +716,23 @@ X int err, cc1, cc2; X X *pdirk = *pfile = *pext = null; X- X+ X cc1 = strlen(ppath); X if (cc1 > 999) return 1; // ppath too long X X strcpy(dirk,ppath); X *pdirk = dirk; X- X+ X err = stat(dirk,&statb); // have directory only X if (! err && S_ISDIR(statb.st_mode)) return 0; X- X+ X pp = (char *) strrchr(dirk,'/'); X if (! pp) return 1; // illegal X X pp++; X cc2 = pp - dirk; X if (cc2 < 2 || cc2 == cc1) return 0; // have /xxxx or /xxxx/ X- X+ X if (strlen(pp) > 199) return 1; // filename too long X X strcpy(file,pp); // file part X@@ -733,7 +741,7 @@ X X pp = (char *) strrchr(file,'.'); X if (! pp || strlen(pp) > 7) return 0; // file part, no .ext X- X+ X strcpy(ext,pp); // .ext part X *pext = ext; X *pp = 0; // remove from file part X@@ -762,7 +770,7 @@ X 2 file was deleted X 3 monitored directory is gone X 9 other X- X+ X NOTE The Linux inotify() function is used and is not reliable X for files renamed. The remove is reported but not the add. X X@@ -777,32 +785,38 @@ X int len; // Size of file name field following X char fname[200]; // null-terminated file name within directory X }; X- X+ X+ int f, kq, nev; X+ struct kevent change; X+ struct kevent event; X+ X+ //evbuff -> event fids -> f X inotify_event evbuff; X struct timeval waitime; X fd_set fids; X int wd, retval, cc, fcc; X- int evbcc = sizeof(evbuff); X+ int evbcc = sizeof(event); X static int fid = -1; X- X+ X if (strEqu(action,"open")) // setup a monitored directory X { X- fid = inotify_init(); X- if (fid < 0) { X+ f = kqueue(); // inotify_init(); X+ if (f < 0) { X return -1; X } X- wd = inotify_add_watch(fid,dirk,IN_ALL_EVENTS); X+ X+ wd = kevent(f, &change, 1, &event, 1, NULL); X if (wd < 0) { X- close(fid); X- fid = -1; X+ close(f); X+ f = -1; X return -1; X } X return 0; X } X- X+ X if (strEqu(action,"event")) // return pending event or zero X { X- if (fid < 0) return -1; X+ if (f < 0) return -1; X X if (file) { X if (*file) zfree(*file); // free prior memory X@@ -816,47 +830,51 @@ X waitime.tv_sec = 0; X waitime.tv_usec = 1; X X- retval = select(fid+1, &fids, null, null, &waitime); X+ retval = select(f+1, &fids, null, null, &waitime); X if (retval == 0) return 0; // nothing pending X X if (retval == -1) { // error X close(fid); X- fid = -1; X+ f = -1; X return -1; X } X X- cc = read(fid,&evbuff,evbcc); // get pending event X+ cc = read(f,&event,evbcc); // get pending event X if (cc == -1) { X- close(fid); X- fid = -1; X+ close(f); X+ f = -1; X return -1; X } X X- fcc = evbuff.len; X- if (fcc > 199) return -1; X- if (fcc > 0 && file) X- *file = strdupz(evbuff.fname,0,"zmondirk_file"); // return filename v.3.5 X+ //fcc = event.len; X+ //if (fcc > 199) return -1; X+ //if (fcc > 0 && file) X+ // *file = strdupz(event.fname,0,"zmondirk_file"); // return filename v.3.5 X X- if (evbuff.mask & (IN_CREATE | IN_MOVED_TO)) // file was added X+ //IN_CREATE -> NOTE_WRITE IN_MOVED_TO -> NOTE_RENAME X+ if (event.fflags & (NOTE_WRITE | NOTE_RENAME)) // file was added X return 1; X- if (evbuff.mask & (IN_CLOSE_WRITE | IN_CLOSE_NOWRITE | IN_MODIFY)) // file was possibly added X+ //IN_CLOSE_WRITE | IN_CLOSE_NOWRITE | IN_MODIFY X+ if (event.fflags & (NOTE_EXIT | NOTE_REVOKE | NOTE_ATTRIB)) // file was possibly added X return 1; X- if (evbuff.mask & (IN_DELETE | IN_MOVED_FROM)) // file was deleted X+ // IN_DELETE | IN_MOVED_FROM X+ if (event.fflags & (NOTE_DELETE)) // file was deleted X return 2; X- if (evbuff.mask & (IN_DELETE_SELF | IN_MOVE_SELF)) // monitored directory gone X- return 3; X+ // IN_DELETE_SELF | IN_MOVE_SELF X+ //if (event.fflags & (IN_DELETE_SELF | IN_MOVE_SELF)) // monitored directory gone X+ // return 3; X return 9; // other X } X } X- X+ X if (strEqu(action,"close")) // stop monitoring X { X- if (fid > -1) retval = close(fid); X+ if (f > -1) retval = close(f); X else retval = -1; X- fid = -1; X+ f = -1; X return retval; X } X- X+ X zappcrash("zmondirk() call error"); X return -1; X } X@@ -865,7 +883,7 @@ X /************************************************************************** X X utility to measure CPU time spent in various functions or code blocks v.2.7 X- X+ X cpu_profile_init() initialize at start of test X cpu_profile_report() report CPU time per function X cpu_profile_enter(fnum) at entry to a function // inline, defined in zfuncs.h X@@ -882,7 +900,7 @@ X { X void * cpu_profile_timekeeper(void *); X X- for (int ii = 0; ii < 99; ii++) X+ for (int ii = 0; ii < 99; ii++) X cpu_profile_table[ii] = 0; X cpu_profile_elapsed = 0; X start_detached_thread(cpu_profile_timekeeper,null); X@@ -915,7 +933,7 @@ X zsleep(0.001); X if (cpu_profile_kill) break; X } X- X+ X cpu_profile_kill = 0; X return 0; X } X@@ -927,33 +945,33 @@ X X cchar * strField(cchar *string, cchar *delim, int Nth) X X- Get the Nth field in input string, which contains at least N fields X+ Get the Nth field in input string, which contains at least N fields X delimited by the character(s) in delim (e.g. blank, comma). X- X+ X Returns a pointer to the found field (actually a pointer to a X copy of the found field, with a null terminator appended). X- X- If a delimiter is immediately followed by another delimiter, it is X+ X+ If a delimiter is immediately followed by another delimiter, it is X considered a field with zero length, and the string "" is returned. X X Leading blanks in a field are omitted from the returned field. X A field with only blanks is returned as a single blank. X X The last field may be terminated by null or a delimiter. X- X- Characters within quotes (") are treated as data within a field, X+ X+ Characters within quotes (") are treated as data within a field, X i.e. blanks and delimiters are not processed as such. X The quotes are removed from the returned field. X X If there are less than N fields, a null pointer is returned. X- X+ X The last 100 fields are saved and recycled in a circular manner. X- The caller does not have to free memory. If more memory depth is X+ The caller does not have to free memory. If more memory depth is X needed, caller must copy the returned data elsewhere. X- X+ X The input string must be < 1000 characters. X The output string may be modified if the length is not increased. X- X+ X Example: input string: ,a,bb, cc, ,dd"ee,ff"ggg, X (first and last characters are comma) X delimiter: comma X@@ -971,12 +989,12 @@ X cchar * strField(cchar *string, cchar *delim, int Nth) X { X static int ftf = 1, nret = 0; X- static char *retf[100]; X+ static char *retf[100]; X char *pf1, pf2[1000]; X cchar quote = '"'; X int ii, nf, fcc = 0; X static char blankstring[2], nullstring[1]; X- X+ X if (ftf) // overall first call X { X ftf = 0; X@@ -990,7 +1008,7 @@ X X pf1 = (char *) string - 1; // start parse X nf = 0; X- X+ X while (nf < Nth) X { X pf1++; // start field X@@ -1008,15 +1026,15 @@ X } X X else if (strchr(delim,*pf1) || *pf1 == 0) break; // found delimiter or null X- X+ X else pf2[fcc++] = *pf1++; // pass normal character X } X X if (*pf1 == 0) break; X } X- X+ X if (nf < Nth) return 0; // no Nth field X- X+ X if (fcc == 0) { // empty field X if (*string && pf1[-1] == ' ' && !strchr(delim,' ')) // all blanks and blank not delim. X return blankstring; // return one blank X@@ -1034,7 +1052,7 @@ X cchar * strField(cchar *string, cchar delim, int Nth) // alternative with one delimiter X { X char delims[2] = "x"; X- X+ X *delims = delim; X return strField(string,delims,Nth); X } X@@ -1046,14 +1064,14 @@ X X Parse an input string with parameter names and values: X "pname1=pval1 | pname2 | pname3=pval3 | pname4 ..." X- X+ X begin int & must be 1 to start new string, is modified X input cchar * input string X pname char * output parameter name X maxcc int max. length for pname, including null X pval double & output parameter value X stat int status: 0=OK, -1=EOL, 1=parse error X- X+ X Each call returns the next pname and pval. X A pname with no pval is assigned a value of 1 (present). X Input format: pname1 | pname2=pval2 | pname3 ... null X@@ -1074,22 +1092,22 @@ X } X X if (begin != beginx) zappcrash("strParms call error"); // thread safe, not reentrant X- X+ X *pname = 0; // initz. outputs to nothing X pval = 0; X- X+ X while (input[ii] == ' ') ii++; // skip leading blanks X if (input[ii] == 0) return -1; // no more data X X pnamex = input + ii; // next pname X- X+ X for (cc = 0; ; cc++) X { // look for delimiter X if (pnamex[cc] == '=') break; X if (pnamex[cc] == '|') break; X if (pnamex[cc] == 0) break; X } X- X+ X if (cc == 0) return 1; // err: 2 delimiters X if (cc >= maxcc) return 1; // err: pname too big X X@@ -1156,7 +1174,7 @@ X X incc = strlen(instring); X if (outcc > 39) zappcrash("strHash2() outcc > 39"); X- X+ X for (ii = 0; ii < outcc; ii++) X { X for (jj = 0; jj < incc; jj++) X@@ -1218,7 +1236,7 @@ X X /**************************************************************************/ X X-// Remove leading and trailing blanks from a string. X+// Remove leading and trailing blanks from a string. X // Returns remaining length, possibly zero. X X int strTrim2(char *dest, cchar *source) // v.2.4 X@@ -1272,7 +1290,7 @@ X /**************************************************************************/ X X // Concatenate multiple strings, staying within a specified overall length. X-// The destination string is also the first source string. X+// The destination string is also the first source string. X // Null marks the end of the source strings (omission --> crash). X // Output is truncated to fit within the specified length. X // A final null is assured and is included in the length. X@@ -1295,7 +1313,7 @@ X if (maxcc < 0) break; X ps = va_arg(arglist,cchar *); X } X- X+ X va_end(arglist); X if (maxcc < 0) return 1; X return 0; X@@ -1386,11 +1404,11 @@ X { X int ccc, cc1, cc2, nfound; X cchar *ppp; // v.2.15 X- X+ X cc1 = strlen(ssin); X cc2 = strlen(ssout); X nfound = 0; X- X+ X while ((ppp = strstr(strin,ssin))) X { X nfound++; X@@ -1411,7 +1429,7 @@ X /**************************************************************************/ X X // like repl_1str, but multiple pairs of substrings are processed X-// (... ssin1, ssout1, ssin2, ssout2, ... null) X+// (... ssin1, ssout1, ssin2, ssout2, ... null) X X int repl_Nstrs(cchar *strin, char *strout, ...) X { X@@ -1419,11 +1437,11 @@ X cchar *ssin, *ssout; X char ftemp[maxfcc]; X int ftf, nfound; X- X+ X ftf = 1; X nfound = 0; X va_start(arglist,strout); X- X+ X while (true) X { X ssin = va_arg(arglist, char *); X@@ -1567,7 +1585,7 @@ X } X strcpy(zdest,source); X return ccs; X-} X+} X X X /**************************************************************************/ X@@ -1582,7 +1600,7 @@ X char char1; X char escapes[] = "abtnvfr"; X int count = 0; X- X+ X while (true) X { X char1 = *pp1++; X@@ -1632,7 +1650,7 @@ X X // Extract a UTF8 substring with a specified count of graphic characters. X // utf8in input UTF8 string X-// utf8out output UTF8 string, which must be long enough X+// utf8out output UTF8 string, which must be long enough X // pos initial graphic character position to get (0 = first) X // cc max. count of graphic characters to get X // returns number of graphic characters extracted, <= cc X@@ -1650,7 +1668,7 @@ X posx++; X } X X- jj = ii; X+ jj = ii; X X for (ccx = 0; ccx < cc && utf8in[jj]; jj++) X { X@@ -1658,12 +1676,12 @@ X while (utf8in[jj+1] < xlimit) jj++; X ccx++; X } X- X+ X kk = jj - ii; X X strncpy(utf8out,utf8in+ii,kk); X utf8out[kk] = 0; X- X+ X return ccx; X } X X@@ -1677,7 +1695,7 @@ X { X cchar *pp; X unsigned char ch1, ch2, nch; X- X+ X for (pp = string; *pp; pp++) X { X ch1 = *pp; X@@ -1727,14 +1745,14 @@ X bitmap functions X ***************************************************************************/ X X-// create a new bitmap with specified bit length. X+// create a new bitmap with specified bit length. X // initially all bits are false. X X bitmap * bitmap_new(int nbits) X { X int cc, ii; X bitmap *bm; X- X+ X bm = (bitmap *) zmalloc(sizeof(bitmap),"bitmap"); // v.3.5 X bm->nbits = nbits; X cc = (nbits + 7) / 8; X@@ -1809,11 +1827,11 @@ X } X X // free memory for variable list X- X+ X void pvlist_free(pvlist *pv) X { X int ii; X- X+ X for (ii = 0; ii < pv->act; ii++) X zfree(pv->list[ii]); X zfree(pv->list); X@@ -1824,7 +1842,7 @@ X // if list if full, first entry is removed and rest are packed down X // return: N >= 0: new entry added at position N X // N = -1: not unique, not added X- X+ X int pvlist_append(pvlist *pv, cchar *entry, int unique) X { X int ii; X@@ -1844,11 +1862,11 @@ X // if list is full, last entry is removed first X // return: N = 0: new entry added at position 0 X // N = -1: not unique, not added X- X+ X int pvlist_prepend(pvlist *pv, cchar *entry, int unique) X { X int ii; X- X+ X if (unique && pvlist_find(pv,entry) >= 0) return -1; // not unique X X if (pv->act == pv->max) pvlist_remove(pv,pv->act-1); // if list full, remove last entry X@@ -1861,7 +1879,7 @@ X } X X // find list entry by name, return -1 if not found X- X+ X int pvlist_find(pvlist *pv, cchar *entry) X { X int ii; X@@ -1873,11 +1891,11 @@ X } X X // remove an entry by name and repack list X- X+ X int pvlist_remove(pvlist *pv, cchar *entry) X { X int ii; X- X+ X ii = pvlist_find(pv,entry); X if (ii < 0) return -1; X pvlist_remove(pv,ii); X@@ -1885,7 +1903,7 @@ X } X X // remove an entry by number and repack list X- X+ X int pvlist_remove(pvlist *pv, int ii) X { X if (ii < 0 || ii >= pv->act) return -1; X@@ -1946,9 +1964,9 @@ X X convIS(inum, string, cc) int to string with returned cc X X- convDS(fnum, digits, string, cc) double to string with specified X+ convDS(fnum, digits, string, cc) double to string with specified X digits of precision and returned cc X- X+ X string input (cchar *) or output (char *) X inum input (int) or output (int &) X dnum input (double) or output (double &) X@@ -1956,8 +1974,8 @@ X low, high input range check (int or double) X cc output string length (int &) X digits input digits of precision (int) to be used for output string X- X- NOTE: decimal point may be comma or period. X+ X+ NOTE: decimal point may be comma or period. X 1000's separators must NOT be present. X X function status returned: X@@ -2092,10 +2110,10 @@ X pch++; X } X X- if ((exp < -36) || (exp > 36)) goto conv_err; // exponent too big X+ if ((exp < -36) || (exp > 36)) goto conv_err; // exponent too big X } X X- if (delim) *delim = pch; // terminating delimiter X+ if (delim) *delim = pch; // terminating delimiter X if (*pch && (*pch != ' ')) tnb++; // not null or blank X X if (!(digits + edigits)) // no digits found X@@ -2108,7 +2126,7 @@ X X if (sign == -1) dnum = - dnum; // negate if negative X X- if (exp) X+ if (exp) X { X if (esign == -1) exp = -exp; // process exponent X dnum = dnum * exponents[exp+37]; X@@ -2147,13 +2165,13 @@ X X X // Convert double to string with specified digits of precision. X-// Shortest length format (f/e) will be used. X+// Shortest length format (f/e) will be used. X // Output length is returned in optional argument cc. X X int convDS(double dnum, int digits, char *string, int *cc) X { X char *pstr; X- X+ X sprintf(string,"%.*g",digits,dnum); X X pstr = strstr(string,"e+"); // 1.23e+12 > 1.23e12 X@@ -2162,7 +2180,7 @@ X pstr = strstr(string,"e0"); // 1.23e02 > 1.23e2 X if (pstr) strcpy(pstr+1,pstr+2); X X- pstr = strstr(string,"e0"); X+ pstr = strstr(string,"e0"); X if (pstr) strcpy(pstr+1,pstr+2); X X pstr = strstr(string,"e-0"); // 1.23e-02 > 1.23e-2 X@@ -2189,9 +2207,9 @@ X cchar *units; X static char output[20]; X double gnum; X- X+ X gnum = fabs(fnum); X- X+ X if (gnum > giga) { X fnum = fnum / giga; X units = "GB"; X@@ -2206,13 +2224,13 @@ X } X else units = "B "; X X- gnum = fabs(fnum); X+ gnum = fabs(fnum); X if (prec == 2 && gnum >= 99.5) prec++; // avoid e+nn formats X if (prec == 3 && gnum >= 999.5) prec++; X if (prec == 4 && gnum >= 9999.5) prec++; X if (prec == 5 && gnum >= 99999.5) prec++; X if (prec == 6 && gnum >= 999999.5) prec++; X- X+ X snprintf(output,20,"%.*g %s",prec,fnum,units); X X return output; X@@ -2223,8 +2241,8 @@ X X Wildcard string match X X- Match candidate string to wildcard string containing any number of X- '*' or '?' wildcard characters. '*' matches any number of characters, X+ Match candidate string to wildcard string containing any number of X+ '*' or '?' wildcard characters. '*' matches any number of characters, X including zero characters. '?' matches any one character. X X Returns 0 if match, 1 if no match. X@@ -2282,30 +2300,30 @@ X in either or both the pathname and filename. X X cchar * SearchWild(cchar *wfilespec, int &flag) X- X+ X inputs: flag = 1 to start a new search X flag = 2 abort a running search X *** do not modify flag within a search *** X X wfilespec = filespec to search with optional wildcards X e.g. "/name1/na*me2/nam??e3/name4*.ext?" X- X+ X return: a pointer to one matching file is returned per call, X or null when there are no more matching files. X- X- The search may be aborted before completion, but make a final X- call with flag = 2 to clean up temp file. A new search with X+ X+ The search may be aborted before completion, but make a final X+ call with flag = 2 to clean up temp file. A new search with X flag = 1 will also finish the cleanup. X- X+ X NOT THREAD SAFE - do not use in parallel threads X- X+ X shell find command is used for the initial search because this X- is much faster than recursive use of readdir() (why?). X+ is much faster than recursive use of readdir() (why?). X X- (#) is used in place of (*) in comments below to prevent X+ (#) is used in place of (*) in comments below to prevent X compiler from interpreting (#/) as end of comments X X- GNU find peculiarities: X+ GNU find peculiarities: X find /path/# omits "." files X find /path/ includes "." files X find /path/# recurses directories under /path/ X@@ -2314,10 +2332,10 @@ X find /path/#/# finds files >= 1 directory level under /path/ X find /path/xxx# never finds anything X X- SearchWild uses simpler and more intuitive matching: X+ SearchWild uses simpler and more intuitive matching: X '/' and '.' are matched by '#' X /path/#.txt finds all .txt files under /path/ at any directory level X- X+ X ***/ X X cchar * SearchWild(cchar *wpath, int &uflag) // use popen() instead of scratch file X@@ -2328,27 +2346,27 @@ X char command[maxfcc]; X int cc, err; X char *pp; X- X+ X if ((uflag == 1) || (uflag == 2)) { // first call or stop flag X if (fid) { X pclose(fid); // if file open, close it X fid = 0; X } X } X- X+ X if (uflag == 2) return 0; // kill flag, done X- X+ X if (uflag == 1) // first call flag X { X cc = strlen(wpath); X if (cc == 0) return 0; X if (cc > maxfcc-20) zappcrash("SearchWild: wpath > maxfcc"); X- X+ X pp = (char *) wpath; X repl_Nstrs(pp,searchpath,"$","\\$","\"","\\\"",null); // init. search path, escape $ and " X X pp = strchr(searchpath,'*'); X- if (pp) { // not efficient but foolproof X+ if (pp) { // not efficient but foolproof X while ((*pp != '/') && (pp > searchpath)) pp--; // /aaa/bbb/cc*cc... >>> /aaa/bbb/ X if (pp > searchpath) *(pp+1) = 0; X } X@@ -2360,7 +2378,7 @@ X } X X if (uflag != 763568954) zappcrash("SearchWild, uflag invalid"); X- X+ X while (true) X { X pp = fgets(matchfile,maxfcc-2,fid); // next matching file X@@ -2436,7 +2454,7 @@ X #define SWAP(x,y) (temp = (x), (x) = (y), (y) = temp) X X X-// heapsort for array of integers X+// heapsort for array of integers X X static void adjust(int vv[], int n1, int n2) X { X@@ -2471,7 +2489,7 @@ X } X X X-// heapsort for array of floats X+// heapsort for array of floats X X static void adjust(float vv[], int n1, int n2) X { X@@ -2508,7 +2526,7 @@ X } X X X-// heapsort for array of doubles X+// heapsort for array of doubles X X static void adjust(double vv[], int n1, int n2) X { X@@ -2621,7 +2639,7 @@ X } X X X-// heapsort for array of strings or records, X+// heapsort for array of strings or records, X // using caller-supplied record compare function. X // HeapSortUcomp returns [ -1 0 +1 ] for rec1 [ < = > ] rec2 X // method: build array of pointers and sort these, then X@@ -2864,7 +2882,7 @@ X X ***/ X X-namespace splinedata X+namespace splinedata X { X int nn; X double px1[100], py1[100], py2[100]; X@@ -2877,7 +2895,7 @@ X X double sig, p, u[100]; X int ii; X- X+ X nn = dnn; X if (nn > 100) zappcrash("spline1(), > 100 data points"); X X@@ -2885,12 +2903,12 @@ X { X px1[ii] = dx1[ii]; X py1[ii] = dy1[ii]; X- if (ii && px1[ii] <= px1[ii-1]) X+ if (ii && px1[ii] <= px1[ii-1]) X zappcrash("spline1(), x-value not increasing"); X } X X py2[0] = u[0] = 0; X- X+ X for (ii = 1; ii < nn-1; ii++) X { X sig = (px1[ii] - px1[ii-1]) / (px1[ii+1] - px1[ii-1]); X@@ -2899,9 +2917,9 @@ X u[ii] = (6 * ((py1[ii+1] - py1[ii]) / (px1[ii+1] - px1[ii]) - (py1[ii] - py1[ii-1]) X / (px1[ii] - px1[ii-1])) / (px1[ii+1] - px1[ii-1]) - sig * u[ii-1]) / p; X } X- X+ X py2[nn-1] = 0; X- X+ X for (ii = nn-2; ii >= 0; ii--) X py2[ii] = py2[ii] * py2[ii+1] + u[ii]; X X@@ -2915,20 +2933,20 @@ X X int kk, klo = 0, khi = nn-1; X double h, a, b, y; X- X+ X while (khi - klo > 1) X { X kk = (khi + klo) / 2; X if (px1[kk] > x) khi = kk; X else klo = kk; X } X- X+ X h = px1[khi] - px1[klo]; X a = (px1[khi] - x) / h; X b = (x - px1[klo]) / h; X- y = a * py1[klo] + b * py1[khi] + ((a*a*a - a) * py2[klo] X+ y = a * py1[klo] + b * py1[khi] + ((a*a*a - a) * py2[klo] X + (b*b*b - b) * py2[khi]) * (h*h) / 6; X- X+ X return y; X } X X@@ -2936,11 +2954,11 @@ X /************************************************************************** X X Initialize application files according to following conventions: X- + use application directories defined by Makefile X+ + use application directories defined by Makefile X + user data files are in /home/user/.appname/ X- + if not already attached to a terminal, redirect stdout/stderr X+ + if not already attached to a terminal, redirect stdout/stderr X to log file at /home/user/.appname/appname.log X- X+ X zappname application name: dcopp, fotoxx, etc. X zdatadir installed data files translations, parameters, etc. X zdocdir user documentation userguide, README, CHANGES X@@ -2968,14 +2986,15 @@ X using namespace zfuncs; X X char work[200], *pp; X+ //passwd *pp; X cchar *appfile; X int err; X FILE *fid; X struct stat statdat; X va_list arglist; X- X+ X catch_signals(); // catch segfault, backtrace v.2.22 X- X+ X strcpy(zappname,appname); X X strcpy(zdatadir,DATADIR); // macros from build script X@@ -2983,7 +3002,7 @@ X strcpy(zicondir,zdatadir); X strcat(zicondir,"/icons"); X X- pp = cuserid(0); X+ pp = getlogin(); //getpwuid(); //cuserid(0); X if (strEqu(pp,"root")) snprintf(zuserdir,199,"/root/.%s",zappname); // get /root/.appname X else snprintf(zuserdir,199,"%s/.%s",getenv("HOME"),zappname); // or /home/user/.appname X X@@ -2994,7 +3013,7 @@ X if (err) zappcrash("%s, %s \n",wstrerror(err),work); // cannot X X va_start(arglist,appname); // copy req. application files X- while (true) { // from install directory to X+ while (true) { // from install directory to X appfile = va_arg(arglist, cchar *); // to /home/user/.appname/ X if (! appfile) break; X snprintf(work,199,"cp %s/%s %s",zdatadir,appfile,zuserdir); X@@ -3004,13 +3023,13 @@ X va_end(arglist); X } X X- if (! isatty(1)) { X+ if (! isatty(1)) { X snprintf(work,199,"%s/%s.log",zuserdir,zappname); // if not attached to a terminal, X fid = freopen(work,"w",stdout); // redirect output to log file X fid = freopen(work,"w",stderr); // /home/user/.appname/appname.log X printf("\n""%s message and error log \n",zappname); // append to old file v.2.5 X } X- X+ X zlockInit(); // initz. for GTK thread lock v.3.8 X X return 1; X@@ -3048,7 +3067,7 @@ X zmessageACK(null,ZTX("help file not found: %s"),docfile); // give up X return; X } X- X+ X if (context && *context) // v.3.7 X strncatv(docfile,199,"#",context,null); // file://.../userguide-xx.html#context X snprintf(url,199,"file://%s",docfile); X@@ -3102,14 +3121,14 @@ X char dtfile[200], work[200]; X FILE *fid; X int err; X- X+ X snprintf(dtfile,199,"%s/Desktop/kornelix-%s.desktop",getenv("HOME"),zappname); X fid = fopen(dtfile,"w"); X if (! fid) { X zmessageACK(null,ZTX("error: %s"),strerror(errno)); X return; X } X- X+ X fputs("[Desktop Entry]\n",fid); X snprintf(work,199,"Name=%s\n",zappname); X fputs(work,fid); X@@ -3124,7 +3143,7 @@ X snprintf(work,199,"GenericName=%s\n",genericname); X fputs(work,fid); X fclose(fid); X- X+ X snprintf(work,199,"xdg-desktop-menu install %s",dtfile); X err = system(work); X if (err) zmessLogACK(null,"error: %s",wstrerror(err)); X@@ -3140,7 +3159,7 @@ X /************************************************************************** X X Translation Functions v.2.9 revised to use .po files X- X+ X Translation files are standard .po files as used in the Gnu gettext X system. However the .po files are used directly, and there is no need X to merge and compile them into a binary format (.mo files). X@@ -3154,27 +3173,27 @@ X both sets, the regional dialect (lc_RC) will be used. X X Translate a text string: cchar * ZTX(cchar *english) X- english: text string to translate, possibly containing X+ english: text string to translate, possibly containing X printf formats (%d %s ...) and escaped characters (\" \n ...). X X- If the user language is English or if no translation is found, X+ If the user language is English or if no translation is found, X the input string is returned, else the translated string. X- X+ X A text string may have a context part "context::string", where X- "context" is any string < 30 characters and "string" is the X- English text or the translation text. The context part "context::" X- is removed in the returned string. This is to handle the case where X- a single English string may need multiple translations, depending X- on context. The English string may be present multiple times in a X- .po file, each one marked with a different context and having a X+ "context" is any string < 30 characters and "string" is the X+ English text or the translation text. The context part "context::" X+ is removed in the returned string. This is to handle the case where X+ a single English string may need multiple translations, depending X+ on context. The English string may be present multiple times in a X+ .po file, each one marked with a different context and having a X different translation. Context is optional in translation strings. X- X- example: X- X- program code: X+ X+ example: X+ X+ program code: X X printf(ZTX("answer: %d %s \n more on next line"), 123, "qwerty"); X- X+ X A German .po file would have the following entry: X X msgid: "answer: %d %s \n" X@@ -3192,7 +3211,7 @@ X int ent, scc; X void ZTXread_pofiles(); X void ZTXgetstring(); X- char **ZTXenglish = null; // English strings and X+ char **ZTXenglish = null; // English strings and X char **ZTXtrans = null; // corresp. translations X } X X@@ -3218,7 +3237,7 @@ X if (! blank_null(lang)) strncpy0(zlanguage,lang,6); // use language from caller X else { // help Linux chaos v.2.9.1 X pp = getenv("LANG"); // use $LANG if defined X- if (! pp) pp = getenv("LANGUAGE"); // use $LANGUAGE if defined X+ if (! pp) pp = getenv("LANGUAGE"); // use $LANGUAGE if defined X if (! pp) pp = setlocale(LC_MESSAGES,""); // use locale if defined X if (pp) strncpy0(zlanguage,pp,6); // "lc_RC" lang/region codes v.2.14 X else strcpy(zlanguage,"en"); // use English X@@ -3234,7 +3253,7 @@ X ent = 0; X X strncpy0(lc_RC,zlanguage,6); // process .../locales/lc_RC/*.po X- if (strlen(lc_RC) > 3 && strNeq(lc_RC,"en_US")) X+ if (strlen(lc_RC) > 3 && strNeq(lc_RC,"en_US")) X ZTXread_pofiles(); X X strncpy0(lc_RC,zlanguage,3); // process .../locales/lc/*.po X@@ -3262,7 +3281,7 @@ X zfree(pofile); X continue; X } X- X+ X porec = 0; // no .po record yet X *Estring = *Tstring = 0; // no strings yet X X@@ -3270,7 +3289,7 @@ X { X if (! porec) porec = fgets_trim(buff,ZTXmaxcc,fid); // get next .po record X if (! porec) break; // EOF X- X+ X if (blank_null(porec)) { // blank record X porec = 0; X continue; X@@ -3317,7 +3336,7 @@ X pstring = Tstring; X scc = 0; X ZTXgetstring(); X- X+ X if (! *Tstring) { X if (*Estring) printf(" no translation: %s \n",Estring); X *Estring = *Tstring = 0; X@@ -3327,14 +3346,14 @@ X *Estring = *Tstring = 0; X } X } X- X+ X else X { X printf(" unrecognized input record: %s \n",porec); X porec = 0; X continue; X } X- X+ X if (*Estring && *Tstring) X { X if (ent == ZTXmaxent) X@@ -3351,7 +3370,7 @@ X fclose(fid); X zfree(pofile); X } X- X+ X return; X } X X@@ -3382,7 +3401,7 @@ X } X porec = ppq2 + 1; X } X- X+ X return; X } X X@@ -3391,7 +3410,7 @@ X // Look for "context::string" and return "string" only if context found. X // X // This function is not efficient: may need a few microseconds. X-// This can be improved if needed by sorting the english strings and X+// This can be improved if needed by sorting the english strings and X // using a binary search (1000 strings >> 10 compares instead of 1-1000). X X cchar * ZTX(cchar *english) X@@ -3399,12 +3418,12 @@ X using namespace ZTXnames; X X cchar *pp, *pp2; X- X+ X if (! english) return 0; X X pp = 0; X X- if (ZTXtrans) X+ if (ZTXtrans) X { X for (int ii = 0; ZTXenglish[ii]; ii++) // find translation X { X@@ -3414,9 +3433,9 @@ X } X } X } X- X+ X if (! pp) pp = english; X- X+ X for (pp2 = pp; *pp2 && pp2 < pp+30; pp2++) // remove context if present v.2.11 X if (*pp2 == ':' && *(pp2+1) == ':') return pp2+2; X X@@ -3446,7 +3465,7 @@ X zinit++; X X for (int ii = 0; ii < tmax; ii++) { X- tids[ii] = 0; X+ tids[ii] = 0; X tlocks[ii] = 0; X } X return; X@@ -3521,7 +3540,7 @@ X { X static int xskip = 0; X pthread_t tid_me; X- X+ X if (! zinit) zappcrash("zmainloop(): zinit() not done"); X X if (skip) { X@@ -3532,7 +3551,7 @@ X tid_me = pthread_self(); X if (! pthread_equal(tid_main,tid_me)) return; // not main() X X- while (gtk_events_pending()) gtk_main_iteration(); X+ while (gtk_events_pending()) gtk_main_iteration(); X return; X } X X@@ -3552,14 +3571,14 @@ X GtkTextIter iter1, iter2; X GtkTextTag *fontag = 0; X int nlines, scroll = 0; X- X+ X if (! mLog) { // if no GUI use STDOUT v.3.0 X printf("%s",message); X return; X } X- X+ X zlock(); X- X+ X textBuff = gtk_text_view_get_buffer(GTK_TEXT_VIEW(mLog)); X X endMark = gtk_text_buffer_get_mark(textBuff,"wpxend"); // get my end mark X@@ -3577,17 +3596,17 @@ X line = nlines + line + 1; // last lines: -1, -2 ... X if (line < 1) line = 1; // above top, use line 1 X } X- X+ X if (line > nlines) line = 0; // below bottom, treat as append X X if (line == 0) gtk_text_buffer_get_end_iter(textBuff,&iter1); // append new line X- X+ X if (line > 0) { X gtk_text_buffer_get_iter_at_line(textBuff,&iter1,line-1); // old line start X if (line < nlines) X gtk_text_buffer_get_iter_at_line(textBuff,&iter2,line); // old line end X if (line == nlines) // or buffer end X- gtk_text_buffer_get_end_iter(textBuff,&iter2); X+ gtk_text_buffer_get_end_iter(textBuff,&iter2); X gtk_text_buffer_delete(textBuff,&iter1,&iter2); // delete old line X } X X@@ -3600,7 +3619,7 @@ X X if (scroll) // scroll line into view X gtk_text_view_scroll_to_mark(GTK_TEXT_VIEW(mLog),endMark,0,0,1,1); X- X+ X zunlock(); X return; X } X@@ -3643,7 +3662,7 @@ X { X GtkTextBuffer *textbuff; X GtkTextIter iter; X- X+ X if (! mLog) return; // v.3.0 X X zlock(); X@@ -3705,9 +3724,9 @@ X GtkTextIter iter1, iter2; X static char *precs = 0, *prec1, *pret; X static int cc; X- X+ X if (! mLog) return 0; // v.3.0 X- X+ X if (ftf) X { // get all window text X ftf = 0; X@@ -3719,7 +3738,7 @@ X prec1 = precs; // 1st record X zunlock(); X } X- X+ X if (! precs || (*prec1 == 0)) // no more records X { X if (precs) g_free(precs); X@@ -3753,13 +3772,13 @@ X if (! mLog) return 0; // v.3.0 X X fid = fopen(filespec,"w"); // open file X- if (! fid) { X+ if (! fid) { X zmessageACK(null,ZTX("cannot open file %s"),filespec); X- return 1; X+ return 1; X } X- X+ X wfiledump_maxcc = 0; X- X+ X ftf = 1; X while (true) X { X@@ -3769,7 +3788,7 @@ X cc = strlen(prec); X if (cc > wfiledump_maxcc) wfiledump_maxcc = cc; X } X- X+ X err = fclose(fid); // close file X if (err) { zmessageACK(null,"file close error"); return 2; } X else return 0; X@@ -3844,7 +3863,7 @@ X { X GtkWidget *wmbar; X X- wmbar = gtk_menu_bar_new(); X+ wmbar = gtk_menu_bar_new(); X gtk_box_pack_start(GTK_BOX(vbox),wmbar,0,0,0); X return wmbar; X } X@@ -3905,7 +3924,7 @@ X if (vert) gtk_toolbar_set_orientation(GTK_TOOLBAR(wtbar),GTK_ORIENTATION_VERTICAL); X gtk_box_pack_start(GTK_BOX(vbox),wtbar,0,0,0); X tbIconSize = iconsize; X- X+ X if (! tbTooltips) tbTooltips = gtk_tooltips_new(); X return wtbar; X } X@@ -3923,10 +3942,10 @@ X GtkWidget *wicon = 0; X char iconpath[200]; X X- if (icon == null || *icon == 0) X+ if (icon == null || *icon == 0) X tbutton = gtk_tool_button_new(0,0); X X- else if (strnEqu(icon,"gtk-",4)) X+ else if (strnEqu(icon,"gtk-",4)) X tbutton = gtk_tool_button_new_from_stock(icon); X X else { X@@ -3954,7 +3973,7 @@ X GtkWidget *stbar; X static PangoFontDescription *fontdesc; X X- stbar = gtk_statusbar_new(); X+ stbar = gtk_statusbar_new(); X fontdesc = pango_font_description_from_string("Monospace 9"); X gtk_widget_modify_font(stbar,fontdesc); // *** GTK does not work *** X gtk_box_pack_start(GTK_BOX(pbox),stbar,0,0,0); X@@ -4014,9 +4033,9 @@ X if (! bulab[nbu]) break; X } X va_end(arglist); X- X+ X zlock(); X- X+ X dialog = gtk_dialog_new(); // attributes optional v.3.3 X if (title) gtk_window_set_title(GTK_WINDOW(dialog),title); X if (parent) gtk_window_set_transient_for(GTK_WINDOW(dialog),GTK_WINDOW(parent)); X@@ -4046,7 +4065,7 @@ X zd->compbutt[ii] = butt; // save button widgets X } X } X- X+ X zunlock(); X X zd->sentinel = zdsentinel; // validity sentinel X@@ -4081,7 +4100,7 @@ X int iiw, iip, kk, err; X X static PangoFontDescription *monofont = 0; X- X+ X if (! zd) zappcrash("zdialog null pointer"); // detect destroyed dialog v.2.2 X if (zd->sentinel != zdsentinel) zappcrash("zdialog invalid"); X X@@ -4112,10 +4131,10 @@ X X pwidget = zd->widget[iip].widget; // parent widget, type X ptype = zd->widget[iip].type; X- X+ X if (strcmpv(ptype,"dialog","hbox","vbox","frame","scrwin",null) == 0) X zappcrash("zdialog, bad widget parent type: %s",ptype); X- X+ X zlock(); X X if (! monofont) monofont = pango_font_description_from_string("Monospace"); X@@ -4125,7 +4144,7 @@ X X if (strEqu(type,"hsep")) widget = gtk_hseparator_new(); // horiz. & vert. separators X if (strEqu(type,"vsep")) widget = gtk_vseparator_new(); X- X+ X if (strEqu(type,"frame")) { // frame around contained widgets X widget = gtk_frame_new(data); X gtk_frame_set_shadow_type(GTK_FRAME(widget),GTK_SHADOW_IN); X@@ -4146,7 +4165,7 @@ X gtk_widget_modify_font(widget,monofont); X G_SIGNAL(widget,"changed",zdialog_widget_event,zd) X } X- X+ X if (strEqu(type,"edit")) { // multiline edit box X widget = gtk_text_view_new(); X editBuff = gtk_text_view_get_buffer(GTK_TEXT_VIEW(widget)); X@@ -4156,7 +4175,7 @@ X gtk_widget_modify_font(widget,monofont); X G_SIGNAL(editBuff,"changed",zdialog_widget_event,zd) // buffer signals, not widget X } X- X+ X if (strEqu(type,"button")) { // button X widget = gtk_button_new_with_label(data); X G_SIGNAL(widget,"clicked",zdialog_widget_event,zd) X@@ -4172,7 +4191,7 @@ X else widget = gtk_check_button_new(); X G_SIGNAL(widget,"toggled",zdialog_widget_event,zd) X } X- X+ X if (strEqu(type,"combo")) { // combo box X widget = gtk_combo_box_new_text(); X zd->widget[iiw].cblist = pvlist_create(zdcbmax); // for drop-down list X@@ -4196,14 +4215,14 @@ X gtk_widget_modify_font(widget,monofont); X G_SIGNAL(widget,"changed",zdialog_widget_event,zd) X } X- X+ X if (strEqu(type,"radio")) { // radio button X- for (kk = iip+1; kk <= iiw; kk++) X+ for (kk = iip+1; kk <= iiw; kk++) X if (strEqu(zd->widget[kk].pname,pname) && // find first radio button X strEqu(zd->widget[kk].type,"radio")) break; // with same container X- if (kk == iiw) X+ if (kk == iiw) X widget = gtk_radio_button_new_with_label(null,data); // this one is first X- else X+ else X widget = gtk_radio_button_new_with_label_from_widget // not first, add to group X (GTK_RADIO_BUTTON(zd->widget[kk].widget),data); X G_SIGNAL(widget,"toggled",zdialog_widget_event,zd) X@@ -4234,7 +4253,7 @@ X sprintf(vdata,"%g",val); X data = vdata; X } X- X+ X if (strEqu(type,"colorbutt")) { // color edit button v.2.17 X if (! data) data = "0|0|0"; // data format: "nnn|nnn|nnn" = RGB X pp = strField(data,'|',1); gdkcolor.red = 256 * atoi(pp); X@@ -4243,7 +4262,7 @@ X widget = gtk_color_button_new_with_color(&gdkcolor); X G_SIGNAL(widget,"color-set",zdialog_widget_event,zd) X } X- X+ X // all widget types come here X X zd->widget[iiw].widget = widget; // set widget in zdialog X@@ -4257,7 +4276,7 @@ X if (strEqu(ptype,"dialog")) // add to dialog box X gtk_box_pack_start(GTK_BOX(GTK_DIALOG(pwidget)->vbox), X widget,expand,expand,space); X- if (data) X+ if (data) X zd->widget[iiw].data = strdupz(data,0,"zdialog.data"); // use heap memory v.3.5 X X zunlock(); X@@ -4268,13 +4287,13 @@ X // add widget to existing zdialog - alternative form (clearer and easier code) X // options: "scc=nn | homog | expand | space=nn" (all optional, any order) X X-int zdialog_add_widget(zdialog *zd, cchar *type, cchar *name, X- cchar *parent, cchar *data, cchar *options) X+int zdialog_add_widget(zdialog *zd, cchar *type, cchar *name, X+ cchar *parent, cchar *data, cchar *options) X { X int stat, scc = 0, homog = 0, expand = 0, space = 0, begin = 1; X char pname[8]; X double pval; X- X+ X while (true) X { X stat = strParms(begin,options,pname,8,pval); X@@ -4286,7 +4305,7 @@ X else if (strEqu(pname,"space")) space = (int(pval)); X else zappcrash("bad zdialog options: %s",options); X } X- X+ X stat = zdialog_add_widget(zd,type,name,parent,data,scc,homog,expand,space); X return stat; X } X@@ -4321,7 +4340,7 @@ X if (! glist) zappcrash("no radio button group"); X X va_start(arglist,radio1); X- X+ X while (true) X { X radio2 = va_arg(arglist,cchar *); X@@ -4329,7 +4348,7 @@ X widget = zdialog_widget(zd,radio2); X gtk_radio_button_set_group(GTK_RADIO_BUTTON(widget),glist); X } X- X+ X va_end(arglist); X X zunlock(); X@@ -4364,16 +4383,16 @@ X cchar *type, *pname, *pp; X char *wdata; X double val; X- X+ X if (! zd || zd->sentinel != zdsentinel) { // detect destroyed dialog v.2.2 X printf("zdialog_put_data(%s,%s), zdialog invalid \n",name,data); X return 0; X } X- X+ X for (iiw = 1; zd->widget[iiw].type; iiw++) // find widget X if (strEqu(zd->widget[iiw].name,name)) break; X if (! zd->widget[iiw].type) return 0; X- X+ X type = zd->widget[iiw].type; X widget = zd->widget[iiw].widget; X pname = zd->widget[iiw].pname; X@@ -4388,15 +4407,15 @@ X if (utf8_check(wdata)) X printf("zdialog: bad UTF8 encoding %s \n",wdata); // v.2.4 X } X- X+ X zd->disabled++; // disable for widget stuffing v.2.9 X X zlock(); X X- if (strEqu(type,"label")) X+ if (strEqu(type,"label")) X gtk_label_set_text(GTK_LABEL(widget),data); X X- if (strEqu(type,"entry")) X+ if (strEqu(type,"entry")) X gtk_entry_set_text(GTK_ENTRY(widget),data); X X if (strEqu(type,"button")) // change button label v.2.21 X@@ -4406,8 +4425,8 @@ X textBuff = gtk_text_view_get_buffer(GTK_TEXT_VIEW(widget)); X gtk_text_buffer_set_text(textBuff,data,-1); X } X- X- if (strcmpv(type,"togbutt","check","radio",null)) X+ X+ if (strcmpv(type,"togbutt","check","radio",null)) X { X if (! data) kk = nn = 0; X else kk = convSI(data,nn); X@@ -4421,23 +4440,23 @@ X if (kk != 0) val = 0.0; X gtk_spin_button_set_value(GTK_SPIN_BUTTON(widget),val); X } X- X+ X if (strEqu(type,"colorbutt")) { // color button v.2.17 X- pp = strField(data,'|',1); X+ pp = strField(data,'|',1); X if (pp) gdkcolor.red = 256 * atoi(pp); // bugfix v.3.8 X- pp = strField(data,'|',2); X+ pp = strField(data,'|',2); X if (pp) gdkcolor.green = 256 * atoi(pp); X- pp = strField(data,'|',3); X+ pp = strField(data,'|',3); X if (pp) gdkcolor.blue = 256 * atoi(pp); X gtk_color_button_set_color(GTK_COLOR_BUTTON(widget),&gdkcolor); X } X- X+ X if (strcmpv(type,"hscale","vscale",null)) { X kk = convSD(data,val); X if (kk != 0) val = 0.0; X gtk_range_set_value(GTK_RANGE(widget),val); X } X- X+ X if (strEqu(type,"combo")) { X if (! blank_null(data)) { X kk = pvlist_prepend(zd->widget[iiw].cblist,data,1); // add to drop-down list X@@ -4473,7 +4492,7 @@ X if (zd->sentinel != zdsentinel) return 0; X X for (int ii = 1; zd->widget[ii].type; ii++) X- if (strEqu(zd->widget[ii].name,name)) X+ if (strEqu(zd->widget[ii].name,name)) X return zd->widget[ii].data; X return 0; X } X@@ -4488,7 +4507,7 @@ X X int ii; X GtkWidget *widget, *dialog; X- X+ X if (! zd) zappcrash("zdialog null pointer"); // detect destroyed dialog v.2.2 X if (zd->sentinel != zdsentinel) zappcrash("zdialog invalid"); X X@@ -4517,7 +4536,7 @@ X G_SIGNAL(dialog,"key-press-event",zdialog_KBpress,zd) // connect KB events v.2.26 X G_SIGNAL(dialog,"key-release-event",zdialog_KBrelease,zd) X G_SIGNAL(dialog,"response",zdialog_response_event,zd); // connect dialog response function X- X+ X if (zd->disabled) zd->disabled--; // enable widget events v.2.23 X X zunlock(); X@@ -4546,11 +4565,11 @@ X X if (! zd) zappcrash("zdialog null pointer"); // detect destroyed dialog v.2.2 X if (zd->sentinel != zdsentinel) zappcrash("zdialog invalid"); X- X+ X for (ii = 0; ii < zdmaxbutts; ii++) // check completion buttons v.3.5 X if (zd->compbutt[ii] == widget) break; X if (ii < zdmaxbutts) { X- zd->zstat = ii+1; // zdialog status = button no. X+ zd->zstat = ii+1; // zdialog status = button no. X if (zd->eventCB) { X evfunc = (zdialog_event *) zd->eventCB; // do callback function X evfunc(zd,"zstat"); X@@ -4584,13 +4603,13 @@ X X if (strEqu(type,"entry")) X wdata = gtk_entry_get_text(GTK_ENTRY(widget)); X- X+ X if (strEqu(type,"edit")) { X gtk_text_buffer_get_bounds(textBuff,&iter1,&iter2); X wdata = gtk_text_buffer_get_text(textBuff,&iter1,&iter2,0); X } X X- if (strcmpv(type,"radio","check","togbutt",null)) X+ if (strcmpv(type,"radio","check","togbutt",null)) X { X nn = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); X if (nn == 0) wdata = "0"; X@@ -4616,35 +4635,35 @@ X } X } X } X- X+ X if (strEqu(type,"spin")) X { X dval = gtk_spin_button_get_value(GTK_SPIN_BUTTON(widget)); X sprintf(sdata,"%g",dval); X wdata = sdata; X } X- X+ X if (strEqu(type,"colorbutt")) // color button v.2.17 X { X gtk_color_button_get_color(GTK_COLOR_BUTTON(widget),&gdkcolor); X sprintf(sdata,"%d|%d|%d",gdkcolor.red/256,gdkcolor.green/256,gdkcolor.blue/256); X wdata = sdata; X } X- X+ X if (strcmpv(type,"hscale","vscale",null)) X { X dval = gtk_range_get_value(GTK_RANGE(widget)); X sprintf(sdata,"%g",dval); X wdata = sdata; X } X- X+ X // all widgets come here X X if (zd->widget[ii].data) zfree(zd->widget[ii].data); // clear prior data X zd->widget[ii].data = 0; X X if (wdata) zd->widget[ii].data = strdupz(wdata,0,"zdialog.data"); // set new data v.3.5 X- X+ X lastwidget = widget; // remember last widget updated X X if (zd->eventCB) { X@@ -4744,7 +4763,7 @@ X { X if (! zd) return 0; // detect destroyed dialog v.2.2 X if (zd->sentinel != zdsentinel) return 0; X- X+ X if (zd->zstat < 0) // destroyed by [x] button or GTK X zd->widget[0].widget = 0; // assume GTK dialog is gone X X@@ -4753,7 +4772,7 @@ X gtk_widget_destroy(zd->widget[0].widget); // destroy GTK dialog X zd->widget[0].widget = 0; X zunlock(); X- X+ X if (! zd->zstat) zd->zstat = -1; // status = destroyed v.3.5 X return 1; X } X@@ -4765,7 +4784,7 @@ X { X if (! zd) return 0; // detect destroyed dialog v.2.2 X if (zd->sentinel != zdsentinel) return 0; X- X+ X zdialog_destroy(zd); // destroy GTK dialog if there X zd->sentinel = 0; // mark invalid v.2.2 X zfree(zd->widget[0].data); // bugfix memory leak v.3.5 X@@ -4777,9 +4796,9 @@ X zfree((char *) zd->widget[ii].type); // free strings X zfree((char *) zd->widget[ii].name); X zfree((char *) zd->widget[ii].pname); X- if (zd->widget[ii].data) zfree(zd->widget[ii].data); // free data X+ if (zd->widget[ii].data) zfree(zd->widget[ii].data); // free data X } X- X+ X zfree(zd); // free zdialog memory X zd = 0; // clear pointer v.3.9 X return 1; X@@ -4807,8 +4826,8 @@ X X int zdialog_goto(zdialog *zd, cchar *name) // v.2.23 X { X- GtkWidget *widget; X- X+ GtkWidget *widget; X+ X if (zd->sentinel != zdsentinel) return 0; X widget = zdialog_widget(zd, name); X if (! widget) return 0; X@@ -4827,7 +4846,7 @@ X void zdialog_set_cursor(zdialog *zd, GdkCursor *cursor) // v.3.8 X { X GtkWidget *dialog; X- X+ X if (zd->sentinel != zdsentinel) return; X dialog = zd->widget[0].widget; X if (! dialog) return; X@@ -4856,7 +4875,7 @@ X int zdialog_stuff(zdialog *zd, cchar *name, double ddata) // stuff a double X { X char string[32]; X- X+ X snprintf(string,31,"%g",ddata); // outputs decimal point or comma X zdialog_put_data(zd,name,string); // (per locale) X return 1; X@@ -4871,7 +4890,7 @@ X *data = 0; X return 0; X } X- X+ X return strncpy0(data,zdata,maxcc); // 0 = OK, 1 = truncation v.2.4 X } X X@@ -4884,7 +4903,7 @@ X idata = 0; X return 0; X } X- X+ X idata = atoi(zdata); X return 1; X } X@@ -4899,7 +4918,7 @@ X ddata = 0; X return 0; X } X- X+ X stat = convSD(zdata,ddata); // period or comma decimal point OK X if (stat < 4) return 1; X return 0; X@@ -4916,7 +4935,7 @@ X fdata = 0; X return 0; X } X- X+ X stat = convSD(zdata,ddata); // period or comma decimal point OK X fdata = ddata; X if (stat < 4) return 1; X@@ -4934,7 +4953,7 @@ X if (zd->sentinel != zdsentinel) zappcrash("zdialog invalid"); X X if (blank_null(data)) return 0; // find widget X- for (ii = 1; zd->widget[ii].type; ii++) X+ for (ii = 1; zd->widget[ii].type; ii++) X if (strEqu(zd->widget[ii].name,name)) break; X if (! zd->widget[ii].type) return 0; // not found X if (! strcmpv(zd->widget[ii].type,"combo","comboE",null)) return 0; // not combo box X@@ -4960,7 +4979,7 @@ X if (zd->sentinel != zdsentinel) zappcrash("zdialog invalid"); X X if (blank_null(data)) return 0; // find widget X- for (ii = 1; zd->widget[ii].type; ii++) X+ for (ii = 1; zd->widget[ii].type; ii++) X if (strEqu(zd->widget[ii].name,name)) break; X if (! zd->widget[ii].type) return 0; // not found X if (! strcmpv(zd->widget[ii].type,"combo","comboE",null)) return 0; // not combo box X@@ -5046,7 +5065,7 @@ X if (strEqu(zd->widget[ii].type,"comboE")) // stuff entry box with nothing X gtk_entry_set_text(GTK_ENTRY(GTK_BIN(zd->widget[ii].widget)->child),""); X X- zunlock(); X+ zunlock(); X return 0; X } X X@@ -5087,26 +5106,26 @@ X X zlock(); X X- if (! monofont) X+ if (! monofont) X monofont = pango_font_description_from_string("monospace 8"); X- X+ X if (strEqu(action,"open")) X { X if (mWin) gtk_widget_destroy(mWin); // only one at a time X X if (! ww) ww = 400; X if (! hh) hh = 300; X- X+ X mWin = gtk_window_new(GTK_WINDOW_TOPLEVEL); // create main window X gtk_window_set_title(GTK_WINDOW(mWin),text); X gtk_window_set_default_size(GTK_WINDOW(mWin),ww,hh); X X if (parent) // parent added v.3.3 X gtk_window_set_transient_for(GTK_WINDOW(mWin),GTK_WINDOW(parent)); X- X+ X if (parent) // v.3.7 X gtk_window_set_position(GTK_WINDOW(mWin),GTK_WIN_POS_CENTER_ON_PARENT); X- else X+ else X gtk_window_set_position(GTK_WINDOW(mWin),GTK_WIN_POS_MOUSE); X X mVbox = gtk_vbox_new(0,0); // vertical packing box X@@ -5122,7 +5141,7 @@ X G_SIGNAL(mWin,"destroy",write_popup_text,"destroypop"); // connect window destroy event X gtk_widget_show_all(mWin); // show window X } X- X+ X if (strEqu(action,"write")) // add text to window X if (mWin) wprintf(mLog," %s\n",text); X X@@ -5130,8 +5149,8 @@ X if (mWin) gtk_widget_destroy(mWin); X mWin = 0; X } X- X- if (text && strEqu(text,"destroypop")) // "destroy" signal from [x] X+ X+ if (text && strEqu(text,"destroypop")) // "destroy" signal from [x] X mWin = 0; X X zunlock(); X@@ -5147,7 +5166,7 @@ X { X char *buff; X int err, contx = 0; X- X+ X write_popup_text("open",command,ww,hh,parent); // bugfix v.3.8 X X while ((buff = command_output(contx,command))) X@@ -5155,7 +5174,7 @@ X write_popup_text("write",buff); X zfree(buff); X } X- X+ X err = command_status(contx); X return err; X } X@@ -5174,7 +5193,7 @@ X va_start(arglist,pMess); X vsnprintf(message,400,pMess,arglist); X va_end(arglist); X- X+ X zd = zdialog_new("",parent," X ",null); // v.3.9 X zdialog_add_widget(zd,"hbox","hb1","dialog",0,"space=5"); X zdialog_add_widget(zd,"label","lab1","hb1",message,"space=5"); X@@ -5198,11 +5217,11 @@ X va_start(arglist,pMess); X vsnprintf(message,200,pMess,arglist); X va_end(arglist); X- X+ X printf("%s \n",message); X zmessageACK(parent,message); X return; X-} X+} X X X /**************************************************************************/ X@@ -5219,7 +5238,7 @@ X va_start(arglist,pMess); X vsnprintf(message,400,pMess,arglist); X va_end(arglist); X- X+ X zd = zdialog_new("message",parent,ZTX("Yes"),ZTX("No"),null); X zdialog_add_widget(zd,"hbox","hb1","dialog",0,"space=5"); X zdialog_add_widget(zd,"label","lab1","hb1",message,"space=5"); X@@ -5250,9 +5269,9 @@ X vsnprintf(message,400,pmess,arglist); X va_end(arglist); X X- if (zmessage_help_topic) zfree(zmessage_help_topic); X+ if (zmessage_help_topic) zfree(zmessage_help_topic); X zmessage_help_topic = strdupz(topic,0,"showz_help_topic"); X- X+ X zd = zdialog_new("context help",parent,"Help"," X ",null); X zdialog_add_widget(zd,"hbox","hb1","dialog",0,"space=5"); X zdialog_add_widget(zd,"label","lab1","hb1",message,"space=5"); X@@ -5290,7 +5309,7 @@ X va_start(arglist,pMess); X vsnprintf(message,400,pMess,arglist); X va_end(arglist); X- X+ X zd = zdialog_new("message",parent,ZTX("cancel"),null); X zdialog_add_widget(zd,"hbox","hb1","dialog",0,"space=5"); X zdialog_add_widget(zd,"label","lab1","hb1",message,"space=5"); X@@ -5316,7 +5335,7 @@ X zdialog *zd; X int zstat; X char *text; X- X+ X zd = zdialog_new(title,parent,"OK",ZTX("cancel"),null); X zdialog_add_widget(zd,"frame","fred","dialog"); X zdialog_add_widget(zd,"edit","edit","fred"); X@@ -5325,7 +5344,7 @@ X zdialog_resize(zd,200,0); // v.3.7 X zdialog_run(zd); X zstat = zdialog_wait(zd); X- if (zstat == 1) X+ if (zstat == 1) X text = strdupz(zdialog_get_data(zd,"edit"),0,"zdialog_text"); // bugfix v.3.7 X else text = 0; X zdialog_free(zd); X@@ -5390,7 +5409,7 @@ X int fcstat, bcode = 0, qnum, hide = 0; X char *qual, *file1, *file2, **flist = 0; X struct stat fstat; X- X+ X zthreadcrash(); // thread usage not allowed v.3.9 X X if (strEqu(action,"open")) { X@@ -5417,25 +5436,25 @@ X fcact = GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER; X button1 = ZTX("create folder"); X } X- X+ X if (buttx) { X if (strnEqu(buttx,"hidden",6)) bcode = 103; X if (strEqu(buttx,"quality")) bcode = 104; X fakeit = ZTX("hidden"); // generate text for translation X fakeit = ZTX("quality"); X } X- X+ X dialog = gtk_file_chooser_dialog_new(title, null, fcact, // create file selection dialog X- button1, GTK_RESPONSE_ACCEPT, X- ZTX("cancel"), GTK_RESPONSE_CANCEL, X+ button1, GTK_RESPONSE_ACCEPT, X+ ZTX("cancel"), GTK_RESPONSE_CANCEL, X ZTX(buttx), bcode, null); X X- gtk_file_chooser_set_preview_widget(GTK_FILE_CHOOSER(dialog),pvwidget); X+ gtk_file_chooser_set_preview_widget(GTK_FILE_CHOOSER(dialog),pvwidget); X X G_SIGNAL(dialog,"update-preview",zgetfile_preview,pvwidget); // create preview for selected file X G_SIGNAL(dialog,"current-folder-changed",zgetfile_newfolder,0); // detect folder change X G_SIGNAL(dialog,"key-release-event",zgetfile_KBkey,0); // respond to F1 help key X- X+ X gtk_window_set_position(GTK_WINDOW(dialog),GTK_WIN_POS_MOUSE); // put dialog at mouse position X gtk_file_chooser_set_show_hidden(GTK_FILE_CHOOSER(dialog),0); // default: no show hidden X X@@ -5455,7 +5474,7 @@ X gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog),pdir); X gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog),pfile); X } X- else X+ else X gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog),pdir); X zfree(pdir); X } X@@ -5467,7 +5486,7 @@ X zgetfile_Finitfile = 1; X } X X- gtk_widget_show_all(dialog); // v.3.9 X+ gtk_widget_show_all(dialog); // v.3.9 X X while (true) X { X@@ -5479,7 +5498,7 @@ X gtk_file_chooser_set_show_hidden(GTK_FILE_CHOOSER(dialog),hide); X } X X- else if (fcstat == 104) { // get JPG quality parameter X+ else if (fcstat == 104) { // get JPG quality parameter X while (true) { X qual = zdialog_text(null,ZTX("JPG quality 0-100"),JPGquality); X if (! qual) break; // cancel = no change X@@ -5491,10 +5510,10 @@ X } X } X X- else break; // some other button X+ else break; // some other button X } X X- if (fcstat == GTK_RESPONSE_ACCEPT) X+ if (fcstat == GTK_RESPONSE_ACCEPT) X { X gslist = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(dialog)); X if (! gslist) goto byebye; X@@ -5502,8 +5521,8 @@ X if (! NF) goto byebye; X X flist = (char **) zmalloc((NF+1)*sizeof(char *),"zgetfile.list"); // allocate returned list v.3.5 X- X- for (ii = 0; ii < NF; ii++) X+ X+ for (ii = 0; ii < NF; ii++) X { // process selected files X file1 = (char *) g_slist_nth_data(gslist,ii); X if (strlen(file1) >= maxfcc) // v.3.5 X@@ -5546,7 +5565,7 @@ X zgetfile_Fnewfolder = 0; // (does not work in newfolder() above, X gtk_file_chooser_unselect_all(GTK_FILE_CHOOSER(dialog)); // but it does work here - why?) X } X- X+ X filename = gtk_file_chooser_get_preview_filename(GTK_FILE_CHOOSER(dialog)); X X if (! filename) { X@@ -5606,12 +5625,12 @@ X if (err) *prog = 0; X } X } X- X+ X if (! *prog) { X zmessLogACK(null,"no xdg-open or firefox, cannot show document"); X return; X } X- X+ X snprintf(command,499,"%s %s &",prog,url); // add '&' v.2.18 X err = system(command); X return; X@@ -5638,7 +5657,7 @@ X } X X X-// private function X+// private function X // get dropped file, clean escapes, pass to user function X // passed filespec is subject for zfree() X X@@ -5649,7 +5668,7 @@ X X char *text, *text2, *file, *file2; X int cc; X- X+ X text = (char *) ((GtkSelectionData *) sdata)->data; X ufunc2 = (drag_drop_func *) ufunc; X X@@ -5663,13 +5682,13 @@ X zfree(file); X ufunc2(mpx,mpy,file2); // pass file to user function X } X- X- else X+ X+ else X { X text2 = strdupz(text,0,"drag_drop_file"); // v.3.5 X ufunc2(mpx,mpy,text2); X } X- X+ X return 1; X } X X@@ -5683,10 +5702,10 @@ X X char inch, *out, *outp; X int nib1, nib2; X- X+ X out = zmalloc(strlen(inp)+1,"drag_drop_file"); // v.3.5 X outp = out; X- X+ X while ((inch = *inp++)) X { X if (inch == '%') X@@ -5697,7 +5716,7 @@ X } X else *outp++ = inch; X } X- X+ X *outp = 0; X return out; X } X@@ -5748,7 +5767,7 @@ X // optional paper format: letter, A4, A5, A6, custom N.N x N.N // v.3.4 X // and orientation: portrait or landscape X X-namespace printimagefile X+namespace printimagefile X { X char printerID[60] = "default"; // printer ID X char paperformat[40] = "A4"; // paper format X@@ -5756,7 +5775,7 @@ X double paperwidth, paperheight; // paper size, cm X X int Npapertab = 5; // known paper formats X- cchar *papertab[5] = { X+ cchar *papertab[5] = { X "letter 21.6 x 27.9 cm" , X "A4 21.0 x 29.7 cm" , X "A5 14.8 x 21.0 cm" , X@@ -5764,7 +5783,7 @@ X "custom N.N x N.N cm" }; // custom format X X cchar *imagefilespec; X- GdkPixbuf *pixbuf; X+ GdkPixbuf *pixbuf; X X int print_dialog_event(zdialog *zd, cchar *event); // private functions X void draw_page(GtkPrintOperation *, GtkPrintContext *, int); X@@ -5779,7 +5798,7 @@ X int ii, fcc, contx = 0; X cchar *pp1, *pp2; X zdialog *zd; X- X+ X zthreadcrash(); // thread usage not allowed v.3.9 X X imagefilespec = imagefile; X@@ -5794,7 +5813,7 @@ X zdialog_add_widget(zd,"hbox","hb1","dialog",0,"space=5"); X zdialog_add_widget(zd,"vbox","vb11","hb1",0,"homog"); X zdialog_add_widget(zd,"vbox","vb12","hb1",0,"homog"); // printer ID [__________|v] X- zdialog_add_widget(zd,"label","labpri","vb11",ZTX("printer ID")); // paper format [__________|v] X+ zdialog_add_widget(zd,"label","labpri","vb11",ZTX("printer ID")); // paper format [__________|v] X zdialog_add_widget(zd,"label","labpap","vb11",ZTX("paper format")); // (o) portrait (o) landscape X zdialog_add_widget(zd,"combo","entpri","vb12",0,"scc=20|space=3"); X zdialog_add_widget(zd,"comboE","entpap","vb12",0,"scc=20|space=3"); X@@ -5834,7 +5853,7 @@ X zdialog_stuff(zd,"entpap",paperformat); // stuff previous settings X if (strEqu(orientation,"landscape")) zdialog_stuff(zd,"land",1); // or caller's settings X else zdialog_stuff(zd,"port",1); X- X+ X zdialog_run(zd,print_dialog_event); // run dialog v.3.5 X zdialog_wait(zd); // wait for completion v.3.4 X return; X@@ -5856,7 +5875,7 @@ X int zstat, port; X cchar *pp; X double wmm, hmm; X- X+ X zstat = zd->zstat; // v.3.5 X if (! zstat) return 0; X X@@ -5867,28 +5886,28 @@ X zdialog_free(zd); X if (zstat != 1) return 0; X X- paperwidth = paperheight = 0; X+ paperwidth = paperheight = 0; X pp = strField(paperformat,' ',2); X if (pp) paperwidth = atof(pp); X pp = strField(paperformat,' ',4); X if (pp) paperheight = atof(pp); X- X+ X if (paperwidth < 3 || paperwidth > 40 || // reasonableness check: X paperheight < 3 || paperheight > 40) { // paper dimensions 3-40 cm X zmessageACK(null,ZTX("paper format is crazy")); X return 0; X } X- X+ X if (port) strcpy(orientation,"portrait"); X else strcpy(orientation,"landscape"); X X wmm = 10.0 * paperwidth; // paper size, mm dimensions X hmm = 10.0 * paperheight; X papersize = gtk_paper_size_new_custom("custom","custom",wmm,hmm,GTK_UNIT_MM); X- X+ X pagesetup = gtk_page_setup_new(); // page setups X gtk_page_setup_set_paper_size(pagesetup,papersize); X- if (strEqu(orientation,"landscape")) X+ if (strEqu(orientation,"landscape")) X gtk_page_setup_set_orientation(pagesetup,GTK_PAGE_ORIENTATION_LANDSCAPE); X else X gtk_page_setup_set_orientation(pagesetup,GTK_PAGE_ORIENTATION_PORTRAIT); X@@ -5901,10 +5920,10 @@ X printop = gtk_print_operation_new(); // print operation X gtk_print_operation_set_default_page_setup(printop,pagesetup); X gtk_print_operation_set_print_settings(printop,printsettings); X- gtk_print_operation_set_n_pages(printop,1); X+ gtk_print_operation_set_n_pages(printop,1); X X g_signal_connect(printop,"draw-page",G_CALLBACK(draw_page),0); // start print X- printstat = gtk_print_operation_run(printop,GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG,0,0); X+ printstat = gtk_print_operation_run(printop,GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG,0,0); X X if (printstat == GTK_PRINT_OPERATION_RESULT_ERROR) { X gtk_print_operation_get_error(printop,&gerror); X@@ -5923,8 +5942,8 @@ X // draw the graphics for the print page X // rescale with cairo: print resolution of 300 dpi is no longer ignored v.3.5.1 X X-void printimagefile::draw_page(GtkPrintOperation *printop, GtkPrintContext *printcontext, int page) X-{ X+void printimagefile::draw_page(GtkPrintOperation *printop, GtkPrintContext *printcontext, int page) X+{ X using namespace printimagefile; X X cairo_t *cairocontext; X@@ -5935,7 +5954,7 @@ X X iww = gdk_pixbuf_get_width(pixbuf); // image size X ihh = gdk_pixbuf_get_height(pixbuf); X- X+ X scale = pww / iww; // rescale to fit page X if (phh / ihh < scale) scale = phh / ihh; X X@@ -5949,7 +5968,7 @@ X } X X X-/************************************************************************** X+/************************************************************************** X X GdkPixbuf * gdk_pixbuf_rotate(GdkPixbuf *pixbuf, double angle, int acolor) X X@@ -5964,11 +5983,11 @@ X Pixbuf must have 8 bits per channel and 3 or 4 channels. X Loss of resolution is about 1/2 pixel. X Speed is about 18 million pixels/sec. on my 2.67 GHz CPU. // v.3.2 X- X+ X NULL is returned if the function fails for one of the following: X - pixbuf not 8 bits/channel or < 3 channels X - unable to create output pixbuf (lack of memory?) X- X+ X Algorithm: X create output pixbuf big enough for rotated input pixbuf X compute coefficients for affine transform X@@ -6017,7 +6036,7 @@ X while (angle < -180) angle += 360; // normalize, -180 to +180 X while (angle > 180) angle -= 360; X angle = angle * pi / 180; // radians, -pi to +pi X- X+ X if (fabs(angle) < 0.001) { // bugfix 0.01 >> 0.001 v.2.1 X pixbuf2 = gdk_pixbuf_copy(pixbuf1); // angle is zero within my precision X return pixbuf2; X@@ -6029,10 +6048,10 @@ X pixbuf2 = gdk_pixbuf_new(color,alpha,nbits,ww2,hh2); // create output pixbuf2 X if (! pixbuf2) return 0; X rs2 = gdk_pixbuf_get_rowstride(pixbuf2); X- X+ X ppix1 = gdk_pixbuf_get_pixels(pixbuf1); // input pixel array X ppix2 = gdk_pixbuf_get_pixels(pixbuf2); // output pixel array X- X+ X ww15 = 0.5 * ww1; X hh15 = 0.5 * hh1; X ww25 = 0.5 * ww2; X@@ -6042,7 +6061,7 @@ X b = sin(angle); X d = - sin(angle); X e = cos(angle); X- X+ X for (py2 = 0; py2 < hh2; py2++) // loop through output pixels X for (px2 = 0; px2 < ww2; px2++) X { X@@ -6052,7 +6071,7 @@ X X px0 = int(px1); // pixel containing (px1,py1) X py0 = int(py1); X- X+ X if (px1 < 0 || px0 >= ww1-1 || py1 < 0 || py0 >= hh1-1) { // if outside input pixel array X pix2 = ppix2 + py2 * rs2 + px2 * nch; // output is acolor v.2.17 X pix2[0] = pix2[1] = pix2[2] = acolor; X@@ -6068,25 +6087,25 @@ X f1 = (px0+1 - px1) * (py1 - py0); // in each of the 4 pixels X f2 = (px1 - px0) * (py0+1 - py1); X f3 = (px1 - px0) * (py1 - py0); X- X+ X red = f0 * pix0[0] + f1 * pix1[0] + f2 * pix2[0] + f3 * pix3[0]; // sum the weighted inputs X green = f0 * pix0[1] + f1 * pix1[1] + f2 * pix2[1] + f3 * pix3[1]; X blue = f0 * pix0[2] + f1 * pix1[2] + f2 * pix2[2] + f3 * pix3[2]; X- if (alpha) X+ if (alpha) X tran = f0 * pix0[3] + f1 * pix1[3] + f2 * pix2[3] + f3 * pix3[3]; // bugfix v.3.3 X- X+ X if (red == acolor && green == acolor && blue == acolor) { // avoid acolor in image v.2.17 X if (blue == 0) blue = 1; X else blue--; X } X- X+ X pix2 = ppix2 + py2 * rs2 + px2 * nch; // output pixel X pix2[0] = int(red); X pix2[1] = int(green); X pix2[2] = int(blue); X if (alpha) pix2[3] = int(tran); // bugfix v.3.3 X } X- X+ X return pixbuf2; X } X X@@ -6165,7 +6184,7 @@ X Make window of thumbnails starting with filez (anchor) X Handle window buttons (up row, down page, open file, etc.) X Call ufunc() when thumbnail image is clicked X- X+ X filez: anchor file or directory of image files X X action: init: get internal list of image files and subdirectories X@@ -6188,7 +6207,7 @@ X void ufunc(char *filez) X - receives filename (path) of selected thumbnail X - filez belongs to caller and is a subject for zfree() X- X+ X parent: optional parent window v.3.8 X if present, gallery window will overlay the parent window X (window replacement that can be undone by the user) X@@ -6213,7 +6232,7 @@ X X if (strstr("init initF sort find prev next first last insert delete",action)) X return image_navigate(filez,action,Nth); // create or navigate image file list X- X+ X if (strEqu(action,"close")) { // v.3.7 X if (wing) gtk_widget_destroy(wing); X return 0; X@@ -6221,16 +6240,16 @@ X X if (strEqu(action,"paint2") && ! wing) return 0; // refresh but window not active X if (strEqu(action,"paint1")) fpresent++; // bring window to z-top X- X+ X if (filez) targfile = strdupz(filez,0,"gallery.targ"); // no initz. if filez not in list v.3.9 X X if (wing) { // repaint existing gallery window X gallery_paint(0,0); X return 0; X } X- X+ X wing = gtk_window_new(GTK_WINDOW_TOPLEVEL); // create new gallery window X- X+ X if (pwing) { X gtk_window_get_size(GTK_WINDOW(pwing),&xwinW,&xwinH); // overlay parent window v.3.8 X gtk_window_get_position(GTK_WINDOW(pwing),&xwinX,&xwinY); X@@ -6245,7 +6264,7 @@ X vboxx = gtk_vbox_new(0,0); // vertical packing box X gtk_container_add(GTK_CONTAINER(wing),vboxx); // add to main window X X- tbarx = create_toolbar(vboxx,24); // add toolbar and buttons X+ tbarx = create_toolbar(vboxx,24); // add toolbar and buttons X X add_toolbar_button(tbarx, ZTX("bigger"), ZTX("increase thumbnail size"), "gtk-zoom-in", menufuncx); X add_toolbar_button(tbarx, ZTX("smaller"), ZTX("reduce thumbnail size"), "gtk-zoom-out", menufuncx); X@@ -6258,7 +6277,7 @@ X add_toolbar_button(tbarx, ZTX("next page"), ZTX("next page"), "next-page.png", menufuncx); X add_toolbar_button(tbarx, ZTX("prev row"), ZTX("previous row"), "prev-row.png", menufuncx); X add_toolbar_button(tbarx, ZTX("next row"), ZTX("next row"), "next-row.png", menufuncx); X- X+ X scrwing = gtk_scrolled_window_new(0,0); // create scrolled window X gtk_container_add(GTK_CONTAINER(vboxx),scrwing); // add to main window X layout = gtk_layout_new(0,0); // create drawing window X@@ -6299,10 +6318,10 @@ X int thumx, thumy, orgx, orgy, ww, hh; X char *fileC, *fileN, *pp, *fname; X char wintitle[200]; X- X+ X xwinW = layout->allocation.width; // curr. gallery window size X xwinH = layout->allocation.height; X- X+ X thumbW = thumbsize + 10; // thumbnail cell size X thumbH = thumbsize + 30; X xmargW = xmargH = 5; // edge margins X@@ -6311,9 +6330,9 @@ X thumbW = 200; // zero, list view v.3.7 X thumbH = 20; X } X- X+ X xrows = int(0.5 + 1.0 * xwinH / thumbH); // get thumbnail rows and cols that X- xcols = int(0.3 + 1.0 * xwinW / thumbW); // (almost) fit in window X+ xcols = int(0.3 + 1.0 * xwinW / thumbW); // (almost) fit in window X if (xrows < 1) xrows = 1; X if (xcols < 1) xcols = 1; X nrows = 1 + (nfiles-1) / xcols; // total thumbnail rows, 1 or more X@@ -6356,7 +6375,7 @@ X ancfile = strdupz(flist[ii],0,"gallery.anchor"); X *ancfile = '/'; X } X- X+ X if (! expose) // initial window or navigation button X { X snprintf(wintitle,199,"%s %d files",dirkx,nfiles); // window title: directory and file count X@@ -6370,7 +6389,7 @@ X fpresent = 0; X return 0; X } X- X+ X rect = expose->area; // exposed area to refresh X expy1 = rect.y; X expy2 = expy1 + rect.height; X@@ -6389,14 +6408,14 @@ X { X thumx = col * thumbW + xmargW; // upper left corner in window space X thumy = row * thumbH + xmargH; X- X+ X if (thumy < expy2 && thumy+14 > expy1) { // if in exposed area, X- pp = (char *) strrchr(fileC,'/'); // draw file name X+ pp = (char *) strrchr(fileC,'/'); // draw file name X if (pp) fname = pp + 1; X else fname = fileC; X draw_text(layout,fname,thumx,thumy,thumbW); X } X- X+ X if (thumbsize) // zero >> list view v.3.7 X pxbT = image_thumbnail(fileC,thumbsize); // get thumbnail X else pxbT = 0; X@@ -6420,10 +6439,10 @@ X } X if (thumy + orgy + hh > expy2) X hh = hh - (thumy + orgy + hh - expy2); X- X+ X if (orgy >= 0 && hh > 0) X gdk_draw_pixbuf(GTK_LAYOUT(layout)->bin_window,0,pxbT, X- orgx,orgy,thumx+orgx,thumy+orgy,ww,hh,NODITHER,0,0); X+ orgx,orgy,thumx+orgx,thumy+orgy,ww,hh,NODITHER,0,0); X g_object_unref(pxbT); X } X X@@ -6477,7 +6496,7 @@ X void image_navi::gallery_destroy() X { X using namespace image_navi; X- X+ X wing = 0; // no window X if (ancfile) zfree(ancfile); // no anchor file X ancfile = 0; X@@ -6498,14 +6517,14 @@ X int ii, scrollp; X char *filex, *filez, *pp; X char buff[maxfcc]; X- X+ X if (strEqu(menu,ZTX("close"))) { X gtk_widget_destroy(wing); // close image gallery window X return; X } X X if (strEqu(menu,ZTX("bigger"))) { // next bigger thumbnail size X- for (ii = 0; ii < thumbxx; ii++) X+ for (ii = 0; ii < thumbxx; ii++) X if (thumbsize == thumbx[ii]) break; X if (ii == 0) return; X thumbsize = thumbx[ii-1]; X@@ -6515,7 +6534,7 @@ X } X X if (strEqu(menu,ZTX("smaller"))) { // next smaller X- for (ii = 0; ii < thumbxx; ii++) X+ for (ii = 0; ii < thumbxx; ii++) X if (thumbsize == thumbx[ii]) break; X if (ii >= thumbxx-1) thumbsize = 0; // no thumbs, list view v.3.7 X else thumbsize = thumbx[ii+1]; X@@ -6525,7 +6544,7 @@ X } X X if (strEqu(menu,ZTX("open"))) { // go to a specific file X- if (ancfile) X+ if (ancfile) X filez = strdupz(ancfile,0,"gallery.open"); X else if (nfiles) { X filez = strdupz(flist[0],0,"gallery.open"); X@@ -6557,14 +6576,14 @@ X zfree(filez); X scrollp = 0; // v.3.7 X } X- X+ X if (strEqu(menu,ZTX("prev row"))) scrollp -= thumbH; X if (strEqu(menu,ZTX("next row"))) scrollp += thumbH; X if (strEqu(menu,ZTX("prev page"))) scrollp -= thumbH * xrows; X if (strEqu(menu,ZTX("next page"))) scrollp += thumbH * xrows; X if (strEqu(menu,ZTX("first page"))) scrollp = 0; X if (strEqu(menu,ZTX("last page"))) scrollp = maxscroll; X- X+ X if (scrollp < 0) scrollp = 0; // enforce limits v.3.7 X if (scrollp > maxscroll) scrollp = maxscroll; X scrollp = scrollp / thumbH * thumbH; // align top row v.3.7 X@@ -6588,9 +6607,9 @@ X int row, col, nrows, ii, err; X char *filez; X struct stat statb; X- X+ X if (! ancfile) return; // empty window X- X+ X mousex = int(event->x); X mousey = int(event->y); X X@@ -6603,10 +6622,10 @@ X X ii = xcols * row + col; X if (ii >= nfiles) return; X- X+ X filez = strdupz(flist[ii],0,"gallery.mouse"); // selected file X *filez = '/'; X- X+ X err = stat(filez,&statb); X if (err) { // file is gone? X zfree(filez); X@@ -6619,7 +6638,7 @@ X zfree(filez); X return; X } X- X+ X if (userfunc) userfunc(filez); // pass clicked file to user function X return; X } X@@ -6639,7 +6658,7 @@ X using namespace image_navi; X X int KBkey; X- X+ X KBkey = event->keyval; X X if (KBkey == GDK_plus) menufuncx(win,ZTX("bigger")); // +/- = bigger/smaller thumbnails X@@ -6652,17 +6671,17 @@ X if (KBkey == GDK_Right) menufuncx(win,ZTX("next page")); // right arrow = next page X if (KBkey == GDK_Up) menufuncx(win,ZTX("prev row")); // up arrow = previous row X if (KBkey == GDK_Down) menufuncx(win,ZTX("next row")); // down arrow = next row X- X+ X if (KBkey == GDK_Home) menufuncx(win,ZTX("first page")); // keys added v.2.26 X if (KBkey == GDK_End) menufuncx(win,ZTX("last page")); X if (KBkey == GDK_Page_Up) menufuncx(win,ZTX("prev page")); X if (KBkey == GDK_Page_Down) menufuncx(win,ZTX("next page")); X X if (KBkey == GDK_Escape) gtk_widget_destroy(win); // Escape = cancel gallery window X- X+ X if (KBkey == GDK_F1) X if (userfunc) userfunc((char *) "F1"); // help request v.2.26 X- X+ X return 1; X } X X@@ -6682,7 +6701,7 @@ X if (flist[ii][0] == '!') nn++; // directories have ! instead of / X if (strcmp(filez,flist[ii]) == 0) posn = ii + 1 - nn; X } X- X+ X if (count) *count = nfiles - nn; // return count (excl. directories) X return posn; // return position or zero X } X@@ -6719,7 +6738,7 @@ X pp = strcasestr(imagefiles,pp); // supported image type X if (pp) return 2; X } X- X+ X return 3; X } X X@@ -6747,14 +6766,14 @@ X err = stat(fpath,&statf); X if (err) return 0; X if (S_ISDIR(statf.st_mode)) return 0; X- X+ X pfile = strrchr(fpath,'/'); // if thumbnail, return same file X if (! pfile) return 0; // v.3.5 X if (pfile > fpath+12 && strnEqu(pfile-12,"/.thumbnails/",13)) { X bpath = strdupz(fpath,0,"gallery.thumb"); // v.3.5 X return bpath; X } X- X+ X pfile++; // file name part X bpath = strdupz(fpath,20,"gallery.thumb"); // v.3.5 X bfile = bpath + (pfile - fpath); // /directory/.thumbnails/filename.png X@@ -6762,9 +6781,9 @@ X bfile += 12; X strcpy(bfile,pfile); X strcat(bfile,".png"); X- X+ X err = stat(bpath,&statb); // found, compare date to image date X- if (err || (statb.st_mtime < statf.st_mtime)) X+ if (err || (statb.st_mtime < statf.st_mtime)) X { // does not exist or stale X *bfile = 0; X err = stat(bpath,&statb); X@@ -6781,7 +6800,7 @@ X g_object_unref(thumbpxb); // bugfix, memory leak v.3.5 X genthumbs++; // count generated thumbnails v.3.9 X } X- X+ X return bpath; X } X X@@ -6809,15 +6828,15 @@ X static time_t mtimecache[cachesize]; X static char *fpathcache[cachesize]; X static GdkPixbuf *pixbufcache[cachesize]; X- X+ X zthreadcrash(); // thread usage not allowed v.3.9 X X if (ftf) { // first call v.3.7 X- for (ii = 0; ii < cachesize; ii++) X+ for (ii = 0; ii < cachesize; ii++) X fpathcache[ii] = 0; // clear cache X ftf = 0; X } X- X+ X err = stat(fpath,&statf); // fpath status info X if (err) return 0; X X@@ -6828,11 +6847,11 @@ X zfree(bpath); X return thumbpxb; X } X- X+ X mtime = statf.st_mtime; // last modification time X- X+ X if (! size) size = thumbfilesize; // default thumb size X- X+ X for (ii = nextcache; ii >= 0; ii--) // get cached pixbuf if found v.3.7 X if (fpathcache[ii] && strEqu(fpath,fpathcache[ii]) && X sizecache[ii] == size && mtime == mtimecache[ii]) break; // check mtime (bugfix) v.3.9 X@@ -6847,12 +6866,12 @@ X thumbpxb = gdk_pixbuf_copy(pixbufcache[ii]); X return thumbpxb; X } X- X+ X if (size > thumbfilesize) { // support huge thumbnails v.3.6 X thumbpxb = gdk_pixbuf_new_from_file_at_size(fpath,size,size,&gerror); X goto addcache; X } X- X+ X bpath = image_thumbfile(fpath); // get thumbnail file X if (! bpath) return 0; X thumbpxb = gdk_pixbuf_new_from_file_at_size(bpath,size,size,&gerror); // get thumbnail X@@ -6911,7 +6930,7 @@ X int err, ii, nn, ftyp, contx = 0, fposn, fpres; X FILE *fid; X struct stat statbuf; X- X+ X if (! strstr("init initF sort find first last prev next insert delete",action)) X zappcrash("image_navigate %s",action); X X@@ -6935,7 +6954,7 @@ X strncpy0(dirkx,filez,maxfcc-2); // copy input file X err = stat(dirkx,&statbuf); X if (err) { X- pp = (char *) strrchr(dirkx,'/'); // bad file, check directory part X+ pp = (char *) strrchr(dirkx,'/'); // bad file, check directory part X if (! pp) return 0; X pp[1] = 0; X err = stat(dirkx,&statbuf); X@@ -6954,7 +6973,7 @@ X zfree(buff); X continue; X } X- X+ X ftyp = image_file_type(buff); X if (ftyp != 1 && ftyp != 2) { // not directory or image file type X zfree(buff); // (.thumbnails not ftyp 1) X@@ -6976,35 +6995,35 @@ X if (strEqu(action,"initF")) // initialize from given list v.2.4 X { X strncpy0(dirkx,filez,maxfcc-1); // copy input file X- X+ X fid = fopen(dirkx,"r"); // open file X if (! fid) return 0; X X buff = zmalloc(maxfcc); X- X+ X while (true) // read list of files X { X pp = fgets_trim(buff,maxfcc-1,fid,1); X if (! pp) break; X flist[nfiles] = strdupz(buff,0,"gallery.file"); // add files to memory list v.3.5 X nfiles++; X- if (nfiles == maxFiles) X+ if (nfiles == maxFiles) X zappcrash("more than %d files",maxFiles); X } X- X+ X fclose(fid); X zfree(buff); // sort removed v.3.9 X X if (nfiles == 0) return 0; // no files X } X- X+ X if (strEqu(action,"sort")) // sort the list from initF v.3.9 X { X if (nfiles == 0) return 0; X HeapSort(flist,nfiles,image_fcomp); // Heap Sort - pointers to strings X return 0; X } X- X+ X if (! filez) *filezz = 0; // no filez arg v.2.5 X else strncpy0(filezz,filez,maxfcc); // make modifiable copy of filez X X@@ -7050,14 +7069,14 @@ X } X X if (nfiles == 0) return 0; // file list is empty X- X+ X if (fposn >= 0 && fposn < nfiles) { X if (ancfile) zfree(ancfile); // bugfix, memory leak v.3.9 X ancfile = strdupz(flist[fposn],0,"gallery.anchor"); // anchor file position v.3.5 X *ancfile = '/'; // restore initial '/' X } X X- if (strnEqu(action,"init",4)) // action = init or initF X+ if (strnEqu(action,"init",4)) // action = init or initF X return 0; X X if (strEqu(action,"find")) // is filez in list or not v.2.4 X@@ -7071,19 +7090,19 @@ X if (fposn < 0) fposn = 0; // if < first file, return first X } X X-prev_next: X+prev_next: X X if (strEqu(action,"prev")) { // Nth previous file X if (fposn == 0) return 0; // filez <= first in list X fposn -= Nth; X if (fposn < 0) fposn = 0; // first file X } X- X+ X if (strEqu(action,"next")) { // Nth next file X if (fpres == 1) fposn += Nth; X if (fposn > nfiles-1) return 0; // beyond last file X } X- X+ X file2 = strdupz(flist[fposn],0,"gallery.file"); // copy file into new memory v.3.5 X file2[0] = '/'; // restore initial '/' X X@@ -7150,7 +7169,7 @@ X int fontascent, fontdescent; X int line, nlines, ii; X char *imagefile, **filelist; X- X+ X zthreadcrash(); // thread usage not allowed v.3.9 X X image_gallery(startdir,"paint1",0,imgl_insert_file,parent); // activate image gallery window X@@ -7174,7 +7193,7 @@ X imgl_drawarea = gtk_drawing_area_new(); X gtk_widget_set_size_request(imgl_drawarea,256,258); // increased v.3.9 X gtk_container_add(GTK_CONTAINER(frame),imgl_drawarea); X- X+ X imgl_files = zdialog_widget(imgl_zd,"files"); // activate mouse-clicks for X gtk_widget_add_events(imgl_files,GDK_BUTTON_PRESS_MASK); // file list widget X G_SIGNAL(imgl_files,"button-press-event",imgl_mouseclick,0) X@@ -7208,7 +7227,7 @@ X X textBuff = gtk_text_view_get_buffer(GTK_TEXT_VIEW(imgl_files)); X nlines = gtk_text_buffer_get_line_count(textBuff); X- X+ X filelist = (char **) zmalloc((nlines+1) * sizeof(char *),"imgl.getfiles"); X X for (ii = line = 0; line < nlines; line++) // get list of files from dialog X@@ -7224,7 +7243,7 @@ X } X } X filelist[ii] = 0; // mark EOL X- X+ X zdialog_free(imgl_zd); // kill dialog X image_gallery(0,"close"); // close image gallery window X X@@ -7247,7 +7266,7 @@ X char *ftemp; X cchar *xfile; X int line; X- X+ X if (strEqu(event,"delete")) // delete file at cursor position X { X if (imagefile) zfree(imagefile); X@@ -7267,7 +7286,7 @@ X X imagefile = strdupz(ftemp,0,"imgl.file"); X free(ftemp); X- X+ X gtk_text_buffer_delete(textBuff,&iter1,&iter2); // delete file text X gtk_text_buffer_get_iter_at_line(textBuff,&iter2,line+1); X gtk_text_buffer_delete(textBuff,&iter1,&iter2); // delete empty line (\n) X@@ -7315,7 +7334,7 @@ X int ftyp; X GtkTextIter iter; X GtkTextBuffer *textBuff; X- X+ X if (strEqu(imagefile,"F1")) { X showz_userguide(zfuncs::F1_help_topic); // F1 context help X return; X@@ -7332,12 +7351,12 @@ X imgl_showthumb(); // update thumbnail X imgl_cursorpos++; // advance cursor position X zfree(imagefile); X- X+ X return; X } X X X-// process mouse click in files window: X+// process mouse click in files window: X // set new cursor position and set thumbnail = clicked file X X int imgl_mouseclick(GtkWidget *, GdkEventButton *event, void *) X@@ -7417,7 +7436,7 @@ X strcpy(zparmfile,get_zuserdir()); X strcat(zparmfile,"/parameters"); // /home/user/.appname/parameters X } X- X+ X if (parmlistvalid) { // delete old parms X delete [] parmlist.name; X delete [] parmlist.value; X@@ -7457,18 +7476,18 @@ X { X char *pfile; X int np; X- X+ X if (! parmlistvalid) zappcrash("parmlistvalid = 0"); X X pfile = zgetfile1(ZTX("load parameters from a file"),"open",zparmfile,"hidden"); X if (! pfile) return 0; X- X+ X np = loadParms(pfile); X zfree(pfile); X X return np; X } X- X+ X X // load parameters from a file X // returns no. parameters loaded X@@ -7480,11 +7499,11 @@ X char buff[100], *fgs, *pp; X cchar *pname, *pvalue; X double dvalue; X- X+ X if (! parmlistvalid) zappcrash("parmlistvalid = 0"); X X if (! pfile) pfile = zparmfile; X- X+ X if (*pfile != '/') { // if parm file name only, X pp = (char *) strrchr(zparmfile,'/'); // make complete absolute path X if (pp) strcpy(pp+1,pfile); // in same directory as prior X@@ -7514,7 +7533,7 @@ X if (! np1) continue; X np2++; X } X- X+ X fclose(fid); // close file X return np2; // return parameter count X } X@@ -7556,7 +7575,7 @@ X } X X fid = fopen(pfile,"w"); X- if (! fid) { X+ if (! fid) { X zmessageACK(null,ZTX("cannot open file %s"),pfile); X return 0; X } X@@ -7565,7 +7584,7 @@ X X for (np = 0; np < parmlist.count; np++) X fprintf(fid," \"%s\" %.12g \n",parmlist.name[np],parmlist.value[np]); X- X+ X fclose(fid); X return np; X } X@@ -7638,7 +7657,7 @@ X pvalue = getParm(pname); X wprintf(textWin," %s %.12g \n",pname,pvalue); X } X- X+ X return parmlist.count; X } X X@@ -7657,37 +7676,37 @@ X double pvalue; X int ii, err, iie = -1, zstat, floaded = 0; X int bcancel=1, bapply=2, bload=3, bsave=4, blist=5, baddp=6; X- X+ X if (! parmlistvalid) zappcrash("parmlistvalid = 0"); X- X+ X zthreadcrash(); // thread usage not allowed v.3.9 X X build_dialog: // build parameter edit dialog X X if (parmlist.count > 100) zappcrash("more than 100 parameters"); X- X- if (textWin && addp) X+ X+ if (textWin && addp) X peDialog = gtk_dialog_new_with_buttons X- (ZTX("edit parameters"), null, GTK_DIALOG_MODAL, X- ZTX("load\nfile"),bload, ZTX("save\nfile"),bsave, ZTX("list\nall"),blist, X+ (ZTX("edit parameters"), null, GTK_DIALOG_MODAL, X+ ZTX("load\nfile"),bload, ZTX("save\nfile"),bsave, ZTX("list\nall"),blist, X ZTX("add\nnew"),baddp, ZTX("cancel"),bcancel, ZTX("apply"),bapply, null); X X- else if (textWin) X+ else if (textWin) X peDialog = gtk_dialog_new_with_buttons X- (ZTX("edit parameters"), null, GTK_DIALOG_MODAL, X- ZTX("load\nfile"),bload, ZTX("save\nfile"),bsave, ZTX("list\nall"),blist, X+ (ZTX("edit parameters"), null, GTK_DIALOG_MODAL, X+ ZTX("load\nfile"),bload, ZTX("save\nfile"),bsave, ZTX("list\nall"),blist, X ZTX("cancel"),bcancel, ZTX("apply"),bapply, null); X X- else if (addp) X+ else if (addp) X peDialog = gtk_dialog_new_with_buttons X- (ZTX("edit parameters"), null, GTK_DIALOG_MODAL, X- ZTX("load\nfile"),bload, ZTX("save\nfile"),bsave, X+ (ZTX("edit parameters"), null, GTK_DIALOG_MODAL, X+ ZTX("load\nfile"),bload, ZTX("save\nfile"),bsave, X ZTX("add\nnew"),baddp, ZTX("cancel"),bcancel, ZTX("apply"),bapply, null); X X- else peDialog = X+ else peDialog = X gtk_dialog_new_with_buttons X- (ZTX("edit parameters"), null, GTK_DIALOG_MODAL, X- ZTX("load\nfile"),bload, ZTX("save\nfile"),bsave, X+ (ZTX("edit parameters"), null, GTK_DIALOG_MODAL, X+ ZTX("load\nfile"),bload, ZTX("save\nfile"),bsave, X ZTX("cancel"),bcancel, ZTX("apply"),bapply, null); X X gtk_window_set_position(GTK_WINDOW(peDialog),GTK_WIN_POS_MOUSE); // v.2.7.1 X@@ -7708,7 +7727,7 @@ X } X X run_dialog: // display dialog and get inputs X- X+ X if (iie > -1) X { X gtk_editable_select_region(GTK_EDITABLE(peEdit[iie]),0,-1); // focus on new or bad parameter X@@ -7723,14 +7742,14 @@ X { X if (floaded) { X zstat = zmessageYN(null,ZTX("apply?")); // if file loaded, clarify v.2.9 X- if (! zstat) { X+ if (! zstat) { X gtk_widget_destroy(peDialog); X return 0; X } X zstat = bapply; X } X } X- X+ X if (zstat == bload) // load from file X { X loadParms(); X@@ -7738,7 +7757,7 @@ X floaded = 1; X goto build_dialog; X } X- X+ X for (ii = 0; ii < parmlist.count; ii++) // capture inputs and check if OK X { X pchval = gtk_entry_get_text(GTK_ENTRY(peEdit[ii])); X@@ -7770,13 +7789,13 @@ X floaded = 0; X goto run_dialog; X } X- X+ X if (zstat == blist) // list parameters X { X listParms(textWin); X goto run_dialog; X } X- X+ X if (zstat == baddp) // add parameter X { X pname = zdialog_text(null,ZTX("add parameter"),ZTX("(new parm name)")); X@@ -7788,7 +7807,7 @@ X gtk_widget_destroy(peDialog); X goto build_dialog; X } X- X+ X gtk_widget_destroy(peDialog); // unknown status X return 0; X } X@@ -7846,7 +7865,7 @@ X X X xstring::~xstring() // delete xstring X-{ X+{ X validate(); X delete[] xpp; // release allocated memory X xpp = 0; X@@ -7947,7 +7966,7 @@ X if (! cc) cc = scc; X X int pad = pos - xcc; X- if (pad < 0) pad = 0; X+ if (pad < 0) pad = 0; X X if (xmem < xcc + cc + pad + 1) // allocate more memory if needed X { X@@ -7998,12 +8017,12 @@ X } X X if (pos > xcc) memset(xpp+xcc,' ',pos-xcc); // add blanks up to pos X- X+ X if (cc > scc) memset(xpp+pos+scc,' ',cc-scc); // blank pad if cc > string X if (cc < scc) scc = cc; X strncpy(xpp+pos,string,scc); // insert string, without null X X- if (pos + cc > xcc) xcc = pos + cc; // set new length X+ if (pos + cc > xcc) xcc = pos + cc; // set new length X xpp[xcc] = 0; X validate(); X } X@@ -8029,7 +8048,7 @@ X ***************************************************************************/ X X Vxstring::Vxstring(int ii) // constructor X-{ X+{ X pdata = 0; X nd = ii; X if (nd) pdata = new xstring[nd]; X@@ -8109,13 +8128,13 @@ X { X kk = strcmp(pdata[ii],string); // check element X X- if (kk > 0) X+ if (kk > 0) X { X ii -= jj; // too high, go down X if (ii < 0) return -1; X } X X- else if (kk < 0) X+ else if (kk < 0) X { X ii += jj; // too low, go up X if (ii > nn) return -1; X@@ -8125,11 +8144,11 @@ X X jj = jj / 2; // reduce increment X X- if (jj == 0) X+ if (jj == 0) X { X jj = 1; // step by 1 element X if (! rkk) rkk = kk; // save direction X- else X+ else X { X if (rkk > 0) { if (kk < 0) return -1; } // if change direction, fail X else if (kk > 0) return -1; X@@ -8291,7 +8310,7 @@ X } X X if (strEqu(string,table+pos)) return -2; // string already present X- } X+ } X X return -3; // table full (trys1 exceeded) X } X@@ -8317,7 +8336,7 @@ X table[pos] = -1; // delete table entry X return (pos/cc); // return rel. table entry X } X- } X+ } X X zappcrash("HashTab::Del() bug",null); // exceed trys2, must not happen X return 0; // (table too full to function) X@@ -8338,7 +8357,7 @@ X if (pos >= cap * cc) pos = 0; // last position wraps to 1st X if (! table[pos]) return -1; // empty slot, string not found X if (strEqu(string,table+pos)) return (pos/cc); // string found, return rel. entry X- } X+ } X X zappcrash("HashTab::Find() bug",null); // cannot happen X return 0; X@@ -8382,12 +8401,12 @@ X { X pos = ii * cc; X X- if (table[pos] && table[pos] != -1) X+ if (table[pos] && table[pos] != -1) X printf("%d, %s \n", ii, table + pos); X X- if (table[pos] == -1) X+ if (table[pos] == -1) X printf("%d, deleted \n", pos); X- } X+ } X X return 1; X } X@@ -8400,7 +8419,7 @@ X Queue::Queue(int cap) // constructor X { X int err; X- X+ X err = mutex_init(&qmutex, 0); // create mutex = queue lock X if (err) zappcrash("Queue(), mutex init fail",null); X X@@ -8454,7 +8473,7 @@ X { X double elaps = 0.0; X int count; X- X+ X if (strNeq(wmi,"queue")) zappcrash("Queue::push wmi fail",null); X X lock(); // lock queue X@@ -8479,7 +8498,7 @@ X xstring *Queue::pop1() // get 1st (oldest) entry and remove X { X xstring *entry; X- X+ X if (strNeq(wmi,"queue")) zappcrash("Queue::pop1 wmi fail",null); X X lock(); // lock queue X@@ -8500,7 +8519,7 @@ X xstring *Queue::popN() // get last (newest) entry and remove X { X xstring *entry; X- X+ X if (strNeq(wmi,"queue")) zappcrash("Queue::popN wmi fail",null); X X lock(); // lock queue X@@ -8528,7 +8547,7 @@ X Node numbers are in the sequence added using put() with names, X or the same as those numbers used in put() with numbers. X X- Internal code conventions: X+ Internal code conventions: X - caller level is node 0, next level is node 1, etc. X - node names and numbers in calls to get() and put() refer to next levels X - number of levels = 1+nn, where nn is max. in calls to put(...nodes[], nn) X@@ -8549,7 +8568,7 @@ X nsub = 0; X psub = 0; X X- if (name) X+ if (name) X { X int cc = strlen(name); X tname = new char[cc+1]; X@@ -8581,7 +8600,7 @@ X int Tree::put(void *data, int dd, char *nodes[], int nn) X { X Tree *tnode; X- X+ X if (wmi != wmid) zappcrash("not a Tree",null); X tnode = make(nodes,nn); X if (tnode->tdata) free(tnode->tdata); X@@ -8598,7 +8617,7 @@ X int Tree::put(void *data, int dd, int nodes[], int nn) X { X Tree *tnode; X- X+ X if (wmi != wmid) zappcrash("not a Tree",null); X tnode = make(nodes,nn); X if (tnode->tdata) free(tnode->tdata); X@@ -8641,7 +8660,7 @@ X Tree * Tree::find(char *nodes[], int nn) X { X int ii; X- X+ X for (ii = 0; ii < nsub; ii++) X if (psub[ii]->tname && strEqu(nodes[0],psub[ii]->tname)) break; X if (ii == nsub) return 0; X@@ -8668,7 +8687,7 @@ X { X int ii; X Tree **psub2; X- X+ X for (ii = 0; ii < nsub; ii++) X if (psub[ii]->tname && strEqu(nodes[0],psub[ii]->tname)) break; X X@@ -8727,12 +8746,12 @@ X void Tree::dump(int level) X { X cchar *name; X- X+ X if (! tname) name = "noname"; X else name = tname; X printf("%*s level: %d name: %s subs: %d mem: %d \n", X level*2,"",level,name,nsub,tmem); X- for (int ii = 0; ii < nsub; ii++) X+ for (int ii = 0; ii < nsub; ii++) X if (psub[ii]) psub[ii]->dump(level+1); X } X X@@ -8745,7 +8764,7 @@ X { X nn[0] += 1; X nd[0] += tmem; X- for (int ii = 0; ii < nsub; ii++) X+ for (int ii = 0; ii < nsub; ii++) X if (psub[ii]) psub[ii]->stats(&nn[1],&nd[1]); X } X f71ad47b5e1ace4342b0c1104a5ad99e echo x - fotoxx/files/patch-zfuncs.h sed 's/^X//' >fotoxx/files/patch-zfuncs.h << 'fee0d12d3fb9870e68672952a50f893f' X--- zfuncs.h.orig 2011-02-28 11:04:24.000000000 -0500 X+++ zfuncs.h 2011-03-10 13:33:22.000000000 -0500 X@@ -36,7 +36,10 @@ X #include X #include X #include X-#include X+/** #include **/ X+#include X+#include X+ X X #define int8 char // number types X #define int16 short fee0d12d3fb9870e68672952a50f893f echo x - fotoxx/files/patch-Makefile sed 's/^X//' >fotoxx/files/patch-Makefile << 'dcf2ef27ff692751e50d3b92bebb83a1' X--- Makefile.orig 2011-02-28 11:04:24.000000000 -0500 X+++ Makefile 2011-04-05 13:55:37.000000000 -0400 X@@ -6,7 +6,7 @@ X X # defaults for parameters that may be pre-defined X CXXFLAGS ?= -O3 -g -Wall X-LDFLAGS ?= -O3 -g -Wall -rdynamic X+LDFLAGS ?= -O3 -g -Wall -rdynamic -I/usr/local/include -lexecinfo X PREFIX ?= /usr/local X X CFLAGS = $(CXXFLAGS) -c `pkg-config --cflags gtk+-2.0` X@@ -21,7 +21,6 @@ X X $(PROGRAM): $(PROGRAM).o zfuncs.o X $(CXX) $(LFLAGS) -ltiff -o $(PROGRAM) $(PROGRAM).o zfuncs.o X- @ ./dependencies.sh X X $(PROGRAM).o: $(SOURCE) X $(CXX) $(CFLAGS) -o $(PROGRAM).o $(SOURCE) \ X@@ -42,8 +41,6 @@ X cp -f icons/* $(DESTDIR)$(ICONDIR) X cp -f -R locales/* $(DESTDIR)$(DATADIR)/locales X cp -f $(PROGRAM) $(DESTDIR)$(BINDIR) X- @ echo use make menu to install desktop menu X- @ echo use make manpage to install man page X X menu: X cp -f desktop $(DESTDIR)$(DESKTOP) dcf2ef27ff692751e50d3b92bebb83a1 echo x - fotoxx/files/patch-dependencies.sh sed 's/^X//' >fotoxx/files/patch-dependencies.sh << '9fffdc6f3c23accf94966a7a311898a2' X--- dependencies.sh.orig 2011-02-28 11:04:24.000000000 -0500 X+++ dependencies.sh 2011-03-28 08:52:03.000000000 -0400 X@@ -1,4 +1,4 @@ X-#! /bin/bash X+#!/bin/sh X # X # Check if dependencies are installed before build. X # X@@ -7,15 +7,15 @@ X # but they are required at run time to handle EXIF data X # and RAW files from digital cameras. X X-dlist=" g++ /usr/include/gtk-2.0/gtk/gtk.h X- /usr/include/tiffio.h /usr/lib*/libtiff.so X- xdg-open xdg-desktop-menu exiftool" X+dlist=" /usr/local/include/gtk-2.0/gtk/gtk.h X+ /usr/local/include/tiffio.h /usr/local/lib/libtiff.so X+ /usr/local/bin/xdg-open /usr/local/bin/xdg-desktop-menu /usr/local/bin/exiftool" X X error=0 X X for dname in $dlist X do X- if [ ${dname:0:1} = "/" ] X+ if [ ${dname#/*} = ${dname} ] X then find $dname >/dev/null 2>&1 X else which $dname >/dev/null X fi X@@ -40,7 +40,7 @@ X X for dname in $dlist X do X- if [ ${dname:0:1} = "/" ] X+ if [ ${dname#/*} = ${dname} ] X then find $dname >/dev/null 2>&1 X else which $dname >/dev/null X fi 9fffdc6f3c23accf94966a7a311898a2 exit