home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / x / volume20 / xball / part03 < prev    next >
Encoding:
Text File  |  1993-05-26  |  79.1 KB  |  2,928 lines

  1. Newsgroups: comp.sources.x
  2. From: daven@ctron.com ("David N. Nedde")
  3. Subject: v20i003:  xball - simulate bouncing balls in a window, Part03/05
  4. Message-ID: <1993May24.202855.24118@sparky.imd.sterling.com>
  5. X-Md4-Signature: e6b47154145105c76681b5d0c0bea571
  6. Sender: chris@sparky.imd.sterling.com (Chris Olson)
  7. Organization: Sterling Software
  8. Date: Mon, 24 May 1993 20:28:55 GMT
  9. Approved: chris@sparky.imd.sterling.com
  10.  
  11. Submitted-by: daven@ctron.com ("David N. Nedde")
  12. Posting-number: Volume 20, Issue 3
  13. Archive-name: xball/part03
  14. Environment: X11, OSF/Motif, Athena
  15.  
  16. #! /bin/sh
  17. # This is a shell archive.  Remove anything before this line, then unpack
  18. # it by saving it into a file and typing "sh file".  To overwrite existing
  19. # files, type "sh file -c".  You can also feed this as standard input via
  20. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  21. # will see the following message at the end:
  22. #        "End of archive 3 (of 5)."
  23. # Contents:  item.c menu.c room.c scrollbar.c sim.c table.c intf.h
  24. #   miscx.h
  25. # Wrapped by daven@osiris on Tue May  4 16:35:08 1993
  26. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  27. if test -f 'item.c' -a "${1}" != "-c" ; then 
  28.   echo shar: Will not clobber existing file \"'item.c'\"
  29. else
  30. echo shar: Extracting \"'item.c'\" \(22401 characters\)
  31. sed "s/^X//" >'item.c' <<'END_OF_FILE'
  32. X/**********************************************************************
  33. X * item.c - defines the item object
  34. X *
  35. X * Copyright 1993, David Nedde
  36. X *
  37. X * Permission to use, copy, modify, and distribute this software
  38. X * and its documentation for any purpose and without fee is granted
  39. X * provided that the above copyright notice appears in all copies.
  40. X * It is provided "as is" without express or implied warranty.
  41. X **********************************************************************/
  42. X
  43. X/* System Headers */
  44. X#include <stdlib.h>
  45. X#include <X11/StringDefs.h>
  46. X
  47. X#ifdef MOTIF
  48. X#include <Xm/ToggleB.h>
  49. X#endif
  50. X
  51. X/* Local headers */
  52. X#include "item.h"
  53. X#include "room.h"
  54. X#include "scrollbar.h"
  55. X#include "color_l.h"
  56. X#include "menu.h"
  57. X#include "misc.h"
  58. X#include "stipple.xbm"
  59. X
  60. X/* Macros */
  61. X#define SHADES      4   /* Number of shades for colors in the rgb.txt file */
  62. X#define ITEM_WIDTH  10  /* The item's default size */
  63. X#define ITEM_HEIGHT 10
  64. X#ifndef RGB_TXT
  65. X#define RGB_TXT     "/usr/lib/X11/rgb.txt"
  66. X#endif
  67. X
  68. X/* put_pixmap - Draws the item's pixmap to the specified location */
  69. X#define put_pixmap( item, x, y) \
  70. X    XCopyArea(item->display, item->pixmap, item->window, \
  71. X              item->static_data->gc, \
  72. X              0, 0, \
  73. X              item->static_data->width, \
  74. X              item->static_data->height, \
  75. X              intf2int(x) - item->static_data->half_width, \
  76. X              intf2int(y) - item->static_data->half_height)
  77. X
  78. X/* File scope variables */
  79. Xstatic item_static_struct_type static_struct;  /* Item object static data */
  80. Xitem_static_type static_data = &static_struct;
  81. Xstatic Bool static_data_initted = False;
  82. X
  83. X/* Resources */
  84. Xtypedef struct {
  85. X    int    item_width;
  86. X    int    item_height;
  87. X    char * rgb_txt;
  88. X    int    elasticity;
  89. X} app_data,*app_data_ptr;
  90. Xstatic app_data res_data;
  91. Xstatic XtResource resources[] = {
  92. X    { "itemWidth", "ItemWidth", XtRInt, sizeof(int),
  93. X        XtOffset(app_data_ptr,item_width), XtRImmediate, (caddr_t)ITEM_WIDTH },
  94. X    { "itemHeight", "ItemHeight", XtRInt, sizeof(int),
  95. X        XtOffset(app_data_ptr,item_height),XtRImmediate, (caddr_t)ITEM_HEIGHT},
  96. X    { "rgbTxt", "RgbTxt", XtRString, sizeof(char *),
  97. X    XtOffset(app_data_ptr,rgb_txt), XtRString, RGB_TXT}
  98. X};
  99. X
  100. X/* Functions */
  101. Xstatic item_static_type static_data__create(/*display, window, background*/);
  102. Xstatic void             draw_item(/* static_data, display, clear_gc, colors, 
  103. X                                     pixmap, background*/);
  104. Xstatic void             draw_circle(/* display, pixmap, 
  105. X                       x_offset, y_offset, 
  106. X                       width, height*/);
  107. Xstatic void             draw_black_ball(/* display, background*/);
  108. Xstatic void             draw_ball(/* display, pixmap, x_offset, y_offset, 
  109. X                   width, height*/);
  110. X
  111. X
  112. X/* Public object methods */
  113. X
  114. X/* Create the item object.  The item is the thing that bounces on the screen */
  115. X/* The item is drawn to the screen after it is created */
  116. Xitem_type item__create( x, y, x_vel, y_vel)
  117. Xint x;
  118. Xint y;
  119. Xint x_vel;
  120. Xint y_vel;
  121. X{
  122. X    item_type item;
  123. X
  124. X
  125. X    item = (item_type)malloc( sizeof( item_struct_type));
  126. X
  127. X    item->static_data = static_data;
  128. X
  129. X    item->display = static_data->display;
  130. X    item->window  = static_data->window;
  131. X
  132. X    /* Draw with the next avaliable pixmap image (color) */
  133. X    static_data->curr_pixmap = 
  134. X        (static_data->curr_pixmap + 1) % static_data->num_colors;
  135. X
  136. X    item->pixmap = static_data->pixmaps[ static_data->curr_pixmap];
  137. X
  138. X    /* Position are stored as intf (int-floats) to get more precision
  139. X       out of an int */
  140. X    item->x     = int2intf( x);
  141. X    item->y     = int2intf( y);
  142. X    item->x_vel = int2intf( x_vel);
  143. X    item->y_vel = int2intf( y_vel);
  144. X    item->shown = False;
  145. X
  146. X    item->rebounded = False;
  147. X
  148. X    item__draw( item);
  149. X
  150. X#if 0
  151. X    /* To generate demos */
  152. X    printf("create %d,%d,%d,%d\n", 
  153. X           intf2int(item->x),intf2int(item->y),
  154. X           intf2int(item->x_vel),intf2int(item->y_vel));
  155. X#endif
  156. X
  157. X    return item;
  158. X}
  159. X
  160. X
  161. X/* Initializes the item's static data.  This can only be done once
  162. X   there is a window, sice we have to get the background color.  Thus, we
  163. X   are called from room's first refresh callback */
  164. Xvoid item__init(toplevel, display, window, background)
  165. XWidget    toplevel;
  166. XDisplay * display;
  167. XWindow    window;
  168. XPixel     background;
  169. X{
  170. X    static_data = static_data__create( toplevel, display, window, background);
  171. X    static_data_initted = True;
  172. X}
  173. X
  174. X/* Returns true of the item's static data is initialized */
  175. XBool item__initted()
  176. X{
  177. X    return static_data_initted;
  178. X}
  179. X
  180. X
  181. X/* Destroys an item */
  182. Xvoid item__destroy( item)
  183. Xitem_type item;
  184. X{
  185. X    item__undraw( item, item->x, item->y); /* Erase item from screen */
  186. X
  187. X    free( (char *)item);
  188. X}
  189. X
  190. X
  191. X/* Draws the item to the screen if it is visible.  Handles the case
  192. X   where the item was already visible on the screen. */
  193. Xvoid item__draw( item)
  194. Xitem_type item;
  195. X{
  196. X    if (!item->shown && item->static_data->visible)
  197. X    {
  198. X        put_pixmap( item, item->x, item->y);
  199. X        item->shown = True;
  200. X    }
  201. X}
  202. X    
  203. X
  204. X/* Erases the item from the screen */
  205. X
  206. Xvoid item__undraw( item, x, y)
  207. Xitem_type item;
  208. Xintf      x,y;
  209. X{
  210. X    if (item->shown && item->static_data->visible)
  211. X    {
  212. X        put_pixmap( item, x, y);
  213. X        item->shown = False;
  214. X    }
  215. X}
  216. X
  217. X
  218. X/* Redraws the item on the screen, regardless of whether it is shown.
  219. X   This method shoulw be used when the window has to be refreshed. 
  220. X   invisible items will not be drawn. */
  221. Xvoid item__redraw( item)
  222. Xitem_type item;
  223. X{
  224. X    if (item->static_data->visible)
  225. X    {
  226. X        put_pixmap( item, item->x, item->y);
  227. X        item->shown = True;
  228. X    }
  229. X}
  230. X    
  231. X
  232. X/* Move an item's image to a new location */
  233. Xvoid item__move_pos( item, x, y)
  234. Xitem_type item;
  235. Xint x,y;
  236. X{
  237. X    item__undraw( item, item->x, item->y);
  238. X
  239. X    item->x = int2intf(x);
  240. X    item->y = int2intf(y);
  241. X
  242. X    item__draw( item);
  243. X}
  244. X
  245. X
  246. X/* Give an item a random velocity, based on the passed ranges */
  247. Xvoid item__randomize( item, min_x_vel, max_x_vel, min_y_vel, max_y_vel)
  248. Xitem_type item;
  249. Xint       min_x_vel;
  250. Xint       max_x_vel;
  251. Xint       min_y_vel;
  252. Xint       max_y_vel;
  253. X{
  254. X    item->x_vel = int2intf(rand_range( min_x_vel, max_x_vel));
  255. X    item->y_vel = int2intf(rand_range( min_y_vel, max_y_vel));
  256. X}
  257. X
  258. X
  259. X/* Perform one item movement iteration, taking into account other
  260. X   balls, gravity, elasticity, and the room boundaries.  The item's new
  261. X   position is calculated and the item's image is moved to the new
  262. X   location.  Invisible items are not redrawn. */
  263. Xvoid item__move( item, room, items)
  264. Xitem_type  item;
  265. Xroom_type  room;
  266. Xitems_type items;
  267. X{
  268. X    /* Calculate new position of item */
  269. X
  270. X    intf oldx = item->x;
  271. X    intf oldy = item->y;
  272. X
  273. X    /* Calculate new y position */
  274. X    /* Gravity adds to velocity */
  275. X    if ((item->y < room__get_floor( room)) || (item->y_vel != 0))
  276. X    {
  277. X        item->y_vel += room__get_gravity( room);
  278. X    }
  279. X
  280. X
  281. X    /* Move vertically based on velocity */
  282. X    item->y += item->y_vel;
  283. X
  284. X    if (item->y >= room__get_floor( room))
  285. X    {
  286. X        /* item hit floor -- bounce off floor */
  287. X
  288. X        /* Reverse ball velocity */
  289. X        item->y_vel = -item->y_vel;
  290. X
  291. X        item->y += item->y_vel;
  292. X
  293. X        if (ABS(item->y_vel) < room__get_gravity(room))
  294. X            /* This helps dampen rounding errors that cause balls to 
  295. X               bounce forever */
  296. X            item->y_vel = 0;
  297. X        else
  298. X        {
  299. X            /* Ball velocity is reduced by the percentage elasticity */
  300. X            item->y_vel *= item->static_data->elasticity;
  301. X#if 1
  302. X            item->y = room__get_floor( room) - 
  303. X                (room__get_floor( room) - item->y) *
  304. X                    item->static_data->elasticity;
  305. X#else
  306. X            item->y = -item->y + room__get_floor( room)*2;
  307. X#endif
  308. X        }
  309. X    }
  310. X    else
  311. X    if (item->y < room__get_ceiling( room))
  312. X    {
  313. X        /* Reverse ball velocity */
  314. X        item->y_vel = -item->y_vel;
  315. X
  316. X        /* Ball velocity is reduced by the percentage elasticity */
  317. X        item->y_vel *= item->static_data->elasticity;
  318. X
  319. X    /* Bounce off the wall */
  320. X        item->y = -item->y + room__get_ceiling( room)*2;
  321. X    }
  322. X
  323. X
  324. X    /* Calculate new x position */
  325. X    /* Move horizontally based on velocity */
  326. X    item->x += item->x_vel;
  327. X
  328. X    if (item->x > room__get_right_wall(room))
  329. X    {
  330. X        /* Hit right wall */
  331. X        /* Reverse ball velocity */
  332. X        item->x_vel = -item->x_vel;
  333. X
  334. X        /* Ball velocity is reduced by the percentage elasticity */
  335. X        item->x_vel *= item->static_data->elasticity;
  336. X
  337. X    /* Bounce off the wall */
  338. X        item->x = -item->x + room__get_right_wall( room)*2;
  339. X    }
  340. X    else
  341. X    if (item->x < room__get_left_wall( room))
  342. X    {
  343. X        /* Hit left wall */
  344. X        /* Reverse ball velocity */
  345. X        item->x_vel = -item->x_vel;
  346. X
  347. X        /* Ball velocity is reduced by the percentage elasticity */
  348. X        item->x_vel *= item->static_data->elasticity;
  349. X
  350. X    /* Bounce off the wall */
  351. X        item->x = -item->x + room__get_left_wall( room)*2;
  352. X    }
  353. X
  354. X
  355. X    /* Slow ball if it is rolling on the floor */
  356. X
  357. X    if (ABS(item->y) >= room__get_floor(room) - room__get_gravity(room) &&
  358. X        item->y_vel == 0)
  359. X        item->x_vel *= item->static_data->elasticity;
  360. X
  361. X
  362. X    /* Collide with other balls or ball being created */
  363. X    if (item->static_data->ball_collide)
  364. X    {
  365. X        /* See if collided with the ball under the pointer being created */
  366. X        item_type room_item = room__get_item( room);
  367. X        if (room_item != (item_type)0)
  368. X        {
  369. X            item__rebound_item(item, room_item);
  370. X        }
  371. X
  372. X        /* See if collided with another item */
  373. X        items__rebound_items( item, items);
  374. X    }
  375. X
  376. X    /* See if item has come to a peaceful rest */
  377. X    if (item__stopped(item, room))
  378. X    {
  379. X        /* on floor && Not bouncing */
  380. X        if (item->static_data->perpetual)
  381. X        {
  382. X            /* Just drop the ball from the ceiling */
  383. X            item->y = room__get_ceiling( room);
  384. X        }
  385. X        else
  386. X        {
  387. X            if (item__stopped( item, room))
  388. X            {
  389. X                item__undraw( item, oldx, oldy);
  390. X                return;       /* Don't draw item */
  391. X            }
  392. X
  393. X            /* Slow down velocity once rolling based on elasticity */
  394. X            if (item->x_vel > 0)
  395. X                item->x_vel *= item->static_data->elasticity;
  396. X        }
  397. X    }
  398. X
  399. X    /* If item moved, redraw it in the new position */
  400. X    if ((item->y != oldy || item->x != oldx) && static_data->visible)
  401. X    {
  402. X        /* Erase old object */
  403. X        item__undraw( item, oldx, oldy);
  404. X        item__draw( item);
  405. X    }
  406. X}
  407. X
  408. X
  409. X
  410. X/* See if items have hit and rebound them if they have.
  411. X   Moved_item is assumed to have just been moved.
  412. X   Only the moved item will have its x,y positions potentially changed. */
  413. Xvoid item__rebound_item( moved_item, fixed_item)
  414. Xitem_type moved_item;
  415. Xitem_type fixed_item;
  416. X{
  417. X    intf xdiff,ydiff;
  418. X
  419. X    xdiff = moved_item->x - fixed_item->x;
  420. X    ydiff = moved_item->y - fixed_item->y;
  421. X
  422. X    if (ABS(xdiff) < int2intf(moved_item->static_data->width) && 
  423. X        ABS(ydiff) < int2intf(moved_item->static_data->height))
  424. X    {
  425. X        SWAP( moved_item->x_vel, fixed_item->x_vel, intf);
  426. X        SWAP( moved_item->y_vel, fixed_item->y_vel, intf);
  427. X
  428. X        if (moved_item->y_vel <= int2intf(moved_item->static_data->height) &&
  429. X            fixed_item->y_vel <= int2intf(moved_item->static_data->height))
  430. X        {
  431. X            moved_item->y += moved_item->y_vel;
  432. X            moved_item->y_vel += ydiff * moved_item->static_data->elasticity/10;
  433. X            fixed_item->y_vel -= ydiff * moved_item->static_data->elasticity/10;
  434. X        }
  435. X        if (moved_item->x_vel <= int2intf(moved_item->static_data->width) &&
  436. X            fixed_item->x_vel <= int2intf(moved_item->static_data->width))
  437. X        {
  438. X            moved_item->x += moved_item->x_vel;
  439. X            moved_item->x_vel += xdiff * moved_item->static_data->elasticity/10;
  440. X            fixed_item->x_vel -= xdiff * moved_item->static_data->elasticity/10;
  441. X        }
  442. X    }
  443. X}
  444. X
  445. X
  446. X/* A scrollbar callback method that sets all the balls' elasticity */
  447. Xvoid item__set_elasticity_cb(w, closure, call_data)
  448. XWidget                    w;
  449. Xcaddr_t                   closure;
  450. XscrollbarCallbackStruct * call_data;
  451. X{
  452. X    static_data->elasticity = call_data->value / 100.0;
  453. X}
  454. X
  455. X
  456. X/* Return all items' width */
  457. Xint item__get_width()
  458. X{
  459. X    return static_data->width;
  460. X}
  461. X
  462. X
  463. X/* Return all items' height */
  464. Xint item__get_height()
  465. X{
  466. X    return static_data->height;
  467. X}
  468. X
  469. X
  470. X/* A menu callback (mcb) that sets all items' perpetual status */
  471. Xvoid item__perpetual_mcb(w, closure, call_data, extra)
  472. XWidget               w;
  473. Xcaddr_t              closure;
  474. XmenuCallbackStruct * call_data;
  475. Xchar *               extra;
  476. X{
  477. X    static_data->perpetual = call_data->set;
  478. X}
  479. X
  480. X
  481. X/* A menu callback (mcb) that sets all items' collide status */
  482. Xvoid item__collide_mcb(w, closure, call_data, extra)
  483. XWidget w;
  484. Xcaddr_t closure;
  485. XmenuCallbackStruct * call_data;
  486. Xchar *extra;
  487. X{
  488. X    static_data->ball_collide = call_data->set;
  489. X}
  490. X
  491. X
  492. X/* Semi-private object methods */
  493. X
  494. X/* Sets all items' perpetual status */
  495. X/* Note that the toggle must be set properly also */
  496. Xvoid item__set_perpetual(set)
  497. XBool set;
  498. X{
  499. X    static_data->perpetual = set;
  500. X}
  501. X
  502. X
  503. X/* Sets all items' collide status */
  504. X/* Note that the toggle must be set properly also */
  505. Xvoid item__set_ball_collide(set)
  506. XBool set;
  507. X{
  508. X    static_data->ball_collide = set;
  509. X}
  510. X
  511. X
  512. X/* Set all item's visible status */
  513. X/* Note that all items must be undrawn from the screen */
  514. Xvoid item__set_visible(visible)
  515. XBool visible;
  516. X{
  517. X    static_data->visible = visible;
  518. X}
  519. X
  520. X
  521. X/* Private object methods */
  522. X
  523. X/* Load items resources */
  524. Xstatic void get_resources( toplevel, display, window, background)
  525. XWidget   toplevel;
  526. XDisplay *display;
  527. XWindow   window;
  528. XPixel    background;
  529. X{
  530. X    XtGetApplicationResources(toplevel, (XtPointer)&res_data, 
  531. X                              resources, XtNumber(resources), 
  532. X                              (ArgList)NULL,(Cardinal)0);
  533. X
  534. X    static_data->width       = res_data.item_width;
  535. X    static_data->height      = res_data.item_height;
  536. X    static_data->half_width  = static_data->width  / 2;
  537. X    static_data->half_height = static_data->height / 2;
  538. X    static_data->rgb_txt     = res_data.rgb_txt;
  539. X}
  540. X
  541. X
  542. X/* Initialize the item's static data object */
  543. Xstatic item_static_type static_data__create( toplevel, display, window, 
  544. X                                             background)
  545. XWidget    toplevel;
  546. XDisplay * display;
  547. XWindow    window;
  548. XPixel     background;
  549. X{
  550. X    GC clear_gc;
  551. X
  552. X
  553. X    /* The following already set in xball_sys object:
  554. X       static_data->elasticity
  555. X       static_data->ball_collide
  556. X       static_data->perpetual */
  557. X
  558. X    get_resources( toplevel, display, window, background);
  559. X
  560. X    static_data->visible    = True;
  561. X    static_data->background = background;
  562. X
  563. X
  564. X    static_data->display = display;
  565. X    static_data->window = window;
  566. X    static_data->gc = XCreateGC(display, window, 0, 0);
  567. X    clear_gc = XCreateGC(display, window, 0, 0);
  568. X    static_data->curr_pixmap = 0;
  569. X
  570. X
  571. X    if (DisplayCells( display, DefaultScreen(display)) > 2)
  572. X    {
  573. X        /* Non-monochrome system */
  574. X        color_list_type color_list = color_list__create(static_data->rgb_txt);
  575. X        color_type color;
  576. X        Colormap colormap = DefaultColormap(display, DefaultScreen(display));
  577. X        XColor   colors[ SHADES];     /* The color shades */
  578. X        Pixel    cells[ SHADES];
  579. X        int      pixmap_index;
  580. X        int      shade;
  581. X
  582. X
  583. X        for (shade = 0; shade < SHADES; shade++)
  584. X            colors[ shade].flags = DoRed | DoGreen | DoBlue;
  585. X
  586. X        for (color = color_list__get_last( color_list), pixmap_index = 0;
  587. X             color != (color_type)0;
  588. X             pixmap_index++)
  589. X        {
  590. X            if (!XAllocColorCells( display, colormap,     /*contig =*/True, 
  591. X                                   /*plane_masks=*/NULL,  /*nplanes=*/0, 
  592. X                                   /*pixels     =*/cells, /*ncolors=*/SHADES))
  593. X                break;          /* All out of colors */
  594. X
  595. X            for (shade = SHADES-1; shade >= 0; shade--)
  596. X            {
  597. X            colors[ shade].red   = color->r * 65535 / 255;
  598. X        colors[ shade].green = color->g * 65535 / 255;
  599. X        colors[ shade].blue  = color->b * 65535 / 255;
  600. X                colors[ shade].pixel = cells[ shade];
  601. X
  602. X        color = color_list__get_prev( color_list);
  603. X            }
  604. X
  605. X        if (shade == -1)
  606. X        {
  607. X                XStoreColors( display, colormap, colors, SHADES);
  608. X        }
  609. X        else
  610. X        {
  611. X            /* Problem with color list */
  612. X            pixmap_index--;
  613. X        XFreeColors( display, colormap, cells, SHADES, 
  614. X                 /*nplanes=*/0);
  615. X        break;
  616. X        }
  617. X
  618. X            static_data->pixmaps[ pixmap_index] = 
  619. X                XCreatePixmap(display, window,
  620. X                              static_data->width,static_data->height,
  621. X                              DefaultDepth(display, DefaultScreen(display)));
  622. X
  623. X        /* Draw the item onto the pixmap */
  624. X            draw_item(static_data, display, clear_gc, colors, 
  625. X                      static_data->pixmaps[ pixmap_index], background);
  626. X        }
  627. X
  628. X    /* printf("Created %d different colored balls (%d possible).\n",
  629. X            pixmap_index, color_list__get_count( color_list) / 4); */
  630. X
  631. X        color_list__destroy( color_list);
  632. X
  633. X        static_data->num_colors = pixmap_index;
  634. X    }
  635. X
  636. X
  637. X    if ((static_data->num_colors == 0) ||
  638. X        (DisplayCells( display, DefaultScreen(display)) == 2))
  639. X    {
  640. X        /* Monochrome system or cannot allocate colors - 
  641. X           just have 1 pixmap of a black ball */
  642. X        draw_black_ball( display, background);
  643. X    }
  644. X
  645. X
  646. X    XFreeGC( display, clear_gc);
  647. X
  648. X    XSetFunction( display, static_data->gc, GXxor);
  649. X
  650. X    return static_data;
  651. X}
  652. X
  653. X
  654. X
  655. X
  656. X/* Draw an item in the passed colors on the passed pixmap */
  657. Xstatic void draw_item( static_data, display, clear_gc, colors, pixmap, 
  658. X                       background)
  659. Xitem_static_type static_data;
  660. XDisplay         *display;
  661. XGC               clear_gc;
  662. XXColor          *colors;
  663. XPixmap           pixmap;
  664. XPixel            background;
  665. X{
  666. X    static struct
  667. X    {
  668. X        double x_offset, y_offset; /* The circle's offset on the item  */
  669. X        double width, height;      /* The width & height of the circle */
  670. X    } offsets[SHADES-1] = 
  671. X    {
  672. X        0.2, 0.2, 0.3, 0.3,
  673. X        0.1, 0.1, 0.5, 0.5,
  674. X        0.0, 0.0, 0.8, 0.8
  675. X    };
  676. X    int x;
  677. X
  678. X
  679. X    /* Clear pixmap */
  680. X    XFillRectangle(display, pixmap, clear_gc, 0, 0, 
  681. X                   static_data->width, 
  682. X                   static_data->height);
  683. X
  684. X    XSetForeground( display, static_data->gc, 
  685. X                    colors[SHADES-1].pixel ^ background);
  686. X    draw_circle(display, pixmap, static_data->gc,
  687. X        0, 0, static_data->width-1, static_data->height-1);
  688. X
  689. X    /* Draw the circles in the different shades.  Shade SHADES-1 is darkest. */
  690. X    for (x = SHADES-2; x >= 0; x--)
  691. X    {
  692. X        XSetForeground(display, static_data->gc, colors[x].pixel ^ background);
  693. X        draw_ball( display, pixmap, 
  694. X           offsets[x].x_offset, offsets[x].y_offset, 
  695. X           offsets[x].width,    offsets[x].height);
  696. X    }
  697. X
  698. X    /* Draw a white specularity smallest and offset */
  699. X    XSetForeground(display, static_data->gc, 
  700. X                   WhitePixel(display, DefaultScreen(display)) ^ background);
  701. X    draw_ball( display, pixmap, 0.3, 0.3, 0.1, 0.1);
  702. X
  703. X    /* Draw a little black shadow in the lower right corner */
  704. X    XSetForeground(display, static_data->gc, 
  705. X                   BlackPixel(display, DefaultScreen(display)) ^ background);
  706. X    XDrawArc(display, pixmap, static_data->gc, 0, 0, 
  707. X             static_data->width - 1, static_data->height - 1, 
  708. X             300*64, 35*64);
  709. X}
  710. X
  711. X
  712. X/* Draw a circle outline and filling at the size and offet determined by 
  713. X   the ball's size */
  714. Xstatic void draw_ball( display, pixmap, x_offset, y_offset, width, height)
  715. XDisplay * display;
  716. XPixmap    pixmap;
  717. Xdouble    x_offset, y_offset;
  718. Xdouble    width, height;
  719. X{
  720. X    draw_circle( display, pixmap, static_data->gc,
  721. X         (int)(static_data->width  * x_offset), 
  722. X         (int)(static_data->height * y_offset), 
  723. X         (int)(static_data->width  * width), 
  724. X         (int)(static_data->height * height));
  725. X}
  726. X
  727. X
  728. X/* Draw a filled circle of the specified size and position */
  729. Xstatic void draw_circle( display, pixmap, gc, x, y, width, height)
  730. XDisplay * display;
  731. XPixmap    pixmap;
  732. XGC        gc;
  733. Xint       x, y;
  734. Xint       width, height;
  735. X{
  736. X    XDrawArc(display, pixmap, static_data->gc, x, y, width, height, 0, 360*64);
  737. X    XFillArc(display, pixmap, static_data->gc, x, y, width, height, 0, 360*64);
  738. X}
  739. X
  740. X
  741. X/* Draw a black ball onto the first pixmap */
  742. Xstatic void draw_black_ball( display, background)
  743. XDisplay * display;
  744. XPixel background;
  745. X{
  746. X    Pixmap stipple_bitmap = 
  747. X        XCreateBitmapFromData( display,
  748. X                               RootWindow( display, DefaultScreen( display)),
  749. X                               stipple_bits, stipple_width, stipple_height);
  750. X
  751. X    static_data->pixmaps[ 0] =  
  752. X        XCreatePixmap(display, 
  753. X                      RootWindow(display, DefaultScreen(display)),
  754. X                      static_data->width, 
  755. X                      static_data->height,
  756. X                      DefaultDepth( display, DefaultScreen(display)));
  757. X
  758. X    /* Reset all pixels in the background so they will not have
  759. X       any effect when the pixmap is xor-copied */
  760. X    XSetBackground(display, static_data->gc, 0);
  761. X    XFillRectangle(display, static_data->pixmaps[0], static_data->gc, 0, 0,
  762. X                   static_data->width, static_data->height);
  763. X
  764. X    XSetForeground(display, static_data->gc, 
  765. X                   BlackPixel(display,DefaultScreen(display)) ^background);
  766. X
  767. X    /* Draw item */
  768. X    draw_circle( display, static_data->pixmaps[0], static_data->gc, 0, 0, 
  769. X         static_data->width-1, static_data->height-1);
  770. X
  771. X    /* draw a grey specularity small and offset */
  772. X    XSetStipple( display, static_data->gc, stipple_bitmap);
  773. X    XSetFillStyle( display, static_data->gc, FillOpaqueStippled);
  774. X
  775. X    draw_ball( display, static_data->pixmaps[0], 0.2, 0.2, 0.3, 0.3);
  776. X
  777. X    XSetFillStyle( display, static_data->gc, FillSolid);
  778. X
  779. X
  780. X    /* draw a white specularity smallest and offset */
  781. X    XSetForeground(display, static_data->gc, 
  782. X                   WhitePixel(display,DefaultScreen(display)) ^background);
  783. X
  784. X    draw_ball( display, static_data->pixmaps[0], 0.3, 0.3, 0.1, 0.1);
  785. X
  786. X
  787. X    static_data->num_colors = 1;
  788. X
  789. X    XFreePixmap( display, stipple_bitmap);
  790. X}
  791. X
  792. X
  793. X#ifdef DEBUG
  794. X
  795. Xitem__print( item)
  796. Xitem_type item;
  797. X{
  798. X  printf("x,y_pos: %4d,%4d; x,y_vel: %4d,%4d, collide = %d\n",
  799. X         item__get_x( item), item__get_y( item),
  800. X         item__get_x_vel( item), item__get_y_vel( item),
  801. X         (int)static_data->ball_collide);
  802. X
  803. X}
  804. X
  805. X#endif
  806. X
  807. END_OF_FILE
  808. if test 22401 -ne `wc -c <'item.c'`; then
  809.     echo shar: \"'item.c'\" unpacked with wrong size!
  810. fi
  811. # end of 'item.c'
  812. fi
  813. if test -f 'menu.c' -a "${1}" != "-c" ; then 
  814.   echo shar: Will not clobber existing file \"'menu.c'\"
  815. else
  816. echo shar: Extracting \"'menu.c'\" \(18009 characters\)
  817. sed "s/^X//" >'menu.c' <<'END_OF_FILE'
  818. X/**********************************************************************
  819. X * menu.c - defines the menu object
  820. X *
  821. X * Copyright 1993, David Nedde
  822. X *
  823. X * Permission to use, copy, modify, and distribute this software
  824. X * and its documentation for any purpose and without fee is granted
  825. X * provided that the above copyright notice appears in all copies.
  826. X * It is provided "as is" without express or implied warranty.
  827. X **********************************************************************/
  828. X
  829. X/* System Headers */
  830. X#include <stdio.h>
  831. X#include <string.h>
  832. X#include <sys/types.h>
  833. X#include <ctype.h>      /* For isspace */
  834. X
  835. X#include <X11/StringDefs.h>
  836. X#include <X11/Intrinsic.h>
  837. X
  838. X#ifdef MOTIF
  839. X#include <Xm/Xm.h>
  840. X#include <Xm/RowColumn.h>
  841. X#include <Xm/CascadeB.h>
  842. X#include <Xm/PushBG.h>
  843. X#include <Xm/SeparatoG.h>
  844. X#include <Xm/ToggleBG.h>
  845. X#endif
  846. X
  847. X#ifdef ATHENA
  848. X#include <X11/Xaw/Box.h>
  849. X#include <X11/Xaw/Form.h>
  850. X#include <X11/Xaw/SmeBSB.h>
  851. X#include <X11/Xaw/SmeLine.h>
  852. X#include <X11/Xaw/MenuButton.h>
  853. X#include <X11/Xaw/SimpleMenu.h>
  854. X#endif
  855. X
  856. X/* Local headers */
  857. X#include "menu.h"
  858. X#include "misc.h"
  859. X#include "table.h"
  860. X#include "miscx.h"
  861. X
  862. X#ifdef ATHENA
  863. X#include "on.xbm"
  864. X#include "off.xbm"
  865. X#endif
  866. X
  867. X/* Macros */
  868. X#define WPATH_LEN 40
  869. X
  870. X/* File scope variables */
  871. Xtypedef struct {
  872. X  char *menu_def;
  873. X} app_data,*app_data_ptr;
  874. Xstatic app_data res_data;
  875. Xstatic XtResource resources[] = {
  876. X  { "menuDef", "MenuDef", XtRString, sizeof(char *),
  877. X        XtOffset( app_data_ptr, menu_def), XtRString, NULL}
  878. X};
  879. X
  880. X/* Structures */
  881. Xtypedef struct {
  882. X    char *           name;
  883. X    menuCallbackProc proc;
  884. X    caddr_t          closure;
  885. X} menuCallback;
  886. X
  887. Xtypedef struct {
  888. X    char * menu_callback_name;
  889. X    char * optional_params;
  890. X    char * widget_class;
  891. X} closure_type;
  892. X
  893. X/* Functions */
  894. Xstatic void   menu_callback(/* w, menu, call_data*/);
  895. Xstatic void   create_menus(/*menu, menubar, menu_def*/);
  896. Xstatic void   create_menubar(/* menu, form, name*/);
  897. Xstatic void   set_widget_and_do_callback(/* menu, w, set*/);
  898. Xstatic void   set_widget_state(/* menu, w, state*/);
  899. Xstatic Widget get_menu_widget(/* menu, widget_name*/);
  900. Xstatic Bool   get_widget_state(/* menu, w*/);
  901. Xstatic Widget create_pulldown(/* menubar, menu_button_name, pull_down_name*/);
  902. Xstatic WidgetClass * get_pushbutton_class(/**/);
  903. Xstatic char *        get_pushbutton_callback(/**/);
  904. Xstatic WidgetClass * get_separator_class(/**/);
  905. Xstatic char *        get_separator_callback(/**/);
  906. Xstatic WidgetClass * get_togglebutton_class(/**/);
  907. Xstatic char *        get_togglebutton_callback(/**/);
  908. X
  909. X
  910. X/* Public object methods */
  911. X
  912. X/* Create the menu object.  The menubar definition resource is loaded
  913. X   and used to create the widgets that make up the menu system.  */
  914. Xmenu_type menu__create( form)
  915. XWidget form;
  916. X{
  917. X    menu_type menu = XtNew( menu_struct_type);
  918. X
  919. X    menu->mc_table = table__create();
  920. X
  921. X    menu->closure_table = table__create();
  922. X
  923. X    create_menubar( menu, form, "menuBar");
  924. X
  925. X    XtGetApplicationResources(get_toplevel(form), (XtPointer)&res_data, 
  926. X                              resources, XtNumber(resources), 
  927. X                              (ArgList)NULL,(Cardinal)0);
  928. X
  929. X
  930. X    convert_newlines( res_data.menu_def);
  931. X
  932. X    create_menus( menu, menu->menubar, res_data.menu_def);
  933. X
  934. X    XtManageChild( menu->menubar);
  935. X
  936. X    return menu;
  937. X}
  938. X
  939. X
  940. X/* Destroy the menu system object */
  941. Xvoid menu__destroy(menu)
  942. Xmenu_type menu;
  943. X{
  944. X    table__destroy( menu->mc_table);
  945. X    table__destroy( menu->closure_table);
  946. X    XtDestroyWidget( menu->menubar);
  947. X
  948. X    XtFree( (char *)menu);
  949. X}
  950. X
  951. X
  952. X/* Registers an avaliable callback.  This callback can then be
  953. X   referenced by the menu definition resource.  If the callback is
  954. X   referenced, the menuCallbackProc is invoked. */
  955. Xvoid menu__add_callback( menu, action_name, menu_callback_proc, user_data)
  956. Xmenu_type        menu;
  957. Xchar            *action_name;
  958. XmenuCallbackProc menu_callback_proc;
  959. Xcaddr_t          user_data;
  960. X{
  961. X    /* Store avaliable callback into table */
  962. X    menuCallback *menu_node = XtNew( menuCallback);
  963. X    
  964. X
  965. X    menu_node->name    = my_strdup( action_name);
  966. X    menu_node->proc    = menu_callback_proc;
  967. X    menu_node->closure = user_data;
  968. X
  969. X    table__store( menu->mc_table, menu_node->name, (void *)menu_node);
  970. X}
  971. X
  972. X
  973. X/* Given the menu item widget name, toggles the widget's state and
  974. X   performs any menu callbacks registered for the callback that the
  975. X   widget references */
  976. Xvoid menu__set_toggle( menu, widget_name, set)
  977. Xmenu_type menu;
  978. Xchar *    widget_name;
  979. XBool      set;
  980. X{
  981. X    Widget w = get_menu_widget( menu, widget_name);
  982. X
  983. X    if (w == (Widget)0)
  984. X      return;
  985. X
  986. X    set_widget_and_do_callback( menu, w, set);
  987. X}
  988. X
  989. X
  990. X
  991. X/* Return the state of the named widget's toggle state */
  992. XBool  menu__get_toggle( menu, widget_name)
  993. Xmenu_type        menu;
  994. Xchar            *widget_name;
  995. X{
  996. X    Widget w = get_menu_widget( menu, widget_name);
  997. X    
  998. X    
  999. X    if (w == (Widget)0)
  1000. X      return False;
  1001. X
  1002. X    return get_widget_state( menu, w);
  1003. X}
  1004. X
  1005. X
  1006. X/* Set or unset the sensitivity of the specified menu widget */
  1007. Xvoid menu__set_sensitivity( menu, widget_name, sensitive)
  1008. Xmenu_type menu;
  1009. Xchar *    widget_name;
  1010. XBoolean   sensitive;
  1011. X{
  1012. X    Widget w = get_menu_widget( menu, widget_name);
  1013. X
  1014. X
  1015. X    if (w == (Widget)0)
  1016. X      return;
  1017. X
  1018. X    XtVaSetValues( w, XtNsensitive, sensitive, NULL);
  1019. X}
  1020. X
  1021. X
  1022. X/* Returned the named menu widget, or NULL if not found */
  1023. Xstatic Widget get_menu_widget( menu, widget_name)
  1024. Xmenu_type menu;
  1025. Xchar *    widget_name;
  1026. X{
  1027. X    Widget w;
  1028. X    char widget_path[50];
  1029. X
  1030. X
  1031. X    sprintf(widget_path,"*%s", widget_name);
  1032. X    w = XtNameToWidget( menu->menubar, widget_path);
  1033. X
  1034. X    if (w == (Widget)0)
  1035. X    {
  1036. X        fprintf(stderr,"get_menu_widget: Cannot find menu widget '%s'\n", 
  1037. X        widget_name);
  1038. X    }
  1039. X
  1040. X    return w;
  1041. X}
  1042. X
  1043. X
  1044. X/* menu_callback
  1045. X   Called for any menu item that is selected.  Sets up the parameters
  1046. X   and makes the callback to the proper menuCallbackProc function. */
  1047. Xstatic void menu_callback( w, menu, call_data)
  1048. XWidget    w;
  1049. Xmenu_type menu;
  1050. Xcaddr_t * call_data;
  1051. X{
  1052. X    closure_type *     closure;
  1053. X    menuCallback *     mc_node;
  1054. X    menuCallbackStruct menu_cbs;
  1055. X
  1056. X
  1057. X    /* Get data passed when callback was referenced in menu configuration */
  1058. X    closure = (closure_type *)table__retrieve( menu->closure_table, XtName(w));
  1059. X
  1060. X
  1061. X    if (closure == (closure_type *)0)
  1062. X    {
  1063. X        fprintf(stderr,"Cannot find menu callback closure for widget %s.\n",
  1064. X                XtName(w));
  1065. X        return;
  1066. X    }
  1067. X
  1068. X    if (strcmp( closure->widget_class, "ToggleButton") == 0)
  1069. X    {
  1070. X#ifdef ATHENA
  1071. X        /* We have to toggle the athena widget by hand */
  1072. X        set_widget_state( menu, w, !get_widget_state( menu, w));
  1073. X#endif
  1074. X
  1075. X        menu_cbs.set = get_widget_state( menu, w);
  1076. X    }
  1077. X    else
  1078. X      /* Non-toggle button - just put any value there */
  1079. X      menu_cbs.set = True;
  1080. X
  1081. X        
  1082. X    /* Get the callback information stored when the callback was registered */
  1083. X    mc_node = (menuCallback *)table__retrieve( menu->mc_table, 
  1084. X                                               closure->menu_callback_name);
  1085. X
  1086. X    if (mc_node == (menuCallback *)0)
  1087. X    {
  1088. X        fprintf(stderr,"Cannot find menu callback '%s'\n", 
  1089. X                closure->menu_callback_name);
  1090. X        return;
  1091. X    }
  1092. X
  1093. X    /* Call the menu callback function */
  1094. X    (*mc_node->proc)(w, mc_node->closure, &menu_cbs, closure->optional_params);
  1095. X}
  1096. X
  1097. X
  1098. X/**********************************************************************
  1099. X * Menu config text format:
  1100. X *
  1101. X *   XBall.menu: 
  1102. X *     pulldownName~
  1103. X *     widgetName,widgetClass,menuCallbackName,optionalParams...~
  1104. X *       .
  1105. X *       .
  1106. X *       .
  1107. X *     pulldownName2~
  1108. X *     widgetName,widgetClass,menuCallbackName,optionalParams...~
  1109. X *       .
  1110. X *       .
  1111. X *       .
  1112. X **********************************************************************/
  1113. X
  1114. Xstatic void create_menus(menu, menubar, menu_def)
  1115. Xmenu_type menu;
  1116. XWidget    menubar;
  1117. Xchar *    menu_def;
  1118. X{
  1119. X    Widget        pull_down;
  1120. X    Widget        button;
  1121. X    char          pull_down_name[30];
  1122. X    char *        curr_pt = menu_def;
  1123. X    char *        comma;
  1124. X    char *        newline;
  1125. X    char *        next_pt;
  1126. X    WidgetClass * w_class_p;
  1127. X    Arg           args[10];
  1128. X    int           n;
  1129. X
  1130. X
  1131. X    while (curr_pt != NULL)
  1132. X    {
  1133. X        /*next_pt = strpbrk( curr_pt, "\"{}");*/
  1134. X
  1135. X        /* Search for first non-space */
  1136. X        for (next_pt = curr_pt; 
  1137. X             next_pt != '\0' && isspace( *next_pt); 
  1138. X             next_pt++)
  1139. X            /* Do nothing*/;
  1140. X
  1141. X        if (*next_pt == '\0')
  1142. X            break;
  1143. X
  1144. X        switch (*next_pt)
  1145. X        {
  1146. X        case '{':
  1147. X            printf("Sorry - '{' not yet implemented\n");
  1148. X            curr_pt = strchr( next_pt, '\n'); /* Go to next line */
  1149. X            break;
  1150. X        case '}':
  1151. X            printf("Sorry - '}' not yet implemented\n");
  1152. X            curr_pt = strchr( next_pt, '\n'); /* Go to next line */
  1153. X            break;
  1154. X        default:
  1155. X            comma = strchr( next_pt, ',');
  1156. X            newline = strpbrk( next_pt, "\n ");
  1157. X            /*newline = strchr( next_pt, '\n');*/
  1158. X            if (newline == NULL || comma == NULL ||
  1159. X                newline < comma)
  1160. X            {
  1161. X                /* At a menu header since no commas before the next newline */
  1162. X                char *menu_button_name = get_string( next_pt);
  1163. X
  1164. X                sprintf(pull_down_name, "%sPullDown", menu_button_name);
  1165. X
  1166. X        pull_down = create_pulldown( menubar, menu_button_name, 
  1167. X                         pull_down_name);
  1168. X
  1169. X                free( menu_button_name);
  1170. X
  1171. X                curr_pt = strchr( next_pt, '\n'); /* Go to next line */
  1172. X            }
  1173. X            else
  1174. X            {
  1175. X                /* At a menu item.  Get the parameters */
  1176. X                char *item_str = get_string( next_pt);
  1177. X                char *w_name;
  1178. X                char *w_class;
  1179. X                char *menu_callback_name;
  1180. X                char *optional_params;
  1181. X                char *callback;
  1182. X
  1183. X                w_name  = strtok( item_str, ",");
  1184. X                w_class = strtok( (char *)0, ",");
  1185. X                menu_callback_name = strtok( (char *)0, ",");
  1186. X                optional_params = strtok( (char *)0, "\n");
  1187. X
  1188. X                n = 0;
  1189. X
  1190. X                if (strcmp( w_class, "PushButton") == 0)
  1191. X                {
  1192. X            w_class_p = get_pushbutton_class();
  1193. X            callback  = get_pushbutton_callback();
  1194. X                }
  1195. X                else
  1196. X                if (strcmp( w_class, "Separator") == 0)
  1197. X                {
  1198. X            w_class_p = get_separator_class();
  1199. X            callback  = get_separator_callback();
  1200. X                }
  1201. X                else
  1202. X                if (strcmp( w_class, "ToggleButton") == 0)
  1203. X                {
  1204. X            w_class_p = get_togglebutton_class();
  1205. X            callback  = get_togglebutton_callback();
  1206. X
  1207. X#ifdef ATHENA
  1208. X            /* Need to initialize some values for the athena toggle */
  1209. X                    XtSetArg(args[n], XtNleftBitmap, menu->off_bitmap); n++;
  1210. X                    XtSetArg(args[n], XtNleftMargin, off_width+4); n++;
  1211. X                    XtSetArg(args[n], XtNvertSpace, 50); n++;
  1212. X#endif
  1213. X                }
  1214. X
  1215. X                button = XtCreateManagedWidget( w_name, *w_class_p, pull_down, 
  1216. X                                                args, n);
  1217. X
  1218. X                if (callback != (char *)0)
  1219. X                {
  1220. X                    closure_type * closure;
  1221. X
  1222. X                    if (optional_params == (char *)0)
  1223. X                        optional_params = "";
  1224. X
  1225. X                    closure = (closure_type *)XtNew( closure_type);
  1226. X                    closure->menu_callback_name= my_strdup(menu_callback_name);
  1227. X                    closure->optional_params = my_strdup( optional_params);
  1228. X                    closure->widget_class = my_strdup( w_class);
  1229. X
  1230. X                    XtAddCallback( button, callback,menu_callback,
  1231. X                                   (XtPointer)menu);
  1232. X
  1233. X                    table__store( menu->closure_table, w_name,(void *)closure);
  1234. X                }
  1235. X                free( item_str);
  1236. X
  1237. X                curr_pt = strchr( next_pt, '\n'); /* Go to next line */
  1238. X            }
  1239. X            break;
  1240. X        }
  1241. X    }
  1242. X}
  1243. X
  1244. X
  1245. X/* Private object methods */
  1246. X
  1247. X#ifdef MOTIF
  1248. X
  1249. Xstatic void create_menubar( menu, form, name)
  1250. Xmenu_type menu;
  1251. XWidget    form;
  1252. Xchar *    name;
  1253. X{
  1254. X    menu->menubar = XmCreateMenuBar( form, name, NULL, 0);
  1255. X}
  1256. X
  1257. X
  1258. X/* Sets the toggle widget to the specified value and performs menu
  1259. X   callbacks to inform of the new value */
  1260. Xstatic void set_widget_and_do_callback( menu, w, set)
  1261. Xmenu_type menu;
  1262. XWidget    w;
  1263. XBool      set;
  1264. X{
  1265. X    set_widget_state( menu, w, set);
  1266. X
  1267. X    XtCallCallbacks( w, XmNvalueChangedCallback, (char *)0);
  1268. X}
  1269. X
  1270. X
  1271. X/* Ser the state of the Motif menu "toggle" widget */
  1272. Xstatic void set_widget_state( menu, w, state)
  1273. Xmenu_type menu;
  1274. XWidget    w;
  1275. XBool      state;
  1276. X{
  1277. X    XtVaSetValues( w, XmNset, state, NULL);
  1278. X}
  1279. X
  1280. X
  1281. X/* Returns the state of the Motif menu widget */
  1282. Xstatic Bool get_widget_state( menu, w)
  1283. Xmenu_type menu;
  1284. XWidget    w;
  1285. X{
  1286. X    return XmToggleButtonGadgetGetState( w);
  1287. X}
  1288. X
  1289. X
  1290. X/* Create the pull down menu for Motif.  If the menu_button is named
  1291. X   "help", it is designated the menu help button. */
  1292. Xstatic Widget create_pulldown( menubar, menu_button_name, pull_down_name)
  1293. XWidget menubar;
  1294. Xchar * menu_button_name;
  1295. Xchar * pull_down_name;
  1296. X{
  1297. X    Widget pull_down;
  1298. X    Widget button;
  1299. X
  1300. X
  1301. X    pull_down = XmCreatePulldownMenu( menubar, pull_down_name, NULL, 0);
  1302. X
  1303. X    button = 
  1304. X        XtVaCreateManagedWidget( menu_button_name, xmCascadeButtonWidgetClass, 
  1305. X                 menubar, 
  1306. X                 XmNsubMenuId, pull_down,
  1307. X                 NULL);
  1308. X
  1309. X    if (strcmp( menu_button_name, "help") == 0)
  1310. X    {
  1311. X        XtVaSetValues(menubar, XmNmenuHelpWidget, button, NULL);
  1312. X    }
  1313. X
  1314. X    return pull_down;
  1315. X}
  1316. X
  1317. X
  1318. Xstatic WidgetClass * get_pushbutton_class()
  1319. X{
  1320. X    return &xmPushButtonGadgetClass;
  1321. X}
  1322. X
  1323. X
  1324. Xstatic char * get_pushbutton_callback()
  1325. X{
  1326. X    return XmNactivateCallback;
  1327. X}
  1328. X
  1329. X
  1330. Xstatic WidgetClass * get_separator_class()
  1331. X{
  1332. X    return &xmSeparatorGadgetClass;
  1333. X}
  1334. X
  1335. X
  1336. Xstatic char * get_separator_callback()
  1337. X{
  1338. X    return (char *)0;
  1339. X}
  1340. X
  1341. X
  1342. Xstatic WidgetClass * get_togglebutton_class()
  1343. X{
  1344. X    return &xmToggleButtonGadgetClass;
  1345. X}
  1346. X
  1347. X
  1348. Xstatic char * get_togglebutton_callback()
  1349. X{
  1350. X    return XmNvalueChangedCallback;
  1351. X}
  1352. X
  1353. X
  1354. X#endif
  1355. X
  1356. X
  1357. X#ifdef ATHENA
  1358. X
  1359. Xmenu_type global_action_menu; /* We need to have a global menu object,
  1360. X                 because actions do not pass client_data */
  1361. X
  1362. Xstatic void menu_action(/* w, event, params, num_params*/);
  1363. X
  1364. Xstatic void create_menubar( menu, form, name)
  1365. Xmenu_type menu;
  1366. XWidget    form;
  1367. Xchar *    name;
  1368. X{
  1369. X    XtActionsRec  action;
  1370. X
  1371. X
  1372. X    menu->menubar = 
  1373. X        XtVaCreateManagedWidget( name, boxWidgetClass, form,
  1374. X                                 XtNorientation, XtorientHorizontal,
  1375. X                                 XtNresizable,   True,
  1376. X                                 NULL);
  1377. X
  1378. X    menu->off_bitmap = 
  1379. X        XCreateBitmapFromData( XtDisplay( form),
  1380. X                               RootWindowOfScreen( XtScreen( form)),
  1381. X                               off_bits, off_width, off_height);
  1382. X    menu->on_bitmap = 
  1383. X        XCreateBitmapFromData( XtDisplay( form),
  1384. X                               RootWindowOfScreen( XtScreen( form)),
  1385. X                               on_bits, on_width, on_height);
  1386. X
  1387. X
  1388. X    global_action_menu = menu;
  1389. X
  1390. X    /* Add a global action for menu actions */
  1391. X    /* Athena needs global actions to implement "menu accelerators" */
  1392. X    action.string = "menu_action";
  1393. X    action.proc   =  menu_action;
  1394. X    XtAppAddActions( XtWidgetToApplicationContext( menu->menubar),
  1395. X                     &action, (Cardinal)1);
  1396. X}
  1397. X
  1398. X
  1399. X/* Sets the toggle widget to the specified value and performs menu
  1400. X   callbacks to inform of the new value */
  1401. Xstatic void set_widget_and_do_callback( menu, w, set)
  1402. Xmenu_type menu;
  1403. XWidget    w;
  1404. XBool      set;
  1405. X{
  1406. X    /* We set the toggle to the opposite of what we finally want,
  1407. X       because of the way the Athena menu callback works with toggles is that
  1408. X       it toggles the value for each callback. */
  1409. X
  1410. X    set_widget_state( menu, w, !set);
  1411. X
  1412. X    XtCallCallbacks( w, XtNcallback, (char *)0);
  1413. X}
  1414. X
  1415. X
  1416. X/* Set the state of the athena menu "toggle" widget */
  1417. Xstatic void set_widget_state( menu, w, state)
  1418. Xmenu_type menu;
  1419. XWidget    w;
  1420. XBool      state;
  1421. X{
  1422. X    XtVaSetValues(w, XtNleftBitmap, state ? menu->on_bitmap : menu->off_bitmap,
  1423. X                  NULL);
  1424. X}
  1425. X
  1426. X
  1427. X/* Returns the state of the Athena menu "toggle" widget */
  1428. Xstatic Bool get_widget_state( menu, w)
  1429. Xmenu_type menu;
  1430. XWidget    w;
  1431. X{
  1432. X    Pixmap pixmap_set;
  1433. X
  1434. X
  1435. X    XtVaGetValues( w, XtNleftBitmap, &pixmap_set, NULL);
  1436. X
  1437. X    return (pixmap_set == menu->on_bitmap);
  1438. X}
  1439. X
  1440. X
  1441. X/* Create the Athena pulldown widget */
  1442. Xstatic Widget create_pulldown( menubar, menu_button_name, pull_down_name)
  1443. XWidget menubar;
  1444. Xchar * menu_button_name;
  1445. Xchar * pull_down_name;
  1446. X{
  1447. X    Widget button;
  1448. X    Widget pull_down;
  1449. X
  1450. X
  1451. X    button = XtVaCreateManagedWidget( menu_button_name, menuButtonWidgetClass, 
  1452. X                      menubar, NULL);
  1453. X
  1454. X    pull_down = XtCreatePopupShell( "menu", simpleMenuWidgetClass, button, 
  1455. X                    NULL, 0);
  1456. X
  1457. X    return pull_down;
  1458. X}
  1459. X
  1460. X
  1461. Xstatic WidgetClass * get_pushbutton_class()
  1462. X{
  1463. X    return &smeBSBObjectClass;
  1464. X}
  1465. X
  1466. X
  1467. Xstatic char * get_pushbutton_callback()
  1468. X{
  1469. X    return XtNcallback;
  1470. X}
  1471. X
  1472. X
  1473. Xstatic WidgetClass * get_separator_class()
  1474. X{
  1475. X    return &smeLineObjectClass;
  1476. X}
  1477. X
  1478. X
  1479. Xstatic char * get_separator_callback()
  1480. X{
  1481. X    return (char *)0;
  1482. X}
  1483. X
  1484. X
  1485. Xstatic WidgetClass * get_togglebutton_class()
  1486. X{
  1487. X    return &smeBSBObjectClass;
  1488. X}
  1489. X
  1490. X
  1491. Xstatic char *get_togglebutton_callback()
  1492. X{
  1493. X    return XtNcallback;
  1494. X}
  1495. X
  1496. X
  1497. X/* This global action is used to implement keyboard accelerators in
  1498. X   Athena.  To get a keyboard accelerator, a widget sets it translations
  1499. X   to call the global "menu_callback" action, passing the menu action
  1500. X   they want to perform. */
  1501. Xstatic void menu_action( w, event, params, num_params)
  1502. XWidget   w;
  1503. XXEvent * event;
  1504. XString * params;
  1505. XCardinal num_params;
  1506. X{
  1507. X    char buff[50];
  1508. X    menu_type menu = global_action_menu;
  1509. X
  1510. X
  1511. X    /* Get the action name passed to the menu_action */
  1512. X    if (num_params < 1)
  1513. X    {
  1514. X        fprintf(stderr,
  1515. X                "No menu action name passed to the menu_action action\n");
  1516. X        return;
  1517. X    }
  1518. X
  1519. X
  1520. X    /* Type of menu action is passed to the action */
  1521. X    w = get_menu_widget( menu, params[0]);
  1522. X
  1523. X    if (w == (Widget)0)
  1524. X      return;
  1525. X    
  1526. X    menu_callback( w, menu, NULL);
  1527. X}
  1528. X
  1529. X#endif
  1530. END_OF_FILE
  1531. if test 18009 -ne `wc -c <'menu.c'`; then
  1532.     echo shar: \"'menu.c'\" unpacked with wrong size!
  1533. fi
  1534. # end of 'menu.c'
  1535. fi
  1536. if test -f 'room.c' -a "${1}" != "-c" ; then 
  1537.   echo shar: Will not clobber existing file \"'room.c'\"
  1538. else
  1539. echo shar: Extracting \"'room.c'\" \(15176 characters\)
  1540. sed "s/^X//" >'room.c' <<'END_OF_FILE'
  1541. X/**********************************************************************
  1542. X * room.c - Room object definition
  1543. X *
  1544. X * Copyright 1993, David Nedde
  1545. X *
  1546. X * Permission to use, copy, modify, and distribute this software
  1547. X * and its documentation for any purpose and without fee is granted
  1548. X * provided that the above copyright notice appears in all copies.
  1549. X * It is provided "as is" without express or implied warranty.
  1550. X **********************************************************************/
  1551. X
  1552. X/* System Headers */
  1553. X#include <stdio.h>
  1554. X
  1555. X#include <X11/Intrinsic.h>
  1556. X#include <X11/StringDefs.h>
  1557. X#include <X11/cursorfont.h>
  1558. X
  1559. X#ifdef MOTIF
  1560. X#include <Xm/DrawingA.h>
  1561. X#endif
  1562. X
  1563. X#ifdef ATHENA
  1564. X#include <X11/Xaw_d/DrawingA.h>
  1565. X#endif
  1566. X
  1567. X/* Local headers */
  1568. X#include "room.h"
  1569. X#include "misc.h"
  1570. X#include "scrollbar.h"
  1571. X
  1572. X/* Macros */
  1573. X/* This is the spacing between the balls representing pixels on the bitmap */
  1574. X#define SF 1.5  /* FIX - make a resource */
  1575. X
  1576. X/* Functions */
  1577. Xstatic void redisplay_cb(/*w, room, call_data*/);
  1578. Xstatic void resize_cb(/*w, datap_ptr, call_data*/);
  1579. Xstatic void process_input_cb(/*w, room, call_data*/);
  1580. Xstatic void wait_for_resize(/* room*/);
  1581. Xstatic Widget create_canvas(/* parent, name*/);
  1582. X
  1583. X
  1584. X/* Object public methods */
  1585. X
  1586. X/* Create the room object */
  1587. Xroom_type room__create( form_w, items, file_sel)
  1588. XWidget        form_w;
  1589. Xitems_type    items;
  1590. Xfile_sel_type file_sel;
  1591. X{
  1592. X    Dimension right_wall;
  1593. X    Dimension floor;
  1594. X
  1595. X
  1596. X    Widget canvas;
  1597. X
  1598. X    room_type room = XtNew( room_struct_type);
  1599. X
  1600. X    room->item       = (item_type)0;
  1601. X    room->items      = items;
  1602. X    room->file_sel   = file_sel;
  1603. X    room->left_wall  = int2intf(0);
  1604. X    room->ceiling    = int2intf(0);
  1605. X    /* room->gravity is set in xball_sys via scrollbar callback */
  1606. X
  1607. X    room->button1 = False;
  1608. X    room->button2 = False;
  1609. X    room->button3 = False;
  1610. X
  1611. X
  1612. X    room->canvas = canvas = create_canvas( room, form_w, "canvas");
  1613. X
  1614. X    XtVaGetValues(canvas, 
  1615. X          XtNbackground,  &room->background, 
  1616. X          XtNwidth,      &right_wall,
  1617. X          XtNheight,       &floor,
  1618. X          NULL);
  1619. X
  1620. X    room->right_wall = int2intf( right_wall);
  1621. X    room->floor      = int2intf( floor);
  1622. X
  1623. X    return room;
  1624. X}
  1625. X
  1626. X
  1627. X/* Destroy the room object */
  1628. Xvoid room__destroy( room)
  1629. Xroom_type room;
  1630. X{
  1631. X    XtDestroyWidget( room->canvas);
  1632. X    XtFree( (char *)room);
  1633. X}
  1634. X
  1635. X
  1636. X/* Called when the scrollbar changes.  Sets the gravity value */
  1637. Xvoid room__set_gravity_cb(w, room, call_data)
  1638. XWidget                    w;
  1639. Xroom_type                 room;
  1640. XscrollbarCallbackStruct * call_data;
  1641. X{
  1642. X    room->gravity = call_data->value;
  1643. X}
  1644. X
  1645. X
  1646. X/* A menu callback that clears the room of all balls */
  1647. Xvoid room__clear_mcb(w, room, call_data, extra)
  1648. XWidget    w;
  1649. Xroom_type room;
  1650. Xcaddr_t   call_data;
  1651. Xchar *    extra;
  1652. X{
  1653. X    items__destroy_all( room->items);
  1654. X}
  1655. X
  1656. X
  1657. X/* A menu callback that randomizes all balls in the room */
  1658. Xvoid room__randomize_mcb(w, room, call_data, extra)
  1659. XWidget    w;
  1660. Xroom_type room;
  1661. Xcaddr_t   call_data;
  1662. Xchar *    extra;
  1663. X{
  1664. X    item_type item;
  1665. X
  1666. X
  1667. X    for (item = items__get_first( room->items);
  1668. X         item != (item_type)0;
  1669. X         item = items__get_next( room->items))
  1670. X    {
  1671. X        item__randomize( item, -16, 16, -16, 16);
  1672. X    }
  1673. X}
  1674. X
  1675. X
  1676. X/* A menu callback that queries the user for a bitmap and then loads it */
  1677. Xvoid room__load_bitmap_mcb(w, room, call_data, extra)
  1678. XWidget    w;
  1679. Xroom_type room;
  1680. Xcaddr_t   call_data;
  1681. Xchar *    extra;
  1682. X{
  1683. X    char *file_name = file_sel__display( room->file_sel, "Load Bitmap");
  1684. X
  1685. X    if (file_name != (char *)0)
  1686. X        room__load_bitmap( room, file_name, 10, 10);
  1687. X}
  1688. X
  1689. X
  1690. X/* Loads the specified bitmap file at the specified position in the room */
  1691. Xvoid room__load_bitmap(room, filename, pos_x, pos_y)
  1692. Xroom_type room;
  1693. Xchar *    filename;
  1694. Xint       pos_x;
  1695. Xint       pos_y;
  1696. X{
  1697. X    unsigned  width, height;  /* Bitmap dimensions */
  1698. X    int       x_hot, y_hot;
  1699. X    Pixmap    bitmap;         /* The bitmap as a pixmap */
  1700. X    XImage *  ximage;         /* The bitmap as an image */
  1701. X    int       x, y;
  1702. X    int       status;
  1703. X    Dimension new_width, new_height;
  1704. X
  1705. X
  1706. X    status = XReadBitmapFile(XtDisplay(room->canvas), XtWindow(room->canvas),
  1707. X                             filename, &width, &height, &bitmap, 
  1708. X                             &x_hot, &y_hot);
  1709. X    switch (status)
  1710. X    {
  1711. X        case BitmapOpenFailed: 
  1712. X        fprintf(stderr,
  1713. X                "room__load_bitmap: Could not open bitmap file %s\n",filename);
  1714. X        return;
  1715. X        break;
  1716. X
  1717. X        case BitmapFileInvalid: 
  1718. X        fprintf(stderr,
  1719. X             "room__load_bitmap: Bitmap file %s does not contain valid data\n",
  1720. X             filename);
  1721. X        return;
  1722. X        break;
  1723. X
  1724. X        case BitmapNoMemory: 
  1725. X        fprintf(stderr,
  1726. X              "room__load_bitmap: Not enough memory to open bitmap file %s\n",
  1727. X              filename);
  1728. X        return;
  1729. X        break;
  1730. X    }
  1731. X
  1732. X    /* Get a local copy of the pixmap so we can query the pixel values */
  1733. X    ximage = XGetImage(XtDisplay(room->canvas),
  1734. X                       bitmap,0,0,width,height,AllPlanes,XYPixmap);
  1735. X    if (ximage == NULL)
  1736. X    {
  1737. X        fprintf(stderr,"room__load_bitmap: Problem getting bitmap image\n");
  1738. X        return;
  1739. X    }
  1740. X
  1741. X    new_width  = MAX( intf2int(room->right_wall), 
  1742. X                      pos_x + width  * item__get_width()  * SF+10);
  1743. X    new_height = MAX( intf2int(room->floor),      
  1744. X                      pos_y + height * item__get_height() * SF+10);
  1745. X
  1746. X    if (new_width  != intf2int(room->right_wall) ||
  1747. X        new_height != intf2int(room->floor))
  1748. X    {
  1749. X        room->resized = False;
  1750. X
  1751. X        /* Set the window width and height so the balls fit on it */
  1752. X        XtVaSetValues(room->canvas,
  1753. X                      XtNwidth,  new_width,
  1754. X                      XtNheight, new_height,
  1755. X                      NULL);
  1756. X
  1757. X        wait_for_resize( room);
  1758. X    }
  1759. X
  1760. X    /* Create a ball for each pixel set in the bitmap */
  1761. X    for (y = 0; y < height; y++)
  1762. X    {
  1763. X        for (x = 0; x < width; x++)
  1764. X        {
  1765. X            if (XGetPixel(ximage, x, y))
  1766. X                items__new_item(room->items, 
  1767. X                                (int)(x * item__get_width()  * SF + pos_x),
  1768. X                                (int)(y * item__get_height() * SF + pos_y),
  1769. X                                /*x_vel*/0, /*y_vel*/0);
  1770. X        }
  1771. X    }
  1772. X}
  1773. X
  1774. X
  1775. X
  1776. X/* Set the room's width and wait for the window to resize before returning */
  1777. Xvoid room__set_width(room, width)
  1778. Xroom_type room;
  1779. Xint       width;
  1780. X{
  1781. X    Dimension d_width = width;
  1782. X
  1783. X
  1784. X    if (intf2int(room->right_wall) == width)
  1785. X        return;
  1786. X
  1787. X    room->resized = False;
  1788. X
  1789. X    XtVaSetValues(room->canvas,
  1790. X                  XtNwidth,       d_width,
  1791. X                  NULL);
  1792. X
  1793. X    /* room->right_wall = int2intf(width); Set in window resize callback */
  1794. X
  1795. X    wait_for_resize( room);
  1796. X}
  1797. X
  1798. X
  1799. X/* Set the height of the room, resize the actual room and wait for it
  1800. X   to resize before returning. */
  1801. Xvoid room__set_height(room, height)
  1802. Xroom_type room;
  1803. XDimension height;
  1804. X{
  1805. X    Dimension d_height = height;
  1806. X
  1807. X
  1808. X    if (intf2int(room->floor) == height)
  1809. X        return;
  1810. X
  1811. X    room->resized = False;
  1812. X
  1813. X    XtVaSetValues(room->canvas,
  1814. X                  XtNheight,       d_height,
  1815. X                  NULL);
  1816. X
  1817. X    /* room->floor = int2intf(height); set in the window resize callback */
  1818. X
  1819. X    wait_for_resize( room);
  1820. X}
  1821. X
  1822. X
  1823. X/* Private object methods */
  1824. X
  1825. X
  1826. X/**********************************************************************
  1827. X * redisplay - Called when DrawingArea canvas gets an expose event
  1828. X *             Redraws all balls in room
  1829. X **********************************************************************/
  1830. Xstatic void redisplay(room, event)
  1831. Xroom_type room;
  1832. XXEvent *  event;
  1833. X{
  1834. X    Display * display = XtDisplay( room->canvas);
  1835. X    Window    window  = XtWindow ( room->canvas);
  1836. X
  1837. X
  1838. X    if (!item__initted())
  1839. X    {
  1840. X        Cursor cursor = XCreateFontCursor( display, XC_watch );
  1841. X        XDefineCursor( display, window, cursor);
  1842. X
  1843. X        item__init( get_toplevel( room->canvas), display, window, 
  1844. X            room->background);
  1845. X
  1846. X    XFreeCursor( display, cursor);
  1847. X    XUndefineCursor( display, window);
  1848. X    }
  1849. X
  1850. X
  1851. X    if (event->xexpose.count == 0) /* Wait until last expose event*/
  1852. X    {
  1853. X        item_type item;
  1854. X
  1855. X        XClearWindow( display, window);
  1856. X
  1857. X        for (item = items__get_first( room->items);
  1858. X             item != (item_type)0;
  1859. X             item = items__get_next( room->items))
  1860. X        {
  1861. X            item__redraw( item);
  1862. X        }
  1863. X    }
  1864. X}
  1865. X
  1866. X
  1867. X/**********************************************************************
  1868. X * resize_cb - Called when DrawingArea canvas is resized
  1869. X *             Adjusts the right wall and floor
  1870. X **********************************************************************/
  1871. Xstatic void resize_cb(w, room, call_data)
  1872. XWidget    w;
  1873. Xroom_type room;
  1874. Xcaddr_t   call_data;
  1875. X{
  1876. X    Dimension     width,height;
  1877. X
  1878. X    XtVaGetValues(w,
  1879. X                  XtNwidth,       &width, 
  1880. X                  XtNheight,      &height,        
  1881. X                  NULL);
  1882. X
  1883. X    room->right_wall = int2intf(width);
  1884. X    room->floor      = int2intf(height);
  1885. X
  1886. X    /* Set flag in case someone is waiting for the resize */
  1887. X    room->resized = True;
  1888. X}
  1889. X
  1890. X/* Waits for the window to actually resize.  This depends on the
  1891. X   resize callback code setting the room->resized flag to True.  Callers
  1892. X   should set the room->resized flag to False before calling.  */
  1893. Xstatic void wait_for_resize( room)
  1894. Xroom_type room;
  1895. X{
  1896. X    XEvent        event;
  1897. X    XtAppContext  app_context;
  1898. X
  1899. X
  1900. X    app_context = XtWidgetToApplicationContext( room->canvas);
  1901. X
  1902. X    /* Wait for the window resize to occur */
  1903. X    while (!room->resized)
  1904. X    {
  1905. X        XtAppNextEvent(app_context, &event);
  1906. X        XtDispatchEvent(&event);
  1907. X    }
  1908. X}
  1909. X
  1910. X
  1911. X/**********************************************************************
  1912. X * process_input - Called when DrawingArea canvas has input
  1913. X *                 Handles mouse button events
  1914. X **********************************************************************/
  1915. Xstatic void process_input( room, event)
  1916. Xroom_type room;
  1917. XXEvent *  event;
  1918. X{
  1919. X    switch (event->type)
  1920. X    {
  1921. X        /* Process mouse button events */
  1922. X        case ButtonPress:
  1923. X        switch (event->xbutton.button) 
  1924. X        {
  1925. X            case 1:
  1926. X            /* Button 1 - Create 1 item under the pointer */
  1927. X
  1928. X            room->oldx = room->newx = event->xbutton.x;
  1929. X            room->oldy = room->newy = event->xbutton.y;
  1930. X
  1931. X            /* Create an item under the pointer */
  1932. X            room->item = item__create(event->xbutton.x, 
  1933. X                                      event->xbutton.y, 
  1934. X                                      /*x,y velocity*/ 0, 0);
  1935. X
  1936. X            room->button1 = True;
  1937. X            break;
  1938. X
  1939. X            /* Remember the button we have pressed (used in mouse motion) */
  1940. X            case 2:  room->button2 = True; break;
  1941. X            case 3:  room->button3 = True; break;
  1942. X        }
  1943. X        break;
  1944. X
  1945. X        case ButtonRelease:
  1946. X        switch (event->xbutton.button) 
  1947. X        {
  1948. X            /* button 1 release - move item to items list */
  1949. X            case 1: 
  1950. X            item__set_x_vel( room->item, room->newx - room->oldx);
  1951. X            item__set_y_vel( room->item, room->newy - room->oldy);
  1952. X
  1953. X            items__add( room->items, room->item);
  1954. X            room->item = (item_type)0;
  1955. X                               
  1956. X            room->button1 = False;
  1957. X            break;
  1958. X
  1959. X            /* Remember the button we have unpressed (used in mouse motion) */
  1960. X            case 2:  room->button2 = False; break;
  1961. X            case 3:  room->button3 = False; break;
  1962. X        }       
  1963. X    }
  1964. X}
  1965. X
  1966. X
  1967. X/**********************************************************************
  1968. X * process_motion - Called when DrawingArea canvas have pointer motion events
  1969. X **********************************************************************/
  1970. Xstatic  void process_motion( room, event)
  1971. Xroom_type room;
  1972. XXEvent *  event;
  1973. X{
  1974. X    if (room->button1)
  1975. X    {
  1976. X        /* When button 1 pressed during movement */
  1977. X        /* Save 'speed' of pointer for when the button is released */
  1978. X        room->oldx = room->newx;  
  1979. X        room->oldy = room->newy;
  1980. X        room->newx = event->xmotion.x;
  1981. X        room->newy = event->xmotion.y;
  1982. X
  1983. X        item__set_x_vel( room->item, (room->newx - room->oldx));
  1984. X        item__set_y_vel( room->item, (room->newy - room->oldy));
  1985. X
  1986. X        item__move_pos( room->item, 
  1987. X                        event->xmotion.x, event->xmotion.y);
  1988. X    } 
  1989. X    else 
  1990. X    if (room->button2)
  1991. X    {
  1992. X        /* Create a random velocity ball */
  1993. X        items__new_item(room->items, event->xmotion.x, event->xmotion.y,
  1994. X                        rand_range( -8, 8),
  1995. X                        rand_range( -8, 0));
  1996. X    }
  1997. X    else
  1998. X    if (room->button3)
  1999. X    {
  2000. X        items__new_item(room->items, event->xmotion.x, event->xmotion.y,
  2001. X                        0, 0);
  2002. X    }
  2003. X}
  2004. X
  2005. X
  2006. X#ifdef MOTIF
  2007. X
  2008. Xstatic void process_motion_act(/*w, datap_ptr, event*/);
  2009. X
  2010. X
  2011. X/* Create motif canvas as a DrawingArea Widget */
  2012. Xstatic Widget create_canvas( room, parent, name)
  2013. Xroom_type room;
  2014. XWidget    parent;
  2015. Xchar *    name;
  2016. X{
  2017. X    Widget canvas =
  2018. X        XtCreateManagedWidget("canvas", xmDrawingAreaWidgetClass, parent, 
  2019. X                              NULL, 0);
  2020. X
  2021. X    XtAddCallback(canvas, XmNexposeCallback, redisplay_cb,    (XtPointer)room);
  2022. X    XtAddCallback(canvas, XmNinputCallback,  process_input_cb,(XtPointer)room);
  2023. X    XtAddCallback(canvas, XmNresizeCallback, resize_cb,       (XtPointer)room);
  2024. X    XtAddEventHandler(canvas, ButtonMotionMask, FALSE, 
  2025. X                      process_motion_act, (XtPointer)room);
  2026. X
  2027. X    return canvas;
  2028. X}
  2029. X
  2030. X
  2031. Xstatic void redisplay_cb(w, room, call_data)
  2032. XWidget                         w;
  2033. Xroom_type                      room;
  2034. XXmDrawingAreaCallbackStruct *  call_data;
  2035. X{
  2036. X    redisplay( room, call_data->event);
  2037. X}
  2038. X
  2039. X
  2040. Xstatic void process_input_cb(w, room, call_data)
  2041. XWidget                        w;
  2042. Xroom_type                     room;
  2043. XXmDrawingAreaCallbackStruct * call_data;
  2044. X{
  2045. X    process_input( room, call_data->event);
  2046. X}
  2047. X
  2048. X
  2049. Xstatic void process_motion_act(w, room, event)
  2050. XWidget    w;
  2051. Xroom_type room;
  2052. XXEvent *  event;
  2053. X{
  2054. X    process_motion( room, event);
  2055. X}
  2056. X
  2057. X#endif
  2058. X
  2059. X
  2060. X#ifdef ATHENA
  2061. X
  2062. X
  2063. Xstatic void process_motion_cb(/*w, room, call_data*/);
  2064. X
  2065. X
  2066. X/* Create canvas as a DrawingArea widget */
  2067. Xstatic Widget create_canvas( room, parent, name)
  2068. Xroom_type room;
  2069. XWidget    parent;
  2070. Xchar *    name;
  2071. X{
  2072. X    Widget canvas =
  2073. X        XtCreateManagedWidget("canvas", drawingAreaWidgetClass, parent, 
  2074. X                              NULL, 0);
  2075. X
  2076. X    XtAddCallback(canvas,XtNexposeCallback,redisplay_cb,      (XtPointer)room);
  2077. X    XtAddCallback(canvas,XtNinputCallback, process_input_cb,  (XtPointer)room);
  2078. X    XtAddCallback(canvas,XtNresizeCallback,resize_cb,         (XtPointer)room);
  2079. X    XtAddCallback(canvas,XtNmotionCallback,process_motion_cb, (XtPointer)room);
  2080. X
  2081. X    return canvas;
  2082. X}
  2083. X
  2084. X
  2085. Xstatic void redisplay_cb(w, room, call_data)
  2086. XWidget                         w;
  2087. Xroom_type                      room;
  2088. XXawDrawingAreaCallbackStruct * call_data;
  2089. X{
  2090. X    redisplay( room, call_data->event);
  2091. X}
  2092. X
  2093. X
  2094. Xstatic void process_input_cb(w, room, call_data)
  2095. XWidget                         w;
  2096. Xroom_type                      room;
  2097. XXawDrawingAreaCallbackStruct * call_data;
  2098. X{
  2099. X    process_input( room, call_data->event);
  2100. X}
  2101. X
  2102. X
  2103. Xstatic void process_motion_cb(w, room, call_data)
  2104. XWidget                         w;
  2105. Xroom_type                room;
  2106. XXawDrawingAreaCallbackStruct * call_data;
  2107. X{
  2108. X    process_motion( room, call_data->event);
  2109. X}
  2110. X
  2111. X
  2112. X#endif
  2113. X
  2114. END_OF_FILE
  2115. if test 15176 -ne `wc -c <'room.c'`; then
  2116.     echo shar: \"'room.c'\" unpacked with wrong size!
  2117. fi
  2118. # end of 'room.c'
  2119. fi
  2120. if test -f 'scrollbar.c' -a "${1}" != "-c" ; then 
  2121.   echo shar: Will not clobber existing file \"'scrollbar.c'\"
  2122. else
  2123. echo shar: Extracting \"'scrollbar.c'\" \(10512 characters\)
  2124. sed "s/^X//" >'scrollbar.c' <<'END_OF_FILE'
  2125. X/**********************************************************************
  2126. X * scrollbar.c
  2127. X *
  2128. X * Copyright 1993, David Nedde
  2129. X *
  2130. X * Permission to use, copy, modify, and distribute this software
  2131. X * and its documentation for any purpose and without fee is granted
  2132. X * provided that the above copyright notice appears in all copies.
  2133. X * It is provided "as is" without express or implied warranty.
  2134. X **********************************************************************/
  2135. X
  2136. X/* System Headers */
  2137. X#ifdef MOTIF
  2138. X#include <Xm/Scale.h>
  2139. X#include <Xm/Label.h>
  2140. X#include <Xm/Form.h>
  2141. X#endif
  2142. X
  2143. X#ifdef ATHENA
  2144. X#include <X11/Intrinsic.h>
  2145. X#include <X11/StringDefs.h>
  2146. X#include <X11/Xaw/Scrollbar.h>
  2147. X#include <X11/Xaw/Label.h>
  2148. X#include <X11/Xaw/Text.h>
  2149. X#include <X11/Xaw/Form.h>
  2150. X#endif
  2151. X
  2152. X/* Local headers */
  2153. X#include "scrollbar.h"
  2154. X#include "misc.h"
  2155. X
  2156. X/* Structures */
  2157. X/* A node in the scrollbar callbacks list */
  2158. Xtypedef struct {
  2159. X    scrollbarCallbackProc proc;
  2160. X    caddr_t               closure;
  2161. X} callback_node;
  2162. X
  2163. X/* Functions */
  2164. Xvoid create_widgets(/* scrollbar, parent, name*/);
  2165. Xstatic void call_callbacks(/* scrollbar, value*/);
  2166. X
  2167. X
  2168. X/* Public object methods */
  2169. X
  2170. X/* Creates a scrollbar object.  Consists of a label, a scrollbar and a
  2171. X   label giving feedback to the user */
  2172. Xscrollbar_type scrollbar__create( parent, name)
  2173. XWidget   parent;
  2174. Xchar *   name;
  2175. X{
  2176. X    scrollbar_type scrollbar;
  2177. X
  2178. X
  2179. X    scrollbar = XtNew( scrollbar_struct);
  2180. X
  2181. X    /* We need to have our own callback list, because callbacks from
  2182. X       Motif and Athea are so different */
  2183. X    scrollbar->callbacks = list__create();
  2184. X
  2185. X    create_widgets( scrollbar, parent, name);
  2186. X
  2187. X    return scrollbar;
  2188. X}
  2189. X
  2190. X
  2191. X/* Destroy the scrollbar object */
  2192. Xvoid scrollbar__destroy( scrollbar)
  2193. Xscrollbar_type scrollbar;
  2194. X{
  2195. X    int i;
  2196. X
  2197. X
  2198. X    for (i = 0; i < list__get_count( scrollbar->callbacks); i++)
  2199. X    {
  2200. X        free( list__get_cell( scrollbar->callbacks, i));
  2201. X    }
  2202. X    list__destroy( scrollbar->callbacks);
  2203. X
  2204. X    XtDestroyWidget( scrollbar->scale);
  2205. X    XtDestroyWidget( scrollbar->label);
  2206. X    XtFree( (char *)scrollbar);
  2207. X}
  2208. X
  2209. X
  2210. X/* Set the value of the scrollbar and make any callbacks */
  2211. Xvoid scrollbar__set_value( scrollbar, value)
  2212. Xscrollbar_type scrollbar;
  2213. Xint value;
  2214. X{
  2215. X    scrollbar->value = value;
  2216. X
  2217. X    scale_set_value( scrollbar, value);
  2218. X
  2219. X    call_callbacks( scrollbar, value);
  2220. X}
  2221. X
  2222. X
  2223. X/* Add a scrollbar callback.  When the scrollbar value changes, the
  2224. X   proc will be called back with a scrollbarCallbackStruct. */
  2225. Xvoid scrollbar__add_callback( scrollbar, proc, closure)
  2226. Xscrollbar_type scrollbar;
  2227. XXtCallbackProc proc;
  2228. XXtPointer      closure;
  2229. X{
  2230. X    callback_node *node_ptr = (callback_node *)malloc( sizeof( callback_node));
  2231. X    
  2232. X
  2233. X    node_ptr->proc    = proc;
  2234. X    node_ptr->closure = closure;
  2235. X
  2236. X    list__add_end( scrollbar->callbacks, node_ptr);
  2237. X}
  2238. X
  2239. X
  2240. X
  2241. X/* Private object methods */
  2242. X
  2243. X/* Make the scrollbar callbacks */
  2244. Xstatic void call_callbacks( scrollbar, value)
  2245. Xscrollbar_type scrollbar;
  2246. Xint            value;
  2247. X{
  2248. X    int                     i;
  2249. X    callback_node *         node_ptr;
  2250. X    scrollbarCallbackStruct scrollbar_call_data;
  2251. X
  2252. X
  2253. X    scrollbar_call_data.reason = 0;
  2254. X    scrollbar_call_data.event  = 0;
  2255. X    scrollbar_call_data.pixel  = 0;
  2256. X    scrollbar_call_data.value  = value;
  2257. X
  2258. X    for (i = 0; i < list__get_count( scrollbar->callbacks); i++)
  2259. X    {
  2260. X        node_ptr = (callback_node *)list__get_cell( scrollbar->callbacks, i);
  2261. X        (*node_ptr->proc)( scrollbar->scale, node_ptr->closure, 
  2262. X                           &scrollbar_call_data);
  2263. X    }
  2264. X}
  2265. X
  2266. X
  2267. X#ifdef MOTIF
  2268. X
  2269. X/* Called when the motif scrollbar moves.  Makes all registered
  2270. X   scrollbar callbacks */
  2271. Xstatic void scrollbar_callback( w, scrollbar, call_data)
  2272. XWidget         w;
  2273. Xscrollbar_type scrollbar;
  2274. Xcaddr_t        call_data;
  2275. X{
  2276. X    call_callbacks( scrollbar, 
  2277. X            ((XmScaleCallbackStruct *)call_data)->value);
  2278. X}
  2279. X
  2280. X
  2281. X#ifdef NOTUSED
  2282. X
  2283. X/* Returns the scrollbar widget's value */
  2284. Xstatic int scrollbar_get_value( scrollbar)
  2285. Xscrollbar_type scrollbar;
  2286. X{
  2287. X    int value;
  2288. X
  2289. X    XmScaleGetValue( scrollbar->scale, &value);
  2290. X
  2291. X    return value;
  2292. X}
  2293. X
  2294. X#endif
  2295. X
  2296. X
  2297. X/* Sets the scrollbar widget's value */
  2298. Xstatic int scale_set_value( scrollbar, value)
  2299. Xscrollbar_type scrollbar;
  2300. Xint value;
  2301. X{
  2302. X    XmScaleSetValue( scrollbar->scale, value);
  2303. X}
  2304. X
  2305. X
  2306. X/* Creates the scrollbar widgets */
  2307. Xvoid create_widgets( scrollbar, parent, name)
  2308. Xscrollbar_type scrollbar;
  2309. XWidget         parent;
  2310. Xchar *         name;
  2311. X{
  2312. X    scrollbar->form =
  2313. X        XtVaCreateManagedWidget(name, xmFormWidgetClass, parent,
  2314. X                                NULL);
  2315. X        
  2316. X    scrollbar->label = 
  2317. X        XtVaCreateManagedWidget("label", xmLabelWidgetClass, scrollbar->form,
  2318. X                                NULL);
  2319. X    scrollbar->scale = 
  2320. X        XtVaCreateManagedWidget("bar", xmScaleWidgetClass, scrollbar->form, 
  2321. X                                XmNleftAttachment, XmATTACH_WIDGET,
  2322. X                                XmNleftWidget,     scrollbar->label,
  2323. X                                NULL);
  2324. X
  2325. X    XmScaleGetValue( scrollbar->scale, &scrollbar->value);
  2326. X
  2327. X    XtAddCallback( scrollbar->scale, XmNvalueChangedCallback, 
  2328. X                   scrollbar_callback, (XtPointer)scrollbar);
  2329. X    XtAddCallback( scrollbar->scale, XmNdragCallback, 
  2330. X                   scrollbar_callback, (XtPointer)scrollbar);
  2331. X}
  2332. X
  2333. X#endif
  2334. X
  2335. X
  2336. X#ifdef ATHENA
  2337. X
  2338. X/* Functions */
  2339. Xstatic void set_feedback_value(/* scrollbar, value*/);
  2340. Xstatic void move_thumb(/* scrollbar, thumb, shown*/);
  2341. Xstatic void set_label_value(/* label_w, value*/);
  2342. X
  2343. X
  2344. X/* Macros */
  2345. X#define SB_MAX 100.0
  2346. X#define SB_MIN   0.0
  2347. X
  2348. X#define thumb_to_value( thumb, shown) \
  2349. X            ((int)((thumb) / (1-(shown))* (SB_MAX - SB_MIN) + 0.5 - SB_MIN))
  2350. X#define value_to_thumb( value, shown) \
  2351. X            ((value)*(1-(shown) + SB_MIN) / (SB_MAX - SB_MIN))
  2352. X
  2353. X
  2354. X/* Called when the athena scrollbar is scrolled incrementally.
  2355. X   Updates the feedback value and makes all registered callbacks. */
  2356. Xstatic void scrollbar_scroll_callback( w, scrollbar, position_ptr)
  2357. XWidget         w;
  2358. Xscrollbar_type scrollbar;
  2359. XXtPointer      position_ptr;
  2360. X{
  2361. X    Dimension     length;
  2362. X    float         thumb;
  2363. X    float         shown;
  2364. X    int           position = (int)position_ptr;
  2365. X    float         change; /* 0.0 .. 1.0 - percentage of full-page change 
  2366. X                             we should do */
  2367. X
  2368. X
  2369. X    /* Position is the number of pixels from left of scrollbar pointer is.
  2370. X       Position > 0 indicates button 1, position < 0 indicates button 3 */
  2371. X
  2372. X
  2373. X    XtVaGetValues( scrollbar->scale, 
  2374. X                   XtNlength,     &length,
  2375. X                   XtNtopOfThumb, &thumb,
  2376. X                   XtNshown,      &shown,
  2377. X                   NULL);
  2378. X
  2379. X    change = (float)position / length;
  2380. X
  2381. X    /* Scroll by the amount of thumb shown * amount of change we
  2382. X       should for the given pointer position */
  2383. X    thumb += shown * change;
  2384. X
  2385. X    move_thumb( scrollbar, thumb, shown);
  2386. X}
  2387. X
  2388. X
  2389. X/* Called when the athena scrollbar is moved in a jumpy fashion.
  2390. X   Updates the feedback value and makes all registered callbacks. */
  2391. Xstatic void scrollbar_jump_callback( w, scrollbar, percent_ptr)
  2392. XWidget         w;
  2393. Xscrollbar_type scrollbar;
  2394. Xfloat *        percent_ptr;
  2395. X{
  2396. X    float shown;
  2397. X    float thumb = *percent_ptr;
  2398. X
  2399. X    XtVaGetValues( scrollbar->scale, 
  2400. X                   XtNshown,      &shown,
  2401. X                   NULL);
  2402. X
  2403. X    move_thumb( scrollbar, thumb, shown);
  2404. X}
  2405. X
  2406. X
  2407. X/* Moves thumb within valid values and updates the feedback value */
  2408. Xstatic void move_thumb( scrollbar, thumb, shown)
  2409. Xscrollbar_type scrollbar;
  2410. Xdouble         thumb;
  2411. Xdouble         shown;
  2412. X{
  2413. X    int value;
  2414. X
  2415. X
  2416. X    /* Keep the value within the proper range */
  2417. X    if (thumb >= 1 - shown)
  2418. X        /* Keep below 1, otherwise thumb stops redrawing due to Athena bug */
  2419. X        thumb = 1 - shown;
  2420. X    else
  2421. X    if (thumb < 0)
  2422. X        thumb = 0;
  2423. X
  2424. X    /* Set the thumb to the new position */
  2425. X    XawScrollbarSetThumb( scrollbar->scale, thumb, -1.0);
  2426. X
  2427. X    value = thumb_to_value( thumb, shown);
  2428. X
  2429. X    set_feedback_value( scrollbar, value);
  2430. X
  2431. X    call_callbacks( scrollbar, value);
  2432. X}
  2433. X
  2434. X
  2435. X/* Returns the value of the scrollbar */
  2436. Xstatic int scrollbar_get_value( scrollbar)
  2437. Xscrollbar_type scrollbar;
  2438. X{
  2439. X    float thumb;
  2440. X    float shown;
  2441. X
  2442. X
  2443. X    XtVaGetValues( scrollbar->scale,
  2444. X                   XtNtopOfThumb, &thumb,
  2445. X                   XtNshown,      &shown,
  2446. X                   NULL);
  2447. X
  2448. X    return thumb_to_value( thumb, shown);
  2449. X}
  2450. X
  2451. X
  2452. X/* Sets the value of the scrollbar - updates thumb and feedback value */
  2453. Xstatic int scale_set_value( scrollbar, value)
  2454. Xscrollbar_type scrollbar;
  2455. Xint value;
  2456. X{
  2457. X    float shown;
  2458. X
  2459. X
  2460. X    XtVaGetValues( scrollbar->scale, XtNshown, &shown, NULL);
  2461. X
  2462. X    /* Set the thumb to the new position */
  2463. X    XawScrollbarSetThumb( scrollbar->scale, 
  2464. X                          value_to_thumb( value, shown), -1.0);
  2465. X             
  2466. X
  2467. X    set_feedback_value( scrollbar, value);
  2468. X}
  2469. X
  2470. X
  2471. X/* Updates the feedback label to the passed value */
  2472. Xstatic void set_feedback_value( scrollbar, value)
  2473. Xscrollbar_type scrollbar;
  2474. Xint            value;
  2475. X{
  2476. X    set_label_value( scrollbar->feedback, value);
  2477. X}
  2478. X
  2479. X
  2480. X/* Sets an athena label so it displays the passed value */
  2481. Xstatic void set_label_value( label_w, value)
  2482. XWidget label_w;
  2483. Xint    value;
  2484. X{
  2485. X    char buff[15];
  2486. X
  2487. X
  2488. X    sprintf(buff,"%d", value);
  2489. X
  2490. X
  2491. X    XtVaSetValues( label_w, XtNlabel, buff, NULL);
  2492. X}
  2493. X
  2494. X
  2495. X/* Create Athena widgets to simulate a scale witget with a label */
  2496. Xvoid create_widgets( scrollbar, parent, name)
  2497. Xscrollbar_type scrollbar;
  2498. XWidget         parent;
  2499. Xchar *         name;
  2500. X{
  2501. X    scrollbar->form = XtVaCreateWidget(name, formWidgetClass, parent, NULL);
  2502. X
  2503. X    scrollbar->label = 
  2504. X        XtVaCreateManagedWidget("label", labelWidgetClass, scrollbar->form,
  2505. X                                NULL);
  2506. X
  2507. X    scrollbar->feedback = 
  2508. X        XtVaCreateManagedWidget("feedback",
  2509. X                                labelWidgetClass, scrollbar->form,
  2510. X                                XtNfromHoriz, scrollbar->label,
  2511. X                                NULL);
  2512. X
  2513. X    scrollbar->scale = 
  2514. X        XtVaCreateManagedWidget("bar",
  2515. X                                scrollbarWidgetClass, scrollbar->form, 
  2516. X                                XtNfromVert,  scrollbar->label,
  2517. X                                XtNfromHoriz, scrollbar->label,
  2518. X                                NULL);
  2519. X
  2520. X    scrollbar->value = scrollbar_get_value( scrollbar);
  2521. X
  2522. X    set_feedback_value( scrollbar, scrollbar->value);
  2523. X
  2524. X    XtAddCallback( scrollbar->scale, XtNscrollProc, 
  2525. X                   scrollbar_scroll_callback, (XtPointer)scrollbar);
  2526. X    XtAddCallback( scrollbar->scale, XtNjumpProc, 
  2527. X                   scrollbar_jump_callback, (XtPointer)scrollbar);
  2528. X
  2529. X    XtManageChild( scrollbar->form);
  2530. X}
  2531. X
  2532. X#endif
  2533. END_OF_FILE
  2534. if test 10512 -ne `wc -c <'scrollbar.c'`; then
  2535.     echo shar: \"'scrollbar.c'\" unpacked with wrong size!
  2536. fi
  2537. # end of 'scrollbar.c'
  2538. fi
  2539. if test -f 'sim.c' -a "${1}" != "-c" ; then 
  2540.   echo shar: Will not clobber existing file \"'sim.c'\"
  2541. else
  2542. echo shar: Extracting \"'sim.c'\" \(4262 characters\)
  2543. sed "s/^X//" >'sim.c' <<'END_OF_FILE'
  2544. X/**********************************************************************
  2545. X * sim.c - definition of the sim object - controls the simlation
  2546. X *
  2547. X * Copyright 1993, David Nedde
  2548. X *
  2549. X * Permission to use, copy, modify, and distribute this software
  2550. X * and its documentation for any purpose and without fee is granted
  2551. X * provided that the above copyright notice appears in all copies.
  2552. X * It is provided "as is" without express or implied warranty.
  2553. X **********************************************************************/
  2554. X
  2555. X/* System Headers */
  2556. X#include <X11/Intrinsic.h>
  2557. X#include <X11/StringDefs.h>
  2558. X
  2559. X/* Local headers */
  2560. X#include "sim.h"
  2561. X#include "misc.h"
  2562. X#include "names.h"
  2563. X
  2564. X/* Macros */
  2565. X#define INVALID_WPID 0
  2566. X#ifndef DELAY
  2567. X#define DELAY 0
  2568. X#endif
  2569. X
  2570. X/* Structures */
  2571. Xtypedef struct {
  2572. X    int delay;
  2573. X} app_data,*app_data_ptr;
  2574. Xstatic app_data res_data;
  2575. Xstatic XtResource resources[] = {
  2576. X    { "delay", "Delay", XtRInt, sizeof(int),
  2577. X          XtOffset(app_data_ptr,delay), XtRImmediate, (caddr_t)DELAY}
  2578. X};
  2579. X
  2580. X/* Functions */
  2581. Xstatic Boolean background_processing(/*sim*/);
  2582. Xstatic int delay(/*sim, length*/);
  2583. Xstatic int process_invisible_backwards(/*datap_ptr*/);
  2584. X
  2585. X
  2586. X/* Public object methods */
  2587. X
  2588. X/* Create the simulation object */
  2589. Xsim_type sim__create(w, menu, items, room, demo)
  2590. XWidget     w;
  2591. Xmenu_type  menu;
  2592. Xitems_type items;
  2593. Xroom_type  room;
  2594. Xdemo_type  demo;
  2595. X{
  2596. X    sim_type sim = (sim_type)malloc( sizeof( sim_struct_type));
  2597. X
  2598. X    sim->menu  = menu;
  2599. X    sim->items = items;
  2600. X    sim->room  = room;
  2601. X    sim->demo  = demo;
  2602. X
  2603. X    XtGetApplicationResources(w, (XtPointer)&res_data, 
  2604. X                              resources, XtNumber(resources), 
  2605. X                              (ArgList)NULL,(Cardinal)0);
  2606. X
  2607. X    sim->step_simulation = False;
  2608. X    sim->delay           = res_data.delay;
  2609. X
  2610. X    sim->wpid = INVALID_WPID;
  2611. X
  2612. X    return sim;
  2613. X}
  2614. X
  2615. X
  2616. X/* Destroys the simulation object */
  2617. Xvoid sim__destroy(sim)
  2618. Xsim_type sim;
  2619. X{
  2620. X    XtRemoveWorkProc(sim->wpid);
  2621. X
  2622. X    free( sim);
  2623. X}
  2624. X
  2625. X
  2626. X/* Steps the simulation one iteration */
  2627. Xvoid sim__step_mcb(w, sim, call_data, extra)
  2628. XWidget   w;
  2629. Xsim_type sim;
  2630. Xcaddr_t  call_data;
  2631. Xchar *   extra;
  2632. X{
  2633. X    background_processing( sim);
  2634. X}
  2635. X
  2636. X
  2637. X/* Halts the simulation */
  2638. Xvoid sim__halt_mcb(w, sim, call_data, extra)
  2639. XWidget               w;
  2640. Xsim_type             sim;
  2641. XmenuCallbackStruct * call_data;
  2642. Xchar               * extra;
  2643. X{
  2644. X    sim->step_simulation = call_data->set;
  2645. X
  2646. X    if (!sim->step_simulation)
  2647. X    {
  2648. X        /* Stepping currently turned off */
  2649. X        /* Add background processing to perform simulation in real-time */
  2650. X        sim->wpid = XtAppAddWorkProc(XtWidgetToApplicationContext(w),
  2651. X                                     background_processing, (char *)sim);
  2652. X
  2653. X    /* The 'Step simulation' menu item is greyed since sim is running */
  2654. X    menu__set_sensitivity( sim->menu, STEP_SIM, /*sensitive=*/False);
  2655. X    }
  2656. X    else
  2657. X    {
  2658. X        /* Stepping turned on - remove the work proc if it has been started */
  2659. X        if (sim->wpid != INVALID_WPID)
  2660. X            XtRemoveWorkProc(sim->wpid);
  2661. X
  2662. X        sim->wpid = INVALID_WPID;
  2663. X
  2664. X    /* The 'Step simulation' menu item is ungreyed since sim not running */
  2665. X    menu__set_sensitivity( sim->menu, STEP_SIM, /*sensitive=*/True);
  2666. X    }
  2667. X}
  2668. X
  2669. X
  2670. X/* Private object methods */
  2671. X
  2672. X/* Performs one iteration of the demo and simulation */
  2673. Xstatic Boolean background_processing(sim)
  2674. Xsim_type sim;
  2675. X{
  2676. X    room_type room = sim->room;
  2677. X
  2678. X    if (demo__running(sim->demo))
  2679. X        demo__process( sim->demo);
  2680. X
  2681. X    /* Delay based on the number of items */
  2682. X    delay(sim, items__get_count( sim->items)); 
  2683. X
  2684. X    items__move_items( sim->items, room);
  2685. X
  2686. X    return /*remove work procedure=*/False;
  2687. X}
  2688. X
  2689. X
  2690. X/* Slow the simulation some amount */
  2691. X/* Slow more if there are less balls, less if there are more balls */
  2692. Xstatic int delay(sim, item_count)
  2693. Xsim_type sim;
  2694. Xint      item_count;
  2695. X{
  2696. X    int utime;
  2697. X
  2698. X    utime = sim->delay - item_count;
  2699. X
  2700. X#ifdef HAVE_USLEEP
  2701. X
  2702. X    if (utime < 0)
  2703. X        utime = 0;
  2704. X
  2705. X    usleep(utime);
  2706. X#else
  2707. X    /* Use this part if you don't have a usleep() */
  2708. X    {
  2709. X        int x,y,sum;
  2710. X
  2711. X        /* Yes, a delay loop to slow small amounts of items */
  2712. X        for (x = 0; x < utime; x++)
  2713. X            for (y = 0; y < sim->delay; y++)
  2714. X                sum = sum + y * x;
  2715. X
  2716. X        return sum;            /* Try to keep it from getting optimized out */
  2717. X    }
  2718. X#endif
  2719. X}
  2720. END_OF_FILE
  2721. if test 4262 -ne `wc -c <'sim.c'`; then
  2722.     echo shar: \"'sim.c'\" unpacked with wrong size!
  2723. fi
  2724. # end of 'sim.c'
  2725. fi
  2726. if test -f 'table.c' -a "${1}" != "-c" ; then 
  2727.   echo shar: Will not clobber existing file \"'table.c'\"
  2728. else
  2729. echo shar: Extracting \"'table.c'\" \(2535 characters\)
  2730. sed "s/^X//" >'table.c' <<'END_OF_FILE'
  2731. X/**********************************************************************
  2732. X * table.c - table object definition
  2733. X *
  2734. X * Copyright 1993, David Nedde
  2735. X *
  2736. X * Permission to use, copy, modify, and distribute this software
  2737. X * and its documentation for any purpose and without fee is granted
  2738. X * provided that the above copyright notice appears in all copies.
  2739. X * It is provided "as is" without express or implied warranty.
  2740. X **********************************************************************/
  2741. X
  2742. X/* System Headers */
  2743. X#include <malloc.h>
  2744. X#include <string.h>
  2745. X
  2746. X/* Local headers */
  2747. X#include "misc.h"
  2748. X#include "table.h"
  2749. X
  2750. X/* Structures */
  2751. Xtypedef struct {
  2752. X    char *key;
  2753. X    void *data;
  2754. X} table_node_struct_type, *table_node_type;
  2755. X
  2756. X
  2757. X/* Public object methods */
  2758. X
  2759. X/* Create a table object */
  2760. Xtable_type table__create()
  2761. X{
  2762. X    table_type table = (table_type)malloc( sizeof(table_struct_type));
  2763. X
  2764. X
  2765. X    table->list = list__create();
  2766. X
  2767. X    return table;
  2768. X}
  2769. X
  2770. X
  2771. X/* Free table but not the data contained by the table */
  2772. Xvoid table__destroy( table)
  2773. Xtable_type table;
  2774. X{
  2775. X    table_node_type table_node;
  2776. X
  2777. X
  2778. X    while ((table_node = 
  2779. X            (table_node_type)list__remove_last(table->list)) != 
  2780. X                                                            (table_node_type)0)
  2781. X    {
  2782. X        free( table_node->key);
  2783. X        free( table_node);
  2784. X    }
  2785. X
  2786. X    list__destroy( table->list);
  2787. X    free( table);
  2788. X}
  2789. X
  2790. X
  2791. X/* Store data in the table by key */
  2792. Xvoid table__store( table, key, data)
  2793. Xtable_type table;
  2794. Xchar *     key;
  2795. Xvoid *     data;
  2796. X{
  2797. X    table_node_type table_node = 
  2798. X        (table_node_type)malloc( sizeof(table_node_struct_type));
  2799. X
  2800. X    table_node->key = my_strdup( key);
  2801. X    table_node->data = data;
  2802. X
  2803. X
  2804. X    list__add_end( table->list, (void *)table_node);
  2805. X}
  2806. X
  2807. X
  2808. X/* Get a value out of the table, given its key */
  2809. Xvoid *table__retrieve( table, key)
  2810. Xtable_type table;
  2811. Xchar *     key;
  2812. X{
  2813. X    table_node_type table_node;
  2814. X
  2815. X
  2816. X    for (table_node = (table_node_type)list__get_first( table->list);
  2817. X         table_node != (table_node_type)0;
  2818. X         table_node = (table_node_type)list__get_next( table->list))
  2819. X    {
  2820. X        if (strcmp( table_node->key, key) == 0)
  2821. X            return table_node->data;
  2822. X    }
  2823. X
  2824. X    return (void *)0;
  2825. X}
  2826. X
  2827. X
  2828. X#ifdef DEBUG
  2829. X
  2830. Xvoid table__dump( table)
  2831. Xtable_type table;
  2832. X{
  2833. X    table_node_type table_node;
  2834. X
  2835. X
  2836. X    for (table_node = (table_node_type)list__get_first( table->list);
  2837. X         table_node != (table_node_type)0;
  2838. X         table_node = (table_node_type)list__get_next( table->list))
  2839. X    {
  2840. X        printf("key = %s\n", table_node->key);
  2841. X    }
  2842. X}
  2843. X        
  2844. X#endif
  2845. END_OF_FILE
  2846. if test 2535 -ne `wc -c <'table.c'`; then
  2847.     echo shar: \"'table.c'\" unpacked with wrong size!
  2848. fi
  2849. # end of 'table.c'
  2850. fi
  2851. if test -f 'intf.h' -a "${1}" != "-c" ; then 
  2852.   echo shar: Will not clobber existing file \"'intf.h'\"
  2853. else
  2854. echo shar: Extracting \"'intf.h'\" \(234 characters\)
  2855. sed "s/^X//" >'intf.h' <<'END_OF_FILE'
  2856. X#ifndef __INTF_H__
  2857. X#define __INTF_H__
  2858. X
  2859. X#define INTFAC  16      /* Multiplied to everything but velocities */
  2860. X
  2861. Xtypedef long intf;
  2862. X
  2863. X#define int2intf( val)   ((intf)((val)*INTFAC))
  2864. X#define intf2int( val)   ((long)((val)/INTFAC))
  2865. X
  2866. X#endif
  2867. END_OF_FILE
  2868. if test 234 -ne `wc -c <'intf.h'`; then
  2869.     echo shar: \"'intf.h'\" unpacked with wrong size!
  2870. fi
  2871. # end of 'intf.h'
  2872. fi
  2873. if test -f 'miscx.h' -a "${1}" != "-c" ; then 
  2874.   echo shar: Will not clobber existing file \"'miscx.h'\"
  2875. else
  2876. echo shar: Extracting \"'miscx.h'\" \(600 characters\)
  2877. sed "s/^X//" >'miscx.h' <<'END_OF_FILE'
  2878. X/**********************************************************************
  2879. X * miscx.h - Misc X, Xt and Xmu related functions
  2880. X *
  2881. X * Copyright 1993, David Nedde
  2882. X *
  2883. X * Permission to use, copy, modify, and distribute this software
  2884. X * and its documentation for any purpose and without fee is granted
  2885. X * provided that the above copyright notice appears in all copies.
  2886. X * It is provided "as is" without express or implied warranty.
  2887. X **********************************************************************/
  2888. X
  2889. X#ifndef __MISCX_H__
  2890. X#define __MISCX_H__
  2891. X
  2892. Xvoid   setupConverters();
  2893. XWidget get_toplevel(/*w*/);
  2894. X
  2895. X
  2896. X#endif
  2897. END_OF_FILE
  2898. if test 600 -ne `wc -c <'miscx.h'`; then
  2899.     echo shar: \"'miscx.h'\" unpacked with wrong size!
  2900. fi
  2901. # end of 'miscx.h'
  2902. fi
  2903. echo shar: End of archive 3 \(of 5\).
  2904. cp /dev/null ark3isdone
  2905. MISSING=""
  2906. for I in 1 2 3 4 5 ; do
  2907.     if test ! -f ark${I}isdone ; then
  2908.     MISSING="${MISSING} ${I}"
  2909.     fi
  2910. done
  2911. if test "${MISSING}" = "" ; then
  2912.     echo You have unpacked all 5 archives.
  2913.     rm -f ark[1-9]isdone
  2914. else
  2915.     echo You still need to unpack the following archives:
  2916.     echo "        " ${MISSING}
  2917. fi
  2918. ##  End of shell archive.
  2919. exit 0
  2920.  
  2921. exit 0 # Just in case...
  2922. -- 
  2923.   // chris@IMD.Sterling.COM       | Send comp.sources.x submissions to:
  2924. \X/  Amiga - The only way to fly! |    sources-x@imd.sterling.com
  2925.  "It's intuitively obvious to the |
  2926.   most casual observer..."        | GCS d+/-- p+ c++ l+ m+ s++/+ g+ w+ t+ r+ x+
  2927.