#ifdef SCCS
static char sccsid[]="@(#)ui.c	1.19 Oki Electric Industry Co., Ltd. 93/05/24";
#endif
/*
	This file is under sccs control at Stardent in:
	/nfs/sole/root/sccs1.p/X11R5/mit/demos/pexdraw/s.ui.c
*/
/*
 *			Copyright (c) 1992 by
 *			Oki Electric Industry Co., Ltd.
 *			All Rights Reserved
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose and without fee is hereby granted,
 * provided that the above copyright notice appear in all copies and that
 * both that copyright notice and this permission notice appear in
 * supporting documentation, and that the name of Oki not be
 * used in advertising or publicity pertaining to distribution of the
 * software without specific, written prior permission. Oki
 * makes no representations about the suitability of this software for any
 * purpose.  It is provided "as is" without express or implied warranty.
 *
 * This supercedes the Stardent copyright granting the same rights that
 * appeared in the pdraw predecessor to pexdraw.
 *
 *************************************************************************
 *
 *             User Interface for   P E X D R A W
 *
 *		The Motif Version.
 *   
 *  void InitUserInterface(argc, argv)
 *  void MainLoop()
 *  int  applyViewSet(int viewNumber)
 *  void GetVPN( int viewNumber,   PEXVector  *vpn )
 *  void SetVPN( int viewNumber,   PEXVector  *vpn )
 *  void GetVUP( int viewNumber,   PEXVector  *vup )
 *  void SetVUP( int viewNumber,   PEXVector  *vup )
 *  void AddWorkProc(int (*worker)(), char *info)
 *  void ApplySurfaceAttrs()
 *  GC CreateDynGC()
 *  GetSomeTextFromUI(int x, int y, int *length, char **charStr, int *flags )
 *  void FinishExec(XButtonReleasedEvent *event );
 *  
 * What about WM_COLORMAP_WINDOWS???
 *************************************************************************/

#include <stdlib.h>         /* for strtod() */
#include <stdio.h>
#include <Xm/Xm.h>          /* Motif Toolkit */
#include <Mrm/MrmPublic.h>   /* Mrm */
#include <Xm/ToggleB.h>     /* for XmToggleButtonGetState() */

#include <math.h>

#include <X11/PEX5/PEXlib.h>

#include "pexdraw.h"

static MrmHierarchy theMrmHierarchy;     /* MRM database hierarchy ID */

XtAppContext    theAppContext;
int theDBFlag = 1;

static Widget theDrawingArea = NULL, /* the PEX area */
              theViewForm = NULL,    /* the View Paramter Form */
              theLightForm = NULL,   /* the Light Form */
	      theSurfaceForm = NULL, /* the surface form */
              theTopLevel = NULL,    /* global parent */
  	      theFileForm = NULL,    /* archive file handler */
  	      theSpinForm = NULL,    /* spin options */
  	      theColorForm = NULL;   /* spin options */

/* Widget array declared after constants */

       /* forward declaration of interface procedures */
static void proc_pexdraw_create();
static void proc_pexdraw_expose();
static void proc_pexdraw_resize();
static void proc_pexdraw_input();
static void proc_pexdraw_exit();
static void proc_pexdraw_activate();
static void proc_pexdraw_file();

#if NeedFunctionPrototypes
static void FinishExec(XButtonReleasedEvent * /* event */ );
#else
static void FinishExec();
#endif


       /* binding of uil procedure names with C functions */
static MRMRegisterArg	regvec[] = {
	{"proc_pexdraw_exit",(caddr_t)proc_pexdraw_exit},
	{"proc_pexdraw_create",(caddr_t)proc_pexdraw_create},
	{"proc_pexdraw_expose",(caddr_t)proc_pexdraw_expose},
	{"proc_pexdraw_resize",(caddr_t)proc_pexdraw_resize},
	{"proc_pexdraw_input",(caddr_t)proc_pexdraw_input},
	{"proc_pexdraw_activate",(caddr_t)proc_pexdraw_activate},
	{"proc_pexdraw_file",(caddr_t)proc_pexdraw_file}
	};
static MrmCount regnum = sizeof(regvec) / sizeof(MRMRegisterArg);

/*************************************************************************
 *
 *   C O N S T A N T S   U S E D   B Y   U I L
 *
 *
 * why the &^%&^% these are not generated by UIL!.
 * 
 */
