#!/bin/bash
### Universal file viewer
### MochiMoppel 2017-04-16

TEMPDIR=/tmp/mm_view					# For temp files. Will be cleaned upon mm_view exit
CNFGDIR=$HOME/tmp/mm_view				# For user settings. ($HOME/tmp not saved to savefile. Eventually should be $HOME/.config/<appname>
[[ -d $TEMPDIR ]] || mkdir -p $TEMPDIR
[[ -d $CNFGDIR ]] || mkdir -p $CNFGDIR
export APPPATH=$(realpath $0)

### Files for TEMPDIR
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 LASTCHO=$TEMPDIR/lastcho.tmp	# contains last selected item (=last vCHOOSER)
export PID_FFP=$TEMPDIR/pid_ffp.tmp	# contains PID of ffplay/avplay
export P2_TEXT=$TEMPDIR/p2_text.tmp	# contains text for page 2 (scale % of image)
export K_SHIFT=$TEMPDIR/k_shift.tmp	# shift key flag
export TMPFILE=$TEMPDIR/tmpfile.tmp	# contains e.g. content of processed MSGFILE (added line numbers etc.)
export STBFILE=$TEMPDIR/stbfile.tmp	# contains optional content for status bar
export FNDFILE=$TEMPDIR/fndfile.tmp	# contains search pattern for Find dialog

### Files for CNFGDIR
export LASTDIR=$CNFGDIR/lastdir		# contains last accessed directory
export LASTGEO=$CNFGDIR/lastgeo		# contains last geometry
export IMG_FIT=$CNFGDIR/img_fit		# image scale flag 
export AUTOAUD=$CNFGDIR/autoaud		# autoplay audio  flag
export AUTOVID=$CNFGDIR/autovid		# autoplay video  flag
export BOXMODE=$CNFGDIR/boxmode		# vertical layout flag
export FNDREGX=$CNFGDIR/fndregx		# regex checkbox  status in Find dialog
export FNDCASE=$CNFGDIR/fndcase		# case  checkbox  status in Find dialog
export FNDWORD=$CNFGDIR/fndword		# word  checkbox  status in Find dialog
export FNDMARK=$CNFGDIR/fndmark		# Do not extract  checkbox status in Find dialog

### Window settings
DEFAULT_WIDTH=1000	# Default window width
DEFAULT_HIGHT=500	# Default window height
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)  

### Determine utilities to be used
type -p ffprobe && PROBE=ffprobe || { type -p avprobe && PROBE=avprobe || PROBE=false ;} ; export PROBE
type -p ffplay  && PLAY=ffplay   || { type -p avplay  && PLAY=avplay   || PLAY=false  ;} ; export PLAY
type -p xclip   && CLIP=xclip    || { type -p xsel    && CLIP=xsel     || CLIP=false  ;} ; export CLIP

### Determine startup folder. Priorities: 1) Passed argument 2) Last used folder 3) Default '/'
if      [[ -e $1 ]];then
		[[ -d $1 ]]       && DEFAULT_DIRECTORY=$1            || DEFAULT_DIRECTORY=$(dirname "$1")
else    [[ -f $LASTDIR ]] && DEFAULT_DIRECTORY=$(< $LASTDIR) || DEFAULT_DIRECTORY=/ 
fi

### Determine startup modes
[[ -f $LASTGEO ]] && GEOMETRY=$(< $LASTGEO)    || GEOMETRY=${DEFAULT_WIDTH}x${DEFAULT_HIGHT}  # window size and position
[[ -f $BOXMODE ]] && LAYOUT_V=true BOX=v SEP=h || LAYOUT_V=false BOX=h SEP=v # orientation (horizontal or vertical)
[[ -f $IMG_FIT ]] && SCALE_IMAGE=true 		   || SCALE_IMAGE=false		     # image scaling
[[ -f $AUTOAUD ]] && AUTO_PLAY_A=true 		   || AUTO_PLAY_A=false		     # autoplay audio
[[ -f $AUTOVID ]] && AUTO_PLAY_V=true 		   || AUTO_PLAY_V=false		     # autoplay video

