wmaker: Restore multi screen functionality by reverting wrong commits
[wmaker-crm.git] / util / wkdemenu.pl
blob3a24517073e4ad44abed2c2af5c466da103b167e
1 #!/usr/bin/perl
4 # kde2wmaker.pl:
7 # This script, made for users of Window Maker (http://windowmaker.info) 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... ]
21 # 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
31 # KDE is updated.
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.
38 # 2) Run the script.
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"
45 # textbox.
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"
99 # or from "~/.kderc".
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
116 # aterm, etc.
118 # Malcolm Cowe, malk@271m.net.
120 # --------------------------------------------------------------------
122 # To Do
123 # -----
125 # Programmatically determine the system location for the KDE menu
126 # directory.
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. =)
138 # Variables
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
148 # programmatically.
149 $prefix="/usr";
150 $basedir = $prefix."/share/applnk";
152 # Terminal to use. May be specified on the command line with the -t
153 # switch.
154 $term = "xterm";
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 -";
161 else {
162 $xmsg = "xmessage -geometry 400x100 -file - -default \"okay\"";
165 # Print to STDOUT, default is YES, a filename is specified
166 $stdout = 1;
168 # KDE Locale Support
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";
178 $kdeLanguage = "";
180 # Open the file, if it exists, otherwise provide a default language.
181 unless(open KDERC, $kde2cf) {
182 unless(open KDERC, $kde1cf) {
183 $kdeLanguage = "C";
187 if ( $kdeLanguage == ""){
188 $kdeLanguage = "C";
189 # Search through the contents of the file
190 while($line = <KDERC>) {
191 chomp($line);
192 # Grab the Language
193 if($line =~ /^Language=/) {
194 $kdeLanguage = $line;
195 $kdeLanguage =~ s/Language=//;
196 ($kdeLanguage) = split /:/,$kdeLanguage;
197 last;
200 close(KDERC);
205 # Begin Main Iteration.
208 # Process command line arguments
209 foreach $arg(@ARGV) {
210 if($last) {
211 if($last eq "-d") {
212 $basedir = $arg;
214 elsif($last eq "-f") {
215 $menufile = $arg;
216 $stdout = 0;
218 elsif($last eq "-t") {
219 $term = $arg;
221 undef($last);
222 } elsif($arg =~ /^-/) {
223 if($arg =~ /^-[dfst]$/) {
224 $last = $arg;
225 } else {
226 die("Unknown option: $arg\n\nUsage: kde2wmaker.pl [ Options... ]\n".
227 "\n\tOptions:\n\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");
231 &Usage;
236 # Make sure the KDE Menu's Top Level Directory exists.
237 if(-d $basedir) {
238 # See if there is an old menu file. If there is, rename it
239 unless($stdout) {
240 if(-e $menufile) {
241 print STDERR "\tFound $menufile, renaming\n\n";
242 rename $menufile, "$menufile.old";
244 open(MENUFILE,"> $menufile");
247 # Start the main menu entry
248 if($stdout) {
249 print STDOUT "\"KDE Applications\" MENU\n";
250 process_dir (STDOUT, $basedir);
251 print STDOUT "\"KDE Applications\" END\n";
252 } else {
253 print MENUFILE "\"KDE Applications\" MENU\n";
254 process_dir (MENUFILE, $basedir);
255 print MENUFILE "\"KDE Applications\" END\n";
258 } else {
259 # Error out :/
260 print STDERR "ERROR:\n\t$basedir not found\n\tTry another directory.\n";
261 exit(0);
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.
269 sub process_dir {
271 my $OUT = @_[0];
272 my $path = @_[1];
273 my $item;
274 my @tld;
275 my @tlf;
276 my @klist;
277 my ($gotLang, $gotDef, $gotExec, $inTerm);
278 my $inDesktop;
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
286 # subroutine.
287 while (defined($file = readdir(TLD))) {
288 next if $file =~ /^\./;
289 if (-d "$path/$file") {
290 @tld = (@tld, $file);
292 else {
293 @tlf = (@tlf, $file);
296 closedir(TLD);
297 # At this stage, only sort the directories, since the application
298 # sorting is done later, using the "Name=" field in the applnk file.
299 @tld = sort (@tld);
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) {
310 $gotLang = 0;
311 $gotDef = 0;
312 $gotExec = 0;
313 $inTerm = 0;
314 $inDesktop = 0;
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.
324 $pname="$item";
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
329 # file.
330 while($line = <SUB>) {
331 chomp($line);
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:
336 # Name=
337 # Name[]=
338 # Name[language]=
340 # Get the default name anyway (one of the first two, just
341 # in case there is no language specific entry).
342 if ($inDesktop) {
343 # Make sure we are in fact still in the [Desktop Entry]
344 # section.
345 if ($line =~ /^\[/) {
346 $inDesktop = 0;
348 # Extract the Name of the Application
349 elsif ($line =~ /^Name\[?\]?=/
350 && (!$gotDef || !gotLang)) {
351 $pname = $line;
352 $pname =~ s/^Name\[?\]?=//s;
353 $pname =~ s/\"/\'\'/g;
354 $gotDef = 1;
356 elsif ($line =~ /^Name\[$kdeLanguage\]=/ && !$gotLang) {
357 $pname = $line;
358 $pname =~ s/^Name\[$kdeLanguage\]=//s;
359 $pname =~ s/\"/\'\'/g;
360 $gotLang = 1;
362 # Grab the command
363 elsif($line =~ /^Exec=/ && !$gotExec) {
364 $pargs = $line;
365 $pargs =~ s/^Exec=//s;
366 # Strip off all command line options unless the
367 # application is "kfmclient", etc.
368 if ($pargs !~ /^kfmclient/
369 && $pargs !~ /^kcm/
370 && $pargs !~ /^\/bin\/bash/
371 && $pargs !~ /^kdesu/){
372 ($pargs) = split(/\s/, $pargs);
374 else {
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;
381 $gotExec = 1;
383 # If Terminal=1, then we need to execute application
384 # within a terminal window.
385 elsif($line =~ /^Terminal=(1|true)$/i) {
386 $inTerm=1;
389 elsif ($line =~ /^\[(KDE\ )?Desktop\ Entry\]/){
390 $inDesktop = 1;
394 close(SUB);
396 if ($inTerm) {
397 $pargs = "$term -T \"$pname\" -e $pargs";
399 @klist = (@klist, "\t\"$pname\" EXEC $pargs\n");
402 @klist = sort(@klist);
403 foreach (@klist) {
404 print $OUT $_;
407 return;