#define    k_drawing_area 0
#define    k_view_set 1
#define    k_apply_vs 2
#define    k_reset_vs 3
#define    k_dismiss_vs 4
#define    k_view_ref_pt_x 5
#define    k_view_ref_pt_y 6
#define    k_view_ref_pt_z 7
#define    k_view_pl_norm_x 8
#define    k_view_pl_norm_y 9
#define    k_view_pl_norm_z 10
#define    k_view_up_vect_x 11
#define    k_view_up_vect_y 12
#define    k_view_up_vect_z 13
#define    k_proj_ref_pt_x 14
#define    k_proj_ref_pt_y 15
#define    k_proj_ref_pt_z 16
#define    k_view_window_minx 17
#define    k_view_window_maxx 18
#define    k_view_window_miny 19
#define    k_view_window_maxy 20
#define    k_view_plane_dist 21
#define    k_view_plane_back 22
#define    k_view_plane_front 23
#define    k_proj_vp_minx 24
#define    k_proj_vp_maxx 25
#define    k_proj_vp_miny 26
#define    k_proj_vp_maxy 27
#define    k_proj_vp_minz 28
#define    k_proj_vp_maxz 29
#define    k_proj_type_para 30
#define    k_proj_type_persp 31
#define    k_dump_strux 32
#define    k_refresh 33
#define    k_tool_pointer 34
#define    k_tool_line 35
#define    k_tool_view 36
#define    k_tool_tristrip 37
#define    k_delete 38
#define    k_light 39
#define    k_light_on1 40
#define    k_light_on2 41
#define    k_light_on3 42
#define    k_light_on4 43
#define    k_light_on5 44
#define    k_light_on6 45
#define    k_light_on7 46
#define    k_light_on8 47
#define    k_light_edit1 48
#define    k_light_edit2 49
#define    k_light_edit3 50
#define    k_light_edit4 51
#define    k_light_edit5 52
#define    k_light_edit6 53
#define    k_light_edit7 54
#define    k_light_edit8 55
#define    k_light_type_ambient 56
#define    k_light_type_directional 57
#define    k_light_type_positional 58
#define    k_light_type_spot 59
#define    k_light_pos_x 60
#define    k_light_pos_y 61
#define    k_light_pos_z 62
#define    k_light_color_red 63
#define    k_light_color_green 64
#define    k_light_color_blue 65
#define    k_light_direction_x 66
#define    k_light_direction_y 67
#define    k_light_direction_z 68
#define    k_light_coeff_const 69
#define    k_light_coeff_dist 70
#define    k_light_conc_exp 71
#define    k_light_spread_angle 72
#define    k_apply_light 73
#define    k_reset_light 74
#define    k_dismiss_light 75
#define    k_surface 76
#define    k_tool_mclip 77
#define    k_reset_model  78
#define    k_spin_slowly  79
#define    k_save 80
#define    k_read 81
#define    k_file 82
#define    k_undo 83
#define    k_file_help 84
#define    k_delete_all 85
#define    k_face_cull 86
#define    k_sphere 87
#define    k_dismiss_surface 88
#define    k_reset_surface 89
#define    k_apply_surface 90
#define    k_surface_refl_transparency 91
#define    k_surface_refl_specexp 92
#define    k_surface_refl_specular 93
#define    k_surface_refl_diffuse 94
#define    k_surface_refl_ambient 95
#define    k_sstyle_empty 96
#define    k_sstyle_solid 97
#define    k_sstyle_hollow 98
#define    k_sshade_flat 99
#define    k_sshade_gouraud 100
#define    k_sshade_dot 101
#define    k_sshade_phong 102
#define    k_cull_none 103
#define    k_cull_back 104
#define    k_cull_front 105
#define    k_tool_zoom 106
#define    k_tool_nurbc 107
#define    k_tool_text 108
#define    k_tool_pgon 109
#define    k_tool_circle 110
#define    k_spin_form 111
#define    k_spinf_strux 112
#define    k_spinf_px 113
#define    k_spinf_py 114
#define    k_spinf_pz 115
#define    k_spinf_ox 116
#define    k_spinf_oy 117
#define    k_spinf_oz 118
#define    k_spinf_xang 119
#define    k_spinf_yang 120
#define    k_spinf_zang 121
#define    k_spinf_dx 122
#define    k_spinf_dy 123
#define    k_spinf_dz 124
#define    k_spinf_stop 125
#define    k_spinf_scale 126
#define    k_apply_spin 127
#define    k_dismiss_spin 128
#define    k_reset_spin 129
#define    k_color_form 130
#define    k_color_red 131
#define    k_color_green 132
#define    k_color_blue 133
#define    k_apply_color 134
#define    k_dismiss_color 135
#define    k_reset_color 136
#define    k_color_strux 137
#define    k_color_elem 138
#define    k_delete_strux 139
#define    k_exec_strux 140
#define    k_unpost_strux 141

#define MAX_WIDGET 140
static Widget widgetArray[MAX_WIDGET]; /* just the widgets with constants +1 */

/*
 * number strings
 */