### Determine startup size of viewer pane (for image scaling) 
set -- ${GEOMETRY//[x+-]/ }													 # e.g. GEOMETRY=980x616+-232+592
	GEO_X=$1	
	GEO_Y=$2
set --
if [[ $LAYOUT_V == true ]] ;then
	VIEWER_X=$((GEO_X - WINDOW_MARGIN *2))
	VIEWER_Y=$((GEO_Y - Y_AXIS_ADJUST - MENUBAR_HIGHT - CHOOSER_HIGHT - WINDOW_MARGIN - ( CENTERSPACING + WIDGETSPACING + STATUS_MARGIN) * 2 ))
else
	VIEWER_X=$((GEO_X - X_AXIS_ADJUST - CHOOSER_WIDTH - (WINDOW_MARGIN + CENTERSPACING) * 2))
	VIEWER_Y=$((GEO_Y - Y_AXIS_ADJUST - MENUBAR_HIGHT - (WINDOW_MARGIN + WIDGETSPACING + STATUS_MARGIN) * 2))
fi
export VIEWER_X VIEWER_Y

### Initialize files and prepare exitus
ln -fsn  /dev/null  $SYMLINK
echo  0	> $NB_PAGE
echo -n	> $LASTCHO
echo -n	> $P2_TEXT
echo -n	> $STBFILE
trap "rm -r $TEMPDIR/*.tmp;busybox pkill -f \"$PLAY -nodisp\"" EXIT # pkill does not depend on PID. More reliable here

function fill_statusbar {
	[[ -s $STBFILE ]] && { echo $(< $STBFILE) ; return ;}
	MIME=$(file --separator "   │ " -i "$vCHOOSER" 2>&1)
	if [[ "$MIME" = *│*symlink* ]];then
		 echo -n "$vCHOOSER"  " ➡"  $(file --separator "  │ " -i "$(realpath "$vCHOOSER")"  2>&1)
	else echo -n $MIME
	fi
};export -f fill_statusbar

function fill_viewer {
	if [[ -s $PID_FFP ]];then					# kill any ffplay/avplay that might still be running
		kill $(<$PID_FFP)
		echo -n > $PID_FFP
	fi
	echo -n "$vCHOOSER" > $LASTCHO				# write path of currently selected item to $LASTCHO 
	echo -n "$vCHOOSER" | $CLIP -i              # mimic ROX-Filer and send selected item to PRIMARY buffer
	((    vNOTE    )) && echo  0 > $NB_PAGE     # if notebook page != 0 reset it to 0
	[[ -s $K_SHIFT ]] && echo -n > $K_SHIFT     # reset Shift key flag (mainly to recover from envoking search box with shift key and then using arrow keys to select next item...far fetched scenario?)
	[[ -s $MSGFILE ]] && echo -n > $MSGFILE   	# reset MSGFILE

	case $vSTATUSBAR in
	### DIRECTORIES AND EMPTY FILES ###
	*│*directory*)
		if  [[ $(echo "$vCHOOSER"/*) == "$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    vCHOOSER=/dev/null
		fi
		;;

	### IMAGES ###
	*'.xpm '*)              							# xpm=us-ascii, must precede 'ascii' case; not scalable
		echo 1 > $NB_PAGE
		;;
	*│*image/svg*|*'.svg '*)
		if [[ $vMENU_SCALE == true ]];then
			 echo -n "SVG image, scaled to fit viewer" > $P2_TEXT
			 echo  2 > $NB_PAGE
		else echo  1 > $NB_PAGE
		fi
		;;
	*│*image*)
		if [[ $vMENU_SCALE == true ]] ;then
			EXIV=$(exiv2 "$vCHOOSER" 2>/dev/null)
			set -- ${EXIV#*Image size}					# '      : 1600 x 1200 ...'
			IMAGE_X=$2									# '1600'
			IMAGE_Y=$4									# '1200'
			set --
			if (( IMAGE_X > VIEWER_X || IMAGE_Y > VIEWER_Y ));then
				 SX=$(( 100 * VIEWER_X / IMAGE_X))		# scale in % ;Unrounded integer only, but good enough
				 SY=$(( 100 * VIEWER_Y / IMAGE_Y))
				 SCALE=$((SY < SX ? SY : SX))			# SCALE = SX or SY, whichever is smaller
				 echo -n "Scaled to ${SCALE}% of ${IMAGE_X}x${IMAGE_Y}" > $P2_TEXT
				 echo 2 > $NB_PAGE
			else echo 1 > $NB_PAGE
			fi
		else echo 1 > $NB_PAGE
		fi
		;;

	### TEXT ###
	 *charset=utf-8)
		;;
	 *charset=*ascii)
		[[ "$vCHOOSER" =~ (^/sys/) ]] && MESSAGE=$(< "$vCHOOSER" )
		;;
	*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
		;;

	### AUDIO/VIDEO ###
	*│*video*|*'.mkv '*)
		if [[ $vMENU_VIDEOPLAY == true && $PLAY != false ]] ;then
			$PLAY -x 320 -y 180 -i "$vCHOOSER"  &
			echo -n $! > $PID_FFP
		fi
		MESSAGE=$($PROBE "$vCHOOSER" 2>&1)
		[[ $MESSAGE ]] || MESSAGE='Display of video specs requires "ffprobe" or "avprobe"'
		;; 
	*│*audio*|*'.mp3 '*|*'.ogg '*|*'.wma '*)
		if [[ $vMENU_AUDIOPLAY == true && $PLAY != false ]] ;then
			$PLAY -nodisp -i "$vCHOOSER"  &
			echo -n $! > $PID_FFP
		fi
		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
		;;    

	### EXECUTABLES ###
	*│*executable*)
		if [[ $(grep -i "usage:" "$vCHOOSER") ]] ;then
				MESSAGE=$'\n\tUsage info may exist. Try F1'
		else    vCHOOSER=/dev/null
		fi
		;;

	### ARCHIVES ###
	*│*zip*|*│*xz*|*'.7z '*|*'.deb '*|*'.iso '*)      # .tar, .pet , .txz, .gz , .gzip, .bzip2, .zip, .7z, .deb, .iso, initrd* 
		MESSAGE=$'\n\tTry F1 to view archive contents'
		;;

	### EVERYTHING ELSE ###
	*)	vCHOOSER=/dev/null ;;
	esac

	if [[ "$MESSAGE" ]];then
		 echo "$MESSAGE"    > $MSGFILE
		 ln -fsn  $MSGFILE    $SYMLINK
	else ln -fsn "$vCHOOSER"  $SYMLINK
	fi
};export -f fill_viewer

function on_demand_info {
   (( vNOTE )) && echo  0 > $NB_PAGE 					    # set to notebook page 0
	FIGURESPACE=$'\xe2\x80\x87'								# Unicode U+2007
   case $vSTATUSBAR in 

#------------ DISPLAY OUTPUT OF <FILENAME> --help COMMAND
	*│*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
		;;
#------------ LIST DIRECTORY SUBFOLDERS
	*│*directory*) 	
		[[ -L $vCHOOSER || $vCHOOSER == /proc || $(< $MSGFILE) == EMPTY ]] && return	# get out of here if SYMLINK, VIRTUAL FILE SYSTEM or EMPTY
		DU_ALL=$(du -hd1 "$vCHOOSER"|sort -k2)				# vCHOOSER on top, followed by subs; not yet sorted by size
		DU_TOP="${DU_ALL%%[[:blank:]]*}		(disk usage)"	# first line (=vCHOOSER)
		CNTSUB=${DU_ALL//[^$'\n']}							# strip everything but newlines
		CNTSUB=${#CNTSUB}									# No. of newlines; zero in case of no subdirectories
		if (( CNTSUB == 0 )) ;then
			echo "$DU_TOP" $'\n   └ (no subdirectories)' > $MSGFILE
		else
			echo "$DU_TOP" > $MSGFILE
			DU_SUB=${DU_ALL#*$'\n'}
			echo -n "$DU_SUB" | sort -hr |awk '
			{
				$1=substr("───── "$1,length($1))
				gsub(/\/.*\//,"")
				print " └"$1" "$2"  "substr($0,index($0,$3))
			}' >> $MSGFILE
		fi
		;;
#------------ LIST ARCHIVE CONTENT
	*'/initrd'*)											# contributed by SFR (http://www.murga-linux.com/puppy/viewtopic.php?p=950405#950405)
		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")
		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 on a gzip file. No solution for failed xz or bzip
			case $vSTATUSBAR in
			*│*gzip*)	list_archive 'gzip  -cd' ;;			# display content of gzip compressed text files (e.g. .gnumeric)
			*│*xz*)		list_archive 'xz    -cd' ;;			# display content of xz compressed text files
			*│*bzip2*)	list_archive 'bzip2 -cd' ;;			# display content of bzip2 compressed text files
			esac
		fi
		;;
#------------
	*'.deb '*)												# extension .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 '*)	list_archive 'iso-info --no-header -l' 	;;	# extension .iso
#------------
	*│*/zip*)	list_archive 'unzip -l' 				;;	# extensions .zip, .xlsx (MS Excel) etc.
#------------
	*'.7z '*)	list_archive '7z l'						;;	# extension .7z
#------------ EVERYTHING ELSE
	*)	NOMATCH=1 ;;
	esac
	((NOMATCH)) && echo false || ln -fsn $MSGFILE $SYMLINK	# 'false' will prevent refresh
};export -f on_demand_info

