home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / x / volume17 / xboncbts / part01 < prev    next >
Encoding:
Text File  |  1992-03-17  |  35.3 KB  |  1,415 lines

  1. Newsgroups: comp.sources.x
  2. Path: uunet!cis.ohio-state.edu!zaphod.mps.ohio-state.edu!mips!msi!dcmartin
  3. From: jef@netcom.com (Jef Poskanzer)
  4. Subject: v17i018: xbouncebits - moving bouncing bitmaps, Part01/01
  5. Message-ID: <1992Mar18.142357.28558@msi.com>
  6. Originator: dcmartin@fascet
  7. Sender: dcmartin@msi.com (David C. Martin - Moderator)
  8. Organization: Molecular Simulations, Inc.
  9. Date: Wed, 18 Mar 1992 14:23:57 GMT
  10. Approved: dcmartin@msi.com
  11.  
  12. Submitted-by: jef@netcom.com (Jef Poskanzer)
  13. Posting-number: Volume 17, Issue 18
  14. Archive-name: xbouncebits/part01
  15.  
  16. Here's a simple root-window bitmap animation hack.  I wouldn't be
  17. surprised if something like this already exists somewhere.
  18. ---
  19. Jef
  20.  
  21.            Jef Poskanzer  jef@netcom.com  jef@well.sf.ca.us
  22.                          execvp(*argv, argv);
  23.  
  24. #! /bin/sh
  25. # This is a shell archive, meaning:
  26. # 1. Remove everything above the #! /bin/sh line.
  27. # 2. Save the resulting text in a file.
  28. # 3. Execute the file with /bin/sh (not csh) to create the files:
  29. #    README
  30. #    Imakefile
  31. #    xbouncebits.c
  32. #    xbouncebits.man
  33. #    Rects.h
  34. #    Rects.c
  35. # This archive created: Wed Mar 11 19:49:12 1992
  36. # By:    Jef Poskanzer
  37. export PATH; PATH=/bin:$PATH
  38. echo shar: extracting "'README'" '(660 characters)'
  39. if test -f 'README'
  40. then
  41.     echo shar: will not over-write existing file "'README'"
  42. else
  43. sed 's/^X//' << \SHAR_EOF > 'README'
  44. X                           xbouncebits
  45. X                     Distribution of 11mar92
  46. X                  Previous distribution -NONE-
  47. X
  48. XXbouncebits displays moving bouncing bitmaps in the X11 root window.
  49. X
  50. XFiles in this distribution:
  51. X
  52. X    README        this
  53. X    Imakefile        guess
  54. X    xbouncebits.c    source file
  55. X    xbouncebits.man    manual entry
  56. X    Rects.h        header file for rectangle routines
  57. X    Rects.c        source file for rectangle routines
  58. X
  59. XTo compile: do an xmkmf, make depend, make.
  60. X
  61. XFeedback is welcome - send bug reports, enhancements, checks, money orders,
  62. Xgold bullion, drugs, etc. to the addresses below.
  63. X
  64. X    Jef Poskanzer
  65. X    jef@netcom.com
  66. X    jef@well.sf.ca.us
  67. SHAR_EOF
  68. if test 660 -ne "`wc -c < 'README'`"
  69. then
  70.     echo shar: error transmitting "'README'" '(should have been 660 characters)'
  71. fi
  72. fi # end of overwriting check
  73. echo shar: extracting "'Imakefile'" '(651 characters)'
  74. if test -f 'Imakefile'
  75. then
  76.     echo shar: will not over-write existing file "'Imakefile'"
  77. else
  78. sed 's/^X//' << \SHAR_EOF > 'Imakefile'
  79. X# @(#) $Header: Imakefile,v 1.1 92/03/11 19:40:30 jef Exp $
  80. X#
  81. X# Copyright (C) 1992 by Jef Poskanzer
  82. X#
  83. X# Permission to use, copy, modify, and distribute this software and its
  84. X# documentation for any purpose and without fee is hereby granted, provided
  85. X# that the above copyright notice appear in all copies and that both that
  86. X# copyright notice and this permission notice appear in supporting
  87. X# documentation.  This software is provided "as is" without express or
  88. X# implied warranty.
  89. X
  90. XLOCAL_LIBRARIES =    $(XMULIB) $(XLIB)
  91. XDEPLIBS =        $(DEPXMULIB) $(DEPXLIB)
  92. XSRCS =            xbouncebits.c Rects.c
  93. XOBJS =            xbouncebits.o Rects.o
  94. X
  95. XComplexProgramTarget(xbouncebits)
  96. SHAR_EOF
  97. if test 651 -ne "`wc -c < 'Imakefile'`"
  98. then
  99.     echo shar: error transmitting "'Imakefile'" '(should have been 651 characters)'
  100. fi
  101. fi # end of overwriting check
  102. echo shar: extracting "'xbouncebits.c'" '(21350 characters)'
  103. if test -f 'xbouncebits.c'
  104. then
  105.     echo shar: will not over-write existing file "'xbouncebits.c'"
  106. else
  107. sed 's/^X//' << \SHAR_EOF > 'xbouncebits.c'
  108. X/* xbouncebits - displays moving bouncing bitmaps in the X11 root window
  109. X**
  110. X** Copyright (C) 1992 by Jef Poskanzer
  111. X**
  112. X** Permission to use, copy, modify, and distribute this software and its
  113. X** documentation for any purpose and without fee is hereby granted, provided
  114. X** that the above copyright notice appear in all copies and that both that
  115. X** copyright notice and this permission notice appear in supporting
  116. X** documentation.  This software is provided "as is" without express or
  117. X** implied warranty.
  118. X*/
  119. X
  120. X#ifndef lint
  121. Xstatic char rcsid[] =
  122. X    "@(#) $Header: xbouncebits.c,v 1.1 92/03/11 19:40:31 jef Exp $";
  123. X#endif
  124. X
  125. X#include <stdio.h>
  126. X#if defined(SYSV) || defined(SVR4)
  127. X#include <string.h>
  128. X#include <sys/termio.h>
  129. X#else /*SYSV*/
  130. X#include <strings.h>
  131. X#endif /*SYSV*/
  132. X#include <signal.h>
  133. X#include <pwd.h>
  134. X#include <sys/types.h>
  135. X#include <sys/ioctl.h>
  136. X#include <sys/time.h>
  137. X#include <errno.h>
  138. Xextern char* sys_errlist[];    /* in case errno.h doesn't declare it */
  139. X
  140. X#include <X11/Xlib.h>
  141. X#include <X11/Xutil.h>
  142. X#include <X11/Xatom.h>
  143. X#include <X11/Xresource.h>
  144. X#define XTSTRINGDEFINES
  145. X#include <X11/StringDefs.h>
  146. X#include "Rects.h"
  147. X
  148. X/* Add fd_set definitions, in case the system doesn't have them. */
  149. X#ifndef FD_SET
  150. X#define NFDBITS        32
  151. X#define FD_SETSIZE    32
  152. X#define FD_SET(n, p)    ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
  153. X#define FD_CLR(n, p)    ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
  154. X#define FD_ISSET(n, p)    ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))
  155. X#define FD_ZERO(p)    bzero((char *)(p), sizeof(*(p)))
  156. X#endif
  157. X
  158. X
  159. X/* Definitions. */
  160. X
  161. X#define X_CLASS "Xbouncebits"
  162. X
  163. X#define CYCLES 10            /* default cycles per second */
  164. X#define GRAVCONST 25            /* cycles per gravity acceleration */
  165. X#define INITIAL_JUMPS 10        /* # of jumps to randomize position */
  166. X#define COLLISION_TRYS 50        /* try this many times, then give up */
  167. X
  168. X#define M_JUMP 1
  169. X#define M_GLIDE 2
  170. X#define M_GRAVITY 3
  171. X
  172. Xtypedef struct rect_struct {
  173. X    XRectangle bb;
  174. X    Pixmap pixmap;
  175. X    int mode;            /* M_JUMP, M_GLIDE, or M_GRAVITY */
  176. X    int clock;            /* for M_JUMP */
  177. X    int dx, dy;            /* for M_GLIDE and M_GRAVITY */
  178. X    } rect;
  179. X
  180. X#define abs(x) ( (x) >= 0 ? (x) : -(x) )
  181. X
  182. X
  183. X/* Externals. */
  184. X
  185. Xextern char* getenv();
  186. Xextern char* malloc();
  187. Xextern long random();
  188. Xextern char* realloc();
  189. Xextern long time();
  190. X
  191. X
  192. X/* Forward routines. */
  193. X
  194. Xstatic void add_rect();
  195. Xstatic void x_init();
  196. Xstatic Window VirtualRootWindowOfScreen();
  197. Xstatic void x_init_rdb();
  198. Xstatic char* x_get_resource();
  199. Xstatic int x_str_to_bool();
  200. Xstatic int x_get_color_resource();
  201. Xstatic void x_cleanup();
  202. Xstatic void stealth();
  203. Xstatic void rects_place();
  204. Xstatic void rect_bounce();
  205. Xstatic void rect_sleep();
  206. Xstatic void rect_glide();
  207. Xstatic void rect_jump();
  208. Xstatic void find_leaders();
  209. Xstatic void main_loop();
  210. Xstatic void sigcatch();
  211. Xstatic void expose();
  212. Xstatic void paint_rect();
  213. X
  214. Xstatic void move_rects();
  215. Xstatic int check_collisions();
  216. X
  217. X
  218. X/* Variables. */
  219. X
  220. Xstatic char* argv0;
  221. X
  222. Xstatic int nrects;
  223. Xstatic int maxrects;
  224. Xstatic rect* rects;
  225. Xstatic int cycles;
  226. Xstatic int goflag;
  227. Xstatic int gravclock;
  228. X
  229. Xstatic char* app_name;
  230. Xstatic Display* display;
  231. Xstatic Screen* screen;
  232. Xstatic Window root;
  233. Xstatic XRectangle rrect;
  234. Xstatic int root_d;
  235. Xstatic unsigned long foreground, background;
  236. Xstatic GC rectgc;
  237. X
  238. X
  239. X/* Routines. */
  240. X
  241. Xvoid
  242. Xmain( argc, argv )
  243. X    int argc;
  244. X    char* argv[];
  245. X    {
  246. X    char* rval;
  247. X    int printpid, mode, copies, i, j, width, height;
  248. X    char* usage = "usage: %s [-cycles n] [-id] [-jump|-glide|-gravity|-copies n] bitmap ...\n";
  249. X    FILE* in;
  250. X    char* data;
  251. X    Pixmap pixmap;
  252. X
  253. X    argv0 = argv[0];
  254. X    app_name = "xbouncebits";
  255. X    cycles = CYCLES;
  256. X    printpid = 0;
  257. X    mode = M_JUMP;
  258. X    copies = 1;
  259. X
  260. X    /* Parse args and initialize X stuff. */
  261. X    x_init( &argc, argv );
  262. X    RectsInit();
  263. X
  264. X    /* Extract and check non-X args. */
  265. X    rval = x_get_resource( "cycles", "Cycles" );
  266. X    if ( rval != (char*) 0 )
  267. X        {
  268. X        cycles = atoi( rval );
  269. X        if ( cycles < 0 )
  270. X        {
  271. X        (void) fprintf( stderr, usage, argv0 );
  272. X        exit( 1 );
  273. X        }
  274. X        }
  275. X    rval = x_get_resource( "id", "Id" );
  276. X    if ( rval != (char*) 0 )
  277. X    printpid = x_str_to_bool( rval );
  278. X
  279. X    /* Read in the bitmap flags and bitmaps. */
  280. X    nrects = 0;
  281. X    maxrects = 0;
  282. X    for ( i = 1; i < argc; ++i )
  283. X    {
  284. X    if ( strcmp( argv[i], "-jump" ) == 0 ||
  285. X         strcmp( argv[i], "-jum" ) == 0 ||
  286. X         strcmp( argv[i], "-ju" ) == 0 ||
  287. X         strcmp( argv[i], "-j" ) == 0 )
  288. X        mode = M_JUMP;
  289. X    else if ( strcmp( argv[i], "-glide" ) == 0 ||
  290. X         strcmp( argv[i], "-glid" ) == 0 ||
  291. X         strcmp( argv[i], "-gli" ) == 0 ||
  292. X         strcmp( argv[i], "-gl" ) == 0 )
  293. X        mode = M_GLIDE;
  294. X    else if ( strcmp( argv[i], "-gravity" ) == 0 ||
  295. X         strcmp( argv[i], "-gravit" ) == 0 ||
  296. X         strcmp( argv[i], "-gravi" ) == 0 ||
  297. X         strcmp( argv[i], "-grav" ) == 0 ||
  298. X         strcmp( argv[i], "-gra" ) == 0 ||
  299. X         strcmp( argv[i], "-gr" ) == 0 )
  300. X        mode = M_GRAVITY;
  301. X    else if ( strcmp( argv[i], "-copies" ) == 0 ||
  302. X         strcmp( argv[i], "-copie" ) == 0 ||
  303. X         strcmp( argv[i], "-copi" ) == 0 ||
  304. X         strcmp( argv[i], "-cop" ) == 0 ||
  305. X         strcmp( argv[i], "-co" ) == 0 ||
  306. X         strcmp( argv[i], "-c" ) == 0 )
  307. X        {
  308. X        ++i;
  309. X        copies = atoi( argv[i] );
  310. X        if ( copies == 0 )
  311. X        {
  312. X        (void) fprintf( stderr, usage, argv0 );
  313. X        exit( 1 );
  314. X        }
  315. X        }
  316. X    else if ( argv[i][0] == '-' && argv[i][1] != '\0' )
  317. X        {
  318. X        (void) fprintf( stderr, usage, argv0 );
  319. X        exit( 1 );
  320. X        }
  321. X    else
  322. X        {
  323. X        /* Read a bitmap. */
  324. X        if ( strcmp( argv[i], "-" ) == 0 )
  325. X        in = stdin;
  326. X        else
  327. X        {
  328. X        in = fopen( argv[i], "r" );
  329. X        if ( in == (FILE*) 0 )
  330. X            {
  331. X            (void) fprintf(
  332. X            stderr, "%s: %s - %s\n", argv0, argv[i],
  333. X            sys_errlist[errno] );
  334. X            exit( 1 );
  335. X            }
  336. X        }
  337. X        j = XmuReadBitmapData(
  338. X        in, &width, &height, &data, (int*) 0, (int*) 0 );
  339. X        if ( j != BitmapSuccess )
  340. X        {
  341. X        (void) fprintf(
  342. X            stderr, "%s: error %d reading %s\n", argv0, j, argv[i] );
  343. X        exit( 1 );
  344. X        }
  345. X        if ( in != stdin )
  346. X        fclose( in );
  347. X        pixmap = XCreatePixmapFromBitmapData(
  348. X        display, root, data, width, height,
  349. X        foreground, background, root_d );
  350. X        free( data );
  351. X        for ( j = 0; j < copies; ++j )
  352. X        {
  353. X        add_rect();
  354. X        rects[nrects].bb.width = (unsigned short) width;
  355. X        rects[nrects].bb.height = (unsigned short) height;
  356. X        rects[nrects].pixmap = pixmap;
  357. X        rects[nrects].mode = mode;
  358. X        ++nrects;
  359. X        }
  360. X        }
  361. X    }
  362. X
  363. X    /* Initialize the random number generator. */
  364. X    srandom( (int) ( time( (long*) 0 ) ^ getpid() ) );
  365. X
  366. X    /* Position the rectangles. */
  367. X    rects_place();
  368. X
  369. X    /* Fork, if necessary. */
  370. X    if ( printpid )
  371. X    stealth();
  372. X
  373. X    /* Main loop. */
  374. X    main_loop();
  375. X
  376. X    /*NOTREACHED*/
  377. X    }
  378. X
  379. Xstatic void
  380. Xadd_rect()
  381. X    {
  382. X    if ( nrects < maxrects )
  383. X    return;
  384. X    if ( maxrects == 0 )
  385. X    {
  386. X    maxrects = 10;        /* non-critical parameter */
  387. X    rects = (rect*) malloc( (unsigned) ( maxrects * sizeof(rect) ) );
  388. X    }
  389. X    else
  390. X    {
  391. X    maxrects *= 2;
  392. X    rects = (rect*) realloc(
  393. X        (char*) rects, (unsigned) ( maxrects * sizeof(rect) ) );
  394. X    }
  395. X    if ( rects == (rect*) 0 )
  396. X    {
  397. X    (void) fprintf( stderr, "%s: out of memory\n", argv0 );
  398. X    exit( 1 );
  399. X    }
  400. X    }
  401. X
  402. Xstatic void
  403. Xx_init( argcP, argv )
  404. X    int* argcP;
  405. X    char** argv;
  406. X    {
  407. X    char* display_name;
  408. X    char* rval;
  409. X    int i;
  410. X    int reverse_video;
  411. X
  412. X    /* Scan args looking for a -display. */
  413. X    display_name = (char*) 0;
  414. X    for ( i = 1; i + 1 < *argcP; ++i )
  415. X    {
  416. X    if ( strcmp( argv[i], "-display" ) == 0 ||
  417. X         strcmp( argv[i], "-displa" ) == 0 ||
  418. X         strcmp( argv[i], "-displ" ) == 0 ||
  419. X         strcmp( argv[i], "-disp" ) == 0 ||
  420. X         strcmp( argv[i], "-dis" ) == 0 ||
  421. X         strcmp( argv[i], "-di" ) == 0 ||
  422. X         strcmp( argv[i], "-d" ) == 0 )
  423. X        {
  424. X        display_name = argv[i + 1];
  425. X        for ( i = i + 2; i <= *argcP; ++i )
  426. X        argv[i - 2] = argv[i];
  427. X        *argcP -= 2;
  428. X        break;
  429. X        }
  430. X    }
  431. X
  432. X    display = XOpenDisplay( display_name );
  433. X    if ( display == (Display*) 0 )
  434. X    {
  435. X    (void) fprintf(
  436. X        stderr, "%s: can't open display \"%s\"\n", argv0,
  437. X        XDisplayName( display_name ) );
  438. X    exit( 1 );
  439. X    }
  440. X
  441. X    screen = DefaultScreenOfDisplay( display );
  442. X    root = VirtualRootWindowOfScreen( screen );
  443. X    rrect.x = rrect.y = 0;
  444. X    rrect.width = WidthOfScreen( screen );
  445. X    rrect.height = HeightOfScreen( screen );
  446. X    root_d = DefaultDepthOfScreen( screen );
  447. X
  448. X    x_init_rdb( argcP, argv );
  449. X
  450. X    rval = x_get_resource( XtNname, "Name" );
  451. X    if ( rval != (char*) 0 )
  452. X    app_name = rval;
  453. X
  454. X    rval = x_get_resource( "synchronous", "Synchronous" );
  455. X    if ( rval != (char*) 0 )
  456. X    if ( x_str_to_bool( rval ) )
  457. X        XSynchronize( display, True );
  458. X
  459. X    reverse_video = 0;
  460. X    rval = x_get_resource( XtNreverseVideo, XtCReverseVideo );
  461. X    if ( rval != (char*) 0 )
  462. X    reverse_video = x_str_to_bool( rval );
  463. X
  464. X    if ( ! x_get_color_resource( XtNforeground, XtCForeground, &foreground ) )
  465. X    foreground = BlackPixelOfScreen( screen );
  466. X
  467. X    if ( ! x_get_color_resource( XtNbackground, XtCBackground, &background ) )
  468. X    background = WhitePixelOfScreen( screen );
  469. X
  470. X    if ( reverse_video )
  471. X    {
  472. X    unsigned long t;
  473. X
  474. X    t = foreground;
  475. X    foreground = background;
  476. X    background = t;
  477. X    }
  478. X
  479. X    rectgc = XCreateGC( display, root, 0, (XGCValues*) 0 );
  480. X    XSetForeground( display, rectgc, foreground );
  481. X    XSetBackground( display, rectgc, background );
  482. X    }
  483. X
  484. X/* From vroot.h by Andreas Stolcke. */
  485. Xstatic Window
  486. XVirtualRootWindowOfScreen( screen )
  487. X    Screen* screen;
  488. X    {
  489. X    static Screen* save_screen = (Screen*) 0;
  490. X    static Window root = (Window) 0;
  491. X
  492. X    if ( screen != save_screen )
  493. X    {
  494. X    Display* dpy = DisplayOfScreen( screen );
  495. X    Atom __SWM_VROOT = None;
  496. X    int i;
  497. X    Window rootReturn, parentReturn;
  498. X    Window* children;
  499. X    unsigned int numChildren;
  500. X
  501. X    root = RootWindowOfScreen( screen );
  502. X
  503. X    /* Go look for a virtual root. */
  504. X    __SWM_VROOT = XInternAtom( dpy, "__SWM_VROOT", False );
  505. X    if ( XQueryTree(
  506. X         dpy, root, &rootReturn, &parentReturn, &children,
  507. X         &numChildren ) )
  508. X        {
  509. X        for ( i = 0; i < numChildren; ++i)
  510. X        {
  511. X        Atom actual_type;
  512. X        int actual_format;
  513. X        unsigned long nitems, bytesafter;
  514. X        Window* newRoot = (Window*) 0;
  515. X
  516. X        if ( XGetWindowProperty(
  517. X             dpy, children[i], __SWM_VROOT, 0, 1, False, XA_WINDOW,
  518. X             &actual_type, &actual_format, &nitems, &bytesafter,
  519. X             (unsigned char**) &newRoot ) == Success && newRoot )
  520. X            {
  521. X            root = *newRoot;
  522. X            break;
  523. X            }
  524. X        }
  525. X        if ( children )
  526. X        XFree( (char*) children );
  527. X        }
  528. X    save_screen = screen;
  529. X    }
  530. X
  531. X    return root;
  532. X    }
  533. X
  534. X/* Resources stuff, extracted from libwin. */
  535. X
  536. Xstatic XrmDatabase rdb;
  537. X
  538. Xstatic XrmOptionDescRec x_options[] = {
  539. X{"-background",        "*background",        XrmoptionSepArg, (caddr_t) 0},
  540. X{"-bg",                "*background",        XrmoptionSepArg, (caddr_t) 0},
  541. X{"-cycles",            "*cycles",            XrmoptionSepArg, (caddr_t) 0},
  542. X{"-fg",                "*foreground",        XrmoptionSepArg, (caddr_t) 0},
  543. X{"-foreground",        "*foreground",        XrmoptionSepArg, (caddr_t) 0},
  544. X{"-id",                "*id",                XrmoptionNoArg,  (caddr_t) "on"},
  545. X{"-name",              ".name",              XrmoptionSepArg, (caddr_t) 0},
  546. X{"-reverse",           "*reverseVideo",      XrmoptionNoArg,  (caddr_t) "on"},
  547. X{"-rv",                "*reverseVideo",      XrmoptionNoArg,  (caddr_t) "on"},
  548. X{"-synchronous",       "*synchronous",       XrmoptionNoArg,  (caddr_t) "on"},
  549. X{"-xrm",               (char*) 0,            XrmoptionResArg, (caddr_t) 0},
  550. X
  551. X};
  552. X
  553. Xstatic void
  554. Xx_init_rdb( argcP, argv )
  555. X    int* argcP;
  556. X    char** argv;
  557. X    {
  558. X    char* resource_string;
  559. X    char* xenv;
  560. X
  561. X    XrmInitialize();
  562. X
  563. X    /* Get resource database from server. */
  564. X    resource_string = XResourceManagerString( display );
  565. X    if ( resource_string != (char*) 0 )
  566. X    rdb = XrmGetStringDatabase( resource_string );
  567. X    else
  568. X    {
  569. X    /* No server database, try ~/.Xdefaults */
  570. X    char* cp;
  571. X    char buf[500];
  572. X
  573. X    cp = getenv( "HOME" );
  574. X    if ( cp != (char*) 0 )
  575. X        (void) strcpy( buf, cp );
  576. X    else
  577. X        {
  578. X        struct passwd* pw;
  579. X
  580. X        cp = getenv( "USER" );
  581. X        if ( cp != (char*) 0 )
  582. X        pw = getpwnam( cp );
  583. X        else
  584. X        pw = getpwuid( getuid() );
  585. X        if ( pw != (struct passwd*) 0 )
  586. X        (void) strcpy( buf, pw->pw_dir );
  587. X        else
  588. X        (void) strcpy( buf, "." );    /* best we can do */
  589. X        }
  590. X    (void) strcat( buf, "/.Xdefaults" );
  591. X    rdb = XrmGetFileDatabase( buf );
  592. X    }
  593. X
  594. X    /* Merge in XENVIRONMENT, if any. */
  595. X    xenv = getenv( "XENVIRONMENT" );
  596. X    if ( xenv != (char*) 0 )
  597. X    {
  598. X    XrmDatabase tdb;
  599. X
  600. X    tdb = XrmGetFileDatabase( xenv );
  601. X    XrmMergeDatabases( tdb, &rdb );
  602. X    }
  603. X
  604. X    /* And add command line options. */
  605. X    XrmParseCommand(
  606. X    &rdb, x_options, sizeof(x_options) / sizeof(*x_options),
  607. X    app_name, argcP, argv );
  608. X    }
  609. X
  610. Xstatic char*
  611. Xx_get_resource( name, class )
  612. X    char* name;
  613. X    char* class;
  614. X    {
  615. X    char rname[500], rclass[500];
  616. X    char* type;
  617. X    XrmValue value;
  618. X
  619. X    (void) sprintf( rname, "%s.%s", app_name, name );
  620. X    (void) sprintf( rclass, "%s.%s", X_CLASS, class );
  621. X    if ( XrmGetResource( rdb, rname, rclass, &type, &value ) == True )
  622. X    if ( strcmp( type, XtRString ) == 0 )
  623. X        return (char*) value.addr;
  624. X    return (char*) 0;
  625. X    }
  626. X
  627. Xstatic int
  628. Xx_str_to_bool( str )
  629. X    char* str;
  630. X    {
  631. X    if ( strcmp( str, "true" ) == 0 ||
  632. X         strcmp( str, "True" ) == 0 ||
  633. X         strcmp( str, "yes" ) == 0 ||
  634. X         strcmp( str, "Yes" ) == 0 ||
  635. X         strcmp( str, "on" ) == 0 ||
  636. X         strcmp( str, "On" ) == 0 ||
  637. X         strcmp( str, "1" ) == 0 )
  638. X    return 1;
  639. X    return 0;
  640. X    }
  641. X
  642. Xstatic int
  643. Xx_get_color_resource( name, class, cP )
  644. X    char* name;
  645. X    char* class;
  646. X    unsigned long* cP;
  647. X    {
  648. X    char* rval;
  649. X    XColor color;
  650. X
  651. X    rval = x_get_resource( name, class );
  652. X    if ( rval == (char*) 0 )
  653. X    return 0;
  654. X    if ( XParseColor( display, DefaultColormapOfScreen( screen ), rval,
  655. X              &color ) != True )
  656. X    {
  657. X    (void) fprintf( stderr, "%s: can't parse color \"%s\"\n", argv0, rval );
  658. X    exit( 1 );
  659. X    }
  660. X    if ( XAllocColor( display, DefaultColormapOfScreen( screen ), &color ) !=
  661. X     True )
  662. X    {
  663. X    (void) fprintf(
  664. X        stderr, "%s: can't allocate color \"%s\"\n", argv0, rval );
  665. X    exit( 1 );
  666. X    }
  667. X    *cP = color.pixel;
  668. X    return 1;
  669. X    }
  670. X
  671. Xstatic void
  672. Xx_cleanup()
  673. X    {
  674. X    XFreeGC( display, rectgc );
  675. X    XCloseDisplay( display );
  676. X    }
  677. X
  678. Xstatic void
  679. Xstealth()
  680. X    {
  681. X    int pid, tty;
  682. X
  683. X    pid = fork();
  684. X    if ( pid < 0 )
  685. X    {
  686. X    perror( "fork" );
  687. X    exit( 1 );
  688. X    }
  689. X    else if ( pid > 0 )
  690. X    /* Parent just exits. */
  691. X    exit( 0 );
  692. X    (void) printf( "%d\n", getpid() );
  693. X    (void) fflush( stdout );
  694. X
  695. X    /* Go stealth (ditch our controlling tty). */
  696. X    tty = open( "/dev/tty", 0 );
  697. X    if ( tty < 0 )
  698. X    {
  699. X    /* ENXIO means that there is no controlling terminal, so we don't
  700. X    ** have to detach anything.
  701. X    */
  702. X        if ( errno != ENXIO )
  703. X        {
  704. X        (void) fprintf( stderr, "%s: ", argv0 );
  705. X        perror( "/dev/tty open" );
  706. X        exit( 1 );
  707. X        }
  708. X    }
  709. X    else
  710. X    {
  711. X    if ( ioctl( tty, TIOCNOTTY, 0 ) < 0 )
  712. X        {
  713. X        (void) fprintf( stderr, "%s: ", argv0 );
  714. X        perror( "TIOCNOTTY ioctl" );
  715. X        exit( 1 );
  716. X        }
  717. X    (void) close( tty );
  718. X    }
  719. X    }
  720. X
  721. Xstatic void
  722. Xrects_place()
  723. X    {
  724. X    int i, j, x0, y0, mh;
  725. X
  726. X    /* Place bitmaps deterministically. */
  727. X    x0 = y0 = mh = 0;
  728. X    for ( i = 0; i < nrects; ++i )
  729. X    {
  730. X    if ( x0 + rects[i].bb.width > rrect.width )
  731. X        {
  732. X        y0 += mh;
  733. X        x0 = mh = 0;
  734. X        if ( y0 + rects[i].bb.height > rrect.height )
  735. X        {
  736. X        (void) fprintf( stderr, "%s: can't place bitmaps\n", argv0 );
  737. X        exit( 1 );
  738. X        }
  739. X        }
  740. X    rects[i].bb.x = x0;
  741. X    rects[i].bb.y = y0;
  742. X    x0 += rects[i].bb.width;
  743. X    if ( rects[i].bb.height > mh )
  744. X        mh = rects[i].bb.height;
  745. X    }
  746. X    /* Randomize positions. */
  747. X    for ( i = 0; i < INITIAL_JUMPS; ++i )
  748. X    for ( j = 0; j < nrects; ++j )
  749. X        rect_jump( j );
  750. X    /* And initialize dx/dy/clock. */
  751. X    for ( i = 0; i < nrects; ++i )
  752. X    if ( rects[i].mode == M_JUMP )
  753. X        rect_sleep( i );
  754. X    else if ( rects[i].mode == M_GLIDE || rects[i].mode == M_GRAVITY )
  755. X        rect_bounce( i );
  756. X    }
  757. X
  758. Xstatic void
  759. Xrect_bounce( i )
  760. X    int i;
  761. X    {
  762. X    do
  763. X    {
  764. X    rects[i].dx = random() % 9 - 4;
  765. X    rects[i].dy = random() % 9 - 4;
  766. X    }
  767. X    while ( ( rects[i].dx == 0 && rects[i].dy == 0 ) ||
  768. X        abs( rects[i].dx ) > rects[i].bb.width ||
  769. X        abs( rects[i].dy ) > rects[i].bb.height );
  770. X    }
  771. X
  772. Xstatic void
  773. Xrect_sleep( i )
  774. X    int i;
  775. X    {
  776. X    rects[i].clock = random() % ( 5 * CYCLES );
  777. X    }
  778. X
  779. Xstatic void
  780. Xrect_glide( i )
  781. X    int i;
  782. X    {
  783. X    int oldx, oldy, j;
  784. X
  785. X    oldx = rects[i].bb.x;
  786. X    oldy = rects[i].bb.y;
  787. X    for ( j = 0; j < COLLISION_TRYS; ++j )
  788. X    {
  789. X    rects[i].bb.x += rects[i].dx;
  790. X    rects[i].bb.y += rects[i].dy;
  791. X    if ( ! check_collisions( i ) )
  792. X        return;
  793. X    rects[i].bb.x = oldx;
  794. X    rects[i].bb.y = oldy;
  795. X    rect_bounce( i );
  796. X    }
  797. X    }
  798. X
  799. Xstatic void
  800. Xrect_jump( i )
  801. X    int i;
  802. X    {
  803. X    int oldx, oldy, j;
  804. X
  805. X    oldx = rects[i].bb.x;
  806. X    oldy = rects[i].bb.y;
  807. X    for ( j = 0; j < COLLISION_TRYS; ++j )
  808. X    {
  809. X    rects[i].bb.x = random() % ( rrect.width - rects[i].bb.width + 1 );
  810. X    rects[i].bb.y = random() % ( rrect.height - rects[i].bb.height + 1);
  811. X    if ( ! check_collisions( i ) )
  812. X        return;
  813. X    }
  814. X    rects[i].bb.x = oldx;
  815. X    rects[i].bb.y = oldy;
  816. X    }
  817. X
  818. Xstatic void
  819. Xmain_loop()
  820. X    {
  821. X    FILE* cfP;
  822. X    int fd, i;
  823. X    fd_set fds;
  824. X    struct timeval timeout;
  825. X    XEvent ev;
  826. X    XRectangle erect;
  827. X
  828. X    /* Set up for signal catching. */
  829. X    goflag = 1;
  830. X    (void) signal( SIGHUP, sigcatch );
  831. X    (void) signal( SIGINT, sigcatch );
  832. X    (void) signal( SIGTERM, sigcatch );
  833. X
  834. X    XSelectInput( display, root, ExposureMask );
  835. X    RectsInvalidate( &rrect, False );
  836. X    FD_ZERO( &fds );
  837. X    fd = ConnectionNumber( display );
  838. X
  839. X    gravclock = GRAVCONST;
  840. X
  841. X    while ( goflag )
  842. X    {
  843. X    if ( RectsNextInvalid( &erect ) )
  844. X        {
  845. X        expose( &erect, False );
  846. X        continue;
  847. X        }
  848. X    if ( cycles != 0 && XPending( display ) == 0 )
  849. X        {
  850. X        /* No X events to handle, so wait for a while. */
  851. X        FD_SET( fd, &fds );
  852. X            timeout.tv_usec = 1000000L / cycles;
  853. X            timeout.tv_sec = timeout.tv_usec / 1000000L;
  854. X            timeout.tv_usec = timeout.tv_usec % 1000000L;
  855. X        (void) select( fd + 1, &fds, (int*) 0, (int*) 0, &timeout );
  856. X        }
  857. X    if ( XPending( display ) == 0 )
  858. X        {
  859. X        /* Still no X events, so let's move. */
  860. X        move_rects();
  861. X        continue;
  862. X        }
  863. X    /* Now there are X events. */
  864. X    XNextEvent( display, &ev );
  865. X    switch ( ev.type )
  866. X        {
  867. X        case Expose:
  868. X        erect.x = ev.xexpose.x;
  869. X        erect.y = ev.xexpose.y;
  870. X        erect.width = ev.xexpose.width;
  871. X        erect.height = ev.xexpose.height;
  872. X        expose( &erect, True );
  873. X        break;
  874. X        }
  875. X    }
  876. X    
  877. X    XClearArea( display, root, 0, 0, rrect.width, rrect.height, True );
  878. X    x_cleanup();
  879. X    exit( 0 );
  880. X    }
  881. X
  882. Xstatic void
  883. Xsigcatch()
  884. X    {
  885. X    goflag = 0;
  886. X    }
  887. X
  888. Xstatic void
  889. Xexpose( erectP, real )
  890. X    XRectangle* erectP;
  891. X    Bool real;
  892. X    {
  893. X    int i, j;
  894. X    XRectangle irect;
  895. X
  896. X    /* If the exposed area is totally in a rect, just paint it. */
  897. X    for ( i = 0; i < nrects; ++i )
  898. X    {
  899. X    if ( RectsInside( erectP, &rects[i].bb ) )
  900. X        {
  901. X        paint_rect( i, erectP );
  902. X        return;
  903. X        }
  904. X    }
  905. X
  906. X    /* Paint the background if needed, then the exposed parts of any rects. */
  907. X    if ( ! real )
  908. X    XClearArea(
  909. X        display, root, erectP->x, erectP->y, erectP->width,
  910. X        erectP->height, False );
  911. X    for ( i = 0; i < nrects; ++i )
  912. X    {
  913. X    irect = *erectP;
  914. X    RectsIntersect( &irect, &rects[i].bb );
  915. X    if ( irect.width > 0 && irect.height > 0 )
  916. X        paint_rect( i, &irect );
  917. X    }
  918. X    }
  919. X
  920. Xstatic void
  921. Xpaint_rect( i, rectP )
  922. X    int i;
  923. X    XRectangle* rectP;
  924. X    {
  925. X    XCopyArea(
  926. X    display, rects[i].pixmap, root, rectgc,
  927. X    rectP->x - rects[i].bb.x, rectP->y - rects[i].bb.y,
  928. X    rectP->width, rectP->height, rectP->x, rectP->y );
  929. X    }
  930. X
  931. Xstatic void
  932. Xmove_rects()
  933. X    {
  934. X    int i, j, oldx, oldy;
  935. X    XRectangle erect;
  936. X
  937. X    --gravclock;
  938. X    for ( i = 0; i < nrects; ++i )
  939. X    if ( rects[i].mode == M_GLIDE || rects[i].mode == M_GRAVITY )
  940. X        {
  941. X        if ( rects[i].mode == M_GRAVITY && gravclock == 0 )
  942. X        ++rects[i].dy;
  943. X        oldx = rects[i].bb.x;
  944. X        oldy = rects[i].bb.y;
  945. X        rect_glide( i );
  946. X
  947. X        /* Erase old trailing edges. */
  948. X        if ( rects[i].dx > 0 )
  949. X        {
  950. X        erect.x = oldx;
  951. X        erect.y = oldy;
  952. X        erect.width = rects[i].dx;
  953. X        erect.height = rects[i].bb.height;
  954. X        RectsInvalidate( &erect, False );
  955. X        }
  956. X        else if ( rects[i].dx < 0 )
  957. X        {
  958. X        erect.x = rects[i].bb.x + rects[i].bb.width;
  959. X        erect.y = oldy;
  960. X        erect.width = -rects[i].dx;
  961. X        erect.height = rects[i].bb.height;
  962. X        RectsInvalidate( &erect, False );
  963. X        }
  964. X        if ( rects[i].dy > 0 )
  965. X        {
  966. X        erect.x = oldx;
  967. X        erect.y = oldy;
  968. X        erect.width = rects[i].bb.width;
  969. X        erect.height = rects[i].dy;
  970. X        RectsInvalidate( &erect, False );
  971. X        }
  972. X        else if ( rects[i].dy < 0 )
  973. X        {
  974. X        erect.x = oldx;
  975. X        erect.y = rects[i].bb.y + rects[i].bb.height;
  976. X        erect.width = rects[i].bb.width;
  977. X        erect.height = -rects[i].dy;
  978. X        RectsInvalidate( &erect, False );
  979. X        }
  980. X
  981. X        /* Paint whole bitmap in new position. */
  982. X        RectsInvalidate( &rects[i].bb, False );
  983. X        }
  984. X    else if ( rects[i].mode == M_JUMP )
  985. X        {
  986. X        --rects[i].clock;
  987. X        if ( rects[i].clock <= 0 )
  988. X        {
  989. X        /* Erase whole bitmap in old position. */
  990. X        RectsInvalidate( &rects[i].bb, True );
  991. X        rect_jump( i );
  992. X        /* Paint whole bitmap in new position. */
  993. X        RectsInvalidate( &rects[i].bb, True );
  994. X        rect_sleep( i );
  995. X        }
  996. X        }
  997. X    if ( gravclock <= 0 )
  998. X    gravclock = GRAVCONST;
  999. X    }
  1000. X
  1001. Xstatic int
  1002. Xcheck_collisions( i )
  1003. X    int i;
  1004. X    {
  1005. X    int j;
  1006. X
  1007. X    /* Check against screen edges. */
  1008. X    if ( ! RectsInside( &rects[i].bb, &rrect ) )
  1009. X    return 1;
  1010. X
  1011. X    /* Check intersection with other rects. */
  1012. X    for ( j = 0; j < nrects; ++j )
  1013. X    if ( i != j )
  1014. X        if ( RectsTouch( &rects[i].bb, &rects[j].bb ) )
  1015. X        return 1;
  1016. X
  1017. X    return 0;
  1018. X    }
  1019. SHAR_EOF
  1020. if test 21350 -ne "`wc -c < 'xbouncebits.c'`"
  1021. then
  1022.     echo shar: error transmitting "'xbouncebits.c'" '(should have been 21350 characters)'
  1023. fi
  1024. fi # end of overwriting check
  1025. echo shar: extracting "'xbouncebits.man'" '(2644 characters)'
  1026. if test -f 'xbouncebits.man'
  1027. then
  1028.     echo shar: will not over-write existing file "'xbouncebits.man'"
  1029. else
  1030. sed 's/^X//' << \SHAR_EOF > 'xbouncebits.man'
  1031. X.TH xbouncebits 1 "11 March 1992"
  1032. X.SH NAME
  1033. Xxbouncebits - display moving bouncing bitmaps in the X11 root window
  1034. X.SH SYNOPSIS
  1035. X.B xbouncebits
  1036. X.RB [ -cycles
  1037. X.IR n ]
  1038. X.RB [ -id ]
  1039. X.RB [ -jump|-glide|-gravity|-copies
  1040. X.IR n ]
  1041. X.I bitmap ...
  1042. X.SH DESCRIPTION
  1043. X.PP
  1044. X.I Xbouncebits
  1045. Xdisplays moving bouncing bitmaps in the root window.
  1046. X.SH OPTIONS
  1047. X.TP
  1048. X.B -cycles
  1049. XSpecifies how often the simulation runs, in cycles per second.
  1050. XIf you specify 0, it runs continuously (and you should probably
  1051. Xnice the
  1052. X.I xbouncebits
  1053. Xprocess, or your interactive response will suffer).
  1054. XDefault: 10.
  1055. XX resource:
  1056. X.BR cycles .
  1057. X.TP
  1058. X.B -id
  1059. XForks a background process and prints the process-id to stdout.
  1060. XUseful if you want to make a menu command to kill
  1061. X.IR xbouncebits .
  1062. XDefault: off.
  1063. XX resource:
  1064. X.BR id .
  1065. X.PP
  1066. X.I Xbouncebits
  1067. Xalso accepts all the usual X flags and resources, such as
  1068. X.BR -fg ,
  1069. X.BR -bg ,
  1070. X.BR -rv ,
  1071. X.BR -sync ,
  1072. Xand
  1073. X.BR -xrm .
  1074. X.PP
  1075. XThe rest of the arguments are a list of bitmap files with interspersed
  1076. Xmode flags.
  1077. XThe mode flags apply to all bitmaps that follow them.
  1078. X.TP
  1079. X.B -jump
  1080. XBitmaps jump around the screen every few seconds.
  1081. XThis is the default mode.
  1082. X.TP
  1083. X.B -glide
  1084. XBitmaps glide slowly around the screen and bounce off each other.
  1085. X.TP
  1086. X.B -gravity
  1087. XLike
  1088. X.BR -glide ,
  1089. Xbut the bitmaps are slowly attracted to the bottom of the screen.
  1090. X.TP
  1091. X.B -copies
  1092. XPuts up
  1093. X.I n
  1094. Xcopies of the subsequent bitmaps.
  1095. X.PP
  1096. XYou can mix modes freely; for example:
  1097. X.nf
  1098. X    xbouncebits cow.x cow.x cow.x cow.x cow.x -glide triangle.x
  1099. X.fi
  1100. Xputs up three cows in jump mode and a triangle in glide mode.
  1101. XThe same setup using the
  1102. X.B -copies
  1103. Xflag:
  1104. X.nf
  1105. X    xbouncebits -copies 5 cow.x -copies 1 -glide triangle.x
  1106. X.fi
  1107. X.PP
  1108. XNote that while jump mode uses very little CPU time, glide and
  1109. Xgravity modes can use a substantial amount.
  1110. X.SH DIAGNOSTICS
  1111. X.TP
  1112. X.B can't place bitmaps
  1113. XThis means that there wasn't enough room on the screen to fit all
  1114. Xthe bitmaps you specified.
  1115. XTry fewer or smaller bitmaps.
  1116. X.SH "BUGS / DEFICIENCIES"
  1117. X.PP
  1118. XDoesn't handle masked images.
  1119. XNot too hard to add, just an argument parsing question.
  1120. X.PP
  1121. XDoesn't handle color images.
  1122. XThis could be added trivially if there
  1123. Xwas a standard X way (i.e. XPM) to read them in.
  1124. X.SH "SEE ALSO"
  1125. X.IR xsetroot (1)
  1126. X.SH AUTHOR
  1127. XCopyright (C) 1992 by Jef Poskanzer
  1128. X.\" Permission to use, copy, modify, and distribute this software and its
  1129. X.\" documentation for any purpose and without fee is hereby granted, provided
  1130. X.\" that the above copyright notice appear in all copies and that both that
  1131. X.\" copyright notice and this permission notice appear in supporting
  1132. X.\" documentation.  This software is provided "as is" without express or
  1133. X.\" implied warranty.
  1134. SHAR_EOF
  1135. if test 2644 -ne "`wc -c < 'xbouncebits.man'`"
  1136. then
  1137.     echo shar: error transmitting "'xbouncebits.man'" '(should have been 2644 characters)'
  1138. fi
  1139. fi # end of overwriting check
  1140. echo shar: extracting "'Rects.h'" '(1749 characters)'
  1141. if test -f 'Rects.h'
  1142. then
  1143.     echo shar: will not over-write existing file "'Rects.h'"
  1144. else
  1145. sed 's/^X//' << \SHAR_EOF > 'Rects.h'
  1146. X/* rects.h - some simple rectangle routines
  1147. X**
  1148. X** Copyright (C) 1992 by Jef Poskanzer
  1149. X**
  1150. X** Permission to use, copy, modify, and distribute this software and its
  1151. X** documentation for any purpose and without fee is hereby granted, provided
  1152. X** that the above copyright notice appear in all copies and that both that
  1153. X** copyright notice and this permission notice appear in supporting
  1154. X** documentation.  This software is provided "as is" without express or
  1155. X** implied warranty.
  1156. X**
  1157. X** @(#) $Header: Rects.h,v 1.1 92/03/11 19:40:31 jef Exp $"
  1158. X*/
  1159. X
  1160. X#ifndef _RECTS_H_
  1161. X#define _RECTS_H_
  1162. X
  1163. X/* Initialize the Rects package. */
  1164. Xextern void RectsInit(
  1165. X#if NeedFunctionPrototypes
  1166. X    void
  1167. X#endif
  1168. X);
  1169. X
  1170. X/* Queue up a rectangle for repainting - better than sending an Expose event. */
  1171. Xextern void RectsInvalidate(
  1172. X#if NeedFunctionPrototypes
  1173. X    XRectangle*        /* rectP */,
  1174. X    Bool        /* merge */
  1175. X#endif
  1176. X);
  1177. X
  1178. X/* Return a rectangle to be repainted, if there are any. */
  1179. Xextern Bool RectsNextInvalid(
  1180. X#if NeedFunctionPrototypes
  1181. X    XRectangle*        /* rectP */
  1182. X#endif
  1183. X);
  1184. X
  1185. X/* Make rect1 the union of rect1 and rect2. */
  1186. Xextern void RectsUnion(
  1187. X#if NeedFunctionPrototypes
  1188. X    XRectangle*        /* rect1P */,
  1189. X    XRectangle*        /* rect2P */
  1190. X#endif
  1191. X);
  1192. X
  1193. X/* Make rect1 the intersection of rect1 and rect2. */
  1194. Xextern void RectsIntersect(
  1195. X#if NeedFunctionPrototypes
  1196. X    XRectangle*        /* rect1P */,
  1197. X    XRectangle*        /* rect2P */
  1198. X#endif
  1199. X);
  1200. X
  1201. X/* Test whether rect1 and rect2 intersect. */
  1202. Xextern Bool RectsTouch(
  1203. X#if NeedFunctionPrototypes
  1204. X    XRectangle*        /* rect1P */,
  1205. X    XRectangle*        /* rect2P */
  1206. X#endif
  1207. X);
  1208. X
  1209. X/* Test whether rect1 is inside rect2. */
  1210. Xextern Bool RectsInside(
  1211. X#if NeedFunctionPrototypes
  1212. X    XRectangle*        /* rect1P */,
  1213. X    XRectangle*        /* rect2P */
  1214. X#endif
  1215. X);
  1216. X
  1217. X#endif /*_RECTS_H_*/
  1218. SHAR_EOF
  1219. if test 1749 -ne "`wc -c < 'Rects.h'`"
  1220. then
  1221.     echo shar: error transmitting "'Rects.h'" '(should have been 1749 characters)'
  1222. fi
  1223. fi # end of overwriting check
  1224. echo shar: extracting "'Rects.c'" '(4299 characters)'
  1225. if test -f 'Rects.c'
  1226. then
  1227.     echo shar: will not over-write existing file "'Rects.c'"
  1228. else
  1229. sed 's/^X//' << \SHAR_EOF > 'Rects.c'
  1230. X/* rects - rectangle routines
  1231. X**
  1232. X** Copyright (C) 1992 by Jef Poskanzer
  1233. X**
  1234. X** Permission to use, copy, modify, and distribute this software and its
  1235. X** documentation for any purpose and without fee is hereby granted, provided
  1236. X** that the above copyright notice appear in all copies and that both that
  1237. X** copyright notice and this permission notice appear in supporting
  1238. X** documentation.  This software is provided "as is" without express or
  1239. X** implied warranty.
  1240. X*/
  1241. X
  1242. X#ifndef lint
  1243. Xstatic char rcsid[] =
  1244. X    "@(#) $Header: Rects.c,v 1.1 92/03/11 19:40:31 jef Exp $";
  1245. X#endif
  1246. X
  1247. X#include <X11/Xlib.h>
  1248. X#include <stdio.h>
  1249. X#include "Rects.h"
  1250. X
  1251. X
  1252. X/* Definitions. */
  1253. X
  1254. Xstatic int num_exposerects, max_exposerects;
  1255. Xstatic XRectangle* exposerects;
  1256. X
  1257. X
  1258. X/* Routines. */
  1259. X
  1260. X/* Initialize the Rects package. */
  1261. Xvoid
  1262. XRectsInit()
  1263. X    {
  1264. X    num_exposerects = max_exposerects = 0;
  1265. X    }
  1266. X
  1267. X/* Queue up a rectangle for repainting - better than sending an Expose event. */
  1268. Xvoid
  1269. XRectsInvalidate( rectP, merge )
  1270. X    XRectangle* rectP;
  1271. X    Bool merge;
  1272. X    {
  1273. X    int i;
  1274. X
  1275. X    if ( merge )
  1276. X    {
  1277. X    /* Check if this rectangle intersects an existing one. */
  1278. X    for ( i = 0; i < num_exposerects; ++i )
  1279. X        {
  1280. X        if ( RectsTouch( &exposerects[i], rectP ) )
  1281. X        {
  1282. X        RectsUnion( &exposerects[i], rectP );
  1283. X        return;
  1284. X        }
  1285. X        }
  1286. X    }
  1287. X
  1288. X    /* Nope, add a new XRectangle. */
  1289. X    if ( num_exposerects == max_exposerects )
  1290. X    {
  1291. X    if ( max_exposerects == 0 )
  1292. X        {
  1293. X        max_exposerects = 32;    /* non-critical parameter */
  1294. X        exposerects = (XRectangle*) malloc(
  1295. X        (unsigned) ( max_exposerects * sizeof(XRectangle) ) );
  1296. X        }
  1297. X    else
  1298. X        {
  1299. X        max_exposerects *= 2;
  1300. X        exposerects = (XRectangle*) realloc(
  1301. X        (char*) exposerects,
  1302. X        (unsigned) ( max_exposerects * sizeof(XRectangle) ) );
  1303. X        }
  1304. X    if ( exposerects == (XRectangle*) 0 )
  1305. X        {
  1306. X        (void) fprintf( stderr, "RectsInvalidate: out of memory\n" );
  1307. X        exit( 1 );
  1308. X        }
  1309. X    }
  1310. X    exposerects[num_exposerects] = *rectP;
  1311. X    ++num_exposerects;
  1312. X    }
  1313. X
  1314. X/* Return a rectangle to be repainted, if there are any. */
  1315. XBool
  1316. XRectsNextInvalid( rectP )
  1317. X    XRectangle* rectP;
  1318. X    {
  1319. X    if ( num_exposerects == 0 )
  1320. X    return False;
  1321. X    --num_exposerects;
  1322. X    *rectP = exposerects[num_exposerects];
  1323. X    return True;
  1324. X    }
  1325. X
  1326. X/* Make rect1 the union of rect1 and rect2. */
  1327. Xvoid
  1328. XRectsUnion( rect1P, rect2P )
  1329. X    XRectangle* rect1P;
  1330. X    XRectangle* rect2P;
  1331. X    {
  1332. X    if ( rect2P->x + rect2P->width > rect1P->x + rect1P->width )
  1333. X    rect1P->width = rect2P->x + rect2P->width - rect1P->x;
  1334. X    if ( rect2P->y + rect2P->height > rect1P->y + rect1P->height )
  1335. X    rect1P->height = rect2P->y + rect2P->height - rect1P->y;
  1336. X    if ( rect2P->x < rect1P->x )
  1337. X    {
  1338. X    rect1P->width = rect1P->x + rect1P->width - rect2P->x;
  1339. X    rect1P->x = rect2P->x;
  1340. X    }
  1341. X    if ( rect2P->y < rect1P->y )
  1342. X    {
  1343. X    rect1P->height = rect1P->y + rect1P->height - rect2P->y;
  1344. X    rect1P->y = rect2P->y;
  1345. X    }
  1346. X    }
  1347. X
  1348. X/* Make rect1 the intersection of rect1 and rect2. */
  1349. Xvoid
  1350. XRectsIntersect( rect1P, rect2P )
  1351. X    XRectangle* rect1P;
  1352. X    XRectangle* rect2P;
  1353. X    {
  1354. X    if ( ! RectsTouch( rect1P, rect2P ) )
  1355. X    {
  1356. X    rect1P->width = rect1P->height = 0;
  1357. X    return;
  1358. X    }
  1359. X    if ( rect2P->x + rect2P->width < rect1P->x + rect1P->width )
  1360. X    rect1P->width = rect2P->x + rect2P->width - rect1P->x;
  1361. X    if ( rect2P->y + rect2P->height < rect1P->y + rect1P->height )
  1362. X    rect1P->height = rect2P->y + rect2P->height - rect1P->y;
  1363. X    if ( rect2P->x > rect1P->x )
  1364. X    {
  1365. X    rect1P->width = rect1P->x + rect1P->width - rect2P->x;
  1366. X    rect1P->x = rect2P->x;
  1367. X    }
  1368. X    if ( rect2P->y > rect1P->y )
  1369. X    {
  1370. X    rect1P->height = rect1P->y + rect1P->height - rect2P->y;
  1371. X    rect1P->y = rect2P->y;
  1372. X    }
  1373. X    }
  1374. X
  1375. X/* Test whether rect1 and rect2 intersect. */
  1376. XBool
  1377. XRectsTouch( rect1P, rect2P )
  1378. X    XRectangle* rect1P;
  1379. X    XRectangle* rect2P;
  1380. X    {
  1381. X    if ( rect1P->x + rect1P->width <= rect2P->x ||
  1382. X         rect1P->y + rect1P->height <= rect2P->y ||
  1383. X         rect2P->x + rect2P->width <= rect1P->x ||
  1384. X         rect2P->y + rect2P->height <= rect1P->y )
  1385. X    return False;
  1386. X    return True;
  1387. X    }
  1388. X
  1389. X/* Test whether rect1 is inside rect2. */
  1390. XBool
  1391. XRectsInside( rect1P, rect2P )
  1392. X    XRectangle* rect1P;
  1393. X    XRectangle* rect2P;
  1394. X    {
  1395. X    if ( rect1P->x >= rect2P->x &&
  1396. X     rect1P->x + rect1P->width <= rect2P->x + rect2P->width &&
  1397. X         rect1P->y >= rect2P->y &&
  1398. X     rect1P->y + rect1P->height <= rect2P->y + rect2P->height )
  1399. X    return True;
  1400. X    return False;
  1401. X    }
  1402. SHAR_EOF
  1403. if test 4299 -ne "`wc -c < 'Rects.c'`"
  1404. then
  1405.     echo shar: error transmitting "'Rects.c'" '(should have been 4299 characters)'
  1406. fi
  1407. fi # end of overwriting check
  1408. #    End of shell archive
  1409. exit 0
  1410. -- 
  1411. --
  1412. Molecular Simulations, Inc.            mail: dcmartin@msi.com
  1413. 796 N. Pastoria Avenue                uucp: uunet!dcmartin
  1414. Sunnyvale, California 94086            at&t: 408/522-9236
  1415.