static char *numberStrings[] = {
  "",				/* k_drawing_area 0 */
  "",				/* k_view_set 1 */
  "",				/* k_apply_vs 2 */
  "",				/* k_reset_vs 3 */
  "",				/* k_dismiss_vs 4 */
  "view_ref_pt_x",		/* k_view_ref_pt_x 5 */
  "view_ref_pt_y",		/* k_view_ref_pt_y 6 */
  "view_ref_pt_z",		/* k_view_ref_pt_z 7 */
  "view_pl_norm_x",		/* k_view_pl_norm_x 8 */
  "view_pl_norm_y",		/* k_view_pl_norm_y 9 */
  "view_pl_norm_z",		/* k_view_pl_norm_z 10 */
  "view_up_vect_x",		/* k_view_up_vect_x 11 */
  "view_up_vect_y",		/* k_view_up_vect_y 12 */
  "view_up_vect_z",		/* k_view_up_vect_z 13 */
  "view_window_minx",		/* k_view_window_minx 17 */
  "view_window_maxx",		/* k_view_window_maxx 18 */
  "view_window_miny",		/* k_view_window_miny 19 */
  "view_window_maxy",		/* k_view_window_maxy 20 */
  "view_plane_dist",		/* k_view_plane_dist 21 */
  "view_plane_back",		/* k_view_plane_back 22 */
  "view_plane_front",		/* k_view_plane_front 23 */
  "proj_vp_minx",		/* k_proj_vp_minx 24 */
  "proj_vp_maxx",		/* k_proj_vp_maxx 25 */
  "proj_vp_miny",		/* k_proj_vp_miny 26 */
  "proj_vp_maxy",		/* k_proj_vp_maxy 27 */
  "proj_vp_minz",		/* k_proj_vp_minz 28 */
  "proj_vp_maxz",		/* k_proj_vp_maxz 29 */
  "proj_type_para",		/* k_proj_type_para 30 */
  "proj_type_persp",		/* k_proj_type_persp 31 */
    "dump_strux",		/* k_dump_strux 32 */
    "refresh",		/* k_refresh 33 */
    "tool_pointer",		/* k_tool_pointer 34 */
    "tool_line",		/* k_tool_line 35 */
    "tool_view",		/* k_tool_view 36 */
    "tool_tristrip",		/* k_tool_tristrip 37 */
    "delete",		/* k_delete 38 */
    "light",		/* k_light 39 */
    "light_on1",		/* k_light_on1 40 */
    "light_on2",		/* k_light_on2 41 */
    "light_on3",		/* k_light_on3 42 */
    "light_on4",		/* k_light_on4 43 */
    "light_on5",		/* k_light_on5 44 */
    "light_on6",		/* k_light_on6 45 */
    "light_on7",		/* k_light_on7 46 */
    "light_on8",		/* k_light_on8 47 */
    "light_edit1",		/* k_light_edit1 48 */
    "light_edit2",		/* k_light_edit2 49 */
    "light_edit3",		/* k_light_edit3 50 */
    "light_edit4",		/* k_light_edit4 51 */
    "light_edit5",		/* k_light_edit5 52 */
    "light_edit6",		/* k_light_edit6 53 */
    "light_edit7",		/* k_light_edit7 54 */
    "light_edit8",		/* k_light_edit8 55 */
    "light_type_ambient",		/* k_light_type_ambient 56 */
    "light_type_directional",		/* k_light_type_directional 57 */
    "light_type_positional",		/* k_light_type_positional 58 */
    "light_type_spot",		/* k_light_type_spot 59 */
    "light_pos_x",		/* k_light_pos_x 60 */
    "light_pos_y",		/* k_light_pos_y 61 */
    "light_pos_z",		/* k_light_pos_z 62 */
    "light_color_red",		/* k_light_color_red 63 */
    "light_color_green",		/* k_light_color_green 64 */
    "light_color_blue",		/* k_light_color_blue 65 */
    "light_direction_x",		/* k_light_direction_x 66 */
    "light_direction_y",		/* k_light_direction_y 67 */
    "light_direction_z",		/* k_light_direction_z 68 */
    "light_coeff_const",		/* k_light_coeff_const 69 */
    "light_coeff_dist",		/* k_light_coeff_dist 70 */
    "light_conc_exp",		/* k_light_conc_exp 71 */
    "light_spread_angle",		/* k_light_spread_angle 72 */
    "apply_light",		/* k_apply_light 73 */
    "reset_light",		/* k_reset_light 74 */
    "dismiss_light",		/* k_dismiss_light 75 */
    "surface",		/* k_surface 76 */
    "FREE",		/* k_FREE 77 */
    "reset_model",		/* k_spin_strux  78 */
    "spin_slowly",		/* k_spin_slowly  79 */
    "save",		/* k_save 80 */
    "read",		/* k_read 81 */
    "file",		/* k_file 82 */
    "undo",		/* k_undo 83 */
    "file_help",		/* k_file_help 84 */
    "delete_all",		/* k_delete_all 85 */
    "face_cull",		/* k_face_cull 86 */
    "sphere",		/* k_sphere 87 */
    "dismiss_surface",		/* k_dismiss_surface 88 */
    "reset_surface",		/* k_reset_surface 89 */
    "apply_surface",		/* k_apply_surface 90 */
    "surface_refl_transparency",		/* k_surface_refl_transparency 91 */
    "surface_refl_specexp",		/* k_surface_refl_specexp 92 */
    "surface_refl_specular",		/* k_surface_refl_specular 93 */
    "surface_refl_diffuse",		/* k_surface_refl_diffuse 94 */
    "surface_refl_ambient",		/* k_surface_refl_ambient 95 */
    "sstyle_empty",		/* k_sstyle_empty 96 */
    "sstyle_solid",		/* k_sstyle_solid 97 */
    "sstyle_hollow",		/* k_sstyle_hollow 98 */
    "sshade_flat",		/* k_sshade_flat 99 */
    "sshade_gouraud",		/* k_sshade_gouraud 100 */
    "sshade_dot",		/* k_sshade_dot 101 */
    "sshade_phong",		/* k_sshade_phong 102 */
    "cull_none",		/* k_cull_none 103 */
    "cull_back",		/* k_cull_back 104 */
    "cull_front",		/* k_cull_front 105 */
  "", 			/* k_tool_zoom : 106; */
      "", 			/* k_tool_nurbc : 107; */
      "", 			/* k_tool_text : 108; */
      "", 			/* k_tool_pgon : 109; */
      "", 			/* k_tool_circle : 110; */
      "", 			/* k_spin_form : 111; */
      "strux_id", 			/* k_spinf_strux : 112; */
      "spinf_pnt_x", 			/* k_spinf_px : 113; */
      "spinf_pnt_y", 			/* k_spinf_py : 114; */
      "spinf_pnt_z", 			/* k_spinf_pz : 115; */
      "spinf_offset_x", 			/* k_spinf_ox : 116; */
  "spinf_offset_y", 			/* k_spinf_oy : 117; */
  "spinf_offset_z", 			/* k_spinf_oz : 118; */
  "spinf_ang_x", 			/* k_spinf_xang : 119; */
  "spinf_ang_y", 			/* k_spinf_yang : 120; */
  "spinf_ang_z", 			/* k_spinf_zang : 121; */
  "spinf_delta_x", 			/* k_spinf_dx : 122; */
  "spinf_delta_y", 			/* k_spinf_dy : 123; */
  "spinf_delta_z", 			/* k_spinf_dz : 124; */
  "", 			/* k_spinf_stop : 125; */
  "spinf_scale", 			/* k_spinf_scale : 126; */
  "", 			/* k_apply_spin : 127; */
  "", 			/* k_dismiss_spin : 128; */
  "", 			/* k_reset_spin : 129; */
  "",			/* k_color_form : 130; */
  "color_red",			/* k_color_red : 131; */
  "color_green",			/* k_color_green : 132; */
  "color_blue",			/* k_color_blue : 133; */
  "",			/* k_apply_color : 134; */
  "",			/* k_dismiss_color : 135; */
  "",			/* k_reset_color : 136; */
  "",			/* k_color_strux : 137; */
  ""			/* k_color_elem : 138; */
};
static int numberStringCount = sizeof(numberStrings) / sizeof(char *);

/*
 * event handler
 */
static XtEventHandler motionHandler(
#if NeedFunctionPrototypes
				    Widget  /* widget */,
				    XtPointer  /* unused */,
				    XMotionEvent * /* event */, 
				    Boolean * /* continue_to_dispatch */
#endif
);

static theSpecialExecMode = 0;

/******************************************************************
 *
 *     M A I N
 */
void
InitUserInterface(argc, argv)
int argc;
char **argv;
{
  Widget pexdrawmain = NULL;
  Arg arglist[1];
  int n, i;
  MrmCode class;
  char *files[1];

  for ( i = 1; i<argc; i++ ) {
    if ((strncmp(argv[i],"-pmdb",strlen(argv[i]))) == 0) {
      thePMDBFlag = 1; 
    } else if ((strncmp(argv[i],"-nodb",strlen(argv[i]))) == 0) {
      theDBFlag = 0; 
    } else if ((strncmp(argv[i],"-wks",strlen(argv[i]))) == 0) {
      theForceWKSFlag = 1; 
    } else if ((strncmp(argv[i],"-nodither",strlen(argv[i]))) == 0) {
      theNoDitherFlag = 1; 
    }
  }

  MrmInitialize ();

  theTopLevel = XtAppInitialize(&theAppContext, "pexdraw", 
				(XrmOptionDescList)NULL , 0,
			        &argc, (String*)argv, 
				(String*)NULL, (ArgList)NULL, 0);

  /*
   *  Open the User Interface Description file. 
   *    pexdraw.uil is compiled into pexdraw.uid
   */ 
  files[0] = "pexdraw.uid";
  if (MrmOpenHierarchy( 1, files, NULL, &theMrmHierarchy) != MrmSUCCESS) {
    printf ("can't open pexdraw.uid\n");
    exit(0);
  }

  if (MrmRegisterNames (regvec, regnum) != MrmSUCCESS) {
    printf("can't register names\n");
    exit(0) ;
  }

  if (MrmFetchWidget (theMrmHierarchy, "pexdraw_obj_main",
		      theTopLevel, &pexdrawmain, &class)
      != MrmSUCCESS) {
    printf("can't fetch interface\n");
    exit(0);
  }

  XtManageChild(pexdrawmain);
    
  XtRealizeWidget(theTopLevel);

  /* iquire what the default too is and ... */
  set_tool_line();

  theTopWindow = XtWindow(theTopLevel);
  theDisplay = XtDisplay(theDrawingArea);
  theWindow = XtWindow(theDrawingArea);
}