function save_settings {
		ACTWINID=$(xprop -root _NET_ACTIVE_WINDOW)
		ACTWINID=${ACTWINID##* }
		XWININFO=$(xwininfo -id $ACTWINID)
		XWIN_ARR=($(awk '/^ *Abs|^ *Rel|^ *Width|^ *Height/ { print $NF }' <<< "$XWININFO"))
		WINDOW_W=${XWIN_ARR[4]}
		WINDOW_H=${XWIN_ARR[5]}
		WINDOW_X=$(( ${XWIN_ARR[0]} - ${XWIN_ARR[2]} ))
		WINDOW_Y=$(( ${XWIN_ARR[1]} - ${XWIN_ARR[3]} ))
		GEOMETRY=${WINDOW_W}x${WINDOW_H}+${WINDOW_X}+${WINDOW_Y}
		echo -n $GEOMETRY              > $LASTGEO
		echo -n $(dirname "$vCHOOSER") > $LASTDIR
};export -f save_settings

function open_editor   {
	echo -n > $K_SHIFT					# reset shiftkey flag
	[[ -f "$vCHOOSER" ]] || return		# editor should open only regular files ...
	[[ $vSTATUSBAR =~ (x-empty|charset=[^b][^i][^n]) ]] && defaulttexteditor "$vCHOOSER" # ...and only non-binaries or empty files
};export -f open_editor

function execute_in_console {
		[[ $vSTATUSBAR =~  (x-executable|x-shellscript) ]] &&
		urxvt -title "$vCHOOSER" -e bash -c "date +\"Start at %R:%S%n----------------\";\"$vCHOOSER\";date +\"%n----------------%nExit  at %R:%S%n\";read -n1 -p \"Press any key to close window\""&
};export -f execute_in_console

function list_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
		ln -fsn $MSGFILE $SYMLINK
};export -f list_archive

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
	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

