#!/bin/dash
# rox-functions library for Fatdog drive icons
# Copyright (C) James Budiono 2013, 2018, 2020
# License: GNU GPL Version 3 or later
#
# dependency: xml2, awk, sed, rox
#
# This file should be sourced, not executed.
#
# Except for rox_set_icon_image, the functions assumes they are executed in the context of current user
#

### configurations - default values
ICON_IMAGE_ROOT=/usr/share/pixmaps/midi-icons
ICON_IMAGE_ROOT2=/usr/share/pixmaps/mini-icons
ICON_ALIGNMENT=bottom SHOW_VOLUME_LABEL=yes	
MARGIN_TOP=32 MARGIN_BOTTOM=64 MARGIN_LEFT=32 MARGIN_RIGHT=64 	# margins in pixels
GRID_X=4	# check every $GRID pixels - old rox default is 64
GRID_Y=16	# check every $GRID pixels - old rox default is 64
ICON_DX=48	# assumed icon width in pixels - for old rox, should not be multiple of GRID_X
ICON_DY=52	# assumed icon height in pixels - for old rox, should not be multiple of GRID_Y
MAX_VOLABEL=6 # truncate volume labels to this length
EVENTMANAGER_CONFIG=/etc/eventmanager
. $EVENTMANAGER_CONFIG # UNPATCHED_ROX. HOTSPOT_xxx variables
DEFAULT_CLICK_ACTION=${DEFAULT_CLICK_ACTION:-devmount} # devmount, labelmount, uuidmount, etc

# prints out icon label based on $1 and $2
# $1-drivename $2-volume label
get_icon_label() {
	if [ -z $MAX_VOLABEL ] || [ $MAX_VOLABEL -eq 0 ]; then
		printf "%s" "$1"
	else
		printf "%s\r\n%.${MAX_VOLABEL}s" "$1" "$2"
	fi
}

### remove icon from pinboard
# $1-path of icon to remove
rox_remove_icon() {
		rox -R << EOF
<?xml version="1.0"?>
<env:Envelope xmlns:env="http://www.w3.org/2001/12/soap-envelope">
	<env:Body xmlns="http://rox.sourceforge.net/SOAP/ROX-Filer">
		<PinboardRemove>
			<Path>$1</Path>
		</PinboardRemove>
	</env:Body>
</env:Envelope>
EOF
}

### add icon from pinboard - for patched Rox
#$1-path $2-COORD_X*UNUSED* $3-COORD_Y*UNUSED* $4-label $5-args
#also settings parameters from $EVENTMANAGER_CONFIG
rox_add_icon() {
		rox -R << EOF
<?xml version="1.0"?>
<env:Envelope xmlns:env="http://www.w3.org/2001/12/soap-envelope">
	<env:Body xmlns="http://rox.sourceforge.net/SOAP/ROX-Filer">
		<PinboardAddDriveIcon>
			<Path>$1</Path>
			<Align>$ICON_ALIGNMENT</Align>			
			<Label>$4</Label>
			<Args>$5</Args>
			<Left>$MARGIN_LEFT</Left>
			<Top>$MARGIN_TOP</Top>
			<Right>$MARGIN_RIGHT</Right>
			<Bottom>$MARGIN_BOTTOM</Bottom>
			<GridX>$GRID_X</GridX>
			<GridY>$GRID_Y</GridY>
		</PinboardAddDriveIcon>
	</env:Body>
</env:Envelope>
EOF
}
# this function is no longer used now, it's done inside Rox itself
get_free_coord() {
	return 0
}