void
MainLoop()
{
  XtAppMainLoop(theAppContext);  /* Hand over control to the UI & User */
}

/*************************************************************************
 *
 *    U S E R    I N T E R F A C E    C A L L B A C K S
 *
 *  All UI callbacks are also defined in pexdraw.uil and begin proc_pexdraw_??
 *
 */

static void proc_pexdraw_create( widget, tag, cbData )
	Widget	widget;
	int    *tag;
	XmAnyCallbackStruct *cbData;
{
    Arg arg ;
    int which = *(int *)tag;

    switch (which) {
    case k_drawing_area:
	theDrawingArea = widget;
	XtAddEventHandler( theDrawingArea, ButtonMotionMask, FALSE, 
			  (XtEventHandler)motionHandler, NULL );

	break;

      case k_view_set:
	theViewForm = widget;
	break;
	
      case k_light:
	theLightForm = widget;
	break;

      case k_file:
	theFileForm = widget;
	break;

      case k_spin_form:
	theSpinForm = widget;
	break;

      case k_color_form:
	theColorForm = widget;
	break;

      default: 
	if (which > MAX_WIDGET) {
	  printf(" got widget #%d, MAX is still %d\n",which,MAX_WIDGET);
	  return;
	}
	widgetArray[which] = widget;
	break;
    }
}

static void proc_pexdraw_expose( widget, tag, cbData )
	Widget	widget;
	int    *tag;
	XmAnyCallbackStruct *cbData;
{
  theRenderProcs.ReDraw();
}


static void proc_pexdraw_resize( widget, tag, cbData )
	Widget	widget;
	int    *tag;
	XmAnyCallbackStruct *cbData;
{
  XWindowAttributes winAttrs;

  /*
   * I'm positive this is a terrible hack in violation of all of Xt
   * rules and regulations, but event was not comming back in call_back data.
   */
  XGetWindowAttributes(XtDisplay(theDrawingArea), XtWindow(theDrawingArea),
		       &winAttrs );

  theWinHeight =  winAttrs.height;

  ResizeWindow( XtWindow(theDrawingArea), winAttrs.width, winAttrs.height );
  theRenderProcs.ReDraw();
}

/*
 * Handle button presses. See fb.c for the actual handler routines.
 */
static void proc_pexdraw_input( widget, tag, cbData )
	Widget	widget;
	int    *tag;
	XmAnyCallbackStruct *cbData;
{
  XEvent *event = cbData->event;

  if (event->xbutton.button < 1 || event->xbutton.button > 3) return;

  if (theSpecialExecMode) {
    if (event->type !=  ButtonRelease) return;
    FinishExec((XButtonReleasedEvent *)event);
    theSpecialExecMode = 0;
  }

  if (event->type ==  ButtonPress) {
    thePressHandlerTable[event->xbutton.button-1](event);
  } else if (event->type ==  ButtonRelease) {
    theReleaseHandlerTable[event->xbutton.button-1](event);
  }
}

/* good-bye */
static void proc_pexdraw_exit( widget, tag, cbData )
	Widget	widget;
	char    *tag;
	XmAnyCallbackStruct *cbData;
{
    exit(0);
}

/*************************************************************************
 *
 *   P R O C _ P D R A W _ A C T I V A T E
 */
