Home | History | Annotate | Line # | Download | only in libexec
      1 #!/bin/sh
      2 #	$NetBSD: ctwm_app_menu,v 1.8 2026/04/17 11:07:12 nia Exp $
      3 #
      4 # Copyright (c) 2020-2026 The NetBSD Foundation, Inc.
      5 # All rights reserved.
      6 #
      7 # This code is derived from software contributed to The NetBSD Foundation
      8 # by Nia Alarie.
      9 #
     10 # Redistribution and use in source and binary forms, with or without
     11 # modification, are permitted provided that the following conditions
     12 # are met:
     13 # 1. Redistributions of source code must retain the above copyright
     14 #    notice, this list of conditions and the following disclaimer.
     15 # 2. Redistributions in binary form must reproduce the above copyright
     16 #    notice, this list of conditions and the following disclaimer in the
     17 #    documentation and/or other materials provided with the distribution.
     18 #
     19 # THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20 # ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21 # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22 # PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23 # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29 # POSSIBILITY OF SUCH DAMAGE.
     30 #
     31 set -eu -o pipefail
     32 
     33 LOCALBASE=$(pkg_info -Q LOCALBASE pkg_install 2>/dev/null) ||
     34     LOCALBASE=/usr/pkg
     35 
     36 find "$LOCALBASE"/share/applications -name '*.desktop' -exec awk '
     37 	function resetentry() {
     38 		name = menu = exec = ""
     39 		terminal = nodisplay = 0
     40 	}
     41 	function printentry() {
     42 		if (nodisplay)
     43 			return
     44 		if (terminal)
     45 			exec = "xterm -class UXTerm -e " exec
     46 		if (!menu)
     47 			menu = "Misc"
     48 		printf "%02d\t%s\t%s\t%s\n", menuorder[menu], quote(menu),
     49 		    quote(" " name), "!" quote(exec " &")
     50 	}
     51 
     52 	function quote(s) {
     53 		gsub(/\\/, "\\\\", s)
     54 		gsub(/\"/, "\\\"", s)
     55 		gsub(/\t/, "\\t", s)
     56 		return "\"" s "\""
     57 	}
     58 
     59 	function iskey(k, loc1) {
     60 		loc1 = $0;
     61 		sub(/ *=.*$/, "", loc1);
     62 		return loc1 == k;
     63 	}
     64 
     65 	function value(v) {
     66 		v = $0;
     67 		sub(/^[^=]*= */, "", v);
     68 		return v;
     69 	}
     70 
     71 	BEGIN {
     72 		menuno = 0
     73 		menuorder["Accessories"] = menuno++
     74 		menuorder["Games"] = menuno++
     75 		menuorder["Graphics"] = menuno++
     76 		menuorder["Internet"] = menuno++
     77 		menuorder["Multimedia"] = menuno++
     78 		menuorder["Office"] = menuno++
     79 		menuorder["Programming"] = menuno++
     80 		menuorder["System"] = menuno++
     81 		menuorder["Misc"] = menuno++
     82 		for (menu in menuorder)
     83 			printf "%02d\t%s\n", menuorder[menu], quote(menu)
     84 
     85 		# Map from matching category to menu.  This is a
     86 		# partial substring match: if the right-hand side of
     87 		# a Categories= line matches a key here, we take the
     88 		# corresponding menu.  So, e.g., any desktop file with
     89 		# a "X-GNOME-SystemSettings" category matches "System".
     90 		catmenu["Audio"] = "Multimedia"
     91 		catmenu["Development"] = "Programming"
     92 		catmenu["Game"] = "Games"
     93 		catmenu["Graphics"] = "Graphics"
     94 		catmenu["Network"] = "Internet"
     95 		catmenu["Office"] = "Office"
     96 		catmenu["System"] = "System"
     97 		catmenu["Utility"] = "Accessories"
     98 
     99 		# Categories to match, in precedence order: the first
    100 		# matching category in this list is the one which we
    101 		# use to decide the menu.
    102 		catno = 0
    103 		catorder[catno++] = "Audio"
    104 		catorder[catno++] = "Development"
    105 		catorder[catno++] = "Graphics"
    106 		catorder[catno++] = "Game"
    107 		catorder[catno++] = "Office"
    108 		catorder[catno++] = "Network"
    109 		catorder[catno++] = "System"
    110 		catorder[catno++] = "Utility"
    111 
    112 		resetentry()
    113 	}
    114 
    115 				{ gsub(/\r/, "") }
    116 	FNR == 1 && NR > 1	{ printentry() }
    117 	END			{ printentry() }
    118 	FNR == 1		{ resetentry() }
    119 
    120 	iskey("Name") && !name	{ name = value() }
    121 	/^Terminal *= *true$/	{ terminal = 1 }
    122 	iskey("OnlyShowIn")	{ nodisplay = 1 }
    123 	/^NoDisplay *= *true$/	{ nodisplay = 1 }
    124 	iskey("Exec") && !exec	{ exec = value()
    125 				  gsub(/ %.*/, "", exec)
    126 				  if (exec ~ /\"/)	# XXX
    127 					nodisplay = 1 }
    128 	iskey("Categories") && !menu {
    129 		categories = value()
    130 		for (i = 0; i < catno; i++) {
    131 			if (categories ~ catorder[i]) {
    132 				menu = catmenu[catorder[i]]
    133 				break
    134 			}
    135 		}
    136 	}
    137 ' '{}' + \
    138 | sort -u \
    139 | awk -F '\t' '
    140 	function startmenu(menu) {
    141 		printf "menu %s\n", menu
    142 		printf "{\n"
    143 		printf "\t%s\tf.title\n", menu
    144 		curmenu = menu
    145 	}
    146 	function endmenu() {
    147 		if (!curmenu)
    148 			return
    149 		printf "}\n"
    150 	}
    151 
    152 	# Inputs: 1=order 2=menu [3=name 4=exec], strings pre-quoted.
    153 	$2 != curmenu			{ endmenu(); startmenu($2) }
    154 	NF == 4				{ printf "\t%s %s \n", $3, $4 }
    155 	END				{ endmenu(); }
    156 '
    157