export FIND_DIALOG='
<window title="Find" modal="false" width-request="400" height-request="200" window-position="3">
<vbox>
	<text xalign="0" label="Search for:"></text>
	<entry activates_default="true">
		<input file>"'$FNDFILE'"</input>
		<variable>vFIND</variable>
	</entry>
	<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>
	<hbox>
		<button label="gtk-ok" use-stock="true" width-request="90" can-default="true" has-default="true">
			<action>echo -n "$vFIND"   > $FNDFILE</action>
			<action>echo -n $vCHB_REGX > $FNDREGX</action>
			<action>echo -n $vCHB_CASE > $FNDCASE</action>
			<action>echo -n $vCHB_WORD > $FNDWORD</action>
			<action>echo -n $vCHB_MARK > $FNDMARK</action>
			<action>find_again</action>
			<action>closewindow:FIND_DIALOG</action>
			<action>activate:vMENU_FINDAGAIN</action>
		</button>
		<button label="gtk-cancel" use-stock="true" width-request="90">
			<action>closewindow:FIND_DIALOG</action>
		</button>
	</hbox>
</vbox>
<variable>FIND_DIALOG</variable>
<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:FIND_DIALOG</action>
</window>'

MACROS='
<menu visible="false">
	<menuitem>
		<variable>vMACRO_REFRESH</variable>
		<action condition="command_is_true([[ \"$(<$LASTCHO)\" == \"$vCHOOSER\" ]] && echo true )">break:</action>
		<action>echo -n > $STBFILE</action>
		<action>refresh:vSTATUSBAR</action>
		<action>fill_viewer</action>
		<action condition="command_is_true([[ $(<$NB_PAGE) != $vNOTE ]] && echo true )">refresh:vNOTE</action>
		<action condition="command_is_true([[ $vNOTE       == 0      ]] && echo true )">refresh:vEDIT</action>
		<action condition="command_is_true([[ $vNOTE       == 1      ]] && echo true )">refresh:vPM01</action>
		<action condition="command_is_true([[ $vNOTE       == 2      ]] && echo true )">refresh:vPM02</action>
		<action condition="command_is_true([[ $vNOTE       == 2      ]] && echo true )">refresh:vTXT2</action>
	</menuitem>
	<menuitem>
		<variable>vMACRO_VIEWTEXT</variable>
		<action>echo -n 0 > $NB_PAGE</action>
		<action>refresh:vEDIT</action>
		<action>refresh:vNOTE</action>
	</menuitem>