static void proc_pexdraw_activate( widget, tag, cbData )
	Widget	widget;
	char    *tag;
	XmAnyCallbackStruct *cbData;
{
  int which = *(int *)tag;
  MrmCode class;
  PEXCoord offset;

  switch (which) {
  case k_view_set:
    if (theViewForm == NULL) {     /* The first time, fetch order box. */
      if (MrmFetchWidget(theMrmHierarchy, "view_set_dialog", theTopLevel,
			 &theViewForm, &class) != MrmSUCCESS) {
	printf("can't fetch view_set_dialog");
	return;
      }
    }

    if (XtIsManaged(theViewForm))
      XtUnmanageChild(theViewForm);
    else
      XtManageChild(theViewForm);
    break;

  case k_apply_vs:
    applyViewSet(1);
    break;

  case k_reset_vs:
    break;

  case k_dismiss_vs:
    XtUnmanageChild(theViewForm);
    break;

  case k_dump_strux:
    DumpStruxCmd(1);
    break;

  case k_refresh:
    theRenderProcs.ReDraw();
    break;

  case k_tool_pointer:
    set_tool_pointer();
    break;

  case k_tool_line:
    set_tool_line();
    break;

  case k_tool_view:
    set_tool_view();
    break;

  case k_tool_tristrip:
    set_tool_tristrip();
    break;

  case k_tool_nurbc:
    set_tool_nurbc();
    break;

  case k_tool_text:
    set_tool_text();
    break;

  case k_tool_zoom:
    set_tool_zoom();
    break;

  case k_tool_pgon:
    set_tool_pgon();
    break;

  case k_tool_mclip:
    set_tool_mclip();
    break;

  case k_tool_circle:
    set_tool_circle();
    break;

  case k_delete:
    DeleteSelected();
    theRenderProcs.ReDraw();
    break;

  case k_light:
    if (theLightForm == NULL) {     /* The first time, fetch order box. */
      if (MrmFetchWidget(theMrmHierarchy, "light_dialog", theTopLevel,
			 &theLightForm, &class) != MrmSUCCESS) {
	printf("can't fetch light form widget");
	return;
      }
    }

    if (XtIsManaged(theLightForm))
      XtUnmanageChild(theLightForm);
    else
      XtManageChild(theLightForm);
    break;

  case k_apply_light:
    break;

  case k_reset_light:
    break;

  case k_dismiss_light:
    XtUnmanageChild(theLightForm);
    break;


  case k_surface:
    if (theSurfaceForm == NULL) {     /* The first time, fetch order box. */
      if (MrmFetchWidget(theMrmHierarchy, "surface_dialog", theTopLevel,
			 &theSurfaceForm, &class) != MrmSUCCESS) {
	printf("can't fetch surface form widget");
	return;
      }
    }

    if (XtIsManaged(theSurfaceForm))
      XtUnmanageChild(theSurfaceForm);
    else
      XtManageChild(theSurfaceForm);
    break;

  case k_apply_surface:
    ApplySurfaceAttrs();
    theRenderProcs.ReDraw();
    break;

  case k_reset_surface:
    break;

  case k_dismiss_surface:
    XtUnmanageChild(theSurfaceForm);
    break;

  case k_reset_model:
    break;

  case k_spin_slowly: {
    PEXStructure sid;
    
    if ( theSelectedElement != -1 ) {
      sid = theSelectedStrux;
    } else if (theNewStrux != 0) {
      sid = theNewStrux;
    } else break;

    if (!StartSpinning(sid)) { /* could not start, must be spinning */
      StopSpinning(sid);
    }}
    break;

  case k_spin_form:
    if (theSpinForm == NULL) {     /* The first time, fetch order box. */
      if (MrmFetchWidget(theMrmHierarchy, "spin_dialog", theTopLevel,
			 &theSpinForm, &class) != MrmSUCCESS) {
	printf("can't fetch Spin form widget");
	return;
      }
    }

    {
      PEXStructure sid;
      SpinInfo *si;

      if ( theSelectedElement != -1 ) {
	sid = theSelectedStrux;
      } else if (theNewStrux != 0) {
	sid = theNewStrux;
      } else { return; }
      si = GetSpinInfo(sid);
      if (!si) return;
      LoadSpinWidget(si);
    }

    if (XtIsManaged(theSpinForm))
      XtUnmanageChild(theSpinForm);
    else
      XtManageChild(theSpinForm);
    break;

  case k_apply_spin: /* must clean this up !!! */
    {
      PEXStructure sid;
      SpinInfo *si;

      if ( theSelectedElement != -1 ) {
	sid = theSelectedStrux;
      } else if (theNewStrux != 0) {
	sid = theNewStrux;
      } else { return; }
      si = GetSpinInfo(sid);
      if (!si) return;
      ApplySpin(si);
    }
    break;

  case k_reset_spin:
    {
      PEXStructure sid;
      SpinInfo *si;

      if ( theSelectedElement != -1 ) {
	sid = theSelectedStrux;
      } else if (theNewStrux != 0) {
	sid = theNewStrux;
      } else { return; }
      si = GetSpinInfo(sid);
      if (!si) return;
      LoadSpinWidget(si);
    }
    break;

  case k_dismiss_spin:
    XtUnmanageChild(theSpinForm);
    break;

  case k_color_form:
    if (theColorForm == NULL) {     /* The first time, fetch order box. */
      if (MrmFetchWidget(theMrmHierarchy, "color_dialog", theTopLevel,
			 &theColorForm, &class) != MrmSUCCESS) {
	printf("can't fetch Color form widget");
	return;
      }
    }

    { PEXColorRGB rgb;
      GetColorAttribute(theSelectedStrux, theSelectedElement, &rgb);
      LoadColorWidget(theSelectedStrux, theSelectedElement, &rgb); }

    if (XtIsManaged(theColorForm))
      XtUnmanageChild(theColorForm);
    else
      XtManageChild(theColorForm);
    break;

  case k_apply_color: /* must clean this up !!! */
    ApplyColor(theSelectedStrux, theSelectedElement);
    theRenderProcs.ReDraw();
    break;

  case k_reset_color:
    { PEXColorRGB rgb;
      GetColorAttribute(theSelectedStrux, theSelectedElement, &rgb);
      LoadColorWidget(theSelectedStrux, theSelectedElement, &rgb); }
    break;

  case k_dismiss_color:
    XtUnmanageChild(theColorForm);
    break;

  case k_read:
  case k_save:
    if (theFileForm == NULL) {     /* The first time, fetch order box. */
      if (MrmFetchWidget(theMrmHierarchy, "file_dialog", theTopLevel,
			 &theFileForm, &class) != MrmSUCCESS) {
	printf("can't fetch order box widget");
	return;
      }
    }


    theFileCmd = (which == k_read)?ReadArchiveFile:WriteArchiveFile;

    if (XtIsManaged(theFileForm))
      XtUnmanageChild(theFileForm);
    else
      XtManageChild(theFileForm);
    break;

  case k_undo:
    break;

  case k_file_help:
    break;

  case k_delete_all:
    StopSpinning((PEXStructure)-1);
    PEXRotate(PEXXAxis, 0.0, theMCMatrix.matrix );
    theMCMatrix.seqNo = 0;
    theRenderProcs.DeleteAll();
    break;

  case k_sphere:
    offset.x = 1.0;
    offset.y = 1.0;
    offset.z = 1.0;
    Cubeoctahedron(&offset, 0.9);
    theRenderProcs.ReDraw();
    break;

  case k_delete_strux:
    if ( theSelectedElement != -1 ) {
      theRenderProcs.Unpost(theSelectedStrux);
      DeleteStrux(theSelectedStrux);
      StopSpinning(theSelectedStrux); /* just in case */
      theRenderProcs.ReDraw();
    }
    break;

  case k_exec_strux:
    if ( theSelectedElement != -1 ) {
      theSpecialExecMode = 1;          /* see FinishExec */
    }
    break;

  case k_unpost_strux:
    if ( theSelectedElement != -1 ) {
      theRenderProcs.Unpost(theSelectedStrux);
      theRenderProcs.ReDraw();
    }
    break;

  default:
    break;
  }
    
}

/*************************************************************************
 * proc_pexdraw_file
 *
 * handle callback fron file selection mechanism.
 */
static void proc_pexdraw_file( widget, tag, cbData )
	Widget	widget;
	char    *tag;
	XmFileSelectionBoxCallbackStruct *cbData;
{
  char *filename;
  int status;

  switch (cbData->reason) {
  case XmCR_OK:
  case XmCR_APPLY:
    if (!XmStringGetLtoR(cbData->value, XmSTRING_DEFAULT_CHARSET, 
			 &filename )) {
      printf("imagine a popup...\n");
    } else {
      status = theFileCmd(filename);
    }
    if (cbData->reason == XmCR_OK) XtUnmanageChild(theFileForm);
    break;

  case XmCR_CANCEL:
    XtUnmanageChild(theFileForm);
    break;

  case XmCR_HELP:
    break;

  default:
    break;
  }
}



/*************************************************************************
 * applyViewSet - get values from widget and set the view representation
 */
