home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #18 / NN_1992_18.iso / spool / comp / lang / perl / 5395 < prev    next >
Encoding:
Text File  |  1992-08-19  |  12.4 KB  |  371 lines

  1. Newsgroups: comp.lang.perl
  2. Path: sparky!uunet!infonode!drew.b17a.ingr.com!drew
  3. From: drew@drew.b17a.ingr.com (Drew Mills)
  4. Subject: MWM Image Menu Spec Generator (see comments at top of script)
  5. Message-ID: <1992Aug19.231215.2241@infonode.ingr.com>
  6. Keywords: menus abp mwm
  7. Sender: usenet@infonode.ingr.com (Usenet Administrator)
  8. Reply-To: drew@drew.b17a.ingr.com
  9. Organization: Cartographic Applications, Intergraph
  10. Date: Wed, 19 Aug 1992 23:12:15 GMT
  11. Lines: 358
  12.  
  13. #!/usr/local/bin/perl
  14. # This is my third try at getting this out & I haven't seen it in our news
  15. # yet.  If this is the third time you've seen this, be kind, drop me a
  16. # line; help stamp out Usenet blunders.  On with the show...
  17. ###########################################################################
  18. #$debug = 1;                 # Uncomment this for debug
  19. #
  20. #   For all you a.b.p* nuts who use the Motif Window Manager!  I
  21. #   couldn't help myself.  I had to have my pictures available on my
  22. #   menus but I didn't want to have to type 'em all in by hand.  I
  23. #   especially didn't want to have to update 'em by hand.  So this
  24. #   script updates my .mwmrc file by reading my image directories and
  25. #   creating menu entries for me.  It 'updates' the menu spec by
  26. #   replacing the 'image menus' section completely whenever you run
  27. #   this script.
  28. #
  29. #   It creates a menu 'tree' that represents the image directory
  30. #   'tree'.  It tries to ignore non-binary files.
  31. #
  32. #   By default, it uses xv to display the pictures on my background.
  33. #
  34. #   Note that it expects you have created an entry like
  35. #
  36. #       "Images"      f.menu "Images"
  37. #
  38. #   in a menu entry in your .mwmrc file.  It also expects to find the
  39. #   following 2 lines:
  40. #
  41. #   #Begin Image Menus
  42. #    .
  43. #    .
  44. #    .
  45. #    .
  46. #   #End Image Menus
  47. #
  48. #   in the .mwmrc file.  Between the two lines are where the menus specs
  49. #   will go.
  50. #
  51. #    For an example, the following directory tree:
  52. #  <image root>--|
  53. #                +-trains--+        +bno42
  54. #                |         +-steam--|
  55. #                |         |        +nw234
  56. #                |         |
  57. #                |         +-diesel--+
  58. #                |                   +-cnw403
  59. #                |                   |
  60. #                |                   +-lnn251
  61. #                |
  62. #                |
  63. #                +-scenery-+       +-yellowstone
  64. #                          |       |
  65. #                          +-parks-+-yosemite
  66. #                          |       |
  67. #                          |       +-denali
  68. #                          |
  69. #                          |
  70. #                          +-fish-+-anemone
  71. #                                 |
  72. #                                 +-blacktip
  73. #                                 |
  74. #                                 +-gourami
  75. #
  76. #  creates menus like this:
  77. #                                                       |=====|
  78. #                               |========|              |bno42|
  79. #      ========|              +-|steam  >|--------------|nw243|
  80. #          .   |              | |diesel >|-\            |=====|
  81. #          .   |              | |========| |
  82. #      Images >|-|=========|  |            |
  83. #          .   | |trains  >|--/            | |======|
  84. #          .   | |scenery >|--\            +-|cnw403|
  85. #          .   | |=========|  |              |lnn241|
  86. #      ========|              |              |======|
  87. #                             |
  88. #                             |
  89. #                             |
  90. #                             | |=======|            |===========|
  91. #                             | |parks >|------------|yellowstone|
  92. #                             +-|fish  >|-\          |yosemite   |
  93. #                               |=======| |          |denali     |
  94. #                                         |          |===========|
  95. #                                         |
  96. #                                         | |========|
  97. #                                         +-|anemone |
  98. #                                           |blacktip|
  99. #                                           |gourami |
  100. #                                           |========|
  101. #
  102. #
  103. #   LIMITATIONS:
  104. #
  105. #       This program will not differentiate between two directories
  106. #       that have the same name on different parts of the tree.  It's
  107. #       not a problem for me so I didn't bother with it.
  108. #
  109. #       It's too slow.  I've got a pretty big image directory tree and
  110. #       it takes awhile to run it.  I think that this is because it
  111. #       just takes a while to read all the directories, splice the
  112. #       lists out into manageable bites and then create all those
  113. #       strings.  I don't have any really big loops.  If anyone can
  114. #       show me where I could get some extra speed, I would welcome
  115. #       suggestions with shouts of praise and adulation (may your
  116. #       mother-in-law live long and have her own apartment).
  117. #
  118. ###########################################################################
  119.  
  120. ###
  121.   #
  122.   #  This first section contains constants that may be altered for your
  123.   #  particular situation.
  124.   #
  125. ###
  126.  
  127. $max_num_rows = 30;        # Maximum number of rows in a menu.  You'll
  128.                 # have to figure this one out by yourself.
  129.                 # If you use a smaller font than did I, then
  130.                 # you can fit more items on each menu.
  131. $picroot = "/usr/local/giffiles"; # Root directory for Image files
  132. $mwmrc_path = "$ENV{HOME}/.mwmrc"; # .mwmrc path
  133. $tmp_mwmrc_path = "/usr/tmp/tmpmwmrc"; # tmp holding file
  134. $display_cmd = "xv -rm 5 -quit -maxpect"; # Command used in menu entry to
  135.                       # display the image (This default
  136.                       # uses xv to maximize the picture
  137.                       # onto the root window)
  138.  
  139. ###########################################################################
  140. #
  141. #   Here on, it's my problem.
  142. #
  143. ###########################################################################
  144.  
  145. system("cp $mwmrc_path $mwmrc_path.sav") &&
  146.     die "I could not make a copy of $mwmrc_path, so I\'m outta here!!!\n\n";
  147.  
  148. die "$picroot is not a directory.\n" if (! -d $picroot);
  149.  
  150. open (TMPMWMRC, "> $tmp_mwmrc_path") ||
  151.     die "Could not open the tmp file $tmp_mwmrc_path!\n";
  152.  
  153. open (MWMRC, "< $mwmrc_path") ||
  154.     die "Hey!! Why can\'t I read your .mwmrc file ($mwmrc_path)???";
  155.  
  156. $found=0;
  157. while (<MWMRC>)
  158. {
  159.     ($found = 1, last) if /#Begin Image Menus/;
  160.     print TMPMWMRC $_;
  161. }
  162.  
  163. die "BAD FILE FORMAT! To indicate where the menus should go, you need to add the lines:\n\n#Begin Image Menus\n   and\n#End Image Menus\n\n   to your.mwmrc!!!\n" if (!$found);
  164.  
  165. print TMPMWMRC "#Begin Image Menus\n";
  166.  
  167. %main_menu_list = ();
  168.  
  169. #
  170. #  This call is the one that does all the work.  See the subroutine
  171. #  below to figure out what's going on.
  172. #
  173. &recurse_menu($picroot, "Images");
  174.  
  175. #
  176. #  Now, print the results out to the TMPMWMRC file
  177. #
  178. foreach(sort(keys(%main_menu_list)))
  179. {
  180.     print TMPMWMRC $main_menu_list{$_};
  181. }
  182.  
  183. print TMPMWMRC "\n#End Image Menus\n";
  184.  
  185. #
  186. # Look for the line that has #End Image Menus
  187. #
  188. $found=0;
  189. while (<MWMRC>)
  190. {
  191.     ($found=1, last) if /#End Image Menus/;
  192. }
  193.  
  194. die "BAD FILE FORMAT! To indicate where the menus should go, you need to add the lines:\n\n#Begin Image Menus\n   and\n#End Image Menus\n\n   to your.mwmrc" if (!$found);
  195.  
  196.  
  197. @therest = <MWMRC>;
  198.  
  199. print TMPMWMRC @therest;
  200.  
  201. close(TMPMWMRC);
  202. close(MWMRC);
  203.  
  204. #
  205. #  Now move the temporary .mwmrc file on top of the original .mwmrc file.
  206. rename($tmp_mwmrc_path, $mwmrc_path) ||
  207.     die "The new file $tmp_mwmrc_path was created but I wasn\'t able to rename it to $mwmrc_path\n\tMaybe you should do it yourself.";
  208.  
  209. #
  210. #  That's all folks!
  211. #
  212. exit(0);
  213.  
  214. ###########################################################################
  215. #
  216. # sub recurse_menu
  217. #
  218. #   This subroutine is the (recursively callable) routine that is used
  219. #   to create the various menus needed.
  220. #
  221. #   We use an associated list of menus to hold each menu entry no
  222. #   matter at what level its on, since mwm sees only a flat file.
  223. #   It goes through the following step for each directory it encounters:
  224. #
  225. #   1) Every subdirectory has this build menu function run on it and the
  226. #      function is expected to add its entire menu spec onto the main
  227. #      menu associated list.  A menu entry is created locally to
  228. #      access this subdirectory menu.
  229. #
  230. #   2) If maxwin > #subdirs + local entries, then create menu entries for
  231. #      each picture locally (append them to the local menu string.)
  232. #      Else, create as many sub menu entries (add them to this current
  233. #      string) as is necessary to fit in the local pictures.  Do this
  234. #      by splitting up the list into lists maxentries long.  Each list
  235. #      is given to a different routine that creates that menu and a
  236. #      f.menu entry is create in the current menu string for that new
  237. #      menu.
  238.  
  239. ###
  240. #
  241. #  This routine is expected to create a full menu spec that will be
  242. #  placed in the global main menu assoc list.
  243. #
  244. #  It is recursive in nature, in that it may call itself in creating
  245. #  it's own subdirectories.
  246. #
  247. #  The arguments it must receive are: directory path & menu name.
  248. ###
  249. sub recurse_menu
  250. {
  251.     local($directory, $menu_name) = @_;
  252.     local($menu_spec, @dirs, @images);
  253.  
  254.     $menu_spec = "Menu $menu_name\n{\n";
  255.  
  256.     # This section first reads in all directory entries that are
  257.     # directories themselves, but aren't named '.' or '..' (but it
  258.     # does get hidden directories).  It then reads in all binary
  259.     # non-directories.
  260.  
  261.     &DBG("Changing to $directory\n");
  262.  
  263.     chdir($directory) || die "Why can't I cd to $directory?\n";
  264.  
  265.     opendir(THIS, ".") ||
  266.     die "Hey, why can't I open this directory: $directory!\n";
  267.  
  268.     @dirs = sort(grep(-d && !/^\.{1,2}$/, readdir(THIS)));
  269.     rewinddir(THIS);
  270.     @images = sort(grep(-B && ! -d, readdir(THIS)));
  271.     closedir(THIS);
  272.  
  273.     #
  274.     #  For the time being I'm not going to worry about having more
  275.     #  than 30 directories.  Thus, this little bugger.
  276.     die "Whooaa, dude!  You've got a directory ($directory)\nthat contains more than $max_num_rows subdirectories!\nI just can't deal with that, dude!  I'm outta here!\n" if @dirs > $max_num_rows;
  277.  
  278.     #
  279.     #  NOTICE!!!!!!!!!!
  280.     #   The following piece of code contains one gotcha.  It creates
  281.     #   menus base on the current dir name.  It doesn't bother to
  282.     #   check on whether or not another menu has already used that dir
  283.     #   name.  In other words, there's a problem if you have two
  284.     #   different directories in your tree that have the same local name.
  285.     #
  286.     foreach $dir (@dirs)
  287.     {
  288.     $menu_spec .= "$dir\tf.menu $dir\n";
  289.     &recurse_menu("$directory/$dir", $dir);
  290.  
  291.     }
  292.  
  293.     if (@images + @dirs > $max_num_rows)
  294.     {
  295.     $index=1;
  296.  
  297.     while(@images)
  298.     {
  299.         $menu_spec .= "\"$dir$index\"\tf.menu \"$dir$index\"\n";
  300.         &create_simple_menu($dir.$index, $directory,
  301.                 splice(@images, 0, $max_num_rows));
  302.         $index++;
  303.     }
  304.  
  305.     }
  306.     else
  307.     {
  308.     for $image (@images)
  309.     {
  310.         $menu_spec .= "\"$image\"\tf.exec \"$display_cmd $directory/$image\"\n";
  311.     }
  312.     }
  313.     $menu_spec .= "}\n\n";
  314.     $main_menu_list{$menu_name} = $menu_spec;
  315. }
  316.  
  317.  
  318. ###
  319. #
  320. #  This routine only creates a single menu of picture entries as given
  321. #  to it.  Arguments are
  322. #
  323. #         1) name of the menu and
  324. #         2) directory
  325. #      rest) images
  326. #
  327. ###
  328. sub create_simple_menu
  329. {
  330.     local($mname, $directory, @images)=@_;
  331.     local($menu_spec, $image);
  332.  
  333.     &DBG("Creating menu spec $mname with %d entries\n", $#images+1);
  334.  
  335.     $menu_spec = "Menu $mname\n{\n";
  336.  
  337.     for $image (@images)
  338.     {
  339.     $menu_spec .= "\"$image\" f.exec \"$display_cmd $directory/$image\"\n";
  340.     }
  341.  
  342.     $menu_spec .= "}\n\n";
  343.  
  344.     $main_menu_list{$mname} = $menu_spec;
  345. }
  346.  
  347.  
  348. ###########################################################################
  349. #
  350. #   A little routine for printing debug statements...
  351. #
  352.  
  353. sub DBG
  354. {
  355.     local(@list) = @_;
  356.  
  357.     print "DEBUG #####################################################################\n" if $debug;
  358.     printf(@_) if $debug;
  359.     print "DEBUG #####################################################################\n" if $debug;
  360. }
  361. #    ________________________________________________________________________
  362. #   /                                    |                                   \
  363. #  |   Drew Mills                        | Mail Stop: IW17A6                  |
  364. #  |   Cartographic Applications         | E-Mail:    drew@drew.b17a.ingr.com |
  365. #  |   Intergraph Corporation            | Telephone: (205) 730-1809          |
  366. #  |   Huntsville, Alabama  35894-0001   | FAX:       (205) 730-7296          |
  367. #  |--------------------------------------------------------------------------|
  368. #  |                   ...Consider yourself a disclaimee                      |
  369. #   \________________________________________________________________________/
  370. #
  371.