/********************************************************************************

   Fotocx - edit photos and manage collections

   Copyright 2007-2024 Michael Cornelison
   source code URL: https://kornelix.net
   contact: mkornelix@gmail.com

   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version. See https://www.gnu.org/licenses

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
   See the GNU General Public License for more details.

*********************************************************************************/

#include <sys/wait.h>
#include <tiffio.h>
#include <png.h>
#include "jpeglib.h"
#include "zfuncs.h"

//  Fotocx definitions

#define Frelease  "fotocx-24.70"                                                 //  current release                       24.70
#define Flicense  "Free software - GNU General Public License v.3"
#define Fwebsite  "https://kornelix.net/fotocx/fotocx.html"                      //  fotocx web site
#define Fgitlab   "https://gitlab.com/fotocx"                                    //  GitLab home
#define Fprivacy  "https://gitlab.com/fotocx/fotocx/wikis/privacy"               //  Gitlab privacy policy
#define Fcontact  "mkornelix@gmail.com"
#define MEGA (1024.0 * 1024.0)                                                   //  2**20
#define GIGA (1024.0 * MEGA)                                                     //  2**30
#define PI 3.141592654
#define RAD (180.0/PI)

//  PXM and PXB pixel address arithmetic                                         //  PXM / PXB >4 GB

#define PXMpix(PXM,px,py) (PXM->pixels+(int64)(1)*(py)*(PXM->rs)+(px)*(PXM->nc))
#define PXBpix(PXB,px,py) (PXB->pixels+(int64)(1)*(py)*(PXB->rs)+(px)*(PXB->nc))
#define PIXBRIGHT(pix) (0.25*(pix)[0]+0.65*(pix)[1]+0.10*(pix)[2])

//  compile time limits that could be increased

#define Xsmp 64                                                                  //  max. SMP compute threads to use
#define thumbfilesize 512                                                        //  thumbnail file pixel size
#define wwhh_limit1 50000                                                        //  max. image width or height
#define wwhh_limit2 (1024 * MEGA)                                                //  max. image width x height             24.60
#define maxtopfolders 200                                                        //  max. no. of top image folders
#define indexrecl 2000                                                           //  max. image index rec. (>XFCC >tagFcc)
#define maximages 1000000                                                        //  max. image files supported
#define maxgallery 100000                                                        //  max. gallery/folder files supported
#define maxworldcities 100000                                                    //  max entries in worldcities.txt
#define SFmax 100000                                                             //  max files for select_files()

#define ANCC   100                                                               //  max album name
#define AFCC   300                                                               //  max album file name (path)
#define maxalbums 300                                                            //  max total albums                      24.20
#define maxalbumfiles maxgallery                                                 //  max files in one album

//  metadata keys for embedded image metadata

#define meta_ww_key "ImageWidth"                                                 //  image width and height
#define meta_hh_key "ImageHeight"                                                //  (replace meta_wwhh_key)
#define meta_date_key "DateTimeOriginal"                                         //  photo date/time
#define meta_file_date_key "FileModifyDate"                                      //  yyyy-mm-dd hh:mm:ss
#define meta_image_size_key "ImageSize"                                          //  pixel width height
#define meta_file_size_key "FileSize"                                            //  bytes

#define meta_creator_key "Creator"                             //  others: artist, by-line, author, photographer
#define meta_description_key "Description"                     //  others: imagedescription, comment, usercomment, caption
#define meta_title_key "Title"                                 //  others: subject, headline

#define meta_orientation_key "Orientation"                                       //  orientation (number format)
#define meta_rollangle_key "RollAngle"                                           //  roll angle - canera tilt error
#define meta_edithist_key "ImageHistory"                                         //  edit history log
#define meta_copyright_key "Copyright"                                           //  image copyright
#define meta_tags_key "Keywords"                                                 //  comma-delimited list for image search
#define meta_rating_key "Rating"                                                 //  star rating, 0-5 stars

#define meta_city_key "City"                                                     //  city or location name (geotags)
#define meta_country_key "Country"                                               //  country name
#define meta_lati_key "GPSLatitude"                                              //  latitude in degrees (-180 to +180)
#define meta_longi_key "GPSLongitude"                                            //  longitude in degrees (-180 to +180)

#define meta_make_key "Make"                                                     //  camera make
#define meta_model_key "Model"                                                   //  camera model
#define meta_lens_key "Lens"                                                     //  camera lens 
#define meta_exp_key "ExposureTime"                                              //  photo exposure time
#define meta_fn_key "FNumber"                                                    //  F-number or aperture
#define meta_fl_key "FocalLength"                                                //  focal length, real
#define meta_fl_35_key "FocalLengthIn35mmFormat"                                 //  focal length, 35mm equivalent
#define meta_iso_key "ISO"                                                       //  ISO speed/sensitivity

//  metadata tag limits ("keywords" metadata key)

#define maxtags 10000                                                            //  max overall tags
#define maxtagcats 200                                                           //  max tag categories
#define tagXcc  50                                                               //  max cc for one tag or category ID
#define catgXcc 20000                                                            //  max tag cc per catg (textwidget_append())
#define filetagsXcc 1000                                                         //  max tag cc for one image file
#define batchtagsXcc 1000                                                        //  max tag cc for batch add tags
#define searchtagsXcc 500                                                        //  max tag cc for search tags
#define recenttagsXcc 300                                                        //  max tag cc for recent tags

#define maxcapkeys 20                                                            //  max captions (metadata items/keys)
#define capsXcc 2000                                                             //  max captions text (metadata text)
#define maxbatchkeys 50                                                          //  max metadata items in batch report
#define maxviewkeys 50                                                           //  max extra metadata items (view metadata)
#define xmetamaxkeys 20                                                          //  max extra indexed metadata items
#define xmetaXcc 1000                                                            //  max extra indexed metadata total cc
#define metakeyXcc 80                                                            //  max cc for metadata key name
#define metadataXcc 2000                                                         //  max cc for metadata key data
#define edithistXcc 200                                                          //  max edit hist cc (per edit step)

//  GTK/GDK definitions

#define TEXTWIN GTK_TEXT_WINDOW_TEXT
#define NODITHER GDK_RGB_DITHER_NONE
#define ALWAYS GTK_POLICY_ALWAYS
#define NEVER GTK_POLICY_NEVER
#define AUTO GTK_POLICY_AUTOMATIC
#define GDKRGB GDK_COLORSPACE_RGB
#define LINEATTRIBUTES GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER
#define BILINEAR GDK_INTERP_BILINEAR
#define HYPER GDK_INTERP_HYPER
#define NEAREST GDK_INTERP_NEAREST
#define SCROLLWIN GTK_SCROLLED_WINDOW
#define VERTICAL GTK_ORIENTATION_VERTICAL
#define HORIZONTAL GTK_ORIENTATION_HORIZONTAL
#define MWIN GTK_WINDOW(Mwin)

//  externals from zfuncs module

namespace zfuncs {
   extern GdkDisplay    *display;                                                //  X11 workstation (KB, mouse, screen)
   extern GdkScreen     *screen;                                                 //  monitor (screen)
   extern GdkDevice     *mouse;                                                  //  pointer device
   extern GtkSettings   *settings;                                               //  screen settings
   extern GtkWidget     *mainwin;                                                //  main window for zfuncs parent
   extern ch            *build_date_time;                                        //  build date and time
   extern ch            *progexe;                                                //  executable path name
   extern int           Floglevel;                                               //  message log level, 1/2/3 = errs/info/all
   extern int           Fescape;                                                 //  zdialog, escape key pressed
   extern int           monitor_ww, monitor_hh;                                  //  monitor pixel dimensions
   extern ch            *appfont;                                                //  app font ("sans 10")
   extern int           appfontsize;                                             //  app font size
   extern ch            zappname[40];                                            //  app name/version
   extern ch            zimagedir[200];                                          //  where application image files live
   extern int           Nmalloc, Nstrdup, Nfree;                                 //  malloc() strdup() free() counters
   extern int           vmenuclickposn;                                          //  Vmenu icon click position, 0-100
   extern int           vmenuclickbutton;                                        //  Vmenu button: 1/3 = left/right mouse
   extern int           vmenustop;                                               //  Vmenu setupfunc() stop flag
   extern int           zdialog_count;                                           //  zdialog count (new - free)
   extern int           zdialog_busy;                                            //  open zdialog count (run - destroy)
   extern zdialog       *zdialog_list[zdialog_max];                              //  active zdialog list
   extern pthread_t     tid_main;                                                //  main() thread ID
   extern float         splcurve_minx;                                           //  min. anchor point dist, % scale
   extern ch            *zappcrash_context1, *zappcrash_context2;                //  zappcrash context data
}

//  gallery files table

enum FTYPE { IMAGE, RAW, VIDEO, FDIR, THUMB, OTHER, FNF };                       //  file types, FNF = file not found
enum GTYPE { TNONE, FOLDER, SEARCH, META, RECENT, NEWEST, ALBUM };               //  gallery types
enum GSORT { SNONE, FNAME, FNUMBER, FDATE, PDATE, FSIZE, PSIZE, MDATA };         //  gallery sort types
enum GSEQ  { QNONE, ASCEND, DESCEND };                                           //  gallery sort sequence

struct Gindex_t  {                                                               //  gallery index
   ch       *file = 0;                                                           //  /folder.../filename
   int      folder;                                                              //  flag, this is a folder
   ch       fdate[16];                                                           //  file date: yyyymmddhhmmss
   ch       pdate[16];                                                           //  photo date: yyyymmddhhmmss
   int      fsize;                                                               //  file size, bytes
   int      psize;                                                               //  image size, pixels
   ch       *mdata1 = 0;                                                         //  fixed text for metadata report
   ch       *mdata2 = 0;                                                         //  variable text for metadata report
};

//  externals from f.gallery

namespace navi                                                                   //  gallery() data
{
   extern Gindex_t *Gindex;                                                      //  gallery index
   extern int      Gmdrows;                                                      //  text rows in metadata list
   extern int      Gfiles;                                                       //  gallery file count (images + subdirs)
   extern int      Gfolders;                                                     //  gallery subfolder count
   extern int      Gimages;                                                      //  gallery image file count
   extern ch       *galleryname;                                                 //  folder path or gallery type name
   extern GTYPE    gallerytype;                                                  //  gallery type: folder, recent, etc.
   extern GSORT    gallerysort;                                                  //  filename/file-date/photo-date
   extern GSEQ     galleryseq;                                                   //  ascending/descending
   extern int      gallerypainted;                                               //  gallery paint is complete
   extern int      galleryposn;                                                  //  gallery target scroll position
   extern int      scrollposn;                                                   //  current scroll position
   extern int      xwinW, xwinH;                                                 //  image gallery window size
   extern int      thumbsize;                                                    //  curr. thumbnail display size
   extern int      genthumbs;                                                    //  counts thumbnails generated
   extern double   thumbcache_MB;                                                //  thumbnail cache size, MB

   int    gallery_paint(GtkWidget *, cairo_t *);                                 //  gallery window paint function
   void   menufuncx(GtkWidget *, ch *menu);                                      //  gallery menu buttons function
   void   changefolder(GtkWidget *widget, GdkEventButton *event);                //  gallery folder change function
   void   newtop(GtkWidget *widget, GdkEventButton *event);                      //  gallery change top folder function
   void   newalbum(GtkWidget *widget, GdkEventButton *event);                    //  gallery change album function
   int    mouse_event(GtkWidget *, GdkEvent *, void *);                          //  gallery window mouse event function
   ch   * gallery_dragfile();                                                    //  gallery window file drag function
   void   gallery_dropfile(int mx, int my, ch *file);                            //  gallery window file drop function
   int    KBaction(ch *action);                                                  //  gallery window KB key function
}

EX ch       *SelFiles[SFmax];                                                    //  select_files(), selected files list
EX int      SFcount;                                                             //  select_files(), file count

//  GTK etc. parameters

EX GtkWidget      *Mwin, *MWhbox, *MWvbox, *MWmenu;                              //  main window containers
EX GtkWidget      *Fhbox, *Fvbox, *Fpanel, *Fpanlab, *Fdrawin;                   //  F window widgets, file view
EX GtkWidget      *Ghbox, *Gvbox, *Gsep, *Gpanel, *Gtop, *Galbum;                //  G window widgets, gallery view
EX GtkWidget      *Gscroll, *Gdrawin;
EX GtkAdjustment  *Gadjust;
EX GtkWidget      *Mhbox, *Mvbox;                                                //  M window widgets, map view
EX GtkWidget      *Cdrawin;                                                      //  curr. drawing window, Fdrawin
EX GdkWindow      *gdkwin;                                                       //  corresp. GDK window
EX PIXBUF         *BGpixbuf;                                                     //  window background pixbuf

EX GdkCursor      *arrowcursor;                                                  //  main window cursors
EX GdkCursor      *dragcursor;
EX GdkCursor      *targcursor;
EX GdkCursor      *drawcursor;
EX GdkCursor      *blankcursor;
EX GdkCursor      *dotcursor;

EX int      BLACK[3], WHITE[3], RED[3], GREEN[3], BLUE[3];                       //  RGB values 0-255
EX int      LINE_COLOR[3];                                                       //  line drawing color, one of the above

EX draw_context_t  draw_context;                                                 //  GDK window drawing context

//  user preferences and settings

EX ch       *menu_style;                                                         //  menu style: icons/text/both
EX int      FBrgb[3];                                                            //  F view background color, RGB 0-255
EX int      GBrgb[3];                                                            //  G view background color, RGB 0-255
EX int      MFrgb[3];                                                            //  menu font color, RGB 0-255
EX int      MBrgb[3];                                                            //  menu background color, RGB 0-255
EX int      iconsize;                                                            //  menu icon size
EX ch       *dialog_font;                                                        //  dialog font e.g. "sans 10"
EX ch       *startalbum;                                                         //  start album: file name
EX ch       *startdisplay;                                                       //  start view: recent/prev/blank/file/folder
EX ch       *startfolder;                                                        //  start folder (startdisplay=folder)
EX ch       *startfile;                                                          //  start image file (startdisplay=file)
EX int      Fdragopt;                                                            //  1/2 = 1x drag / magnified scroll
EX int      Fshowhidden;                                                         //  show hidden files in gallery view
EX int      Flastversion;                                                        //  gallery shows last versions only
EX ch       *ImagePosn;                                                          //  F-view image posn: left/center/right
EX int      Faskquit;                                                            //  ask to quit option
EX int      zoomcount;                                                           //  zoom count to reach 2x (1-8)
EX float    zoomratio;                                                           //  corresp. zoom ratio: 2**(1/zoomcount)
EX int      map_dotsize;                                                         //  map dot size / mouse capture size
EX int      captext_cc[2];                                                       //  captions text line cc range
EX int      jpeg_def_quality;                                                    //  default jpeg save quality
EX int      tiff_comp_method;                                                    //  TIFF file compression method
EX ch       *raw_loader_command;                                                 //  RAW file loader command
EX int      Fraw_match_embed;                                                    //  match RAW colors to embedded image
EX ch       *RAWfiletypes;                                                       //  recognized RAW files: .raw .rw2 ...
EX ch       *VIDEOfiletypes;                                                     //  recognized video files: .mov .mp4 ...

//  menu name and function table

typedef void menufunc_t(GtkWidget *,ch *);                                       //  menu function type

struct menutab_t {
   GtkWidget    *topmenu;                                                        //  parent menu
   ch           *menu = 0;                                                       //  menu text
   ch           *icon = 0;                                                       //  menu icon
   ch           *desc = 0;                                                       //  menu short description (tooltip)
   menufunc_t   *func;                                                           //  menu function (GtkWidget *, ch *)
   ch           *arg = 0;                                                        //  argument
};

#define CCC (XFCC*2+200)                                                         //  max. command line size
EX ch       command[CCC];                                                        //  (command, parameters, 2 filespecs)

#define maxmenus 250
EX menutab_t   menutab[maxmenus];
EX int         Nmenus;

//  KB shortcut tables

struct kbsftab_t {                                                               //  eligible menus for KB shortcut
   ch          *menu = 0;                                                        //  menu name
   menufunc_t  *func;                                                            //  function
   ch          *arg = 0;                                                         //  argument
};

#define maxkbsf 200                                                              //  functions that can have KB shortcuts
EX kbsftab_t   kbsftab[maxkbsf];
EX int         Nkbsf;

struct kbsutab_t {                                                               //  user-defined shortcuts
   ch          *key = 0;                                                         //  key name, e.g. "Shift+U"
   ch          *menu = 0;                                                        //  menu name, e.g. "Redo"
};

#define maxkbsu 100                                                              //  max. KB shortcuts
EX kbsutab_t   kbsutab[maxkbsu];
EX int         Nkbsu;

//  general parameters

EX int         NSMP;                                                             //  no. SMP compute threads to use
EX int         Fdevmenu;                                                         //  flag, show developer menu
EX ch          desktopname[100];                                                 //  locale specific desktop folder
EX ch          *Prelease;                                                        //  prior fotocx version
EX int         Ffirsttime;                                                       //  first time startup
EX int         mwgeom[4];                                                        //  main window position and size
EX pid_t       fotocxPID;                                                        //  my process PID
EX int         *Nval;                                                            //  static integer values 0-maximages
EX ch          FGM;                                                              //  curr. view mode: 'F' 'G' 'M'
EX ch          PFGM;                                                             //  prior view mode
EX int         Fdcraw;                                                           //  flag, dcraw installed
EX int         Fexiftool;                                                        //  flag, exiftool installed
EX int         Fheif;                                                            //  flag, heif-convert installed
EX int         Fjp2;                                                             //  flag, opj_decompress installed
EX int         Fwebp;                                                            //  flag, dwebp installed
EX int         Fvlc;                                                             //  flag, vlc installed
EX int         Ffmpeg;                                                           //  flag, ffmpeg installed
EX int         Faddr2line;                                                       //  flag, addr2line installed
EX int         Fshutdown;                                                        //  flag, app shutdown underway
EX int         Findexlev;                                                        //  0/1/2 = none/old/old+new image files
EX int         FMindexlev;                                                       //  Findexlev if start via file manager
EX int         Fpaintrequest;                                                    //  window paint request pending
EX int         Fpaintlock;                                                       //  main window paint is blocked
EX int         Fmetamod;                                                         //  image metadata unsaved changes
EX int         Ffullscreen;                                                      //  flag, window is fullscreen
EX int         Fpanelshow;                                                       //  show or hide F view top panel
EX int         Fmashup;                                                          //  flag, mashup function is active
EX int         Fslideshow;                                                       //  flag, slide show is active
EX int         Fview360;                                                         //  flag, view360 function is active
EX int         Nfuncbusy;                                                        //  top panel: function is busy/working
EX int         Frecent;                                                          //  start with recent files gallery
EX int         Fnew;                                                             //  start with newly added files gallery
EX int         Fprev;                                                            //  start with previous file
EX int         Fblank;                                                           //  start with blank window
EX int         Fmousevents;                                                      //  show popup text of mouse events
EX ch          *topmenu;                                                         //  latest top-menu selection
EX ch          *initial_menu;                                                    //  menu on command line
EX ch          *initial_file;                                                    //  file name on command line
EX ch          *initial_album;                                                   //  album name on command line
EX ch          *video_command;                                                   //  command to show video file
EX ch          *F1_help_topic;                                                   //  current function help topic
EX int         Fcaps;                                                            //  toggle captions on or off
EX ch          *topfolders[maxtopfolders];                                       //  user top-level image folders
EX int         Ntopfolders;                                                      //  topfolders[] count
EX ch          *misstops[maxtopfolders];                                         //  missing top folders (not mounted)
EX int         Nmisstops;                                                        //  missing top folders count
EX ch          *blacklist[1000];                                                 //  list of blacklisted folders/files
EX int         Nblacklist;                                                       //  blacklist count
EX ch          *thumbfolder;                                                     //  thumbnails folder
EX ch          *curr_file;                                                       //  current image file
EX ch          curr_file_type[8];                                                //  jpg / tif / png / other
EX int         curr_file_bpc;                                                    //  image file bits/color, 8/16
EX uint        curr_file_size;                                                   //  image file size on disk
EX int         curr_file_posn;                                                   //  position in current gallery, 0-last
EX ch          *recent_folders[10];                                              //  recently used file folders
EX ch          meta_edithist[metadataXcc];                                       //  EXIF edit history text
EX int         meta_edithist_cc0;                                                //  edit history text cc at file open
EX int         Fmeta_edithist;                                                   //  edit history loaded for curr. file
EX ch          *curr_album;                                                      //  current or last used album
EX ch          *copymove_loc;                                                    //  last used copy/move to location
EX ch          *clicked_file;                                                    //  image file / thumbnail clicked
EX int         clicked_posn;                                                     //  clicked gallery position (Nth)
EX int         clicked_width;                                                    //  clicked thumbnail position
EX int         clicked_height;                                                   //    (normalized 0-100)
EX ch          *imagefiletypes;                                                  //  supported image types: .jpg .png etc.
EX ch          *colormapfile;                                                    //  curr. printer color map file
EX ch          *RGB_chooser_file;                                                //  user's color chooser image file
EX ch          paneltext[200];                                                   //  top panel application text

EX int         Fscriptbuild;                                                     //  edit script build is in-progress
EX ch          scriptfile[200];                                                  //  current script file name
EX FILE        *script_fid;                                                      //  current script file FID
EX int         Fscriptrun;                                                       //  flag, script file is active

EX ch          f_load_type[8];                                                   //  data set by PXB/PXM_load()
EX int         f_load_bpc;
EX int         f_load_bpc_raw;
EX int         f_load_size;
EX ch          *f_save_file;                                                     //  data set by PXB/PXM_save()
EX ch          f_save_type[8];
EX int         f_save_bpc;
EX uint        f_save_size;

EX int         index_updates;                                                    //  file indexing progress counters
EX int         thumb_updates;
EX int         thumb_deletes;

//  files and folders in Fotocx home folder (normally /home/<user>/.fotocx)

EX ch          index_folder[200];                                                //  image index folder
EX ch          image_folders_file[200];                                          //  top image and thumbnail folders
EX ch          image_index_file[200];                                            //  image index file
EX ch          meta_index_file[200];                                             //  extra metadata index items
EX ch          parameters_file[200];                                             //  fotocx parameters file
EX ch          albums_folder[200];                                               //  saved image albums
EX ch          custom_kernel_folder[200];                                        //  custom convolution kernels
EX ch          markup_folder[200];                                               //  saved markup text
EX ch          mashup_folder[200];                                               //  mashup projects
EX ch          image_array_maps_folder[200];                                     //  image array map files
EX ch          palettes_folder[200];                                             //  color palett files
EX ch          pattern_folder[200];                                              //  pattern files
EX ch          printer_color_folder[200];                                        //  printer calibration
EX ch          saved_areas_folder[200];                                          //  saved select area files
EX ch          saved_curves_folder[200];                                         //  saved curve data
EX ch          scripts_folder[200];                                              //  script files
EX ch          saved_searches_folder[200];                                       //  saved search dialogs
EX ch          slideshow_folder[200];                                            //  slide show files
EX ch          slideshow_trans_folder[200];                                      //  slide show transition files
EX ch          temp_folder[200];                                                 //  temp. files folder
EX ch          tags_defined_file[200];                                           //  tags defined file
EX ch          recentfiles_file[200];                                            //  file of recent image files
EX ch          recent_folders_file[200];                                         //  file of recently used folders
EX ch          gallerymem_file[200];                                             //  file for recent galleries memory
EX ch          searchresults_file[200];                                          //  file for search results
EX ch          meta_picklist_file[200];                                          //  metadata keyname picklist
EX ch          meta_view_extras_file[200];                                       //  view metadata optional keynames
EX ch          meta_report_items_file[200];                                      //  metadata report keynames
EX ch          KB_shortcuts_file[200];                                           //  KB shortcuts file
EX ch          blacklist_file[200];                                              //  file for blacklisted folders/files
EX ch          capskeys_file[200];                                               //  metadata keys for image captions
EX ch          raw_commands_file[200];                                           //  file for RAW file loader commands
EX ch          bookmarks_file[200];                                              //  file for gallery bookmarks
EX ch          custom_menu_file[200];                                            //  file for user custom menu functions
EX ch          map_regions_file[200];                                            //  internet map regions file
EX ch          plugins_file[200];                                                //  plugin menu functions file

//  fotocx PXM and PXB pixmaps

struct PXM {                                                                     //  PXM pixmap, 3|4 x float per pixel
   ch          wmi[8];                                                           //  self-identifier
   int         ww, hh, nc, rs;                                                   //  width, height, channels, row stride
   float       *pixels;                                                          //  ww * hh * nc * sizeof(float)
};

struct PXB {                                                                     //  PXB pixmap, 3|4 x uint8/pixel
   ch          wmi[8];                                                           //  self-identifier
   int         ww, hh, nc, rs;                                                   //  width, height, channels, row stride
   uint8       *pixels;                                                          //  hh * rs bytes (in pixbuf)
   PIXBUF      *pixbuf;                                                          //  parallel GDK pixbuf sharing pixels
};

//  parameters for F/W image window painting (functions Fpaint() etc.)

struct Fstate_t {
   PXB         *fpxb;                                                            //  image PXB, size = 1x
   PXB         *mpxb;                                                            //  image PXB, size = Mscale
   int         morgx, morgy;                                                     //  Dpxb origin in Mpxb image
   int         dorgx, dorgy;                                                     //  Dpxb origin in drawing window
   float       fzoom;                                                            //  image zoom scale (0 = fit window)
   float       mscale;                                                           //  scale factor, 1x image to window image
   float       pscale;                                                           //  prior scale factor
};

EX Fstate_t    Fstate;                                                           //  parameters for F view windows
EX Fstate_t    *Cstate;

#define Fpxb   Fstate.fpxb                                                       //  F/W window parameters
#define Mpxb   Fstate.mpxb
#define Morgx  Fstate.morgx
#define Morgy  Fstate.morgy
#define Dorgx  Fstate.dorgx
#define Dorgy  Fstate.dorgy
#define Fzoom  Fstate.fzoom
#define Mscale Fstate.mscale
#define Pscale Fstate.pscale

EX PXM         *E0pxm;                                                           //  edit pixmap, original image
EX PXM         *E1pxm;                                                           //  edit pixmap, base image for editing
EX PXM         *E3pxm;                                                           //  edit pixmap, edited image
EX PXM         *ERpxm;                                                           //  edit pixmap, undo/redo image
EX PXM         *E8pxm;                                                           //  scratch image for some functions
EX PXM         *E9pxm;                                                           //  scratch image for some functions

EX int         Dww, Dhh;                                                         //  main/drawing window size
EX int         dww, dhh;                                                         //  Dpxb size in drawing window, <= Dww, Dhh
EX int         zoomx, zoomy;                                                     //  req. zoom center of window

EX int         Mbutton;                                                          //  mouse button, 1/3 = left/right
EX int         Mwxposn, Mwyposn;                                                 //  mouse position, window space
EX int         Mxposn, Myposn;                                                   //  mouse position, image space
EX int         LMclick, RMclick;                                                 //  mouse left, right click
EX int         Mxclick, Myclick;                                                 //  mouse click position, image space
EX int         Mdrag;                                                            //  mouse drag underway
EX int         mouse_dragtime;                                                   //  current drag duration, milliseconds
EX double      wacom_pressure;                                                   //  Wacom tablet, stylus pressure 0.0 to 1.0
EX int         Mwdragx, Mwdragy;                                                 //  drag increment, window space
EX int         Mxdown, Mydown, Mxdrag, Mydrag;                                   //  mouse drag vector, image space
EX int         Fmousemain;                                                       //  mouse acts on main window not dialog
EX int         Mcapture;                                                         //  mouse captured by edit function
EX int         Mradius;                                                          //  mouse circle radius
EX int         MCpower, MEpower;                                                 //  mouse paint power, center and edge

EX int         KBcapture;                                                        //  KB key captured by edit function
EX int         KBkey;                                                            //  active keyboard key
EX int         KBcontrolkey;                                                     //  keyboard key states, 1 = down
EX int         KBshiftkey;
EX int         KBaltkey;

//  lines, text and circles drawn over window image whenever repainted

struct topline_t {
   int      x1, y1, x2, y2;                                                      //  endpoint coordinates in image space
   int      type;                                                                //  1/2/3/4 = black/white/both/dash
};

#define maxtoplines 8                                                            //  max. top lines
EX topline_t   toplines[8], ptoplines[8];                                        //  top lines, prior top lines
EX int         Ntoplines, Nptoplines;                                            //  current counts

struct toptext_t {
   int      ID, px, py;
   ch       *text = 0;
   ch       *font = 0;
};

#define maxtoptext 100                                                           //  max. text strings
EX toptext_t   toptext[100];                                                     //  text strings
EX int         Ntoptext;                                                         //  current count

struct topcircle_t {                                                             //  circle drawn over image
   int      px, py;
   int      radius;
};

#define maxtopcircles 200                                                        //  max. circles on image
EX topcircle_t    topcircles[200];                                               //  circles
EX int            Ntopcircles;                                                   //  current count

//  select area data

#define sa_initseq 10                     //  initial sequence number (0/1/2 reserved)
#define sa_maxseq 9999                    //  ultimate limit 64K

#define sa_mode_rect       1              //  select rectangle by drag/click
#define sa_mode_ellipse    2              //  select ellipse by drag
#define sa_mode_draw       3              //  freehand draw by drag/click
#define sa_mode_follow     4              //  follow edge indicated by clicks
#define sa_mode_mouse      5              //  select area within mouse (radius)
#define sa_mode_onecolor   6              //  select one matching color within mouse
#define sa_mode_allcolors  7              //  select all matching colors within mouse

#define sa_stat_none       0              //  no select area present
#define sa_stat_edit       1              //  select area edit mode
#define sa_stat_fini       2              //  select area finished, enabled
#define sa_stat_disab      3              //  select area finished, disabled

EX VOL int     sa_stat;                                                          //  select area status
EX int         sa_mode;                                                          //  select area edit method
EX uint16      sa_endpx[10000], sa_endpy[10000];                                 //  last pixel drawn per sequence no.
EX int         sa_thresh;                                                        //  mouse pixel distance threshold
EX int         sa_mouseradius;                                                   //  mouse selection radius
EX int         sa_searchrange;                                                   //  search range (* mouse radius)
EX int         sa_mousex, sa_mousey;                                             //  mouse position in image
EX int         sa_lastx, sa_lasty;                                               //  last selected mouse position
EX float       sa_colormatch;                                                    //  color range to match (0.001 to 1.0)
EX int         sa_edgecalc_done;                                                 //  edge distance calculation done
EX int         sa_edgecalc_busy;                                                 //  edge distance calculation busy
EX int         sa_minx, sa_maxx;                                                 //  enclosing rectangle for area
EX int         sa_miny, sa_maxy;
EX ch          *sa_stackdirec;                                                   //  pixel search stack
EX int         *sa_stack;
EX int         sa_maxstack;
EX int         sa_Nstack;
EX int         sa_currseq;                                                       //  current select sequence no.
EX int         sa_Ncurrseq;                                                      //  current sequence pixel count
EX uint8       *sa_pixselc;                                                      //  maps pixels selected in current cycle
EX uint16      *sa_pixmap;                                                       //  0/1/2+ = outside/edge/inside edge dist
EX uint8       *sa_pixmap2;                                                      //  maps mouse-selected pixels
EX uint        sa_Npixel;                                                        //  total select area pixel count
EX int         sa_fww, sa_fhh;                                                   //  valid image dimensions for select area
EX int         Fshowarea;                                                        //  show/hide select area outline
EX int         areanumber;                                                       //  increasing sequential number

EX int         gridsettings[9];                                                  //  grid line settings
#define GON    0                                                                 //    [0]  grid lines on/off
#define GX     1                                                                 //    [1]  x-lines on/off
#define GY     2                                                                 //    [2]  y-lines on/off
#define GXS    3                                                                 //    [3]  x-lines spacing
#define GYS    4                                                                 //    [4]  y-lines spacing
#define GXC    5                                                                 //    [5]  x-lines count
#define GYC    6                                                                 //    [6]  y-lines count
#define GXF    7                                                                 //    [7]  x-lines offset
#define GYF    8                                                                 //    [8]  y-lines offset

//  Image index record.
//  pdate, wwhh, tags, title, desc, gtags may have "null" (char) as a missing value.

struct xxrec_t {
   ch          *file = 0;                                                        //  image filespec
   ch          fdate[16];                                                        //  file date, yyyymmddhhmmss
   ch          pdate[16];                                                        //  EXIF photo date, yyyymmddhhmmss
   ch          rating[4];                                                        //  meta rating, "0" to "5" stars
   int         ww, hh;                                                           //  image width x height, pixels
   int         fsize;                                                            //  image file size, bytes
   ch          *tags = 0;                                                        //  meta tags
   ch          *title = 0;                                                       //  meta title
   ch          *desc = 0;                                                        //  meta description
   ch          *location = 0;                                                    //  city, park, monument ...
   ch          *country = 0;                                                     //  country
   float       flati, flongi;                                                    //  earth coordinates
   ch          *xmeta = 0;                                                       //  extra indexed metadata
};

EX xxrec_t     **xxrec_tab;                                                      //  image index table, file sequence
EX int         Nxxrec;                                                           //  count, < maximages
EX int         Findexvalid;                                                      //  0/1/2 = no / old files / old+new files
EX ch          *xmeta_keys[xmetamaxkeys];                                        //  extra indexed metadata key names

//  image edit function data

struct editfunc {                                                                //  edit function data
   ch          *menuname = 0;                                                    //  menu name in menutab[*]
   ch          edit_hist[edithistXcc];                                           //  metadata edit history text
   int         FprevReq;                                                         //  request to use smaller image if poss.
   int         Farea;                                                            //  area: 0/1/2 = delete/ignore/usable
   int         Fmods;                                                            //  flag, image modifications by this func
   int         Fpreview;                                                         //  flag, using smaller image for edits
   int         Fpaintedits;                                                      //  flag, OK to use with paint edits
   int         Fscript;                                                          //  flag, function can be scripted
   int         Fsaved;                                                           //  current mods are saved to disk
   zdialog     *zd = 0;                                                          //  edit dialog
   spldat      *sd = 0;                                                          //  edit curve data
   void        (*menufunc)(GtkWidget *, ch *);                                   //  edit menu function in menutab[*]
   void *      (*threadfunc)(void *);                                            //  edit thread function
   void        (*mousefunc)();                                                   //  edit mouse function
};

EX editfunc *CEF;                                                                //  current active edit function

EX int         Eww, Ehh;                                                         //  dimensions of image being edited

EX int         Fpaintedits;                                                      //  paint_edits() is active

EX int         editpixels_pxlo;                                                  //  get_edit_pixels() image area:
EX int         editpixels_pxhi;                                                  //   - mouse circle box enclosure
EX int         editpixels_pylo;                                                  //   - select area box enclosure
EX int         editpixels_pyhi;                                                  //   - full image

//  edit undo/redo stack data

#define maxedits 100                                                             //  undo/redo stack size
EX ch          URS_filename[200];                                                //  stack image filename template
EX int         URS_pos;                                                          //  stack position, 0-99
EX int         URS_max;                                                          //  stack max. position, 0-99
EX ch          URS_menu[100][32];                                                //  edit function menu name
EX ch          URS_parms[100][edithistXcc];                                      //  edit parameters or null
EX int         URS_saved[100];                                                   //  flag, edit saved to file or not

struct textattr_t {                                                              //  attributes for gentext() function
   ch       text[1000];                                                          //  text to generate image from
   ch       font[80];                                                            //  font name
   int      size;                                                                //  font size
   int      tww, thh;                                                            //  generated image size, unrotated
   float    angle;                                                               //  text angle, degrees
   float    sinT, cosT;                                                          //  trig funcs for text angle
   ch       color[4][20];                                                        //  text, backing, outline, shadow "R|G|B"
   int      transp[4];                                                           //  corresponding transparencies 0-255
   int      towidth;                                                             //  outline width, pixels
   int      shwidth;                                                             //  shadow width
   int      shangle;                                                             //  shadow angle -180...+180
   int      emboss[2];                                                           //  emboss radius, depth
   PXB      *pxb_text;                                                           //  image with text/outline/shadow
};

struct lineattr_t {                                                              //  attributes for genline() function
   int      length, width;                                                       //  line length and width, pixels
   int      larrow, rarrow;                                                      //  left/right arrow head size (0 = no arrow)
   int      lww, lhh;                                                            //  generated image size, unrotated
   float    angle;                                                               //  line angle, degrees
   float    sinT, cosT;                                                          //  trig funcs for line angle
   ch       color[4][20];                                                        //  line, background, outline, shadow "R|G|B"
   int      transp[4];                                                           //  corresponding transparencies 0-255
   int      towidth;                                                             //  outline width, pixels
   int      shwidth;                                                             //  shadow width
   int      shangle;                                                             //  shadow angle -180...+180
   PXB      *pxb_line;                                                           //  image with line/outline/shadow
};

//  dialogs with global visibility

EX zdialog     *zd_paintedits;                                                   //  m_paint_edits(), control dialog
EX zdialog     *zd_RGB_hist;                                                     //  brightness histogram window
EX zdialog     *zd_darkbrite;                                                    //  highlight dark/bright pixels zdialog
EX zdialog     *zd_editmeta;                                                     //  edit metadata zdialog
EX zdialog     *zd_editanymeta;                                                  //  edit any metadata zdialog
EX zdialog     *zd_deletemeta;                                                   //  delete metadata zdialog
EX zdialog     *zd_batchtags;                                                    //  batch tags zdialog
EX zdialog     *zd_metaview;                                                     //  view metadata zdialog
EX zdialog     *zd_filesave;                                                     //  file save zdialog
EX zdialog     *zd_rename;                                                       //  rename file zdialog
EX zdialog     *zd_permissions;                                                  //  file permissions dialog
EX zdialog     *zd_copymove;                                                     //  copy/move file zdialog
EX zdialog     *zd_deltrash;                                                     //  delete/trash zdialog
EX zdialog     *zd_sela;                                                         //  select area zdialog
EX zdialog     *zd_magnify;                                                      //  magnify image zdialog
EX zdialog     *zd_album_update;                                                 //  album_replacefile zdialog
EX zdialog     *zd_select_files1;                                                //  select_files1 zdialog
EX zdialog     *zd_select_files;                                                 //  select_files zdialog
EX zdialog     *zd_edit_bookmarks;                                               //  bookmarks edit zdialog
EX zdialog     *zd_ss_imageprefs;                                                //  slide show image prefs zdialog

//  method for created threads to send events to an active zdialog

EX zdialog     *zd_thread;                                                       //  active zdialog
EX ch          *zd_thread_event;                                                 //  event to send

//  edit function parameters

EX int         cropx1, cropy1, cropx2, cropy2;                                   //  crop rectangle NW and SE corners
EX ch          *cropsizes[10];                                                   //  previous crop sizes "NNNNxNNNN"
EX ch          *cropbuttons[5];                                                  //  crop dialog button labels
EX ch          *cropratios[5];                                                   //  corresponding aspect ratios
EX int         editrescale[2];                                                   //  edit rescale width, height
EX int         Fupright;                                                         //  flag, image was uprighted
EX int         Flevel;                                                           //  flag, image was levelled

//  initialization and GTK functions (fotocx main)

int   check_outboards(int fshow);                                                //  check required/optional program installs
int   main(int argc, ch * argv[]);                                               //  main program
void  first_index();                                                             //  initial user indexing decision
int   delete_event();                                                            //  window delete event function
int   destroy_event();                                                           //  window destroy event function
int   state_event(GtkWidget *, GdkEvent *event);                                 //  window state event function
void  drop_event(int mousex, int mousey, ch *file);                              //  file drag-drop event function
int   gtimefunc(void *arg);                                                      //  periodic function
void  update_Fpanel();                                                           //  update top panel information
void  update_progress();                                                         //  update top panel progress or 'working'
void  Funcbusy(int delta, int Fsleep = 0);                                       //  incr/decr function busy status
int   Fblock(ch *funcname);                                                      //  block/unblock mutex functions
int   paintlock(int lock);                                                       //  block/unblock main window updates
int   Fpaint(GtkWidget *, cairo_t *);                                            //  F and W drawing area paint function
void  Fpaintnow();                                                               //  window repaint synchronously
void  Fpaint2();                                                                 //  window repaint (thread callable)
void  Fpaint3(int px, int py, int ww, int hh, cairo_t *cr);                      //  update Mpxb area from updated E3 area
void  Fpaint0(int px, int py, int ww, int hh, cairo_t *cr);                      //  update Mpxb area from updated E0 area
void  Fpaint4(int px, int py, int ww, int hh, cairo_t *cr);                      //  update Dpxb area from updated Mpxb
void  Fpaint3_thread(int px, int py, int ww, int hh);                            //  Fpaint3 for threads (define update area)
void  Fpaint3_main();                                                            //  update Fpaint3 area in main thread
void  Fpaintmouse(int mxposn, int mypons, int radius);                           //  update Mpxb area for mouse painted E3 area
void  mouse_event(GtkWidget *, GdkEventButton *, void *);                        //  mouse event function
void  m_zoom(GtkWidget *, ch *);                                                 //  zoom image +/-
void  KBevent(GdkEventKey *event);                                               //  pass dialog KB events to main app
int   KBpress(GtkWidget *, GdkEventKey *, void *);                               //  KB key press event function
int   KBrelease(GtkWidget *, GdkEventKey *, void *);                             //  KB key release event function
void  win_fullscreen(int hidemenu);                                              //  full screen without menu/panel
void  win_unfullscreen();                                                        //  restore to prior size with menu etc.
void  set_mwin_title();                                                          //  main window title = curr_file path

//  cairo drawing functions (fotocx main)

void  draw_pixel(int px, int py, cairo_t *cr, int mode = 0);                     //  draw pixel
void  erase_pixel(int px, int py, cairo_t *cr);                                  //  erase pixel
void  draw_line(int x1, int y1, int x2, int y2, int type, cairo_t *cr);          //  draw line or dotted line (type 1/2)
void  erase_line(int x1, int y1, int x2, int y2, cairo_t *cr);                   //  erase line
void  draw_toplines(int arg, cairo_t *cr);                                       //  draw all pre-set overlay lines
void  draw_gridlines(cairo_t *cr);                                               //  draw grid lines on image
void  add_toptext(int ID, int px, int py, ch *text, ch *font);                   //  add text string with ID on window
void  draw_toptext(cairo_t *cr);                                                 //  draw text strings when window repainted
void  erase_toptext(int ID);                                                     //  remove all text strings with ID
void  draw_text(int px, int py, ch *text, ch *font, cairo_t *cr);                //  draw text on window
void  add_topcircle(int px, int py, int radius);                                 //  draw circle on window
void  draw_topcircles(cairo_t *cr);                                              //  draw circles when window repainted
void  erase_topcircles();                                                        //  remove all circles
void  draw_mousecircle(int cx, int cy, int rad, int Ferase, cairo_t *cr);        //  draw circle around mouse pointer
void  draw_mousecircle2(int cx, int cy, int rad, int Ferase, cairo_t *cr);       //  2nd circle for m_copypixels1()
void  draw_mousearc(int cx, int cy, int ww, int hh, int Ferase, cairo_t *cr);    //  draw ellipse around pointer

float RGBmatch(uint8 r1, uint8 g1, uint8 b1, uint8 r2, uint8 g2, uint8 b2);      //  match two RGB values
float RGBmatch(float r1, float g1, float b1, float r2, float g2, float b2);      //    0 - 1.0 = perfect match
float RGBmatch(float r1, float g1, float b1, uint8 r2, uint8 g2, uint8 b2);
float PIXmatch(uint8 *pix1, uint8 *pix2);                                        //  match two RGB pixels
float PIXmatch(float *pix1, float *pix2);                                        //    0 - 1.0 = perfect match
float PIXmatch(float *pix1, uint8 *pix2);
void  RGBfix(float &R, float &G, float &B);                                      //  fix overflows, preserve colors
void  RGBfix(int &R, int &G, int &B);