int
applyViewSet(viewNumber)
  int viewNumber;
{
  PEXCoord  vrp;  /* view reference point */
  PEXVector  vpn;  /* view plane normal    */
  PEXVector  vup;  /* view up vector       */

/* clean this up, why use a view struct? use view entry */
  
  PEXViewRep vrep;                           /*  view structure */

  PEXCoord2D          frame[2];
  PEXNPCSubVolume     viewport;
  int                 perspective;
  PEXCoord            prp;
  float               view_plane, back_plane, front_plane;
 
  int err;

  int persp;
  MrmCode class;

  if (theViewForm == NULL) {     /* The first time, fetch order box. */
    if (MrmFetchWidget(theMrmHierarchy, "view_set_dialog", theTopLevel,
		       &theViewForm, &class) != MrmSUCCESS) {
      printf("can't fetch view set dialog");
      return;
    }
  }

#define FetchValue(_a,_b)  {if (getNumberWidgetValue((_a), (_b))) return(1);}

  /* View Reference Point */
  FetchValue(k_view_ref_pt_x, &vrp.x);
  FetchValue(k_view_ref_pt_y, &vrp.y);
  FetchValue(k_view_ref_pt_z, &vrp.z);

  /* view plane normal */
  FetchValue(k_view_pl_norm_x, &vpn.x);
  FetchValue(k_view_pl_norm_y, &vpn.y);
  FetchValue(k_view_pl_norm_z, &vpn.z);

  /*  view up vector */
  FetchValue(k_view_up_vect_x, &vup.x);
  FetchValue(k_view_up_vect_y, &vup.y);
  FetchValue(k_view_up_vect_z, &vup.z);
  
  err = PEXViewOrientationMatrix( &vrp, &vpn, &vup, vrep.view.orientation);
  if (err != 0) {
    printf( "view orientation error %d\n",err); return (1);
  }

  FetchValue(k_proj_ref_pt_x, &prp.x);
  FetchValue(k_proj_ref_pt_y, &prp.y);
  FetchValue(k_proj_ref_pt_z, &prp.z);

  FetchValue(k_view_window_minx, &frame[0].x);
  FetchValue(k_view_window_maxx, &frame[1].x);
  FetchValue(k_view_window_miny, &frame[0].y);
  FetchValue(k_view_window_maxy, &frame[1].y);

  FetchValue(k_view_plane_dist, &view_plane);
  FetchValue(k_view_plane_back, &back_plane);
  FetchValue(k_view_plane_front, &front_plane);

  FetchValue(k_proj_vp_minx, &viewport.min.x);
  FetchValue(k_proj_vp_maxx, &viewport.max.x);
  FetchValue(k_proj_vp_miny, &viewport.min.y);
  FetchValue(k_proj_vp_maxy, &viewport.max.y);
  FetchValue(k_proj_vp_minz, &viewport.min.z);
  FetchValue(k_proj_vp_maxz, &viewport.max.z);

  if (widgetArray[k_proj_type_persp] == NULL) {
      /* The first time, fetch order box. */
      if (MrmFetchWidget(theMrmHierarchy, numberStrings[k_proj_type_persp],
                         theTopLevel, &widgetArray[k_proj_type_persp],
			 &class) != MrmSUCCESS) {
	printf("can't fetch number perspective\n");
	return (1);
      }
    }
 
  /* View Reference Point */
  persp = XmToggleButtonGetState(widgetArray[k_proj_type_persp]);

  err = PEXViewMappingMatrix( frame, &viewport, persp, &prp,
		       view_plane, back_plane, front_plane,
		       vrep.view.mapping);
  
  if (err != 0) { printf( "view mapping error %d\n",err); return (1); }
  
  vrep.view.clip_limits.min.x = viewport.min.x;
  vrep.view.clip_limits.min.y = viewport.min.y;
  vrep.view.clip_limits.min.z = viewport.min.z;
  vrep.view.clip_limits.max.x = viewport.max.x;
  vrep.view.clip_limits.max.y = viewport.max.y;
  vrep.view.clip_limits.max.z = viewport.max.z;
  vrep.view.clip_flags = PEXClipXY | PEXClipBack | PEXClipFront;
  vrep.index = viewNumber;

  theRenderProcs.SetView( 1, &vrep.view );

  bcopy((char *)&vrep.view.orientation, (char *)&theMatOri,sizeof(PEXMatrix));
  bcopy((char *)&vrep.view.mapping, (char *)&theMatMap, sizeof(PEXMatrix));

  theRenderProcs.ReDraw();

  return (0);
}

/*************************************************************************
 * getNumberWidgetValue - get a number from a string widget.
int getNumberWidgetValue(int id, float *value)
 */
int getNumberWidgetValue(id, value)
     int id; 
     float *value;
{
  double number;
  char *text, *notText;
  MrmCode class;

  if (id > numberStringCount) return (1);

  if (widgetArray[id] == NULL) {     /* The first time, fetch order box. */
      if (MrmFetchWidget(theMrmHierarchy, numberStrings[id], theTopLevel,
			 &widgetArray[id], &class) != MrmSUCCESS) {
	printf("can't fetch number %d\n",id);
	return (1);
      }
    }
 
  /* View Reference Point */
  XtVaGetValues(widgetArray[id], XmNvalue, &text, NULL);

  number = strtod(text,&notText);
  if (number == 0.0 && text == notText) {
    printf(" could get a number %s, %s\n",numberStrings[id],text);
    return (1);
  }

  *value = (float) number;
  return (0);
}

/*************************************************************************
 * setNumberWidgetValue - set a number into a string widget.
int setNumberWidgetValue(int id, float value)
 */
int setNumberWidgetValue( id, value)
int id; 
float value;
{
  double number;
  char text[80];
  MrmCode class;
  Arg al[1];
    
  if (id > numberStringCount) return (1);

  if (widgetArray[id] == NULL) {     /* The first time, fetch order box. */
      if (MrmFetchWidget(theMrmHierarchy, numberStrings[id], theTopLevel,
			 &widgetArray[id], &class) != MrmSUCCESS) {
	printf("can't fetch number %d\n",id);
	return (1);
      }
    }

  sprintf(text, "%1.6f", value);

  XtSetArg(al[0],  XmNvalue, text );
  XtSetValues(widgetArray[id], al, 1);

  return (0);
}

/*************************************************************************
 * getWidgetValue - get a floating point number from an integer 
static int getWidgetValue(int id, float *value)
 */
static int getWidgetValue( id, value)
int id;
 float *value;
{
  double number;
  char *text, *notText;
  MrmCode class;
  int intVal, i;
  short decVal;
  

  if (id > numberStringCount) return (1);

  if (widgetArray[id] == NULL) {     /* The first time, fetch order box. */
      if (MrmFetchWidget(theMrmHierarchy, numberStrings[id], theTopLevel,
			 &widgetArray[id], &class) != MrmSUCCESS) {
	printf("can't fetch number %d\n",id);
	return (1);
      }
    }
 
  /* View Reference Point */
  XtVaGetValues(widgetArray[id],
		XmNvalue, &intVal, 
		XmNdecimalPoints, &decVal,
		NULL);

  number = (double)intVal;

  for (i = 0; i < (int)decVal; i++ ) number = number / 10.0;

/*  printf ("getWidgetValue %d, %d, %d, %g\n", id, intVal, decVal, number); */

  *value = (float) number;
  return (0);
}

