From gnats@FreeBSD.org  Fri Apr  8 01:56:58 2011
Return-Path: <gnats@FreeBSD.org>
Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34])
	by hub.freebsd.org (Postfix) with ESMTP id 6AED91065672
	for <freebsd-gnats-submit@FreeBSD.org>; Fri,  8 Apr 2011 01:56:58 +0000 (UTC)
	(envelope-from gnats@FreeBSD.org)
Received: from freefall.freebsd.org (freefall.freebsd.org [IPv6:2001:4f8:fff6::28])
	by mx1.freebsd.org (Postfix) with ESMTP id 3EC2B8FC0C
	for <freebsd-gnats-submit@FreeBSD.org>; Fri,  8 Apr 2011 01:56:58 +0000 (UTC)
Received: from freefall.freebsd.org (localhost [127.0.0.1])
	by freefall.freebsd.org (8.14.4/8.14.4) with ESMTP id p381uv3I055694
	for <freebsd-gnats-submit@FreeBSD.org>; Fri, 8 Apr 2011 01:56:57 GMT
	(envelope-from gnats@freefall.freebsd.org)
Received: (from gnats@localhost)
	by freefall.freebsd.org (8.14.4/8.14.4/Submit) id p381uvGR055693;
	Fri, 8 Apr 2011 01:56:57 GMT
	(envelope-from gnats)
Message-Id: <201104080156.p381uvGR055693@freefall.freebsd.org>
Date: Fri, 8 Apr 2011 01:56:57 GMT
From: Rod Person <rodperson@rodperson.com>
To: freebsd-gnats-submit@FreeBSD.org
Subject: [New Port] graphics/fotoxx, image editor and collection manager
X-Send-Pr-Version: www-3.1
X-GNATS-Notify:

>Number:         156265
>Category:       ports
>Synopsis:       [New Port] graphics/fotoxx, image editor and collection manager
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    decke
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Fri Apr 08 02:00:23 UTC 2011
>Closed-Date:    Thu May 26 08:56:32 UTC 2011
>Last-Modified:  Thu May 26 09:00:21 UTC 2011
>Originator:     Rod Person
>Release:        8.2 Stable
>Organization:
>Environment:
FreeBSD atomizer.opensourcebeef.net 8.2-STABLE FreeBSD 8.2-STABLE #1: Wed Mar 23 11:29:03 EDT 2011     roddierod@atomizer.opensourcebeef.net:/usr/obj/usr/src/sys/ATOMIZER  i386

>Description:
fotoxx is an image editor and collection manager written in C++.
http://kornelix.squarespace.com/fotoxx
>How-To-Repeat:

>Fix:
# 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 <rodperson@rodperson.com>
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 <bsd.port.mk>
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 <tiffio.h>
X #include "zfuncs.h"
X 
X+
X+//Including the next two allows the use of getpwuid() instead of cuserid()
X+#include <sys/types.h>
X+#include <pwd.h>
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/<user>/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/<user>/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 <sys/event.h>
X+#include <sys/types.h>
X+#include <sys/times.h>
X+#include <pwd.h>
X+#include <execinfo.h>
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 <signal.h>
X #include <execinfo.h>
X #include <locale.h>
X-#include <sys/inotify.h>
X+/** #include <sys/inotify.h> **/
X+#include <sys/event.h>
X+#include <sys/types.h>
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
>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: freebsd-ports-bugs->decke 
Responsible-Changed-By: decke 
Responsible-Changed-When: Tue May 24 08:08:39 UTC 2011 
Responsible-Changed-Why:  
I'll take it. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=156265 
State-Changed-From-To: open->closed 
State-Changed-By: decke 
State-Changed-When: Thu May 26 08:56:31 UTC 2011 
State-Changed-Why:  
New port added with lots of changes. Please check if I have broken any 
of your patches because I needed to rewrite them quite a bit. Hope you 
have a look at the latest release and submit an update. Thanks! 

http://www.freebsd.org/cgi/query-pr.cgi?pr=156265 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: ports/156265: commit references a PR
Date: Thu, 26 May 2011 08:51:11 +0000 (UTC)

 decke       2011-05-26 08:50:57 UTC
 
   FreeBSD ports repository
 
   Modified files:
     graphics             Makefile 
   Added files:
     graphics/fotoxx      Makefile distinfo pkg-descr pkg-plist 
     graphics/fotoxx/files patch-Makefile patch-dependencies.sh 
                           patch-fotoxx-11.03.cc patch-zfuncs.cc 
                           patch-zfuncs.h 
   Log:
   Fotoxx is a free open source Linux program for photo editing
   and collection management. The goal is to meet most user needs
   while remaining fast and easy to use.
   
   WWW:    http://kornelix.squarespace.com/fotoxx
   
   PR:             ports/156265
   Submitted by:   Rod Person <rodperson@rodperson.com>
   
   Revision  Changes    Path
   1.1403    +1 -0      ports/graphics/Makefile
   1.1       +37 -0     ports/graphics/fotoxx/Makefile (new)
   1.1       +2 -0      ports/graphics/fotoxx/distinfo (new)
   1.1       +26 -0     ports/graphics/fotoxx/files/patch-Makefile (new)
   1.1       +37 -0     ports/graphics/fotoxx/files/patch-dependencies.sh (new)
   1.1       +43 -0     ports/graphics/fotoxx/files/patch-fotoxx-11.03.cc (new)
   1.1       +119 -0    ports/graphics/fotoxx/files/patch-zfuncs.cc (new)
   1.1       +17 -0     ports/graphics/fotoxx/files/patch-zfuncs.h (new)
   1.1       +5 -0      ports/graphics/fotoxx/pkg-descr (new)
   1.1       +98 -0     ports/graphics/fotoxx/pkg-plist (new)
 _______________________________________________
 cvs-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/cvs-all
 To unsubscribe, send any mail to "cvs-all-unsubscribe@freebsd.org"
 
>Unformatted:
