#!/bin/bash
### Universal file viewer
### ‎Version:0.32
### ‎© MochiMoppel 2025
### http://www.murga-linux.com/puppy/viewtopic.php?t=109573
{ #Application Specs
export APP_VERS=0.32
export APP_NAME=MMview
export APP_PATH=$(realpath "$0")
export WINTITLE="$APP_NAME v$APP_VERS"
}
{ #Directories & Files
#Directories
[[ $USER = root ]] && export TEMPDIR=/tmp/mm_view/ || export TEMPDIR="/tmp/mm_view.${USER}/"
export DUMPDIR=${TEMPDIR}dump/
export CNFGDIR=$HOME/.config/mm_view/
[[ -d $TEMPDIR ]] || mkdir -p $TEMPDIR
[[ -d $DUMPDIR ]] || mkdir -p $DUMPDIR
[[ -d $CNFGDIR ]] || mkdir -p $CNFGDIR
#Temporary files  (*.tmp and *.svg deleted after MMview session, other files stay alive until Puppy shutdown)
export SYMLINK=${TEMPDIR}symlink.tmp	# <input file> source for <edit> and  <pixmap> widgets.
export MSGFILE=${TEMPDIR}msgfile.tmp	# viewer pane text
export NB_PAGE=${TEMPDIR}nb_page.tmp	# notebook page number
export COMMAND=${TEMPDIR}command.tmp	# command string for vCMDLINE
export TMPFILE=${TEMPDIR}tmpfile.tmp	# multipurpose tmp file
export STBFILE=${TEMPDIR}stbfile.tmp	# optional content for status bar
export HISTORY=${TEMPDIR}history.txt	# command history
export MD5LIST=${TEMPDIR}md5list.tmp	# new and previous md5sum output
export TTPFILE=${TEMPDIR}ttpfile.tmp	# DIALOG_TOOLTIP tooltip text 
export D_TITLE=${TEMPDIR}d_title.tmp	# DIALOG_MULTI title
export D_LABEL=${TEMPDIR}d_label.tmp	# DIALOG_MULTI text label 
export D_DEFLT=${TEMPDIR}d_deflt.tmp	# DIALOG_MULTI default text for entry widget
export FNDFILE=${TEMPDIR}fndfile.txt	# DIALOG_MULTI last used searchstring
export FNDREGX=${TEMPDIR}fndregx.txt	# DIALOG_MULTI regex checkbox status
export FNDCASE=${TEMPDIR}fndcase.txt	# DIALOG_MULTI case  checkbox status
export FNDWORD=${TEMPDIR}fndword.txt	# DIALOG_MULTI word  checkbox status
export FNDMARK=${TEMPDIR}fndmark.txt	# DIALOG_MULTI mark  checkbox status
export FNDBINA=${TEMPDIR}fndbina.txt	# DIALOG_MULTI binar checkbox status
export FNDSYML=${TEMPDIR}fndsyml.txt	# DIALOG_MULTI symlk checkbox status
export FNDTREE=${TEMPDIR}fndtree.txt	# DIALOG_MULTI files rbutton  status
export FNDPANE=${TEMPDIR}fndpane.txt	# DIALOG_MULTI vpane rbutton  status
export ICONMMV=${TEMPDIR}iconmmv.svg	# icon MMview
export ICOWRAP=${TEMPDIR}icowrap.svg	# icon line wrap
export ICOVIEW=${TEMPDIR}icoview.svg	# icon instant view
export ICONHEX=${TEMPDIR}iconhex.svg	# icon hexdump
export ICONSEL=${TEMPDIR}iconsel.svg	# icon selection
export ICOASCI=${TEMPDIR}icoasci.svg	# icon ASCII
export ASCIMAP=${TEMPDIR}ascimap.tmp	# ASCII table
export UTF8MAP=${TEMPDIR}utf8map.txt	# decompressed and sanitized /usr/share/i18n/charmaps/UTF-8.gz
export RESTRTD=${TEMPDIR}restrtd.tmp	# app restarted flag
#Permanent files
export CFGFILE=${CNFGDIR}config			# config file
}
{ #File initialization
ln -fsn  /dev/null  $SYMLINK
echo  0	> $NB_PAGE
echo	> $TMPFILE
echo -n	> $STBFILE
echo -n	> $COMMAND
[[ -s $UTF8MAP ]] || gzip -cd /usr/share/i18n/charmaps/UTF-8.gz | sed -rn '
s@<control>@(control)@
s@^<U0+([^>]{5,})(.*)@<U\1\2@
s@^<U([^>]*)> .*/x.. +(.*)@\1\t\2@p
' | gzip > ${UTF8MAP}.gz &

}
{ #Utilities
export cmdPLAY ISPLAY cmdPROB ISPROB 
cmdPLAY=$(type -p ffplay)  && ISPLAY=true || { cmdPLAY=$(type -p avplay)  && ISPLAY=true || cmdPLAY=false ISPLAY=false ;}
cmdPROB=$(type -p ffprobe) && ISPROB=true || { cmdPROB=$(type -p avprobe) && ISPROB=true || cmdPROB=false ISPROB=false ;}
cmdCLIP=$(type -p xclip) cmdCLIP2BOARD="$cmdCLIP -loops 1 -sel c"  || { cmdCLIP=$(type  -p xsel) cmdCLIP2BOARD="$cmdCLIP -ib"   || cmdCLIP=false cmdCLIP2BOARD=false ;} ; export cmdCLIP cmdCLIP2BOARD
}
{ #Config file
export ASCIISTRING_LENGTH SHOW_ASCIISTRING_OFFSETS LAYOUT_V WIN_W WIN_H WIN_X WIN_Y FILESPEC HEXDUMP_VIEWER
[[ -s $CFGFILE ]] || echo -n '## To be set manually here
RESTORE_LAST_WINPOSITION=2	# at startup let wmctrl set last used win position:  0=no, 1=yes ,2=only at restart
RESTORE_LAST_SELECTION=2	# at startup let xdotool select last used file: 0=no, 1=yes, 2=only after restart or when file passed as argument
HEXDUMP_VIEWER=leafpad		# editor used for hexdump

## Set via GUI (no need to edit here)
ASCIISTRING_LENGTH=4
SHOW_ASCIISTRING_OFFSETS=off
LAYOUT_V=0

## Set automatically (do not edit)
WIN_W=1000
WIN_H=500
WIN_X=-1
WIN_Y=-1
FILESPEC=/
' > $CFGFILE
}
{ #Defaults/preferences
source $CFGFILE #LAYOUT_V FILESPEC
#override config values if wmctrl/xdotool not installed
[[ $(type -p wmctrl)  ]] || RESTORE_LAST_WINPOSITION=0
[[ $(type -p xdotool) ]] || RESTORE_LAST_SELECTION=0
# Orientation (horizontal or vertical)
((LAYOUT_V)) && BOX=v SEP=h	|| BOX=h SEP=v
#Set startup directory. Priorities: 1) Passed argument 2) Last used folder 3) Default '/'
[[ -e $1 ]] && DEFAULT_DIRECTORY=${1%/*} || DEFAULT_DIRECTORY=${FILESPEC%/*}
[[ -d $DEFAULT_DIRECTORY ]] || DEFAULT_DIRECTORY=/
#Configure xdotool 'Jump to file' functionality 
((RESTORE_LAST_SELECTION)) && {
	[[ -e $1 ]]          &&  RESTORE_LAST_SELECTION=1 FILESPEC=$1	#force 1 and override CFGFILE's FILESPEC if $1 exists
	[[ -e $RESTRTD ]]    &&  RESTORE_LAST_SELECTION=1				#force 1 if restarted, otherwise keep possible value 2 
	if [[ $FILESPEC != / && $RESTORE_LAST_SELECTION = 1 ]];then	#default '/' does not need xdotool
	FILENAME=${FILESPEC##*/} 
	FNN=$(printf '%s\n' "${DEFAULT_DIRECTORY}"/* | wc -l)										#calculate number of files/folders in chooser tree
	((FNN<100)) && XTS=0.8 || { ((FNN<1000))&&XTS=1.5 ;} || { ((FNN<2000))&&XTS=2 ;} || XTS=2.5	#set sleep depending on number of tree items
	(($(printf "$FILENAME"|wc -c) != ${#FILENAME} )) && XTD='--delay=200'						#set extra delay for multibyte filenames
	MAP_XDOTOOL="<action signal=\"map-event\">xdotool sleep $XTS  type $XTD  \"$FILENAME\" &&  xdotool  key Escape F5 & </action>"
	fi
}
#Remember Window position
((RESTORE_LAST_WINPOSITION)) && {
	[[ -e $RESTRTD ]]  && RESTORE_LAST_WINPOSITION=1 #force win positioning after restart
	((RESTORE_LAST_WINPOSITION==1)) && MAP_GEOMTRY="<action signal=\"map-event\">wmctrl -r :ACTIVE: -e 0,$WIN_X,$WIN_Y,-1,-1</action>"
}
}
{ #Miscellaneous variables
export BR=$'&#013;'	# LF in pango text
export PQ=$'&#034;'	# " in pango text
export PB=$'&#092;'	# \ in pango text
export LF=$'\n'
export TB=$'\t'
export CR=$'\r'
export ZERO_W_NBSP='﻿'	#$'\uFEFF'
export FIGURESPACE=' '	#$'\u2007'
export PUNCTNSPACE=' '	#$'\u2008'
export LEFTTORIGHT='‎'	#$'\u200E'
export INLINE_MARK='▊'
export LINEFF="\n-${ZERO_W_NBSP}------------------------------------------------------\n"
export LINE20=$'\n────────────────────\n'
export LINE40=$'\n────────────────────────────────────────\n'
export EMPTY=$'\n\n\n▒▒▒▒ ▒▒   ▒▒ ▒▒▒▒ ▒▒▒▒▒▒ ▒    ▒\n▒    ▒  ▒ ▒  ▒ ▒   ▒   ▒   ▒ ▒\n▒▒▒▒ ▒   ▒  ▒ ▒▒▒▒   ▒    ▒\n▒    ▒      ▒ ▒      ▒    ▒\n▒▒▒▒ ▒      ▒ ▒      ▒    ▒'
export HEXDUMP_MAXBYTES=10000
export SEL2UTF_MAXLINES=100	# max lines of character codes displayed
	   SELZOOM_MAXBYTES=18	# max bytes of zoom
export CLICKPRESS_DELAY=30	# clickpress time lag in 100/sec
export TOPT ; [[ $(busybox timeout 2>&1)  = *-t* ]] && TOPT=-t #new bb versions expect -t timeout arg
#Show/hide toolbar buttons (value 1 or 0)
TB_SEL2UTF=1
TB_ASCII=1
TB_HEX=1
TB_WRAP=1
TB_PROPERTIES=1
TB_OPENEDITOR=1
[[ $XDG_SESSION_TYPE = wayland ]] && TB_SHOWINROX=0 || TB_SHOWINROX=1
TB_INSTANTVIEW=1
TB_REFRESH=1
TB_ALTERNATEVIEW=1
}
{ #Screen and Viewer pane dimension
#Screen dimension
export SCREEN_W SCREEN_H
if [[ $XDG_SESSION_TYPE = wayland ]] ;then
	WLR=$(wlr-randr | grep -m1 current) # 1600x1200 px, 60.000000 Hz (preferred, current)
	SCREEN_W=${WLR%%x*}
	SCREEN_H=${WLR#*x}
	SCREEN_H=${SCREEN_H%% *}
else
	[[ $(xwininfo -root) =~ Width:\ ([0-9]*).*Height:\ ([0-9]*) ]]
	SCREEN_W=${BASH_REMATCH[1]}
	SCREEN_H=${BASH_REMATCH[2]}
fi

#Viewer pane dimension
CHOOSER_WIDTH=500	# Effective only in horizontal layout (default 500)
CHOOSER_HIGHT=200	# Effective only in vertical layout (default 200)
MENUBAR_HIGHT=25	# Should not be set to 0 (disables shortcuts). Value 1 hides mbar but still allows access via F10 (default 25)
WINDOW_MARGIN=0		# Inner margin of window (default 0)
WIDGETSPACING=3		# Spaces between menu - chooser&viewer - statusbar  (default 3)
CENTERSPACING=0		# Space between chooser - viewer (default 0)
L_EDIT_MARGIN=5		# Left margin of the text viewer pane (default 5)
STATUS_MARGIN=5		# Margin around bottom box containing statusbar & close button (default 5)
X_AXIS_ADJUST=2		# Compensates for width of separator. Increase value to reduce width of scaled images (default 2)
Y_AXIS_ADJUST=47	# Compensates for height of status bar, image page text and separator. Increase value to reduce height of scaled images(default 47)  
if	((LAYOUT_V)) ;then
	export VIEWER_W=$((WIN_W - WINDOW_MARGIN *2))
	export VIEWER_H=$((WIN_H - Y_AXIS_ADJUST - MENUBAR_HIGHT - CHOOSER_HIGHT - WINDOW_MARGIN - ( CENTERSPACING + WIDGETSPACING + STATUS_MARGIN) * 2 ))
else
	export VIEWER_W=$((WIN_W - X_AXIS_ADJUST - CHOOSER_WIDTH - (WINDOW_MARGIN + CENTERSPACING) * 2))
	export VIEWER_H=$((WIN_H - Y_AXIS_ADJUST - MENUBAR_HIGHT - (WINDOW_MARGIN + WIDGETSPACING + STATUS_MARGIN) * 2))
fi
}
{ #Icons
printf -v RNDCOLOR '%xffffff' $((RANDOM*RANDOM));RNDCOLOR=${RNDCOLOR::6}
echo '<svg width="48" height="48" viewBox="0 0 100 100">
<style type="text/css">circle{fill:#'$RNDCOLOR'}*{fill:#fff;stroke:#000;stroke-width:6;stroke-linecap:round;}</style>
<path	d="M-2,100 C0,-10 100,-10 102,100M 40,5 50,15 70,10 60,17M 65,80 70,80"/>
<circle	cx="26" cy="50" r="23"/>
<circle	cx="74" cy="50" r="23"/>
</svg>' > $ICONMMV

export SVGWRAP_1='99,0 0,22 -99,0 m'	# Wrap off
export SVGWRAP_2='69,0 0,22 -69,0'		# Wrap on
echo '<svg width="20" height="20" viewBox="0 0 100 100" >
<style type="text/css">*	{fill:#fff;stroke-width:2;stroke:#000}path{fill:none;stroke-width:6;stroke:#222;stroke-linecap:round;stroke-linejoin:round}</style>
<rect height="100" width="100"/>
<path d="m 16,29 
'"$SVGWRAP_1"'
 0,23 42,0"/>
</svg>'  > $ICOWRAP

export SVGVIEW_1='0"/></svg>'	#Viewer on
export SVGVIEW_2='4"/></svg>'	#Viewer off
echo '<svg width="20" height="20" viewBox="0 0 100 100">
<path d="M0,50 C50,-20 90,50 100,50" stroke="#000" stroke-width="7" fill="none"/>
<path d="M0,50 C50,25 90,50 100,50M0,50 C50,120 90,50 100,50" stroke="#000" stroke-width="4" fill="#fff"/>
<circle	cx="40" cy="58" r="22"	fill="#1EB0FF"/>
<circle	cx="40" cy="58" r="12"	fill="#000"/>
<path d="M0,0 100,100 M0,100 100,0" stroke="#000" stroke-width="'$SVGVIEW_1''  > $ICOVIEW

SVGHEAD='<svg width="20" height="20" viewBox="0 0 100 100">'

[[ -e $ICONHEX ]] || echo "$SVGHEAD"'
<rect height="100" width="100" fill="#fff"/>
<text font-size="60">
<tspan x="0" y="70">H</tspan>
<tspan x="33" fill="#f00">E</tspan>
<tspan x="58">X</tspan>
</text></svg>'  > $ICONHEX

[[ -e $ICONSEL ]] || echo "$SVGHEAD"'
<rect height="100" width="100" fill="#fff"/>
<rect height="60" width="100" y="20" fill="#ccc"/>
<text y="70" font-size="60" letter-spacing="-7">SEL</text></svg>'  > $ICONSEL

[[ -e $ICOASCI ]] || echo "$SVGHEAD"'
<rect height="100" width="100" fill="#fff"/> 
<style type="text/css">text{text-anchor:middle;font-size:50;font-family:sans}</style>
<text x="50%" y="49%">A S</text>
<text x="50%" y="93%">C I I</text></svg>'  > $ICOASCI

[[ -f "/usr/local/apps/ROX-Filer/ROX/MIME/application-x-xz.png" ]] && ICON_COMPRESS='image-name="/usr/local/apps/ROX-Filer/ROX/MIME/application-x-xz.png"'
}
{ #Help and tooltips
TT01=$'Executables:	Usage message (if available)\nDirectories:	Total size, incl. subdirectories\nImages:		Metadata (if available)\nGzipped files:	Unzipped content (if text)\nArchives:		List of archive content\nSVG,XPM files: Source code\nHTML files:	Plain text\nOther types:	ignored'
TT02=$'Keep terminal open when selecting different file\ninstead of closing terminal and showing file contents\n\nThis setting has no effect while command box is closed,\nin which case the terminal keeps also closed'
TT03=$'Execute command shown in command box\n(menu item has no effect when command box is closed)'
TT04=$'Start/stop playing video/audio files\nPlay will start/stop immediately\nAs long as this menu item is checked, any selected video/audio files will play automatically'
TT05=$'Add line numbers to the content of the viewer pane\nThe selected file will not be modified'
TT06=$'Refresh viewer pane\n(Reset to default view)'
TT07=$'Open a command box beneath file list to enter shell commands'
TT08=$'Open command box  with previously entered command'
TT09=$'Close command box'
TT10=$'View history of Commandbox\nWhen the Commandbox has focus the history can also be retrieved/closed by pressing Up/Down key'
TT11=$'Edit history of Commandbox ('$HISTORY')'
TT12=$'Clears history of Commandbox'
TT13=$'Open text file in default editor'
TT14=$'Open console\nand run selected file\n(if executable)'
TT15=$'Show in ROX-Filer window'
TT16=$'View file properties'
TT18=$'Rename selected file\nAdding path will move the file\n\nNote: Unlike ROX-Filer MMview supports rel.paths,\ne.g. \x27../foo\x27 will move \x27foo\x27 to parent folder'
TT19=$'Make a duplicate (copy) of the selected file in the same folder. Name MUST be different.\nAdding path will copy the file\n\nNote: Unlike ROX-Filer MMview supports rel.paths,\ne.g. \x27../foo\x27 will copy \x27foo\x27 to parent folder'
TT20=$'Delete file/directory\n\nNote: Wildcard characters supported, e.g. \x27*.mp3\x27 would deleted all mp3 files in the current folder'
TT21=$'Lclick: Fullscreen - normal size\nRclick: Fullscreen - fit to screen'
TT22=$'<b>Fullscreen - normal size</b>\nLclick: close fullscreen\nRclick: fit to screen'
TT23=$'<b>Fullscreen - fit to screen</b>\nLclick: normal size\nRclick: close fullscreen'
export TT24="<span font='14' color='#A52A2A'><b>Fullscreen</b>&#013;</span>Rclick: close fullscreen"
TT25=$'Rclick: Fullscreen'
TT26=$'Save window size and directory,\nthen quit\n\nTo quit without saving use\nAlt+F4 or window bar\x27s [X] icon'
TT27=$'Create new file or directory\nTo create directory: Append / (slash) to name'
TT31=$'Toggle Line Wrapping'
TT33=$'Create MD5 checksum\n\nChecked files and their checksum are kept in history.\nIdentical checksums in history (=identical files) are marked'
TT34=$'Compress/decompress\nselected file using gz compression\n\nWorks only on regular files,\ndirectories will be ignored'
TT35=$'Mark matching strings with a ■ character'
TT37=$'Find text in files or in viewer pane'
TT39=$'Toggle Instant View mode'
TT40=$'Alternate view for certain file types\n───────────────────────────\n'$TT01
TT42=$'Send selected file to an application stored in ROX-Filer\x27s \x27\x27SendTo\x27\x27 directory'
TT43=$'Change application layout\n(arrange file chooser and viewer pane vertically)'
TT44="Lclick:   Hexdump (max $(($HEXDUMP_MAXBYTES/1000))KB)${LF}Lpress: Hexdump in $HEXDUMP_VIEWER${LINE20}Rclick:  ❰hex❱view (max $(($HEXDUMP_MAXBYTES/1000))KB)${LF}Rpress:❰hex❱view in $HEXDUMP_VIEWER"
TT46="Displays up to $(($HEXDUMP_MAXBYTES/1000))KB of file content as hex values${LF}Left col displays decimal offsets, right col ASCII representations"
TT47="Special hexdump format, displaying hex values only for (non printable) control characters, marked as ❰hex❱, and extended ASCII characters, marked as ◀hex▶. All other characters, incl. tab and linefeed, are displayed as normal text."
TT48="Output in external editor, no size restriction"
TT50=$'Display ASCII strings\n(useful for extracting human readable text from binaries)'
TT51=$'Display ASCII table'
TT52=$'Lclick\tDisplay ASCII strings\nLpress\tConfigure options\nRclick\tASCII table\n\n\x27Display ASCII strings\x27 is useful\nfor extracting human readable\ntext from binaries'
TT54="${ZERO_W_NBSP}Show char codes of selected (highlighted) text${ZERO_W_NBSP}${LF}${LF}Note:${LF}- Selection is limited to $SEL2UTF_MAXLINES characters${LF}${ZERO_W_NBSP}- Selection source may be $APP_NAME or any${LF}  external source (e.g. a web page)."
TT55=${TT54/$ZERO_W_NBSP/Lclick: }; TT55=${TT55/$ZERO_W_NBSP/${LF}Rclick: Zoom selection}; TT55=${TT55/$ZERO_W_NBSP/- Zoom is limited to $SELZOOM_MAXBYTES bytes${LF}} 
TT60="<b>Search for text in Viewer Pane</b>${BR}${BR}Searches the text currently displayed in the Viewer Pane"
TT61=$'Case insensitive search\n\nThis option can make search very slow\nUsing alternatives may be faster, e.g.\nfoobar|Foobar|FOOBAR\nor regex\n[Ff]oobar'
TT62=$'Search also binary files\n\nChecks only if the search string exists, but would not display matching text lines\nIf binary found, only file path and consecutive dashed line will be displayed'
TT63=$'Follow symlinks in selected directory and all its subdirectories\n\nIf file, not directory, is selected, symlinks in the currently listed files are always followed, regardles of the option status'
TT64=$'Match only if search string is delimited by whitespace or special character'
TT65=$'\x27\x27Whole words\x27\x27 are strings containing ASCII letters and/or numerals, delimited by whitespace, punctuation or other symbols\n\nNote that the underbar _ is treated as a letter and therefore part of a word'
TT66="Use <b>Extended Regular Expressions (ERE)</b>${BR}${BR}
If unchecked all characters are searched for literally.
<u>Exception:</u>The vertical bar '|' can be used like a regex logical OR${BR}(see 3rd example)${BR}${BR}
<b>Examples:</b>${BR}
<b>-bg [Gg]reen</b>		<small>finds <b>-bg green</b> or <b>-bg Green</b></small>
<b>-bg (green|red)</b>		<small>finds <b>-bg green</b> or <b>-bg red</b></small>
<b>-bg green|-bg red</b>	<small>same. Does not require regex option</small>
<b>^#!.*perl</b>			<small>finds perl shebangs like <b>#!/usr/bin/perl</b></small>
<b>${PB}${PQ}#[a-fA-F0-9]{6}${PB}${PQ}</b> 	<small>finds quoted 6-digit hex like <b>${PQ}#14BD40${PQ}</b></small>"
TT67="<b>Search for text in ...</b>${BR}${BR}
<b><u>Currently listed files</u></b>${BR}
If any file (not directory!) is selected in MMview's file list, all files in the list will be searched${BR}
Subdirectories are ignored${BR}${BR}
<b><u>Selected directory</u></b>
If a directory is selected in MMview's file list, this directory and all of its subdirectories will be searched"

		HLP1='Enter a shell command\n\nTo execute command press Enter or F4\nClose command box with Esc key or via menu\n\n\$@ can be used as placeholder for the basename of the currently selected file.\nTo use \$@ literally add a backslash: \\\$@'
export	HLP2=$'\n\n\tInstant View mode disabled\n\n\tUse "Refresh" button or press F5\n\tto view a file'
}
{ #Prelaunch actions
[[ -e $RESTRTD ]] && rm $RESTRTD
}
function fill_statusbar {
	[[ -s $STBFILE   ]]	&& { echo "$(< $STBFILE)" ; echo -n > $STBFILE; return ;}
	[[ ! -L $vCHOOSER && ! -e $vCHOOSER  ]]	&& return
	[[ -L $vCHOOSER  ]]	&& { LNK='  ➡  ' RP=$(realpath "$vCHOOSER") RP=${RP:-<dead link target>} ; true ;} || OP=$vCHOOSER	# link
	if [[ -L $vCHOOSER  ]]; then 
		LNK='  ➡  '
		RP=$(realpath "$vCHOOSER" 2>/dev/null)
		(($?)) && echo "${vCHOOSER}${LNK}INVALID LINK TARGET ($(readlink "$vCHOOSER"))" && return
	else OP=$vCHOOSER	# link
	fi
	[[ -d ${OP}${RP} ]]	&& echo -n "${vCHOOSER}${LNK}${RP} │ x-directory" && return
	echo -n "${vCHOOSER}${LNK}${RP} │ $(file -bi "${OP}${RP}")"
};export -f fill_statusbar
function view_instantly {
	[[ -s $MSGFILE ]] && echo -n > $MSGFILE
	[[ -s $TMPFILE ]] && echo -n > $TMPFILE
	$vMENU_PLAY && busybox pkill MMplayme
	$vMENU_WRAP && echo  1 > $NB_PAGE || echo  0 > $NB_PAGE 
	shopt -s nocasematch extglob
	case $vSTATUSBAR in
	*'x-directory')	{
		if  [[ -z $(ls -A "$vCHOOSER") ]];then
			MESSAGE=$EMPTY
		elif [[ -L $vCHOOSER ]];then
			MESSAGE="SYMLINK to $(realpath "$vCHOOSER")" 
		elif [[ $vCHOOSER =~ ^/(proc|sys) ]];then
			MESSAGE="VIRTUAL FILE SYSTEM" 
		else
			MESSAGE=$(busybox timeout $TOPT 1 du -hs  "$vCHOOSER")
			if (($?));then
				MESSAGE="Press F1 for directory info"
			else
				MESSAGE="${MESSAGE%%[[:blank:]]*}		(disk usage)"
			fi 
		fi
		};;
	*│*'empty'*) {
		if [[ "$vCHOOSER" = /proc/* ]] ;then         # /proc contains seemingly empty virtual files that can't be read by linking them
				MESSAGE=$(< "$vCHOOSER")
		else    
			ln -fsn /dev/null $SYMLINK
			return
		fi
		};;
	*'.xpm '*|*'.pcx '*|*'.ani '*|*'.icns '*|*'.qtif '*|*'.qif '*)	{	# Non scalable images
		echo -n "Original Size" > $TMPFILE
		echo 2 > $NB_PAGE
		};;
	*'.xbm '*) {
		echo 2 > $NB_PAGE
		CONVERTER=$(type -p ffmpeg avconv | head -1)
		rm -r ${DUMPDIR}* &>/dev/null
		$CONVERTER -i "$vCHOOSER" ${DUMPDIR}converted.png &>/dev/null
		ln -fsn ${DUMPDIR}converted.png $SYMLINK
		return
		};;
	*'.webp '*|*'.p'[bgp]'m '*)		{
		CONVERTER=$(type -p ffmpeg avconv | head -1)
		if [[ $CONVERTER ]];then
			rm -r ${DUMPDIR}* &>/dev/null
			$CONVERTER -i "$vCHOOSER" ${DUMPDIR}converted.jpg &>/dev/null
			if (($?));then
				MESSAGE="${CONVERTER##*/} could not convert this image"
			else
				echo -n "Converted to JPG, scaled to fit viewer" > $TMPFILE
				echo 3 > $NB_PAGE
				ln -fsn ${DUMPDIR}converted.jpg $SYMLINK
				return
			fi
		else
			MESSAGE=$'\n\n\tDisplay requires ffmpeg or avconv'
		fi
		};;
	*'.svg '*|*'.svgz '*|*'.svg.gz '*) { #gtkdialog can read them natively
		 echo  3 > $NB_PAGE
		[[ ${vCHOOSER: -1} = z ]] && pre='Compressed ' MESSAGE=$(gzip -cd "$vCHOOSER")
		 echo -n "${pre}SVG image, scaled to fit viewer" > $TMPFILE
		};;
	*│*'xcursor'*) {
		type -p xcur2png >/dev/null || return
		rm -r ${DUMPDIR}* &>/dev/null
		xcur2png -c /dev/null -d $DUMPDIR  "$vCHOOSER"  2>/dev/null
		echo 2 > $NB_PAGE
		ln -fsn "$DUMPDIR"*000.png $SYMLINK
		return
		};;
	*│*'troff'*|*'/man/'*'.gz '*) {	#man page in plain or gzipped troff format
		MESSAGE=$(man "$vCHOOSER")
		};;
	*'.psd '*|*'.dng '*|*'.cr2 '*|*[.mnp]'ef '*|*[.eo]'rf '*|*.[ams]'rw '*|*'.rw2 '*|*'.raf '*|*'.3fr '*) { #previews to be extracted with exiv2
		rm -r ${DUMPDIR}* &>/dev/null
		exiv2  -ep1 -l $DUMPDIR  "$vCHOOSER"
		if [[ $(ls -A "$DUMPDIR") ]];then
			echo 3 > $NB_PAGE
			ln -fsn "$DUMPDIR"* $SYMLINK
			view_exif getEXIFMSG
			echo -n "Extracted preview   $EXIFMSG" > $TMPFILE
		fi
		return
		};;
	*│*'image'*)	{
			view_exif getSIZEEXIFMSG
			[[ $IMAGE_W ]] && IMGSIZE=${IMAGE_W}x${IMAGE_H}			#if no $IMAGE_W then exiv2 didn't understand format, e.g. ICO
			if (( IMAGE_W > VIEWER_W || IMAGE_H > VIEWER_H ));then	#if image bigger than pane calculate scaling for info only. Actual scaling is handled by pixmap widget with its WIDTH/HEIGHT  arguments
				SX=$(( 100 * VIEWER_W / IMAGE_W))		# scale in % ;Unrounded integer only, but good enough
				SY=$(( 100 * VIEWER_H / IMAGE_H))
				SCALE=$((SY < SX ? SY : SX))			# SCALE = SX or SY, whichever is smaller
				echo -n "${SCALE}% of $IMGSIZE  $EXIFMSG" > $TMPFILE
				echo 3 > $NB_PAGE
			else echo -n "Original size $IMGSIZE  $EXIFMSG" > $TMPFILE
				echo 2 > $NB_PAGE
			fi
		};;
	*'charset=iso'*|*'charset='*'unknown'*) {
		CHARSET=${vSTATUSBAR#*charset=}
		[[ $CHARSET = *unknown* ]] && CHARSET=iso-8859-1    # Seems to work best
		OOPS=$(iconv -f $CHARSET -t UTF-8 -o $MSGFILE -c "$vCHOOSER" 2>&1>/dev/null )
		if [[ $OOPS ]] ;then
			MESSAGE=$'Something went wrong.\n\nMaybe "iconv" is not installed or could not convert charset '"$CHARSET"$'\nHere is the error message:\n\n'"$OOPS"
		else ln -fsn $MSGFILE  $SYMLINK; return
		fi
		};;
	*'.od'[pt]\ *|*'.ott '*|*'.docx '*|*'.doc '*|*'.rtf '*|*'.abw '*){
		# Note:Softmaker .tmdx document would be readable when renamed to .docx
		echo  1 > $NB_PAGE # force line wrap
		abiword  -t txt "$vCHOOSER" -o $MSGFILE
		ln -fsn  $MSGFILE    $SYMLINK
		return
	};;
	*'.tt'[fc]\ *|*'.otf '*|*'.pcf '*){ #FONTS
	echo  1 > $NB_PAGE # force line wrap
	fc-query --format='Name:\t%{fullname}
Family:\t%{family}
Style:\t%{style}
Foundry: %{foundry}

Supported languages:
%{lang}

Supported characters:
%{charset}' "$vCHOOSER" > $MSGFILE
	ln -fsn  $MSGFILE    $SYMLINK
	return
};;
	*│*'text/'*|*│*'script'*|*│*'xml'*) {
		[[ $vCHOOSER = /sys/* ]] && MESSAGE=$(< "$vCHOOSER" )
		};;
	*│*'video'*|*'.mkv '*|*'.mpg '*) {
		MESSAGE=$($cmdPROB "$vCHOOSER" 2>&1)
		$vMENU_PLAY && $ISPLAY && exec -a MMplayme $cmdPLAY -x 320 -y 180 -i "$vCHOOSER"  &
		};; 
	*│*'audio'*|*'.mp3 '*|*'.ogg '*|*'.wma '*) {
		$vMENU_PLAY && $ISPLAY && exec -a MMplayme $cmdPLAY -nodisp -i "$vCHOOSER"  &
		if $ISPROB ;then
			FFP=$($cmdPROB "$vCHOOSER" 2>&1)
			DUR=Duration:${FFP#*Duration:}
			ID3=${FFP##*Metadata:$'\n'}
			if [[ "$ID3" = "$FFP" ]] ;then          # No Metadata found
				ID3=""
			else
				EN_SPACE=$'\xe2\x80\x82'			# Unicode U+2002 EN SPACE (" ")
				ID3=${ID3/$DUR}                     # Strip trailing $DUR
				ID3=${ID3// /$EN_SPACE}             # replace SPACE with EN SPACE
				ID3=${ID3//$EN_SPACE:/$'\t:'}       # replace single EN SPACE followed by colon with a tab
			fi
			MESSAGE=$(echo -n "$DUR"$'\n\n'"$ID3" | sed "s/^[[:blank:]]*//")
		else
			MESSAGE='Display of audio specs requires "ffprobe" or "avprobe"'
		fi
		};;    
	*│*'executable'*)	{
		if [[ $(grep -i "usage:" "$vCHOOSER") ]] ;then
				MESSAGE=$'⚫ Usage info for this file may exist. Try F1\n'
		else    vCHOOSER=/dev/null
		fi
		};;
	*│*'pdf'*)	{
		[[ -d ${DUMPDIR} ]] && rm -r ${DUMPDIR}*  &>/dev/null
		OUTFILE="${DUMPDIR}${vCHOOSER##*/}.jpg" 
		gs -sDEVICE=jpeg -dBATCH -dNOPAUSE  -r300 -sOutputFile="$OUTFILE"  -dLastPage=1 "$vCHOOSER" 1>/dev/null
		echo 3 > $NB_PAGE
		ln -fsn "$OUTFILE" $SYMLINK
		return
		};;
	*'.epub '*)			{
		echo  1 > $NB_PAGE
		MESSAGE=$(
		unzip -p "$vCHOOSER" *.opf |
			{
			echo -e "-------------------------------------\nPress F1 to read this eBook\n-------------------------------------\n"
			sed -rn '
			s/.*<dc:creator[^>]*>([^<]*).*/Author:	\1\n/p
			s/.*<dc:title[^>]*>([^<]*).*/Title:	\1\n/p
			s/.*<dc:description[^>]*>([^<]*).*/Description:	\1\n/p'
			}
		)
		};;
	*│*'zip'*|*│*'xz'*|*'.7z '*|*'.deb '*|*'.iso '*) { #ARCHIVE .tar, .pet , .txz, .gz , .gzip, .bzip2, .zip, .7z, .deb, .iso, initrd* 
		MESSAGE=$'\n\tTry F1 to view archive contents'
		};;
	*) ln -fsn /dev/null $SYMLINK ; return ;;
	esac
	if [[ "$MESSAGE" ]];then
		 echo "$MESSAGE"    > $MSGFILE
		 ln -fsn  $MSGFILE    $SYMLINK
	else ln -fsn "$vCHOOSER"  $SYMLINK
	fi
};export -f view_instantly
function view_on_demand {
	[[ $vMENU_WRAP = false ]] && echo  0 > $NB_PAGE || echo  1 > $NB_PAGE
	shopt -s nocasematch
	case $vSTATUSBAR in 
	*│*'executable'*) {
		grep -iq "usage:" "$vCHOOSER" || return             # exit function if 'usage:' not found
		for ARG in --help -help;do 
			urxvt -g 1x1+0+0  -e bash -c "                  # open console in minimum size in upper left corner to reduce flicker
			{ sleep 0.5; kill \$$ ;} &                      # let console commit suicide after 0.5sec.
			\"$vCHOOSER\" $ARG  &> $MSGFILE                 # redirect all output to MSGFILE
			"
			grep -iqm1 "usage:" $MSGFILE && break           # leave loop if output contains 'usage:' 
		done
		};;
	*│*'directory'*) {
		[[ $(< $MSGFILE) == $EMPTY || $vCHOOSER == /proc || -L $vCHOOSER ]] && return	# get out of here if SYMLINK, VIRTUAL FILE SYSTEM or EMPTY
		file_count
		};;
	*'.svg '*|*'.xpm '*) {
		ln -fsn "$vCHOOSER" $SYMLINK; return
		};;
	*'.epub '*)	{
		XDIALOG_ITEMS=$(unzip -l "$vCHOOSER" '*.htm*' | sort -k3 |sed -nr 's/[-0-9: ]*(.*\/)(.*\.html?$)/\1\2\n\2/p')
		IFS=$'\n'
		CHOICE=$(Xdialog --title "Select file to view" --stdout -ok-label View --no-tags --menubox "HTML files contained in eBook" 400x200 6 $XDIALOG_ITEMS)
		(($?)) && return
		view_htm2txt "$(unzip -p "$vCHOOSER" "$CHOICE")" > $MSGFILE
		echo  1 > $NB_PAGE
		};;
	*'/initrd'*) {
		COMPRESSION=${vSTATUSBAR##*x-}						# '/initrd.gz │ application/x-gzip; charset=binary' => 'gzip; charset=binary' 
		COMPRESSION=${COMPRESSION##*application/}			# '/initrd.gz | application/gzip; charset=binary' => 'gzip; charset=binary' 
		COMPRESSION=${COMPRESSION%;*}						# 'gzip; charset=binary' => 'gzip' 
		case $COMPRESSION in 
		  gzip)		CMND='gunzip  -c -d'	;; 
		  bzip2)	CMND='bunzip2 -c -d'	;; 
		  xz|lzma)	CMND='unxz    -c -d'	;; 
		  lz4)		CMND='unlz4   -c -d'	;; 
		  *)		CMND='cat'				;;				# not compressed 
		esac 
		$CMND "$vCHOOSER" | busybox cpio -ivt | awk '
		{
			$1=toupper(substr($1,1,1))					# 1st char = filetype; uppercase helps to align proportional fonts
			if ($1=="-") $1="F"							# - = regular file
			$3=substr("       "$3,length($3))			# padd with " " (Unicode U+2007 e2 80 87 FIGURE SPACE); max diplayed value: 99M
			print $1,$3"\t"$4"\t"substr($0,index($0,$6))	# filetype \t size \t date \t filename
		}'  > $MSGFILE
		};; 
	*│*'gzip'*|*│*'xz'*|*│*'bzip2'*) {	# extensions .tar, .pet , .txz, .gz , .gzip, .bzip2
		ARCH_OUTPUT=$(tar -vtf "$vCHOOSER" 2>/dev/null)
		if [[ $ARCH_OUTPUT ]] ;then 						# output: tar extracted something, no output: most likely gzip contains to tarball, but in some cases of gzipped text files tar returned no output and exit code 0, so checking for exit codes does not help here
			echo "$ARCH_OUTPUT" | awk '
			{
				if (substr($6,length($6),1) == "/" ) next	# ignore folders
				$3=substr("       "$3,length($3))			# padd with " " (Unicode U+2007 e2 80 87 FIGURE SPACE); max diplayed value: 99M
				print $3,$4,$5"\t"$6						# size date time \t filename
			}'  > $MSGFILE
		else												# alternative if tar failed
			case $vSTATUSBAR in
			*│*gzip*)	view_archive 'gzip  -cd' ;;			# display content of gzip compressed text files (e.g. .gnumeric)
			*│*xz*)		view_archive 'xz    -cd' ;;			# display content of xz compressed text files
			*│*bzip2*)	view_archive 'bzip2 -cd' ;;			# display content of bzip2 compressed text files
			esac
		fi
		};;
	*'.deb '*) {
		dpkg-deb -c "$vCHOOSER" | awk '
		{
			if (substr($6,length($6),1) == "/" ) next	# ignore folders
			$3=substr("       "$3,length($3))			# padd with " " (Unicode U+2007 e2 80 87 FIGURE SPACE); max diplayed value: 99M
			print $3,$4,$5"\t"$6						# size date time \t filename
		}'  > $MSGFILE
		};;
	*'.iso '*)	view_archive 'iso-info --no-header -l' 	;;
	*│*'/zip'*)	view_archive 'unzip -l' 				;;
	*'.7z '*)	view_archive '7z l'						;;
	*│*'html'*|*'.html │'*|*'.htm │'*|*'.abw │'*|*'.ncd │'*) {
				view_htm2txt $LWRAP_01 "$(< $vCHOOSER)" > $MSGFILE
	};;
	*)	view_exif || return 1
	esac
	ln -fsn $MSGFILE $SYMLINK
};export -f view_on_demand
function file_properties {
	FCONTENTS=$(file -bL "$vCHOOSER")
	TMP=$IFS IFS='|'
	STATARRAY=($(stat -c "%U|%G|%s|%b|%z|%y|%x|%A|%F" "$vCHOOSER"))
	IFS=$TMP
	## stat values
	V0=${STATARRAY[0]}	# owner
	V1=${STATARRAY[1]}	# group
	V2=${STATARRAY[2]}	# size
	V3=${STATARRAY[3]}	# blocks
	V4=${STATARRAY[4]}	# ctime
	V5=${STATARRAY[5]}	# mtime
	V6=${STATARRAY[6]}	# atime
	V7=${STATARRAY[7]}	# permissions
	V8=${STATARRAY[8]}	# type
	## formatted stat values
	case $V8 in
	directory)	F2=- F3=$(du -sh "$vCHOOSER") F3=${F3%%$'\t'*} ;;
		*link)	LINKED="LINKED " ;&
			*)	printf -v F2 "%'d\tbytes" $V2
				printf -v F3 "%'d\tbytes  %s" $((V3*512)) "($V3 blocks x 512 bytes)" ;;
	esac
	F4=${V4%%.*}
	F5=${V5%%.*}
	F6=${V6%%.*}
	## Permissions
	case ${V7:3:1} in # Owner
	-) OX="--" ;;
	x) OX="x-" ;;
	s) OX="xx" ;;
	S) OX="-x" ;;
	esac
	case ${V7:6:1} in # Group
	-) GX="--" ;;
	x) GX="x-" ;;
	s) GX="xx" ;;
	S) GX="-x" ;;
	esac
	case ${V7:9:1} in # World
	-) WX="--" ;;
	x) WX="x-" ;;
	t) WX="xx" ;;
	T) WX="-x" ;;
	esac
	F7="${V7:1:2}$OX"$'\n'"${V7:4:2}$GX"$'\n'"${V7:7:2}$WX"
	F7=$(echo "$F7" | sed '
	s/[rw]/x/g
	s/./&	/g' | sed '
	1s/.*[x-]/Owner	&  SUID/
	2s/.*[x-]/Group	&  SGID/
	3s/.*[x-]/World	&  Sticky/
	')
	echo "\
${V8^^}    \"${vCHOOSER##*/}\"

■PROPERTIES
Owner,Group:	${V0},${V1}
File size:  	$F2
Used on disk:	$F3

Change time:	$F4
Modify time:	$F5
Access time:	$F6

■PERMISSIONS
${TB}    Read Write Exec
$F7

■${LINKED}CONTENTS INDICATE...
${FCONTENTS}${LF}" >	$MSGFILE

	############# ROX RELATED STUFF ################
#~ 	[[ $(type -p rox) ]]|| { ln -fsn $MSGFILE $SYMLINK ; return ;}	# stop here if ROX not installed
	[[ $XDG_SESSION_TYPE =  wayland ]] && { ln -fsn $MSGFILE $SYMLINK ; return ;}	# stop here if ROX not installed
	ROXTYPE=$(rox_get_mime)	# e.g. image/png
	echo "\
■ROX MIME TYPE
${ROXTYPE}${LF}" >>	$MSGFILE
	[[ -f $vCHOOSER ]]		|| { ln -fsn $MSGFILE $SYMLINK ; return ;}	# stop here if file not a regular file

	if [[ $ROXTYPE =~ executable|script|x-desktop ]] ;then echo "\
■ROX RUN ACTION
Execute file"  >> $MSGFILE
		ln -fsn $MSGFILE $SYMLINK ; return
	fi

	ROXMIME=${ROXTYPE/\//_}	# e.g. image/png => image_png

	## Directories where ROX stores its "run action" scripts
	TYPE_PATH[3]=/root/.config/rox.sourceforge.net/MIME-types/
	TYPE_PATH[2]=/etc/xdg/rox.sourceforge.net/MIME-types/
	TYPE_PATH[1]=/root/Choices/MIME-types/

	TYPE_FILE[6]=${TYPE_PATH[3]}$ROXMIME
	TYPE_FILE[5]=${TYPE_PATH[2]}$ROXMIME
	TYPE_FILE[4]=${TYPE_PATH[1]}$ROXMIME
	TYPE_FILE[3]=${TYPE_PATH[3]}${ROXMIME%%_*}
	TYPE_FILE[2]=${TYPE_PATH[2]}${ROXMIME%%_*}
	TYPE_FILE[1]=${TYPE_PATH[1]}${ROXMIME%%_*}
	for i in {6..0}; do	# From highest to lowest ROX priority; 0 will return TYPE_FILE[0] (=empty var) if none of the defined files exist
	[[ -f ${TYPE_FILE[$i]} ]] && break
	done
	if ((i)) ;then
		RUN_ACTION_FILE=${TYPE_FILE[$i]}						# e.g. /root/.config/rox.sourceforge.net/MIME-types/text_plain
		RUN_ACTION=$(grep "^[ 	]*exec " "$RUN_ACTION_FILE")	# more generous than ROX: 'exec' command not necessarily on 2nd line, may be preceded by whitespace
		if [[ $RUN_ACTION ]];then 								# e.g. 'exec defaulttexteditor $1'
			RUN_ACTION_APPLICATIONPATH=$(type -p $RUN_ACTION)	# e.g. '/usr/local/bin/defaulttexteditor'
			if [[ $RUN_ACTION_APPLICATIONPATH = */default* ]] ;then
				DEF_APP=$(awk '/exec/ {print $2}' "$RUN_ACTION_APPLICATIONPATH" )	# e.g. geany
				[[ $(type -p "$DEF_APP") ]] && DEF_ARROW=$"↳ ${DEF_APP}${LF}"		# if exists preceded with arrow
			fi
		else
			RUN_ACTION=$(< $RUN_ACTION_FILE)	# = complete contents of run action file
		fi
	else
		RUN_ACTION_FILE="( no run action file created )"
	fi
	echo "\
■ROX RUN ACTION
File:     $RUN_ACTION_FILE
Code: $RUN_ACTION
				$DEF_ARROW"  >> $MSGFILE
	ln -fsn $MSGFILE 		$SYMLINK
} ;export -f file_properties
function file_openwith {
	[[ -d  "$vCHOOSER" ]] && FILETYPE=directory || FILETYPE=file
	MIME=$(rox_get_mime "$vCHOOSER")
	MIME=${MIME/\//_}							#e.g. image_jpeg
	SNDTOSPACE=$'\n:\n─────────────────────\n'	#Xdialog tag ':' is valid bash command
	SNDTOCUSTM=$'Customize\nCustomize'
	SENDTOPATH="$HOME/.config/rox.sourceforge.net/SendTo/" # Contains "Open With" actions
	SNDTO_MIME=$(ls -d1 "${SENDTOPATH}".$MIME/*			2>/dev/null)
	SNDTOCATGR=$(ls -d1 "${SENDTOPATH}".${MIME%_*}/*	2>/dev/null)
	SNDTOEVERY=$(ls -d1 "${SENDTOPATH}"*				2>/dev/null)
	[[ $SNDTO_MIME && $SNDTOCATGR ]] && SPACER1=$SNDTOSPACE
	[[ $SNDTOCATGR && $SNDTOEVERY ]] && SPACER2=$SNDTOSPACE
	[[ $SNDTO_MIME && $SNDTOEVERY && -z $SNDTOCATGR ]] && SPACER3=$SNDTOSPACE
	XDIALOGITEMS=$(echo -n "${SNDTO_MIME}${SPACER1}${SNDTOCATGR}${SPACER2}${SPACER3}${SNDTOEVERY}${SNDTOSPACE}${SNDTOCUSTM}" | sed -r "s|.*/(.*)|&\n\1|" )
	SENDTO_CHARS=$(echo "$XDIALOGITEMS" | wc -L)	#width of longest line
	SENDTO_LINES=$(echo "$XDIALOGITEMS" | wc -l)	#no of lines
	SENDTO_GEO_W=$((SENDTO_CHARS*3+40))				#estimated width
	SENDTO_GEO_H=$((SENDTO_LINES*8+130))			#estimated height
	TMP=$IFS; IFS=$LF
	CMD=$(Xdialog --title "$WINTITLE" --no-tags --under-mouse --stdout --menubox "ROX \"Open With...\" actions for\n$FILETYPE \"${vCHOOSER##*/}\"" ${SENDTO_GEO_W}x${SENDTO_GEO_H} 6 $XDIALOGITEMS)
	RET=$?
	IFS=$TMP
	(($RET)) && return
	[[ $CMD = Customize             ]] && rox -d  "$SENDTOPATH"		&& return
	[[ -d "$CMD"                    ]] && "$CMD/AppRun" "$vCHOOSER"	&& return			# if CMD is directory assume ROX App
	[[ $(rox  -m "$CMD") = *desktop ]] && CMD=$(grep ^Exec= "$CMD")	&& CMD=${CMD/Exec=}	# if desktop file, retrieve command line after 'Exec='
	[[ $(type -p "$CMD")            ]] && "$CMD" "$vCHOOSER" &
} ;export -f file_openwith
function file_md5 {
	[[ -d $vCHOOSER  ]] && return
	MD5CURRENT=$(md5sum  "$vCHOOSER")
	(($?)) && MD5CURRENT="???????????????????????????????? $vCHOOSER"
	MD5HISTORY=$(
		sed "s/◀/ /					# remove all markers
		\|$MD5CURRENT|d				# same MD5 + filespec means file was tested already. Remove from list to prevent irritating ◀ marker
		/${MD5CURRENT%% *}/ s/ /◀/	# append marker to any identical MD5 in list
		" $MD5LIST 2>/dev/null
		)
	echo "${MD5CURRENT}${LF}${MD5HISTORY}" > $MD5LIST
	echo $'■ MD5SUM CURRENT FILE:\n'"$MD5CURRENT"$'\n\n■ MD5SUM PREVIOUS FILES:\n'"$MD5HISTORY" > $MSGFILE
	ln -fsn $MSGFILE $SYMLINK
}; export -f file_md5
function file_edit   {
	[[ -f $vCHOOSER ]] || return		# open only regular files
	if [[ ! $(file -bL --mime-type "$vCHOOSER" ) =~ (empty|script|text|ascii|utf-8) ]];then
		Xdialog --title "$WINTITLE" --yesno "Does not appear to be a text file\nTry to open anyway?" x
		(($?)) && return
	fi
	defaulttexteditor "$vCHOOSER" &
};export -f file_edit
function file_compress { 
	[[ $(file -b "$vCHOOSER") =~ ^gz ]]  && gzip -d "$vCHOOSER" 2> $STBFILE || gzip -f "$vCHOOSER"  2> $STBFILE
	[[ -s $STBFILE ]] || echo > $STBFILE	# clear statusbar
	ln -fsn /dev/null $SYMLINK
} ;export -f file_compress
function file_count   {
	MSG="DIRECTORY    \"${vCHOOSER##*/}\"${LF}${LF}■COUNT${LF}"
	MSG="${MSG}$(find "$vCHOOSER" -printf '%y %s\n' | awk 'BEGIN {fcnt=0} { if ($1!="d") { fsum+=$2 ; fcnt++ } else dcnt++ } END { printf "%s %'"'"'d %s\n" ,"Total: ",fsum," bytes   ( Files:"fcnt",  Subdirectories:"dcnt-1" )\n"}')"
	DU_ALL=$(du -h --max-depth=1 "$vCHOOSER"|sort -k2)				# vCHOOSER on top, followed by subs; not yet sorted by size; du --max-depth more compatible than -d
	DU_TOP="${LF}${LF}■DISK USAGE${LF}${DU_ALL%%[[:blank:]]*}${LF}"	# first line (=vCHOOSER)
	if [[ ${MSG##*Directories:1 } = ')' ]] ;then
		MSG="${MSG}${DU_TOP}   └ (no subdirectories)"
	else
		DU_SUB=${DU_ALL#*$'\n'}
		MSG=${MSG}${DU_TOP}$(echo -n "$DU_SUB" | sort -hr |awk '
		{
		$1=substr("───── "$1,length($1))
		gsub(/\/.*\//,"")
		print " └"$1" "$2"  "substr($0,index($0,$3))
		}')
	fi
	echo "$MSG" >  $MSGFILE
} ;export -f file_count
function find_again {
	[[ -s $FNDFILE ]] && FINDSTRING="$(< $FNDFILE)" || return 1
	FIND=$FINDSTRING COMMANDLINEFIND=$FINDSTRING
	## DEFAULTS
	OPT_LNUM=n
	## IN CASE OF ADDITIONAL SEARCH ...
	if [[ $vSTATUSBAR = Matches* ]];then
		$vCHB_TREE || OPT_LNUM= #no numbers in viewer pane searches
		$vCHB_MARK && sed -i "s/$INLINE_MARK//g" $MSGFILE	#remove any existing markers
	fi
	## CREATE PATTERN BASED ON CHECKBOXES
	$vCHB_REGX && OPT_REGX=E || { OPT_REGX=F; [[ $FIND =~ '\|'  ]] && FIND=${FIND//'\|'/|} || FIND=${FIND//|/$'\n'}   ;}
	$vCHB_CASE && OPT_CASE=i
	$vCHB_WORD && OPT_WORD=w
	$vCHB_MARK && { $vCHB_TREE && OPT_MARK=' --color=always' || OPT_MARK='C999999 --color=always' OPT_LNUM= ;}
	if $vCHB_TREE ;then
		shopt -s dotglob			#search hidden dirs/files
		$vCHB_BINA || OPT_BINARY=I  #I prevents search in binaries
		if [[ -d $vCHOOSER ]];then
				$vCHB_SYML && OPT_RECUR=R || OPT_RECUR=r
				SELECTED_FILETYPE=D ; cd "$vCHOOSER"		; SOURCE=\"$PWD\"	#SOURCE used in statusbar only
		else	SELECTED_FILETYPE=F ; cd "${vCHOOSER%/*}"	; SOURCE=\"$PWD/\"*
		fi
		OPT_FNAM=H	#Force filespec header. By default grep doesn't do that if arg is single file, but awk formatting always expects filespec
	else
		SOURCEFILE=$(readlink $SYMLINK)
		SOURCE=\"$SOURCEFILE\"
		SELECTED_FILETYPE=X
	fi
	OPT_NULL=Z
	GREP_OPTIONS="-${OPT_REGX}${OPT_FNAM}${OPT_BINARY}${OPT_LNUM}${OPT_RECUR}${OPT_CASE}${OPT_WORD}${OPT_NULL}${OPT_MARK} --" #final '--' needed to avoid misinterpretation of match patterns that start with '-' like searching for '-bg green'
	[[ $CMDLINEFIND != $FIND ]] && P='"$'\''\n'\''"' && CMDLINEFIND=${FIND//$'\n'/$P} #FIND may have had '|' substituted by LF
	COMMANDLINE="grep $GREP_OPTIONS \"$CMDLINEFIND\" $SOURCE" #for use in statusbar only
	## SEARCH
	kill_me_softly grep "Searching for \"$FINDSTRING\"" & 
	function pipe2sed { ESC=$'\x1B' ; sed -r "s/$ESC\[01;31m$ESC\[K/$INLINE_MARK/g; s/$ESC\[[0-9;]*m$ESC\[K//g" ;}
	function pipe2awk { awk -F"\0" '{if ($1!=b && $1~/^[B/].*/) {b=$1;print "\n"b"\n-----------------------------"};print $2}' ;}
	case ${vCHB_MARK}${vCHB_TREE}${SELECTED_FILETYPE} in
		true*)		ESC=$'\x1B' ;;&	#continue
		falsefalseX)grep $GREP_OPTIONS "$FIND" "$SOURCEFILE"	2>/dev/null > $TMPFILE ;;
		truefalseX)	grep $GREP_OPTIONS "$FIND" "$SOURCEFILE"	2>/dev/null | pipe2sed				> $TMPFILE ;;
		truetrueD)	grep $GREP_OPTIONS "$FIND" "$PWD"			2>/dev/null | pipe2sed | pipe2awk	> $TMPFILE ;;
		falsetrueD)	grep $GREP_OPTIONS "$FIND" "$PWD"			2>/dev/null | pipe2awk				> $TMPFILE ;;
		truetrueF)	grep $GREP_OPTIONS "$FIND" "$PWD/"*			2>/dev/null | pipe2sed | pipe2awk	> $TMPFILE ;;
		falsetrueF)	grep $GREP_OPTIONS "$FIND" "$PWD/"*			2>/dev/null | pipe2awk				> $TMPFILE ;;
	esac 
	## GET OUT OF HERE IF TMPFILE EMPTY  (= NO MATCH)
	[[ ! -s $TMPFILE ]] && echo "Matches for \"$FINDSTRING\":0 │ Command: $COMMANDLINE" > $STBFILE && return
	##COUNT BINARY MATCHES
	$vCHB_BINA && $vCHB_TREE && BINATEXT="+ $(grep -c '^B' $TMPFILE) binaries" && sed -ri 's/^Binary file (.*) matches$/\1/' $TMPFILE
	##COUNT TEXT MATCHES
	COUNTOPTIONS="-${OPT_REGX}${OPT_CASE}${OPT_WORD} -o --"
	if $vCHB_TREE ;then
		CNT=$(sed " 
		/^[/-]/d		#delete filespecs and separator lines
		s/${INLNMARK}//g #delete marks
		s/^[0-9: ]*//	#delete line numbers
		" $TMPFILE | grep $COUNTOPTIONS "$FIND"  2>/dev/null|wc -l)
	else
		CNT=$(grep $COUNTOPTIONS "$FIND" $TMPFILE 2>/dev/null|wc -l)
	fi
	##WRITE RESULT TO STATUSBAR; LINK OUTPUT TO VIEWER PANE
	echo "Matches for \"$FINDSTRING\": $CNT $BINATEXT │ Command: $COMMANDLINE" > $STBFILE
	iconv -ct UTF-8 $TMPFILE > $MSGFILE
	ln -fsn $MSGFILE $SYMLINK
} ;export -f find_again
function view_htm2txt {
	echo "$1"  | busybox tr '\r\n' '\x01' | sed -r '	# change Unix/Win/Mac line endings into hex01 markers, i.e put whole file content on a single line, then pipe to sed
	s/^.*<\/head>//Ig					# delete document declarations and the <head> section
	s/<style[^<]*<\/style>//Ig			# delete <style> sections
	s/<script/\x0&/Ig					# add NULL markers before <script>
	s/\x0<script[^\x0]*<\/script>//Ig	# delete <script> sections (unlike <style> sections <script> sections may contain < characters, making it difficult to match the content, hence the unlikely NULL character)
	s/<pre>/\n&/Ig						# put <pre> on separate line
	s/<\/pre>/&\n/Ig' | sed -r '		# following /<pre>/! condition works only with fresh pipe (line structure changed!)
	/<pre>/! s/\x01//Ig					# delete all lineend markers except those between <pre> tags
	s/&nbsp;|\t/ /g						# replace  &nbsp and tabs with normal space.
	s/  +/ /g							# reduce consecutive spaces (bad habit of NYT) to 1 space
	s/>[ \x01]+</></g					# delete all spaces or newlines between tags (if they are the only characters that separate the tags)
	s/<metadata.*<\/metadata>//			# delete <metadata> section (Abiword)
	s/<d[ >][^<]*<\/d>//g				# delete <d> sections (Abiword. <data> may contain multiple <d>, so greedy match will delete until last </d>. Good! Deleting whole <data> section instead might conflict with HTML5 <data>)
	s/<div|<p[ >]/\x01\x01&/Ig			# precede <div> and <p> with blank line (does not match <pre>,<progress>,<param>,<picture>)
	s/<h[1-6]/\x01\x01● & /Ig			# precede <h> with blank line and bullet
	s/<dt/\x01\x01◆ &/Ig				# precede <dt> (Notecase likes them) with lineend markers and bullet
	s/<li/\x01• &/Ig						# put <li> on new line and add bullet (unfortunately not possible to determine if list should be vertical or horizontal)
	s/<\/h[1-9]|<dd|<tr|<br/\x01</Ig	# precede </h <dd <tr <br with lineend marker, i.e. put them always on a new line
	s/<[^>]*>|-->//g					# delete all tags and --> (a leftover in Gtkdialog references)
	s/&[lr]?d?quot?;/"/g					# convert &ldquo; &rdquo; &quot;
	s/&lt;/</g							# convert &lt;
	s/&gt;/>/g							# convert &gt;
	s/&amp;/\&/g							# convert &amp;
	s/&copy;/©/g							# convert &copy;
	s/^[ \x01]+//						# delete first line if blank
	s/\x01 +/\x01/g						# delete all spaces at line start
	s/[•◆●] *\x01//g					# delete lines with orphaned bullets
	s/\x01\x01\x01+/\x01\x01/g			# reduce consecutive blank lines to 1 line
	s/\x01/\n/g							# change lineend markers back into newlines
'
}; export -f view_htm2txt
function view_archive {
		TOOLNAME=${@%% *}
		if type -p "$TOOLNAME" ;then
			case $vSTATUSBAR in
			 *'.iso '*|*│*/zip*|*'.7z '*)	$@ "$vCHOOSER" | sed "s/ /$FIGURESPACE/g" > $MSGFILE ;;
			 *)								$@ "$vCHOOSER" > $MSGFILE ;;
			esac
		else echo "Requires command line tool $TOOLNAME"	> $MSGFILE
		fi
		[[ $(file -b --mime-type $MSGFILE ) != text* ]] && { file -bL "$vCHOOSER"; echo -e "\n\nExtracted content does not seem to be plain text.\nCan\x27t be displayed here."  ;} > $MSGFILE
		ln -fsn $MSGFILE $SYMLINK
};export -f view_archive
function view_exif {
	EXIV2=$(exiv2 "${vCHOOSER}" 2>/dev/null)
	RET=$?
	((RET==1)) && return 1
	case $1 in
	getSIZEEXIFMSG) 					#called from view_instantly, case image
		IMGSIZE=(${EXIV2#*Image size})	# ' : 1600 x 1200 ...'
		IMAGE_W=${IMGSIZE[1]}			# '1600'
		IMAGE_H=${IMGSIZE[3]}			# '1200'
		;&								#continue
	getEXIFMSG)							#called from view_instantly, case RAW extensions
		EXIFMSG=
		if ((RET==0));then				#Exif data exist
			EXIFMSG="Metadata:Exif"
			[[ $(exiv2 -g "Exif.GPSInfo.GPSLatitude" -Pt "$vCHOOSER") ]] && EXIFMSG="$EXIFMSG,GPS"
			[[ $EXIV2 =~ (Exif comment.*[^ :]) ]]  && EXIFMSG="$EXIFMSG,Comment"
		fi
		return
		;;
	'')
		((RET>1)) && return 1
		SUMRY=$(echo "$EXIV2" | sed "
		1,4d				#remove first 4 lines (basic data)
		/:[[:blank:]]$/d	#remove empty categories
		s/  /${FIGURESPACE}${PUNCTNSPACE}/g	#format 2nd column for proportional fonts
		s/:/\t\t:/			#add tabs to  align 2nd column
		s/File size/& /"	#"File size" needs extra space to align
		)		

		LOHI=$(printf "\\\x%X" {{0..8},11,12,{14..31},{127..255}})
		MDATA=$(exiv2 -pa "${vCHOOSER}" | tr -d $LOHI |sed -r '	#remove low/high ASCII, exc. TAB,LF,CR
		s/^([^ ]*) +[^ ]+ +[^ ]+(.*)$/\1=\2/	#skip 2nd and 3rd field
		0,/^Exi/s//\n■EXIF METADATA\n&/			#Act on only 1st match
		0,/^Ipt/s//\n■IPTC METADATA\n&/
		0,/^Xmp/s//\n■XMP  METADATA\n&/
		') 

		MSG="■EXIF SUMMARY${LF}${SUMRY}${LF}${MDATA}"
		echo "$MSG" >  $MSGFILE
		;;
	esac
}; export -f view_exif
function view_hexdump {
#~ [[ -d $vCHOOSER ]] && echo "■HEXDUMP/HEXVIEW possible only for regular files" > $MSGFILE && ln -fsn $MSGFILE $SYMLINK && return #do not process when directory
[[ -d $vCHOOSER ]] && return #do not process when directory
	FSIZE=$(stat -Lc %s "$vCHOOSER")
	(( HEXDUMP_MAXBYTES < FSIZE )) && PARAM="-n$HEXDUMP_MAXBYTES" && MAXKB="(only first $((HEXDUMP_MAXBYTES/1000)) KB)"
	case $1 in
	dumphead)	TITLE="■HEXDUMP $MAXKB of $vCHOOSER" ;;
	dumpall)	TITLE="■HEXDUMP of $vCHOOSER" ;PARAM=  ;;
	markhead)	TITLE="■HEXVIEW $MAXKB of $vCHOOSER" ;;
	markall)	TITLE="■HEXVIEW of $vCHOOSER" ;PARAM=  ;;
	esac
	echo -n "${TITLE}$LINE40" > $TMPFILE
	case $1 in
	dump[ha]*)	hexdump $PARAM -e '1 "%03_ad: "' -e '10/1 " %02X" "\t""|" ' -e '10/1 "%_p" "\n"'  "$vCHOOSER" >> $TMPFILE
				;;&	#continue pattern match
	   dumpall)	$HEXDUMP_VIEWER $TMPFILE & return ;;
	 mark[ha]*)	echo -e $(hexdump $PARAM -ve '"\\"' -e '1/1 "x%02x"' "$vCHOOSER" | sed -r "
				s/.x0[0-8b-f]|.x1[0-9a-f]|.x7f/❰& ❱/g	#low ASCII exc. TAB and LF
				s/.x[8-9a-f][0-9a-f]/◀& ▶/g				#high ASCII
				s/◀.x/◀/g
				s/▶◀//g
				s/ ▶/▶/g
				s/❰.x/❰/g
				s/❱❰//g
				s/ ❱/❱/g") >> $TMPFILE
				;;&	#continue pattern match
	  markall)	$HEXDUMP_VIEWER $TMPFILE & return ;;
	esac
	mv $TMPFILE $MSGFILE #writing directly to $MSGFILE would create problems caused by *all option. MSGFILE would not be source anymore of current viewer pane display. Some functions rely on MSGFILE beeing source of pane.
	ln -fsn $MSGFILE $SYMLINK
} ;export -f view_hexdump
function prep_selection {
	case $1 in
	press)	c=$($cmdCLIP -o)
			echo -n "${c::$SEL2UTF_MAXLINES}" > $MSGFILE ;;
		*)	[[ -s $MSGFILE ]] || return 1
			view_selection ;;
	esac 
} ;export -f prep_selection
function view_selection {
	[[ -s $MSGFILE ]] && TXTSTRING=$(<$MSGFILE) || return
	[[ -s $UTF8MAP ]] || gzip -d ${UTF8MAP}.gz
	HEXCOLUMN=$(printf %s "$TXTSTRING" | sed 's/./&\x0/g' | hexdump -ve '"\\"' -e '1/1 "x%02x"' | sed 's/\\x00/\n/g; s/\\x0a/&\n/g')	# Last special treatment of LF needed as sed is line oriented and ignores LF char and would not put \x0 marker in front
	CHAR_CCNT=${#TXTSTRING}
	CHAR_BCNT=$(echo -n "$TXTSTRING" | wc -c )
	((CHAR_CCNT >1)) && s=s
	LL=$(echo "$HEXCOLUMN" | wc --max-line-length)
	for CHARHEX in $HEXCOLUMN;do
		CHRNAME=
		case $CHARHEX in
		'\x09') LETTER='(tb)' UTFHEX=U+0009	;;  
		'\x0a') LETTER='(lf)' UTFHEX=U+000A	;;
		'\x0d') LETTER='(cr)' UTFHEX=U+000D	;;
			 *) printf -v LETTER %b		"$CHARHEX"
				printf -v UTFHEX U+%04X	"'$LETTER" ;;
		esac
		CHRNAME=$(grep -hm1 "^0*${UTFHEX:2}	" ${TEMPDIR}utf8* )
		CHRNAME=${CHRNAME#*	}
		CHARHEX=${CHARHEX}"               "	# add 15 FIGURE SPACEs
		CHARHEX=${CHARHEX::$LL}				# only first LL characters
		HEXTITL='hex                '		# hex<space> + 15 FS
		HEXTITL=${HEXTITL::$LL}
		CNT=$((CNT+1))
		printf -v MSG '%s%s%02d\t%s\t%s\t%s\t  %s\n' "$MSG" $LEFTTORIGHT $CNT "$LETTER" $UTFHEX $CHARHEX "$CHRNAME"
	done
	echo -n "■ CURRENT TEXT SELECTION  ($CHAR_CCNT character$s; ${CHAR_BCNT} byte$s):${LINE40}
${TXTSTRING}${LF}${LINE40}No. Char	UTF-8	$HEXTITL	  Name${LINE40}${MSG}" > $MSGFILE
	ln -fsn $MSGFILE $SYMLINK
} ;export -f view_selection
function ascii_strings {
	[[ -d $vCHOOSER || ! -s $vCHOOSER ]] && return 1 
	source $CFGFILE #ASCIISTRING_LENGTH SHOW_ASCIISTRING_OFFSETS
	echo -n "■ASCII strings, min. $ASCIISTRING_LENGTH chars$LINE40" > $MSGFILE
	if [[ $SHOW_ASCIISTRING_OFFSETS = on ]]
	then busybox strings -on $ASCIISTRING_LENGTH "$vCHOOSER" | awk '$1=strtonum("0" $1)": "'  >> $MSGFILE
	else busybox strings  -n $ASCIISTRING_LENGTH "$vCHOOSER" >> $MSGFILE
	fi
	ln -fsn $MSGFILE $SYMLINK
} ;export -f ascii_strings
function ascii_strings_length {
	source $CFGFILE #ASCIISTRING_LENGTH SHOW_ASCIISTRING_OFFSETS
	A=($(Xdialog --title "$WINTITLE" --check "Display decimal offsets" $SHOW_ASCIISTRING_OFFSETS  --left --stdout -u -spinbox "Minimum length of ASCII string\nto be displayed:" x 1 999 $ASCIISTRING_LENGTH characters))
	(($?)) && return 1
	[[ ${A[1]} = checked ]] && A[1]=on || A[1]=off
	sed -i "/ASCIISTRING_LENGTH/s|=.*|=${A[0]}| ; /SHOW_ASCIISTRING_OFFSETS/s|=.*|=${A[1]}|" $CFGFILE
} ;export -f ascii_strings_length
function ascii_table {
	for f in /usr/share/cups/charmaps/windows-1252.txt /usr/lib/aspell/cp1252.cset /usr/lib64/aspell/cp1252.cset ;do
	[[ -s $f ]] && ASCIMAP=$f && break
	done
	(($?)) && awk 'BEGIN {for (i=0  ;i<=255;i++) printf "%02X\t%04X\t%s\n",i,i,"#"}' > $ASCIMAP #we roll our own
	LC_ALL=C awk '
	BEGIN {
	hline="---------------------------------------------------------"
	print "=========== ASCII Table ==========\n\nDEC\tHEX\tCHR\tCODEPNT NAME\n"hline
	}
	/^[0-9A-F]/{						# process only lines starting with hex characters
	text=substr($0, match($0,/#/)+1) 	# extract from position of first encountered #, plus 1 to excl. #
	sub(/^ /,"",text)					# remove leading space from text (cp1252.cset)
	$1=substr($1, match($1,/x/)+1)		# remove 0x from 0xnn (windows-1252.txt) or keep nn (cp1252.cset)
	dec=strtonum("0x" $1)				# hex to dec 
	cpnt="U+"substr($2, match($2,/x/)+1)# remove 0x from 0xnnnn (windows-1252.txt) or keep nnnn (cp1252.cset)
	if (cpnt ~ /#/) cpnt="U+00"$1		# if cpnt rendered as U+#UNDEFINED (windows-1252.txt)
	if (dec<32||dec==127) char=""; else char=sprintf("%c",dec)
	if (dec==7)	text="BELL (esc \\a)"
	if (dec==8)	text="BACKSPACE (esc \\b)"
	if (dec==9)	{text="HORIZONTAL TABULATION (esc \\t)";char="TAB"}
	if (dec==10)	{text="LINE FEED (esc \\n)";char="LF" }
	if (dec==11)	text="VERTICAL TABULATION (esc \\v)"
	if (dec==12)	text="FORM FEED (esc \\f)"
	if (dec==13)	{text="CARRIAGE RETURN (esc \\r)";char="CR"}
	if ($1==20)	print hline"\nPrintable ASCII\n"hline
	if ($1==80)	print hline"\nExtended ASCII (example: codepage 1252)\n"hline
	printf "%03d\t%s\t%s\t%s\t%s\n"	,dec,$1,char,cpnt,text
	}' $ASCIMAP | iconv -c -f CP1252 -t UTF-8 > $MSGFILE
	ln -fsn $MSGFILE $SYMLINK
}  ;export -f ascii_table
function add_linenumbers {
	[[ -s $MSGFILE ]] && SOURCEFILE=$MSGFILE || SOURCEFILE=$vCHOOSER
	grep -n ^ "$SOURCEFILE"  > $TMPFILE
	ln -fsn $TMPFILE $SYMLINK
};export -f add_linenumbers
function run_in_console {
		[[ -x $vCHOOSER ]] && urxvt -title "$vCHOOSER" -e bash -c "\"$vCHOOSER\";echo;read -n1 -p \"Press any key to close\"" &
};export -f run_in_console
function run_dialog {
	if [[ $1 ]];then							# 1 argument = function called from Menu
			echo -n "$1"							> $D_TITLE
		case $1 in
		Rename|Duplicate)
			echo -n "<b><big>${1^^}</big></b>"	> $D_LABEL
			echo -n "${vCHOOSER##*/}"			> $D_DEFLT
			;;
		Create)
			echo -n "<b><big>${1^^}</big> new file or directory</b> <small>(append / )</small>"	> $D_LABEL
			echo -n "$vCHOOSER"					> $D_DEFLT
			;;
		Delete)
			[[ -d $vCHOOSER ]] && D=" DIRECTORY"
			echo -n "<span color='white' bgcolor='red'><b><big> ${1^^}$D </big></b></span>"	> $D_LABEL
			echo -n "${vCHOOSER##*/}"			> $D_DEFLT
			;;
		Find)
			echo -n "<b><big>Search for text</big></b>"	> $D_LABEL
			echo -n "$(<$FNDFILE)"				> $D_DEFLT
			;;
		esac
	else										# no argumet = function called from dialog's OK button action
		case $(<$D_TITLE) in
