#!/bin/bash
### Universal file viewer
### MochiMoppel 2019-04-09
### http://www.murga-linux.com/puppy/viewtopic.php?t=109573
{ #File locations
[[ $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
}
{ #Files for TEMPDIR
  #*.tmp will be deleted after MMview session, other files remain alive until Puppy shutdown
export SYMLINK=${TEMPDIR}symlink.tmp	# <input file> source for <edit> and  <pixmap> widgets.
export MSGFILE=${TEMPDIR}msgfile.tmp	# contains info text
export NB_PAGE=${TEMPDIR}nb_page.tmp	# contains notebook page
export COMMAND=${TEMPDIR}command.tmp	# contains command string for vCMDLINE
export TMPFILE=${TEMPDIR}tmpfile.tmp	# multipurpose tmp file
export STBFILE=${TEMPDIR}stbfile.tmp	# contains optional content for status bar
export HISTORY=${TEMPDIR}history.txt	# contains command history
export D_TITLE=${TEMPDIR}d_title.tmp	# multi_dialog: title
export D_LABEL=${TEMPDIR}d_label.tmp	# multi_dialog: text label 
export D_DEFLT=${TEMPDIR}d_deflt.tmp	# multi_dialog: default text for entry widget
export TTPFILE=${TEMPDIR}ttpfile.tmp	# contains tooltip text for TOOLTIP_DIALOG
export MD5LIST=${TEMPDIR}md5list.tmp	# contains new and previous md5sum output
export FNDFILE=${TEMPDIR}fndfile.txt	# contains last used search pattern of Find dialog
export FNDREGX=${TEMPDIR}fndregx.txt	# regex checkbox  status (Find dialog)
export FNDCASE=${TEMPDIR}fndcase.txt	# case  checkbox  status (Find dialog)
export FNDWORD=${TEMPDIR}fndword.txt	# word  checkbox  status (Find dialog)
export FNDMARK=${TEMPDIR}fndmark.txt	# Do not extract  checkbox status (Find dialog)
export ICONMMV=${TEMPDIR}iconmmv.svg	# icon for titlebar and tray
export ICOWRAP=${TEMPDIR}icowrap.svg	# line wrap icon
export ICOVIEW=${TEMPDIR}icoview.svg	# instant view icon
export ICONHEX=${TEMPDIR}iconhex.svg	# hexdump icon
}
{ #Files for CNFGDIR
export LASTDIR=${CNFGDIR}lastdir		# contains last accessed directory
export LAST_WH=${CNFGDIR}last_wh		# contains last width height of window
export BOXMODE=${CNFGDIR}boxmode		# vertical layout flag
}
{ #Startup folder
  #Priorities: 1) Passed argument 2) Last used folder 3) Default '/'
if		[[ -e $1 ]];then
		[[ -d $1 ]]       && DEFAULT_DIRECTORY=$1 || DEFAULT_DIRECTORY=${1%/*}
else	[[ -s $LASTDIR ]] && DEFAULT_DIRECTORY=$(< $LASTDIR)
fi
[[ -d $DEFAULT_DIRECTORY ]] || DEFAULT_DIRECTORY=/
}
{ #Preferences
[[ -f $BOXMODE ]] && LAYOUT_V=true BOX=v SEP=h	|| LAYOUT_V=false BOX=h SEP=v	# orientation (horizontal or vertical)
}
{ #Miscellaneous variables
export BR=$'&#013;'			# new line in pango text
export LF=$'\n'
export TB=$'\t'
export S7='\xe2\x80\x87'	#FIGURE SPACE		( )
export S8='\xe2\x80\x88'	#PUNCTUATION SPACE	( )
export LINE20=$'\n────────────────────\n'
export LINE40=$'\n────────────────────────────────────────\n'
export APP_PATH=$(realpath "$0")
export SENDTOPATH="/root/.config/rox.sourceforge.net/SendTo/" # Contains "Open With" actions. Trailing slash mandatory.
export HEXDUMP_MAXBYTES=10000	#Max no. of bytes displayed as file header/footer
export HEXDUMP_VIEWER=leafpad	#external program to display complete hexdump 
export THRESHOLD=30				#clickpress time lag in 10/sec

}
{ #Screen dimension
[[ $(xwininfo -root) =~ Width:\ ([0-9]*).*Height:\ ([0-9]*) ]]
export SCREEN_W=${BASH_REMATCH[1]}
export SCREEN_H=${BASH_REMATCH[2]}
}
{ #Window dimension
[[ -s $LAST_WH ]] && read DEFAULT_WIDTH DEFAULT_HIGHT < $LAST_WH
((DEFAULT_WIDTH)) || DEFAULT_WIDTH=1000
((DEFAULT_HIGHT)) || DEFAULT_HIGHT=500
}
{ #Window content size
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)  
}
{ #Viewer pane dimension
if [[ $LAYOUT_V == true ]] ;then
	VIEWER_W=$((DEFAULT_WIDTH - WINDOW_MARGIN *2))
	VIEWER_H=$((DEFAULT_HIGHT - Y_AXIS_ADJUST - MENUBAR_HIGHT - CHOOSER_HIGHT - WINDOW_MARGIN - ( CENTERSPACING + WIDGETSPACING + STATUS_MARGIN) * 2 ))
else
	VIEWER_W=$((DEFAULT_WIDTH - X_AXIS_ADJUST - CHOOSER_WIDTH - (WINDOW_MARGIN + CENTERSPACING) * 2))
	VIEWER_H=$((DEFAULT_HIGHT - Y_AXIS_ADJUST - MENUBAR_HIGHT - (WINDOW_MARGIN + WIDGETSPACING + STATUS_MARGIN) * 2))
fi
export VIEWER_W VIEWER_H
}
{ #Utilities
PROBE=$(type  -p ffprobe) || { PROBE=$(type -p avprobe) || PROBE=false ;} ; export PROBE
PLAY=$(type   -p ffplay)  || { PLAY=$(type  -p avplay)  || PLAY=false  ;} ; export PLAY
CLIP=$(type   -p xclip)   || { CLIP=$(type  -p xsel)    || CLIP=false  ;} ; export CLIP
WMCTRL=$(type -p wmctrl)  || WMCTRL=false ; export WMCTRL
}
{ #File initialization
ln -fsn  /dev/null  $SYMLINK
echo  0	> $NB_PAGE
echo	> $TMPFILE
echo -n	> $STBFILE
echo -n	> $COMMAND
}
{ #Icons
RNDCOLOR=$(printf %x $RANDOM$RANDOM$RANDOM);RNDCOLOR=${RNDCOLOR//[0-7]};RNDCOLOR=${RNDCOLOR::3}
echo '<svg width="48" height="48" viewBox="0 0 100 100">
<style type="text/css" >
*			{fill:#fff;	stroke:#000;stroke-width:6}
polyline	{fill:none;stroke-linecap:round;}
circle		{fill:#'$RNDCOLOR'}
</style>
<!-- body,glasses,mouth,hair -->
<path		d="M-2,100 C0,-10 100,-10 102,100"/>
<circle		cx="27" cy="50" r="20"/>
<circle		cx="73" cy="50" r="20"/>
<polyline	points="65,80 70,80"/>
<polyline	points="40,5 50,15 70,10 60,17"/>
</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="#0" stroke-width="7" fill="none"/>
<path d="M0,50 C50,25 90,50 100,50M0,50 C50,120 90,50 100,50" stroke="#0" stroke-width="4" fill="#fff"/>
<circle	cx="40" cy="58" r="22"	fill="#1EB0FF"/>
<circle	cx="40" cy="58" r="12"	fill="#0"/>
<path d="M0L100 100M100 0L0 100" stroke="#0" stroke-width="'$SVGVIEW_1''  > $ICOVIEW

[[ -e $ICONHEX ]] || echo '<svg width="20" height="20" viewBox="0 0 100 100">
<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

[[ -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
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'
TT01=$'Executables:	Usage message (if available)\nDirectories:	Total size, incl. subdirectories\nImages:		Metadata (if available)\nArchives:		List of archive contents\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. '\''../foo'\'' will move '\''foo'\'' 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. '\''../foo'\'' will copy '\''foo'\'' to parent folder'
TT20=$'Delete file/directory\n\nNote: Wildcard characters supported, e.g. '\''*.mp3'\'' 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>${BR}</span>Rclick: close fullscreen"
TT25=$'Rclick: Fullscreen'
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'
TT39=$'Toggle Instant View mode'
TT40=$'Additional info for certain file types\n───────────────────────────\n'$TT01
TT42=$'Sends selected file to an application stored in ROX-Filer\x27s \x27\x27SendTo\x27\x27 directory\n\nA different directory can be defined by changing MMview\x27s SENDTOPATH variable'
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:  Convert text string${LINE20}Mclick:  ❰hex❱view (max $(($HEXDUMP_MAXBYTES/1000))KB)${LF}Mpress:❰hex❱view in $HEXDUMP_VIEWER${LINE20}For help press button > 1 sec"
export TT46="Displays up to $(($HEXDUMP_MAXBYTES/1000))KB of file content as hex values${LF}Left col displays decimal offsets, right col ASCII representations"
export 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."
export TT48="Output in external editor, no size restriction"
export TT49="Breaks a text string into its individual characters and displays each character's hex value"

}
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 {
	[[ $vMENU_PLAY = true  ]] && busybox pkill MMplayme
	[[ -s $MSGFILE         ]] && echo -n > $MSGFILE
	[[ $vMENU_WRAP = false ]] && echo  0 > $NB_PAGE || echo  1 > $NB_PAGE
	echo -n "$vCHOOSER" | $CLIP -i			# mimic ROX-Filer and send selected item to PRIMARY buffer

	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 ]];then
			MESSAGE="VIRTUAL FILE SYSTEM" 
		else
			MESSAGE=$(busybox timeout -t1 du -hs  "$vCHOOSER")
			if (($?));then
				MESSAGE="This takes too long. Instead 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 '*)	{	# Non scalable images
		echo -n "Original Size" > $TMPFILE
		echo 2 > $NB_PAGE
		};;
	*'.webp '*|*'.p'[bgp]'m '*)		{	# Images to be converted to JPG with ffmpeg
		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 '*) {
			 echo -n "SVG image, scaled to fit viewer" > $TMPFILE
			 echo  3 > $NB_PAGE
		};;
	*'.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
		};;
	*│*'text/'*|*│*'script'*|*│*'xml'*) {
		[[ $vCHOOSER = /sys/* ]] && MESSAGE=$(< "$vCHOOSER" )
		};;
	*│*'video'*|*'.mkv '*|*'.mpg '*) {
		MESSAGE=$($PROBE "$vCHOOSER" 2>&1)
		[[ $vMENU_PLAY == true && $PLAY != false ]] && exec -a MMplayme $PLAY -x 320 -y 180 -i "$vCHOOSER"  &
		};; 
	*│*'audio'*|*'.mp3 '*|*'.ogg '*|*'.wma '*) {
		[[ $vMENU_PLAY == true && $PLAY != false ]] && exec -a MMplayme $PLAY -nodisp -i "$vCHOOSER"  &
		if [[ $PROBE != false ]];then
			FFP=$($PROBE "$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
		};;
	*'.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
	FIGURESPACE=$'\xe2\x80\x87'	# Unicode U+2007
	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'*) {
		[[ -L $vCHOOSER || $vCHOOSER == /proc || $(< $MSGFILE) == EMPTY ]] && return
		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",  Directories:"dcnt" )\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
		};;
	*'.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.gz'*) {
		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 || { echo false &&  return ;}
	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 " ;&
	        *)	F2=$(printf "%'d\tbytes" $V2) F3=$(printf "%'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
	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 {
	local FILETYPE MIME CMD TMP SNDTOCATGR SNDTOCUSTM SNDTOEVERY SNDTO_MIME SNDTOSPACE SPACER1 SPACER2 SPACER3 XDIALOGITEMS
	[[ -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'
	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 "MMview" --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		# editor should open only regular files ...
	if [[ ! $vSTATUSBAR =~ (x-empty|│.*script|│.*text|│.*ascii|│.*utf-8) ]];then
		Xdialog --title MMview --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 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 convert_txt2hex {
	TXTSTRING="$@"
	ENCSTRING=$(printf %s "$TXTSTRING" | hexdump -ve '"\\"' -e '1/1 "x%02x"')
	CHAR_CODE=$(printf %s "$TXTSTRING" | sed 's/./&\x0/g' | hexdump -ve '"\\"' -e '1/1 "x%02x"' | sed 's/\\x00/\n/g; s/\\x0a/&\n/g')
	CHAR_CCNT=${#TXTSTRING}
	CHAR_BCNT=${ENCSTRING//[^x]/}
	CHAR_BCNT=${#CHAR_BCNT}
	((CHAR_CCNT >1)) && CPLURAL=s
	((CHAR_BCNT >1)) && BPLURAL=s
	for line in $CHAR_CODE;do
		NOTE=
		case $line in
		'\x09') CHAR='(TB)';;
		'\x0a') CHAR='(LF)';;
		'\x0d') CHAR='(CR)';;
		'\x6c') CHAR="$line" NOTE='lowercase L';;
		'\x49') CHAR="$line" NOTE='uppercase i';;
		'\x7c') CHAR="$line" NOTE='vertical bar';;
		'\x31') CHAR="$line" NOTE='number 1';;
		'\x30') CHAR="$line" NOTE='number 0';;
		'\x4f') CHAR="$line" NOTE='uppercase o';;
		'\x20') CHAR="$line" NOTE='space';;
		'\x7b') CHAR="$line" NOTE='left brace';;
		'\x7d') CHAR="$line" NOTE='right brace';;
		'\x28') CHAR="$line" NOTE='left parenthesis';;
		'\x29') CHAR="$line" NOTE='right parenthesis';;
		'\x27') CHAR="$line" NOTE='single quote';;
		'\x60') CHAR="$line" NOTE='grave';;
			 *) CHAR="$line";;
		esac
		CNT=$((CNT+1))
		MSG=${MSG}$(printf "%02d\t%b\t%s\t\t%s" $CNT $CHAR $line "$NOTE")$LF
	done
echo -n "▊TEXT STRING  ($CHAR_CCNT character${CPLURAL}; ${CHAR_BCNT} byte${BPLURAL}):
${TXTSTRING}${LF}
▊UTF-8 BYTESTRING:
${ENCSTRING}${LF}
▊CHARACTERS and their UTF-8 HEX CODES:
No. Char	Hex		Remarks${LINE40}${MSG}" > $MSGFILE

	ln -fsn $MSGFILE $SYMLINK
	echo true
} ;export -f convert_txt2hex
function view_archive {
		TOOLNAME=${@%% *}
		if type -p "$TOOLNAME" ;then
			case $vSTATUSBAR in
			 *'.iso '*|*│*/zip*|*'.7z '*)	$@ "$vCHOOSER" | sed "s/ /$S7/g" > $MSGFILE ;;
			 *)								$@ "$vCHOOSER" > $MSGFILE ;;
			esac
		else echo "Requires command line tool $TOOLNAME"	> $MSGFILE
		fi
		[[ $(file -b --mime-type $MSGFILE ) != 'text/plain' ]] && file -bL "$vCHOOSER" > $MSGFILE
		ln -fsn $MSGFILE $SYMLINK
};export -f view_archive
function view_exif {
	local SUMRY EXIV2 MDATA MSG IMGSIZE
	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
		;;
	'')									#no argument=called from view_on_demand
		((RET>1)) && return 1
		SUMRY=$(echo "$EXIV2" | sed "
		1,4d				#remove first 4 lines (basic data)
		/:[[:blank:]]$/d	#remove empty categories
		s/  /${S7}${S8}/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
		)		
		MDATA=$(exiv2 -pa "${vCHOOSER}" |sed -r '
		s/^([^ ]*) +[^ ]+ +[^ ]+(.*)$/\1=\2/	#skip 2nd and 3rd field
		s/\x0//g								#exiv2 output may contain NUL garbage; Gtk edit widget chokes  on it
		0,/^Exi/s//\n▊ EXIF METADATA\n&/			#Act on only 1st match of REGEX: 0,/REGEX/s//REPLACE_WITH/
		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 {
	if [[ $1 == help ]];then
		PRESS="Press means pressing button > ${THRESHOLD}/100 sec, i.e. slightly longer than normal click"
		echo "▊BUTTON HELP${LF}
LeftClick Hexdump${LINE40}${TT46}${LF}
LeftPress Hexdump${LINE40}${TT48}${LF}${PRESS}${LF}
RightClick Convert text string${LINE40}${TT49}${LF}Multiline strings are supported.${LF}Useful to determine UTF-8 codes, line endings, whitespaces and hard to distinguish characters like lowercase 'L' and uppercase 'i'${LF}
MiddleClick ❰hex❱view${LINE40}${TT47}${LF}Useful for binary files with large text content but few non-ASCII characters, e.g. corrupted text files${LF}
MiddlePress ❰hex❱view${LINE40}${TT48}${LF}${PRESS}" > $MSGFILE
		ln -fsn $MSGFILE $SYMLINK
		return
	fi
	[[ -d $vCHOOSER ]] && return
	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}"		;;
	dumpall)	TITLE="▊HEXDUMP of $vCHOOSER"	;PARAM= ;;
	markhead)	TITLE="▊HEXVIEW nonprintable and extended ASCII ${MAXKB}" ;;
	markall)	TITLE="▊HEXVIEW nonprintable and extended ASCII of $vCHOOSER" ;PARAM=  ;;
	esac
	TITLE=${TITLE}$LINE40
	case $1 in
	dump[ha]*)	{ echo -n "$TITLE" ; hexdump $PARAM -e '1 "%03_ad: "' -e '10/1 " %02X" "\t""|" ' -e '10/1 "%_p" "\n"'  "$vCHOOSER" ;} > $MSGFILE
				;;&	#continue pattern match
	   dumpall)	$HEXDUMP_VIEWER $MSGFILE & return ;;
	 mark[ha]*)	{ echo -e "$TITLE"$(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") ;} > $MSGFILE

				;;&	#continue pattern match
	  markall)	$HEXDUMP_VIEWER $MSGFILE & return ;;
	esac
	ln -fsn $MSGFILE $SYMLINK
} ;export -f view_hexdump
function find_again {
	[[ -s $MSGFILE ]] && SOURCEFILE=$MSGFILE || SOURCEFILE=$vCHOOSER
	FIND="$(< $FNDFILE)"
	[[ $FIND ]] || return 1
	[[ $vCHB_REGX = true ]] && OPT_REGX=-E TXT=Regex || OPT_REGX=-F TXT=Text
	[[ $vCHB_CASE = true ]] && OPT_CASE=             || OPT_CASE=-i
	[[ $vCHB_WORD = true ]] && OPT_WORD=-w           || OPT_WORD=
	CNT=$(grep $OPT_REGX $OPT_CASE $OPT_WORD -o "$FIND" "$SOURCEFILE" |wc -l)
	((CNT>1)) && PL=es || { ((CNT<1)) && CNT=no ;}
	echo "$TXT Search for \"$FIND\" found $CNT match$PL" > $STBFILE
	((CNT)) || return	# avoid blank viewer pane
	if [[ $vCHB_MARK = true ]];then
		ESC=$(echo -e "\033")
		grep --color=always -C999 $OPT_REGX $OPT_CASE  $OPT_WORD -n "$FIND" "$SOURCEFILE" | sed "s/$ESC\[01;31m$ESC\[K/▊/g;s/$ESC\[[0-9;]*m$ESC\[K//g" > $TMPFILE
	else
		grep $OPT_REGX $OPT_CASE  $OPT_WORD  -n "$FIND" "$SOURCEFILE" > $TMPFILE
	fi
	ln -fsn $TMPFILE $SYMLINK
};export -f find_again
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 {
		[[ $vSTATUSBAR =~  (x-executable|x-shellscript) ]] &&
		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
			printf "$1"							> $D_TITLE
		case $1 in
		Rename|Duplicate)
			printf "<b><big>${1^^}</big></b>"	> $D_LABEL
			printf "${vCHOOSER##*/}"			> $D_DEFLT
			;;
		Create)
			printf "<b><big>${1^^}</big> new file or directory</b> <small>(append / )</small>"	> $D_LABEL
			printf "$vCHOOSER"					> $D_DEFLT
			;;
		Delete)
			[[ -d $vCHOOSER ]] && D=" DIRECTORY"
			printf "<span color='white' bgcolor='red'><b><big> ${1^^}$D </big></b></span>"	> $D_LABEL
			printf "${vCHOOSER##*/}"			> $D_DEFLT
			;;
		Convert_Text*)
			printf $'<b><big>Enter text string</big></b>\nto be converted to hex and single character codes'	> $D_LABEL
			printf ""							> $D_DEFLT
			;;
		Find)
			printf "<b><big>${1^^}</big></b>"	> $D_LABEL
			printf "$(<$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
						[[ ${vD_ENTRY: -1} = / ]] &&  mkdir -p "$vD_ENTRY" &> $STBFILE  || touch "$vD_ENTRY" &> $STBFILE
						;;
			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	;;
			Convert_Text)	convert_txt2hex "$vD_ENTRY";;
			Find)		printf "$vD_ENTRY"	> $FNDFILE
						printf $vCHB_REGX	> $FNDREGX
						printf $vCHB_CASE	> $FNDCASE
						printf $vCHB_WORD	> $FNDWORD
						printf $vCHB_MARK	> $FNDMARK
						;;
		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 lastrites_save {
		ACTWINID=$(xprop -root _NET_ACTIVE_WINDOW)
		ACTWINID=${ACTWINID##* }
		XWININFO=$(xwininfo -id $ACTWINID)
		local ARRAY=(${XWININFO#* X: })
		echo -n "${ARRAY[14]} ${ARRAY[16]}" > $LAST_WH
		dir_name "$vCHOOSER" > $LASTDIR
};export -f lastrites_save
function lastrites_cleanup {
	busybox pkill MMplayme
	lastrites_save
	[[ $(busybox pidof MMVprocess) =~ ^[0-9]+$ ]] || return	# stop here if another instance running
	[[ -d ${TEMPDIR} ]] && rm -rf ${TEMPDIR}*{.tmp,/} 
}; export -f lastrites_cleanup
{ #TOOLTIP_DIALOG
export TOOLTIP_DIALOG='
<window type-hint="6" skip_taskbar_hint="true">
<eventbox>
	<hbox spacing="9">
	<pixmap icon_size="3"><input file stock="gtk-info"></input></pixmap>
	<text use-markup="true"><input file>"'$TTPFILE'"</input></text>
	</hbox>
</eventbox>
<variable>TOOLTIP_DIALOG</variable>
<action signal="enter-notify-event">closewindow:TOOLTIP_DIALOG</action>
<action signal="leave-notify-event">closewindow:TOOLTIP_DIALOG</action>
<action signal="focus-out-event">   closewindow:TOOLTIP_DIALOG</action>
<action signal="key-press-event">   closewindow:TOOLTIP_DIALOG</action>
<action signal="button-press-event">closewindow:TOOLTIP_DIALOG</action> 
</window>
'
}
{ #FULLSCREEN_DIALOG_TXT
export FULLSCREEN_DIALOG_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:FULLSCREEN_DIALOG_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:FULLSCREEN_DIALOG_TXT</action> 
			</edit>
			<variable>vFDT_NOTE</variable>
			<input>echo $vNOTE</input>
		</notebook>
	</vbox>
	<variable>FULLSCREEN_DIALOG_TXT</variable>
	<action signal="key-press-event" condition="command_is_true([[ $KEY_SYM == Escape ]] && echo true )">closewindow:FULLSCREEN_DIALOG_TXT</action>
	<action signal="show">echo -n "$TT24" > $TTPFILE</action>
	<action signal="show">refresh:vFDT_NOTE</action>
	<action signal="map-event">launch:TOOLTIP_DIALOG</action>
</window>
'
}
{ #FULLSCREEN_DIALOG_PIX_NORMALSIZE
export FULLSCREEN_DIALOG_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>FULLSCREEN_DIALOG_PIX_NORMALSIZE</variable>
	<action signal="button-press-event" condition="command_is_true( [[ $PTR_BTN == [12] ]]  && echo true )">closewindow:FULLSCREEN_DIALOG_PIX_NORMALSIZE</action> 
	<action signal="button-press-event" condition="command_is_true( [[ $PTR_BTN == [12] ]]  && echo true )">closewindow:FULLSCREEN_DIALOG_PIX_FIT2SCREEN</action> 
	<action signal="button-press-event" condition="command_is_true( [[ $PTR_BTN == 3    ]]  && echo true )">launch:     FULLSCREEN_DIALOG_PIX_FIT2SCREEN</action> 
	<action signal="key-press-event"    condition="command_is_true( [[ $KEY_SYM == Escape ]] && echo true )">closewindow:FULLSCREEN_DIALOG_PIX_NORMALSIZE</action>
	<action signal="key-press-event"    condition="command_is_true( [[ $KEY_SYM == Escape ]] && echo true )">closewindow:FULLSCREEN_DIALOG_PIX_FIT2SCREEN</action> 
</window>
'
}
{ #FULLSCREEN_DIALOG_PIX_FIT2SCREEN
export FULLSCREEN_DIALOG_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>FULLSCREEN_DIALOG_PIX_FIT2SCREEN</variable>
	<action signal="button-press-event" condition="command_is_true( [[ $PTR_BTN == [23] ]] && echo true )">closewindow:FULLSCREEN_DIALOG_PIX_FIT2SCREEN</action> 
	<action signal="button-press-event" condition="command_is_true( [[ $PTR_BTN == [23] ]] && echo true )">closewindow:FULLSCREEN_DIALOG_PIX_NORMALSIZE</action> 
	<action signal="button-press-event" condition="command_is_true( [[ $PTR_BTN == 1    ]] && echo true )">launch:     FULLSCREEN_DIALOG_PIX_NORMALSIZE</action> 
	<action signal="key-press-event"    condition="command_is_true( [[ $KEY_SYM == Escape ]] && echo true )">closewindow:FULLSCREEN_DIALOG_PIX_FIT2SCREEN</action>
	<action signal="key-press-event"    condition="command_is_true( [[ $KEY_SYM == Escape ]] && echo true )">closewindow:FULLSCREEN_DIALOG_PIX_NORMALSIZE</action>
</window>
'
}
{ #MULTI_DIALOG
export MULTI_DIALOG='
<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>
		<checkbox label="Use regular expressions"><variable>vCHB_REGX</variable></checkbox>
		<checkbox label="Match case">             <variable>vCHB_CASE</variable></checkbox>
		<checkbox label="Match only whole word">  <variable>vCHB_WORD</variable></checkbox>
		<hseparator></hseparator>
		<checkbox label="Use inline markers (do not extract matching lines)"><variable>vCHB_MARK</variable></checkbox>
		<variable>vD_CHECKBOXES</variable>
	</vbox>
	<hbox>
		<button label="gtk-cancel" use-stock="true" width-request="180">
			<variable>vD_BTN_CANCEL</variable>
			<action>closewindow:MULTI_DIALOG</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:MULTI_DIALOG</action>
			<action>presentwindow:MAIN_DIALOG</action>
		</button>
	</hbox>
</vbox>
<variable>MULTI_DIALOG</variable>
<input file>'$D_TITLE'</input>
<action signal="map-event">$WMCTRL -r :ACTIVE: -b add,above &</action>
<action signal="show" condition="command_is_true([[ $(<$D_TITLE) != Find ]] && echo true )">hide:vD_CHECKBOXES</action>
<action signal="show" condition="command_is_true([[ $(<$D_TITLE) != Find ]] && echo true )">break:</action>
<action signal="show" condition="command_is_true( echo $(<$FNDREGX) )">activate:vCHB_REGX</action>
<action signal="show" condition="command_is_true( echo $(<$FNDCASE) )">activate:vCHB_CASE</action>
<action signal="show" condition="command_is_true( echo $(<$FNDWORD) )">activate:vCHB_WORD</action>
<action signal="show" condition="command_is_true( echo $(<$FNDMARK) )">activate:vCHB_MARK</action>
<action signal="key-press-event" condition="command_is_true([ $KEY_SYM = Escape ] && echo true )">closewindow:MULTI_DIALOG</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>refresh:vSTATUSBAR</action>
		<action condition="active_is_true(vMENU_DISABLEVIEW)">break:</action>
		<action>activate:vMACRO_REFRESH_SUBROUTINE</action>
	</menuitem>
	<menuitem>
		<variable>vMACRO_REFRESH_FORCE</variable>
		<action>refresh:vSTATUSBAR</action>
		<action>activate:vMACRO_REFRESH_SUBROUTINE</action>
	</menuitem>
	<menuitem>
		<variable export="false">vMACRO_REFRESH_SUBROUTINE</variable>
		<action>view_instantly</action>
		<action condition="command_is_true([[ $(<$NB_PAGE) != $vNOTE ]] && echo true )">refresh:vNOTE</action>
		<action condition="command_is_true([[ $vNOTE       == 0      ]] && echo true )">refresh:vEDI0</action>
		<action condition="command_is_true([[ $vNOTE       == 1      ]] && echo true )">refresh:vEDI1</action>
		<action condition="command_is_true([[ $vNOTE       == 2      ]] && echo true )">refresh:vPIX2</action>
		<action condition="command_is_true([[ $vNOTE       == 2      ]] && echo true )">refresh:vTXT2</action>
		<action condition="command_is_true([[ $vNOTE       == 3      ]] && echo true )">refresh:vPIX3</action>
		<action condition="command_is_true([[ $vNOTE       == 3      ]] && echo true )">refresh:vTXT3</action>
	</menuitem>
	<menuitem>
		<variable export="false">vMACRO_WRITECMD</variable>
		<action>grabfocus:vCMDLINE</action>
		<action>clear:vCMDLINE</action>
		<action>refresh:vCMDLINE</action>
	</menuitem>
	<menuitem>
		<variable export="false">vMACRO_OPEN_COMMANDBOX</variable>
		<action>disable:vMENU_CMDBOX_OPEN</action>
		<action>enable:vMENU_F4</action>
		<action>show:vCOMMANDBOX</action>
	</menuitem>
	<menuitem>
		<variable export="false">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 export="false">vMACRO_VIEWTEXT_WRAPPED</variable>
		<action>printf 1 > $NB_PAGE</action> 
		<action>refresh:vEDI1</action> 
		<action>refresh:vNOTE</action>
	</menuitem>
	<menuitem>
		<variable export="false">vMACRO_RESTART</variable>
		<action>lastrites_save;exec "$APP_PATH" &</action>
		<action>exit:</action>
	</menuitem>
</menu>
'
}
{ #MENU
MENU='
<menubar  height-request="'$MENUBAR_HIGHT'" space-fill="true" space-expand="true">
'$MACROS'
<menu label="File">
	<menuitem label="New" accel-key="0x6e" accel-mods="4" stock-id="gtk-file" tooltip-text="'$TT27'">
		<action>run_dialog Create</action>
		<action>launch:MULTI_DIALOG</action>
	</menuitem>
	<menuitemseparator></menuitemseparator>
	<menuitem label="Rename" accel-key="0x72" accel-mods="4"stock-id="gtk-strikethrough" tooltip-text="'$TT18'">
		<action>run_dialog Rename</action>
		<action>launch:MULTI_DIALOG</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:MULTI_DIALOG</action>
	</menuitem>
	<menuitem label="Compress/Decompress"  accel-key="0x47" accel-mods="4"  '$ICON_COMPRESS'  tooltip-text="'$TT34'">
		<variable export="false">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 export="false">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:MULTI_DIALOG</action>
	</menuitem>
	<menuitemseparator></menuitemseparator>
	<menuitem label="Run in console" accel-key="0xffc2" accel-mods="4" stock-id="gtk-execute" tooltip-text="'$TT14'">
		<variable export="false">vMENU_RUNCONSOLE</variable>
		<action>run_in_console</action>
	</menuitem>
	<menuitem label="Show in ROX" accel-key="0x72" accel-mods="5" stock-id="gtk-jump-to" tooltip-text="'$TT15'">
		<variable export="false">vMENU_SHOWINROX</variable>
		<action>rox -s "$vCHOOSER"</action>
	</menuitem>
	<menuitem label="Open With ...	(MiddleClick)" tooltip-text="'$TT42'">
		<variable export="false">vMENU_OPENWITH</variable>
		<action>file_openwith &</action>
	</menuitem>
	<menuitemseparator></menuitemseparator>
	<menuitem label="Properties"  accel-key="0x70" accel-mods="4" stock-id="gtk-properties" tooltip-text="'$TT16'">
		<variable export="false">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 export="false">vMENU_MD5</variable>
		<action>file_md5</action>
		<action>activate:vMACRO_VIEWTEXT</action>
	</menuitem>
	<menuitemseparator></menuitemseparator>
	<menuitem label="Quit" accel-key="0x071" accel-mods="4" stock-id="gtk-quit">
		<action>activate:vBTN_QUIT</action>
	</menuitem>
</menu>
<menu label="Search">
	<menuitem label="Find ..." accel-key="0x46" accel-mods="4"  stock-id="gtk-find">
		<action>run_dialog Find</action>
		<action>launch:MULTI_DIALOG</action>
	</menuitem>
	<menuitem label="Find again" accel-key="0xffc0" accel-mods="0">
		<variable export="false">vMENU_FINDAGAIN</variable>
		<action>find_again</action>
		<action>refresh:vSTATUSBAR</action>
		<action>activate:vMACRO_VIEWTEXT</action>
	</menuitem>
</menu>
<menu label="View">
	<menuitem label="Additional info (see tooltip)" tooltip-text="'$TT01'" accel-key="0xffbe" accel-mods="0"  stock-id="gtk-info">
		<variable export="false">vMENU_F1</variable>
		<action condition="command_is_true( [[ $vSTATUSBAR != *│* ]] && echo true )">refresh:vSTATUSBAR</action>
		<action condition="command_is_false(view_on_demand)">break:</action>
		<action condition="command_is_true([[ $(<$NB_PAGE) != $vNOTE ]] && echo true )">refresh:vNOTE</action>
		<action condition="command_is_true([[ $vNOTE       == 0      ]] && echo true )">refresh:vEDI0</action>
		<action condition="command_is_true([[ $vNOTE       == 1      ]] && echo true )">refresh:vEDI1</action>
		<action condition="command_is_true([[ $vNOTE       == 2      ]] && echo true )">refresh:vPIX2</action>
		<action condition="command_is_true([[ $vNOTE       == 2      ]] && echo true )">refresh:vTXT2</action>
		<action condition="command_is_true([[ $vNOTE       == 3      ]] && echo true )">refresh:vPIX3</action>
		<action condition="command_is_true([[ $vNOTE       == 3      ]] && echo true )">refresh:vTXT3</action>
	</menuitem>
	<menuitemseparator></menuitemseparator>
	<menuitem label="Hexdump (max '$((HEXDUMP_MAXBYTES/1000))'KB)"  image-name="'$ICONHEX'" accel-key="0x48" accel-mods="4" tooltip-text="'$TT46'">
		<variable>vMENU_HEXDUMP_HEAD</variable>
		<width>16</width>
		<action>view_hexdump dumphead</action>
		<action>activate:vMACRO_VIEWTEXT</action>
	</menuitem>
	<menuitem label="Convert text string ..."   image-name="'$ICONHEX'" accel-key="0x64" accel-mods="5"  tooltip-text="'$TT49'">
		<variable>vMENU_CHAR2HEX</variable>
		<width>16</width>
		<action>run_dialog Convert_Text</action>
		<action>launch:MULTI_DIALOG</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>
		<width>16</width>
		<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>
		<width>16</width>
		<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>
		<width>16</width>
		<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>
	</menu>
	<menuitemseparator></menuitemseparator>
	<menuitem label="Refresh" accel-key="0xffc2" accel-mods="0" stock-id="gtk-refresh"  tooltip-text="'$TT06'">
		<variable export="false">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 >   $BOXMODE</action>
		<action>if false rm $BOXMODE</action>
		<action>activate:vMACRO_RESTART</action>
	</menuitem>
</menu>
<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 label="Document">
	<menuitem label="Line Wrapping" checkbox="" 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="0xffbf" accel-mods="0"  tooltip-text="'$TT05'">
		<action>add_linenumbers</action>
		<action>activate:vMACRO_VIEWTEXT</action>
	</menuitem>
</menu><menu label="Commandbox">
	<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 export="false">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>
</menubar>
'
}
{ #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 signal="button-release-event" condition="command_is_true( (( vDURATION>100 )) && echo true )">activate:vMENU_HEXDUMP_HELP</action>
	<action signal="button-release-event" condition="command_is_true( (( vDURATION>100 )) && echo true )">break:</action>
	<action signal="button-release-event" condition="command_is_true( [[ $PTR_BTN == 1 ]] && ((vDURATION<=THRESHOLD)) && echo true )">activate:vMENU_HEXDUMP_HEAD</action>
	<action signal="button-release-event" condition="command_is_true( [[ $PTR_BTN == 1 ]] && ((vDURATION >THRESHOLD)) && echo true )">activate:vMENU_HEXDUMP_ALL</action>
	<action signal="button-release-event" condition="command_is_true( [[ $PTR_BTN == 2 ]] && ((vDURATION<=THRESHOLD)) && echo true )">activate:vMENU_HEXMARK_HEAD</action>
	<action signal="button-release-event" condition="command_is_true( [[ $PTR_BTN == 2 ]] && ((vDURATION >THRESHOLD)) && echo true )">activate:vMENU_HEXMARK_ALL</action>
	<action signal="button-release-event" condition="command_is_true( [[ $PTR_BTN == 3 ]] && echo true )">activate:vMENU_CHAR2HEX</action> 
</button>

<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>
<button can-focus="false" tooltip-text="'$TT16'"><action>activate:vMENU_PROPERTIES</action><input file stock="gtk-properties"></input></button>
<button can-focus="false" tooltip-text="'$TT13'"><action>activate:vMENU_OPENEDITOR</action><input file stock="gtk-edit"></input></button>
<button can-focus="false" tooltip-text="'$TT15'"><action>activate:vMENU_SHOWINROX</action><input file stock="gtk-jump-to"></input></button>
<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>
<button can-focus="false" tooltip-text="'$TT06'"><action>activate:vMENU_REFRESH</action><input file stock="gtk-refresh"></input></button>
<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="MMview" default-width="'$DEFAULT_WIDTH'"  default-height="'$DEFAULT_HIGHT'" allow-shrink="true" margin="'$WINDOW_MARGIN'" image-name="'$ICONMMV'">
<vbox space-expand="true" space-fill="true"  spacing="'$WIDGETSPACING'">
	<hbox space-expand="false" spacing="0">
		'"$MENU"'
		'"$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:FULLSCREEN_DIALOG_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:FULLSCREEN_DIALOG_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:FULLSCREEN_DIALOG_PIX_NORMALSIZE</action> 
				<action signal="button-press-event" condition="command_is_true( [[ $PTR_BTN == 3 ]] && echo true )">launch:FULLSCREEN_DIALOG_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:FULLSCREEN_DIALOG_PIX_NORMALSIZE</action> 
				<action signal="button-press-event" condition="command_is_true( [[ $PTR_BTN == 3 ]] && echo true )">launch:FULLSCREEN_DIALOG_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 "MMview" --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   ">
			<variable export="false">
"vBTN_QUIT"
			</variable>
			<action>lastrites_save</action>
			<action>lastrites_cleanup</action>
			<action>exit:OK</action>
		</button>
	</hbox>
</vbox>
<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>
</vbox>
<variable>MAIN_DIALOG</variable>
<action signal="show">disable:vMENU_F4</action>
<action signal="delete-event">lastrites_cleanup</action>
</window>
'
}
exec -a MMVprocess gtkdialog
