home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / x / volume18 / xdtree / part01 < prev    next >
Encoding:
Text File  |  1992-07-19  |  50.7 KB  |  1,818 lines

  1. Newsgroups: comp.sources.x
  2. Path: uunet!darwin.sura.net!mips!msi!dcmartin
  3. From: Konstantinos Konstantinides <kk@hpkronos.hpl.hp.com>
  4. Subject: v18i031: xdtree (Motif), Part01/03
  5. Message-ID: <csx-18i031-xdtree@uunet.UU.NET>
  6. Originator: dcmartin@fascet
  7. Sender: dcmartin@msi.com (David C. Martin - Moderator)
  8. Organization: Molecular Simulations, Inc.
  9. Date: Mon, 20 Jul 1992 15:41:25 GMT
  10. Approved: dcmartin@msi.com
  11. Lines: 1805
  12.  
  13. Submitted-by: Konstantinos Konstantinides <kk@hpkronos.hpl.hp.com>
  14. Posting-number: Volume 18, Issue 31
  15. Archive-name: xdtree/part01
  16.  
  17. From the README:
  18.  
  19. xdtree is an extension of dtree,  the program originally written by
  20. Dave Borman. It is very similar to my old "dtree" I posted in
  21. comp.sources.x in 1990, but it has a new user interface, and I changed
  22. the name to xdtree to avoid any confusion with the original program.
  23. It displays on a terminal or under X11 (using Motif widgets) the tree
  24. structure of a Unix directory tree.  On a color terminal, different
  25. colors can be used for files, directories, and symbolic links. On a
  26. monochrome terminal, one may try to use different button bitmaps for
  27. files and directories using the PushButton resources.
  28.  
  29. #!/bin/sh
  30. # This is a shell archive (produced by shar 3.50)
  31. # To extract the files from this archive, save it to a file, remove
  32. # everything above the "!/bin/sh" line above, and type "sh file_name".
  33. #
  34. # made 07/20/1992 15:37 UTC by dcmartin@fascet
  35. # Source directory /home/fascet/dcmartin/csx/src/tmp
  36. #
  37. # existing files will NOT be overwritten unless -c is specified
  38. #
  39. # This is part 1 of a multipart archive                                    
  40. # do not concatenate these parts, unpack them in order with /bin/sh        
  41. #
  42. # This shar contains:
  43. # length  mode       name
  44. # ------ ---------- ------------------------------------------
  45. #   6123 -rw-r--r-- xdtree.1
  46. #  47318 -rw-r--r-- xdtree.c
  47. #  10452 -rw-r--r-- Makefile
  48. #    785 -rw-r--r-- XDtree
  49. #   2270 -rw-r--r-- xdtree-i.h
  50. #    261 -rw-r--r-- Imakefile
  51. #   1418 -rw-r--r-- README
  52. #  21424 -rw-r--r-- Tree.c
  53. #   2420 -rw-r--r-- Tree.h
  54. #   3293 -rw-r--r-- TreeP.h
  55. #
  56. if test -r _shar_seq_.tmp; then
  57.     echo 'Must unpack archives in sequence!'
  58.     echo Please unpack part `cat _shar_seq_.tmp` next
  59.     exit 1
  60. fi
  61. # ============= xdtree.1 ==============
  62. if test -f 'xdtree.1' -a X"$1" != X"-c"; then
  63.     echo 'x - skipping xdtree.1 (File already exists)'
  64.     rm -f _shar_wnt_.tmp
  65. else
  66. > _shar_wnt_.tmp
  67. echo 'x - extracting xdtree.1 (Text)'
  68. sed 's/^X//' << 'SHAR_EOF' > 'xdtree.1' &&
  69. .TH XDTREE 1L
  70. .SH NAME
  71. xdtree \- display directory tree structures
  72. .SH SYNOPSIS
  73. .B xdtree
  74. [
  75. .I \-aDfghHNpsStvx
  76. ] [
  77. .I \-l level
  78. ] [
  79. .I \-c linelength
  80. ] [
  81. .BR directory ...
  82. ]
  83. .SH DESCRIPTION
  84. .I xdtree
  85. is an extension of
  86. .I dtree
  87. and displays a graphic representation of the directory structure of each given
  88. .B directory 
  89. and its children either on the terminal stdout or on an X11 window, using
  90. the Motif widgets (default). If no directories are specified, the current
  91. directory is used.
  92. By default, only directories, not regular files, are shown, and only their
  93. filenames are given.  Various options add additional
  94. information to the tree.
  95. .SS OPTIONS
  96. .TP
  97. .I \-a
  98. Include files in the listing (excluding entries beginning with '.').
  99. .TP
  100. .I \-c linelength
  101. Make
  102. .I linelength
  103. the length of each
  104. column of the printout.  By default, this is 14.
  105. Any entries longer than
  106. the column length are truncated accordingly, and the last character that
  107. fits into the column is replaced by an asterisk.
  108. This option only has an effect if the
  109. .I -v 
  110. option is specified.
  111. .TP
  112. .I \-l level
  113. Search only up to the specified level. (Maximum is 10).
  114. .TP
  115. .I \-D
  116. List directories first.  For each directory, its subdirectories
  117. will be listed first, and then all of its other entries.
  118. .TP
  119. .I \-f
  120. List files first.  The reverse of
  121. .IR  \-D .
  122. .TP
  123. .I \-S
  124. Long listing.  Display useful information to the right of
  125. each entry: the name of the file's owner, its size in blocks, and its mode.
  126. .TP
  127. .I \-g
  128. Same as the
  129. .I \-S
  130. option, except that the group name is used instead of
  131. the owner name.  If both the
  132. .I \-S
  133. and
  134. .I \-g
  135. options are used, both the
  136. owner and group will be displayed.
  137. .TP
  138. .I \-H
  139. Display a header at the top of the printout that gives the time and
  140. date that the printout was made and a summary of the type of
  141. information contained in the tree.
  142. .TP
  143. .I \-N
  144. No sort.  Entries are listed in the order they are read
  145. from the directories.
  146. .TP
  147. .I \-p
  148. Include entries beginning with '.' (except '.' and '..').
  149. .TP
  150. .I \-s
  151. Simplify the long listing: display the user id, size in blocks, and
  152. octal mode of the file.  This option implies the
  153. .I \-S
  154. option unless the
  155. .I \-g
  156. option is specified.
  157. .TP
  158. .I \-v
  159. Do not let column lengths vary; use the same
  160. width for each column of output.  The width defaults to 14
  161. but can be set with the
  162. .I \-c
  163. option.
  164. .TP
  165. .I \-x
  166. Do not cross file systems.  
  167. .I xdtree
  168. will not cross over to a
  169. subdirectory if it is on a different file system.
  170. .TP
  171. .I \-h
  172. Will print a list of the options.
  173. .TP
  174. .I \-t
  175. Terminal mode.
  176. In default mode
  177. .I
  178. xdtree
  179. will display the directory tree structure in an X11 window.
  180. The \-t option allows the tree to be printed on the terminal stdout.
  181. X
  182. Under the X11 window mode, a button click on a tree node,  makes it
  183. the "active" node. The name of the "active" node always appears
  184. at the top of the window, under the "quit" button.
  185. Below the area where the name of the "active" node is shown,
  186. a table displays the mode of the node, the group and user IDs, and its
  187. size.
  188. Next to this menu are
  189. the \fIfile,\fR \fIdirectory,\fR and \fIPrint-Tree\fR option buttons.
  190. There are
  191. four \fIfile\fR options: \fIview, topview, edit\fR and \fIprint\fR.
  192. There are three \fIdirectory\fR options: \fIshow subtree, list files\fR,
  193. and \fIlist '../'\fR.
  194. Thus, the \-c, \-S, \-g, \-s, and \-v options are meaningful only
  195. when the \-t option is used.
  196. However, the \-S, \-g, and \-H options are accessible from the toggle buttons
  197. in the \fIPrint-Tree\fR options menu.
  198. .TP
  199. .B view 
  200. Display the whole file on a scrolled window.
  201. Since the program reads a file all at once,
  202. the wait may be significant for a very large file.  However, the option
  203. .TP
  204. .B topview 
  205. shows only the top of the file (2000 bytes).
  206. .TP
  207. .B edit
  208. Edit the file. \fIxdtree\fR first checks and executes the command 
  209. specified by the
  210. .B xdtree*editor:
  211. resource in .Xdefaults. If that command is NULL, \fIxdtree\fR
  212. forks an hpterm window using the editor command specified
  213. in the
  214. .B EDITOR
  215. environmental variable. If that variable is not specified, it uses \fIvi.\fR
  216. .TP
  217. .B print
  218. Print the file. It prints the file on the printer destination specified
  219. by the
  220. .B xdtree*lpdest:
  221. resource in .Xdefaults.
  222. If that variable is not specified it uses
  223. the default lp destination.
  224. The same variable is also being used when the \fIPrint-Tree\fR button
  225. is selected.
  226. .TP
  227. .B "show subtree"
  228. Show the directory subtree starting from the selected "active"
  229. directory node.
  230. .TP
  231. .B "list files"
  232. List all files and directories for the "active" directory node.
  233. This is equivalent to an "ls" command on that directory.
  234. .TP
  235. .B "list \.\.\/"
  236. List the directories in the parent (top) directory.  Allows the user
  237. to traverse upwards the directory tree.
  238. .TP
  239. .B "Print-Tree"
  240. Print the tree.  This is equivalent to using the \fIxdtree\fR command
  241. with the \-t option and piping the output to your printer.
  242. X
  243. Except for the \fIview\fR and \fItopview\fR options, in all other cases
  244. a click on the "quit" button of the "parent" will
  245. cause the "parent" \fIxdtree\fR window to freeze until the selected command
  246. has been executed or the "child" window has been killed.
  247. Then the "parent" window will automatically die.
  248. Thus it is recommended to kill "children" applications before
  249. you try to kill the "parent".
  250. X
  251. On a color terminal, one can choose different colors to distinguish
  252. between directories, files, and symbolic links.
  253. To set up a simple color scheme for \fIxdtree\fR, put the following entries
  254. in your ~/.Xdefaults file:
  255. X
  256. xdtree*geometry:                     500x500
  257. .br
  258. xdtree*quit.background:              DarkSlateBlue
  259. .br
  260. xdtree*dir.background:               Red      
  261. .br
  262. xdtree*sym_link.background:          Brown  
  263. .br
  264. xdtree*options.background:           Red        
  265. X
  266. A set of simple resources is also specified in
  267. /usr/lib/X11/app-defaults/XDtree
  268. .SH AUTHOR
  269. Dave Borman, Digital Unix Engineering Group, wrote the original
  270. dtree program.
  271. .br
  272. decvax!borman
  273. .br
  274. Originally written at St. Olaf College, Northfield, MN.
  275. .br
  276. Additions for the X11 windows display by K. Konstantinides,
  277. Hewlett-Packard Laboratories.
  278. Copyright: Hewlett-Packard, 1990, and 1992.
  279. e-mail:kk@hpkronos.hpl.hp.com
  280. SHAR_EOF
  281. chmod 0644 xdtree.1 ||
  282. echo 'restore of xdtree.1 failed'
  283. Wc_c="`wc -c < 'xdtree.1'`"
  284. test 6123 -eq "$Wc_c" ||
  285.     echo 'xdtree.1: original size 6123, current size' "$Wc_c"
  286. rm -f _shar_wnt_.tmp
  287. fi
  288. # ============= xdtree.c ==============
  289. if test -f 'xdtree.c' -a X"$1" != X"-c"; then
  290.     echo 'x - skipping xdtree.c (File already exists)'
  291.     rm -f _shar_wnt_.tmp
  292. else
  293. > _shar_wnt_.tmp
  294. echo 'x - extracting xdtree.c (Text)'
  295. sed 's/^X//' << 'SHAR_EOF' > 'xdtree.c' &&
  296. /*
  297. X *    DTREE - Print the tree structure of a directory
  298. X *    4/7/83 name was changed from TREE to DTREE
  299. X *    9/7/83 mods for 4.1c and 4.2 dirctory structure added
  300. X *
  301. X *    Dave Borman, Digital Unix Engineering Group
  302. X *        decvax!borman
  303. X *    Originally written at St. Olaf College, Northfield MN.
  304. X *    Copyright (c) 1983 by Dave Borman
  305. X *    All rights reserved
  306. X *    This program may not be sold, but may be distributed
  307. X *    provided this header is included.
  308. X *
  309. X *    Usage:    xdtree [-aDfghHlNpstvx] [-c line-length] [directory...]
  310. X *    Flags:    -a) include non-directory entries in listing
  311. X *        -D) sort tree with directories at the top
  312. X *        -f) sort tree with files at the top
  313. X *        -g) same as S, but use group name instead of user name
  314. X *              -h) help
  315. X *        -H) display a header at top
  316. X *        -S) print stats with each listing
  317. X *            if both g & S flags are given, both owner and
  318. X *            group will be printed
  319. X *        -N) do not sort the tree
  320. X *        -p) include files starting with a '.' (except "." & "..")
  321. X *        -s) use shorter stats. Implies -S if -g isn't given.
  322. X *              -t) Use terminal mode (no X windows)
  323. X *        -v) variable length columns off
  324. X *        -x) do not cross mounted file systems.
  325. X *        -c length) set max column length to "length"
  326. X *        -l level) search up to the specified "level".
  327. X */
  328. X
  329. X /*     Modified by      Ed Arnold      CSU-CS   (csu-cs!arnold)     3-5-84
  330. X  *
  331. X  *     Allows symbolic links to both directories and individual files.
  332. X  *     With a '-S' or '-aS' option, links are denoted with a 'l' in front of 
  333. X  *     file or directory permissions. In all other instances both links to 
  334. X  *     directories and files are represented just as files are. Contents of
  335. X  *     linked directories are not printed due to the possibility of 
  336. X  *     recursively linked directories.
  337. X  *
  338. X  *     Big directory name option added by:
  339. X  *                      Mike Vevea      CSU-CS (csu-cs!vevea)      3-22-84
  340. X  *
  341. X  *    Toggle sense of -v (running 4.2), and eliminate some extraneous
  342. X  *        print info    Mike Meyer Energy Analysts (mwm@ea)    4/17/84
  343. X  *
  344. X  *    Fix the exit status to correctly indicate what happened.
  345. X  *                Mike Meyer Energy Analysts (mwm@ea)    4/23/84
  346. X  *
  347. X  *    Change MAX to INITIAL_ELEM to fix conflict on Suns,
  348. X  *    fix incorrect default value for Clength when -v not given,
  349. X  *    add -H option to print header with date and description of tree,
  350. X  *    remove -b option (useless) and simplify array access,
  351. X  *    use getopt to parse options, fix usage message,
  352. X  *    use getwd instead of opening a pipe to pwd,
  353. X  *    make error messages more informative,
  354. X  *    use strncpy instead of sprintf for speed,
  355. X  *    move function declarations to top of file,
  356. X  *    comment out junk after #else and #endif,
  357. X  *    make symbolic link configuring automatic,
  358. X  *    check all error returns from malloc and realloc,
  359. X  *    add System V/Xenix/Unos compatibility,
  360. X  *    remove definition of rindex.
  361. X  *        David MacKenzie <djm@eng.umd.edu> 12/20/89
  362. X  *
  363. X  *    Modified to display the tree on X11 windows using the Motif
  364. X  *    widgets and the Tree widget described by D.Young in his book,
  365. X  *     "The X Window System, Programming and applications with Xt,
  366. X  *     OSF/MOTIF EDITION", Prentice Hall, 1990.
  367. X  *     Clicking on the "active" node pops-up a menu with the Mode, and Group
  368. X  *     and User IDs. Clicking on "view" pops up a window with the whole
  369. X  *     contents of the file. Clicking on "topview" shows the top
  370. X  *    of the file only (2000 bytes).
  371. X  *     On the tree, files, directories, and symbolic links can be
  372. X  *     shown with different colors.
  373. X  *     Changed some options so there is no conflict with X-window
  374. X  *    options ( -d to -D, and -n to -N).
  375. X  *    Added the -t and -h options. Changed the -l option to -S
  376. X  *     Added the "-l level" option.
  377. X  *    Konstantinos Konstantinides, Hewlett-Packard Laboratories
  378. X  *     konstantinos_konstantinides@hplabs.hp.com  3/23/90
  379. X  *
  380. X  *     Copyright: HEWLETT-PACKARD, 1990
  381. X  *     Motif is a trademark of Open Software Foundation, Inc.
  382. X  *     X Window System is a trademark of the Massachusetts Institute of
  383. X  *     Technology
  384. X  *
  385. X  *    Added support for both the Tree and XmGraph widgets
  386. X  *    K. Konstantinides 4/16/90
  387. X  *
  388. X  *     Rewrote the user interface, renamed program from dtree to xdtree
  389. X  *     K. Konstantinides 4/30/92
  390. X  */
  391. X
  392. /* Compile-time options:
  393. X *
  394. X * STATS    leave undefined to remove stats, giving more core space
  395. X * and thus the ability to tree larger tree structures on PDP 11/70s.
  396. X *
  397. X * NEWDIR    directory structure a la Berkeley 4.1c or 4.2
  398. X *
  399. X * NDIR        use <sys/ndir.h> instead of <sys/dir.h>
  400. X * NEWDIR must be defined as well.
  401. X *
  402. X * DIRENT    use Posix directory library.
  403. X * NEWDIR must be defined as well.
  404. X *
  405. X * SYSV        use getcwd instead of getwd, strrchr instead of rindex.
  406. X */
  407. void re_orient();
  408. void disarm_callback();
  409. void activate_callback();
  410. void arm_callback();
  411. void clickB();
  412. void w_print();
  413. void button_print();
  414. void pop_data();
  415. void view();
  416. void quit_b();
  417. void quit_b_pop();
  418. void do_menu(), stoggle(), htoggle(), gtoggle(), print_tree();
  419. X
  420. static    char Sccsid[]="@(#)xdtree.c    2.0    4/30/92";
  421. X
  422. #ifdef S_IFLNK
  423. static  char Rcsid[] ="$Header: xdtree.c,v 2.1 92/04/30 18:01:12 kk Exp $";
  424. #endif /* S_IFLNK */
  425. X
  426. #include    <stdio.h>
  427. #include    <sys/types.h>
  428. #include    <sys/stat.h>
  429. #include    <time.h>
  430. #include    <string.h>
  431. #include    <stdlib.h>
  432. X
  433. /* Include files for X windows */
  434. #include <X11/Intrinsic.h>
  435. #include <X11/Shell.h>
  436. #include <X11/StringDefs.h>
  437. #include <Xm/Xm.h>
  438. #include <Xm/Label.h>
  439. #include <Xm/PushB.h>
  440. #include <Xm/PushBG.h>
  441. #include <Xm/CascadeB.h>
  442. #include <Xm/RowColumn.h>
  443. #include <Xm/ScrolledW.h>
  444. #include <Xm/Separator.h>
  445. #include <Xm/MainW.h>
  446. #include <Xm/Frame.h>
  447. #include <Xm/Form.h>
  448. #include <Xm/Text.h>
  449. #include <Xm/ToggleB.h>
  450. #include "Tree.h"
  451. X
  452. /* Original Defs */
  453. #ifdef    STATS
  454. # include    <pwd.h>
  455. # include    <grp.h>
  456. #endif    /* STATS */
  457. X
  458. #ifdef    NEWDIR
  459. # if    DIRENT
  460. #  include    <dirent.h>
  461. #  define    direct    dirent
  462. # else
  463. #  if    NDIR
  464. #   include    <sys/ndir.h>
  465. #  else
  466. #   include    <sys/dir.h>
  467. #  endif
  468. # endif /* DIRENT */
  469. #else
  470. # include    <sys/dir.h>
  471. #endif    /* NEWDIR */
  472. X
  473. /* default column length when -v is given */
  474. #ifdef unos
  475. #define DEFCOLWID    30
  476. #else
  477. #define DEFCOLWID       14
  478. #endif
  479. X
  480. #include    <sys/param.h>    /* for MAXPATHLEN */
  481. #ifndef MAXPATHLEN
  482. # ifdef LPNMAX        /* Xenix from stdio.h */
  483. #  define MAXPATHLEN (LPNMAX - 1)
  484. # else
  485. #  include <limits.h>    /* try somewhere else */
  486. #  define MAXPATHLEN PATH_MAX
  487. # endif
  488. #endif
  489. X
  490. #ifndef MAXNAMLEN    /* defined with NEWDIR routines */
  491. # ifdef LFNMAX        /* Xenix again */
  492. #  define MAXNAMLEN (LFNMAX - 1)
  493. # else
  494. #  define MAXNAMLEN      DEFCOLWID
  495. # endif
  496. #endif
  497. X
  498. #define    DEPTH 10    /* maximum depth that dtree will go */
  499. #define    INITIAL_ELEM    100    /* initial # of elements for list of files */
  500. X
  501. #define    FFIRST    2    /* sort files first */
  502. #define DFIRST    1    /* sort directories first */
  503. #define    FAIL    -1    /* failure return status of sys calls */
  504. #define    GREATER    1    /* return value of strcmp if arg1 > arg2 */
  505. #define    LESSTHAN -1    /* return value of strcmp if arg1 < arg2 */
  506. #define    SAME    0    /* return value of strcmp if arg1 == arg2 */
  507. X
  508. #ifdef    STATS
  509. char *getmode();
  510. char *guid();
  511. char *ggid();
  512. struct passwd *getpwuid();
  513. struct group *getgrgid();
  514. #endif /* STATS */
  515. X
  516. #ifdef    SYSV
  517. #define    rindex    strrchr
  518. #endif /* SYSV */
  519. X
  520. char *getwd();
  521. char *rindex();
  522. /* 
  523. int qsort();
  524. char *malloc();
  525. char *realloc();
  526. */
  527. long time();
  528. X
  529. int compar();            /* comparison routine for qsort */
  530. char *xmalloc();
  531. char *xrealloc();
  532. X
  533. #ifdef    SYSV
  534. #define getwd(buf) getcwd((buf), MAXPATHLEN + 1)
  535. #endif /* SYSV */
  536. X
  537. int    Index = 0;        /* current element of list[]    */
  538. int     CLength = 0;        /* max length of a column       */
  539. int    All = 0;        /* all != 0; list non-directory entries */
  540. int    File_dir = 0;        /* flag for how to sort */
  541. int    Sort = 1;        /* flag to cause sorting of entries */
  542. int    Point = 1;        /* skip point files if set    */
  543. int    Header = 0;        /* print verbose header */
  544. int    Maxes[DEPTH];        /* array keeps track of max length in columns */
  545. int    Level = 0;        /* counter for how deep we are    */
  546. int    Device;            /* device that we are starting tree on */
  547. int    Xdev = 1;        /* set to allow crossing of devices */
  548. int    Varspaces = 1;        /* set to allow compaction of column width */
  549. #ifdef    STATS
  550. int    Gflag = 0;        /* set for group stats instead of owner */
  551. int    Longflg = 0;        /* set for long listing */
  552. int    Compact = 0;        /* set for shortened long listing */
  553. #endif    /* STATS */
  554. #undef Status
  555. struct    stat Status;
  556. #ifdef  S_IFLNK
  557. struct  stat Lstat;   /* stat of link, if there is one */
  558. #endif  /* S_IFLNK */
  559. X
  560. struct entry {
  561. X    int next;            /* index to next element in list */
  562. X                    /* could be a ptr, but realloc() */
  563. X                    /* might screw us then */
  564. #ifdef    STATS
  565. X    off_t    e_size;            /* size in blocks */
  566. X    unsigned short    e_mode;        /* file mode */
  567. X    short    e_uid;            /* uid of owner */
  568. X    short    e_gid;            /* gid of owner */
  569. #endif    /* STATS */
  570. X    unsigned short dir : 1;        /* entry is a directory */
  571. X    unsigned short last : 1;    /* last entry in the dir. */
  572. X    unsigned short dev : 1;        /* set if same device as top */
  573. X    unsigned short end : 13;    /* index of last subdir entry*/
  574. X    char    e_name[MAXNAMLEN + 1];    /* name from directory entry */
  575. X    char    path_name[MAXPATHLEN + 1]; /* path name */
  576. } *List, *SaveList;
  577. X
  578. unsigned Size;                /* how big of space we've malloced */
  579. X
  580. char    *Spaces;    /* used for output */
  581. char    Buf1[BUFSIZ];    /* buffers for stdio stuff.  We don't want    */
  582. #ifndef NEWDIR
  583. char    Buf2[BUFSIZ];    /* anyone calling malloc, because then        */
  584. X            /* realloc() will have to move the whole list    */
  585. #endif
  586. #define FS(str) (void) fprintf(stderr,str)
  587. X
  588. help()
  589. {
  590. X                    fprintf(stderr,
  591. #ifdef    STATS
  592. X        "Usage: xdtree [-aDfghHlNpstvx] [-c linelength] [directory ... ]\n"
  593. #else    /* STATS */
  594. X        "Usage: xdtree [-aDfhHNptvx] [-c linelength] [directory ... ]\n"
  595. #endif    /* STATS */
  596. X                        );
  597. FS("   options  -a) include non-directory entries in listing\n");
  598. FS("            -D) sort tree with directories at the top\n");
  599. FS("            -f) sort tree with files at the top\n");
  600. FS("            -h) help - prints this message\n");
  601. FS("            -H) display a header at top\n");
  602. FS("            -x) do not cross mounted file systems.\n");
  603. FS("            -p) include files starting with a . (except . and ..)\n");
  604. FS("            -N) do not sort the tree\n");
  605. FS("            -t) Use terminal mode, don't display on an X window\n\n");
  606. FS("            -l level) Search only up to the specified level \n\n");
  607. FS("            Valid only if -t is used. Under default mode, a click on a \n");
  608. FS("            node pops up a menu with mode, user and group ids.\n\n");
  609. FS("            -S) print stats with each listing\n");
  610. FS("                if both g & S flags are given, both owner and\n");
  611. FS("                group will be printed\n");
  612. FS("            -g) same as S, but use group name instead of user name \n");
  613. FS("            -s) use shorter stats. Implies -S if -g isn't given.\n");
  614. FS("            -v) variable length columns \n");
  615. FS("            -c length) set max column length to -length-\n");
  616. FS("  X-Window version 2.0 4/30/92 \n");
  617. }
  618. int newlevel = DEPTH;
  619. Widget boxes[12], options;
  620. Widget submenu_file, submenu_dir,file_menu, dir_menu;
  621. struct entry *file_pointer;
  622. int S_flag = FALSE;
  623. int H_flag=FALSE;
  624. int g_flag=FALSE;
  625. X
  626. X
  627. main(argc, argv)
  628. char    **argv;
  629. int    argc;
  630. {
  631. X    extern int optind;
  632. X    extern char *optarg;
  633. X    register int i;
  634. X    char    top[MAXPATHLEN + 1];    /* array for treetop name */
  635. X    char    home[MAXPATHLEN + 1];    /* starting dir for multiple trees */
  636. X    char    *ptr;
  637. X
  638. X    Widget toplevel;
  639. X    Widget sw, tree, q_button, w_button;
  640. X    Widget menu_bar, frame, main_w, title;
  641. X    Arg    wargs[10],arg[15];
  642. X    int    flagX=1;            /* use X windows as default */
  643. X    Widget quit_menu, exit_b, reorient;
  644. X    int really_quit, n;
  645. X
  646. X    setbuf(stdout, Buf1);
  647. X
  648. X    while ((i = getopt (argc, argv,
  649. #ifdef STATS
  650. X                "haDfgHl:NpsSvxtc:"
  651. #else
  652. X                "haDfHl:Npvxtc:"
  653. #endif /* STATS */
  654. X                )) != EOF) {
  655. X        switch (i) {
  656. X                case 'a':
  657. X                    All = 1;
  658. X                    break;
  659. X                case 'c':
  660. X                    CLength = atoi(optarg);
  661. X                    if (CLength > MAXNAMLEN)
  662. X                        CLength = MAXNAMLEN;
  663. X                    else if (CLength < 1)
  664. X                        CLength = DEFCOLWID;
  665. X                    break;
  666. X                case 'l':
  667. X                    newlevel = atoi(optarg);
  668. X                    if(newlevel > DEPTH) {
  669. X                    newlevel = DEPTH;
  670. X                    fprintf(stderr,"Warning: Depth is limited by DEPTH=%d\n",newlevel);
  671. X                    }
  672. X                    break;
  673. X                case 'D':
  674. X                    File_dir = DFIRST;
  675. X                    break;
  676. X                case 'f':
  677. X                    File_dir = FFIRST;
  678. X                    break;
  679. X                case 'H':
  680. X                    Header = 1;
  681. X                    break;
  682. X                case 'N':
  683. X                    Sort = 0;
  684. X                    break;
  685. X                case 'p':
  686. X                    Point = 0;
  687. X                    break;
  688. X                case 'v':
  689. X                    Varspaces = 0;
  690. X                    break;
  691. X                case 'x':
  692. X                    Xdev = 0;
  693. X                    break;
  694. X                case 't':
  695. X                    flagX = 0;
  696. X                    break;
  697. X
  698. X                case 'h':
  699. X                    help();
  700. X                    exit(0);
  701. #ifdef    STATS
  702. X                case 'g':
  703. X                    Gflag = 1;
  704. X                    break;
  705. X                case 'S':
  706. X                    Longflg = 1;
  707. X                    break;
  708. X                case 's':
  709. X                    Compact = 1;
  710. X                    break;
  711. #endif    /* STATS */
  712. X                default:
  713. X                    help();
  714. X                    exit(FAIL);
  715. X                }
  716. X    }
  717. #ifdef    STATS
  718. X    if (Compact && !Gflag)
  719. X        Longflg = 1;
  720. #endif    /* STATS */
  721. X    if (CLength == 0)
  722. X        CLength = Varspaces ? MAXNAMLEN : DEFCOLWID;
  723. X
  724. X    /* Establish where we are (our home base...) */
  725. X    if (getwd(home) == 0) {
  726. X        fprintf(stderr,
  727. X            "xdtree: Cannot get initial directory: %s\n", home);
  728. X        exit(1);
  729. X    }
  730. X
  731. X    Spaces = xmalloc(MAXNAMLEN+2);
  732. X    for(i = 0; i <= MAXNAMLEN; i++)
  733. X        Spaces[i] = ' ';
  734. X    Spaces[i] = '\0';
  735. X
  736. X    /* Get initial Storage space */
  737. X    Size = sizeof(struct entry) * INITIAL_ELEM;
  738. X    SaveList = (struct entry *)xmalloc(Size);
  739. X
  740. X    /* adjust for no specified directory */
  741. X    if (optind == argc )
  742. X        if(optind > 1) argv[--optind] = ".";
  743. X        else { argv[1] = ".", optind = 1; argc = 2;}
  744. X
  745. X    if (Header)
  746. X        print_date();
  747. X
  748. X    /* walk down the rest of the args, treeing them one at at time */
  749. X    for (; optind < argc; optind++) {
  750. X        if (chdir(home) == -1) {
  751. X            fprintf(stderr, "xdtree: Cannot change to initial directory ");
  752. X            perror(home);
  753. X            exit(1);
  754. X        }
  755. X        strncpy (top, argv[optind], MAXPATHLEN);
  756. X
  757. X        if (chdir(top) == FAIL) {
  758. X            fprintf(stderr, "xdtree: Cannot change to top directory ");
  759. X            perror(top);
  760. X            continue;
  761. X        } else if (getwd(top) == 0) {
  762. X            fprintf(stderr,"xdtree: Cannot get current directory: %s\n", top);
  763. X            continue;
  764. X        }
  765. X
  766. X        List = SaveList; Index = 0;
  767. X        getwd(List[0].path_name);
  768. X        ptr = rindex(top, '/');
  769. X
  770. X        if (!ptr || *++ptr == '\0')
  771. X            strncpy(List[Index].e_name, top, MAXNAMLEN);
  772. X        else
  773. X            strncpy(List[Index].e_name, ptr, MAXNAMLEN);
  774. X
  775. X        if(stat(top, &Status) == FAIL) {
  776. X            fprintf(stderr, "xdtree: Cannot stat directory ");
  777. X            perror(top);
  778. X            continue;
  779. X        }
  780. X        Device = Status.st_dev;
  781. X        List[0].dir = 1;
  782. X        List[0].last = 1;
  783. X        List[0].next = 1;
  784. #ifdef    STATS
  785. X        List[0].e_mode = Status.st_mode;
  786. X        List[0].e_uid = Status.st_uid;
  787. X        List[0].e_gid = Status.st_gid;
  788. X        List[0].e_size = Status.st_size;
  789. #endif    /* STATS */
  790. X        Index = 1;
  791. X        for (i = 1; i < DEPTH; i++)
  792. X            Maxes[i] = 0;
  793. X        Maxes[0] = stln(List[0].e_name);
  794. X        Level = 1;
  795. X
  796. X        /* Don't waste time if there is no display */
  797. X        if(flagX == 1)
  798. X        toplevel = XtInitialize(argv[0], "XDtree", NULL, 0, &argc, argv);
  799. X
  800. X        fprintf(stderr,"Started searching....Please wait \n");
  801. X        /* search the tree */
  802. X        List[0].end = t_search(top, &List[0]);
  803. X
  804. X        if (Index == 1)                /* empty tree */
  805. X            List[0].next = 0;
  806. X
  807. X        if (Header) {
  808. X        if (All)
  809. X            printf("\nDirectory structure and contents of %s\n", top);
  810. X        else
  811. X            printf("\nDirectory structure of %s\n", top);
  812. X        if (Point)
  813. X            printf("(excluding entries that begin with '.')\n");
  814. X        }
  815. X
  816. X        if(flagX == 0) pt_tree();
  817. X        else {
  818. X
  819. X    /* Create a Form, with button options and a Frame window
  820. X       Put on the Frame, a ScrolledWindow and the Tree window
  821. X       The Top has a quit button and the directory Name
  822. X    */
  823. X            fprintf(stderr,"Opening display now...Please wait\n");
  824. X
  825. X            /* main window */
  826. X            n=0;
  827. X            main_w = XtCreateManagedWidget(NULL, xmFormWidgetClass,
  828. X                           toplevel, wargs, n);
  829. X
  830. X             n=0;
  831. X                       XtSetArg(arg[n], XmNleftAttachment, XmATTACH_FORM); n++;
  832. X               XtSetArg(arg[n], XmNtopAttachment, XmATTACH_FORM); n++;
  833. X               XtSetArg(arg[n], XmNrightAttachment, XmATTACH_FORM); n++;
  834. X             menu_bar = XmCreateMenuBar(main_w,"menu",arg,n); 
  835. X             XtManageChild(menu_bar);
  836. X
  837. X
  838. X            /* quit button */
  839. X
  840. X            quit_menu = XmCreatePulldownMenu(menu_bar,
  841. X                    "quit_menu",NULL,0);
  842. X            XtSetArg(wargs[0], XmNsubMenuId,quit_menu);
  843. X            q_button = XmCreateCascadeButton(menu_bar, 
  844. X                           "quit",wargs,1);
  845. X            XtManageChild(q_button);
  846. X
  847. X               w_button =XtCreateManagedWidget("warning",
  848. X                xmLabelWidgetClass,quit_menu, NULL,0);
  849. X        w_print(w_button,"Don't exit unless all children are dead\n");
  850. X               exit_b = XtCreateManagedWidget("Exit", 
  851. X                  xmPushButtonWidgetClass, quit_menu, NULL, 0);
  852. X               XtAddCallback(exit_b, XmNarmCallback, 
  853. X                arm_callback, &really_quit);
  854. X               XtAddCallback(exit_b, XmNdisarmCallback, 
  855. X                disarm_callback, &really_quit);
  856. X               XtAddCallback(exit_b, XmNactivateCallback, 
  857. X                activate_callback, &really_quit);     
  858. X
  859. X            /* Create the options buttons */
  860. X            file_pointer = &List[0];
  861. X            show_menu(main_w,file_pointer,menu_bar); 
  862. X
  863. X                       title = XtCreateManagedWidget("title",
  864. X               xmCascadeButtonWidgetClass, menu_bar, NULL,0);
  865. X               XtSetArg(wargs[0],XmNmenuHelpWidget, title);
  866. X               XtSetValues(menu_bar, wargs, 1);
  867. X                       w_print(title,top);
  868. X
  869. X            /* frame */
  870. X            n=0;
  871. X            XtSetArg(arg[n], XmNshadowType, XmSHADOW_OUT); n++;
  872. X            XtSetArg(arg[n], XmNtopWidget, submenu_file); n++;
  873. X        XtSetArg(arg[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
  874. X        XtSetArg(arg[n], XmNrightAttachment, XmATTACH_FORM); n++;
  875. X        XtSetArg(arg[n], XmNleftAttachment, XmATTACH_FORM); n++;
  876. X        XtSetArg(arg[n], XmNbottomAttachment, XmATTACH_FORM); n++;
  877. X            frame = XmCreateFrame(main_w,"frame",arg,n);
  878. X            XtManageChild(frame);
  879. X
  880. X            XtSetArg(wargs[0], XmNscrollingPolicy, XmAUTOMATIC);
  881. X            sw = XtCreateManagedWidget("swindow",
  882. X                xmScrolledWindowWidgetClass, frame, wargs, 1);
  883. X
  884. X
  885. X            /* Tree widget */
  886. X            tree = XtCreateManagedWidget("tree",XstreeWidgetClass,
  887. X                    sw, NULL,0);
  888. X            show_dtree(tree);
  889. X            clickB(options,file_pointer,NULL);
  890. X            XtRealizeWidget(toplevel);
  891. X            XtMainLoop();
  892. X        }
  893. X        
  894. X    }
  895. X    exit(0) ;
  896. }
  897. X
  898. X
  899. t_search(dir, addrs)
  900. char *dir;
  901. struct    entry *addrs;
  902. {
  903. X    int    bsort;            /* index to begin sort */
  904. X    int    stmp;            /* save temporary index value */
  905. X    struct entry *sstep;        /* saved step in list */
  906. X    int    nitems;            /* # of items in this directory */
  907. #ifdef    NEWDIR
  908. X    DIR    *dirp;            /* pointer to directory */
  909. #else
  910. X    FILE    *dirp;
  911. #endif
  912. X    char    sub[MAXNAMLEN+1];    /* used for subdirectory names */
  913. X    int    i;
  914. #ifdef    NEWDIR
  915. X    struct direct *dp;
  916. #else
  917. X    struct direct dirent;
  918. X    struct direct *dp = &dirent;
  919. #endif    /* NEWDIR */
  920. X    int    n_subs = 0;
  921. X    int    tmp = 0;
  922. X
  923. #ifdef    NEWDIR
  924. X    dirp = opendir(".");
  925. #else
  926. X    dirp = fopen(".", "r");
  927. #endif    /* NEWDIR */
  928. X    if (dirp == NULL) {
  929. X        fprintf(stderr, "xdtree: Cannot open directory ");
  930. X        perror(dir);
  931. X        return(0);
  932. X    }
  933. #ifndef    NEWDIR
  934. X    setbuf(dirp, Buf2);
  935. #endif    /* NEWDIR */
  936. X
  937. X    bsort = Index;
  938. X    sstep = &List[bsort]; /* initialize sstep for for loop later on */
  939. X    nitems = Index;
  940. X    /* get the entries of the directory that we are interested in */
  941. #ifndef    NEWDIR
  942. X    while (fread((char *)(dp), sizeof(struct direct), 1, dirp) == 1) {
  943. #else
  944. X    while ((dp = readdir(dirp)) != NULL) {
  945. #endif    /* NEWDIR */
  946. X
  947. X        if (dp->d_ino
  948. #ifdef unos
  949. X            == -1
  950. #else
  951. X            == 0
  952. #endif /* unos */
  953. X            || (strcmp(dp->d_name, ".") == SAME)
  954. X            || (strcmp(dp->d_name, "..") == SAME)
  955. X            || (Point && dp->d_name[0] == '.'))
  956. X                continue;
  957. X
  958. X        strncpy(sub, dp->d_name, MAXNAMLEN);
  959. #ifdef S_IFLNK
  960. X        if (lstat(sub,&Lstat) == FAIL) {
  961. X            fprintf(stderr, "xdtree: In directory %s, cannot lstat entry ", dir);
  962. X            perror(sub);
  963. X            continue;
  964. X                }
  965. #endif /* S_IFLNK */
  966. X        if (stat(sub, &Status) == FAIL) {
  967. X            fprintf(stderr, "xdtree: In directory %s, cannot stat entry ", dir);
  968. X            perror(sub);
  969. X            continue;
  970. X        }
  971. #ifdef S_IFLNK
  972. X        if (((Lstat.st_mode & S_IFMT) == S_IFLNK)  &&
  973. X            ((Status.st_mode & S_IFMT) == S_IFDIR)) 
  974. X                List[Index].dir = 0;    
  975. X        else if ((((Lstat.st_mode & S_IFMT) == S_IFLNK) &&
  976. X            ((Status.st_mode & S_IFMT) != S_IFDIR)) && (All)) 
  977. X                        List[Index].dir = 0;
  978. #endif /* S_IFLNK */
  979. X        else if ((Status.st_mode & S_IFMT) == S_IFDIR)
  980. X            List[Index].dir = 1;
  981. X        else if (All)
  982. X            List[Index].dir = 0;
  983. X        else
  984. X            continue;
  985. X        strncpy(List[Index].e_name, dp->d_name, MAXNAMLEN);
  986. X        getwd(List[Index].path_name);
  987. X        List[Index].last = 0;
  988. X        List[Index].end = 0;
  989. #ifdef S_IFLNK
  990. X        if ((Lstat.st_mode & S_IFMT) == S_IFLNK) {
  991. X             List[Index].dev = (Device == Lstat.st_dev);
  992. X             List[Index].e_mode = Lstat.st_mode;
  993. X             List[Index].e_uid = Lstat.st_uid;
  994. X             List[Index].e_gid = Lstat.st_gid;
  995. X             List[Index].e_size = Lstat.st_size;
  996. X                }
  997. X                else {
  998. #endif /* S_IFLNK */
  999. X             List[Index].dev = (Device == Status.st_dev);
  1000. #ifdef STATS
  1001. X             List[Index].e_mode = Status.st_mode;
  1002. X             List[Index].e_uid = Status.st_uid;
  1003. X             List[Index].e_gid = Status.st_gid;
  1004. X             List[Index].e_size = Status.st_size;
  1005. #endif /* STATS */
  1006. #ifdef S_IFLNK
  1007. X                }
  1008. #endif /* S_IFLNK */
  1009. X        if (stln(List[Index].e_name) > Maxes[Level])
  1010. X            Maxes[Level] = stln(List[Index].e_name);
  1011. X        ++Index;
  1012. X        if (Index*sizeof(struct entry) >= Size) {
  1013. X            Size += 20*sizeof(struct entry);
  1014. X            List = (struct entry *)xrealloc((char *)List, Size);
  1015. X        }
  1016. X    }
  1017. #ifdef    NEWDIR
  1018. X    closedir(dirp);
  1019. #else
  1020. X    fclose(dirp);
  1021. #endif    /* NEWDIR */
  1022. X
  1023. X    nitems = Index - nitems;    /* nitems now contains the # of */
  1024. X                    /* items in this dir, rather than */
  1025. X                    /* # total items before this dir */
  1026. X
  1027. X    if (Sort)
  1028. X        qsort(&List[bsort], nitems, sizeof(struct entry), compar);
  1029. X
  1030. X    List[Index-1].last = 1;    /* mark last item for this dir */
  1031. X    n_subs = nitems;
  1032. X    stmp = Index;
  1033. X
  1034. X    /* now walk through, and recurse on directory entries */
  1035. X    /* sstep was initialized above */
  1036. X
  1037. X    for (i = 0; i < nitems; sstep = &List[stmp - nitems+(++i)]) {
  1038. X        if (sstep->dir && (Level < newlevel) && (Xdev || sstep->dev)) {
  1039. X            sstep->next = Index;
  1040. X            strncpy(sub, sstep->e_name, MAXNAMLEN);
  1041. X            tmp = n_subs;
  1042. X            Level++;
  1043. X            if (chdir(sub) == FAIL) {
  1044. X                fprintf(stderr,
  1045. X                    "xdtree: Cannot change to directory %s/", dir);
  1046. X                perror(sub);
  1047. X            } else {
  1048. X                n_subs += t_search(sub, sstep);
  1049. X                if (chdir("..") == FAIL) {
  1050. X                    fprintf(stderr,
  1051. X                        "xdtree: %s/%s lacks '..' entry\n",dir, sub);
  1052. X                    exit(1);
  1053. X                }
  1054. X            }
  1055. X            --Level;
  1056. X            if (n_subs - tmp <= 0)
  1057. X                sstep->next = 0;
  1058. X            else
  1059. X                --n_subs;
  1060. X        }
  1061. X        else
  1062. X            sstep->next = 0;
  1063. X    }
  1064. X    addrs->end = (unsigned)n_subs;
  1065. X    return(n_subs);
  1066. }
  1067. X
  1068. /*
  1069. X *    comparison routine for qsort
  1070. X */
  1071. X
  1072. compar(a, b)
  1073. struct entry *a, *b;
  1074. {
  1075. X    if (!File_dir)        /* straight alphabetical */
  1076. X        return(strncmp(a->e_name, b->e_name, MAXNAMLEN));
  1077. X
  1078. X    /* sort alphabetically if both dirs or both not dirs */
  1079. X
  1080. X    if ((a->dir && b->dir) || (!a->dir && !b->dir))
  1081. X        return(strncmp(a->e_name, b->e_name, MAXNAMLEN));
  1082. X
  1083. X    if (File_dir == FFIRST) {    /* sort by files first */
  1084. X        if (a->dir)
  1085. X            return(GREATER);
  1086. X        else
  1087. X            return(LESSTHAN);
  1088. X    }
  1089. X
  1090. X    if (a->dir)            /* sort by dir first */
  1091. X        return(LESSTHAN);
  1092. X    else
  1093. X        return(GREATER);
  1094. }
  1095. X
  1096. X
  1097. pt_tree()
  1098. {
  1099. X    register int    i,j;
  1100. X    struct entry *l;
  1101. X    struct entry *hdr[DEPTH];
  1102. X    int posit[DEPTH];        /* array of positions to print dirs */
  1103. X    int con[DEPTH];            /* flags for connecting up tree */
  1104. X    char    flag = 0;        /* flag to leave blank line after dir */
  1105. X    struct    entry *stack[DEPTH];    /* save positions for changing levels */
  1106. X    int    top = 0;        /* index to top of stack */
  1107. X    int    count = 1;        /* count of line of output */
  1108. X
  1109. X    Level = 0;            /* initialize Level */
  1110. X
  1111. X    /* this loop appends each entry with dashes or spaces, for */
  1112. X    /* directories or files respectively */
  1113. X
  1114. X    for (i = 0; i < Index; i++) {
  1115. X        for (j = 0; j < MAXNAMLEN; j++) {
  1116. X            if (!List[i].e_name[j])
  1117. X                break;
  1118. X        }
  1119. X        if (List[i].dir) {
  1120. X            for (; j < MAXNAMLEN; j++)
  1121. X                List[i].e_name[j] = '-';
  1122. X        } else {
  1123. X            for (; j < MAXNAMLEN; j++)
  1124. X                List[i].e_name[j] = ' ';
  1125. X        }
  1126. X    }
  1127. X
  1128. X    /* adjust the Maxes array according to the flags */
  1129. X
  1130. X    for (i = 0; i < DEPTH; i++) {
  1131. X        if (Varspaces) {
  1132. X            if (Maxes[i] > CLength )
  1133. X                Maxes[i] = CLength;
  1134. X        } else
  1135. X            Maxes[i] = CLength;
  1136. X    }
  1137. X
  1138. X    /* clear the connective and position flags */
  1139. X
  1140. X    for (i = 0; i < DEPTH; i++)
  1141. X        con[i] = posit[i] = 0;
  1142. X
  1143. X    /* this is the main loop to print the tree structure. */
  1144. X    l = &List[0];
  1145. X    j = 0;
  1146. X    for (;;) {
  1147. X        /* directory entry, save it for later printing */
  1148. X        if (l->dir != 0 && l->next != 0) {
  1149. X            hdr[Level] = l;
  1150. X            posit[Level] = count + (l->end + 1)/2 - 1;
  1151. X            flag = 1;
  1152. X            stack[top++] = l;
  1153. X            l = &List[l->next];
  1154. X            ++Level;
  1155. X            continue;
  1156. X        }
  1157. X
  1158. #ifdef    STATS
  1159. X    do_it_again:
  1160. #endif    /* STATS */
  1161. X        /* print columns up to our entry */
  1162. X        for (j = 0; j < (flag ? Level-1 : Level); j++) {
  1163. X            if (!flag && posit[j] && posit[j] <= count) {
  1164. X                /* time to print it */
  1165. X                if (hdr[j]->e_name[CLength-1] != '-')
  1166. X                    hdr[j]->e_name[CLength-1] = '*';
  1167. X                printf("|-%.*s",Maxes[j],hdr[j]->e_name);
  1168. X                posit[j] = 0;
  1169. X                if (hdr[j]->last != 0)
  1170. X                    con[j] = 0;
  1171. X                else
  1172. X                    con[j] = 1;
  1173. #ifdef    STATS
  1174. X                if (Gflag || Longflg) {
  1175. X                    if ((i = j+1) <= Level)
  1176. X                    printf("| %.*s", Maxes[i], Spaces);
  1177. X                    for (i++; i <= Level; i++) {
  1178. X                    printf("%c %.*s",
  1179. X                        (con[i] ? '|' : ' '),
  1180. X                        Maxes[i], Spaces);
  1181. X                    }
  1182. X                    if (!Compact) {
  1183. X                    printf("%s ", getmode(hdr[j]->e_mode));
  1184. X                    if (Longflg)
  1185. X                       printf("%8.8s ",guid(hdr[j]->e_uid));
  1186. X                    if (Gflag)
  1187. X                       printf("%8.8s ",ggid(hdr[j]->e_gid));
  1188. X                    printf("%7ld\n",
  1189. X                        (hdr[j]->e_size+511L)/512L);
  1190. X                    } else {
  1191. X                    printf(" %04o ",hdr[j]->e_mode & 07777);
  1192. X                    if (Longflg)
  1193. X                        printf("%5u ", hdr[j]->e_uid);
  1194. X                    if (Gflag)
  1195. X                        printf("%5u ", hdr[j]->e_gid);
  1196. X                    printf("%7ld\n",
  1197. X                        (hdr[j]->e_size+511L)/512L);
  1198. X                    }
  1199. X                    goto do_it_again;
  1200. X                }
  1201. #endif    /* STATS */
  1202. X            } else
  1203. X                printf("%c %.*s", (con[j] ? '|' : ' '),
  1204. X                    Maxes[j], Spaces);
  1205. X        }
  1206. X        if (flag) {    /* start of directory, so leave a blank line */
  1207. X            printf(con[j] ? "|\n" : "\n");
  1208. X            flag = 0;
  1209. X            continue;
  1210. X        } else {
  1211. X                /* normal file name, print it out */
  1212. X            if (l->e_name[CLength-1] != '-' &&
  1213. X                l->e_name[CLength-1] != ' ')
  1214. X                l->e_name[CLength-1] = '*';
  1215. X            printf("|-%.*s",Maxes[Level],l->e_name);
  1216. X            if (l->last) {
  1217. X                con[j] = 0;
  1218. X            } else {
  1219. X                con[j] = 1;
  1220. X            }
  1221. #ifdef    STATS
  1222. X            if (Gflag || Longflg) {
  1223. X                if (Compact) {
  1224. X                    printf(" %04o ", l->e_mode & 07777);
  1225. X                    if (Longflg)
  1226. X                        printf("%5u ", l->e_uid);
  1227. X                    if (Gflag)
  1228. X                        printf("%5u ", l->e_gid);
  1229. X                    printf("%7ld",
  1230. X                        (l->e_size+511L)/512L);
  1231. X                } else {
  1232. X                    printf("%s ", getmode(l->e_mode));
  1233. X                    if (Longflg)
  1234. X                        printf("%8.8s ",guid(l->e_uid));
  1235. X                    if (Gflag)
  1236. X                        printf("%8.8s ",ggid(l->e_gid));
  1237. X                    printf("%7ld",
  1238. X                        (l->e_size+511L)/512L);
  1239. X                }
  1240. X            }
  1241. #endif    /* STATS */
  1242. X        }
  1243. X        printf("\n");
  1244. X
  1245. X        if (l->last) {
  1246. X            /* walk back up */
  1247. X            while (l->last) {
  1248. X                --Level;
  1249. X                if (--top <= 0)
  1250. X                    return;
  1251. X                l = stack[top];
  1252. X            }
  1253. X        }
  1254. X        l = &l[1];
  1255. X        ++count;
  1256. X    }
  1257. }
  1258. X
  1259. #ifdef    STATS
  1260. X
  1261. char *
  1262. guid(uid)
  1263. short uid;
  1264. {
  1265. X    static char tb[10];
  1266. X    struct passwd *pswd;
  1267. X
  1268. X    pswd = getpwuid(uid);
  1269. X    if (pswd == NULL)
  1270. X        sprintf(tb,"%u", uid);
  1271. X    else
  1272. X        sprintf(tb, "%8s", pswd->pw_name);
  1273. X    return(tb);
  1274. }
  1275. X
  1276. char *
  1277. ggid(gid)
  1278. short gid;
  1279. {
  1280. X    static char tb[10];
  1281. X    struct group *grp;
  1282. X
  1283. X    grp = getgrgid(gid);
  1284. X    if (grp == NULL)
  1285. X        sprintf(tb,"%u", gid);
  1286. X    else
  1287. X        sprintf(tb, "%8s", grp->gr_name);
  1288. X    return(tb);
  1289. }
  1290. X
  1291. /* take the mode and make it into a nice character string */
  1292. X
  1293. char    *
  1294. getmode(p_mode)
  1295. unsigned short p_mode;
  1296. {
  1297. X    static char a_mode[16];
  1298. X    register int    i = 0, j = 0;
  1299. X
  1300. X    a_mode[j++] = ' ';
  1301. X
  1302. X    switch (p_mode & S_IFMT) {
  1303. #ifdef S_IFLNK
  1304. X    case S_IFLNK:
  1305. X        a_mode[j++] = 'l';
  1306. X        break;
  1307. #endif /* S_IFLNK */
  1308. X    case S_IFDIR:
  1309. X        a_mode[j++] = 'd';
  1310. X        break;
  1311. #ifdef    S_IFMPC        /* defined in stat.h if you have MPX files */
  1312. X    case S_IFMPC:
  1313. X        a_mode[j-1] = 'm';
  1314. X        /* FALL THROUGH */
  1315. #endif    /* S_IFMPC */
  1316. X    case S_IFCHR:
  1317. X        a_mode[j++] = 'c';
  1318. X        break;
  1319. #ifdef    S_IFMPB        /* defined in stat.h if you have MPX files */
  1320. X    case S_IFMPB:
  1321. X        a_mode[j-1] = 'm';
  1322. X        /* FALL THROUGH */
  1323. #endif    /* S_IFMPB */
  1324. X    case S_IFBLK:
  1325. X        a_mode[j++] = 'b';
  1326. X        break;
  1327. X    case S_IFREG:
  1328. X    default:
  1329. X        a_mode[j++] = (p_mode & S_ISVTX) ? 't' : ' ';
  1330. X        break;
  1331. X    }
  1332. X    a_mode[j++] = ' ';
  1333. X    for( i = 0;i<3;i++ ) {
  1334. X        a_mode[j++] = (p_mode<<(3*i) & S_IREAD) ? 'r' : '-';
  1335. X        a_mode[j++] = (p_mode<<(3*i) & S_IWRITE) ? 'w' : '-';
  1336. X        a_mode[j++] = (i<2 && (p_mode<<i & S_ISUID)) ? 's' :
  1337. X                  ((p_mode<<(3*i) & S_IEXEC ) ? 'x' : '-');
  1338. X        a_mode[j++] = ' ';
  1339. X    }
  1340. X    a_mode[j] = '\0';
  1341. X    return(a_mode);
  1342. }
  1343. #endif
  1344. X
  1345. /* like strlen, but returns length up to MAXNAMLEN-1 */
  1346. stln(st)
  1347. register char *st;
  1348. {
  1349. X    register int t;
  1350. X
  1351. X    for (t=0; t<MAXNAMLEN-1; ++t)
  1352. X        if (!st[t])
  1353. X            return (++t);
  1354. X    return (++t);
  1355. }
  1356. X
  1357. print_date()
  1358. {
  1359. X    long now;
  1360. X
  1361. X    time(&now);
  1362. X    printf ("%s", ctime(&now));
  1363. }
  1364. X
  1365. void
  1366. memory_out()
  1367. {
  1368. X    fprintf(stderr, "xdtree: Virtual memory exhausted\n");
  1369. X    exit(1);
  1370. }
  1371. X
  1372. /* Allocate `size' bytes of memory dynamically, with error checking.  */
  1373. X
  1374. char *
  1375. xmalloc (size)
  1376. unsigned size;
  1377. {
  1378. X    char *ptr;
  1379. X
  1380. X    ptr = malloc (size);
  1381. X    if (ptr == 0 && size != 0)
  1382. X        memory_out ();
  1383. X    return ptr;
  1384. }
  1385. X
  1386. /* Change the size of an allocated block of memory `ptr' to `size' bytes,
  1387. X   with error checking.
  1388. X   If `ptr' is NULL, run xmalloc.
  1389. X   If `size' is 0, run free and return NULL.  */
  1390. X
  1391. char *
  1392. xrealloc (ptr, size)
  1393. char *ptr;
  1394. unsigned size;
  1395. {
  1396. X    if (ptr == 0)
  1397. X        return xmalloc (size);
  1398. X    if (size == 0) {
  1399. X        free (ptr);
  1400. X        return 0;
  1401. X    }
  1402. X    ptr = realloc (ptr, size);
  1403. X    if (ptr == 0 && size != 0)
  1404. X        memory_out ();
  1405. X    return ptr;
  1406. }
  1407. /*-------------------------New functions for X windows -----------------*/
  1408. X
  1409. /* Main program to display the tree in an X window */
  1410. X
  1411. show_dtree(parent)
  1412. X    Widget parent;
  1413. X
  1414. {
  1415. X    Arg wargs[4];
  1416. X    struct entry *stack[DEPTH], *branch;
  1417. X    int n, top=0, *dir_index;
  1418. X    int dir_node=0, dir_count=0, i;
  1419. X    Widget parent_node=NULL, *Dir, arc;
  1420. X    XmString label_s = NULL;    
  1421. X
  1422. X    /* Find the number of directories */
  1423. X    for(i=0; i < Index; i++)
  1424. X        if(List[i].dir == 1) dir_count++;
  1425. X
  1426. X    if((Dir = (Widget *) malloc( dir_count * sizeof(Widget))) == NULL){
  1427. X        fprintf(stderr,"malloc failure\n");
  1428. X            exit(1);
  1429. X    }
  1430. X    if((dir_index = (int *) malloc(dir_count * sizeof(int))) == NULL) {
  1431. X        fprintf(stderr,"malloc failure\n");
  1432. X        exit(1) ;
  1433. X    }
  1434. X
  1435. X    branch = &List[0];
  1436. X
  1437. X    if(dir_count == 1 && branch->next == 0) {
  1438. X        if(All == 0) {
  1439. X        fprintf(stderr,"No subdirectories under directory %s\n",
  1440. X             branch->e_name);
  1441. X        fprintf(stderr,"You may want to try the -ap option\n");
  1442. X        }
  1443. X        else fprintf(stderr,"No files under directory %s\n", 
  1444. X             branch->e_name);
  1445. X        exit(0);
  1446. X    }
  1447. X
  1448. X    /* Distinguish between directories and files */
  1449. X
  1450. X    for(;;)  {
  1451. X        if(branch->dir != 0 && branch->next != 0) {
  1452. X            dir_index[top] = dir_node;
  1453. X            stack[top++] = branch;
  1454. X            n=0;
  1455. X            XtSetArg(wargs[n], XtNsuperNode,parent_node); n++;
  1456. X            label_s = XmStringCreateLtoR(branch->e_name,
  1457. X                                  XmSTRING_DEFAULT_CHARSET);
  1458. X            XtSetArg(wargs[n], XmNlabelString,label_s); n++;
  1459. X            Dir[dir_node] = XmCreatePushButton(parent,"dir",
  1460. X                                    wargs,n);
  1461. X            XtManageChild(Dir[dir_node]);
  1462. X            XtAddCallback(Dir[dir_node],XmNactivateCallback,
  1463. X                   clickB, branch);
  1464. X
  1465. X            branch = &List[branch->next];
  1466. X            parent_node = Dir[dir_node++];
  1467. X            continue;
  1468. X        }
  1469. X        create_file_node(parent,branch,parent_node);
  1470. X        if(branch->last) {
  1471. X            while(branch->last) {
  1472. X                if(--top <= 0 ) {
  1473. X                    free(Dir);
  1474. X                    free(dir_index);
  1475. X                    return;
  1476. X                    }
  1477. X                branch = stack[top];
  1478. X                parent_node = Dir[dir_index[top-1]];
  1479. X                }
  1480. X            }
  1481. X        branch = &branch[1];
  1482. X    }
  1483. }
  1484. /* Function that creates a widget for a node. Three types are available,
  1485. X   dir, for directories , file, for files, and sym_link for
  1486. X   symbolic links
  1487. */
  1488. create_file_node(pparent,bbranch,nnode)
  1489. X    Widget pparent, nnode;
  1490. X    struct entry *bbranch;
  1491. {
  1492. X    Widget w, arc;
  1493. X    Arg wargs[4];
  1494. X    int n;
  1495. X    char *win_type;
  1496. X    XmString label_s = NULL;    
  1497. X    int Gflag=1;        /* this is a gadget */
  1498. X
  1499. X
  1500. X    n=0;
  1501. X    label_s = XmStringCreateLtoR(bbranch->e_name,
  1502. X                          XmSTRING_DEFAULT_CHARSET);
  1503. X    XtSetArg(wargs[n], XmNlabelString,label_s); n++;
  1504. X
  1505. X    /* Check the type of the node */
  1506. X    if(bbranch->dir == 1) { 
  1507. X        win_type = "dir";
  1508. X        Gflag = 0;
  1509. X    }
  1510. #ifdef STATS
  1511. X    else if(strncmp(" l",getmode(bbranch->e_mode),2) == 0)
  1512. X            {win_type = "sym_link"; Gflag = 0;}
  1513. #endif /* STATS */
  1514. X    else win_type = "file";
  1515. X        XtSetArg(wargs[n], XtNsuperNode, nnode); n++; 
  1516. X    w = XmCreatePushButton(pparent, win_type, wargs, n);
  1517. X    XtManageChild(w);
  1518. X    XtAddCallback(w,XmNactivateCallback,clickB,bbranch);
  1519. X
  1520. }
  1521. /* Function that creates the pull-down menu when someone clicks on the 
  1522. X  active node of the tree.  
  1523. */
  1524. X
  1525. show_menu(pparent, bbranch, top_widget)
  1526. X    Widget pparent,top_widget;
  1527. X    struct entry *bbranch;
  1528. {
  1529. X    Widget menu ;
  1530. X    Widget submenu_mode,submenu_print;
  1531. X    Widget print, S_toggle,plabel,H_toggle,g_toggle;
  1532. X    int i,n;
  1533. X    char *mode_name;
  1534. X    Arg  wargs[4];
  1535. X    Arg  arg[15];
  1536. X
  1537. X    n=0;
  1538. X     XtSetArg(arg[n], XmNleftAttachment, XmATTACH_FORM); n++;
  1539. X     XtSetArg(arg[n], XmNtopWidget, top_widget); n++;
  1540. X    XtSetArg(arg[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
  1541. X    submenu_mode = XtCreateManagedWidget("menu_file", 
  1542. X                         xmRowColumnWidgetClass, pparent, arg,n);
  1543. X
  1544. X        n=0;
  1545. X    XtSetArg(arg[n], XmNleftWidget, submenu_mode); n++;
  1546. X    XtSetArg(arg[n], XmNleftAttachment, XmATTACH_WIDGET); n++;
  1547. X     XtSetArg(arg[n], XmNtopWidget, top_widget); n++;
  1548. X    XtSetArg(arg[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
  1549. X    submenu_file = XtCreateManagedWidget("menu_mode",
  1550. X                            xmRowColumnWidgetClass, pparent, arg,n);
  1551. X
  1552. X        n=0;
  1553. X    XtSetArg(arg[n], XmNleftWidget, submenu_file); n++;
  1554. X    XtSetArg(arg[n], XmNleftAttachment, XmATTACH_WIDGET); n++;
  1555. X     XtSetArg(arg[n], XmNtopWidget, top_widget); n++;
  1556. X    XtSetArg(arg[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
  1557. X    submenu_dir = XtCreateManagedWidget("menu_dir",
  1558. X                            xmRowColumnWidgetClass, pparent, arg,n);
  1559. X
  1560. X        n=0;
  1561. X    XtSetArg(arg[n], XmNleftWidget, submenu_dir); n++;
  1562. X    XtSetArg(arg[n], XmNleftAttachment, XmATTACH_WIDGET); n++;
  1563. X     XtSetArg(arg[n], XmNtopWidget, top_widget); n++;
  1564. X    XtSetArg(arg[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
  1565. X    submenu_print = XtCreateManagedWidget("printer",
  1566. X                            xmRowColumnWidgetClass, pparent, arg,n);
  1567. X
  1568. X    options = XtCreateManagedWidget("options",xmLabelWidgetClass,
  1569. X           submenu_mode, wargs, 1);
  1570. X    w_print(options, bbranch->e_name);
  1571. X
  1572. X    plabel = XtCreateManagedWidget("plabel",xmLabelWidgetClass,
  1573. X           submenu_print, wargs, 1);
  1574. X    w_print(plabel, "Print-Tree Options");
  1575. X    /*
  1576. X    boxes[0] = XtCreateManagedWidget("title",xmLabelWidgetClass, 
  1577. X           submenu_mode, NULL,0);
  1578. X        */
  1579. X    XtCreateManagedWidget("separator2",xmSeparatorWidgetClass, 
  1580. X           submenu_mode, NULL,0);
  1581. X    /*
  1582. X    XtCreateManagedWidget("separator",xmSeparatorWidgetClass, 
  1583. X           submenu_print, NULL,0);
  1584. X        */
  1585. #ifdef STATS
  1586. X    for(i = 1; i < 4 ; i++)
  1587. X    boxes[i] =  XtCreateManagedWidget("id",xmLabelWidgetClass,
  1588. X           submenu_mode, NULL,0);
  1589. X    boxes[11] = XtCreateManagedWidget("id",xmLabelWidgetClass,
  1590. X               submenu_mode, NULL,0);
  1591. X    button_print(bbranch); /* print the labels on the menu */
  1592. X        
  1593. X    
  1594. X
  1595. X    /* Create sub-menus */
  1596. X
  1597. #endif /*STATS */
  1598. X
  1599. X    file_menu = XtCreateManagedWidget("File Options",
  1600. X        xmLabelWidgetClass, submenu_file, NULL,0);
  1601. X    dir_menu  = XtCreateManagedWidget("Directory Options",
  1602. X        xmLabelWidgetClass, submenu_dir, NULL,0);
  1603. X
  1604. X    /* If it is a file */
  1605. X    /*submenu_file = XtCreateManagedWidget(menu, "filesubmenu", NULL, 0);*/
  1606. X
  1607. X    boxes[4] = XtCreateManagedWidget("view",xmPushButtonWidgetClass,
  1608. X                           submenu_file, NULL,0);
  1609. X        XtAddCallback(boxes[4], XmNactivateCallback,view, NULL);
  1610. X        boxes[5] = XtCreateManagedWidget("topview",
  1611. X            xmPushButtonWidgetClass, submenu_file, NULL,0);
  1612. X        XtAddCallback(boxes[5], XmNactivateCallback,view, NULL);
  1613. X        boxes[6] = XtCreateManagedWidget("edit",
  1614. X            xmPushButtonWidgetClass, submenu_file, NULL,0);
  1615. X        XtAddCallback(boxes[6], XmNactivateCallback,do_menu, NULL);
  1616. X        boxes[7] = XtCreateManagedWidget("print",
  1617. X            xmPushButtonWidgetClass, submenu_file, NULL,0);
  1618. X        XtAddCallback(boxes[7], XmNactivateCallback,do_menu, NULL);
  1619. X
  1620. X    /* if it a directory */
  1621. X        boxes[8] = XtCreateManagedWidget("show subtree",
  1622. X            xmPushButtonWidgetClass, submenu_dir, NULL,0);
  1623. X        XtAddCallback(boxes[8], XmNactivateCallback,do_menu, NULL);
  1624. X        boxes[9] = XtCreateManagedWidget("list files",
  1625. X            xmPushButtonWidgetClass, submenu_dir, NULL,0);
  1626. X        XtAddCallback(boxes[9], XmNactivateCallback,do_menu, NULL);
  1627. X        boxes[10] = XtCreateManagedWidget("list ../",
  1628. X            xmPushButtonWidgetClass, submenu_dir, NULL,0);
  1629. X        XtAddCallback(boxes[10], XmNactivateCallback,do_menu, NULL);
  1630. X
  1631. X        /* print command */
  1632. X        print = XtCreateManagedWidget("print tree",
  1633. X                     xmPushButtonWidgetClass, submenu_print, NULL,0);
  1634. X        XtAddCallback(print, XmNactivateCallback,print_tree, NULL);
  1635. X
  1636. X        S_toggle = XtCreateManagedWidget("Print Stats. (-S)",
  1637. X                     xmToggleButtonWidgetClass, submenu_print, NULL,0);
  1638. X        XtAddCallback(S_toggle, XmNvalueChangedCallback,stoggle, NULL);
  1639. X
  1640. X        H_toggle = XtCreateManagedWidget("Print Header (-H)",
  1641. X                     xmToggleButtonWidgetClass, submenu_print, NULL,0);
  1642. X        XtAddCallback(H_toggle, XmNvalueChangedCallback,htoggle, NULL);
  1643. X
  1644. X        g_toggle = XtCreateManagedWidget("Use Group Name (-g)",
  1645. X                     xmToggleButtonWidgetClass, submenu_print, NULL,0);
  1646. X        XtAddCallback(g_toggle, XmNvalueChangedCallback,gtoggle, NULL);
  1647. }
  1648. /* Not used here, but may be useful in the future !!! */
  1649. /* Copied from D. Young's book */
  1650. /*
  1651. void post_menu_handler(w, menu, event)
  1652. X    Widget w, menu;
  1653. X    XEvent *event;
  1654. {
  1655. X    Arg wargs[10];
  1656. X    int button;
  1657. X
  1658. X     XtSetArg(wargs[0], XmNwhichButton, &button); 
  1659. X    XtGetValues(menu, wargs, 1);
  1660. X        if(event->xbutton.button == button) {
  1661. X        XmMenuPosition(menu, event);
  1662. X        XtManageChild(menu);
  1663. X        }
  1664. }
  1665. */
  1666. /* Quick and dirty way to view a file in a pop-up window 
  1667. X   Speed may improve, if one reads and displays page by page
  1668. X   No check to see if the file is binary
  1669. */
  1670. void view(w, call_mydata, call_data)
  1671. X    Widget w;
  1672. X    caddr_t call_data, call_mydata;
  1673. X
  1674. {
  1675. X    struct entry *branch;
  1676. X    char *filename[MAXPATHLEN+1];  
  1677. X        struct stat statbuf;         /* Information on a file. */
  1678. X        int file_length;             /* Length of file.        */
  1679. X        unsigned char * file_string; /* Contents of file.      */
  1680. X    FILE *fp = NULL;
  1681. X    Widget text, toplevel2, sw2, button, frame, outer;
  1682. X    Widget title;
  1683. X    XmString name_string = NULL;
  1684. X    char *button_name = NULL;
  1685. X    int topflag=0;
  1686. X    Arg    wargs[10];
  1687. X    Arg     arg[10];
  1688. X    int n=0;
  1689. X
  1690. X    branch = file_pointer;
  1691. X    /* find which button called us */
  1692. X    XtSetArg(wargs[0], XmNlabelString, &name_string);
  1693. X    XtGetValues(w,wargs,1);
  1694. X    XmStringGetLtoR(name_string,XmSTRING_DEFAULT_CHARSET,&button_name);
  1695. X    if(strcmp("topview",button_name) == 0) topflag = 1;
  1696. X
  1697. X    /* find first the correct path */
  1698. X
  1699. X    strncpy(filename,branch->path_name,MAXPATHLEN);
  1700. X    strcat(filename,"/");
  1701. X    strcat(filename,branch->e_name);
  1702. X    
  1703. X
  1704. X    if ((fp = fopen(filename, "r")) == NULL) {
  1705. X        fprintf(stderr,"Can't open file name %s\n",filename);
  1706. X        return;
  1707. X    }
  1708. X     if (stat(filename, &statbuf) == 0)
  1709. X           file_length = statbuf.st_size;
  1710. X         else
  1711. X              file_length = 1000000; /* arbitrary file length */
  1712. X
  1713. X     /* read the file string */
  1714. X
  1715. X     if(topflag == 1 && file_length >= 2000 ) file_length = 2000;
  1716. X
  1717. X     file_string = (unsigned char *) XtMalloc((unsigned)file_length);
  1718. X         fread(file_string, sizeof(char), file_length, fp);
  1719. X
  1720. X     if (fclose(fp) != NULL) fprintf(stderr, "Warning: unable to close file.\n");
  1721. X
  1722. X    /* Create another pop-pup top-shell with a MainWindow */
  1723. X
  1724. X    toplevel2 = XtCreateApplicationShell("Dtreef",topLevelShellWidgetClass,
  1725. X             NULL,0);
  1726. X
  1727. X    n=0;
  1728. X    outer = XtCreateManagedWidget(NULL, xmFormWidgetClass,
  1729. X               toplevel2, wargs, n);
  1730. X
  1731. X    n=0;
  1732. X    XtSetArg(arg[n], XmNleftAttachment, XmATTACH_FORM); n++;
  1733. X    XtSetArg(arg[n], XmNtopAttachment, XmATTACH_FORM); n++;
  1734. X    XtSetArg(arg[n], XmNlabelString, XmStringCreate("Quit",
  1735. X                      XmSTRING_DEFAULT_CHARSET)); n++;
  1736. X    button = XtCreateManagedWidget("button", xmPushButtonWidgetClass,
  1737. X                                    outer, arg, n);
  1738. X
  1739. X    XtAddCallback(button,XmNactivateCallback,quit_b_pop,toplevel2);
  1740. X
  1741. X       n=0;
  1742. X       XtSetArg(arg[n], XmNrightAttachment, XmATTACH_FORM); n++;
  1743. X       XtSetArg(arg[n], XmNtopAttachment, XmATTACH_FORM); n++;
  1744. X       XtSetArg(arg[n], XmNlabelString, XmStringCreate(filename, 
  1745. X                   XmSTRING_DEFAULT_CHARSET)); n++;
  1746. X      title = XtCreateManagedWidget("title",
  1747. X                             xmLabelWidgetClass, outer, arg,n);
  1748. X
  1749. X    n=0;
  1750. X    XtSetArg(arg[n], XmNtopWidget, button); n++;
  1751. X    XtSetArg(arg[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
  1752. X        XtSetArg(arg[n], XmNleftAttachment, XmATTACH_FORM); n++;
  1753. X    XtSetArg(arg[n], XmNrightAttachment, XmATTACH_FORM); n++;
  1754. X    XtSetArg(arg[n], XmNshadowType, XmSHADOW_OUT); n++;
  1755. X    XtSetArg(arg[n], XmNbottomAttachment, XmATTACH_FORM); n++;
  1756. X    frame = XtCreateManagedWidget("frame", xmFrameWidgetClass, 
  1757. X                   outer, arg,n);
  1758. X
  1759. X    n=0;
  1760. X    XtSetArg(wargs[n], XmNscrollingPolicy, XmAUTOMATIC); n++;
  1761. X    sw2 = XtCreateManagedWidget("swindowf",
  1762. X        xmScrolledWindowWidgetClass,frame, wargs,n);
  1763. X
  1764. X
  1765. X    /* Create Text widget */
  1766. X    n=0;
  1767. X    XtSetArg (wargs[n], XmNcolumns, 85); n++;
  1768. X        XtSetArg (wargs[n], XmNeditable, FALSE); n++; 
  1769. X
  1770. X    text = XmCreateText(sw2, "text", wargs, n);
  1771. X
  1772. X    /* added the file string to the text widget */
  1773. X
  1774. X       XmTextSetString(text, file_string);
  1775. X        if(file_string != NULL) XtFree(file_string);
  1776. X        if(name_string != NULL) XtFree(name_string);
  1777. X
  1778. X    /* Poput the text file */
  1779. X
  1780. X    XtPopup(toplevel2,XtGrabNone); 
  1781. X    XtManageChild(text); 
  1782. }
  1783. X
  1784. /* CallBack function of the quit button on a pop-up window */
  1785. X
  1786. void quit_b_pop(w, topshell, call_data)
  1787. X    Widget w;
  1788. X    Widget topshell;
  1789. X    caddr_t  call_data;
  1790. {
  1791. X     XtPopdown(topshell);
  1792. }
  1793. X
  1794. /* function that forks a command from the menu */
  1795. /* Needs work!!!!!
  1796. */
  1797. void do_menu(w,call_mydata,call_data)
  1798. X    Widget w;
  1799. X    caddr_t call_data, call_mydata;
  1800. X
  1801. {
  1802. X    struct entry *branch;
  1803. X    char *filename[MAXPATHLEN+1];  
  1804. X    char *topdir[MAXPATHLEN+1];
  1805. X    XmString name_string = NULL;
  1806. SHAR_EOF
  1807. true || echo 'restore of xdtree.c failed'
  1808. fi
  1809. echo 'End of  part 1'
  1810. echo 'File xdtree.c is continued in part 2'
  1811. echo 2 > _shar_seq_.tmp
  1812. exit 0
  1813. -- 
  1814. ---
  1815. Senior Systems Scientist        mail: dcmartin@msi.com
  1816. Molecular Simulations, Inc.        uucp: uunet!dcmartin
  1817. 796 North Pastoria Avenue        at&t: 408/522-9236
  1818.