7 # This script, made for users of Window Maker (http://windowmaker.org) is to
8 # be used along with KDE (http://www.kde.org).
11 # The default directory, /usr/share/applnk, will contain various
12 # sub-directories such as Development, Editors, Internet, etc. If for some
13 # reason, you wish to use an alternate (parent) directory that contains the
14 # various applnk files, it can be specified on the command line.
16 # The directory, if an alternate is specified, MUST be a parent directory to
17 # any/all sub-directories.
19 # Usage: kde2wmaker.pl [ Options... ]
23 # -d <KDE App.kdelnk dir>
24 # -f <output menufile>
25 # -t <X terminal application>
27 # When the script is run, it will write out a proper Window Maker "External
28 # Menu" entry, that can be included in the menu. When the External Menu has
29 # been correctly configured, the root menu will display a sub-menu containing
30 # all of the KDE related items found. The script only needs to be run when/if
34 # Installation and Configuration:
36 # 1) If /usr/bin/perl is not the location of the perl binary on your system,
37 # the first line should be changed to reflect upon it's location.
39 # 3) Configure Window Maker's menu by editing ~/GNUstep/Defaults/WMRootMenu
40 # This could be done with any text editor, or by using WPrefs. Insert
41 # the following line (if done with a text editor) into the WMRootMenu file.
42 # ("External Menu", OPEN_MENU, "$HOME/.kde2wmaker.menu"),
43 # If done using WPrefs, simply "Add External Menu" from the drop down menu,
44 # then type: $HOME/.kde2wmaker.menu into the "Menu Path/Directory List"
46 # 4) Some KDE entries, such as "Pine" will require a terminal to
47 # execute it. There is a terminal variable below. You may use any
48 # terminal, XTerm is the default. Any command line options such as:
49 # -fg -bg, etc. can be specified in this variable as well.
52 # Michael Hokenson - logan@dct.com
55 #---------------------------------------------------------------------
57 # v1.2.0 -- 14th February 2001.
59 # Added alphabetic sorting of the menus.
61 # Directories are now displayed before files in the menu.
63 #---------------------------------------------------------------------
65 # v1.1.5 -- 3rd February 2001. (No public release)
67 # Unsupported applnk files have a fallback entry in the menu tree so
68 # that users can report menu entries that do not work. So far,
69 # wkdemenu.pl assumes that there is an Exec= line in the application
70 # definition, which is not always the case.
72 # --------------------------------------------------------------------
74 # v1.1.0 -- 29th January 2001.
76 # Code cleanup and bug fixes.
78 # --------------------------------------------------------------------
80 # v1.0.0 -- 21st January 2001.
82 # This script has been completely re-written to allow recursion of the
83 # KDE menu directories to an arbitrary depth, fixing a major
84 # functional limitation in the original script. To do this, I have
85 # rewritten the code to traverse directories recursively, introducing
86 # a subroutine, process_dir() to carry out the task.
88 # wkdemenu.pl provides an excellent extension to the user interface in
89 # Window Maker, working well with the "Generated Submenu" feature.
92 # Summary of New Features
93 # -----------------------
95 # Added support for menus of arbitrary depth.
97 # Added basic internationalisation based on KDE's language
98 # setting. The language is taken from "~/.kde/share/config/kdeglobals"
101 # Corrected the generation of menu names, incorporating
102 # internationalisation, where appropriate.
104 # Changed the double quotes to two single quotes in application names
105 # so that they do not break the Menu parser in Window Maker.
107 # Stripped off the arguments to commands on the Exec= line, except in
108 # a few KDE specific cases (e.g. kfmclient). The extra options are
109 # only usable by KDE and were preventing many applications from
110 # launching, since they could parse the option %c or %s, for example.
111 # This "feature" will probably need a more formal or interactive way
112 # of specifying exceptions in the future.
114 # Added a command line option for specifying the X terminal to
115 # use. This still defaults to xterm, but could be used to specify
118 # Malcolm Cowe, malk@271m.net.
120 # --------------------------------------------------------------------
125 # Programmatically determine the system location for the KDE menu
128 # Find a better way to parse the Exec= lines. In the short term,
129 # provide a user mechanism for generating exceptions to the curtailing
130 # of command line options. In the longer term, emulate what KDE does
131 # with these command line features.
133 # Optimise the code. This is my first proper PERL script, and I'm sure
134 # there's a better way. =)
141 # The External Menu file, this should NEVER point to the root menu file
142 $menufile = "$ENV{'HOME'}/.kde2wmaker.menu";
144 # Base directory, location of all the KDE AppName.kdelnk files.
146 # Change the base directory default to point at the system files,
147 # not the user files. Need to find a way of determining the prefix
150 $basedir = $prefix."/share/applnk";
152 # Terminal to use. May be specified on the command line with the -t
156 # Xmessage command line to invoke (can vary platform to platform)
157 $ostype = `uname -s`;
158 if ($ostype =~ /^HP-UX$/) {
159 $xmsg = "xmessage -geometry 400x100 -f -";
162 $xmsg = "xmessage -geometry 400x100 -file - -default \"okay\"";
165 # Print to STDOUT, default is YES, a filename is specified
170 # Support for KDE internationalisation so that menu entries appear
171 # in the language chosen by the user. Also gets around some problems
172 # with the KDE applnk file format.
174 # The Locale is stored in one of two places, depending on the
175 # version of KDE that is running.
176 $kde2cf="$ENV{'HOME'}/.kde/share/config/kdeglobals";
177 $kde1cf="$ENV{'HOME'}/.kderc";
180 # Open the file, if it exists, otherwise provide a default language.
181 unless(open KDERC
, $kde2cf) {
182 unless(open KDERC
, $kde1cf) {
187 if ( $kdeLanguage == ""){
189 # Search through the contents of the file
190 while($line = <KDERC
>) {
193 if($line =~ /^Language=/) {
194 $kdeLanguage = $line;
195 $kdeLanguage =~ s/Language=//;
196 ($kdeLanguage) = split /:/,$kdeLanguage;
205 # Begin Main Iteration.
208 # Process command line arguments
209 foreach $arg(@ARGV) {
214 elsif($last eq "-f") {
218 elsif($last eq "-t") {
222 } elsif($arg =~ /^-/) {
223 if($arg =~ /^-[dfst]$/) {
226 die("Unknown option: $arg\n\nUsage: kde2wmaker.pl [ Options... ]\n".
228 "\t\t-d <KDE App.kdelnk dir>\n".
229 "\t\t-f <output menufile>\n".
230 "\t\t-t <X terminal application>\n");
236 # Make sure the KDE Menu's Top Level Directory exists.
238 # See if there is an old menu file. If there is, rename it
241 print STDERR
"\tFound $menufile, renaming\n\n";
242 rename $menufile, "$menufile.old";
244 open(MENUFILE
,"> $menufile");
247 # Start the main menu entry
249 print STDOUT
"\"KDE Applications\" MENU\n";
250 process_dir
(STDOUT
, $basedir);
251 print STDOUT
"\"KDE Applications\" END\n";
253 print MENUFILE
"\"KDE Applications\" MENU\n";
254 process_dir
(MENUFILE
, $basedir);
255 print MENUFILE
"\"KDE Applications\" END\n";
260 print STDERR
"ERROR:\n\t$basedir not found\n\tTry another directory.\n";
264 # End of Main Iteration.
267 # process_dir() works it's way through each file and directory in
268 # the tree and generates the menu output to be used by Window Maker.
277 my ($gotLang, $gotDef, $gotExec, $inTerm);
280 # tld == Top Level Directory.
281 opendir(TLD
, $path) || return;
282 # In order to display directories before files, the directory
283 # contents must be split. Directories are added to one array, files
284 # to a second. The lists are then sorted alphabetically by name and
285 # combined into a single list for processing by the rest of the
287 while (defined($file = readdir(TLD
))) {
288 next if $file =~ /^\./;
289 if (-d
"$path/$file") {
290 @tld = (@tld, $file);
293 @tlf = (@tlf, $file);
297 # At this stage, only sort the directories, since the application
298 # sorting is done later, using the "Name=" field in the applnk file.
301 # Print out directory names first and then process the directories.
302 foreach $item(@tld) {
303 print $OUT "\"$item\" MENU\n";
304 process_dir
($OUT, "$path/$item");
305 print $OUT "\"$item\" END\n";
308 # Process the applnk files in the current directory.
309 foreach $item(@tlf) {
316 # Process the contents of the applnk file to generate a menu
317 # entry for the application.
319 open(SUB
,"$path/$item");
321 # Set a default application warning to run in case there is no
322 # Exec= line in the application definition. This will be
323 # useful for debugging exceptions.
325 $pargs="echo \"Could not extract executable information from:\\n\\n$path/$item.\"|".$xmsg;
327 # Search through the contents of the file. Exit the loop at the
328 # EOF or if we have processed the [Desktop Entry Section] of the
330 while($line = <SUB
>) {
332 # Get the application's name. This is stored in the
333 # [Desktop Entry] section of the applnk description.
335 # The application's name can have one of these forms:
340 # Get the default name anyway (one of the first two, just
341 # in case there is no language specific entry).
343 # Make sure we are in fact still in the [Desktop Entry]
345 if ($line =~ /^\[/) {
348 # Extract the Name of the Application
349 elsif ($line =~ /^Name\[?\]?=/
350 && (!$gotDef || !gotLang
)) {
352 $pname =~ s/^Name\[?\]?=//s;
353 $pname =~ s/\"/\'\'/g;
356 elsif ($line =~ /^Name\[$kdeLanguage\]=/ && !$gotLang) {
358 $pname =~ s/^Name\[$kdeLanguage\]=//s;
359 $pname =~ s/\"/\'\'/g;
363 elsif($line =~ /^Exec=/ && !$gotExec) {
365 $pargs =~ s/^Exec=//s;
366 # Strip off all command line options unless the
367 # application is "kfmclient", etc.
368 if ($pargs !~ /^kfmclient/
370 && $pargs !~ /^\/bin\
/bash/
371 && $pargs !~ /^kdesu/){
372 ($pargs) = split(/\s/, $pargs);
375 # A double check to remove any dubious characters from
376 # the command line of the exceptions listed in the
377 # above "if" statement. The only culprit so far is the
378 # KDE 1 kfmclient command line.
379 $pargs =~ s/\%[a-zA-Z]//g;
383 # If Terminal=1, then we need to execute application
384 # within a terminal window.
385 elsif($line =~ /^Terminal=(1|true)$/i) {
389 elsif ($line =~ /^\[(KDE\ )?Desktop\ Entry\]/){
397 $pargs = "$term -T \"$pname\" -e $pargs";
399 @klist = (@klist, "\t\"$pname\" EXEC $pargs\n");
402 @klist = sort(@klist);