//  edit support functions (fotocx main)

int   edit_wwhhOK(int ww, int hh);                                               //  check image size within limits
int   edit_setup(editfunc &EF);                                                  //  start new edit transaction
void  edit_cancel(int keep);                                                     //  cancel edit (keep zdialog etc.)
void  edit_fullsize();                                                           //  convert to full-size pixmaps
void  edit_done(int keep);                                                       //  commit edit, add undo stack
void  edit_undo();                                                               //  undo edit, back to org. image
void  edit_redo();                                                               //  redo the edit after undo
void  edit_reset();                                                              //  reset to initial status
void  edit_addhist(ch *format, ...);                                             //  edit params > editfunc.edit_hist

void  m_undo_redo(GtkWidget *, ch *);                                            //  undo / redo if left / right mouse click
void  m_undo(GtkWidget *, ch *);                                                 //  undo one edit
void  m_redo(GtkWidget *, ch *);                                                 //  redo one edit
void  undo_all();                                                                //  undo all edits of current image
void  redo_all();                                                                //  redo all edits of current image
void  save_undo();                                                               //  undo/redo save function
PXM * load_undo(int posn);                                                       //  load image from undo/redo stack

typedef void mcbFunc();                                                          //  callback function type
EX mcbFunc   *mouseCBfunc;                                                       //  current edit mouse function
void  takeMouse(mcbFunc func, GdkCursor *);                                      //  capture mouse for edit dialog
void  freeMouse();                                                               //  free mouse for main window

//  thread support functions (fotocx main)

typedef void * threadfunc(void *);                                               //  thread function type
void  thread_start(threadfunc func, void *arg);                                  //  start thread in idle state
void  thread_signal();                                                           //  signal thread that work is pending
void  thread_stop();                                                             //  stop thread and wait for exit
void  thread_wait();                                                             //  wait for thread to become idle
void  do_wthreads(threadfunc func, int Nt);                                      //  thread: start worker threads and wait

//  progress tracking functions (fotocx main)

void  progress_setgoal(double goal);                                             //  reset progress counters, set goal value
void  progress_setvalue(double value);                                           //  set current progress value, 0 - goal
void  progress_addvalue(double value);                                           //  accumulate progress value
void  progress_setvalue(int tid, double value);                                  //  set thread progress value
void  progress_addvalue(int tid, double value);                                  //  increment thread progress value
int   progress_percent();                                                        //  get current progress as percent 0-100

//  save and load parameters (fotocx main)

void  save_params();                                                             //  save parameters for next session
void  load_params();                                                             //  load parameters from prior session

void  free_resources(int fkeepundo = 0);                                         //  free resources associated with curr file

//  window and menu builder (f.widgets.cc)

void  build_widgets();                                                           //  build widgets for F/G/W/M view modes
void  popup_menufunc(GtkWidget *, ch *menu);                                     //  image/thumb right-click menu func
void  image_Rclick_popup();                                                      //  popup menu for image right-click
void  gallery_Lclick_func(int Nth);                                              //  function for thumbnail left-click
void  gallery_Rclick_popup(int Nth);                                             //  popup menu for thumbnail right-click
void  m_viewmode(GtkWidget *, ch *fgm);                                          //  set F/G/M view mode - menu func
void  viewmode(ch fgm);                                                          //  set F/G/M view mode - callable
void  m_custom_menu(GtkWidget *, ch *);                                          //  build custom user menu
void  m_edit_script(GtkWidget *, ch *);                                          //  build script file with N edit funcs
void  edit_script_addfunc(editfunc *);                                           //  edit_done() hook to add script func
void  m_run_script(GtkWidget *, ch *);                                           //  run script on current image file
void  m_batch_script(GtkWidget *, ch *);                                         //  run script on batch of image files
void  m_plugins(GtkWidget *, ch *);                                              //  plugins menu function
void  m_edit_plugins(GtkWidget *, ch *);                                         //  edit plugin function
void  m_run_plugin(GtkWidget *, ch *);                                           //  run plugin function
ch  * find_outfile(ch *infile, double modtime);                                  //  find plugin output file

//  pixmap/pixbuf memory image and file I/O functions (f.pixmap.cc)

int64 imagesize(int ww, int hh, int nc, int pz);                                 //  get image size (pz = 1/4 for PXB/PXM)
PXM * PXM_make(int ww, int hh, int nc);                                          //  create a PXM pixmap
void  PXM_free(PXM *&pxm);                                                       //  free PXM pixmap
void  PXM_audit(PXM *pxm);                                                       //  audit contents of a PXM pixmap
void  PXM_clear(PXM *pxm, int BW);                                               //  clear PXM pixmap to value BW (0/255)
void  PXM_addalpha(PXM *pxm);                                                    //  add alpha channel to PXM pixmap
void  PXM_subalpha(PXM *pxm);                                                    //  remove alpha channel from PXM pixmap
void  PXM_applyalpha(PXM *pxm);                                                  //  apply alpha channel to RGB values
PXM * PXM_copy(PXM *pxm);                                                        //  copy PXM pixmap >> created PXM
void  PXM_copy(PXM *pxm1, PXM *pxm2);                                            //  copy PXM to existing PXM of equal size
PXM * PXM_copy_area(PXM *pxm, int orgx, int orgy, int ww, int hh);               //  copy PXM section to a new PXM
void  PXM_copy_area(PXM *pxm1, PXM *pxm2, int orgx, int orgy, int ww, int hh);   //  copy PXM section into another PXM
void  PXM_copy_area(PXM *pxm1, PXM *pxm2, int orgx1, int orgy1,                  //  copy PXM section into another PXM
                      int orgx2, int orgy2, int ww, int hh);                     //    (with destination offset)
PXM * PXM_rescale(PXM *pxm, int ww, int hh);                                     //  rescale PXM pixmap (ww/hh)
PXM * PXM_rotate(PXM *pxm, float angle, int fast = 0);                           //  rotate PXM pixmap
PXM * PXM_upright(PXM *pxm, int angle, int mirror);                              //  upright PXM pixmap (rotate and mirror)
void  PXM_blur(PXM *pxm, int radius);                                            //  blur PXM pixmap image using blur radius
void  PXM_rgbdepth(PXM *pxm, int depth);                                         //  set PXM pixmap image RGB color depth 1-16

PXB * PXB_make(int ww, int hh, int nc);                                          //  create a PXB pixmap
void  PXB_free(PXB *&pxb);                                                       //  free PXB pixmap
void  PXB_clear(PXB *pxb);                                                       //  clear PXB pixmap to zeros (black)
int   PXB_addalpha(PXB *pxb);                                                    //  add alpha channel to PXB pixmap
int   PXB_subalpha(PXB *pxb);                                                    //  remove alpha channel from PXB pixmap
PXB * PXB_copy(PXB *pxb);                                                        //  copy (duplicate) PXB pixmap
void  PXB_copy_area(PXB *, int, int, int, int, PXB *, int, int);                 //  copy area from one PXB to another
PXB * PXB_subpxb(PXB *pxb1, int px1, int py1, int ww, int hh);                   //  create new PXB from PXB section
PXB * PXB_half(PXB *pxb1);                                                       //  rescale PXB pixmap to 1/2 size
PXB * PXB_rescale(PXB *pxb, int ww, int hh);                                     //  rescale PXB pixmap (ww/hh)
PXB * PXB_rescale_fast(PXB *pxb1, int ww, int hh);                               //  rescale  " " faster, less quality
PXB * PXB_rescale(PXB *pxb1, int size);                                          //  rescale PXB pixmap to max. ww/hh
PXB * PXB_rescale_fast(PXB *pxb1, int size);                                     //  rescale PXB pixmap to max. ww/hh
PXB * PXB_rotate(PXB *pxb, float angle);                                         //  rotate PXB pixmap

int   vpixel(PXB *pxb, float px, float py, uint8 *vpix);                         //  get PXB virtual pixel at (px,py)
int   vpixel(PXM *pxm, float px, float py, float *vpix);                         //  get PXM virtual pixel at (px,py)

PXB * PXM_PXB_copy(PXM *pxm);                                                    //  PXM to pixbuf, same scale
void  PXM_PXB_update(PXM *, PXB *, int px3, int py3, int ww3, int hh3);          //  update PXB area from PXM, same scale
void  PXB_PXB_update(PXB *, PXB *, int px3, int py3, int ww3, int hh3);          //  update PXB area from PXB, any scale

PXB * PXB_load(ch *filespec, int fack);                                          //  load file to PXB pixmap, 8 bpc
PXM * PXM_load(ch *filespec, int fack);                                          //  load file to PXM pixmap, 8/16 bpc
int   PXB_save(PXB *pxb, ch *filespec, int bpc, int quality, int fack);          //  save PXB pixmap to file
int   PXM_save(PXM *pxm, ch *filespec, int bpc, int quality, int fack);          //  save PXM pixmap to file

PXB * JPG_PXB_load(ch *file, int size = 0);                                      //  JPG file to PXB, 8 bpc
PXM * JPG_PXM_load(ch *file);                                                    //  JPG file to PXM, 8 bpc
int   PXB_JPG_save(PXB *pxb, ch *file, int quality);                             //  PXB to JPG file, 8 bpc
int   PXM_JPG_save(PXM *pxm, ch *file, int quality);                             //  PXM to JPG file, 8 bpc

PXB * HEIC_PXB_load(ch *file, int size = 0);                                     //  HEIC file to PXB, 8 bpc
PXM * HEIC_PXM_load(ch *file);                                                   //  HEIC file to PXM, 8 bpc
int   PXB_HEIC_save(PXB *pxb, ch *file);                                         //  PXB to HEIC file, 8 bpc
int   PXM_HEIC_save(PXM *pxm, ch *file);                                         //  PXM to HEIC file, 8 bpc

PXB * JP2_PXB_load(ch *file);                                                    //  JP2 file to PXB, 8 bpc
PXM * JP2_PXM_load(ch *file);                                                    //  JP2 file to PXM, 8 bpc
int   PXB_JP2_save(PXB *pxb, ch *file);                                          //  PXB to JP2 file, 8 bpc
int   PXM_JP2_save(PXM *pxm, ch *file);                                          //  PXM to JP2 file, 8 bpc

PXB * WEBP_PXB_load(ch *file);                                                   //  WEBP file to PXB, 8 bpc
PXM * WEBP_PXM_load(ch *file);                                                   //  WEBP file to PXM, 8 bpc
int   PXB_WEBP_save(PXB *pxb, ch *file);                                         //  PXB to WEBP file, 8 bpc
int   PXM_WEBP_save(PXM *pxm, ch *file);                                         //  PXM to WEBP file, 8 bpc

PXB * PDF_PXB_load(ch *file);                                                    //  PDF/PS/EPS file to PXB, 8 bpc
PXM * PDF_PXM_load(ch *file);                                                    //  PDF/PS/EPS file to PXM, 8 bpc
int   PXB_PDF_save(PXB *pxb, ch *file);                                          //  PXB to PDF/PS/EPS file, 8 bpc
int   PXM_PDF_save(PXM *pxm, ch *file);                                          //  PXM to PDF/PS/EPS file, 8 bpc