### override these functions with unpatched-ROX version when asked
if [ "$UNPATCHED_ROX" ]; then
### add icon from pinboard
#$1-path $2-COORD_X $3-COORD_Y $4-label $5-args
rox_add_icon() {
		rox -R << EOF
<?xml version="1.0"?>
<env:Envelope xmlns:env="http://www.w3.org/2001/12/soap-envelope">
	<env:Body xmlns="http://rox.sourceforge.net/SOAP/ROX-Filer">
		<PinboardAdd>
			<Path>$1</Path>
			<X>$2</X>
			<Y>$3</Y>
			<Label>$4</Label>
			<Args>$5</Args>
		</PinboardAdd>
	</env:Body>
</env:Envelope>
EOF
}
### get coordinates of a free location on pinboard, for adding icons
# $1-pinboard file
# $2-aligment = top, bottom, left, right (default is bottom)
# (top & bottom the same, only starting position is different)
# (left & right the same, only starting position is different)
# returns COORD_X and COORD_Y for historical reasons
GRID_X=64 GRID_Y=64 # old default
get_free_coord() {
	out=$(/usr/sbin/fatdog-drive-icon-get_free_coord.awk -v pinboard="$1" \
		-v xgrid=$GRID_X -v ygrid=$GRID_Y -v xicon=$ICON_DX -v yicon=$ICON_DY \
		-v top=$MARGIN_TOP -v bottom=$MARGIN_BOTTOM -v left=$MARGIN_LEFT -v right=$MARGIN_RIGHT \
		-v align="$2")
	COORD_X=${out% *}
	COORD_Y=${out#* }
}
fi


### create a rox icon file
# svg icon inspired by technosaurus (Brad Conroy), see http://www.murga-linux.com/puppy/viewtopic.php?t=76431
#$1-path $2-type $3-state (mounted/unmounted/system) $4-fstype 
create_rox_icon_file() {
	local DRVICON=drive48.png USBICON=usb48.png LOCKICON=mini-lock.xpm OVERLAY=""
	
	# primary image
	case $2 in
		card*) DRVICON=card48.png ;;
		optical*) DRVICON=optical48.png ;;		
		floppy*) DRVICON=floppy48.png ;;
	esac

	# secondary image - usb overlay
	case $2 in
		*usb*) OVERLAY='<image xlink:href="'$ICON_IMAGE_ROOT/$USBICON'" width="48" height="48"/>' ;;
	esac

	# third image - state overlay
	local xh yh wh hh ph xph xpwh yph yphh sx sy
	xh=${HOTSPOT_X:-0} yh=${HOTSPOT_Y:-0}
	wh=${HOTSPOT_W:-12} hh=${HOTSPOT_H:-12} ph=${HOTSPOT_P:-2}
	xph=$((xh + ph)) xpwh=$((xh + ph + wh)) yph=$((yh + ph)) yphh=$((yh + ph + hh))		
				
	# emblem originally designed for 96x96, we scale it for 12x12 hotspot
	# parameter: scaling 0.25, offset -3,-24, dimension is 24x24
	# with 0.25 scaling and 24x24 wxh (so wh & hh must be multiplied by 2)
	sx="$(awk "END{print $wh/(12*4),$hh/(12*4)}" /dev/null)"; sy=${sx#* }; sx=${sx% *}

	case $3 in
		unmounted) ;; # do nothing
		mounted) OVERLAY=$(cat << EOF
$OVERLAY
<rect x="$xph" y="$yph" width="$wh" height="$hh" fill="#00ff00" stroke="black" stroke-width="2"/>
<line x1="$xph" y1="$yph" x2="$xpwh" y2="$yphh" stroke="black"/>
<line x1="$xph" y1="$yphh" x2="$xpwh" y2="$yph" stroke="black"/>
EOF
)
;;
		system) OVERLAY=$(cat << EOF
$OVERLAY
<!-- <rect x="$xph" y="$yph" width="$wh" height="$hh" fill="#ffff00" stroke="black" stroke-width="2"/> -->
<svg x="$((xph-1))" y="$((yph-1))" width="$((wh*2))" height="$((hh*2))"><defs><linearGradient id="G"><stop offset="5%" stop-color="#CC8B35"/><stop offset="50%" stop-color="#E3AD2F"/><stop offset="95%" stop-color="#F0C727"/></linearGradient></defs><path transform="scale($sx,$sy) translate(-4,-24)" fill="url(#G)" stroke="black" stroke-width="2" d="M18 37l6 1-7 2zm-7-1c7-3 14-3 21 0m3-1l4 4-7-3zm7 11c-17 18-40 1-20-8m-8 8c0 4-5 6-8 2m42-22c17 1 25 3 36 14 3-6 0-10-8-10 9-10 20 6 12 16 2 4 3 7 3 11 0 8-5 33-8 36-3 2-12 2-12-1 2-3 3-6 3-10-5 3-8 4-14 5 0 2 0 3-2 4-3 1-12 2-12-1v-2h-3c-1 3-1 4-3 5-4 2-12 2-12-1 1-2 2-4 2-7-3-1-3.596-.626-6-2 1 2 1 4 0 6-2 2-13 4-13 1 2-3 4-7-2-20-2-3-4-8-4-13 0-2 0-5 1-9-1-2-1-3-1-5 0-3 3-5 6-7l1-1s-3-1-3-3c0-4 5-7 8-7s6 3 6 3c4-1 6-1 7-1h5c4-1 7-1 13-1zm-9 2c6-5 16 0 16 4 0 2-5 4-7 4s-1-5-6-5m9 11c0 9-10 16-21 16-6 0-9 0-13-2m7 27c-2-1-4-2-6-4m28 9c5 0 8 0 14-1m14-5c3-2 5-4 7-7m7-29c-2-3-3-5-4-6m-72-5c3-3 6-5 11-7m0 26c-3 1-8 4-11 1-2-3 0-4 4-5M6 48c1 2 3 4 5 5m-1-1l5-4m5 7c8 0 15 0 22-9m1 33c1 4 1 5 0 9M28 77c2 3 2 5 2 8"/></svg>
EOF
)		
;;
	esac

	# additional overlay (padlock) for LUKS encrypted paritions
	case $4 in
		crypto_LUKS) OVERLAY=$(cat << EOF
$OVERLAY
<image xlink:href="$ICON_IMAGE_ROOT2/$LOCKICON" x="0" y="32" width="16" height="16"/>
EOF
)
;;
	esac