</menu>
'

MENU='
<vbox space-expand="false">
	<menubar  height-request="'$MENUBAR_HIGHT'">
		'$MACROS'
		<menu label="File">
			<menuitem label="Open in default editor Shift+click" accel-key="0x45" accel-mods="4"  icon-name="geany">
				<action>open_editor defaulttexteditor</action>
			</menuitem>
			<menuitem label="Show in ROX            MiddleClick" accel-key="0x72" accel-mods="4"  stock-id="gtk-jump-to">
				<action>rox -s "$vCHOOSER"</action>
			</menuitem>
			<menuitemseparator></menuitemseparator>
			<menuitem label="Exit" accel-key="0x71" accel-mods="4" stock-id="gtk-quit">
				<action>activate:vBTN_CLOSE</action>
			</menuitem>
		</menu>
		<menu label="Search">
			<menuitem label="Find ..." accel-key="0x46" accel-mods="4"  stock-id="gtk-find">
				<action>launch:FIND_DIALOG</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 label="View">
			<menuitem label="Additional info (see tooltip)" tooltip-text="'$'Executables:	Usage message (if available)\nDirectories:	Total size, incl. subdirectories\nArchives:		List of archive contents''"stock-id="gtk-info" accel-key="0xffbe" accel-mods="0">
				<action condition="command_is_false(on_demand_info)">break:</action>
				<action>refresh:vEDIT</action> 
				<action>refresh:vNOTE</action> 
			</menuitem>
			<menuitem label="Refresh" accel-key="0xffc2" accel-mods="0" stock-id="gtk-refresh">
				<action>echo > $LASTCHO</action>
				<action>activate:vMACRO_REFRESH</action>
			</menuitem>
			<menuitem label="Show line numbers" accel-key="0xffbf" accel-mods="0">
				<action>add_linenumbers</action>
				<action>activate:vMACRO_VIEWTEXT</action>
			</menuitem>
		</menu>
		<menu label="Run">
			<menuitem label="Execute selected file in console"        accel-key="0xffc2" accel-mods="4" stock-id="gtk-execute">
				<action>execute_in_console</action>
			</menuitem>
		</menu>
		<menu label="Preferences">
			<menuitem label="Fit images to viewer size" checkbox="'$SCALE_IMAGE'">
				<variable>vMENU_SCALE</variable>
				<action>if true >   $IMG_FIT</action>
				<action>if false rm $IMG_FIT</action>
				<action condition="command_is_true( ((vNOTE)) &&  > $LASTCHO || echo true)">break:</action>
				<action>activate:vMACRO_REFRESH</action>
			</menuitem>
			<menuitem label="Autoplay audio files" checkbox="'$AUTO_PLAY_A'">
				<variable>vMENU_AUDIOPLAY</variable>
 				<action>if true >   $AUTOAUD</action>
				<action>if false rm $AUTOAUD</action>
			   <action>fill_viewer</action> 
			</menuitem>
			<menuitem label="Autoplay video files" checkbox="'$AUTO_PLAY_V'">
				<variable>vMENU_VIDEOPLAY</variable>
 				<action>if true >   $AUTOVID</action>
				<action>if false rm $AUTOVID</action>
				<action>fill_viewer</action> 
			</menuitem>
			<menuitem label="Vertical layout (viewer below chooser)" checkbox="'$LAYOUT_V'" >
 				<action>if true >   $BOXMODE</action>
				<action>if false rm $BOXMODE</action>
				<action>save_settings; $APPPATH &</action>
				<action>exit:</action>
			</menuitem>
		</menu>
	</menubar>
