home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / x / volume8 / vpuzzle / part01 next >
Internet Message Format  |  1990-08-21  |  34KB

  1. Path: uunet!decwrl!wuarchive!cs.utexas.edu!sun-barr!newstop!sun!Solbourne.COM
  2. From: imp@Solbourne.COM (Warner Losh)
  3. Newsgroups: comp.sources.x
  4. Subject: v08i091: Vpuzzle -- screen destruction program :-)
  5. Message-ID: <141102@sun.Eng.Sun.COM>
  6. Date: 22 Aug 90 01:56:51 GMT
  7. Sender: news@sun.Eng.Sun.COM
  8. Lines: 1180
  9. Approved: argv@sun.com
  10.  
  11. Submitted-by: imp@Solbourne.COM (Warner Losh)
  12. Posting-number: Volume 8, Issue 91
  13. Archive-name: vpuzzle/part01
  14.  
  15.     This is a program that will make your X display into one of
  16. those old plastic 16 square puzzle games.  It is quite flexible in the
  17. area of the screen it uses, as well as the number of squares that it
  18. can have on the screen at one time.  It will also fake solving the
  19. puzzle when you abort it, if you desire it.
  20.  
  21.     Included is a README file, a Imakefile file, a Makefile
  22. generated from the Imakefile, a manual page and the source.  This
  23. program has only been tested on a Solbourne and a Sun 4.  It should,
  24. however, work on any BSD system.
  25.  
  26. Warner Losh        imp@Solbourne.COM
  27.  
  28. #!/bin/sh
  29. # shar:    Shell Archiver  (v1.22)
  30. #
  31. #    Run the following text with /bin/sh to create:
  32. #      Imakefile
  33. #      Makefile
  34. #      README
  35. #      vpuzzle.1
  36. #      vpuzzle.c
  37. #
  38. sed 's/^X//' << 'SHAR_EOF' > Imakefile &&
  39. X        DEPLIBS = $(DEPXLIB)
  40. XLOCAL_LIBRARIES = $(XLIB)
  41. X  SYS_LIBRARIES =
  42. X
  43. XSimpleProgramTarget(vpuzzle)
  44. SHAR_EOF
  45. chmod 0664 Imakefile || echo "restore of Imakefile fails"
  46. sed 's/^X//' << 'SHAR_EOF' > Makefile &&
  47. X# Makefile generated by imake - do not edit!
  48. X# $XConsortium: imake.c,v 1.51 89/12/12 12:37:30 jim Exp $
  49. X#
  50. X# The cpp used on this machine replaces all newlines and multiple tabs and
  51. X# spaces in a macro expansion with a single space.  Imake tries to compensate
  52. X# for this, but is not always successful.
  53. X#
  54. X
  55. X###########################################################################
  56. X# Makefile generated from "Imake.tmpl" and <Imakefile>
  57. X# $XConsortium: Imake.tmpl,v 1.77 89/12/18 17:01:37 jim Exp $
  58. X#
  59. X# Platform-specific parameters may be set in the appropriate .cf
  60. X# configuration files.  Site-wide parameters may be set in the file
  61. X# site.def.  Full rebuilds are recommended if any parameters are changed.
  62. X#
  63. X# If your C preprocessor doesn't define any unique symbols, you'll need
  64. X# to set BOOTSTRAPCFLAGS when rebuilding imake (usually when doing
  65. X# "make Makefile", "make Makefiles", or "make World").
  66. X#
  67. X# If you absolutely can't get imake to work, you'll need to set the
  68. X# variables at the top of each Makefile as well as the dependencies at the
  69. X# bottom (makedepend will do this automatically).
  70. X#
  71. X
  72. X###########################################################################
  73. X# platform-specific configuration parameters - edit sol.cf to change
  74. X
  75. X# platform:  $XConsortium: sun.cf,v 1.32 89/10/11 18:54:52 jim Exp $
  76. X# operating system:  SunOS 4.0.3
  77. X
  78. X###########################################################################
  79. X# site-specific configuration parameters - edit site.def to change
  80. X
  81. X# site:  $XConsortium: site.def,v 1.21 89/12/06 11:46:50 jim Exp $
  82. X
  83. X            SHELL = /bin/sh
  84. X
  85. X              TOP = .
  86. X      CURRENT_DIR = .
  87. X
  88. X               AR = ar cq
  89. X  BOOTSTRAPCFLAGS =
  90. X               CC = cc
  91. X
  92. X         COMPRESS = compress
  93. X              CPP = /lib/cpp $(STD_CPP_DEFINES)
  94. X    PREPROCESSCMD = cc -E $(STD_CPP_DEFINES)
  95. X          INSTALL = install
  96. X               LD = ld
  97. X             LINT = lint
  98. X      LINTLIBFLAG = -C
  99. X         LINTOPTS = -axz
  100. X               LN = ln -s
  101. X             MAKE = make
  102. X               MV = mv
  103. X               CP = cp
  104. X           RANLIB = ranlib
  105. X  RANLIBINSTFLAGS =
  106. X               RM = rm -f
  107. X     STD_INCLUDES =
  108. X  STD_CPP_DEFINES =
  109. X      STD_DEFINES =
  110. X EXTRA_LOAD_FLAGS =
  111. X  EXTRA_LIBRARIES =
  112. X             TAGS = ctags
  113. X
  114. X    SHAREDCODEDEF = -DSHAREDCODE
  115. X         SHLIBDEF = -DSUNSHLIB
  116. X
  117. X    PROTO_DEFINES =
  118. X
  119. X     INSTPGMFLAGS =
  120. X
  121. X     INSTBINFLAGS = -m 0755
  122. X     INSTUIDFLAGS = -m 4755
  123. X     INSTLIBFLAGS = -m 0664
  124. X     INSTINCFLAGS = -m 0444
  125. X     INSTMANFLAGS = -m 0444
  126. X     INSTDATFLAGS = -m 0444
  127. X    INSTKMEMFLAGS = -g kmem -m 2755
  128. X
  129. X          DESTDIR =
  130. X
  131. X     TOP_INCLUDES = -I$(INCROOT)
  132. X
  133. X      CDEBUGFLAGS = -O
  134. X        CCOPTIONS =
  135. X      COMPATFLAGS =
  136. X
  137. X         SOLTOP = $(TOP)/../Solbourne
  138. X       SOLOILIB = -L$(SOLTOP)/OI -lOI
  139. X      ALLINCLUDES = -I$(SOLTOP)/OI $(STD_INCLUDES) $(TOP_INCLUDES) $(INCLUDES) $(EXTRA_INCLUDES)
  140. X       ALLDEFINES = $(ALLINCLUDES) $(STD_DEFINES) $(PROTO_DEFINES) $(DEFINES) $(COMPATFLAGS)
  141. X           CFLAGS = $(CDEBUGFLAGS) $(CCOPTIONS) $(ALLDEFINES)
  142. X        LINTFLAGS = $(LINTOPTS) -DLINT $(ALLDEFINES)
  143. X           LDLIBS = $(SYS_LIBRARIES) $(EXTRA_LIBRARIES)
  144. X        LDOPTIONS = $(CDEBUGFLAGS) $(CCOPTIONS)
  145. X   LDCOMBINEFLAGS = -X -r
  146. X
  147. X        MACROFILE = sol.cf
  148. X           RM_CMD = $(RM) *.CKP *.ln *.BAK *.bak *.o core errs ,* *~ *.a .emacs_* tags TAGS make.log MakeOut
  149. X
  150. X    IMAKE_DEFINES =
  151. X
  152. X         IRULESRC = $(CONFIGDIR)
  153. X        IMAKE_CMD = $(IMAKE) -DUseInstalled -I$(IRULESRC) $(IMAKE_DEFINES)
  154. X
  155. X     ICONFIGFILES = $(IRULESRC)/Imake.tmpl $(IRULESRC)/Imake.rules \
  156. X            $(IRULESRC)/Project.tmpl $(IRULESRC)/site.def \
  157. X            $(IRULESRC)/$(MACROFILE) $(EXTRA_ICONFIGFILES)
  158. X
  159. X###########################################################################
  160. X# X Window System Build Parameters
  161. X# $XConsortium: Project.tmpl,v 1.63 89/12/18 16:46:44 jim Exp $
  162. X
  163. X###########################################################################
  164. X# X Window System make variables; this need to be coordinated with rules
  165. X# $XConsortium: Project.tmpl,v 1.63 89/12/18 16:46:44 jim Exp $
  166. X
  167. X          PATHSEP = /
  168. X        USRLIBDIR = $(DESTDIR)/usr/lib
  169. X           BINDIR = $(DESTDIR)/usr/bin/X11
  170. X          INCROOT = $(DESTDIR)/usr/include
  171. X     BUILDINCROOT = $(TOP)
  172. X      BUILDINCDIR = $(BUILDINCROOT)/X11
  173. X      BUILDINCTOP = ..
  174. X           INCDIR = $(INCROOT)/X11
  175. X           ADMDIR = $(DESTDIR)/usr/adm
  176. X           LIBDIR = $(USRLIBDIR)/X11
  177. X        CONFIGDIR = $(LIBDIR)/config
  178. X       LINTLIBDIR = $(USRLIBDIR)/lint
  179. X
  180. X          FONTDIR = $(LIBDIR)/fonts
  181. X         XINITDIR = $(LIBDIR)/xinit
  182. X           XDMDIR = $(LIBDIR)/xdm
  183. X           AWMDIR = $(LIBDIR)/awm
  184. X           TWMDIR = $(LIBDIR)/twm
  185. X           GWMDIR = $(LIBDIR)/gwm
  186. X          MANPATH = $(DESTDIR)/usr/man
  187. X    MANSOURCEPATH = $(MANPATH)/man
  188. X           MANDIR = $(MANSOURCEPATH)n
  189. X        LIBMANDIR = $(MANSOURCEPATH)3
  190. X      XAPPLOADDIR = $(LIBDIR)/app-defaults
  191. X
  192. X        SOXLIBREV = 4.2
  193. X          SOXTREV = 4.0
  194. X         SOXAWREV = 4.0
  195. X        SOOLDXREV = 4.0
  196. X         SOXMUREV = 4.0
  197. X        SOXEXTREV = 4.0
  198. X
  199. X       FONTCFLAGS = -t
  200. X
  201. X     INSTAPPFLAGS = $(INSTDATFLAGS)
  202. X
  203. X            IMAKE = imake
  204. X           DEPEND = makedepend
  205. X              RGB = rgb
  206. X            FONTC = bdftosnf
  207. X        MKFONTDIR = mkfontdir
  208. X        MKDIRHIER = /bin/sh $(BINDIR)/mkdirhier.sh
  209. X
  210. X        CONFIGSRC = $(TOP)/config
  211. X        CLIENTSRC = $(TOP)/clients
  212. X          DEMOSRC = $(TOP)/demos
  213. X           LIBSRC = $(TOP)/lib
  214. X          FONTSRC = $(TOP)/fonts
  215. X       INCLUDESRC = $(TOP)/X11
  216. X        SERVERSRC = $(TOP)/server
  217. X          UTILSRC = $(TOP)/util
  218. X        SCRIPTSRC = $(UTILSRC)/scripts
  219. X       EXAMPLESRC = $(TOP)/examples
  220. X       CONTRIBSRC = $(TOP)/../contrib
  221. X           DOCSRC = $(TOP)/doc
  222. X           RGBSRC = $(TOP)/rgb
  223. X        DEPENDSRC = $(UTILSRC)/makedepend
  224. X         IMAKESRC = $(CONFIGSRC)
  225. X         XAUTHSRC = $(LIBSRC)/Xau
  226. X          XLIBSRC = $(LIBSRC)/X
  227. X           XMUSRC = $(LIBSRC)/Xmu
  228. X       TOOLKITSRC = $(LIBSRC)/Xt
  229. X       AWIDGETSRC = $(LIBSRC)/Xaw
  230. X       OLDXLIBSRC = $(LIBSRC)/oldX
  231. X      XDMCPLIBSRC = $(LIBSRC)/Xdmcp
  232. X      BDFTOSNFSRC = $(FONTSRC)/bdftosnf
  233. X     MKFONTDIRSRC = $(FONTSRC)/mkfontdir
  234. X     EXTENSIONSRC = $(TOP)/extensions
  235. X
  236. X  DEPEXTENSIONLIB = $(USRLIBDIR)/libXext.a
  237. X     EXTENSIONLIB =  -lXext
  238. X
  239. X          DEPXLIB = $(DEPEXTENSIONLIB)
  240. X             XLIB = $(EXTENSIONLIB) -lX11
  241. X
  242. X      DEPXAUTHLIB = $(USRLIBDIR)/libXau.a
  243. X         XAUTHLIB =  -lXau
  244. X
  245. X        DEPXMULIB =
  246. X           XMULIB = -lXmu
  247. X
  248. X       DEPOLDXLIB =
  249. X          OLDXLIB = -loldX
  250. X
  251. X      DEPXTOOLLIB =
  252. X         XTOOLLIB = -lXt
  253. X
  254. X        DEPXAWLIB =
  255. X           XAWLIB = -lXaw
  256. X
  257. X LINTEXTENSIONLIB = $(USRLIBDIR)/llib-lXext.ln
  258. X         LINTXLIB = $(USRLIBDIR)/llib-lX11.ln
  259. X          LINTXMU = $(USRLIBDIR)/llib-lXmu.ln
  260. X        LINTXTOOL = $(USRLIBDIR)/llib-lXt.ln
  261. X          LINTXAW = $(USRLIBDIR)/llib-lXaw.ln
  262. X
  263. X          DEPLIBS = $(DEPXAWLIB) $(DEPXMULIB) $(DEPXTOOLLIB) $(DEPXLIB)
  264. X
  265. X         DEPLIBS1 = $(DEPLIBS)
  266. X         DEPLIBS2 = $(DEPLIBS)
  267. X         DEPLIBS3 = $(DEPLIBS)
  268. X
  269. X###########################################################################
  270. X# Imake rules for building libraries, programs, scripts, and data files
  271. X# rules:  $XConsortium: Imake.rules,v 1.67 89/12/18 17:14:15 jim Exp $
  272. X
  273. X###########################################################################
  274. X# start of Imakefile
  275. X
  276. X        DEPLIBS = $(DEPXLIB)
  277. XLOCAL_LIBRARIES = $(XLIB)
  278. X  SYS_LIBRARIES =
  279. X
  280. X OBJS = vpuzzle.o
  281. X SRCS = vpuzzle.c
  282. X
  283. X PROGRAM = vpuzzle
  284. X
  285. Xall:: vpuzzle
  286. X
  287. Xvpuzzle: $(OBJS) $(DEPLIBS)
  288. X    $(RM) $@
  289. X    $(CC) -o $@ $(OBJS) $(LDOPTIONS) $(LOCAL_LIBRARIES) $(LDLIBS) $(EXTRA_LOAD_FLAGS)
  290. X
  291. Xinstall:: vpuzzle
  292. X    $(INSTALL) -c $(INSTPGMFLAGS)   vpuzzle $(BINDIR)
  293. X
  294. Xinstall.man:: vpuzzle.man
  295. X    $(INSTALL) -c $(INSTMANFLAGS) vpuzzle.man $(MANDIR)/vpuzzle.n
  296. X
  297. Xdepend::
  298. X    $(DEPEND) -s "# DO NOT DELETE" -- $(ALLDEFINES) -- $(SRCS)
  299. X
  300. Xlint:
  301. X    $(LINT) $(LINTFLAGS) $(SRCS) $(LINTLIBS)
  302. Xlint1:
  303. X    $(LINT) $(LINTFLAGS) $(FILE) $(LINTLIBS)
  304. X
  305. Xclean::
  306. X    $(RM) $(PROGRAM)
  307. X
  308. X###########################################################################
  309. X# common rules for all Makefiles - do not edit
  310. X
  311. Xemptyrule::
  312. X
  313. Xclean::
  314. X    $(RM_CMD) \#*
  315. X
  316. XMakefile::
  317. X    -@if [ -f Makefile ]; then \
  318. X    echo "    $(RM) Makefile.bak; $(MV) Makefile Makefile.bak"; \
  319. X    $(RM) Makefile.bak; $(MV) Makefile Makefile.bak; \
  320. X    else exit 0; fi
  321. X    $(IMAKE_CMD) -DTOPDIR=$(TOP) -DCURDIR=$(CURRENT_DIR)
  322. X
  323. Xtags::
  324. X    $(TAGS) -w *.[ch]
  325. X    $(TAGS) -xw *.[ch] > TAGS
  326. X
  327. X###########################################################################
  328. X# empty rules for directories that do not have SUBDIRS - do not edit
  329. X
  330. Xinstall::
  331. X    @echo "install in $(CURRENT_DIR) done"
  332. X
  333. Xinstall.man::
  334. X    @echo "install.man in $(CURRENT_DIR) done"
  335. X
  336. XMakefiles::
  337. X
  338. Xincludes::
  339. X
  340. X###########################################################################
  341. X# dependencies generated by makedepend
  342. X
  343. SHAR_EOF
  344. chmod 0664 Makefile || echo "restore of Makefile fails"
  345. sed 's/^X//' << 'SHAR_EOF' > README &&
  346. XThis is a simple program that I wrote after I saw a MAC screen saver
  347. Xdoing the same thing.  I couldn't figure out how to make it a screen
  348. Xsaver, but it is amusing none the less.
  349. X
  350. XThis program shuffles a display like those old 16 square plastic
  351. Xpuzzles that I played with as a kid.  It will do this to your screen
  352. Xforever, until you hit ^C, or you hit any key on the root menu.  It
  353. Xwill optionally solve the puzzle when it either exhausts its move buffer
  354. X(after about 65356 moves), you hit a key in the root window, or hit ^C
  355. Xin the window that it started in.  Please see the manual for details.
  356. X
  357. XTo make the program, just use xmkmf, then type make.  Or, if you don't
  358. Xhave imake installed, you can compile it:
  359. X    cc -O -o vpuzzle vpuzzle.c -lX11
  360. X
  361. XThis program is know to work against the following servers:
  362. X
  363. X    MIT Sun 3
  364. X    MIT Sun 4
  365. X    Solbourne
  366. X
  367. XIt has been tested and compiled on OS/MP 4.0C and OS/SMP 4.0D from
  368. XSolbourne with X release tape 1.1.  These are both based on SunOS
  369. X4.0.3.  X 1.1 is basically X11 R4.  It has been compiled only on
  370. XX11R4, so some changes may be needed to compile on R3.  It uses
  371. Xstraight Xlib calls, no extended calls, and no toolkit calls.  It
  372. Xshould work in any environment where signals exist.  Please let the
  373. Xauthor know the platforms that you are able to get it to run on.  I'm
  374. Xcurious.  My email address is below.
  375. X
  376. XWarner Losh        imp@Solbourne.COM
  377. SHAR_EOF
  378. chmod 0664 README || echo "restore of README fails"
  379. sed 's/^X//' << 'SHAR_EOF' > vpuzzle.1 &&
  380. X.TH VPUZZLE 1 "15 August 1990"
  381. X.sp
  382. X.SH NAME
  383. Xvpuzzle \- Shuffles your display like on old 16 puzzle.
  384. X.SH SYNOPSIS
  385. X\f3vpuzzle [ -\f2option\f3 ... ]\f1
  386. X.sp
  387. X.SH DESCRIPTION
  388. XThe \f3vpuzzle\f1 
  389. Xshuffles your display around like the old puzzle programs.
  390. X.PP
  391. XIf you use
  392. Xthe
  393. X.B \-solve
  394. Xoption, then the program will undo all the moves that have been done
  395. Xto restote the screen to its original state.  There are three
  396. Xways to signal the program to start solving:
  397. X.IP\(bu
  398. XAllowing the program to make 65364 moves.
  399. X.IP\(bu
  400. XHitting one ^C in the window that started the program
  401. X.IP\(bu
  402. XAny keystroke in the root window.
  403. X.PP
  404. XIf you do not use the
  405. X.B \-solve
  406. Xoption, then you can terminate the program by doing any of the above.
  407. XIn addition, if you are waiting for all the moves to be undone, any of
  408. Xthe above actions will cause the program to quit.
  409. X.sp
  410. X.SH OPTIONS
  411. X\f3vpuzzle\f1 accepts the options listed below:
  412. X.PP
  413. X.TP 8
  414. X.B \-display \f2display\f1
  415. XThis option specifies the display. By default it is
  416. Xthe current machine or the current setting of the DISPLAY variable.
  417. X.PP
  418. X.TP 8
  419. X.B \-border
  420. XThis option indicates that a white border should be drawn around all
  421. Xof the squares of the puzzle.
  422. X.PP
  423. X.TP 8
  424. X.B \-solve
  425. XThis option indicates that the program should try to solve the puzzle,
  426. Xgiven half a chance.
  427. X.PP
  428. X.TP 8
  429. X.B \-numsquares \f2n\f1
  430. XThis option specifies the number of squares in both direction to
  431. Xbe used.  The default is 16.
  432. X.PP
  433. X.TP 8
  434. X.B \-xnumsquares \f2n\f1
  435. XThis option specifies the number of squares horizontally that
  436. Xshould be used.  The default is 16.
  437. X.PP
  438. X.TP 8
  439. X.B \-ynumsquares \f2n\f1
  440. XThis option specifies the number of squares vertically that
  441. Xshould be used.  The default is 16.
  442. X.PP
  443. X.TP 8
  444. X.B \-max \f2n\f1
  445. XThis option specifies the number of pixels that should be used
  446. Xwhen doing the shuffling.  The default is the the screen size.
  447. X.PP
  448. X.TP 8
  449. X.B \-xmax \f2n\f1
  450. XThis option specifies the number of pixels across that should be used 
  451. Xwhen doing the shuffling.  The default is the the screen size.
  452. X.PP
  453. X.TP 8
  454. X.B \-ymax \f2n\f1
  455. XThis option specifies the number of pixels up and down that should be used
  456. Xwhen doing the shuffling.  The default is the the screen size.
  457. X.SH X DEFAULTS
  458. XThis program doesn't use X defaults (for shame).
  459. X.sp
  460. X.SH "SEE ALSO"
  461. X\f3X\f1(1), \f3xpuzzle\f1(1)
  462. X.sp
  463. X.SH BUGS
  464. XThe algorithm to solve the puzzle is too simple.  It just
  465. Xundoes the moves that have been done so far.  It should use the same
  466. Xalgorithm that xpuzzle uses.
  467. X.sp
  468. X.SH COPYRIGHT
  469. XCopyright 1990, Solbourne Computer, Inc.
  470. X.sp
  471. X.SH AUTHORS
  472. XM. Warner Losh (Solbourne)
  473. SHAR_EOF
  474. chmod 0664 vpuzzle.1 || echo "restore of vpuzzle.1 fails"
  475. sed 's/^X//' << 'SHAR_EOF' > vpuzzle.c &&
  476. X/*****************************************************************************/
  477. X/**                Copyright 1990 by Solbourne Computer, Inc            **/
  478. X/**                           Longmont, Colorado                            **/
  479. X/**                                                                         **/
  480. X/**                           All Rights Reserved                           **/
  481. X/**                                                                         **/
  482. X/**    Permission to use, copy, modify, and distribute this software and    **/
  483. X/**    its documentation  for  any  purpose  and  without  fee is hereby    **/
  484. X/**    granted, provided that the above copyright notice appear  in  all    **/
  485. X/**    copies and that both  that  copyright  notice  and  this  permis-    **/
  486. X/**    sion  notice appear in supporting  documentation,  and  that  the    **/
  487. X/**    name  of  Solbourne  not  be  used  in  advertising  in publicity    **/
  488. X/**    pertaining  to  distribution  of  the software  without specific,    **/
  489. X/**    written prior permission.                                            **/
  490. X/**                                                                         **/
  491. X/**    SOLBOURNE  DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,    **/
  492. X/**    INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND  FITNESS,    **/
  493. X/**    IN  NO  EVENT SHALL SOLBROUNE BE LIABLE FOR ANY SPECIAL, INDIRECT    **/
  494. X/**    OR CONSEQUENTIAL DAMAGES OR  ANY  DAMAGES  WHATSOEVER   RESULTING    **/
  495. X/**    FROM LOSS OF USE,  DATA OR  PROFITS,  WHETHER  IN  AN  ACTION  OF    **/
  496. X/**    CONTRACT, NEGLIGENCE  OR OTHER TORTIOUS ACTION, ARISING OUT OF OR    **/
  497. X/**    IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.          **/
  498. X/*****************************************************************************/
  499. X
  500. X/*
  501. X *    xshuffle.c -- makes your display into one of those 16 square puzzles.
  502. X *
  503. X *    Author        : M. Warner Losh    (imp@Solbourne.COM)
  504. X *    Version        : V01.00
  505. X *    Version date    : Wed Aug 15 10:58:36 1990
  506. X *    Creation date    : Sun Aug  5 10:00:03 1990
  507. X *
  508. X *    Usage:    xshuffle
  509. X *            [-numsquares {number-of-squares}] Num squares both ways
  510. X *            [-xnumsquares {num-squares-x}]    Num squares across
  511. X *            [-ynumsquares {num-squares-y}]    Num squares down
  512. X *            [-display {display}]        Display to use
  513. X *            [-border]            Draw a border
  514. X *            [-solve]            Undo moves at end
  515. X *            [-xmax n]            Width of area
  516. X *            [-ymax n]            Height of area
  517. X *            [-max n]            size of square area
  518. X */
  519. X
  520. X/* Include files */
  521. X
  522. X# include <stdio.h>
  523. X# include <signal.h>
  524. X# include <X11/Xlib.h>
  525. X# include <X11/Xatom.h>
  526. X
  527. X/*
  528. X * Macro Definitions
  529. X */
  530. X
  531. X/* Config parameters. */
  532. X
  533. X#define NUM_SQUARES 16            /* Default numberof squares */
  534. X#define MAX_SOLVE    1024*64        /* Max number of moves saved */
  535. X
  536. X/* Magic numbers */
  537. X#define DOWN 0                /* Move down */
  538. X#define UP 1                /* Move up */
  539. X#define RIGHT 2                /* Move rigth */
  540. X#define LEFT 3                /* Move left */
  541. X
  542. X#define MODE_SCRAMBLE    0        /* We're scrambling now */
  543. X#define MODE_SOLVE    1        /* We're solving now */
  544. X#define MODE_EXIT    2        /* Time to exit */
  545. X
  546. X#define X_FLAG    1            /* X coord specified */
  547. X#define Y_FLAG    2            /* Y coord specified */
  548. X
  549. X/*
  550. X * Variables
  551. X */
  552. Xint moves[MAX_SOLVE];            /* Saved moves. */
  553. Xint cur_move = 0;            /* Current move number */
  554. Xint max_moves = MAX_SOLVE;        /* Max moves to make */
  555. Xint solve = 0;                /* True when we are solving puzzle */
  556. Xint mode = MODE_SCRAMBLE;        /* Mode we are in */
  557. Xint boarder_width = 2;            /* Size of the boarder */
  558. Xint nxsquares = NUM_SQUARES;        /* Number of squares across */
  559. Xint nysquares = NUM_SQUARES;        /* Number of squares veritcally */
  560. Xint speed = 1;                /* How fast to move.  Keep at 1 */
  561. Xint last = -1;                /* What was the last move */
  562. Xint x_size;                /* Size in pixels of square */
  563. Xint y_size;                /* Size in pixels of square */
  564. Xint y_max;                /* Biggest y we have. */
  565. Xint x_max;                /* Biggest x we have. */
  566. Xint x;                    /* current X of upper left of blank */
  567. Xint y;                    /* Current Y of upper left of blank*/
  568. Xint x_start = 0;            /* Start X location */
  569. Xint y_start = 0;            /* Start Y location */
  570. X
  571. XWindow w_root;                /* Real root window */
  572. XDisplay *dpy;                /* display connection */
  573. XGC mygc;                /* Drawing GC */
  574. XPixmap pm = 0;                /* Pixmap to save first square */
  575. Xunsigned long fg, bg;            /* Foreground and background pixel */
  576. Xunsigned long scr;            /* Screen number */
  577. Xint (*old_handler)();            /* Old Error handler We restore this */
  578. X
  579. X/* Function Declarations */
  580. X
  581. Xint create_pm_handler ();
  582. Xvoid die_usage ();
  583. Xvoid done ();
  584. Xint main ();
  585. Xvoid move_a_square ();
  586. Xvoid move_down ();
  587. Xvoid move_left ();
  588. Xvoid move_right ();
  589. Xvoid move_up ();
  590. Xvoid process_event ();
  591. Xvoid rand_move_a_square ();
  592. Xvoid save_move ();
  593. Xvoid time_to_go();
  594. Xvoid undo_move_a_square ();
  595. Xint unique_match ();
  596. Xvoid usage ();
  597. X
  598. X/**********************************************************************
  599. X *     create_pm_handler () --- This is the handler for the one
  600. X *                 XCreatePixmap request that we have.
  601. X *                 All it does is to set pm to zero.  It
  602. X *                 assumes that the only error it can get
  603. X *                 is from CreatePixmap.  That is the
  604. X *                 reason for the XSyncs around the
  605. X *                 XCreatePixmap.
  606. X * 
  607. X * Arguments:
  608. X * 
  609. X *     dpy            -i- Display the error happened on
  610. X *     e            -i- Event that caused us to get called.
  611. X * 
  612. X * Returns:
  613. X * 
  614. X */
  615. X
  616. Xint create_pm_handler (dpy, e)
  617. XDisplay *dpy;
  618. XXErrorEvent *e;
  619. X{
  620. X    pm = 0;
  621. X}    /* end of create_pm_handler () */
  622. X
  623. X/**********************************************************************
  624. X *     time_to_go () --- This function is the signal handler for ^C.
  625. X *              It gets called when the user wants to exit.
  626. X *              If the user requested solving of the puzzle,
  627. X *              then we just bump the mode one.  Otherwise,
  628. X *              we set the mode to exit.
  629. X * 
  630. X * Arguments:
  631. X * 
  632. X *     sig         -i- Signal number that caused us to execute.
  633. X *     code         -i- Code for that signal
  634. X *     scp         -i- Signal contexted
  635. X *     addr         -i- Address of the exception.
  636. X */
  637. X
  638. Xvoid time_to_go (sig, code, scp, addr)
  639. Xint sig;
  640. Xint code;
  641. Xstruct sigcontext *scp;
  642. Xchar *addr;
  643. X{
  644. X    if (solve)
  645. X        mode++;
  646. X    else
  647. X        mode = MODE_EXIT;
  648. X}    /* end of time_to_go () */
  649. X
  650. X/**********************************************************************
  651. X *     done () --- Gets called when we are done.  This function sleeps
  652. X *            a while if we just got done solving the puzzle.
  653. X *            Then it maps a big window over all of the other
  654. X *            windows to force them to repaint.  Then it exits.
  655. X */
  656. X
  657. Xvoid done ()
  658. X{
  659. X    Window w;        /* big window */
  660. X    XSetWindowAttributes att; /* Attributes for the window */
  661. X    Visual visual;        /* Visual info */
  662. X    unsigned long mask;    /* Mask for atributes */
  663. X
  664. X    /*
  665. X     * If we just got done solving the puzzle, then we wait a
  666. X     * while.  We also flush all of Xlib's buffers.
  667. X     */
  668. X    if (solve && cur_move == 0)
  669. X    {
  670. X        if (pm)
  671. X            XCopyArea (dpy, pm, w_root, mygc, 0, 0, x_size, y_size,
  672. X                   x_start, y_start);
  673. X        XSync(dpy, False);
  674. X        sleep (3);
  675. X    }
  676. X
  677. X    /*
  678. X     * Free the Pixmap if we need to.
  679. X     */
  680. X    if (pm)
  681. X        XFreePixmap (dpy, pm);
  682. X    
  683. X    /*
  684. X     * Create an override redirect window, map it over all the
  685. X     * clients, then unmap it.  This will cause the screen to
  686. X     * refresh.  Exit when done.
  687. X     */
  688. X    att.override_redirect = True;
  689. X    att.backing_store = False;
  690. X    att.save_under = False;
  691. X    mask = CWOverrideRedirect | CWBackingStore | CWSaveUnder;
  692. X    visual.visualid = CopyFromParent;
  693. X    w = XCreateWindow (dpy, w_root, 0, 0, 9999, 9999, 0,
  694. X               DefaultDepth (dpy, scr), InputOutput, &visual,
  695. X               mask, &att);
  696. X    XMapRaised (dpy, w);
  697. X    XSync(dpy, False);
  698. X    XDestroyWindow(dpy, w);
  699. X    exit(1);
  700. X}    /* end of done () */
  701. X
  702. X/**********************************************************************
  703. X *     main () --- Main routine.
  704. X * 
  705. X * Arguments:
  706. X * 
  707. X *     argc    -i- Num args
  708. X *     argv    -i- args
  709. X */
  710. X
  711. Xint main (argc, argv)
  712. Xint argc;
  713. Xchar **argv;
  714. X{
  715. X    int i;            /* Index for loops */
  716. X    int do_border = False;    /* Draw a border around all the squares */
  717. X    char *display = NULL;    /* Text of display to use. */
  718. X    int max_flag = 0;    /* Flag for what max's are specified. */
  719. X    
  720. X    /*
  721. X     * Parse the arguments.  This is a real kludge right now, so
  722. X     * please be kind...
  723. X     */
  724. X    while (--argc)
  725. X    {
  726. X        if (unique_match(*++argv, "-numsquares", 2))
  727. X        {
  728. X            if (--argc)
  729. X                nysquares = nxsquares = atoi(*++argv);
  730. X            else
  731. X                die_usage ("-numsquares requires another arg");
  732. X            continue;
  733. X        }
  734. X        if (unique_match(*argv, "-display", 2))
  735. X        {
  736. X            if (--argc)
  737. X                display = *++argv;
  738. X            else
  739. X                die_usage ("-display requires another arg");
  740. X            continue;
  741. X        }
  742. X        if (unique_match (*argv, "-xnumsquares", 3))
  743. X        {
  744. X            if (--argc)
  745. X                nxsquares = atoi (*++argv);
  746. X            else
  747. X                die_usage("-xnumsquares requires another arg");
  748. X            continue;
  749. X        }
  750. X        if (unique_match (*argv, "-ynumsquares", 3))
  751. X        {
  752. X            if (--argc)
  753. X                nysquares = atoi (*++argv);
  754. X            else
  755. X                die_usage("-ynumsquares requires another arg");
  756. X            continue;
  757. X        }
  758. X        if (unique_match (*argv, "-border", 2))
  759. X        {
  760. X            do_border = True;
  761. X            continue;
  762. X        }
  763. X        if (unique_match (*argv, "-solve", 2))
  764. X        {
  765. X            solve = 1;
  766. X            continue;
  767. X        }
  768. X        if (unique_match (*argv, "-max", 2))
  769. X        {
  770. X            if (--argc)
  771. X            {
  772. X                max_flag |= X_FLAG | Y_FLAG;
  773. X                x_max = y_max = atoi (*++argv);
  774. X            }
  775. X            else
  776. X                die_usage("-max requires another arg");
  777. X            continue;
  778. X        }
  779. X        if (unique_match (*argv, "-ymax", 3))
  780. X        {
  781. X            if (--argc)
  782. X            {
  783. X                max_flag |= Y_FLAG;
  784. X                y_max = atoi (*++argv);
  785. X            }
  786. X            else
  787. X                die_usage("-ymax requires another arg");
  788. X            continue;
  789. X        }
  790. X        if (unique_match (*argv, "-xmax", 3))
  791. X        {
  792. X            if (--argc)
  793. X            {
  794. X                max_flag |= X_FLAG;
  795. X                x_max = atoi (*++argv);
  796. X            }
  797. X            else
  798. X                die_usage("-xmax requires another arg");
  799. X            continue;
  800. X        }
  801. X        fprintf (stderr,"Unknown option %s\n", *argv);
  802. X        usage();
  803. X    }
  804. X    
  805. X    /*
  806. X     * Setup the random number seed.
  807. X     */
  808. X    srand (getpid());
  809. X
  810. X    /*
  811. X     * Open this display.
  812. X     */
  813. X    dpy = XOpenDisplay(display); 
  814. X    if (!dpy)
  815. X    { 
  816. X        fprintf(stderr, "xfroot: Can't open display.\n");
  817. X        exit(1); 
  818. X    }
  819. X
  820. X    /*
  821. X     * Trap ^C so we can do a refresh
  822. X     */
  823. X    (void) signal (SIGINT, time_to_go);
  824. X    
  825. X    /*
  826. X     * Get the id of the root window.  No need for pseudo root
  827. X     * here becuase we draw on top of everything that is ontop of
  828. X     * the root.
  829. X     */
  830. X    w_root = DefaultRootWindow(dpy);
  831. X
  832. X    /*
  833. X     * Get the default fg and bg colors.
  834. X     */
  835. X    scr = DefaultScreen(dpy);
  836. X    fg = WhitePixel(dpy, scr);
  837. X    bg = BlackPixel(dpy, scr);
  838. X    
  839. X    /*
  840. X     * Setup the GC that will let us do the magic.  Key points are
  841. X     * the drawing mode IncludeInferios.  This is what lets us
  842. X     * draw on top of things.
  843. X     */
  844. X    mygc = XCreateGC (dpy, w_root, 0, 0);
  845. X    XSetForeground (dpy, mygc, fg);
  846. X    XSetBackground (dpy, mygc, bg);
  847. X    XSetSubwindowMode (dpy, mygc, IncludeInferiors);
  848. X
  849. X    /*
  850. X     * OK, find out how big to make things...
  851. X     */
  852. X    if ((max_flag & X_FLAG) == 0)
  853. X        x_max = DisplayWidth (dpy, scr);
  854. X    if ((max_flag & Y_FLAG) == 0)
  855. X        y_max = DisplayHeight (dpy, scr);
  856. X    x_size = x_max / nxsquares;
  857. X    y_size = y_max / nysquares;
  858. X    x_max = x_size * nxsquares;
  859. X    y_max = y_size * nysquares;
  860. X    
  861. X    /*
  862. X     * Create the grid.
  863. X     */
  864. X    if (do_border)
  865. X    {
  866. X        XSetLineAttributes (dpy, mygc, boarder_width, LineSolid,
  867. X                    CapNotLast, JoinMiter);
  868. X        for (i = 0; i <= y_max; i+= y_size)
  869. X            XDrawLine (dpy, w_root, mygc, 0, i, x_max, i);
  870. X        for (i = 0; i <= x_max; i+= x_size)
  871. X            XDrawLine (dpy, w_root, mygc, i, 0, i, y_max);
  872. X    }
  873. X    
  874. X    /*
  875. X     * Start in the upper left hand corner.
  876. X     */
  877. X    x = x_start;
  878. X    y = y_start;
  879. X    
  880. X    /*
  881. X     * Save the upper left hand corner square if we are going to
  882. X     * solve this later.  We will later assume that if pm is
  883. X     * non-zero, that it must be freed.  Also, check to make sure
  884. X     * that we can create this pixmap.  Some servers can't handle
  885. X     * all pixmap create requests.  We have to do this the hard
  886. X     * way.  If you know a better way (other than ignoring the
  887. X     * condition), please let me know at the above address.
  888. X     */
  889. X    if (solve)
  890. X    {
  891. X        XSync (dpy, False);
  892. X        old_handler = XSetErrorHandler (create_pm_handler);
  893. X        pm = XCreatePixmap (dpy, w_root, x_size, y_size,
  894. X                    DefaultDepth(dpy, scr));
  895. X        XSync (dpy, False);
  896. X        XSetErrorHandler (old_handler);
  897. X        if (pm)
  898. X            XCopyArea (dpy, w_root, pm, mygc, x_start, y_start,
  899. X                   x_size, y_size, 0, 0);
  900. X        else
  901. X            fprintf (stderr, "Warning: Start square not saved.\n");
  902. X    }
  903. X    
  904. X    /*
  905. X     * Setup the mask of events.  I'm just looking for a key press
  906. X     * right now.
  907. X     */
  908. X    XSelectInput (dpy, w_root, KeyPressMask);
  909. X    
  910. X    /*
  911. X     * Loop forever.  Get a random number, move a square if it
  912. X     * hasn't been just moved and is also on the screen.
  913. X     */
  914. X    while (1)
  915. X    {
  916. X        if (mode == MODE_EXIT)
  917. X            done();
  918. X        if (XEventsQueued (dpy, QueuedAfterReading) == 0)
  919. X            move_a_square();
  920. X        else
  921. X            process_event();
  922. X    }        
  923. X}    /* end of main () */
  924. X
  925. X/**********************************************************************
  926. X *     process_event () --- Processes events that we are interested
  927. X *                 in.  All others are ignored.
  928. X */
  929. X
  930. Xvoid process_event ()
  931. X{
  932. X    XEvent e;        /* Event we are looking at.*/
  933. X
  934. X    /*
  935. X     * Read the event, and dispatch it.
  936. X     */
  937. X    XNextEvent(dpy, &e);
  938. X    switch (e.type)
  939. X    {
  940. X    /*
  941. X     * KeyPress events cause us to go to the next mode.
  942. X     */
  943. X    case KeyPress:
  944. X        if (solve)
  945. X            mode++;
  946. X        else
  947. X            mode = MODE_EXIT;
  948. X        break;
  949. X        
  950. X    /*
  951. X     * All XLib clients need to do this.
  952. X     */
  953. X    case MappingNotify:
  954. X        XRefreshKeyboardMapping (&e);
  955. X        break;
  956. X    }
  957. X}    /* end of process_event () */
  958. X
  959. X/**********************************************************************
  960. X *     move_a_square () --- Moves a square.  Will shuffle it when we
  961. X *                 are randomizing the screen.  Will
  962. X *                 unshuffle it when we aren't.
  963. X */
  964. X
  965. Xvoid move_a_square ()
  966. X{
  967. X    if (mode == MODE_SCRAMBLE)
  968. X        rand_move_a_square();
  969. X    else
  970. X        undo_move_a_square();
  971. X}    /* end of move_a_square () */
  972. X
  973. X/**********************************************************************
  974. X *     rand_move_a_square () --- Moves a square randomly.  Updates the
  975. X *                  current X and Y positions.  Also
  976. X *                  saves the move.
  977. X */
  978. X
  979. Xvoid rand_move_a_square ()
  980. X{
  981. X    switch ((rand() >> 15) & 3)
  982. X    {
  983. X    case DOWN:            /* Move down */
  984. X        if (last != UP && y - y_size >= 0)
  985. X        {
  986. X            move_down (x,y);
  987. X            y -= y_size;
  988. X            save_move(DOWN);
  989. X        }                
  990. X        break;
  991. X            
  992. X    case UP:            /* Move up */
  993. X        if (last != DOWN && y + y_size < y_max)
  994. X        {
  995. X            move_up (x, y);
  996. X            y += y_size;
  997. X            save_move(UP);
  998. X        }
  999. X        break;
  1000. X
  1001. X    case RIGHT:            /* Move right */
  1002. X        if (last != LEFT && x - x_size >= 0)
  1003. X        {
  1004. X            move_right (x,y);
  1005. X            x -= x_size;
  1006. X            save_move(RIGHT);
  1007. X        }
  1008. X        break;
  1009. X
  1010. X    case LEFT:            /* Move left */
  1011. X        if (last != RIGHT && x + x_size < x_max)
  1012. X        {
  1013. X            move_left (x, y);
  1014. X            x += x_size;
  1015. X            save_move(LEFT);
  1016. X        }
  1017. X        break;
  1018. X    }
  1019. X}    /* end of rand_move_a_square () */
  1020. X
  1021. X/**********************************************************************
  1022. X *     undo_move_a_square () --- Undoes the latest move that hasn't
  1023. X *                  been undone.
  1024. X */
  1025. X
  1026. Xvoid undo_move_a_square ()
  1027. X{
  1028. X    switch (moves[--cur_move])
  1029. X    {
  1030. X    case DOWN:            /* Move down */
  1031. X        move_up (x,y);
  1032. X        y += y_size;
  1033. X        break;
  1034. X            
  1035. X    case UP:            /* Move up */
  1036. X        move_down (x, y);
  1037. X        y -= y_size;
  1038. X        break;
  1039. X
  1040. X    case RIGHT:            /* Move right */
  1041. X        move_left (x,y);
  1042. X        x += x_size;
  1043. X        break;
  1044. X
  1045. X    case LEFT:            /* Move left */
  1046. X        move_right (x, y);
  1047. X        x -= x_size;
  1048. X        break;
  1049. X    }
  1050. X    if (cur_move <= 0)
  1051. X        mode = MODE_EXIT;
  1052. X}    /* end of undo_move_a_square () */
  1053. X
  1054. X/**********************************************************************
  1055. X *     save_move () --- Saves the move, iff we are solving this thing
  1056. X *             later.
  1057. X * 
  1058. X * Arguments:
  1059. X * 
  1060. X *     move        -i- Move to save (eg LEFT, RIGHT)
  1061. X */
  1062. X
  1063. Xvoid save_move (move)
  1064. Xint move;
  1065. X{
  1066. X    last = move;
  1067. X    if (solve)
  1068. X    {
  1069. X        moves[cur_move++] = move;
  1070. X        if (cur_move >= max_moves)
  1071. X            mode = MODE_SOLVE;
  1072. X    }
  1073. X}    /* end of save_move () */
  1074. X
  1075. X/**********************************************************************
  1076. X *     unique_match () --- Does st match pat for at least len
  1077. X *                characters?
  1078. X * 
  1079. X * Arguments:
  1080. X * 
  1081. X *     st           -i- String to match.  This is what the user
  1082. X *                types
  1083. X *     pat           -i- Pattern to match against
  1084. X *     len           -i- Minimum unque length.
  1085. X * 
  1086. X * Returns:
  1087. X * 
  1088. X *     SUCCESS           --- String matches to at least the length
  1089. X *                requested.
  1090. X *     FAILURE           --- Strings don't match.
  1091. X */
  1092. X
  1093. Xint unique_match (st, pat, len)
  1094. Xchar *st;
  1095. Xchar *pat;
  1096. Xint len;
  1097. X{
  1098. X    return len <= strlen (st) && strncmp (st, pat, strlen (st)) == 0;
  1099. X    
  1100. X}    /* end of unique_match () */
  1101. X
  1102. X/**********************************************************************
  1103. X *     move_right () --- Moves the square on the left of the blank
  1104. X *              square to the right.
  1105. X * 
  1106. X */
  1107. X
  1108. Xvoid move_right ()
  1109. X{
  1110. X    int i;
  1111. X    
  1112. X    for (i = x - x_size; i < x; i+=speed)
  1113. X        XCopyArea (dpy, w_root, w_root, mygc, i, y, x_size, y_size,
  1114. X               i+1,y);
  1115. X}    /* end of move_right () */
  1116. X
  1117. X/**********************************************************************
  1118. X *     move_left () --- Moves the square to the right of the blank
  1119. X *             square to the left
  1120. X */
  1121. X
  1122. Xvoid move_left ()
  1123. X{
  1124. X    int i;
  1125. X    
  1126. X    for (i = x + x_size; i > x; i-=speed)
  1127. X        XCopyArea (dpy, w_root, w_root, mygc, i, y, x_size, y_size,
  1128. X               i-1,y);
  1129. X}    /* end of move_left () */
  1130. X
  1131. X/**********************************************************************
  1132. X *     move_up () --- Moves the square below the blank square up.
  1133. X */
  1134. X
  1135. Xvoid move_up ()
  1136. X{
  1137. X    int i;
  1138. X
  1139. X    for (i = y + y_size; i > y; i-=speed)
  1140. X        XCopyArea (dpy, w_root, w_root, mygc, x, i, x_size, y_size,
  1141. X               x,i-1);
  1142. X}
  1143. X
  1144. X/**********************************************************************
  1145. X *     move_down () --- Moves the square above the blank square down.
  1146. X */
  1147. X
  1148. Xvoid move_down ()
  1149. X{
  1150. X    int i;
  1151. X
  1152. X    for (i = y - y_size; i < y; i+=speed)
  1153. X        XCopyArea (dpy, w_root, w_root, mygc, x, i, x_size, y_size,
  1154. X               x,i+1);
  1155. X}
  1156. X
  1157. X/**********************************************************************
  1158. X *     usage () --- Tells the user how to use this program.
  1159. X */
  1160. X
  1161. Xvoid usage ()
  1162. X{
  1163. X    fprintf (stderr, "xshuffle [-numsuqares n] [-xnumsquares n]\
  1164. X[-ynumsquares n]\n\
  1165. X    [-display disp] [-noborder] [-solve] [-max n] [-ymax n] [-xmax n]\n");
  1166. X    exit(1);
  1167. X}    /* end of usage () */
  1168. X
  1169. X/**********************************************************************
  1170. X *     die_usage () --- Prints the error, then calls usage.
  1171. X * 
  1172. X * Arguments:
  1173. X * 
  1174. X *     msg        -i- Message to print.
  1175. X */
  1176. X
  1177. Xvoid die_usage (msg)
  1178. Xchar *msg;
  1179. X{
  1180. X    fprintf (stderr, "%s\n", msg);
  1181. X    usage();
  1182. X}    /* end of die_usage () */
  1183. SHAR_EOF
  1184. chmod 0664 vpuzzle.c || echo "restore of vpuzzle.c fails"
  1185. exit 0
  1186.  
  1187. dan
  1188. ----------------------------------------------------
  1189. O'Reilly && Associates   argv@sun.com / argv@ora.com
  1190. Opinions expressed reflect those of the author only.
  1191.