PXB * TIFF_PXB_load(ch *filespec);                                               //  TIFF file to PXB, 8 bpc
PXM * TIFF_PXM_load(ch *filespec);                                               //  TIFF file to PXM, 8/16 bpc
int   PXB_TIFF_save(PXB *pxb, ch *filespec, int bpc);                            //  PXB to TIFF file, 8/16 bpc
int   PXM_TIFF_save(PXM *pxm, ch *filespec, int bpc);                            //  PXM to TIFF file, 8/16 bpc

PXB * PNG_PXB_load(ch *filespec);                                                //  PNG file to PXB, 8 bpc, keep alpha
PXM * PNG_PXM_load(ch *filespec);                                                //  PNG file to PXM, 8/16 bpc
int   PXB_PNG_save(PXB *pxb, ch *filespec, int bpc);                             //  PXB to PNG file, 8/16 bpc
int   PXM_PNG_save(PXM *pxm, ch *filespec, int bpc);                             //  PXM to PNG file, 8/16 bpc

PXB * ANY_PXB_load(ch *filespec);                                                //  ANY file to PXB, 8 bpc
PXM * ANY_PXM_load(ch *filespec);                                                //  ANY file to PXM, 8 bpc

PXB * RAW_PXB_load(ch *rawfile, int matchthumb);                                 //  RAW file to PXB, 8 bpc
PXM * RAW_PXM_load(ch *rawfile, int matchthumb);                                 //  RAW file to PXM, 16 bpc
PXB * RAW_thumb_pxb(ch *rawfile);                                                //  RAW file to PXB for thumbnail creation

void pixelvert(uint8  *buff1, uint8  *buff2, int ww, int hh, int nc1, int nc2);  //  convert pixel buffer format
void pixelvert(uint8  *buff1, uint16 *buff2, int ww, int hh, int nc1, int nc2);  //    and/or channel count
void pixelvert(uint8  *buff1, float  *buff2, int ww, int hh, int nc1, int nc2);
void pixelvert(uint16 *buff1, uint8  *buff2, int ww, int hh, int nc1, int nc2);
void pixelvert(uint16 *buff1, uint16 *buff2, int ww, int hh, int nc1, int nc2);
void pixelvert(uint16 *buff1, float  *buff2, int ww, int hh, int nc1, int nc2);
void pixelvert(float  *buff1, uint8  *buff2, int ww, int hh, int nc1, int nc2);
void pixelvert(float  *buff1, uint16 *buff2, int ww, int hh, int nc1, int nc2);
void pixelvert(float  *buff1, float  *buff2, int ww, int hh, int nc1, int nc2);

//  file menu functions (f.file.cc)

void  m_new_session(GtkWidget *, ch *);                                          //  start parallel fotocx session
void  new_session(ch *args);                                                     //  callable function
void  m_open_file(GtkWidget *, ch *);                                            //  file open dialog
void  m_open_drag(int x, int y, ch *file);                                       //  open drag-drop file
void  m_cycle2files(GtkWidget *, ch *);                                          //  open/cycle 2 previous files
void  m_cycle3files(GtkWidget *, ch *);                                          //  open/cycle 3 previous files
void  m_view360(GtkWidget *, ch *);                                              //  view a 360 degree panorama
int   f_open(ch *file, int n=0, int kp=0, int ak=1, int z=0);                    //  open new current image file
int   f_open_saved();                                                            //  open saved file, retain undo/redo stack
int   f_remove(ch *file, ch *opt);                                               //  delete/trash file/index/thumb/gallery
void  f_preload(int next);                                                       //  start preload of next file
void  m_prev(GtkWidget *, ch *);                                                 //  open previous file in gallery
void  m_next(GtkWidget *, ch *);                                                 //  open next file in gallery
void  m_prev_next(GtkWidget *, ch *);                                            //  left/right mouse >> prev/next image
void  m_zoom_menu(GtkWidget *, ch *);                                            //  left/right mouse >> image/thumb zoom
void  m_rename(GtkWidget *, ch *);                                               //  rename an image file (same location)
void  m_permissions(GtkWidget *, ch *);                                          //  view and change file permissions
void  m_change_alpha(GtkWidget *, ch *);                                         //  change image file alpha channel
void  m_blank_image(GtkWidget *, ch *);                                          //  create new blank image file
int   create_blank_file(ch *file, int ww, int hh, int RGB[3]);                   //  create new blank image file, callable
void  play_gif(ch *file);                                                        //  play GIF file animation
void  m_copy_move(GtkWidget *, ch *);                                            //  copy or move image file to new location
void  m_copyto_desktop(GtkWidget *, ch *);                                       //  copy image file to desktop
void  m_copyto_clip(GtkWidget *, ch *file);                                      //  copy an image file to the clipboard
void  m_delete_trash(GtkWidget *, ch *);                                         //  delete or trash an image file
void  m_convert_adobe(GtkWidget *, ch *);                                        //  convert adobe file into jpeg image(s)
void  m_wallpaper(GtkWidget *, ch *file);                                        //  current file >> desktop wallpaper
void  m_print_image(GtkWidget *, ch *);                                          //  print an image file
void  m_print_calibrated(GtkWidget *, ch *);                                     //  print an image file with adjusted colors
void  m_calibrate_printer(GtkWidget *, ch *);                                    //  calibrate printer colors
void  m_quit(GtkWidget *, ch *);                                                 //  exit application with checks
void  quitxx();                                                                  //  exit unconditionally
void  m_uninstall(GtkWidget *, ch *);                                            //  uninstall fotocx
void  m_help(GtkWidget *, ch *menu);                                             //  various help menu functions

void  m_file_save(GtkWidget *, ch *);                                            //  save modified image file to disk
void  m_file_save_replace(GtkWidget *, ch *menu);                                //  for KB shortcut Save File (replace)
void  m_file_save_version(GtkWidget *, ch *menu);                                //  for KB shortcut Save File Version
int   f_save(ch *outfile, ch *type, int bpc, int qual, int ack);                 //  save current image file to disk
int   f_save_as();                                                               //  save_as dialog (choose file and bpc)

ch * f_realpath(ch *infile);                                                     //  get real path for file with symlinks
ch * file_rootname(ch *file);                                                    //  get root name without .vNN.ext
ch * file_basename(ch *file);                                                    //  get base name /.../filename.ext
ch ** file_all_versions(ch *file, int &nf);                                      //  get all versions for given file
ch * file_new_version(ch *file);                                                 //  get next avail. file version name
ch * file_newest_version(ch *file);                                              //  get newest version or original file
ch * file_prior_version(ch *file);                                               //  get prior version or original file

int  find_imagefiles(ch *dr, int fgs, ch **&fls, int &nf, int zf = 1);           //  find all image files within a folder

int  regfile(ch *file, struct stat *statb = 0);                                  //  test file is regular file, opt. return stat
int  dirfile(ch *file, struct stat *statb = 0);                                  //  test file is directory, opt. return stat
int  hasperm(ch *file, ch rw);                                                   //  test file exists with 'r'/'w' permission

int  set_permissions(GtkWidget *win, ch *file, ch *p1, ch *p2);                  //  show and set file permissions
int  conv_permissions(ch *perms, mode_t &mode);                                  //  conv. "read+write" etc. to mode_t
int  conv_permissions(mode_t mode, ch *perms);                                   //  conv. mode_t to "read+write" etc.

//  thumbnail gallery and navigation functions (f.gallery.cc)

ch     * gallery(ch *filez, ch *action, int Nth);                                //  display image gallery window, navigate
void     gallery_memory(ch *action);                                             //  save/recall gallery sort and posn.
void     set_gwin_title();                                                       //  main window title = gallery name
ch     * prev_next_file(int index, int lastver);                                 //  get prev/next file with last version option
ch     * prev_next_gallery(int index);                                           //  get prev/next gallery (physical folder)
int      file_position(ch *file, int Nth);                                       //  get rel. position of file in gallery

FTYPE    image_file_type(ch *file);                                              //  FNF folder IMAGE RAW THUMB OTHER
ch     * thumb2imagefile(ch *thumbfile);                                         //  get image file for thumbnail file
ch     * image2thumbfile(ch *imagefile);                                         //  get thumbnail file for image file
int      thumbfile_OK(ch *imagefile);                                            //  check thumbnail file exists and not stale
int      update_thumbfile(ch *imagefile);                                        //  create or refresh thumbnail file
int      thumbfile_set_mod_time(ch *imagefile);                                  //  set thumbnail mod time from image file
void     delete_thumbfile(ch *imagefile);                                        //  delete thumbnail for file
PIXBUF * get_thumb_pixbuf(ch *imagefile);                                        //  get thumbnail pixbuf for image file
void     gallery_popimage();                                                     //  popup big image of clicked thumbnail

ch     * select_files1(ch *gfolder);                                             //  select one file from gallery window
void     select_files1_Lclick_func(int Nth);                                     //  select_files1, thumbnail left-click
void     select_files(int fclear = 0, int fsetcurr = 0);                         //  select files from gallery window      24.20
void     add_file_to_selection(ch *file);                                        //  add file to selection                 24.20
void     select_files_Lclick_func(int Nth);                                      //  select_files, thumbnail left-click
void     select_files_Rclick_func(int Nth);                                      //  select_files, thumbnail right-click

void  m_thumbview(GtkWidget *, ch *);                                            //  gallery, thumbnails + file data
void  m_metaview(GtkWidget *, ch *);                                             //  gallery, thumbnails + basic metadata
void  m_recentfiles(GtkWidget *, ch *);                                          //  gallery of recently viewed files
void  add_recent_file(ch *file);                                                 //  add file to recent file list
void  m_newfiles(GtkWidget *, ch *);                                             //  gallery of newest files
void  m_gallery_sort(GtkWidget *, ch *);                                         //  sort gallery by file, date, size ...
void  m_gallery_screen(GtkWidget *, ch *);                                       //  screen gallery for new, old, pattern match
void  m_current_folder(GtkWidget *, ch *);                                       //  set gallery to current file folder
void  m_recent_folders(GtkWidget *, ch *);                                       //  set gallery to chosen recent folder   24.60
void  add_recent_folder(ch *foldername);                                         //  add current folder to top of list     24.60
void  m_folder_tree(GtkWidget *, ch *);                                          //  list folders, click for gallery
void  m_select_files(GtkWidget *, ch *);                                         //  files for album/batch/script funcs
void  m_rename_folder(GtkWidget *, ch *);                                        //  rename current folder (file gallery)
void  m_add_subfolder(GtkWidget *, ch *);                                        //  add subfolder to existing file gallery

void  m_bookmarks(GtkWidget *, ch *);                                            //  select bookmark, goto gallery posn
void  m_edit_bookmarks(GtkWidget *, ch *);                                       //  edit bookmarks (gallery/file position)
void  edit_bookmarks_Lclick_func(int Nth);                                       //  thumbnail click response function

void  m_thumbframe(GtkWidget *, ch *);                                           //  set video frame for video thumbnail
void  m_show_hidden(GtkWidget *, ch *);                                          //  for KB shortcut "show hidden files"
void  m_current_album(GtkWidget *, ch *);                                        //  for KB shortcut "Current Album"

