home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / x / volume20 / pexdraw / part09 < prev    next >
Encoding:
Text File  |  1993-06-07  |  61.3 KB  |  2,234 lines

  1. Newsgroups: comp.sources.x
  2. From: jch@okimicro.oki.com (Jan Hardenbergh)
  3. Subject: v20i019:  pexdraw - A PEX drawing program, Part09/14
  4. Message-ID: <1993Jun8.150207.19172@sparky.imd.sterling.com>
  5. X-Md4-Signature: e79ab9c01a4b72c343f8c86057687d1d
  6. Sender: chris@sparky.imd.sterling.com (Chris Olson)
  7. Organization: Sterling Software
  8. Date: Tue, 8 Jun 1993 15:02:07 GMT
  9. Approved: chris@sparky.imd.sterling.com
  10.  
  11. Submitted-by: jch@okimicro.oki.com (Jan Hardenbergh)
  12. Posting-number: Volume 20, Issue 19
  13. Archive-name: pexdraw/part09
  14. Environment: X11R5, PEX
  15.  
  16. #! /bin/sh
  17. # This is a shell archive.  Remove anything before this line, then feed it
  18. # into a shell via "sh file" or similar.  To overwrite existing files,
  19. # type "sh file -c".
  20. # Contents:  fb.c pexdrawc.1
  21. # Wrapped by chris@sparky on Tue Jun  8 09:46:33 1993
  22. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin ; export PATH
  23. echo If this archive is complete, you will see the following message:
  24. echo '          "shar: End of archive 9 (of 14)."'
  25. if test -f 'fb.c' -a "${1}" != "-c" ; then 
  26.   echo shar: Will not clobber existing file \"'fb.c'\"
  27. else
  28.   echo shar: Extracting \"'fb.c'\" \(27419 characters\)
  29.   sed "s/^X//" >'fb.c' <<'END_OF_FILE'
  30. X#ifdef SCCS
  31. Xstatic char sccsid[]="@(#)fb.c    1.14 Oki Electric Industry Co., Ltd. 93/05/24";
  32. X#endif
  33. X/*
  34. X    This file is under sccs control at Stardent in:
  35. X    /nfs/sole/root/sccs1.p/X11R5/mit/demos/pexdraw/s.fb.c
  36. X*/
  37. X/*
  38. X *            Copyright (c) 1992 by
  39. X *            Oki Electric Industry Co., Ltd.
  40. X *            All Rights Reserved
  41. X *
  42. X * Permission to use, copy, modify, and distribute this software and its
  43. X * documentation for any purpose and without fee is hereby granted,
  44. X * provided that the above copyright notice appear in all copies and that
  45. X * both that copyright notice and this permission notice appear in
  46. X * supporting documentation, and that the name of Oki not be
  47. X * used in advertising or publicity pertaining to distribution of the
  48. X * software without specific, written prior permission. Oki
  49. X * makes no representations about the suitability of this software for any
  50. X * purpose.  It is provided "as is" without express or implied warranty.
  51. X *
  52. X * This supercedes the Stardent copyright granting the same rights that
  53. X * appeared in the pdraw predecessor to pexdraw.
  54. X *
  55. X *************************************************************************
  56. X *
  57. X *                         P E X D R A W
  58. X *
  59. X *  A PEX drawing program based on PDRAW,
  60. X *
  61. X *   
  62. X *
  63. X *************************************************************************/
  64. X
  65. X#include <stdio.h>
  66. X
  67. X#include <math.h>
  68. X
  69. X#include <X11/PEX5/PEXlib.h>
  70. X#include <X11/Xutil.h> /* because of XVisualInfo in pexdraw.h !?! */
  71. X
  72. X#include "pexdraw.h"
  73. X
  74. Xint theAnchorX, theAnchorY, theDynX, theDynY, theAltX, theAltY;
  75. Xint theTriStripCount = 0;
  76. X
  77. X#define TRIMAX 12
  78. XXPoint theTriDCs[TRIMAX];
  79. XPEXCoord       theTriPoints[TRIMAX];
  80. X
  81. Xfloat theTheta, thePhi, theDeltaTheta, theDeltaPhi;
  82. X
  83. X
  84. X /*************************************************************************
  85. X *
  86. X * D Y N A M I C    F E E D B A C K   R O U T I N E S
  87. X *
  88. X */
  89. Xstatic void fbInitLine(
  90. X#if NeedFunctionPrototypes
  91. XXButtonPressedEvent * /* event */
  92. X#endif
  93. X);
  94. X
  95. Xstatic void fbDynLine(
  96. X#if NeedFunctionPrototypes
  97. XXMotionEvent * /* event */
  98. X#endif
  99. X);
  100. X
  101. Xstatic void fbEndLine(
  102. X#if NeedFunctionPrototypes
  103. XXButtonReleasedEvent * /* event */
  104. X#endif
  105. X);
  106. X
  107. Xstatic void fbEndMClip(
  108. X#if NeedFunctionPrototypes
  109. XXButtonReleasedEvent * /* event */
  110. X#endif
  111. X);
  112. X
  113. Xstatic void fbDummy();
  114. Xstatic void fbDynBox(
  115. X#if NeedFunctionPrototypes
  116. XXMotionEvent * /* event */
  117. X#endif
  118. X);
  119. X
  120. Xstatic void fbEndPick(
  121. X#if NeedFunctionPrototypes
  122. XXButtonReleasedEvent * /* event */
  123. X#endif
  124. X);
  125. X
  126. X
  127. Xstatic void fbInitTriStrip(
  128. X#if NeedFunctionPrototypes
  129. XXButtonPressedEvent * /* event */
  130. X#endif
  131. X);
  132. X
  133. Xstatic void fbDynTriStrip(
  134. X#if NeedFunctionPrototypes
  135. XXMotionEvent * /* event */
  136. X#endif
  137. X);
  138. X
  139. Xstatic void fbEndTriStrip(
  140. X#if NeedFunctionPrototypes
  141. XXButtonReleasedEvent * /* event */
  142. X#endif
  143. X);
  144. X
  145. Xstatic void fbFinishTriStrip(
  146. X#if NeedFunctionPrototypes
  147. XXButtonReleasedEvent * /* event */
  148. X#endif
  149. X);
  150. X
  151. X
  152. Xstatic void fbInitNURBCurve(
  153. X#if NeedFunctionPrototypes
  154. XXButtonPressedEvent * /* event */
  155. X#endif
  156. X);
  157. X
  158. Xstatic void fbDynNURBCurve(
  159. X#if NeedFunctionPrototypes
  160. XXMotionEvent * /* event */
  161. X#endif
  162. X);
  163. X
  164. Xstatic void fbEndNURBCurve(
  165. X#if NeedFunctionPrototypes
  166. XXButtonReleasedEvent * /* event */
  167. X#endif
  168. X);
  169. X
  170. Xstatic void fbFinishNURBCurve(
  171. X#if NeedFunctionPrototypes
  172. XXButtonReleasedEvent * /* event */
  173. X#endif
  174. X);
  175. X
  176. X
  177. Xstatic void fbFinishPolygon (
  178. X#if NeedFunctionPrototypes
  179. XXButtonReleasedEvent * /* event */
  180. X#endif
  181. X);
  182. X
  183. X
  184. Xstatic void fbEndText(
  185. X#if NeedFunctionPrototypes
  186. XXButtonReleasedEvent * /* event */
  187. X#endif
  188. X);
  189. X
  190. X
  191. Xstatic void fbInitView(
  192. X#if NeedFunctionPrototypes
  193. XXButtonPressedEvent * /* event */
  194. X#endif
  195. X);
  196. X
  197. Xstatic void fbDynView(
  198. X#if NeedFunctionPrototypes
  199. XXMotionEvent * /* event */
  200. X#endif
  201. X);
  202. X
  203. Xstatic void fbEndView(
  204. X#if NeedFunctionPrototypes
  205. XXButtonReleasedEvent * /* event */
  206. X#endif
  207. X);
  208. X
  209. X
  210. Xstatic void fbInitTranslate(
  211. X#if NeedFunctionPrototypes
  212. XXButtonPressedEvent * /* event */
  213. X#endif
  214. X);
  215. X
  216. X/* use dynline */
  217. Xstatic void fbEndTranslate(
  218. X#if NeedFunctionPrototypes
  219. XXButtonReleasedEvent * /* event */
  220. X#endif
  221. X);
  222. X
  223. X
  224. Xstatic void fbInitStretch(
  225. X#if NeedFunctionPrototypes
  226. XXButtonPressedEvent * /* event */
  227. X#endif
  228. X);
  229. X
  230. X/* use dynline, or dyntristrip */
  231. Xstatic void fbEndStretch(
  232. X#if NeedFunctionPrototypes
  233. XXButtonReleasedEvent * /* event */
  234. X#endif
  235. X);
  236. X
  237. X
  238. Xstatic void fbEndZoom(
  239. X#if NeedFunctionPrototypes
  240. XXButtonReleasedEvent * /* event */
  241. X#endif
  242. X);
  243. X
  244. Xstatic void fbZoomReset(
  245. X#if NeedFunctionPrototypes
  246. XXButtonReleasedEvent * /* event */
  247. X#endif
  248. X);
  249. X
  250. X
  251. Xstatic void fbInitCircle(
  252. X#if NeedFunctionPrototypes
  253. XXButtonPressedEvent * /* event */
  254. X#endif
  255. X);
  256. X
  257. Xstatic void fbEndCircle(
  258. X#if NeedFunctionPrototypes
  259. XXButtonReleasedEvent * /* event */
  260. X#endif
  261. X);
  262. X
  263. Xstatic void fbDynCircle(
  264. X#if NeedFunctionPrototypes
  265. XXMotionEvent * /* event */
  266. X#endif
  267. X);
  268. X
  269. X
  270. X
  271. X
  272. X/*************************************************************************
  273. X *
  274. X *  T O O L   S E L E C T I O N   R O U T I N E S
  275. X *
  276. X *************************************************************************
  277. X */
  278. X
  279. Xvoid 
  280. Xset_tool_pointer()
  281. X{
  282. X    theCurrentTool = TOOL_POINTER;
  283. X
  284. X    /*
  285. X     * don't deal with fancy pre-pick hilite, yet.
  286. X     */
  287. X    if (the51Flag) {
  288. X      thePressHandlerTable[0] = fbInitLine;
  289. X      theMotionHandlerTable[0] = fbDynBox;
  290. X    } else {
  291. X      thePressHandlerTable[0] = fbDummy;
  292. X      theMotionHandlerTable[0] = fbDummy;
  293. X    }
  294. X    theReleaseHandlerTable[0] = fbEndPick;
  295. X
  296. X    thePressHandlerTable[1] = fbInitTranslate;
  297. X    theMotionHandlerTable[1] = fbDynLine;
  298. X    theReleaseHandlerTable[1] = fbEndTranslate;
  299. X
  300. X    thePressHandlerTable[2] = fbInitStretch;
  301. X    theMotionHandlerTable[2] = fbDummy;
  302. X    theReleaseHandlerTable[2] = fbEndStretch;
  303. X}
  304. X
  305. Xvoid 
  306. Xset_tool_line()
  307. X{
  308. X    theCurrentTool = TOOL_LINE;
  309. X
  310. X    thePressHandlerTable[0] = fbInitLine;
  311. X    theMotionHandlerTable[0] = fbDynLine;
  312. X    theReleaseHandlerTable[0] = fbEndLine;
  313. X
  314. X    thePressHandlerTable[1] = fbInitLine;
  315. X    theMotionHandlerTable[1] = fbDynLine;
  316. X    theReleaseHandlerTable[1] = fbEndLine;
  317. X
  318. X    thePressHandlerTable[2] = fbInitView;
  319. X    theMotionHandlerTable[2] = fbDynView;
  320. X    theReleaseHandlerTable[2] = fbEndView;
  321. X}
  322. X
  323. Xvoid 
  324. Xset_tool_view()
  325. X{
  326. X
  327. X    theCurrentTool = TOOL_VIEW;
  328. X
  329. X    thePressHandlerTable[0] = fbInitView;
  330. X    theMotionHandlerTable[0] = fbDynView;
  331. X    theReleaseHandlerTable[0] = fbEndView;
  332. X
  333. X    thePressHandlerTable[1] = fbDummy;
  334. X    theMotionHandlerTable[1] = fbDummy;
  335. X    theReleaseHandlerTable[1] = fbDummy;
  336. X
  337. X    thePressHandlerTable[2] = fbInitView;
  338. X    theMotionHandlerTable[2] = fbDynView;
  339. X    theReleaseHandlerTable[2] = fbEndView;
  340. X}
  341. X
  342. Xvoid
  343. Xset_tool_nurbc()
  344. X{
  345. X    theCurrentTool = TOOL_NURBC;
  346. X
  347. X    thePressHandlerTable[0] = fbInitNURBCurve;
  348. X    theMotionHandlerTable[0] = fbDynLine;
  349. X    theReleaseHandlerTable[0] = fbEndNURBCurve;
  350. X
  351. X    thePressHandlerTable[1] = fbFinishNURBCurve;
  352. X    theMotionHandlerTable[1] = fbDummy;
  353. X    theReleaseHandlerTable[1] = fbDummy;
  354. X
  355. X    thePressHandlerTable[2] = fbInitView;
  356. X    theMotionHandlerTable[2] = fbDynView;
  357. X    theReleaseHandlerTable[2] = fbEndView;
  358. X}
  359. X
  360. Xvoid
  361. Xset_tool_pgon()
  362. X{
  363. X    theCurrentTool = TOOL_PGON;
  364. X
  365. X    thePressHandlerTable[0] = fbInitNURBCurve;
  366. X    theMotionHandlerTable[0] = fbDynLine;
  367. X    theReleaseHandlerTable[0] = fbEndNURBCurve;
  368. X
  369. X    thePressHandlerTable[1] = fbFinishPolygon;
  370. X    theMotionHandlerTable[1] = fbDummy;
  371. X    theReleaseHandlerTable[1] = fbDummy;
  372. X
  373. X    thePressHandlerTable[2] = fbInitView;
  374. X    theMotionHandlerTable[2] = fbDynView;
  375. X    theReleaseHandlerTable[2] = fbEndView;
  376. X}
  377. X
  378. Xvoid
  379. Xset_tool_circle()
  380. X{
  381. X    theCurrentTool = TOOL_CIRCLE;
  382. X
  383. X    thePressHandlerTable[0] = fbInitCircle;
  384. X    theMotionHandlerTable[0] = fbDynCircle;
  385. X    theReleaseHandlerTable[0] = fbEndCircle;
  386. X
  387. X    thePressHandlerTable[1] = fbDummy;
  388. X    theMotionHandlerTable[1] = fbDummy;
  389. X    theReleaseHandlerTable[1] = fbDummy;
  390. X
  391. X    thePressHandlerTable[2] = fbInitView;
  392. X    theMotionHandlerTable[2] = fbDynView;
  393. X    theReleaseHandlerTable[2] = fbEndView;
  394. X}
  395. X
  396. X
  397. Xvoid
  398. Xset_tool_text()
  399. X{
  400. X  theCurrentTool = TOOL_TEXT;
  401. X
  402. X  thePressHandlerTable[0] = fbDummy;
  403. X  theMotionHandlerTable[0] = fbDummy;
  404. X  theReleaseHandlerTable[0] = fbEndText;
  405. X
  406. X  thePressHandlerTable[1] = fbDummy;
  407. X  theMotionHandlerTable[1] = fbDummy;
  408. X  theReleaseHandlerTable[1] = fbDummy;
  409. X
  410. X  thePressHandlerTable[2] = fbInitView;
  411. X  theMotionHandlerTable[2] = fbDynView;
  412. X  theReleaseHandlerTable[2] = fbEndView;
  413. X}
  414. X
  415. Xvoid
  416. Xset_tool_tristrip()
  417. X{
  418. X    theCurrentTool = TOOL_TRISTRIP;
  419. X
  420. X    thePressHandlerTable[0] = fbInitTriStrip;
  421. X    theMotionHandlerTable[0] = fbDynTriStrip;
  422. X    theReleaseHandlerTable[0] = fbEndTriStrip;
  423. X
  424. X    thePressHandlerTable[1] = fbFinishTriStrip;
  425. X    theMotionHandlerTable[1] = fbDummy;
  426. X    theReleaseHandlerTable[1] = fbDummy;
  427. X
  428. X    thePressHandlerTable[2] = fbInitView;
  429. X    theMotionHandlerTable[2] = fbDynView;
  430. X    theReleaseHandlerTable[2] = fbEndView;
  431. X}
  432. X
  433. Xvoid
  434. Xset_tool_zoom()
  435. X{
  436. X  if (theCurrentTool != TOOL_ZOOM) {
  437. X    theCurrentTool = TOOL_ZOOM;
  438. X
  439. X    thePressHandlerTable[0] = fbInitLine;
  440. X    theMotionHandlerTable[0] = fbDynBox;
  441. X    theReleaseHandlerTable[0] = fbEndZoom;
  442. X
  443. X    thePressHandlerTable[1] = fbDummy;
  444. X    theMotionHandlerTable[1] = fbDummy;
  445. X    theReleaseHandlerTable[1] = fbZoomReset;
  446. X
  447. X    thePressHandlerTable[2] = fbInitView;
  448. X    theMotionHandlerTable[2] = fbDynView;
  449. X    theReleaseHandlerTable[2] = fbEndView;
  450. X  }
  451. X}
  452. X
  453. Xvoid
  454. Xset_tool_mclip()
  455. X{
  456. X  if (theCurrentTool != TOOL_MCLIP) {
  457. X    theCurrentTool = TOOL_MCLIP;
  458. X
  459. X    thePressHandlerTable[0] = fbInitLine;
  460. X    theMotionHandlerTable[0] = fbDynLine;
  461. X    theReleaseHandlerTable[0] = fbEndMClip;
  462. X
  463. X    thePressHandlerTable[1] = fbDummy;
  464. X    theMotionHandlerTable[1] = fbDummy;
  465. X    theReleaseHandlerTable[1] = fbDummy;;
  466. X
  467. X    thePressHandlerTable[2] = fbInitView;
  468. X    theMotionHandlerTable[2] = fbDynView;
  469. X    theReleaseHandlerTable[2] = fbEndView;
  470. X  }
  471. X}
  472. X
  473. X/*************************************************************************
  474. X *
  475. X * D Y N A M I C     F E E D B A C K     R O U T I N E S
  476. X *
  477. X */
  478. Xstatic void fbInitLine(event )
  479. X XButtonPressedEvent *event;
  480. X{
  481. X  XGCValues values;
  482. X
  483. X  theAnchorX = event->x;
  484. X  theAnchorY = event->y;
  485. X  theDynX = event->x;
  486. X  theDynY = event->y;
  487. X  XDrawLine( theDisplay, theWindow, theDynGC, 
  488. X        theAnchorX, theAnchorY, theDynX, theDynY );
  489. X}
  490. X
  491. Xstatic void fbDynLine(event )
  492. X XMotionEvent *event;
  493. X{
  494. X  XDrawLine( theDisplay, theWindow, theDynGC, 
  495. X        theAnchorX, theAnchorY, theDynX, theDynY );
  496. X  theDynX = event->x;
  497. X  theDynY = event->y;
  498. X  XDrawLine( theDisplay, theWindow, theDynGC, 
  499. X        theAnchorX, theAnchorY, theDynX, theDynY );
  500. X}
  501. X
  502. Xstatic void fbDynBox(event )
  503. X XMotionEvent *event;
  504. X{
  505. X  XDrawLine( theDisplay, theWindow, theDynGC, 
  506. X        theAnchorX, theAnchorY, theAnchorX, theDynY );
  507. X  XDrawLine( theDisplay, theWindow, theDynGC, 
  508. X        theAnchorX, theDynY, theDynX, theDynY );
  509. X  XDrawLine( theDisplay, theWindow, theDynGC, 
  510. X        theDynX, theDynY, theDynX, theAnchorY );
  511. X  XDrawLine( theDisplay, theWindow, theDynGC, 
  512. X        theDynX, theAnchorY, theAnchorX, theAnchorY );
  513. X  theDynX = event->x;
  514. X  theDynY = event->y;
  515. X  XDrawLine( theDisplay, theWindow, theDynGC, 
  516. X        theAnchorX, theAnchorY, theAnchorX, theDynY );
  517. X  XDrawLine( theDisplay, theWindow, theDynGC, 
  518. X        theAnchorX, theDynY, theDynX, theDynY );
  519. X  XDrawLine( theDisplay, theWindow, theDynGC, 
  520. X        theDynX, theDynY, theDynX, theAnchorY );
  521. X  XDrawLine( theDisplay, theWindow, theDynGC, 
  522. X        theDynX, theAnchorY, theAnchorX, theAnchorY );
  523. X}
  524. X
  525. Xstatic void fbEndLine(event )
  526. X XButtonReleasedEvent *event;
  527. X{
  528. X  XPoint xp[2];
  529. X  PEXCoord *pl;
  530. X  int count;
  531. X
  532. X  xp[0].x = theAnchorX;
  533. X  xp[0].y = theAnchorY;
  534. X  xp[1].x = theDynX;
  535. X  xp[1].y = theDynY;
  536. X
  537. X  if ((count = theRenderProcs.MapXToMC( &theMCMatrix, 2, xp, &pl)) ==  2) {
  538. X    InsertLineCmd( 2, pl, 1 );
  539. X    free((char *)pl);
  540. X    theRenderProcs.ReDraw();
  541. X  }
  542. X}
  543. X
  544. Xstatic void fbEndMClip(event )
  545. X XButtonReleasedEvent *event;
  546. X{
  547. X  XPoint xp[2];
  548. X  PEXCoord *pl;
  549. X  int count;
  550. X
  551. X  xp[0].x = theAnchorX;
  552. X  xp[0].y = theAnchorY;
  553. X  xp[1].x = theDynX;
  554. X  xp[1].y = theDynY;
  555. X
  556. X  if ((count = theRenderProcs.MapXToMC( &theMCMatrix, 2, xp, &pl)) ==  2) {
  557. X    InsertMClipCmd( pl, 1 );
  558. X    free((char *)pl);
  559. X    theRenderProcs.ReDraw();
  560. X  }
  561. X}
  562. X
  563. X
  564. X/*
  565. X * no dynamic hiliting
  566. X */
  567. Xstatic void fbDummy() {}
  568. X
  569. X#define DIFFERENT(a,b) (((((a)-(b))>3)||(((a)-(b))<-3))?1:0)
  570. X
  571. Xstatic void fbEndPick(event )
  572. X XButtonReleasedEvent *event;
  573. X{
  574. X  long s;
  575. X  int e;
  576. X  int count;
  577. X  long *struxArray;
  578. X  int *elemArray;
  579. X
  580. X  XDrawPoint(  theDisplay, theWindow, theDynGC, event->x, event->y );
  581. X  ClearSelection();
  582. X
  583. X  if (the51Flag && 
  584. X      (DIFFERENT(event->x,theAnchorX) || DIFFERENT(event->y,theAnchorY))) {
  585. X    /* do pick all */
  586. X    theRenderProcs.PickAll( event->x, event->y, theAnchorX,theAnchorY,
  587. X               &count, &struxArray, &elemArray );
  588. X    if (count > 0) {
  589. X      ColorGroup( count, struxArray, elemArray );
  590. X      SelectSomething( struxArray[0], elemArray[0] );
  591. X    }
  592. X  } else {
  593. X    theRenderProcs.PickOne( event->x, event->y, &s, &e);
  594. X    if ( e != -1 )
  595. X      SelectSomething( s, e );
  596. X  }
  597. X  theRenderProcs.ReDraw();
  598. X}
  599. X
  600. X /*************************************************************************
  601. X *  fbInitTriStrip - initialze and reinit tristrip inster dynamics.
  602. X *
  603. X * if we are working on a tristrip, then start the next point. Otherwise,
  604. X *  we are just drawing a line!
  605. X */
  606. Xstatic void fbInitTriStrip(event )
  607. X XButtonPressedEvent *event;
  608. X{
  609. X  if (theTriStripCount) {
  610. X    if (theTriStripCount == TRIMAX) {
  611. X      fbFinishTriStrip( event );
  612. X      return;
  613. X    }
  614. X    theAnchorX = theAltX;
  615. X    theAnchorY = theAltY;
  616. X    theAltX = theDynX;
  617. X    theAltY = theDynY;
  618. X    theDynX = event->x;
  619. X    theDynY = event->y;
  620. X    XDrawLine( theDisplay, theWindow, theDynGC, 
  621. X        theAnchorX, theAnchorY, theDynX, theDynY );
  622. X    XDrawLine( theDisplay, theWindow, theDynGC, 
  623. X        theAltX, theAltY, theDynX, theDynY );
  624. X  } else {
  625. X    theAnchorX = event->x;
  626. X    theAnchorY = event->y;
  627. X    theDynX = event->x;
  628. X    theDynY = event->y;
  629. X    theAltX = event->x;
  630. X    theAltY = event->y;
  631. X    XDrawLine( theDisplay, theWindow, theDynGC, 
  632. X          theAnchorX, theAnchorY, theDynX, theDynY );
  633. X  }
  634. X}
  635. X
  636. Xstatic void fbDynTriStrip(event )
  637. X XMotionEvent *event;
  638. X{
  639. X  if (theTriStripCount) {
  640. X    XDrawLine( theDisplay, theWindow, theDynGC, 
  641. X        theAnchorX, theAnchorY, theDynX, theDynY );
  642. X    XDrawLine( theDisplay, theWindow, theDynGC, 
  643. X        theAltX, theAltY, theDynX, theDynY );
  644. X    theDynX = event->x;
  645. X    theDynY = event->y;
  646. X    XDrawLine( theDisplay, theWindow, theDynGC, 
  647. X        theAnchorX, theAnchorY, theDynX, theDynY );
  648. X    XDrawLine( theDisplay, theWindow, theDynGC, 
  649. X        theAltX, theAltY, theDynX, theDynY );
  650. X  } else {
  651. X    XDrawLine( theDisplay, theWindow, theDynGC, 
  652. X          theAnchorX, theAnchorY, theDynX, theDynY );
  653. X    theDynX = event->x;
  654. X    theDynY = event->y;
  655. X    XDrawLine( theDisplay, theWindow, theDynGC, 
  656. X          theAnchorX, theAnchorY, theDynX, theDynY );
  657. X  }
  658. X}
  659. Xstatic void fbEndTriStrip(event )
  660. X XButtonReleasedEvent *event;
  661. X{
  662. X  if (theTriStripCount) {
  663. X    XDrawLine( theDisplay, theWindow, 
  664. X          theDynGC, theAnchorX, theAnchorY, theDynX, theDynY );
  665. X    XDrawLine( theDisplay, theWindow,
  666. X          theDynGC, theAltX, theAltY, theDynX, theDynY );
  667. X    theDynX = event->x;
  668. X    theDynY = event->y;
  669. X    XDrawLine( theDisplay, theWindow, 
  670. X          theDynGC, theAnchorX, theAnchorY, theDynX, theDynY );
  671. X    XDrawLine( theDisplay, theWindow,
  672. X          theDynGC, theAltX, theAltY, theDynX, theDynY );
  673. X    theTriDCs[theTriStripCount].x = theDynX;
  674. X    theTriDCs[theTriStripCount].y = theDynY;
  675. X    theTriStripCount++;
  676. X  } else {
  677. X    XDrawLine( theDisplay, theWindow, theDynGC, 
  678. X          theAnchorX, theAnchorY, theDynX, theDynY );
  679. X    theDynX = event->x;
  680. X    theDynY = event->y;
  681. X    XDrawLine( theDisplay, theWindow, theDynGC, 
  682. X          theAnchorX, theAnchorY, theDynX, theDynY );
  683. X    theTriDCs[0].x = theAnchorX;
  684. X    theTriDCs[0].y = theAnchorY;
  685. X    theTriDCs[1].x = theDynX;
  686. X    theTriDCs[1].y = theDynY;
  687. X    theTriStripCount = 2;
  688. X  }
  689. X}
  690. X
  691. Xstatic void fbFinishTriStrip (event )
  692. X XButtonReleasedEvent *event;
  693. X{
  694. X  int i, count;
  695. X  PEXCoord *p;
  696. X
  697. X  if (theTriStripCount < 3) return;
  698. X
  699. X  if ((count = theRenderProcs.MapXToMC( &theMCMatrix, theTriStripCount,
  700. X                       theTriDCs, &p))  ==  theTriStripCount) {
  701. X    if ( count > 2 ) {
  702. X      InsertTriStripCmd( count, p, 1 );
  703. X      free((char *)p);
  704. X      theRenderProcs.ReDraw();
  705. X    }
  706. X  }
  707. X  theTriStripCount = 0;
  708. X}
  709. X
  710. X /*************************************************************************
  711. X *  fbInitNURBCurve - initialze and reinit NURBCurve inster dynamics.
  712. X *
  713. X * if we are working on a NURBCurve, then start the next point. Otherwise,
  714. X *  we are just drawing a line!
  715. X *
  716. X * made applicable to polygons by calling the press handler of [1] when full.
  717. X */
  718. Xstatic void fbInitNURBCurve(event )
  719. X XButtonPressedEvent *event;
  720. X{
  721. X  if (theTriStripCount) {
  722. X    if (theTriStripCount == TRIMAX) {
  723. X      thePressHandlerTable[1]( event );
  724. X      return;
  725. X    }
  726. X    theAnchorX = theDynX;
  727. X    theAnchorY = theDynY;
  728. X    theDynX = event->x;
  729. X    theDynY = event->y;
  730. X    XDrawLine( theDisplay, theWindow, theDynGC, 
  731. X        theAnchorX, theAnchorY, theDynX, theDynY );
  732. X  } else {
  733. X    theAnchorX = event->x;
  734. X    theAnchorY = event->y;
  735. X    theDynX = event->x;
  736. X    theDynY = event->y;
  737. X    XDrawLine( theDisplay, theWindow, theDynGC, 
  738. X          theAnchorX, theAnchorY, theDynX, theDynY );
  739. X    theTriDCs[theTriStripCount].x = theDynX;
  740. X    theTriDCs[theTriStripCount].y = theDynY;
  741. X    theTriStripCount++;  /* save this point as the first point */
  742. X  }
  743. X}
  744. X
  745. Xstatic void fbEndNURBCurve(event )
  746. X XButtonReleasedEvent *event;
  747. X{
  748. X  if (theTriStripCount) {
  749. X    XDrawLine( theDisplay, theWindow, 
  750. X          theDynGC, theAnchorX, theAnchorY, theDynX, theDynY );
  751. X    theDynX = event->x;
  752. X    theDynY = event->y;
  753. X    XDrawLine( theDisplay, theWindow, 
  754. X          theDynGC, theAnchorX, theAnchorY, theDynX, theDynY );
  755. X    theTriDCs[theTriStripCount].x = theDynX;
  756. X    theTriDCs[theTriStripCount].y = theDynY;
  757. X    theTriStripCount++;
  758. X  }
  759. X}
  760. X
  761. Xstatic void fbFinishNURBCurve (event )
  762. X XButtonReleasedEvent *event;
  763. X{
  764. X  int i, count;
  765. X  PEXCoord *p;
  766. X
  767. X  if (theTriStripCount < 3) return;
  768. X
  769. X  if ((count = theRenderProcs.MapXToMC( &theMCMatrix, theTriStripCount,
  770. X                       theTriDCs, &p))  ==  theTriStripCount) {
  771. X    if ( count > 2 ) {
  772. X      InsertNURBCurveCmd( count, p, 1 );
  773. X      free((char *)p);
  774. X      theRenderProcs.ReDraw();
  775. X    }
  776. X  }
  777. X  theTriStripCount = 0;
  778. X}
  779. X
  780. Xstatic void fbFinishPolygon (event )
  781. X XButtonReleasedEvent *event;
  782. X{
  783. X  int i, count;
  784. X  PEXCoord *p;
  785. X
  786. X  if (theTriStripCount < 3) return;
  787. X
  788. X  if ((count = theRenderProcs.MapXToMC( &theMCMatrix, theTriStripCount,
  789. X                       theTriDCs, &p))  ==  theTriStripCount) {
  790. X    if ( count > 2 ) {
  791. X      InsertPolygonCmd( count, p, 1 );
  792. X      free((char *)p);
  793. X      theRenderProcs.ReDraw();
  794. X    }
  795. X  }
  796. X  theTriStripCount = 0;
  797. X}
  798. X
  799. Xstatic void fbEndText(event )
  800. X XButtonReleasedEvent *event;
  801. X{
  802. X  XPoint xp[2];
  803. X  PEXCoord *pl;
  804. X  int count;
  805. X  char *charStr;
  806. X  int flags;
  807. X  
  808. X
  809. X  XDrawPoint(  theDisplay, theWindow, theDynGC, event->x, event->y );
  810. X
  811. X  xp[0].x = event->x;
  812. X  xp[0].y = event->y;
  813. X
  814. X  if ((theRenderProcs.MapXToMC( &theMCMatrix, 1, xp, &pl)) == 1) {
  815. X    GetSomeTextFromUI( event->x, event->y, &count, &charStr, &flags );
  816. X    InsertTextCmd( pl, count, charStr, flags, 1 );
  817. X    free(charStr);
  818. X    free((char *)pl);
  819. X    theRenderProcs.ReDraw();
  820. X  }
  821. X}
  822. X
  823. X
  824. X/*************************************************************************
  825. X *
  826. X */
  827. Xstatic void fbInitTranslate(event )
  828. X XButtonPressedEvent *event;
  829. X{
  830. X
  831. X  theAnchorX = event->x;
  832. X  theAnchorY = event->y;
  833. X  theDynX = event->x;
  834. X  theDynY = event->y;
  835. X  XDrawPoint( theDisplay, theWindow, theDynGC, 
  836. X        theAnchorX, theAnchorY );
  837. X}
  838. X
  839. Xstatic void fbEndTranslate(event ) 
  840. X XButtonReleasedEvent *event;
  841. X{
  842. X  XPoint xp[2];
  843. X  PEXCoord *pl;
  844. X  int count;
  845. X
  846. X  if ( theSelectedElement == -1 ) {
  847. X    printf("nothing selected\n");
  848. X    return;
  849. X  }
  850. X
  851. X  theDynX = event->x;
  852. X  theDynY = event->y;
  853. X  XDrawPoint( theDisplay, theWindow, theDynGC, 
  854. X        theDynX, theDynY );
  855. X
  856. X  xp[0].x = theAnchorX;
  857. X  xp[0].y = theAnchorY;
  858. X  xp[1].x = theDynX;
  859. X  xp[1].y = theDynY;
  860. X  if ((count = theRenderProcs.MapXToMC( &theMCMatrix, 2, xp, &pl)) ==  2) {
  861. X    TranslateSelected( pl );
  862. X    free((char *)pl);
  863. X    theRenderProcs.ReDraw();
  864. X  }
  865. X}
  866. X
  867. X/*************************************************************************
  868. X *
  869. X */
  870. Xstatic void fbInitStretch(event )
  871. X XButtonPressedEvent *event;
  872. X{
  873. X  int i, count;
  874. X  XPoint *points, *p;
  875. X  float dist, currentDist;
  876. X  int error;
  877. X
  878. X  theSelectedIndex = -1;
  879. X
  880. X  error = GetXPointsFromSelected(&count, &points);
  881. X  if (error) {
  882. X    printf("imagine a popup dialog... bad mapping in InitStretch %d\n", error );
  883. X    return;
  884. X  }
  885. X
  886. X  currentDist = MAXFLOAT;
  887. X
  888. X  for (i = 0, p = points; i < count; i++, p++ ) {
  889. X    /* don't bother with divide, only relative dist counts */
  890. X    dist = (event->x - p->x)*(event->x - p->x) + 
  891. X           (event->y - p->y)*(event->y - p->y);
  892. X    if (dist < currentDist) {
  893. X      currentDist = dist;
  894. X      theSelectedIndex = i;
  895. X    }
  896. X  }
  897. X
  898. X  if (theSelectedIndex == -1) return;
  899. X
  900. X  if (theSelectedIndex > 0) {
  901. X    theAnchorX = points[theSelectedIndex-1].x;
  902. X    theAnchorY = points[theSelectedIndex-1].y;
  903. X  } else {
  904. X    theAnchorX = points[theSelectedIndex+1].x;
  905. X    theAnchorY = points[theSelectedIndex+1].y;
  906. X  }
  907. X  free(points); /* all done */
  908. X  
  909. X  theDynX = event->x;
  910. X  theDynY = event->y;
  911. X  XDrawLine( theDisplay, theWindow, theDynGC, 
  912. X        theAnchorX, theAnchorY, theDynX, theDynY );
  913. X
  914. X  /*
  915. X   * O.K.  we're ready.
  916. X   */
  917. X  theMotionHandlerTable[2] = fbDynLine;
  918. X}
  919. X
  920. X/*************************************************************************
  921. X * fbEndStretch
  922. X */
  923. Xstatic void fbEndStretch(event )
  924. X XButtonReleasedEvent *event;
  925. X{
  926. X  XPoint xp;
  927. X  PEXCoord *pl;
  928. X  int count;
  929. X
  930. X  xp.x = event->x;
  931. X  xp.y = event->y;
  932. X  if ((count = theRenderProcs.MapXToMC( &theMCMatrix, 1, &xp, &pl)) ==  1) {
  933. X    if ( count == 1 ) {
  934. X      StretchSelected(pl);
  935. X      free((char *)pl);
  936. X      theRenderProcs.ReDraw();
  937. X    }
  938. X    theMotionHandlerTable[2] = fbDummy;
  939. X  }
  940. X}       
  941. X
  942. X/*************************************************************************
  943. X *
  944. X */
  945. Xstatic void fbInitView(event ) 
  946. X XButtonPressedEvent *event;
  947. X{
  948. X  PEXVector  vpn;  /* view plane normal    */
  949. X  float tsinTheta;
  950. X    
  951. X  theDynX = event->x;
  952. X  theDynY = event->y;
  953. X
  954. X  /* view plane normal */
  955. X  GetVPN(1, &vpn);
  956. X
  957. X  PEXNormalizeVectors(1,&vpn,&vpn); /* just in case the user was playing */
  958. X
  959. X  /*
  960. X   * theta = atan2(cos(phi)*sin(theta), cos(phi)*cos(theta))
  961. X   */
  962. X  theTheta = atan2(vpn.x, vpn.z);
  963. X  /*
  964. X   * atan2(sin(theta), cos(theta)) gives theta.
  965. X   * since we have sin(phi) = dy and dx = cos(phi)*sin(theta)
  966. X   * we want atan2(dy, dx/sin(theta)) BUT sin(theta) will be zero
  967. X   * so we use dy*sin(theta) BUT when sin(theta) and dx are negative
  968. X   * it changes the quadrant. so...
  969. X   */
  970. X  tsinTheta = sin(theTheta);
  971. X  if (tsinTheta >= 0 ) {
  972. X   thePhi = atan2( vpn.y * tsinTheta, vpn.x);
  973. X  } else {
  974. X   thePhi = atan2( -(vpn.y * tsinTheta), -vpn.x);
  975. X  }
  976. X/*  
  977. X  thedebug = 1;
  978. X  printf("start t %g, p %g, x,y,z %g, %g, %g\n", theTheta, thePhi,  
  979. X   vpn.x, vpn.y, vpn.z);
  980. X*/
  981. X}
  982. X
  983. Xstatic void fbDynView(event )
  984. X XMotionEvent *event;
  985. X{
  986. X  PEXVector  vpn;  /* view plane normal    */
  987. X  PEXVector  vup;  /* view up vector       */
  988. X  float cx, cy, cz;
  989. X  int t, c;
  990. X        
  991. X  theTheta += 0.005 * (theDynX - event->x);
  992. X  thePhi   += 0.005 * (event->y - theDynY);
  993. X
  994. X  theDynX = event->x;
  995. X  theDynY = event->y;
  996. X
  997. X
  998. X  vpn.x = cos( thePhi ) * sin( theTheta );
  999. X  vpn.y = sin( thePhi );
  1000. X  vpn.z = cos( thePhi ) * cos( theTheta );
  1001. X
  1002. X  /* view up vector */
  1003. X  GetVUP(1, &vup);
  1004. X
  1005. X  t = 6; c = 0;
  1006. X  while (t--) {
  1007. X    cx = vpn.y*vup.z - vpn.z*vup.y;
  1008. X    cy = vpn.z*vup.x - vpn.x*vup.z;
  1009. X    cz = vpn.x*vup.y - vpn.y*vup.x;
  1010. X  
  1011. X    if ((cx*cx + cy*cy + cz*cz) < 0.1) {
  1012. X        if ((vup.y < 0.8) && (vup.y > -0.8)) {
  1013. X          vup.y += 0.03;
  1014. X        } else {
  1015. X          vup.x += 0.05;
  1016. X        }
  1017. X    PEXNormalizeVectors(1,&vup,&vup);
  1018. X        c = 1;
  1019. X    } else {
  1020. X        t = 0;
  1021. X    }
  1022. X  }
  1023. X
  1024. X  if (c) {
  1025. X    SetVUP(1,&vup);
  1026. X  }      
  1027. X  SetVPN(1,&vpn);
  1028. X
  1029. X  applyViewSet(1);
  1030. X  XSync(theDisplay,1); /* sync and discard events */
  1031. X}
  1032. X
  1033. Xstatic void fbEndView(event )
  1034. X XButtonReleasedEvent *event;
  1035. X{
  1036. X  Window root, child;
  1037. X  int root_x, root_y;
  1038. X  int win_x, win_y;
  1039. X  unsigned int keys_buttons;
  1040. X      
  1041. X  XQueryPointer(theDisplay,theWindow,
  1042. X                &root, &child, &root_x, &root_y, &win_x, &win_y,
  1043. X                &keys_buttons);
  1044. X  XQueryPointer(theDisplay,theWindow,
  1045. X                &root, &child, &root_x, &root_y, &win_x, &win_y,
  1046. X                &keys_buttons);
  1047. X/*                
  1048. X    if ((win_x != theDynX) && (win_y != theDynY)) {
  1049. X        printf("spinning... %d, %d, %d, %d\n", 
  1050. X        theDynX,win_x,theDynY,win_y);
  1051. X    }
  1052. X*/
  1053. X}
  1054. X
  1055. X/*************************************************************************
  1056. X * fbEndZoom
  1057. X *
  1058. X */
  1059. Xstatic void fbEndZoom(event )
  1060. X XButtonReleasedEvent *event;
  1061. X{
  1062. X  PEXMatrix XCtoNPC;
  1063. X  PEXCoord p[2];
  1064. X  int err;
  1065. X  float t;
  1066. X  XWindowAttributes winAttrs;
  1067. X  
  1068. X  p[0].x = event->x;
  1069. X  p[0].y = event->y;
  1070. X  p[0].z = 0.0;
  1071. X  p[1].x = theAnchorX;
  1072. X  p[1].y = theAnchorY;
  1073. X  p[1].z = 0.0;
  1074. X
  1075. X  theRenderProcs.MapXToNPC( 2, p );
  1076. X
  1077. X  /* this really belongs next to Resize */
  1078. X
  1079. X#define SWAP(a,b) {t=a;a=b;b=t;}
  1080. X
  1081. X  if (p[0].x > p[1].x) SWAP(p[0].x, p[1].x);
  1082. X  if (p[0].y > p[1].y) SWAP(p[0].y, p[1].y);
  1083. X
  1084. X  if ((p[1].y - p[0].y) > (p[1].x - p[0].x)) {
  1085. X    theWindowSize = (p[1].y - p[0].y)/2.0;
  1086. X  } else {
  1087. X    theWindowSize = (p[1].x - p[0].x)/2.0;
  1088. X  }
  1089. X  theWindowCenterX = (p[0].x+p[1].x)/2.0;
  1090. X  theWindowCenterY = (p[0].y+p[1].y)/2.0;
  1091. X
  1092. X  XGetWindowAttributes(theDisplay,theWindow,&winAttrs);
  1093. X
  1094. X  ResizeWindow(theWindow, winAttrs.width, winAttrs.height );
  1095. X
  1096. X  theRenderProcs.ReDraw();
  1097. X}
  1098. X
  1099. Xstatic void fbZoomReset(event )
  1100. X XButtonReleasedEvent *event;
  1101. X{
  1102. X  XWindowAttributes winAttrs;
  1103. X
  1104. X  theWindowSize = 0.5;
  1105. X  theWindowCenterX = 0.5;
  1106. X  theWindowCenterY = 0.5;
  1107. X
  1108. X  XGetWindowAttributes(theDisplay,theWindow,&winAttrs);
  1109. X
  1110. X  ResizeWindow(theWindow, winAttrs.width, winAttrs.height );
  1111. X
  1112. X  theRenderProcs.ReDraw();
  1113. X}
  1114. X
  1115. X/*************************************************************************
  1116. X * fbInitCircle - 
  1117. X */
  1118. Xstatic void fbInitCircle(event )
  1119. X XButtonPressedEvent *event;
  1120. X{
  1121. X  double angle;
  1122. X  int i;
  1123. X  double distance;
  1124. X
  1125. X  theAnchorX = event->x;
  1126. X  theAnchorY = event->y;
  1127. X  theDynX = event->x+1;
  1128. X  theDynY = event->y;
  1129. X
  1130. X  angle = (2*M_PI) / (double)(TRIMAX-1);
  1131. X  distance = sqrt((double)((theDynX-theAnchorX)*(theDynX-theAnchorX) + 
  1132. X               (theDynY-theAnchorY)*(theDynY-theAnchorY)));
  1133. X
  1134. X  for (i = 0; i < TRIMAX; i++) {
  1135. X    theTriDCs[i].x = theDynX + (int)(distance*cos((double)i*angle));
  1136. X    theTriDCs[i].y = theDynY + (int)(distance*sin((double)i*angle));;
  1137. X  }
  1138. X  XDrawLines( theDisplay, theWindow, theDynGC, 
  1139. X         theTriDCs, TRIMAX, CoordModeOrigin );
  1140. X}
  1141. X
  1142. Xstatic void fbEndCircle(event )
  1143. X XButtonReleasedEvent *event;
  1144. X{
  1145. X  XPoint xp[3];
  1146. X  PEXCoord *pl;
  1147. X  int count;
  1148. X
  1149. X  xp[0].x = theAnchorX;
  1150. X  xp[0].y = theAnchorY;
  1151. X  xp[1].x = theDynX;
  1152. X  xp[1].y = theDynY;
  1153. X
  1154. X  xp[2].x = (theDynX == theAnchorY)?theDynX+5:theDynX;
  1155. X  xp[2].y = (theDynY == theAnchorY)?theAnchorX+5:theAnchorX;
  1156. X
  1157. X  if ((count = theRenderProcs.MapXToMC( &theMCMatrix, 3, xp, &pl)) ==  3) {
  1158. X    InsertCircleCmd( 3, pl, 1 );
  1159. X    free((char *)pl);
  1160. X    theRenderProcs.ReDraw();
  1161. X  }
  1162. X}
  1163. X
  1164. Xstatic void fbDynCircle(event )
  1165. X XMotionEvent *event;
  1166. X{
  1167. X  double angle;
  1168. X  int i;
  1169. X  double distance;
  1170. X
  1171. X  XDrawLines( theDisplay, theWindow, theDynGC, 
  1172. X         theTriDCs, TRIMAX, CoordModeOrigin );
  1173. X  theDynX = event->x;
  1174. X  theDynY = event->y;
  1175. X
  1176. X  angle = (2*M_PI) / (double)(TRIMAX-1);
  1177. X  distance = sqrt((double)((theDynX-theAnchorX)*(theDynX-theAnchorX) + 
  1178. X               (theDynY-theAnchorY)*(theDynY-theAnchorY)));
  1179. X
  1180. X  for (i = 0; i < TRIMAX; i++) {
  1181. X    theTriDCs[i].x = theDynX + (int)(distance*cos((double)i*angle));
  1182. X    theTriDCs[i].y = theDynY + (int)(distance*sin((double)i*angle));;
  1183. X  }
  1184. X  XDrawLines( theDisplay, theWindow, theDynGC, 
  1185. X         theTriDCs, TRIMAX, CoordModeOrigin );
  1186. X}
  1187. END_OF_FILE
  1188.   if test 27419 -ne `wc -c <'fb.c'`; then
  1189.     echo shar: \"'fb.c'\" unpacked with wrong size!
  1190.   fi
  1191.   # end of 'fb.c'
  1192. fi
  1193. if test -f 'pexdrawc.1' -a "${1}" != "-c" ; then 
  1194.   echo shar: Will not clobber existing file \"'pexdrawc.1'\"
  1195. else
  1196.   echo shar: Extracting \"'pexdrawc.1'\" \(30534 characters\)
  1197.   sed "s/^X//" >'pexdrawc.1' <<'END_OF_FILE'
  1198. X#ifdef SCCS
  1199. Xstatic char sccsid[]="@(#)pexdraw.c    1.30 Oki Electric Industry Co., Ltd. 93/06/01";
  1200. X#endif
  1201. X/*
  1202. X *            Copyright (c) 1992 by
  1203. X *            Oki Electric Industry Co., Ltd.
  1204. X *            All Rights Reserved
  1205. X *
  1206. X * Permission to use, copy, modify, and distribute this software and its
  1207. X * documentation for any purpose and without fee is hereby granted,
  1208. X * provided that the above copyright notice appear in all copies and that
  1209. X * both that copyright notice and this permission notice appear in
  1210. X * supporting documentation, and that the name of Oki not be
  1211. X * used in advertising or publicity pertaining to distribution of the
  1212. X * software without specific, written prior permission. Oki
  1213. X * makes no representations about the suitability of this software for any
  1214. X * purpose.  It is provided "as is" without express or implied warranty.
  1215. X *
  1216. X *************************************************************************
  1217. X *
  1218. X *                         P E X D R A W
  1219. X *
  1220. X *  A PEX drawing program based on PDRAW,
  1221. X *
  1222. X *   
  1223. X *
  1224. X *************************************************************************/
  1225. X
  1226. X#include <stdio.h>
  1227. X
  1228. X#include <math.h>
  1229. X
  1230. X#include <X11/Xlib.h>
  1231. X#include <X11/Xutil.h>
  1232. X#include <X11/Xatom.h>
  1233. X
  1234. X#include <X11/PEX5/PEXlib.h>
  1235. X
  1236. X#define DECL_GLOBALS 1
  1237. X
  1238. X#include "pexdraw.h"
  1239. X
  1240. X#define LIGHTMAX 8
  1241. XPEXLookupTable    theLightLUT;
  1242. XPEXTableIndex    theLightsOn[LIGHTMAX];
  1243. Xint        theLightsOnCount = 0;
  1244. XPEXTableIndex    theLightsOff[1];
  1245. Xint        theLightsOffCount = 0;
  1246. X
  1247. Xstatic float    AmbientColor[3] = { 1,1,1 };
  1248. Xstatic float    LightColor[3] = { 0.9, 0.9, 0.9 };
  1249. Xstatic float    LightVector[3] = { 0.0, 0.0, -1.0 };
  1250. X
  1251. X#define SELECT_COLOR_IND 3
  1252. Xstatic int theRandomColorIndex = 1;
  1253. X#define RANDOM_COLOR_MAX 8
  1254. X
  1255. X#define INT_STYLE_ELEM 3
  1256. X#define REFL_EQN_ELEM 4
  1257. X#define REFL_ATTRS_ELEM 5
  1258. X#define INT_SHAD_ELEM 6
  1259. X#define LIGHT_SRC_ELEM 7
  1260. X#define MATRIX_ELEM 8
  1261. X#define FACE_CULL_ELEM 9
  1262. X
  1263. Xextern renderProcs wksProcs, rdrProcs;
  1264. X
  1265. Xstatic int theMCSeqNo = 0;
  1266. Xint theHPFlag = 0;
  1267. X
  1268. X /*************************************************************************
  1269. X *
  1270. X * A P P L I C A T I O N    P R O C E D U R E S
  1271. X *
  1272. X *************************************************************************
  1273. X *
  1274. X * Still a little overlap with the selected object interactions.
  1275. X */
  1276. X
  1277. X
  1278. X/*************************************************************************
  1279. X * TranslateSelected - translate whatever is selected by the given vector
  1280. X */
  1281. Xvoid
  1282. XTranslateSelected(points)
  1283. X PEXCoord *points;
  1284. X{
  1285. X  int error;
  1286. X  char *eData;
  1287. X  float deltaX, deltaY, deltaZ;
  1288. X  PEXCoord *p;
  1289. X  int i, nPoints;
  1290. X  unsigned long count, length;
  1291. X  PEXOCData *ocd, *OCData;
  1292. X
  1293. X  if ( theSelectedElement == -1 ) return;
  1294. X
  1295. X  deltaX = points[1].x - points[0].x;
  1296. X  deltaY = points[1].y - points[0].y;
  1297. X  deltaZ = points[1].z - points[0].z;
  1298. X
  1299. X  if (!(PEXFetchElements( theDisplay, theSelectedStrux,
  1300. X               PEXBeginning, theSelectedElement+1,
  1301. X               PEXBeginning, theSelectedElement+1, theFF,
  1302. X               &count, &length, &eData ))) { return; }
  1303. X
  1304. X  OCData = PEXDecodeOCs( theFF, count, length, eData );
  1305. X
  1306. X  if ( OCData->oc_type  == PEXOCPolyline) {
  1307. X
  1308. X    nPoints = OCData->data.Polyline.count;
  1309. X    p = OCData->data.Polyline.points;
  1310. X
  1311. X    for (i = 0; i < nPoints; i++, p++ ) {
  1312. X      p->x += deltaX;
  1313. X      p->y += deltaY;
  1314. X      p->z +=deltaZ;
  1315. X    }
  1316. X
  1317. X    PEXSetElementPtr( theDisplay, theSelectedStrux, 
  1318. X             PEXBeginning, theSelectedElement+2 );
  1319. X    PEXPolyline(theDisplay, theSelectedStrux, PEXOCStore, nPoints,  
  1320. X        OCData->data.Polyline.points);
  1321. X    PEXMarkers(theDisplay, theSelectedStrux, PEXOCStore, nPoints,  
  1322. X           OCData->data.Polyline.points);
  1323. X    PEXDeleteElements( theDisplay, theSelectedStrux, 
  1324. X              PEXCurrent, -3, PEXCurrent, -2);
  1325. X  } else if ( OCData->oc_type == PEXOCTriangleStrip ) { 
  1326. X
  1327. X    if (OCData->data.TriangleStrip.vertex_attributes) {
  1328. X      /* should check to make sure there are no normals!!! */
  1329. X      /* it would be fairly easy to work with these, but not now */
  1330. X      return;
  1331. X    }
  1332. X
  1333. X    p = OCData->data.TriangleStrip.vertices.no_data;
  1334. X
  1335. X    for (i = 0; i < OCData->data.TriangleStrip.count; i++, p++ ) {
  1336. X      p->x += deltaX;
  1337. X      p->y += deltaY;
  1338. X      p->z += deltaZ;
  1339. X    }
  1340. X
  1341. X    PEXSetElementPtr( theDisplay, theSelectedStrux, 
  1342. X             PEXBeginning, theSelectedElement+2 );
  1343. X    PEXTriangleStrip( theDisplay, theSelectedStrux, PEXOCStore, 
  1344. X             OCData->data.TriangleStrip.facet_attributes,
  1345. X             OCData->data.TriangleStrip.vertex_attributes,
  1346. X             OCData->data.TriangleStrip.color_type,
  1347. X             OCData->data.TriangleStrip.facet_data,
  1348. X             OCData->data.TriangleStrip.count,
  1349. X             OCData->data.TriangleStrip.vertices );
  1350. X    PEXMarkers( theDisplay, theSelectedStrux, PEXOCStore, 
  1351. X           OCData->data.TriangleStrip.count,
  1352. X           OCData->data.TriangleStrip.vertices.no_data );
  1353. X    PEXDeleteElements( theDisplay, theSelectedStrux, 
  1354. X              PEXCurrent, -3, PEXCurrent, -2 );
  1355. X  } else if ( OCData->oc_type == PEXOCNURBCurve ) { 
  1356. X
  1357. X    if (OCData->data.NURBCurve.rationality == PEXRational) {
  1358. X      int i;
  1359. X      double w;
  1360. X      PEXCoord4D *p4;
  1361. X
  1362. X      p4 = OCData->data.NURBCurve.points.point_4d;
  1363. X      for (i = 0; i < OCData->data.NURBCurve.count; i++, p4++ ) {
  1364. X    w = 1.0 / p4->w;
  1365. X    p4->x = ((p4->x * w) + deltaX) * p4->w;
  1366. X    p4->y = ((p4->y * w) + deltaY) * p4->w;
  1367. X    p4->z = ((p4->z * w) + deltaZ) * p4->w;
  1368. X      }
  1369. X    } else {
  1370. X      p = OCData->data.NURBCurve.points.point;
  1371. X
  1372. X      for (i = 0; i < OCData->data.NURBCurve.count; i++, p++ ) {
  1373. X    p->x += deltaX;
  1374. X    p->y += deltaY;
  1375. X    p->z += deltaZ;
  1376. X      }
  1377. X    }
  1378. X
  1379. X    PEXSetElementPtr( theDisplay, theSelectedStrux, 
  1380. X             PEXBeginning, theSelectedElement+2 );
  1381. X    PEXNURBCurve(theDisplay, theSelectedStrux, PEXOCStore, 
  1382. X         OCData->data.NURBCurve.rationality,
  1383. X         OCData->data.NURBCurve.order, 
  1384. X         OCData->data.NURBCurve.knots,
  1385. X         OCData->data.NURBCurve.count, OCData->data.NURBCurve.points,
  1386. X         OCData->data.NURBCurve.tmin, OCData->data.NURBCurve.tmax );
  1387. X    if (OCData->data.NURBCurve.rationality == PEXRational) {
  1388. X      int i;
  1389. X      double w;
  1390. X      for (i = 0; i < OCData->data.NURBCurve.count; i++ ) {
  1391. X    w = 1.0 / OCData->data.NURBCurve.points.point_4d[i].w;
  1392. X    OCData->data.NURBCurve.points.point[i].x = 
  1393. X      OCData->data.NURBCurve.points.point_4d[i].x * w;
  1394. X    OCData->data.NURBCurve.points.point[i].y = 
  1395. X      OCData->data.NURBCurve.points.point_4d[i].y * w;
  1396. X    OCData->data.NURBCurve.points.point[i].z = 
  1397. X      OCData->data.NURBCurve.points.point_4d[i].z * w;
  1398. X      }
  1399. X    }
  1400. X    PEXMarkers( theDisplay, theSelectedStrux, PEXOCStore, 
  1401. X           OCData->data.NURBCurve.count,
  1402. X           OCData->data.NURBCurve.points.point );
  1403. X    PEXDeleteElements( theDisplay, theSelectedStrux, 
  1404. X              PEXCurrent, -3, PEXCurrent, -2 );
  1405. X  } else if ( OCData->oc_type == PEXOCText ) { 
  1406. X
  1407. X    OCData->data.EncodedText.origin.x += deltaX;
  1408. X    OCData->data.EncodedText.origin.y += deltaY;
  1409. X    OCData->data.EncodedText.origin.z += deltaZ;
  1410. X
  1411. X    PEXSetElementPtr( theDisplay, theSelectedStrux, 
  1412. X             PEXBeginning, theSelectedElement+2 );
  1413. X    PEXEncodedText( theDisplay, theSelectedStrux, PEXOCStore, 
  1414. X           &OCData->data.EncodedText.origin,
  1415. X           &OCData->data.EncodedText.vector1,
  1416. X           &OCData->data.EncodedText.vector2,
  1417. X           OCData->data.EncodedText.count,
  1418. X           OCData->data.EncodedText.encoded_text );
  1419. X    PEXMarkers( theDisplay, theSelectedStrux, PEXOCStore, 1,
  1420. X           &OCData->data.EncodedText.origin );
  1421. X    PEXDeleteElements( theDisplay, theSelectedStrux, 
  1422. X              PEXCurrent, -3, PEXCurrent, -2 );
  1423. X  } else {
  1424. X    printf("imagine a Motif alarm! selecting unknown element type %d\n",
  1425. X       OCData->oc_type );
  1426. X    return;
  1427. X  }
  1428. X}
  1429. X
  1430. X/*************************************************************************
  1431. X * StretchSelected
  1432. X */
  1433. XStretchSelected(points)
  1434. X     PEXCoord *points;
  1435. X{
  1436. X  int error;
  1437. X  char *eData;
  1438. X  float deltaX, deltaY, deltaZ;
  1439. X  PEXCoord *p;
  1440. X  int i, nPoints;
  1441. X  unsigned long count, length;
  1442. X  PEXOCData *ocd, *OCData;
  1443. X
  1444. X  if ( theSelectedElement == -1 ) return;
  1445. X
  1446. X  if (!(PEXFetchElements( theDisplay, theSelectedStrux,
  1447. X               PEXBeginning, theSelectedElement+1,
  1448. X               PEXBeginning, theSelectedElement+1, theFF,
  1449. X               &count, &length, &eData ))) { return; }
  1450. X
  1451. X  OCData = PEXDecodeOCs( theFF, count, length, eData );
  1452. X
  1453. X  if (OCData->oc_type  == PEXOCPolyline) {
  1454. X
  1455. X    nPoints = OCData->data.Polyline.count;
  1456. X    p = OCData->data.Polyline.points;
  1457. X
  1458. X    p[theSelectedIndex] = points[0];
  1459. X    PEXSetElementPtr( theDisplay, theSelectedStrux,
  1460. X             PEXBeginning,  theSelectedElement+2 );
  1461. X    PEXPolyline(theDisplay, theSelectedStrux, PEXOCStore, nPoints,
  1462. X        OCData->data.Polyline.points);
  1463. X    PEXMarkers(theDisplay, theSelectedStrux, PEXOCStore, nPoints,
  1464. X        OCData->data.Polyline.points);
  1465. X    PEXDeleteElements( theDisplay, theSelectedStrux, 
  1466. X              PEXCurrent, -3, PEXCurrent, -2);
  1467. X  } else if (OCData->oc_type == PEXOCTriangleStrip ) { 
  1468. X
  1469. X    if (OCData->data.TriangleStrip.vertex_attributes) {
  1470. X      /* should check to make sure there are no normals!!! */
  1471. X      return;
  1472. X    }
  1473. X
  1474. X    p = OCData->data.TriangleStrip.vertices.no_data;
  1475. X    p[theSelectedIndex] = points[0];
  1476. X
  1477. X    PEXSetElementPtr( theDisplay, theSelectedStrux,
  1478. X             PEXBeginning,  theSelectedElement+2 );
  1479. X    PEXTriangleStrip( theDisplay, theSelectedStrux, PEXOCStore, 
  1480. X             OCData->data.TriangleStrip.facet_attributes,
  1481. X             OCData->data.TriangleStrip.vertex_attributes,
  1482. X             OCData->data.TriangleStrip.color_type,
  1483. X             OCData->data.TriangleStrip.facet_data,
  1484. X             OCData->data.TriangleStrip.count,
  1485. X             OCData->data.TriangleStrip.vertices );
  1486. X    PEXMarkers( theDisplay, theSelectedStrux, PEXOCStore, 
  1487. X           OCData->data.TriangleStrip.count,
  1488. X           OCData->data.TriangleStrip.vertices.no_data );
  1489. X    PEXDeleteElements( theDisplay, theSelectedStrux, 
  1490. X              PEXCurrent, -3, PEXCurrent, -2);
  1491. X  } else if ( OCData->oc_type == PEXOCNURBCurve ) { 
  1492. X
  1493. X    if (OCData->data.NURBCurve.rationality == PEXRational) {
  1494. X      PEXCoord4D *p4;
  1495. X
  1496. X      p4 = OCData->data.NURBCurve.points.point_4d;
  1497. X      p4[theSelectedIndex].x = points[0].x * p4[theSelectedIndex].w;
  1498. X      p4[theSelectedIndex].y = points[0].y * p4[theSelectedIndex].w;
  1499. X      p4[theSelectedIndex].z = points[0].z * p4[theSelectedIndex].w;
  1500. X    } else {
  1501. X      p = OCData->data.NURBCurve.points.point;
  1502. X      p[theSelectedIndex] = points[0];
  1503. X    }
  1504. X
  1505. X    PEXSetElementPtr( theDisplay, theSelectedStrux, 
  1506. X             PEXBeginning, theSelectedElement+2 );
  1507. X    PEXNURBCurve(theDisplay, theSelectedStrux, PEXOCStore, 
  1508. X         OCData->data.NURBCurve.rationality,
  1509. X         OCData->data.NURBCurve.order, 
  1510. X         OCData->data.NURBCurve.knots,
  1511. X         OCData->data.NURBCurve.count, OCData->data.NURBCurve.points,
  1512. X         OCData->data.NURBCurve.tmin, OCData->data.NURBCurve.tmax );
  1513. X    if (OCData->data.NURBCurve.rationality == PEXRational) {
  1514. X      int i;
  1515. X      double w;
  1516. X      for (i = 0; i < OCData->data.NURBCurve.count; i++ ) {
  1517. X    w = 1.0 / OCData->data.NURBCurve.points.point_4d[i].w;
  1518. X    OCData->data.NURBCurve.points.point[i].x = 
  1519. X      OCData->data.NURBCurve.points.point_4d[i].x * w;
  1520. X    OCData->data.NURBCurve.points.point[i].y = 
  1521. X      OCData->data.NURBCurve.points.point_4d[i].y * w;
  1522. X    OCData->data.NURBCurve.points.point[i].z = 
  1523. X      OCData->data.NURBCurve.points.point_4d[i].z * w;
  1524. X      }
  1525. X    }
  1526. X    PEXMarkers( theDisplay, theSelectedStrux, PEXOCStore, 
  1527. X           OCData->data.NURBCurve.count,
  1528. X           OCData->data.NURBCurve.points.point );
  1529. X    PEXDeleteElements( theDisplay, theSelectedStrux, 
  1530. X              PEXCurrent, -3, PEXCurrent, -2 );
  1531. X  } else if ( OCData->oc_type == PEXOCText ) { 
  1532. X
  1533. X    OCData->data.EncodedText.origin = points[0];
  1534. X
  1535. X    PEXSetElementPtr( theDisplay, theSelectedStrux, 
  1536. X             PEXBeginning, theSelectedElement+2 );
  1537. X    PEXEncodedText( theDisplay, theSelectedStrux, PEXOCStore, 
  1538. X           &OCData->data.EncodedText.origin,
  1539. X           &OCData->data.EncodedText.vector1,
  1540. X           &OCData->data.EncodedText.vector2,
  1541. X           OCData->data.EncodedText.count,
  1542. X           OCData->data.EncodedText.encoded_text );
  1543. X    PEXMarkers( theDisplay, theSelectedStrux, PEXOCStore, 1,
  1544. X           &OCData->data.EncodedText.origin );
  1545. X    PEXDeleteElements( theDisplay, theSelectedStrux, 
  1546. X              PEXCurrent, -3, PEXCurrent, -2 );
  1547. X  } else {
  1548. X    printf("imagine a Motif alarm! selecting unknown element type %d, %d\n",
  1549. X       OCData->oc_type );
  1550. X  }
  1551. X}
  1552. X
  1553. X/*************************************************************************
  1554. X * SelectSomething - make something look selected.
  1555. X *
  1556. X */
  1557. Xvoid SelectSomething(strux,element)
  1558. X long strux;
  1559. X long element;
  1560. X{
  1561. X  int error;
  1562. X  char *eData;
  1563. X  PEXCoord *p;  
  1564. X  int nPoints;
  1565. X  unsigned long count, length;
  1566. X  PEXOCData *OCData;
  1567. X
  1568. X  if (!(PEXFetchElements( theDisplay, strux,
  1569. X                PEXBeginning, element, PEXBeginning, element, 
  1570. X                theFF, &count, &length, &eData ))) { return; }
  1571. X
  1572. X  PEXSetElementPtr( theDisplay, strux, PEXBeginning,  element );
  1573. X
  1574. X  OCData = PEXDecodeOCs( theFF, count, length, eData );
  1575. X
  1576. X  if (OCData->oc_type  == PEXOCPolyline) {
  1577. X
  1578. X    nPoints = OCData->data.Polyline.count;
  1579. X    p = OCData->data.Polyline.points;
  1580. X    PEXMarkers(theDisplay, strux, PEXOCStore, nPoints, p);
  1581. X    PEXSetElementPtr( theDisplay, strux, PEXCurrent,  -2 );
  1582. X    PEXSetLineColorIndex( theDisplay, strux, PEXOCStore,
  1583. X             SELECT_COLOR_IND);
  1584. X  } else if (OCData->oc_type == PEXOCTriangleStrip ) { 
  1585. X
  1586. X   if (OCData->data.TriangleStrip.vertex_attributes) {
  1587. X      /* should check to make sure there are no normals!!! */
  1588. X      /* it would be fairly easy to work with these, but not now */
  1589. X      return;
  1590. X    }
  1591. X
  1592. X    PEXMarkers(theDisplay, strux, PEXOCStore, 
  1593. X           OCData->data.TriangleStrip.count, 
  1594. X           OCData->data.TriangleStrip.vertices.no_data );
  1595. X    PEXSetElementPtr( theDisplay, strux, PEXCurrent,  -2 );
  1596. X    PEXSetSurfaceColorIndex( theDisplay, strux, PEXOCStore, 
  1597. X                SELECT_COLOR_IND);
  1598. X  } else if (OCData->oc_type == PEXOCNURBCurve ) { 
  1599. X
  1600. X    if (OCData->data.NURBCurve.rationality == PEXRational) {
  1601. X      int i;
  1602. X      double w;
  1603. X      for (i = 0; i < OCData->data.NURBCurve.count; i++ ) {
  1604. X    w = 1.0 / OCData->data.NURBCurve.points.point_4d[i].w;
  1605. X    OCData->data.NURBCurve.points.point[i].x = 
  1606. X      OCData->data.NURBCurve.points.point_4d[i].x * w;
  1607. X    OCData->data.NURBCurve.points.point[i].y = 
  1608. X      OCData->data.NURBCurve.points.point_4d[i].y * w;
  1609. X    OCData->data.NURBCurve.points.point[i].z = 
  1610. X      OCData->data.NURBCurve.points.point_4d[i].z * w;
  1611. X      }
  1612. X    }
  1613. X
  1614. X    PEXMarkers(theDisplay, strux, PEXOCStore, 
  1615. X           OCData->data.NURBCurve.count, 
  1616. X           OCData->data.NURBCurve.points.point );
  1617. X    PEXSetElementPtr( theDisplay, strux, PEXCurrent,  -2 );
  1618. X    PEXSetLineColorIndex( theDisplay, strux, PEXOCStore, 
  1619. X                SELECT_COLOR_IND);
  1620. X  } else if (OCData->oc_type == PEXOCText ) { 
  1621. X
  1622. X    if (GetTextRect(OCData, theSelectedStrux, theSelectedElement-1, &p)) {
  1623. X      PEXMarkers(theDisplay, strux, PEXOCStore, 4, p);
  1624. X    } else {
  1625. X      PEXMarkers(theDisplay, strux, PEXOCStore, 1,
  1626. X         &OCData->data.EncodedText.origin );
  1627. X    }
  1628. X    PEXSetElementPtr( theDisplay, strux, PEXCurrent,  -2 );
  1629. X    PEXSetTextColorIndex( theDisplay, strux, PEXOCStore, 
  1630. X                SELECT_COLOR_IND);
  1631. X  } else {
  1632. X    printf("imagine a Motif alarm! selecting unknown element type %d\n",
  1633. X       OCData->oc_type );
  1634. X    PEXFreeOCData(count, OCData);
  1635. X    free(eData);
  1636. X    return;
  1637. X  }
  1638. X
  1639. X  theSelectedStrux = strux;
  1640. X  theSelectedElement = element;
  1641. X  PEXFreeOCData(count, OCData);
  1642. X  free(eData);
  1643. X}
  1644. X
  1645. X/*************************************************************************
  1646. X * ClearSelection
  1647. X *
  1648. X * Implicitly knows that each element has a color followed by a primitive
  1649. X *  - color
  1650. X *  - primitive
  1651. X *  
  1652. X * The selected Element has an extra color between the color & prim and 
  1653. X * the point primitive directly afterwords.  Two extra elements.  This
  1654. X * will be a headache if multiple elements are allowed to be selected.
  1655. X *
  1656. X *  - color
  1657. X *  - select color
  1658. X *  - primitive
  1659. X *  - points.
  1660. X *
  1661. X * The selected color is really at theSelectedElement. Set the pointer and 
  1662. X * delete it. The element pointer moves forward.  Skip two elements and 
  1663. X * delete the points.
  1664. X *
  1665. X */
  1666. Xvoid ClearSelection()
  1667. X{
  1668. X  if ( theSelectedElement == -1 ) return;
  1669. X
  1670. X  PEXDeleteElements( theDisplay, theSelectedStrux,
  1671. X            PEXBeginning, theSelectedElement,
  1672. X            PEXBeginning, theSelectedElement);
  1673. X
  1674. X  PEXDeleteElements( theDisplay, theSelectedStrux,
  1675. X            PEXBeginning, theSelectedElement+1,
  1676. X            PEXBeginning, theSelectedElement+1);
  1677. X
  1678. X  theSelectedStrux = -1;
  1679. X  theSelectedElement= -1;
  1680. X}
  1681. X
  1682. X/*************************************************************************
  1683. X * DeleteSelected
  1684. X */
  1685. Xvoid DeleteSelected()
  1686. X{
  1687. X  if ( theSelectedElement == -1 ) return;
  1688. X
  1689. X  PEXDeleteElements( theDisplay, theSelectedStrux,
  1690. X            PEXBeginning, theSelectedElement-1,
  1691. X            PEXBeginning, theSelectedElement+2);
  1692. X
  1693. X  theSelectedStrux = -1;
  1694. X  theSelectedElement= -1;
  1695. X
  1696. X}
  1697. X/*************************************************************************
  1698. X * ColorGroup -- this is in lieu of SelectGroup and the management of
  1699. X * a group of selected objects.
  1700. X *
  1701. X */
  1702. Xvoid ColorGroup( count, struxArray, elemArray )
  1703. X     int count;
  1704. X     long *struxArray;
  1705. X     int *elemArray;
  1706. X{
  1707. X  int i;
  1708. X  unsigned long length;
  1709. X
  1710. X  PEXElementInfo *eInfo;
  1711. X  unsigned long eCount;
  1712. X
  1713. X  if ( ++theRandomColorIndex > RANDOM_COLOR_MAX) theRandomColorIndex = 2;
  1714. X
  1715. X  for (i = 0; i < count; i++ ) {
  1716. X       if(PEXGetElementInfo(theDisplay, struxArray[i],
  1717. X                PEXBeginning, elemArray[i],
  1718. X                PEXBeginning, elemArray[i],
  1719. X                theFF, &eCount, &eInfo )){
  1720. X    if ((eCount == 1) &&
  1721. X    ((eInfo->type >= OCPRIMTAB_BASE) && (eInfo->type <= OCPRIMTAB_MAX))) {
  1722. X
  1723. X      PEXDeleteElements( theDisplay, struxArray[i],
  1724. X            PEXBeginning, elemArray[i]-1,
  1725. X            PEXBeginning, elemArray[i]-1 );
  1726. X
  1727. X      switch (myOCPrimType[eInfo->type-OCPRIMTAB_BASE]) {
  1728. X      case OCPRIM_MARKER:
  1729. X    PEXSetMarkerColorIndex( theDisplay, struxArray[i], PEXOCStore,
  1730. X                 theRandomColorIndex );
  1731. X    break;
  1732. X      case OCPRIM_LINE:
  1733. X    PEXSetLineColorIndex( theDisplay, struxArray[i], PEXOCStore,
  1734. X                 theRandomColorIndex );
  1735. X    break;
  1736. X      case OCPRIM_PGON:
  1737. X    PEXSetSurfaceColorIndex( theDisplay, struxArray[i], PEXOCStore, 
  1738. X                 theRandomColorIndex );
  1739. X    break;
  1740. X      case OCPRIM_TEXT:
  1741. X    PEXSetTextColorIndex( theDisplay, struxArray[i], PEXOCStore,
  1742. X                 theRandomColorIndex );
  1743. X    break;
  1744. X      default:
  1745. X    break;
  1746. X      }
  1747. X    }
  1748. X  } else { printf("PEXGetStructureInfo failed\n");}
  1749. X}
  1750. X}
  1751. X
  1752. X/*************************************************************************
  1753. X * InitStrux
  1754. X */
  1755. XPEXStructure 
  1756. XInitStrux()
  1757. X{
  1758. X  PEXName names[2];
  1759. X  int error;
  1760. X  PEXMatrix matrix;
  1761. X  PEXReflectionAttributes reflAttrs;
  1762. X  PEXStructure struxid;
  1763. X
  1764. X  struxid = PEXCreateStructure(theDisplay);
  1765. X
  1766. X  PEXSetEditingMode(theDisplay, struxid, PEXStructureInsert);
  1767. X
  1768. X  theRenderProcs.Post( struxid );
  1769. X
  1770. X  /*
  1771. X   * need this for picking
  1772. X   */
  1773. X  names[0] = 2;
  1774. X  names[1] = 1;
  1775. X  PEXAddToNameSet(theDisplay, struxid, PEXOCStore, 2, names );
  1776. X
  1777. X  PEXSetViewIndex(theDisplay, struxid, PEXOCStore, 1);
  1778. X
  1779. X  /* INT_STYLE_ELEM == element 3 */
  1780. X  PEXSetInteriorStyle(theDisplay, struxid, PEXOCStore, PEXInteriorStyleHollow );
  1781. X
  1782. X  /* REFL_EQN_ELEM  == element 4 */
  1783. X  PEXSetReflectionModel(theDisplay, struxid, PEXOCStore, PEXReflectionSpecular);
  1784. X
  1785. X  /* set the area properties */
  1786. X  reflAttrs.ambient = 0.3;
  1787. X  reflAttrs.diffuse = 0.3;
  1788. X  reflAttrs.specular = 0.7;
  1789. X  reflAttrs.specular_conc = 50.0;
  1790. X  reflAttrs.transmission = 0.0;
  1791. X  reflAttrs.specular_color.type = PEXColorTypeRGB;
  1792. X  reflAttrs.specular_color.value.rgb.red   = 1.0;
  1793. X  reflAttrs.specular_color.value.rgb.green = 1.0;
  1794. X  reflAttrs.specular_color.value.rgb.blue  = 1.0;
  1795. X
  1796. X  PEXSetReflectionAttributes(theDisplay, struxid, PEXOCStore, &reflAttrs);
  1797. X  /* INT_SHAD_ELEM  == element */
  1798. X  PEXSetSurfaceInterpMethod(theDisplay, struxid, PEXOCStore, 
  1799. X                PEXSurfaceInterpNone);
  1800. X  PEXSetLightSourceState(theDisplay, struxid, PEXOCStore, 
  1801. X             theLightsOnCount, theLightsOn, 
  1802. X             theLightsOffCount, theLightsOff );
  1803. X  PEXRotate(PEXXAxis, 0.0, theMCMatrix.matrix );
  1804. X  PEXSetLocalTransform(theDisplay, struxid, PEXOCStore, PEXReplace, 
  1805. X               theMCMatrix.matrix);
  1806. X  theMCMatrix.strux = struxid;
  1807. X  theMCMatrix.seqNo = ++theMCSeqNo;
  1808. X
  1809. X  return (struxid);
  1810. X}
  1811. X
  1812. X/*************************************************************************
  1813. X * InsertLine
  1814. X */
  1815. Xvoid InsertLineCmd( nPoints, points, select )
  1816. X     int nPoints;
  1817. X     PEXCoord *points;
  1818. X     int select;
  1819. X{
  1820. X
  1821. X  int error, e;
  1822. X
  1823. X  if (theNewStrux == 0) {
  1824. X    theNewStrux = InitStrux();
  1825. X  } else if ( theSelectedElement != -1 ) {
  1826. X    ClearSelection();
  1827. X  }
  1828. X
  1829. X  PEXSetElementPtr( theDisplay, theNewStrux, PEXEnd,  0 );
  1830. X
  1831. X  PEXSetLineColorIndex( theDisplay, theNewStrux, PEXOCStore, 1);
  1832. X
  1833. X  PEXPolyline(theDisplay, theNewStrux, PEXOCStore, nPoints, points);
  1834. X
  1835. X  if (select) {
  1836. X    PEXStructureInfo info;
  1837. X
  1838. X    if (PEXGetStructureInfo(theDisplay, theNewStrux, theFF, PEXElementPtr,
  1839. X                &info )) {
  1840. X      SelectSomething( theNewStrux, info.element_pointer );
  1841. X    } else { printf("PEXGetStructureInfo failed\n");}
  1842. X  }
  1843. X}
  1844. X
  1845. X/*************************************************************************
  1846. X * InsertTriStrip
  1847. X */
  1848. Xvoid
  1849. XInsertTriStripCmd( nPoints, points, select )
  1850. X     int nPoints;
  1851. X     PEXCoord *points;
  1852. X     int select;
  1853. X{
  1854. X  int error, e;
  1855. X  PEXArrayOfFacetData tooLateToCast;
  1856. X  PEXArrayOfVertex too;  /* should be able to cast these somehow, too late */
  1857. X
  1858. X  if (theNewStrux == 0) {
  1859. X    theNewStrux = InitStrux();
  1860. X  } else if ( theSelectedElement != -1 ) {
  1861. X    ClearSelection();
  1862. X  }
  1863. X
  1864. X  PEXSetElementPtr( theDisplay, theNewStrux, PEXEnd,  0 );
  1865. X
  1866. X  PEXSetSurfaceColorIndex( theDisplay, theNewStrux, PEXOCStore, 1);
  1867. X  too.no_data = points;
  1868. X  tooLateToCast.index = NULL;
  1869. X  PEXTriangleStrip( theDisplay, theNewStrux, PEXOCStore, 0, 0, PEXColorTypeRGB,
  1870. X           tooLateToCast, nPoints, too);
  1871. X
  1872. X  if (select) {
  1873. X    PEXStructureInfo  info;
  1874. X
  1875. X    if (PEXGetStructureInfo(theDisplay, theNewStrux, theFF, PEXElementPtr,
  1876. X                &info )) {
  1877. X      SelectSomething( theNewStrux, info.element_pointer );
  1878. X    } else { printf("PEXGetStructureInfo failed\n");}
  1879. X  }
  1880. X}
  1881. X
  1882. X/*************************************************************************
  1883. X * InsertNURBCurveCmd
  1884. X */
  1885. Xvoid InsertNURBCurveCmd( nPoints, points, select )
  1886. X     int nPoints;
  1887. X     PEXCoord *points;
  1888. X     int select;
  1889. X{
  1890. X  int order = 3;
  1891. X  float *knots, knotValue;
  1892. X  int error, e, i;
  1893. X  PEXArrayOfCoord p;
  1894. X
  1895. X  if (nPoints < order) {printf("not enough points\n"); return;}
  1896. X
  1897. X  if (theNewStrux == 0) {
  1898. X    theNewStrux = InitStrux();
  1899. X  } else if ( theSelectedElement != -1 ) {
  1900. X    ClearSelection();
  1901. X  }
  1902. X
  1903. X  knots = (float *)malloc((nPoints+order)*sizeof(float)); if (!knots)
  1904. X    {printf("Knots\n"); exit(1);}
  1905. X  p.point = points;
  1906. X
  1907. X  /*
  1908. X   * generate a knot vector for a uniform B-splines
  1909. X   */
  1910. X  knotValue = 0.0;
  1911. X  for (i = 0; i < order; i++ ) knots[i] = knotValue;
  1912. X  knotValue++;
  1913. X  for (i = order; i < nPoints; i++, knotValue++) knots[i] = knotValue;
  1914. X  for (i = nPoints; i < nPoints+order; i++ ) knots[i] = knotValue;
  1915. X
  1916. X  PEXSetElementPtr( theDisplay, theNewStrux, PEXEnd,  0 );
  1917. X
  1918. X  PEXSetLineColorIndex( theDisplay, theNewStrux, PEXOCStore, 1);
  1919. X
  1920. X  PEXNURBCurve(theDisplay, theNewStrux, PEXOCStore, PEXNonRational, order, 
  1921. X           knots, (unsigned int)nPoints, p, 
  1922. X           (double)0.0, (double)knotValue);
  1923. X
  1924. X  free((char *)knots);
  1925. X
  1926. X  if (select) {
  1927. X    PEXStructureInfo info;
  1928. X
  1929. X    if (PEXGetStructureInfo(theDisplay, theNewStrux, theFF, PEXElementPtr,
  1930. X                &info )) {
  1931. X      SelectSomething( theNewStrux, info.element_pointer );
  1932. X    } else { printf("PEXGetStructureInfo failed\n");}
  1933. X  }
  1934. X}
  1935. X
  1936. Xvoid Cross3D( A, B, C )
  1937. X     PEXVector *A;
  1938. X     PEXVector *B;
  1939. X     PEXVector *C;
  1940. X{
  1941. X  C->x = (A->y * B->z) - (A->z * B->y);
  1942. X  C->y = (A->z * B->x) - (A->x * B->z);
  1943. X  C->z = (A->x * B->y) - (A->y * B->x);
  1944. X}
  1945. X
  1946. X/*************************************************************************
  1947. X * InsertCircleCmd - do a rational NURB. There are at least three ways to do
  1948. X *  this:
  1949. X * 2 are found on page 374, Mathematical Elements for Computer Graphics, 
  1950. X *   2nd ed. David F. Rogers and J Alan Adams. McGraw Hill, 1990.
  1951. X * One of which is the triangle method, using 7 control points at the corners
  1952. X *   and middles of an equilateral triangle, with knot vector
  1953. X *   [ 0, 0, 0, 1, 1, 2, 2, 3, 3, 3 ] and weights ( or H or W values )
  1954. X *   [ 1.0, 0.5, 1.0, 0.5, 1.0, 0.5, 1.0]
  1955. X *
  1956. X * The second is a square, with control points at the corners and midpoints.
  1957. X *  X (knots) = [0,0,0,1,1,2,2,3,3,4,4,4]
  1958. X *  W         = [1.0, 0.707, 1.0, 0.707, 1.0, 0.707, 1.0] 
  1959. X *                                           0.707 = sqrt(2)/sqrt(2)
  1960. X *
  1961. X * A third is a square, but only two of the sides have midpoint controls.
  1962. X *  X [ 0,0,0, 0.25, 0.5, 0.5, 0.75, 1,1,1]
  1963. X *  W [1, 0.5, 0.5, 1, 0.5, 0.5, 1]
  1964. X * from Piegl, Les. On NURBS: A Survey. IEEE CG&A, January 1991.
  1965. X *
  1966. X * We are going to use the triangle.
  1967. X *
  1968. X * we have two points, center of circle & triangle & p1 == p7.
  1969. X *  distance to p2, & p6  is RADICAL3 * distance from p1 to center.
  1970. X *  distance from p1 to p4 ( top of triangle ) is 3 * distance to center.
  1971. X *  just make p3 & p5 midpoints.
  1972. X *
  1973. X * We must have a thrid point to construct the plane.
  1974. X *
  1975. X */
  1976. Xvoid InsertCircleCmd( nPoints, points, select )
  1977. X     int nPoints;
  1978. X     PEXCoord *points;
  1979. X     int select;
  1980. X{
  1981. X  int order = 3;
  1982. X  float knots[10];
  1983. X  PEXCoord4D p4[7];
  1984. X  PEXArrayOfCoord p;
  1985. X  double distance;
  1986. X  PEXVector A, B, C;
  1987. X
  1988. X  if (nPoints != 3) {printf("not enough points\n"); return;}
  1989. X
  1990. X  if (theNewStrux == 0) {
  1991. X    theNewStrux = InitStrux();
  1992. X  } else if ( theSelectedElement != -1 ) {
  1993. X    ClearSelection();
  1994. X  }
  1995. X
  1996. X  A.x = points[0].x - points[1].x;
  1997. X  A.y = points[0].y - points[1].y;
  1998. X  A.z = points[0].z - points[1].z;
  1999. X
  2000. X  B.x = points[2].x - points[1].x;
  2001. X  B.y = points[2].y - points[1].y;
  2002. X  B.z = points[2].z - points[1].z;
  2003. X
  2004. X  Cross3D( &A, &B, &C );
  2005. X  Cross3D( &A, &C, &B );
  2006. X  PEXNormalizeVectors( 1, &B, &B );
  2007. X
  2008. X  /* 
  2009. X   * B now contains a unit vector perpedicular to A in the plane
  2010. X   * defined by the three input points.  After we get the distance
  2011. X   * we can define all of the points of the equilateral triangle.
  2012. X   */
  2013. X  distance = sqrt(A.x*A.x + A.y*A.y + A.z*A.z);
  2014. X
  2015. X#define RADICAL3 1.732
  2016. X
  2017. X  p4[0].x =points[0].x; p4[0].y =points[0].y; p4[0].z =points[0].z; 
  2018. X  p4[0].w = 1.0;
  2019. X
  2020. X  p4[6] = p4[0];
  2021. X
  2022. X  /*
  2023. X   * rational NURB control points are given as x*w, y*w, z*w, w 
  2024. X   * p1 & p7 are the midpoint of the base.
  2025. X   * p2 & p6 are the corners of base.
  2026. X   */
  2027. X  p4[1].w = 0.5;
  2028. X  p4[1].x = (points[0].x + RADICAL3 * distance * B.x) * p4[1].w;
  2029. X  p4[1].y = (points[0].y + RADICAL3 * distance * B.y) * p4[1].w;
  2030. X  p4[1].z = (points[0].z + RADICAL3 * distance * B.z) * p4[1].w;
  2031. X
  2032. X  p4[5].w = 0.5;
  2033. X  p4[5].x = (points[0].x - RADICAL3 * distance * B.x) * p4[1].w;
  2034. X  p4[5].y = (points[0].y - RADICAL3 * distance * B.y) * p4[1].w;
  2035. X  p4[5].z = (points[0].z - RADICAL3 * distance * B.z) * p4[1].w;
  2036. X
  2037. X  /* the top of the triangle is 3X past the center */
  2038. X
  2039. X  p4[3].w = 0.5;
  2040. X  p4[3].x = (points[0].x - 3 * A.x) * p4[1].w;
  2041. X  p4[3].y = (points[0].y - 3 * A.y) * p4[1].w;
  2042. X  p4[3].z = (points[0].z - 3 * A.z) * p4[1].w;
  2043. X
  2044. X  /* now get the midpoints, special case of weights = 0.5 !!! */
  2045. X
  2046. X  p4[2].w = p4[1].w + p4[3].w;
  2047. X  p4[2].x = p4[1].x + p4[3].x;
  2048. X  p4[2].y = p4[1].y + p4[3].y;
  2049. X  p4[2].z = p4[1].z + p4[3].z;
  2050. X
  2051. X  p4[4].w = p4[5].w + p4[3].w;
  2052. X  p4[4].x = p4[5].x + p4[3].x;
  2053. X  p4[4].y = p4[5].y + p4[3].y;
  2054. X  p4[4].z = p4[5].z + p4[3].z;
  2055. X
  2056. X  p.point_4d = p4;
  2057. X
  2058. X  /*
  2059. X   * generate a knot vector for a uniform B-splines
  2060. X   *   [ 0, 0, 0, 1, 1, 2, 2, 3, 3, 3 ]
  2061. X   */
  2062. X  knots[0] = 0; knots[1] = 0; knots[2] = 0;
  2063. X  knots[3] = 1; knots[4] = 1;  
  2064. X  knots[5] = 2; knots[6] = 2;
  2065. X  knots[7] = 3; knots[8] = 3; knots[9] = 3;
  2066. X
  2067. X  PEXSetElementPtr( theDisplay, theNewStrux, PEXEnd,  0 );
  2068. X
  2069. X  PEXSetLineColorIndex( theDisplay, theNewStrux, PEXOCStore, 1);
  2070. X
  2071. X  PEXNURBCurve(theDisplay, theNewStrux, PEXOCStore, PEXRational,
  2072. X           order, knots, (unsigned int)7, p, 
  2073. X           (double)0.0, (double)3.0);
  2074. X
  2075. X  if (select) {
  2076. X    PEXStructureInfo info;
  2077. X
  2078. X    if (PEXGetStructureInfo(theDisplay, theNewStrux, theFF, PEXElementPtr,
  2079. X                &info )) {
  2080. X      SelectSomething( theNewStrux, info.element_pointer );
  2081. X    } else { printf("PEXGetStructureInfo failed\n");}
  2082. X  }
  2083. X}
  2084. X
  2085. X/*************************************************************************
  2086. X * InsertPolygonCmd
  2087. X */
  2088. Xvoid InsertPolygonCmd( nPoints, points, select )
  2089. X     int nPoints;
  2090. X     PEXCoord *points;
  2091. X     int select;
  2092. X{
  2093. X
  2094. X  if (nPoints < 3) {printf("not enough points\n"); return;}
  2095. X
  2096. X  if (theNewStrux == 0) {
  2097. X    theNewStrux = InitStrux();
  2098. X  } else if ( theSelectedElement != -1 ) {
  2099. X    ClearSelection();
  2100. X  }
  2101. X
  2102. X  PEXSetElementPtr( theDisplay, theNewStrux, PEXEnd,  0 );
  2103. X
  2104. X  PEXSetSurfaceColorIndex( theDisplay, theNewStrux, PEXOCStore, 1);
  2105. X
  2106. X  PEXFillArea(theDisplay, theNewStrux, PEXOCStore, PEXShapeUnknown, 
  2107. X          True, /* ignore edges, for the heck of it */
  2108. X           (unsigned int)nPoints, points );
  2109. X
  2110. X  if (select) {
  2111. X    PEXStructureInfo info;
  2112. X
  2113. X    if (PEXGetStructureInfo(theDisplay, theNewStrux, theFF, PEXElementPtr,
  2114. X                &info )) {
  2115. X      SelectSomething( theNewStrux, info.element_pointer );
  2116. X    } else { printf("PEXGetStructureInfo failed\n");}
  2117. X  }
  2118. X}
  2119. X
  2120. X/*************************************************************************
  2121. X * InsertTextCmd - 
  2122. X */
  2123. Xvoid InsertTextCmd( point,nChars,charStr, flags, select )
  2124. X     PEXCoord *point;
  2125. X     int nChars;
  2126. X     char *charStr;
  2127. X     int flags;
  2128. X     int select;
  2129. X{
  2130. X  PEXVector vector1, vector2;
  2131. X  int error, e;
  2132. X
  2133. X  if (theNewStrux == 0) {
  2134. X    theNewStrux = InitStrux();
  2135. X  } else if ( theSelectedElement != -1 ) {
  2136. X    ClearSelection();
  2137. X  }
  2138. X
  2139. X    vector1.x = 1.0;
  2140. X    vector1.y = 0.0;
  2141. X    vector1.z = 0.0;
  2142. X    vector2.x = 0.0;
  2143. X    vector2.y = 1.0;
  2144. X    vector2.z = 0.0;
  2145. X
  2146. X  PEXSetElementPtr( theDisplay, theNewStrux, PEXEnd,  0 );
  2147. X
  2148. X  PEXSetTextColorIndex( theDisplay, theNewStrux, PEXOCStore, 1);
  2149. X
  2150. X  PEXText(theDisplay, theNewStrux, PEXOCStore,
  2151. X      point, &vector1, &vector2, nChars, charStr );
  2152. X
  2153. X  if (select) {
  2154. X    PEXStructureInfo info;
  2155. X
  2156. X    if (PEXGetStructureInfo(theDisplay, theNewStrux, theFF, PEXElementPtr,
  2157. X                &info )) {
  2158. X      SelectSomething( theNewStrux, info.element_pointer );
  2159. X    } else { printf("PEXGetStructureInfo failed\n");}
  2160. X  }
  2161. X}
  2162. X
  2163. X/*************************************************************************
  2164. X *  GetXPointsFromSelected
  2165. X *
  2166. X *  generate X coordinates for each vertex of the selected object.
  2167. X *   - inquire element contents
  2168. X *   - map from world [should be model] to screen using MapWCPointsToX
  2169. X *
  2170. X * ALLOCATES points array.
  2171. X */
  2172. Xint
  2173. XGetXPointsFromSelected(nPoints_return, points )
  2174. X     int *nPoints_return;
  2175. X     XPoint **points;
  2176. X{
  2177. X  int i;
  2178. X  int error;
  2179. X  char *eData;
  2180. X  PEXCoord *p;  
  2181. X  int nPoints, nGot;
  2182. X  unsigned long count, length;
  2183. X  PEXOCData *OCData, *matrixOC;
  2184. X  MCMatrix mc;
  2185. X
  2186. X  if (!(PEXFetchElements( theDisplay, theSelectedStrux,
  2187. X               PEXBeginning, theSelectedElement+1,
  2188. X               PEXBeginning, theSelectedElement+1, theFF,
  2189. X               &count, &length, &eData ))) { return; }
  2190. X
  2191. X
  2192. X  OCData = PEXDecodeOCs( theFF, count, length, eData );
  2193. X  XFree((char *)eData);
  2194. X
  2195. X  if (OCData->oc_type  == PEXOCPolyline) {
  2196. X    nPoints = OCData->data.Polyline.count;
  2197. X    p = OCData->data.Polyline.points;
  2198. END_OF_FILE
  2199.   if test 30534 -ne `wc -c <'pexdrawc.1'`; then
  2200.     echo shar: \"'pexdrawc.1'\" unpacked with wrong size!
  2201.   fi
  2202.   # end of 'pexdrawc.1'
  2203. fi
  2204. echo shar: End of archive 9 \(of 14\).
  2205. cp /dev/null ark9isdone
  2206. MISSING=""
  2207. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ; do
  2208.     if test ! -f ark${I}isdone ; then
  2209.     MISSING="${MISSING} ${I}"
  2210.     fi
  2211. done
  2212. if test "${MISSING}" = "" ; then
  2213.     echo You have unpacked all 14 archives.
  2214.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2215.     echo "concatentating pexdraw.c ..."
  2216.     cat pexdrawc.? > pexdraw.c
  2217.     rm pexdrawc.?
  2218.     echo "concatentating pexdraw.uil ..."
  2219.     cat pexdrawu.? > pexdraw.uil
  2220.     rm pexdrawu.?
  2221.     echo "concatentating teapot.c ..."
  2222.     rm teapotc.?
  2223. else
  2224.     echo You still must unpack the following archives:
  2225.     echo "        " ${MISSING}
  2226. fi
  2227. exit 0
  2228. exit 0 # Just in case...
  2229. -- 
  2230.   // chris@IMD.Sterling.COM       | Send comp.sources.x submissions to:
  2231. \X/  Amiga - The only way to fly! |    sources-x@imd.sterling.com
  2232.  "It's intuitively obvious to the |
  2233.   most casual observer..."        | GCS d+/-- p+ c++ l+ m+ s++/+ g+ w+ t+ r+ x+
  2234.