/*************************************************************************
 * setWidgetValue - get a floating point number from an integer 
 * static int getWidgetValue(int id, float *value)
 */
static int setWidgetValue( id, value)
     int id;
     float *value;
{
  double number;
  MrmCode class;
  int intVal, i;
  short decVal;
  
  if (id > numberStringCount) return (1);

  if (widgetArray[id] == NULL) {     /* The first time, fetch order box. */
      if (MrmFetchWidget(theMrmHierarchy, numberStrings[id], theTopLevel,
			 &widgetArray[id], &class) != MrmSUCCESS) {
	printf("can't fetch number %d\n",id);
	return (1);
      }
    }

  XtVaGetValues(widgetArray[id],
		XmNvalue, &intVal, 
		XmNdecimalPoints, &decVal,
		NULL);

  number = (double)*value;

  for (i = 0; i < (int)decVal; i++ ) number = number * 10.0;

  intVal = (int)number;
  XtVaSetValues(widgetArray[id],
		XmNvalue, &intVal, 
		NULL);

  return (0);
}

/*************************************************************************
 * AddWorkProc - give us something to do when not busy
void AddWorkProc(int (*worker)(), char *info)
 */
void AddWorkProc(worker, info)
int (*worker)();
char *info;
{
  XtAppAddWorkProc(theAppContext,(XtWorkProc)worker,(XtPointer)info);
}


/*************************************************************************
 * motionHandler
 *
 * Registered for button motion, meaning when the mouse moves while the
 * button is down, this routine gets called. 
 XtEventHandler motionHandler( Widget widget,  XtPointer unused,
			  XMotionEvent *event,  Boolean *continue_to_dispatch )
 */

static XtEventHandler motionHandler( widget, unused,event,continue_to_dispatch)
     Widget widget;
     XtPointer unused;
     XMotionEvent *event;
     Boolean *continue_to_dispatch;
{
  int button;

  if ( event->state == Button1MotionMask ) {
    button = 0;
  } else if ( event->state == Button2MotionMask ) {
    button = 1;
  } else if ( event->state == Button3MotionMask ) {
    button = 2;
  } else {
    return;
  }

  theMotionHandlerTable[button](event);
  
  *continue_to_dispatch = 1;  /* tells whether to call other dispatchers */
}

/*************************************************************************
 * CreateDynGC - create an X GC Resource for Dynamics.
 *
 * Got the rubberbanding methodology from contrib/clients/xfig/w_drawPrim.c
 * But just the idea, no code was copied, hence no copyright.
 *
 * The idea is to xor ( exclusive or ) the foreground and the background
 * together. When it is xor'd with the background it produces the foreground.
 * 
 * must be called after the window is set up.
 */
GC CreateDynGC()
{
  XGCValues values;
  unsigned long fg, bg;
  GC tGC;

  if (theWimpyWindow) {
    values.foreground = -1;
    values.background = 0;
  } else {
    XtVaGetValues(theDrawingArea, XmNforeground, &fg, XmNbackground, &bg, NULL);
    values.foreground = fg ^ bg;
    values.background = bg;
  }
  values.function = GXxor;
  tGC = XCreateGC(XtDisplay(theDrawingArea), theWindow,
		  GCFunction | GCForeground | GCBackground, &values );
  return (tGC);
}

#define GetNumValue(_a,_b)  {if (getNumberWidgetValue((_a), (_b))) return;}

/*
void GetVPN( int viewNumber,   PEXVector  *vpn )
*/
void GetVPN( viewNumber, vpn )
     int viewNumber;
     PEXVector  *vpn;
{
  /* view plane normal */
  GetNumValue(k_view_pl_norm_x, &vpn->x);
  GetNumValue(k_view_pl_norm_y, &vpn->y);
  GetNumValue(k_view_pl_norm_z, &vpn->z);
}

void SetVPN( viewNumber, vpn )
     int viewNumber;
     PEXVector  *vpn;
{
  setNumberWidgetValue(k_view_pl_norm_x, vpn->x);
  setNumberWidgetValue(k_view_pl_norm_y, vpn->y);
  setNumberWidgetValue(k_view_pl_norm_z, vpn->z);
}


void GetVUP( viewNumber, vup )
     int viewNumber;
     PEXVector  *vup;
{
  /* view plane normal */
  GetNumValue(k_view_pl_norm_x, &vup->x);
  GetNumValue(k_view_pl_norm_y, &vup->y);
  GetNumValue(k_view_pl_norm_z, &vup->z);
}

void SetVUP( viewNumber, vup )
     int viewNumber;
     PEXVector  *vup;
{
  setNumberWidgetValue(k_view_pl_norm_x, vup->x);
  setNumberWidgetValue(k_view_pl_norm_y, vup->y);
  setNumberWidgetValue(k_view_pl_norm_z, vup->z);
}

/*************************************************************************
 * ApplySurfaceAttrs
 */
