#!/bin/sh
#
# ob-pipe-menu - Openbox pipe menus for the Openbox-only session.
#
# Usage: ob-pipe-menu apps|folders
#   apps     installed applications (.desktop) sorted by category
#   folders  home, desktop and GTK3 bookmarks, opened in file-manager
#
# Labels come from the .desktop files themselves (Name[lang]) and from
# the slitaz-menus or lxmenu-data category names: no .mo file needed.
#
# Copyright (C) 2026 SliTaz GNU/Linux - BSD License
#

apps_dir='/usr/share/applications'
dirs_dir='/usr/share/desktop-directories'

# fr_FR.UTF-8 -> fr_FR and fr, the two keys looked up for Name[]
lang=${LC_ALL:-${LC_MESSAGES:-$LANG}}
lang=${lang%%.*}; lang=${lang%%@*}
short=${lang%%_*}

xml() {
	sed 's|&|\&amp;|g; s|<|\&lt;|g; s|>|\&gt;|g; s|"|\&quot;|g'
}

# Category id, .directory names (slitaz-menus, lxmenu-data), English label
categories="\
utility:Utilities lxde-utility:Accessories
graphics:Graphics lxde-graphics:Graphics
network:Internet lxde-network:Internet
audiovideo:Multimedia lxde-audio-video:Multimedia
office:Office lxde-office:Office
development:Development lxde-development:Development
education:Education lxde-education:Education
game:Games lxde-game:Games
system:SystemTools lxde-system:System Tools
settings:Settings lxde-settings:Preferences
other:lxde-other:Other"

# Localized Name of a .directory file, empty if not translated
name_of() {
	awk -F= -v l="$lang" -v s="$short" '
		/^\[/ { grp = $0; next }
		grp != "[Desktop Entry]" { next }
		$1 == "Name[" l "]" { n1 = substr($0, length($1) + 2) }
		$1 == "Name[" s "]" { n2 = substr($0, length($1) + 2) }
		END { print (n1 ? n1 : n2) }' "$1" 2>/dev/null
}

# One line per application: category <tab> name <tab> command
list_apps() {
	awk -F= -v l="$lang" -v s="$short" '
		function flush() {
			if (file && type == "Application" && !hide && exec) {
				name = n1 ? n1 : n2 ? n2 : n3
				gsub(/ %[fFuUdDnNickvm]/, "", exec)
				gsub(/%[fFuUdDnNickvm]/, "", exec)
				gsub(/\\\\/, "\\", exec)	# Exec escaping: \\ is \
				if (term == "true") exec = "terminal -e " exec
				c = ";" cats ";"
				cat = c ~ /;(Settings|DesktopSettings);/ ? "settings" :
				      c ~ /;System;/ ? "system" :
				      c ~ /;Development;/ ? "development" :
				      c ~ /;Graphics;/ ? "graphics" :
				      c ~ /;Network;/ ? "network" :
				      c ~ /;(AudioVideo|Audio|Video);/ ? "audiovideo" :
				      c ~ /;Office;/ ? "office" :
				      c ~ /;Game;/ ? "game" :
				      c ~ /;(Education|Science);/ ? "education" :
				      c ~ /;Utility;/ ? "utility" : "other"
				printf "%s\t%s\t%s\n", cat, name, exec
			}
			type = cats = exec = term = n1 = n2 = n3 = ""; hide = 0
		}
		FNR == 1 { flush(); file = FILENAME; grp = "" }
		/^\[/ { grp = $0; next }
		grp != "[Desktop Entry]" { next }
		{ v = substr($0, length($1) + 2) }
		$1 == "Type" { type = v }
		$1 == "Exec" { exec = v }
		$1 == "Terminal" { term = v }
		$1 == "Categories" { cats = v }
		$1 == "NoDisplay" && v == "true" { hide = 1 }
		$1 == "Hidden" && v == "true" { hide = 1 }
		$1 == "OnlyShowIn" { hide = 1 }
		$1 == "Name[" l "]" { n1 = v }
		$1 == "Name[" s "]" { n2 = v }
		$1 == "Name" { n3 = v }
		END { flush() }' $apps_dir/*.desktop 2>/dev/null | sort -t '	' -k2,2f
}

# Category id <tab> localized label, in menu order
labels() {
	echo "$categories" | while IFS=: read id dirs label; do
		for d in $dirs; do
			name=$(name_of "$dirs_dir/$d.directory")
			[ -n "$name" ] && label=$(echo "$name" | xml) && break
		done
		printf '%s\t%s\n' "$id" "$label"
	done
}

# One awk pass: a fork per item made the menu open in a second
apps() {
	list_apps | xml | awk -F'\t' -v labels="$(labels)" '
		{ items[$1] = items[$1] "<item label=\"" $2 "\">\n" \
			"  <action name=\"Execute\"><command>" $3 \
			"</command></action>\n</item>\n" }
		END {
			print "<openbox_pipe_menu>"
			n = split(labels, line, "\n")
			for (i = 1; i <= n; i++) {
				split(line[i], f, "\t")
				if (!(f[1] in items)) continue
				print "<menu id=\"ob-apps-" f[1] "\" label=\"" f[2] "\">"
				printf "%s", items[f[1]]
				print "</menu>"
			}
			print "</openbox_pipe_menu>"
		}'
}

folder_item() {
	cat <<EOT
<item label="$(echo "$2" | xml)">
  <action name="Execute"><command>file-manager "$(echo "$1" | xml)"</command></action>
</item>
EOT
}

folders() {
	echo '<openbox_pipe_menu>'
	folder_item "$HOME" "$(whoami)"
	desk=$(xdg-user-dir DESKTOP 2>/dev/null)
	[ -d "${desk:=$HOME/Desktop}" ] && [ "$desk" != "$HOME" ] &&
		folder_item "$desk" "$(basename "$desk")"
	bookmarks="${XDG_CONFIG_HOME:-$HOME/.config}/gtk-3.0/bookmarks"
	if [ -s "$bookmarks" ]; then
		echo '<separator />'
		# Lines: file:///path/with%20escapes [label]
		grep '^file://' "$bookmarks" | while read uri label; do
			path=$(printf '%b' "$(echo "${uri#file://}" | sed 's|%|\\x|g')")
			folder_item "$path" "${label:-$(basename "$path")}"
		done
	fi
	echo '</openbox_pipe_menu>'
}

case "$1" in
	apps) apps ;;
	folders) folders ;;
	*) sed -n '5,7s|^# *||p' "$0" ;;
esac