Rename|Duplicate|Delete|Create)cd "$(dir_name "$vCHOOSER")" ;;&
			Create)		[[ -e $vD_ENTRY ]] && echo "File/Directory \"$vD_ENTRY\" already exists" > $STBFILE && return
						if [[ ${vD_ENTRY: -1}  = / ]] ;then
							mkdir -p "$vD_ENTRY" &> $STBFILE
						else
							if [[ $vD_ENTRY =~ / ]] ;then
								[[ -d ${vD_ENTRY%/*} ]] || mkdir -p "${vD_ENTRY%/*}"
							fi
							touch "$vD_ENTRY" &> $STBFILE
						fi
						;;
			Rename)		mv -uv	--	"$vCHOOSER"	"$vD_ENTRY"	&> $STBFILE	;;
			Duplicate)	cp -ruv	--	"$vCHOOSER"	"$vD_ENTRY"	&> $STBFILE	;;
			Delete)		if [[ $vD_ENTRY =~ [*?] ]];then
							eval rm -v -- "$vD_ENTRY" &> $STBFILE
						else
							rm -rv -- "$vD_ENTRY" &> $STBFILE
						fi	;;
			Find)		echo -n "$vD_ENTRY"	> $FNDFILE
						echo -n $vCHB_REGX	> $FNDREGX
						echo -n $vCHB_CASE	> $FNDCASE
						echo -n $vCHB_WORD	> $FNDWORD
						echo -n $vCHB_MARK	> $FNDMARK
						echo -n $vCHB_TREE	> $FNDTREE
						echo -n $vCHB_PANE	> $FNDPANE
						echo -n $vCHB_BINA	> $FNDBINA
						echo -n $vCHB_SYML	> $FNDSYML
						;;
		esac
	fi
}; export -f run_dialog
function run_shell_command {
		cd "$(dir_name "$vCHOOSER")"
		FCMD=${vCMDLINE//\$@/$(basename "$vCHOOSER")}	# $@ = Basename of currently selected file/directory
		OUT=$(bash -c "$FCMD" 2>&1)
		RET=$?
		[[ $RET     = 0 ]] && [[ "$(tail -n1 $HISTORY)" != "$vCMDLINE" ]] && echo "$vCMDLINE" >> $HISTORY
		[[ $RET$OUT = 0 ]] && return
		echo -n "$OUT" > $MSGFILE
		ln -fsn $MSGFILE $SYMLINK
};export -f run_shell_command
function rox_get_mime {
	local ROX_M=$(rox -m "$vCHOOSER")
	if [[ ! $(file -bL "$vCHOOSER") =~ executable|script && $ROX_M = *script*  && $vCHOOSER = *.*  ]];then
			printf  'text/plain'
	else 	printf  $ROX_M
	fi
} ;export -f rox_get_mime
function dir_name {
	local d=${@%/*}
	echo ${d:-/}
};export -f dir_name
function kill_me_softly {
	sleep 1
	pgrep $1 1>/dev/null || return 1			#if pgrep fails then process has finished and we dont need dialog
	gxmessage -bo -c -fn 'bold 14' -bg '#008A00' -fg '#FFF' -bu "ABORT" "$LF  $2" &
	PID_DIALOG=$!
	while kill -0 $PID_DIALOG 2>/dev/null ;do 	#while PID_DIALOG is killable = dialog still running
		sleep .2
		pgrep $1 1>/dev/null || break 			#if pgrep fails then process has finished
	done
	kill  $PID_DIALOG	2>/dev/null				#kill gxmessage dialog (Abort button pushed or loop executed break because of finished process)
	pkill $1									#returns 0 if aborted, 1 if process has already finished
} ;export -f kill_me_softly
function lastrites_save {
	[[ $XDG_SESSION_TYPE = wayland ]] && return
	source $CFGFILE
	ACTWINID=$(xprop -root _NET_ACTIVE_WINDOW)
	ACTWINID=${ACTWINID##* }
	XWININFO=$(xwininfo -id $ACTWINID)
	ARRAY=(${XWININFO#* X: })
	  AX=${ARRAY[0]}
	  AY=${ARRAY[4]}
	  RX=${ARRAY[8]}
	  RY=${ARRAY[12]}
	NEWW=${ARRAY[14]}
	NEWH=${ARRAY[16]}
	NEWX=$((AX-RX))
	NEWY=$((AY-RY))
	NEWD=$vCHOOSER
	[[ $NEWW$NEWH$NEWX$NEWY$NEWD = $WIN_W$WIN_H$WIN_X$WIN_Y$FILESPEC ]] && return	#no change
	[[ $NEWD = *\&* ]] && NEWD=${NEWD//&/\\&}	#escape any '&' (sed would interpret as placeholder)
	sed -i "
	/WIN_W/s/=.*/=$NEWW/
	/WIN_H/s/=.*/=$NEWH/
	/WIN_X/s/=.*/=$NEWX/
	/WIN_Y/s/=.*/=$NEWY/
	/FILESPEC/s|=.*|=\"$NEWD\"|
	" $CFGFILE
} ;export -f lastrites_save
function lastrites_cleanup {
	busybox pkill MMplayme
	[[ $1 = save ]] && lastrites_save
	[[ $(busybox pidof "$WINTITLE") = *' '* ]] && return	#stop here if another instance running
	rm -rf ${TEMPDIR}*{.tmp,.svg,/} 2>/dev/null
}; export -f lastrites_cleanup
{ #DIALOG_TOOLTIP
export DIALOG_TOOLTIP='
<window type-hint="6" skip_taskbar_hint="true" window_position="2">
<eventbox>
	<hbox spacing="9">
	<vbox><pixmap icon_size="3"><input file stock="gtk-info"></input></pixmap></vbox>
	<text use-markup="true"><input file>"'$TTPFILE'"</input></text>
	</hbox>
</eventbox>
<variable>DIALOG_TOOLTIP</variable>
<action signal="leave-notify-event">closewindow:DIALOG_TOOLTIP</action>
<action signal="key-press-event">   closewindow:DIALOG_TOOLTIP</action>
<action signal="button-press-event">closewindow:DIALOG_TOOLTIP</action> 
</window>
'
}
{ #DIALOG_FULLSCREEN_TXT
export DIALOG_FULLSCREEN_TXT='
<window  type-hint="6"> 
	<vbox scrollable="true" width="'$SCREEN_W'" height="'$SCREEN_H'" >
		<notebook space-expand="true" space-fill="true"  show-tabs="false">
			<edit>
				<input file>'$SYMLINK'</input>
				<action signal="button-press-event" condition="command_is_true([[ $PTR_BTN == 3 ]] && echo true )">closewindow:DIALOG_FULLSCREEN_TXT</action> 
			</edit>
			<edit wrap-mode="2">
				<input file>'$SYMLINK'</input>
				<action signal="button-press-event" condition="command_is_true([[ $PTR_BTN == 3 ]] && echo true )">closewindow:DIALOG_FULLSCREEN_TXT</action> 
			</edit>
			<variable>vFDT_NOTE</variable>
			<input>echo $vNOTE</input>
		</notebook>
	</vbox>
	<variable>DIALOG_FULLSCREEN_TXT</variable>
	<action signal="key-press-event" condition="command_is_true([[ $KEY_SYM == Escape ]] && echo true )">closewindow:DIALOG_FULLSCREEN_TXT</action>
	<action signal="show">echo -n "$TT24" > $TTPFILE</action>
	<action signal="show">refresh:vFDT_NOTE</action>
	<action signal="map-event">launch:DIALOG_TOOLTIP</action>
</window>
'
}
{ #DIALOG_FULLSCREEN_PIX_NORMALSIZE
export DIALOG_FULLSCREEN_PIX_NORMALSIZE='
<window  type-hint="6" border-width="0"> 
	<vbox scrollable="true" shadow-type="0" width="'$SCREEN_W'" height="'$SCREEN_H'" >
		<pixmap  space-expand="true" space-fill="true" tooltip-markup="'$TT22'">
			<input file>'$SYMLINK'</input>
		</pixmap>
	</vbox>
	<variable>DIALOG_FULLSCREEN_PIX_NORMALSIZE</variable>
<action signal="button-press-event" condition="command_is_true( echo $((PTR_BTN==3))		)">launch:     DIALOG_FULLSCREEN_PIX_FIT2SCREEN</action> 
<action signal="button-press-event" condition="command_is_true( echo $((PTR_BTN!=3))		)">closewindow:DIALOG_FULLSCREEN_PIX_NORMALSIZE</action> 
<action signal="button-press-event" condition="command_is_true( echo $((PTR_BTN!=3))		)">closewindow:DIALOG_FULLSCREEN_PIX_FIT2SCREEN</action> 
<action signal="key-press-event"    condition="command_is_true( echo $(($KEY_VAL==0xff1b))	)">closewindow:DIALOG_FULLSCREEN_PIX_NORMALSIZE</action>
<action signal="key-press-event"    condition="command_is_true( echo $(($KEY_VAL==0xff1b))	)">closewindow:DIALOG_FULLSCREEN_PIX_FIT2SCREEN</action> 
</window>
'
}
{ #DIALOG_FULLSCREEN_PIX_FIT2SCREEN
export DIALOG_FULLSCREEN_PIX_FIT2SCREEN='
<window  type-hint="6" border-width="0" width-request="'$SCREEN_W'" height-request="'$SCREEN_H'">
	<eventbox>
			<pixmap tooltip-markup="'$TT23'">
				<width>'$SCREEN_W'</width>
				<height>'$SCREEN_H'</height>
				<input file>'$SYMLINK'</input>
			</pixmap>
	</eventbox>
	<variable>DIALOG_FULLSCREEN_PIX_FIT2SCREEN</variable>
<action signal="button-press-event" condition="command_is_true( echo $((PTR_BTN==1))		)">launch:     DIALOG_FULLSCREEN_PIX_NORMALSIZE</action> 
<action signal="button-press-event" condition="command_is_true( echo $((PTR_BTN!=1))		)">closewindow:DIALOG_FULLSCREEN_PIX_NORMALSIZE</action> 
<action signal="button-press-event" condition="command_is_true( echo $((PTR_BTN!=1))		)">closewindow:DIALOG_FULLSCREEN_PIX_FIT2SCREEN</action> 
<action signal="key-press-event"    condition="command_is_true( echo $(($KEY_VAL==0xff1b))	)">closewindow:DIALOG_FULLSCREEN_PIX_NORMALSIZE</action>
<action signal="key-press-event"    condition="command_is_true( echo $(($KEY_VAL==0xff1b))	)">closewindow:DIALOG_FULLSCREEN_PIX_FIT2SCREEN</action> 
</window>
'
}
{ #DIALOG_MULTI
export DIALOG_MULTI='
<window modal="true" window-position="2" image-name="'$ICONMMV'" resizable="false">
<vbox>
	<text xalign="0" use-markup="true"><input file>'$D_LABEL'</input></text>
	<entry activates_default="true">
		<input file>'$D_DEFLT'</input>
		<variable>vD_ENTRY</variable>
	</entry>
	<vbox>
		<frame Search in ...>
		<hbox space-expand="true" space-fill="true" sensitive="true">
			<radiobutton label="FILES" tooltip-markup="'$TT67'">
				<variable>vCHB_TREE</variable>
				<input file>'$FNDTREE'</input>
				<action>if true enable:vVBOX_FILESEARCH</action>
			</radiobutton>
			<radiobutton label="VIEWER PANE" tooltip-markup="'$TT60'">
				<variable>vCHB_PANE</variable>
				<input file>'$FNDPANE'</input>
				<action>if true disable:vVBOX_FILESEARCH</action>
			</radiobutton>
		</hbox>
		</frame>
		<frame Options>
			<checkbox label="Use regular expressions" tooltip-markup="'$TT66'"><variable>vCHB_REGX</variable><input file>'$FNDREGX'</input></checkbox>
			<checkbox label="Match any case" tooltip-text="'$TT61'"><variable>vCHB_CASE</variable><input file>'$FNDCASE'</input></checkbox>
			<checkbox label="Match only whole word"  tooltip-text="'$TT65'"><variable>vCHB_WORD</variable><input file>'$FNDWORD'</input></checkbox>
			<checkbox label="Use inline markers" tooltip-text="'$TT35'"><variable>vCHB_MARK</variable><input file>'$FNDMARK'</input></checkbox>
			<hseparator></hseparator>
			<vbox>
				<checkbox label="Include binaries" tooltip-text="'$TT62'"><variable>vCHB_BINA</variable><input file>'$FNDBINA'</input></checkbox>
				<checkbox label="Follow symlinks"  tooltip-text="'$TT63'"><variable>vCHB_SYML</variable><input file>'$FNDSYML'</input></checkbox>
				<variable>vVBOX_FILESEARCH</variable>
			</vbox>
		</frame>
		<variable>vD_CHECKBOXES</variable>
	</vbox>
	<hbox>
		<button label="gtk-cancel" use-stock="true" width-request="180">
			<variable>vD_BTN_CANCEL</variable>
			<action>closewindow:DIALOG_MULTI</action>
			<action>presentwindow:MAIN_DIALOG</action>
		</button>
		<button label="gtk-ok" use-stock="true" width-request="180" can-default="true" has-default="true">
			<action condition="command_is_true(run_dialog)">activate:vMACRO_VIEWTEXT</action>
			<action condition="command_is_true([[ -s $STBFILE ]] && echo true  )">refresh:vSTATUSBAR</action>
			<action condition="visible_is_true(vD_CHECKBOXES)">activate:vMENU_FINDAGAIN</action>
			<action>closewindow:DIALOG_MULTI</action>
			<action>presentwindow:MAIN_DIALOG</action>
		</button>
	</hbox>
</vbox>
<variable>DIALOG_MULTI</variable>
<input file>'$D_TITLE'</input>
<action signal="focus-out-event">presentwindow:DIALOG_MULTI</action>
<action signal="show" condition="command_is_true([[ $(<$D_TITLE) != Find ]] && echo true )">hide:vD_CHECKBOXES</action>
<action signal="key-press-event" condition="command_is_true([ $KEY_SYM = Escape ] && echo true )">closewindow:DIALOG_MULTI</action>
<action signal="key-press-event" condition="command_is_true([ $KEY_SYM = Escape ] && echo true )">presentwindow:MAIN_DIALOG</action>
</window>'
}
{ #MACROS
MACROS='
<menu visible="false">
	<menuitem>
		<variable>vMACRO_REFRESH</variable>
		<action condition="active_is_false(vMENU_DISABLEVIEW)">activate:vMACRO_REFRESH_FORCE</action>
	</menuitem>
	<menuitem>
		<variable>vMACRO_REFRESH_FORCE</variable>
		<action>refresh:vSTATUSBAR</action>
		<action>view_instantly</action>
		<action>activate:vMACRO_REFRESH_NOTE</action>
	</menuitem>
	<menuitem>
		<variable>vMACRO_REFRESH_NOTE</variable>
		<action condition="command_is_true( echo $(($(<$NB_PAGE)!=vNOTE)) )">refresh:vNOTE</action>
		<action condition="command_is_true( echo $((vNOTE==0)) )">refresh:vEDI0</action>
		<action condition="command_is_true( echo $((vNOTE==1)) )">refresh:vEDI1</action>
		<action condition="command_is_true( echo $((vNOTE==2)) )">refresh:vPIX2</action>
		<action condition="command_is_true( echo $((vNOTE==2)) )">refresh:vTXT2</action>
		<action condition="command_is_true( echo $((vNOTE==3)) )">refresh:vPIX3</action>
		<action condition="command_is_true( echo $((vNOTE==3)) )">refresh:vTXT3</action>
	</menuitem>
	<menuitem>
		<variable>vMACRO_WRITECMD</variable>
		<action>grabfocus:vCMDLINE</action>
		<action>clear:vCMDLINE</action>
		<action>refresh:vCMDLINE</action>
	</menuitem>
	<menuitem>
		<variable>vMACRO_OPEN_COMMANDBOX</variable>
		<action>disable:vMENU_CMDBOX_OPEN</action>
		<action>enable:vMENU_F4</action>
		<action>enable:vMENU_CMDBOX_CLOSE</action>
		<action>show:vCOMMANDBOX</action>
	</menuitem>
	<menuitem>
		<variable>vMACRO_VIEWTEXT</variable>
		<action condition="active_is_true (vMENU_WRAP)">printf 1 > $NB_PAGE</action> 
		<action condition="active_is_false(vMENU_WRAP)">printf 0 > $NB_PAGE</action> 
		<action condition="active_is_true (vMENU_WRAP)">refresh:vEDI1</action> 
		<action condition="active_is_false(vMENU_WRAP)">refresh:vEDI0</action> 
		<action>refresh:vNOTE</action>
	</menuitem>
	<menuitem>
		<variable>vMACRO_VIEWTEXT_WRAPPED</variable>
		<action>printf 1 > $NB_PAGE</action> 
		<action>refresh:vEDI1</action> 
		<action>refresh:vNOTE</action>
	</menuitem>
</menu>
'
}
{ #MENU_FILE
MENU_FILE='<menu label="File">
	<menuitem label="New File" accel-key="0x6e" accel-mods="4" stock-id="gtk-file" tooltip-text="'$TT27'">
		<action>run_dialog Create</action>
		<action>launch:DIALOG_MULTI</action>
	</menuitem>
	<menuitemseparator></menuitemseparator>
	<menuitem label="Rename"  accel-key="0xffbf" accel-mods="0" stock-id="gtk-strikethrough" tooltip-text="'$TT18'">
		<action>run_dialog Rename</action>
		<action>launch:DIALOG_MULTI</action>
	</menuitem>
	<menuitem label="Duplicate (copy)" accel-key="0x64" accel-mods="4"stock-id="gtk-copy" tooltip-text="'$TT19'">
		<action>run_dialog Duplicate</action>
		<action>launch:DIALOG_MULTI</action>
	</menuitem>
	<menuitem label="Compress/Decompress"  accel-key="0x47" accel-mods="4"  '$ICON_COMPRESS'  tooltip-text="'$TT34'">
		<variable>vMENU_COMPRESS</variable>
		<width>16</width>
		<action>file_compress</action>
		<action>refresh:vSTATUSBAR</action>
	</menuitem>
	<menuitem label="Edit" accel-key="0x45" accel-mods="4" stock-id="gtk-edit" tooltip-text="'$TT13'">
		<variable>vMENU_OPENEDITOR</variable>
		<action>file_edit</action>
	</menuitem>
	<menuitem label="Delete" accel-key="0x78" accel-mods="4" stock-id="gtk-delete" tooltip-text="'$TT20'">
		<action>run_dialog Delete</action>
		<action>launch:DIALOG_MULTI</action>
	</menuitem>
	<menuitemseparator></menuitemseparator>
	<menuitem label="Run in console" accel-key="0xffc2" accel-mods="4" stock-id="gtk-execute" tooltip-text="'$TT14'">
		<variable>vMENU_RUNCONSOLE</variable>
		<action>run_in_console</action>
	</menuitem>'

	[[ $XDG_SESSION_TYPE !=  wayland ]] && MENU_FILE+='
	<menuitem label="Show in ROX" accel-key="0x72" accel-mods="4" stock-id="gtk-jump-to" tooltip-text="'$TT15'">
		<variable>vMENU_SHOWINROX</variable>
		<action>rox -s "$vCHOOSER"</action>
	</menuitem>
	<menuitem label="Open With ...	(MiddleClick)" tooltip-text="'$TT42'">
		<variable>vMENU_OPENWITH</variable>
		<action>file_openwith &</action>
	</menuitem>'

	MENU_FILE+='<menuitemseparator></menuitemseparator>
	<menuitem label="Properties"  accel-key="0x70" accel-mods="4" stock-id="gtk-properties" tooltip-text="'$TT16'">
		<variable>vMENU_PROPERTIES</variable>
		<action>file_properties</action>
		<action>activate:vMACRO_VIEWTEXT</action>
	</menuitem>
	<menuitem label="MD5 checksum" accel-key="0x35" accel-mods="4" stock-id="gtk-properties" tooltip-text="'$TT33'">
		<variable>vMENU_MD5</variable>
		<action>file_md5</action>
		<action>activate:vMACRO_VIEWTEXT</action>
	</menuitem>
	<menuitemseparator></menuitemseparator>
	<menuitem label="New Window" accel-key="0x6e" accel-mods="5"  stock-id="gtk-add">
		<action>echo -n > $RESTRTD ; exec "$APP_PATH" "$vCHOOSER" &</action>
	</menuitem>
	<menuitem label="Restart" accel-key="0x071" accel-mods="5" stock-id="gtk-quit">
		<variable>vMENU_RESTART</variable>
		<action>lastrites_save;echo -n > $RESTRTD;exec "$APP_PATH" &</action>
		<action>exit:</action>
	</menuitem>
	<menuitem label="Quit" accel-key="0x071" accel-mods="4" stock-id="gtk-quit"  tooltip-text="'$TT26'">
		<action>activate:vBTN_QUIT</action>
	</menuitem>
</menu>'
}
{ #MENU_SEARCH
MENU_SEARCH='<menu label="Search">
	<menuitem label="Find ..." accel-key="0x46" accel-mods="4"  stock-id="gtk-find" tooltip-text="'$TT37'">
		<action>run_dialog Find</action>
		<action>launch:DIALOG_MULTI</action>
	</menuitem>
	<menuitem label="Find again" accel-key="0xffc0" accel-mods="0">
		<variable>vMENU_FINDAGAIN</variable>
		<action>find_again</action>
		<action>refresh:vSTATUSBAR</action>
		<action>activate:vMACRO_VIEWTEXT</action>
	</menuitem>
</menu>'
}
{ #MENU_VIEW
MENU_VIEW='<menu label="View">
	<menuitem label="Alternate view (see tooltip)" tooltip-text="'$TT01'" accel-key="0xffbe" accel-mods="0"  stock-id="gtk-info">
		<variable>vMENU_F1</variable>
		<action condition="command_is_true( [[ $vSTATUSBAR != *$vCHOOSER*│* ]] && echo true )">refresh:vSTATUSBAR</action>
		<action condition="command_is_true(view_on_demand && echo 1)">activate:vMACRO_REFRESH_NOTE</action>
	</menuitem>
	<menuitemseparator></menuitemseparator>
	<menuitem label="Hexdump of current file"  image-name="'$ICONHEX'" accel-key="0x48" accel-mods="4" tooltip-text="'$TT46'">
		<variable>vMENU_HEXDUMP_HEAD</variable>
		<action>view_hexdump dumphead</action>
		<action>activate:vMACRO_VIEWTEXT</action>
	</menuitem>
	<menuitem label="ASCII strings in current file" image-name="'$ICOASCI'" tooltip-text="'$TT50'">
		<variable>vMENU_PRINTABLES</variable>
		<action condition="command_is_true(ascii_strings && echo true )">activate:vMACRO_VIEWTEXT</action>
	</menuitem>
<menu label="More View Options for Binaries...">
	<menuitem label="Hexdump (in '"$HEXDUMP_VIEWER"')" image-name="'$ICONHEX'" tooltip-text="'$TT48'">
		<variable>vMENU_HEXDUMP_ALL</variable>
		<action>view_hexdump dumpall</action>
	</menuitem>
	<menuitem label="❰hex❱view (max '$((HEXDUMP_MAXBYTES/1000))'KB)" image-name="'$ICONHEX'" tooltip-text="'$TT47'">
		<variable>vMENU_HEXMARK_HEAD</variable>
		<action>view_hexdump markhead</action>
		<action>activate:vMACRO_VIEWTEXT_WRAPPED</action>
	</menuitem>
	<menuitem label="❰hex❱view (in '"$HEXDUMP_VIEWER"')" image-name="'$ICONHEX'" tooltip-text="'$TT48'">
		<variable>vMENU_HEXMARK_ALL</variable>
		<action>view_hexdump markall</action>
	</menuitem>
	<menuitem visible="false">
		<variable>vMENU_HEXDUMP_HELP</variable>
		<action>view_hexdump help</action>
		<action>activate:vMACRO_VIEWTEXT_WRAPPED</action>
	</menuitem>
	<menuitemseparator></menuitemseparator>
	<menuitem label="Printable strings - set minimum length ..." image-name="'$ICOASCI'" tooltip-text="">
		<variable>vMENU_PRINTABLES_SET</variable>
		<action>ascii_strings_length</action> 
	</menuitem>
</menu>
	<menuitemseparator></menuitemseparator>
	<menuitem label="Current Text Selection" image-name="'$ICONSEL'"   REM="accel-key can cause freeze!" tooltip-text="'$TT54'">
		<variable>vMENU_SELECTION</variable>
		<action>prep_selection press &</action>
		<action>activate:vHIDDENBUT_VIEWCHAR</action>
	</menuitem>
	<menuitem label="ASCII table" image-name="'$ICOASCI'" tooltip-text="'$TT51'">
		<variable>vMENU_ASCII_TABLE</variable>
		<action>ascii_table</action> 
		<action>activate:vMACRO_VIEWTEXT</action>
	</menuitem>
	<menuitemseparator></menuitemseparator>
	<menuitem label="Refresh" accel-key="0xffc2" accel-mods="0" stock-id="gtk-refresh"  tooltip-text="'$TT06'">
		<variable>vMENU_REFRESH</variable>
		<action>echo 0 > $NB_PAGE</action>
		<action>activate:vMACRO_REFRESH_FORCE</action>
	</menuitem>
	<menuitem label="Disable Instant View Mode" checkbox="" tooltip-text="">
		<variable>vMENU_DISABLEVIEW</variable>
		<action condition="command_is_true( [[ $vMENU_DISABLEVIEW != $vBTN_DISABLEVIEW ]] && echo true )">activate:vBTN_DISABLEVIEW</action> 
		<action>if true echo  "$HLP2" > $MSGFILE && ln -fsn $MSGFILE $SYMLINK</action>
		<action>if true activate:vMACRO_VIEWTEXT</action>
		<action>if false activate:vMENU_REFRESH</action>
	</menuitem>
	<menuitem label="Vertical layout" tooltip-text="'$TT43'" checkbox="'$LAYOUT_V'" >
		<variable>vMENU_LAYOUT</variable>
		<action>if true  sed -i "/LAYOUT_V/s/=.*/=1/" $CFGFILE</action>
		<action>if false sed -i "/LAYOUT_V/s/=.*/=0/" $CFGFILE</action>
		<action>activate:vMENU_RESTART</action>
	</menuitem>
</menu>'
}
{ #MENU_PLAY
MENU_PLAY='<menu label="Play">
	<menuitem label="Play video/audio files" checkbox="" accel-key="0x7a" accel-mods="4"  tooltip-text="'$TT04'">
		<variable>vMENU_PLAY</variable>
	   <action>if false busybox pkill MMplayme</action>
	   <action>if true view_instantly</action> 
	</menuitem>
</menu>'
}
{ #MENU_DOCUMENT
MENU_DOCUMENT='<menu label="Document">
	<menuitem label="Wrap Lines" checkbox="" accel-key="0xffc3" accel-mods="0" tooltip-text="'$TT31'">
		<variable>vMENU_WRAP</variable>
		<action condition="command_is_true( (( $vNOTE < 2 )) && echo true )">activate:vMACRO_VIEWTEXT</action> 
		<action condition="command_is_true( [[ $vMENU_WRAP != $vBTN_WRAP ]] && echo true )">activate:vBTN_WRAP</action> 
	</menuitem>
	<menuitem label="Show Line Numbers" accel-key="0xffc3" accel-mods="4"  tooltip-text="'$TT05'">
		<action>add_linenumbers</action>
		<action>activate:vMACRO_VIEWTEXT</action>
	</menuitem>
</menu>'
}
{ #MENU_COMMANDS
MENU_COMMANDBOX='<menu label="Commands">
	<menuitem label="Open"  accel-key="0x21"   accel-mods="1" tooltip-text="'$TT07'">
		<variable>vMENU_CMDBOX_OPEN</variable>
		<action>activate:vMACRO_OPEN_COMMANDBOX</action>
		<action>echo " \"\$@\" " > $COMMAND</action>
		<action>activate:vMACRO_WRITECMD</action>
	</menuitem>
	<menuitem label="Open with last command"  accel-key="0x21" accel-mods="5" tooltip-text="'$TT08'">
		<action>activate:vMACRO_OPEN_COMMANDBOX</action>
		<action>tail -n1 $HISTORY > $COMMAND</action>
		<action>activate:vMACRO_WRITECMD</action>
	</menuitem>
	<menuitem label="Close" accel-key="0xff1b" accel-mods="0" stock-id="gtk-close" tooltip-text="'$TT09'">
		<action>hide:vCOMMANDBOX</action>
		<action>enable:vMENU_CMDBOX_OPEN</action>
		<action>disable:vMENU_F4</action>
		<action>activate:vMENU_REFRESH</action>
	</menuitem>
	<menuitem label="Run command" accel-key="0xffc1" accel-mods="0" stock-id="gtk-execute" tooltip-text="'$TT03'">
		<variable>vMENU_F4</variable>
		<action>run_shell_command</action>
		<action>activate:vMACRO_VIEWTEXT</action>
	</menuitem>
	<menuitemseparator></menuitemseparator>
	<menuitem label="View Command History" image-name="'$ICONMMV'" tooltip-text="'$TT10'">
		<variable>vMENU_VIEWHISTORY</variable>
		<width>16</width>
		<action>ln -fsn $HISTORY $SYMLINK</action>
		<action>activate:vMACRO_VIEWTEXT</action>
	</menuitem>
	<menuitem label="Edit Command History" stock-id="gtk-edit" tooltip-text="'$TT11'">
		<action>defaulttexteditor $HISTORY</action>
	</menuitem>
	<menuitem label="Clear Command History" stock-id="gtk-delete" tooltip-text="'$TT12'">
		<action>echo -n > $HISTORY</action>
	</menuitem>
</menu>'
}
{ #TOOLBAR
((TB_SEL2UTF)) && TOOLBAR=$TOOLBAR'<button can-focus="false"  tooltip-text="'$TT55'">
<input file>"'$ICONSEL'"</input>
	<action signal="button-press-event"  >((PTR_BTN==3))&& $cmdCLIP -o > $TMPFILE &</action> 
	<action signal="button-release-event">((PTR_BTN==3))&& gxmessage -title "MMview - Selection Zoom (max '$SELZOOM_MAXBYTES' bytes)" -ne -geo 530x-1 -fn "124" -de okay $(head -c'$SELZOOM_MAXBYTES' $TMPFILE | iconv -ct UTF-8) &</action> 
	<action>activate:vMENU_SELECTION</action>
</button>'
((TB_ASCII)) && TOOLBAR=$TOOLBAR'<button can-focus="false" tooltip-text="'$TT52'">
	<input file>"'$ICOASCI'"</input>
	<action signal="button-press-event">  refresh:vTSTART</action>
	<action signal="button-release-event">refresh:vDURATION</action>
	<action signal="button-release-event" condition="command_is_true( echo $((PTR_BTN==3)))">activate:vMENU_ASCII_TABLE</action> 
	<action condition="command_is_true( echo $((vDURATION<=CLICKPRESS_DELAY)) )">activate:vMENU_PRINTABLES</action>
	<action condition="command_is_true( echo $((vDURATION >CLICKPRESS_DELAY)) )">activate:vMENU_PRINTABLES_SET</action>
</button>'
((TB_HEX)) && TOOLBAR=$TOOLBAR'<button can-focus="false" tooltip-text="'$TT44'">
	<input file>"'$ICONHEX'"</input>
	<action signal="button-press-event">  refresh:vTSTART</action>
	<action signal="button-release-event">refresh:vDURATION</action>
	<action condition="command_is_true( echo $((vDURATION<=CLICKPRESS_DELAY)) )">activate:vMENU_HEXDUMP_HEAD</action>
	<action condition="command_is_true( echo $((vDURATION >CLICKPRESS_DELAY)) )">activate:vMENU_HEXDUMP_ALL</action>
	<action signal="button-release-event" condition="command_is_true( echo $((PTR_BTN==3 && vDURATION<=CLICKPRESS_DELAY)) )">activate:vMENU_HEXMARK_HEAD</action>
	<action signal="button-release-event" condition="command_is_true( echo $((PTR_BTN==3 && vDURATION >CLICKPRESS_DELAY)) )">activate:vMENU_HEXMARK_ALL</action>
</button>'
((TB_WRAP)) && TOOLBAR=$TOOLBAR'<togglebutton can-focus="false" tooltip-text="'$TT31'">
	<variable>vBTN_WRAP</variable>
	<input file>"'$ICOWRAP'"</input>
	<action>if true sed -i  "s|$SVGWRAP_1|$SVGWRAP_2|" "'$ICOWRAP'"</action>
	<action>if false sed -i "s|$SVGWRAP_2|$SVGWRAP_1|" "'$ICOWRAP'"</action>
	<action condition="command_is_true( [[ $vMENU_WRAP != $vBTN_WRAP ]] && echo true )">activate:vMENU_WRAP</action> 
	<action>refresh:vBTN_WRAP</action>
</togglebutton>'
((TB_PROPERTIES)) && TOOLBAR=$TOOLBAR'<button can-focus="false" tooltip-text="'$TT16'"><action>activate:vMENU_PROPERTIES</action><input file stock="gtk-properties"></input></button>'
((TB_OPENEDITOR)) && TOOLBAR=$TOOLBAR'<button can-focus="false" tooltip-text="'$TT13'"><action>activate:vMENU_OPENEDITOR</action><input file stock="gtk-edit"></input></button>'
((TB_SHOWINROX))  && TOOLBAR=$TOOLBAR'<button can-focus="false" tooltip-text="'$TT15'"><action>activate:vMENU_SHOWINROX</action><input file stock="gtk-jump-to"></input></button>'
((TB_INSTANTVIEW))&& TOOLBAR=$TOOLBAR'<togglebutton can-focus="false" tooltip-text="'"$TT39"'" can-focus="false">
	<variable>vBTN_DISABLEVIEW</variable>
	<input file>"'$ICOVIEW'"</input>
	<action>if true sed  -i "s|$SVGVIEW_1|$SVGVIEW_2|" "'$ICOVIEW'"</action>
	<action>if false sed -i "s|$SVGVIEW_2|$SVGVIEW_1|" "'$ICOVIEW'"</action>
	<action>refresh:vBTN_DISABLEVIEW</action>
	<action condition="command_is_true( [[ $vMENU_DISABLEVIEW != $vBTN_DISABLEVIEW ]] && echo true )">activate:vMENU_DISABLEVIEW</action> 
	</togglebutton>'
((TB_REFRESH))		&& TOOLBAR=$TOOLBAR'<button can-focus="false" tooltip-text="'$TT06'"><action>activate:vMENU_REFRESH</action><input file stock="gtk-refresh"></input></button>'
((TB_ALTERNATEVIEW))&& TOOLBAR=$TOOLBAR'<button can-focus="false" tooltip-text="'$TT40'"><action>activate:vMENU_F1</action><input file stock="gtk-info"></input></button>'
}
{ #MAIN_DIALOG
export MAIN_DIALOG='
<window title="'"$WINTITLE"'" default-width="'$WIN_W'"  default-height="'$WIN_H'" allow-shrink="true" margin="'$WINDOW_MARGIN'" image-name="'$ICONMMV'">
<vbox space-expand="true" space-fill="true"  spacing="'$WIDGETSPACING'">
	<hbox space-expand="false" spacing="0">
		<menubar  height-request="'$MENUBAR_HIGHT'" space-fill="true" space-expand="true">
			'"$MACROS"'
			'"$MENU_FILE"'
			'"$MENU_SEARCH"'
			'"$MENU_VIEW"'
			'"$MENU_PLAY"'
			'"$MENU_DOCUMENT"'
			'"$MENU_COMMANDBOX"'
		</menubar>
		'"$TOOLBAR"'
	</hbox>
	<'$BOX'box space-expand="true"  spacing="'$CENTERSPACING'">
		<chooser width-request="'$CHOOSER_WIDTH'" height-request="'$CHOOSER_HIGHT'" space-expand="false" space-fill="true">
			<variable>
"vCHOOSER"
			</variable>
			<default>"'$DEFAULT_DIRECTORY'"</default>
			<action>rox "$vCHOOSER"</action> 
			<action signal="button-release-event">[[ $PTR_BTN = 2 ]] && file_openwith &</action>
			<action when="update-preview">activate:vMACRO_REFRESH</action>
		</chooser>
		<'$SEP'separator space-expand="false"></'$SEP'separator>
		<notebook space-fill="true" space-expand="true" show-tabs="false" show-border="false">
			<vbox   tooltip-text="'$TT25'">
				<edit left-margin="'$L_EDIT_MARGIN'">
					<variable export="false">
"vEDI0"
					</variable>
					<input file>'$SYMLINK'</input>
					<action signal="button-press-event" condition="command_is_false( echo $((PTR_BTN-3)) )">launch:DIALOG_FULLSCREEN_TXT</action> 
				</edit>
			</vbox>
			<vbox   tooltip-text="'$TT25'">
				<edit left-margin="'$L_EDIT_MARGIN'" wrap-mode="2">
					<variable export="false">
"vEDI1"
					</variable>
					<input file>'$SYMLINK'</input>
					<action signal="button-press-event" condition="command_is_false( echo $((PTR_BTN-3)) )">launch:DIALOG_FULLSCREEN_TXT</action> 
				</edit>
			</vbox>
			<eventbox  tooltip-text="'$TT21'">
				<vbox>
					<text>
						<variable export="false">
"vTXT2"
						</variable>
						<input file>"'$TMPFILE'"</input>
					</text>
					<vbox scrollable="true" shadow-type="0" space-expand="true">
						<pixmap>
							<variable export="false">
"vPIX2"
							</variable>
							<input file>'$SYMLINK'</input>
						</pixmap>
					</vbox>
				</vbox>
				<action signal="button-press-event" condition="command_is_true( [[ $PTR_BTN == 1 ]] && echo true )">launch:DIALOG_FULLSCREEN_PIX_NORMALSIZE</action> 
				<action signal="button-press-event" condition="command_is_true( [[ $PTR_BTN == 3 ]] && echo true )">launch:DIALOG_FULLSCREEN_PIX_FIT2SCREEN</action> 
			</eventbox>
			<eventbox  tooltip-text="'$TT21'">
				<vbox>
					<text>
						<variable export="false">
"vTXT3"
						</variable>
						<input file>"'$TMPFILE'"</input>
					</text>
					<pixmap space-expand="true">
						<variable export="false">
"vPIX3"
						</variable>
						<width>'$VIEWER_W'</width>
						<height>'$VIEWER_H'</height>
						<input file>'$SYMLINK'</input>
					</pixmap>
				</vbox>
				<action signal="button-press-event" condition="command_is_true( [[ $PTR_BTN == 1 ]] && echo true )">launch:DIALOG_FULLSCREEN_PIX_NORMALSIZE</action> 
				<action signal="button-press-event" condition="command_is_true( [[ $PTR_BTN == 3 ]] && echo true )">launch:DIALOG_FULLSCREEN_PIX_FIT2SCREEN</action> 
			</eventbox>
			<variable>
"vNOTE"
			</variable>
			<input file>'$NB_PAGE'</input>
		</notebook>
	</'$BOX'box>
	<hbox space-expand="false" visible="false" spacing="0">
		<button relief="2"><input file stock="gtk-help"></input>
			<action>Xdialog --title "$WINTITLE" --left --msgbox "'$HLP1'" x &</action>
		</button>
		<text space-expand="false" xalign="0" label="Shell: "></text> 
		<entry space-fill="true" space-expand="true" secondary-icon-stock="gtk-clear" secondary-icon-tooltip-text="Clear command line">
			<variable>
"vCMDLINE"
			</variable>
			<input file>"'$COMMAND'"</input>
			<action signal="key-press-event" condition="command_is_true([[ $KEY_VAL == 0xff52 ]] && echo true )">activate:vMENU_VIEWHISTORY</action>
			<action signal="secondary-icon-release">clear:vCMDLINE</action>
			<action signal="activate">activate:vMENU_F4</action>
		</entry>
		<variable export="false">
"vCOMMANDBOX"
		</variable>
	</hbox>
	<hbox space-expand="false" margin="'$STATUS_MARGIN'" visible="true"> 
		<entry  space-expand="true">
			<variable>
"vSTATUSBAR"
			</variable>
			<input>fill_statusbar</input>
		</entry>
		<button label="   Quit   "  tooltip-text="'$TT26'">
			<variable>
"vBTN_QUIT"
			</variable>
			<action>lastrites_cleanup save</action>
			<action>exit:OK</action>
		</button>
	</hbox>
	<vbox visible="false">
		<text><variable>vTSTART</variable><input>date +%s%2N</input></text>
		<text><variable>vDURATION</variable><input>echo -n $(($(date +%s%2N)-vTSTART))</input></text>
		<button>
			<variable>vHIDDENBUT_VIEWCHAR</variable>
			<action condition="command_is_false( prep_selection || echo false )">break:</action> 
			<action>printf 0 > $NB_PAGE</action>
			<action>refresh:vNOTE</action> 
			<action>refresh:vEDI0</action> 
		</button>
	</vbox>
</vbox>
<variable>MAIN_DIALOG</variable>
<action signal="delete-event">lastrites_cleanup</action>
<action signal="show">disable:vMENU_F4</action>
'"$MAP_XDOTOOL"'
'"$MAP_GEOMTRY"'
</window>
'
}
type -p gtk2dialog >/dev/null && GD=2 || GD=
exec -a "$WINTITLE" gtk${GD}dialog