int   popup_image(ch *imagefile, GtkWindow *parent, int Fnewin, int size);       //  popup window with image

//  albums menu (f.albums.cc)

void  m_manage_albums(GtkWidget *, ch *);                                        //  create and edit image albums
int   album_create_from_gallery(ch *newalbumfile);                               //  create album from current gallery
void  album_show(ch *albumfile = 0);                                             //  set/show current album gallery
void  album_add_selfiles(int mode);                                              //  add selected files to album
void  album_add_currfile(int mode);                                              //  add current file to album
void  album_add_file(ch *file, int posn);                                        //  add one file to album (drag/drop)
void  album_remove_file(int posn);                                               //  remove file from album
void  album_move_file(int pos1, int pos2);                                       //  move file position (drag/drop)
void  album_folder_rename(ch *oldname, ch *newname);                             //  fix album files after folder rename
void  album_purge_replace(ch *album, int Nt, ch **tfile, ch **rfile);            //  purge missing, replace target files
void  album_purge_replace(ch *album, ch *targfile, ch *repfile);                 //  version for single target file
void  m_update_albums(GtkWidget *, ch *);                                        //  update albums for new file version
void  update_albums_Lclick_func(int Nth);                                        //  m_update_albums() thumbnail click
void  m_gallery2album(GtkWidget *, ch *);                                        //  save current gallery as album
void  m_album_mass_update(GtkWidget *, ch *);                                    //  album mass update tools
void  m_cycle_wallpaper(int argc, ch *argv[]);                                   //  cycle wallpaper

//  slide show menu (f.albums.cc)

void  m_slideshow(GtkWidget *, ch *);                                            //  enter or leave slideshow mode
void  ss_imageprefs_Lclick_func(int Nth);                                        //  slideshow image prefs thumbnail click func
void  ss_KBfunc(int KBkey);                                                      //  slideshow keyboard input

//  metadata menu functions (f.meta.cc)

int   select_meta_keys(zlist_t *mlist, int maxout, int Fex);                     //  dialog - select metadata items
void  meta_view(int type);                                                       //  popup metadata report
void  m_meta_view_short(GtkWidget *, ch *);                                      //  view selected metadata
void  m_meta_view_long(GtkWidget *, ch *);                                       //  view all metadata
void  m_meta_edit_main(GtkWidget *, ch *);                                       //  edit date/rating/tags dialog
void  m_meta_edit_any(GtkWidget *, ch *);                                        //  add or change any metadata
void  m_meta_delete(GtkWidget *, ch *);                                          //  delete metadata
void  m_meta_copy(GtkWidget *, ch *);                                            //  copy metadata from one file to another
void  m_meta_fix(GtkWidget *, ch *);                                             //  repair malformed metadata blocking edits
void  m_meta_manage_tags(GtkWidget *, ch *);                                     //  manage tags (keywords)
void  m_meta_choose_caps(GtkWidget *, ch *);                                     //  choose metadata keys for image captions
void  meta_show_caps(int show);                                                  //  show captions on current image
void  m_meta_toggle_caps(GtkWidget *, ch *);                                     //  toggle image captions on/off

void  m_batch_tags(GtkWidget *, ch *);                                           //  add and remove tags
void  m_batch_rename_tags(GtkWidget *, ch *);                                    //  rename tags for all image files
void  m_batch_photo_date_time(GtkWidget *, ch *menu);                            //  change or shift photo dates/times
void  m_batch_change_meta(GtkWidget *, ch *);                                    //  add/change/delete metadata
void  m_batch_report_meta(GtkWidget *, ch *);                                    //  metadata report
void  m_batch_meta_mover(GtkWidget *, ch *);                                     //  move metadata between keys
void  m_batch_geotags(GtkWidget *, ch *menu);                                    //  add or change geotags

void  m_meta_places_dates(GtkWidget *, ch *);                                    //  report images by location and date range
void  m_meta_timeline(GtkWidget *, ch *);                                        //  report images by month
void  m_autosearch(GtkWidget *, ch *);                                           //  search images, write to stdout
void  m_search_images(GtkWidget *, ch *);                                        //  search image metadata

void  metadate_pdate(ch *metadate, ch *pdate, ch *ptime);                        //  "yyyymmddhhmm" > "yyyy-mm-dd" + "hh:mm:ss"
void  load_filemeta(ch *file);                                                   //  load metadata for image file
void  save_filemeta(ch *file);                                                   //  save metadata in file and image index
void  set_meta_wwhh(int ww, int hh);                                             //  set ww/hh outside m_meta_edit()
void  update_image_index(ch *file);                                              //  update image index for image file
void  delete_image_index(ch *file);                                              //  delete image index for image file

void  m_worldmap(GtkWidget *, ch *);                                             //  load the initial world map
void  m_map_regions(GtkWidget *, ch *);                                          //  add custom map regions, goto region
void  m_map_location(GtkWidget *, ch *);                                         //  resolve partial location name, go there
void  m_set_map_markers(GtkWidget *, ch *);                                      //  show markers for all images or gallery
void  paint_map_markers();                                                       //  paint markers on map image locations
void  m_map_zoomin(GtkWidget *, ch *);                                           //  zoom map to given location

int   meta_get1(ch *files, ch **keys, ch **kdat, int NK);                        //  get metadata for file and given keys
int   meta_getN(ch **files, int NF, ch **keys, ch **kdat, int NK);               //  get metadata for multiple files and keys
int   meta_put(ch *file, ch **keys, ch **kdat, int NK);                          //  put metadata for given keys
int   meta_copy(ch *f1, ch *f2, ch **keys, ch **kdat, int NK);                   //  copy metadata from file to file
void  meta_tagdate(ch *metadate, ch *tagdate);                                   //  yyyy:mm:dd:hh:mm:ss to yyyymmddhhmmss
void  tag_metadate(ch *tagdate, ch *metadate);                                   //  yyyymmddhhmmss to yyyy:mm:dd:hh:mm:ss

xxrec_t * get_xxrec(ch *file);                                                   //  get index record from memory table
int put_xxrec(xxrec_t *xxrec, ch *file);                                         //  add/update index table and file
xxrec_t * read_xxrec_seq(int &ftf);                                              //  read image index records 1-last
int write_xxrec_seq(xxrec_t *xxrec, int &ftf);                                   //  write image index records 1-last

//  select area menu functions (f.select.cc)

void  m_select_area(GtkWidget *, ch *);                                          //  select area to edit within image
void  m_select_find_gap(GtkWidget *, ch *);                                      //  find gap in area outline
void  m_select_blend(GtkWidget *, ch *);                                         //  blend area edits using mouse
void  m_select_show(GtkWidget *, ch *);                                          //  enable area for subsequent edits
void  m_select_hide(GtkWidget *, ch *);                                          //  show area outline
void  m_select_enable(GtkWidget *, ch *);                                        //  hide area outline
void  m_select_disable(GtkWidget *, ch *);                                       //  disable area
void  m_select_invert(GtkWidget *, ch *);                                        //  invert area
void  m_select_clear(GtkWidget *, ch *);                                         //  clear area
void  m_select_copy(GtkWidget *, ch *);                                          //  copy area to default file
void  m_select_save(GtkWidget *, ch *);                                          //  copy area to designated file
void  select_copysave(GtkWidget *, ch *menu);                                    //  common function for above two
void  m_select_load(GtkWidget *, ch *);                                          //  load file and paste as area in image
void  m_select_paste(GtkWidget *, ch *);                                         //  paste last copied area into image

void  sa_geom_mousefunc();                                                       //  select rectangle or ellipse
void  sa_draw_mousefunc();                                                       //  edge line drawing function
int   sa_nearpix(int mx, int my, int rad, int &px, int &py, int fx);             //  find nearest pixel
void  sa_draw_line(int px1, int py1, int px2, int py2, cairo_t *cr);             //  draw a connected line
void  sa_draw1pix(int px, int py, cairo_t *cr);                                  //  add one pixel to select area
void  sa_mouse_select();                                                         //  select by mouse (opt. color match)
void  sa_nextseq();                                                              //  start next sequence number
void  sa_unselect_pixels(cairo_t *cr);                                           //  remove current selection
void  sa_pixmap_create();                                                        //  create area pixel maps
void  sa_finish();                                                               //  finish - map interior pixels
void  sa_finish_auto();                                                          //  finish - interior pixels already known
void  sa_unfinish();                                                             //  set finished area back to edit mode
void  sa_map_pixels();                                                           //  map edge and interior pixels
void  sa_show(int flag, cairo_t *cr);                                            //  show or hide area outline
void  sa_show_rect(int px1, int py1, int ww, int hh, cairo_t *cr);               //  show area outline inside a rectangle
int   sa_validate();                                                             //  validate area for curr. image
void  sa_enable();                                                               //  enable area
void  sa_disable();                                                              //  disable area
void  sa_invert();                                                               //  invert area
void  sa_clear();                                                                //  clear area
void  sa_edgecalc();                                                             //  calculate area edge distances
void  sa_edgecreep(int);                                                         //  adjust area edge +/-
void  sa_postfix();                                                              //  copy E1 to E3 outside area, blend E3 edges

//  image edit functions - Edit menu (f.edit.cc)

void  get_edit_pixels_init(int Nthreads, int margin);                            //  get edit pixels initz. (mouse/area/full)
int   get_edit_pixels(int thread, int &px, int &py, float &blend);               //  get edit pixels from image, area, or mouse
void  m_rotate(GtkWidget *, ch *);                                               //  rotate or level image
void  m_upright(GtkWidget *, ch *);                                              //  1-button image upright function
void  m_crop(GtkWidget *, ch *);                                                 //  crop image margins
void  m_retouch(GtkWidget *, ch *);                                              //  brightness, contrast, color
void  blackbodyRGB(int K, float &R, float &G, float &B);                         //  convert deg. K to RGB factors
void  m_rescale(GtkWidget *, ch *);                                              //  rescale image
void  m_margins(GtkWidget *, ch *);                                              //  add margins around image
void  m_markup(GtkWidget *, ch *);                                               //  draw text/line/box/oval on image
void  m_draw_text(GtkWidget *, ch *);                                            //  draw text on image
void  load_text(zdialog *zd);                                                    //  load text and attributes from a file
void  save_text(zdialog *zd);                                                    //  save text and attributes to a file
int   gentext(textattr_t *attr);                                                 //  generate text image from attributes
void  m_draw_line(GtkWidget *, ch *);                                            //  draw line/arrow on image
void  load_line(zdialog *zd);                                                    //  load line attributes from a file
void  save_line(zdialog *zd);                                                    //  save line attributes to a file
int   genline(lineattr_t *attr);                                                 //  generate line/arrow image from attributes
void  m_draw_box(GtkWidget *, ch *);                                             //  draw box on image
void  m_draw_oval(GtkWidget *, ch *);                                            //  draw oval on image
void  m_color_mode(GtkWidget *, ch *);                                           //  B+W/color, negative/positive, sepia
void  m_paint_edits(GtkWidget *, ch *);                                          //  paint edits gradually by mouse painting
void  m_paint_image(GtkWidget *, ch *);                                          //  paint on image with the mouse
int   RGB_chooser(zdialog *zd, ch *butt, uint8 rgb[3]);                          //  dialog, get color from color file
int   HSL_chooser(zdialog *zd, ch *butt, uint8 RGB[3]);                          //  dialog, get color from HSL dialog
void  m_paint_transp(GtkWidget *, ch *);                                         //  paint transparency with the mouse
void  m_area_fill(GtkWidget *, ch *);                                            //  fill selected areas or transparent areas
void  m_copy_in_image(GtkWidget *, ch *);                                        //  copy pixels within one image
void  m_copy_from_image(GtkWidget *, ch *);                                      //  copy pixels from one image to another
void  m_copy_from_image_slave(GtkWidget *, ch *);                                //  source image slave process for the above
void  m_copy_prior_edit(GtkWidget *, ch *);                                      //  undo prior edits by mouse painting
void  m_template(GtkWidget *, ch *);                                             //  edit function template (developer menu)