cat > $1/.DirIcon << EOF
<svg width="48" height="48" id="svg1" xmlns:xlink="http://www.w3.org/1999/xlink">
<image xlink:href="$ICON_IMAGE_ROOT/$DRVICON" width="48" height="48"/>
$OVERLAY
</svg>
EOF
}


### create drive-icon rox application 
# $1-path, $2-type, $3-devname (with /dev) $4-summary $5-state (mounted/unmounted/system), $6-fstype
create_rox_app() {
	{
	# standard menus
	cat << EOF
<?xml version="1.0"?>
<AppInfo>
	<Summary>$4</Summary>
	<About>
		<Purpose>Fatdog desktop drive icons</Purpose>
		<Authors>Re-written for Fatdog64-600, James Budiono 2012</Authors>
		<License>GNU GPL Version 3 or later</License>
	</About>
	<AppMenu>
		<Item option="umount $3" icon="gtk-cancel"><Label>Un-mount ${3##*/}</Label></Item>
EOF
	if [ "$6" != 'crypto_LUKS' ]; then	# LUKS - only devmount
		[ $DEFAULT_CLICK_ACTION = devmount ] &&
		echo "<Item option=\"labelmount $3\" icon=\"gtk-jump-to\"><Label>Mount by label</Label></Item>" ||
		echo "<Item option=\"devmount $3\" icon=\"gtk-jump-to\"><Label>Mount by device</Label></Item>"
	fi

	cat << EOF
		<Item option="pmount" icon="gtk-execute"><Label>Drive Mounter</Label></Item>
		<Item option="usage" icon="gtk-execute"><Label>Disk Usage</Label></Item>
EOF
	
	# extra menus for optical drives & non-optical drives
	case $2 in
		optical*) cat << EOF
		<Item option="explore $3" icon="gtk-cdrom"><Label>Explore disc</Label></Item>
		<Item option="eject $3" icon="gtk-disconnect"><Label>Eject disc</Label></Item>
		<Item option="rip2iso $3" icon="gtk-save"><Label>Save as ISO</Label></Item>			
EOF
		;;
		
		*) cat << EOF
		<Item option="fsck $3" icon="gtk-execute"><Label>Check integrity</Label></Item>		
EOF
		;;
	esac
	
	# extra menus for usb/mmc drives
	case $2 in
		*usb*|*card*)
		if ([ "$6" = 'crypto_LUKS' ] && [ "$(find /sys/devices/virtual/block/dm-*/slaves -type l -name "${3##*/}" 2>/dev/null | grep -wo 'dm-[0-9]\+')" = "" ]) ||
		   ([ "$6" != 'crypto_LUKS' ] && ! grep -qE "^$3" /proc/mounts > /dev/null); then 
			cat << EOF
		<Item option="safe-remove $3" icon="gtk-disconnect"><Label>Safely remove ${3##*/}</Label></Item>
EOF
		fi
		;;
	esac
	
	# closing tags
cat << EOF
		<Item option="redraw" icon="gtk-refresh"><Label>Redraw all icons</Label></Item>
</AppMenu></AppInfo>
EOF
	} > $1/AppInfo.xml
	
	create_rox_icon_file $1 $2 $5 $6
	ln -s /usr/sbin/fatdog-drive-icon-action-handler.sh $1/AppRun
}


### set image for the icon 
#$1-path $2-icon $USER=user to use for contacting Rox, $DISPLAY=the correct display to connect to
rox_set_icon_image() {
	pidof ROX-Filer > /dev/null || return
	ROX='rox -R'
	[ $(id -u) -eq 0 ] && [ $USER != "root" ] && ROX="su $USER -c '$ROX'"
	eval $ROX << EOF
<?xml version="1.0"?>
<env:Envelope xmlns:env="http://www.w3.org/2001/12/soap-envelope">
	<env:Body xmlns="http://rox.sourceforge.net/SOAP/ROX-Filer">
		<SetIcon>
			<Path>$1</Path>
			<Icon>$2</Icon>
		</SetIcon>
	</env:Body>
</env:Envelope>
EOF
}