</vbox>
'

export MAIN_DIALOG='
<window title="'${0##*/}'"allow-shrink="true" margin="'$WINDOW_MARGIN'">
<vbox space-expand="true" space-fill="true"  spacing="'$WIDGETSPACING'">
'$MENU' 
	<'$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>"[[ -s $PID_FFP ]] && { kill $(<$PID_FFP); echo -n > $PID_FFP ;} "</action> 
			<action>rox "$vCHOOSER"</action> 
			<action when="update-preview">activate:vMACRO_REFRESH</action>
			<action signal="button-release-event">[[ $PTR_BTN == 1 && -s $K_SHIFT ]] && open_editor &</action> 
			<action signal="button-release-event">[[ $PTR_BTN == 2                ]] && rox -s  "$vCHOOSER" &</action> 
			<action signal="key-press-event">     [[ $KEY_SYM == Shift_[LR]       ]] && echo    > $K_SHIFT</action>
			<action signal="key-release-event">   [[ $KEY_SYM == Shift_[LR]       ]] && echo -n > $K_SHIFT</action>
		</chooser>
		<'$SEP'separator space-expand="false"></'$SEP'separator>
		<notebook space-fill="true" space-expand="true" show-tabs="false" show-border="false">
			<vbox>
				<edit editable="true" left-margin="'$L_EDIT_MARGIN'">
					<variable export="false">
"vEDIT"
					</variable>
					<input file>'$SYMLINK'</input>
				</edit>
			</vbox>
			<vbox>
				<text label="Original size" xalign="2"></text>
				<vbox scrollable="true">
					<pixmap space-expand="true">
						<variable>
"vPM01"
						</variable>
						<input file>'$SYMLINK'</input>
					</pixmap>
				</vbox>
			</vbox>
			<vbox>
				<text xalign="2">
					<variable>
"vTXT2"
					</variable>
					<input file>"'$P2_TEXT'"</input>
				</text>
				<pixmap space-expand="true" space-fill="true">
					<variable>
"vPM02"
					</variable>
					<width>'$VIEWER_X'</width>
					<height>'$VIEWER_Y'</height>
					<input file>'$SYMLINK'</input>
				</pixmap>
			</vbox>
			<variable>
"vNOTE"
			</variable>
			<input file>'$NB_PAGE'</input>
		</notebook>
	</'$BOX'box>
	<hbox space-expand="false" margin="'$STATUS_MARGIN'" visible="true"> 
		<entry  space-expand="true">
			<variable>
"vSTATUSBAR"
			</variable>
			<input>fill_statusbar</input>
		</entry>
		<button label="   Close   ">
			<variable>
"vBTN_CLOSE"
			</variable>
			<action>save_settings</action>
			<action>exit:OK</action>
		</button>
	</hbox>
</vbox>
<action signal="key-press-event" condition="command_is_true([[ $KEY_SYM == Escape ]] && echo true )">busybox pkill -f "$PLAY -nodisp" && > $PID_FFP</action>
</window>
'
gtkdialog -G $GEOMETRY