home *** CD-ROM | disk | FTP | other *** search
/ Plug-In Power Pack for Netscape Communicator / Plug-In Power Pack for Netscape Communicator.iso / plugins / dataviews / dvtools / demos / procdemo / procdemo.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-07-10  |  32.6 KB  |  1,180 lines

  1. #ifndef lint
  2. static char SccsId[]= "@(#)procdemo.c    V1.23    3/17/95";
  3. #endif
  4.  
  5. /*
  6. |    file name - procdemo.c
  7. |===================================================================
  8. |
  9. |               copyright (c) 1986
  10. |                          V. I. Corporation
  11. |
  12. |===================================================================
  13. |
  14. |    module description/function:
  15. |
  16. |    demonstrates use of DVtools subroutines for a process
  17. |    application.
  18. |
  19. |    This program can be linked to run:
  20. |        With 100% CPU usage (which shows updates in a tight loop)
  21. |        With Xt-base Time-Outs (which show update based on a timer.
  22. |
  23. |        Set DV_RUNNING_IN_X according to the comments below.
  24. |
  25. |    If the program is compiled to run in X, the optional arguments are:
  26. |
  27. |       <time-out rate in milliseconds>         The default is 100
  28. |       <top view name>                 The default is top.v
  29. |
  30. |    Other wise the optional arguments are:
  31. |
  32. |       <device name>                           The default is NULL.
  33. |       <top view name>                 The default is top.v
  34. |
  35. |===================================================================
  36. */
  37.  
  38. #include "std.h"
  39. #include "dvstd.h"
  40. #include "VOstd.h"
  41. #include "dvtools.h"
  42. #include "Tfundecl.h"
  43. #include "VOfundecl.h"
  44. #include "VTfundecl.h"
  45. #include "VUfundecl.h"
  46. #include "VGfundecl.h"
  47. #include "GRfundecl.h"
  48. #include "prc_fundecl.h"
  49. #include "MISCfuns.h"
  50.  
  51. #ifdef WINNT 
  52. #include <windows.h>
  53. #endif /* WINNT */
  54.  
  55.  
  56. #define MAXNAMELEN     256
  57. #define DEF_COLORTAB    (CHAR*)NULL
  58. #define DEF_PATH    (CHAR*)NULL
  59. #define DEF_DISPTAB    (CHAR*)NULL
  60.  
  61. /* This program can be linked to run:
  62. |
  63. |  With 100% CPU usage (which shows updates in a tight loop)
  64. |       comment #define DV_USE_TIMER
  65. |  With Xt-base Time-Outs (which show update based on a timer.
  66. |       uncomment #define DV_USE_TIMER
  67. */
  68. #define DV_USE_TIMER
  69.  
  70.  
  71. /* Set the DV_RUNNNG_IN_X flag based on the -D compile option */
  72. #ifdef DV_NOT_USING_TIMER
  73. #undef DV_USE_TIMER
  74. #endif
  75.  
  76. #ifdef DV_USE_TIMER
  77.  
  78. LOCAL INT TimeoutInterval = 100;
  79. long updating=0;  /* prevent timer from updating screen too often */
  80. #ifdef WINNT
  81.  
  82.  
  83. LOCAL HWND Hwnd;
  84. LOCAL VOID CALLBACK TimeOutProc V_P_((HWND hwnd,
  85.                                       UINT uMsg,
  86.                                       UINT idEvent,
  87.                                       DWORD dwTime));
  88.  
  89. #else /* UNIX */
  90. /* Include the X based files so we can add AppTimeOuts */
  91. #ifdef CONST
  92. #undef CONST
  93. #endif
  94.  
  95. #ifndef __STDC__
  96. #define _NO_PROTO
  97. #endif
  98.  
  99. /*
  100.  *  X11 include files
  101.  */
  102. #include <X11/Xlib.h>
  103. #include <X11/Intrinsic.h>
  104.  
  105. LOCAL XtAppContext app_context;
  106. LOCAL  void UpdateProc V_P_((ADDRESS args, XtIntervalId *interval_id));
  107.  
  108. #endif /* WINNT */
  109. #endif /* DV_USE_TIMER */
  110.  
  111. /*
  112.  *   Define a data structure for storing the view information.  These
  113.  *     structures will be stored in a symbol table.
  114.  */
  115. typedef struct infostruct
  116. {
  117.   VIEW view;                    /* The loaded view */
  118.   DRAWPORT drawport;            /* The drawport, if required */
  119.   struct infostruct *previous_info;     /* Previous view in chain */
  120.   OBJECT holding_obj;           /* The holding tank object */
  121.   OBJECT reaction_obj;          /* The reaction tank object */
  122.   RECTANGLE holding_rect;       /* Screen area for holding_obj */
  123.   RECTANGLE reaction_rect;      /* Screen area for reaction_obj */
  124.   VIEW merge_view;              /* View merged into */
  125. } VIEWINFO;
  126.  
  127. /*
  128.  *   Global definition of the symbol table identifier.
  129.  */
  130. LOCAL ADDRESS ViewSymTab;
  131.  
  132. LOCAL OBJECT DVscreen;
  133. LOCAL VIEWINFO *current_info;
  134. LOCAL DV_BOOL QuitStatus = NO;
  135. LOCAL DV_BOOL TopViewDrawn = NO;
  136.  
  137. /***************** Begin Function Declarations *************/
  138. LOCAL  void UpdateDisplay V_P_((void));
  139. LOCAL  void HandlePick V_P_((OBJECT location, int key, int button_num));
  140. LOCAL  void QuitProgram V_P_((void));
  141. LOCAL  void LoadSymbolTable V_P_((OBJECT screen, char *filename));
  142. LOCAL  ADDRESS AddSubViews V_P_((OBJECT object, char *name, OBJECT screen));
  143. LOCAL  VIEWINFO *DrawNewView V_P_((VIEWINFO *current, char *object_name));
  144. LOCAL  void DrawMergedDrawing V_P_((VIEWINFO *current, char *object_name));
  145. LOCAL  void TurnValve V_P_((char *object_name, int key, int button_num));
  146. LOCAL  void SetTankRectangles V_P_((VIEWINFO *info));
  147. LOCAL  void ChangeRectangle V_P_((DRAWPORT drawport, OBJECT object, RECTANGLE *rect));
  148. LOCAL  void GetFilename V_P_((char *name, char *filename));
  149. LOCAL  VIEWINFO *CreateViewRecord V_P_((void));
  150. LOCAL  void ExciseAllMergedDrawings V_P_((VIEWINFO *current_info));
  151. LOCAL  VIEWINFO *GetViewRecord V_P_((ADDRESS SymTab, char *key));
  152. LOCAL  ADDRESS GetTankRectangles V_P_((OBJECT object, char *name, VIEWINFO *viewinfo));
  153. LOCAL  void CleanUp V_P_((void));
  154. LOCAL  ADDRESS RebindVdps V_P_((OBJECT vd_obj, ADDRESS vdp, ADDRESS args));
  155. LOCAL  OBJECT GetSubObj V_P_((OBJECT object, int type));
  156. LOCAL  ADDRESS GetObjHelper V_P_((OBJECT object, int *type));
  157. /***************** End Function Declarations *************/
  158.  
  159. /* --------------------------------------------------------------- */
  160.  
  161.  
  162. /*
  163.  *   Main Program
  164.  */
  165. #ifdef WINNT
  166. int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
  167.                      LPSTR lpCmdLine,  int nCmdShow  )
  168. {
  169.   OBJECT location;
  170.   CHAR *device = NULL;
  171.   CHAR *top_view = "top.v";
  172.   INT button_num;
  173.   INT argc = 0;
  174.   CHAR **argv;
  175.   int error_code;
  176.   char buf[50];
  177.  
  178.   make_argv(&argc,&argv,GetCommandLine());
  179.  
  180. #else  /* Not WINNT */
  181. int 
  182. main (argc, argv)
  183.      int argc;
  184.      char *argv[];
  185. {
  186.   OBJECT location;
  187.   CHAR *device = NULL;
  188.   CHAR *top_view = "top.v";
  189.   INT button_num;
  190.   int error_code; 
  191. #endif /* WINNT */
  192.  
  193.  
  194.   /*
  195.    *   Check if the display device is on the command line.
  196.    */
  197.   if (argc > 1)
  198. #ifdef DV_USE_TIMER
  199.     TimeoutInterval = atoi (argv[1]);
  200. #else
  201.     device = argv[1];
  202. #endif
  203.  
  204.   /*
  205.    *   Check if the top view name is on the command line.
  206.    */
  207.   if (argc > 2)
  208.     top_view = argv[2];
  209.  
  210.   /*
  211.    *   Initialize the DV-Tools environment and open the graphics
  212.    *     device.
  213.    */
  214.   VUoff_copyright ();
  215.   (VOID) TInit (DEF_PATH, DEF_DISPTAB);
  216.   DVscreen = TscOpenSet (device, DEF_COLORTAB,
  217.              V_WINDOW_NAME, "DataViews Process Control Demo",
  218. #ifdef WINNT
  219.                          V_WIN32_ICON_NAME,    "procicon",
  220. #ifdef DOUBLE_BUFFER
  221.                          V_WIN32_DOUBLE_BUFFER,  YES,
  222. #endif /* DOUBLE_BUFFER */
  223. #else  /* Not WINNT */
  224.                  V_X_EXPOSURE_BLOCK,    YES,
  225. #endif /* WINNT */
  226.                          V_INITIAL_CURSOR,
  227.                          V_END_OF_LIST);
  228.  
  229.   if(!DVscreen)
  230.  {
  231.    error_code=TscOpenError();
  232. #ifdef WINNT
  233.    sprintf(buf,"Product is not validated. Error code %d.",error_code);
  234.    MessageBox(NULL,buf,"Validation Error",MB_OK);
  235. #else
  236.    fprintf(stderr,"Product is not validated. Error code %d.",error_code);
  237. #endif
  238.    exit(error_code);
  239.   }
  240.  
  241.   /* Setup the window events */
  242.   (VOID) VOscWinEventMask ((ULONG) (V_KEYPRESS |
  243.                                     V_BUTTONPRESS |
  244.                                     V_RESIZE | V_EXPOSE |
  245.                                     V_WINDOW_QUIT),
  246.                            (ULONG) V_END_OF_LIST);
  247.  
  248. #ifdef DV_USE_TIMER
  249. #ifdef WINNT
  250.     /* Get the Windows based information */
  251.     (VOID) GRget (V_WIN32_WINDOW_HANDLE, &Hwnd, V_END_OF_LIST);
  252.     
  253.  /* Post a timeout for dynamic updates
  254.   |  The timeout procedure will update the dynamics of
  255.   |  all screens which have been opened. The procedure is invoked
  256.   |  whenever the specified time interval elapses. The interval is
  257.   |  specified in milliseconds.
  258.   */
  259.     SetTimer (Hwnd, (UINT)Hwnd, TimeoutInterval, (TIMERPROC)TimeOutProc);
  260. #else /* WINNT */
  261.   /* Extract the X information so we can setup a Time-Out Proc
  262.    |  for updating....
  263.    |     Get the Xt Application Context information.
  264.    |     Post a timeout procedure will update the dynamics of
  265.    |     all screens which have been opened. The procedure is invoked
  266.    |     whenever the specified time interval elapses. The interval is
  267.    |     specified in milliseconds.
  268.    */
  269.   (VOID) GRget (V_X_APPLIC_CONTEXT, &app_context, V_END_OF_LIST);
  270.   XtAppAddTimeOut (app_context, TimeoutInterval, 
  271.            (XtTimerCallbackProc) UpdateProc, NULL);
  272.  
  273. #endif /* WINNT */
  274. #endif /* DV_USE_TIMER */
  275.  
  276.   /*
  277.    *   Initialize the data model.
  278.    */
  279.   MDLinit ();
  280.  
  281.   /*
  282.    *   Load all views into the symbol table and get the node for the
  283.    *     initial view. It draws the top view, before loading additional
  284.    *     views;
  285.    */
  286.   LoadSymbolTable (DVscreen, top_view);
  287.   current_info = GetViewRecord (ViewSymTab, top_view);
  288.  
  289.   /* Now that we are ready, reset the cursor */
  290.   (VOID) GRset (V_ACTIVE_CURSOR, V_END_OF_LIST);
  291.  
  292.   while (QuitStatus == NO)
  293.     {
  294.  
  295. #ifdef DV_USE_TIMER
  296.  
  297.       /* Get the Event, The, TimeOut Proc will Update the Display */
  298.       location = VOloWinEventPoll (V_WAIT);
  299. #else
  300.       
  301.       /* Update the Display */
  302.       UpdateDisplay ();
  303.  
  304.       /* Get the Event */
  305.       location = VOloWinEventPoll (V_NO_WAIT);
  306.  
  307.  
  308. #endif
  309.  
  310.       if (location)
  311.         {
  312.  
  313.           /*
  314.            *   Get the key/mouse press.  If the key is the middle mouse button,
  315.            *     then extract all drawings that have been merged into the
  316.            *     current view.  Otherwise get the selected named object
  317.            *     if there is one.
  318.            */
  319.           switch (VOloType (location))
  320.             {
  321.             case V_EXPOSE:
  322.                 if (  updating <= 0)
  323.         {
  324.           updating++;
  325.           (VOID) TscRedraw (DVscreen, VOloRegion (location));
  326.           updating--;
  327.         
  328.         }
  329.               break;
  330.             case V_RESIZE:
  331.                if ( updating <= 0 )
  332.         {
  333.               updating++;
  334.              (VOID) TscReset (DVscreen);
  335.              updating--;
  336.         }
  337.               break;
  338.             case V_WINDOW_QUIT:
  339.               QuitStatus = YES;
  340.               break;
  341.             case V_KEYPRESS:
  342.               HandlePick (location, VOloKey (location), 0);
  343.               break;
  344.             case V_BUTTONPRESS:
  345.               button_num = VOloButton (location);
  346.               switch (button_num)
  347.                 {
  348.                 case 1:
  349.                 case 3:
  350.                   HandlePick (location, 0, button_num);
  351.                   break;
  352.                 case 2:
  353.                   ExciseAllMergedDrawings (current_info);
  354.                   break;
  355.                 default:
  356.                   break;
  357.                   break;
  358.                 }
  359.             }
  360.         }
  361.     }
  362.  
  363.   QuitProgram ();
  364.  
  365.   return (EXIT_OK);
  366. }
  367.  
  368. #ifdef DV_USE_TIMER
  369. #ifdef WINNT
  370. /*ARGSUSED*/
  371. LOCAL VOID CALLBACK
  372. TimeOutProc (hwnd, uMsg, idEvent, dwTime)
  373.     HWND hwnd;
  374.   UINT uMsg;
  375.     UINT idEvent;
  376.     DWORD dwTime;
  377. {
  378.     updating++;
  379.     if ( updating == 1)
  380.     UpdateDisplay ();
  381.     updating--;
  382. }
  383.  
  384. #else /* UNIX */
  385. /*ARGSUSED*/
  386. LOCAL void 
  387. UpdateProc (args, interval_id)
  388.      ADDRESS args;
  389.      XtIntervalId *interval_id;
  390. {
  391.  
  392.   /* Update the current View */
  393.   UpdateDisplay ();
  394.  
  395.   /* Re-Post the Time-Out */
  396.   XtAppAddTimeOut (app_context, TimeoutInterval, 
  397.            (XtTimerCallbackProc) UpdateProc, NULL);
  398. }
  399.  
  400. #endif /* WINNT */
  401. #endif /* DV_USE_TIMER */
  402.  
  403. LOCAL void UpdateDisplay 
  404. V_P_ ((void))
  405. {
  406.   /*
  407.    *   Update the data model to get the next data iteration, adjust
  408.    *     the tank objects, and update all other dynamic portions
  409.    *     of the current view.
  410.    */
  411.   MDLupdate ();
  412.   SetTankRectangles (current_info);
  413.   (VOID) TdpDrawNext (current_info->drawport);
  414. }
  415.  
  416. LOCAL void 
  417. HandlePick (location, key, button_num)
  418.      OBJECT location;
  419.      int key;
  420.      int button_num;
  421. {
  422.   CHAR *object_name;
  423.  
  424.   if ((object_name = TloGetSelectedObjectName (location)))
  425.     {
  426.       /*
  427.        *   If the object name begins with an 'r', then this may be an
  428.        *     indicator of a view to replace the current one.  If it
  429.        *     begins with an 'm', it may be a view to merge with the
  430.        *     current one.  If it begins with a 'v' the this may be a
  431.        *     valve being turned.
  432.        */
  433.       if (*object_name == 'r')
  434.         current_info = DrawNewView (current_info, object_name);
  435.       else if (*object_name == 'm')
  436.         DrawMergedDrawing (current_info, object_name);
  437.       else if (*object_name == 'v')     /* a valve has been found */
  438.         TurnValve (object_name, key, button_num);
  439.  
  440.       /*
  441.        *   If the object name begins with a 'c', then this may be a
  442.        *     command to be performed.  The only current command is
  443.        *     'return' which means to return to the previous view.
  444.        *     If there is no previous view, then break out of the loop
  445.        *     and exit the program.
  446.        */
  447.       else if (*object_name == 'c')     /* a command: */
  448.         if (strcmp (object_name, "c:return") == 0)
  449.           if (current_info->previous_info == NULL)
  450.             /* We're at the top so QUIT */
  451.             QuitStatus = YES;
  452.           else
  453.             {
  454.               (VOID) TdpErase (current_info->drawport);
  455.               current_info = current_info->previous_info;
  456.               (VOID) TdpDraw (current_info->drawport);
  457.             }
  458.     }
  459. }
  460.  
  461.  
  462. LOCAL void QuitProgram 
  463. V_P_ ((void))
  464. {
  465.   /*
  466.    *   When we're done, erase the screen, clean up the memory
  467.    *     we've allocated, and close the graphics device.
  468.    */
  469.   CleanUp ();
  470.   (VOID) TscClose (DVscreen);
  471.   (VOID) TTerminate ();
  472.   S_EXIT (0);
  473. }
  474.  
  475.  
  476. /* --------------------------------------------------------------- */
  477.  
  478.  
  479. /*
  480.  *   LoadSymbolTable  --  creates the symbol table, enters the first
  481.  *     node, and then looks object names indicating that other views
  482.  *     should be loaded in.  Also, checks for tank objects that need
  483.  *     to be treated seperately.
  484.  */
  485. LOCAL void 
  486. LoadSymbolTable (screen, filename)
  487.      OBJECT screen;
  488.      char *filename;
  489. {
  490.   OBJECT drawing;
  491.   VIEWINFO *viewinfo;
  492.  
  493.   /*
  494.    *   Create the symbol table.
  495.    */
  496.   ViewSymTab = VTstcreate ("View Information", (VTSTCOMPAREFUNPTR)NULL);
  497.  
  498.   /*
  499.    *   Make a new node containing the initial view, its drawport,
  500.    *     and the tank object information.  Also, rebind all of this
  501.    *     view's variable descriptors.  Enter this node into the
  502.    *     symbol table.
  503.    */
  504.   viewinfo = CreateViewRecord ();
  505.   viewinfo->view = TviLoad (filename);
  506.   viewinfo->drawport = TdpCreate (screen, viewinfo->view,
  507.                               (RECTANGLE *) NULL, (RECTANGLE *) NULL);
  508.   drawing = TviGetDrawing (viewinfo->view);
  509.   (VOID) TobForEachVdp (drawing, RebindVdps, (ADDRESS) NULL);
  510.   (VOID) TdrForEachNamedObject (drawing, 
  511.                 (TDRFOREACHNAMEDOBJFUNPTR) GetTankRectangles,
  512.                                 (ADDRESS) viewinfo);
  513.   (VOID) VTstsninsert (ViewSymTab, StrClone (filename), (INT *) viewinfo);
  514.  
  515.   /* If top view... Draw it */
  516.   if (TopViewDrawn == NO)
  517.     {
  518.       /*
  519.        *   Adjust the size of the tank objects if necessary, and draw the
  520.        *     initial view.
  521.        */
  522.       SetTankRectangles (viewinfo);
  523.       (VOID) TdpDraw (viewinfo->drawport);
  524.       TopViewDrawn = YES;
  525.     }
  526.  
  527.   /*
  528.    *   Search this view for object names refering to other views that
  529.    *     also need to be loaded into the symbol table.
  530.    */
  531.   (VOID) TdrForEachNamedObject (drawing,
  532.                 (TDRFOREACHNAMEDOBJFUNPTR) AddSubViews, 
  533.                 (ADDRESS) screen);
  534. }
  535.  
  536.  
  537. /* -------------------------------------------------------------- */
  538.  
  539.  
  540. /*
  541.  *   AddSubViews  --  recursively searches for all other needed
  542.  *     views and and loads them into the symbol table.
  543.  */
  544. /*ARGSUSED*/
  545. LOCAL ADDRESS 
  546. AddSubViews (object, name, screen)
  547.      OBJECT object;
  548.      char *name;
  549.      OBJECT screen;
  550. {
  551.   CHAR filename[MAXNAMELEN];
  552.   OBJECT drawing;
  553.   VIEW view;
  554.   VIEWINFO *viewinfo;
  555.  
  556.   /*
  557.    *   If the current object name begins with an 'r' or an 'm' then
  558.    *     name might refer to a view to be loaded.
  559.    */
  560.   if (*name == 'r' || *name == 'm')
  561.     {
  562.  
  563.       /*
  564.        *   Extract the filename from the object name, make sure it hasn't
  565.        *     already been loaded, and attempt to load the file as a view.
  566.        */
  567.       GetFilename (name, filename);
  568.       if (!VTstkeyfind (ViewSymTab, filename))
  569.         /* if not already loaded */
  570.         if ((view = TviLoad (filename)))
  571.           {
  572.  
  573.             /*
  574.              *   Create a new symbol table node for the view, possibly
  575.              *     making a drawport for it, otherwise setting the drawing
  576.              *     part to have no background color (this is necessary
  577.              *     to be able to draw the drawing as a unit without it
  578.              *     trying to erase the entire drawport in its background
  579.              *     color).  Save the new node in the symbol table.
  580.              */
  581.             viewinfo = CreateViewRecord ();
  582.             viewinfo->view = view;
  583.             drawing = TviGetDrawing (view);
  584.             if (*name == 'r')
  585.               viewinfo->drawport = TdpCreate (screen, view,
  586.                                               (RECTANGLE *) NULL,
  587.                                               (RECTANGLE *) NULL);
  588.             else
  589.               (VOID) VOdrBackcolor (drawing, (OBJECT) NO_BACKGROUND);
  590.             (VOID) TdrForEachNamedObject (drawing, 
  591.                       (TDRFOREACHNAMEDOBJFUNPTR) 
  592.                       GetTankRectangles,
  593.                                           (ADDRESS) viewinfo);
  594.             (VOID) VTstsninsert (ViewSymTab, StrClone (filename),
  595.                                  (INT *) viewinfo);
  596.  
  597.             /*
  598.              *   Rebind all variable descriptors in this view and continue
  599.              *     to search recursively for other views to be loaded.
  600.              */
  601.             (VOID) TobForEachVdp (drawing, RebindVdps, (ADDRESS) NULL);
  602.             (VOID) TdrForEachNamedObject (drawing, 
  603.                       (TDRFOREACHNAMEDOBJFUNPTR) 
  604.                       AddSubViews, 
  605.                       (ADDRESS) screen);
  606.           }
  607.     }
  608.  
  609.   return NULL;
  610. }
  611.  
  612.  
  613. /* -------------------------------------------------------------- */
  614.  
  615.  
  616. /*
  617.  *   DrawNewView  --  switches from the current view to a new view
  618.  *     specified by the object name parameter.
  619.  */
  620. LOCAL VIEWINFO *
  621. DrawNewView (current, object_name)
  622.      VIEWINFO *current;
  623.      char *object_name;
  624. {
  625.   CHAR filename[MAXNAMELEN];
  626.   VIEWINFO *new_info;
  627.  
  628.   /*
  629.    *   Get the file name from the object name and see if the view
  630.    *     is stored in the symbol table.
  631.    */
  632.   GetFilename (object_name, filename);
  633.   if ((new_info = GetViewRecord (ViewSymTab, filename)))
  634.     {
  635.  
  636.       /*
  637.        *   Save the current information to return to when the user
  638.        *     selects the return area.
  639.        */
  640.       new_info->previous_info = current;
  641.  
  642.       /*
  643.        *   If there are tank objects in the new view, then reset their
  644.        *     variable descriptors to force them to be drawn correctly.
  645.        */
  646.       if (new_info->holding_obj)
  647.         VOvdReset (GetSubObj (new_info->holding_obj, OT_VD));
  648.       if (new_info->reaction_obj)
  649.         VOvdReset (GetSubObj (new_info->reaction_obj, OT_VD));
  650.  
  651.       /*
  652.        *   Erase the current drawport and draw the new one after
  653.        *     manipulating the tank objects.  Return a pointer to the
  654.        *     new information.  If the object name didn't match any in
  655.        *     the symbol table return a pointer to the current
  656.        *     information.
  657.        */
  658.       (VOID) TdpErase (current->drawport);
  659.       SetTankRectangles (new_info);
  660.       (VOID) TdpDraw (new_info->drawport);
  661.       return new_info;
  662.     }
  663.   else
  664.     return current;
  665. }
  666.  
  667.  
  668. /* -------------------------------------------------------------- */
  669.  
  670.  
  671. /*
  672.  *   DrawMergedDrawing  --  merges another drawing into the current
  673.  *     view according to the object name parameter.
  674.  */
  675. LOCAL void 
  676. DrawMergedDrawing (current, object_name)
  677.      VIEWINFO *current;
  678.      char *object_name;
  679. {
  680.   CHAR filename[MAXNAMELEN];
  681.   VIEWINFO *new_info;
  682.   OBJECT drawing;
  683.  
  684.   /*
  685.    *   Get the file name from the object name and see if the view is
  686.    *     stored in the symbol table.
  687.    */
  688.   GetFilename (object_name, filename);
  689.   if ((new_info = GetViewRecord (ViewSymTab, filename)))
  690.     {
  691.  
  692.       /*
  693.        *   Get the drawing object from the view.  If the drawing is
  694.        *     already merged into the current view, then excise the
  695.        *     drawing and erase it.  Otherwise, merge the drawing into
  696.        *     the current view and draw it.
  697.        */
  698.       drawing = TviGetDrawing (new_info->view);
  699.       if (new_info->merge_view)
  700.         {
  701.           (VOID) TdpEraseObject (current->drawport, drawing);
  702.           (VOID) TviExciseDrawing (current->view, drawing);
  703.           new_info->merge_view = NULL;
  704.         }
  705.       else
  706.         {
  707.           (VOID) TviMergeDrawing (current->view, drawing);
  708.           new_info->merge_view = current->view;
  709.           (VOID) TdpDrawObject (current->drawport, drawing);
  710.         }
  711.     }
  712. }
  713.  
  714.  
  715. /* -------------------------------------------------------------- */
  716.  
  717.  
  718. /*
  719.  *   TurnValve  --  modifies the data model by changing the value of
  720.  *     one of the valves.
  721.  */
  722. LOCAL void 
  723. TurnValve (object_name, key, button_num)
  724.      char *object_name;
  725.      int key;
  726.      int button_num;
  727. {
  728.   INT change = 0;
  729.  
  730.   if (key == 'o' || key == 'O' || button_num == 1)
  731.     change = 1;
  732.   if (key == 'c' || key == 'C' || button_num == 3)
  733.     change = -1;
  734.   MDLchangevalve (object_name, change);
  735. }
  736.  
  737.  
  738. /* -------------------------------------------------------------- */
  739.  
  740.  
  741. /*
  742.  *   SetTankRectangles  --  changes the size and redraws the tank
  743.  *     objects in the current view, if they exist.
  744.  */
  745. LOCAL void 
  746. SetTankRectangles (info)
  747.      VIEWINFO *info;
  748. {
  749.   /*
  750.    *   If each tank exists, then update each rectangle.
  751.    */
  752.   if (info->holding_obj)
  753.     ChangeRectangle (info->drawport, info->holding_obj,
  754.                      &info->holding_rect);
  755.   if (info->reaction_obj)
  756.     ChangeRectangle (info->drawport, info->reaction_obj,
  757.                      &info->reaction_rect);
  758. }
  759.  
  760.  
  761. /* -------------------------------------------------------------- */
  762.  
  763.  
  764. /*
  765.  *   ChangeRectangle  --  changes the size of a rectangle according to
  766.  *     an existing variable descriptor.  The color of the rectangle is
  767.  *     also taken into account.  The routine redraws the rectangle if
  768.  *     possible and/or necessary.
  769.  */
  770. LOCAL void 
  771. ChangeRectangle (drawport, object, rect)
  772.      DRAWPORT drawport;
  773.      OBJECT object;
  774.      RECTANGLE *rect;
  775. {
  776.   ADDRESS vdp;
  777.   OBJECT vd_obj;
  778.   FLOAT *dataptr;
  779.   FLOAT size;
  780.   DOUBLE minval, maxval;
  781.   OBJECT point1, point2;
  782.   DV_POINT pt1, pt2, dummy;
  783.   DV_BOOL color_changed = NO;
  784.   INT newy;
  785.  
  786.  
  787.   /*
  788.    *   Get the variable descriptor subobject for the object.  Then, get
  789.    *     the actual variable descriptor and the address of the data
  790.    *     buffer used by the variable descriptor.  The buffer should
  791.    *     point to two floating point values, the first of which
  792.    *     controls the color dynamics of the object, and the second
  793.    *     of which we'll use to control the size of the rectangle.
  794.    */
  795.   vd_obj = GetSubObj (object, OT_VD);
  796.   vdp = VOvdAddress (vd_obj);
  797.   dataptr = (FLOAT *) MDLget_buffer (vdp);
  798.   size = *(++dataptr);
  799.  
  800.   /*
  801.    *   Get the range of the variable descriptor and use it to compute
  802.    *     the new y position of the upper left corner of the rectangle.
  803.    */
  804.   VGvd_drange (vdp, &minval, &maxval);
  805.   size = (FLOAT)S_MIN (size, maxval);
  806.   size = (FLOAT)S_MAX (size, minval);
  807.   size = (FLOAT)((size - minval) / (maxval - minval));
  808.   newy = (INT)(rect->ll.y + (rect->ur.y - rect->ll.y) * size);
  809.  
  810.   /*
  811.    *   Get the control points of the rectangle and the world coordinate
  812.    *     positions they represent.
  813.    */
  814.   point1 = VOobPtGet (object, 1);
  815.   point2 = VOobPtGet (object, 2);
  816.   VOptGet (point1, &pt1, &dummy);
  817.   VOptGet (point2, &pt2, &dummy);
  818.  
  819.   /*
  820.    *   Check to see if the color of the rectangle should change.
  821.    */
  822.   if (VOvdChanged (vd_obj))
  823.     color_changed = YES;
  824.  
  825.   /*
  826.    *   If the drawport hasn't been drawn yet, just move the control
  827.    *      point.
  828.    */
  829.   if (!TdpIsDrawn (drawport))
  830.     VOptMove (point2, 'A', (INT) pt2.x, newy);
  831.  
  832.   /*
  833.    *   If the color hasn't changed and the rectangle is bigger,
  834.    *     then draw the entire rectangle over.
  835.    */
  836.   else if (!color_changed && (newy > pt2.y))
  837.     {
  838.       VOptMove (point2, 'A', (INT) pt2.x, newy);
  839.       (VOID) TdpDrawObject (drawport, object);
  840.     }
  841.  
  842.   /*
  843.    *   If the color hasn't changed and the rectangle is smaller,
  844.    *     then move the bottom control point up and just erase the top
  845.    *     part.  Then move the bottom control point back and move the
  846.    *     top control point down to the correct position.
  847.    */
  848.   else if (!color_changed && (newy < pt2.y))
  849.     {
  850.       VOptMove (point1, 'A', (INT) pt1.x, newy);
  851.       (VOID) TdpEraseObject (drawport, object);
  852.       VOptMove (point1, 'A', (INT) rect->ll.x, (INT) rect->ll.y);
  853.       VOptMove (point2, 'A', (INT) pt2.x, newy);
  854.     }
  855.  
  856.   /*
  857.    *   If the color has changed, then redraw the rectangle, erasing the
  858.    *     old one only if the size has also changed.
  859.    */
  860.   else if (color_changed)
  861.     {
  862.       if (newy != pt2.y)
  863.         {
  864.           (VOID) TdpEraseObject (drawport, object);
  865.           VOptMove (point2, 'A', (INT) pt2.x, newy);
  866.         }
  867.       (VOID) TdpDrawObject (drawport, object);
  868.     }
  869. }
  870.  
  871.  
  872. /* -------------------------------------------------------------- */
  873.  
  874.  
  875. /*
  876.  *   GetFilename  --  finds the file name portion of an object name and
  877.  *     adds a .v extension.
  878.  */
  879. LOCAL void 
  880. GetFilename (name, filename)
  881.      char *name;
  882.      char *filename;
  883. {
  884.   CHAR *ptr;
  885.   INT length;
  886.  
  887.   /*
  888.    *   Find the ':' delimeter and set the pointer to the next position.
  889.    */
  890.   for (ptr = name; *ptr != ':'; ptr++)
  891.     ;
  892.  
  893.   ptr++;
  894.  
  895.   /*
  896.    *   Copy the rest of the string into the destination and then
  897.    *     copy the extension.
  898.    */
  899.   length = strlen (ptr);
  900.   memcpy(filename, ptr, (unsigned)length);
  901.   memcpy(&filename[length], ".v", 5);
  902. }
  903.  
  904.  
  905. /* --------------------------------------------------------------- */
  906.  
  907.  
  908. /*
  909.  *   CreateViewRecord  --  creates and initializes a view record to be
  910.  *     used in the symbol table.
  911.  */
  912. LOCAL VIEWINFO *CreateViewRecord 
  913. V_P_ ((void))
  914. {
  915.   VIEWINFO *record;
  916.  
  917.   /*
  918.    *   Allocate a new block of dynamic memory of the correct size --
  919.    *     we need to remember to free this when we're finished with it.
  920.    */
  921.   record = (VIEWINFO *) S_ALLOC ((LONG) sizeof (VIEWINFO));
  922.  
  923.   record->view = NULL;
  924.   record->drawport = NULL;
  925.   record->merge_view = NULL;
  926.   record->previous_info = NULL;
  927.   record->holding_rect.ll.x = record->holding_rect.ll.y =
  928.     record->holding_rect.ur.x = record->holding_rect.ur.y = 0;
  929.   record->reaction_rect.ll.x = record->reaction_rect.ll.y =
  930.     record->reaction_rect.ur.x = record->reaction_rect.ur.y = 0;
  931.   record->holding_obj = 0;
  932.   record->reaction_obj = 0;
  933.  
  934.   return record;
  935. }
  936.  
  937.  
  938. /* -------------------------------------------------------------- */
  939.  
  940.  
  941. /*
  942.  *   ExciseAllMergedDrawings  --  finds all drawing that are merged
  943.  *     into current drawing, excising them and erasing them.
  944.  */
  945. LOCAL void 
  946. ExciseAllMergedDrawings (current_info)
  947.      VIEWINFO *current_info;
  948. {
  949.   INT i;
  950.   VIEWINFO *info;
  951.   OBJECT drawing;
  952.  
  953.   /*
  954.    *   Traverse the symbol table looking for drawings that are merged
  955.    *     into the current view.
  956.    */
  957.   for (i = 0; i < (VTstlen (ViewSymTab) - 1); i++)
  958.     {
  959.       info = (VIEWINFO *) VTsnvalue (VTstsnget (ViewSymTab, i));
  960.       if (info->merge_view == current_info->view)
  961.         {
  962.  
  963.           /*
  964.            *   Excise each drawing that we find, erase it, and clear the
  965.            *     correct fields in the record.
  966.            */
  967.           drawing = TviGetDrawing (info->view);
  968.           (VOID) TviExciseDrawing (current_info->view, drawing);
  969.           (VOID) TdpEraseObject (current_info->drawport, drawing);
  970.           info->merge_view = NULL;
  971.         }
  972.     }
  973. }
  974.  
  975.  
  976. /* -------------------------------------------------------------- */
  977.  
  978.  
  979. /*
  980.  *   GetViewRecord  --  performs symbol table lookup based on the key
  981.  *     value.
  982.  */
  983. LOCAL VIEWINFO *
  984. GetViewRecord (SymTab, key)
  985.      ADDRESS SymTab;
  986.      char *key;
  987. {
  988.   return (VIEWINFO *) VTsnvalue (VTstkeyfind (SymTab, key));
  989. }
  990.  
  991.  
  992. /* ----------------------------------------------------------------- */
  993.  
  994.  
  995. /*
  996.  *   GetTankRectangles  --  Finds the tank objects in the current view
  997.  *     and saves some information associated with them.
  998.  */
  999. /*ARGSUSED*/
  1000. LOCAL ADDRESS 
  1001. GetTankRectangles (object, name, viewinfo)
  1002.      OBJECT object;
  1003.      char *name;
  1004.      VIEWINFO *viewinfo;
  1005. {
  1006.   OBJECT pt1, pt2;
  1007.   DV_POINT dummy;
  1008.   OBJECT vd_obj;
  1009.   ADDRESS vdp;
  1010.  
  1011.   /*
  1012.    *   If the object isn't dynamic, its not one we're looking for.
  1013.    */
  1014.   if (!(vd_obj = GetSubObj (object, OT_VD)))
  1015.     return NULL;
  1016.  
  1017.   /*
  1018.    *   Get the variable descriptor and use its name to see if this
  1019.    *     object is one we're interested in.  If it is, get the world
  1020.    *     coordinate values of its control points and also save the
  1021.    *     object identifier.
  1022.    */
  1023.   vdp = VOvdAddress (vd_obj);
  1024.   if (strcmp (VGvdvarname (vdp), "hold_tmp_vol") == 0)
  1025.     {
  1026.       pt1 = VOobPtGet (object, 1);
  1027.       pt2 = VOobPtGet (object, 2);
  1028.       VOptGet (pt1, &viewinfo->holding_rect.ll, &dummy);
  1029.       VOptGet (pt2, &viewinfo->holding_rect.ur, &dummy);
  1030.       viewinfo->holding_obj = object;
  1031.     }
  1032.   else if (strcmp (VGvdvarname (vdp), "reac_tmp_vol") == 0)
  1033.     {
  1034.       pt1 = VOobPtGet (object, 1);
  1035.       pt2 = VOobPtGet (object, 2);
  1036.       VOptGet (pt1, &viewinfo->reaction_rect.ll, &dummy);
  1037.       VOptGet (pt2, &viewinfo->reaction_rect.ur, &dummy);
  1038.       viewinfo->reaction_obj = object;
  1039.     }
  1040.  
  1041.   return NULL;
  1042. }
  1043.  
  1044.  
  1045. /* ----------------------------------------------------------------- */
  1046.  
  1047.  
  1048. /*
  1049.  *   CleanUp  --  clean up the symbol table, freeing all previously
  1050.  *     allocated dynamic memory.
  1051.  */
  1052. LOCAL void CleanUp 
  1053. V_P_ ((void))
  1054. {
  1055.   INT i;
  1056.   VIEWINFO *info;
  1057.   OBJECT drawing;
  1058.  
  1059.   /*
  1060.    *   Traverse the symbol table finding and excising all merged
  1061.    *     drawings.  This is necessary to keep the keep the reference
  1062.    *     counts consistent from view to view.
  1063.    */
  1064.   for (i = 0; i < (VTstlen (ViewSymTab) - 1); i++)
  1065.     {
  1066.       info = (VIEWINFO *) VTsnvalue (VTstsnget (ViewSymTab, i));
  1067.       if (info->merge_view)
  1068.         {
  1069.           drawing = TviGetDrawing (info->view);
  1070.           (VOID) TviExciseDrawing (info->merge_view, drawing);
  1071.         }
  1072.     }
  1073.  
  1074.   /*
  1075.    *   Traverse the symbol table again, removing each node as we go,
  1076.    *     destroying drawports if they exist and destroying each view.
  1077.    *     Also, free the memory we allocated for each record.
  1078.    */
  1079.   while (VTstlen (ViewSymTab) > 0)
  1080.     {
  1081.       info = (VIEWINFO *) VTsnvalue (VTstsnget (ViewSymTab, 0));
  1082.       VTstsnremove (ViewSymTab, VTstsnget (ViewSymTab, 0));
  1083.       if (info->drawport)
  1084.         (VOID) TdpDestroy (info->drawport);
  1085.       (VOID) TviDestroy (info->view);
  1086.       S_FREE ((ADDRESS) info);
  1087.     }
  1088.  
  1089.   /*
  1090.    *   Finally, destroy the symbol table.
  1091.    */
  1092.   VTstdestroy (ViewSymTab);
  1093. }
  1094.  
  1095.  
  1096. /* ----------------------------------------------------------------- */
  1097.  
  1098.  
  1099. /*
  1100.  *   RebindVdps  --  rebinds all variable descriptors in a view that
  1101.  *     are recognized by the underlying data model.
  1102.  */
  1103. /*ARGSUSED*/
  1104. LOCAL ADDRESS 
  1105. RebindVdps (vd_obj, vdp, args)
  1106.      OBJECT vd_obj;
  1107.      ADDRESS vdp;
  1108.      ADDRESS args;
  1109. {
  1110.   ADDRESS buffer;
  1111.  
  1112.   buffer = MDLget_buffer (vdp);
  1113.   if (buffer)
  1114.     (VOID) TvdPutBuffer (vdp, buffer);
  1115.  
  1116.   return NULL;
  1117. }
  1118.  
  1119.  
  1120. /* ----------------------------------------------------------------- */
  1121.  
  1122.  
  1123. /*
  1124.  *   GetSubObj  --  gets the first subobject of a given type of an
  1125.  *     object.
  1126.  */
  1127. LOCAL OBJECT 
  1128. GetSubObj (object, type)
  1129.      OBJECT object;
  1130.      int type;
  1131. {
  1132.  
  1133.   return (OBJECT) TobForEachSubobject (object, 
  1134.                        (TOBFOREACHSUBOBJFUNPTR) GetObjHelper,
  1135.                                        (ADDRESS) & type);
  1136. }
  1137.  
  1138.  
  1139. /*
  1140.  *   GetObjHelper  --  used by GetSubObj to traverse the subobjects
  1141.  *     of an object, looking for a certain type.
  1142.  */
  1143. LOCAL ADDRESS 
  1144. GetObjHelper (object, type)
  1145.      OBJECT object;
  1146.      int *type;
  1147. {
  1148.   if (VOobType (object) == *type)
  1149.     return (ADDRESS) object;
  1150.   else
  1151.     return NULL;
  1152. }
  1153.  
  1154. /*==================================================================
  1155. |
  1156. |    StrClone
  1157. |       Allocates space for and makes a copy of a specified string,
  1158. |       returning a pointer to the string.  If there is no input
  1159. |       string, the routine returns a NULL.
  1160. */
  1161. CHAR *StrClone( str )
  1162.   CHAR *str;
  1163.   {
  1164.   FAST INT len;
  1165.   CHAR *newstr;
  1166.   FAST CHAR *to;
  1167.   FAST CHAR *from;
  1168.  
  1169.   if( str == NULL )
  1170.     return( NULL );
  1171.   len = S_STRLEN( str ) + 1;
  1172.   newstr = (CHAR *)S_ALLOC( len );
  1173.   if( newstr )
  1174.     for( to = newstr, from = str; len > 0; len-- )
  1175.       *to++ = *from++;
  1176.   return( newstr );
  1177.   }
  1178.  
  1179.  
  1180.