void
ApplySurfaceAttrs()
{
  int error, ptr;
  int style;
  int shade;
  int cull;
  float value;
  PEXReflectionAttributes reflAttrs;

  MrmCode class;

  if (theSurfaceForm == NULL) {     /* The first time, fetch order box. */
    if (MrmFetchWidget(theMrmHierarchy, "surface_dialog", theTopLevel,
		       &theSurfaceForm, &class) != MrmSUCCESS) {
      printf("can't fetch Surface set dialog");
      return;
    }
  }

  if (XmToggleButtonGetState(widgetArray[k_sstyle_hollow]))
    style = PEXInteriorStyleHollow;
  else if (XmToggleButtonGetState(widgetArray[k_sstyle_solid]))
    style = PEXInteriorStyleSolid;
  else if (XmToggleButtonGetState(widgetArray[k_sstyle_empty]))
    style = PEXInteriorStyleEmpty;
  else {
    printf("bad style\n");
    style = PEXInteriorStyleHollow;
  }

  InteriorStyleCmd(style);

  if (XmToggleButtonGetState(widgetArray[k_sshade_flat]))
    shade = PEXSurfaceInterpNone;
  else if (XmToggleButtonGetState(widgetArray[k_sshade_gouraud]))
    shade = PEXSurfaceInterpColor;
  else if (XmToggleButtonGetState(widgetArray[k_sshade_dot]))
    shade = PEXSurfaceInterpDotProduct;
  else if (XmToggleButtonGetState(widgetArray[k_sshade_phong]))
    shade = PEXSurfaceInterpNormal;
  else {
    printf("bad shade\n");
    shade = PEXSurfaceInterpNone;
  }

  SurfaceInterpCmd(shade); /* let this be done in pexdraw */

  if (XmToggleButtonGetState(widgetArray[k_cull_none]))
    cull = PEXNone;
  else if (XmToggleButtonGetState(widgetArray[k_cull_back]))
    cull = PEXBackFaces;
  else if (XmToggleButtonGetState(widgetArray[k_cull_front]))
    cull = PEXFrontFaces;
  else {
    printf("bad cull\n");
    cull = PEXNone;
  }

  FacetCullingCmd(cull);

#ifndef NO_TRANS
  if (getWidgetValue(k_surface_refl_transparency, &value)) return;
  if (value > /* arbitrary threshold for transparency */0.00001 ) {
    reflAttrs.transmission = value;
  } else reflAttrs.transmission = 0.0;
#endif
    
  if (getWidgetValue(k_surface_refl_ambient, &value)) return;
  reflAttrs.ambient = value;	/* ambient coefficient */
  if (getWidgetValue(k_surface_refl_diffuse, &value)) return;
  reflAttrs.diffuse = value;	/* diffuse coefficient */
  if (getWidgetValue(k_surface_refl_specular, &value)) return;
  reflAttrs.specular = value;	/* specular coefficient */
  /* set specular color to white */
  if (getWidgetValue(k_surface_refl_specexp, &value)) return;
  reflAttrs.specular_conc = value;	/* specular exponent */
  reflAttrs.specular_color.type = PEXColorTypeRGB;
  reflAttrs.specular_color.value.rgb.red   = 1.0;
  reflAttrs.specular_color.value.rgb.green = 1.0;
  reflAttrs.specular_color.value.rgb.blue  = 1.0;

  ReflectionAttributesCmd(&reflAttrs);

}

/*
GetSomeTextFromUI(int x, int y, int *length, char **charStr, int *flags )
*/
GetSomeTextFromUI( x, y, length, charStr, flags )
     int x;
     int y;
     int *length;
     char **charStr;
     int *flags;
{
  *length = strlen("hello world");
  *charStr = malloc(*length+1);
  strcpy(*charStr, "hello world");
  *flags = 0;
}

/*************************************************************************
 * ApplySpin
 */
int
ApplySpin(si)
     SpinInfo *si;
{
  int error, okToSet;
  float value;

  MrmCode class;

  if (theSpinForm == NULL) {     /* The first time, fetch order box. */
    if (MrmFetchWidget(theMrmHierarchy, "spin_dialog", theTopLevel,
		       &theSpinForm, &class) != MrmSUCCESS) {
      printf("can't fetch Spin set dialog");
      return;
    }
  }
    
  FetchValue(k_spinf_px, &si->point.x);
  FetchValue(k_spinf_py, &si->point.y);
  FetchValue(k_spinf_pz, &si->point.z);

  FetchValue(k_spinf_ox, &si->offset.x);
  FetchValue(k_spinf_oy, &si->offset.y);
  FetchValue(k_spinf_oz, &si->offset.z);

  okToSet = XmToggleButtonGetState(widgetArray[k_spinf_stop]);

  if (okToSet) {
    FetchValue(k_spinf_xang, &si->x_ang);
    FetchValue(k_spinf_yang, &si->y_ang);
    FetchValue(k_spinf_zang, &si->z_ang);
  }

  FetchValue(k_spinf_dx, &si->delta_x);
  FetchValue(k_spinf_dy, &si->delta_y);
  FetchValue(k_spinf_dz, &si->delta_z);

  FetchValue(k_spinf_scale, &value);

  si->scale.x = value;
  si->scale.y = value;
  si->scale.z = value;

}

int
LoadSpinWidget(si)
     SpinInfo *si;
{
  char text[80];
  Arg al[1];

  setNumberWidgetValue(k_spinf_px, si->point.x);
  setNumberWidgetValue(k_spinf_py, si->point.y);
  setNumberWidgetValue(k_spinf_pz, si->point.z);

  setNumberWidgetValue(k_spinf_ox, si->offset.x);
  setNumberWidgetValue(k_spinf_oy, si->offset.y);
  setNumberWidgetValue(k_spinf_oz, si->offset.z);

  setNumberWidgetValue(k_spinf_xang, si->x_ang);
  setNumberWidgetValue(k_spinf_yang, si->y_ang);
  setNumberWidgetValue(k_spinf_zang, si->z_ang);

  setNumberWidgetValue(k_spinf_dx, si->delta_x);
  setNumberWidgetValue(k_spinf_dy, si->delta_y);
  setNumberWidgetValue(k_spinf_dz, si->delta_z);

  setNumberWidgetValue(k_spinf_scale, si->scale.x);

  XmToggleButtonSetState(widgetArray[k_spinf_stop],False,False);

  sprintf(text, "%x", si->strux);

  XtSetArg(al[0],  XmNvalue, text );
  XtSetValues(widgetArray[k_spinf_strux], al, 1);

}
/*************************************************************************
 * LoadColorWidget - actually, that is all widget in form
 */
int
LoadColorWidget(strux, elem, rgb)
     PEXStructure strux;
     long  elem;
     PEXColorRGB *rgb;
{
  char text[80];
  Arg al[1];

  setWidgetValue(k_color_red, &rgb->red);
  setWidgetValue(k_color_green, &rgb->green);
  setWidgetValue(k_color_blue, &rgb->blue);

  sprintf(text, "%x", strux);
  XtSetArg(al[0],  XmNvalue, text );
  XtSetValues(widgetArray[k_color_strux], al, 1);

  sprintf(text, "%d", elem);
  XtSetArg(al[0],  XmNvalue, text );
  XtSetValues(widgetArray[k_color_elem], al, 1);

}

/*************************************************************************
 * ApplyColor, get the color, call SetColorAttribute
 */
int
ApplyColor(strux, elem)
     PEXStructure strux;
     long  elem;
{
  PEXColorRGB rgb;

  if (elem == -1 ) {printf("nothing selected, can't change colour\n"); return;}

  getWidgetValue(k_color_red, &rgb.red);
  getWidgetValue(k_color_green, &rgb.green);
  getWidgetValue(k_color_blue, &rgb.blue);

  SetColorAttribute( strux, elem, &rgb);
}


/***********************************************************************
 * FinishExec - last minute hacking for the sake of a cheap example
 */
static void
FinishExec(event)
 XButtonReleasedEvent *event;
{
  long s;
  int e;

  if ( theSelectedElement != -1 ) {
    theRenderProcs.PickOne( event->x, event->y, &s, &e);
    if ( e != -1 )
      ExecStrux(s);
    theRenderProcs.ReDraw();
  }
}