//  image edit functions - Repair menu (f.repair.cc)

void  m_sharpen(GtkWidget *, ch *);                                              //  sharpen image
void  sharp_AC(int amount, int thresh);                                          //  callable amplify contrast
void  m_blur(GtkWidget *, ch *);                                                 //  blur image - steering dialog
void  m_fix_motionblur(GtkWidget *, ch *);                                       //  reduce blur from camera motion
void  m_denoise(GtkWidget *, ch *);                                              //  image noise reduction
void  m_defog(GtkWidget *, ch *);                                                //  add/remove fog/haze based on brightness
void  m_redeyes(GtkWidget *, ch *);                                              //  red-eye removal
void  m_smart_erase(GtkWidget *, ch *);                                          //  smart erase object
void  m_remove_halo(GtkWidget *, ch *);                                          //  remove halo left by other edits
void  m_jpeg_artifacts(GtkWidget *, ch *);                                       //  suppress jpeg compression artifacts
void  m_anti_alias(GtkWidget *, ch *);                                           //  suppress jaggies on feature edges
void  m_adjust_RGB(GtkWidget *, ch *);                                           //  color adjust using RGB or CMY colors
void  m_adjust_HSL(GtkWidget *, ch *);                                           //  color adjust with HSL
void  HSLtoRGB(float H, float S, float L, float &R, float &G, float &B);         //  convert HSL color space to RGB
void  RGBtoHSL(float R, float G, float B, float &H, float &S, float &L);         //  convert RGB color space to HSL
void  m_remove_dust(GtkWidget *, ch *);                                          //  remove dust spots
void  m_fringes(GtkWidget *, ch *);                                              //  reduce lateral chromatic aberration

//  image edit functions - Refine menu (f.refine.cc)

void  m_edit_hist(GtkWidget *, ch *);                                            //  edit brightness histogram
void  m_flat_hist(GtkWidget *, ch *);                                            //  flatten brightness histogram
void  m_localcon(GtkWidget *, ch *);                                             //  increase local contrast
void  m_amplifycon(GtkWidget *, ch *);                                           //  amplify existing contrast levels
void  m_gretinex(GtkWidget *, ch *);                                             //  rescale RGB levels - global
void  m_lretinex(GtkWidget *, ch *);                                             //  rescale RGB levels - local
void  m_saturation(GtkWidget *, ch *);                                           //  adjust saturation based on brightness
void  m_soft_focus(GtkWidget *, ch *);                                           //  apply lens soft focus effect
void  m_match_colors(GtkWidget *, ch *);                                         //  set image2 colors to match image1
void  m_brite_ramp(GtkWidget *, ch *);                                           //  add brightness ramp across image
void  m_vignette(GtkWidget *, ch *);                                             //  vignette tool

//  image edit functions - Effects menu (f.effects.cc)

void  m_outlines(GtkWidget *, ch *);                                             //  outline drawing
void  m_sketch(GtkWidget *, ch *);                                               //  simulated sketch
void  m_cartoon(GtkWidget *, ch *);                                              //  cartoon drawing
void  m_emboss(GtkWidget *, ch *);                                               //  simulated embossing
void  m_tiles1(GtkWidget *, ch *);                                               //  square tiles
void  m_tiles2(GtkWidget *, ch *);                                               //  irregular tiles matching image
void  m_painting(GtkWidget *, ch *);                                             //  simulated painting
void  m_texture(GtkWidget *, ch *);                                              //  add texture to image
void  m_pattern(GtkWidget *, ch *);                                              //  tile image with a pattern
void  m_dither(GtkWidget *, ch *);                                               //  dithered dots
void  m_dither0(GtkWidget *, ch *);                                              //  Roy Lichtenstein dots
void  m_dither1(GtkWidget *, ch *);                                              //  pure RGB or B&W dots
void  m_dither2(GtkWidget *, ch *);                                              //  RGB reduced bit-depth dots
void  m_dither3(GtkWidget *, ch *);                                              //  custom palette color dots
void  m_dither4(GtkWidget *, ch *);                                              //  pixels condense into blobs
void  m_engrave(GtkWidget *, ch *);                                              //  engrave - black/white lines
void  m_mosaic(GtkWidget *, ch *);                                               //  make mosaic with tiles from images
void  m_add_noise(GtkWidget *, ch *);                                            //  add random_noise to image
void  m_set_colors(GtkWidget *, ch *);                                           //  set no. colors for R/G/B or total     24.30
void  m_shift_colors(GtkWidget *, ch *);                                         //  shift colors into other colors
void  m_alien_colors(GtkWidget *, ch *);                                         //  revise hues using an algorithm
void  m_anykernel(GtkWidget *, ch *);                                            //  apply custom convolution kernel

//  image edit functions - Warp menu (f.warp.cc)

void  m_unbend(GtkWidget *, ch *);                                               //  unbend panoramas
void  m_perspective(GtkWidget *, ch *);                                          //  warp tetragon into rectangle
void  m_warp_area(GtkWidget *, ch *);                                            //  warp image within an area
void  m_warp_curved(GtkWidget *, ch *);                                          //  warp image, curved transform
void  m_warp_linear(GtkWidget *, ch *);                                          //  warp image, linear transform
void  m_warp_affine(GtkWidget *, ch *);                                          //  warp image, affine transform
void  m_warp_radial(GtkWidget *, ch *);                                          //  add/remove barrel/pincushion distortion
void  m_unwarp_closeup(GtkWidget *, ch *);                                       //  warp image within closeup face area
void  m_makewaves(GtkWidget *, ch *);                                            //  warp image using a wave pattern
void  m_twist(GtkWidget *, ch *);                                                //  twist image centered at mouse
void  m_sphere(GtkWidget *, ch *);                                               //  image spherical projection
void  m_inside_out(GtkWidget *, ch *);                                           //  turn an image inside-out
void  m_tiny_planet(GtkWidget *, ch *);                                          //  convert image to tiny planet
void  m_escher_spiral(GtkWidget *, ch *);                                        //  generate inward spiraling image
void  m_flatphoto(GtkWidget *, ch *);                                            //  flatten photo of a curved surface

//  image edit functions - Combine menu (f.comb.cc)

void  m_HDR(GtkWidget *, ch *);                                                  //  make HDR combined image
void  m_HDF(GtkWidget *, ch *);                                                  //  make HDF combined image
void  m_stack_paint(GtkWidget *, ch *);                                          //  stack / paint images
void  m_stack_noise(GtkWidget *, ch *);                                          //  stack / noise reduction
void  m_stack_layers(GtkWidget *, ch *);                                         //  stack / paint image layers            24.30
void  m_stack_split(GtkWidget *, ch *);                                          //  stack / split (sliding image split)
void  m_panorama(GtkWidget *, ch *);                                             //  make panorama combined image
void  m_cim_show_files(GtkWidget *, ch *);                                       //  show input files for cim edit function

//  image edit functions - mashup and image_array (f.mashup.cc)

void  m_mashup(GtkWidget *, ch *);                                               //  arrange images and text in custom layout
void  m_image_array(GtkWidget *, ch *);                                          //  combine images into a array layout
void  image_array_Lclick_func(int mx, int my);                                   //  array image click function

//  batch menu functions (f.batch.cc)

void  m_batch_convert(GtkWidget *, ch *);                                        //  rename/convert/rescale/export image files
void  m_batch_copy_move(GtkWidget *, ch *);                                      //  copy/move image files to new folder
void  m_batch_upright(GtkWidget *, ch *);                                        //  upright rotated image files
void  m_batch_deltrash(GtkWidget *, ch *);                                       //  delete or trash selected files
void  m_batch_RAW(GtkWidget *, ch *);                                            //  convert RAW files using Raw Therapee
void  m_batch_overlay(GtkWidget *, ch *);                                        //  add overlay image to selected host images
void  m_export_filelist(GtkWidget *, ch *);                                      //  create file of selected image files
void  m_export_files(GtkWidget *, ch *);                                         //  export image files to a folder

//  tools menu functions (f.tools.cc)

void  m_index(GtkWidget *, ch *);                                                //  rebuild image index and thumbnails
void  index_rebuild(int level, int keepopen);                                    //  index rebuild function
void  m_quick_index(GtkWidget *, ch *);                                          //  quick incremental index, no UI
void  m_settings(GtkWidget *, ch *);                                             //  user preferences and settings
void  m_KB_shortcuts(GtkWidget *, ch *);                                         //  edit KB shortcuts, update file
void  KB_shortcuts_load();                                                       //  load KB shortcuts at startup time
void  m_RGB_hist(GtkWidget *, ch *);                                             //  show brightness histogram graph
void  brightness_scale(GtkWidget *drawarea, cairo_t *cr, int *);                 //  draw black to white horizontal band
void  m_magnify(GtkWidget *, ch *);                                              //  magnify image within a radius of the mouse
void  m_measure_image(GtkWidget *, ch *);                                        //  measure distances within an image
void  m_show_RGB(GtkWidget *, ch *);                                             //  show RGB values at mouse click
void  m_grid_settings(GtkWidget *, ch *);                                        //  grid lines settings dialog
void  m_toggle_grid(GtkWidget *, ch *);                                          //  toggle grid lines on and off
void  m_line_color(GtkWidget *, ch *);                                           //  foreground line color (area/mouse/crop...)
void  m_darkbrite(GtkWidget *, ch *);                                            //  highlight the darkest and brightest pixels
void  darkbrite_paint();                                                         //  paint function called from Fpaint()
void  m_monitor_color(GtkWidget *, ch *);                                        //  check monitor brightness and color
void  m_duplicates(GtkWidget *, ch *);                                           //  find duplicate image files
void  m_resources(GtkWidget *, ch *);                                            //  report CPU and memory usage

//  developer menu (f.tools.cc)

void  m_zmalloc_report(GtkWidget *, ch *);                                       //  popup report, zmalloc allocations by tag
void  m_zmalloc_growth(GtkWidget *, ch *);                                       //  same, only tags with allocation growth
void  m_mouse_events(GtkWidget *, ch *);                                         //  show mouse events popup text
void  m_audit_userguide(GtkWidget *, ch *);                                      //  audit user guide: all F1 topics present
void  m_zappcrash_test(GtkWidget *, ch *);                                       //  zappcrash test function

